From ed051614697f1184f04150d5f43ee871d95b31e8 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Tue, 17 May 2022 13:31:26 +0200 Subject: [PATCH 001/254] [DE-218] changed default protocol from VST to HTTP --- ChangeLog.md | 2 ++ pom.xml | 3 +-- src/main/java/com/arangodb/internal/ArangoDefaults.java | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/ChangeLog.md b/ChangeLog.md index c65303ea8..c7bcfb8e4 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -6,6 +6,8 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) a ## [Unreleased] +- changed default protocol from VST to HTTP/1.1 + ## [6.18.0] - 2022-06-07 - deprecated usage of deprecated server API (#440) diff --git a/pom.xml b/pom.xml index c9b2825a0..649739b52 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ com.arangodb arangodb-java-driver - 6.18.0 + 7.0.0-SNAPSHOT 2016 jar @@ -244,7 +244,6 @@ org.apache.httpcomponents httpclient - true com.arangodb diff --git a/src/main/java/com/arangodb/internal/ArangoDefaults.java b/src/main/java/com/arangodb/internal/ArangoDefaults.java index ad8f1ed36..64ab6468b 100644 --- a/src/main/java/com/arangodb/internal/ArangoDefaults.java +++ b/src/main/java/com/arangodb/internal/ArangoDefaults.java @@ -46,7 +46,7 @@ private ArangoDefaults() { public static final int MAX_CONNECTIONS_VST_DEFAULT = 1; public static final Integer CONNECTION_TTL_VST_DEFAULT = null; public static final int MAX_CONNECTIONS_HTTP_DEFAULT = 20; - public static final Protocol DEFAULT_NETWORK_PROTOCOL = Protocol.VST; + public static final Protocol DEFAULT_NETWORK_PROTOCOL = Protocol.HTTP_VPACK; public static final boolean DEFAULT_ACQUIRE_HOST_LIST = false; public static final int DEFAULT_ACQUIRE_HOST_LIST_INTERVAL = 60 * 60 * 1000; // hour public static final LoadBalancingStrategy DEFAULT_LOAD_BALANCING_STRATEGY = LoadBalancingStrategy.NONE; From 873e574913039bb18ac859db0242f23d775bf99a Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Wed, 22 Jun 2022 14:44:19 +0200 Subject: [PATCH 002/254] [DE-221] remove deprecated server api (#441) * remove MMFiles related APIs * removed executeTraversal API * removed getLogs API * removed invalid deprecation on collection id * removed minReplicationFactor * remove MMFiles related APIs * removed DocumentCreateOptions#overwrite APIs * removed GraphCreateOptions#minReplicationFactor API * removed executeTraversal API --- .../java/com/arangodb/ArangoCollection.java | 25 -- src/main/java/com/arangodb/ArangoDB.java | 13 - .../java/com/arangodb/ArangoDatabase.java | 16 - .../arangodb/async/ArangoCollectionAsync.java | 23 -- .../com/arangodb/async/ArangoDBAsync.java | 12 - .../arangodb/async/ArangoDatabaseAsync.java | 17 - .../internal/ArangoCollectionAsyncImpl.java | 10 - .../async/internal/ArangoDBAsyncImpl.java | 5 - .../internal/ArangoDatabaseAsyncImpl.java | 10 - .../com/arangodb/entity/CollectionEntity.java | 18 - .../entity/CollectionPropertiesEntity.java | 82 ---- .../com/arangodb/entity/CollectionStatus.java | 22 +- .../java/com/arangodb/entity/GraphEntity.java | 9 - .../java/com/arangodb/entity/LogEntity.java | 75 ---- .../arangodb/entity/MinReplicationFactor.java | 46 --- .../java/com/arangodb/entity/PathEntity.java | 56 --- .../com/arangodb/entity/TraversalEntity.java | 56 --- .../internal/ArangoCollectionImpl.java | 10 - .../com/arangodb/internal/ArangoDBImpl.java | 5 - .../arangodb/internal/ArangoDatabaseImpl.java | 8 - .../internal/InternalArangoCollection.java | 13 +- .../arangodb/internal/InternalArangoDB.java | 12 - .../internal/InternalArangoDatabase.java | 47 --- .../velocypack/VPackDeserializers.java | 7 - .../velocypack/VPackDriverModule.java | 4 - .../internal/velocypack/VPackSerializers.java | 16 - .../model/CollectionCreateOptions.java | 133 ------- .../model/CollectionPropertiesOptions.java | 26 -- .../arangodb/model/DocumentCreateOptions.java | 22 +- .../arangodb/model/GraphCreateOptions.java | 43 --- .../com/arangodb/model/TraversalOptions.java | 353 ------------------ .../com/arangodb/ArangoCollectionTest.java | 67 ---- src/test/java/com/arangodb/ArangoDBTest.java | 100 ----- .../java/com/arangodb/ArangoDatabaseTest.java | 47 --- .../arangodb/async/ArangoCollectionTest.java | 15 - .../java/com/arangodb/async/ArangoDBTest.java | 136 ------- .../arangodb/async/ArangoDatabaseTest.java | 53 --- 37 files changed, 3 insertions(+), 1609 deletions(-) delete mode 100644 src/main/java/com/arangodb/entity/LogEntity.java delete mode 100644 src/main/java/com/arangodb/entity/MinReplicationFactor.java delete mode 100644 src/main/java/com/arangodb/entity/PathEntity.java delete mode 100644 src/main/java/com/arangodb/entity/TraversalEntity.java delete mode 100644 src/main/java/com/arangodb/model/TraversalOptions.java diff --git a/src/main/java/com/arangodb/ArangoCollection.java b/src/main/java/com/arangodb/ArangoCollection.java index 40a5cdfd7..2073ff689 100644 --- a/src/main/java/com/arangodb/ArangoCollection.java +++ b/src/main/java/com/arangodb/ArangoCollection.java @@ -654,31 +654,6 @@ MultiDocumentEntity> deleteDocuments( */ void drop(boolean isSystem) throws ArangoDBException; - /** - * Tells the server to load the collection into memory. - * - * @return information about the collection - * @throws ArangoDBException - * @see API - * Documentation - * @deprecated MMFiles only - */ - @Deprecated - CollectionEntity load() throws ArangoDBException; - - /** - * Tells the server to remove the collection from memory. This call does not delete any documents. You can use the - * collection afterwards; in which case it will be loaded into memory, again. - * - * @return information about the collection - * @throws ArangoDBException - * @see API - * Documentation - * @deprecated MMFiles only - */ - @Deprecated - CollectionEntity unload() throws ArangoDBException; - /** * Returns information about the collection * diff --git a/src/main/java/com/arangodb/ArangoDB.java b/src/main/java/com/arangodb/ArangoDB.java index bb149d55c..d429754b3 100644 --- a/src/main/java/com/arangodb/ArangoDB.java +++ b/src/main/java/com/arangodb/ArangoDB.java @@ -1001,19 +1001,6 @@ default Boolean createDatabase(String name) throws ArangoDBException { */ Response execute(Request request, HostHandle hostHandle) throws ArangoDBException; - /** - * Returns fatal, error, warning or info log messages from the server's global log. - * - * @param options Additional options, can be null - * @return the log messages - * @throws ArangoDBException - * @see API - * Documentation - * @deprecated use {@link #getLogEntries(LogOptions)} instead - */ - @Deprecated - LogEntity getLogs(LogOptions options) throws ArangoDBException; - /** * Returns the server logs * diff --git a/src/main/java/com/arangodb/ArangoDatabase.java b/src/main/java/com/arangodb/ArangoDatabase.java index f0cfede5f..d9d2a8eff 100644 --- a/src/main/java/com/arangodb/ArangoDatabase.java +++ b/src/main/java/com/arangodb/ArangoDatabase.java @@ -623,22 +623,6 @@ GraphEntity createGraph(String name, Collection edgeDefinitions, */ DatabaseEntity getInfo() throws ArangoDBException; - /** - * Execute a server-side traversal - * - * @param vertexClass The type of the vertex documents (POJO class, VPackSlice or String for JSON) - * @param edgeClass The type of the edge documents (POJO class, VPackSlice or String for JSON) - * @param options Additional options - * @return Result of the executed traversal - * @throws ArangoDBException - * @see API - * Documentation - * @deprecated use {@link this#query(String, Map, AqlQueryOptions, Class)} - */ - @Deprecated - TraversalEntity executeTraversal(Class vertexClass, Class edgeClass, TraversalOptions options) - throws ArangoDBException; - /** * Reads a single document * diff --git a/src/main/java/com/arangodb/async/ArangoCollectionAsync.java b/src/main/java/com/arangodb/async/ArangoCollectionAsync.java index c54a7c8e1..91837285b 100644 --- a/src/main/java/com/arangodb/async/ArangoCollectionAsync.java +++ b/src/main/java/com/arangodb/async/ArangoCollectionAsync.java @@ -609,29 +609,6 @@ CompletableFuture ensureFulltextIndex( */ CompletableFuture drop(final boolean isSystem); - /** - * Loads a collection into memory. - * - * @return information about the collection - * @see API - * Documentation - * @deprecated MMFiles only - */ - @Deprecated - CompletableFuture load(); - - /** - * Removes a collection from memory. This call does not delete any documents. You can use the collection afterwards; - * in which case it will be loaded into memory, again. - * - * @return information about the collection - * @see API - * Documentation - * @deprecated MMFiles only - */ - @Deprecated - CompletableFuture unload(); - /** * Returns information about the collection * diff --git a/src/main/java/com/arangodb/async/ArangoDBAsync.java b/src/main/java/com/arangodb/async/ArangoDBAsync.java index ed4eb8ed3..f809f78d8 100644 --- a/src/main/java/com/arangodb/async/ArangoDBAsync.java +++ b/src/main/java/com/arangodb/async/ArangoDBAsync.java @@ -299,18 +299,6 @@ default CompletableFuture createDatabase(final String name) { */ CompletableFuture execute(final Request request); - /** - * Returns fatal, error, warning or info log messages from the server's global log. - * - * @param options Additional options, can be null - * @return the log messages - * @see API - * Documentation - * @deprecated use {@link #getLogEntries(LogOptions)} instead - */ - @Deprecated - CompletableFuture getLogs(final LogOptions options); - /** * Returns the server logs * diff --git a/src/main/java/com/arangodb/async/ArangoDatabaseAsync.java b/src/main/java/com/arangodb/async/ArangoDatabaseAsync.java index 420034655..d5d391fbe 100644 --- a/src/main/java/com/arangodb/async/ArangoDatabaseAsync.java +++ b/src/main/java/com/arangodb/async/ArangoDatabaseAsync.java @@ -603,23 +603,6 @@ CompletableFuture createGraph( */ CompletableFuture getInfo(); - /** - * Execute a server-side traversal - * - * @param vertexClass The type of the vertex documents (POJO class, VPackSlice or String for Json) - * @param edgeClass The type of the edge documents (POJO class, VPackSlice or String for Json) - * @param options Additional options - * @return Result of the executed traversal - * @see API - * Documentation - * @deprecated use {@link this#query(String, Map, AqlQueryOptions, Class)} - */ - @Deprecated - CompletableFuture> executeTraversal( - final Class vertexClass, - final Class edgeClass, - final TraversalOptions options); - /** * Reads a single document * diff --git a/src/main/java/com/arangodb/async/internal/ArangoCollectionAsyncImpl.java b/src/main/java/com/arangodb/async/internal/ArangoCollectionAsyncImpl.java index 036f16da2..b5be30c1c 100644 --- a/src/main/java/com/arangodb/async/internal/ArangoCollectionAsyncImpl.java +++ b/src/main/java/com/arangodb/async/internal/ArangoCollectionAsyncImpl.java @@ -360,16 +360,6 @@ public CompletableFuture drop(final boolean isSystem) { return executor.execute(dropRequest(isSystem), Void.class); } - @Override - public CompletableFuture load() { - return executor.execute(loadRequest(), CollectionEntity.class); - } - - @Override - public CompletableFuture unload() { - return executor.execute(unloadRequest(), CollectionEntity.class); - } - @Override public CompletableFuture getInfo() { return executor.execute(getInfoRequest(), CollectionEntity.class); diff --git a/src/main/java/com/arangodb/async/internal/ArangoDBAsyncImpl.java b/src/main/java/com/arangodb/async/internal/ArangoDBAsyncImpl.java index 170e4d1a7..23cf6af31 100644 --- a/src/main/java/com/arangodb/async/internal/ArangoDBAsyncImpl.java +++ b/src/main/java/com/arangodb/async/internal/ArangoDBAsyncImpl.java @@ -221,11 +221,6 @@ public CompletableFuture execute(final Request request) { return executor.execute(request, response -> response); } - @Override - public CompletableFuture getLogs(final LogOptions options) { - return executor.execute(getLogsRequest(options), LogEntity.class); - } - @Override public CompletableFuture getLogEntries(final LogOptions options) { return executor.execute(getLogEntriesRequest(options), LogEntriesEntity.class); diff --git a/src/main/java/com/arangodb/async/internal/ArangoDatabaseAsyncImpl.java b/src/main/java/com/arangodb/async/internal/ArangoDatabaseAsyncImpl.java index 61fed58d9..1ff2ede2e 100644 --- a/src/main/java/com/arangodb/async/internal/ArangoDatabaseAsyncImpl.java +++ b/src/main/java/com/arangodb/async/internal/ArangoDatabaseAsyncImpl.java @@ -48,7 +48,6 @@ import com.arangodb.model.GraphCreateOptions; import com.arangodb.model.StreamTransactionOptions; import com.arangodb.model.TransactionOptions; -import com.arangodb.model.TraversalOptions; import com.arangodb.model.arangosearch.AnalyzerDeleteOptions; import com.arangodb.model.arangosearch.ArangoSearchCreateOptions; import com.arangodb.velocypack.Type; @@ -401,15 +400,6 @@ public CompletableFuture getInfo() { return executor.execute(getInfoRequest(), getInfoResponseDeserializer()); } - @Override - public CompletableFuture> executeTraversal( - final Class vertexClass, - final Class edgeClass, - final TraversalOptions options) { - final Request request = executeTraversalRequest(options); - return executor.execute(request, executeTraversalResponseDeserializer(vertexClass, edgeClass)); - } - @Override public CompletableFuture getDocument(final String id, final Class type) throws ArangoDBException { DocumentUtil.validateDocumentId(id); diff --git a/src/main/java/com/arangodb/entity/CollectionEntity.java b/src/main/java/com/arangodb/entity/CollectionEntity.java index 846ed76fa..72530c808 100644 --- a/src/main/java/com/arangodb/entity/CollectionEntity.java +++ b/src/main/java/com/arangodb/entity/CollectionEntity.java @@ -31,11 +31,6 @@ public class CollectionEntity implements Entity { private String id; private String name; private Boolean waitForSync; - /** - * @deprecated MMFiles only - */ - @Deprecated - private Boolean isVolatile; private Boolean isSystem; private CollectionStatus status; private CollectionType type; @@ -45,11 +40,6 @@ public CollectionEntity() { super(); } - /** - * @deprecated Accessing collections by their internal ID instead of accessing them by name is deprecated and highly - * discouraged. This functionality may be removed in future versions of ArangoDB. - */ - @Deprecated public String getId() { return id; } @@ -62,14 +52,6 @@ public Boolean getWaitForSync() { return waitForSync; } - /** - * @deprecated MMFiles only - */ - @Deprecated - public Boolean getIsVolatile() { - return isVolatile; - } - public Boolean getIsSystem() { return isSystem; } diff --git a/src/main/java/com/arangodb/entity/CollectionPropertiesEntity.java b/src/main/java/com/arangodb/entity/CollectionPropertiesEntity.java index 8a1809152..73f55d758 100644 --- a/src/main/java/com/arangodb/entity/CollectionPropertiesEntity.java +++ b/src/main/java/com/arangodb/entity/CollectionPropertiesEntity.java @@ -29,27 +29,11 @@ */ public class CollectionPropertiesEntity extends CollectionEntity { - /** - * @deprecated MMFiles only - */ - @Deprecated - private Boolean doCompact; - /** - * @deprecated MMFiles only - */ - @Deprecated - private Long journalSize; - /** - * @deprecated MMFiles only - */ - @Deprecated - private Integer indexBuckets; private KeyOptions keyOptions; private Long count; private Integer numberOfShards; private Collection shardKeys; private final ReplicationFactor replicationFactor; - private final MinReplicationFactor minReplicationFactor; private Integer writeConcern; private String shardingStrategy; // cluster option private String smartJoinAttribute; // enterprise option @@ -57,56 +41,6 @@ public class CollectionPropertiesEntity extends CollectionEntity { public CollectionPropertiesEntity() { super(); replicationFactor = new ReplicationFactor(); - minReplicationFactor = new MinReplicationFactor(); - } - - /** - * @deprecated MMFiles only - */ - @Deprecated - public Boolean getDoCompact() { - return doCompact; - } - - /** - * @deprecated MMFiles only - */ - @Deprecated - public void setDoCompact(final Boolean doCompact) { - this.doCompact = doCompact; - } - - /** - * @deprecated MMFiles only - */ - @Deprecated - public Long getJournalSize() { - return journalSize; - } - - /** - * @deprecated MMFiles only - */ - @Deprecated - public void setJournalSize(final Long journalSize) { - this.journalSize = journalSize; - } - - - /** - * @deprecated MMFiles only - */ - @Deprecated - public Integer getIndexBuckets() { - return indexBuckets; - } - - /** - * @deprecated MMFiles only - */ - @Deprecated - public void setIndexBuckets(final Integer indexBuckets) { - this.indexBuckets = indexBuckets; } public KeyOptions getKeyOptions() { @@ -156,22 +90,6 @@ public void setReplicationFactor(final Integer replicationFactor) { this.replicationFactor.setReplicationFactor(replicationFactor); } - /** - * @deprecated use {@link #getWriteConcern()} instead - */ - @Deprecated - public Integer getMinReplicationFactor() { - return minReplicationFactor.getMinReplicationFactor(); - } - - /** - * @deprecated use {@link #setWriteConcern(Integer)} instead - */ - @Deprecated - public void setMinReplicationFactor(final Integer minReplicationFactor) { - this.minReplicationFactor.setMinReplicationFactor(minReplicationFactor); - } - public Integer getWriteConcern() { return writeConcern; } diff --git a/src/main/java/com/arangodb/entity/CollectionStatus.java b/src/main/java/com/arangodb/entity/CollectionStatus.java index 08816ddc1..7cfa65c9d 100644 --- a/src/main/java/com/arangodb/entity/CollectionStatus.java +++ b/src/main/java/com/arangodb/entity/CollectionStatus.java @@ -25,27 +25,7 @@ */ public enum CollectionStatus { - /** - * @deprecated MMFiles only - */ - @Deprecated - NEW_BORN_COLLECTION(1), - - /** - * @deprecated MMFiles only - */ - @Deprecated - UNLOADED(2), - - LOADED(3), - - /** - * @deprecated MMFiles only - */ - @Deprecated - IN_THE_PROCESS_OF_BEING_UNLOADED(4), - - DELETED(5); + LOADED(3),DELETED(5); private final int status; diff --git a/src/main/java/com/arangodb/entity/GraphEntity.java b/src/main/java/com/arangodb/entity/GraphEntity.java index 96dcc3299..151979131 100644 --- a/src/main/java/com/arangodb/entity/GraphEntity.java +++ b/src/main/java/com/arangodb/entity/GraphEntity.java @@ -40,7 +40,6 @@ public class GraphEntity implements Entity { private Integer numberOfShards; private String smartGraphAttribute; private ReplicationFactor replicationFactor; - private Integer minReplicationFactor; private Integer writeConcern; public String getName() { @@ -75,14 +74,6 @@ public Boolean getSatellite() { return this.replicationFactor.getSatellite(); } - /** - * @deprecated use {@link #getWriteConcern()} instead - */ - @Deprecated - public Integer getMinReplicationFactor() { - return minReplicationFactor; - } - public Integer getWriteConcern() { return writeConcern; } diff --git a/src/main/java/com/arangodb/entity/LogEntity.java b/src/main/java/com/arangodb/entity/LogEntity.java deleted file mode 100644 index fe4e52ea8..000000000 --- a/src/main/java/com/arangodb/entity/LogEntity.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.entity; - -import java.util.List; - -/** - * @author Mark Vollmary - * @see API - * Documentation - */ -public class LogEntity implements Entity { - - private List lid; - private List level; - private List timestamp; - private List text; - private Long totalAmount; - - /** - * @return a list of log entry identifiers. Each log message is uniquely identified by its @LIT{lid} and the - * identifiers are in ascending order - */ - public List getLid() { - return lid; - } - - /** - * @return a list of the log-levels for all log entries - */ - public List getLevel() { - return level; - } - - /** - * @return a list of the timestamps as seconds since 1970-01-01 for all log entries - */ - public List getTimestamp() { - return timestamp; - } - - /** - * @return a list of the texts of all log entries - */ - public List getText() { - return text; - } - - /** - * @return the total amount of log entries before pagination - */ - public Long getTotalAmount() { - return totalAmount; - } - -} diff --git a/src/main/java/com/arangodb/entity/MinReplicationFactor.java b/src/main/java/com/arangodb/entity/MinReplicationFactor.java deleted file mode 100644 index 5a1bfa915..000000000 --- a/src/main/java/com/arangodb/entity/MinReplicationFactor.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2019 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.entity; - -import com.arangodb.model.CollectionCreateOptions; - -/** - * @author Heiko Kernbach - * @deprecated use {@link CollectionCreateOptions#writeConcern(Integer)} instead - */ -@Deprecated -public class MinReplicationFactor { - - private Integer minReplicationFactor; - - public MinReplicationFactor() { - super(); - } - - public Integer getMinReplicationFactor() { - return minReplicationFactor; - } - - public void setMinReplicationFactor(final Integer minReplicationFactor) { - this.minReplicationFactor = minReplicationFactor; - } - -} \ No newline at end of file diff --git a/src/main/java/com/arangodb/entity/PathEntity.java b/src/main/java/com/arangodb/entity/PathEntity.java deleted file mode 100644 index 52f25840e..000000000 --- a/src/main/java/com/arangodb/entity/PathEntity.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.entity; - -import java.util.Collection; - -/** - * @author Mark Vollmary - * @see API - * Documentation - */ -@Deprecated -public class PathEntity implements Entity { - - private Collection edges; - private Collection vertices; - - public PathEntity() { - super(); - } - - public Collection getEdges() { - return edges; - } - - public void setEdges(final Collection edges) { - this.edges = edges; - } - - public Collection getVertices() { - return vertices; - } - - public void setVertices(final Collection vertices) { - this.vertices = vertices; - } - -} diff --git a/src/main/java/com/arangodb/entity/TraversalEntity.java b/src/main/java/com/arangodb/entity/TraversalEntity.java deleted file mode 100644 index 2d7f9a52a..000000000 --- a/src/main/java/com/arangodb/entity/TraversalEntity.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.entity; - -import java.util.Collection; - -/** - * @author Mark Vollmary - * @see API - * Documentation - */ -@Deprecated -public class TraversalEntity implements Entity { - - private Collection vertices; - private Collection> paths; - - public TraversalEntity() { - super(); - } - - public Collection getVertices() { - return vertices; - } - - public void setVertices(final Collection vertices) { - this.vertices = vertices; - } - - public Collection> getPaths() { - return paths; - } - - public void setPaths(final Collection> paths) { - this.paths = paths; - } - -} diff --git a/src/main/java/com/arangodb/internal/ArangoCollectionImpl.java b/src/main/java/com/arangodb/internal/ArangoCollectionImpl.java index ef362803b..6dded7789 100644 --- a/src/main/java/com/arangodb/internal/ArangoCollectionImpl.java +++ b/src/main/java/com/arangodb/internal/ArangoCollectionImpl.java @@ -361,16 +361,6 @@ public void drop(final boolean isSystem) throws ArangoDBException { executor.execute(dropRequest(isSystem), Void.class); } - @Override - public CollectionEntity load() throws ArangoDBException { - return executor.execute(loadRequest(), CollectionEntity.class); - } - - @Override - public CollectionEntity unload() throws ArangoDBException { - return executor.execute(unloadRequest(), CollectionEntity.class); - } - @Override public CollectionEntity getInfo() throws ArangoDBException { return executor.execute(getInfoRequest(), CollectionEntity.class); diff --git a/src/main/java/com/arangodb/internal/ArangoDBImpl.java b/src/main/java/com/arangodb/internal/ArangoDBImpl.java index be0ffd48c..ea980dede 100644 --- a/src/main/java/com/arangodb/internal/ArangoDBImpl.java +++ b/src/main/java/com/arangodb/internal/ArangoDBImpl.java @@ -249,11 +249,6 @@ public Response execute(final Request request, final HostHandle hostHandle) thro return executor.execute(request, response -> response, hostHandle); } - @Override - public LogEntity getLogs(final LogOptions options) throws ArangoDBException { - return executor.execute(getLogsRequest(options), LogEntity.class); - } - @Override public LogEntriesEntity getLogEntries(final LogOptions options) throws ArangoDBException { return executor.execute(getLogEntriesRequest(options), LogEntriesEntity.class); diff --git a/src/main/java/com/arangodb/internal/ArangoDatabaseImpl.java b/src/main/java/com/arangodb/internal/ArangoDatabaseImpl.java index 6b38136ac..cebbe794b 100644 --- a/src/main/java/com/arangodb/internal/ArangoDatabaseImpl.java +++ b/src/main/java/com/arangodb/internal/ArangoDatabaseImpl.java @@ -360,14 +360,6 @@ public DatabaseEntity getInfo() throws ArangoDBException { return executor.execute(getInfoRequest(), getInfoResponseDeserializer()); } - @Override - public TraversalEntity executeTraversal( - final Class vertexClass, final Class edgeClass, final TraversalOptions options) - throws ArangoDBException { - final Request request = executeTraversalRequest(options); - return executor.execute(request, executeTraversalResponseDeserializer(vertexClass, edgeClass)); - } - @Override public T getDocument(final String id, final Class type) throws ArangoDBException { DocumentUtil.validateDocumentId(id); diff --git a/src/main/java/com/arangodb/internal/InternalArangoCollection.java b/src/main/java/com/arangodb/internal/InternalArangoCollection.java index a30525543..5099a443c 100644 --- a/src/main/java/com/arangodb/internal/InternalArangoCollection.java +++ b/src/main/java/com/arangodb/internal/InternalArangoCollection.java @@ -56,7 +56,6 @@ public abstract class InternalArangoCollection, D private static final String RETURN_NEW = "returnNew"; private static final String NEW = "new"; private static final String RETURN_OLD = "returnOld"; - private static final String OVERWRITE = "overwrite"; private static final String OVERWRITE_MODE = "overwriteMode"; private static final String OLD = "old"; private static final String SILENT = "silent"; @@ -87,7 +86,6 @@ protected Request insertDocumentRequest(final T value, final DocumentCreateO request.putQueryParam(RETURN_NEW, params.getReturnNew()); request.putQueryParam(RETURN_OLD, params.getReturnOld()); request.putQueryParam(SILENT, params.getSilent()); - request.putQueryParam(OVERWRITE, params.getOverwrite()); request.putQueryParam(OVERWRITE_MODE, params.getOverwriteMode() != null ? params.getOverwriteMode().getValue() : null); request.putQueryParam(MERGE_OBJECTS, params.getMergeObjects()); request.putHeaderParam(TRANSACTION_ID, params.getStreamTransactionId()); @@ -127,7 +125,6 @@ protected Request insertDocumentsRequest(final Collection values, final D request.putQueryParam(RETURN_NEW, params.getReturnNew()); request.putQueryParam(RETURN_OLD, params.getReturnOld()); request.putQueryParam(SILENT, params.getSilent()); - request.putQueryParam(OVERWRITE, params.getOverwrite()); request.putQueryParam(OVERWRITE_MODE, params.getOverwriteMode() != null ? params.getOverwriteMode().getValue() : null); request.putQueryParam(MERGE_OBJECTS, params.getMergeObjects()); request.putHeaderParam(TRANSACTION_ID, params.getStreamTransactionId()); @@ -195,7 +192,7 @@ protected Request importDocumentsRequest(final DocumentImportOptions options) { return request(db.dbName(), RequestType.POST, PATH_API_IMPORT).putQueryParam(COLLECTION, name) .putQueryParam(ArangoRequestParam.WAIT_FOR_SYNC, params.getWaitForSync()) .putQueryParam("fromPrefix", params.getFromPrefix()).putQueryParam("toPrefix", params.getToPrefix()) - .putQueryParam(OVERWRITE, params.getOverwrite()).putQueryParam("onDuplicate", params.getOnDuplicate()) + .putQueryParam("onDuplicate", params.getOnDuplicate()) .putQueryParam("complete", params.getComplete()).putQueryParam("details", params.getDetails()); } @@ -636,14 +633,6 @@ protected Request dropRequest(final Boolean isSystem) { return request(db.dbName(), RequestType.DELETE, PATH_API_COLLECTION, name).putQueryParam("isSystem", isSystem); } - protected Request loadRequest() { - return request(db.dbName(), RequestType.PUT, PATH_API_COLLECTION, name, "load"); - } - - protected Request unloadRequest() { - return request(db.dbName(), RequestType.PUT, PATH_API_COLLECTION, name, "unload"); - } - protected Request getInfoRequest() { return request(db.dbName(), RequestType.GET, PATH_API_COLLECTION, name); } diff --git a/src/main/java/com/arangodb/internal/InternalArangoDB.java b/src/main/java/com/arangodb/internal/InternalArangoDB.java index 017ddab6b..db5d9135d 100644 --- a/src/main/java/com/arangodb/internal/InternalArangoDB.java +++ b/src/main/java/com/arangodb/internal/InternalArangoDB.java @@ -164,18 +164,6 @@ protected Request updateUserDefaultCollectionAccessRequest(final String user, fi "*", "*").setBody(util().serialize(OptionsBuilder.build(new UserAccessOptions(), permissions))); } - protected Request getLogsRequest(final LogOptions options) { - final LogOptions params = options != null ? options : new LogOptions(); - return request(DbName.SYSTEM, RequestType.GET, PATH_API_ADMIN_LOG) - .putQueryParam(LogOptions.PROPERTY_UPTO, params.getUpto()) - .putQueryParam(LogOptions.PROPERTY_LEVEL, params.getLevel()) - .putQueryParam(LogOptions.PROPERTY_START, params.getStart()) - .putQueryParam(LogOptions.PROPERTY_SIZE, params.getSize()) - .putQueryParam(LogOptions.PROPERTY_OFFSET, params.getOffset()) - .putQueryParam(LogOptions.PROPERTY_SEARCH, params.getSearch()) - .putQueryParam(LogOptions.PROPERTY_SORT, params.getSort()); - } - protected Request getLogEntriesRequest(final LogOptions options) { final LogOptions params = options != null ? options : new LogOptions(); return request(DbName.SYSTEM, RequestType.GET, PATH_API_ADMIN_LOG_ENTRIES) diff --git a/src/main/java/com/arangodb/internal/InternalArangoDatabase.java b/src/main/java/com/arangodb/internal/InternalArangoDatabase.java index 933b5c175..71a3f0099 100644 --- a/src/main/java/com/arangodb/internal/InternalArangoDatabase.java +++ b/src/main/java/com/arangodb/internal/InternalArangoDatabase.java @@ -35,13 +35,10 @@ import com.arangodb.util.ArangoSerializer; import com.arangodb.velocypack.Type; import com.arangodb.velocypack.VPackSlice; -import com.arangodb.velocypack.exception.VPackException; import com.arangodb.velocystream.Request; import com.arangodb.velocystream.RequestType; -import java.util.ArrayList; import java.util.Collection; -import java.util.Iterator; import java.util.Map; /** @@ -65,7 +62,6 @@ public abstract class InternalArangoDatabase getInfoResponseDeserializer() { return response -> util().deserialize(response.getBody().get(ArangoResponseField.RESULT), DatabaseEntity.class); } - protected Request executeTraversalRequest(final TraversalOptions options) { - return request(dbName, RequestType.POST, PATH_API_TRAVERSAL) - .setBody(util().serialize(options != null ? options : new TransactionOptions())); - } - - protected ResponseDeserializer> executeTraversalResponseDeserializer( - final Class vertexClass, final Class edgeClass) { - return response -> { - final TraversalEntity result = new TraversalEntity<>(); - final VPackSlice visited = response.getBody().get(ArangoResponseField.RESULT).get("visited"); - result.setVertices(deserializeVertices(vertexClass, visited)); - - final Collection> paths = new ArrayList<>(); - for (final Iterator iterator = visited.get("paths").arrayIterator(); iterator.hasNext(); ) { - final PathEntity path = new PathEntity<>(); - final VPackSlice next = iterator.next(); - path.setEdges(deserializeEdges(edgeClass, next)); - path.setVertices(deserializeVertices(vertexClass, next)); - paths.add(path); - } - result.setPaths(paths); - return result; - }; - } - - protected Collection deserializeVertices(final Class vertexClass, final VPackSlice vpack) - throws VPackException { - final Collection vertices = new ArrayList<>(); - for (final Iterator iterator = vpack.get("vertices").arrayIterator(); iterator.hasNext(); ) { - vertices.add(util(Serializer.CUSTOM).deserialize(iterator.next(), vertexClass)); - } - return vertices; - } - - protected Collection deserializeEdges(final Class edgeClass, final VPackSlice next) - throws VPackException { - final Collection edges = new ArrayList<>(); - for (final Iterator iteratorEdge = next.get("edges").arrayIterator(); iteratorEdge.hasNext(); ) { - edges.add(util(Serializer.CUSTOM).deserialize(iteratorEdge.next(), edgeClass)); - } - return edges; - } - protected Request reloadRoutingRequest() { return request(dbName, RequestType.POST, PATH_API_ADMIN_ROUTING_RELOAD); } diff --git a/src/main/java/com/arangodb/internal/velocypack/VPackDeserializers.java b/src/main/java/com/arangodb/internal/velocypack/VPackDeserializers.java index 3a5a32084..2e8849214 100644 --- a/src/main/java/com/arangodb/internal/velocypack/VPackDeserializers.java +++ b/src/main/java/com/arangodb/internal/velocypack/VPackDeserializers.java @@ -26,7 +26,6 @@ import com.arangodb.entity.CollectionType; import com.arangodb.entity.License; import com.arangodb.entity.LogLevel; -import com.arangodb.entity.MinReplicationFactor; import com.arangodb.entity.Permissions; import com.arangodb.entity.QueryExecutionState; import com.arangodb.entity.ReplicationFactor; @@ -150,12 +149,6 @@ public class VPackDeserializers { return replicationFactor; }; - public static final VPackDeserializer MIN_REPLICATION_FACTOR = (parent, vpack, context) -> { - final MinReplicationFactor minReplicationFactor = new MinReplicationFactor(); - minReplicationFactor.setMinReplicationFactor(vpack.getAsInt()); - return minReplicationFactor; - }; - public static final VPackDeserializer VIEW_TYPE = (parent, vpack, context) -> "arangosearch".equals(vpack.getAsString()) ? ViewType.ARANGO_SEARCH : ViewType.valueOf(vpack.getAsString().toUpperCase(Locale.ENGLISH)); diff --git a/src/main/java/com/arangodb/internal/velocypack/VPackDriverModule.java b/src/main/java/com/arangodb/internal/velocypack/VPackDriverModule.java index 4bd3e84f9..46a18784b 100644 --- a/src/main/java/com/arangodb/internal/velocypack/VPackDriverModule.java +++ b/src/main/java/com/arangodb/internal/velocypack/VPackDriverModule.java @@ -30,7 +30,6 @@ import com.arangodb.internal.velocystream.internal.AuthenticationRequest; import com.arangodb.internal.velocystream.internal.JwtAuthenticationRequest; import com.arangodb.model.CollectionSchema; -import com.arangodb.model.TraversalOptions; import com.arangodb.model.ZKDIndexOptions; import com.arangodb.model.arangosearch.ArangoSearchPropertiesOptions; import com.arangodb.velocypack.VPackModule; @@ -74,11 +73,9 @@ public > void setup(final C context) { context.registerSerializer(CollectionType.class, VPackSerializers.COLLECTION_TYPE); context.registerSerializer(BaseDocument.class, VPackSerializers.BASE_DOCUMENT); context.registerSerializer(BaseEdgeDocument.class, VPackSerializers.BASE_EDGE_DOCUMENT); - context.registerSerializer(TraversalOptions.Order.class, VPackSerializers.TRAVERSAL_ORDER); context.registerSerializer(LogLevel.class, VPackSerializers.LOG_LEVEL); context.registerSerializer(Permissions.class, VPackSerializers.PERMISSIONS); context.registerSerializer(ReplicationFactor.class, VPackSerializers.REPLICATION_FACTOR); - context.registerSerializer(MinReplicationFactor.class, VPackSerializers.MIN_REPLICATION_FACTOR); context.registerSerializer(ViewType.class, VPackSerializers.VIEW_TYPE); context.registerSerializer(ArangoSearchPropertiesOptions.class, VPackSerializers.ARANGO_SEARCH_PROPERTIES_OPTIONS); context.registerSerializer(ArangoSearchProperties.class, VPackSerializers.ARANGO_SEARCH_PROPERTIES); @@ -98,7 +95,6 @@ public > void setup(final C context) { context.registerDeserializer(Permissions.class, VPackDeserializers.PERMISSIONS); context.registerDeserializer(QueryExecutionState.class, VPackDeserializers.QUERY_EXECUTION_STATE); context.registerDeserializer(ReplicationFactor.class, VPackDeserializers.REPLICATION_FACTOR); - context.registerDeserializer(MinReplicationFactor.class, VPackDeserializers.MIN_REPLICATION_FACTOR); context.registerDeserializer(ViewType.class, VPackDeserializers.VIEW_TYPE); context.registerDeserializer(ArangoSearchProperties.class, VPackDeserializers.ARANGO_SEARCH_PROPERTIES); context.registerDeserializer(ArangoSearchPropertiesEntity.class, VPackDeserializers.ARANGO_SEARCH_PROPERTIES_ENTITY); diff --git a/src/main/java/com/arangodb/internal/velocypack/VPackSerializers.java b/src/main/java/com/arangodb/internal/velocypack/VPackSerializers.java index 4d786183d..399c8c8b5 100644 --- a/src/main/java/com/arangodb/internal/velocypack/VPackSerializers.java +++ b/src/main/java/com/arangodb/internal/velocypack/VPackSerializers.java @@ -26,8 +26,6 @@ import com.arangodb.internal.velocystream.internal.AuthenticationRequest; import com.arangodb.internal.velocystream.internal.JwtAuthenticationRequest; import com.arangodb.model.CollectionSchema; -import com.arangodb.model.TraversalOptions; -import com.arangodb.model.TraversalOptions.Order; import com.arangodb.model.ZKDIndexOptions; import com.arangodb.model.arangosearch.ArangoSearchPropertiesOptions; import com.arangodb.velocypack.*; @@ -103,14 +101,6 @@ public class VPackSerializers { context.serialize(builder, attribute, doc); }; - public static final VPackSerializer TRAVERSAL_ORDER = (builder, attribute, value, context) -> { - if (Order.preorder_expander == value) { - builder.add(attribute, "preorder-expander"); - } else { - builder.add(attribute, value.name()); - } - }; - public static final VPackSerializer LOG_LEVEL = (builder, attribute, value, context) -> builder.add(attribute, value.getLevel()); public static final VPackSerializer PERMISSIONS = (builder, attribute, value, context) -> builder.add(attribute, value.toString().toLowerCase(Locale.ENGLISH)); @@ -124,12 +114,6 @@ public class VPackSerializers { } }; - public static final VPackSerializer MIN_REPLICATION_FACTOR = (builder, attribute, value, context) -> { - if (value.getMinReplicationFactor() != null) { - builder.add(attribute, value.getMinReplicationFactor()); - } - }; - public static final VPackSerializer VIEW_TYPE = (builder, attribute, value, context) -> { final String type = value == ViewType.ARANGO_SEARCH ? "arangosearch" : value.name().toLowerCase(Locale.ENGLISH); builder.add(attribute, type); diff --git a/src/main/java/com/arangodb/model/CollectionCreateOptions.java b/src/main/java/com/arangodb/model/CollectionCreateOptions.java index 8ef7eff6b..4e69ea8f9 100644 --- a/src/main/java/com/arangodb/model/CollectionCreateOptions.java +++ b/src/main/java/com/arangodb/model/CollectionCreateOptions.java @@ -23,7 +23,6 @@ import com.arangodb.entity.CollectionType; import com.arangodb.entity.KeyOptions; import com.arangodb.entity.KeyType; -import com.arangodb.entity.MinReplicationFactor; import com.arangodb.entity.ReplicationFactor; /** @@ -34,31 +33,14 @@ public class CollectionCreateOptions { private String name; - private Long journalSize; private final ReplicationFactor replicationFactor; - private final MinReplicationFactor minReplicationFactor; private Integer writeConcern; private KeyOptions keyOptions; private Boolean waitForSync; - /** - * @deprecated MMFiles only - */ - @Deprecated - private Boolean doCompact; - /** - * @deprecated MMFiles only - */ - @Deprecated - private Boolean isVolatile; private String[] shardKeys; private Integer numberOfShards; private Boolean isSystem; private CollectionType type; - /** - * @deprecated MMFiles only - */ - @Deprecated - private Integer indexBuckets; private String distributeShardsLike; private String shardingStrategy; // cluster option @@ -69,7 +51,6 @@ public class CollectionCreateOptions { public CollectionCreateOptions() { super(); replicationFactor = new ReplicationFactor(); - minReplicationFactor = new MinReplicationFactor(); } protected String getName() { @@ -85,37 +66,10 @@ protected CollectionCreateOptions name(final String name) { return this; } - /** - * @deprecated MMFiles only - */ - @Deprecated - public Long getJournalSize() { - return journalSize; - } - - /** - * @param journalSize The maximal size of a journal or datafile in bytes. The value must be at least 1048576 (1 MiB). - * @return options - * @deprecated MMFiles only - */ - @Deprecated - public CollectionCreateOptions journalSize(final Long journalSize) { - this.journalSize = journalSize; - return this; - } - public Integer getReplicationFactor() { return replicationFactor.getReplicationFactor(); } - /** - * @deprecated use {@link #getWriteConcern()} instead - */ - @Deprecated - public Integer getMinReplicationFactor() { - return minReplicationFactor.getMinReplicationFactor(); - } - /** * @param replicationFactor (The default is 1): in a cluster, this attribute determines how many copies of each shard are kept on * different DBServers. The value 1 means that only one copy (no synchronous replication) is kept. A @@ -131,24 +85,6 @@ public CollectionCreateOptions replicationFactor(final Integer replicationFactor return this; } - /** - * @param minReplicationFactor (optional, default is 1): in a cluster, this attribute determines how many desired copies of each - * shard are kept on different DBServers. The value 1 means that only one copy (no synchronous - * replication) is kept. A value of k means that desired k-1 replicas are kept. If in a failover scenario - * a shard of a collection has less than minReplicationFactor many insync followers it will go into - * "read-only" mode and will reject writes until enough followers are insync again. In more detail: - * Having `minReplicationFactor == 1` means as soon as a "master-copy" is available of the data writes - * are allowed. Having `minReplicationFactor > 1` requires additional insync copies on follower servers - * to allow writes. - * @return options - * @deprecated use {@link #writeConcern(Integer)} instead - */ - @Deprecated - public CollectionCreateOptions minReplicationFactor(final Integer minReplicationFactor) { - this.minReplicationFactor.setMinReplicationFactor(minReplicationFactor); - return this; - } - public Integer getWriteConcern() { return writeConcern; } @@ -217,50 +153,6 @@ public CollectionCreateOptions waitForSync(final Boolean waitForSync) { return this; } - /** - * @deprecated MMFiles only - */ - @Deprecated - public Boolean getDoCompact() { - return doCompact; - } - - /** - * @param doCompact whether or not the collection will be compacted (default is true) - * @return options - * @deprecated MMFiles only - */ - @Deprecated - public CollectionCreateOptions doCompact(final Boolean doCompact) { - this.doCompact = doCompact; - return this; - } - - /** - * @deprecated MMFiles only - */ - @Deprecated - public Boolean getIsVolatile() { - return isVolatile; - } - - /** - * @param isVolatile If true then the collection data is kept in-memory only and not made persistent. Unloading the - * collection will cause the collection data to be discarded. Stopping or re-starting the server will - * also cause full loss of data in the collection. Setting this option will make the resulting collection - * be slightly faster than regular collections because ArangoDB does not enforce any synchronization to - * disk and does not calculate any CRC checksums for datafiles (as there are no datafiles). This option - * should therefore be used for cache-type collections only, and not for data that cannot be re-created - * otherwise. (The default is false) - * @return options - * @deprecated MMFiles only - */ - @Deprecated - public CollectionCreateOptions isVolatile(final Boolean isVolatile) { - this.isVolatile = isVolatile; - return this; - } - public String[] getShardKeys() { return shardKeys; } @@ -347,31 +239,6 @@ public CollectionCreateOptions type(final CollectionType type) { return this; } - /** - * @deprecated MMFiles only - */ - @Deprecated - public Integer getIndexBuckets() { - return indexBuckets; - } - - /** - * @param indexBuckets The number of buckets into which indexes using a hash table are split. The default is 16 and this - * number has to be a power of 2 and less than or equal to 1024. For very large collections one should - * increase this to avoid long pauses when the hash table has to be initially built or resized, since - * buckets are resized individually and can be initially built in parallel. For example, 64 might be a - * sensible value for a collection with 100 000 000 documents. Currently, only the edge index respects - * this value, but other index types might follow in future ArangoDB versions. Changes (see below) are - * applied when the collection is loaded the next time. - * @return options - * @deprecated MMFiles only - */ - @Deprecated - public CollectionCreateOptions indexBuckets(final Integer indexBuckets) { - this.indexBuckets = indexBuckets; - return this; - } - public String getDistributeShardsLike() { return distributeShardsLike; } diff --git a/src/main/java/com/arangodb/model/CollectionPropertiesOptions.java b/src/main/java/com/arangodb/model/CollectionPropertiesOptions.java index e7c62f71f..d4ca9ac8e 100644 --- a/src/main/java/com/arangodb/model/CollectionPropertiesOptions.java +++ b/src/main/java/com/arangodb/model/CollectionPropertiesOptions.java @@ -28,11 +28,6 @@ public class CollectionPropertiesOptions { private Boolean waitForSync; - /** - * @deprecated MMFiles only - */ - @Deprecated - private Long journalSize; private CollectionSchema schema; public CollectionPropertiesOptions() { @@ -52,27 +47,6 @@ public CollectionPropertiesOptions waitForSync(final Boolean waitForSync) { return this; } - /** - * @deprecated MMFiles only - */ - @Deprecated - public Long getJournalSize() { - return journalSize; - } - - /** - * @param journalSize The maximal size of a journal or datafile in bytes. The value must be at least 1048576 (1 MB). Note - * that when changing the journalSize value, it will only have an effect for additional journals or - * datafiles that are created. Already existing journals or datafiles will not be affected. - * @return options - * @deprecated MMFiles only - */ - @Deprecated - public CollectionPropertiesOptions journalSize(final Long journalSize) { - this.journalSize = journalSize; - return this; - } - public CollectionSchema getSchema() { return schema; } diff --git a/src/main/java/com/arangodb/model/DocumentCreateOptions.java b/src/main/java/com/arangodb/model/DocumentCreateOptions.java index 3c8a52337..057a382e7 100644 --- a/src/main/java/com/arangodb/model/DocumentCreateOptions.java +++ b/src/main/java/com/arangodb/model/DocumentCreateOptions.java @@ -31,7 +31,6 @@ public class DocumentCreateOptions { private Boolean waitForSync; private Boolean returnNew; private Boolean returnOld; - private Boolean overwrite; private OverwriteMode overwriteMode; private Boolean silent; private String streamTransactionId; @@ -73,8 +72,7 @@ public Boolean getReturnOld() { } /** - * @param returnOld Additionally return the complete old document under the attribute old in the result. Only - * available if the {@code overwrite} option is used. + * @param returnOld Additionally return the complete old document under the attribute old in the result. * @return options * @since ArangoDB 3.4 */ @@ -83,24 +81,6 @@ public DocumentCreateOptions returnOld(final Boolean returnOld) { return this; } - public Boolean getOverwrite() { - return overwrite; - } - - /** - * @param overwrite If set to true, the insert becomes a replace-insert. If a document with the same {@code _key} - * already exists the new document is not rejected with unique constraint violated but will replace - * the old document. - * @return options - * @since ArangoDB 3.4 - * @deprecated use {@link #overwriteMode(OverwriteMode)} instead - */ - @Deprecated - public DocumentCreateOptions overwrite(final Boolean overwrite) { - this.overwrite = overwrite; - return this; - } - public OverwriteMode getOverwriteMode() { return overwriteMode; } diff --git a/src/main/java/com/arangodb/model/GraphCreateOptions.java b/src/main/java/com/arangodb/model/GraphCreateOptions.java index cf06b3e4b..6d75fb4e1 100644 --- a/src/main/java/com/arangodb/model/GraphCreateOptions.java +++ b/src/main/java/com/arangodb/model/GraphCreateOptions.java @@ -143,32 +143,6 @@ public GraphCreateOptions satellite(final Boolean satellite) { return this; } - /** - * @deprecated use {@link #getWriteConcern()} instead - */ - @Deprecated - public Integer getMinReplicationFactor() { - return getOptions().getMinReplicationFactor(); - } - - /** - * @param minReplicationFactor (optional, default is 1): in a cluster, this attribute determines how many desired copies of each - * shard are kept on different DBServers. The value 1 means that only one copy (no synchronous - * replication) is kept. A value of k means that desired k-1 replicas are kept. If in a failover scenario - * a shard of a collection has less than minReplicationFactor many insync followers it will go into - * "read-only" mode and will reject writes until enough followers are insync again. In more detail: - * Having `minReplicationFactor == 1` means as soon as a "master-copy" is available of the data writes - * are allowed. Having `minReplicationFactor > 1` requires additional insync copies on follower servers - * to allow writes. - * @return options - * @deprecated use {@link #writeConcern(Integer)} instead - */ - @Deprecated - public GraphCreateOptions minReplicationFactor(final Integer minReplicationFactor) { - getOptions().setMinReplicationFactor(minReplicationFactor); - return this; - } - public Integer getWriteConcern() { return getOptions().getWriteConcern(); } @@ -238,7 +212,6 @@ private SmartOptions getOptions() { public static class SmartOptions { private ReplicationFactor replicationFactor; - private Integer minReplicationFactor; private Integer writeConcern; private Integer numberOfShards; private String smartGraphAttribute; @@ -266,22 +239,6 @@ public void setSatellite(final Boolean satellite) { replicationFactor.setSatellite(satellite); } - /** - * @deprecated use {{@link #getWriteConcern()}} instead - */ - @Deprecated - public Integer getMinReplicationFactor() { - return minReplicationFactor; - } - - /** - * @deprecated use {{@link #setWriteConcern(Integer)}} instead - */ - @Deprecated - public void setMinReplicationFactor(final Integer minReplicationFactor) { - this.minReplicationFactor = minReplicationFactor; - } - public Integer getWriteConcern() { return writeConcern; } diff --git a/src/main/java/com/arangodb/model/TraversalOptions.java b/src/main/java/com/arangodb/model/TraversalOptions.java deleted file mode 100644 index 1d7abada7..000000000 --- a/src/main/java/com/arangodb/model/TraversalOptions.java +++ /dev/null @@ -1,353 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.model; - -/** - * @author Mark Vollmary - * @see API Documentation - */ -@Deprecated -public class TraversalOptions { - - public enum Direction { - outbound, inbound, any - } - - public enum ItemOrder { - forward, backward - } - - public enum Strategy { - depthfirst, breadthfirst - } - - public enum UniquenessType { - none, global, path - } - - public enum Order { - preorder, postorder, preorder_expander - } - - private String sort; - private Direction direction; - private Integer minDepth; - private String startVertex; - private String visitor; - private ItemOrder itemOrder; - private Strategy strategy; - private String filter; - private String init; - private Integer maxIterations; - private Integer maxDepth; - private Uniqueness uniqueness; - private Order order; - private String graphName; - private String expander; - private String edgeCollection; - - public String getSort() { - return sort; - } - - /** - * @param sort JavaScript code of a custom comparison function for the edges. The signature of this function is (l, - * r) -> integer (where l and r are edges) and must return -1 if l is smaller than, +1 if l is greater - * than, and 0 if l and r are equal. The reason for this is the following: The order of edges returned - * for a certain vertex is undefined. This is because there is no natural order of edges for a vertex - * with multiple connected edges. To explicitly define the order in which edges on the vertex are - * followed, you can specify an edge comparator function with this attribute. Note that the value here - * has to be a string to conform to the JSON standard, which in turn is parsed as function body on the - * server side. Furthermore note that this attribute is only used for the standard expanders. If you use - * your custom expander you have to do the sorting yourself within the expander code. - * @return options - */ - public TraversalOptions sort(final String sort) { - this.sort = sort; - return this; - } - - public Direction getDirection() { - return direction; - } - - /** - * @param direction direction for traversal - *

- * if set, must be either "outbound", "inbound", or "any" - *

- * if not set, the expander attribute must be specified - * @return options - */ - public TraversalOptions direction(final Direction direction) { - this.direction = direction; - return this; - } - - public Integer getMinDepth() { - return minDepth; - } - - /** - * @param minDepth ANDed with any existing filters): visits only nodes in at least the given depth - * @return options - */ - public TraversalOptions minDepth(final Integer minDepth) { - this.minDepth = minDepth; - return this; - } - - public String getStartVertex() { - return startVertex; - } - - /** - * @param startVertex The id of the startVertex, e.g. "users/foo". - * @return options - */ - public TraversalOptions startVertex(final String startVertex) { - this.startVertex = startVertex; - return this; - } - - public String getVisitor() { - return visitor; - } - - /** - * @param visitor JavaScript code of custom visitor function function signature: (config, result, vertex, path, - * connected) -> void The visitor function can do anything, but its return value is ignored. To populate - * a result, use the result variable by reference. Note that the connected argument is only populated - * when the order attribute is set to "preorder-expander". - * @return options - */ - public TraversalOptions visitor(final String visitor) { - this.visitor = visitor; - return this; - } - - public ItemOrder getItemOrder() { - return itemOrder; - } - - /** - * @param itemOrder The item iteration order can be "forward" or "backward" - * @return options - */ - public TraversalOptions itemOrder(final ItemOrder itemOrder) { - this.itemOrder = itemOrder; - return this; - } - - public Strategy getStrategy() { - return strategy; - } - - /** - * @param strategy The traversal strategy can be "depthfirst" or "breadthfirst" - * @return options - */ - public TraversalOptions strategy(final Strategy strategy) { - this.strategy = strategy; - return this; - } - - public String getFilter() { - return filter; - } - - /** - * @param filter default is to include all nodes: body (JavaScript code) of custom filter function function signature: - * (config, vertex, path) -> mixed can return four different string values: - *

- * "exclude" -> this vertex will not be visited. - *

- * "prune" -> the edges of this vertex will not be followed. - *

- * "" or undefined -> visit the vertex and follow it's edges. - *

- * Array -> containing any combination of the above. - *

- * If there is at least one "exclude" or "prune" respectivly is contained, it's effect will occur. - * @return options - */ - public TraversalOptions filter(final String filter) { - this.filter = filter; - return this; - } - - public String getInit() { - return init; - } - - /** - * @param init JavaScript code of custom result initialization function function signature: (config, result) -> void - * initialize any values in result with what is required - * @return options - */ - public TraversalOptions init(final String init) { - this.init = init; - return this; - } - - public Integer getMaxIterations() { - return maxIterations; - } - - /** - * @param maxIterations Maximum number of iterations in each traversal. This number can be set to prevent endless loops in - * traversal of cyclic graphs. When a traversal performs as many iterations as the maxIterations value, - * the traversal will abort with an error. If maxIterations is not set, a server-defined value may be - * used. - * @return options - */ - public TraversalOptions maxIterations(final Integer maxIterations) { - this.maxIterations = maxIterations; - return this; - } - - public Integer getMaxDepth() { - return maxDepth; - } - - /** - * @param maxDepth ANDed with any existing filters visits only nodes in at most the given depth. - * @return options - */ - public TraversalOptions maxDepth(final Integer maxDepth) { - this.maxDepth = maxDepth; - return this; - } - - public UniquenessType getVerticesUniqueness() { - return uniqueness != null ? uniqueness.vertices : null; - } - - /** - * @param vertices Specifies uniqueness for vertices can be "none", "global" or "path" - * @return options - */ - public TraversalOptions verticesUniqueness(final UniquenessType vertices) { - getUniqueness().setVertices(vertices); - return this; - } - - public UniquenessType getEdgesUniqueness() { - return uniqueness != null ? uniqueness.edges : null; - } - - /** - * @param edges Specifies uniqueness for edges can be "none", "global" or "path" - * @return options - */ - public TraversalOptions edgesUniqueness(final UniquenessType edges) { - getUniqueness().setEdges(edges); - return this; - } - - public Order getOrder() { - return order; - } - - /** - * @param order The traversal order can be "preorder", "postorder" or "preorder-expander" - * @return options - */ - public TraversalOptions order(final Order order) { - this.order = order; - return this; - } - - public String getGraphName() { - return graphName; - } - - /** - * @param graphName The name of the graph that contains the edges. Either edgeCollection or graphName has to be given. In - * case both values are set the graphName is prefered. - * @return options - */ - public TraversalOptions graphName(final String graphName) { - this.graphName = graphName; - return this; - } - - public String getExpander() { - return expander; - } - - /** - * @param expander JavaScript code of custom expander function must be set if direction attribute is not set function - * signature: (config, vertex, path) -> array expander must return an array of the connections for vertex - * each connection is an object with the attributes edge and vertex - * @return options - */ - public TraversalOptions expander(final String expander) { - this.expander = expander; - return this; - } - - public String getEdgeCollection() { - return edgeCollection; - } - - /** - * @param edgeCollection The name of the collection that contains the edges. - * @return options - */ - public TraversalOptions edgeCollection(final String edgeCollection) { - this.edgeCollection = edgeCollection; - return this; - } - - public static class Uniqueness { - - private UniquenessType vertices; - private UniquenessType edges; - - public UniquenessType getVertices() { - return vertices; - } - - public void setVertices(final UniquenessType vertices) { - this.vertices = vertices; - } - - public UniquenessType getEdges() { - return edges; - } - - public void setEdges(final UniquenessType edges) { - this.edges = edges; - } - } - - private Uniqueness getUniqueness() { - if (uniqueness == null) { - uniqueness = new Uniqueness(); - uniqueness.vertices = UniquenessType.none; - uniqueness.edges = UniquenessType.none; - } - - return uniqueness; - } - -} diff --git a/src/test/java/com/arangodb/ArangoCollectionTest.java b/src/test/java/com/arangodb/ArangoCollectionTest.java index f1467ce72..d332312e9 100644 --- a/src/test/java/com/arangodb/ArangoCollectionTest.java +++ b/src/test/java/com/arangodb/ArangoCollectionTest.java @@ -161,28 +161,6 @@ void insertDocumentReturnNew(ArangoCollection collection) { assertThat(doc.getRev()).isNotNull(); assertThat(doc.getNew()).isNotNull(); } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void insertDocumentOverwriteReturnOld(ArangoCollection collection) { - assumeTrue(isAtLeastVersion(3, 4)); - Long initialCount = collection.count().getCount(); - - final BaseDocument doc = new BaseDocument(); - doc.addAttribute("value", "a"); - final DocumentCreateEntity meta = collection.insertDocument(doc); - - doc.addAttribute("value", "b"); - final DocumentCreateEntity repsert = collection - .insertDocument(doc, new DocumentCreateOptions().overwrite(true).returnOld(true).returnNew(true)); - - assertThat(repsert).isNotNull(); - assertThat(repsert.getRev()).isNotEqualTo(meta.getRev()); - assertThat(repsert.getOld().getAttribute("value")).isEqualTo("a"); - assertThat(repsert.getNew().getAttribute("value")).isEqualTo("b"); - assertThat(collection.count().getCount()).isEqualTo(initialCount + 1L); - } - @ParameterizedTest(name = "{index}") @MethodSource("cols") void insertDocumentOverwriteModeIgnore(ArangoCollection collection) { @@ -1841,36 +1819,6 @@ void insertDocuments(ArangoCollection collection) { assertThat(docs.getErrors()).isEmpty(); } - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void insertDocumentsOverwrite(ArangoCollection collection) { - assumeTrue(isAtLeastVersion(3, 4)); - - final BaseDocument doc1 = new BaseDocument(); - doc1.addAttribute("value", "a"); - final DocumentCreateEntity meta1 = collection.insertDocument(doc1); - - final BaseDocument doc2 = new BaseDocument(); - doc2.addAttribute("value", "a"); - final DocumentCreateEntity meta2 = collection.insertDocument(doc2); - - doc1.addAttribute("value", "b"); - doc2.addAttribute("value", "b"); - - final MultiDocumentEntity> repsert = collection - .insertDocuments(Arrays.asList(doc1, doc2), - new DocumentCreateOptions().overwrite(true).returnOld(true).returnNew(true)); - assertThat(repsert).isNotNull(); - assertThat(repsert.getDocuments()).hasSize(2); - assertThat(repsert.getErrors()).isEmpty(); - for (final DocumentCreateEntity documentCreateEntity : repsert.getDocuments()) { - assertThat(documentCreateEntity.getRev()).isNotEqualTo(meta1.getRev()); - assertThat(documentCreateEntity.getRev()).isNotEqualTo(meta2.getRev()); - assertThat(documentCreateEntity.getOld().getAttribute("value")).isEqualTo("a"); - assertThat(documentCreateEntity.getNew().getAttribute("value")).isEqualTo("b"); - } - } - @ParameterizedTest(name = "{index}") @MethodSource("cols") void insertDocumentsOverwriteModeUpdate(ArangoCollection collection) { @@ -2804,21 +2752,6 @@ void replaceDocumentsJson(ArangoCollection collection) { assertThat(updateResult.getDocuments()).hasSize(2); assertThat(updateResult.getErrors()).isEmpty(); } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void load(ArangoCollection collection) { - final CollectionEntity result = collection.load(); - assertThat(result.getName()).isEqualTo(COLLECTION_NAME); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void unload(ArangoCollection collection) { - final CollectionEntity result = collection.unload(); - assertThat(result.getName()).isEqualTo(COLLECTION_NAME); - } - @ParameterizedTest(name = "{index}") @MethodSource("cols") void getInfo(ArangoCollection collection) { diff --git a/src/test/java/com/arangodb/ArangoDBTest.java b/src/test/java/com/arangodb/ArangoDBTest.java index eadb0806c..76d991e6a 100644 --- a/src/test/java/com/arangodb/ArangoDBTest.java +++ b/src/test/java/com/arangodb/ArangoDBTest.java @@ -31,7 +31,6 @@ import com.arangodb.velocystream.Response; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.MethodSource; @@ -400,105 +399,6 @@ void execute(ArangoDB arangoDB) throws VPackException { assertThat(response.getBody().get("version").isString()).isTrue(); } - @ParameterizedTest(name = "{index}") - @MethodSource("arangos") - void getLogs(ArangoDB arangoDB) { - assumeTrue(isAtLeastVersion(3, 7)); // it fails in 3.6 active-failover (BTS-362) - final LogEntity logs = arangoDB.getLogs(null); - assertThat(logs.getTotalAmount()).isPositive(); - assertThat(logs.getLid()).hasSize(logs.getTotalAmount().intValue()); - assertThat(logs.getLevel()).hasSize(logs.getTotalAmount().intValue()); - assertThat(logs.getTimestamp()).hasSize(logs.getTotalAmount().intValue()); - assertThat(logs.getText()).hasSize(logs.getTotalAmount().intValue()); - } - - @Disabled - @ParameterizedTest(name = "{index}") - @MethodSource("arangos") - void getLogsUpto(ArangoDB arangoDB) { - assumeTrue(isAtLeastVersion(3, 7)); // it fails in 3.6 active-failover (BTS-362) - final LogEntity logsUpto = arangoDB.getLogs(new LogOptions().upto(LogLevel.WARNING)); - assertThat(logsUpto.getLevel()) - .isNotEmpty() - .doesNotContain(LogLevel.INFO); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("arangos") - void getLogsLevel(ArangoDB arangoDB) { - assumeTrue(isAtLeastVersion(3, 7)); // it fails in 3.6 active-failover (BTS-362) - final LogEntity logsInfo = arangoDB.getLogs(new LogOptions().level(LogLevel.INFO)); - assertThat(logsInfo.getLevel()).containsOnly(LogLevel.INFO); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("arangos") - void getLogsStart(ArangoDB arangoDB) { - assumeTrue(isAtLeastVersion(3, 7)); // it fails in 3.6 active-failover (BTS-362) - final LogEntity logs = arangoDB.getLogs(null); - assertThat(logs.getLid()).isNotEmpty(); - final LogEntity logsStart = arangoDB.getLogs(new LogOptions().start(logs.getLid().get(0) + 1)); - assertThat(logsStart.getLid()) - .isNotEmpty() - .doesNotContain(logs.getLid().get(0)); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("arangos") - void getLogsSize(ArangoDB arangoDB) { - assumeTrue(isAtLeastVersion(3, 7)); // it fails in 3.6 active-failover (BTS-362) - final LogEntity logs = arangoDB.getLogs(null); - assertThat(logs.getLid()).isNotEmpty(); - final LogEntity logsSize = arangoDB.getLogs(new LogOptions().size(logs.getLid().size() - 1)); - assertThat(logsSize.getLid()).hasSize(logs.getLid().size() - 1); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("arangos") - void getLogsOffset(ArangoDB arangoDB) { - assumeTrue(isAtLeastVersion(3, 7)); // it fails in 3.6 active-failover (BTS-362) - assumeTrue(isLessThanVersion(3, 9)); // deprecated - final LogEntity logs = arangoDB.getLogs(null); - assertThat(logs.getTotalAmount()).isPositive(); - final LogEntity logsOffset = arangoDB.getLogs(new LogOptions().offset(1)); - assertThat(logsOffset.getLid()) - .isNotEmpty() - .doesNotContain(logs.getLid().get(0)); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("arangos") - void getLogsSearch(ArangoDB arangoDB) { - assumeTrue(isAtLeastVersion(3, 7)); // it fails in 3.6 active-failover (BTS-362) - final LogEntity logs = arangoDB.getLogs(null); - final LogEntity logsSearch = arangoDB.getLogs(new LogOptions().search(TEST_DB.get())); - assertThat(logs.getTotalAmount()).isGreaterThan(logsSearch.getTotalAmount()); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("arangos") - void getLogsSortAsc(ArangoDB arangoDB) { - assumeTrue(isAtLeastVersion(3, 7)); // it fails in 3.6 active-failover (BTS-362) - final LogEntity logs = arangoDB.getLogs(new LogOptions().sort(SortOrder.asc)); - long lastId = -1; - for (final Long id : logs.getLid()) { - assertThat(id).isGreaterThan(lastId); - lastId = id; - } - } - - @ParameterizedTest(name = "{index}") - @MethodSource("arangos") - void getLogsSortDesc(ArangoDB arangoDB) { - assumeTrue(isAtLeastVersion(3, 7)); // it fails in 3.6 active-failover (BTS-362) - final LogEntity logs = arangoDB.getLogs(new LogOptions().sort(SortOrder.desc)); - long lastId = Long.MAX_VALUE; - for (final Long id : logs.getLid()) { - assertThat(lastId).isGreaterThan(id); - lastId = id; - } - } - @ParameterizedTest(name = "{index}") @MethodSource("arangos") void getLogEntries(ArangoDB arangoDB) { diff --git a/src/test/java/com/arangodb/ArangoDatabaseTest.java b/src/test/java/com/arangodb/ArangoDatabaseTest.java index 4d6c5b10d..35073c24b 100644 --- a/src/test/java/com/arangodb/ArangoDatabaseTest.java +++ b/src/test/java/com/arangodb/ArangoDatabaseTest.java @@ -25,7 +25,6 @@ import com.arangodb.entity.CursorEntity.Warning; import com.arangodb.entity.QueryCachePropertiesEntity.CacheMode; import com.arangodb.model.*; -import com.arangodb.model.TraversalOptions.Direction; import com.arangodb.util.MapBuilder; import com.arangodb.velocypack.VPackBuilder; import com.arangodb.velocypack.VPackSlice; @@ -1297,52 +1296,6 @@ void getInfo(ArangoDatabase db) { } } - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void executeTraversal(ArangoDatabase db) { - String k1 = "key-" + rnd(); - String k2 = "key-" + rnd(); - String k3 = "key-" + rnd(); - String k4 = "key-" + rnd(); - String k5 = "key-" + rnd(); - - for (final String e : new String[]{ - k1, k2, k3, k4, k5 - }) { - db.collection(CNAME1).insertDocument(new BaseDocument(e), null); - } - for (final String[] e : new String[][]{ - new String[]{k1, k2}, new String[]{k2, k3}, - new String[]{k2, k4}, new String[]{k5, k1}, new String[]{k5, k2} - }) { - final BaseEdgeDocument edge = new BaseEdgeDocument(); - edge.setKey(e[0] + "_knows_" + e[1]); - edge.setFrom(CNAME1 + "/" + e[0]); - edge.setTo(CNAME1 + "/" + e[1]); - db.collection(ENAMES).insertDocument(edge, null); - } - - final TraversalOptions options = new TraversalOptions().edgeCollection(ENAMES).startVertex(CNAME1 + "/" + k1).direction(Direction.outbound); - final TraversalEntity traversal = db.executeTraversal(BaseDocument.class, BaseEdgeDocument.class, options); - assertThat(traversal).isNotNull(); - - final Collection vertices = traversal.getVertices(); - assertThat(vertices).hasSize(4); - - final Iterator verticesIterator = vertices.iterator(); - final Collection v = Arrays.asList(k1, k2, k3, k4); - while (verticesIterator.hasNext()) { - assertThat(v).contains(verticesIterator.next().getKey()); - } - - final Collection> paths = traversal.getPaths(); - assertThat(paths).hasSize(4); - final PathEntity first = paths.iterator().next(); - assertThat(first.getEdges()).isEmpty(); - assertThat(first.getVertices()).hasSize(1); - assertThat(first.getVertices().iterator().next().getKey()).isEqualTo(k1); - } - @ParameterizedTest(name = "{index}") @MethodSource("dbs") void getDocument(ArangoDatabase db) { diff --git a/src/test/java/com/arangodb/async/ArangoCollectionTest.java b/src/test/java/com/arangodb/async/ArangoCollectionTest.java index 541d147ae..d7dfbdec2 100644 --- a/src/test/java/com/arangodb/async/ArangoCollectionTest.java +++ b/src/test/java/com/arangodb/async/ArangoCollectionTest.java @@ -2105,20 +2105,6 @@ void replaceDocumentsWithoutKey() throws InterruptedException, ExecutionExceptio .get(); } - @Test - void load() throws InterruptedException, ExecutionException { - db.collection(COLLECTION_NAME).load() - .whenComplete((result, ex) -> assertThat(result.getName()).isEqualTo(COLLECTION_NAME)) - .get(); - } - - @Test - void unload() throws InterruptedException, ExecutionException { - db.collection(COLLECTION_NAME).unload() - .whenComplete((result, ex) -> assertThat(result.getName()).isEqualTo(COLLECTION_NAME)) - .get(); - } - @Test void getInfo() throws InterruptedException, ExecutionException { db.collection(COLLECTION_NAME).getInfo() @@ -2145,7 +2131,6 @@ void changeProperties() throws InterruptedException, ExecutionException { assertThat(properties.getWaitForSync()).isNotNull(); final CollectionPropertiesOptions options = new CollectionPropertiesOptions(); options.waitForSync(!properties.getWaitForSync()); - options.journalSize(2000000L); db.collection(collection).changeProperties(options) .whenComplete((changedProperties, ex) -> { assertThat(changedProperties.getWaitForSync()).isNotNull(); diff --git a/src/test/java/com/arangodb/async/ArangoDBTest.java b/src/test/java/com/arangodb/async/ArangoDBTest.java index 89ea13f5f..6b7f7321c 100644 --- a/src/test/java/com/arangodb/async/ArangoDBTest.java +++ b/src/test/java/com/arangodb/async/ArangoDBTest.java @@ -24,7 +24,6 @@ import com.arangodb.entity.*; import com.arangodb.mapping.ArangoJack; import com.arangodb.model.*; -import com.arangodb.model.LogOptions.SortOrder; import com.arangodb.util.TestUtils; import com.arangodb.velocypack.exception.VPackException; import com.arangodb.velocystream.Request; @@ -460,129 +459,6 @@ void execute_acquireHostList_enabled() throws VPackException, InterruptedExcepti .get(); } - @Test - void getLogs() throws InterruptedException, ExecutionException { - assumeTrue(isAtLeastVersion(3, 7)); // it fails in 3.6 active-failover (BTS-362) - arangoDB.getLogs(null) - .whenComplete((logs, ex) -> { - assertThat(logs).isNotNull(); - assertThat(logs.getTotalAmount()).isPositive(); - assertThat((long) logs.getLid().size()).isEqualTo(logs.getTotalAmount()); - assertThat((long) logs.getLevel().size()).isEqualTo(logs.getTotalAmount()); - assertThat((long) logs.getTimestamp().size()).isEqualTo(logs.getTotalAmount()); - assertThat((long) logs.getText().size()).isEqualTo(logs.getTotalAmount()); - }) - .get(); - } - - @Test - void getLogsUpto() throws InterruptedException, ExecutionException { - assumeTrue(isAtLeastVersion(3, 7)); // it fails in 3.6 active-failover (BTS-362) - final LogEntity logs = arangoDB.getLogs(null).get(); - arangoDB.getLogs(new LogOptions().upto(LogLevel.WARNING)) - .whenComplete((logsUpto, ex) -> { - assertThat(logsUpto).isNotNull(); - assertThat(logs.getTotalAmount() >= logsUpto.getTotalAmount()).isTrue(); - assertThat(logsUpto.getLevel()).doesNotContain(LogLevel.INFO); - }) - .get(); - } - - @Test - void getLogsLevel() throws InterruptedException, ExecutionException { - assumeTrue(isAtLeastVersion(3, 7)); // it fails in 3.6 active-failover (BTS-362) - final LogEntity logs = arangoDB.getLogs(null).get(); - arangoDB.getLogs(new LogOptions().level(LogLevel.INFO)) - .whenComplete((logsInfo, ex) -> { - assertThat(logsInfo).isNotNull(); - assertThat(logs.getTotalAmount() >= logsInfo.getTotalAmount()).isTrue(); - assertThat(logsInfo.getLevel()).containsOnly(LogLevel.INFO); - }) - .get(); - } - - @Test - void getLogsStart() throws InterruptedException, ExecutionException { - assumeTrue(isAtLeastVersion(3, 7)); // it fails in 3.6 active-failover (BTS-362) - final LogEntity logs = arangoDB.getLogs(null).get(); - assertThat(logs.getLid()).isNotEmpty(); - arangoDB.getLogs(new LogOptions().start(logs.getLid().get(0) + 1)) - .whenComplete((logsStart, ex) -> { - assertThat(logsStart).isNotNull(); - assertThat(logsStart.getLid()).doesNotContain(logs.getLid().get(0)); - }) - .get(); - } - - @Test - void getLogsSize() throws InterruptedException, ExecutionException { - assumeTrue(isAtLeastVersion(3, 7)); // it fails in 3.6 active-failover (BTS-362) - final LogEntity logs = arangoDB.getLogs(null).get(); - assertThat(logs.getLid()).isNotEmpty(); - arangoDB.getLogs(new LogOptions().size(logs.getLid().size() - 1)) - .whenComplete((logsSize, ex) -> { - assertThat(logsSize).isNotNull(); - assertThat(logsSize.getLid()).hasSize(logs.getLid().size() - 1); - }) - .get(); - } - - @Test - void getLogsOffset() throws InterruptedException, ExecutionException { - assumeTrue(isAtLeastVersion(3, 7)); // it fails in 3.6 active-failover (BTS-362) - assumeTrue(isLessThanVersion(3, 9)); // deprecated - final LogEntity logs = arangoDB.getLogs(null).get(); - assertThat(logs.getTotalAmount()).isPositive(); - arangoDB.getLogs(new LogOptions().offset((int) (logs.getTotalAmount() - 1))) - .whenComplete((logsOffset, ex) -> { - assertThat(logsOffset).isNotNull(); - assertThat(logsOffset.getLid()).hasSize(1); - }) - .get(); - } - - @Test - void getLogsSearch() throws InterruptedException, ExecutionException { - assumeTrue(isAtLeastVersion(3, 7)); // it fails in 3.6 active-failover (BTS-362) - final LogEntity logs = arangoDB.getLogs(null).get(); - arangoDB.getLogs(new LogOptions().search(BaseTest.TEST_DB.get())) - .whenComplete((logsSearch, ex) -> { - assertThat(logsSearch).isNotNull(); - assertThat(logs.getTotalAmount()).isGreaterThan(logsSearch.getTotalAmount()); - }) - .get(); - } - - @Test - void getLogsSortAsc() throws InterruptedException, ExecutionException { - assumeTrue(isAtLeastVersion(3, 7)); // it fails in 3.6 active-failover (BTS-362) - arangoDB.getLogs(new LogOptions().sort(SortOrder.asc)) - .whenComplete((logs, ex) -> { - assertThat(logs).isNotNull(); - long lastId = -1; - for (final Long id : logs.getLid()) { - assertThat(id).isGreaterThan(lastId); - lastId = id; - } - }) - .get(); - } - - @Test - void getLogsSortDesc() throws InterruptedException, ExecutionException { - assumeTrue(isAtLeastVersion(3, 7)); // it fails in 3.6 active-failover (BTS-362) - arangoDB.getLogs(new LogOptions().sort(SortOrder.desc)) - .whenComplete((logs, ex) -> { - assertThat(logs).isNotNull(); - long lastId = Long.MAX_VALUE; - for (final Long id : logs.getLid()) { - assertThat(lastId).isGreaterThan(id); - lastId = id; - } - }) - .get(); - } - @Test void getLogEntries() throws InterruptedException, ExecutionException { assumeTrue(isAtLeastVersion(3, 8)); @@ -595,18 +471,6 @@ void getLogEntries() throws InterruptedException, ExecutionException { .get(); } - @Test - void getLogEntriesSearch() throws InterruptedException, ExecutionException { - assumeTrue(isAtLeastVersion(3, 8)); - final LogEntriesEntity logs = arangoDB.getLogEntries(null).get(); - arangoDB.getLogs(new LogOptions().search(BaseTest.TEST_DB.get())) - .whenComplete((logsSearch, ex) -> { - assertThat(logsSearch).isNotNull(); - assertThat(logs.getTotal()).isGreaterThan(logsSearch.getTotalAmount()); - }) - .get(); - } - @Test void getLogLevel() throws InterruptedException, ExecutionException { assumeTrue(isAtLeastVersion(3, 7)); // it fails in 3.6 active-failover (BTS-362) diff --git a/src/test/java/com/arangodb/async/ArangoDatabaseTest.java b/src/test/java/com/arangodb/async/ArangoDatabaseTest.java index de76da620..b58e1e6ef 100644 --- a/src/test/java/com/arangodb/async/ArangoDatabaseTest.java +++ b/src/test/java/com/arangodb/async/ArangoDatabaseTest.java @@ -27,7 +27,6 @@ import com.arangodb.entity.AqlParseEntity.AstNode; import com.arangodb.entity.QueryCachePropertiesEntity.CacheMode; import com.arangodb.model.*; -import com.arangodb.model.TraversalOptions.Direction; import com.arangodb.velocypack.VPackBuilder; import com.arangodb.velocypack.VPackSlice; import com.arangodb.velocypack.exception.VPackException; @@ -966,58 +965,6 @@ void getInfo() throws InterruptedException, ExecutionException { f.get(); } - @Test - void executeTraversal() throws InterruptedException, ExecutionException { - try { - db.createCollection("person", null).get(); - db.createCollection("knows", new CollectionCreateOptions().type(CollectionType.EDGES)).get(); - for (final String e : new String[]{"Alice", "Bob", "Charlie", "Dave", "Eve"}) { - final BaseDocument doc = new BaseDocument(); - doc.setKey(e); - db.collection("person").insertDocument(doc, null).get(); - } - for (final String[] e : new String[][]{new String[]{"Alice", "Bob"}, new String[]{"Bob", "Charlie"}, - new String[]{"Bob", "Dave"}, new String[]{"Eve", "Alice"}, new String[]{"Eve", "Bob"}}) { - final BaseEdgeDocument edge = new BaseEdgeDocument(); - edge.setKey(e[0] + "_knows_" + e[1]); - edge.setFrom("person/" + e[0]); - edge.setTo("person/" + e[1]); - db.collection("knows").insertDocument(edge, null).get(); - } - final TraversalOptions options = new TraversalOptions().edgeCollection("knows").startVertex("person/Alice") - .direction(Direction.outbound); - db.executeTraversal(BaseDocument.class, BaseEdgeDocument.class, options) - .whenComplete((traversal, ex) -> { - assertThat(traversal).isNotNull(); - - final Collection vertices = traversal.getVertices(); - assertThat(vertices).isNotNull(); - assertThat(vertices.size()).isEqualTo(4); - - final Iterator verticesIterator = vertices.iterator(); - final Collection v = Arrays.asList("Alice", "Bob", "Charlie", "Dave"); - while (verticesIterator.hasNext()) { - assertThat(v.contains(verticesIterator.next().getKey())).isEqualTo(true); - } - - final Collection> paths = traversal.getPaths(); - assertThat(paths).isNotNull(); - assertThat(paths.size()).isEqualTo(4); - - assertThat(paths.iterator().hasNext()).isEqualTo(true); - final PathEntity first = paths.iterator().next(); - assertThat(first).isNotNull(); - assertThat(first.getEdges().size()).isEqualTo(0); - assertThat(first.getVertices().size()).isEqualTo(1); - assertThat(first.getVertices().iterator().next().getKey()).isEqualTo("Alice"); - }) - .get(); - } finally { - db.collection("person").drop().get(); - db.collection("knows").drop().get(); - } - } - @Test void getDocument() throws InterruptedException, ExecutionException { String collectionName = COLLECTION_NAME + "getDocument"; From 9c6ff4db9362287a7e2f0ccb4406eaa992204313 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Thu, 23 Jun 2022 10:30:40 +0200 Subject: [PATCH 003/254] fixed importDocuments overwrite --- .../java/com/arangodb/internal/InternalArangoCollection.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/arangodb/internal/InternalArangoCollection.java b/src/main/java/com/arangodb/internal/InternalArangoCollection.java index 5099a443c..70b32b23c 100644 --- a/src/main/java/com/arangodb/internal/InternalArangoCollection.java +++ b/src/main/java/com/arangodb/internal/InternalArangoCollection.java @@ -56,6 +56,7 @@ public abstract class InternalArangoCollection, D private static final String RETURN_NEW = "returnNew"; private static final String NEW = "new"; private static final String RETURN_OLD = "returnOld"; + private static final String OVERWRITE = "overwrite"; private static final String OVERWRITE_MODE = "overwriteMode"; private static final String OLD = "old"; private static final String SILENT = "silent"; @@ -192,7 +193,7 @@ protected Request importDocumentsRequest(final DocumentImportOptions options) { return request(db.dbName(), RequestType.POST, PATH_API_IMPORT).putQueryParam(COLLECTION, name) .putQueryParam(ArangoRequestParam.WAIT_FOR_SYNC, params.getWaitForSync()) .putQueryParam("fromPrefix", params.getFromPrefix()).putQueryParam("toPrefix", params.getToPrefix()) - .putQueryParam("onDuplicate", params.getOnDuplicate()) + .putQueryParam(OVERWRITE, params.getOverwrite()).putQueryParam("onDuplicate", params.getOnDuplicate()) .putQueryParam("complete", params.getComplete()).putQueryParam("details", params.getDetails()); } From e466421d119d6f5321dc97f1a717f069c6ca435a Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Thu, 23 Jun 2022 21:40:17 +0200 Subject: [PATCH 004/254] [DE-220] removed deprecated ArangoSearch client API (#443) * removed deprecated ArangoSearch client API * removed deprecated entities methods * removed deprecated ArangoCursor methods * removed deprecated DocumentField annotations * removed deprecated methods handling db names as strings * removed deprecated serialization customization methods --- src/main/java/com/arangodb/ArangoDB.java | 364 +----------------- .../java/com/arangodb/ArangoDatabase.java | 75 ---- .../java/com/arangodb/ArangoIterable.java | 98 ----- src/main/java/com/arangodb/Consumer.java | 38 -- src/main/java/com/arangodb/Predicate.java | 39 -- .../com/arangodb/async/ArangoDBAsync.java | 342 ---------------- .../arangodb/async/ArangoDatabaseAsync.java | 70 ---- .../internal/ArangoDatabaseAsyncImpl.java | 31 +- .../com/arangodb/entity/DocumentField.java | 83 ---- .../entity/arangosearch/AnalyzerEntity.java | 75 ---- .../analyzer/StopwordsAnalyzerProperties.java | 9 - .../arangodb/internal/ArangoDatabaseImpl.java | 30 +- .../com/arangodb/internal/DocumentCache.java | 4 +- .../internal/InternalArangoDatabase.java | 14 - .../cursor/AbstractArangoIterable.java | 74 ---- .../internal/cursor/ArangoCursorImpl.java | 8 - .../internal/cursor/ArangoFilterIterable.java | 57 --- .../internal/cursor/ArangoFilterIterator.java | 73 ---- .../cursor/ArangoMappingIterable.java | 55 --- .../cursor/ArangoMappingIterator.java | 55 --- .../mapping/ArangoAnnotationIntrospector.java | 6 - .../velocypack/VPackDriverModule.java | 4 +- .../model/CollectionCreateOptions.java | 10 - .../com/arangodb/model/DBCreateOptions.java | 10 - .../com/arangodb/velocystream/Request.java | 16 - .../java/com/arangodb/ArangoCursorTest.java | 173 +-------- .../java/com/arangodb/ArangoSearchTest.java | 262 +------------ .../com/arangodb/async/ArangoSearchTest.java | 194 +--------- .../com/arangodb/example/ExampleBase.java | 10 +- .../com/arangodb/example/FirstProject.java | 7 +- .../annotations/ArangoAnnotationsTest.java | 24 -- .../annotations/DocumentFieldEntity.java | 112 ------ 32 files changed, 25 insertions(+), 2397 deletions(-) delete mode 100644 src/main/java/com/arangodb/Consumer.java delete mode 100644 src/main/java/com/arangodb/Predicate.java delete mode 100644 src/main/java/com/arangodb/entity/DocumentField.java delete mode 100644 src/main/java/com/arangodb/entity/arangosearch/AnalyzerEntity.java delete mode 100644 src/main/java/com/arangodb/internal/cursor/ArangoFilterIterable.java delete mode 100644 src/main/java/com/arangodb/internal/cursor/ArangoFilterIterator.java delete mode 100644 src/main/java/com/arangodb/internal/cursor/ArangoMappingIterable.java delete mode 100644 src/main/java/com/arangodb/internal/cursor/ArangoMappingIterator.java delete mode 100644 src/test/java/com/arangodb/mapping/annotations/DocumentFieldEntity.java diff --git a/src/main/java/com/arangodb/ArangoDB.java b/src/main/java/com/arangodb/ArangoDB.java index d429754b3..f58064a08 100644 --- a/src/main/java/com/arangodb/ArangoDB.java +++ b/src/main/java/com/arangodb/ArangoDB.java @@ -27,11 +27,7 @@ import com.arangodb.internal.InternalArangoDBBuilder; import com.arangodb.internal.http.HttpCommunication; import com.arangodb.internal.http.HttpConnectionFactory; -import com.arangodb.internal.net.ConnectionFactory; -import com.arangodb.internal.net.Host; -import com.arangodb.internal.net.HostHandle; -import com.arangodb.internal.net.HostHandler; -import com.arangodb.internal.net.HostResolver; +import com.arangodb.internal.net.*; import com.arangodb.internal.util.ArangoDeserializerImpl; import com.arangodb.internal.util.ArangoSerializationFactory; import com.arangodb.internal.util.ArangoSerializerImpl; @@ -42,19 +38,12 @@ import com.arangodb.model.LogOptions; import com.arangodb.model.UserCreateOptions; import com.arangodb.model.UserUpdateOptions; -import com.arangodb.util.*; +import com.arangodb.util.ArangoCursorInitializer; +import com.arangodb.util.ArangoDeserializer; +import com.arangodb.util.ArangoSerialization; +import com.arangodb.util.ArangoSerializer; import com.arangodb.velocypack.VPack; -import com.arangodb.velocypack.VPackAnnotationFieldFilter; -import com.arangodb.velocypack.VPackAnnotationFieldNaming; -import com.arangodb.velocypack.VPackDeserializer; -import com.arangodb.velocypack.VPackInstanceCreator; -import com.arangodb.velocypack.VPackJsonDeserializer; -import com.arangodb.velocypack.VPackJsonSerializer; -import com.arangodb.velocypack.VPackModule; import com.arangodb.velocypack.VPackParser; -import com.arangodb.velocypack.VPackParserModule; -import com.arangodb.velocypack.VPackSerializer; -import com.arangodb.velocypack.ValueType; import com.arangodb.velocystream.Request; import com.arangodb.velocystream.Response; import org.apache.http.client.HttpRequestRetryHandler; @@ -64,7 +53,6 @@ import javax.net.ssl.HostnameVerifier; import javax.net.ssl.SSLContext; import java.io.InputStream; -import java.lang.annotation.Annotation; import java.util.Collection; import java.util.Locale; import java.util.Properties; @@ -339,321 +327,6 @@ public Builder responseQueueTimeSamples(final Integer responseQueueTimeSamples) return this; } - /** - * Register a custom {@link VPackSerializer} for a specific type to be used within the internal serialization - * process. - * - *

- * Attention:can not be used together with {@link #serializer(ArangoSerialization)} - *

- * - * @param clazz the type the serializer should be registered for - * @param serializer serializer to register - * @return {@link ArangoDB.Builder} - * @deprecated Use {@link com.arangodb.mapping.ArangoJack} instead and register custom serializers and deserializers by implementing {@link com.fasterxml.jackson.databind.JsonSerializer} and {@link com.fasterxml.jackson.databind.JsonDeserializer}. - * @see Reference Documentation - */ - @Deprecated - public Builder registerSerializer(final Class clazz, final VPackSerializer serializer) { - vpackBuilder.registerSerializer(clazz, serializer); - return this; - } - - /** - * Register a special serializer for a member class which can only be identified by its enclosing class. - * - *

- * Attention:can not be used together with {@link #serializer(ArangoSerialization)} - *

- * - * @param clazz the type of the enclosing class - * @param serializer serializer to register - * @return {@link ArangoDB.Builder} - * @deprecated Use {@link com.arangodb.mapping.ArangoJack} instead and register custom serializers and deserializers by implementing {@link com.fasterxml.jackson.databind.JsonSerializer} and {@link com.fasterxml.jackson.databind.JsonDeserializer}. - * @see Reference Documentation - */ - @Deprecated - public Builder registerEnclosingSerializer(final Class clazz, final VPackSerializer serializer) { - vpackBuilder.registerEnclosingSerializer(clazz, serializer); - return this; - } - - /** - * Register a custom {@link VPackDeserializer} for a specific type to be used within the internal serialization - * process. - * - *

- * Attention:can not be used together with {@link #serializer(ArangoSerialization)} - *

- * - * @param clazz the type the serializer should be registered for - * @param deserializer - * @return {@link ArangoDB.Builder} - * @deprecated Use {@link com.arangodb.mapping.ArangoJack} instead and register custom serializers and deserializers by implementing {@link com.fasterxml.jackson.databind.JsonSerializer} and {@link com.fasterxml.jackson.databind.JsonDeserializer}. - * @see Reference Documentation - */ - @Deprecated - public Builder registerDeserializer(final Class clazz, final VPackDeserializer deserializer) { - vpackBuilder.registerDeserializer(clazz, deserializer); - return this; - } - - /** - * Register a custom {@link VPackInstanceCreator} for a specific type to be used within the internal - * serialization process. - * - *

- * Attention:can not be used together with {@link #serializer(ArangoSerialization)} - *

- * - * @param clazz the type the instance creator should be registered for - * @param creator - * @return {@link ArangoDB.Builder} - * @deprecated Use {@link com.arangodb.mapping.ArangoJack} instead and register custom serializers and deserializers by implementing {@link com.fasterxml.jackson.databind.JsonSerializer} and {@link com.fasterxml.jackson.databind.JsonDeserializer}. - * @see Reference Documentation - */ - @Deprecated - public Builder registerInstanceCreator(final Class clazz, final VPackInstanceCreator creator) { - vpackBuilder.registerInstanceCreator(clazz, creator); - return this; - } - - /** - * Register a custom {@link VPackJsonDeserializer} for a specific type to be used within the internal - * serialization process. - * - *

- * Attention:can not be used together with {@link #serializer(ArangoSerialization)} - *

- * - * @param type the type the serializer should be registered for - * @param deserializer - * @return {@link ArangoDB.Builder} - * @deprecated Use {@link com.arangodb.mapping.ArangoJack} instead and register custom serializers and deserializers by implementing {@link com.fasterxml.jackson.databind.JsonSerializer} and {@link com.fasterxml.jackson.databind.JsonDeserializer}. - * @see Reference Documentation - */ - @Deprecated - public Builder registerJsonDeserializer(final ValueType type, final VPackJsonDeserializer deserializer) { - vpackParserBuilder.registerDeserializer(type, deserializer); - return this; - } - - /** - * Register a custom {@link VPackJsonDeserializer} for a specific type and attribute name to be used within the - * internal serialization process. - * - *

- * Attention:can not be used together with {@link #serializer(ArangoSerialization)} - *

- * - * @param attribute - * @param type the type the serializer should be registered for - * @param deserializer - * @return {@link ArangoDB.Builder} - * @deprecated Use {@link com.arangodb.mapping.ArangoJack} instead and register custom serializers and deserializers by implementing {@link com.fasterxml.jackson.databind.JsonSerializer} and {@link com.fasterxml.jackson.databind.JsonDeserializer}. - * @see Reference Documentation - */ - @Deprecated - public Builder registerJsonDeserializer( - final String attribute, - final ValueType type, - final VPackJsonDeserializer deserializer) { - vpackParserBuilder.registerDeserializer(attribute, type, deserializer); - return this; - } - - /** - * Register a custom {@link VPackJsonSerializer} for a specific type to be used within the internal - * serialization process. - * - *

- * Attention:can not be used together with {@link #serializer(ArangoSerialization)} - *

- * - * @param clazz the type the serializer should be registered for - * @param serializer - * @return {@link ArangoDB.Builder} - * @deprecated Use {@link com.arangodb.mapping.ArangoJack} instead and register custom serializers and deserializers by implementing {@link com.fasterxml.jackson.databind.JsonSerializer} and {@link com.fasterxml.jackson.databind.JsonDeserializer}. - * @see Reference Documentation - */ - @Deprecated - public Builder registerJsonSerializer(final Class clazz, final VPackJsonSerializer serializer) { - vpackParserBuilder.registerSerializer(clazz, serializer); - return this; - } - - /** - * Register a custom {@link VPackJsonSerializer} for a specific type and attribute name to be used within the - * internal serialization process. - * - *

- * Attention:can not be used together with {@link #serializer(ArangoSerialization)} - *

- * - * @param attribute - * @param clazz the type the serializer should be registered for - * @param serializer - * @return {@link ArangoDB.Builder} - * @deprecated Use {@link com.arangodb.mapping.ArangoJack} instead and register custom serializers and deserializers by implementing {@link com.fasterxml.jackson.databind.JsonSerializer} and {@link com.fasterxml.jackson.databind.JsonDeserializer}. - * @see Reference Documentation - */ - @Deprecated - public Builder registerJsonSerializer( - final String attribute, - final Class clazz, - final VPackJsonSerializer serializer) { - vpackParserBuilder.registerSerializer(attribute, clazz, serializer); - return this; - } - - /** - * Register a custom {@link VPackAnnotationFieldFilter} for a specific type to be used within the internal - * serialization process. - * - *

- * Attention:can not be used together with {@link #serializer(ArangoSerialization)} - *

- * - * @param type the type the serializer should be registered for - * @param fieldFilter - * @return {@link ArangoDB.Builder} - * @deprecated Use {@link com.arangodb.mapping.ArangoJack} instead and register custom serializers and deserializers by implementing {@link com.fasterxml.jackson.databind.JsonSerializer} and {@link com.fasterxml.jackson.databind.JsonDeserializer}. - * @see Reference Documentation - */ - @Deprecated - public Builder annotationFieldFilter( - final Class type, - final VPackAnnotationFieldFilter fieldFilter) { - vpackBuilder.annotationFieldFilter(type, fieldFilter); - return this; - } - - /** - * Register a custom {@link VPackAnnotationFieldNaming} for a specific type to be used within the internal - * serialization process. - * - *

- * Attention:can not be used together with {@link #serializer(ArangoSerialization)} - *

- * - * @param type the type the serializer should be registered for - * @param fieldNaming - * @return {@link ArangoDB.Builder} - * @deprecated Use {@link com.arangodb.mapping.ArangoJack} instead and register custom serializers and deserializers by implementing {@link com.fasterxml.jackson.databind.JsonSerializer} and {@link com.fasterxml.jackson.databind.JsonDeserializer}. - * @see
Reference Documentation - */ - @Deprecated - public Builder annotationFieldNaming( - final Class type, - final VPackAnnotationFieldNaming fieldNaming) { - vpackBuilder.annotationFieldNaming(type, fieldNaming); - return this; - } - - /** - * Register a {@link VPackModule} to be used within the internal serialization process. - * - *

- * Attention:can not be used together with {@link #serializer(ArangoSerialization)} - *

- * - * @param module module to register - * @return {@link ArangoDB.Builder} - * @deprecated Use {@link com.arangodb.mapping.ArangoJack} instead and register custom modules. - * @see
Reference Documentation - */ - @Deprecated - public Builder registerModule(final VPackModule module) { - vpackBuilder.registerModule(module); - return this; - } - - /** - * Register a list of {@link VPackModule} to be used within the internal serialization process. - * - *

- * Attention:can not be used together with {@link #serializer(ArangoSerialization)} - *

- * - * @param modules modules to register - * @return {@link ArangoDB.Builder} - * @deprecated Use {@link com.arangodb.mapping.ArangoJack} instead and register custom modules. - * @see Reference Documentation - */ - @Deprecated - public Builder registerModules(final VPackModule... modules) { - vpackBuilder.registerModules(modules); - return this; - } - - /** - * Register a {@link VPackParserModule} to be used within the internal serialization process. - * - *

- * Attention:can not be used together with {@link #serializer(ArangoSerialization)} - *

- * - * @param module module to register - * @return {@link ArangoDB.Builder} - * @deprecated Use {@link com.arangodb.mapping.ArangoJack} instead and register custom modules. - * @see Reference Documentation - */ - @Deprecated - public Builder registerJsonModule(final VPackParserModule module) { - vpackParserBuilder.registerModule(module); - return this; - } - - /** - * Register a list of {@link VPackParserModule} to be used within the internal serialization process. - * - *

- * Attention:can not be used together with {@link #serializer(ArangoSerialization)} - *

- * - * @param modules modules to register - * @return {@link ArangoDB.Builder} - * @deprecated Use {@link com.arangodb.mapping.ArangoJack} instead and register custom modules. - * @see Reference Documentation - */ - @Deprecated - public Builder registerJsonModules(final VPackParserModule... modules) { - vpackParserBuilder.registerModules(modules); - return this; - } - - /** - * Replace the built-in serializer with the given serializer. - *

- *
- * ATTENTION!: Use at your own risk - * - * @param serializer custom serializer - * @return {@link ArangoDB.Builder} - * @deprecated use {@link #serializer(ArangoSerialization)} instead - */ - @Deprecated - public Builder setSerializer(final ArangoSerializer serializer) { - serializer(serializer); - return this; - } - - /** - * Replace the built-in deserializer with the given deserializer. - *

- *
- * ATTENTION!: Use at your own risk - * - * @param deserializer custom deserializer - * @return {@link ArangoDB.Builder} - * @deprecated use {@link #serializer(ArangoSerialization)} instead - */ - @Deprecated - public Builder setDeserializer(final ArangoDeserializer deserializer) { - deserializer(deserializer); - return this; - } - /** * Replace the built-in serializer/deserializer with the given one. *

@@ -746,18 +419,6 @@ public synchronized ArangoDB build() { */ ArangoDatabase db(); - /** - * Returns a {@code ArangoDatabase} instance for the given database name. - * - * @param name Name of the database - * @return database handler - * @deprecated Use {@link #db(DbName)} instead - */ - @Deprecated - default ArangoDatabase db(String name) { - return db(DbName.of(name)); - } - /** * Returns a {@code ArangoDatabase} instance for the given database name. * @@ -771,21 +432,6 @@ default ArangoDatabase db(String name) { */ ArangoMetrics metrics(); - /** - * Creates a new database with the given name. - * - * @param name Name of the database to create - * @return true if the database was created successfully. - * @throws ArangoDBException - * @see API - * Documentation - * @deprecated Use {@link #createDatabase(DbName)} instead - */ - @Deprecated - default Boolean createDatabase(String name) throws ArangoDBException { - return createDatabase(DbName.of(name)); - } - /** * Creates a new database with the given name. * diff --git a/src/main/java/com/arangodb/ArangoDatabase.java b/src/main/java/com/arangodb/ArangoDatabase.java index d9d2a8eff..24146626c 100644 --- a/src/main/java/com/arangodb/ArangoDatabase.java +++ b/src/main/java/com/arangodb/ArangoDatabase.java @@ -21,7 +21,6 @@ package com.arangodb; import com.arangodb.entity.*; -import com.arangodb.entity.arangosearch.AnalyzerEntity; import com.arangodb.entity.arangosearch.analyzer.SearchAnalyzer; import com.arangodb.model.*; import com.arangodb.model.arangosearch.AnalyzerDeleteOptions; @@ -48,17 +47,6 @@ public interface ArangoDatabase extends ArangoSerializationAccessor { */ ArangoDB arango(); - /** - * Returns the name of the database - * - * @return database name - * @deprecated Use {@link #dbName()} instead - */ - @Deprecated - default String name() { - return dbName().get(); - } - /** * Returns the name of the database * @@ -719,19 +707,6 @@ GraphEntity createGraph(String name, Collection edgeDefinitions, */ ViewEntity createArangoSearch(String name, ArangoSearchCreateOptions options) throws ArangoDBException; - /** - * Creates an Analyzer - * - * @param options AnalyzerEntity - * @return the created Analyzer - * @throws ArangoDBException - * @see API Documentation - * @since ArangoDB 3.5.0 - * @deprecated use {@link this#createSearchAnalyzer(SearchAnalyzer)}} - */ - @Deprecated - AnalyzerEntity createAnalyzer(AnalyzerEntity options) throws ArangoDBException; - /** * Creates an Analyzer * @@ -743,19 +718,6 @@ GraphEntity createGraph(String name, Collection edgeDefinitions, */ SearchAnalyzer createSearchAnalyzer(SearchAnalyzer analyzer) throws ArangoDBException; - /** - * Gets information about an Analyzer - * - * @param name of the Analyzer without database prefix - * @return information about an Analyzer - * @throws ArangoDBException - * @see API Documentation - * @since ArangoDB 3.5.0 - * @deprecated use {@link this#getSearchAnalyzer(String)}} - */ - @Deprecated - AnalyzerEntity getAnalyzer(String name) throws ArangoDBException; - /** * Gets information about an Analyzer * @@ -767,18 +729,6 @@ GraphEntity createGraph(String name, Collection edgeDefinitions, */ SearchAnalyzer getSearchAnalyzer(String name) throws ArangoDBException; - /** - * Retrieves all analyzers definitions. - * - * @return collection of all analyzers definitions - * @throws ArangoDBException - * @see API Documentation - * @since ArangoDB 3.5.0 - * @deprecated use {@link this#getSearchAnalyzers()} - */ - @Deprecated - Collection getAnalyzers() throws ArangoDBException; - /** * Retrieves all analyzers definitions. * @@ -789,31 +739,6 @@ GraphEntity createGraph(String name, Collection edgeDefinitions, */ Collection getSearchAnalyzers() throws ArangoDBException; - /** - * Deletes an Analyzer - * - * @param name of the Analyzer without database prefix - * @throws ArangoDBException - * @see API Documentation - * @since ArangoDB 3.5.0 - * @deprecated use {@link this#deleteSearchAnalyzer(String)}}} - */ - @Deprecated - void deleteAnalyzer(String name) throws ArangoDBException; - - /** - * Deletes an Analyzer - * - * @param name of the Analyzer without database prefix - * @param options AnalyzerDeleteOptions - * @throws ArangoDBException - * @see API Documentation - * @since ArangoDB 3.5.0 - * @deprecated use {@link this#deleteSearchAnalyzer(String, AnalyzerDeleteOptions)}}} - */ - @Deprecated - void deleteAnalyzer(String name, AnalyzerDeleteOptions options) throws ArangoDBException; - /** * Deletes an Analyzer * diff --git a/src/main/java/com/arangodb/ArangoIterable.java b/src/main/java/com/arangodb/ArangoIterable.java index 40ab262bc..b0848c292 100644 --- a/src/main/java/com/arangodb/ArangoIterable.java +++ b/src/main/java/com/arangodb/ArangoIterable.java @@ -20,7 +20,6 @@ package com.arangodb; -import java.util.Collection; import java.util.stream.Stream; /** @@ -33,101 +32,4 @@ public interface ArangoIterable extends Iterable { Stream stream(); - /** - * Performs the given action for each element of the {@code ArangoIterable} - * - * @param action - * a action to perform on the elements - * @deprecated Use {@link #forEach(java.util.function.Consumer)} instead. - */ - @Deprecated - void foreach(Consumer action); - - /** - * Returns a {@code ArangoIterable} consisting of the results of applying the given function to the elements of this - * {@code ArangoIterable}. - * - * @param mapper - * a function to apply to each element - * @return the new {@code ArangoIterable} - * - * @deprecated Use {@link #stream()} and {@link Stream#map(java.util.function.Function)} instead. - */ - @Deprecated - ArangoIterable map(Function mapper); - - /** - * Returns a {@code ArangoIterable} consisting of the elements of this {@code ArangoIterable} that match the given - * predicate. - * - * @param predicate - * a predicate to apply to each element to determine if it should be included - * @return the new {@code ArangoIterable} - * - * @deprecated Use {@link #stream()} and {@link Stream#filter(java.util.function.Predicate)} instead. - */ - @Deprecated - ArangoIterable filter(Predicate predicate); - - /** - * Returns the first element or {@code null} if no element exists. - * - * @return first element or {@code null} - * @deprecated Use {@link #stream()} and {@link Stream#findFirst()} instead. - */ - @Deprecated - T first(); - - /** - * Returns the count of elements of this {@code ArangoIterable}. - * - * @return the count of elements - * @deprecated Use {@link #stream()} and {@link Stream#count()} instead. - */ - @Deprecated - long count(); - - /** - * Returns whether any elements of this {@code ArangoIterable} match the provided predicate. - * - * @param predicate a predicate to apply to elements of this {@code ArangoIterable} - * @return {@code true} if any elements of the {@code ArangoIterable} match the provided predicate, otherwise - * {@code false} - * @deprecated Use {@link #stream()} and {@link Stream#anyMatch(java.util.function.Predicate)} instead. - */ - @Deprecated - boolean anyMatch(Predicate predicate); - - /** - * Returns whether all elements of this {@code ArangoIterable} match the provided predicate. - * - * @param predicate a predicate to apply to elements of this {@code ArangoIterable} - * @return {@code true} if all elements of the {@code ArangoIterable} match the provided predicate, otherwise - * {@code false} - * @deprecated Use {@link #stream()} and {@link Stream#allMatch(java.util.function.Predicate)} instead. - */ - @Deprecated - boolean allMatch(Predicate predicate); - - /** - * Returns whether no elements of this {@code ArangoIterable} match the provided predicate. - * - * @param predicate a predicate to apply to elements of this {@code ArangoIterable} - * @return {@code true} if no elements of the {@code ArangoIterable} match the provided predicate, otherwise - * {@code false} - * @deprecated Use {@link #stream()} and {@link Stream#noneMatch(java.util.function.Predicate)} instead. - */ - @Deprecated - boolean noneMatch(Predicate predicate); - - /** - * Iterates over all elements of this {@code ArangoIterable} and adds each to the given target. - * - * @param target the collection to insert into - * @return the filled target - * @deprecated Use {@link #stream()} and {@link Stream#collect} instead. - */ - @Deprecated - > R collectInto(R target); - } diff --git a/src/main/java/com/arangodb/Consumer.java b/src/main/java/com/arangodb/Consumer.java deleted file mode 100644 index 3edbe3c4e..000000000 --- a/src/main/java/com/arangodb/Consumer.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2018 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb; - -/** - * @param the type of the input to the operation - * @author Mark Vollmary - * @deprecated Use {@link java.util.function.Consumer} instead. - */ -@Deprecated -public interface Consumer { - - /** - * Performs this operation on the given argument. - * - * @param t the input argument - */ - void accept(T t); - -} diff --git a/src/main/java/com/arangodb/Predicate.java b/src/main/java/com/arangodb/Predicate.java deleted file mode 100644 index 4c7257862..000000000 --- a/src/main/java/com/arangodb/Predicate.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2018 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb; - -/** - * @param the type of the input to the predicate - * @author Mark Vollmary - * @deprecated Use {@link java.util.function.Predicate} instead. - */ -@Deprecated -public interface Predicate { - - /** - * Evaluates this predicate on the given argument. - * - * @param t the input argument - * @return {@code true} if the input argument matches the predicate, otherwise {@code false} - */ - boolean test(T t); - -} diff --git a/src/main/java/com/arangodb/async/ArangoDBAsync.java b/src/main/java/com/arangodb/async/ArangoDBAsync.java index f809f78d8..8b3b0b75d 100644 --- a/src/main/java/com/arangodb/async/ArangoDBAsync.java +++ b/src/main/java/com/arangodb/async/ArangoDBAsync.java @@ -52,7 +52,6 @@ import javax.net.ssl.SSLContext; import java.io.InputStream; -import java.lang.annotation.Annotation; import java.util.Collection; import java.util.concurrent.CompletableFuture; @@ -89,18 +88,6 @@ public interface ArangoDBAsync extends ArangoSerializationAccessor { */ ArangoDatabaseAsync db(); - /** - * Returns a handler of the database by the given name - * - * @param name Name of the database - * @return database handler - * @deprecated Use {@link #db(DbName)} instead - */ - @Deprecated - default ArangoDatabaseAsync db(final String name) { - return db(DbName.of(name)); - } - /** * Returns a handler of the database by the given name * @@ -114,20 +101,6 @@ default ArangoDatabaseAsync db(final String name) { */ ArangoMetrics metrics(); - /** - * Creates a new database - * - * @param name Has to contain a valid database name - * @return true if the database was created successfully. - * @see API - * Documentation - * @deprecated Use {@link #createDatabase(DbName)} instead - */ - @Deprecated - default CompletableFuture createDatabase(final String name) { - return createDatabase(DbName.of(name)); - } - /** * Creates a new database * @@ -515,321 +488,6 @@ public Builder loadBalancingStrategy(final LoadBalancingStrategy loadBalancingSt return this; } - /** - * Register a custom {@link VPackSerializer} for a specific type to be used within the internal serialization - * process. - * - *

- * Attention:can not be used together with {@link #serializer(ArangoSerialization)} - *

- * - * @param clazz the type the serializer should be registered for - * @param serializer serializer to register - * @return {@link ArangoDBAsync.Builder} - * @deprecated Use {@link com.arangodb.mapping.ArangoJack} instead and register custom serializers and deserializers by implementing {@link com.fasterxml.jackson.databind.JsonSerializer} and {@link com.fasterxml.jackson.databind.JsonDeserializer}. - * @see Reference Documentation - */ - @Deprecated - public Builder registerSerializer(final Class clazz, final VPackSerializer serializer) { - vpackBuilder.registerSerializer(clazz, serializer); - return this; - } - - /** - * Register a special serializer for a member class which can only be identified by its enclosing class. - * - *

- * Attention:can not be used together with {@link #serializer(ArangoSerialization)} - *

- * - * @param clazz the type of the enclosing class - * @param serializer serializer to register - * @return {@link ArangoDBAsync.Builder} - * @deprecated Use {@link com.arangodb.mapping.ArangoJack} instead and register custom serializers and deserializers by implementing {@link com.fasterxml.jackson.databind.JsonSerializer} and {@link com.fasterxml.jackson.databind.JsonDeserializer}. - * @see Reference Documentation - */ - @Deprecated - public Builder registerEnclosingSerializer(final Class clazz, final VPackSerializer serializer) { - vpackBuilder.registerEnclosingSerializer(clazz, serializer); - return this; - } - - /** - * Register a custom {@link VPackDeserializer} for a specific type to be used within the internal serialization - * process. - * - *

- * Attention:can not be used together with {@link #serializer(ArangoSerialization)} - *

- * - * @param clazz the type the serializer should be registered for - * @param deserializer - * @return {@link ArangoDBAsync.Builder} - * @deprecated Use {@link com.arangodb.mapping.ArangoJack} instead and register custom serializers and deserializers by implementing {@link com.fasterxml.jackson.databind.JsonSerializer} and {@link com.fasterxml.jackson.databind.JsonDeserializer}. - * @see Reference Documentation - */ - @Deprecated - public Builder registerDeserializer(final Class clazz, final VPackDeserializer deserializer) { - vpackBuilder.registerDeserializer(clazz, deserializer); - return this; - } - - /** - * Register a custom {@link VPackInstanceCreator} for a specific type to be used within the internal - * serialization process. - * - *

- * Attention:can not be used together with {@link #serializer(ArangoSerialization)} - *

- * - * @param clazz the type the instance creator should be registered for - * @param creator - * @return {@link ArangoDBAsync.Builder} - * @deprecated Use {@link com.arangodb.mapping.ArangoJack} instead and register custom serializers and deserializers by implementing {@link com.fasterxml.jackson.databind.JsonSerializer} and {@link com.fasterxml.jackson.databind.JsonDeserializer}. - * @see Reference Documentation - */ - @Deprecated - public Builder registerInstanceCreator(final Class clazz, final VPackInstanceCreator creator) { - vpackBuilder.registerInstanceCreator(clazz, creator); - return this; - } - - /** - * Register a custom {@link VPackJsonDeserializer} for a specific type to be used within the internal - * serialization process. - * - *

- * Attention:can not be used together with {@link #serializer(ArangoSerialization)} - *

- * - * @param type the type the serializer should be registered for - * @param deserializer - * @return {@link ArangoDBAsync.Builder} - * @deprecated Use {@link com.arangodb.mapping.ArangoJack} instead and register custom serializers and deserializers by implementing {@link com.fasterxml.jackson.databind.JsonSerializer} and {@link com.fasterxml.jackson.databind.JsonDeserializer}. - * @see Reference Documentation - */ - @Deprecated - public Builder registerJsonDeserializer(final ValueType type, final VPackJsonDeserializer deserializer) { - vpackParserBuilder.registerDeserializer(type, deserializer); - return this; - } - - /** - * Register a custom {@link VPackJsonDeserializer} for a specific type and attribute name to be used within the - * internal serialization process. - * - *

- * Attention:can not be used together with {@link #serializer(ArangoSerialization)} - *

- * - * @param attribute - * @param type the type the serializer should be registered for - * @param deserializer - * @return {@link ArangoDBAsync.Builder} - * @deprecated Use {@link com.arangodb.mapping.ArangoJack} instead and register custom serializers and deserializers by implementing {@link com.fasterxml.jackson.databind.JsonSerializer} and {@link com.fasterxml.jackson.databind.JsonDeserializer}. - * @see Reference Documentation - */ - @Deprecated - public Builder registerJsonDeserializer( - final String attribute, - final ValueType type, - final VPackJsonDeserializer deserializer) { - vpackParserBuilder.registerDeserializer(attribute, type, deserializer); - return this; - } - - /** - * Register a custom {@link VPackJsonSerializer} for a specific type to be used within the internal - * serialization process. - * - *

- * Attention:can not be used together with {@link #serializer(ArangoSerialization)} - *

- * - * @param clazz the type the serializer should be registered for - * @param serializer - * @return {@link ArangoDBAsync.Builder} - * @deprecated Use {@link com.arangodb.mapping.ArangoJack} instead and register custom serializers and deserializers by implementing {@link com.fasterxml.jackson.databind.JsonSerializer} and {@link com.fasterxml.jackson.databind.JsonDeserializer}. - * @see Reference Documentation - */ - @Deprecated - public Builder registerJsonSerializer(final Class clazz, final VPackJsonSerializer serializer) { - vpackParserBuilder.registerSerializer(clazz, serializer); - return this; - } - - /** - * Register a custom {@link VPackJsonSerializer} for a specific type and attribute name to be used within the - * internal serialization process. - * - *

- * Attention:can not be used together with {@link #serializer(ArangoSerialization)} - *

- * - * @param attribute - * @param clazz the type the serializer should be registered for - * @param serializer - * @return {@link ArangoDBAsync.Builder} - * @deprecated Use {@link com.arangodb.mapping.ArangoJack} instead and register custom serializers and deserializers by implementing {@link com.fasterxml.jackson.databind.JsonSerializer} and {@link com.fasterxml.jackson.databind.JsonDeserializer}. - * @see Reference Documentation - */ - @Deprecated - public Builder registerJsonSerializer( - final String attribute, - final Class clazz, - final VPackJsonSerializer serializer) { - vpackParserBuilder.registerSerializer(attribute, clazz, serializer); - return this; - } - - /** - * Register a custom {@link VPackAnnotationFieldFilter} for a specific type to be used within the internal - * serialization process. - * - *

- * Attention:can not be used together with {@link #serializer(ArangoSerialization)} - *

- * - * @param type the type the serializer should be registered for - * @param fieldFilter - * @return {@link ArangoDBAsync.Builder} - * @deprecated Use {@link com.arangodb.mapping.ArangoJack} instead and register custom serializers and deserializers by implementing {@link com.fasterxml.jackson.databind.JsonSerializer} and {@link com.fasterxml.jackson.databind.JsonDeserializer}. - * @see Reference Documentation - */ - @Deprecated - public Builder annotationFieldFilter( - final Class type, - final VPackAnnotationFieldFilter fieldFilter) { - vpackBuilder.annotationFieldFilter(type, fieldFilter); - return this; - } - - /** - * Register a custom {@link VPackAnnotationFieldNaming} for a specific type to be used within the internal - * serialization process. - * - *

- * Attention:can not be used together with {@link #serializer(ArangoSerialization)} - *

- * - * @param type the type the serializer should be registered for - * @param fieldNaming - * @return {@link ArangoDBAsync.Builder} - * @deprecated Use {@link com.arangodb.mapping.ArangoJack} instead and register custom serializers and deserializers by implementing {@link com.fasterxml.jackson.databind.JsonSerializer} and {@link com.fasterxml.jackson.databind.JsonDeserializer}. - * @see
Reference Documentation - */ - @Deprecated - public Builder annotationFieldNaming( - final Class type, - final VPackAnnotationFieldNaming fieldNaming) { - vpackBuilder.annotationFieldNaming(type, fieldNaming); - return this; - } - - /** - * Register a {@link VPackModule} to be used within the internal serialization process. - * - *

- * Attention:can not be used together with {@link #serializer(ArangoSerialization)} - *

- * - * @param module module to register - * @return {@link ArangoDBAsync.Builder} - * @deprecated Use {@link com.arangodb.mapping.ArangoJack} instead and register custom modules. - * @see
Reference Documentation - */ - @Deprecated - public Builder registerModule(final VPackModule module) { - vpackBuilder.registerModule(module); - return this; - } - - /** - * Register a list of {@link VPackModule} to be used within the internal serialization process. - * - *

- * Attention:can not be used together with {@link #serializer(ArangoSerialization)} - *

- * - * @param modules modules to register - * @return {@link ArangoDBAsync.Builder} - * @deprecated Use {@link com.arangodb.mapping.ArangoJack} instead and register custom modules. - * @see Reference Documentation - */ - @Deprecated - public Builder registerModules(final VPackModule... modules) { - vpackBuilder.registerModules(modules); - return this; - } - - /** - * Register a {@link VPackParserModule} to be used within the internal serialization process. - * - *

- * Attention:can not be used together with {@link #serializer(ArangoSerialization)} - *

- * - * @param module module to register - * @return {@link ArangoDBAsync.Builder} - * @deprecated Use {@link com.arangodb.mapping.ArangoJack} instead and register custom modules. - * @see Reference Documentation - */ - @Deprecated - public Builder registerJsonModule(final VPackParserModule module) { - vpackParserBuilder.registerModule(module); - return this; - } - - /** - * Register a list of {@link VPackParserModule} to be used within the internal serialization process. - * - *

- * Attention:can not be used together with {@link #serializer(ArangoSerialization)} - *

- * - * @param modules modules to register - * @return {@link ArangoDBAsync.Builder} - * @deprecated Use {@link com.arangodb.mapping.ArangoJack} instead and register custom modules. - * @see Reference Documentation - */ - @Deprecated - public Builder registerJsonModules(final VPackParserModule... modules) { - vpackParserBuilder.registerModules(modules); - return this; - } - - /** - * Replace the built-in serializer with the given serializer. - *

- *
- * ATTENTION!: Use at your own risk - * - * @param serializer custom serializer - * @return {@link ArangoDBAsync.Builder} - * @deprecated use {@link #serializer(ArangoSerialization)} instead - */ - @Deprecated - public Builder setSerializer(final ArangoSerializer serializer) { - serializer(serializer); - return this; - } - - /** - * Replace the built-in deserializer with the given deserializer. - *

- *
- * ATTENTION!: Use at your own risk - * - * @param deserializer custom deserializer - * @return {@link ArangoDBAsync.Builder} - * @deprecated use {@link #serializer(ArangoSerialization)} instead - */ - @Deprecated - public Builder setDeserializer(final ArangoDeserializer deserializer) { - deserializer(deserializer); - return this; - } - /** * Replace the built-in serializer/deserializer with the given one. *

diff --git a/src/main/java/com/arangodb/async/ArangoDatabaseAsync.java b/src/main/java/com/arangodb/async/ArangoDatabaseAsync.java index d5d391fbe..d3ed12c32 100644 --- a/src/main/java/com/arangodb/async/ArangoDatabaseAsync.java +++ b/src/main/java/com/arangodb/async/ArangoDatabaseAsync.java @@ -24,7 +24,6 @@ import com.arangodb.ArangoSerializationAccessor; import com.arangodb.DbName; import com.arangodb.entity.*; -import com.arangodb.entity.arangosearch.AnalyzerEntity; import com.arangodb.entity.arangosearch.analyzer.SearchAnalyzer; import com.arangodb.model.*; import com.arangodb.model.arangosearch.AnalyzerDeleteOptions; @@ -51,17 +50,6 @@ public interface ArangoDatabaseAsync extends ArangoSerializationAccessor { */ ArangoDBAsync arango(); - /** - * Returns the name of the database - * - * @return database name - * @deprecated Use {@link #dbName()} instead - */ - @Deprecated - default String name() { - return dbName().get(); - } - /** * Returns the name of the database * @@ -695,18 +683,6 @@ CompletableFuture getDocument(final String id, final Class type, final */ CompletableFuture createArangoSearch(String name, ArangoSearchCreateOptions options); - /** - * Creates an Analyzer - * - * @param options AnalyzerEntity - * @return the created Analyzer - * @see API Documentation - * @since ArangoDB 3.5.0 - * @deprecated use {@link this#createSearchAnalyzer(SearchAnalyzer)}} - */ - @Deprecated - CompletableFuture createAnalyzer(AnalyzerEntity options); - /** * Creates an Analyzer * @@ -718,18 +694,6 @@ CompletableFuture getDocument(final String id, final Class type, final */ CompletableFuture createSearchAnalyzer(SearchAnalyzer analyzer); - /** - * Gets information about an Analyzer - * - * @param name of the Analyzer without database prefix - * @return information about an Analyzer - * @see API Documentation - * @since ArangoDB 3.5.0 - * @deprecated use {@link this#getSearchAnalyzer(String)}} - */ - @Deprecated - CompletableFuture getAnalyzer(String name); - /** * Gets information about an Analyzer * @@ -741,17 +705,6 @@ CompletableFuture getDocument(final String id, final Class type, final */ CompletableFuture getSearchAnalyzer(String name); - /** - * Retrieves all analyzers definitions. - * - * @return collection of all analyzers definitions - * @see API Documentation - * @since ArangoDB 3.5.0 - * @deprecated use {@link this#getSearchAnalyzers()} - */ - @Deprecated - CompletableFuture> getAnalyzers(); - /** * Retrieves all analyzers definitions. * @@ -762,29 +715,6 @@ CompletableFuture getDocument(final String id, final Class type, final */ CompletableFuture> getSearchAnalyzers(); - /** - * Deletes an Analyzer - * - * @param name of the Analyzer without database prefix - * @see API Documentation - * @since ArangoDB 3.5.0 - * @deprecated use {@link this#deleteSearchAnalyzer(String)}}} - */ - @Deprecated - CompletableFuture deleteAnalyzer(String name); - - /** - * Deletes an Analyzer - * - * @param name of the Analyzer without database prefix - * @param options AnalyzerDeleteOptions - * @see API Documentation - * @since ArangoDB 3.5.0 - * @deprecated use {@link this#deleteSearchAnalyzer(String, AnalyzerDeleteOptions)}}} - */ - @Deprecated - CompletableFuture deleteAnalyzer(String name, AnalyzerDeleteOptions options); - /** * Deletes an Analyzer * diff --git a/src/main/java/com/arangodb/async/internal/ArangoDatabaseAsyncImpl.java b/src/main/java/com/arangodb/async/internal/ArangoDatabaseAsyncImpl.java index 1ff2ede2e..224d80d7c 100644 --- a/src/main/java/com/arangodb/async/internal/ArangoDatabaseAsyncImpl.java +++ b/src/main/java/com/arangodb/async/internal/ArangoDatabaseAsyncImpl.java @@ -30,7 +30,6 @@ import com.arangodb.async.ArangoSearchAsync; import com.arangodb.async.ArangoViewAsync; import com.arangodb.entity.*; -import com.arangodb.entity.arangosearch.AnalyzerEntity; import com.arangodb.entity.arangosearch.analyzer.SearchAnalyzer; import com.arangodb.internal.ArangoCursorExecute; import com.arangodb.internal.ArangoErrors; @@ -450,55 +449,29 @@ public CompletableFuture createArangoSearch(final String name, final return executor.execute(createArangoSearchRequest(name, options), ViewEntity.class); } - @Override - public CompletableFuture createAnalyzer(AnalyzerEntity options) { - return executor.execute(createAnalyzerRequest(options), AnalyzerEntity.class); - } - @Override public CompletableFuture createSearchAnalyzer(SearchAnalyzer analyzer) { return executor.execute(createAnalyzerRequest(analyzer), SearchAnalyzer.class); } - @Override - public CompletableFuture getAnalyzer(String name) { - return executor.execute(getAnalyzerRequest(name), AnalyzerEntity.class); - } - @Override public CompletableFuture getSearchAnalyzer(String name) { return executor.execute(getAnalyzerRequest(name), SearchAnalyzer.class); } - @Override - public CompletableFuture> getAnalyzers() { - return executor.execute(getAnalyzersRequest(), getAnalyzersResponseDeserializer()); - } - @Override public CompletableFuture> getSearchAnalyzers() { return executor.execute(getAnalyzersRequest(), getSearchAnalyzersResponseDeserializer()); } - @Override - public CompletableFuture deleteAnalyzer(String name) { - return executor.execute(deleteAnalyzerRequest(name, null), Void.class); - } - - @Override - public CompletableFuture deleteAnalyzer(String name, AnalyzerDeleteOptions options) { - return executor.execute(deleteAnalyzerRequest(name, options), Void.class); - } - @Override public CompletableFuture deleteSearchAnalyzer(String name) { - return deleteAnalyzer(name); + return deleteSearchAnalyzer(name, null); } @Override public CompletableFuture deleteSearchAnalyzer(String name, AnalyzerDeleteOptions options) { - return deleteAnalyzer(name, options); + return executor.execute(deleteAnalyzerRequest(name, options), Void.class); } - } diff --git a/src/main/java/com/arangodb/entity/DocumentField.java b/src/main/java/com/arangodb/entity/DocumentField.java deleted file mode 100644 index 23341da94..000000000 --- a/src/main/java/com/arangodb/entity/DocumentField.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.entity; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * @author Mark Vollmary - * @deprecated Use {@link Id}, {@link Key}, {@link Rev}, {@link From} or {@link To} instead. - */ -@Retention(RetentionPolicy.RUNTIME) -@Target({ElementType.FIELD}) -@Deprecated -public @interface DocumentField { - - @Deprecated - enum Type { - - /** - * @deprecated Use {@link Id} instead. - */ - @Deprecated - ID("_id"), - - /** - * @deprecated Use {@link Key} instead. - */ - @Deprecated - KEY("_key"), - - /** - * @deprecated Use {@link Rev} instead. - */ - @Deprecated - REV("_rev"), - - /** - * @deprecated Use {@link From} instead. - */ - @Deprecated - FROM("_from"), - - /** - * @deprecated Use {@link To} instead. - */ - @Deprecated - TO("_to"); - - private final String serializeName; - - Type(final String serializeName) { - this.serializeName = serializeName; - } - - public String getSerializeName() { - return serializeName; - } - } - - Type value(); - -} diff --git a/src/main/java/com/arangodb/entity/arangosearch/AnalyzerEntity.java b/src/main/java/com/arangodb/entity/arangosearch/AnalyzerEntity.java deleted file mode 100644 index 5b5e5c019..000000000 --- a/src/main/java/com/arangodb/entity/arangosearch/AnalyzerEntity.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2018 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.entity.arangosearch; - -import java.util.Collection; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; - -/** - * @author Michele Rastelli - * @deprecated use typed analyzers {@link com.arangodb.entity.arangosearch.analyzer} - */ -@Deprecated -public class AnalyzerEntity { - - private Collection features; - private AnalyzerType type; - private String name; - private Map properties; - - public AnalyzerEntity() { - } - - public Set getFeatures() { - return features != null ? new HashSet<>(features) : null; - } - - public void setFeatures(Set features) { - this.features = features; - } - - public AnalyzerType getType() { - return type; - } - - public void setType(AnalyzerType type) { - this.type = type; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public Map getProperties() { - return properties; - } - - public void setProperties(Map properties) { - this.properties = properties; - } - -} diff --git a/src/main/java/com/arangodb/entity/arangosearch/analyzer/StopwordsAnalyzerProperties.java b/src/main/java/com/arangodb/entity/arangosearch/analyzer/StopwordsAnalyzerProperties.java index a82374b31..8b094e709 100644 --- a/src/main/java/com/arangodb/entity/arangosearch/analyzer/StopwordsAnalyzerProperties.java +++ b/src/main/java/com/arangodb/entity/arangosearch/analyzer/StopwordsAnalyzerProperties.java @@ -57,15 +57,6 @@ public StopwordsAnalyzerProperties() { private final List stopwords; private final boolean hex; - /** - * @return list of hex-encoded strings that describe the tokens to be discarded. - * @deprecated use {@link #getStopwordsAsHexList()} instead - */ - @Deprecated - public List getStopwords() { - return getStopwordsAsHexList(); - } - /** * @return list of verbatim strings that describe the tokens to be discarded. */ diff --git a/src/main/java/com/arangodb/internal/ArangoDatabaseImpl.java b/src/main/java/com/arangodb/internal/ArangoDatabaseImpl.java index cebbe794b..e73fa0fa0 100644 --- a/src/main/java/com/arangodb/internal/ArangoDatabaseImpl.java +++ b/src/main/java/com/arangodb/internal/ArangoDatabaseImpl.java @@ -22,7 +22,6 @@ import com.arangodb.*; import com.arangodb.entity.*; -import com.arangodb.entity.arangosearch.AnalyzerEntity; import com.arangodb.entity.arangosearch.analyzer.SearchAnalyzer; import com.arangodb.internal.cursor.ArangoCursorImpl; import com.arangodb.internal.net.HostHandle; @@ -416,54 +415,29 @@ public ViewEntity createArangoSearch(final String name, final ArangoSearchCreate return executor.execute(createArangoSearchRequest(name, options), ViewEntity.class); } - @Override - public AnalyzerEntity createAnalyzer(AnalyzerEntity options) throws ArangoDBException { - return executor.execute(createAnalyzerRequest(options), AnalyzerEntity.class); - } - @Override public SearchAnalyzer createSearchAnalyzer(SearchAnalyzer analyzer) throws ArangoDBException { return executor.execute(createAnalyzerRequest(analyzer), SearchAnalyzer.class); } - @Override - public AnalyzerEntity getAnalyzer(String name) throws ArangoDBException { - return executor.execute(getAnalyzerRequest(name), AnalyzerEntity.class); - } - @Override public SearchAnalyzer getSearchAnalyzer(String name) throws ArangoDBException { return executor.execute(getAnalyzerRequest(name), SearchAnalyzer.class); } - @Override - public Collection getAnalyzers() throws ArangoDBException { - return executor.execute(getAnalyzersRequest(), getAnalyzersResponseDeserializer()); - } - @Override public Collection getSearchAnalyzers() throws ArangoDBException { return executor.execute(getAnalyzersRequest(), getSearchAnalyzersResponseDeserializer()); } - @Override - public void deleteAnalyzer(String name) throws ArangoDBException { - executor.execute(deleteAnalyzerRequest(name, null), Void.class); - } - - @Override - public void deleteAnalyzer(String name, AnalyzerDeleteOptions options) throws ArangoDBException { - executor.execute(deleteAnalyzerRequest(name, options), Void.class); - } - @Override public void deleteSearchAnalyzer(String name) throws ArangoDBException { - deleteAnalyzer(name); + deleteSearchAnalyzer(name, null); } @Override public void deleteSearchAnalyzer(String name, AnalyzerDeleteOptions options) throws ArangoDBException { - deleteAnalyzer(name, options); + executor.execute(deleteAnalyzerRequest(name, options), Void.class); } } diff --git a/src/main/java/com/arangodb/internal/DocumentCache.java b/src/main/java/com/arangodb/internal/DocumentCache.java index e548be08f..63254a6be 100644 --- a/src/main/java/com/arangodb/internal/DocumentCache.java +++ b/src/main/java/com/arangodb/internal/DocumentCache.java @@ -94,9 +94,7 @@ private void findAnnotation( if (annotation != null && !field.isSynthetic() && !Modifier.isStatic(field.getModifiers()) && String.class.isAssignableFrom(field.getType())) { String value = null; - if (annotation instanceof DocumentField) { - value = ((DocumentField) annotation).value().getSerializeName(); - } else if (annotation instanceof Id) { + if (annotation instanceof Id) { value = DocumentFields.ID; } else if (annotation instanceof Key) { value = DocumentFields.KEY; diff --git a/src/main/java/com/arangodb/internal/InternalArangoDatabase.java b/src/main/java/com/arangodb/internal/InternalArangoDatabase.java index 71a3f0099..879f30987 100644 --- a/src/main/java/com/arangodb/internal/InternalArangoDatabase.java +++ b/src/main/java/com/arangodb/internal/InternalArangoDatabase.java @@ -22,7 +22,6 @@ import com.arangodb.DbName; import com.arangodb.entity.*; -import com.arangodb.entity.arangosearch.AnalyzerEntity; import com.arangodb.entity.arangosearch.analyzer.SearchAnalyzer; import com.arangodb.internal.ArangoExecutor.ResponseDeserializer; import com.arangodb.internal.util.ArangoSerializationFactory; @@ -432,14 +431,6 @@ protected Request getAnalyzersRequest() { return request(dbName, RequestType.GET, InternalArangoView.PATH_API_ANALYZER); } - protected ResponseDeserializer> getAnalyzersResponseDeserializer() { - return response -> { - final VPackSlice result = response.getBody().get(ArangoResponseField.RESULT); - return util().deserialize(result, new Type>() { - }.getType()); - }; - } - protected ResponseDeserializer> getSearchAnalyzersResponseDeserializer() { return response -> { final VPackSlice result = response.getBody().get(ArangoResponseField.RESULT); @@ -448,11 +439,6 @@ protected ResponseDeserializer> getSearchAnalyzersRes }; } - protected Request createAnalyzerRequest(final AnalyzerEntity options) { - return request(dbName, RequestType.POST, InternalArangoView.PATH_API_ANALYZER) - .setBody(util().serialize(options)); - } - protected Request createAnalyzerRequest(final SearchAnalyzer options) { return request(dbName, RequestType.POST, InternalArangoView.PATH_API_ANALYZER) .setBody(util().serialize(options)); diff --git a/src/main/java/com/arangodb/internal/cursor/AbstractArangoIterable.java b/src/main/java/com/arangodb/internal/cursor/AbstractArangoIterable.java index 93ede0a1b..958446e67 100644 --- a/src/main/java/com/arangodb/internal/cursor/AbstractArangoIterable.java +++ b/src/main/java/com/arangodb/internal/cursor/AbstractArangoIterable.java @@ -21,12 +21,7 @@ package com.arangodb.internal.cursor; import com.arangodb.ArangoIterable; -import com.arangodb.ArangoIterator; -import com.arangodb.Function; -import com.arangodb.Predicate; -import java.util.Collection; -import java.util.Iterator; import java.util.stream.Stream; import java.util.stream.StreamSupport; @@ -40,73 +35,4 @@ public Stream stream() { return StreamSupport.stream(spliterator(), false); } - @Override - public ArangoIterable map(final Function mapper) { - return new ArangoMappingIterable<>(this, mapper); - } - - @Override - public ArangoIterable filter(final Predicate predicate) { - return new ArangoFilterIterable<>(this, predicate); - } - - @Override - public T first() { - final ArangoIterator iterator = iterator(); - return iterator.hasNext() ? iterator.next() : null; - } - - @Override - public long count() { - long count = 0L; - for (final Iterator iterator = iterator(); iterator.hasNext(); iterator.next()) { - count++; - } - return count; - } - - @Override - public boolean anyMatch(final Predicate predicate) { - boolean match = false; - for (final T t : this) { - if (predicate.test(t)) { - match = true; - break; - } - } - return match; - } - - @Override - public boolean allMatch(final Predicate predicate) { - boolean match = false; - for (final T t : this) { - match = predicate.test(t); - if (!match) { - break; - } - } - return match; - } - - @Override - public boolean noneMatch(final Predicate predicate) { - boolean match = false; - for (final T t : this) { - match = !predicate.test(t); - if (!match) { - break; - } - } - return match; - } - - @Override - public > R collectInto(final R target) { - for (final T t : this) { - target.add(t); - } - return target; - } - } diff --git a/src/main/java/com/arangodb/internal/cursor/ArangoCursorImpl.java b/src/main/java/com/arangodb/internal/cursor/ArangoCursorImpl.java index 228989657..1de76a083 100644 --- a/src/main/java/com/arangodb/internal/cursor/ArangoCursorImpl.java +++ b/src/main/java/com/arangodb/internal/cursor/ArangoCursorImpl.java @@ -22,7 +22,6 @@ import com.arangodb.ArangoCursor; import com.arangodb.ArangoIterator; -import com.arangodb.Consumer; import com.arangodb.entity.CursorEntity; import com.arangodb.entity.CursorEntity.Extras; import com.arangodb.entity.CursorEntity.Stats; @@ -130,11 +129,4 @@ public ArangoIterator iterator() { return iterator; } - @Override - public void foreach(final Consumer action) { - while (hasNext()) { - action.accept(next()); - } - } - } diff --git a/src/main/java/com/arangodb/internal/cursor/ArangoFilterIterable.java b/src/main/java/com/arangodb/internal/cursor/ArangoFilterIterable.java deleted file mode 100644 index bb0ff1054..000000000 --- a/src/main/java/com/arangodb/internal/cursor/ArangoFilterIterable.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2018 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.internal.cursor; - -import com.arangodb.ArangoIterable; -import com.arangodb.ArangoIterator; -import com.arangodb.Consumer; -import com.arangodb.Predicate; - -/** - * @author Mark Vollmary - */ -@Deprecated -public class ArangoFilterIterable extends AbstractArangoIterable implements ArangoIterable { - - private final ArangoIterable iterable; - private final Predicate predicate; - - protected ArangoFilterIterable(final ArangoIterable iterable, final Predicate predicate) { - super(); - this.iterable = iterable; - this.predicate = predicate; - } - - @Override - public ArangoIterator iterator() { - return new ArangoFilterIterator<>(iterable.iterator(), predicate); - } - - @Override - public void foreach(final Consumer action) { - for (final T t : iterable) { - if (predicate.test(t)) { - action.accept(t); - } - } - } - -} diff --git a/src/main/java/com/arangodb/internal/cursor/ArangoFilterIterator.java b/src/main/java/com/arangodb/internal/cursor/ArangoFilterIterator.java deleted file mode 100644 index 7c65f9d22..000000000 --- a/src/main/java/com/arangodb/internal/cursor/ArangoFilterIterator.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2018 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.internal.cursor; - -import com.arangodb.ArangoIterator; -import com.arangodb.Predicate; - -import java.util.NoSuchElementException; - -/** - * @author Mark Vollmary - */ -public class ArangoFilterIterator implements ArangoIterator { - - private final ArangoIterator iterator; - private final Predicate predicate; - private T next; - - protected ArangoFilterIterator(final ArangoIterator iterator, final Predicate predicate) { - super(); - this.iterator = iterator; - this.predicate = predicate; - next = null; - } - - @Override - public boolean hasNext() { - if (next != null) { - return true; - } - while (iterator.hasNext()) { - next = iterator.next(); - if (predicate.test(next)) { - return true; - } - } - next = null; - return false; - } - - @Override - public T next() { - if (next == null && !hasNext()) { - throw new NoSuchElementException(); - } - final T tmp = next; - next = null; - return tmp; - } - - @Override - public void remove() { - throw new UnsupportedOperationException(); - } -} diff --git a/src/main/java/com/arangodb/internal/cursor/ArangoMappingIterable.java b/src/main/java/com/arangodb/internal/cursor/ArangoMappingIterable.java deleted file mode 100644 index c1b818c2b..000000000 --- a/src/main/java/com/arangodb/internal/cursor/ArangoMappingIterable.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2018 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.internal.cursor; - -import com.arangodb.ArangoIterable; -import com.arangodb.ArangoIterator; -import com.arangodb.Consumer; -import com.arangodb.Function; - -/** - * @author Mark Vollmary - */ -@Deprecated -public class ArangoMappingIterable extends AbstractArangoIterable implements ArangoIterable { - - private final ArangoIterable iterable; - private final Function mapper; - - protected ArangoMappingIterable(final ArangoIterable iterable, final Function mapper) { - super(); - this.iterable = iterable; - this.mapper = mapper; - } - - @Override - public ArangoIterator iterator() { - return new ArangoMappingIterator<>(iterable.iterator(), mapper); - } - - @Override - public void foreach(final Consumer action) { - for (final R t : iterable) { - action.accept(mapper.apply(t)); - } - } - -} diff --git a/src/main/java/com/arangodb/internal/cursor/ArangoMappingIterator.java b/src/main/java/com/arangodb/internal/cursor/ArangoMappingIterator.java deleted file mode 100644 index e3594a1cc..000000000 --- a/src/main/java/com/arangodb/internal/cursor/ArangoMappingIterator.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2018 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.internal.cursor; - -import com.arangodb.ArangoIterator; -import com.arangodb.Function; - -/** - * @author Mark Vollmary - */ -public class ArangoMappingIterator implements ArangoIterator { - - private final ArangoIterator iterator; - private final Function mapper; - - public ArangoMappingIterator(final ArangoIterator iterator, final Function mapper) { - super(); - this.iterator = iterator; - this.mapper = mapper; - } - - @Override - public boolean hasNext() { - return iterator.hasNext(); - } - - @Override - public T next() { - return mapper.apply(iterator.next()); - } - - @Override - public void remove() { - throw new UnsupportedOperationException(); - } - -} diff --git a/src/main/java/com/arangodb/internal/mapping/ArangoAnnotationIntrospector.java b/src/main/java/com/arangodb/internal/mapping/ArangoAnnotationIntrospector.java index 33dab6a91..6f80f1e01 100644 --- a/src/main/java/com/arangodb/internal/mapping/ArangoAnnotationIntrospector.java +++ b/src/main/java/com/arangodb/internal/mapping/ArangoAnnotationIntrospector.java @@ -21,7 +21,6 @@ package com.arangodb.internal.mapping; -import com.arangodb.entity.DocumentField; import com.arangodb.velocypack.annotations.Expose; import com.arangodb.velocypack.annotations.SerializedName; import com.fasterxml.jackson.annotation.JsonProperty; @@ -116,11 +115,6 @@ private PropertyName findPropertyName(Annotated a) { return null; } - final DocumentField documentField = a.getAnnotation(DocumentField.class); - if (documentField != null) { - return PropertyName.construct(documentField.value().getSerializeName()); - } - final SerializedName serializedName = a.getAnnotation(SerializedName.class); if (serializedName != null) { return PropertyName.construct(serializedName.value()); diff --git a/src/main/java/com/arangodb/internal/velocypack/VPackDriverModule.java b/src/main/java/com/arangodb/internal/velocypack/VPackDriverModule.java index 46a18784b..ca86c5946 100644 --- a/src/main/java/com/arangodb/internal/velocypack/VPackDriverModule.java +++ b/src/main/java/com/arangodb/internal/velocypack/VPackDriverModule.java @@ -51,9 +51,7 @@ public class VPackDriverModule implements VPackModule, VPackParserModule { public > void setup(final C context) { context.fieldNamingStrategy(field -> { for (Annotation annotation : field.getAnnotations()) { - if(annotation instanceof DocumentField) { - return ((DocumentField) annotation).value().getSerializeName(); - } else if (annotation instanceof Id) { + if (annotation instanceof Id) { return DocumentFields.ID; } else if (annotation instanceof Key) { return DocumentFields.KEY; diff --git a/src/main/java/com/arangodb/model/CollectionCreateOptions.java b/src/main/java/com/arangodb/model/CollectionCreateOptions.java index 4e69ea8f9..e4c425aa0 100644 --- a/src/main/java/com/arangodb/model/CollectionCreateOptions.java +++ b/src/main/java/com/arangodb/model/CollectionCreateOptions.java @@ -271,14 +271,4 @@ public CollectionCreateOptions schema(final CollectionSchema schema) { return this; } - /** - * @since ArangoDB 3.7 - * @deprecated Use {@link #schema(CollectionSchema)} instead. - */ - @Deprecated - public CollectionCreateOptions setSchema(final CollectionSchema schema) { - this.schema = schema; - return this; - } - } diff --git a/src/main/java/com/arangodb/model/DBCreateOptions.java b/src/main/java/com/arangodb/model/DBCreateOptions.java index 23708bb18..1c9d6ed07 100644 --- a/src/main/java/com/arangodb/model/DBCreateOptions.java +++ b/src/main/java/com/arangodb/model/DBCreateOptions.java @@ -58,16 +58,6 @@ public String getName() { return name; } - /** - * @param name Has to contain a valid database name - * @return options - * @deprecated Use {@link #name(DbName)} instead. - */ - @Deprecated - public DBCreateOptions name(final String name) { - return name(DbName.of(name)); - } - /** * @param dbName database name * @return options diff --git a/src/main/java/com/arangodb/velocystream/Request.java b/src/main/java/com/arangodb/velocystream/Request.java index c57e22a81..cfa9eead7 100644 --- a/src/main/java/com/arangodb/velocystream/Request.java +++ b/src/main/java/com/arangodb/velocystream/Request.java @@ -42,14 +42,6 @@ public class Request { @Expose(serialize = false) private VPackSlice body; - /** - * @deprecated Use {@link #Request(DbName, RequestType, String)} instead - */ - @Deprecated - public Request(final String database, final RequestType requestType, final String path) { - this(DbName.of(database), requestType, path); - } - public Request(final DbName dbName, final RequestType requestType, final String path) { super(); this.dbName = dbName; @@ -78,14 +70,6 @@ public Request setType(final int type) { return this; } - /** - * @deprecated Use {@link #getDbName()} instead - */ - @Deprecated - public String getDatabase() { - return getDbName().get(); - } - public DbName getDbName() { return dbName; } diff --git a/src/test/java/com/arangodb/ArangoCursorTest.java b/src/test/java/com/arangodb/ArangoCursorTest.java index 2872451bf..41d9d5d99 100644 --- a/src/test/java/com/arangodb/ArangoCursorTest.java +++ b/src/test/java/com/arangodb/ArangoCursorTest.java @@ -43,22 +43,12 @@ static void init() { initDB(); } - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void first(ArangoDatabase db) { - final ArangoCursor cursor = db.query("FOR i IN 0..99 RETURN i", VPackSlice.class); - final VPackSlice first = cursor.first(); - assertThat(first).isNotNull(); - assertThat(first.isInteger()).isTrue(); - assertThat(first.getAsLong()).isZero(); - } - @ParameterizedTest(name = "{index}") @MethodSource("dbs") void firstStream(ArangoDatabase db) { final ArangoCursor cursor = db.query("FOR i IN 0..99 RETURN i", VPackSlice.class); final Optional first = cursor.stream().findFirst(); - assertThat(first.isPresent()).isTrue(); + assertThat(first).isPresent(); assertThat(first.get().isInteger()).isTrue(); assertThat(first.get().getAsLong()).isZero(); } @@ -66,21 +56,10 @@ void firstStream(ArangoDatabase db) { @ParameterizedTest(name = "{index}") @MethodSource("dbs") void next(ArangoDatabase db) { - final ArangoCursor cursor = db.query("FOR i IN 0..99 RETURN i", new AqlQueryOptions().batchSize(5), VPackSlice.class); - while (cursor.hasNext()) { cursor.next(); } - - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void mapFilterCount(ArangoDatabase db) { - final ArangoCursor cursor = db.query("FOR i IN 0..99 RETURN i", VPackSlice.class); - final long count = cursor.map(VPackSlice::getAsLong).filter(t -> t < 50).count(); - assertThat(count).isEqualTo(50L); } @ParameterizedTest(name = "{index}") @@ -91,71 +70,14 @@ void mapFilterCountStream(ArangoDatabase db) { assertThat(count).isEqualTo(50L); } - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void mapMapFilterCount(ArangoDatabase db) { - final ArangoCursor cursor = db.query("FOR i IN 0..99 RETURN i", VPackSlice.class); - final long count = cursor.map(VPackSlice::getAsLong).map(t -> t * 10).filter(t -> t < 500).count(); - assertThat(count).isEqualTo(50L); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void mapMapFilterFilterCount(ArangoDatabase db) { - final ArangoCursor cursor = db.query("FOR i IN 0..99 RETURN i", VPackSlice.class); - final long count = cursor.map(VPackSlice::getAsLong).map(t -> t * 10).filter(t -> t < 500).filter(t -> t < 250).count(); - assertThat(count).isEqualTo(25L); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void mapFilterNext(ArangoDatabase db) { - final ArangoCursor cursor = db.query("FOR i IN 0..99 RETURN i", VPackSlice.class); - final long count = cursor.map(VPackSlice::getAsLong).filter(t -> t < 50).iterator().next(); - assertThat(count).isZero(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void mapFilterFirst(ArangoDatabase db) { - final ArangoCursor cursor = db.query("FOR i IN 0..99 RETURN i", VPackSlice.class); - final long count = cursor.map(VPackSlice::getAsLong).filter(t -> t < 50).first(); - assertThat(count).isZero(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void mapFilterCollectIntoList(ArangoDatabase db) { - final ArangoCursor cursor = db.query("FOR i IN 0..99 RETURN i", VPackSlice.class); - final List target = cursor.map(VPackSlice::getAsLong).filter(t -> t < 50).collectInto(new ArrayList<>()); - assertThat(target).isNotNull(); - assertThat(target).hasSize(50); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void mapFilterCollectIntoSet(ArangoDatabase db) { - final ArangoCursor cursor = db.query("FOR i IN 0..99 RETURN i", VPackSlice.class); - final Set target = cursor.map(VPackSlice::getAsLong).filter(t -> t < 50).collectInto(new HashSet<>()); - assertThat(target).isNotNull(); - assertThat(target).hasSize(50); - } - @ParameterizedTest(name = "{index}") @MethodSource("dbs") void mapFilterCollectIntoSetStream(ArangoDatabase db) { final ArangoCursor cursor = db.query("FOR i IN 0..99 RETURN i", VPackSlice.class); final Set target = cursor.stream().map(VPackSlice::getAsLong).filter(t -> t < 50).collect(Collectors.toSet()); - assertThat(target).isNotNull(); - assertThat(target).hasSize(50); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void foreach(ArangoDatabase db) { - final AtomicLong i = new AtomicLong(0L); - final ArangoCursor cursor = db.query("FOR i IN 0..99 RETURN i", VPackSlice.class); - cursor.foreach(t -> assertThat(t.getAsLong()).isEqualTo(i.getAndIncrement())); + assertThat(target) + .isNotNull() + .hasSize(50); } @ParameterizedTest(name = "{index}") @@ -166,14 +88,6 @@ void forEach(ArangoDatabase db) { cursor.forEach(t -> assertThat(t.getAsLong()).isEqualTo(i.getAndIncrement())); } - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void mapForeach(ArangoDatabase db) { - final AtomicLong i = new AtomicLong(0L); - final ArangoCursor cursor = db.query("FOR i IN 0..99 RETURN i", VPackSlice.class); - cursor.map(VPackSlice::getAsLong).foreach(t -> assertThat(t).isEqualTo(i.getAndIncrement())); - } - @ParameterizedTest(name = "{index}") @MethodSource("dbs") void mapForeachStream(ArangoDatabase db) { @@ -182,14 +96,6 @@ void mapForeachStream(ArangoDatabase db) { cursor.stream().map(VPackSlice::getAsLong).forEach(t -> assertThat(t).isEqualTo(i.getAndIncrement())); } - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void mapFilterForeach(ArangoDatabase db) { - final AtomicLong i = new AtomicLong(0L); - final ArangoCursor cursor = db.query("FOR i IN 0..99 RETURN i", VPackSlice.class); - cursor.map(VPackSlice::getAsLong).filter(t -> t < 50).foreach(t -> assertThat(t).isEqualTo(i.getAndIncrement())); - } - @ParameterizedTest(name = "{index}") @MethodSource("dbs") void mapFilterForEachStream(ArangoDatabase db) { @@ -198,14 +104,6 @@ void mapFilterForEachStream(ArangoDatabase db) { cursor.stream().map(VPackSlice::getAsLong).filter(t -> t < 50).forEach(t -> assertThat(t).isEqualTo(i.getAndIncrement())); } - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void anyMatch(ArangoDatabase db) { - final ArangoCursor cursor = db.query("FOR i IN 0..99 RETURN i", VPackSlice.class); - final boolean match = cursor.anyMatch(t -> t.getAsLong() == 50L); - assertThat(match).isTrue(); - } - @ParameterizedTest(name = "{index}") @MethodSource("dbs") void anyMatchStream(ArangoDatabase db) { @@ -214,30 +112,6 @@ void anyMatchStream(ArangoDatabase db) { assertThat(match).isTrue(); } - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void mapAnyMatch(ArangoDatabase db) { - final ArangoCursor cursor = db.query("FOR i IN 0..99 RETURN i", VPackSlice.class); - final boolean match = cursor.map(VPackSlice::getAsLong).anyMatch(t -> t == 50L); - assertThat(match).isTrue(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void mapFilterAnyMatch(ArangoDatabase db) { - final ArangoCursor cursor = db.query("FOR i IN 0..99 RETURN i", VPackSlice.class); - final boolean match = cursor.map(VPackSlice::getAsLong).filter(t -> t < 50).anyMatch(t -> t == 25L); - assertThat(match).isTrue(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void noneMatch(ArangoDatabase db) { - final ArangoCursor cursor = db.query("FOR i IN 0..99 RETURN i", VPackSlice.class); - final boolean match = cursor.noneMatch(t -> t.getAsLong() == 100L); - assertThat(match).isTrue(); - } - @ParameterizedTest(name = "{index}") @MethodSource("dbs") void noneMatchStream(ArangoDatabase db) { @@ -246,30 +120,6 @@ void noneMatchStream(ArangoDatabase db) { assertThat(match).isTrue(); } - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void mapNoneMatch(ArangoDatabase db) { - final ArangoCursor cursor = db.query("FOR i IN 0..99 RETURN i", VPackSlice.class); - final boolean match = cursor.map(VPackSlice::getAsLong).noneMatch(t -> t == 100L); - assertThat(match).isTrue(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void mapFilterNoneMatch(ArangoDatabase db) { - final ArangoCursor cursor = db.query("FOR i IN 0..99 RETURN i", VPackSlice.class); - final boolean match = cursor.map(VPackSlice::getAsLong).filter(t -> t < 50).noneMatch(t -> t == 50L); - assertThat(match).isTrue(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void allMatch(ArangoDatabase db) { - final ArangoCursor cursor = db.query("FOR i IN 0..99 RETURN i", VPackSlice.class); - final boolean match = cursor.allMatch(t -> t.getAsLong() < 100L); - assertThat(match).isTrue(); - } - @ParameterizedTest(name = "{index}") @MethodSource("dbs") void allMatchStream(ArangoDatabase db) { @@ -278,19 +128,4 @@ void allMatchStream(ArangoDatabase db) { assertThat(match).isTrue(); } - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void mapAllMatch(ArangoDatabase db) { - final ArangoCursor cursor = db.query("FOR i IN 0..99 RETURN i", VPackSlice.class); - final boolean match = cursor.map(VPackSlice::getAsLong).allMatch(t -> t < 100); - assertThat(match).isTrue(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void mapFilterAllMatch(ArangoDatabase db) { - final ArangoCursor cursor = db.query("FOR i IN 0..99 RETURN i", VPackSlice.class); - final boolean match = cursor.map(VPackSlice::getAsLong).filter(t -> t < 50).allMatch(t -> t < 50); - assertThat(match).isTrue(); - } } diff --git a/src/test/java/com/arangodb/ArangoSearchTest.java b/src/test/java/com/arangodb/ArangoSearchTest.java index 173c0a47e..cfbf8a477 100644 --- a/src/test/java/com/arangodb/ArangoSearchTest.java +++ b/src/test/java/com/arangodb/ArangoSearchTest.java @@ -253,45 +253,6 @@ void replaceProperties(ArangoDatabase db) { assertThat(link.getFields().iterator().next().getName()).isEqualTo("value"); } - private void createGetAndDeleteAnalyzer(ArangoDatabase db, AnalyzerEntity options) { - - String fullyQualifiedName = db.dbName().get() + "::" + options.getName(); - - // createAnalyzer - AnalyzerEntity createdAnalyzer = db.createAnalyzer(options); - - assertThat(createdAnalyzer.getName()).isEqualTo(fullyQualifiedName); - assertThat(createdAnalyzer.getType()).isEqualTo(options.getType()); - assertThat(createdAnalyzer.getFeatures()).isEqualTo(options.getFeatures()); - compareProperties(createdAnalyzer.getProperties(), options.getProperties()); - - // getAnalyzer - AnalyzerEntity gotAnalyzer = db.getAnalyzer(options.getName()); - assertThat(gotAnalyzer.getName()).isEqualTo(fullyQualifiedName); - assertThat(gotAnalyzer.getType()).isEqualTo(options.getType()); - assertThat(gotAnalyzer.getFeatures()).isEqualTo(options.getFeatures()); - compareProperties(gotAnalyzer.getProperties(), options.getProperties()); - - // getAnalyzers - @SuppressWarnings("OptionalGetWithoutIsPresent") - AnalyzerEntity foundAnalyzer = db.getAnalyzers().stream().filter(it -> it.getName().equals(fullyQualifiedName)) - .findFirst().get(); - - assertThat(foundAnalyzer.getName()).isEqualTo(fullyQualifiedName); - assertThat(foundAnalyzer.getType()).isEqualTo(options.getType()); - assertThat(foundAnalyzer.getFeatures()).isEqualTo(options.getFeatures()); - compareProperties(foundAnalyzer.getProperties(), options.getProperties()); - - AnalyzerDeleteOptions deleteOptions = new AnalyzerDeleteOptions(); - deleteOptions.setForce(true); - - // deleteAnalyzer - db.deleteAnalyzer(options.getName(), deleteOptions); - - Throwable thrown = catchThrowable(() -> db.getAnalyzer(options.getName())); - assertThat(thrown).isInstanceOf(ArangoDBException.class); - } - private void createGetAndDeleteTypedAnalyzer(ArangoDatabase db, SearchAnalyzer analyzer) { String fullyQualifiedName = db.dbName().get() + "::" + analyzer.getName(); @@ -317,7 +278,7 @@ private void createGetAndDeleteTypedAnalyzer(ArangoDatabase db, SearchAnalyzer a db.deleteSearchAnalyzer(analyzer.getName(), deleteOptions); - Throwable thrown = catchThrowable(() -> db.getAnalyzer(analyzer.getName())); + Throwable thrown = catchThrowable(() -> db.getSearchAnalyzer(analyzer.getName())); assertThat(thrown).isInstanceOf(ArangoDBException.class); ArangoDBException e = (ArangoDBException) thrown; assertThat(e.getResponseCode()).isEqualTo(404); @@ -325,42 +286,6 @@ private void createGetAndDeleteTypedAnalyzer(ArangoDatabase db, SearchAnalyzer a } @SuppressWarnings("unchecked") - private void compareProperties(Map actualProperties, Map expectedProperties) { - expectedProperties.forEach((key, expectedValue) -> { - Object actualValue = actualProperties.get(key); - if (expectedValue instanceof Map) { - assertThat(actualValue).isNotNull(); - assertThat(actualValue).isInstanceOf(Map.class); - compareProperties((Map) actualValue, (Map) expectedValue); - } else if (expectedValue instanceof Number) { - assertThat(Double.valueOf(actualValue.toString())).isEqualTo(Double.valueOf(expectedValue.toString())); - } else { - assertThat(actualValue).isEqualTo(expectedValue); - } - }); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void identityAnalyzer(ArangoDatabase db) { - assumeTrue(isAtLeastVersion(3, 5)); - - String name = "test-" + rnd(); - - Set features = new HashSet<>(); - features.add(AnalyzerFeature.frequency); - features.add(AnalyzerFeature.norm); - features.add(AnalyzerFeature.position); - - AnalyzerEntity options = new AnalyzerEntity(); - options.setFeatures(features); - options.setName(name); - options.setType(AnalyzerType.identity); - options.setProperties(Collections.emptyMap()); - - createGetAndDeleteAnalyzer(db, options); - } - @ParameterizedTest(name = "{index}") @MethodSource("dbs") void identityAnalyzerTyped(ArangoDatabase db) { @@ -380,27 +305,6 @@ void identityAnalyzerTyped(ArangoDatabase db) { createGetAndDeleteTypedAnalyzer(db, analyzer); } - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void delimiterAnalyzer(ArangoDatabase db) { - assumeTrue(isAtLeastVersion(3, 5)); - - String name = "test-" + rnd(); - - Set features = new HashSet<>(); - features.add(AnalyzerFeature.frequency); - features.add(AnalyzerFeature.norm); - features.add(AnalyzerFeature.position); - - AnalyzerEntity options = new AnalyzerEntity(); - options.setFeatures(features); - options.setName(name); - options.setType(AnalyzerType.delimiter); - options.setProperties(Collections.singletonMap("delimiter", "-")); - - createGetAndDeleteAnalyzer(db, options); - } - @ParameterizedTest(name = "{index}") @MethodSource("dbs") void delimiterAnalyzerTyped(ArangoDatabase db) { @@ -424,27 +328,6 @@ void delimiterAnalyzerTyped(ArangoDatabase db) { createGetAndDeleteTypedAnalyzer(db, analyzer); } - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void stemAnalyzer(ArangoDatabase db) { - assumeTrue(isAtLeastVersion(3, 5)); - - String name = "test-" + rnd(); - - Set features = new HashSet<>(); - features.add(AnalyzerFeature.frequency); - features.add(AnalyzerFeature.norm); - features.add(AnalyzerFeature.position); - - AnalyzerEntity options = new AnalyzerEntity(); - options.setFeatures(features); - options.setName(name); - options.setType(AnalyzerType.stem); - options.setProperties(Collections.singletonMap("locale", "ru")); - - createGetAndDeleteAnalyzer(db, options); - } - @ParameterizedTest(name = "{index}") @MethodSource("dbs") void stemAnalyzerTyped(ArangoDatabase db) { @@ -468,32 +351,6 @@ void stemAnalyzerTyped(ArangoDatabase db) { createGetAndDeleteTypedAnalyzer(db, options); } - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void normAnalyzer(ArangoDatabase db) { - assumeTrue(isAtLeastVersion(3, 5)); - - String name = "test-" + rnd(); - - Set features = new HashSet<>(); - features.add(AnalyzerFeature.frequency); - features.add(AnalyzerFeature.norm); - features.add(AnalyzerFeature.position); - - Map properties = new HashMap<>(); - properties.put("locale", "ru"); - properties.put("case", "lower"); - properties.put("accent", true); - - AnalyzerEntity options = new AnalyzerEntity(); - options.setFeatures(features); - options.setName(name); - options.setType(AnalyzerType.norm); - options.setProperties(properties); - - createGetAndDeleteAnalyzer(db, options); - } - @ParameterizedTest(name = "{index}") @MethodSource("dbs") void normAnalyzerTyped(ArangoDatabase db) { @@ -519,32 +376,6 @@ void normAnalyzerTyped(ArangoDatabase db) { createGetAndDeleteTypedAnalyzer(db, options); } - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void ngramAnalyzer(ArangoDatabase db) { - assumeTrue(isAtLeastVersion(3, 5)); - - String name = "test-" + rnd(); - - Set features = new HashSet<>(); - features.add(AnalyzerFeature.frequency); - features.add(AnalyzerFeature.norm); - features.add(AnalyzerFeature.position); - - Map properties = new HashMap<>(); - properties.put("max", 6L); - properties.put("min", 3L); - properties.put("preserveOriginal", true); - - AnalyzerEntity options = new AnalyzerEntity(); - options.setFeatures(features); - options.setName(name); - options.setType(AnalyzerType.ngram); - options.setProperties(properties); - - createGetAndDeleteAnalyzer(db, options); - } - @ParameterizedTest(name = "{index}") @MethodSource("dbs") void ngramAnalyzerTyped(ArangoDatabase db) { @@ -571,35 +402,6 @@ void ngramAnalyzerTyped(ArangoDatabase db) { createGetAndDeleteTypedAnalyzer(db, analyzer); } - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void enhancedNgramAnalyzer(ArangoDatabase db) { - assumeTrue(isAtLeastVersion(3, 6)); - - String name = "test-" + UUID.randomUUID(); - - Set features = new HashSet<>(); - features.add(AnalyzerFeature.frequency); - features.add(AnalyzerFeature.norm); - features.add(AnalyzerFeature.position); - - Map properties = new HashMap<>(); - properties.put("max", 6L); - properties.put("min", 3L); - properties.put("preserveOriginal", true); - properties.put("startMarker", "^"); - properties.put("endMarker", "^"); - properties.put("streamType", "utf8"); - - AnalyzerEntity options = new AnalyzerEntity(); - options.setFeatures(features); - options.setName(name); - options.setType(AnalyzerType.ngram); - options.setProperties(properties); - - createGetAndDeleteAnalyzer(db, options); - } - @ParameterizedTest(name = "{index}") @MethodSource("dbs") void enhancedNgramAnalyzerTyped(ArangoDatabase db) { @@ -628,34 +430,6 @@ void enhancedNgramAnalyzerTyped(ArangoDatabase db) { createGetAndDeleteTypedAnalyzer(db, analyzer); } - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void textAnalyzer(ArangoDatabase db) { - assumeTrue(isAtLeastVersion(3, 5)); - - String name = "test-" + rnd(); - - Set features = new HashSet<>(); - features.add(AnalyzerFeature.frequency); - features.add(AnalyzerFeature.norm); - features.add(AnalyzerFeature.position); - - Map properties = new HashMap<>(); - properties.put("locale", "ru"); - properties.put("case", "lower"); - properties.put("stopwords", Collections.emptyList()); - properties.put("accent", true); - properties.put("stemming", true); - - AnalyzerEntity options = new AnalyzerEntity(); - options.setFeatures(features); - options.setName(name); - options.setType(AnalyzerType.text); - options.setProperties(properties); - - createGetAndDeleteAnalyzer(db, options); - } - @ParameterizedTest(name = "{index}") @MethodSource("dbs") void textAnalyzerTyped(ArangoDatabase db) { @@ -683,40 +457,6 @@ void textAnalyzerTyped(ArangoDatabase db) { createGetAndDeleteTypedAnalyzer(db, analyzer); } - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void enhancedTextAnalyzer(ArangoDatabase db) { - assumeTrue(isAtLeastVersion(3, 6)); - - String name = "test-" + UUID.randomUUID(); - - Set features = new HashSet<>(); - features.add(AnalyzerFeature.frequency); - features.add(AnalyzerFeature.norm); - features.add(AnalyzerFeature.position); - - Map edgeNgram = new HashMap<>(); - edgeNgram.put("min", 2L); - edgeNgram.put("max", 100000L); - edgeNgram.put("preserveOriginal", true); - - Map properties = new HashMap<>(); - properties.put("locale", "ru"); - properties.put("case", "lower"); - properties.put("stopwords", Collections.emptyList()); - properties.put("accent", true); - properties.put("stemming", true); - properties.put("edgeNgram", edgeNgram); - - AnalyzerEntity options = new AnalyzerEntity(); - options.setFeatures(features); - options.setName(name); - options.setType(AnalyzerType.text); - options.setProperties(properties); - - createGetAndDeleteAnalyzer(db, options); - } - @ParameterizedTest(name = "{index}") @MethodSource("dbs") void enhancedTextAnalyzerTyped(ArangoDatabase db) { diff --git a/src/test/java/com/arangodb/async/ArangoSearchTest.java b/src/test/java/com/arangodb/async/ArangoSearchTest.java index 47c183b54..5cf5aedfe 100644 --- a/src/test/java/com/arangodb/async/ArangoSearchTest.java +++ b/src/test/java/com/arangodb/async/ArangoSearchTest.java @@ -251,7 +251,7 @@ private void createGetAndDeleteTypedAnalyzer(SearchAnalyzer analyzer) throws Exe db.deleteSearchAnalyzer(analyzer.getName(), deleteOptions).get(); try { - db.getAnalyzer(analyzer.getName()).get(); + db.getSearchAnalyzer(analyzer.getName()).get(); fail("deleted analyzer should not be found!"); } catch (ExecutionException e) { assertThat(e.getCause()).isInstanceOf(ArangoDBException.class); @@ -261,84 +261,6 @@ private void createGetAndDeleteTypedAnalyzer(SearchAnalyzer analyzer) throws Exe } - private void createGetAndDeleteAnalyzer(AnalyzerEntity options) throws ExecutionException, InterruptedException { - - String fullyQualifiedName = db.dbName().get() + "::" + options.getName(); - - // createAnalyzer - AnalyzerEntity createdAnalyzer = db.createAnalyzer(options).get(); - - assertThat(createdAnalyzer.getName()).isEqualTo(fullyQualifiedName); - assertThat(createdAnalyzer.getType()).isEqualTo(options.getType()); - assertThat(createdAnalyzer.getFeatures()).isEqualTo(options.getFeatures()); - compareProperties(createdAnalyzer.getProperties(), options.getProperties()); - - // getAnalyzer - AnalyzerEntity gotAnalyzer = db.getAnalyzer(options.getName()).get(); - assertThat(gotAnalyzer.getName()).isEqualTo(fullyQualifiedName); - assertThat(gotAnalyzer.getType()).isEqualTo(options.getType()); - assertThat(gotAnalyzer.getFeatures()).isEqualTo(options.getFeatures()); - compareProperties(gotAnalyzer.getProperties(), options.getProperties()); - - // getAnalyzers - @SuppressWarnings("OptionalGetWithoutIsPresent") - AnalyzerEntity foundAnalyzer = db.getAnalyzers().get().stream().filter(it -> it.getName().equals(fullyQualifiedName)) - .findFirst().get(); - - assertThat(foundAnalyzer.getName()).isEqualTo(fullyQualifiedName); - assertThat(foundAnalyzer.getType()).isEqualTo(options.getType()); - assertThat(foundAnalyzer.getFeatures()).isEqualTo(options.getFeatures()); - compareProperties(foundAnalyzer.getProperties(), options.getProperties()); - - AnalyzerDeleteOptions deleteOptions = new AnalyzerDeleteOptions(); - deleteOptions.setForce(true); - - // deleteAnalyzer - db.deleteAnalyzer(options.getName(), deleteOptions).get(); - - try { - db.getAnalyzer(options.getName()).get(); - fail(); - } catch (ExecutionException e) { - assertThat(e.getCause()).isInstanceOf(ArangoDBException.class); - assertThat(((ArangoDBException) e.getCause()).getResponseCode()).isEqualTo(404); - } - } - - private void compareProperties(Map actualProperties, Map expectedProperties) { - expectedProperties.forEach((key, expectedValue) -> { - Object actualValue = actualProperties.get(key); - if (expectedValue instanceof Map) { - assertThat(actualValue).isNotNull(); - assertThat(actualValue).isInstanceOf(Map.class); - compareProperties((Map) actualValue, (Map) expectedValue); - } else if (expectedValue instanceof Number) { - assertThat(Double.valueOf(actualValue.toString())).isEqualTo(Double.valueOf(expectedValue.toString())); - } else { - assertThat(actualValue).isEqualTo(expectedValue); - } - }); - } - - @Test - void identityAnalyzer() throws ExecutionException, InterruptedException { - assumeTrue(isAtLeastVersion(3, 5)); - String name = "test-" + UUID.randomUUID(); - - Set features = new HashSet<>(); - features.add(AnalyzerFeature.frequency); - features.add(AnalyzerFeature.norm); - features.add(AnalyzerFeature.position); - - AnalyzerEntity options = new AnalyzerEntity(); - options.setFeatures(features); - options.setName(name); - options.setType(AnalyzerType.identity); - options.setProperties(Collections.emptyMap()); - - createGetAndDeleteAnalyzer(options); - } - @Test void identityAnalyzerTyped() throws ExecutionException, InterruptedException { assumeTrue(isAtLeastVersion(3, 5)); @@ -357,25 +279,6 @@ void identityAnalyzerTyped() throws ExecutionException, InterruptedException { createGetAndDeleteTypedAnalyzer(analyzer); } - @Test - void delimiterAnalyzer() throws ExecutionException, InterruptedException { - assumeTrue(isAtLeastVersion(3, 5)); - String name = "test-" + UUID.randomUUID(); - - Set features = new HashSet<>(); - features.add(AnalyzerFeature.frequency); - features.add(AnalyzerFeature.norm); - features.add(AnalyzerFeature.position); - - AnalyzerEntity options = new AnalyzerEntity(); - options.setFeatures(features); - options.setName(name); - options.setType(AnalyzerType.delimiter); - options.setProperties(Collections.singletonMap("delimiter", "-")); - - createGetAndDeleteAnalyzer(options); - } - @Test void delimiterAnalyzerTyped() throws ExecutionException, InterruptedException { assumeTrue(isAtLeastVersion(3, 5)); @@ -398,25 +301,6 @@ void delimiterAnalyzerTyped() throws ExecutionException, InterruptedException { createGetAndDeleteTypedAnalyzer(analyzer); } - @Test - void stemAnalyzer() throws ExecutionException, InterruptedException { - assumeTrue(isAtLeastVersion(3, 5)); - String name = "test-" + UUID.randomUUID(); - - Set features = new HashSet<>(); - features.add(AnalyzerFeature.frequency); - features.add(AnalyzerFeature.norm); - features.add(AnalyzerFeature.position); - - AnalyzerEntity options = new AnalyzerEntity(); - options.setFeatures(features); - options.setName(name); - options.setType(AnalyzerType.stem); - options.setProperties(Collections.singletonMap("locale", "ru")); - - createGetAndDeleteAnalyzer(options); - } - @Test void stemAnalyzerTyped() throws ExecutionException, InterruptedException { assumeTrue(isAtLeastVersion(3, 5)); @@ -439,30 +323,6 @@ void stemAnalyzerTyped() throws ExecutionException, InterruptedException { createGetAndDeleteTypedAnalyzer(options); } - @Test - void normAnalyzer() throws ExecutionException, InterruptedException { - assumeTrue(isAtLeastVersion(3, 5)); - String name = "test-" + UUID.randomUUID(); - - Set features = new HashSet<>(); - features.add(AnalyzerFeature.frequency); - features.add(AnalyzerFeature.norm); - features.add(AnalyzerFeature.position); - - Map properties = new HashMap<>(); - properties.put("locale", "ru"); - properties.put("case", "lower"); - properties.put("accent", true); - - AnalyzerEntity options = new AnalyzerEntity(); - options.setFeatures(features); - options.setName(name); - options.setType(AnalyzerType.norm); - options.setProperties(properties); - - createGetAndDeleteAnalyzer(options); - } - @Test void normAnalyzerTyped() throws ExecutionException, InterruptedException { assumeTrue(isAtLeastVersion(3, 5)); @@ -487,31 +347,6 @@ void normAnalyzerTyped() throws ExecutionException, InterruptedException { createGetAndDeleteTypedAnalyzer(options); } - @Test - void ngramAnalyzer() throws ExecutionException, InterruptedException { - assumeTrue(isAtLeastVersion(3, 5)); - - String name = "test-" + UUID.randomUUID(); - - Set features = new HashSet<>(); - features.add(AnalyzerFeature.frequency); - features.add(AnalyzerFeature.norm); - features.add(AnalyzerFeature.position); - - Map properties = new HashMap<>(); - properties.put("max", 6L); - properties.put("min", 3L); - properties.put("preserveOriginal", true); - - AnalyzerEntity options = new AnalyzerEntity(); - options.setFeatures(features); - options.setName(name); - options.setType(AnalyzerType.ngram); - options.setProperties(properties); - - createGetAndDeleteAnalyzer(options); - } - @Test void ngramAnalyzerTyped() throws ExecutionException, InterruptedException { assumeTrue(isAtLeastVersion(3, 5)); @@ -537,33 +372,6 @@ void ngramAnalyzerTyped() throws ExecutionException, InterruptedException { createGetAndDeleteTypedAnalyzer(analyzer); } - @Test - void textAnalyzer() throws ExecutionException, InterruptedException { - assumeTrue(isAtLeastVersion(3, 5)); - - String name = "test-" + UUID.randomUUID(); - - Set features = new HashSet<>(); - features.add(AnalyzerFeature.frequency); - features.add(AnalyzerFeature.norm); - features.add(AnalyzerFeature.position); - - Map properties = new HashMap<>(); - properties.put("locale", "ru"); - properties.put("case", "lower"); - properties.put("stopwords", Collections.emptyList()); - properties.put("accent", true); - properties.put("stemming", true); - - AnalyzerEntity options = new AnalyzerEntity(); - options.setFeatures(features); - options.setName(name); - options.setType(AnalyzerType.text); - options.setProperties(properties); - - createGetAndDeleteAnalyzer(options); - } - @Test void textAnalyzerTyped() throws ExecutionException, InterruptedException { assumeTrue(isAtLeastVersion(3, 5)); diff --git a/src/test/java/com/arangodb/example/ExampleBase.java b/src/test/java/com/arangodb/example/ExampleBase.java index c378c789c..b4bd582e6 100644 --- a/src/test/java/com/arangodb/example/ExampleBase.java +++ b/src/test/java/com/arangodb/example/ExampleBase.java @@ -23,6 +23,7 @@ import com.arangodb.ArangoCollection; import com.arangodb.ArangoDB; import com.arangodb.ArangoDatabase; +import com.arangodb.DbName; import com.arangodb.mapping.ArangoJack; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; @@ -42,10 +43,11 @@ public class ExampleBase { @BeforeAll static void setUp() { arangoDB = new ArangoDB.Builder().serializer(new ArangoJack()).build(); - if (arangoDB.db(DB_NAME).exists()) - arangoDB.db(DB_NAME).drop(); - arangoDB.createDatabase(DB_NAME); - db = arangoDB.db(DB_NAME); + DbName dbName = DbName.of(DB_NAME); + if (arangoDB.db(dbName).exists()) + arangoDB.db(dbName).drop(); + arangoDB.createDatabase(dbName); + db = arangoDB.db(dbName); db.createCollection(COLLECTION_NAME); collection = db.collection(COLLECTION_NAME); } diff --git a/src/test/java/com/arangodb/example/FirstProject.java b/src/test/java/com/arangodb/example/FirstProject.java index db14e3741..63bcf034e 100644 --- a/src/test/java/com/arangodb/example/FirstProject.java +++ b/src/test/java/com/arangodb/example/FirstProject.java @@ -1,9 +1,6 @@ package com.arangodb.example; -import com.arangodb.ArangoCollection; -import com.arangodb.ArangoCursor; -import com.arangodb.ArangoDB; -import com.arangodb.ArangoDBException; +import com.arangodb.*; import com.arangodb.entity.BaseDocument; import com.arangodb.entity.CollectionEntity; import com.arangodb.mapping.ArangoJack; @@ -18,7 +15,7 @@ public static void main(final String[] args) { final ArangoDB arangoDB = new ArangoDB.Builder().user("root").serializer(new ArangoJack()).build(); // create database - final String dbName = "mydb"; + final DbName dbName = DbName.of("mydb"); try { arangoDB.createDatabase(dbName); System.out.println("Database created: " + dbName); diff --git a/src/test/java/com/arangodb/mapping/annotations/ArangoAnnotationsTest.java b/src/test/java/com/arangodb/mapping/annotations/ArangoAnnotationsTest.java index 63c1b87ae..0aa1ace84 100644 --- a/src/test/java/com/arangodb/mapping/annotations/ArangoAnnotationsTest.java +++ b/src/test/java/com/arangodb/mapping/annotations/ArangoAnnotationsTest.java @@ -36,30 +36,6 @@ class ArangoAnnotationsTest { private final ArangoJack mapper = new ArangoJack(); - @Test - void documentField() { - DocumentFieldEntity e = new DocumentFieldEntity(); - e.setId("Id"); - e.setKey("Key"); - e.setRev("Rev"); - e.setFrom("From"); - e.setTo("To"); - - VPackSlice slice = mapper.serialize(e); - System.out.println(slice); - Map deserialized = mapper.deserialize(slice, Object.class); - assertThat(deserialized) - .containsEntry("_id", e.getId()) - .containsEntry("_key", e.getKey()) - .containsEntry("_rev", e.getRev()) - .containsEntry("_from", e.getFrom()) - .containsEntry("_to", e.getTo()) - .hasSize(5); - - DocumentFieldEntity deserializedEntity = mapper.deserialize(slice, DocumentFieldEntity.class); - assertThat(deserializedEntity).isEqualTo(e); - } - @Test void documentFieldAnnotations() { AnnotatedEntity e = new AnnotatedEntity(); diff --git a/src/test/java/com/arangodb/mapping/annotations/DocumentFieldEntity.java b/src/test/java/com/arangodb/mapping/annotations/DocumentFieldEntity.java deleted file mode 100644 index 20241673f..000000000 --- a/src/test/java/com/arangodb/mapping/annotations/DocumentFieldEntity.java +++ /dev/null @@ -1,112 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.mapping.annotations; - -import com.arangodb.entity.DocumentField; - -import java.util.Objects; - -/** - * @author Michele Rastelli - */ -public class DocumentFieldEntity { - - @DocumentField(DocumentField.Type.ID) - private String id; - - @DocumentField(DocumentField.Type.KEY) - private String key; - - @DocumentField(DocumentField.Type.REV) - private String rev; - - @DocumentField(DocumentField.Type.FROM) - private String from; - - @DocumentField(DocumentField.Type.TO) - private String to; - - public DocumentFieldEntity() { - } - - public String getId() { - return id; - } - - public void setId(String id) { - this.id = id; - } - - public String getKey() { - return key; - } - - public void setKey(String key) { - this.key = key; - } - - public String getRev() { - return rev; - } - - public void setRev(String rev) { - this.rev = rev; - } - - public String getFrom() { - return from; - } - - public void setFrom(String from) { - this.from = from; - } - - public String getTo() { - return to; - } - - public void setTo(String to) { - this.to = to; - } - - @Override - public boolean equals(Object o) { - if (this == o) - return true; - if (o == null || getClass() != o.getClass()) - return false; - DocumentFieldEntity that = (DocumentFieldEntity) o; - return Objects.equals(id, that.id) && Objects.equals(key, that.key) && Objects.equals(rev, that.rev) && Objects - .equals(from, that.from) && Objects.equals(to, that.to); - } - - @Override - public int hashCode() { - return Objects.hash(id, key, rev, from, to); - } - - @Override - public String toString() { - return "AnnotatedEntity{" + "idField='" + id + '\'' + ", keyField='" + key + '\'' + ", revField='" + rev + '\'' - + ", fromField='" + from + '\'' + ", toField='" + to + '\'' + '}'; - } - -} From 53d3b230b58e72f0952ba2eeacee4c5ef520a8d4 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Thu, 23 Jun 2022 21:46:32 +0200 Subject: [PATCH 005/254] enabled CI tests for v7 branch --- .github/workflows/maven.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index 388a156d5..896069eb4 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -4,6 +4,7 @@ on: push: branches: - master + - v7 pull_request: types: [ opened, synchronize, reopened ] branches: From 0448cd4be8d595711e1367f9df43cb25968f8bc0 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Tue, 28 Jun 2022 15:50:21 +0200 Subject: [PATCH 006/254] new serializer API --- .../java/com/arangodb/serde/ArangoSerde.java | 60 ++++++++++++++++++ .../java/com/arangodb/serde/DataType.java | 24 +++++++ .../com/arangodb/serde/InternalSerde.java | 42 +++++++++++++ .../com/arangodb/serde/InternalSerdeImpl.java | 44 +++++++++++++ .../java/com/arangodb/serde/JacksonSerde.java | 63 +++++++++++++++++++ .../com/arangodb/serde/JacksonSerdeImpl.java | 53 ++++++++++++++++ 6 files changed, 286 insertions(+) create mode 100644 src/main/java/com/arangodb/serde/ArangoSerde.java create mode 100644 src/main/java/com/arangodb/serde/DataType.java create mode 100644 src/main/java/com/arangodb/serde/InternalSerde.java create mode 100644 src/main/java/com/arangodb/serde/InternalSerdeImpl.java create mode 100644 src/main/java/com/arangodb/serde/JacksonSerde.java create mode 100644 src/main/java/com/arangodb/serde/JacksonSerdeImpl.java diff --git a/src/main/java/com/arangodb/serde/ArangoSerde.java b/src/main/java/com/arangodb/serde/ArangoSerde.java new file mode 100644 index 000000000..3b310548c --- /dev/null +++ b/src/main/java/com/arangodb/serde/ArangoSerde.java @@ -0,0 +1,60 @@ +package com.arangodb.serde; + +import com.fasterxml.jackson.databind.ObjectMapper; + +import java.lang.reflect.Type; + +/** + * Contract for serialization/deserialization of user data. + * Implementations of this interface could be used for customizing serialization/deserialization of user related data + * using serialization/deserialization libraries other than Jackson Databind, like: + * - serialization libraries for specific JVM languages (e.g. Scala, Kotlin, ...) + * - serialization libraries already in use in frameworks (e.g. JSON-B, Micronaut Serialization, ...) + * - high performance serialization libraries (e.g. supporting compile-time databinding code generation) + * - lower level libraries without support to data binding + *

+ * This interface should not be directly implemented as an adapter to Jackson Databind. A more performant way to provide + * custom implementations based on Jackson Databind is by extending {@link JacksonSerde}, which exposes additional + * methods based on Jackson's types. + * Furthermore, existing implementations {@link JacksonSerde} can be instantiated providing a custom configured Jackson + * ObjectMapper, see {@link JacksonSerde#of(DataType, ObjectMapper)}. + */ +public interface ArangoSerde { + + /** + * @return the data type supported by this implementation + */ + DataType getDataType(); + + /** + * Serializes the object into the target data type. For data type {@link DataType#JSON}, the serialized JSON string + * must be encoded into a byte array using the UTF-8 charset. + * + * @param value object to serialize + * @return serialized byte array + */ + byte[] serialize(Object value); + + /** + * Deserializes the content and binds it to the target data type. + * For data type {@link DataType#JSON}, the byte array is the JSON string encoded using the UTF-8 charset. + * + * @param content byte array to deserialize + * @param clazz class of target data type + * @return deserialized object + */ + default T deserialize(byte[] content, Class clazz) { + return deserialize(content, (Type) clazz); + } + + /** + * Deserializes the content and binds it to the target data type. + * For data type {@link DataType#JSON}, the byte array is the JSON string encoded using the UTF-8 charset. + * + * @param content byte array to deserialize + * @param type target data type + * @return deserialized object + */ + T deserialize(byte[] content, Type type); + +} diff --git a/src/main/java/com/arangodb/serde/DataType.java b/src/main/java/com/arangodb/serde/DataType.java new file mode 100644 index 000000000..0b071915a --- /dev/null +++ b/src/main/java/com/arangodb/serde/DataType.java @@ -0,0 +1,24 @@ +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed 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. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ +package com.arangodb.serde; + +public enum DataType { + JSON, VPACK +} diff --git a/src/main/java/com/arangodb/serde/InternalSerde.java b/src/main/java/com/arangodb/serde/InternalSerde.java new file mode 100644 index 000000000..bdc40760b --- /dev/null +++ b/src/main/java/com/arangodb/serde/InternalSerde.java @@ -0,0 +1,42 @@ +package com.arangodb.serde; + +import com.arangodb.jackson.dataformat.velocypack.VPackMapper; +import com.fasterxml.jackson.databind.ObjectMapper; + +public interface InternalSerde extends JacksonSerde { + + /** + * Creates a new InternalSerde with default settings for the specified data type. + * + * @param dataType serialization target data type + * @return the created InternalSerde + */ + static JacksonSerde of(final DataType dataType) { + if (dataType == DataType.JSON) { + return new InternalSerdeImpl(dataType, new ObjectMapper()); + } else if (dataType == DataType.VPACK) { + return new InternalSerdeImpl(dataType, new VPackMapper()); + } else { + throw new IllegalStateException("Unexpected value: " + dataType); + } + } + + /** + * Used for logging and debugging. + * + * @param content byte array + * @return JSON string + */ + String toJsonString(byte[] content); + + /** + * Extract the nested content pointed by the json pointer. + * Used for extracting nested user data. + * + * @param content byte array + * @param jsonPointer location of user data + * @return byte array + */ + byte[] extract(byte[] content, String jsonPointer); + +} diff --git a/src/main/java/com/arangodb/serde/InternalSerdeImpl.java b/src/main/java/com/arangodb/serde/InternalSerdeImpl.java new file mode 100644 index 000000000..4cf6c3e77 --- /dev/null +++ b/src/main/java/com/arangodb/serde/InternalSerdeImpl.java @@ -0,0 +1,44 @@ +package com.arangodb.serde; + +import com.arangodb.ArangoDBException; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; + +import java.io.IOException; +import java.nio.charset.StandardCharsets; + +class InternalSerdeImpl extends JacksonSerdeImpl implements InternalSerde { + private final ObjectMapper jsonMapper = new ObjectMapper(); + + InternalSerdeImpl(DataType dataType, ObjectMapper mapper) { + super(dataType, mapper); + } + + @Override + public String toJsonString(final byte[] content) { + switch (dataType) { + case JSON: + return new String(content, StandardCharsets.UTF_8); + case VPACK: + try { + JsonNode tree = mapper.readTree(content); + return jsonMapper.writeValueAsString(tree); + } catch (IOException e) { + throw new ArangoDBException(e); + } + default: + throw new IllegalStateException("Unexpected value: " + dataType); + } + } + + @Override + public byte[] extract(final byte[] content, final String jsonPointer) { + try { + JsonNode target = mapper.readTree(content).at(jsonPointer); + return mapper.writeValueAsBytes(target); + } catch (IOException e) { + throw new ArangoDBException(e); + } + } + +} diff --git a/src/main/java/com/arangodb/serde/JacksonSerde.java b/src/main/java/com/arangodb/serde/JacksonSerde.java new file mode 100644 index 000000000..9887a7767 --- /dev/null +++ b/src/main/java/com/arangodb/serde/JacksonSerde.java @@ -0,0 +1,63 @@ +package com.arangodb.serde; + +import com.arangodb.jackson.dataformat.velocypack.VPackMapper; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; + +import java.lang.reflect.Type; + +/** + * Contract for serialization/deserialization of user data, based on Jackson Databind. + * In comparison to {@link ArangoSerde}, this API improves the deserialization performance by allowing reusing the JSON + * tree already parsed by the root deserializer. + */ +public interface JacksonSerde extends ArangoSerde { + + /** + * Creates a new JacksonSerde with default settings for the specified data type. + * + * @param dataType serialization target data type + * @return the created JacksonSerde + */ + static JacksonSerde of(final DataType dataType) { + if (dataType == DataType.JSON) { + return of(dataType, new ObjectMapper()); + } else if (dataType == DataType.VPACK) { + return of(dataType, new VPackMapper()); + } else { + throw new IllegalStateException("Unexpected value: " + dataType); + } + } + + /** + * Creates a new JacksonSerde using the provided ObjectMapper. + * + * @param dataType serialization target data type + * @param mapper Jackson ObjectMapper to use + * @return the created JacksonSerde + */ + static JacksonSerde of(final DataType dataType, final ObjectMapper mapper) { + return new JacksonSerdeImpl(dataType, mapper); + } + + /** + * Deserializes the parsed json node and binds it to the target data type. + * + * @param node parsed json node + * @param clazz class of target data type + * @return deserialized object + */ + default T deserialize(JsonNode node, Class clazz) { + return deserialize(node, (Type) clazz); + } + + /** + * Deserializes the parsed json node and binds it to the target data type. + * + * @param node parsed json node + * @param type target data type + * @return deserialized object + */ + T deserialize(JsonNode node, Type type); + +} diff --git a/src/main/java/com/arangodb/serde/JacksonSerdeImpl.java b/src/main/java/com/arangodb/serde/JacksonSerdeImpl.java new file mode 100644 index 000000000..3964f0ea4 --- /dev/null +++ b/src/main/java/com/arangodb/serde/JacksonSerdeImpl.java @@ -0,0 +1,53 @@ +package com.arangodb.serde; + +import com.arangodb.ArangoDBException; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; + +import java.io.IOException; +import java.lang.reflect.Type; + +class JacksonSerdeImpl implements JacksonSerde { + + protected final DataType dataType; + protected final ObjectMapper mapper; + + JacksonSerdeImpl(final DataType dataType, final ObjectMapper mapper) { + this.dataType = dataType; + this.mapper = mapper; + } + + @Override + public DataType getDataType() { + return dataType; + } + + @Override + public byte[] serialize(final Object value) { + try { + return mapper.writeValueAsBytes(value); + } catch (JsonProcessingException e) { + throw new ArangoDBException(e); + } + } + + @Override + public T deserialize(final byte[] content, final Type type) { + try { + return mapper.readerFor(mapper.constructType(type)).readValue(content); + } catch (IOException e) { + throw new ArangoDBException(e); + } + } + + @Override + public T deserialize(final JsonNode node, final Type type) { + try { + return mapper.readerFor(mapper.constructType(type)).readValue(node); + } catch (IOException e) { + throw new ArangoDBException(e); + } + } + +} From 6a6f3a3e1e614433d5e998029d4faf1fa7fd254c Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Wed, 29 Jun 2022 11:10:05 +0200 Subject: [PATCH 007/254] serde InternalModule --- .../com/arangodb/serde/InternalModule.java | 24 ++++++++++++++++ .../com/arangodb/serde/InternalSerde.java | 2 +- .../com/arangodb/serde/InternalSerdeImpl.java | 1 + .../arangodb/serde/InternalSerializers.java | 28 +++++++++++++++++++ 4 files changed, 54 insertions(+), 1 deletion(-) create mode 100644 src/main/java/com/arangodb/serde/InternalModule.java create mode 100644 src/main/java/com/arangodb/serde/InternalSerializers.java diff --git a/src/main/java/com/arangodb/serde/InternalModule.java b/src/main/java/com/arangodb/serde/InternalModule.java new file mode 100644 index 000000000..cd0679b25 --- /dev/null +++ b/src/main/java/com/arangodb/serde/InternalModule.java @@ -0,0 +1,24 @@ +package com.arangodb.serde; + +import com.arangodb.internal.velocystream.internal.AuthenticationRequest; +import com.fasterxml.jackson.databind.Module; +import com.fasterxml.jackson.databind.module.SimpleModule; + +import java.util.function.Supplier; + +enum InternalModule implements Supplier { + INSTANCE; + + private final SimpleModule module; + + InternalModule() { + module = new SimpleModule(); + module.addSerializer(AuthenticationRequest.class, InternalSerializers.AUTHENTICATION_REQUEST); + } + + @Override + public Module get() { + return module; + } + +} diff --git a/src/main/java/com/arangodb/serde/InternalSerde.java b/src/main/java/com/arangodb/serde/InternalSerde.java index bdc40760b..839c7e5f5 100644 --- a/src/main/java/com/arangodb/serde/InternalSerde.java +++ b/src/main/java/com/arangodb/serde/InternalSerde.java @@ -11,7 +11,7 @@ public interface InternalSerde extends JacksonSerde { * @param dataType serialization target data type * @return the created InternalSerde */ - static JacksonSerde of(final DataType dataType) { + static InternalSerde of(final DataType dataType) { if (dataType == DataType.JSON) { return new InternalSerdeImpl(dataType, new ObjectMapper()); } else if (dataType == DataType.VPACK) { diff --git a/src/main/java/com/arangodb/serde/InternalSerdeImpl.java b/src/main/java/com/arangodb/serde/InternalSerdeImpl.java index 4cf6c3e77..4ef9b3c72 100644 --- a/src/main/java/com/arangodb/serde/InternalSerdeImpl.java +++ b/src/main/java/com/arangodb/serde/InternalSerdeImpl.java @@ -12,6 +12,7 @@ class InternalSerdeImpl extends JacksonSerdeImpl implements InternalSerde { InternalSerdeImpl(DataType dataType, ObjectMapper mapper) { super(dataType, mapper); + mapper.registerModule(InternalModule.INSTANCE.get()); } @Override diff --git a/src/main/java/com/arangodb/serde/InternalSerializers.java b/src/main/java/com/arangodb/serde/InternalSerializers.java new file mode 100644 index 000000000..5ec7ae03c --- /dev/null +++ b/src/main/java/com/arangodb/serde/InternalSerializers.java @@ -0,0 +1,28 @@ +package com.arangodb.serde; + +import com.arangodb.internal.velocystream.internal.AuthenticationRequest; +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.databind.JsonSerializer; +import com.fasterxml.jackson.databind.SerializerProvider; + +import java.io.IOException; + +final class InternalSerializers { + + private InternalSerializers() { + } + + static final JsonSerializer AUTHENTICATION_REQUEST = new JsonSerializer() { + @Override + public void serialize(AuthenticationRequest value, JsonGenerator gen, SerializerProvider serializers) throws IOException { + gen.writeStartArray(); + gen.writeNumber(value.getVersion()); + gen.writeNumber(value.getType()); + gen.writeString(value.getEncryption()); + gen.writeString(value.getUser()); + gen.writeString(value.getPassword()); + gen.writeEndArray(); + } + }; + +} From 53ff3749883c3c43f4b6a9a295a8707ba7007d6a Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Wed, 29 Jun 2022 13:36:24 +0200 Subject: [PATCH 008/254] serde serialization refactoring --- src/main/java/com/arangodb/ArangoDB.java | 7 +++++- .../com/arangodb/async/ArangoDBAsync.java | 5 +++- .../java/com/arangodb/entity/Permissions.java | 7 ++++++ .../internal/http/HttpConnection.java | 5 +++- .../util/DefaultArangoSerialization.java | 20 +++++++++++++-- .../velocypack/VPackDeserializers.java | 3 ++- .../com/arangodb/model/AqlQueryOptions.java | 7 +++--- .../model/CollectionCreateOptions.java | 2 +- .../com/arangodb/model/UserAccessOptions.java | 2 +- .../com/arangodb/model/UserCreateOptions.java | 4 +-- .../com/arangodb/serde/InternalModule.java | 2 ++ .../arangodb/serde/InternalSerializers.java | 25 +++++++++++++++++++ .../com/arangodb/velocystream/Response.java | 19 +++++++++++++- 13 files changed, 93 insertions(+), 15 deletions(-) diff --git a/src/main/java/com/arangodb/ArangoDB.java b/src/main/java/com/arangodb/ArangoDB.java index f58064a08..0686ca6cc 100644 --- a/src/main/java/com/arangodb/ArangoDB.java +++ b/src/main/java/com/arangodb/ArangoDB.java @@ -38,6 +38,9 @@ import com.arangodb.model.LogOptions; import com.arangodb.model.UserCreateOptions; import com.arangodb.model.UserUpdateOptions; +import com.arangodb.serde.ArangoSerde; +import com.arangodb.serde.DataType; +import com.arangodb.serde.InternalSerde; import com.arangodb.util.ArangoCursorInitializer; import com.arangodb.util.ArangoDeserializer; import com.arangodb.util.ArangoSerialization; @@ -362,8 +365,10 @@ public synchronized ArangoDB build() { : new ArangoSerializerImpl(vpacker, vpackerNull, vpackParser); final ArangoDeserializer deserializerTemp = deserializer != null ? deserializer : new ArangoDeserializerImpl(vpackerNull, vpackParser); + final InternalSerde internalSerde = protocol == Protocol.HTTP_JSON ? InternalSerde.of(DataType.JSON) + : InternalSerde.of(DataType.VPACK); final DefaultArangoSerialization internal = new DefaultArangoSerialization(serializerTemp, - deserializerTemp); + deserializerTemp, internalSerde); final ArangoSerialization custom = customSerializer != null ? customSerializer : internal; final ArangoSerializationFactory util = new ArangoSerializationFactory(internal, custom); diff --git a/src/main/java/com/arangodb/async/ArangoDBAsync.java b/src/main/java/com/arangodb/async/ArangoDBAsync.java index 8b3b0b75d..28dff5ee6 100644 --- a/src/main/java/com/arangodb/async/ArangoDBAsync.java +++ b/src/main/java/com/arangodb/async/ArangoDBAsync.java @@ -41,6 +41,8 @@ import com.arangodb.model.LogOptions; import com.arangodb.model.UserCreateOptions; import com.arangodb.model.UserUpdateOptions; +import com.arangodb.serde.DataType; +import com.arangodb.serde.InternalSerde; import com.arangodb.util.ArangoDeserializer; import com.arangodb.util.ArangoSerialization; import com.arangodb.util.ArangoSerializer; @@ -523,8 +525,9 @@ public synchronized ArangoDBAsync build() { : new ArangoSerializerImpl(vpacker, vpackerNull, vpackParser); final ArangoDeserializer deserializerTemp = deserializer != null ? deserializer : new ArangoDeserializerImpl(vpackerNull, vpackParser); + final InternalSerde internalSerde = InternalSerde.of(DataType.VPACK); final DefaultArangoSerialization internal = new DefaultArangoSerialization(serializerTemp, - deserializerTemp); + deserializerTemp, internalSerde); final ArangoSerialization custom = customSerializer != null ? customSerializer : internal; final ArangoSerializationFactory util = new ArangoSerializationFactory(internal, custom); diff --git a/src/main/java/com/arangodb/entity/Permissions.java b/src/main/java/com/arangodb/entity/Permissions.java index 774f36c42..73f8b8105 100644 --- a/src/main/java/com/arangodb/entity/Permissions.java +++ b/src/main/java/com/arangodb/entity/Permissions.java @@ -20,6 +20,8 @@ package com.arangodb.entity; +import com.fasterxml.jackson.annotation.JsonProperty; + /** * @author Mark Vollmary */ @@ -28,11 +30,16 @@ public enum Permissions { /** * read and write access */ + @JsonProperty("rw") RW, + /** * read-only access */ + @JsonProperty("ro") RO, + + @JsonProperty("none") NONE } diff --git a/src/main/java/com/arangodb/internal/http/HttpConnection.java b/src/main/java/com/arangodb/internal/http/HttpConnection.java index 7cc380e22..c74af9b2a 100644 --- a/src/main/java/com/arangodb/internal/http/HttpConnection.java +++ b/src/main/java/com/arangodb/internal/http/HttpConnection.java @@ -27,6 +27,7 @@ import com.arangodb.internal.net.HostDescription; import com.arangodb.internal.util.IOUtils; import com.arangodb.internal.util.ResponseUtils; +import com.arangodb.serde.DataType; import com.arangodb.util.ArangoSerialization; import com.arangodb.util.ArangoSerializer.Options; import com.arangodb.velocypack.VPackSlice; @@ -173,6 +174,7 @@ public HttpConnection build() { private final ArangoSerialization util; private final Boolean useSsl; private final Protocol contentType; + private final DataType dataType; private final HostDescription host; private HttpConnection(final HostDescription host, final Integer timeout, final String user, final String password, @@ -185,6 +187,7 @@ private HttpConnection(final HostDescription host, final Integer timeout, final this.useSsl = useSsl; this.util = util; this.contentType = contentType; + dataType = contentType == Protocol.HTTP_JSON ? DataType.JSON : DataType.VPACK; final RegistryBuilder registryBuilder = RegistryBuilder .create(); if (Boolean.TRUE == useSsl) { @@ -355,7 +358,7 @@ private static void addHeader(final Request request, final HttpRequestBase httpR public Response buildResponse(final CloseableHttpResponse httpResponse) throws UnsupportedOperationException, IOException { - final Response response = new Response(); + final Response response = new Response(dataType); response.setResponseCode(httpResponse.getStatusLine().getStatusCode()); final HttpEntity entity = httpResponse.getEntity(); if (entity != null && entity.getContent() != null) { diff --git a/src/main/java/com/arangodb/internal/util/DefaultArangoSerialization.java b/src/main/java/com/arangodb/internal/util/DefaultArangoSerialization.java index f77f2ee49..d6a6c6e29 100644 --- a/src/main/java/com/arangodb/internal/util/DefaultArangoSerialization.java +++ b/src/main/java/com/arangodb/internal/util/DefaultArangoSerialization.java @@ -21,9 +21,12 @@ package com.arangodb.internal.util; import com.arangodb.ArangoDBException; +import com.arangodb.serde.DataType; +import com.arangodb.serde.InternalSerde; import com.arangodb.util.ArangoDeserializer; import com.arangodb.util.ArangoSerialization; import com.arangodb.util.ArangoSerializer; +import com.arangodb.velocypack.VPackParser; import com.arangodb.velocypack.VPackSlice; import java.lang.reflect.Type; @@ -35,16 +38,29 @@ public class DefaultArangoSerialization implements ArangoSerialization { private final ArangoSerializer serializer; private final ArangoDeserializer deserializer; + private final InternalSerde serde; - public DefaultArangoSerialization(final ArangoSerializer serializer, final ArangoDeserializer deserializer) { + public DefaultArangoSerialization(final ArangoSerializer serializer, final ArangoDeserializer deserializer, final InternalSerde serde) { super(); this.serializer = serializer; this.deserializer = deserializer; + this.serde = serde; } @Override public VPackSlice serialize(final Object entity) throws ArangoDBException { - return serializer.serialize(entity); +// return serializer.serialize(entity); + DataType dataType = serde.getDataType(); + switch (dataType) { + case JSON: + String json = new String(serde.serialize(entity)); + VPackParser parser = new VPackParser.Builder().build(); + return parser.fromJson(json); + case VPACK: + return new VPackSlice(serde.serialize(entity)); + default: + throw new IllegalStateException("Unexpected value: " + dataType); + } } @Override diff --git a/src/main/java/com/arangodb/internal/velocypack/VPackDeserializers.java b/src/main/java/com/arangodb/internal/velocypack/VPackDeserializers.java index 2e8849214..344b66983 100644 --- a/src/main/java/com/arangodb/internal/velocypack/VPackDeserializers.java +++ b/src/main/java/com/arangodb/internal/velocypack/VPackDeserializers.java @@ -45,6 +45,7 @@ import com.arangodb.entity.arangosearch.analyzer.*; import com.arangodb.model.CollectionSchema; import com.arangodb.model.ZKDIndexOptions; +import com.arangodb.serde.DataType; import com.arangodb.velocypack.VPackDeserializer; import com.arangodb.velocypack.VPackParser; import com.arangodb.velocypack.VPackSlice; @@ -66,7 +67,7 @@ public class VPackDeserializers { private static final String DATE_TIME_FORMAT = "yyyy-MM-dd'T'HH:mm:ss.SSSZ"; public static final VPackDeserializer RESPONSE = (parent, vpack, context) -> { - final Response response = new Response(); + final Response response = new Response(DataType.VPACK); response.setVersion(vpack.get(0).getAsInt()); response.setType(vpack.get(1).getAsInt()); response.setResponseCode(vpack.get(2).getAsInt()); diff --git a/src/main/java/com/arangodb/model/AqlQueryOptions.java b/src/main/java/com/arangodb/model/AqlQueryOptions.java index 52e344663..ddb5a4f16 100644 --- a/src/main/java/com/arangodb/model/AqlQueryOptions.java +++ b/src/main/java/com/arangodb/model/AqlQueryOptions.java @@ -42,7 +42,6 @@ public class AqlQueryOptions implements Serializable { private Integer ttl; private Integer batchSize; private Boolean cache; - private Boolean fillBlockCache; private Long memoryLimit; private VPackSlice bindVars; private String query; @@ -165,7 +164,7 @@ protected AqlQueryOptions bindVars(final VPackSlice bindVars) { return this; } - protected String getQuery() { + public String getQuery() { return query; } @@ -430,14 +429,14 @@ public static class Options implements Serializable { private Double maxRuntime; private Boolean fillBlockCache; - protected Optimizer getOptimizer() { + public Optimizer getOptimizer() { if (optimizer == null) { optimizer = new Optimizer(); } return optimizer; } - protected Collection getShardIds() { + public Collection getShardIds() { if (shardIds == null) { shardIds = new ArrayList<>(); } diff --git a/src/main/java/com/arangodb/model/CollectionCreateOptions.java b/src/main/java/com/arangodb/model/CollectionCreateOptions.java index e4c425aa0..a8c89af51 100644 --- a/src/main/java/com/arangodb/model/CollectionCreateOptions.java +++ b/src/main/java/com/arangodb/model/CollectionCreateOptions.java @@ -53,7 +53,7 @@ public CollectionCreateOptions() { replicationFactor = new ReplicationFactor(); } - protected String getName() { + public String getName() { return name; } diff --git a/src/main/java/com/arangodb/model/UserAccessOptions.java b/src/main/java/com/arangodb/model/UserAccessOptions.java index 85f86bc66..12355c642 100644 --- a/src/main/java/com/arangodb/model/UserAccessOptions.java +++ b/src/main/java/com/arangodb/model/UserAccessOptions.java @@ -33,7 +33,7 @@ public UserAccessOptions() { super(); } - protected Permissions getGrant() { + public Permissions getGrant() { return grant; } diff --git a/src/main/java/com/arangodb/model/UserCreateOptions.java b/src/main/java/com/arangodb/model/UserCreateOptions.java index 2ac216259..f4808da27 100644 --- a/src/main/java/com/arangodb/model/UserCreateOptions.java +++ b/src/main/java/com/arangodb/model/UserCreateOptions.java @@ -37,7 +37,7 @@ public UserCreateOptions() { super(); } - protected String getUser() { + public String getUser() { return user; } @@ -50,7 +50,7 @@ protected UserCreateOptions user(final String user) { return this; } - protected String getPasswd() { + public String getPasswd() { return passwd; } diff --git a/src/main/java/com/arangodb/serde/InternalModule.java b/src/main/java/com/arangodb/serde/InternalModule.java index cd0679b25..26ab243ae 100644 --- a/src/main/java/com/arangodb/serde/InternalModule.java +++ b/src/main/java/com/arangodb/serde/InternalModule.java @@ -1,6 +1,7 @@ package com.arangodb.serde; import com.arangodb.internal.velocystream.internal.AuthenticationRequest; +import com.arangodb.velocystream.Request; import com.fasterxml.jackson.databind.Module; import com.fasterxml.jackson.databind.module.SimpleModule; @@ -14,6 +15,7 @@ enum InternalModule implements Supplier { InternalModule() { module = new SimpleModule(); module.addSerializer(AuthenticationRequest.class, InternalSerializers.AUTHENTICATION_REQUEST); + module.addSerializer(Request.class, InternalSerializers.REQUEST); } @Override diff --git a/src/main/java/com/arangodb/serde/InternalSerializers.java b/src/main/java/com/arangodb/serde/InternalSerializers.java index 5ec7ae03c..feffa6c5a 100644 --- a/src/main/java/com/arangodb/serde/InternalSerializers.java +++ b/src/main/java/com/arangodb/serde/InternalSerializers.java @@ -1,11 +1,13 @@ package com.arangodb.serde; import com.arangodb.internal.velocystream.internal.AuthenticationRequest; +import com.arangodb.velocystream.Request; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.databind.JsonSerializer; import com.fasterxml.jackson.databind.SerializerProvider; import java.io.IOException; +import java.util.Map; final class InternalSerializers { @@ -25,4 +27,27 @@ public void serialize(AuthenticationRequest value, JsonGenerator gen, Serializer } }; + static final JsonSerializer REQUEST = new JsonSerializer() { + @Override + public void serialize(Request value, JsonGenerator gen, SerializerProvider serializers) throws IOException { + gen.writeStartArray(); + gen.writeNumber(value.getVersion()); + gen.writeNumber(value.getType()); + gen.writeString(value.getDbName().get()); + gen.writeNumber(value.getRequestType().getType()); + gen.writeString(value.getRequest()); + gen.writeStartObject(); + for (final Map.Entry entry : value.getQueryParam().entrySet()) { + gen.writeStringField(entry.getKey(), entry.getValue()); + } + gen.writeEndObject(); + gen.writeStartObject(); + for (final Map.Entry entry : value.getHeaderParam().entrySet()) { + gen.writeStringField(entry.getKey(), entry.getValue()); + } + gen.writeEndObject(); + gen.writeEndArray(); + } + }; + } diff --git a/src/main/java/com/arangodb/velocystream/Response.java b/src/main/java/com/arangodb/velocystream/Response.java index 9e3811793..9c5869869 100644 --- a/src/main/java/com/arangodb/velocystream/Response.java +++ b/src/main/java/com/arangodb/velocystream/Response.java @@ -20,9 +20,11 @@ package com.arangodb.velocystream; +import com.arangodb.serde.DataType; import com.arangodb.velocypack.VPackSlice; import com.arangodb.velocypack.annotations.Expose; +import java.nio.charset.StandardCharsets; import java.util.HashMap; import java.util.Map; @@ -38,8 +40,11 @@ public class Response { @Expose(deserialize = false) private VPackSlice body = null; - public Response() { + private final DataType dataType; + + public Response(final DataType dataType) { super(); + this.dataType = dataType; meta = new HashMap<>(); } @@ -83,4 +88,16 @@ public void setBody(final VPackSlice body) { this.body = body; } + public byte[] getBodyBytes() { + if (body == null) { + return new byte[0]; + } else if (dataType == DataType.JSON) { + return body.toString().getBytes(StandardCharsets.UTF_8); + } else if (dataType == DataType.VPACK) { + return body.toByteArray(); + } else { + throw new IllegalStateException("Unexpected value: " + dataType); + } + } + } From db0835da49aa8d82e0399f120ff33499f68befa1 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Wed, 29 Jun 2022 14:05:23 +0200 Subject: [PATCH 009/254] serde serialization refactoring: graph API --- src/main/java/com/arangodb/ArangoDB.java | 1 - .../java/com/arangodb/entity/EdgeDefinition.java | 14 +++++++++++--- .../com/arangodb/model/GraphCreateOptions.java | 9 ++++++--- .../arangodb/model/StreamTransactionOptions.java | 4 ++++ .../model/TransactionCollectionOptions.java | 7 ++++--- .../model/VertexCollectionCreateOptions.java | 9 ++++++--- src/test/java/com/arangodb/ArangoDBTest.java | 2 ++ src/test/java/com/arangodb/async/ArangoDBTest.java | 2 ++ .../com/arangodb/async/ArangoDatabaseTest.java | 4 ++-- .../java/com/arangodb/async/ArangoGraphTest.java | 2 +- src/test/resources/logback-test.xml | 2 +- 11 files changed, 39 insertions(+), 17 deletions(-) diff --git a/src/main/java/com/arangodb/ArangoDB.java b/src/main/java/com/arangodb/ArangoDB.java index 0686ca6cc..5dbad9ef3 100644 --- a/src/main/java/com/arangodb/ArangoDB.java +++ b/src/main/java/com/arangodb/ArangoDB.java @@ -38,7 +38,6 @@ import com.arangodb.model.LogOptions; import com.arangodb.model.UserCreateOptions; import com.arangodb.model.UserUpdateOptions; -import com.arangodb.serde.ArangoSerde; import com.arangodb.serde.DataType; import com.arangodb.serde.InternalSerde; import com.arangodb.util.ArangoCursorInitializer; diff --git a/src/main/java/com/arangodb/entity/EdgeDefinition.java b/src/main/java/com/arangodb/entity/EdgeDefinition.java index 140e01567..8fc808428 100644 --- a/src/main/java/com/arangodb/entity/EdgeDefinition.java +++ b/src/main/java/com/arangodb/entity/EdgeDefinition.java @@ -22,6 +22,7 @@ import java.util.Arrays; import java.util.Collection; +import java.util.Collections; /** * @author Mark Vollmary @@ -32,7 +33,7 @@ public class EdgeDefinition { private String collection; private Collection from; private Collection to; - private Options options; + private final Options options = new Options(); public String getCollection() { return collection; @@ -65,6 +66,10 @@ public Collection getSatellites() { return options.satellites; } + public Options getOptions() { + return options; + } + /** * @param satellites collection names that will be used to create SatelliteCollections * for a Hybrid (Disjoint) SmartGraph (Enterprise Edition only). Each array element @@ -73,12 +78,15 @@ public Collection getSatellites() { * @since ArangoDB 3.9.0 */ public EdgeDefinition satellites(final String... satellites) { - options = new Options(); options.satellites = Arrays.asList(satellites); return this; } public static class Options { - private Collection satellites; + private Collection satellites = Collections.emptyList(); + + public Collection getSatellites() { + return satellites; + } } } diff --git a/src/main/java/com/arangodb/model/GraphCreateOptions.java b/src/main/java/com/arangodb/model/GraphCreateOptions.java index 6d75fb4e1..1f4c3780b 100644 --- a/src/main/java/com/arangodb/model/GraphCreateOptions.java +++ b/src/main/java/com/arangodb/model/GraphCreateOptions.java @@ -25,6 +25,8 @@ import java.util.Arrays; import java.util.Collection; +import java.util.Collections; +import java.util.Objects; /** * @author Mark Vollmary @@ -33,8 +35,8 @@ public class GraphCreateOptions { private String name; - private Collection edgeDefinitions; - private Collection orphanCollections; + private Collection edgeDefinitions = Collections.emptyList(); + private Collection orphanCollections = Collections.emptyList(); private Boolean isSmart; private SmartOptions options; @@ -42,7 +44,7 @@ public GraphCreateOptions() { super(); } - protected String getName() { + public String getName() { return name; } @@ -64,6 +66,7 @@ public Collection getEdgeDefinitions() { * @return options */ protected GraphCreateOptions edgeDefinitions(final Collection edgeDefinitions) { + Objects.requireNonNull(edgeDefinitions); this.edgeDefinitions = edgeDefinitions; return this; } diff --git a/src/main/java/com/arangodb/model/StreamTransactionOptions.java b/src/main/java/com/arangodb/model/StreamTransactionOptions.java index 98f8b451d..52cae19d2 100644 --- a/src/main/java/com/arangodb/model/StreamTransactionOptions.java +++ b/src/main/java/com/arangodb/model/StreamTransactionOptions.java @@ -39,6 +39,10 @@ public StreamTransactionOptions() { collections = new TransactionCollectionOptions(); } + public TransactionCollectionOptions getCollections() { + return collections; + } + public Integer getLockTimeout() { return lockTimeout; } diff --git a/src/main/java/com/arangodb/model/TransactionCollectionOptions.java b/src/main/java/com/arangodb/model/TransactionCollectionOptions.java index d11d14220..e16060a33 100644 --- a/src/main/java/com/arangodb/model/TransactionCollectionOptions.java +++ b/src/main/java/com/arangodb/model/TransactionCollectionOptions.java @@ -22,6 +22,7 @@ import java.util.Arrays; import java.util.Collection; +import java.util.Collections; /** * @author Mark Vollmary @@ -29,9 +30,9 @@ */ public class TransactionCollectionOptions { - private Collection read; - private Collection write; - private Collection exclusive; + private Collection read = Collections.emptyList(); + private Collection write = Collections.emptyList(); + private Collection exclusive = Collections.emptyList(); private Boolean allowImplicit; public Collection getRead() { diff --git a/src/main/java/com/arangodb/model/VertexCollectionCreateOptions.java b/src/main/java/com/arangodb/model/VertexCollectionCreateOptions.java index b79b8ed41..4013a2c74 100644 --- a/src/main/java/com/arangodb/model/VertexCollectionCreateOptions.java +++ b/src/main/java/com/arangodb/model/VertexCollectionCreateOptions.java @@ -29,13 +29,13 @@ public class VertexCollectionCreateOptions { private String collection; - private Options options; + private final Options options = new Options();; public VertexCollectionCreateOptions() { super(); } - protected String getCollection() { + public String getCollection() { return collection; } @@ -60,13 +60,16 @@ public Collection getSatellites() { * @since ArangoDB 3.9.0 */ public VertexCollectionCreateOptions satellites(final String... satellites) { - options = new Options(); options.satellites = Arrays.asList(satellites); return this; } public static class Options { private Collection satellites; + + public Collection getSatellites() { + return satellites; + } } } diff --git a/src/test/java/com/arangodb/ArangoDBTest.java b/src/test/java/com/arangodb/ArangoDBTest.java index 76d991e6a..4495121d0 100644 --- a/src/test/java/com/arangodb/ArangoDBTest.java +++ b/src/test/java/com/arangodb/ArangoDBTest.java @@ -31,6 +31,7 @@ import com.arangodb.velocystream.Response; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.MethodSource; @@ -591,6 +592,7 @@ void accessMultipleDatabases(ArangoDB arangoDB) { @ParameterizedTest(name = "{index}") @MethodSource("arangos") + @Disabled("Manual execution only") void queueTime(ArangoDB arangoDB) throws InterruptedException, ExecutionException { List> futures = IntStream.range(0, 80) .mapToObj(i -> CompletableFuture.runAsync( diff --git a/src/test/java/com/arangodb/async/ArangoDBTest.java b/src/test/java/com/arangodb/async/ArangoDBTest.java index 6b7f7321c..965f84a3a 100644 --- a/src/test/java/com/arangodb/async/ArangoDBTest.java +++ b/src/test/java/com/arangodb/async/ArangoDBTest.java @@ -28,6 +28,7 @@ import com.arangodb.velocypack.exception.VPackException; import com.arangodb.velocystream.Request; import com.arangodb.velocystream.RequestType; +import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Timeout; @@ -501,6 +502,7 @@ void setLogLevel() throws InterruptedException, ExecutionException { } @Test + @Disabled("Manual execution only") void queueTime() throws InterruptedException, ExecutionException { List>> reqs = IntStream.range(0, 80) .mapToObj(__ -> arangoDB.db().query("RETURN SLEEP(1)", Void.class)) diff --git a/src/test/java/com/arangodb/async/ArangoDatabaseTest.java b/src/test/java/com/arangodb/async/ArangoDatabaseTest.java index b58e1e6ef..01a34350b 100644 --- a/src/test/java/com/arangodb/async/ArangoDatabaseTest.java +++ b/src/test/java/com/arangodb/async/ArangoDatabaseTest.java @@ -847,7 +847,7 @@ void createGetDeleteAqlFunctionWithNamespace() throws InterruptedException, Exec @Test void createGraph() throws InterruptedException, ExecutionException { try { - db.createGraph(GRAPH_NAME, null, null) + db.createGraph(GRAPH_NAME, Collections.emptyList(), null) .whenComplete((result, ex) -> { assertThat(result).isNotNull(); assertThat(result.getName()).isEqualTo(GRAPH_NAME); @@ -861,7 +861,7 @@ void createGraph() throws InterruptedException, ExecutionException { @Test void getGraphs() throws InterruptedException, ExecutionException { try { - db.createGraph(GRAPH_NAME, null, null).get(); + db.createGraph(GRAPH_NAME, Collections.emptyList(), null).get(); db.getGraphs() .whenComplete((graphs, ex) -> { assertThat(graphs).isNotNull(); diff --git a/src/test/java/com/arangodb/async/ArangoGraphTest.java b/src/test/java/com/arangodb/async/ArangoGraphTest.java index 9513d4fec..93a266c0f 100644 --- a/src/test/java/com/arangodb/async/ArangoGraphTest.java +++ b/src/test/java/com/arangodb/async/ArangoGraphTest.java @@ -85,7 +85,7 @@ void teardown() throws InterruptedException, ExecutionException { @Test void create() throws InterruptedException, ExecutionException { try { - final GraphEntity result = db.graph(GRAPH_NAME + "_1").create(null).get(); + final GraphEntity result = db.graph(GRAPH_NAME + "_1").create(Collections.emptyList()).get(); assertThat(result).isNotNull(); assertThat(result.getName()).isEqualTo(GRAPH_NAME + "_1"); } finally { diff --git a/src/test/resources/logback-test.xml b/src/test/resources/logback-test.xml index f67855e9c..579f1b9db 100644 --- a/src/test/resources/logback-test.xml +++ b/src/test/resources/logback-test.xml @@ -8,7 +8,7 @@ - + From e40962fa661a9e89e55c0bcfe8c07f9cd4d446d2 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Wed, 29 Jun 2022 20:11:15 +0200 Subject: [PATCH 010/254] serde serialization refactoring: collections API --- .../internal/InternalArangoCollection.java | 2 +- .../util/DefaultArangoSerialization.java | 8 ++++++-- .../java/com/arangodb/mapping/ArangoJack.java | 5 +++++ .../model/AqlFunctionCreateOptions.java | 4 ++-- .../model/AqlQueryExplainOptions.java | 4 ++-- .../arangodb/model/AqlQueryParseOptions.java | 2 +- .../model/CollectionCreateOptions.java | 5 ++++- .../com/arangodb/model/CollectionSchema.java | 17 ++++++++-------- .../arangodb/model/FulltextIndexOptions.java | 4 ++-- .../com/arangodb/model/GeoIndexOptions.java | 4 ++-- .../com/arangodb/model/HashIndexOptions.java | 4 ++-- .../java/com/arangodb/model/IndexOptions.java | 2 +- .../model/PersistentIndexOptions.java | 6 +++--- .../arangodb/model/SkiplistIndexOptions.java | 4 ++-- .../arangodb/model/TransactionOptions.java | 2 +- .../com/arangodb/model/TtlIndexOptions.java | 6 +++--- .../com/arangodb/model/ZKDIndexOptions.java | 6 ++++-- .../com/arangodb/serde/InternalModule.java | 2 ++ .../com/arangodb/serde/InternalSerde.java | 8 ++++++++ .../com/arangodb/serde/InternalSerdeImpl.java | 10 ++++++++++ .../arangodb/serde/InternalSerializers.java | 20 ++++++++++++++++++- .../arangodb/util/ArangoSerialization.java | 4 +++- .../com/arangodb/ArangoCollectionTest.java | 2 +- .../arangodb/ArangoVertexCollectionTest.java | 2 +- 24 files changed, 94 insertions(+), 39 deletions(-) diff --git a/src/main/java/com/arangodb/internal/InternalArangoCollection.java b/src/main/java/com/arangodb/internal/InternalArangoCollection.java index 70b32b23c..4d9bcbba9 100644 --- a/src/main/java/com/arangodb/internal/InternalArangoCollection.java +++ b/src/main/java/com/arangodb/internal/InternalArangoCollection.java @@ -180,7 +180,7 @@ protected ResponseDeserializer>> } protected Request importDocumentsRequest(final String values, final DocumentImportOptions options) { - return importDocumentsRequest(options).putQueryParam("type", ImportType.auto).setBody(util().serialize(values)); + return importDocumentsRequest(options).putQueryParam("type", ImportType.auto).setBody(util().serialize(util().parseJson(values))); } protected Request importDocumentsRequest(final Collection values, final DocumentImportOptions options) { diff --git a/src/main/java/com/arangodb/internal/util/DefaultArangoSerialization.java b/src/main/java/com/arangodb/internal/util/DefaultArangoSerialization.java index d6a6c6e29..f9ae383d3 100644 --- a/src/main/java/com/arangodb/internal/util/DefaultArangoSerialization.java +++ b/src/main/java/com/arangodb/internal/util/DefaultArangoSerialization.java @@ -28,6 +28,7 @@ import com.arangodb.util.ArangoSerializer; import com.arangodb.velocypack.VPackParser; import com.arangodb.velocypack.VPackSlice; +import com.fasterxml.jackson.databind.JsonNode; import java.lang.reflect.Type; @@ -49,13 +50,12 @@ public DefaultArangoSerialization(final ArangoSerializer serializer, final Arang @Override public VPackSlice serialize(final Object entity) throws ArangoDBException { -// return serializer.serialize(entity); DataType dataType = serde.getDataType(); switch (dataType) { case JSON: String json = new String(serde.serialize(entity)); VPackParser parser = new VPackParser.Builder().build(); - return parser.fromJson(json); + return parser.fromJson(json, true); case VPACK: return new VPackSlice(serde.serialize(entity)); default: @@ -73,4 +73,8 @@ public T deserialize(final VPackSlice vpack, final Type type) throws ArangoD return deserializer.deserialize(vpack, type); } + @Override + public JsonNode parseJson(String json) { + return serde.parseJson(json); + } } diff --git a/src/main/java/com/arangodb/mapping/ArangoJack.java b/src/main/java/com/arangodb/mapping/ArangoJack.java index 132a724b2..b768ea727 100644 --- a/src/main/java/com/arangodb/mapping/ArangoJack.java +++ b/src/main/java/com/arangodb/mapping/ArangoJack.java @@ -51,6 +51,11 @@ */ public class ArangoJack implements ArangoSerialization { + @Override + public JsonNode parseJson(String json) { + return null; + } + public interface ConfigureFunction { void configure(ObjectMapper mapper); } diff --git a/src/main/java/com/arangodb/model/AqlFunctionCreateOptions.java b/src/main/java/com/arangodb/model/AqlFunctionCreateOptions.java index a1897c491..d9c578804 100644 --- a/src/main/java/com/arangodb/model/AqlFunctionCreateOptions.java +++ b/src/main/java/com/arangodb/model/AqlFunctionCreateOptions.java @@ -44,7 +44,7 @@ protected AqlFunctionCreateOptions name(final String name) { return this; } - protected String getName() { + public String getName() { return name; } @@ -57,7 +57,7 @@ protected AqlFunctionCreateOptions code(final String code) { return this; } - protected String getCode() { + public String getCode() { return code; } diff --git a/src/main/java/com/arangodb/model/AqlQueryExplainOptions.java b/src/main/java/com/arangodb/model/AqlQueryExplainOptions.java index 27b962465..7e453a4b7 100644 --- a/src/main/java/com/arangodb/model/AqlQueryExplainOptions.java +++ b/src/main/java/com/arangodb/model/AqlQueryExplainOptions.java @@ -52,7 +52,7 @@ protected AqlQueryExplainOptions bindVars(final VPackSlice bindVars) { return this; } - protected String getQuery() { + public String getQuery() { return query; } @@ -119,7 +119,7 @@ public static class Options { private Integer maxNumberOfPlans; private Boolean allPlans; - protected Optimizer getOptimizer() { + public Optimizer getOptimizer() { if (optimizer == null) { optimizer = new Optimizer(); } diff --git a/src/main/java/com/arangodb/model/AqlQueryParseOptions.java b/src/main/java/com/arangodb/model/AqlQueryParseOptions.java index b2194779c..2059415e2 100644 --- a/src/main/java/com/arangodb/model/AqlQueryParseOptions.java +++ b/src/main/java/com/arangodb/model/AqlQueryParseOptions.java @@ -32,7 +32,7 @@ public AqlQueryParseOptions() { super(); } - protected String getQuery() { + public String getQuery() { return query; } diff --git a/src/main/java/com/arangodb/model/CollectionCreateOptions.java b/src/main/java/com/arangodb/model/CollectionCreateOptions.java index a8c89af51..5dafdf6f2 100644 --- a/src/main/java/com/arangodb/model/CollectionCreateOptions.java +++ b/src/main/java/com/arangodb/model/CollectionCreateOptions.java @@ -25,6 +25,8 @@ import com.arangodb.entity.KeyType; import com.arangodb.entity.ReplicationFactor; +import java.util.Objects; + /** * @author Mark Vollmary * @see API @@ -37,7 +39,7 @@ public class CollectionCreateOptions { private Integer writeConcern; private KeyOptions keyOptions; private Boolean waitForSync; - private String[] shardKeys; + private String[] shardKeys = new String[]{}; private Integer numberOfShards; private Boolean isSystem; private CollectionType type; @@ -166,6 +168,7 @@ public String[] getShardKeys() { * @return options */ public CollectionCreateOptions shardKeys(final String... shardKeys) { + Objects.requireNonNull(shardKeys); this.shardKeys = shardKeys; return this; } diff --git a/src/main/java/com/arangodb/model/CollectionSchema.java b/src/main/java/com/arangodb/model/CollectionSchema.java index 49b6fea85..bbc956c86 100644 --- a/src/main/java/com/arangodb/model/CollectionSchema.java +++ b/src/main/java/com/arangodb/model/CollectionSchema.java @@ -22,6 +22,10 @@ package com.arangodb.model; +import com.arangodb.serde.InternalSerializers; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; + /** * @author Michele Rastelli * @see API Documentation @@ -29,14 +33,6 @@ */ public class CollectionSchema { - /** - * Value to unset the collection schema on properties update {@link com.arangodb.ArangoCollection#changeProperties(CollectionPropertiesOptions)}. - */ - public static final CollectionSchema NULL_SCHEMA = new CollectionSchema() - .setLevel(null) - .setMessage(null) - .setRule(null); - private String rule; private Level level; private String message; @@ -44,6 +40,7 @@ public class CollectionSchema { /** * @return JSON Schema description */ + @JsonSerialize(using = InternalSerializers.CollectionSchemaRuleSerializer.class) public String getRule() { return rule; } @@ -82,11 +79,13 @@ public enum Level { /** * The rule is inactive and validation thus turned off. */ + @JsonProperty("none") NONE("none"), /** * Only newly inserted documents are validated. */ + @JsonProperty("new") NEW("new"), /** @@ -95,11 +94,13 @@ public enum Level { * but you want to stop the insertion of more invalid documents and prohibit that valid documents are changed to * invalid documents. */ + @JsonProperty("moderate") MODERATE("moderate"), /** * All new and modified document must strictly pass validation. No exceptions are made (default). */ + @JsonProperty("strict") STRICT("strict"); private final String value; diff --git a/src/main/java/com/arangodb/model/FulltextIndexOptions.java b/src/main/java/com/arangodb/model/FulltextIndexOptions.java index 9bf8f82a5..607e1b908 100644 --- a/src/main/java/com/arangodb/model/FulltextIndexOptions.java +++ b/src/main/java/com/arangodb/model/FulltextIndexOptions.java @@ -42,7 +42,7 @@ protected FulltextIndexOptions getThis() { return this; } - protected Iterable getFields() { + public Iterable getFields() { return fields; } @@ -55,7 +55,7 @@ protected FulltextIndexOptions fields(final Iterable fields) { return this; } - protected IndexType getType() { + public IndexType getType() { return type; } diff --git a/src/main/java/com/arangodb/model/GeoIndexOptions.java b/src/main/java/com/arangodb/model/GeoIndexOptions.java index 691ed0ec2..c55ba0c70 100644 --- a/src/main/java/com/arangodb/model/GeoIndexOptions.java +++ b/src/main/java/com/arangodb/model/GeoIndexOptions.java @@ -41,7 +41,7 @@ protected GeoIndexOptions getThis() { return this; } - protected Iterable getFields() { + public Iterable getFields() { return fields; } @@ -54,7 +54,7 @@ protected GeoIndexOptions fields(final Iterable fields) { return this; } - protected IndexType getType() { + public IndexType getType() { return type; } diff --git a/src/main/java/com/arangodb/model/HashIndexOptions.java b/src/main/java/com/arangodb/model/HashIndexOptions.java index 3af784ebb..6268a3718 100644 --- a/src/main/java/com/arangodb/model/HashIndexOptions.java +++ b/src/main/java/com/arangodb/model/HashIndexOptions.java @@ -47,7 +47,7 @@ protected HashIndexOptions getThis() { return this; } - protected Iterable getFields() { + public Iterable getFields() { return fields; } @@ -60,7 +60,7 @@ protected HashIndexOptions fields(final Iterable fields) { return this; } - protected IndexType getType() { + public IndexType getType() { return type; } diff --git a/src/main/java/com/arangodb/model/IndexOptions.java b/src/main/java/com/arangodb/model/IndexOptions.java index 1132e1c8e..7cafad173 100644 --- a/src/main/java/com/arangodb/model/IndexOptions.java +++ b/src/main/java/com/arangodb/model/IndexOptions.java @@ -59,7 +59,7 @@ public T name(final String name) { return getThis(); } - protected String getName() { + public String getName() { return name; } } diff --git a/src/main/java/com/arangodb/model/PersistentIndexOptions.java b/src/main/java/com/arangodb/model/PersistentIndexOptions.java index c9ba08c34..d7a752cd2 100644 --- a/src/main/java/com/arangodb/model/PersistentIndexOptions.java +++ b/src/main/java/com/arangodb/model/PersistentIndexOptions.java @@ -30,7 +30,7 @@ public class PersistentIndexOptions extends IndexOptions { private Iterable fields; - protected final IndexType type = IndexType.persistent; + private final IndexType type = IndexType.persistent; private Boolean unique; private Boolean sparse; private Boolean deduplicate; @@ -45,7 +45,7 @@ protected PersistentIndexOptions getThis() { return this; } - protected Iterable getFields() { + public Iterable getFields() { return fields; } @@ -58,7 +58,7 @@ protected PersistentIndexOptions fields(final Iterable fields) { return this; } - protected IndexType getType() { + public IndexType getType() { return type; } diff --git a/src/main/java/com/arangodb/model/SkiplistIndexOptions.java b/src/main/java/com/arangodb/model/SkiplistIndexOptions.java index 15f3dcdfe..981d7fa62 100644 --- a/src/main/java/com/arangodb/model/SkiplistIndexOptions.java +++ b/src/main/java/com/arangodb/model/SkiplistIndexOptions.java @@ -47,7 +47,7 @@ protected SkiplistIndexOptions getThis() { return this; } - protected Iterable getFields() { + public Iterable getFields() { return fields; } @@ -60,7 +60,7 @@ protected SkiplistIndexOptions fields(final Iterable fields) { return this; } - protected IndexType getType() { + public IndexType getType() { return type; } diff --git a/src/main/java/com/arangodb/model/TransactionOptions.java b/src/main/java/com/arangodb/model/TransactionOptions.java index e1226a1bd..249985805 100644 --- a/src/main/java/com/arangodb/model/TransactionOptions.java +++ b/src/main/java/com/arangodb/model/TransactionOptions.java @@ -40,7 +40,7 @@ public TransactionOptions() { collections = new TransactionCollectionOptions(); } - protected String getAction() { + public String getAction() { return action; } diff --git a/src/main/java/com/arangodb/model/TtlIndexOptions.java b/src/main/java/com/arangodb/model/TtlIndexOptions.java index 59ee57e82..a12e45ceb 100644 --- a/src/main/java/com/arangodb/model/TtlIndexOptions.java +++ b/src/main/java/com/arangodb/model/TtlIndexOptions.java @@ -41,7 +41,7 @@ protected TtlIndexOptions getThis() { return this; } - protected Iterable getFields() { + public Iterable getFields() { return fields; } @@ -54,7 +54,7 @@ protected TtlIndexOptions fields(final Iterable fields) { return this; } - protected IndexType getType() { + public IndexType getType() { return type; } @@ -67,7 +67,7 @@ public TtlIndexOptions expireAfter(final Integer expireAfter) { return this; } - protected Integer getExpireAfter() { + public Integer getExpireAfter() { return expireAfter; } diff --git a/src/main/java/com/arangodb/model/ZKDIndexOptions.java b/src/main/java/com/arangodb/model/ZKDIndexOptions.java index 4e570a9ad..6f17e5b87 100644 --- a/src/main/java/com/arangodb/model/ZKDIndexOptions.java +++ b/src/main/java/com/arangodb/model/ZKDIndexOptions.java @@ -21,6 +21,7 @@ package com.arangodb.model; import com.arangodb.entity.IndexType; +import com.fasterxml.jackson.annotation.JsonProperty; /** * @author Michele Rastelli @@ -43,7 +44,7 @@ protected ZKDIndexOptions getThis() { return this; } - protected Iterable getFields() { + public Iterable getFields() { return fields; } @@ -56,7 +57,7 @@ protected ZKDIndexOptions fields(final Iterable fields) { return this; } - protected IndexType getType() { + public IndexType getType() { return type; } @@ -87,6 +88,7 @@ public ZKDIndexOptions fieldValueTypes(final FieldValueTypes fieldValueTypes) { } public enum FieldValueTypes { + @JsonProperty("double") DOUBLE } diff --git a/src/main/java/com/arangodb/serde/InternalModule.java b/src/main/java/com/arangodb/serde/InternalModule.java index 26ab243ae..454d176ff 100644 --- a/src/main/java/com/arangodb/serde/InternalModule.java +++ b/src/main/java/com/arangodb/serde/InternalModule.java @@ -1,5 +1,6 @@ package com.arangodb.serde; +import com.arangodb.entity.CollectionType; import com.arangodb.internal.velocystream.internal.AuthenticationRequest; import com.arangodb.velocystream.Request; import com.fasterxml.jackson.databind.Module; @@ -16,6 +17,7 @@ enum InternalModule implements Supplier { module = new SimpleModule(); module.addSerializer(AuthenticationRequest.class, InternalSerializers.AUTHENTICATION_REQUEST); module.addSerializer(Request.class, InternalSerializers.REQUEST); + module.addSerializer(CollectionType.class, InternalSerializers.COLLECTION_TYPE); } @Override diff --git a/src/main/java/com/arangodb/serde/InternalSerde.java b/src/main/java/com/arangodb/serde/InternalSerde.java index 839c7e5f5..3d22df9fa 100644 --- a/src/main/java/com/arangodb/serde/InternalSerde.java +++ b/src/main/java/com/arangodb/serde/InternalSerde.java @@ -1,6 +1,7 @@ package com.arangodb.serde; import com.arangodb.jackson.dataformat.velocypack.VPackMapper; +import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; public interface InternalSerde extends JacksonSerde { @@ -39,4 +40,11 @@ static InternalSerde of(final DataType dataType) { */ byte[] extract(byte[] content, String jsonPointer); + /** + * Parse a JSON string. + * @param json JSON string to parse + * @return root of the parsed tree + */ + JsonNode parseJson(String json); + } diff --git a/src/main/java/com/arangodb/serde/InternalSerdeImpl.java b/src/main/java/com/arangodb/serde/InternalSerdeImpl.java index 4ef9b3c72..124ea7714 100644 --- a/src/main/java/com/arangodb/serde/InternalSerdeImpl.java +++ b/src/main/java/com/arangodb/serde/InternalSerdeImpl.java @@ -1,6 +1,7 @@ package com.arangodb.serde; import com.arangodb.ArangoDBException; +import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; @@ -42,4 +43,13 @@ public byte[] extract(final byte[] content, final String jsonPointer) { } } + @Override + public JsonNode parseJson(final String json) { + try { + return jsonMapper.readTree(json); + } catch (JsonProcessingException e) { + throw new ArangoDBException(e); + } + } + } diff --git a/src/main/java/com/arangodb/serde/InternalSerializers.java b/src/main/java/com/arangodb/serde/InternalSerializers.java index feffa6c5a..9498c16cc 100644 --- a/src/main/java/com/arangodb/serde/InternalSerializers.java +++ b/src/main/java/com/arangodb/serde/InternalSerializers.java @@ -1,15 +1,26 @@ package com.arangodb.serde; +import com.arangodb.entity.CollectionType; import com.arangodb.internal.velocystream.internal.AuthenticationRequest; import com.arangodb.velocystream.Request; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.databind.JsonSerializer; +import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializerProvider; import java.io.IOException; import java.util.Map; -final class InternalSerializers { +public final class InternalSerializers { + + private static final ObjectMapper jsonMapper = new ObjectMapper(); + + public static class CollectionSchemaRuleSerializer extends JsonSerializer { + @Override + public void serialize(String value, JsonGenerator gen, SerializerProvider serializers) throws IOException { + gen.writeTree(jsonMapper.readTree(value)); + } + } private InternalSerializers() { } @@ -50,4 +61,11 @@ public void serialize(Request value, JsonGenerator gen, SerializerProvider seria } }; + static final JsonSerializer COLLECTION_TYPE = new JsonSerializer() { + @Override + public void serialize(CollectionType value, JsonGenerator gen, SerializerProvider serializers) throws IOException { + gen.writeNumber(value.getType()); + } + }; + } diff --git a/src/main/java/com/arangodb/util/ArangoSerialization.java b/src/main/java/com/arangodb/util/ArangoSerialization.java index 2396d51b2..a2667a0d2 100644 --- a/src/main/java/com/arangodb/util/ArangoSerialization.java +++ b/src/main/java/com/arangodb/util/ArangoSerialization.java @@ -20,9 +20,11 @@ package com.arangodb.util; +import com.fasterxml.jackson.databind.JsonNode; + /** * @author Mark Vollmary */ public interface ArangoSerialization extends ArangoSerializer, ArangoDeserializer { - + JsonNode parseJson(String json); } diff --git a/src/test/java/com/arangodb/ArangoCollectionTest.java b/src/test/java/com/arangodb/ArangoCollectionTest.java index d332312e9..cf4aa26e8 100644 --- a/src/test/java/com/arangodb/ArangoCollectionTest.java +++ b/src/test/java/com/arangodb/ArangoCollectionTest.java @@ -2807,7 +2807,7 @@ void changeProperties(ArangoCollection collection) { // revert changes CollectionPropertiesEntity revertedProperties = collection.changeProperties(new CollectionPropertiesOptions() .waitForSync(properties.getWaitForSync()) - .schema(CollectionSchema.NULL_SCHEMA) + .schema(null) ); if (isAtLeastVersion(3, 7)) { assertThat(revertedProperties.getSchema()).isNull(); diff --git a/src/test/java/com/arangodb/ArangoVertexCollectionTest.java b/src/test/java/com/arangodb/ArangoVertexCollectionTest.java index 84283f19f..84f6530e4 100644 --- a/src/test/java/com/arangodb/ArangoVertexCollectionTest.java +++ b/src/test/java/com/arangodb/ArangoVertexCollectionTest.java @@ -58,7 +58,7 @@ static void init() { initCollections(COLLECTION_NAME); initGraph( GRAPH_NAME, - null, + Collections.emptyList(), new GraphCreateOptions().orphanCollections(COLLECTION_NAME) ); } From 5c258930aa59705e785b8944e25c691be1571469 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Thu, 30 Jun 2022 09:32:48 +0200 Subject: [PATCH 011/254] serde serialization refactoring: vertex collection API --- .../java/com/arangodb/async/ArangoVertexCollectionTest.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/test/java/com/arangodb/async/ArangoVertexCollectionTest.java b/src/test/java/com/arangodb/async/ArangoVertexCollectionTest.java index cdaa860c8..3da69c137 100644 --- a/src/test/java/com/arangodb/async/ArangoVertexCollectionTest.java +++ b/src/test/java/com/arangodb/async/ArangoVertexCollectionTest.java @@ -31,6 +31,7 @@ import java.util.Collection; +import java.util.Collections; import java.util.concurrent.ExecutionException; @@ -51,7 +52,7 @@ static void setup() throws InterruptedException, ExecutionException { db.createCollection(COLLECTION_NAME, null).get(); } final GraphCreateOptions options = new GraphCreateOptions().orphanCollections(COLLECTION_NAME); - db.createGraph(GRAPH_NAME, null, options).get(); + db.createGraph(GRAPH_NAME, Collections.emptyList(), options).get(); } @AfterEach From 07a629507fbb4888becb01634e025e975a276c13 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Thu, 30 Jun 2022 12:44:33 +0200 Subject: [PATCH 012/254] serde serialization refactoring: ArangoSearch API --- .../arangodb/entity/DocumentUpdateEntity.java | 2 + .../com/arangodb/entity/EdgeUpdateEntity.java | 2 + .../arangodb/entity/VertexUpdateEntity.java | 2 + .../java/com/arangodb/entity/ViewType.java | 3 + .../arangosearch/ArangoSearchProperties.java | 4 ++ .../entity/arangosearch/CollectionLink.java | 6 ++ .../arangosearch/ConsolidationType.java | 8 ++- .../entity/arangosearch/FieldLink.java | 6 ++ .../entity/arangosearch/StoreValuesType.java | 4 ++ .../analyzer/NormAnalyzerProperties.java | 2 + .../SegmentationAnalyzerProperties.java | 3 + .../analyzer/StopwordsAnalyzerProperties.java | 8 +++ .../analyzer/TextAnalyzerProperties.java | 2 + .../velocypack/VPackDriverModule.java | 1 - .../internal/velocypack/VPackSerializers.java | 7 -- .../com/arangodb/model/CollectionSchema.java | 8 +++ .../arangodb/model/GraphCreateOptions.java | 2 - .../ArangoSearchCreateOptions.java | 72 ++++++++++++++++--- .../ArangoSearchPropertiesOptions.java | 52 +++++++++----- .../com/arangodb/serde/InternalSerdeImpl.java | 2 + .../arangodb/serde/InternalSerializers.java | 27 ++++++- .../com/arangodb/ArangoCollectionTest.java | 2 +- .../java/com/arangodb/ArangoGraphTest.java | 4 +- .../arangodb/ArangoVertexCollectionTest.java | 2 +- .../arangodb/async/ArangoDatabaseTest.java | 4 +- .../com/arangodb/async/ArangoGraphTest.java | 6 +- .../async/ArangoVertexCollectionTest.java | 3 +- 27 files changed, 195 insertions(+), 49 deletions(-) diff --git a/src/main/java/com/arangodb/entity/DocumentUpdateEntity.java b/src/main/java/com/arangodb/entity/DocumentUpdateEntity.java index 009468000..c2bacbf94 100644 --- a/src/main/java/com/arangodb/entity/DocumentUpdateEntity.java +++ b/src/main/java/com/arangodb/entity/DocumentUpdateEntity.java @@ -22,6 +22,7 @@ import com.arangodb.velocypack.annotations.Expose; import com.arangodb.velocypack.annotations.SerializedName; +import com.fasterxml.jackson.annotation.JsonProperty; /** * @param @@ -31,6 +32,7 @@ */ public class DocumentUpdateEntity extends DocumentEntity { + @JsonProperty("_oldRev") @SerializedName("_oldRev") private String oldRev; @Expose(deserialize = false) diff --git a/src/main/java/com/arangodb/entity/EdgeUpdateEntity.java b/src/main/java/com/arangodb/entity/EdgeUpdateEntity.java index f872666a3..ea26e50ed 100644 --- a/src/main/java/com/arangodb/entity/EdgeUpdateEntity.java +++ b/src/main/java/com/arangodb/entity/EdgeUpdateEntity.java @@ -21,6 +21,7 @@ package com.arangodb.entity; import com.arangodb.velocypack.annotations.SerializedName; +import com.fasterxml.jackson.annotation.JsonProperty; /** * @author Mark Vollmary @@ -28,6 +29,7 @@ */ public class EdgeUpdateEntity extends DocumentEntity { + @JsonProperty("_oldRev") @SerializedName("_oldRev") private String oldRev; diff --git a/src/main/java/com/arangodb/entity/VertexUpdateEntity.java b/src/main/java/com/arangodb/entity/VertexUpdateEntity.java index 22d2d1078..89be57062 100644 --- a/src/main/java/com/arangodb/entity/VertexUpdateEntity.java +++ b/src/main/java/com/arangodb/entity/VertexUpdateEntity.java @@ -21,12 +21,14 @@ package com.arangodb.entity; import com.arangodb.velocypack.annotations.SerializedName; +import com.fasterxml.jackson.annotation.JsonProperty; /** * @author Mark Vollmary */ public class VertexUpdateEntity extends DocumentEntity { + @JsonProperty("_oldRev") @SerializedName("_oldRev") private String oldRev; diff --git a/src/main/java/com/arangodb/entity/ViewType.java b/src/main/java/com/arangodb/entity/ViewType.java index 21c039906..4844fe560 100644 --- a/src/main/java/com/arangodb/entity/ViewType.java +++ b/src/main/java/com/arangodb/entity/ViewType.java @@ -20,11 +20,14 @@ package com.arangodb.entity; +import com.fasterxml.jackson.annotation.JsonProperty; + /** * @author Mark Vollmary */ public enum ViewType { + @JsonProperty("arangosearch") ARANGO_SEARCH } diff --git a/src/main/java/com/arangodb/entity/arangosearch/ArangoSearchProperties.java b/src/main/java/com/arangodb/entity/arangosearch/ArangoSearchProperties.java index 7353cba66..443ac0dfe 100644 --- a/src/main/java/com/arangodb/entity/arangosearch/ArangoSearchProperties.java +++ b/src/main/java/com/arangodb/entity/arangosearch/ArangoSearchProperties.java @@ -20,6 +20,9 @@ package com.arangodb.entity.arangosearch; +import com.arangodb.serde.InternalSerializers; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; + import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; @@ -80,6 +83,7 @@ public void setConsolidationPolicy(final ConsolidationPolicy consolidationPolicy this.consolidationPolicy = consolidationPolicy; } + @JsonSerialize(using = InternalSerializers.CollectionLinksSerializer.class) public Collection getLinks() { return links; } diff --git a/src/main/java/com/arangodb/entity/arangosearch/CollectionLink.java b/src/main/java/com/arangodb/entity/arangosearch/CollectionLink.java index adf57d9da..897119991 100644 --- a/src/main/java/com/arangodb/entity/arangosearch/CollectionLink.java +++ b/src/main/java/com/arangodb/entity/arangosearch/CollectionLink.java @@ -20,6 +20,10 @@ package com.arangodb.entity.arangosearch; +import com.arangodb.serde.InternalSerializers; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; + import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; @@ -100,6 +104,7 @@ public CollectionLink fields(final FieldLink... fields) { return this; } + @JsonIgnore public String getName() { return name; } @@ -120,6 +125,7 @@ public StoreValuesType getStoreValues() { return storeValues; } + @JsonSerialize(using = InternalSerializers.FieldLinksSerializer.class) public Collection getFields() { return fields; } diff --git a/src/main/java/com/arangodb/entity/arangosearch/ConsolidationType.java b/src/main/java/com/arangodb/entity/arangosearch/ConsolidationType.java index 978a6a0d5..9ab2da72a 100644 --- a/src/main/java/com/arangodb/entity/arangosearch/ConsolidationType.java +++ b/src/main/java/com/arangodb/entity/arangosearch/ConsolidationType.java @@ -1,7 +1,13 @@ package com.arangodb.entity.arangosearch; +import com.fasterxml.jackson.annotation.JsonProperty; + public enum ConsolidationType { - BYTES_ACCUM, TIER + @JsonProperty("bytes_accum") + BYTES_ACCUM, + + @JsonProperty("tier") + TIER } \ No newline at end of file diff --git a/src/main/java/com/arangodb/entity/arangosearch/FieldLink.java b/src/main/java/com/arangodb/entity/arangosearch/FieldLink.java index d6bf26381..4027498fe 100644 --- a/src/main/java/com/arangodb/entity/arangosearch/FieldLink.java +++ b/src/main/java/com/arangodb/entity/arangosearch/FieldLink.java @@ -1,5 +1,9 @@ package com.arangodb.entity.arangosearch; +import com.arangodb.serde.InternalSerializers; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; + import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; @@ -77,6 +81,7 @@ public FieldLink fields(final FieldLink... fields) { return this; } + @JsonIgnore public String getName() { return name; } @@ -97,6 +102,7 @@ public StoreValuesType getStoreValues() { return storeValues; } + @JsonSerialize(using = InternalSerializers.FieldLinksSerializer.class) public Collection getFields() { return fields; } diff --git a/src/main/java/com/arangodb/entity/arangosearch/StoreValuesType.java b/src/main/java/com/arangodb/entity/arangosearch/StoreValuesType.java index 3630e903a..23577a4f8 100644 --- a/src/main/java/com/arangodb/entity/arangosearch/StoreValuesType.java +++ b/src/main/java/com/arangodb/entity/arangosearch/StoreValuesType.java @@ -20,6 +20,8 @@ package com.arangodb.entity.arangosearch; +import com.fasterxml.jackson.annotation.JsonProperty; + /** * @author Mark Vollmary */ @@ -28,11 +30,13 @@ public enum StoreValuesType { /** * Do not track values by the view */ + @JsonProperty("none") NONE, /** * Track only value presence, to allow use of the EXISTS() function. */ + @JsonProperty("id") ID } diff --git a/src/main/java/com/arangodb/entity/arangosearch/analyzer/NormAnalyzerProperties.java b/src/main/java/com/arangodb/entity/arangosearch/analyzer/NormAnalyzerProperties.java index cb1bcfbb8..ec0d7820c 100644 --- a/src/main/java/com/arangodb/entity/arangosearch/analyzer/NormAnalyzerProperties.java +++ b/src/main/java/com/arangodb/entity/arangosearch/analyzer/NormAnalyzerProperties.java @@ -22,6 +22,7 @@ import com.arangodb.velocypack.annotations.SerializedName; +import com.fasterxml.jackson.annotation.JsonProperty; import java.util.Objects; @@ -34,6 +35,7 @@ public class NormAnalyzerProperties { private boolean accent; + @JsonProperty("case") @SerializedName("case") private SearchAnalyzerCase analyzerCase; diff --git a/src/main/java/com/arangodb/entity/arangosearch/analyzer/SegmentationAnalyzerProperties.java b/src/main/java/com/arangodb/entity/arangosearch/analyzer/SegmentationAnalyzerProperties.java index 221cda81e..0140437c8 100644 --- a/src/main/java/com/arangodb/entity/arangosearch/analyzer/SegmentationAnalyzerProperties.java +++ b/src/main/java/com/arangodb/entity/arangosearch/analyzer/SegmentationAnalyzerProperties.java @@ -22,6 +22,7 @@ import com.arangodb.velocypack.annotations.SerializedName; +import com.fasterxml.jackson.annotation.JsonProperty; import java.util.Objects; @@ -31,9 +32,11 @@ */ public class SegmentationAnalyzerProperties { + @JsonProperty("break") @SerializedName("break") private BreakMode breakMode; + @JsonProperty("case") @SerializedName("case") private SearchAnalyzerCase analyzerCase; diff --git a/src/main/java/com/arangodb/entity/arangosearch/analyzer/StopwordsAnalyzerProperties.java b/src/main/java/com/arangodb/entity/arangosearch/analyzer/StopwordsAnalyzerProperties.java index 8b094e709..d00809337 100644 --- a/src/main/java/com/arangodb/entity/arangosearch/analyzer/StopwordsAnalyzerProperties.java +++ b/src/main/java/com/arangodb/entity/arangosearch/analyzer/StopwordsAnalyzerProperties.java @@ -21,6 +21,8 @@ package com.arangodb.entity.arangosearch.analyzer; +import com.fasterxml.jackson.annotation.JsonIgnore; + import java.util.ArrayList; import java.util.List; import java.util.Objects; @@ -57,9 +59,14 @@ public StopwordsAnalyzerProperties() { private final List stopwords; private final boolean hex; + public List getStopwords() { + return stopwords; + } + /** * @return list of verbatim strings that describe the tokens to be discarded. */ + @JsonIgnore public List getStopwordsAsStringList() { if (hex) { return stopwords.stream() @@ -73,6 +80,7 @@ public List getStopwordsAsStringList() { /** * @return list of hex-encoded strings that describe the tokens to be discarded. */ + @JsonIgnore public List getStopwordsAsHexList() { if (hex) { return stopwords; diff --git a/src/main/java/com/arangodb/entity/arangosearch/analyzer/TextAnalyzerProperties.java b/src/main/java/com/arangodb/entity/arangosearch/analyzer/TextAnalyzerProperties.java index b22f7bc34..5b68d0247 100644 --- a/src/main/java/com/arangodb/entity/arangosearch/analyzer/TextAnalyzerProperties.java +++ b/src/main/java/com/arangodb/entity/arangosearch/analyzer/TextAnalyzerProperties.java @@ -22,6 +22,7 @@ import com.arangodb.velocypack.annotations.SerializedName; +import com.fasterxml.jackson.annotation.JsonProperty; import java.util.Collections; import java.util.List; @@ -40,6 +41,7 @@ public TextAnalyzerProperties() { private boolean accent; + @JsonProperty("case") @SerializedName("case") private SearchAnalyzerCase analyzerCase; diff --git a/src/main/java/com/arangodb/internal/velocypack/VPackDriverModule.java b/src/main/java/com/arangodb/internal/velocypack/VPackDriverModule.java index ca86c5946..3635f386c 100644 --- a/src/main/java/com/arangodb/internal/velocypack/VPackDriverModule.java +++ b/src/main/java/com/arangodb/internal/velocypack/VPackDriverModule.java @@ -75,7 +75,6 @@ public > void setup(final C context) { context.registerSerializer(Permissions.class, VPackSerializers.PERMISSIONS); context.registerSerializer(ReplicationFactor.class, VPackSerializers.REPLICATION_FACTOR); context.registerSerializer(ViewType.class, VPackSerializers.VIEW_TYPE); - context.registerSerializer(ArangoSearchPropertiesOptions.class, VPackSerializers.ARANGO_SEARCH_PROPERTIES_OPTIONS); context.registerSerializer(ArangoSearchProperties.class, VPackSerializers.ARANGO_SEARCH_PROPERTIES); context.registerSerializer(ConsolidationType.class, VPackSerializers.CONSOLIDATE_TYPE); context.registerSerializer(CollectionSchema.class, VPackSerializers.COLLECTION_VALIDATION); diff --git a/src/main/java/com/arangodb/internal/velocypack/VPackSerializers.java b/src/main/java/com/arangodb/internal/velocypack/VPackSerializers.java index 399c8c8b5..fd94cc022 100644 --- a/src/main/java/com/arangodb/internal/velocypack/VPackSerializers.java +++ b/src/main/java/com/arangodb/internal/velocypack/VPackSerializers.java @@ -27,7 +27,6 @@ import com.arangodb.internal.velocystream.internal.JwtAuthenticationRequest; import com.arangodb.model.CollectionSchema; import com.arangodb.model.ZKDIndexOptions; -import com.arangodb.model.arangosearch.ArangoSearchPropertiesOptions; import com.arangodb.velocypack.*; import com.arangodb.velocystream.Request; @@ -119,12 +118,6 @@ public class VPackSerializers { builder.add(attribute, type); }; - public static final VPackSerializer ARANGO_SEARCH_PROPERTIES_OPTIONS = (builder, attribute, value, context) -> { - builder.add(ValueType.OBJECT); - context.serialize(builder, attribute, value.getProperties()); - builder.close(); - }; - public static final VPackSerializer ARANGO_SEARCH_PROPERTIES = (builder, attribute, value, context) -> { final Long consolidationIntervalMsec = value.getConsolidationIntervalMsec(); if (consolidationIntervalMsec != null) { diff --git a/src/main/java/com/arangodb/model/CollectionSchema.java b/src/main/java/com/arangodb/model/CollectionSchema.java index bbc956c86..8aa7bf098 100644 --- a/src/main/java/com/arangodb/model/CollectionSchema.java +++ b/src/main/java/com/arangodb/model/CollectionSchema.java @@ -33,6 +33,14 @@ */ public class CollectionSchema { + /** + * Value to unset the collection schema on properties update {@link com.arangodb.ArangoCollection#changeProperties(CollectionPropertiesOptions)}. + */ + public static final CollectionSchema NULL_SCHEMA = new CollectionSchema() + .setLevel(null) + .setMessage(null) + .setRule(null); + private String rule; private Level level; private String message; diff --git a/src/main/java/com/arangodb/model/GraphCreateOptions.java b/src/main/java/com/arangodb/model/GraphCreateOptions.java index 1f4c3780b..989999c08 100644 --- a/src/main/java/com/arangodb/model/GraphCreateOptions.java +++ b/src/main/java/com/arangodb/model/GraphCreateOptions.java @@ -26,7 +26,6 @@ import java.util.Arrays; import java.util.Collection; import java.util.Collections; -import java.util.Objects; /** * @author Mark Vollmary @@ -66,7 +65,6 @@ public Collection getEdgeDefinitions() { * @return options */ protected GraphCreateOptions edgeDefinitions(final Collection edgeDefinitions) { - Objects.requireNonNull(edgeDefinitions); this.edgeDefinitions = edgeDefinitions; return this; } diff --git a/src/main/java/com/arangodb/model/arangosearch/ArangoSearchCreateOptions.java b/src/main/java/com/arangodb/model/arangosearch/ArangoSearchCreateOptions.java index 2fcfe376b..66653bd5d 100644 --- a/src/main/java/com/arangodb/model/arangosearch/ArangoSearchCreateOptions.java +++ b/src/main/java/com/arangodb/model/arangosearch/ArangoSearchCreateOptions.java @@ -22,6 +22,11 @@ import com.arangodb.entity.ViewType; import com.arangodb.entity.arangosearch.*; +import com.arangodb.serde.InternalSerializers; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; + +import java.util.Arrays; +import java.util.Collection; /** * @author Mark Vollmary @@ -32,12 +37,18 @@ public class ArangoSearchCreateOptions { private String name; @SuppressWarnings("unused") private final ViewType type; - private final ArangoSearchProperties properties; + private Long consolidationIntervalMsec; + private Long commitIntervalMsec; + private Long cleanupIntervalStep; + private ConsolidationPolicy consolidationPolicy; + private Collection links; + private Collection primarySorts; + private ArangoSearchCompression primarySortCompression; + private Collection storedValues; public ArangoSearchCreateOptions() { super(); type = ViewType.ARANGO_SEARCH; - properties = new ArangoSearchProperties(); } protected ArangoSearchCreateOptions name(final String name) { @@ -54,7 +65,7 @@ protected ArangoSearchCreateOptions name(final String name) { * @return options */ public ArangoSearchCreateOptions consolidationIntervalMsec(final Long consolidationIntervalMsec) { - properties.setConsolidationIntervalMsec(consolidationIntervalMsec); + this.consolidationIntervalMsec = consolidationIntervalMsec; return this; } @@ -73,7 +84,7 @@ public ArangoSearchCreateOptions consolidationIntervalMsec(final Long consolidat * @return options */ public ArangoSearchCreateOptions commitIntervalMsec(final Long commitIntervalMsec) { - properties.setCommitIntervalMsec(commitIntervalMsec); + this.commitIntervalMsec = commitIntervalMsec; return this; } @@ -86,7 +97,7 @@ public ArangoSearchCreateOptions commitIntervalMsec(final Long commitIntervalMse * @return options */ public ArangoSearchCreateOptions cleanupIntervalStep(final Long cleanupIntervalStep) { - properties.setCleanupIntervalStep(cleanupIntervalStep); + this.cleanupIntervalStep = cleanupIntervalStep; return this; } @@ -95,7 +106,7 @@ public ArangoSearchCreateOptions cleanupIntervalStep(final Long cleanupIntervalS * @return options */ public ArangoSearchCreateOptions consolidationPolicy(final ConsolidationPolicy consolidationPolicy) { - properties.setConsolidationPolicy(consolidationPolicy); + this.consolidationPolicy = consolidationPolicy; return this; } @@ -104,7 +115,7 @@ public ArangoSearchCreateOptions consolidationPolicy(final ConsolidationPolicy c * @return options */ public ArangoSearchCreateOptions link(final CollectionLink... links) { - properties.addLink(links); + this.links = Arrays.asList(links); return this; } @@ -113,7 +124,7 @@ public ArangoSearchCreateOptions link(final CollectionLink... links) { * @return options */ public ArangoSearchCreateOptions primarySort(final PrimarySort... primarySorts) { - properties.addPrimarySort(primarySorts); + this.primarySorts = Arrays.asList(primarySorts); return this; } @@ -122,7 +133,7 @@ public ArangoSearchCreateOptions primarySort(final PrimarySort... primarySorts) * @return options */ public ArangoSearchCreateOptions primarySortCompression(final ArangoSearchCompression primarySortCompression) { - properties.setPrimarySortCompression(primarySortCompression); + this.primarySortCompression = primarySortCompression; return this; } @@ -130,8 +141,49 @@ public ArangoSearchCreateOptions primarySortCompression(final ArangoSearchCompre * @return options */ public ArangoSearchCreateOptions storedValues(final StoredValue... storedValues) { - properties.addStoredValues(storedValues); + this.storedValues = Arrays.asList(storedValues); return this; } + public String getName() { + return name; + } + + public ViewType getType() { + return type; + } + + public Long getConsolidationIntervalMsec() { + return consolidationIntervalMsec; + } + + public Long getCommitIntervalMsec() { + return commitIntervalMsec; + } + + public Long getCleanupIntervalStep() { + return cleanupIntervalStep; + } + + public ConsolidationPolicy getConsolidationPolicy() { + return consolidationPolicy; + } + + @JsonSerialize(using = InternalSerializers.CollectionLinksSerializer.class) + public Collection getLinks() { + return links; + } + + public Collection getPrimarySorts() { + return primarySorts; + } + + public ArangoSearchCompression getPrimarySortCompression() { + return primarySortCompression; + } + + public Collection getStoredValues() { + return storedValues; + } + } diff --git a/src/main/java/com/arangodb/model/arangosearch/ArangoSearchPropertiesOptions.java b/src/main/java/com/arangodb/model/arangosearch/ArangoSearchPropertiesOptions.java index a874e6d30..5283169d3 100644 --- a/src/main/java/com/arangodb/model/arangosearch/ArangoSearchPropertiesOptions.java +++ b/src/main/java/com/arangodb/model/arangosearch/ArangoSearchPropertiesOptions.java @@ -20,26 +20,26 @@ package com.arangodb.model.arangosearch; -import com.arangodb.entity.arangosearch.ArangoSearchProperties; import com.arangodb.entity.arangosearch.CollectionLink; import com.arangodb.entity.arangosearch.ConsolidationPolicy; import com.arangodb.entity.arangosearch.PrimarySort; +import com.arangodb.serde.InternalSerializers; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; + +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; /** * @author Mark Vollmary */ public class ArangoSearchPropertiesOptions { - private final ArangoSearchProperties properties; - - public ArangoSearchPropertiesOptions() { - super(); - properties = new ArangoSearchProperties(); - } - - public ArangoSearchProperties getProperties() { - return properties; - } + private Long consolidationIntervalMsec; + private Long cleanupIntervalStep; + private ConsolidationPolicy consolidationPolicy; + private Collection links; + private Collection primarySorts; /** * @param consolidationIntervalMsec Wait at least this many milliseconds between committing index data changes and making them visible to @@ -50,7 +50,7 @@ public ArangoSearchProperties getProperties() { * @return options */ public ArangoSearchPropertiesOptions consolidationIntervalMsec(final Long consolidationIntervalMsec) { - properties.setConsolidationIntervalMsec(consolidationIntervalMsec); + this.consolidationIntervalMsec = consolidationIntervalMsec; return this; } @@ -63,7 +63,7 @@ public ArangoSearchPropertiesOptions consolidationIntervalMsec(final Long consol * @return options */ public ArangoSearchPropertiesOptions cleanupIntervalStep(final Long cleanupIntervalStep) { - properties.setCleanupIntervalStep(cleanupIntervalStep); + this.cleanupIntervalStep = cleanupIntervalStep; return this; } @@ -72,7 +72,7 @@ public ArangoSearchPropertiesOptions cleanupIntervalStep(final Long cleanupInter * @return options */ public ArangoSearchPropertiesOptions consolidationPolicy(final ConsolidationPolicy consolidationPolicy) { - properties.setConsolidationPolicy(consolidationPolicy); + this.consolidationPolicy = consolidationPolicy; return this; } @@ -81,7 +81,7 @@ public ArangoSearchPropertiesOptions consolidationPolicy(final ConsolidationPoli * @return options */ public ArangoSearchPropertiesOptions link(final CollectionLink... links) { - properties.addLink(links); + this.links = Arrays.asList(links); return this; } @@ -90,8 +90,28 @@ public ArangoSearchPropertiesOptions link(final CollectionLink... links) { * @return options */ public ArangoSearchPropertiesOptions primarySort(final PrimarySort... primarySorts) { - properties.addPrimarySort(primarySorts); + this.primarySorts = Arrays.asList(primarySorts); return this; } + public Long getConsolidationIntervalMsec() { + return consolidationIntervalMsec; + } + + public Long getCleanupIntervalStep() { + return cleanupIntervalStep; + } + + public ConsolidationPolicy getConsolidationPolicy() { + return consolidationPolicy; + } + + @JsonSerialize(using = InternalSerializers.CollectionLinksSerializer.class) + public Collection getLinks() { + return links; + } + + public Collection getPrimarySorts() { + return primarySorts; + } } diff --git a/src/main/java/com/arangodb/serde/InternalSerdeImpl.java b/src/main/java/com/arangodb/serde/InternalSerdeImpl.java index 124ea7714..6ff759591 100644 --- a/src/main/java/com/arangodb/serde/InternalSerdeImpl.java +++ b/src/main/java/com/arangodb/serde/InternalSerdeImpl.java @@ -1,6 +1,7 @@ package com.arangodb.serde; import com.arangodb.ArangoDBException; +import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; @@ -14,6 +15,7 @@ class InternalSerdeImpl extends JacksonSerdeImpl implements InternalSerde { InternalSerdeImpl(DataType dataType, ObjectMapper mapper) { super(dataType, mapper); mapper.registerModule(InternalModule.INSTANCE.get()); + mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); } @Override diff --git a/src/main/java/com/arangodb/serde/InternalSerializers.java b/src/main/java/com/arangodb/serde/InternalSerializers.java index 9498c16cc..a6ec41e11 100644 --- a/src/main/java/com/arangodb/serde/InternalSerializers.java +++ b/src/main/java/com/arangodb/serde/InternalSerializers.java @@ -1,6 +1,9 @@ package com.arangodb.serde; import com.arangodb.entity.CollectionType; +import com.arangodb.entity.arangosearch.CollectionLink; +import com.arangodb.entity.arangosearch.FieldLink; +import com.arangodb.entity.arangosearch.StoreValuesType; import com.arangodb.internal.velocystream.internal.AuthenticationRequest; import com.arangodb.velocystream.Request; import com.fasterxml.jackson.core.JsonGenerator; @@ -9,7 +12,7 @@ import com.fasterxml.jackson.databind.SerializerProvider; import java.io.IOException; -import java.util.Map; +import java.util.*; public final class InternalSerializers { @@ -22,6 +25,28 @@ public void serialize(String value, JsonGenerator gen, SerializerProvider serial } } + public static class FieldLinksSerializer extends JsonSerializer> { + @Override + public void serialize(Collection value, JsonGenerator gen, SerializerProvider serializers) throws IOException { + Map mapLikeValue = new HashMap<>(); + for (FieldLink fl : value) { + mapLikeValue.put(fl.getName(), fl); + } + gen.writeObject(mapLikeValue); + } + } + + public static class CollectionLinksSerializer extends JsonSerializer> { + @Override + public void serialize(Collection value, JsonGenerator gen, SerializerProvider serializers) throws IOException { + Map mapLikeValue = new HashMap<>(); + for (CollectionLink cl : value) { + mapLikeValue.put(cl.getName(), cl); + } + gen.writeObject(mapLikeValue); + } + } + private InternalSerializers() { } diff --git a/src/test/java/com/arangodb/ArangoCollectionTest.java b/src/test/java/com/arangodb/ArangoCollectionTest.java index cf4aa26e8..d332312e9 100644 --- a/src/test/java/com/arangodb/ArangoCollectionTest.java +++ b/src/test/java/com/arangodb/ArangoCollectionTest.java @@ -2807,7 +2807,7 @@ void changeProperties(ArangoCollection collection) { // revert changes CollectionPropertiesEntity revertedProperties = collection.changeProperties(new CollectionPropertiesOptions() .waitForSync(properties.getWaitForSync()) - .schema(null) + .schema(CollectionSchema.NULL_SCHEMA) ); if (isAtLeastVersion(3, 7)) { assertThat(revertedProperties.getSchema()).isNull(); diff --git a/src/test/java/com/arangodb/ArangoGraphTest.java b/src/test/java/com/arangodb/ArangoGraphTest.java index 93aa505ce..f42d5848b 100644 --- a/src/test/java/com/arangodb/ArangoGraphTest.java +++ b/src/test/java/com/arangodb/ArangoGraphTest.java @@ -165,7 +165,7 @@ void addSatelliteVertexCollection(ArangoDatabase db) { String v1Name = "vertex-" + rnd(); ArangoGraph g = db.graph(GRAPH_NAME + rnd()); - g.create(Collections.emptyList(), new GraphCreateOptions().isSmart(true).smartGraphAttribute("test")); + g.create(null, new GraphCreateOptions().isSmart(true).smartGraphAttribute("test")); g.addVertexCollection(v1Name, new VertexCollectionCreateOptions().satellites(v1Name)); Collection vertexCollections = g.getVertexCollections(); @@ -229,7 +229,7 @@ void addSatelliteEdgeDefinition(ArangoDatabase db) { 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.create(null, new GraphCreateOptions().isSmart(true).smartGraphAttribute("test")); g.addEdgeDefinition(ed); final GraphEntity ge = g.getInfo(); assertThat(ge).isNotNull(); diff --git a/src/test/java/com/arangodb/ArangoVertexCollectionTest.java b/src/test/java/com/arangodb/ArangoVertexCollectionTest.java index 84f6530e4..84283f19f 100644 --- a/src/test/java/com/arangodb/ArangoVertexCollectionTest.java +++ b/src/test/java/com/arangodb/ArangoVertexCollectionTest.java @@ -58,7 +58,7 @@ static void init() { initCollections(COLLECTION_NAME); initGraph( GRAPH_NAME, - Collections.emptyList(), + null, new GraphCreateOptions().orphanCollections(COLLECTION_NAME) ); } diff --git a/src/test/java/com/arangodb/async/ArangoDatabaseTest.java b/src/test/java/com/arangodb/async/ArangoDatabaseTest.java index 01a34350b..b58e1e6ef 100644 --- a/src/test/java/com/arangodb/async/ArangoDatabaseTest.java +++ b/src/test/java/com/arangodb/async/ArangoDatabaseTest.java @@ -847,7 +847,7 @@ void createGetDeleteAqlFunctionWithNamespace() throws InterruptedException, Exec @Test void createGraph() throws InterruptedException, ExecutionException { try { - db.createGraph(GRAPH_NAME, Collections.emptyList(), null) + db.createGraph(GRAPH_NAME, null, null) .whenComplete((result, ex) -> { assertThat(result).isNotNull(); assertThat(result.getName()).isEqualTo(GRAPH_NAME); @@ -861,7 +861,7 @@ void createGraph() throws InterruptedException, ExecutionException { @Test void getGraphs() throws InterruptedException, ExecutionException { try { - db.createGraph(GRAPH_NAME, Collections.emptyList(), null).get(); + db.createGraph(GRAPH_NAME, null, null).get(); db.getGraphs() .whenComplete((graphs, ex) -> { assertThat(graphs).isNotNull(); diff --git a/src/test/java/com/arangodb/async/ArangoGraphTest.java b/src/test/java/com/arangodb/async/ArangoGraphTest.java index 93a266c0f..60658aa86 100644 --- a/src/test/java/com/arangodb/async/ArangoGraphTest.java +++ b/src/test/java/com/arangodb/async/ArangoGraphTest.java @@ -85,7 +85,7 @@ void teardown() throws InterruptedException, ExecutionException { @Test void create() throws InterruptedException, ExecutionException { try { - final GraphEntity result = db.graph(GRAPH_NAME + "_1").create(Collections.emptyList()).get(); + final GraphEntity result = db.graph(GRAPH_NAME + "_1").create(null).get(); assertThat(result).isNotNull(); assertThat(result.getName()).isEqualTo(GRAPH_NAME + "_1"); } finally { @@ -169,7 +169,7 @@ void addSatelliteVertexCollection() throws ExecutionException, InterruptedExcept String v1Name = "vertex-" + rnd(); ArangoGraphAsync g = db.graph(GRAPH_NAME + rnd()); - g.createGraph(Collections.emptyList(), new GraphCreateOptions().isSmart(true).smartGraphAttribute("test")).get(); + g.createGraph(null, new GraphCreateOptions().isSmart(true).smartGraphAttribute("test")).get(); g.addVertexCollection(v1Name, new VertexCollectionCreateOptions().satellites(v1Name)).get(); Collection vertexCollections = g.getVertexCollections().get(); @@ -229,7 +229,7 @@ void addSatelliteEdgeDefinition() throws ExecutionException, InterruptedExceptio 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.createGraph(null, new GraphCreateOptions().isSmart(true).smartGraphAttribute("test")).get(); g.addEdgeDefinition(ed).get(); final GraphEntity ge = g.getInfo().get(); assertThat(ge).isNotNull(); diff --git a/src/test/java/com/arangodb/async/ArangoVertexCollectionTest.java b/src/test/java/com/arangodb/async/ArangoVertexCollectionTest.java index 3da69c137..cdaa860c8 100644 --- a/src/test/java/com/arangodb/async/ArangoVertexCollectionTest.java +++ b/src/test/java/com/arangodb/async/ArangoVertexCollectionTest.java @@ -31,7 +31,6 @@ import java.util.Collection; -import java.util.Collections; import java.util.concurrent.ExecutionException; @@ -52,7 +51,7 @@ static void setup() throws InterruptedException, ExecutionException { db.createCollection(COLLECTION_NAME, null).get(); } final GraphCreateOptions options = new GraphCreateOptions().orphanCollections(COLLECTION_NAME); - db.createGraph(GRAPH_NAME, Collections.emptyList(), options).get(); + db.createGraph(GRAPH_NAME, null, options).get(); } @AfterEach From f3c6dda6ac8ead03bb9abf7453098205665f2b56 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Thu, 30 Jun 2022 17:27:53 +0200 Subject: [PATCH 013/254] SerdeUtils --- .../internal/InternalArangoCollection.java | 3 +- .../util/DefaultArangoSerialization.java | 4 -- .../java/com/arangodb/mapping/ArangoJack.java | 5 --- .../com/arangodb/serde/InternalSerde.java | 8 ---- .../com/arangodb/serde/InternalSerdeImpl.java | 13 +------ .../arangodb/serde/InternalSerializers.java | 10 ++--- .../java/com/arangodb/serde/SerdeUtils.java | 39 +++++++++++++++++++ .../arangodb/util/ArangoSerialization.java | 3 -- 8 files changed, 46 insertions(+), 39 deletions(-) create mode 100644 src/main/java/com/arangodb/serde/SerdeUtils.java diff --git a/src/main/java/com/arangodb/internal/InternalArangoCollection.java b/src/main/java/com/arangodb/internal/InternalArangoCollection.java index 4d9bcbba9..2f48005dc 100644 --- a/src/main/java/com/arangodb/internal/InternalArangoCollection.java +++ b/src/main/java/com/arangodb/internal/InternalArangoCollection.java @@ -28,6 +28,7 @@ import com.arangodb.internal.util.DocumentUtil; import com.arangodb.internal.util.RequestUtils; import com.arangodb.model.*; +import com.arangodb.serde.SerdeUtils; import com.arangodb.util.ArangoSerializer; import com.arangodb.velocypack.Type; import com.arangodb.velocypack.VPackSlice; @@ -180,7 +181,7 @@ protected ResponseDeserializer>> } protected Request importDocumentsRequest(final String values, final DocumentImportOptions options) { - return importDocumentsRequest(options).putQueryParam("type", ImportType.auto).setBody(util().serialize(util().parseJson(values))); + return importDocumentsRequest(options).putQueryParam("type", ImportType.auto).setBody(util().serialize(SerdeUtils.INSTANCE.parseJson(values))); } protected Request importDocumentsRequest(final Collection values, final DocumentImportOptions options) { diff --git a/src/main/java/com/arangodb/internal/util/DefaultArangoSerialization.java b/src/main/java/com/arangodb/internal/util/DefaultArangoSerialization.java index f9ae383d3..8672016bd 100644 --- a/src/main/java/com/arangodb/internal/util/DefaultArangoSerialization.java +++ b/src/main/java/com/arangodb/internal/util/DefaultArangoSerialization.java @@ -73,8 +73,4 @@ public T deserialize(final VPackSlice vpack, final Type type) throws ArangoD return deserializer.deserialize(vpack, type); } - @Override - public JsonNode parseJson(String json) { - return serde.parseJson(json); - } } diff --git a/src/main/java/com/arangodb/mapping/ArangoJack.java b/src/main/java/com/arangodb/mapping/ArangoJack.java index b768ea727..132a724b2 100644 --- a/src/main/java/com/arangodb/mapping/ArangoJack.java +++ b/src/main/java/com/arangodb/mapping/ArangoJack.java @@ -51,11 +51,6 @@ */ public class ArangoJack implements ArangoSerialization { - @Override - public JsonNode parseJson(String json) { - return null; - } - public interface ConfigureFunction { void configure(ObjectMapper mapper); } diff --git a/src/main/java/com/arangodb/serde/InternalSerde.java b/src/main/java/com/arangodb/serde/InternalSerde.java index 3d22df9fa..839c7e5f5 100644 --- a/src/main/java/com/arangodb/serde/InternalSerde.java +++ b/src/main/java/com/arangodb/serde/InternalSerde.java @@ -1,7 +1,6 @@ package com.arangodb.serde; import com.arangodb.jackson.dataformat.velocypack.VPackMapper; -import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; public interface InternalSerde extends JacksonSerde { @@ -40,11 +39,4 @@ static InternalSerde of(final DataType dataType) { */ byte[] extract(byte[] content, String jsonPointer); - /** - * Parse a JSON string. - * @param json JSON string to parse - * @return root of the parsed tree - */ - JsonNode parseJson(String json); - } diff --git a/src/main/java/com/arangodb/serde/InternalSerdeImpl.java b/src/main/java/com/arangodb/serde/InternalSerdeImpl.java index 6ff759591..a56bb25f8 100644 --- a/src/main/java/com/arangodb/serde/InternalSerdeImpl.java +++ b/src/main/java/com/arangodb/serde/InternalSerdeImpl.java @@ -2,7 +2,6 @@ import com.arangodb.ArangoDBException; import com.fasterxml.jackson.annotation.JsonInclude; -import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; @@ -10,7 +9,6 @@ import java.nio.charset.StandardCharsets; class InternalSerdeImpl extends JacksonSerdeImpl implements InternalSerde { - private final ObjectMapper jsonMapper = new ObjectMapper(); InternalSerdeImpl(DataType dataType, ObjectMapper mapper) { super(dataType, mapper); @@ -26,7 +24,7 @@ public String toJsonString(final byte[] content) { case VPACK: try { JsonNode tree = mapper.readTree(content); - return jsonMapper.writeValueAsString(tree); + return SerdeUtils.INSTANCE.writeJson(tree); } catch (IOException e) { throw new ArangoDBException(e); } @@ -45,13 +43,4 @@ public byte[] extract(final byte[] content, final String jsonPointer) { } } - @Override - public JsonNode parseJson(final String json) { - try { - return jsonMapper.readTree(json); - } catch (JsonProcessingException e) { - throw new ArangoDBException(e); - } - } - } diff --git a/src/main/java/com/arangodb/serde/InternalSerializers.java b/src/main/java/com/arangodb/serde/InternalSerializers.java index a6ec41e11..bcdb81fc9 100644 --- a/src/main/java/com/arangodb/serde/InternalSerializers.java +++ b/src/main/java/com/arangodb/serde/InternalSerializers.java @@ -3,25 +3,23 @@ import com.arangodb.entity.CollectionType; import com.arangodb.entity.arangosearch.CollectionLink; import com.arangodb.entity.arangosearch.FieldLink; -import com.arangodb.entity.arangosearch.StoreValuesType; import com.arangodb.internal.velocystream.internal.AuthenticationRequest; import com.arangodb.velocystream.Request; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.databind.JsonSerializer; -import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializerProvider; import java.io.IOException; -import java.util.*; +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; public final class InternalSerializers { - private static final ObjectMapper jsonMapper = new ObjectMapper(); - public static class CollectionSchemaRuleSerializer extends JsonSerializer { @Override public void serialize(String value, JsonGenerator gen, SerializerProvider serializers) throws IOException { - gen.writeTree(jsonMapper.readTree(value)); + gen.writeTree(SerdeUtils.INSTANCE.parseJson(value)); } } diff --git a/src/main/java/com/arangodb/serde/SerdeUtils.java b/src/main/java/com/arangodb/serde/SerdeUtils.java new file mode 100644 index 000000000..27e0c9eae --- /dev/null +++ b/src/main/java/com/arangodb/serde/SerdeUtils.java @@ -0,0 +1,39 @@ +package com.arangodb.serde; + +import com.arangodb.ArangoDBException; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; + +public enum SerdeUtils { + INSTANCE; + + private ObjectMapper jsonMapper = new ObjectMapper(); + + /** + * Parse a JSON string. + * + * @param json JSON string to parse + * @return root of the parsed tree + */ + public JsonNode parseJson(final String json) { + try { + return jsonMapper.readTree(json); + } catch (JsonProcessingException e) { + throw new ArangoDBException(e); + } + } + + /** + * @param data JsonNode + * @return JSON string + */ + public String writeJson(final JsonNode data) { + try { + return jsonMapper.writeValueAsString(data); + } catch (JsonProcessingException e) { + throw new ArangoDBException(e); + } + } + +} diff --git a/src/main/java/com/arangodb/util/ArangoSerialization.java b/src/main/java/com/arangodb/util/ArangoSerialization.java index a2667a0d2..c6f710171 100644 --- a/src/main/java/com/arangodb/util/ArangoSerialization.java +++ b/src/main/java/com/arangodb/util/ArangoSerialization.java @@ -20,11 +20,8 @@ package com.arangodb.util; -import com.fasterxml.jackson.databind.JsonNode; - /** * @author Mark Vollmary */ public interface ArangoSerialization extends ArangoSerializer, ArangoDeserializer { - JsonNode parseJson(String json); } From 7df2e593ea42810f79284bb4417d58d383342179 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Thu, 30 Jun 2022 20:19:34 +0200 Subject: [PATCH 014/254] serde serialization refactoring: View API --- .../java/com/arangodb/entity/LogLevelEntity.java | 4 ++++ .../com/arangodb/model/ViewCreateOptions.java | 8 ++++++++ .../java/com/arangodb/serde/InternalModule.java | 2 ++ .../com/arangodb/serde/InternalSerializers.java | 15 +++++++++++++++ 4 files changed, 29 insertions(+) diff --git a/src/main/java/com/arangodb/entity/LogLevelEntity.java b/src/main/java/com/arangodb/entity/LogLevelEntity.java index adcc1b393..1801d0cea 100644 --- a/src/main/java/com/arangodb/entity/LogLevelEntity.java +++ b/src/main/java/com/arangodb/entity/LogLevelEntity.java @@ -53,6 +53,10 @@ public LogLevelEntity() { super(); } + public LogLevel getAll() { + return all; + } + public void setAll(final LogLevel all) { this.all = all; } diff --git a/src/main/java/com/arangodb/model/ViewCreateOptions.java b/src/main/java/com/arangodb/model/ViewCreateOptions.java index b2287a6de..0fa34d0aa 100644 --- a/src/main/java/com/arangodb/model/ViewCreateOptions.java +++ b/src/main/java/com/arangodb/model/ViewCreateOptions.java @@ -46,4 +46,12 @@ protected ViewCreateOptions type(final ViewType type) { return this; } + public String getName() { + return name; + } + + public ViewType getType() { + return type; + } + } diff --git a/src/main/java/com/arangodb/serde/InternalModule.java b/src/main/java/com/arangodb/serde/InternalModule.java index 454d176ff..c30b5c663 100644 --- a/src/main/java/com/arangodb/serde/InternalModule.java +++ b/src/main/java/com/arangodb/serde/InternalModule.java @@ -2,6 +2,7 @@ import com.arangodb.entity.CollectionType; import com.arangodb.internal.velocystream.internal.AuthenticationRequest; +import com.arangodb.internal.velocystream.internal.JwtAuthenticationRequest; import com.arangodb.velocystream.Request; import com.fasterxml.jackson.databind.Module; import com.fasterxml.jackson.databind.module.SimpleModule; @@ -16,6 +17,7 @@ enum InternalModule implements Supplier { InternalModule() { module = new SimpleModule(); module.addSerializer(AuthenticationRequest.class, InternalSerializers.AUTHENTICATION_REQUEST); + module.addSerializer(JwtAuthenticationRequest.class, InternalSerializers.JWT_AUTHENTICATION_REQUEST); module.addSerializer(Request.class, InternalSerializers.REQUEST); module.addSerializer(CollectionType.class, InternalSerializers.COLLECTION_TYPE); } diff --git a/src/main/java/com/arangodb/serde/InternalSerializers.java b/src/main/java/com/arangodb/serde/InternalSerializers.java index bcdb81fc9..1917fc45b 100644 --- a/src/main/java/com/arangodb/serde/InternalSerializers.java +++ b/src/main/java/com/arangodb/serde/InternalSerializers.java @@ -1,9 +1,12 @@ package com.arangodb.serde; +import com.arangodb.entity.BaseDocument; import com.arangodb.entity.CollectionType; import com.arangodb.entity.arangosearch.CollectionLink; import com.arangodb.entity.arangosearch.FieldLink; import com.arangodb.internal.velocystream.internal.AuthenticationRequest; +import com.arangodb.internal.velocystream.internal.JwtAuthenticationRequest; +import com.arangodb.velocypack.ValueType; import com.arangodb.velocystream.Request; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.databind.JsonSerializer; @@ -61,6 +64,18 @@ public void serialize(AuthenticationRequest value, JsonGenerator gen, Serializer } }; + static final JsonSerializer JWT_AUTHENTICATION_REQUEST = new JsonSerializer() { + @Override + public void serialize(JwtAuthenticationRequest value, JsonGenerator gen, SerializerProvider serializers) throws IOException { + gen.writeStartArray(); + gen.writeNumber(value.getVersion()); + gen.writeNumber(value.getType()); + gen.writeString(value.getEncryption()); + gen.writeString(value.getToken()); + gen.writeEndArray(); + } + }; + static final JsonSerializer REQUEST = new JsonSerializer() { @Override public void serialize(Request value, JsonGenerator gen, SerializerProvider serializers) throws IOException { From e50aedf5c884de2af889e263d03af7537651804b Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Fri, 1 Jul 2022 10:24:11 +0200 Subject: [PATCH 015/254] serde serialization refactoring: ArangoJack --- src/main/java/com/arangodb/ArangoDB.java | 2 +- .../com/arangodb/entity/BaseDocument.java | 4 ++ .../internal/InternalArangoCollection.java | 8 ++- .../internal/mapping/VPackDeserializers.java | 18 ------ .../internal/mapping/VPackSerializers.java | 35 ---------- .../util/DefaultArangoSerialization.java | 1 - .../java/com/arangodb/mapping/ArangoJack.java | 64 ++++++++----------- .../com/arangodb/serde/InternalSerdeImpl.java | 3 + .../com/arangodb/example/ExampleBase.java | 7 +- 9 files changed, 44 insertions(+), 98 deletions(-) diff --git a/src/main/java/com/arangodb/ArangoDB.java b/src/main/java/com/arangodb/ArangoDB.java index 5dbad9ef3..ec3265318 100644 --- a/src/main/java/com/arangodb/ArangoDB.java +++ b/src/main/java/com/arangodb/ArangoDB.java @@ -378,7 +378,7 @@ public synchronized ArangoDB build() { final ConnectionFactory connectionFactory = (protocol == null || Protocol.VST == protocol) ? new VstConnectionFactorySync(host, timeout, connectionTtl, keepAliveInterval, useSsl, sslContext) - : new HttpConnectionFactory(timeout, user, password, useSsl, sslContext, hostnameVerifier, custom, + : new HttpConnectionFactory(timeout, user, password, useSsl, sslContext, hostnameVerifier, internal, protocol, connectionTtl, httpCookieSpec, httpRequestRetryHandler); final Collection hostList = createHostList(max, connectionFactory); diff --git a/src/main/java/com/arangodb/entity/BaseDocument.java b/src/main/java/com/arangodb/entity/BaseDocument.java index 2d6fe1967..72ea06cdc 100644 --- a/src/main/java/com/arangodb/entity/BaseDocument.java +++ b/src/main/java/com/arangodb/entity/BaseDocument.java @@ -21,6 +21,8 @@ package com.arangodb.entity; import com.arangodb.internal.DocumentFields; +import com.fasterxml.jackson.annotation.JsonAnyGetter; +import com.fasterxml.jackson.annotation.JsonAnySetter; import java.io.Serializable; import java.util.HashMap; @@ -92,6 +94,7 @@ public void setRevision(final String revision) { this.revision = revision; } + @JsonAnyGetter public Map getProperties() { return properties; } @@ -100,6 +103,7 @@ public void setProperties(final Map properties) { this.properties = properties; } + @JsonAnySetter public void addAttribute(final String key, final Object value) { properties.put(key, value); } diff --git a/src/main/java/com/arangodb/internal/InternalArangoCollection.java b/src/main/java/com/arangodb/internal/InternalArangoCollection.java index 2f48005dc..7314b325e 100644 --- a/src/main/java/com/arangodb/internal/InternalArangoCollection.java +++ b/src/main/java/com/arangodb/internal/InternalArangoCollection.java @@ -92,7 +92,13 @@ protected Request insertDocumentRequest(final T value, final DocumentCreateO request.putQueryParam(MERGE_OBJECTS, params.getMergeObjects()); request.putHeaderParam(TRANSACTION_ID, params.getStreamTransactionId()); - request.setBody(util(Serializer.CUSTOM).serialize(value)); + VPackSlice body; + if (value instanceof String) { + body = util().serialize(SerdeUtils.INSTANCE.parseJson((String) value)); + } else { + body = util(Serializer.CUSTOM).serialize(value); + } + request.setBody(body); return request; } diff --git a/src/main/java/com/arangodb/internal/mapping/VPackDeserializers.java b/src/main/java/com/arangodb/internal/mapping/VPackDeserializers.java index a30d9d0cf..6402a9e26 100644 --- a/src/main/java/com/arangodb/internal/mapping/VPackDeserializers.java +++ b/src/main/java/com/arangodb/internal/mapping/VPackDeserializers.java @@ -93,22 +93,4 @@ public java.sql.Timestamp deserialize(final JsonParser p, final DeserializationC } }; - public static final JsonDeserializer BASE_DOCUMENT = new JsonDeserializer() { - @SuppressWarnings("unchecked") - @Override - public BaseDocument deserialize(final JsonParser p, final DeserializationContext ctxt) - throws IOException, JsonProcessingException { - return new BaseDocument(p.readValueAs(Map.class)); - } - }; - - public static final JsonDeserializer BASE_EDGE_DOCUMENT = new JsonDeserializer() { - @SuppressWarnings("unchecked") - @Override - public BaseEdgeDocument deserialize(final JsonParser p, final DeserializationContext ctxt) - throws IOException, JsonProcessingException { - return new BaseEdgeDocument(p.readValueAs(Map.class)); - } - }; - } diff --git a/src/main/java/com/arangodb/internal/mapping/VPackSerializers.java b/src/main/java/com/arangodb/internal/mapping/VPackSerializers.java index eb4b4ad8f..3f8f34577 100644 --- a/src/main/java/com/arangodb/internal/mapping/VPackSerializers.java +++ b/src/main/java/com/arangodb/internal/mapping/VPackSerializers.java @@ -21,9 +21,6 @@ package com.arangodb.internal.mapping; -import com.arangodb.entity.BaseDocument; -import com.arangodb.entity.BaseEdgeDocument; -import com.arangodb.internal.DocumentFields; import com.arangodb.jackson.dataformat.velocypack.internal.VPackGenerator; import com.arangodb.velocypack.VPackSlice; import com.arangodb.velocypack.internal.util.DateUtil; @@ -35,8 +32,6 @@ import java.io.IOException; import java.sql.Date; import java.sql.Timestamp; -import java.util.HashMap; -import java.util.Map; /** * @author Mark Vollmary @@ -79,34 +74,4 @@ public void serialize(final Timestamp value, final JsonGenerator gen, final Seri } }; - public static final JsonSerializer BASE_DOCUMENT = new JsonSerializer() { - @Override - public void serialize(final BaseDocument value, final JsonGenerator gen, final SerializerProvider serializers) - throws IOException { - final Map doc = new HashMap<>(); - doc.putAll(value.getProperties()); - doc.put(DocumentFields.ID, value.getId()); - doc.put(DocumentFields.KEY, value.getKey()); - doc.put(DocumentFields.REV, value.getRevision()); - gen.writeObject(doc); - } - }; - - public static final JsonSerializer BASE_EDGE_DOCUMENT = new JsonSerializer() { - @Override - public void serialize( - final BaseEdgeDocument value, - final JsonGenerator gen, - final SerializerProvider serializers) throws IOException { - final Map doc = new HashMap<>(); - doc.putAll(value.getProperties()); - doc.put(DocumentFields.ID, value.getId()); - doc.put(DocumentFields.KEY, value.getKey()); - doc.put(DocumentFields.REV, value.getRevision()); - doc.put(DocumentFields.FROM, value.getFrom()); - doc.put(DocumentFields.TO, value.getTo()); - gen.writeObject(doc); - } - }; - } diff --git a/src/main/java/com/arangodb/internal/util/DefaultArangoSerialization.java b/src/main/java/com/arangodb/internal/util/DefaultArangoSerialization.java index 8672016bd..166f36644 100644 --- a/src/main/java/com/arangodb/internal/util/DefaultArangoSerialization.java +++ b/src/main/java/com/arangodb/internal/util/DefaultArangoSerialization.java @@ -28,7 +28,6 @@ import com.arangodb.util.ArangoSerializer; import com.arangodb.velocypack.VPackParser; import com.arangodb.velocypack.VPackSlice; -import com.fasterxml.jackson.databind.JsonNode; import java.lang.reflect.Type; diff --git a/src/main/java/com/arangodb/mapping/ArangoJack.java b/src/main/java/com/arangodb/mapping/ArangoJack.java index 132a724b2..06fb8e695 100644 --- a/src/main/java/com/arangodb/mapping/ArangoJack.java +++ b/src/main/java/com/arangodb/mapping/ArangoJack.java @@ -21,20 +21,18 @@ package com.arangodb.mapping; import com.arangodb.ArangoDBException; -import com.arangodb.entity.BaseDocument; -import com.arangodb.entity.BaseEdgeDocument; import com.arangodb.internal.mapping.ArangoAnnotationIntrospector; import com.arangodb.internal.mapping.VPackDeserializers; import com.arangodb.internal.mapping.VPackSerializers; import com.arangodb.jackson.dataformat.velocypack.VPackMapper; +import com.arangodb.serde.DataType; +import com.arangodb.serde.JacksonSerde; import com.arangodb.util.ArangoSerialization; -import com.arangodb.util.ArangoSerializer; import com.arangodb.velocypack.VPackParser; import com.arangodb.velocypack.VPackSlice; import com.fasterxml.jackson.annotation.JsonAutoDetect; import com.fasterxml.jackson.annotation.JsonInclude.Include; import com.fasterxml.jackson.annotation.PropertyAccessor; -import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; @@ -44,7 +42,6 @@ import java.io.IOException; import java.lang.reflect.Type; import java.util.Arrays; -import java.util.Iterator; /** * @author Mark Vollmary @@ -60,6 +57,8 @@ public interface ConfigureFunction { private final ObjectMapper jsonMapper; private final VPackParser vpackParser; + private final JacksonSerde serde; + private static final class ArangoModule extends SimpleModule { @Override public void setupModule(SetupContext context) { @@ -73,39 +72,43 @@ static VPackMapper createDefaultMapper() { mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false); mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); mapper.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY); + return configureDefaultMapper(mapper); + } + static VPackMapper configureDefaultMapper(final VPackMapper mapper) { final SimpleModule module = new ArangoJack.ArangoModule(); module.addSerializer(VPackSlice.class, VPackSerializers.VPACK); module.addSerializer(java.util.Date.class, VPackSerializers.UTIL_DATE); module.addSerializer(java.sql.Date.class, VPackSerializers.SQL_DATE); module.addSerializer(java.sql.Timestamp.class, VPackSerializers.SQL_TIMESTAMP); - module.addSerializer(BaseDocument.class, VPackSerializers.BASE_DOCUMENT); - module.addSerializer(BaseEdgeDocument.class, VPackSerializers.BASE_EDGE_DOCUMENT); module.addDeserializer(VPackSlice.class, VPackDeserializers.VPACK); module.addDeserializer(java.util.Date.class, VPackDeserializers.UTIL_DATE); module.addDeserializer(java.sql.Date.class, VPackDeserializers.SQL_DATE); module.addDeserializer(java.sql.Timestamp.class, VPackDeserializers.SQL_TIMESTAMP); - module.addDeserializer(BaseDocument.class, VPackDeserializers.BASE_DOCUMENT); - module.addDeserializer(BaseEdgeDocument.class, VPackDeserializers.BASE_EDGE_DOCUMENT); mapper.registerModule(module); return mapper; } public ArangoJack() { - this(createDefaultMapper()); + this(createDefaultMapper(), JacksonSerde.of(DataType.VPACK, configureDefaultMapper(new VPackMapper()))); + } + + public ArangoJack(final JacksonSerde jacksonSerde) { + this(createDefaultMapper(), jacksonSerde); } /** * @param mapper configured VPackMapper to use. A defensive copy is created and used. */ - public ArangoJack(final VPackMapper mapper) { + public ArangoJack(final VPackMapper mapper, final JacksonSerde jacksonSerde) { super(); vpackMapper = mapper.copy().setSerializationInclusion(Include.NON_NULL); vpackMapperNull = mapper.copy().setSerializationInclusion(Include.ALWAYS); jsonMapper = new ObjectMapper().setSerializationInclusion(Include.NON_NULL); vpackParser = new VPackParser.Builder().build(); + this.serde = jacksonSerde; } public void configure(final ArangoJack.ConfigureFunction f) { @@ -116,37 +119,24 @@ public void configure(final ArangoJack.ConfigureFunction f) { @Override public VPackSlice serialize(final Object entity) throws ArangoDBException { - return serialize(entity, new ArangoSerializer.Options()); + DataType dataType = serde.getDataType(); + switch (dataType) { + case JSON: + String json = new String(serde.serialize(entity)); + VPackParser parser = new VPackParser.Builder().build(); + return parser.fromJson(json, true); + case VPACK: + return new VPackSlice(serde.serialize(entity)); + default: + throw new IllegalStateException("Unexpected value: " + dataType); + } + } @SuppressWarnings("unchecked") @Override public VPackSlice serialize(final Object entity, final Options options) throws ArangoDBException { - if (options.getType() == null) { - options.type(entity.getClass()); - } - try { - final VPackSlice vpack; - final Class type = entity.getClass(); - final boolean serializeNullValues = options.isSerializeNullValues(); - if (String.class.isAssignableFrom(type)) { - vpack = vpackParser.fromJson((String) entity, serializeNullValues); - } else if (options.isStringAsJson() && Iterable.class.isAssignableFrom(type)) { - final Iterator iterator = Iterable.class.cast(entity).iterator(); - if (iterator.hasNext() && String.class.isAssignableFrom(iterator.next().getClass())) { - vpack = vpackParser.fromJson((Iterable) entity, serializeNullValues); - } else { - final ObjectMapper vp = serializeNullValues ? vpackMapperNull : vpackMapper; - vpack = new VPackSlice(vp.writeValueAsBytes(entity)); - } - } else { - final ObjectMapper vp = serializeNullValues ? vpackMapperNull : vpackMapper; - vpack = new VPackSlice(vp.writeValueAsBytes(entity)); - } - return vpack; - } catch (final JsonProcessingException e) { - throw new ArangoDBException(e); - } + return serialize(entity); } @SuppressWarnings("unchecked") diff --git a/src/main/java/com/arangodb/serde/InternalSerdeImpl.java b/src/main/java/com/arangodb/serde/InternalSerdeImpl.java index a56bb25f8..10b46c980 100644 --- a/src/main/java/com/arangodb/serde/InternalSerdeImpl.java +++ b/src/main/java/com/arangodb/serde/InternalSerdeImpl.java @@ -17,6 +17,9 @@ class InternalSerdeImpl extends JacksonSerdeImpl implements InternalSerde { } @Override + // FIXME: refactor to: + // return SerdeUtils.INSTANCE.writeJson(mapper.readTree(content)); + // afterwards dataType should not be needed anymore public String toJsonString(final byte[] content) { switch (dataType) { case JSON: diff --git a/src/test/java/com/arangodb/example/ExampleBase.java b/src/test/java/com/arangodb/example/ExampleBase.java index b4bd582e6..0c189b295 100644 --- a/src/test/java/com/arangodb/example/ExampleBase.java +++ b/src/test/java/com/arangodb/example/ExampleBase.java @@ -20,10 +20,7 @@ package com.arangodb.example; -import com.arangodb.ArangoCollection; -import com.arangodb.ArangoDB; -import com.arangodb.ArangoDatabase; -import com.arangodb.DbName; +import com.arangodb.*; import com.arangodb.mapping.ArangoJack; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; @@ -42,7 +39,7 @@ public class ExampleBase { @BeforeAll static void setUp() { - arangoDB = new ArangoDB.Builder().serializer(new ArangoJack()).build(); + arangoDB = new ArangoDB.Builder().useProtocol(Protocol.VST).serializer(new ArangoJack()).build(); DbName dbName = DbName.of(DB_NAME); if (arangoDB.db(dbName).exists()) arangoDB.db(dbName).drop(); From c2703cb7fd24fb18330e17b14590ffd34b86e62a Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Fri, 1 Jul 2022 11:59:43 +0200 Subject: [PATCH 016/254] serde serialization refactoring: Collection API --- .../internal/InternalArangoCollection.java | 36 ++++++++++++------ .../arangodb/model/DocumentUpdateOptions.java | 16 -------- .../com/arangodb/ArangoCollectionTest.java | 37 ++++++++++++++++--- .../com/arangodb/example/ExampleBase.java | 2 +- .../arangodb/serde/CustomTypeHintTest.java | 4 +- 5 files changed, 59 insertions(+), 36 deletions(-) diff --git a/src/main/java/com/arangodb/internal/InternalArangoCollection.java b/src/main/java/com/arangodb/internal/InternalArangoCollection.java index 7314b325e..6d2082750 100644 --- a/src/main/java/com/arangodb/internal/InternalArangoCollection.java +++ b/src/main/java/com/arangodb/internal/InternalArangoCollection.java @@ -29,11 +29,11 @@ import com.arangodb.internal.util.RequestUtils; import com.arangodb.model.*; import com.arangodb.serde.SerdeUtils; -import com.arangodb.util.ArangoSerializer; import com.arangodb.velocypack.Type; import com.arangodb.velocypack.VPackSlice; import com.arangodb.velocystream.Request; import com.arangodb.velocystream.RequestType; +import com.fasterxml.jackson.databind.JsonNode; import java.util.*; @@ -137,8 +137,9 @@ protected Request insertDocumentsRequest(final Collection values, final D request.putQueryParam(MERGE_OBJECTS, params.getMergeObjects()); request.putHeaderParam(TRANSACTION_ID, params.getStreamTransactionId()); - request.setBody(util(Serializer.CUSTOM) - .serialize(values, new ArangoSerializer.Options().serializeNullValues(false).stringAsJson(true))); + VPackSlice body = isStringCollection(values) ? util().serialize(stringCollectionToJsonArray((Collection) values)) + : util(Serializer.CUSTOM).serialize(values); + request.setBody(body); return request; } @@ -191,8 +192,9 @@ protected Request importDocumentsRequest(final String values, final DocumentImpo } protected Request importDocumentsRequest(final Collection values, final DocumentImportOptions options) { - return importDocumentsRequest(options).putQueryParam("type", ImportType.list).setBody(util(Serializer.CUSTOM) - .serialize(values, new ArangoSerializer.Options().serializeNullValues(false).stringAsJson(true))); + VPackSlice body = isStringCollection(values) ? util().serialize(stringCollectionToJsonArray((Collection) values)) + : util(Serializer.CUSTOM).serialize(values); + return importDocumentsRequest(options).putQueryParam("type", ImportType.list).setBody(body); } protected Request importDocumentsRequest(final DocumentImportOptions options) { @@ -304,8 +306,10 @@ protected Request replaceDocumentsRequest(final Collection values, final request.putQueryParam(RETURN_NEW, params.getReturnNew()); request.putQueryParam(RETURN_OLD, params.getReturnOld()); request.putQueryParam(SILENT, params.getSilent()); - request.setBody(util(Serializer.CUSTOM) - .serialize(values, new ArangoSerializer.Options().serializeNullValues(false).stringAsJson(true))); + + VPackSlice body = isStringCollection(values) ? util().serialize(stringCollectionToJsonArray((Collection) values)) + : util(Serializer.CUSTOM).serialize(values); + request.setBody(body); return request; } @@ -366,8 +370,7 @@ protected Request updateDocumentRequest(final String key, final T value, fin request.putQueryParam(RETURN_NEW, params.getReturnNew()); request.putQueryParam(RETURN_OLD, params.getReturnOld()); request.putQueryParam(SILENT, params.getSilent()); - request.setBody(util(Serializer.CUSTOM).serialize(value, new ArangoSerializer.Options() - .serializeNullValues(params.getSerializeNull() == null || params.getSerializeNull()))); + request.setBody(util(Serializer.CUSTOM).serialize(value)); return request; } @@ -405,9 +408,10 @@ protected Request updateDocumentsRequest(final Collection values, final D request.putQueryParam(RETURN_NEW, params.getReturnNew()); request.putQueryParam(RETURN_OLD, params.getReturnOld()); request.putQueryParam(SILENT, params.getSilent()); - request.setBody(util(Serializer.CUSTOM).serialize(values, new ArangoSerializer.Options() - .serializeNullValues(params.getSerializeNull() == null || params.getSerializeNull()) - .stringAsJson(true))); + + VPackSlice body = isStringCollection(values) ? util().serialize(stringCollectionToJsonArray((Collection) values)) + : util(Serializer.CUSTOM).serialize(values); + request.setBody(body); return request; } @@ -699,4 +703,12 @@ protected ResponseDeserializer getPermissionsResponseDeserialzer() }; } + private boolean isStringCollection(final Collection values) { + return values.stream().allMatch(String.class::isInstance); + } + + private JsonNode stringCollectionToJsonArray(final Collection values) { + return SerdeUtils.INSTANCE.parseJson("[" + String.join(",", values) + "]"); + } + } diff --git a/src/main/java/com/arangodb/model/DocumentUpdateOptions.java b/src/main/java/com/arangodb/model/DocumentUpdateOptions.java index 20d7b8cca..4ca261670 100644 --- a/src/main/java/com/arangodb/model/DocumentUpdateOptions.java +++ b/src/main/java/com/arangodb/model/DocumentUpdateOptions.java @@ -35,7 +35,6 @@ public class DocumentUpdateOptions { private String ifMatch; private Boolean returnNew; private Boolean returnOld; - private Boolean serializeNull; private Boolean silent; private String streamTransactionId; @@ -142,21 +141,6 @@ public DocumentUpdateOptions returnOld(final Boolean returnOld) { return this; } - public Boolean getSerializeNull() { - return serializeNull; - } - - /** - * @param serializeNull By default, or if this is set to true, all fields of the document which have null values are - * serialized to VelocyPack otherwise they are excluded from serialization. Use this to update single - * fields from a stored document. - * @return options - */ - public DocumentUpdateOptions serializeNull(final Boolean serializeNull) { - this.serializeNull = serializeNull; - return this; - } - public Boolean getSilent() { return silent; } diff --git a/src/test/java/com/arangodb/ArangoCollectionTest.java b/src/test/java/com/arangodb/ArangoCollectionTest.java index d332312e9..2e6ef6278 100644 --- a/src/test/java/com/arangodb/ArangoCollectionTest.java +++ b/src/test/java/com/arangodb/ArangoCollectionTest.java @@ -39,6 +39,8 @@ import com.arangodb.model.DocumentImportOptions.OnDuplicate; import com.arangodb.util.MapBuilder; import com.arangodb.velocypack.VPackSlice; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonIncludeProperties; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import org.junit.jupiter.api.BeforeAll; @@ -161,6 +163,7 @@ void insertDocumentReturnNew(ArangoCollection collection) { assertThat(doc.getRev()).isNotNull(); assertThat(doc.getNew()).isNotNull(); } + @ParameterizedTest(name = "{index}") @MethodSource("cols") void insertDocumentOverwriteModeIgnore(ArangoCollection collection) { @@ -732,6 +735,29 @@ void updateDocumentKeepNullFalse(ArangoCollection collection) { static class TestUpdateEntity { @SuppressWarnings("unused") private String a, b; + + public String getA() { + return a; + } + + public String getB() { + return b; + } + } + + static class TestUpdateEntitySerializeNullFalse { + @SuppressWarnings("unused") + private String a, b; + + @JsonInclude(JsonInclude.Include.NON_NULL) + public String getA() { + return a; + } + + @JsonInclude(JsonInclude.Include.NON_NULL) + public String getB() { + return b; + } } @ParameterizedTest(name = "{index}") @@ -758,14 +784,14 @@ void updateDocumentSerializeNullTrue(ArangoCollection collection) { @ParameterizedTest(name = "{index}") @MethodSource("cols") void updateDocumentSerializeNullFalse(ArangoCollection collection) { - final TestUpdateEntity doc = new TestUpdateEntity(); + final TestUpdateEntitySerializeNullFalse doc = new TestUpdateEntitySerializeNullFalse(); doc.a = "foo"; doc.b = "foo"; - final DocumentCreateEntity createResult = collection.insertDocument(doc); - final TestUpdateEntity patchDoc = new TestUpdateEntity(); + final DocumentCreateEntity createResult = collection.insertDocument(doc); + final TestUpdateEntitySerializeNullFalse patchDoc = new TestUpdateEntitySerializeNullFalse(); patchDoc.a = "bar"; - final DocumentUpdateEntity updateResult = collection - .updateDocument(createResult.getKey(), patchDoc, new DocumentUpdateOptions().serializeNull(false)); + final DocumentUpdateEntity updateResult = collection + .updateDocument(createResult.getKey(), patchDoc); assertThat(updateResult).isNotNull(); assertThat(updateResult.getKey()).isEqualTo(createResult.getKey()); @@ -2752,6 +2778,7 @@ void replaceDocumentsJson(ArangoCollection collection) { assertThat(updateResult.getDocuments()).hasSize(2); assertThat(updateResult.getErrors()).isEmpty(); } + @ParameterizedTest(name = "{index}") @MethodSource("cols") void getInfo(ArangoCollection collection) { diff --git a/src/test/java/com/arangodb/example/ExampleBase.java b/src/test/java/com/arangodb/example/ExampleBase.java index 0c189b295..b903a31d5 100644 --- a/src/test/java/com/arangodb/example/ExampleBase.java +++ b/src/test/java/com/arangodb/example/ExampleBase.java @@ -39,7 +39,7 @@ public class ExampleBase { @BeforeAll static void setUp() { - arangoDB = new ArangoDB.Builder().useProtocol(Protocol.VST).serializer(new ArangoJack()).build(); + arangoDB = new ArangoDB.Builder().serializer(new ArangoJack()).build(); DbName dbName = DbName.of(DB_NAME); if (arangoDB.db(dbName).exists()) arangoDB.db(dbName).drop(); diff --git a/src/test/java/com/arangodb/serde/CustomTypeHintTest.java b/src/test/java/com/arangodb/serde/CustomTypeHintTest.java index a19eda063..f3e9bf046 100644 --- a/src/test/java/com/arangodb/serde/CustomTypeHintTest.java +++ b/src/test/java/com/arangodb/serde/CustomTypeHintTest.java @@ -25,9 +25,9 @@ import com.arangodb.ArangoDB; import com.arangodb.ArangoDatabase; import com.arangodb.DbName; +import com.arangodb.entity.Key; import com.arangodb.mapping.ArangoJack; import com.arangodb.model.DocumentCreateOptions; -import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonTypeInfo; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; @@ -61,7 +61,7 @@ public void setName(String name) { public static class Zoo { - @JsonProperty("_key") + @Key private String key; private Animal animal; From 6477ed42566d5c771f5bff1d626e20021fb571a6 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Fri, 1 Jul 2022 12:17:31 +0200 Subject: [PATCH 017/254] JacksonSerde configuration --- src/main/java/com/arangodb/mapping/ArangoJack.java | 11 ++++------- src/main/java/com/arangodb/serde/JacksonSerde.java | 7 +++++++ .../java/com/arangodb/serde/JacksonSerdeImpl.java | 6 ++++++ src/test/java/com/arangodb/serde/CustomSerdeTest.java | 1 + 4 files changed, 18 insertions(+), 7 deletions(-) diff --git a/src/main/java/com/arangodb/mapping/ArangoJack.java b/src/main/java/com/arangodb/mapping/ArangoJack.java index 06fb8e695..e8c318232 100644 --- a/src/main/java/com/arangodb/mapping/ArangoJack.java +++ b/src/main/java/com/arangodb/mapping/ArangoJack.java @@ -92,29 +92,26 @@ static VPackMapper configureDefaultMapper(final VPackMapper mapper) { } public ArangoJack() { - this(createDefaultMapper(), JacksonSerde.of(DataType.VPACK, configureDefaultMapper(new VPackMapper()))); - } - - public ArangoJack(final JacksonSerde jacksonSerde) { - this(createDefaultMapper(), jacksonSerde); + this(createDefaultMapper()); } /** * @param mapper configured VPackMapper to use. A defensive copy is created and used. */ - public ArangoJack(final VPackMapper mapper, final JacksonSerde jacksonSerde) { + public ArangoJack(final VPackMapper mapper) { super(); vpackMapper = mapper.copy().setSerializationInclusion(Include.NON_NULL); vpackMapperNull = mapper.copy().setSerializationInclusion(Include.ALWAYS); jsonMapper = new ObjectMapper().setSerializationInclusion(Include.NON_NULL); vpackParser = new VPackParser.Builder().build(); - this.serde = jacksonSerde; + serde = JacksonSerde.of(DataType.VPACK, configureDefaultMapper(new VPackMapper())); } public void configure(final ArangoJack.ConfigureFunction f) { f.configure(vpackMapper); f.configure(vpackMapperNull); f.configure(jsonMapper); + serde.configure(f::configure); } @Override diff --git a/src/main/java/com/arangodb/serde/JacksonSerde.java b/src/main/java/com/arangodb/serde/JacksonSerde.java index 9887a7767..91d9ede18 100644 --- a/src/main/java/com/arangodb/serde/JacksonSerde.java +++ b/src/main/java/com/arangodb/serde/JacksonSerde.java @@ -5,6 +5,7 @@ import com.fasterxml.jackson.databind.ObjectMapper; import java.lang.reflect.Type; +import java.util.function.Consumer; /** * Contract for serialization/deserialization of user data, based on Jackson Databind. @@ -40,6 +41,12 @@ static JacksonSerde of(final DataType dataType, final ObjectMapper mapper) { return new JacksonSerdeImpl(dataType, mapper); } + /** + * Allows configuring the underlying Jackson ObjectMapper + * @param configureFunction function to configure the Jackson ObjectMapper + */ + void configure(final Consumer configureFunction); + /** * Deserializes the parsed json node and binds it to the target data type. * diff --git a/src/main/java/com/arangodb/serde/JacksonSerdeImpl.java b/src/main/java/com/arangodb/serde/JacksonSerdeImpl.java index 3964f0ea4..e6c373a04 100644 --- a/src/main/java/com/arangodb/serde/JacksonSerdeImpl.java +++ b/src/main/java/com/arangodb/serde/JacksonSerdeImpl.java @@ -7,6 +7,7 @@ import java.io.IOException; import java.lang.reflect.Type; +import java.util.function.Consumer; class JacksonSerdeImpl implements JacksonSerde { @@ -41,6 +42,11 @@ public T deserialize(final byte[] content, final Type type) { } } + @Override + public void configure(Consumer configureFunction) { + configureFunction.accept(mapper); + } + @Override public T deserialize(final JsonNode node, final Type type) { try { diff --git a/src/test/java/com/arangodb/serde/CustomSerdeTest.java b/src/test/java/com/arangodb/serde/CustomSerdeTest.java index 834d1cd56..e5cd72078 100644 --- a/src/test/java/com/arangodb/serde/CustomSerdeTest.java +++ b/src/test/java/com/arangodb/serde/CustomSerdeTest.java @@ -26,6 +26,7 @@ import com.arangodb.ArangoDatabase; import com.arangodb.DbName; import com.arangodb.entity.BaseDocument; +import com.arangodb.jackson.dataformat.velocypack.VPackMapper; import com.arangodb.mapping.ArangoJack; import com.arangodb.model.DocumentCreateOptions; import com.arangodb.util.ArangoSerialization; From 0ff7790ec7d5b29b1ae803ed4068cade9b62b526 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Fri, 1 Jul 2022 12:54:30 +0200 Subject: [PATCH 018/254] VPackSlice serializer --- .../java/com/arangodb/model/AqlQueryOptions.java | 4 ++-- .../java/com/arangodb/serde/InternalModule.java | 2 ++ .../com/arangodb/serde/InternalSerializers.java | 13 +++++++++++-- 3 files changed, 15 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/arangodb/model/AqlQueryOptions.java b/src/main/java/com/arangodb/model/AqlQueryOptions.java index ddb5a4f16..56fc50c68 100644 --- a/src/main/java/com/arangodb/model/AqlQueryOptions.java +++ b/src/main/java/com/arangodb/model/AqlQueryOptions.java @@ -151,7 +151,7 @@ public AqlQueryOptions fillBlockCache(final Boolean fillBlockCache) { return this; } - protected VPackSlice getBindVars() { + public VPackSlice getBindVars() { return bindVars; } @@ -172,7 +172,7 @@ public String getQuery() { * @param query the query which you want parse * @return options */ - protected AqlQueryOptions query(final String query) { + public AqlQueryOptions query(final String query) { this.query = query; return this; } diff --git a/src/main/java/com/arangodb/serde/InternalModule.java b/src/main/java/com/arangodb/serde/InternalModule.java index c30b5c663..2c8d1442d 100644 --- a/src/main/java/com/arangodb/serde/InternalModule.java +++ b/src/main/java/com/arangodb/serde/InternalModule.java @@ -3,6 +3,7 @@ import com.arangodb.entity.CollectionType; import com.arangodb.internal.velocystream.internal.AuthenticationRequest; import com.arangodb.internal.velocystream.internal.JwtAuthenticationRequest; +import com.arangodb.velocypack.VPackSlice; import com.arangodb.velocystream.Request; import com.fasterxml.jackson.databind.Module; import com.fasterxml.jackson.databind.module.SimpleModule; @@ -16,6 +17,7 @@ enum InternalModule implements Supplier { InternalModule() { module = new SimpleModule(); + module.addSerializer(VPackSlice.class, InternalSerializers.VPACK_SLICE_JSON_SERIALIZER); module.addSerializer(AuthenticationRequest.class, InternalSerializers.AUTHENTICATION_REQUEST); module.addSerializer(JwtAuthenticationRequest.class, InternalSerializers.JWT_AUTHENTICATION_REQUEST); module.addSerializer(Request.class, InternalSerializers.REQUEST); diff --git a/src/main/java/com/arangodb/serde/InternalSerializers.java b/src/main/java/com/arangodb/serde/InternalSerializers.java index 1917fc45b..46514b8c3 100644 --- a/src/main/java/com/arangodb/serde/InternalSerializers.java +++ b/src/main/java/com/arangodb/serde/InternalSerializers.java @@ -1,12 +1,12 @@ package com.arangodb.serde; -import com.arangodb.entity.BaseDocument; import com.arangodb.entity.CollectionType; import com.arangodb.entity.arangosearch.CollectionLink; import com.arangodb.entity.arangosearch.FieldLink; import com.arangodb.internal.velocystream.internal.AuthenticationRequest; import com.arangodb.internal.velocystream.internal.JwtAuthenticationRequest; -import com.arangodb.velocypack.ValueType; +import com.arangodb.jackson.dataformat.velocypack.VPackMapper; +import com.arangodb.velocypack.VPackSlice; import com.arangodb.velocystream.Request; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.databind.JsonSerializer; @@ -48,9 +48,18 @@ public void serialize(Collection value, JsonGenerator gen, Seria } } + private static final VPackMapper vPackMapper = new VPackMapper(); + private InternalSerializers() { } + static final JsonSerializer VPACK_SLICE_JSON_SERIALIZER = new JsonSerializer() { + @Override + public void serialize(VPackSlice value, JsonGenerator gen, SerializerProvider serializers) throws IOException { + gen.writeObject(vPackMapper.readTree(value.toByteArray())); + } + }; + static final JsonSerializer AUTHENTICATION_REQUEST = new JsonSerializer() { @Override public void serialize(AuthenticationRequest value, JsonGenerator gen, SerializerProvider serializers) throws IOException { From 2e61252ff04e78c76915ae07e0d404c00fd32172 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Fri, 1 Jul 2022 13:04:34 +0200 Subject: [PATCH 019/254] serde serialization refactoring: Transactions API --- src/main/java/com/arangodb/model/TransactionOptions.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/java/com/arangodb/model/TransactionOptions.java b/src/main/java/com/arangodb/model/TransactionOptions.java index 249985805..ebe31c7d9 100644 --- a/src/main/java/com/arangodb/model/TransactionOptions.java +++ b/src/main/java/com/arangodb/model/TransactionOptions.java @@ -40,6 +40,10 @@ public TransactionOptions() { collections = new TransactionCollectionOptions(); } + public TransactionCollectionOptions getCollections() { + return collections; + } + public String getAction() { return action; } From ce9d295af41dac1ae1397382c79096bbe7a90a66 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Fri, 1 Jul 2022 13:07:18 +0200 Subject: [PATCH 020/254] serde serialization refactoring: Cursor API --- .../InternalArangoVertexCollection.java | 10 +++- .../com/arangodb/model/AqlQueryOptions.java | 58 ++++++++++++++++++- 2 files changed, 66 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/arangodb/internal/InternalArangoVertexCollection.java b/src/main/java/com/arangodb/internal/InternalArangoVertexCollection.java index 0472adbb9..4962fa6fa 100644 --- a/src/main/java/com/arangodb/internal/InternalArangoVertexCollection.java +++ b/src/main/java/com/arangodb/internal/InternalArangoVertexCollection.java @@ -27,6 +27,7 @@ import com.arangodb.internal.util.DocumentUtil; import com.arangodb.internal.util.RequestUtils; import com.arangodb.model.*; +import com.arangodb.serde.SerdeUtils; import com.arangodb.util.ArangoSerializer; import com.arangodb.velocypack.VPackSlice; import com.arangodb.velocystream.Request; @@ -73,7 +74,14 @@ protected Request insertVertexRequest(final T value, final VertexCreateOptio final VertexCreateOptions params = (options != null ? options : new VertexCreateOptions()); request.putHeaderParam(TRANSACTION_ID, params.getStreamTransactionId()); request.putQueryParam(ArangoRequestParam.WAIT_FOR_SYNC, params.getWaitForSync()); - request.setBody(util(Serializer.CUSTOM).serialize(value)); + + VPackSlice body; + if (value instanceof String) { + body = util().serialize(SerdeUtils.INSTANCE.parseJson((String) value)); + } else { + body = util(Serializer.CUSTOM).serialize(value); + } + request.setBody(body); return request; } diff --git a/src/main/java/com/arangodb/model/AqlQueryOptions.java b/src/main/java/com/arangodb/model/AqlQueryOptions.java index 56fc50c68..51e8494f7 100644 --- a/src/main/java/com/arangodb/model/AqlQueryOptions.java +++ b/src/main/java/com/arangodb/model/AqlQueryOptions.java @@ -402,7 +402,7 @@ public AqlQueryOptions shardIds(final String... shardIds) { return this; } - private Options getOptions() { + public Options getOptions() { if (options == null) { options = new Options(); } @@ -429,6 +429,58 @@ public static class Options implements Serializable { private Double maxRuntime; private Boolean fillBlockCache; + public Boolean getFailOnWarning() { + return failOnWarning; + } + + public Boolean getProfile() { + return profile; + } + + public Long getMaxTransactionSize() { + return maxTransactionSize; + } + + public Long getMaxWarningCount() { + return maxWarningCount; + } + + public Long getIntermediateCommitCount() { + return intermediateCommitCount; + } + + public Long getIntermediateCommitSize() { + return intermediateCommitSize; + } + + public Double getSatelliteSyncWait() { + return satelliteSyncWait; + } + + public Boolean getSkipInaccessibleCollections() { + return skipInaccessibleCollections; + } + + public Boolean getFullCount() { + return fullCount; + } + + public Integer getMaxPlans() { + return maxPlans; + } + + public Boolean getStream() { + return stream; + } + + public Double getMaxRuntime() { + return maxRuntime; + } + + public Boolean getFillBlockCache() { + return fillBlockCache; + } + public Optimizer getOptimizer() { if (optimizer == null) { optimizer = new Optimizer(); @@ -447,6 +499,10 @@ public Collection getShardIds() { public static class Optimizer { private Collection rules; + + public Collection getRules() { + return rules; + } } /** From e894791d69ce5e25e79e026d7e96d58bce7bd3f3 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Tue, 5 Jul 2022 12:27:42 +0200 Subject: [PATCH 021/254] ReplicationFactor refactoring --- .../entity/CollectionPropertiesEntity.java | 22 +++------ .../com/arangodb/entity/DatabaseEntity.java | 15 ++----- .../java/com/arangodb/entity/GraphEntity.java | 8 +--- .../arangodb/entity/ReplicationFactor.java | 45 +++++++++++-------- .../velocypack/VPackDeserializers.java | 6 +-- .../velocypack/VPackDriverModule.java | 1 - .../internal/velocypack/VPackSerializers.java | 9 ---- .../model/CollectionCreateOptions.java | 35 +++++++-------- .../com/arangodb/model/DatabaseOptions.java | 36 +++++++-------- .../arangodb/model/GraphCreateOptions.java | 42 ++++++----------- .../model/VertexCollectionCreateOptions.java | 4 ++ src/test/java/com/arangodb/ArangoDBTest.java | 8 ++-- .../java/com/arangodb/ArangoDatabaseTest.java | 21 ++++----- .../java/com/arangodb/ArangoGraphTest.java | 21 ++++----- .../java/com/arangodb/async/ArangoDBTest.java | 8 ++-- .../arangodb/async/ArangoDatabaseTest.java | 5 +-- .../com/arangodb/async/ArangoGraphTest.java | 27 +++++------ 17 files changed, 127 insertions(+), 186 deletions(-) diff --git a/src/main/java/com/arangodb/entity/CollectionPropertiesEntity.java b/src/main/java/com/arangodb/entity/CollectionPropertiesEntity.java index 73f55d758..050104ffe 100644 --- a/src/main/java/com/arangodb/entity/CollectionPropertiesEntity.java +++ b/src/main/java/com/arangodb/entity/CollectionPropertiesEntity.java @@ -33,14 +33,13 @@ public class CollectionPropertiesEntity extends CollectionEntity { private Long count; private Integer numberOfShards; private Collection shardKeys; - private final ReplicationFactor replicationFactor; + private ReplicationFactor replicationFactor; private Integer writeConcern; private String shardingStrategy; // cluster option private String smartJoinAttribute; // enterprise option public CollectionPropertiesEntity() { super(); - replicationFactor = new ReplicationFactor(); } public KeyOptions getKeyOptions() { @@ -82,12 +81,12 @@ public void setShardKeys(final Collection shardKeys) { this.shardKeys = shardKeys; } - public Integer getReplicationFactor() { - return replicationFactor.getReplicationFactor(); + public ReplicationFactor getReplicationFactor() { + return replicationFactor; } - public void setReplicationFactor(final Integer replicationFactor) { - this.replicationFactor.setReplicationFactor(replicationFactor); + public void setReplicationFactor(final ReplicationFactor replicationFactor) { + this.replicationFactor = replicationFactor; } public Integer getWriteConcern() { @@ -98,17 +97,6 @@ public void setWriteConcern(final Integer writeConcern) { this.writeConcern = writeConcern; } - /** - * @return whether the collection is a satellite collection. Only in an enterprise cluster setup (else returning null). - */ - public Boolean getSatellite() { - return this.replicationFactor.getSatellite(); - } - - public void setSatellite(final Boolean satellite) { - this.replicationFactor.setSatellite(satellite); - } - public String getShardingStrategy() { return shardingStrategy; } diff --git a/src/main/java/com/arangodb/entity/DatabaseEntity.java b/src/main/java/com/arangodb/entity/DatabaseEntity.java index 975065f50..524db2c63 100644 --- a/src/main/java/com/arangodb/entity/DatabaseEntity.java +++ b/src/main/java/com/arangodb/entity/DatabaseEntity.java @@ -30,13 +30,12 @@ public class DatabaseEntity implements Entity { private String name; private String path; private Boolean isSystem; - private final ReplicationFactor replicationFactor; + private ReplicationFactor replicationFactor; private Integer writeConcern; private String sharding; public DatabaseEntity() { super(); - replicationFactor = new ReplicationFactor(); } /** @@ -71,8 +70,8 @@ public Boolean getIsSystem() { * @return the default replication factor for collections in this database * @since ArangoDB 3.6.0 */ - public Integer getReplicationFactor() { - return replicationFactor.getReplicationFactor(); + public ReplicationFactor getReplicationFactor() { + return replicationFactor; } /** @@ -87,14 +86,6 @@ public Integer getWriteConcern() { return writeConcern; } - /** - * @return whether the collection is a satellite collection. Only in an enterprise cluster setup (else returning null). - * @since ArangoDB 3.6.0 - */ - public Boolean getSatellite() { - return this.replicationFactor.getSatellite(); - } - /** * @return information about the default sharding method for collections created in this database * @since ArangoDB 3.6.0 diff --git a/src/main/java/com/arangodb/entity/GraphEntity.java b/src/main/java/com/arangodb/entity/GraphEntity.java index 151979131..858a60acd 100644 --- a/src/main/java/com/arangodb/entity/GraphEntity.java +++ b/src/main/java/com/arangodb/entity/GraphEntity.java @@ -66,12 +66,8 @@ public Integer getNumberOfShards() { return numberOfShards; } - public Integer getReplicationFactor() { - return replicationFactor.getReplicationFactor(); - } - - public Boolean getSatellite() { - return this.replicationFactor.getSatellite(); + public ReplicationFactor getReplicationFactor() { + return replicationFactor; } public Integer getWriteConcern() { diff --git a/src/main/java/com/arangodb/entity/ReplicationFactor.java b/src/main/java/com/arangodb/entity/ReplicationFactor.java index b228f3f66..9b84bbf4f 100644 --- a/src/main/java/com/arangodb/entity/ReplicationFactor.java +++ b/src/main/java/com/arangodb/entity/ReplicationFactor.java @@ -20,32 +20,41 @@ package com.arangodb.entity; -/** - * @author Mark Vollmary - */ -public class ReplicationFactor { +import com.fasterxml.jackson.annotation.JsonValue; - private Integer replicationFactor; - private Boolean satellite; +public interface ReplicationFactor { - public ReplicationFactor() { - super(); + static NumericReplicationFactor of(int value) { + return new NumericReplicationFactor(value); } - public Integer getReplicationFactor() { - return replicationFactor; + static SatelliteReplicationFactor ofSatellite() { + return SatelliteReplicationFactor.INSTANCE; } - public void setReplicationFactor(final Integer replicationFactor) { - this.replicationFactor = replicationFactor; - } + @JsonValue + Object getValue(); - public Boolean getSatellite() { - return satellite; - } + class NumericReplicationFactor implements ReplicationFactor { + + private Integer value; - public void setSatellite(final Boolean satellite) { - this.satellite = satellite; + public NumericReplicationFactor(Integer value) { + this.value = value; + } + + @Override + public Integer getValue() { + return value; + } } + enum SatelliteReplicationFactor implements ReplicationFactor { + INSTANCE; + + @Override + public String getValue() { + return "satellite"; + } + } } diff --git a/src/main/java/com/arangodb/internal/velocypack/VPackDeserializers.java b/src/main/java/com/arangodb/internal/velocypack/VPackDeserializers.java index 344b66983..f2cad52d6 100644 --- a/src/main/java/com/arangodb/internal/velocypack/VPackDeserializers.java +++ b/src/main/java/com/arangodb/internal/velocypack/VPackDeserializers.java @@ -141,13 +141,11 @@ public class VPackDeserializers { public static final VPackDeserializer QUERY_EXECUTION_STATE = (parent, vpack, context) -> QueryExecutionState.valueOf(vpack.getAsString().toUpperCase(Locale.ENGLISH).replaceAll(" ", "_")); public static final VPackDeserializer REPLICATION_FACTOR = (parent, vpack, context) -> { - final ReplicationFactor replicationFactor = new ReplicationFactor(); if (vpack.isString() && vpack.getAsString().equals("satellite")) { - replicationFactor.setSatellite(true); + return ReplicationFactor.ofSatellite(); } else { - replicationFactor.setReplicationFactor(vpack.getAsInt()); + return ReplicationFactor.of(vpack.getAsInt()); } - return replicationFactor; }; public static final VPackDeserializer VIEW_TYPE = (parent, vpack, context) -> "arangosearch".equals(vpack.getAsString()) ? ViewType.ARANGO_SEARCH diff --git a/src/main/java/com/arangodb/internal/velocypack/VPackDriverModule.java b/src/main/java/com/arangodb/internal/velocypack/VPackDriverModule.java index 3635f386c..5172f8e3a 100644 --- a/src/main/java/com/arangodb/internal/velocypack/VPackDriverModule.java +++ b/src/main/java/com/arangodb/internal/velocypack/VPackDriverModule.java @@ -73,7 +73,6 @@ public > void setup(final C context) { context.registerSerializer(BaseEdgeDocument.class, VPackSerializers.BASE_EDGE_DOCUMENT); context.registerSerializer(LogLevel.class, VPackSerializers.LOG_LEVEL); context.registerSerializer(Permissions.class, VPackSerializers.PERMISSIONS); - context.registerSerializer(ReplicationFactor.class, VPackSerializers.REPLICATION_FACTOR); context.registerSerializer(ViewType.class, VPackSerializers.VIEW_TYPE); context.registerSerializer(ArangoSearchProperties.class, VPackSerializers.ARANGO_SEARCH_PROPERTIES); context.registerSerializer(ConsolidationType.class, VPackSerializers.CONSOLIDATE_TYPE); diff --git a/src/main/java/com/arangodb/internal/velocypack/VPackSerializers.java b/src/main/java/com/arangodb/internal/velocypack/VPackSerializers.java index fd94cc022..56494405f 100644 --- a/src/main/java/com/arangodb/internal/velocypack/VPackSerializers.java +++ b/src/main/java/com/arangodb/internal/velocypack/VPackSerializers.java @@ -104,15 +104,6 @@ public class VPackSerializers { public static final VPackSerializer PERMISSIONS = (builder, attribute, value, context) -> builder.add(attribute, value.toString().toLowerCase(Locale.ENGLISH)); - public static final VPackSerializer REPLICATION_FACTOR = (builder, attribute, value, context) -> { - final Boolean satellite = value.getSatellite(); - if (Boolean.TRUE == satellite) { - builder.add(attribute, "satellite"); - } else if (value.getReplicationFactor() != null) { - builder.add(attribute, value.getReplicationFactor()); - } - }; - public static final VPackSerializer VIEW_TYPE = (builder, attribute, value, context) -> { final String type = value == ViewType.ARANGO_SEARCH ? "arangosearch" : value.name().toLowerCase(Locale.ENGLISH); builder.add(attribute, type); diff --git a/src/main/java/com/arangodb/model/CollectionCreateOptions.java b/src/main/java/com/arangodb/model/CollectionCreateOptions.java index 5dafdf6f2..4f98a9dcd 100644 --- a/src/main/java/com/arangodb/model/CollectionCreateOptions.java +++ b/src/main/java/com/arangodb/model/CollectionCreateOptions.java @@ -35,7 +35,7 @@ public class CollectionCreateOptions { private String name; - private final ReplicationFactor replicationFactor; + private ReplicationFactor replicationFactor; private Integer writeConcern; private KeyOptions keyOptions; private Boolean waitForSync; @@ -52,7 +52,6 @@ public class CollectionCreateOptions { public CollectionCreateOptions() { super(); - replicationFactor = new ReplicationFactor(); } public String getName() { @@ -68,8 +67,8 @@ protected CollectionCreateOptions name(final String name) { return this; } - public Integer getReplicationFactor() { - return replicationFactor.getReplicationFactor(); + public ReplicationFactor getReplicationFactor() { + return replicationFactor; } /** @@ -82,8 +81,18 @@ public Integer getReplicationFactor() { * reported. * @return options */ - public CollectionCreateOptions replicationFactor(final Integer replicationFactor) { - this.replicationFactor.setReplicationFactor(replicationFactor); + public CollectionCreateOptions replicationFactor(final ReplicationFactor replicationFactor) { + this.replicationFactor = replicationFactor; + return this; + } + + public CollectionCreateOptions replicationFactor(int replicationFactor) { + this.replicationFactor = ReplicationFactor.of(replicationFactor); + return this; + } + + public CollectionCreateOptions satellite() { + this.replicationFactor = ReplicationFactor.ofSatellite(); return this; } @@ -104,20 +113,6 @@ public CollectionCreateOptions writeConcern(final Integer writeConcern) { return this; } - public Boolean getSatellite() { - return replicationFactor.getSatellite(); - } - - /** - * @param satellite If the true the collection is created as a satellite collection. In this case - * {@link #replicationFactor(Integer)} is ignored. - * @return options - */ - public CollectionCreateOptions satellite(final Boolean satellite) { - this.replicationFactor.setSatellite(satellite); - return this; - } - public KeyOptions getKeyOptions() { return keyOptions; } diff --git a/src/main/java/com/arangodb/model/DatabaseOptions.java b/src/main/java/com/arangodb/model/DatabaseOptions.java index 81052c6c5..df5cca03b 100644 --- a/src/main/java/com/arangodb/model/DatabaseOptions.java +++ b/src/main/java/com/arangodb/model/DatabaseOptions.java @@ -28,27 +28,22 @@ */ public class DatabaseOptions { - private final ReplicationFactor replicationFactor; + private ReplicationFactor replicationFactor; private Integer writeConcern; private String sharding; public DatabaseOptions() { super(); - replicationFactor = new ReplicationFactor(); } - public Integer getReplicationFactor() { - return replicationFactor.getReplicationFactor(); + public ReplicationFactor getReplicationFactor() { + return replicationFactor; } public Integer getWriteConcern() { return writeConcern; } - public Boolean getSatellite() { - return this.replicationFactor.getSatellite(); - } - public String getSharding() { return sharding; } @@ -58,8 +53,18 @@ public String getSharding() { * @return options * @since ArangoDB 3.6.0 */ - public DatabaseOptions replicationFactor(final Integer replicationFactor) { - this.replicationFactor.setReplicationFactor(replicationFactor); + public DatabaseOptions replicationFactor(final ReplicationFactor replicationFactor) { + this.replicationFactor = replicationFactor; + return this; + } + + public DatabaseOptions replicationFactor(int replicationFactor) { + this.replicationFactor = ReplicationFactor.of(replicationFactor); + return this; + } + + public DatabaseOptions satellite() { + this.replicationFactor = ReplicationFactor.ofSatellite(); return this; } @@ -77,17 +82,6 @@ public DatabaseOptions writeConcern(final Integer writeConcern) { return this; } - /** - * @param satellite whether the collection is a satellite collection. Only in an enterprise cluster setup (else - * returning null). - * @return options - * @since ArangoDB 3.6.0 - */ - public DatabaseOptions satellite(final Boolean satellite) { - this.replicationFactor.setSatellite(satellite); - return this; - } - /** * @param sharding The sharding method to use for new collections in this database. * Valid values are: “”, “flexible”, or “single”. The first two are equivalent. diff --git a/src/main/java/com/arangodb/model/GraphCreateOptions.java b/src/main/java/com/arangodb/model/GraphCreateOptions.java index 989999c08..f6453a4e1 100644 --- a/src/main/java/com/arangodb/model/GraphCreateOptions.java +++ b/src/main/java/com/arangodb/model/GraphCreateOptions.java @@ -110,8 +110,8 @@ public GraphCreateOptions isDisjoint(final Boolean isDisjoint) { return this; } - public Integer getReplicationFactor() { - return getOptions().replicationFactor.getReplicationFactor(); + public ReplicationFactor getReplicationFactor() { + return getOptions().replicationFactor; } /** @@ -124,23 +124,18 @@ public Integer getReplicationFactor() { * reported. * @return options */ - public GraphCreateOptions replicationFactor(final Integer replicationFactor) { - getOptions().replicationFactor.setReplicationFactor(replicationFactor); + public GraphCreateOptions replicationFactor(final ReplicationFactor replicationFactor) { + getOptions().setReplicationFactor(replicationFactor); return this; } - public Boolean getSatellite() { - return getOptions().replicationFactor.getSatellite(); + public GraphCreateOptions replicationFactor(int replicationFactor) { + getOptions().setReplicationFactor(ReplicationFactor.of(replicationFactor)); + return this; } - /** - * @param satellite If the true the graph is created as a satellite graph. In this case - * {@link #replicationFactor(Integer)} is ignored. - * @return options - * @since ArangoDB 3.7 - */ - public GraphCreateOptions satellite(final Boolean satellite) { - getOptions().replicationFactor.setSatellite(satellite); + public GraphCreateOptions satellite() { + getOptions().setReplicationFactor(ReplicationFactor.ofSatellite()); return this; } @@ -204,7 +199,7 @@ public GraphCreateOptions satellites(final String... satellites) { return this; } - private SmartOptions getOptions() { + public SmartOptions getOptions() { if (options == null) { options = new SmartOptions(); } @@ -221,23 +216,14 @@ public static class SmartOptions { public SmartOptions() { super(); - replicationFactor = new ReplicationFactor(); - } - - public Integer getReplicationFactor() { - return replicationFactor.getReplicationFactor(); - } - - public void setReplicationFactor(final Integer replicationFactor) { - this.replicationFactor.setReplicationFactor(replicationFactor); } - public Boolean getSatellite() { - return replicationFactor.getSatellite(); + public ReplicationFactor getReplicationFactor() { + return replicationFactor; } - public void setSatellite(final Boolean satellite) { - replicationFactor.setSatellite(satellite); + public void setReplicationFactor(final ReplicationFactor replicationFactor) { + this.replicationFactor = replicationFactor; } public Integer getWriteConcern() { diff --git a/src/main/java/com/arangodb/model/VertexCollectionCreateOptions.java b/src/main/java/com/arangodb/model/VertexCollectionCreateOptions.java index 4013a2c74..2e4f97a9c 100644 --- a/src/main/java/com/arangodb/model/VertexCollectionCreateOptions.java +++ b/src/main/java/com/arangodb/model/VertexCollectionCreateOptions.java @@ -48,6 +48,10 @@ protected VertexCollectionCreateOptions collection(final String collection) { return this; } + public Options getOptions() { + return options; + } + public Collection getSatellites() { return options.satellites; } diff --git a/src/test/java/com/arangodb/ArangoDBTest.java b/src/test/java/com/arangodb/ArangoDBTest.java index 4495121d0..284ae526e 100644 --- a/src/test/java/com/arangodb/ArangoDBTest.java +++ b/src/test/java/com/arangodb/ArangoDBTest.java @@ -147,10 +147,9 @@ void createDatabaseWithOptions(ArangoDB arangoDB) { assertThat(resultCreate).isTrue(); DatabaseEntity info = arangoDB.db(dbName).getInfo(); - assertThat(info.getReplicationFactor()).isEqualTo(2); + assertThat(info.getReplicationFactor().getValue()).isEqualTo(2); assertThat(info.getWriteConcern()).isEqualTo(2); assertThat(info.getSharding()).isEmpty(); - assertThat(info.getSatellite()).isNull(); final Boolean resultDelete = arangoDB.db(dbName).drop(); assertThat(resultDelete).isTrue(); @@ -168,15 +167,14 @@ void createDatabaseWithOptionsSatellite(ArangoDB arangoDB) { .name(dbName) .options(new DatabaseOptions() .writeConcern(2) - .satellite(true) + .satellite() .sharding("") ) ); assertThat(resultCreate).isTrue(); DatabaseEntity info = arangoDB.db(dbName).getInfo(); - assertThat(info.getReplicationFactor()).isNull(); - assertThat(info.getSatellite()).isTrue(); + assertThat(info.getReplicationFactor()).isEqualTo(ReplicationFactor.ofSatellite()); assertThat(info.getWriteConcern()).isEqualTo(2); assertThat(info.getSharding()).isEmpty(); diff --git a/src/test/java/com/arangodb/ArangoDatabaseTest.java b/src/test/java/com/arangodb/ArangoDatabaseTest.java index 35073c24b..068107c5e 100644 --- a/src/test/java/com/arangodb/ArangoDatabaseTest.java +++ b/src/test/java/com/arangodb/ArangoDatabaseTest.java @@ -115,8 +115,7 @@ void createCollectionWithReplicationFactor(ArangoDatabase db) { assertThat(result).isNotNull(); assertThat(result.getId()).isNotNull(); CollectionPropertiesEntity props = db.collection(name).getProperties(); - assertThat(props.getReplicationFactor()).isEqualTo(2); - assertThat(props.getSatellite()).isNull(); + assertThat(props.getReplicationFactor().getValue()).isEqualTo(2); } @ParameterizedTest(name = "{index}") @@ -131,9 +130,8 @@ void createCollectionWithWriteConcern(ArangoDatabase db) { assertThat(result).isNotNull(); assertThat(result.getId()).isNotNull(); CollectionPropertiesEntity props = db.collection(name).getProperties(); - assertThat(props.getReplicationFactor()).isEqualTo(2); + assertThat(props.getReplicationFactor().getValue()).isEqualTo(2); assertThat(props.getWriteConcern()).isEqualTo(2); - assertThat(props.getSatellite()).isNull(); } @ParameterizedTest(name = "{index}") @@ -144,13 +142,12 @@ void createSatelliteCollection(ArangoDatabase db) { String name = "collection-" + rnd(); final CollectionEntity result = db - .createCollection(name, new CollectionCreateOptions().satellite(true)); + .createCollection(name, new CollectionCreateOptions().satellite()); assertThat(result).isNotNull(); assertThat(result.getId()).isNotNull(); CollectionPropertiesEntity props = db.collection(name).getProperties(); - assertThat(props.getReplicationFactor()).isNull(); - assertThat(props.getSatellite()).isTrue(); + assertThat(props.getReplicationFactor()).isEqualTo(ReplicationFactor.ofSatellite()); } @ParameterizedTest(name = "{index}") @@ -1079,14 +1076,14 @@ void createGraphSatellite(ArangoDatabase db) { assumeTrue(isEnterprise()); String name = "graph-" + rnd(); - final GraphEntity result = db.createGraph(name, null, new GraphCreateOptions().satellite(true)); - assertThat(result.getSatellite()).isTrue(); + final GraphEntity result = db.createGraph(name, null, new GraphCreateOptions().satellite()); + assertThat(result.getReplicationFactor()).isEqualTo(ReplicationFactor.ofSatellite()); GraphEntity info = db.graph(name).getInfo(); - assertThat(info.getSatellite()).isTrue(); + assertThat(info.getReplicationFactor()).isEqualTo(ReplicationFactor.ofSatellite()); GraphEntity graph = db.getGraphs().stream().filter(g -> name.equals(g.getName())).findFirst().get(); - assertThat(graph.getSatellite()).isTrue(); + assertThat(graph.getReplicationFactor()).isEqualTo(ReplicationFactor.ofSatellite()); } @ParameterizedTest(name = "{index}") @@ -1102,7 +1099,7 @@ void createGraphReplicationFaktor(ArangoDatabase db) { assertThat(result).isNotNull(); for (final String collection : Arrays.asList(edgeCollection, fromCollection, toCollection)) { final CollectionPropertiesEntity properties = db.collection(collection).getProperties(); - assertThat(properties.getReplicationFactor()).isEqualTo(2); + assertThat(properties.getReplicationFactor().getValue()).isEqualTo(2); } } diff --git a/src/test/java/com/arangodb/ArangoGraphTest.java b/src/test/java/com/arangodb/ArangoGraphTest.java index f42d5848b..9314d5dd1 100644 --- a/src/test/java/com/arangodb/ArangoGraphTest.java +++ b/src/test/java/com/arangodb/ArangoGraphTest.java @@ -23,6 +23,7 @@ import com.arangodb.entity.CollectionPropertiesEntity; import com.arangodb.entity.EdgeDefinition; import com.arangodb.entity.GraphEntity; +import com.arangodb.entity.ReplicationFactor; import com.arangodb.model.GraphCreateOptions; import com.arangodb.model.VertexCollectionCreateOptions; import org.junit.jupiter.api.BeforeAll; @@ -96,7 +97,7 @@ void createWithReplicationAndWriteConcern(ArangoDatabase db) { assertThat(graph).isNotNull(); assertThat(graph.getName()).isEqualTo(GRAPH_NAME + "_1"); assertThat(graph.getWriteConcern()).isEqualTo(2); - assertThat(graph.getReplicationFactor()).isEqualTo(2); + assertThat(graph.getReplicationFactor().getValue()).isEqualTo(2); db.graph(GRAPH_NAME + "_1").drop(); } @@ -128,7 +129,7 @@ void getInfo(ArangoGraph graph) { if (isCluster()) { for (final String collection : new String[]{EDGE_COL_1, EDGE_COL_2, VERTEX_COL_1, VERTEX_COL_2}) { final CollectionPropertiesEntity properties = graph.db().collection(collection).getProperties(); - assertThat(properties.getReplicationFactor()).isEqualTo(REPLICATION_FACTOR); + assertThat(properties.getReplicationFactor().getValue()).isEqualTo(REPLICATION_FACTOR); assertThat(properties.getNumberOfShards()).isEqualTo(NUMBER_OF_SHARDS); } } @@ -170,7 +171,7 @@ void addSatelliteVertexCollection(ArangoDatabase db) { Collection vertexCollections = g.getVertexCollections(); assertThat(vertexCollections).contains(v1Name); - assertThat(db.collection(v1Name).getProperties().getSatellite()).isTrue(); + assertThat(db.collection(v1Name).getProperties().getReplicationFactor()).isEqualTo(ReplicationFactor.ofSatellite()); // revert g.drop(); @@ -208,7 +209,7 @@ void addEdgeDefinition(ArangoGraph graph) { } if (isCluster()) { final CollectionPropertiesEntity properties = graph.db().collection(EDGE_COL_3).getProperties(); - assertThat(properties.getReplicationFactor()).isEqualTo(REPLICATION_FACTOR); + assertThat(properties.getReplicationFactor().getValue()).isEqualTo(REPLICATION_FACTOR); assertThat(properties.getNumberOfShards()).isEqualTo(NUMBER_OF_SHARDS); } @@ -240,7 +241,7 @@ void addSatelliteEdgeDefinition(ArangoDatabase db) { assertThat(e.getFrom()).contains(v1Name); assertThat(e.getTo()).contains(v2Name); - assertThat(db.collection(v1Name).getProperties().getSatellite()).isTrue(); + assertThat(db.collection(v1Name).getProperties().getReplicationFactor()).isEqualTo(ReplicationFactor.ofSatellite()); // revert g.drop(); @@ -326,9 +327,9 @@ void hybridSmartGraph(ArangoDatabase db) { assertThat(g.getSmartGraphAttribute()).isEqualTo("test"); assertThat(g.getNumberOfShards()).isEqualTo(2); - assertThat(db.collection(eName).getProperties().getSatellite()).isTrue(); - assertThat(db.collection(v1Name).getProperties().getSatellite()).isTrue(); - assertThat(db.collection(v2Name).getProperties().getReplicationFactor()).isEqualTo(2); + assertThat(db.collection(eName).getProperties().getReplicationFactor()).isEqualTo(ReplicationFactor.ofSatellite()); + assertThat(db.collection(v1Name).getProperties().getReplicationFactor()).isEqualTo(ReplicationFactor.ofSatellite()); + assertThat(db.collection(v2Name).getProperties().getReplicationFactor().getValue()).isEqualTo(2); } @ParameterizedTest(name = "{index}") @@ -376,8 +377,8 @@ void hybridDisjointSmartGraph(ArangoDatabase db) { assertThat(g.getSmartGraphAttribute()).isEqualTo("test"); assertThat(g.getNumberOfShards()).isEqualTo(2); - assertThat(db.collection(v1Name).getProperties().getSatellite()).isTrue(); - assertThat(db.collection(v2Name).getProperties().getReplicationFactor()).isEqualTo(2); + assertThat(db.collection(v1Name).getProperties().getReplicationFactor()).isEqualTo(ReplicationFactor.ofSatellite()); + assertThat(db.collection(v2Name).getProperties().getReplicationFactor().getValue()).isEqualTo(2); } @ParameterizedTest(name = "{index}") diff --git a/src/test/java/com/arangodb/async/ArangoDBTest.java b/src/test/java/com/arangodb/async/ArangoDBTest.java index 965f84a3a..429f2c643 100644 --- a/src/test/java/com/arangodb/async/ArangoDBTest.java +++ b/src/test/java/com/arangodb/async/ArangoDBTest.java @@ -169,10 +169,9 @@ void createDatabaseWithOptions() throws ExecutionException, InterruptedException assertThat(resultCreate).isTrue(); DatabaseEntity info = arangoDB.db(dbName).getInfo().get(); - assertThat(info.getReplicationFactor()).isEqualTo(2); + assertThat(info.getReplicationFactor().getValue()).isEqualTo(2); assertThat(info.getWriteConcern()).isEqualTo(2); assertThat(info.getSharding()).isEmpty(); - assertThat(info.getSatellite()).isNull(); final Boolean resultDelete = arangoDB.db(dbName).drop().get(); assertThat(resultDelete).isTrue(); @@ -189,15 +188,14 @@ void createDatabaseWithOptionsSatellite() throws ExecutionException, Interrupted .name(dbName) .options(new DatabaseOptions() .writeConcern(2) - .satellite(true) + .satellite() .sharding("") ) ).get(); assertThat(resultCreate).isTrue(); DatabaseEntity info = arangoDB.db(dbName).getInfo().get(); - assertThat(info.getReplicationFactor()).isNull(); - assertThat(info.getSatellite()).isTrue(); + assertThat(info.getReplicationFactor()).isEqualTo(ReplicationFactor.ofSatellite()); assertThat(info.getWriteConcern()).isEqualTo(2); assertThat(info.getSharding()).isEmpty(); diff --git a/src/test/java/com/arangodb/async/ArangoDatabaseTest.java b/src/test/java/com/arangodb/async/ArangoDatabaseTest.java index b58e1e6ef..54df6dedb 100644 --- a/src/test/java/com/arangodb/async/ArangoDatabaseTest.java +++ b/src/test/java/com/arangodb/async/ArangoDatabaseTest.java @@ -117,7 +117,7 @@ void createCollectionWithReplicationFactor() throws InterruptedException, Execut .createCollection(COLLECTION_NAME, new CollectionCreateOptions().replicationFactor(2)).get(); assertThat(result).isNotNull(); assertThat(result.getId()).isNotNull(); - assertThat(db.collection(COLLECTION_NAME).getProperties().get().getReplicationFactor()).isEqualTo(2); + assertThat(db.collection(COLLECTION_NAME).getProperties().get().getReplicationFactor().getValue()).isEqualTo(2); db.collection(COLLECTION_NAME).drop().get(); } @@ -130,9 +130,8 @@ void createCollectionWithWriteConcern() throws ExecutionException, InterruptedEx new CollectionCreateOptions().replicationFactor(2).writeConcern(2)).get(); assertThat(result).isNotNull(); assertThat(result.getId()).isNotNull(); - assertThat(db.collection(COLLECTION_NAME).getProperties().get().getReplicationFactor()).isEqualTo(2); + assertThat(db.collection(COLLECTION_NAME).getProperties().get().getReplicationFactor().getValue()).isEqualTo(2); assertThat(db.collection(COLLECTION_NAME).getProperties().get().getWriteConcern()).isEqualTo(2); - assertThat(db.collection(COLLECTION_NAME).getProperties().get().getSatellite()).isNull(); db.collection(COLLECTION_NAME).drop(); } diff --git a/src/test/java/com/arangodb/async/ArangoGraphTest.java b/src/test/java/com/arangodb/async/ArangoGraphTest.java index 60658aa86..1e7407aa4 100644 --- a/src/test/java/com/arangodb/async/ArangoGraphTest.java +++ b/src/test/java/com/arangodb/async/ArangoGraphTest.java @@ -20,10 +20,7 @@ package com.arangodb.async; -import com.arangodb.entity.CollectionPropertiesEntity; -import com.arangodb.entity.EdgeDefinition; -import com.arangodb.entity.GraphEntity; -import com.arangodb.entity.ServerRole; +import com.arangodb.entity.*; import com.arangodb.model.GraphCreateOptions; import com.arangodb.model.VertexCollectionCreateOptions; import org.junit.jupiter.api.AfterEach; @@ -102,7 +99,7 @@ void createWithReplicationAndWriteConcern() throws ExecutionException, Interrupt assertThat(graph).isNotNull(); assertThat(graph.getName()).isEqualTo(GRAPH_NAME + "_1"); assertThat(graph.getWriteConcern()).isEqualTo(2); - assertThat(graph.getReplicationFactor()).isEqualTo(2); + assertThat(graph.getReplicationFactor().getValue()).isEqualTo(2); db.graph(GRAPH_NAME + "_1").drop(); } @@ -133,12 +130,12 @@ void getInfo() throws InterruptedException, ExecutionException { if (isCluster()) { for (final String collection : new String[]{VERTEX_COL_1, VERTEX_COL_2}) { final CollectionPropertiesEntity properties = db.collection(collection).getProperties().get(); - assertThat(properties.getReplicationFactor()).isEqualTo(REPLICATION_FACTOR); + assertThat(properties.getReplicationFactor().getValue()).isEqualTo(REPLICATION_FACTOR); assertThat(properties.getNumberOfShards()).isEqualTo(NUMBER_OF_SHARDS); } for (final String collection : new String[]{EDGE_COL_1, EDGE_COL_2}) { final CollectionPropertiesEntity properties = db.collection(collection).getProperties().get(); - assertThat(properties.getReplicationFactor()).isEqualTo(REPLICATION_FACTOR); + assertThat(properties.getReplicationFactor().getValue()).isEqualTo(REPLICATION_FACTOR); } } } @@ -174,7 +171,7 @@ void addSatelliteVertexCollection() throws ExecutionException, InterruptedExcept Collection vertexCollections = g.getVertexCollections().get(); assertThat(vertexCollections).contains(v1Name); - assertThat(db.collection(v1Name).getProperties().get().getSatellite()).isTrue(); + assertThat(db.collection(v1Name).getProperties().get().getReplicationFactor()).isEqualTo(ReplicationFactor.ofSatellite()); // revert g.drop().get(); @@ -211,7 +208,7 @@ void addEdgeDefinition() throws InterruptedException, ExecutionException { } if (isCluster()) { final CollectionPropertiesEntity properties = db.collection(EDGE_COL_3).getProperties().get(); - assertThat(properties.getReplicationFactor()).isEqualTo(REPLICATION_FACTOR); + assertThat(properties.getReplicationFactor().getValue()).isEqualTo(REPLICATION_FACTOR); assertThat(properties.getNumberOfShards()).isEqualTo(NUMBER_OF_SHARDS); } setup(); @@ -240,7 +237,7 @@ void addSatelliteEdgeDefinition() throws ExecutionException, InterruptedExceptio assertThat(e.getFrom()).contains(v1Name); assertThat(e.getTo()).contains(v2Name); - assertThat(db.collection(v1Name).getProperties().get().getSatellite()).isTrue(); + assertThat(db.collection(v1Name).getProperties().get().getReplicationFactor()).isEqualTo(ReplicationFactor.ofSatellite()); // revert g.drop().get(); @@ -327,9 +324,9 @@ void hybridSmartGraph() throws ExecutionException, InterruptedException { assertThat(g.getSmartGraphAttribute()).isEqualTo("test"); assertThat(g.getNumberOfShards()).isEqualTo(2); - assertThat(db.collection(eName).getProperties().get().getSatellite()).isTrue(); - assertThat(db.collection(v1Name).getProperties().get().getSatellite()).isTrue(); - assertThat(db.collection(v2Name).getProperties().get().getReplicationFactor()).isEqualTo(2); + assertThat(db.collection(eName).getProperties().get().getReplicationFactor()).isEqualTo(ReplicationFactor.ofSatellite()); + assertThat(db.collection(v1Name).getProperties().get().getReplicationFactor()).isEqualTo(ReplicationFactor.ofSatellite()); + assertThat(db.collection(v2Name).getProperties().get().getReplicationFactor().getValue()).isEqualTo(2); } @Test @@ -355,8 +352,8 @@ void hybridDisjointSmartGraph() throws ExecutionException, InterruptedException assertThat(g.getSmartGraphAttribute()).isEqualTo("test"); assertThat(g.getNumberOfShards()).isEqualTo(2); - assertThat(db.collection(v1Name).getProperties().get().getSatellite()).isTrue(); - assertThat(db.collection(v2Name).getProperties().get().getReplicationFactor()).isEqualTo(2); + assertThat(db.collection(v1Name).getProperties().get().getReplicationFactor()).isEqualTo(ReplicationFactor.ofSatellite()); + assertThat(db.collection(v2Name).getProperties().get().getReplicationFactor().getValue()).isEqualTo(2); } @Test From e78144868100ebfd46b34bc04071955ba54d35eb Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Tue, 5 Jul 2022 13:01:11 +0200 Subject: [PATCH 022/254] ArangoSerializer refactoring --- .../arangodb/ArangoSerializationAccessor.java | 11 +- .../async/internal/ArangoDBAsyncImpl.java | 9 +- .../com/arangodb/internal/ArangoDBImpl.java | 7 +- .../arangodb/internal/ArangoExecuteable.java | 14 ++- .../com/arangodb/internal/ArangoExecutor.java | 5 +- .../internal/InternalArangoCollection.java | 113 +++++++++--------- .../arangodb/internal/InternalArangoDB.java | 22 ++-- .../internal/InternalArangoDatabase.java | 57 +++++---- .../InternalArangoEdgeCollection.java | 15 ++- .../internal/InternalArangoGraph.java | 16 +-- .../internal/InternalArangoRoute.java | 2 +- .../internal/InternalArangoSearch.java | 4 +- .../InternalArangoVertexCollection.java | 17 ++- .../arangodb/internal/InternalArangoView.java | 2 +- .../internal/cursor/ArangoCursorIterator.java | 3 +- .../util/ArangoSerializationFactory.java | 28 ++--- src/test/java/com/arangodb/JwtAuthTest.java | 2 +- .../java/com/arangodb/async/JwtAuthTest.java | 2 +- .../com/arangodb/serde/CustomSerdeTest.java | 5 +- .../util/ArangoSerializationTest.java | 2 +- 20 files changed, 160 insertions(+), 176 deletions(-) diff --git a/src/main/java/com/arangodb/ArangoSerializationAccessor.java b/src/main/java/com/arangodb/ArangoSerializationAccessor.java index f140f054e..1bd7dcfa4 100644 --- a/src/main/java/com/arangodb/ArangoSerializationAccessor.java +++ b/src/main/java/com/arangodb/ArangoSerializationAccessor.java @@ -20,7 +20,6 @@ package com.arangodb; -import com.arangodb.internal.util.ArangoSerializationFactory.Serializer; import com.arangodb.util.ArangoSerialization; /** @@ -29,19 +28,17 @@ public interface ArangoSerializationAccessor { /** - * Returns driver internal serialization API for serializing and deserializing Java POJOs to/from {@link com.arangodb.velocypack.VPackSlice} + * Returns driver internal serialization implementation for serializing and deserializing driver's classes. * * @return ArangoSerialization */ - ArangoSerialization util(); + ArangoSerialization getInternalSerialization(); /** - * Returns serialization API for serializing and deserializing Java POJOs to/from {@link com.arangodb.velocypack.VPackSlice} by the given - * type + * Returns serialization implementation for serializing and deserializing user's classes. * - * @param serializer type of serializer * @return ArangoSerialization */ - ArangoSerialization util(Serializer serializer); + ArangoSerialization getUserSerialization(); } diff --git a/src/main/java/com/arangodb/async/internal/ArangoDBAsyncImpl.java b/src/main/java/com/arangodb/async/internal/ArangoDBAsyncImpl.java index 23cf6af31..70c2ef595 100644 --- a/src/main/java/com/arangodb/async/internal/ArangoDBAsyncImpl.java +++ b/src/main/java/com/arangodb/async/internal/ArangoDBAsyncImpl.java @@ -32,7 +32,6 @@ import com.arangodb.internal.net.HostHandler; import com.arangodb.internal.net.HostResolver; import com.arangodb.internal.util.ArangoSerializationFactory; -import com.arangodb.internal.util.ArangoSerializationFactory.Serializer; import com.arangodb.internal.velocystream.VstCommunication; import com.arangodb.internal.velocystream.VstCommunicationSync; import com.arangodb.internal.velocystream.VstProtocol; @@ -74,10 +73,10 @@ public ArangoDBAsyncImpl( final int timeoutMs ) { - super(new ArangoExecutorAsync(asyncCommBuilder.build(util.get(Serializer.INTERNAL)), util, new DocumentCache(), + super(new ArangoExecutorAsync(asyncCommBuilder.build(util.getInternalSerialization()), util, new DocumentCache(), new QueueTimeMetricsImpl(responseQueueTimeSamples), timeoutMs), util, context); - final VstCommunication cacheCom = syncCommBuilder.build(util.get(Serializer.INTERNAL)); + final VstCommunication cacheCom = syncCommBuilder.build(util.getInternalSerialization()); cp = new VstProtocol(cacheCom); this.asyncHostHandler = asyncHostHandler; @@ -85,8 +84,8 @@ public ArangoDBAsyncImpl( ArangoExecutorSync arangoExecutorSync = new ArangoExecutorSync(cp, util, new DocumentCache(), new QueueTimeMetricsImpl(responseQueueTimeSamples), timeoutMs); - asyncHostResolver.init(arangoExecutorSync, util.get(Serializer.INTERNAL)); - syncHostResolver.init(arangoExecutorSync, util.get(Serializer.INTERNAL)); + asyncHostResolver.init(arangoExecutorSync, util.getInternalSerialization()); + syncHostResolver.init(arangoExecutorSync, util.getInternalSerialization()); } diff --git a/src/main/java/com/arangodb/internal/ArangoDBImpl.java b/src/main/java/com/arangodb/internal/ArangoDBImpl.java index ea980dede..690991dc9 100644 --- a/src/main/java/com/arangodb/internal/ArangoDBImpl.java +++ b/src/main/java/com/arangodb/internal/ArangoDBImpl.java @@ -29,7 +29,6 @@ import com.arangodb.internal.net.HostHandler; import com.arangodb.internal.net.HostResolver; import com.arangodb.internal.util.ArangoSerializationFactory; -import com.arangodb.internal.util.ArangoSerializationFactory.Serializer; import com.arangodb.internal.velocystream.VstCommunicationSync; import com.arangodb.internal.velocystream.VstProtocol; import com.arangodb.model.DBCreateOptions; @@ -64,7 +63,7 @@ public ArangoDBImpl(final VstCommunicationSync.Builder vstBuilder, final HttpCom final HostHandler hostHandler, final ArangoContext context, int responseQueueTimeSamples, final int timeoutMs) { super(new ArangoExecutorSync( - createProtocol(vstBuilder, httpBuilder, util.get(Serializer.INTERNAL), protocol), + createProtocol(vstBuilder, httpBuilder, util.getInternalSerialization(), protocol), util, new DocumentCache(), new QueueTimeMetricsImpl(responseQueueTimeSamples), timeoutMs), util, @@ -73,11 +72,11 @@ public ArangoDBImpl(final VstCommunicationSync.Builder vstBuilder, final HttpCom cp = createProtocol( new VstCommunicationSync.Builder(vstBuilder).maxConnections(1), new HttpCommunication.Builder(httpBuilder), - util.get(Serializer.INTERNAL), + util.getInternalSerialization(), protocol); this.hostHandler = hostHandler; - hostResolver.init(this.executor(), util()); + hostResolver.init(this.executor(), getInternalSerialization()); LOGGER.debug("ArangoDB Client is ready to use"); diff --git a/src/main/java/com/arangodb/internal/ArangoExecuteable.java b/src/main/java/com/arangodb/internal/ArangoExecuteable.java index dc58fe914..8145a1fd0 100644 --- a/src/main/java/com/arangodb/internal/ArangoExecuteable.java +++ b/src/main/java/com/arangodb/internal/ArangoExecuteable.java @@ -20,9 +20,9 @@ package com.arangodb.internal; +import com.arangodb.ArangoSerializationAccessor; import com.arangodb.DbName; import com.arangodb.internal.util.ArangoSerializationFactory; -import com.arangodb.internal.util.ArangoSerializationFactory.Serializer; import com.arangodb.internal.util.EncodeUtils; import com.arangodb.util.ArangoSerialization; import com.arangodb.velocystream.Request; @@ -33,7 +33,7 @@ /** * @author Mark Vollmary */ -public abstract class ArangoExecuteable { +public abstract class ArangoExecuteable implements ArangoSerializationAccessor { private static final String SLASH = "/"; @@ -52,12 +52,14 @@ protected E executor() { return executor; } - public ArangoSerialization util() { - return util.get(Serializer.INTERNAL); + @Override + public ArangoSerialization getInternalSerialization() { + return util.getInternalSerialization(); } - public ArangoSerialization util(final Serializer serializer) { - return util.get(serializer); + @Override + public ArangoSerialization getUserSerialization() { + return util.getUserSerialization(); } protected Request request(final DbName dbName, final RequestType requestType, final String... path) { diff --git a/src/main/java/com/arangodb/internal/ArangoExecutor.java b/src/main/java/com/arangodb/internal/ArangoExecutor.java index 1dff75c10..bbdd8d1b1 100644 --- a/src/main/java/com/arangodb/internal/ArangoExecutor.java +++ b/src/main/java/com/arangodb/internal/ArangoExecutor.java @@ -23,7 +23,6 @@ import com.arangodb.QueueTimeMetrics; import com.arangodb.entity.Entity; import com.arangodb.internal.util.ArangoSerializationFactory; -import com.arangodb.internal.util.ArangoSerializationFactory.Serializer; import com.arangodb.velocypack.exception.VPackException; import com.arangodb.velocystream.Request; import com.arangodb.velocystream.Response; @@ -41,9 +40,9 @@ public abstract class ArangoExecutor { protected T createResult(final Type type, final Response response) { if (type != Void.class && response.getBody() != null) { if (isInternal(type)) { - return (T) util.get(Serializer.INTERNAL).deserialize(response.getBody(), type); + return (T) util.getInternalSerialization().deserialize(response.getBody(), type); } else { - return (T) util.get(Serializer.CUSTOM).deserialize(response.getBody(), type); + return (T) util.getUserSerialization().deserialize(response.getBody(), type); } } else { return null; diff --git a/src/main/java/com/arangodb/internal/InternalArangoCollection.java b/src/main/java/com/arangodb/internal/InternalArangoCollection.java index 6d2082750..8d9194dc2 100644 --- a/src/main/java/com/arangodb/internal/InternalArangoCollection.java +++ b/src/main/java/com/arangodb/internal/InternalArangoCollection.java @@ -24,7 +24,6 @@ import com.arangodb.DbName; import com.arangodb.entity.*; import com.arangodb.internal.ArangoExecutor.ResponseDeserializer; -import com.arangodb.internal.util.ArangoSerializationFactory.Serializer; import com.arangodb.internal.util.DocumentUtil; import com.arangodb.internal.util.RequestUtils; import com.arangodb.model.*; @@ -94,9 +93,9 @@ protected Request insertDocumentRequest(final T value, final DocumentCreateO VPackSlice body; if (value instanceof String) { - body = util().serialize(SerdeUtils.INSTANCE.parseJson((String) value)); + body = getInternalSerialization().serialize(SerdeUtils.INSTANCE.parseJson((String) value)); } else { - body = util(Serializer.CUSTOM).serialize(value); + body = getUserSerialization().serialize(value); } request.setBody(body); @@ -107,14 +106,14 @@ protected ResponseDeserializer> insertDocumentRespon final T value, final DocumentCreateOptions options) { return response -> { final VPackSlice body = response.getBody(); - final DocumentCreateEntity doc = util().deserialize(body, DocumentCreateEntity.class); + final DocumentCreateEntity doc = getInternalSerialization().deserialize(body, DocumentCreateEntity.class); final VPackSlice newDoc = body.get(NEW); if (newDoc.isObject()) { - doc.setNew(util(Serializer.CUSTOM).deserialize(newDoc, value.getClass())); + doc.setNew(getUserSerialization().deserialize(newDoc, value.getClass())); } final VPackSlice oldDoc = body.get(OLD); if (oldDoc.isObject()) { - doc.setOld(util(Serializer.CUSTOM).deserialize(oldDoc, value.getClass())); + doc.setOld(getUserSerialization().deserialize(oldDoc, value.getClass())); } if (options == null || Boolean.TRUE != options.getSilent()) { final Map values = new HashMap<>(); @@ -137,8 +136,8 @@ protected Request insertDocumentsRequest(final Collection values, final D request.putQueryParam(MERGE_OBJECTS, params.getMergeObjects()); request.putHeaderParam(TRANSACTION_ID, params.getStreamTransactionId()); - VPackSlice body = isStringCollection(values) ? util().serialize(stringCollectionToJsonArray((Collection) values)) - : util(Serializer.CUSTOM).serialize(values); + VPackSlice body = isStringCollection(values) ? getInternalSerialization().serialize(stringCollectionToJsonArray((Collection) values)) + : getUserSerialization().serialize(values); request.setBody(body); return request; } @@ -162,18 +161,18 @@ protected ResponseDeserializer>> for (final Iterator iterator = body.arrayIterator(); iterator.hasNext(); ) { final VPackSlice next = iterator.next(); if (next.get(ArangoResponseField.ERROR).isTrue()) { - final ErrorEntity error = util().deserialize(next, ErrorEntity.class); + final ErrorEntity error = getInternalSerialization().deserialize(next, ErrorEntity.class); errors.add(error); documentsAndErrors.add(error); } else { - final DocumentCreateEntity doc = util().deserialize(next, DocumentCreateEntity.class); + final DocumentCreateEntity doc = getInternalSerialization().deserialize(next, DocumentCreateEntity.class); final VPackSlice newDoc = next.get(NEW); if (newDoc.isObject()) { - doc.setNew(util(Serializer.CUSTOM).deserialize(newDoc, type)); + doc.setNew(getUserSerialization().deserialize(newDoc, type)); } final VPackSlice oldDoc = next.get(OLD); if (oldDoc.isObject()) { - doc.setOld(util(Serializer.CUSTOM).deserialize(oldDoc, type)); + doc.setOld(getUserSerialization().deserialize(oldDoc, type)); } docs.add(doc); documentsAndErrors.add(doc); @@ -188,12 +187,12 @@ protected ResponseDeserializer>> } protected Request importDocumentsRequest(final String values, final DocumentImportOptions options) { - return importDocumentsRequest(options).putQueryParam("type", ImportType.auto).setBody(util().serialize(SerdeUtils.INSTANCE.parseJson(values))); + return importDocumentsRequest(options).putQueryParam("type", ImportType.auto).setBody(getInternalSerialization().serialize(SerdeUtils.INSTANCE.parseJson(values))); } protected Request importDocumentsRequest(final Collection values, final DocumentImportOptions options) { - VPackSlice body = isStringCollection(values) ? util().serialize(stringCollectionToJsonArray((Collection) values)) - : util(Serializer.CUSTOM).serialize(values); + VPackSlice body = isStringCollection(values) ? getInternalSerialization().serialize(stringCollectionToJsonArray((Collection) values)) + : getUserSerialization().serialize(values); return importDocumentsRequest(options).putQueryParam("type", ImportType.list).setBody(body); } @@ -224,7 +223,7 @@ protected Request getDocumentsRequest(final Collection keys, final Docum final Request request = request(db.dbName(), RequestType.PUT, PATH_API_DOCUMENT, name) .putQueryParam("onlyget", true) .putHeaderParam(ArangoRequestParam.IF_NONE_MATCH, params.getIfNoneMatch()) - .putHeaderParam(ArangoRequestParam.IF_MATCH, params.getIfMatch()).setBody(util().serialize(keys)) + .putHeaderParam(ArangoRequestParam.IF_MATCH, params.getIfMatch()).setBody(getInternalSerialization().serialize(keys)) .putHeaderParam(TRANSACTION_ID, params.getStreamTransactionId()); if (params.getAllowDirtyRead() == Boolean.TRUE) { RequestUtils.allowDirtyRead(request); @@ -243,11 +242,11 @@ protected ResponseDeserializer> getDocumentsResponseD for (final Iterator iterator = body.arrayIterator(); iterator.hasNext(); ) { final VPackSlice next = iterator.next(); if (next.get(ArangoResponseField.ERROR).isTrue()) { - final ErrorEntity error = util().deserialize(next, ErrorEntity.class); + final ErrorEntity error = getInternalSerialization().deserialize(next, ErrorEntity.class); errors.add(error); documentsAndErrors.add(error); } else { - final T doc = util(Serializer.CUSTOM).deserialize(next, type); + final T doc = getUserSerialization().deserialize(next, type); docs.add(doc); documentsAndErrors.add(doc); } @@ -271,7 +270,7 @@ protected Request replaceDocumentRequest( request.putQueryParam(RETURN_NEW, params.getReturnNew()); request.putQueryParam(RETURN_OLD, params.getReturnOld()); request.putQueryParam(SILENT, params.getSilent()); - request.setBody(util(Serializer.CUSTOM).serialize(value)); + request.setBody(getUserSerialization().serialize(value)); return request; } @@ -279,14 +278,14 @@ protected ResponseDeserializer> replaceDocumentRespo final T value, final DocumentReplaceOptions options) { return response -> { final VPackSlice body = response.getBody(); - final DocumentUpdateEntity doc = util().deserialize(body, DocumentUpdateEntity.class); + final DocumentUpdateEntity doc = getInternalSerialization().deserialize(body, DocumentUpdateEntity.class); final VPackSlice newDoc = body.get(NEW); if (newDoc.isObject()) { - doc.setNew(util(Serializer.CUSTOM).deserialize(newDoc, value.getClass())); + doc.setNew(getUserSerialization().deserialize(newDoc, value.getClass())); } final VPackSlice oldDoc = body.get(OLD); if (oldDoc.isObject()) { - doc.setOld(util(Serializer.CUSTOM).deserialize(oldDoc, value.getClass())); + doc.setOld(getUserSerialization().deserialize(oldDoc, value.getClass())); } if (options == null || Boolean.TRUE != options.getSilent()) { final Map values = new HashMap<>(); @@ -307,8 +306,8 @@ protected Request replaceDocumentsRequest(final Collection values, final request.putQueryParam(RETURN_OLD, params.getReturnOld()); request.putQueryParam(SILENT, params.getSilent()); - VPackSlice body = isStringCollection(values) ? util().serialize(stringCollectionToJsonArray((Collection) values)) - : util(Serializer.CUSTOM).serialize(values); + VPackSlice body = isStringCollection(values) ? getInternalSerialization().serialize(stringCollectionToJsonArray((Collection) values)) + : getUserSerialization().serialize(values); request.setBody(body); return request; } @@ -332,18 +331,18 @@ protected ResponseDeserializer>> for (final Iterator iterator = body.arrayIterator(); iterator.hasNext(); ) { final VPackSlice next = iterator.next(); if (next.get(ArangoResponseField.ERROR).isTrue()) { - final ErrorEntity error = util().deserialize(next, ErrorEntity.class); + final ErrorEntity error = getInternalSerialization().deserialize(next, ErrorEntity.class); errors.add(error); documentsAndErrors.add(error); } else { - final DocumentUpdateEntity doc = util().deserialize(next, DocumentUpdateEntity.class); + final DocumentUpdateEntity doc = getInternalSerialization().deserialize(next, DocumentUpdateEntity.class); final VPackSlice newDoc = next.get(NEW); if (newDoc.isObject()) { - doc.setNew(util(Serializer.CUSTOM).deserialize(newDoc, type)); + doc.setNew(getUserSerialization().deserialize(newDoc, type)); } final VPackSlice oldDoc = next.get(OLD); if (oldDoc.isObject()) { - doc.setOld(util(Serializer.CUSTOM).deserialize(oldDoc, type)); + doc.setOld(getUserSerialization().deserialize(oldDoc, type)); } docs.add(doc); documentsAndErrors.add(doc); @@ -370,7 +369,7 @@ protected Request updateDocumentRequest(final String key, final T value, fin request.putQueryParam(RETURN_NEW, params.getReturnNew()); request.putQueryParam(RETURN_OLD, params.getReturnOld()); request.putQueryParam(SILENT, params.getSilent()); - request.setBody(util(Serializer.CUSTOM).serialize(value)); + request.setBody(getUserSerialization().serialize(value)); return request; } @@ -378,14 +377,14 @@ protected ResponseDeserializer> updateDocumentRes final T value, final DocumentUpdateOptions options, final Class returnType) { return response -> { final VPackSlice body = response.getBody(); - final DocumentUpdateEntity doc = util().deserialize(body, DocumentUpdateEntity.class); + final DocumentUpdateEntity doc = getInternalSerialization().deserialize(body, DocumentUpdateEntity.class); final VPackSlice newDoc = body.get(NEW); if (newDoc.isObject()) { - doc.setNew(util(Serializer.CUSTOM).deserialize(newDoc, returnType)); + doc.setNew(getUserSerialization().deserialize(newDoc, returnType)); } final VPackSlice oldDoc = body.get(OLD); if (oldDoc.isObject()) { - doc.setOld(util(Serializer.CUSTOM).deserialize(oldDoc, returnType)); + doc.setOld(getUserSerialization().deserialize(oldDoc, returnType)); } if (options == null || Boolean.TRUE != options.getSilent()) { final Map values = new HashMap<>(); @@ -409,8 +408,8 @@ protected Request updateDocumentsRequest(final Collection values, final D request.putQueryParam(RETURN_OLD, params.getReturnOld()); request.putQueryParam(SILENT, params.getSilent()); - VPackSlice body = isStringCollection(values) ? util().serialize(stringCollectionToJsonArray((Collection) values)) - : util(Serializer.CUSTOM).serialize(values); + VPackSlice body = isStringCollection(values) ? getInternalSerialization().serialize(stringCollectionToJsonArray((Collection) values)) + : getUserSerialization().serialize(values); request.setBody(body); return request; } @@ -428,18 +427,18 @@ protected ResponseDeserializer>> for (final Iterator iterator = body.arrayIterator(); iterator.hasNext(); ) { final VPackSlice next = iterator.next(); if (next.get(ArangoResponseField.ERROR).isTrue()) { - final ErrorEntity error = util().deserialize(next, ErrorEntity.class); + final ErrorEntity error = getInternalSerialization().deserialize(next, ErrorEntity.class); errors.add(error); documentsAndErrors.add(error); } else { - final DocumentUpdateEntity doc = util().deserialize(next, DocumentUpdateEntity.class); + final DocumentUpdateEntity doc = getInternalSerialization().deserialize(next, DocumentUpdateEntity.class); final VPackSlice newDoc = next.get(NEW); if (newDoc.isObject()) { - doc.setNew(util(Serializer.CUSTOM).deserialize(newDoc, returnType)); + doc.setNew(getUserSerialization().deserialize(newDoc, returnType)); } final VPackSlice oldDoc = next.get(OLD); if (oldDoc.isObject()) { - doc.setOld(util(Serializer.CUSTOM).deserialize(oldDoc, returnType)); + doc.setOld(getUserSerialization().deserialize(oldDoc, returnType)); } docs.add(doc); documentsAndErrors.add(doc); @@ -469,10 +468,10 @@ protected ResponseDeserializer> deleteDocumentRespon final Class type) { return response -> { final VPackSlice body = response.getBody(); - final DocumentDeleteEntity doc = util().deserialize(body, DocumentDeleteEntity.class); + final DocumentDeleteEntity doc = getInternalSerialization().deserialize(body, DocumentDeleteEntity.class); final VPackSlice oldDoc = body.get(OLD); if (oldDoc.isObject()) { - doc.setOld(util(Serializer.CUSTOM).deserialize(oldDoc, type)); + doc.setOld(getUserSerialization().deserialize(oldDoc, type)); } return doc; }; @@ -485,7 +484,7 @@ protected Request deleteDocumentsRequest(final Collection keys, final Doc request.putQueryParam(ArangoRequestParam.WAIT_FOR_SYNC, params.getWaitForSync()); request.putQueryParam(RETURN_OLD, params.getReturnOld()); request.putQueryParam(SILENT, params.getSilent()); - request.setBody(util().serialize(keys)); + request.setBody(getInternalSerialization().serialize(keys)); return request; } @@ -501,14 +500,14 @@ protected ResponseDeserializer>> for (final Iterator iterator = body.arrayIterator(); iterator.hasNext(); ) { final VPackSlice next = iterator.next(); if (next.get(ArangoResponseField.ERROR).isTrue()) { - final ErrorEntity error = util().deserialize(next, ErrorEntity.class); + final ErrorEntity error = getInternalSerialization().deserialize(next, ErrorEntity.class); errors.add(error); documentsAndErrors.add(error); } else { - final DocumentDeleteEntity doc = util().deserialize(next, DocumentDeleteEntity.class); + final DocumentDeleteEntity doc = getInternalSerialization().deserialize(next, DocumentDeleteEntity.class); final VPackSlice oldDoc = next.get(OLD); if (oldDoc.isObject()) { - doc.setOld(util(Serializer.CUSTOM).deserialize(oldDoc, type)); + doc.setOld(getUserSerialization().deserialize(oldDoc, type)); } docs.add(doc); documentsAndErrors.add(doc); @@ -561,7 +560,7 @@ protected Request createHashIndexRequest(final Iterable fields, final Ha final Request request = request(db.dbName(), RequestType.POST, PATH_API_INDEX); request.putQueryParam(COLLECTION, name); request.setBody( - util().serialize(OptionsBuilder.build(options != null ? options : new HashIndexOptions(), fields))); + getInternalSerialization().serialize(OptionsBuilder.build(options != null ? options : new HashIndexOptions(), fields))); return request; } @@ -570,7 +569,7 @@ protected Request createSkiplistIndexRequest(final Iterable fields, fina final Request request = request(db.dbName(), RequestType.POST, PATH_API_INDEX); request.putQueryParam(COLLECTION, name); request.setBody( - util().serialize(OptionsBuilder.build(options != null ? options : new SkiplistIndexOptions(), fields))); + getInternalSerialization().serialize(OptionsBuilder.build(options != null ? options : new SkiplistIndexOptions(), fields))); return request; } @@ -578,7 +577,7 @@ protected Request createPersistentIndexRequest( final Iterable fields, final PersistentIndexOptions options) { final Request request = request(db.dbName(), RequestType.POST, PATH_API_INDEX); request.putQueryParam(COLLECTION, name); - request.setBody(util().serialize( + request.setBody(getInternalSerialization().serialize( OptionsBuilder.build(options != null ? options : new PersistentIndexOptions(), fields))); return request; } @@ -587,7 +586,7 @@ protected Request createGeoIndexRequest(final Iterable fields, final Geo final Request request = request(db.dbName(), RequestType.POST, PATH_API_INDEX); request.putQueryParam(COLLECTION, name); request.setBody( - util().serialize(OptionsBuilder.build(options != null ? options : new GeoIndexOptions(), fields))); + getInternalSerialization().serialize(OptionsBuilder.build(options != null ? options : new GeoIndexOptions(), fields))); return request; } @@ -595,7 +594,7 @@ protected Request createFulltextIndexRequest(final Iterable fields, fina final Request request = request(db.dbName(), RequestType.POST, PATH_API_INDEX); request.putQueryParam(COLLECTION, name); request.setBody( - util().serialize(OptionsBuilder.build(options != null ? options : new FulltextIndexOptions(), fields))); + getInternalSerialization().serialize(OptionsBuilder.build(options != null ? options : new FulltextIndexOptions(), fields))); return request; } @@ -603,7 +602,7 @@ protected Request createTtlIndexRequest(final Iterable fields, final Ttl final Request request = request(db.dbName(), RequestType.POST, PATH_API_INDEX); request.putQueryParam(COLLECTION, name); request.setBody( - util().serialize(OptionsBuilder.build(options != null ? options : new TtlIndexOptions(), fields))); + getInternalSerialization().serialize(OptionsBuilder.build(options != null ? options : new TtlIndexOptions(), fields))); return request; } @@ -611,7 +610,7 @@ protected Request createZKDIndexRequest( final Iterable fields, final ZKDIndexOptions options) { final Request request = request(db.dbName(), RequestType.POST, PATH_API_INDEX); request.putQueryParam(COLLECTION, name); - request.setBody(util().serialize(OptionsBuilder.build(options != null ? options : + request.setBody(getInternalSerialization().serialize(OptionsBuilder.build(options != null ? options : new ZKDIndexOptions().fieldValueTypes(ZKDIndexOptions.FieldValueTypes.DOUBLE), fields))); return request; } @@ -623,7 +622,7 @@ protected Request getIndexesRequest() { } protected ResponseDeserializer> getIndexesResponseDeserializer() { - return response -> util().deserialize(response.getBody().get("indexes"), new Type>() { + return response -> getInternalSerialization().deserialize(response.getBody().get("indexes"), new Type>() { }.getType()); } @@ -655,19 +654,19 @@ protected Request getPropertiesRequest() { protected Request changePropertiesRequest(final CollectionPropertiesOptions options) { final Request request = request(db.dbName(), RequestType.PUT, PATH_API_COLLECTION, name, "properties"); - request.setBody(util().serialize(options != null ? options : new CollectionPropertiesOptions())); + request.setBody(getInternalSerialization().serialize(options != null ? options : new CollectionPropertiesOptions())); return request; } protected Request renameRequest(final String newName) { final Request request = request(db.dbName(), RequestType.PUT, PATH_API_COLLECTION, name, "rename"); - request.setBody(util().serialize(OptionsBuilder.build(new CollectionRenameOptions(), newName))); + request.setBody(getInternalSerialization().serialize(OptionsBuilder.build(new CollectionRenameOptions(), newName))); return request; } protected Request responsibleShardRequest(final T value) { final Request request = request(db.dbName(), RequestType.PUT, PATH_API_COLLECTION, name, "responsibleShard"); - request.setBody(util(Serializer.CUSTOM).serialize(value)); + request.setBody(getUserSerialization().serialize(value)); return request; } @@ -677,7 +676,7 @@ protected Request getRevisionRequest() { protected Request grantAccessRequest(final String user, final Permissions permissions) { return request(DbName.SYSTEM, RequestType.PUT, PATH_API_USER, user, ArangoRequestParam.DATABASE, - db.dbName().get(), name).setBody(util().serialize(OptionsBuilder.build(new UserAccessOptions(), permissions))); + db.dbName().get(), name).setBody(getInternalSerialization().serialize(OptionsBuilder.build(new UserAccessOptions(), permissions))); } protected Request resetAccessRequest(final String user) { @@ -696,7 +695,7 @@ protected ResponseDeserializer getPermissionsResponseDeserialzer() if (body != null) { final VPackSlice result = body.get(ArangoResponseField.RESULT); if (!result.isNone()) { - return util().deserialize(result, Permissions.class); + return getInternalSerialization().deserialize(result, Permissions.class); } } return null; diff --git a/src/main/java/com/arangodb/internal/InternalArangoDB.java b/src/main/java/com/arangodb/internal/InternalArangoDB.java index db5d9135d..e1ccaeef5 100644 --- a/src/main/java/com/arangodb/internal/InternalArangoDB.java +++ b/src/main/java/com/arangodb/internal/InternalArangoDB.java @@ -62,17 +62,17 @@ protected Request getServerIdRequest() { } protected ResponseDeserializer getRoleResponseDeserializer() { - return response -> util().deserialize(response.getBody().get("role"), ServerRole.class); + return response -> getInternalSerialization().deserialize(response.getBody().get("role"), ServerRole.class); } protected ResponseDeserializer getServerIdResponseDeserializer() { - return response -> util().deserialize(response.getBody().get("id"), String.class); + return response -> getInternalSerialization().deserialize(response.getBody().get("id"), String.class); } protected Request createDatabaseRequest(final DBCreateOptions options) { final Request request = request(DbName.SYSTEM, RequestType.POST, InternalArangoDatabase.PATH_API_DATABASE); - request.setBody(util().serialize(options)); + request.setBody(getInternalSerialization().serialize(options)); return request; } @@ -87,7 +87,7 @@ protected Request getDatabasesRequest(final DbName dbName) { protected ResponseDeserializer> getDatabaseResponseDeserializer() { return response -> { final VPackSlice result = response.getBody().get(ArangoResponseField.RESULT); - return util().deserialize(result, new Type>() { + return getInternalSerialization().deserialize(result, new Type>() { }.getType()); }; } @@ -116,7 +116,7 @@ protected Request createUserRequest( final Request request; request = request(dbName, RequestType.POST, PATH_API_USER); request.setBody( - util().serialize(OptionsBuilder.build(options != null ? options : new UserCreateOptions(), user, passwd))); + getInternalSerialization().serialize(OptionsBuilder.build(options != null ? options : new UserCreateOptions(), user, passwd))); return request; } @@ -135,7 +135,7 @@ protected Request getUserRequest(final DbName dbName, final String user) { protected ResponseDeserializer> getUsersResponseDeserializer() { return response -> { final VPackSlice result = response.getBody().get(ArangoResponseField.RESULT); - return util().deserialize(result, new Type>() { + return getInternalSerialization().deserialize(result, new Type>() { }.getType()); }; } @@ -143,25 +143,25 @@ protected ResponseDeserializer> getUsersResponseDeseriali protected Request updateUserRequest(final DbName dbName, final String user, final UserUpdateOptions options) { final Request request; request = request(dbName, RequestType.PATCH, PATH_API_USER, user); - request.setBody(util().serialize(options != null ? options : new UserUpdateOptions())); + request.setBody(getInternalSerialization().serialize(options != null ? options : new UserUpdateOptions())); return request; } protected Request replaceUserRequest(final DbName dbName, final String user, final UserUpdateOptions options) { final Request request; request = request(dbName, RequestType.PUT, PATH_API_USER, user); - request.setBody(util().serialize(options != null ? options : new UserUpdateOptions())); + request.setBody(getInternalSerialization().serialize(options != null ? options : new UserUpdateOptions())); return request; } protected Request updateUserDefaultDatabaseAccessRequest(final String user, final Permissions permissions) { return request(DbName.SYSTEM, RequestType.PUT, PATH_API_USER, user, ArangoRequestParam.DATABASE, - "*").setBody(util().serialize(OptionsBuilder.build(new UserAccessOptions(), permissions))); + "*").setBody(getInternalSerialization().serialize(OptionsBuilder.build(new UserAccessOptions(), permissions))); } protected Request updateUserDefaultCollectionAccessRequest(final String user, final Permissions permissions) { return request(DbName.SYSTEM, RequestType.PUT, PATH_API_USER, user, ArangoRequestParam.DATABASE, - "*", "*").setBody(util().serialize(OptionsBuilder.build(new UserAccessOptions(), permissions))); + "*", "*").setBody(getInternalSerialization().serialize(OptionsBuilder.build(new UserAccessOptions(), permissions))); } protected Request getLogEntriesRequest(final LogOptions options) { @@ -182,7 +182,7 @@ protected Request getLogLevelRequest() { protected Request setLogLevelRequest(final LogLevelEntity entity) { return request(DbName.SYSTEM, RequestType.PUT, PATH_API_ADMIN_LOG_LEVEL) - .setBody(util().serialize(entity)); + .setBody(getInternalSerialization().serialize(entity)); } } diff --git a/src/main/java/com/arangodb/internal/InternalArangoDatabase.java b/src/main/java/com/arangodb/internal/InternalArangoDatabase.java index 879f30987..294830a2e 100644 --- a/src/main/java/com/arangodb/internal/InternalArangoDatabase.java +++ b/src/main/java/com/arangodb/internal/InternalArangoDatabase.java @@ -25,7 +25,6 @@ import com.arangodb.entity.arangosearch.analyzer.SearchAnalyzer; import com.arangodb.internal.ArangoExecutor.ResponseDeserializer; import com.arangodb.internal.util.ArangoSerializationFactory; -import com.arangodb.internal.util.ArangoSerializationFactory.Serializer; import com.arangodb.internal.util.RequestUtils; import com.arangodb.model.*; import com.arangodb.model.arangosearch.AnalyzerDeleteOptions; @@ -101,7 +100,7 @@ protected Request getEngineRequest() { protected Request createCollectionRequest(final String name, final CollectionCreateOptions options) { - VPackSlice body = util() + VPackSlice body = getInternalSerialization() .serialize(OptionsBuilder.build(options != null ? options : new CollectionCreateOptions(), name)); return request(dbName, RequestType.POST, InternalArangoCollection.PATH_API_COLLECTION).setBody(body); @@ -118,7 +117,7 @@ protected Request getCollectionsRequest(final CollectionsReadOptions options) { protected ResponseDeserializer> getCollectionsResponseDeserializer() { return response -> { final VPackSlice result = response.getBody().get(ArangoResponseField.RESULT); - return util().deserialize(result, new Type>() { + return getInternalSerialization().deserialize(result, new Type>() { }.getType()); }; } @@ -133,7 +132,7 @@ protected ResponseDeserializer createDropResponseDeserializer() { protected Request grantAccessRequest(final String user, final Permissions permissions) { return request(DbName.SYSTEM, RequestType.PUT, PATH_API_USER, user, ArangoRequestParam.DATABASE, - dbName.get()).setBody(util().serialize(OptionsBuilder.build(new UserAccessOptions(), permissions))); + dbName.get()).setBody(getInternalSerialization().serialize(OptionsBuilder.build(new UserAccessOptions(), permissions))); } protected Request resetAccessRequest(final String user) { @@ -143,7 +142,7 @@ protected Request resetAccessRequest(final String user) { protected Request updateUserDefaultCollectionAccessRequest(final String user, final Permissions permissions) { return request(DbName.SYSTEM, RequestType.PUT, PATH_API_USER, user, ArangoRequestParam.DATABASE, - dbName.get(), "*").setBody(util().serialize(OptionsBuilder.build(new UserAccessOptions(), permissions))); + dbName.get(), "*").setBody(getInternalSerialization().serialize(OptionsBuilder.build(new UserAccessOptions(), permissions))); } protected Request getPermissionsRequest(final String user) { @@ -157,7 +156,7 @@ protected ResponseDeserializer getPermissionsResponseDeserialzer() if (body != null) { final VPackSlice result = body.get(ArangoResponseField.RESULT); if (!result.isNone()) { - return util().deserialize(result, Permissions.class); + return getInternalSerialization().deserialize(result, Permissions.class); } } return null; @@ -168,9 +167,9 @@ protected Request queryRequest( final String query, final Map bindVars, final AqlQueryOptions options) { final AqlQueryOptions opt = options != null ? options : new AqlQueryOptions(); final Request request = request(dbName, RequestType.POST, PATH_API_CURSOR) - .setBody(util().serialize(OptionsBuilder + .setBody(getInternalSerialization().serialize(OptionsBuilder .build(opt, query, bindVars != null ? - util(ArangoSerializationFactory.Serializer.CUSTOM).serialize(bindVars, new ArangoSerializer.Options().serializeNullValues(true)) : + getUserSerialization().serialize(bindVars, new ArangoSerializer.Options().serializeNullValues(true)) : null))); if (opt.getAllowDirtyRead() == Boolean.TRUE) { RequestUtils.allowDirtyRead(request); @@ -222,17 +221,17 @@ protected Request explainQueryRequest( final AqlQueryExplainOptions opt = options != null ? options : new AqlQueryExplainOptions(); return request(dbName, RequestType.POST, PATH_API_EXPLAIN) - .setBody(util().serialize(OptionsBuilder.build( + .setBody(getInternalSerialization().serialize(OptionsBuilder.build( opt, query, - bindVars != null ? util(ArangoSerializationFactory.Serializer.CUSTOM).serialize( + bindVars != null ? getUserSerialization().serialize( bindVars, new ArangoSerializer.Options().serializeNullValues(true)) : null))); } protected Request parseQueryRequest(final String query) { return request(dbName, RequestType.POST, PATH_API_QUERY) - .setBody(util().serialize(OptionsBuilder.build(new AqlQueryParseOptions(), query))); + .setBody(getInternalSerialization().serialize(OptionsBuilder.build(new AqlQueryParseOptions(), query))); } protected Request clearQueryCacheRequest() { @@ -244,7 +243,7 @@ protected Request getQueryCachePropertiesRequest() { } protected Request setQueryCachePropertiesRequest(final QueryCachePropertiesEntity properties) { - return request(dbName, RequestType.PUT, PATH_API_QUERY_CACHE_PROPERTIES).setBody(util().serialize(properties)); + return request(dbName, RequestType.PUT, PATH_API_QUERY_CACHE_PROPERTIES).setBody(getInternalSerialization().serialize(properties)); } protected Request getQueryTrackingPropertiesRequest() { @@ -252,7 +251,7 @@ protected Request getQueryTrackingPropertiesRequest() { } protected Request setQueryTrackingPropertiesRequest(final QueryTrackingPropertiesEntity properties) { - return request(dbName, RequestType.PUT, PATH_API_QUERY_PROPERTIES).setBody(util().serialize(properties)); + return request(dbName, RequestType.PUT, PATH_API_QUERY_PROPERTIES).setBody(getInternalSerialization().serialize(properties)); } protected Request getCurrentlyRunningQueriesRequest() { @@ -273,7 +272,7 @@ protected Request killQueryRequest(final String id) { protected Request createAqlFunctionRequest( final String name, final String code, final AqlFunctionCreateOptions options) { - return request(dbName, RequestType.POST, PATH_API_AQLFUNCTION).setBody(util().serialize( + return request(dbName, RequestType.POST, PATH_API_AQLFUNCTION).setBody(getInternalSerialization().serialize( OptionsBuilder.build(options != null ? options : new AqlFunctionCreateOptions(), name, code))); } @@ -313,19 +312,19 @@ protected ResponseDeserializer> getAqlFunctionsRes // compatibility with ArangoDB < 3.4 // https://www.arangodb.com/docs/stable/release-notes-upgrading-changes34.html final VPackSlice result = body.isArray() ? body : body.get(ArangoResponseField.RESULT); - return util().deserialize(result, new Type>() { + return getInternalSerialization().deserialize(result, new Type>() { }.getType()); }; } protected Request createGraphRequest( final String name, final Collection edgeDefinitions, final GraphCreateOptions options) { - return request(dbName, RequestType.POST, InternalArangoGraph.PATH_API_GHARIAL).setBody(util().serialize( + return request(dbName, RequestType.POST, InternalArangoGraph.PATH_API_GHARIAL).setBody(getInternalSerialization().serialize( OptionsBuilder.build(options != null ? options : new GraphCreateOptions(), name, edgeDefinitions))); } protected ResponseDeserializer createGraphResponseDeserializer() { - return response -> util().deserialize(response.getBody().get("graph"), GraphEntity.class); + return response -> getInternalSerialization().deserialize(response.getBody().get("graph"), GraphEntity.class); } protected Request getGraphsRequest() { @@ -333,13 +332,13 @@ protected Request getGraphsRequest() { } protected ResponseDeserializer> getGraphsResponseDeserializer() { - return response -> util().deserialize(response.getBody().get("graphs"), new Type>() { + return response -> getInternalSerialization().deserialize(response.getBody().get("graphs"), new Type>() { }.getType()); } protected Request transactionRequest(final String action, final TransactionOptions options) { return request(dbName, RequestType.POST, PATH_API_TRANSACTION).setBody( - util().serialize(OptionsBuilder.build(options != null ? options : new TransactionOptions(), action))); + getInternalSerialization().serialize(OptionsBuilder.build(options != null ? options : new TransactionOptions(), action))); } protected ResponseDeserializer transactionResponseDeserializer(final Class type) { @@ -348,7 +347,7 @@ protected ResponseDeserializer transactionResponseDeserializer(final Clas if (body != null) { final VPackSlice result = body.get(ArangoResponseField.RESULT); if (!result.isNone() && !result.isNull()) { - return util(Serializer.CUSTOM).deserialize(result, type); + return getUserSerialization().deserialize(result, type); } } return null; @@ -357,7 +356,7 @@ protected ResponseDeserializer transactionResponseDeserializer(final Clas protected Request beginStreamTransactionRequest(final StreamTransactionOptions options) { return request(dbName, RequestType.POST, PATH_API_BEGIN_STREAM_TRANSACTION) - .setBody(util().serialize(options != null ? options : new StreamTransactionOptions())); + .setBody(getInternalSerialization().serialize(options != null ? options : new StreamTransactionOptions())); } protected Request abortStreamTransactionRequest(String id) { @@ -375,7 +374,7 @@ protected Request getStreamTransactionRequest(String id) { protected ResponseDeserializer> transactionsResponseDeserializer() { return response -> { final VPackSlice result = response.getBody().get("transactions"); - return util().deserialize(result, new Type>() { + return getInternalSerialization().deserialize(result, new Type>() { }.getType()); }; } @@ -385,7 +384,7 @@ protected Request commitStreamTransactionRequest(String id) { } protected ResponseDeserializer streamTransactionResponseDeserializer() { - return response -> util() + return response -> getInternalSerialization() .deserialize(response.getBody().get(ArangoResponseField.RESULT), StreamTransactionEntity.class); } @@ -394,7 +393,7 @@ protected Request getInfoRequest() { } protected ResponseDeserializer getInfoResponseDeserializer() { - return response -> util().deserialize(response.getBody().get(ArangoResponseField.RESULT), DatabaseEntity.class); + return response -> getInternalSerialization().deserialize(response.getBody().get(ArangoResponseField.RESULT), DatabaseEntity.class); } protected Request reloadRoutingRequest() { @@ -408,18 +407,18 @@ protected Request getViewsRequest() { protected ResponseDeserializer> getViewsResponseDeserializer() { return response -> { final VPackSlice result = response.getBody().get(ArangoResponseField.RESULT); - return util().deserialize(result, new Type>() { + return getInternalSerialization().deserialize(result, new Type>() { }.getType()); }; } protected Request createViewRequest(final String name, final ViewType type) { return request(dbName, RequestType.POST, InternalArangoView.PATH_API_VIEW) - .setBody(util().serialize(OptionsBuilder.build(new ViewCreateOptions(), name, type))); + .setBody(getInternalSerialization().serialize(OptionsBuilder.build(new ViewCreateOptions(), name, type))); } protected Request createArangoSearchRequest(final String name, final ArangoSearchCreateOptions options) { - return request(dbName, RequestType.POST, InternalArangoView.PATH_API_VIEW).setBody(util().serialize( + return request(dbName, RequestType.POST, InternalArangoView.PATH_API_VIEW).setBody(getInternalSerialization().serialize( ArangoSearchOptionsBuilder.build(options != null ? options : new ArangoSearchCreateOptions(), name))); } @@ -434,14 +433,14 @@ protected Request getAnalyzersRequest() { protected ResponseDeserializer> getSearchAnalyzersResponseDeserializer() { return response -> { final VPackSlice result = response.getBody().get(ArangoResponseField.RESULT); - return util().deserialize(result, new Type>() { + return getInternalSerialization().deserialize(result, new Type>() { }.getType()); }; } protected Request createAnalyzerRequest(final SearchAnalyzer options) { return request(dbName, RequestType.POST, InternalArangoView.PATH_API_ANALYZER) - .setBody(util().serialize(options)); + .setBody(getInternalSerialization().serialize(options)); } protected Request deleteAnalyzerRequest(final String name, final AnalyzerDeleteOptions options) { diff --git a/src/main/java/com/arangodb/internal/InternalArangoEdgeCollection.java b/src/main/java/com/arangodb/internal/InternalArangoEdgeCollection.java index 44ad70837..6b6271c8b 100644 --- a/src/main/java/com/arangodb/internal/InternalArangoEdgeCollection.java +++ b/src/main/java/com/arangodb/internal/InternalArangoEdgeCollection.java @@ -23,7 +23,6 @@ import com.arangodb.entity.EdgeEntity; import com.arangodb.entity.EdgeUpdateEntity; import com.arangodb.internal.ArangoExecutor.ResponseDeserializer; -import com.arangodb.internal.util.ArangoSerializationFactory.Serializer; import com.arangodb.internal.util.DocumentUtil; import com.arangodb.internal.util.RequestUtils; import com.arangodb.model.*; @@ -69,14 +68,14 @@ protected Request insertEdgeRequest(final T value, final EdgeCreateOptions o final EdgeCreateOptions params = (options != null ? options : new EdgeCreateOptions()); request.putHeaderParam(TRANSACTION_ID, params.getStreamTransactionId()); request.putQueryParam(ArangoRequestParam.WAIT_FOR_SYNC, params.getWaitForSync()); - request.setBody(util(Serializer.CUSTOM).serialize(value)); + request.setBody(getUserSerialization().serialize(value)); return request; } protected ResponseDeserializer insertEdgeResponseDeserializer(final T value) { return response -> { final VPackSlice body = response.getBody().get(EDGE); - final EdgeEntity doc = util().deserialize(body, EdgeEntity.class); + final EdgeEntity doc = getInternalSerialization().deserialize(body, EdgeEntity.class); final Map values = new HashMap<>(); values.put(DocumentFields.ID, doc.getId()); values.put(DocumentFields.KEY, doc.getKey()); @@ -100,7 +99,7 @@ protected Request getEdgeRequest(final String key, final GraphDocumentReadOption } protected ResponseDeserializer getEdgeResponseDeserializer(final Class type) { - return response -> util(Serializer.CUSTOM).deserialize(response.getBody().get(EDGE), type); + return response -> getUserSerialization().deserialize(response.getBody().get(EDGE), type); } protected Request replaceEdgeRequest(final String key, final T value, final EdgeReplaceOptions options) { @@ -110,14 +109,14 @@ protected Request replaceEdgeRequest(final String key, final T value, final request.putHeaderParam(TRANSACTION_ID, params.getStreamTransactionId()); request.putQueryParam(ArangoRequestParam.WAIT_FOR_SYNC, params.getWaitForSync()); request.putHeaderParam(ArangoRequestParam.IF_MATCH, params.getIfMatch()); - request.setBody(util(Serializer.CUSTOM).serialize(value)); + request.setBody(getUserSerialization().serialize(value)); return request; } protected ResponseDeserializer replaceEdgeResponseDeserializer(final T value) { return response -> { final VPackSlice body = response.getBody().get(EDGE); - final EdgeUpdateEntity doc = util().deserialize(body, EdgeUpdateEntity.class); + final EdgeUpdateEntity doc = getInternalSerialization().deserialize(body, EdgeUpdateEntity.class); final Map values = new HashMap<>(); values.put(DocumentFields.REV, doc.getRev()); executor.documentCache().setValues(value, values); @@ -135,14 +134,14 @@ protected Request updateEdgeRequest(final String key, final T value, final E request.putQueryParam(ArangoRequestParam.WAIT_FOR_SYNC, params.getWaitForSync()); request.putHeaderParam(ArangoRequestParam.IF_MATCH, params.getIfMatch()); request.setBody( - util(Serializer.CUSTOM).serialize(value, new ArangoSerializer.Options().serializeNullValues(true))); + getUserSerialization().serialize(value, new ArangoSerializer.Options().serializeNullValues(true))); return request; } protected ResponseDeserializer updateEdgeResponseDeserializer(final T value) { return response -> { final VPackSlice body = response.getBody().get(EDGE); - final EdgeUpdateEntity doc = util().deserialize(body, EdgeUpdateEntity.class); + final EdgeUpdateEntity doc = getInternalSerialization().deserialize(body, EdgeUpdateEntity.class); final Map values = new HashMap<>(); values.put(DocumentFields.REV, doc.getRev()); executor.documentCache().setValues(value, values); diff --git a/src/main/java/com/arangodb/internal/InternalArangoGraph.java b/src/main/java/com/arangodb/internal/InternalArangoGraph.java index a03e090e6..10059c705 100644 --- a/src/main/java/com/arangodb/internal/InternalArangoGraph.java +++ b/src/main/java/com/arangodb/internal/InternalArangoGraph.java @@ -84,13 +84,13 @@ protected Request getVertexCollectionsRequest() { } protected ResponseDeserializer> getVertexCollectionsResponseDeserializer() { - return response -> util().deserialize(response.getBody().get("collections"), new Type>() { + return response -> getInternalSerialization().deserialize(response.getBody().get("collections"), new Type>() { }.getType()); } 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(options, name))); + request.setBody(getInternalSerialization().serialize(OptionsBuilder.build(options, name))); return request; } @@ -103,29 +103,29 @@ protected Request getEdgeDefinitionsRequest() { } protected ResponseDeserializer> getEdgeDefinitionsDeserializer() { - return response -> util().deserialize(response.getBody().get("collections"), new Type>() { + return response -> getInternalSerialization().deserialize(response.getBody().get("collections"), new Type>() { }.getType()); } protected Request addEdgeDefinitionRequest(final EdgeDefinition definition) { final Request request = request(db.dbName(), RequestType.POST, PATH_API_GHARIAL, name, EDGE); - request.setBody(util().serialize(definition)); + request.setBody(getInternalSerialization().serialize(definition)); return request; } protected ResponseDeserializer addEdgeDefinitionResponseDeserializer() { - return response -> util().deserialize(response.getBody().get(GRAPH), GraphEntity.class); + return response -> getInternalSerialization().deserialize(response.getBody().get(GRAPH), GraphEntity.class); } protected Request replaceEdgeDefinitionRequest(final EdgeDefinition definition) { final Request request = request(db.dbName(), RequestType.PUT, PATH_API_GHARIAL, name, EDGE, definition.getCollection()); - request.setBody(util().serialize(definition)); + request.setBody(getInternalSerialization().serialize(definition)); return request; } protected ResponseDeserializer replaceEdgeDefinitionResponseDeserializer() { - return response -> util().deserialize(response.getBody().get(GRAPH), GraphEntity.class); + return response -> getInternalSerialization().deserialize(response.getBody().get(GRAPH), GraphEntity.class); } protected Request removeEdgeDefinitionRequest(final String definitionName) { @@ -133,7 +133,7 @@ protected Request removeEdgeDefinitionRequest(final String definitionName) { } protected ResponseDeserializer removeEdgeDefinitionResponseDeserializer() { - return response -> util().deserialize(response.getBody().get(GRAPH), GraphEntity.class); + return response -> getInternalSerialization().deserialize(response.getBody().get(GRAPH), GraphEntity.class); } } diff --git a/src/main/java/com/arangodb/internal/InternalArangoRoute.java b/src/main/java/com/arangodb/internal/InternalArangoRoute.java index 9c6a4171a..f0936eb87 100644 --- a/src/main/java/com/arangodb/internal/InternalArangoRoute.java +++ b/src/main/java/com/arangodb/internal/InternalArangoRoute.java @@ -74,7 +74,7 @@ protected Request createRequest(final RequestType requestType) { request.putQueryParam(param.getKey(), param.getValue()); } if (body != null) { - request.setBody(util().serialize(body)); + request.setBody(getInternalSerialization().serialize(body)); } return request; } diff --git a/src/main/java/com/arangodb/internal/InternalArangoSearch.java b/src/main/java/com/arangodb/internal/InternalArangoSearch.java index dac8d35e8..3bdf9d90f 100644 --- a/src/main/java/com/arangodb/internal/InternalArangoSearch.java +++ b/src/main/java/com/arangodb/internal/InternalArangoSearch.java @@ -40,13 +40,13 @@ protected Request getPropertiesRequest() { protected Request replacePropertiesRequest(final ArangoSearchPropertiesOptions options) { final Request request = request(db.dbName(), RequestType.PUT, PATH_API_VIEW, name, "properties"); - request.setBody(util().serialize(options != null ? options : new ArangoSearchPropertiesOptions())); + request.setBody(getInternalSerialization().serialize(options != null ? options : new ArangoSearchPropertiesOptions())); return request; } protected Request updatePropertiesRequest(final ArangoSearchPropertiesOptions options) { final Request request = request(db.dbName(), RequestType.PATCH, PATH_API_VIEW, name, "properties"); - request.setBody(util().serialize(options != null ? options : new ArangoSearchPropertiesOptions())); + request.setBody(getInternalSerialization().serialize(options != null ? options : new ArangoSearchPropertiesOptions())); return request; } diff --git a/src/main/java/com/arangodb/internal/InternalArangoVertexCollection.java b/src/main/java/com/arangodb/internal/InternalArangoVertexCollection.java index 4962fa6fa..17ef9beb7 100644 --- a/src/main/java/com/arangodb/internal/InternalArangoVertexCollection.java +++ b/src/main/java/com/arangodb/internal/InternalArangoVertexCollection.java @@ -23,7 +23,6 @@ import com.arangodb.entity.VertexEntity; import com.arangodb.entity.VertexUpdateEntity; import com.arangodb.internal.ArangoExecutor.ResponseDeserializer; -import com.arangodb.internal.util.ArangoSerializationFactory.Serializer; import com.arangodb.internal.util.DocumentUtil; import com.arangodb.internal.util.RequestUtils; import com.arangodb.model.*; @@ -77,9 +76,9 @@ protected Request insertVertexRequest(final T value, final VertexCreateOptio VPackSlice body; if (value instanceof String) { - body = util().serialize(SerdeUtils.INSTANCE.parseJson((String) value)); + body = getInternalSerialization().serialize(SerdeUtils.INSTANCE.parseJson((String) value)); } else { - body = util(Serializer.CUSTOM).serialize(value); + body = getUserSerialization().serialize(value); } request.setBody(body); return request; @@ -88,7 +87,7 @@ protected Request insertVertexRequest(final T value, final VertexCreateOptio protected ResponseDeserializer insertVertexResponseDeserializer(final T value) { return response -> { final VPackSlice body = response.getBody().get(VERTEX); - final VertexEntity doc = util().deserialize(body, VertexEntity.class); + final VertexEntity doc = getInternalSerialization().deserialize(body, VertexEntity.class); final Map values = new HashMap<>(); values.put(DocumentFields.ID, doc.getId()); values.put(DocumentFields.KEY, doc.getKey()); @@ -112,7 +111,7 @@ protected Request getVertexRequest(final String key, final GraphDocumentReadOpti } protected ResponseDeserializer getVertexResponseDeserializer(final Class type) { - return response -> util(Serializer.CUSTOM).deserialize(response.getBody().get(VERTEX), type); + return response -> getUserSerialization().deserialize(response.getBody().get(VERTEX), type); } protected Request replaceVertexRequest(final String key, final T value, final VertexReplaceOptions options) { @@ -122,14 +121,14 @@ protected Request replaceVertexRequest(final String key, final T value, fina request.putHeaderParam(TRANSACTION_ID, params.getStreamTransactionId()); request.putQueryParam(ArangoRequestParam.WAIT_FOR_SYNC, params.getWaitForSync()); request.putHeaderParam(ArangoRequestParam.IF_MATCH, params.getIfMatch()); - request.setBody(util(Serializer.CUSTOM).serialize(value)); + request.setBody(getUserSerialization().serialize(value)); return request; } protected ResponseDeserializer replaceVertexResponseDeserializer(final T value) { return response -> { final VPackSlice body = response.getBody().get(VERTEX); - final VertexUpdateEntity doc = util().deserialize(body, VertexUpdateEntity.class); + final VertexUpdateEntity doc = getInternalSerialization().deserialize(body, VertexUpdateEntity.class); final Map values = new HashMap<>(); values.put(DocumentFields.REV, doc.getRev()); executor.documentCache().setValues(value, values); @@ -147,14 +146,14 @@ protected Request updateVertexRequest(final String key, final T value, final request.putQueryParam(ArangoRequestParam.WAIT_FOR_SYNC, params.getWaitForSync()); request.putHeaderParam(ArangoRequestParam.IF_MATCH, params.getIfMatch()); request.setBody( - util(Serializer.CUSTOM).serialize(value, new ArangoSerializer.Options().serializeNullValues(true))); + getUserSerialization().serialize(value, new ArangoSerializer.Options().serializeNullValues(true))); return request; } protected ResponseDeserializer updateVertexResponseDeserializer(final T value) { return response -> { final VPackSlice body = response.getBody().get(VERTEX); - final VertexUpdateEntity doc = util().deserialize(body, VertexUpdateEntity.class); + final VertexUpdateEntity doc = getInternalSerialization().deserialize(body, VertexUpdateEntity.class); final Map values = new HashMap<>(); values.put(DocumentFields.REV, doc.getRev()); executor.documentCache().setValues(value, values); diff --git a/src/main/java/com/arangodb/internal/InternalArangoView.java b/src/main/java/com/arangodb/internal/InternalArangoView.java index 1fa76f015..0257e3643 100644 --- a/src/main/java/com/arangodb/internal/InternalArangoView.java +++ b/src/main/java/com/arangodb/internal/InternalArangoView.java @@ -58,7 +58,7 @@ protected Request dropRequest() { protected Request renameRequest(final String newName) { final Request request = request(db.dbName(), RequestType.PUT, PATH_API_VIEW, name, "rename"); - request.setBody(util().serialize(OptionsBuilder.build(new ViewRenameOptions(), newName))); + request.setBody(getInternalSerialization().serialize(OptionsBuilder.build(new ViewRenameOptions(), newName))); return request; } diff --git a/src/main/java/com/arangodb/internal/cursor/ArangoCursorIterator.java b/src/main/java/com/arangodb/internal/cursor/ArangoCursorIterator.java index b67ed820d..ff83bfbc4 100644 --- a/src/main/java/com/arangodb/internal/cursor/ArangoCursorIterator.java +++ b/src/main/java/com/arangodb/internal/cursor/ArangoCursorIterator.java @@ -25,7 +25,6 @@ import com.arangodb.entity.CursorEntity; import com.arangodb.internal.ArangoCursorExecute; import com.arangodb.internal.InternalArangoDatabase; -import com.arangodb.internal.util.ArangoSerializationFactory.Serializer; import com.arangodb.velocypack.VPackSlice; import java.util.Iterator; @@ -76,7 +75,7 @@ public T next() { } protected R deserialize(final VPackSlice result, final Class type) { - return db.util(Serializer.CUSTOM).deserialize(result, type); + return db.getUserSerialization().deserialize(result, type); } @Override diff --git a/src/main/java/com/arangodb/internal/util/ArangoSerializationFactory.java b/src/main/java/com/arangodb/internal/util/ArangoSerializationFactory.java index 035c2dc92..b015b59ec 100644 --- a/src/main/java/com/arangodb/internal/util/ArangoSerializationFactory.java +++ b/src/main/java/com/arangodb/internal/util/ArangoSerializationFactory.java @@ -27,27 +27,21 @@ */ public class ArangoSerializationFactory { - public enum Serializer { - INTERNAL, CUSTOM - } - - private final ArangoSerialization interal; - private final ArangoSerialization custom; + private final ArangoSerialization internal; + private final ArangoSerialization user; - public ArangoSerializationFactory(final ArangoSerialization interal, final ArangoSerialization custom) { + public ArangoSerializationFactory(final ArangoSerialization internal, final ArangoSerialization user) { super(); - this.interal = interal; - this.custom = custom; + this.internal = internal; + this.user = user; + } + + public ArangoSerialization getInternalSerialization() { + return internal; } - public ArangoSerialization get(final Serializer serializer) { - switch (serializer) { - case CUSTOM: - return custom; - case INTERNAL: - default: - return interal; - } + public ArangoSerialization getUserSerialization() { + return user; } } diff --git a/src/test/java/com/arangodb/JwtAuthTest.java b/src/test/java/com/arangodb/JwtAuthTest.java index 6c0c3029f..7ba60adbb 100644 --- a/src/test/java/com/arangodb/JwtAuthTest.java +++ b/src/test/java/com/arangodb/JwtAuthTest.java @@ -83,7 +83,7 @@ private ArangoDB.Builder getBuilder(Protocol protocol) { } private static String getJwt(ArangoDB arangoDB) { - ArangoSerialization serde = arangoDB.util(); + ArangoSerialization serde = arangoDB.getInternalSerialization(); Map reqBody = new HashMap<>(); reqBody.put("username", "root"); reqBody.put("password", "test"); diff --git a/src/test/java/com/arangodb/async/JwtAuthTest.java b/src/test/java/com/arangodb/async/JwtAuthTest.java index c9d0f40d1..ba119bcc7 100644 --- a/src/test/java/com/arangodb/async/JwtAuthTest.java +++ b/src/test/java/com/arangodb/async/JwtAuthTest.java @@ -90,7 +90,7 @@ private ArangoDBAsync.Builder getBuilder() { } private static String getJwt(ArangoDB arangoDB) { - ArangoSerialization serde = arangoDB.util(); + ArangoSerialization serde = arangoDB.getInternalSerialization(); Map reqBody = new HashMap<>(); reqBody.put("username", "root"); reqBody.put("password", "test"); diff --git a/src/test/java/com/arangodb/serde/CustomSerdeTest.java b/src/test/java/com/arangodb/serde/CustomSerdeTest.java index e5cd72078..790425c0a 100644 --- a/src/test/java/com/arangodb/serde/CustomSerdeTest.java +++ b/src/test/java/com/arangodb/serde/CustomSerdeTest.java @@ -51,7 +51,6 @@ import java.util.HashMap; import java.util.UUID; -import static com.arangodb.internal.util.ArangoSerializationFactory.Serializer.CUSTOM; import static com.fasterxml.jackson.databind.DeserializationFeature.USE_BIG_INTEGER_FOR_INTS; import static com.fasterxml.jackson.databind.SerializationFeature.WRITE_SINGLE_ELEM_ARRAYS_UNWRAPPED; @@ -143,7 +142,7 @@ void customPersonDeserializer() { void manualCustomPersonDeserializer() { Person person = new Person(); person.name = "Joe"; - ArangoSerialization serialization = arangoDB.util(CUSTOM); + ArangoSerialization serialization = arangoDB.getUserSerialization(); VPackSlice serializedPerson = serialization.serialize(person); Person deserializedPerson = serialization.deserialize(serializedPerson, Person.class); assertThat(deserializedPerson.name).isEqualTo(PERSON_DESERIALIZER_ADDED_PREFIX + PERSON_SERIALIZER_ADDED_PREFIX + person.name); @@ -237,7 +236,7 @@ void getDocument() { @Test void parseNullString() { - final String json = arangoDB.util(CUSTOM).deserialize(new VPackBuilder().add((String) null).slice(), String.class); + final String json = arangoDB.getUserSerialization().deserialize(new VPackBuilder().add((String) null).slice(), String.class); assertThat(json).isNull(); } diff --git a/src/test/java/com/arangodb/util/ArangoSerializationTest.java b/src/test/java/com/arangodb/util/ArangoSerializationTest.java index d17bd27c4..ebe7cec85 100644 --- a/src/test/java/com/arangodb/util/ArangoSerializationTest.java +++ b/src/test/java/com/arangodb/util/ArangoSerializationTest.java @@ -45,7 +45,7 @@ class ArangoSerializationTest { @BeforeAll static void setup() { final ArangoDB arangoDB = new ArangoDB.Builder().serializer(new ArangoJack()).build(); - util = arangoDB.util(); + util = arangoDB.getInternalSerialization(); } @Test From 77986cb473db3f128265cec9a0fc814ce96798a7 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Tue, 5 Jul 2022 14:27:24 +0200 Subject: [PATCH 023/254] removed old ArangoSerialization --- src/main/java/com/arangodb/ArangoDB.java | 7 +- .../com/arangodb/async/ArangoDBAsync.java | 7 +- .../internal/InternalArangoDBBuilder.java | 6 - .../internal/InternalArangoDatabase.java | 8 +- .../InternalArangoEdgeCollection.java | 4 +- .../InternalArangoVertexCollection.java | 4 +- .../internal/http/HttpConnection.java | 8 +- .../internal/util/ArangoSerializerImpl.java | 86 ------------- .../util/DefaultArangoSerialization.java | 10 +- .../java/com/arangodb/mapping/ArangoJack.java | 6 - .../arangodb/util/ArangoSerialization.java | 5 +- .../com/arangodb/util/ArangoSerializer.java | 121 ------------------ .../util/ArangoSerializationTest.java | 22 ++-- 13 files changed, 27 insertions(+), 267 deletions(-) delete mode 100644 src/main/java/com/arangodb/internal/util/ArangoSerializerImpl.java delete mode 100644 src/main/java/com/arangodb/util/ArangoSerializer.java diff --git a/src/main/java/com/arangodb/ArangoDB.java b/src/main/java/com/arangodb/ArangoDB.java index ec3265318..e6056cf9f 100644 --- a/src/main/java/com/arangodb/ArangoDB.java +++ b/src/main/java/com/arangodb/ArangoDB.java @@ -30,7 +30,6 @@ import com.arangodb.internal.net.*; import com.arangodb.internal.util.ArangoDeserializerImpl; import com.arangodb.internal.util.ArangoSerializationFactory; -import com.arangodb.internal.util.ArangoSerializerImpl; import com.arangodb.internal.util.DefaultArangoSerialization; import com.arangodb.internal.velocystream.VstCommunicationSync; import com.arangodb.internal.velocystream.VstConnectionFactorySync; @@ -43,7 +42,6 @@ import com.arangodb.util.ArangoCursorInitializer; import com.arangodb.util.ArangoDeserializer; import com.arangodb.util.ArangoSerialization; -import com.arangodb.util.ArangoSerializer; import com.arangodb.velocypack.VPack; import com.arangodb.velocypack.VPackParser; import com.arangodb.velocystream.Request; @@ -360,14 +358,11 @@ public synchronized ArangoDB build() { final VPack vpacker = vpackBuilder.serializeNullValues(false).build(); final VPack vpackerNull = vpackBuilder.serializeNullValues(true).build(); final VPackParser vpackParser = vpackParserBuilder.build(); - final ArangoSerializer serializerTemp = serializer != null ? serializer - : new ArangoSerializerImpl(vpacker, vpackerNull, vpackParser); final ArangoDeserializer deserializerTemp = deserializer != null ? deserializer : new ArangoDeserializerImpl(vpackerNull, vpackParser); final InternalSerde internalSerde = protocol == Protocol.HTTP_JSON ? InternalSerde.of(DataType.JSON) : InternalSerde.of(DataType.VPACK); - final DefaultArangoSerialization internal = new DefaultArangoSerialization(serializerTemp, - deserializerTemp, internalSerde); + final DefaultArangoSerialization internal = new DefaultArangoSerialization(deserializerTemp, internalSerde); final ArangoSerialization custom = customSerializer != null ? customSerializer : internal; final ArangoSerializationFactory util = new ArangoSerializationFactory(internal, custom); diff --git a/src/main/java/com/arangodb/async/ArangoDBAsync.java b/src/main/java/com/arangodb/async/ArangoDBAsync.java index 28dff5ee6..8075310b2 100644 --- a/src/main/java/com/arangodb/async/ArangoDBAsync.java +++ b/src/main/java/com/arangodb/async/ArangoDBAsync.java @@ -33,7 +33,6 @@ import com.arangodb.internal.net.HostResolver; import com.arangodb.internal.util.ArangoDeserializerImpl; import com.arangodb.internal.util.ArangoSerializationFactory; -import com.arangodb.internal.util.ArangoSerializerImpl; import com.arangodb.internal.util.DefaultArangoSerialization; import com.arangodb.internal.velocystream.VstCommunicationSync; import com.arangodb.internal.velocystream.VstConnectionFactorySync; @@ -45,7 +44,6 @@ import com.arangodb.serde.InternalSerde; import com.arangodb.util.ArangoDeserializer; import com.arangodb.util.ArangoSerialization; -import com.arangodb.util.ArangoSerializer; import com.arangodb.velocypack.*; import com.arangodb.velocystream.Request; import com.arangodb.velocystream.Response; @@ -521,13 +519,10 @@ public synchronized ArangoDBAsync build() { final VPack vpacker = vpackBuilder.serializeNullValues(false).build(); final VPack vpackerNull = vpackBuilder.serializeNullValues(true).build(); final VPackParser vpackParser = vpackParserBuilder.build(); - final ArangoSerializer serializerTemp = serializer != null ? serializer - : new ArangoSerializerImpl(vpacker, vpackerNull, vpackParser); final ArangoDeserializer deserializerTemp = deserializer != null ? deserializer : new ArangoDeserializerImpl(vpackerNull, vpackParser); final InternalSerde internalSerde = InternalSerde.of(DataType.VPACK); - final DefaultArangoSerialization internal = new DefaultArangoSerialization(serializerTemp, - deserializerTemp, internalSerde); + final DefaultArangoSerialization internal = new DefaultArangoSerialization(deserializerTemp, internalSerde); final ArangoSerialization custom = customSerializer != null ? customSerializer : internal; final ArangoSerializationFactory util = new ArangoSerializationFactory(internal, custom); diff --git a/src/main/java/com/arangodb/internal/InternalArangoDBBuilder.java b/src/main/java/com/arangodb/internal/InternalArangoDBBuilder.java index 6abc81bfa..07f741e5d 100644 --- a/src/main/java/com/arangodb/internal/InternalArangoDBBuilder.java +++ b/src/main/java/com/arangodb/internal/InternalArangoDBBuilder.java @@ -39,7 +39,6 @@ import com.arangodb.internal.velocypack.VPackDriverModule; import com.arangodb.util.ArangoDeserializer; import com.arangodb.util.ArangoSerialization; -import com.arangodb.util.ArangoSerializer; import com.arangodb.velocypack.VPack; import com.arangodb.velocypack.VPackParser; import org.apache.http.client.HttpRequestRetryHandler; @@ -96,7 +95,6 @@ public abstract class InternalArangoDBBuilder { protected Integer keepAliveInterval; protected final VPack.Builder vpackBuilder; protected final VPackParser.Builder vpackParserBuilder; - protected ArangoSerializer serializer; protected ArangoDeserializer deserializer; protected Boolean acquireHostList; protected Integer acquireHostListInterval; @@ -225,10 +223,6 @@ protected void setResponseQueueTimeSamples(final Integer responseQueueTimeSample this.responseQueueTimeSamples = responseQueueTimeSamples; } - protected void serializer(final ArangoSerializer serializer) { - this.serializer = serializer; - } - protected void deserializer(final ArangoDeserializer deserializer) { this.deserializer = deserializer; } diff --git a/src/main/java/com/arangodb/internal/InternalArangoDatabase.java b/src/main/java/com/arangodb/internal/InternalArangoDatabase.java index 294830a2e..422b4aba4 100644 --- a/src/main/java/com/arangodb/internal/InternalArangoDatabase.java +++ b/src/main/java/com/arangodb/internal/InternalArangoDatabase.java @@ -24,13 +24,11 @@ import com.arangodb.entity.*; import com.arangodb.entity.arangosearch.analyzer.SearchAnalyzer; import com.arangodb.internal.ArangoExecutor.ResponseDeserializer; -import com.arangodb.internal.util.ArangoSerializationFactory; import com.arangodb.internal.util.RequestUtils; import com.arangodb.model.*; import com.arangodb.model.arangosearch.AnalyzerDeleteOptions; import com.arangodb.model.arangosearch.ArangoSearchCreateOptions; import com.arangodb.model.arangosearch.ArangoSearchOptionsBuilder; -import com.arangodb.util.ArangoSerializer; import com.arangodb.velocypack.Type; import com.arangodb.velocypack.VPackSlice; import com.arangodb.velocystream.Request; @@ -169,7 +167,7 @@ protected Request queryRequest( final Request request = request(dbName, RequestType.POST, PATH_API_CURSOR) .setBody(getInternalSerialization().serialize(OptionsBuilder .build(opt, query, bindVars != null ? - getUserSerialization().serialize(bindVars, new ArangoSerializer.Options().serializeNullValues(true)) : + getUserSerialization().serialize(bindVars) : null))); if (opt.getAllowDirtyRead() == Boolean.TRUE) { RequestUtils.allowDirtyRead(request); @@ -224,9 +222,7 @@ protected Request explainQueryRequest( .setBody(getInternalSerialization().serialize(OptionsBuilder.build( opt, query, - bindVars != null ? getUserSerialization().serialize( - bindVars, - new ArangoSerializer.Options().serializeNullValues(true)) : null))); + bindVars != null ? getUserSerialization().serialize(bindVars) : null))); } protected Request parseQueryRequest(final String query) { diff --git a/src/main/java/com/arangodb/internal/InternalArangoEdgeCollection.java b/src/main/java/com/arangodb/internal/InternalArangoEdgeCollection.java index 6b6271c8b..0c84c3734 100644 --- a/src/main/java/com/arangodb/internal/InternalArangoEdgeCollection.java +++ b/src/main/java/com/arangodb/internal/InternalArangoEdgeCollection.java @@ -26,7 +26,6 @@ import com.arangodb.internal.util.DocumentUtil; import com.arangodb.internal.util.RequestUtils; import com.arangodb.model.*; -import com.arangodb.util.ArangoSerializer; import com.arangodb.velocypack.VPackSlice; import com.arangodb.velocystream.Request; import com.arangodb.velocystream.RequestType; @@ -133,8 +132,7 @@ protected Request updateEdgeRequest(final String key, final T value, final E request.putQueryParam(ArangoRequestParam.KEEP_NULL, params.getKeepNull()); request.putQueryParam(ArangoRequestParam.WAIT_FOR_SYNC, params.getWaitForSync()); request.putHeaderParam(ArangoRequestParam.IF_MATCH, params.getIfMatch()); - request.setBody( - getUserSerialization().serialize(value, new ArangoSerializer.Options().serializeNullValues(true))); + request.setBody(getUserSerialization().serialize(value)); return request; } diff --git a/src/main/java/com/arangodb/internal/InternalArangoVertexCollection.java b/src/main/java/com/arangodb/internal/InternalArangoVertexCollection.java index 17ef9beb7..5fabbe2b1 100644 --- a/src/main/java/com/arangodb/internal/InternalArangoVertexCollection.java +++ b/src/main/java/com/arangodb/internal/InternalArangoVertexCollection.java @@ -27,7 +27,6 @@ import com.arangodb.internal.util.RequestUtils; import com.arangodb.model.*; import com.arangodb.serde.SerdeUtils; -import com.arangodb.util.ArangoSerializer; import com.arangodb.velocypack.VPackSlice; import com.arangodb.velocystream.Request; import com.arangodb.velocystream.RequestType; @@ -145,8 +144,7 @@ protected Request updateVertexRequest(final String key, final T value, final request.putQueryParam(ArangoRequestParam.KEEP_NULL, params.getKeepNull()); request.putQueryParam(ArangoRequestParam.WAIT_FOR_SYNC, params.getWaitForSync()); request.putHeaderParam(ArangoRequestParam.IF_MATCH, params.getIfMatch()); - request.setBody( - getUserSerialization().serialize(value, new ArangoSerializer.Options().serializeNullValues(true))); + request.setBody(getUserSerialization().serialize(value)); return request; } diff --git a/src/main/java/com/arangodb/internal/http/HttpConnection.java b/src/main/java/com/arangodb/internal/http/HttpConnection.java index c74af9b2a..e10964990 100644 --- a/src/main/java/com/arangodb/internal/http/HttpConnection.java +++ b/src/main/java/com/arangodb/internal/http/HttpConnection.java @@ -29,7 +29,7 @@ import com.arangodb.internal.util.ResponseUtils; import com.arangodb.serde.DataType; import com.arangodb.util.ArangoSerialization; -import com.arangodb.util.ArangoSerializer.Options; +import com.arangodb.velocypack.VPackParser; import com.arangodb.velocypack.VPackSlice; import com.arangodb.velocystream.Request; import com.arangodb.velocystream.Response; @@ -356,6 +356,9 @@ private static void addHeader(final Request request, final HttpRequestBase httpR } } + // FIXME: remove + private final VPackParser parser = new VPackParser.Builder().build(); + public Response buildResponse(final CloseableHttpResponse httpResponse) throws UnsupportedOperationException, IOException { final Response response = new Response(dataType); @@ -370,8 +373,7 @@ public Response buildResponse(final CloseableHttpResponse httpResponse) } else { final String content = IOUtils.toString(entity.getContent()); if (!content.isEmpty()) { - response.setBody( - util.serialize(content, new Options().stringAsJson(true).serializeNullValues(true))); + response.setBody(parser.fromJson(content, true)); } } } diff --git a/src/main/java/com/arangodb/internal/util/ArangoSerializerImpl.java b/src/main/java/com/arangodb/internal/util/ArangoSerializerImpl.java deleted file mode 100644 index 7561622ce..000000000 --- a/src/main/java/com/arangodb/internal/util/ArangoSerializerImpl.java +++ /dev/null @@ -1,86 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.internal.util; - -import com.arangodb.ArangoDBException; -import com.arangodb.util.ArangoSerializer; -import com.arangodb.velocypack.VPack; -import com.arangodb.velocypack.VPack.SerializeOptions; -import com.arangodb.velocypack.VPackParser; -import com.arangodb.velocypack.VPackSlice; -import com.arangodb.velocypack.exception.VPackException; - -import java.util.Iterator; - -/** - * @author Mark Vollmary - */ -public class ArangoSerializerImpl implements ArangoSerializer { - - private final VPack vpacker; - private final VPack vpackerNull; - private final VPackParser vpackParser; - - public ArangoSerializerImpl(final VPack vpacker, final VPack vpackerNull, final VPackParser vpackParser) { - super(); - this.vpacker = vpacker; - this.vpackerNull = vpackerNull; - this.vpackParser = vpackParser; - } - - @Override - public VPackSlice serialize(final Object entity) throws ArangoDBException { - return serialize(entity, new ArangoSerializer.Options()); - } - - @SuppressWarnings("unchecked") - @Override - public VPackSlice serialize(final Object entity, final Options options) throws ArangoDBException { - if (options.getType() == null) { - options.type(entity.getClass()); - } - try { - final VPackSlice vpack; - final Class type = entity.getClass(); - final boolean serializeNullValues = options.isSerializeNullValues(); - if (String.class.isAssignableFrom(type)) { - vpack = vpackParser.fromJson((String) entity, serializeNullValues); - } else if (options.isStringAsJson() && Iterable.class.isAssignableFrom(type)) { - final Iterator iterator = ((Iterable) entity).iterator(); - if (iterator.hasNext() && String.class.isAssignableFrom(iterator.next().getClass())) { - vpack = vpackParser.fromJson((Iterable) entity, serializeNullValues); - } else { - final VPack vp = serializeNullValues ? vpackerNull : vpacker; - vpack = vp.serialize(entity, - new SerializeOptions().type(options.getType()).additionalFields(options.getAdditionalFields())); - } - } else { - final VPack vp = serializeNullValues ? vpackerNull : vpacker; - vpack = vp.serialize(entity, - new SerializeOptions().type(options.getType()).additionalFields(options.getAdditionalFields())); - } - return vpack; - } catch (final VPackException e) { - throw new ArangoDBException(e); - } - } - -} diff --git a/src/main/java/com/arangodb/internal/util/DefaultArangoSerialization.java b/src/main/java/com/arangodb/internal/util/DefaultArangoSerialization.java index 166f36644..fc258f2f3 100644 --- a/src/main/java/com/arangodb/internal/util/DefaultArangoSerialization.java +++ b/src/main/java/com/arangodb/internal/util/DefaultArangoSerialization.java @@ -25,7 +25,6 @@ import com.arangodb.serde.InternalSerde; import com.arangodb.util.ArangoDeserializer; import com.arangodb.util.ArangoSerialization; -import com.arangodb.util.ArangoSerializer; import com.arangodb.velocypack.VPackParser; import com.arangodb.velocypack.VPackSlice; @@ -36,13 +35,11 @@ */ public class DefaultArangoSerialization implements ArangoSerialization { - private final ArangoSerializer serializer; private final ArangoDeserializer deserializer; private final InternalSerde serde; - public DefaultArangoSerialization(final ArangoSerializer serializer, final ArangoDeserializer deserializer, final InternalSerde serde) { + public DefaultArangoSerialization(final ArangoDeserializer deserializer, final InternalSerde serde) { super(); - this.serializer = serializer; this.deserializer = deserializer; this.serde = serde; } @@ -62,11 +59,6 @@ public VPackSlice serialize(final Object entity) throws ArangoDBException { } } - @Override - public VPackSlice serialize(final Object entity, final Options options) throws ArangoDBException { - return serializer.serialize(entity, options); - } - @Override public T deserialize(final VPackSlice vpack, final Type type) throws ArangoDBException { return deserializer.deserialize(vpack, type); diff --git a/src/main/java/com/arangodb/mapping/ArangoJack.java b/src/main/java/com/arangodb/mapping/ArangoJack.java index e8c318232..d9c2b78a3 100644 --- a/src/main/java/com/arangodb/mapping/ArangoJack.java +++ b/src/main/java/com/arangodb/mapping/ArangoJack.java @@ -130,12 +130,6 @@ public VPackSlice serialize(final Object entity) throws ArangoDBException { } - @SuppressWarnings("unchecked") - @Override - public VPackSlice serialize(final Object entity, final Options options) throws ArangoDBException { - return serialize(entity); - } - @SuppressWarnings("unchecked") @Override public T deserialize(final VPackSlice vpack, final Type type) throws ArangoDBException { diff --git a/src/main/java/com/arangodb/util/ArangoSerialization.java b/src/main/java/com/arangodb/util/ArangoSerialization.java index c6f710171..4d271d753 100644 --- a/src/main/java/com/arangodb/util/ArangoSerialization.java +++ b/src/main/java/com/arangodb/util/ArangoSerialization.java @@ -20,8 +20,11 @@ package com.arangodb.util; +import com.arangodb.velocypack.VPackSlice; + /** * @author Mark Vollmary */ -public interface ArangoSerialization extends ArangoSerializer, ArangoDeserializer { +public interface ArangoSerialization extends ArangoDeserializer { + VPackSlice serialize(final Object entity); } diff --git a/src/main/java/com/arangodb/util/ArangoSerializer.java b/src/main/java/com/arangodb/util/ArangoSerializer.java deleted file mode 100644 index ee327d234..000000000 --- a/src/main/java/com/arangodb/util/ArangoSerializer.java +++ /dev/null @@ -1,121 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.util; - -import com.arangodb.ArangoDBException; -import com.arangodb.velocypack.VPackSlice; - -import java.lang.reflect.Type; -import java.util.Collections; -import java.util.Map; - -/** - * @author Mark Vollmary - */ -public interface ArangoSerializer { - - class Options { - private Type type; - private boolean serializeNullValues; - private Map additionalFields; - private boolean stringAsJson; - - public Options() { - super(); - serializeNullValues = false; - stringAsJson = false; - additionalFields = Collections.emptyMap(); - } - - /** - * @param type The source type of the Object. - * @return options - */ - public Options type(final Type type) { - this.type = type; - return this; - } - - /** - * @param serializeNullValues Whether or not null values should be excluded from serialization. - * @return options - */ - public Options serializeNullValues(final boolean serializeNullValues) { - this.serializeNullValues = serializeNullValues; - return this; - } - - /** - * @param additionalFields Additional Key/Value pairs to include in the created VelocyPack. - * @return options - */ - public Options additionalFields(final Map additionalFields) { - this.additionalFields = additionalFields; - return this; - } - - /** - * @param stringAsJson Wheter or not String should be interpreted as json - * @return options - */ - public Options stringAsJson(final boolean stringAsJson) { - this.stringAsJson = stringAsJson; - return this; - } - - public Type getType() { - return type; - } - - public boolean isSerializeNullValues() { - return serializeNullValues; - } - - public Map getAdditionalFields() { - return additionalFields; - } - - public boolean isStringAsJson() { - return stringAsJson; - } - - } - - /** - * Serialize a given Object to VelocyPack - * - * @param entity The Object to serialize. If it is from type String, it will be handled as a JSON. - * @return The serialized VelocyPack - * @throws ArangoDBException - */ - VPackSlice serialize(final Object entity) throws ArangoDBException; - - /** - * Serialize a given Object to VelocyPack - * - * @param entity The Object to serialize. If it is from type String, it will be handled as a JSON. - * @param options Additional options - * @return the serialized VelocyPack - * @throws ArangoDBException - */ - VPackSlice serialize(final Object entity, final Options options) throws ArangoDBException; - -} diff --git a/src/test/java/com/arangodb/util/ArangoSerializationTest.java b/src/test/java/com/arangodb/util/ArangoSerializationTest.java index ebe7cec85..26a5a8494 100644 --- a/src/test/java/com/arangodb/util/ArangoSerializationTest.java +++ b/src/test/java/com/arangodb/util/ArangoSerializationTest.java @@ -40,18 +40,20 @@ */ class ArangoSerializationTest { - private static ArangoSerialization util; + private static ArangoSerialization internalSer; + private static ArangoSerialization userSer; @BeforeAll static void setup() { final ArangoDB arangoDB = new ArangoDB.Builder().serializer(new ArangoJack()).build(); - util = arangoDB.getInternalSerialization(); + internalSer = arangoDB.getInternalSerialization(); + userSer = arangoDB.getUserSerialization(); } @Test void deserialize() { final VPackBuilder builder = new VPackBuilder().add(ValueType.OBJECT).add("foo", "bar").close(); - final BaseDocument doc = util.deserialize(builder.slice(), BaseDocument.class); + final BaseDocument doc = internalSer.deserialize(builder.slice(), BaseDocument.class); assertThat(doc.getAttribute("foo")).isEqualTo("bar"); } @@ -59,7 +61,7 @@ void deserialize() { void serialize() { final BaseDocument entity = new BaseDocument(); entity.addAttribute("foo", "bar"); - final VPackSlice vpack = util.serialize(entity); + final VPackSlice vpack = internalSer.serialize(entity); assertThat(vpack.get("foo").isString()).isTrue(); assertThat(vpack.get("foo").getAsString()).isEqualTo("bar"); } @@ -68,7 +70,7 @@ void serialize() { void serializeNullValues() { final BaseDocument entity = new BaseDocument(); entity.addAttribute("foo", null); - final VPackSlice vpack = util.serialize(entity, new ArangoSerializer.Options().serializeNullValues(true)); + final VPackSlice vpack = userSer.serialize(entity); assertThat(vpack.get("foo").isNull()).isTrue(); } @@ -76,7 +78,7 @@ void serializeNullValues() { void skipSerializeNullValues() { final BaseDocument entity = new BaseDocument(); entity.addAttribute("bar", null); - final VPackSlice vpack = util.serialize(entity); + final VPackSlice vpack = internalSer.serialize(entity); assertThat(vpack.get("bar").isNone()).isTrue(); } @@ -86,9 +88,7 @@ void serializeType() { list.add(new BaseDocument()); list.add(new BaseDocument()); - final VPackSlice vpack = util.serialize(list, - new ArangoSerializer.Options().type(new Type>() { - }.getType())); + final VPackSlice vpack = internalSer.serialize(list); assertThat(vpack.isArray()).isTrue(); assertThat(vpack.getLength()).isEqualTo(list.size()); } @@ -97,13 +97,13 @@ void serializeType() { void parseJsonIncludeNull() { final Map entity = new HashMap<>(); entity.put("value", new String[]{"test", null}); - final String json = util.deserialize(util.serialize(entity, new ArangoSerializer.Options()), String.class); + final String json = internalSer.deserialize(internalSer.serialize(entity), String.class); assertThat(json).isEqualTo("{\"value\":[\"test\",null]}"); } @Test void parseNullString() { - final String json = util.deserialize(new VPackBuilder().add((String) null).slice(), String.class); + final String json = internalSer.deserialize(new VPackBuilder().add((String) null).slice(), String.class); assertThat(json).isNull(); } From f2cb928daeaf488ce1c5731d38f0990de080d4ae Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Wed, 6 Jul 2022 14:23:14 +0200 Subject: [PATCH 024/254] refctored communication API using byte[] instead of VPackSlice for outgoing buffer --- .../internal/InternalArangoCollection.java | 10 ++++----- .../internal/InternalArangoDatabase.java | 6 ++--- .../InternalArangoVertexCollection.java | 2 +- .../arangodb/internal/http/CURLLogger.java | 2 +- .../internal/http/HttpConnection.java | 18 +++------------ .../util/DefaultArangoSerialization.java | 21 ++++++------------ .../velocystream/internal/Message.java | 6 ++--- .../velocystream/internal/VstConnection.java | 7 +++--- .../java/com/arangodb/mapping/ArangoJack.java | 22 ++++++------------- .../java/com/arangodb/serde/ArangoSerde.java | 2 +- .../arangodb/util/ArangoSerialization.java | 5 ++--- .../com/arangodb/velocystream/Request.java | 7 +++--- src/test/java/com/arangodb/BaseJunit5.java | 3 ++- .../annotations/ArangoAnnotationsTest.java | 10 ++++----- .../com/arangodb/serde/CustomSerdeTest.java | 3 +-- .../util/ArangoSerializationTest.java | 10 ++++----- 16 files changed, 53 insertions(+), 81 deletions(-) diff --git a/src/main/java/com/arangodb/internal/InternalArangoCollection.java b/src/main/java/com/arangodb/internal/InternalArangoCollection.java index 8d9194dc2..298772824 100644 --- a/src/main/java/com/arangodb/internal/InternalArangoCollection.java +++ b/src/main/java/com/arangodb/internal/InternalArangoCollection.java @@ -91,7 +91,7 @@ protected Request insertDocumentRequest(final T value, final DocumentCreateO request.putQueryParam(MERGE_OBJECTS, params.getMergeObjects()); request.putHeaderParam(TRANSACTION_ID, params.getStreamTransactionId()); - VPackSlice body; + byte[] body; if (value instanceof String) { body = getInternalSerialization().serialize(SerdeUtils.INSTANCE.parseJson((String) value)); } else { @@ -136,7 +136,7 @@ protected Request insertDocumentsRequest(final Collection values, final D request.putQueryParam(MERGE_OBJECTS, params.getMergeObjects()); request.putHeaderParam(TRANSACTION_ID, params.getStreamTransactionId()); - VPackSlice body = isStringCollection(values) ? getInternalSerialization().serialize(stringCollectionToJsonArray((Collection) values)) + byte[] body = isStringCollection(values) ? getInternalSerialization().serialize(stringCollectionToJsonArray((Collection) values)) : getUserSerialization().serialize(values); request.setBody(body); return request; @@ -191,7 +191,7 @@ protected Request importDocumentsRequest(final String values, final DocumentImpo } protected Request importDocumentsRequest(final Collection values, final DocumentImportOptions options) { - VPackSlice body = isStringCollection(values) ? getInternalSerialization().serialize(stringCollectionToJsonArray((Collection) values)) + byte[] body = isStringCollection(values) ? getInternalSerialization().serialize(stringCollectionToJsonArray((Collection) values)) : getUserSerialization().serialize(values); return importDocumentsRequest(options).putQueryParam("type", ImportType.list).setBody(body); } @@ -306,7 +306,7 @@ protected Request replaceDocumentsRequest(final Collection values, final request.putQueryParam(RETURN_OLD, params.getReturnOld()); request.putQueryParam(SILENT, params.getSilent()); - VPackSlice body = isStringCollection(values) ? getInternalSerialization().serialize(stringCollectionToJsonArray((Collection) values)) + byte[] body = isStringCollection(values) ? getInternalSerialization().serialize(stringCollectionToJsonArray((Collection) values)) : getUserSerialization().serialize(values); request.setBody(body); return request; @@ -408,7 +408,7 @@ protected Request updateDocumentsRequest(final Collection values, final D request.putQueryParam(RETURN_OLD, params.getReturnOld()); request.putQueryParam(SILENT, params.getSilent()); - VPackSlice body = isStringCollection(values) ? getInternalSerialization().serialize(stringCollectionToJsonArray((Collection) values)) + byte[] body = isStringCollection(values) ? getInternalSerialization().serialize(stringCollectionToJsonArray((Collection) values)) : getUserSerialization().serialize(values); request.setBody(body); return request; diff --git a/src/main/java/com/arangodb/internal/InternalArangoDatabase.java b/src/main/java/com/arangodb/internal/InternalArangoDatabase.java index 422b4aba4..f0ecd708e 100644 --- a/src/main/java/com/arangodb/internal/InternalArangoDatabase.java +++ b/src/main/java/com/arangodb/internal/InternalArangoDatabase.java @@ -98,7 +98,7 @@ protected Request getEngineRequest() { protected Request createCollectionRequest(final String name, final CollectionCreateOptions options) { - VPackSlice body = getInternalSerialization() + byte[] body = getInternalSerialization() .serialize(OptionsBuilder.build(options != null ? options : new CollectionCreateOptions(), name)); return request(dbName, RequestType.POST, InternalArangoCollection.PATH_API_COLLECTION).setBody(body); @@ -167,7 +167,7 @@ protected Request queryRequest( final Request request = request(dbName, RequestType.POST, PATH_API_CURSOR) .setBody(getInternalSerialization().serialize(OptionsBuilder .build(opt, query, bindVars != null ? - getUserSerialization().serialize(bindVars) : + new VPackSlice(getUserSerialization().serialize(bindVars)) : null))); if (opt.getAllowDirtyRead() == Boolean.TRUE) { RequestUtils.allowDirtyRead(request); @@ -222,7 +222,7 @@ protected Request explainQueryRequest( .setBody(getInternalSerialization().serialize(OptionsBuilder.build( opt, query, - bindVars != null ? getUserSerialization().serialize(bindVars) : null))); + bindVars != null ? new VPackSlice(getUserSerialization().serialize(bindVars)) : null))); } protected Request parseQueryRequest(final String query) { diff --git a/src/main/java/com/arangodb/internal/InternalArangoVertexCollection.java b/src/main/java/com/arangodb/internal/InternalArangoVertexCollection.java index 5fabbe2b1..7bc503289 100644 --- a/src/main/java/com/arangodb/internal/InternalArangoVertexCollection.java +++ b/src/main/java/com/arangodb/internal/InternalArangoVertexCollection.java @@ -73,7 +73,7 @@ protected Request insertVertexRequest(final T value, final VertexCreateOptio request.putHeaderParam(TRANSACTION_ID, params.getStreamTransactionId()); request.putQueryParam(ArangoRequestParam.WAIT_FOR_SYNC, params.getWaitForSync()); - VPackSlice body; + byte[] body; if (value instanceof String) { body = getInternalSerialization().serialize(SerdeUtils.INSTANCE.parseJson((String) value)); } else { diff --git a/src/main/java/com/arangodb/internal/http/CURLLogger.java b/src/main/java/com/arangodb/internal/http/CURLLogger.java index 941769fe4..4c6121330 100644 --- a/src/main/java/com/arangodb/internal/http/CURLLogger.java +++ b/src/main/java/com/arangodb/internal/http/CURLLogger.java @@ -73,7 +73,7 @@ public static void log( buffer.append(" '").append(url).append("'"); if (includeBody) { buffer.append("\n"); - buffer.append((String) util.deserialize(request.getBody(), String.class)); + buffer.append(util.toJsonString(request.getBody())); buffer.append("\n"); buffer.append("___EOB___"); } diff --git a/src/main/java/com/arangodb/internal/http/HttpConnection.java b/src/main/java/com/arangodb/internal/http/HttpConnection.java index e10964990..eb1ea7d74 100644 --- a/src/main/java/com/arangodb/internal/http/HttpConnection.java +++ b/src/main/java/com/arangodb/internal/http/HttpConnection.java @@ -48,7 +48,6 @@ import org.apache.http.conn.ssl.SSLConnectionSocketFactory; import org.apache.http.entity.ByteArrayEntity; import org.apache.http.entity.ContentType; -import org.apache.http.entity.StringEntity; import org.apache.http.impl.auth.BasicScheme; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.DefaultHttpRequestRetryHandler; @@ -65,7 +64,6 @@ import javax.net.ssl.SSLContext; import java.io.IOException; import java.util.ArrayList; -import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.Map.Entry; @@ -83,9 +81,6 @@ public class HttpConnection implements Connection { "utf-8"); private static final ContentType CONTENT_TYPE_VPACK = ContentType.create("application/x-velocypack"); - // max safe UTF-8 json string length, so that it can be converted to byte array - private static final int MAX_JSON_LENGTH = (Integer.MAX_VALUE - 8) / 4; - public static class Builder { private String user; private String password; @@ -290,19 +285,12 @@ private HttpRequestBase buildHttpRequestBase(final Request request, final String } private HttpRequestBase requestWithBody(final HttpEntityEnclosingRequestBase httpRequest, final Request request) { - final VPackSlice body = request.getBody(); + final byte[] body = request.getBody(); if (body != null) { if (contentType == Protocol.HTTP_VPACK) { - httpRequest.setEntity(new ByteArrayEntity( - Arrays.copyOfRange(body.getBuffer(), body.getStart(), body.getStart() + body.getByteSize()), - CONTENT_TYPE_VPACK)); + httpRequest.setEntity(new ByteArrayEntity(body, CONTENT_TYPE_VPACK)); } else { - String json = body.toString(); - if (json.length() > MAX_JSON_LENGTH) { - LOGGER.warn("Json string length is greater than safe threshold (" + MAX_JSON_LENGTH + "). " + - "This could cause memory allocation errors."); - } - httpRequest.setEntity(new StringEntity(json, CONTENT_TYPE_APPLICATION_JSON_UTF8)); + httpRequest.setEntity(new ByteArrayEntity(body, CONTENT_TYPE_APPLICATION_JSON_UTF8)); } } return httpRequest; diff --git a/src/main/java/com/arangodb/internal/util/DefaultArangoSerialization.java b/src/main/java/com/arangodb/internal/util/DefaultArangoSerialization.java index fc258f2f3..c858c4bb7 100644 --- a/src/main/java/com/arangodb/internal/util/DefaultArangoSerialization.java +++ b/src/main/java/com/arangodb/internal/util/DefaultArangoSerialization.java @@ -21,11 +21,9 @@ package com.arangodb.internal.util; import com.arangodb.ArangoDBException; -import com.arangodb.serde.DataType; import com.arangodb.serde.InternalSerde; import com.arangodb.util.ArangoDeserializer; import com.arangodb.util.ArangoSerialization; -import com.arangodb.velocypack.VPackParser; import com.arangodb.velocypack.VPackSlice; import java.lang.reflect.Type; @@ -45,18 +43,13 @@ public DefaultArangoSerialization(final ArangoDeserializer deserializer, final I } @Override - public VPackSlice serialize(final Object entity) throws ArangoDBException { - DataType dataType = serde.getDataType(); - switch (dataType) { - case JSON: - String json = new String(serde.serialize(entity)); - VPackParser parser = new VPackParser.Builder().build(); - return parser.fromJson(json, true); - case VPACK: - return new VPackSlice(serde.serialize(entity)); - default: - throw new IllegalStateException("Unexpected value: " + dataType); - } + public byte[] serialize(final Object entity) throws ArangoDBException { + return serde.serialize(entity); + } + + @Override + public String toJsonString(byte[] content) { + return serde.toJsonString(content); } @Override diff --git a/src/main/java/com/arangodb/internal/velocystream/internal/Message.java b/src/main/java/com/arangodb/internal/velocystream/internal/Message.java index 6ad13259c..5a2e74724 100644 --- a/src/main/java/com/arangodb/internal/velocystream/internal/Message.java +++ b/src/main/java/com/arangodb/internal/velocystream/internal/Message.java @@ -45,11 +45,11 @@ public Message(final long id, final byte[] chunkBuffer) throws BufferUnderflowEx } } - public Message(final long id, final VPackSlice head, final VPackSlice body) { + public Message(final long id, final byte[] head, final byte[] body) { super(); this.id = id; - this.head = head; - this.body = body; + this.head = new VPackSlice(head); + this.body = body != null ? new VPackSlice(body) : null; } public long getId() { diff --git a/src/main/java/com/arangodb/internal/velocystream/internal/VstConnection.java b/src/main/java/com/arangodb/internal/velocystream/internal/VstConnection.java index 266820773..142660a8b 100644 --- a/src/main/java/com/arangodb/internal/velocystream/internal/VstConnection.java +++ b/src/main/java/com/arangodb/internal/velocystream/internal/VstConnection.java @@ -87,7 +87,7 @@ public abstract class VstConnection implements Connection { private final String connectionName; - private final VPackSlice keepAliveRequest = new VPackBuilder() + private final byte[] keepAliveRequest = new VPackBuilder() .add(ValueType.ARRAY) .add(1) .add(1) @@ -99,7 +99,8 @@ public abstract class VstConnection implements Connection { .add(ValueType.OBJECT) .close() .close() - .slice(); + .slice() + .toByteArray(); protected VstConnection(final HostDescription host, final Integer timeout, @@ -130,7 +131,7 @@ protected T sendKeepAlive() { } return write(message, Collections.singleton(new Chunk( id, 0, 1, -1, - 0, keepAliveRequest.getByteSize() + 0, keepAliveRequest.length ))); } diff --git a/src/main/java/com/arangodb/mapping/ArangoJack.java b/src/main/java/com/arangodb/mapping/ArangoJack.java index d9c2b78a3..11dbb9739 100644 --- a/src/main/java/com/arangodb/mapping/ArangoJack.java +++ b/src/main/java/com/arangodb/mapping/ArangoJack.java @@ -28,7 +28,6 @@ import com.arangodb.serde.DataType; import com.arangodb.serde.JacksonSerde; import com.arangodb.util.ArangoSerialization; -import com.arangodb.velocypack.VPackParser; import com.arangodb.velocypack.VPackSlice; import com.fasterxml.jackson.annotation.JsonAutoDetect; import com.fasterxml.jackson.annotation.JsonInclude.Include; @@ -55,7 +54,6 @@ public interface ConfigureFunction { private final ObjectMapper vpackMapper; private final ObjectMapper vpackMapperNull; private final ObjectMapper jsonMapper; - private final VPackParser vpackParser; private final JacksonSerde serde; @@ -103,7 +101,6 @@ public ArangoJack(final VPackMapper mapper) { vpackMapper = mapper.copy().setSerializationInclusion(Include.NON_NULL); vpackMapperNull = mapper.copy().setSerializationInclusion(Include.ALWAYS); jsonMapper = new ObjectMapper().setSerializationInclusion(Include.NON_NULL); - vpackParser = new VPackParser.Builder().build(); serde = JacksonSerde.of(DataType.VPACK, configureDefaultMapper(new VPackMapper())); } @@ -115,19 +112,14 @@ public void configure(final ArangoJack.ConfigureFunction f) { } @Override - public VPackSlice serialize(final Object entity) throws ArangoDBException { - DataType dataType = serde.getDataType(); - switch (dataType) { - case JSON: - String json = new String(serde.serialize(entity)); - VPackParser parser = new VPackParser.Builder().build(); - return parser.fromJson(json, true); - case VPACK: - return new VPackSlice(serde.serialize(entity)); - default: - throw new IllegalStateException("Unexpected value: " + dataType); - } + public byte[] serialize(final Object entity) throws ArangoDBException { + return serde.serialize(entity); + } + // FIXME: toJsonString should only be required for internal serialization + @Override + public String toJsonString(byte[] content) { + throw new UnsupportedOperationException(); } @SuppressWarnings("unchecked") diff --git a/src/main/java/com/arangodb/serde/ArangoSerde.java b/src/main/java/com/arangodb/serde/ArangoSerde.java index 3b310548c..ce56485d2 100644 --- a/src/main/java/com/arangodb/serde/ArangoSerde.java +++ b/src/main/java/com/arangodb/serde/ArangoSerde.java @@ -16,7 +16,7 @@ * This interface should not be directly implemented as an adapter to Jackson Databind. A more performant way to provide * custom implementations based on Jackson Databind is by extending {@link JacksonSerde}, which exposes additional * methods based on Jackson's types. - * Furthermore, existing implementations {@link JacksonSerde} can be instantiated providing a custom configured Jackson + * Furthermore, existing {@link JacksonSerde} implementations can be instantiated providing a custom configured Jackson * ObjectMapper, see {@link JacksonSerde#of(DataType, ObjectMapper)}. */ public interface ArangoSerde { diff --git a/src/main/java/com/arangodb/util/ArangoSerialization.java b/src/main/java/com/arangodb/util/ArangoSerialization.java index 4d271d753..6fee87692 100644 --- a/src/main/java/com/arangodb/util/ArangoSerialization.java +++ b/src/main/java/com/arangodb/util/ArangoSerialization.java @@ -20,11 +20,10 @@ package com.arangodb.util; -import com.arangodb.velocypack.VPackSlice; - /** * @author Mark Vollmary */ public interface ArangoSerialization extends ArangoDeserializer { - VPackSlice serialize(final Object entity); + byte[] serialize(final Object entity); + String toJsonString(byte[] content); } diff --git a/src/main/java/com/arangodb/velocystream/Request.java b/src/main/java/com/arangodb/velocystream/Request.java index cfa9eead7..872b01cf3 100644 --- a/src/main/java/com/arangodb/velocystream/Request.java +++ b/src/main/java/com/arangodb/velocystream/Request.java @@ -21,7 +21,6 @@ package com.arangodb.velocystream; import com.arangodb.DbName; -import com.arangodb.velocypack.VPackSlice; import com.arangodb.velocypack.annotations.Expose; import java.util.HashMap; @@ -40,7 +39,7 @@ public class Request { private final Map queryParam; private final Map headerParam; @Expose(serialize = false) - private VPackSlice body; + private byte[] body; public Request(final DbName dbName, final RequestType requestType, final String path) { super(); @@ -104,11 +103,11 @@ public Request putHeaderParam(final String key, final String value) { return this; } - public VPackSlice getBody() { + public byte[] getBody() { return body; } - public Request setBody(final VPackSlice body) { + public Request setBody(final byte[] body) { this.body = body; return this; } diff --git a/src/test/java/com/arangodb/BaseJunit5.java b/src/test/java/com/arangodb/BaseJunit5.java index f6e9390ee..11ee86790 100644 --- a/src/test/java/com/arangodb/BaseJunit5.java +++ b/src/test/java/com/arangodb/BaseJunit5.java @@ -22,7 +22,8 @@ class BaseJunit5 { private static final List adbs = Arrays.stream(Protocol.values()) .map(p -> new ArangoDB.Builder() .useProtocol(p) - .serializer(new ArangoJack()) + // FIXME +// .serializer(new ArangoJack()) .build()) .collect(Collectors.toList()); diff --git a/src/test/java/com/arangodb/mapping/annotations/ArangoAnnotationsTest.java b/src/test/java/com/arangodb/mapping/annotations/ArangoAnnotationsTest.java index 0aa1ace84..482d1287b 100644 --- a/src/test/java/com/arangodb/mapping/annotations/ArangoAnnotationsTest.java +++ b/src/test/java/com/arangodb/mapping/annotations/ArangoAnnotationsTest.java @@ -45,7 +45,7 @@ void documentFieldAnnotations() { e.setFrom("From"); e.setTo("To"); - VPackSlice slice = mapper.serialize(e); + VPackSlice slice = new VPackSlice(mapper.serialize(e)); System.out.println(slice); Map deserialized = mapper.deserialize(slice, Object.class); assertThat(deserialized) @@ -67,7 +67,7 @@ void serializedName() { e.setB("B"); e.setC("C"); - VPackSlice slice = mapper.serialize(e); + VPackSlice slice = new VPackSlice(mapper.serialize(e)); System.out.println(slice); Map deserialized = mapper.deserialize(slice, Object.class); assertThat(deserialized) @@ -87,7 +87,7 @@ void serializedNameParameter() { e.put(SerializedNameParameterEntity.SERIALIZED_NAME_B, "B"); e.put(SerializedNameParameterEntity.SERIALIZED_NAME_C, "C"); - VPackSlice slice = mapper.serialize(e); + VPackSlice slice = new VPackSlice(mapper.serialize(e)); SerializedNameParameterEntity deserializedEntity = mapper .deserialize(slice, SerializedNameParameterEntity.class); assertThat(deserializedEntity).isEqualTo(new SerializedNameParameterEntity("A", "B", "C")); @@ -101,7 +101,7 @@ void expose() { e.setWriteOnly("writeOnly"); e.setIgnored("ignored"); - VPackSlice serializedEntity = mapper.serialize(e); + VPackSlice serializedEntity = new VPackSlice(mapper.serialize(e)); Map deserializedEntity = mapper.deserialize(serializedEntity, Object.class); assertThat(deserializedEntity) .containsEntry("readWrite", "readWrite") @@ -114,7 +114,7 @@ void expose() { map.put("writeOnly", "writeOnly"); map.put("ignored", "ignored"); - VPackSlice serializedMap = mapper.serialize(map); + VPackSlice serializedMap = new VPackSlice(mapper.serialize(map)); ExposeEntity deserializedMap = mapper.deserialize(serializedMap, ExposeEntity.class); assertThat(deserializedMap.getIgnored()).isNull(); assertThat(deserializedMap.getReadOnly()).isNull(); diff --git a/src/test/java/com/arangodb/serde/CustomSerdeTest.java b/src/test/java/com/arangodb/serde/CustomSerdeTest.java index 790425c0a..e703ecae4 100644 --- a/src/test/java/com/arangodb/serde/CustomSerdeTest.java +++ b/src/test/java/com/arangodb/serde/CustomSerdeTest.java @@ -26,7 +26,6 @@ import com.arangodb.ArangoDatabase; import com.arangodb.DbName; import com.arangodb.entity.BaseDocument; -import com.arangodb.jackson.dataformat.velocypack.VPackMapper; import com.arangodb.mapping.ArangoJack; import com.arangodb.model.DocumentCreateOptions; import com.arangodb.util.ArangoSerialization; @@ -143,7 +142,7 @@ void manualCustomPersonDeserializer() { Person person = new Person(); person.name = "Joe"; ArangoSerialization serialization = arangoDB.getUserSerialization(); - VPackSlice serializedPerson = serialization.serialize(person); + VPackSlice serializedPerson = new VPackSlice(serialization.serialize(person)); Person deserializedPerson = serialization.deserialize(serializedPerson, Person.class); assertThat(deserializedPerson.name).isEqualTo(PERSON_DESERIALIZER_ADDED_PREFIX + PERSON_SERIALIZER_ADDED_PREFIX + person.name); } diff --git a/src/test/java/com/arangodb/util/ArangoSerializationTest.java b/src/test/java/com/arangodb/util/ArangoSerializationTest.java index 26a5a8494..28ed2612c 100644 --- a/src/test/java/com/arangodb/util/ArangoSerializationTest.java +++ b/src/test/java/com/arangodb/util/ArangoSerializationTest.java @@ -61,7 +61,7 @@ void deserialize() { void serialize() { final BaseDocument entity = new BaseDocument(); entity.addAttribute("foo", "bar"); - final VPackSlice vpack = internalSer.serialize(entity); + final VPackSlice vpack = new VPackSlice(internalSer.serialize(entity)); assertThat(vpack.get("foo").isString()).isTrue(); assertThat(vpack.get("foo").getAsString()).isEqualTo("bar"); } @@ -70,7 +70,7 @@ void serialize() { void serializeNullValues() { final BaseDocument entity = new BaseDocument(); entity.addAttribute("foo", null); - final VPackSlice vpack = userSer.serialize(entity); + final VPackSlice vpack = new VPackSlice(userSer.serialize(entity)); assertThat(vpack.get("foo").isNull()).isTrue(); } @@ -78,7 +78,7 @@ void serializeNullValues() { void skipSerializeNullValues() { final BaseDocument entity = new BaseDocument(); entity.addAttribute("bar", null); - final VPackSlice vpack = internalSer.serialize(entity); + final VPackSlice vpack = new VPackSlice(internalSer.serialize(entity)); assertThat(vpack.get("bar").isNone()).isTrue(); } @@ -88,7 +88,7 @@ void serializeType() { list.add(new BaseDocument()); list.add(new BaseDocument()); - final VPackSlice vpack = internalSer.serialize(list); + final VPackSlice vpack = new VPackSlice(internalSer.serialize(list)); assertThat(vpack.isArray()).isTrue(); assertThat(vpack.getLength()).isEqualTo(list.size()); } @@ -97,7 +97,7 @@ void serializeType() { void parseJsonIncludeNull() { final Map entity = new HashMap<>(); entity.put("value", new String[]{"test", null}); - final String json = internalSer.deserialize(internalSer.serialize(entity), String.class); + final String json = internalSer.deserialize(new VPackSlice(internalSer.serialize(entity)), String.class); assertThat(json).isEqualTo("{\"value\":[\"test\",null]}"); } From 9f0309ab00bef70a76fcd48cf9c18e7eebc94b34 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Fri, 8 Jul 2022 09:32:51 +0200 Subject: [PATCH 025/254] serialize AQL bindvars as byte[] --- src/main/java/com/arangodb/ArangoDB.java | 11 ++----- .../com/arangodb/async/ArangoDBAsync.java | 8 ++--- .../internal/InternalArangoDatabase.java | 3 +- .../util/DefaultArangoSerialization.java | 13 ++++++-- .../java/com/arangodb/mapping/ArangoJack.java | 8 ++++- .../com/arangodb/model/AqlQueryOptions.java | 30 ++++++++++++++----- .../com/arangodb/model/OptionsBuilder.java | 2 +- .../java/com/arangodb/serde/DataType.java | 16 +++++++++- .../com/arangodb/serde/InternalSerde.java | 7 +++++ .../com/arangodb/serde/InternalSerdeImpl.java | 11 ++++++- .../arangodb/serde/InternalSerializers.java | 11 +++++++ .../arangodb/util/ArangoSerialization.java | 4 +++ .../java/com/arangodb/ArangoDatabaseTest.java | 8 +++-- 13 files changed, 100 insertions(+), 32 deletions(-) diff --git a/src/main/java/com/arangodb/ArangoDB.java b/src/main/java/com/arangodb/ArangoDB.java index e6056cf9f..b8aba440f 100644 --- a/src/main/java/com/arangodb/ArangoDB.java +++ b/src/main/java/com/arangodb/ArangoDB.java @@ -39,6 +39,7 @@ import com.arangodb.model.UserUpdateOptions; import com.arangodb.serde.DataType; import com.arangodb.serde.InternalSerde; +import com.arangodb.serde.JacksonSerde; import com.arangodb.util.ArangoCursorInitializer; import com.arangodb.util.ArangoDeserializer; import com.arangodb.util.ArangoSerialization; @@ -347,11 +348,6 @@ public Builder serializer(final ArangoSerialization serialization) { * @return {@link ArangoDB} */ public synchronized ArangoDB build() { - if (customSerializer == null) { - logger.warn("Usage of VelocyPack Java serialization is now deprecated for removal. " + - "Future driver versions will only support Jackson serialization (for both JSON and VPACK formats). " + - "Please configure according to: https://www.arangodb.com/docs/stable/drivers/java-reference-serialization.html"); - } if (hosts.isEmpty()) { hosts.add(host); } @@ -360,10 +356,9 @@ public synchronized ArangoDB build() { final VPackParser vpackParser = vpackParserBuilder.build(); final ArangoDeserializer deserializerTemp = deserializer != null ? deserializer : new ArangoDeserializerImpl(vpackerNull, vpackParser); - final InternalSerde internalSerde = protocol == Protocol.HTTP_JSON ? InternalSerde.of(DataType.JSON) - : InternalSerde.of(DataType.VPACK); + final InternalSerde internalSerde = InternalSerde.of(DataType.of(protocol)); final DefaultArangoSerialization internal = new DefaultArangoSerialization(deserializerTemp, internalSerde); - final ArangoSerialization custom = customSerializer != null ? customSerializer : internal; + final ArangoSerialization custom = customSerializer != null ? customSerializer : new DefaultArangoSerialization(deserializerTemp, JacksonSerde.of(DataType.of(protocol)));; final ArangoSerializationFactory util = new ArangoSerializationFactory(internal, custom); int protocolMaxConnections = protocol == Protocol.VST ? diff --git a/src/main/java/com/arangodb/async/ArangoDBAsync.java b/src/main/java/com/arangodb/async/ArangoDBAsync.java index 8075310b2..17cdce649 100644 --- a/src/main/java/com/arangodb/async/ArangoDBAsync.java +++ b/src/main/java/com/arangodb/async/ArangoDBAsync.java @@ -42,6 +42,7 @@ import com.arangodb.model.UserUpdateOptions; import com.arangodb.serde.DataType; import com.arangodb.serde.InternalSerde; +import com.arangodb.serde.JacksonSerde; import com.arangodb.util.ArangoDeserializer; import com.arangodb.util.ArangoSerialization; import com.arangodb.velocypack.*; @@ -508,11 +509,6 @@ public Builder serializer(final ArangoSerialization serialization) { * @return {@link ArangoDBAsync} */ public synchronized ArangoDBAsync build() { - if (customSerializer == null) { - logger.warn("Usage of VelocyPack Java serialization is now deprecated for removal. " + - "Future driver versions will only support Jackson serialization (for both JSON and VPACK formats). " + - "Please configure according to: https://www.arangodb.com/docs/stable/drivers/java-reference-serialization.html"); - } if (hosts.isEmpty()) { hosts.add(host); } @@ -523,7 +519,7 @@ public synchronized ArangoDBAsync build() { : new ArangoDeserializerImpl(vpackerNull, vpackParser); final InternalSerde internalSerde = InternalSerde.of(DataType.VPACK); final DefaultArangoSerialization internal = new DefaultArangoSerialization(deserializerTemp, internalSerde); - final ArangoSerialization custom = customSerializer != null ? customSerializer : internal; + final ArangoSerialization custom = customSerializer != null ? customSerializer : new DefaultArangoSerialization(deserializerTemp, JacksonSerde.of(DataType.VPACK)); final ArangoSerializationFactory util = new ArangoSerializationFactory(internal, custom); final int max = maxConnections != null ? Math.max(1, maxConnections) diff --git a/src/main/java/com/arangodb/internal/InternalArangoDatabase.java b/src/main/java/com/arangodb/internal/InternalArangoDatabase.java index f0ecd708e..ba2ca8237 100644 --- a/src/main/java/com/arangodb/internal/InternalArangoDatabase.java +++ b/src/main/java/com/arangodb/internal/InternalArangoDatabase.java @@ -167,8 +167,7 @@ protected Request queryRequest( final Request request = request(dbName, RequestType.POST, PATH_API_CURSOR) .setBody(getInternalSerialization().serialize(OptionsBuilder .build(opt, query, bindVars != null ? - new VPackSlice(getUserSerialization().serialize(bindVars)) : - null))); + getUserSerialization().serialize(bindVars) : null))); if (opt.getAllowDirtyRead() == Boolean.TRUE) { RequestUtils.allowDirtyRead(request); } diff --git a/src/main/java/com/arangodb/internal/util/DefaultArangoSerialization.java b/src/main/java/com/arangodb/internal/util/DefaultArangoSerialization.java index c858c4bb7..fba587c7b 100644 --- a/src/main/java/com/arangodb/internal/util/DefaultArangoSerialization.java +++ b/src/main/java/com/arangodb/internal/util/DefaultArangoSerialization.java @@ -21,10 +21,12 @@ package com.arangodb.internal.util; import com.arangodb.ArangoDBException; +import com.arangodb.serde.ArangoSerde; import com.arangodb.serde.InternalSerde; import com.arangodb.util.ArangoDeserializer; import com.arangodb.util.ArangoSerialization; import com.arangodb.velocypack.VPackSlice; +import com.fasterxml.jackson.databind.JsonNode; import java.lang.reflect.Type; @@ -34,9 +36,9 @@ public class DefaultArangoSerialization implements ArangoSerialization { private final ArangoDeserializer deserializer; - private final InternalSerde serde; + private final ArangoSerde serde; - public DefaultArangoSerialization(final ArangoDeserializer deserializer, final InternalSerde serde) { + public DefaultArangoSerialization(final ArangoDeserializer deserializer, final ArangoSerde serde) { super(); this.deserializer = deserializer; this.serde = serde; @@ -49,7 +51,12 @@ public byte[] serialize(final Object entity) throws ArangoDBException { @Override public String toJsonString(byte[] content) { - return serde.toJsonString(content); + return ((InternalSerde) serde).toJsonString(content); + } + + @Override + public JsonNode parse(byte[] content) { + return ((InternalSerde) serde).parse(content); } @Override diff --git a/src/main/java/com/arangodb/mapping/ArangoJack.java b/src/main/java/com/arangodb/mapping/ArangoJack.java index 11dbb9739..bb0cc271f 100644 --- a/src/main/java/com/arangodb/mapping/ArangoJack.java +++ b/src/main/java/com/arangodb/mapping/ArangoJack.java @@ -116,12 +116,18 @@ public byte[] serialize(final Object entity) throws ArangoDBException { return serde.serialize(entity); } - // FIXME: toJsonString should only be required for internal serialization + // FIXME: only required for internal serialization @Override public String toJsonString(byte[] content) { throw new UnsupportedOperationException(); } + // FIXME: only required for internal serialization + @Override + public JsonNode parse(byte[] content) { + throw new UnsupportedOperationException(); + } + @SuppressWarnings("unchecked") @Override public T deserialize(final VPackSlice vpack, final Type type) throws ArangoDBException { diff --git a/src/main/java/com/arangodb/model/AqlQueryOptions.java b/src/main/java/com/arangodb/model/AqlQueryOptions.java index 51e8494f7..a83b05cee 100644 --- a/src/main/java/com/arangodb/model/AqlQueryOptions.java +++ b/src/main/java/com/arangodb/model/AqlQueryOptions.java @@ -20,10 +20,13 @@ package com.arangodb.model; +import com.arangodb.serde.InternalSerializers; import com.arangodb.velocypack.VPackSlice; import com.arangodb.velocypack.annotations.Expose; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; -import java.io.Serializable; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; @@ -34,9 +37,7 @@ * @see API * Documentation */ -public class AqlQueryOptions implements Serializable { - - private static final long serialVersionUID = 1L; +public class AqlQueryOptions { private Boolean count; private Integer ttl; @@ -44,6 +45,7 @@ public class AqlQueryOptions implements Serializable { private Boolean cache; private Long memoryLimit; private VPackSlice bindVars; + private byte[] bindVarsBytes; private String query; private Options options; @Expose(serialize = false) @@ -151,10 +153,17 @@ public AqlQueryOptions fillBlockCache(final Boolean fillBlockCache) { return this; } + @JsonIgnore public VPackSlice getBindVars() { return bindVars; } + @JsonProperty("bindVars") + @JsonSerialize(using = InternalSerializers.AqlParamsSerializer.class) + public byte[] getBindVarsBytes() { + return bindVarsBytes; + } + /** * @param bindVars key/value pairs representing the bind parameters * @return options @@ -164,6 +173,15 @@ protected AqlQueryOptions bindVars(final VPackSlice bindVars) { return this; } + /** + * @param bindVarsBytes serialized bind parameters + * @return options + */ + protected AqlQueryOptions bindVars(final byte[] bindVarsBytes) { + this.bindVarsBytes = bindVarsBytes; + return this; + } + public String getQuery() { return query; } @@ -409,9 +427,7 @@ public Options getOptions() { return options; } - public static class Options implements Serializable { - - private static final long serialVersionUID = 1L; + public static class Options { private Boolean failOnWarning; private Boolean profile; diff --git a/src/main/java/com/arangodb/model/OptionsBuilder.java b/src/main/java/com/arangodb/model/OptionsBuilder.java index ab99ad37f..52c79b62e 100644 --- a/src/main/java/com/arangodb/model/OptionsBuilder.java +++ b/src/main/java/com/arangodb/model/OptionsBuilder.java @@ -83,7 +83,7 @@ public static CollectionCreateOptions build(final CollectionCreateOptions option return options.name(name); } - public static AqlQueryOptions build(final AqlQueryOptions options, final String query, final VPackSlice bindVars) { + public static AqlQueryOptions build(final AqlQueryOptions options, final String query, final byte[] bindVars) { return options.query(query).bindVars(bindVars); } diff --git a/src/main/java/com/arangodb/serde/DataType.java b/src/main/java/com/arangodb/serde/DataType.java index 0b071915a..801e89234 100644 --- a/src/main/java/com/arangodb/serde/DataType.java +++ b/src/main/java/com/arangodb/serde/DataType.java @@ -19,6 +19,20 @@ */ package com.arangodb.serde; +import com.arangodb.Protocol; + public enum DataType { - JSON, VPACK + JSON, VPACK; + + public static DataType of(Protocol protocol) { + switch (protocol) { + case HTTP_JSON: + return DataType.JSON; + case HTTP_VPACK: + case VST: + return DataType.VPACK; + default: + throw new IllegalStateException("Unexpected value: " + protocol); + } + } } diff --git a/src/main/java/com/arangodb/serde/InternalSerde.java b/src/main/java/com/arangodb/serde/InternalSerde.java index 839c7e5f5..1d13abd2c 100644 --- a/src/main/java/com/arangodb/serde/InternalSerde.java +++ b/src/main/java/com/arangodb/serde/InternalSerde.java @@ -1,6 +1,7 @@ package com.arangodb.serde; import com.arangodb.jackson.dataformat.velocypack.VPackMapper; +import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; public interface InternalSerde extends JacksonSerde { @@ -39,4 +40,10 @@ static InternalSerde of(final DataType dataType) { */ byte[] extract(byte[] content, String jsonPointer); + /** + * TODO + * @param content + * @return + */ + JsonNode parse(byte[] content); } diff --git a/src/main/java/com/arangodb/serde/InternalSerdeImpl.java b/src/main/java/com/arangodb/serde/InternalSerdeImpl.java index 10b46c980..0dd204379 100644 --- a/src/main/java/com/arangodb/serde/InternalSerdeImpl.java +++ b/src/main/java/com/arangodb/serde/InternalSerdeImpl.java @@ -39,11 +39,20 @@ public String toJsonString(final byte[] content) { @Override public byte[] extract(final byte[] content, final String jsonPointer) { try { - JsonNode target = mapper.readTree(content).at(jsonPointer); + JsonNode target = parse(content).at(jsonPointer); return mapper.writeValueAsBytes(target); } catch (IOException e) { throw new ArangoDBException(e); } } + @Override + public JsonNode parse(byte[] content) { + try { + return mapper.readTree(content); + } catch (IOException e) { + throw new ArangoDBException(e); + } + } + } diff --git a/src/main/java/com/arangodb/serde/InternalSerializers.java b/src/main/java/com/arangodb/serde/InternalSerializers.java index 46514b8c3..635b35991 100644 --- a/src/main/java/com/arangodb/serde/InternalSerializers.java +++ b/src/main/java/com/arangodb/serde/InternalSerializers.java @@ -9,6 +9,7 @@ import com.arangodb.velocypack.VPackSlice; import com.arangodb.velocystream.Request; import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.databind.JsonSerializer; import com.fasterxml.jackson.databind.SerializerProvider; @@ -19,6 +20,16 @@ public final class InternalSerializers { + public static class AqlParamsSerializer extends JsonSerializer { + @Override + public void serialize(byte[] value, JsonGenerator gen, SerializerProvider serializers) throws IOException { + // TODO: find a way to append raw bytes directly + try (JsonParser parser = gen.getCodec().getFactory().createParser(value)) { + gen.writeTree(parser.readValueAsTree()); + } + } + } + public static class CollectionSchemaRuleSerializer extends JsonSerializer { @Override public void serialize(String value, JsonGenerator gen, SerializerProvider serializers) throws IOException { diff --git a/src/main/java/com/arangodb/util/ArangoSerialization.java b/src/main/java/com/arangodb/util/ArangoSerialization.java index 6fee87692..1786eef2e 100644 --- a/src/main/java/com/arangodb/util/ArangoSerialization.java +++ b/src/main/java/com/arangodb/util/ArangoSerialization.java @@ -20,10 +20,14 @@ package com.arangodb.util; +import com.fasterxml.jackson.databind.JsonNode; + /** * @author Mark Vollmary */ public interface ArangoSerialization extends ArangoDeserializer { byte[] serialize(final Object entity); String toJsonString(byte[] content); + JsonNode parse(byte[] content); + } diff --git a/src/test/java/com/arangodb/ArangoDatabaseTest.java b/src/test/java/com/arangodb/ArangoDatabaseTest.java index 068107c5e..37b7e2efd 100644 --- a/src/test/java/com/arangodb/ArangoDatabaseTest.java +++ b/src/test/java/com/arangodb/ArangoDatabaseTest.java @@ -1259,12 +1259,16 @@ void transactionAllowImplicit(ArangoDatabase db) { .isEqualTo(400); } - static class TransactionTestEntity { + public static class TransactionTestEntity { private String value; - TransactionTestEntity() { + public TransactionTestEntity() { super(); } + + public String getValue() { + return value; + } } @ParameterizedTest(name = "{index}") From 9910876065468c5309197402754633b17f2adfe1 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Fri, 8 Jul 2022 10:07:11 +0200 Subject: [PATCH 026/254] separated ArangoSerialization from InternalSerialization --- src/main/java/com/arangodb/ArangoDB.java | 8 ++-- .../arangodb/ArangoSerializationAccessor.java | 3 +- .../com/arangodb/async/ArangoDBAsync.java | 10 +++-- .../velocystream/VstCommunicationAsync.java | 6 +-- .../com/arangodb/internal/ArangoDBImpl.java | 8 ++-- .../arangodb/internal/ArangoExecuteable.java | 3 +- .../internal/InternalArangoDBBuilder.java | 13 +------ .../arangodb/internal/http/CURLLogger.java | 4 +- .../internal/http/HttpCommunication.java | 4 +- .../internal/http/HttpConnection.java | 10 ++--- .../internal/http/HttpConnectionFactory.java | 4 +- .../internal/net/ExtendedHostResolver.java | 6 +-- .../arangodb/internal/net/HostResolver.java | 4 +- .../internal/net/SimpleHostResolver.java | 4 +- .../util/ArangoSerializationFactory.java | 7 ++-- .../util/ArangoSerializationImpl.java | 32 ++++++++++++++++ ...on.java => InternalSerializationImpl.java} | 13 +++---- .../arangodb/internal/util/ResponseUtils.java | 4 +- .../velocystream/VstCommunication.java | 6 +-- .../velocystream/VstCommunicationSync.java | 6 +-- .../java/com/arangodb/mapping/ArangoJack.java | 12 ------ .../arangodb/util/ArangoSerialization.java | 38 +++---------------- .../arangodb/util/InternalSerialization.java | 33 ++++++++++++++++ src/test/java/com/arangodb/JwtAuthTest.java | 4 +- .../java/com/arangodb/async/JwtAuthTest.java | 4 +- .../arangodb/internal/HostHandlerTest.java | 6 +-- .../com/arangodb/serde/CustomSerdeTest.java | 1 + .../util/ArangoSerializationTest.java | 2 +- 28 files changed, 138 insertions(+), 117 deletions(-) create mode 100644 src/main/java/com/arangodb/internal/util/ArangoSerializationImpl.java rename src/main/java/com/arangodb/internal/util/{DefaultArangoSerialization.java => InternalSerializationImpl.java} (79%) create mode 100644 src/main/java/com/arangodb/util/InternalSerialization.java diff --git a/src/main/java/com/arangodb/ArangoDB.java b/src/main/java/com/arangodb/ArangoDB.java index b8aba440f..fa63cb244 100644 --- a/src/main/java/com/arangodb/ArangoDB.java +++ b/src/main/java/com/arangodb/ArangoDB.java @@ -30,7 +30,8 @@ import com.arangodb.internal.net.*; import com.arangodb.internal.util.ArangoDeserializerImpl; import com.arangodb.internal.util.ArangoSerializationFactory; -import com.arangodb.internal.util.DefaultArangoSerialization; +import com.arangodb.internal.util.ArangoSerializationImpl; +import com.arangodb.internal.util.InternalSerializationImpl; import com.arangodb.internal.velocystream.VstCommunicationSync; import com.arangodb.internal.velocystream.VstConnectionFactorySync; import com.arangodb.model.DBCreateOptions; @@ -43,6 +44,7 @@ import com.arangodb.util.ArangoCursorInitializer; import com.arangodb.util.ArangoDeserializer; import com.arangodb.util.ArangoSerialization; +import com.arangodb.util.InternalSerialization; import com.arangodb.velocypack.VPack; import com.arangodb.velocypack.VPackParser; import com.arangodb.velocystream.Request; @@ -357,8 +359,8 @@ public synchronized ArangoDB build() { final ArangoDeserializer deserializerTemp = deserializer != null ? deserializer : new ArangoDeserializerImpl(vpackerNull, vpackParser); final InternalSerde internalSerde = InternalSerde.of(DataType.of(protocol)); - final DefaultArangoSerialization internal = new DefaultArangoSerialization(deserializerTemp, internalSerde); - final ArangoSerialization custom = customSerializer != null ? customSerializer : new DefaultArangoSerialization(deserializerTemp, JacksonSerde.of(DataType.of(protocol)));; + final InternalSerialization internal = new InternalSerializationImpl(deserializerTemp, internalSerde); + final ArangoSerialization custom = customSerializer != null ? customSerializer : new ArangoSerializationImpl(deserializerTemp, JacksonSerde.of(DataType.of(protocol))); final ArangoSerializationFactory util = new ArangoSerializationFactory(internal, custom); int protocolMaxConnections = protocol == Protocol.VST ? diff --git a/src/main/java/com/arangodb/ArangoSerializationAccessor.java b/src/main/java/com/arangodb/ArangoSerializationAccessor.java index 1bd7dcfa4..0f811517c 100644 --- a/src/main/java/com/arangodb/ArangoSerializationAccessor.java +++ b/src/main/java/com/arangodb/ArangoSerializationAccessor.java @@ -21,6 +21,7 @@ package com.arangodb; import com.arangodb.util.ArangoSerialization; +import com.arangodb.util.InternalSerialization; /** * @author Mark Vollmary @@ -32,7 +33,7 @@ public interface ArangoSerializationAccessor { * * @return ArangoSerialization */ - ArangoSerialization getInternalSerialization(); + InternalSerialization getInternalSerialization(); /** * Returns serialization implementation for serializing and deserializing user's classes. diff --git a/src/main/java/com/arangodb/async/ArangoDBAsync.java b/src/main/java/com/arangodb/async/ArangoDBAsync.java index 17cdce649..aae9d3684 100644 --- a/src/main/java/com/arangodb/async/ArangoDBAsync.java +++ b/src/main/java/com/arangodb/async/ArangoDBAsync.java @@ -33,7 +33,8 @@ import com.arangodb.internal.net.HostResolver; import com.arangodb.internal.util.ArangoDeserializerImpl; import com.arangodb.internal.util.ArangoSerializationFactory; -import com.arangodb.internal.util.DefaultArangoSerialization; +import com.arangodb.internal.util.ArangoSerializationImpl; +import com.arangodb.internal.util.InternalSerializationImpl; import com.arangodb.internal.velocystream.VstCommunicationSync; import com.arangodb.internal.velocystream.VstConnectionFactorySync; import com.arangodb.model.DBCreateOptions; @@ -45,7 +46,8 @@ import com.arangodb.serde.JacksonSerde; import com.arangodb.util.ArangoDeserializer; import com.arangodb.util.ArangoSerialization; -import com.arangodb.velocypack.*; +import com.arangodb.velocypack.VPack; +import com.arangodb.velocypack.VPackParser; import com.arangodb.velocystream.Request; import com.arangodb.velocystream.Response; import org.slf4j.Logger; @@ -518,8 +520,8 @@ public synchronized ArangoDBAsync build() { final ArangoDeserializer deserializerTemp = deserializer != null ? deserializer : new ArangoDeserializerImpl(vpackerNull, vpackParser); final InternalSerde internalSerde = InternalSerde.of(DataType.VPACK); - final DefaultArangoSerialization internal = new DefaultArangoSerialization(deserializerTemp, internalSerde); - final ArangoSerialization custom = customSerializer != null ? customSerializer : new DefaultArangoSerialization(deserializerTemp, JacksonSerde.of(DataType.VPACK)); + final InternalSerializationImpl internal = new InternalSerializationImpl(deserializerTemp, internalSerde); + final ArangoSerialization custom = customSerializer != null ? customSerializer : new ArangoSerializationImpl(deserializerTemp, JacksonSerde.of(DataType.VPACK)); final ArangoSerializationFactory util = new ArangoSerializationFactory(internal, custom); final int max = maxConnections != null ? Math.max(1, maxConnections) diff --git a/src/main/java/com/arangodb/async/internal/velocystream/VstCommunicationAsync.java b/src/main/java/com/arangodb/async/internal/velocystream/VstCommunicationAsync.java index 38acb45be..030ebc5f2 100644 --- a/src/main/java/com/arangodb/async/internal/velocystream/VstCommunicationAsync.java +++ b/src/main/java/com/arangodb/async/internal/velocystream/VstCommunicationAsync.java @@ -30,7 +30,7 @@ import com.arangodb.internal.velocystream.internal.AuthenticationRequest; import com.arangodb.internal.velocystream.internal.JwtAuthenticationRequest; import com.arangodb.internal.velocystream.internal.Message; -import com.arangodb.util.ArangoSerialization; +import com.arangodb.util.InternalSerialization; import com.arangodb.velocypack.exception.VPackException; import com.arangodb.velocypack.exception.VPackParserException; import com.arangodb.velocystream.Request; @@ -50,7 +50,7 @@ public class VstCommunicationAsync extends VstCommunication hosts, final Integer maxConnections, @@ -69,7 +69,7 @@ public ExtendedHostResolver(final List hosts, final Integer maxConnections } @Override - public void init(ArangoExecutorSync executor, ArangoSerialization arangoSerialization) { + public void init(ArangoExecutorSync executor, InternalSerialization arangoSerialization) { this.executor = executor; this.arangoSerialization = arangoSerialization; } diff --git a/src/main/java/com/arangodb/internal/net/HostResolver.java b/src/main/java/com/arangodb/internal/net/HostResolver.java index 85bdd2038..3dd9e6e1a 100644 --- a/src/main/java/com/arangodb/internal/net/HostResolver.java +++ b/src/main/java/com/arangodb/internal/net/HostResolver.java @@ -21,14 +21,14 @@ package com.arangodb.internal.net; import com.arangodb.internal.ArangoExecutorSync; -import com.arangodb.util.ArangoSerialization; +import com.arangodb.util.InternalSerialization; /** * @author Mark Vollmary */ public interface HostResolver { - void init(ArangoExecutorSync executorSync, ArangoSerialization arangoSerialization); + void init(ArangoExecutorSync executorSync, InternalSerialization arangoSerialization); HostSet resolve(boolean initial, boolean closeConnections); diff --git a/src/main/java/com/arangodb/internal/net/SimpleHostResolver.java b/src/main/java/com/arangodb/internal/net/SimpleHostResolver.java index e139e3866..088189747 100644 --- a/src/main/java/com/arangodb/internal/net/SimpleHostResolver.java +++ b/src/main/java/com/arangodb/internal/net/SimpleHostResolver.java @@ -21,7 +21,7 @@ package com.arangodb.internal.net; import com.arangodb.internal.ArangoExecutorSync; -import com.arangodb.util.ArangoSerialization; +import com.arangodb.util.InternalSerialization; import java.util.List; @@ -38,7 +38,7 @@ public SimpleHostResolver(final List hosts) { } @Override - public void init(ArangoExecutorSync executor, ArangoSerialization arangoSerialization) { + public void init(ArangoExecutorSync executor, InternalSerialization arangoSerialization) { } diff --git a/src/main/java/com/arangodb/internal/util/ArangoSerializationFactory.java b/src/main/java/com/arangodb/internal/util/ArangoSerializationFactory.java index b015b59ec..c5c3558f9 100644 --- a/src/main/java/com/arangodb/internal/util/ArangoSerializationFactory.java +++ b/src/main/java/com/arangodb/internal/util/ArangoSerializationFactory.java @@ -21,22 +21,23 @@ package com.arangodb.internal.util; import com.arangodb.util.ArangoSerialization; +import com.arangodb.util.InternalSerialization; /** * @author Mark Vollmary */ public class ArangoSerializationFactory { - private final ArangoSerialization internal; + private final InternalSerialization internal; private final ArangoSerialization user; - public ArangoSerializationFactory(final ArangoSerialization internal, final ArangoSerialization user) { + public ArangoSerializationFactory(final InternalSerialization internal, final ArangoSerialization user) { super(); this.internal = internal; this.user = user; } - public ArangoSerialization getInternalSerialization() { + public InternalSerialization getInternalSerialization() { return internal; } diff --git a/src/main/java/com/arangodb/internal/util/ArangoSerializationImpl.java b/src/main/java/com/arangodb/internal/util/ArangoSerializationImpl.java new file mode 100644 index 000000000..e0048baea --- /dev/null +++ b/src/main/java/com/arangodb/internal/util/ArangoSerializationImpl.java @@ -0,0 +1,32 @@ +package com.arangodb.internal.util; + +import com.arangodb.ArangoDBException; +import com.arangodb.serde.ArangoSerde; +import com.arangodb.util.ArangoDeserializer; +import com.arangodb.util.ArangoSerialization; +import com.arangodb.velocypack.VPackSlice; + +import java.lang.reflect.Type; + +public class ArangoSerializationImpl implements ArangoSerialization { + + private final ArangoDeserializer deserializer; + private final ArangoSerde serde; + + public ArangoSerializationImpl(final ArangoDeserializer deserializer, final ArangoSerde serde) { + super(); + this.deserializer = deserializer; + this.serde = serde; + } + + @Override + public byte[] serialize(final Object entity) throws ArangoDBException { + return serde.serialize(entity); + } + + @Override + public T deserialize(final VPackSlice vpack, final Type type) throws ArangoDBException { + return deserializer.deserialize(vpack, type); + } + +} diff --git a/src/main/java/com/arangodb/internal/util/DefaultArangoSerialization.java b/src/main/java/com/arangodb/internal/util/InternalSerializationImpl.java similarity index 79% rename from src/main/java/com/arangodb/internal/util/DefaultArangoSerialization.java rename to src/main/java/com/arangodb/internal/util/InternalSerializationImpl.java index fba587c7b..05f249697 100644 --- a/src/main/java/com/arangodb/internal/util/DefaultArangoSerialization.java +++ b/src/main/java/com/arangodb/internal/util/InternalSerializationImpl.java @@ -21,10 +21,9 @@ package com.arangodb.internal.util; import com.arangodb.ArangoDBException; -import com.arangodb.serde.ArangoSerde; import com.arangodb.serde.InternalSerde; import com.arangodb.util.ArangoDeserializer; -import com.arangodb.util.ArangoSerialization; +import com.arangodb.util.InternalSerialization; import com.arangodb.velocypack.VPackSlice; import com.fasterxml.jackson.databind.JsonNode; @@ -33,12 +32,12 @@ /** * @author Mark Vollmary */ -public class DefaultArangoSerialization implements ArangoSerialization { +public class InternalSerializationImpl implements InternalSerialization { private final ArangoDeserializer deserializer; - private final ArangoSerde serde; + private final InternalSerde serde; - public DefaultArangoSerialization(final ArangoDeserializer deserializer, final ArangoSerde serde) { + public InternalSerializationImpl(final ArangoDeserializer deserializer, final InternalSerde serde) { super(); this.deserializer = deserializer; this.serde = serde; @@ -51,12 +50,12 @@ public byte[] serialize(final Object entity) throws ArangoDBException { @Override public String toJsonString(byte[] content) { - return ((InternalSerde) serde).toJsonString(content); + return serde.toJsonString(content); } @Override public JsonNode parse(byte[] content) { - return ((InternalSerde) serde).parse(content); + return serde.parse(content); } @Override diff --git a/src/main/java/com/arangodb/internal/util/ResponseUtils.java b/src/main/java/com/arangodb/internal/util/ResponseUtils.java index 0cc5e38cb..bd181ddb5 100644 --- a/src/main/java/com/arangodb/internal/util/ResponseUtils.java +++ b/src/main/java/com/arangodb/internal/util/ResponseUtils.java @@ -24,7 +24,7 @@ import com.arangodb.entity.ErrorEntity; import com.arangodb.internal.ArangoErrors; import com.arangodb.internal.net.ArangoDBRedirectException; -import com.arangodb.util.ArangoSerialization; +import com.arangodb.util.InternalSerialization; import com.arangodb.velocypack.exception.VPackParserException; import com.arangodb.velocystream.Response; @@ -43,7 +43,7 @@ private ResponseUtils() { super(); } - public static void checkError(final ArangoSerialization util, final Response response) throws ArangoDBException { + public static void checkError(final InternalSerialization util, final Response response) throws ArangoDBException { try { final int responseCode = response.getResponseCode(); if (responseCode >= ERROR_STATUS) { diff --git a/src/main/java/com/arangodb/internal/velocystream/VstCommunication.java b/src/main/java/com/arangodb/internal/velocystream/VstCommunication.java index 0cb2faea1..b76e1971c 100644 --- a/src/main/java/com/arangodb/internal/velocystream/VstCommunication.java +++ b/src/main/java/com/arangodb/internal/velocystream/VstCommunication.java @@ -31,7 +31,7 @@ import com.arangodb.internal.velocystream.internal.Chunk; import com.arangodb.internal.velocystream.internal.Message; import com.arangodb.internal.velocystream.internal.VstConnection; -import com.arangodb.util.ArangoSerialization; +import com.arangodb.util.InternalSerialization; import com.arangodb.velocypack.VPackSlice; import com.arangodb.velocypack.exception.VPackParserException; import com.arangodb.velocystream.Request; @@ -56,7 +56,7 @@ public abstract class VstCommunication implements Cl private static final Logger LOGGER = LoggerFactory.getLogger(VstCommunication.class); protected static final AtomicLong mId = new AtomicLong(0L); - protected final ArangoSerialization util; + protected final InternalSerialization util; protected final String user; protected final String password; @@ -66,7 +66,7 @@ public abstract class VstCommunication implements Cl protected final HostHandler hostHandler; protected VstCommunication(final Integer timeout, final String user, final String password, final String jwt, - final Boolean useSsl, final SSLContext sslContext, final ArangoSerialization util, + final Boolean useSsl, final SSLContext sslContext, final InternalSerialization util, final Integer chunksize, final HostHandler hostHandler) { this.user = user; this.password = password; diff --git a/src/main/java/com/arangodb/internal/velocystream/VstCommunicationSync.java b/src/main/java/com/arangodb/internal/velocystream/VstCommunicationSync.java index e01e22bc2..140882367 100644 --- a/src/main/java/com/arangodb/internal/velocystream/VstCommunicationSync.java +++ b/src/main/java/com/arangodb/internal/velocystream/VstCommunicationSync.java @@ -30,7 +30,7 @@ import com.arangodb.internal.velocystream.internal.JwtAuthenticationRequest; import com.arangodb.internal.velocystream.internal.Message; import com.arangodb.internal.velocystream.internal.VstConnectionSync; -import com.arangodb.util.ArangoSerialization; +import com.arangodb.util.InternalSerialization; import com.arangodb.velocypack.exception.VPackParserException; import com.arangodb.velocystream.Request; import com.arangodb.velocystream.Response; @@ -116,7 +116,7 @@ public Builder connectionTtl(final Long connectionTtl) { return this; } - public VstCommunication build(final ArangoSerialization util) { + public VstCommunication build(final InternalSerialization util) { return new VstCommunicationSync(hostHandler, timeout, user, password, jwt, useSsl, sslContext, util, chunksize, maxConnections, connectionTtl); } @@ -125,7 +125,7 @@ public VstCommunication build(final ArangoSerializa protected VstCommunicationSync(final HostHandler hostHandler, final Integer timeout, final String user, final String password, final String jwt, final Boolean useSsl, - final SSLContext sslContext, final ArangoSerialization util, + final SSLContext sslContext, final InternalSerialization util, final Integer chunksize, final Integer maxConnections, final Long ttl) { super(timeout, user, password, jwt, useSsl, sslContext, util, chunksize, hostHandler); } diff --git a/src/main/java/com/arangodb/mapping/ArangoJack.java b/src/main/java/com/arangodb/mapping/ArangoJack.java index bb0cc271f..392548dd8 100644 --- a/src/main/java/com/arangodb/mapping/ArangoJack.java +++ b/src/main/java/com/arangodb/mapping/ArangoJack.java @@ -116,18 +116,6 @@ public byte[] serialize(final Object entity) throws ArangoDBException { return serde.serialize(entity); } - // FIXME: only required for internal serialization - @Override - public String toJsonString(byte[] content) { - throw new UnsupportedOperationException(); - } - - // FIXME: only required for internal serialization - @Override - public JsonNode parse(byte[] content) { - throw new UnsupportedOperationException(); - } - @SuppressWarnings("unchecked") @Override public T deserialize(final VPackSlice vpack, final Type type) throws ArangoDBException { diff --git a/src/main/java/com/arangodb/util/ArangoSerialization.java b/src/main/java/com/arangodb/util/ArangoSerialization.java index 1786eef2e..8efa1b522 100644 --- a/src/main/java/com/arangodb/util/ArangoSerialization.java +++ b/src/main/java/com/arangodb/util/ArangoSerialization.java @@ -1,33 +1,5 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.util; - -import com.fasterxml.jackson.databind.JsonNode; - -/** - * @author Mark Vollmary - */ -public interface ArangoSerialization extends ArangoDeserializer { - byte[] serialize(final Object entity); - String toJsonString(byte[] content); - JsonNode parse(byte[] content); - -} +package com.arangodb.util; + +public interface ArangoSerialization extends ArangoDeserializer { + byte[] serialize(final Object entity); +} diff --git a/src/main/java/com/arangodb/util/InternalSerialization.java b/src/main/java/com/arangodb/util/InternalSerialization.java new file mode 100644 index 000000000..690d02a71 --- /dev/null +++ b/src/main/java/com/arangodb/util/InternalSerialization.java @@ -0,0 +1,33 @@ +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed 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. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.util; + +import com.fasterxml.jackson.databind.JsonNode; + +/** + * @author Mark Vollmary + */ +public interface InternalSerialization extends ArangoDeserializer { + byte[] serialize(final Object entity); + String toJsonString(byte[] content); + JsonNode parse(byte[] content); + +} diff --git a/src/test/java/com/arangodb/JwtAuthTest.java b/src/test/java/com/arangodb/JwtAuthTest.java index 7ba60adbb..835c2cade 100644 --- a/src/test/java/com/arangodb/JwtAuthTest.java +++ b/src/test/java/com/arangodb/JwtAuthTest.java @@ -1,7 +1,7 @@ package com.arangodb; import com.arangodb.mapping.ArangoJack; -import com.arangodb.util.ArangoSerialization; +import com.arangodb.util.InternalSerialization; import com.arangodb.velocystream.Request; import com.arangodb.velocystream.RequestType; import com.arangodb.velocystream.Response; @@ -83,7 +83,7 @@ private ArangoDB.Builder getBuilder(Protocol protocol) { } private static String getJwt(ArangoDB arangoDB) { - ArangoSerialization serde = arangoDB.getInternalSerialization(); + InternalSerialization serde = arangoDB.getInternalSerialization(); Map reqBody = new HashMap<>(); reqBody.put("username", "root"); reqBody.put("password", "test"); diff --git a/src/test/java/com/arangodb/async/JwtAuthTest.java b/src/test/java/com/arangodb/async/JwtAuthTest.java index ba119bcc7..a55c23527 100644 --- a/src/test/java/com/arangodb/async/JwtAuthTest.java +++ b/src/test/java/com/arangodb/async/JwtAuthTest.java @@ -4,7 +4,7 @@ import com.arangodb.ArangoDBException; import com.arangodb.DbName; import com.arangodb.mapping.ArangoJack; -import com.arangodb.util.ArangoSerialization; +import com.arangodb.util.InternalSerialization; import com.arangodb.velocystream.Request; import com.arangodb.velocystream.RequestType; import com.arangodb.velocystream.Response; @@ -90,7 +90,7 @@ private ArangoDBAsync.Builder getBuilder() { } private static String getJwt(ArangoDB arangoDB) { - ArangoSerialization serde = arangoDB.getInternalSerialization(); + InternalSerialization serde = arangoDB.getInternalSerialization(); Map reqBody = new HashMap<>(); reqBody.put("username", "root"); reqBody.put("password", "test"); diff --git a/src/test/java/com/arangodb/internal/HostHandlerTest.java b/src/test/java/com/arangodb/internal/HostHandlerTest.java index 56b09ca5d..0fcc2bc92 100644 --- a/src/test/java/com/arangodb/internal/HostHandlerTest.java +++ b/src/test/java/com/arangodb/internal/HostHandlerTest.java @@ -23,7 +23,7 @@ import com.arangodb.ArangoDBException; import com.arangodb.ArangoDBMultipleException; import com.arangodb.internal.net.*; -import com.arangodb.util.ArangoSerialization; +import com.arangodb.util.InternalSerialization; import org.junit.jupiter.api.Test; import java.util.List; @@ -73,7 +73,7 @@ public HostSet resolve(final boolean initial, final boolean closeConnections) { } @Override - public void init(ArangoExecutorSync executor, ArangoSerialization arangoSerialization) { + public void init(ArangoExecutorSync executor, InternalSerialization arangoSerialization) { } @@ -92,7 +92,7 @@ public HostSet resolve(final boolean initial, final boolean closeConnections) { } @Override - public void init(ArangoExecutorSync executor, ArangoSerialization arangoSerialization) { + public void init(ArangoExecutorSync executor, InternalSerialization arangoSerialization) { } diff --git a/src/test/java/com/arangodb/serde/CustomSerdeTest.java b/src/test/java/com/arangodb/serde/CustomSerdeTest.java index e703ecae4..06bbb18c8 100644 --- a/src/test/java/com/arangodb/serde/CustomSerdeTest.java +++ b/src/test/java/com/arangodb/serde/CustomSerdeTest.java @@ -29,6 +29,7 @@ import com.arangodb.mapping.ArangoJack; import com.arangodb.model.DocumentCreateOptions; import com.arangodb.util.ArangoSerialization; +import com.arangodb.util.InternalSerialization; import com.arangodb.velocypack.VPackBuilder; import com.arangodb.velocypack.VPackSlice; import com.fasterxml.jackson.core.JsonGenerator; diff --git a/src/test/java/com/arangodb/util/ArangoSerializationTest.java b/src/test/java/com/arangodb/util/ArangoSerializationTest.java index 28ed2612c..7f08a8d81 100644 --- a/src/test/java/com/arangodb/util/ArangoSerializationTest.java +++ b/src/test/java/com/arangodb/util/ArangoSerializationTest.java @@ -40,7 +40,7 @@ */ class ArangoSerializationTest { - private static ArangoSerialization internalSer; + private static InternalSerialization internalSer; private static ArangoSerialization userSer; @BeforeAll From a9d0cd72aa7491ca5a43c7473efb8339355da4bc Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Fri, 8 Jul 2022 12:38:01 +0200 Subject: [PATCH 027/254] deserializer refactoring --- src/main/java/com/arangodb/ArangoDB.java | 13 +- .../com/arangodb/async/ArangoDBAsync.java | 6 +- .../com/arangodb/entity/CursorEntity.java | 5 +- .../internal/ArangoResponseField.java | 4 +- .../internal/InternalArangoCollection.java | 122 +++++++------- .../arangodb/internal/InternalArangoDB.java | 34 ++-- .../internal/InternalArangoDatabase.java | 157 +++++------------- .../InternalArangoEdgeCollection.java | 12 +- .../internal/InternalArangoGraph.java | 10 +- .../InternalArangoVertexCollection.java | 12 +- .../internal/cursor/ArangoCursorIterator.java | 12 +- .../internal/http/HttpConnection.java | 16 +- .../internal/net/ExtendedHostResolver.java | 18 +- .../util/ArangoSerializationImpl.java | 10 +- .../util/InternalSerializationImpl.java | 30 +++- .../velocypack/VPackDeserializers.java | 27 +-- .../velocystream/VstCommunication.java | 4 +- .../java/com/arangodb/mapping/ArangoJack.java | 21 +-- .../arangodb/serde/InternalDeserializers.java | 49 ++++++ .../com/arangodb/serde/InternalModule.java | 7 + .../com/arangodb/serde/InternalSerde.java | 25 ++- .../com/arangodb/serde/InternalSerdeImpl.java | 12 ++ .../arangodb/util/ArangoSerialization.java | 5 +- .../arangodb/util/InternalSerialization.java | 16 +- .../com/arangodb/velocystream/Response.java | 26 +-- src/test/java/com/arangodb/ArangoDBTest.java | 2 +- .../java/com/arangodb/ArangoRouteTest.java | 2 +- src/test/java/com/arangodb/BaseJunit5.java | 1 - .../java/com/arangodb/async/ArangoDBTest.java | 4 +- .../annotations/ArangoAnnotationsTest.java | 14 +- .../com/arangodb/serde/CustomSerdeTest.java | 12 +- .../util/ArangoSerializationTest.java | 6 +- 32 files changed, 313 insertions(+), 381 deletions(-) create mode 100644 src/main/java/com/arangodb/serde/InternalDeserializers.java diff --git a/src/main/java/com/arangodb/ArangoDB.java b/src/main/java/com/arangodb/ArangoDB.java index fa63cb244..5efa9db1e 100644 --- a/src/main/java/com/arangodb/ArangoDB.java +++ b/src/main/java/com/arangodb/ArangoDB.java @@ -28,7 +28,6 @@ import com.arangodb.internal.http.HttpCommunication; import com.arangodb.internal.http.HttpConnectionFactory; import com.arangodb.internal.net.*; -import com.arangodb.internal.util.ArangoDeserializerImpl; import com.arangodb.internal.util.ArangoSerializationFactory; import com.arangodb.internal.util.ArangoSerializationImpl; import com.arangodb.internal.util.InternalSerializationImpl; @@ -42,11 +41,8 @@ import com.arangodb.serde.InternalSerde; import com.arangodb.serde.JacksonSerde; import com.arangodb.util.ArangoCursorInitializer; -import com.arangodb.util.ArangoDeserializer; import com.arangodb.util.ArangoSerialization; import com.arangodb.util.InternalSerialization; -import com.arangodb.velocypack.VPack; -import com.arangodb.velocypack.VPackParser; import com.arangodb.velocystream.Request; import com.arangodb.velocystream.Response; import org.apache.http.client.HttpRequestRetryHandler; @@ -353,14 +349,9 @@ public synchronized ArangoDB build() { if (hosts.isEmpty()) { hosts.add(host); } - final VPack vpacker = vpackBuilder.serializeNullValues(false).build(); - final VPack vpackerNull = vpackBuilder.serializeNullValues(true).build(); - final VPackParser vpackParser = vpackParserBuilder.build(); - final ArangoDeserializer deserializerTemp = deserializer != null ? deserializer - : new ArangoDeserializerImpl(vpackerNull, vpackParser); final InternalSerde internalSerde = InternalSerde.of(DataType.of(protocol)); - final InternalSerialization internal = new InternalSerializationImpl(deserializerTemp, internalSerde); - final ArangoSerialization custom = customSerializer != null ? customSerializer : new ArangoSerializationImpl(deserializerTemp, JacksonSerde.of(DataType.of(protocol))); + final InternalSerialization internal = new InternalSerializationImpl(internalSerde); + final ArangoSerialization custom = customSerializer != null ? customSerializer : new ArangoSerializationImpl(JacksonSerde.of(DataType.of(protocol))); final ArangoSerializationFactory util = new ArangoSerializationFactory(internal, custom); int protocolMaxConnections = protocol == Protocol.VST ? diff --git a/src/main/java/com/arangodb/async/ArangoDBAsync.java b/src/main/java/com/arangodb/async/ArangoDBAsync.java index aae9d3684..275adf982 100644 --- a/src/main/java/com/arangodb/async/ArangoDBAsync.java +++ b/src/main/java/com/arangodb/async/ArangoDBAsync.java @@ -517,11 +517,9 @@ public synchronized ArangoDBAsync build() { final VPack vpacker = vpackBuilder.serializeNullValues(false).build(); final VPack vpackerNull = vpackBuilder.serializeNullValues(true).build(); final VPackParser vpackParser = vpackParserBuilder.build(); - final ArangoDeserializer deserializerTemp = deserializer != null ? deserializer - : new ArangoDeserializerImpl(vpackerNull, vpackParser); final InternalSerde internalSerde = InternalSerde.of(DataType.VPACK); - final InternalSerializationImpl internal = new InternalSerializationImpl(deserializerTemp, internalSerde); - final ArangoSerialization custom = customSerializer != null ? customSerializer : new ArangoSerializationImpl(deserializerTemp, JacksonSerde.of(DataType.VPACK)); + final InternalSerializationImpl internal = new InternalSerializationImpl(internalSerde); + final ArangoSerialization custom = customSerializer != null ? customSerializer : new ArangoSerializationImpl(JacksonSerde.of(DataType.VPACK)); final ArangoSerializationFactory util = new ArangoSerializationFactory(internal, custom); final int max = maxConnections != null ? Math.max(1, maxConnections) diff --git a/src/main/java/com/arangodb/entity/CursorEntity.java b/src/main/java/com/arangodb/entity/CursorEntity.java index 66a9a7010..5e73fbe9f 100644 --- a/src/main/java/com/arangodb/entity/CursorEntity.java +++ b/src/main/java/com/arangodb/entity/CursorEntity.java @@ -21,6 +21,7 @@ package com.arangodb.entity; import com.arangodb.velocypack.VPackSlice; +import com.fasterxml.jackson.databind.JsonNode; import java.util.Collection; import java.util.Collections; @@ -38,7 +39,7 @@ public class CursorEntity implements Entity, MetaAware { private Extras extra = new Extras(); private Boolean cached; private Boolean hasMore; - private VPackSlice result; + private JsonNode result; private Map meta; @@ -83,7 +84,7 @@ public Boolean getHasMore() { /** * @return an vpack-array of result documents (might be empty if query has no results) */ - public VPackSlice getResult() { + public JsonNode getResult() { return result; } diff --git a/src/main/java/com/arangodb/internal/ArangoResponseField.java b/src/main/java/com/arangodb/internal/ArangoResponseField.java index 846774a3e..2a828cc03 100644 --- a/src/main/java/com/arangodb/internal/ArangoResponseField.java +++ b/src/main/java/com/arangodb/internal/ArangoResponseField.java @@ -29,7 +29,7 @@ private ArangoResponseField() { super(); } - public static final String ERROR = "error"; - public static final String RESULT = "result"; + public static final String ERROR = "/error"; + public static final String RESULT = "/result"; } diff --git a/src/main/java/com/arangodb/internal/InternalArangoCollection.java b/src/main/java/com/arangodb/internal/InternalArangoCollection.java index 298772824..3bb982a51 100644 --- a/src/main/java/com/arangodb/internal/InternalArangoCollection.java +++ b/src/main/java/com/arangodb/internal/InternalArangoCollection.java @@ -29,7 +29,6 @@ import com.arangodb.model.*; import com.arangodb.serde.SerdeUtils; import com.arangodb.velocypack.Type; -import com.arangodb.velocypack.VPackSlice; import com.arangodb.velocystream.Request; import com.arangodb.velocystream.RequestType; import com.fasterxml.jackson.databind.JsonNode; @@ -105,15 +104,15 @@ protected Request insertDocumentRequest(final T value, final DocumentCreateO protected ResponseDeserializer> insertDocumentResponseDeserializer( final T value, final DocumentCreateOptions options) { return response -> { - final VPackSlice body = response.getBody(); + final JsonNode body = getInternalSerialization().parse(response.getBody()); final DocumentCreateEntity doc = getInternalSerialization().deserialize(body, DocumentCreateEntity.class); - final VPackSlice newDoc = body.get(NEW); + final JsonNode newDoc = body.get(NEW); if (newDoc.isObject()) { - doc.setNew(getUserSerialization().deserialize(newDoc, value.getClass())); + doc.setNew(getUserSerialization().deserialize(getInternalSerialization().serialize(newDoc), value.getClass())); } - final VPackSlice oldDoc = body.get(OLD); + final JsonNode oldDoc = body.get(OLD); if (oldDoc.isObject()) { - doc.setOld(getUserSerialization().deserialize(oldDoc, value.getClass())); + doc.setOld(getUserSerialization().deserialize(getInternalSerialization().serialize(oldDoc), value.getClass())); } if (options == null || Boolean.TRUE != options.getSilent()) { final Map values = new HashMap<>(); @@ -156,23 +155,23 @@ protected ResponseDeserializer>> final Collection> docs = new ArrayList<>(); final Collection errors = new ArrayList<>(); final Collection documentsAndErrors = new ArrayList<>(); - final VPackSlice body = response.getBody(); + final JsonNode body = getInternalSerialization().parse(response.getBody()); if (body.isArray()) { - for (final Iterator iterator = body.arrayIterator(); iterator.hasNext(); ) { - final VPackSlice next = iterator.next(); - if (next.get(ArangoResponseField.ERROR).isTrue()) { + for (final Iterator iterator = body.iterator(); iterator.hasNext(); ) { + final JsonNode next = iterator.next(); + if (next.get(ArangoResponseField.ERROR).booleanValue()) { final ErrorEntity error = getInternalSerialization().deserialize(next, ErrorEntity.class); errors.add(error); documentsAndErrors.add(error); } else { final DocumentCreateEntity doc = getInternalSerialization().deserialize(next, DocumentCreateEntity.class); - final VPackSlice newDoc = next.get(NEW); + final JsonNode newDoc = next.get(NEW); if (newDoc.isObject()) { - doc.setNew(getUserSerialization().deserialize(newDoc, type)); + doc.setNew(getUserSerialization().deserialize(getInternalSerialization().serialize(newDoc), type)); } - final VPackSlice oldDoc = next.get(OLD); + final JsonNode oldDoc = next.get(OLD); if (oldDoc.isObject()) { - doc.setOld(getUserSerialization().deserialize(oldDoc, type)); + doc.setOld(getUserSerialization().deserialize(getInternalSerialization().serialize(oldDoc), type)); } docs.add(doc); documentsAndErrors.add(doc); @@ -238,15 +237,15 @@ protected ResponseDeserializer> getDocumentsResponseD final Collection docs = new ArrayList<>(); final Collection errors = new ArrayList<>(); final Collection documentsAndErrors = new ArrayList<>(); - final VPackSlice body = response.getBody(); - for (final Iterator iterator = body.arrayIterator(); iterator.hasNext(); ) { - final VPackSlice next = iterator.next(); - if (next.get(ArangoResponseField.ERROR).isTrue()) { + final JsonNode body = getInternalSerialization().parse(response.getBody()); + for (final Iterator iterator = body.iterator(); iterator.hasNext(); ) { + final JsonNode next = iterator.next(); + if (next.get(ArangoResponseField.ERROR).booleanValue()) { final ErrorEntity error = getInternalSerialization().deserialize(next, ErrorEntity.class); errors.add(error); documentsAndErrors.add(error); } else { - final T doc = getUserSerialization().deserialize(next, type); + final T doc = getUserSerialization().deserialize(getInternalSerialization().serialize(next), type); docs.add(doc); documentsAndErrors.add(doc); } @@ -277,15 +276,15 @@ protected Request replaceDocumentRequest( protected ResponseDeserializer> replaceDocumentResponseDeserializer( final T value, final DocumentReplaceOptions options) { return response -> { - final VPackSlice body = response.getBody(); + final JsonNode body = getInternalSerialization().parse(response.getBody()); final DocumentUpdateEntity doc = getInternalSerialization().deserialize(body, DocumentUpdateEntity.class); - final VPackSlice newDoc = body.get(NEW); + final JsonNode newDoc = body.get(NEW); if (newDoc.isObject()) { - doc.setNew(getUserSerialization().deserialize(newDoc, value.getClass())); + doc.setNew(getUserSerialization().deserialize(getInternalSerialization().serialize(newDoc), value.getClass())); } - final VPackSlice oldDoc = body.get(OLD); + final JsonNode oldDoc = body.get(OLD); if (oldDoc.isObject()) { - doc.setOld(getUserSerialization().deserialize(oldDoc, value.getClass())); + doc.setOld(getUserSerialization().deserialize(getInternalSerialization().serialize(oldDoc), value.getClass())); } if (options == null || Boolean.TRUE != options.getSilent()) { final Map values = new HashMap<>(); @@ -326,23 +325,23 @@ protected ResponseDeserializer>> final Collection> docs = new ArrayList<>(); final Collection errors = new ArrayList<>(); final Collection documentsAndErrors = new ArrayList<>(); - final VPackSlice body = response.getBody(); + final JsonNode body = getInternalSerialization().parse(response.getBody()); if (body.isArray()) { - for (final Iterator iterator = body.arrayIterator(); iterator.hasNext(); ) { - final VPackSlice next = iterator.next(); - if (next.get(ArangoResponseField.ERROR).isTrue()) { + for (final Iterator iterator = body.iterator(); iterator.hasNext(); ) { + final JsonNode next = iterator.next(); + if (next.get(ArangoResponseField.ERROR).booleanValue()) { final ErrorEntity error = getInternalSerialization().deserialize(next, ErrorEntity.class); errors.add(error); documentsAndErrors.add(error); } else { final DocumentUpdateEntity doc = getInternalSerialization().deserialize(next, DocumentUpdateEntity.class); - final VPackSlice newDoc = next.get(NEW); + final JsonNode newDoc = next.get(NEW); if (newDoc.isObject()) { - doc.setNew(getUserSerialization().deserialize(newDoc, type)); + doc.setNew(getUserSerialization().deserialize(getInternalSerialization().serialize(newDoc), type)); } - final VPackSlice oldDoc = next.get(OLD); + final JsonNode oldDoc = next.get(OLD); if (oldDoc.isObject()) { - doc.setOld(getUserSerialization().deserialize(oldDoc, type)); + doc.setOld(getUserSerialization().deserialize(getInternalSerialization().serialize(oldDoc), type)); } docs.add(doc); documentsAndErrors.add(doc); @@ -376,15 +375,15 @@ protected Request updateDocumentRequest(final String key, final T value, fin protected ResponseDeserializer> updateDocumentResponseDeserializer( final T value, final DocumentUpdateOptions options, final Class returnType) { return response -> { - final VPackSlice body = response.getBody(); + final JsonNode body = getInternalSerialization().parse(response.getBody()); final DocumentUpdateEntity doc = getInternalSerialization().deserialize(body, DocumentUpdateEntity.class); - final VPackSlice newDoc = body.get(NEW); + final JsonNode newDoc = body.get(NEW); if (newDoc.isObject()) { - doc.setNew(getUserSerialization().deserialize(newDoc, returnType)); + doc.setNew(getUserSerialization().deserialize(getInternalSerialization().serialize(newDoc), returnType)); } - final VPackSlice oldDoc = body.get(OLD); + final JsonNode oldDoc = body.get(OLD); if (oldDoc.isObject()) { - doc.setOld(getUserSerialization().deserialize(oldDoc, returnType)); + doc.setOld(getUserSerialization().deserialize(getInternalSerialization().serialize(oldDoc), returnType)); } if (options == null || Boolean.TRUE != options.getSilent()) { final Map values = new HashMap<>(); @@ -422,23 +421,23 @@ protected ResponseDeserializer>> final Collection> docs = new ArrayList<>(); final Collection errors = new ArrayList<>(); final Collection documentsAndErrors = new ArrayList<>(); - final VPackSlice body = response.getBody(); + final JsonNode body = getInternalSerialization().parse(response.getBody()); if (body.isArray()) { - for (final Iterator iterator = body.arrayIterator(); iterator.hasNext(); ) { - final VPackSlice next = iterator.next(); - if (next.get(ArangoResponseField.ERROR).isTrue()) { + for (final Iterator iterator = body.iterator(); iterator.hasNext(); ) { + final JsonNode next = iterator.next(); + if (next.get(ArangoResponseField.ERROR).booleanValue()) { final ErrorEntity error = getInternalSerialization().deserialize(next, ErrorEntity.class); errors.add(error); documentsAndErrors.add(error); } else { final DocumentUpdateEntity doc = getInternalSerialization().deserialize(next, DocumentUpdateEntity.class); - final VPackSlice newDoc = next.get(NEW); + final JsonNode newDoc = next.get(NEW); if (newDoc.isObject()) { - doc.setNew(getUserSerialization().deserialize(newDoc, returnType)); + doc.setNew(getUserSerialization().deserialize(getInternalSerialization().serialize(newDoc), returnType)); } - final VPackSlice oldDoc = next.get(OLD); + final JsonNode oldDoc = next.get(OLD); if (oldDoc.isObject()) { - doc.setOld(getUserSerialization().deserialize(oldDoc, returnType)); + doc.setOld(getUserSerialization().deserialize(getInternalSerialization().serialize(oldDoc), returnType)); } docs.add(doc); documentsAndErrors.add(doc); @@ -467,11 +466,11 @@ protected Request deleteDocumentRequest(final String key, final DocumentDeleteOp protected ResponseDeserializer> deleteDocumentResponseDeserializer( final Class type) { return response -> { - final VPackSlice body = response.getBody(); + final JsonNode body = getInternalSerialization().parse(response.getBody()); final DocumentDeleteEntity doc = getInternalSerialization().deserialize(body, DocumentDeleteEntity.class); - final VPackSlice oldDoc = body.get(OLD); + final JsonNode oldDoc = body.get(OLD); if (oldDoc.isObject()) { - doc.setOld(getUserSerialization().deserialize(oldDoc, type)); + doc.setOld(getUserSerialization().deserialize(getInternalSerialization().serialize(oldDoc), type)); } return doc; }; @@ -495,19 +494,19 @@ protected ResponseDeserializer>> final Collection> docs = new ArrayList<>(); final Collection errors = new ArrayList<>(); final Collection documentsAndErrors = new ArrayList<>(); - final VPackSlice body = response.getBody(); + final JsonNode body = getInternalSerialization().parse(response.getBody()); if (body.isArray()) { - for (final Iterator iterator = body.arrayIterator(); iterator.hasNext(); ) { - final VPackSlice next = iterator.next(); - if (next.get(ArangoResponseField.ERROR).isTrue()) { + for (final Iterator iterator = body.iterator(); iterator.hasNext(); ) { + final JsonNode next = iterator.next(); + if (next.get(ArangoResponseField.ERROR).booleanValue()) { final ErrorEntity error = getInternalSerialization().deserialize(next, ErrorEntity.class); errors.add(error); documentsAndErrors.add(error); } else { final DocumentDeleteEntity doc = getInternalSerialization().deserialize(next, DocumentDeleteEntity.class); - final VPackSlice oldDoc = next.get(OLD); + final JsonNode oldDoc = next.get(OLD); if (oldDoc.isObject()) { - doc.setOld(getUserSerialization().deserialize(oldDoc, type)); + doc.setOld(getUserSerialization().deserialize(getInternalSerialization().serialize(oldDoc), type)); } docs.add(doc); documentsAndErrors.add(doc); @@ -540,7 +539,7 @@ protected Request deleteIndexRequest(final String id) { } protected ResponseDeserializer deleteIndexResponseDeserializer() { - return response -> response.getBody().get("id").getAsString(); + return response -> getInternalSerialization().deserialize(response.getBody(), "id", String.class); } private String createIndexId(final String id) { @@ -622,7 +621,7 @@ protected Request getIndexesRequest() { } protected ResponseDeserializer> getIndexesResponseDeserializer() { - return response -> getInternalSerialization().deserialize(response.getBody().get("indexes"), new Type>() { + return response -> getInternalSerialization().deserialize(response.getBody(), "indexes", new Type>() { }.getType()); } @@ -690,16 +689,7 @@ protected Request getPermissionsRequest(final String user) { } protected ResponseDeserializer getPermissionsResponseDeserialzer() { - return response -> { - final VPackSlice body = response.getBody(); - if (body != null) { - final VPackSlice result = body.get(ArangoResponseField.RESULT); - if (!result.isNone()) { - return getInternalSerialization().deserialize(result, Permissions.class); - } - } - return null; - }; + return response -> getInternalSerialization().deserialize(response.getBody(), ArangoResponseField.RESULT, Permissions.class); } private boolean isStringCollection(final Collection values) { diff --git a/src/main/java/com/arangodb/internal/InternalArangoDB.java b/src/main/java/com/arangodb/internal/InternalArangoDB.java index e1ccaeef5..49c545c60 100644 --- a/src/main/java/com/arangodb/internal/InternalArangoDB.java +++ b/src/main/java/com/arangodb/internal/InternalArangoDB.java @@ -21,19 +21,20 @@ package com.arangodb.internal; import com.arangodb.DbName; -import com.arangodb.entity.*; +import com.arangodb.entity.LogLevelEntity; +import com.arangodb.entity.Permissions; +import com.arangodb.entity.ServerRole; +import com.arangodb.entity.UserEntity; import com.arangodb.internal.ArangoExecutor.ResponseDeserializer; import com.arangodb.internal.util.ArangoSerializationFactory; import com.arangodb.model.*; import com.arangodb.velocypack.Type; -import com.arangodb.velocypack.VPackSlice; import com.arangodb.velocystream.Request; import com.arangodb.velocystream.RequestType; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; -import java.util.Map.Entry; /** * @author Mark Vollmary @@ -62,11 +63,11 @@ protected Request getServerIdRequest() { } protected ResponseDeserializer getRoleResponseDeserializer() { - return response -> getInternalSerialization().deserialize(response.getBody().get("role"), ServerRole.class); + return response -> getInternalSerialization().deserialize(response.getBody(), "/role", ServerRole.class); } protected ResponseDeserializer getServerIdResponseDeserializer() { - return response -> getInternalSerialization().deserialize(response.getBody().get("id"), String.class); + return response -> getInternalSerialization().deserialize(response.getBody(), "/id", String.class); } protected Request createDatabaseRequest(final DBCreateOptions options) { @@ -77,7 +78,7 @@ protected Request createDatabaseRequest(final DBCreateOptions options) { } protected ResponseDeserializer createDatabaseResponseDeserializer() { - return response -> response.getBody().get(ArangoResponseField.RESULT).getAsBoolean(); + return response -> getInternalSerialization().deserialize(response.getBody(), ArangoResponseField.RESULT, Boolean.class); } protected Request getDatabasesRequest(final DbName dbName) { @@ -85,11 +86,8 @@ protected Request getDatabasesRequest(final DbName dbName) { } protected ResponseDeserializer> getDatabaseResponseDeserializer() { - return response -> { - final VPackSlice result = response.getBody().get(ArangoResponseField.RESULT); - return getInternalSerialization().deserialize(result, new Type>() { - }.getType()); - }; + return response -> getInternalSerialization().deserialize(response.getBody(), ArangoResponseField.RESULT, new Type>() { + }.getType()); } protected Request getAccessibleDatabasesForRequest(final DbName dbName, final String user) { @@ -98,11 +96,10 @@ protected Request getAccessibleDatabasesForRequest(final DbName dbName, final St protected ResponseDeserializer> getAccessibleDatabasesForResponseDeserializer() { return response -> { - final VPackSlice result = response.getBody().get(ArangoResponseField.RESULT); + Iterator names = getInternalSerialization().parse(response.getBody(), ArangoResponseField.RESULT).fieldNames(); final Collection dbs = new ArrayList<>(); - for (final Iterator> iterator = result.objectIterator(); iterator - .hasNext(); ) { - dbs.add(iterator.next().getKey()); + while (names.hasNext()) { + dbs.add(names.next()); } return dbs; }; @@ -133,11 +130,8 @@ protected Request getUserRequest(final DbName dbName, final String user) { } protected ResponseDeserializer> getUsersResponseDeserializer() { - return response -> { - final VPackSlice result = response.getBody().get(ArangoResponseField.RESULT); - return getInternalSerialization().deserialize(result, new Type>() { - }.getType()); - }; + return response -> getInternalSerialization().deserialize(response.getBody(), ArangoResponseField.RESULT, new Type>() { + }.getType()); } protected Request updateUserRequest(final DbName dbName, final String user, final UserUpdateOptions options) { diff --git a/src/main/java/com/arangodb/internal/InternalArangoDatabase.java b/src/main/java/com/arangodb/internal/InternalArangoDatabase.java index ba2ca8237..ba23a1c66 100644 --- a/src/main/java/com/arangodb/internal/InternalArangoDatabase.java +++ b/src/main/java/com/arangodb/internal/InternalArangoDatabase.java @@ -41,8 +41,7 @@ * @author Mark Vollmary * @author Michele Rastelli */ -public abstract class InternalArangoDatabase, EXECUTOR extends ArangoExecutor> - extends ArangoExecuteable { +public abstract class InternalArangoDatabase, EXECUTOR extends ArangoExecutor> extends ArangoExecuteable { protected static final String PATH_API_DATABASE = "/_api/database"; private static final String PATH_API_VERSION = "/_api/version"; @@ -98,8 +97,7 @@ protected Request getEngineRequest() { protected Request createCollectionRequest(final String name, final CollectionCreateOptions options) { - byte[] body = getInternalSerialization() - .serialize(OptionsBuilder.build(options != null ? options : new CollectionCreateOptions(), name)); + byte[] body = getInternalSerialization().serialize(OptionsBuilder.build(options != null ? options : new CollectionCreateOptions(), name)); return request(dbName, RequestType.POST, InternalArangoCollection.PATH_API_COLLECTION).setBody(body); } @@ -113,11 +111,8 @@ protected Request getCollectionsRequest(final CollectionsReadOptions options) { } protected ResponseDeserializer> getCollectionsResponseDeserializer() { - return response -> { - final VPackSlice result = response.getBody().get(ArangoResponseField.RESULT); - return getInternalSerialization().deserialize(result, new Type>() { - }.getType()); - }; + return response -> getInternalSerialization().deserialize(getInternalSerialization().parse(response.getBody(), ArangoResponseField.RESULT), new Type>() { + }.getType()); } protected Request dropRequest() { @@ -125,49 +120,32 @@ protected Request dropRequest() { } protected ResponseDeserializer createDropResponseDeserializer() { - return response -> response.getBody().get(ArangoResponseField.RESULT).getAsBoolean(); + return response -> getInternalSerialization().deserialize(response.getBody(), ArangoResponseField.RESULT, Boolean.class); } protected Request grantAccessRequest(final String user, final Permissions permissions) { - return request(DbName.SYSTEM, RequestType.PUT, PATH_API_USER, user, ArangoRequestParam.DATABASE, - dbName.get()).setBody(getInternalSerialization().serialize(OptionsBuilder.build(new UserAccessOptions(), permissions))); + return request(DbName.SYSTEM, RequestType.PUT, PATH_API_USER, user, ArangoRequestParam.DATABASE, dbName.get()).setBody(getInternalSerialization().serialize(OptionsBuilder.build(new UserAccessOptions(), permissions))); } protected Request resetAccessRequest(final String user) { - return request(DbName.SYSTEM, RequestType.DELETE, PATH_API_USER, user, ArangoRequestParam.DATABASE, - dbName.get()); + return request(DbName.SYSTEM, RequestType.DELETE, PATH_API_USER, user, ArangoRequestParam.DATABASE, dbName.get()); } protected Request updateUserDefaultCollectionAccessRequest(final String user, final Permissions permissions) { - return request(DbName.SYSTEM, RequestType.PUT, PATH_API_USER, user, ArangoRequestParam.DATABASE, - dbName.get(), "*").setBody(getInternalSerialization().serialize(OptionsBuilder.build(new UserAccessOptions(), permissions))); + return request(DbName.SYSTEM, RequestType.PUT, PATH_API_USER, user, ArangoRequestParam.DATABASE, dbName.get(), "*").setBody(getInternalSerialization().serialize(OptionsBuilder.build(new UserAccessOptions(), permissions))); } protected Request getPermissionsRequest(final String user) { - return request(DbName.SYSTEM, RequestType.GET, PATH_API_USER, user, ArangoRequestParam.DATABASE, - dbName.get()); + return request(DbName.SYSTEM, RequestType.GET, PATH_API_USER, user, ArangoRequestParam.DATABASE, dbName.get()); } protected ResponseDeserializer getPermissionsResponseDeserialzer() { - return response -> { - final VPackSlice body = response.getBody(); - if (body != null) { - final VPackSlice result = body.get(ArangoResponseField.RESULT); - if (!result.isNone()) { - return getInternalSerialization().deserialize(result, Permissions.class); - } - } - return null; - }; - } - - protected Request queryRequest( - final String query, final Map bindVars, final AqlQueryOptions options) { + return response -> getInternalSerialization().deserialize(response.getBody(), ArangoResponseField.RESULT, Permissions.class); + } + + protected Request queryRequest(final String query, final Map bindVars, final AqlQueryOptions options) { final AqlQueryOptions opt = options != null ? options : new AqlQueryOptions(); - final Request request = request(dbName, RequestType.POST, PATH_API_CURSOR) - .setBody(getInternalSerialization().serialize(OptionsBuilder - .build(opt, query, bindVars != null ? - getUserSerialization().serialize(bindVars) : null))); + final Request request = request(dbName, RequestType.POST, PATH_API_CURSOR).setBody(getInternalSerialization().serialize(OptionsBuilder.build(opt, query, bindVars != null ? getUserSerialization().serialize(bindVars) : null))); if (opt.getAllowDirtyRead() == Boolean.TRUE) { RequestUtils.allowDirtyRead(request); } @@ -209,24 +187,15 @@ protected Request queryCloseRequest(final String id, final AqlQueryOptions optio return request; } - protected Request explainQueryRequest( - final String query, - final Map bindVars, - final AqlQueryExplainOptions options - ) { + protected Request explainQueryRequest(final String query, final Map bindVars, final AqlQueryExplainOptions options) { final AqlQueryExplainOptions opt = options != null ? options : new AqlQueryExplainOptions(); - return request(dbName, RequestType.POST, PATH_API_EXPLAIN) - .setBody(getInternalSerialization().serialize(OptionsBuilder.build( - opt, - query, - bindVars != null ? new VPackSlice(getUserSerialization().serialize(bindVars)) : null))); + return request(dbName, RequestType.POST, PATH_API_EXPLAIN).setBody(getInternalSerialization().serialize(OptionsBuilder.build(opt, query, bindVars != null ? new VPackSlice(getUserSerialization().serialize(bindVars)) : null))); } protected Request parseQueryRequest(final String query) { - return request(dbName, RequestType.POST, PATH_API_QUERY) - .setBody(getInternalSerialization().serialize(OptionsBuilder.build(new AqlQueryParseOptions(), query))); + return request(dbName, RequestType.POST, PATH_API_QUERY).setBody(getInternalSerialization().serialize(OptionsBuilder.build(new AqlQueryParseOptions(), query))); } protected Request clearQueryCacheRequest() { @@ -265,10 +234,8 @@ protected Request killQueryRequest(final String id) { return request(dbName, RequestType.DELETE, PATH_API_QUERY, id); } - protected Request createAqlFunctionRequest( - final String name, final String code, final AqlFunctionCreateOptions options) { - return request(dbName, RequestType.POST, PATH_API_AQLFUNCTION).setBody(getInternalSerialization().serialize( - OptionsBuilder.build(options != null ? options : new AqlFunctionCreateOptions(), name, code))); + protected Request createAqlFunctionRequest(final String name, final String code, final AqlFunctionCreateOptions options) { + return request(dbName, RequestType.POST, PATH_API_AQLFUNCTION).setBody(getInternalSerialization().serialize(OptionsBuilder.build(options != null ? options : new AqlFunctionCreateOptions(), name, code))); } protected Request deleteAqlFunctionRequest(final String name, final AqlFunctionDeleteOptions options) { @@ -279,19 +246,7 @@ protected Request deleteAqlFunctionRequest(final String name, final AqlFunctionD } protected ResponseDeserializer deleteAqlFunctionResponseDeserializer() { - return response -> { - // compatibility with ArangoDB < 3.4 - // https://www.arangodb.com/docs/stable/release-notes-upgrading-changes34.html - Integer count = null; - final VPackSlice body = response.getBody(); - if (body.isObject()) { - final VPackSlice deletedCount = body.get("deletedCount"); - if (deletedCount.isInteger()) { - count = deletedCount.getAsInt(); - } - } - return count; - }; + return response -> getInternalSerialization().deserialize(response.getBody(), "/deletedCount", Integer.class); } protected Request getAqlFunctionsRequest(final AqlFunctionGetOptions options) { @@ -302,24 +257,16 @@ protected Request getAqlFunctionsRequest(final AqlFunctionGetOptions options) { } protected ResponseDeserializer> getAqlFunctionsResponseDeserializer() { - return response -> { - final VPackSlice body = response.getBody(); - // compatibility with ArangoDB < 3.4 - // https://www.arangodb.com/docs/stable/release-notes-upgrading-changes34.html - final VPackSlice result = body.isArray() ? body : body.get(ArangoResponseField.RESULT); - return getInternalSerialization().deserialize(result, new Type>() { - }.getType()); - }; + return response -> getInternalSerialization().deserialize(response.getBody(), ArangoResponseField.RESULT, new Type>() { + }.getType()); } - protected Request createGraphRequest( - final String name, final Collection edgeDefinitions, final GraphCreateOptions options) { - return request(dbName, RequestType.POST, InternalArangoGraph.PATH_API_GHARIAL).setBody(getInternalSerialization().serialize( - OptionsBuilder.build(options != null ? options : new GraphCreateOptions(), name, edgeDefinitions))); + protected Request createGraphRequest(final String name, final Collection edgeDefinitions, final GraphCreateOptions options) { + return request(dbName, RequestType.POST, InternalArangoGraph.PATH_API_GHARIAL).setBody(getInternalSerialization().serialize(OptionsBuilder.build(options != null ? options : new GraphCreateOptions(), name, edgeDefinitions))); } protected ResponseDeserializer createGraphResponseDeserializer() { - return response -> getInternalSerialization().deserialize(response.getBody().get("graph"), GraphEntity.class); + return response -> getInternalSerialization().deserialize(response.getBody(), "/graph", GraphEntity.class); } protected Request getGraphsRequest() { @@ -327,31 +274,20 @@ protected Request getGraphsRequest() { } protected ResponseDeserializer> getGraphsResponseDeserializer() { - return response -> getInternalSerialization().deserialize(response.getBody().get("graphs"), new Type>() { + return response -> getInternalSerialization().deserialize(response.getBody(), "/graphs", new Type>() { }.getType()); } protected Request transactionRequest(final String action, final TransactionOptions options) { - return request(dbName, RequestType.POST, PATH_API_TRANSACTION).setBody( - getInternalSerialization().serialize(OptionsBuilder.build(options != null ? options : new TransactionOptions(), action))); + return request(dbName, RequestType.POST, PATH_API_TRANSACTION).setBody(getInternalSerialization().serialize(OptionsBuilder.build(options != null ? options : new TransactionOptions(), action))); } protected ResponseDeserializer transactionResponseDeserializer(final Class type) { - return response -> { - final VPackSlice body = response.getBody(); - if (body != null) { - final VPackSlice result = body.get(ArangoResponseField.RESULT); - if (!result.isNone() && !result.isNull()) { - return getUserSerialization().deserialize(result, type); - } - } - return null; - }; + return response -> getUserSerialization().deserialize(getInternalSerialization().extract(response.getBody(), ArangoResponseField.RESULT), type); } protected Request beginStreamTransactionRequest(final StreamTransactionOptions options) { - return request(dbName, RequestType.POST, PATH_API_BEGIN_STREAM_TRANSACTION) - .setBody(getInternalSerialization().serialize(options != null ? options : new StreamTransactionOptions())); + return request(dbName, RequestType.POST, PATH_API_BEGIN_STREAM_TRANSACTION).setBody(getInternalSerialization().serialize(options != null ? options : new StreamTransactionOptions())); } protected Request abortStreamTransactionRequest(String id) { @@ -367,11 +303,8 @@ protected Request getStreamTransactionRequest(String id) { } protected ResponseDeserializer> transactionsResponseDeserializer() { - return response -> { - final VPackSlice result = response.getBody().get("transactions"); - return getInternalSerialization().deserialize(result, new Type>() { - }.getType()); - }; + return response -> getInternalSerialization().deserialize(response.getBody(), "/transactions", new Type>() { + }.getType()); } protected Request commitStreamTransactionRequest(String id) { @@ -379,8 +312,7 @@ protected Request commitStreamTransactionRequest(String id) { } protected ResponseDeserializer streamTransactionResponseDeserializer() { - return response -> getInternalSerialization() - .deserialize(response.getBody().get(ArangoResponseField.RESULT), StreamTransactionEntity.class); + return response -> getInternalSerialization().deserialize(response.getBody(), ArangoResponseField.RESULT, StreamTransactionEntity.class); } protected Request getInfoRequest() { @@ -388,7 +320,7 @@ protected Request getInfoRequest() { } protected ResponseDeserializer getInfoResponseDeserializer() { - return response -> getInternalSerialization().deserialize(response.getBody().get(ArangoResponseField.RESULT), DatabaseEntity.class); + return response -> getInternalSerialization().deserialize(response.getBody(), ArangoResponseField.RESULT, DatabaseEntity.class); } protected Request reloadRoutingRequest() { @@ -400,21 +332,16 @@ protected Request getViewsRequest() { } protected ResponseDeserializer> getViewsResponseDeserializer() { - return response -> { - final VPackSlice result = response.getBody().get(ArangoResponseField.RESULT); - return getInternalSerialization().deserialize(result, new Type>() { - }.getType()); - }; + return response -> getInternalSerialization().deserialize(response.getBody(), ArangoResponseField.RESULT, new Type>() { + }.getType()); } protected Request createViewRequest(final String name, final ViewType type) { - return request(dbName, RequestType.POST, InternalArangoView.PATH_API_VIEW) - .setBody(getInternalSerialization().serialize(OptionsBuilder.build(new ViewCreateOptions(), name, type))); + return request(dbName, RequestType.POST, InternalArangoView.PATH_API_VIEW).setBody(getInternalSerialization().serialize(OptionsBuilder.build(new ViewCreateOptions(), name, type))); } protected Request createArangoSearchRequest(final String name, final ArangoSearchCreateOptions options) { - return request(dbName, RequestType.POST, InternalArangoView.PATH_API_VIEW).setBody(getInternalSerialization().serialize( - ArangoSearchOptionsBuilder.build(options != null ? options : new ArangoSearchCreateOptions(), name))); + return request(dbName, RequestType.POST, InternalArangoView.PATH_API_VIEW).setBody(getInternalSerialization().serialize(ArangoSearchOptionsBuilder.build(options != null ? options : new ArangoSearchCreateOptions(), name))); } protected Request getAnalyzerRequest(final String name) { @@ -426,16 +353,12 @@ protected Request getAnalyzersRequest() { } protected ResponseDeserializer> getSearchAnalyzersResponseDeserializer() { - return response -> { - final VPackSlice result = response.getBody().get(ArangoResponseField.RESULT); - return getInternalSerialization().deserialize(result, new Type>() { - }.getType()); - }; + return response -> getInternalSerialization().deserialize(response.getBody(), ArangoResponseField.RESULT, new Type>() { + }.getType()); } protected Request createAnalyzerRequest(final SearchAnalyzer options) { - return request(dbName, RequestType.POST, InternalArangoView.PATH_API_ANALYZER) - .setBody(getInternalSerialization().serialize(options)); + return request(dbName, RequestType.POST, InternalArangoView.PATH_API_ANALYZER).setBody(getInternalSerialization().serialize(options)); } protected Request deleteAnalyzerRequest(final String name, final AnalyzerDeleteOptions options) { diff --git a/src/main/java/com/arangodb/internal/InternalArangoEdgeCollection.java b/src/main/java/com/arangodb/internal/InternalArangoEdgeCollection.java index 0c84c3734..cb24a0730 100644 --- a/src/main/java/com/arangodb/internal/InternalArangoEdgeCollection.java +++ b/src/main/java/com/arangodb/internal/InternalArangoEdgeCollection.java @@ -26,7 +26,6 @@ import com.arangodb.internal.util.DocumentUtil; import com.arangodb.internal.util.RequestUtils; import com.arangodb.model.*; -import com.arangodb.velocypack.VPackSlice; import com.arangodb.velocystream.Request; import com.arangodb.velocystream.RequestType; @@ -73,8 +72,7 @@ protected Request insertEdgeRequest(final T value, final EdgeCreateOptions o protected ResponseDeserializer insertEdgeResponseDeserializer(final T value) { return response -> { - final VPackSlice body = response.getBody().get(EDGE); - final EdgeEntity doc = getInternalSerialization().deserialize(body, EdgeEntity.class); + final EdgeEntity doc = getInternalSerialization().deserialize(response.getBody(), EDGE, EdgeEntity.class); final Map values = new HashMap<>(); values.put(DocumentFields.ID, doc.getId()); values.put(DocumentFields.KEY, doc.getKey()); @@ -98,7 +96,7 @@ protected Request getEdgeRequest(final String key, final GraphDocumentReadOption } protected ResponseDeserializer getEdgeResponseDeserializer(final Class type) { - return response -> getUserSerialization().deserialize(response.getBody().get(EDGE), type); + return response -> getUserSerialization().deserialize(getInternalSerialization().extract(response.getBody(), EDGE), type); } protected Request replaceEdgeRequest(final String key, final T value, final EdgeReplaceOptions options) { @@ -114,8 +112,7 @@ protected Request replaceEdgeRequest(final String key, final T value, final protected ResponseDeserializer replaceEdgeResponseDeserializer(final T value) { return response -> { - final VPackSlice body = response.getBody().get(EDGE); - final EdgeUpdateEntity doc = getInternalSerialization().deserialize(body, EdgeUpdateEntity.class); + final EdgeUpdateEntity doc = getInternalSerialization().deserialize(response.getBody(), EDGE, EdgeUpdateEntity.class); final Map values = new HashMap<>(); values.put(DocumentFields.REV, doc.getRev()); executor.documentCache().setValues(value, values); @@ -138,8 +135,7 @@ protected Request updateEdgeRequest(final String key, final T value, final E protected ResponseDeserializer updateEdgeResponseDeserializer(final T value) { return response -> { - final VPackSlice body = response.getBody().get(EDGE); - final EdgeUpdateEntity doc = getInternalSerialization().deserialize(body, EdgeUpdateEntity.class); + final EdgeUpdateEntity doc = getInternalSerialization().deserialize(response.getBody(), EDGE, EdgeUpdateEntity.class); final Map values = new HashMap<>(); values.put(DocumentFields.REV, doc.getRev()); executor.documentCache().setValues(value, values); diff --git a/src/main/java/com/arangodb/internal/InternalArangoGraph.java b/src/main/java/com/arangodb/internal/InternalArangoGraph.java index 10059c705..e65d3a9cb 100644 --- a/src/main/java/com/arangodb/internal/InternalArangoGraph.java +++ b/src/main/java/com/arangodb/internal/InternalArangoGraph.java @@ -84,7 +84,7 @@ protected Request getVertexCollectionsRequest() { } protected ResponseDeserializer> getVertexCollectionsResponseDeserializer() { - return response -> getInternalSerialization().deserialize(response.getBody().get("collections"), new Type>() { + return response -> getInternalSerialization().deserialize(response.getBody(), "collections", new Type>() { }.getType()); } @@ -103,7 +103,7 @@ protected Request getEdgeDefinitionsRequest() { } protected ResponseDeserializer> getEdgeDefinitionsDeserializer() { - return response -> getInternalSerialization().deserialize(response.getBody().get("collections"), new Type>() { + return response -> getInternalSerialization().deserialize(response.getBody(), "collections", new Type>() { }.getType()); } @@ -114,7 +114,7 @@ protected Request addEdgeDefinitionRequest(final EdgeDefinition definition) { } protected ResponseDeserializer addEdgeDefinitionResponseDeserializer() { - return response -> getInternalSerialization().deserialize(response.getBody().get(GRAPH), GraphEntity.class); + return response -> getInternalSerialization().deserialize(response.getBody(), GRAPH, GraphEntity.class); } protected Request replaceEdgeDefinitionRequest(final EdgeDefinition definition) { @@ -125,7 +125,7 @@ protected Request replaceEdgeDefinitionRequest(final EdgeDefinition definition) } protected ResponseDeserializer replaceEdgeDefinitionResponseDeserializer() { - return response -> getInternalSerialization().deserialize(response.getBody().get(GRAPH), GraphEntity.class); + return response -> getInternalSerialization().deserialize(response.getBody(), GRAPH, GraphEntity.class); } protected Request removeEdgeDefinitionRequest(final String definitionName) { @@ -133,7 +133,7 @@ protected Request removeEdgeDefinitionRequest(final String definitionName) { } protected ResponseDeserializer removeEdgeDefinitionResponseDeserializer() { - return response -> getInternalSerialization().deserialize(response.getBody().get(GRAPH), GraphEntity.class); + return response -> getInternalSerialization().deserialize(response.getBody(), GRAPH, GraphEntity.class); } } diff --git a/src/main/java/com/arangodb/internal/InternalArangoVertexCollection.java b/src/main/java/com/arangodb/internal/InternalArangoVertexCollection.java index 7bc503289..92e03d195 100644 --- a/src/main/java/com/arangodb/internal/InternalArangoVertexCollection.java +++ b/src/main/java/com/arangodb/internal/InternalArangoVertexCollection.java @@ -27,7 +27,6 @@ import com.arangodb.internal.util.RequestUtils; import com.arangodb.model.*; import com.arangodb.serde.SerdeUtils; -import com.arangodb.velocypack.VPackSlice; import com.arangodb.velocystream.Request; import com.arangodb.velocystream.RequestType; @@ -85,8 +84,7 @@ protected Request insertVertexRequest(final T value, final VertexCreateOptio protected ResponseDeserializer insertVertexResponseDeserializer(final T value) { return response -> { - final VPackSlice body = response.getBody().get(VERTEX); - final VertexEntity doc = getInternalSerialization().deserialize(body, VertexEntity.class); + final VertexEntity doc = getInternalSerialization().deserialize(response.getBody(), VERTEX, VertexEntity.class); final Map values = new HashMap<>(); values.put(DocumentFields.ID, doc.getId()); values.put(DocumentFields.KEY, doc.getKey()); @@ -110,7 +108,7 @@ protected Request getVertexRequest(final String key, final GraphDocumentReadOpti } protected ResponseDeserializer getVertexResponseDeserializer(final Class type) { - return response -> getUserSerialization().deserialize(response.getBody().get(VERTEX), type); + return response -> getUserSerialization().deserialize(getInternalSerialization().extract(response.getBody(), VERTEX), type); } protected Request replaceVertexRequest(final String key, final T value, final VertexReplaceOptions options) { @@ -126,8 +124,7 @@ protected Request replaceVertexRequest(final String key, final T value, fina protected ResponseDeserializer replaceVertexResponseDeserializer(final T value) { return response -> { - final VPackSlice body = response.getBody().get(VERTEX); - final VertexUpdateEntity doc = getInternalSerialization().deserialize(body, VertexUpdateEntity.class); + final VertexUpdateEntity doc = getInternalSerialization().deserialize(response.getBody(), VERTEX, VertexUpdateEntity.class); final Map values = new HashMap<>(); values.put(DocumentFields.REV, doc.getRev()); executor.documentCache().setValues(value, values); @@ -150,8 +147,7 @@ protected Request updateVertexRequest(final String key, final T value, final protected ResponseDeserializer updateVertexResponseDeserializer(final T value) { return response -> { - final VPackSlice body = response.getBody().get(VERTEX); - final VertexUpdateEntity doc = getInternalSerialization().deserialize(body, VertexUpdateEntity.class); + final VertexUpdateEntity doc = getInternalSerialization().deserialize(response.getBody(), VERTEX, VertexUpdateEntity.class); final Map values = new HashMap<>(); values.put(DocumentFields.REV, doc.getRev()); executor.documentCache().setValues(value, values); diff --git a/src/main/java/com/arangodb/internal/cursor/ArangoCursorIterator.java b/src/main/java/com/arangodb/internal/cursor/ArangoCursorIterator.java index ff83bfbc4..8b108f8ff 100644 --- a/src/main/java/com/arangodb/internal/cursor/ArangoCursorIterator.java +++ b/src/main/java/com/arangodb/internal/cursor/ArangoCursorIterator.java @@ -25,7 +25,7 @@ import com.arangodb.entity.CursorEntity; import com.arangodb.internal.ArangoCursorExecute; import com.arangodb.internal.InternalArangoDatabase; -import com.arangodb.velocypack.VPackSlice; +import com.fasterxml.jackson.databind.JsonNode; import java.util.Iterator; import java.util.NoSuchElementException; @@ -37,7 +37,7 @@ public class ArangoCursorIterator implements ArangoIterator { private CursorEntity result; - private Iterator arrayIterator; + private Iterator arrayIterator; private final ArangoCursor cursor; private final InternalArangoDatabase db; @@ -50,7 +50,7 @@ protected ArangoCursorIterator(final ArangoCursor cursor, final ArangoCursorE this.execute = execute; this.db = db; this.result = result; - arrayIterator = result.getResult().arrayIterator(); + arrayIterator = result.getResult().iterator(); } public CursorEntity getResult() { @@ -66,15 +66,15 @@ public boolean hasNext() { public T next() { if (!arrayIterator.hasNext() && result.getHasMore()) { result = execute.next(cursor.getId(), result.getMeta()); - arrayIterator = result.getResult().arrayIterator(); + arrayIterator = result.getResult().iterator(); } if (!hasNext()) { throw new NoSuchElementException(); } - return deserialize(arrayIterator.next(), cursor.getType()); + return deserialize(db.getInternalSerialization().serialize(arrayIterator.next()), cursor.getType()); } - protected R deserialize(final VPackSlice result, final Class type) { + protected R deserialize(final byte[] result, final Class type) { return db.getUserSerialization().deserialize(result, type); } diff --git a/src/main/java/com/arangodb/internal/http/HttpConnection.java b/src/main/java/com/arangodb/internal/http/HttpConnection.java index 789c0abfc..3f46c0bd7 100644 --- a/src/main/java/com/arangodb/internal/http/HttpConnection.java +++ b/src/main/java/com/arangodb/internal/http/HttpConnection.java @@ -30,7 +30,6 @@ import com.arangodb.serde.DataType; import com.arangodb.util.InternalSerialization; import com.arangodb.velocypack.VPackParser; -import com.arangodb.velocypack.VPackSlice; import com.arangodb.velocystream.Request; import com.arangodb.velocystream.Response; import org.apache.http.*; @@ -349,20 +348,13 @@ private static void addHeader(final Request request, final HttpRequestBase httpR public Response buildResponse(final CloseableHttpResponse httpResponse) throws UnsupportedOperationException, IOException { - final Response response = new Response(dataType); + final Response response = new Response(); response.setResponseCode(httpResponse.getStatusLine().getStatusCode()); final HttpEntity entity = httpResponse.getEntity(); if (entity != null && entity.getContent() != null) { - if (contentType == Protocol.HTTP_VPACK) { - final byte[] content = IOUtils.toByteArray(entity.getContent()); - if (content.length > 0) { - response.setBody(new VPackSlice(content)); - } - } else { - final String content = IOUtils.toString(entity.getContent()); - if (!content.isEmpty()) { - response.setBody(parser.fromJson(content, true)); - } + final byte[] content = IOUtils.toByteArray(entity.getContent()); + if (content.length > 0) { + response.setBody(content); } } final Header[] headers = httpResponse.getAllHeaders(); diff --git a/src/main/java/com/arangodb/internal/net/ExtendedHostResolver.java b/src/main/java/com/arangodb/internal/net/ExtendedHostResolver.java index 6e300f6ba..e0bb05117 100644 --- a/src/main/java/com/arangodb/internal/net/ExtendedHostResolver.java +++ b/src/main/java/com/arangodb/internal/net/ExtendedHostResolver.java @@ -22,10 +22,11 @@ import com.arangodb.ArangoDBException; import com.arangodb.DbName; +import com.arangodb.entity.CollectionEntity; import com.arangodb.internal.ArangoExecutorSync; import com.arangodb.internal.util.HostUtils; import com.arangodb.util.InternalSerialization; -import com.arangodb.velocypack.VPackSlice; +import com.arangodb.velocypack.Type; import com.arangodb.velocystream.Request; import com.arangodb.velocystream.RequestType; import org.slf4j.Logger; @@ -127,16 +128,11 @@ private Collection resolveFromServer() throws ArangoDBException { response = executor.execute( new Request(DbName.SYSTEM, RequestType.GET, "/_api/cluster/endpoints"), response1 -> { - final VPackSlice field = response1.getBody().get("endpoints"); - Collection endpoints; - if (field.isNone()) { - endpoints = Collections.emptyList(); - } else { - final Collection> tmp = arangoSerialization.deserialize(field, Collection.class); - endpoints = new ArrayList<>(); - for (final Map map : tmp) { - endpoints.add(map.get("endpoint")); - } + final Collection> tmp = arangoSerialization.deserialize(response1.getBody(), "/endpoints", new Type>() { + }.getType()); + Collection endpoints = new ArrayList<>(); + for (final Map map : tmp) { + endpoints.add(map.get("endpoint")); } return endpoints; }, null); diff --git a/src/main/java/com/arangodb/internal/util/ArangoSerializationImpl.java b/src/main/java/com/arangodb/internal/util/ArangoSerializationImpl.java index e0048baea..3cba46382 100644 --- a/src/main/java/com/arangodb/internal/util/ArangoSerializationImpl.java +++ b/src/main/java/com/arangodb/internal/util/ArangoSerializationImpl.java @@ -2,20 +2,16 @@ import com.arangodb.ArangoDBException; import com.arangodb.serde.ArangoSerde; -import com.arangodb.util.ArangoDeserializer; import com.arangodb.util.ArangoSerialization; -import com.arangodb.velocypack.VPackSlice; import java.lang.reflect.Type; public class ArangoSerializationImpl implements ArangoSerialization { - private final ArangoDeserializer deserializer; private final ArangoSerde serde; - public ArangoSerializationImpl(final ArangoDeserializer deserializer, final ArangoSerde serde) { + public ArangoSerializationImpl(final ArangoSerde serde) { super(); - this.deserializer = deserializer; this.serde = serde; } @@ -25,8 +21,8 @@ public byte[] serialize(final Object entity) throws ArangoDBException { } @Override - public T deserialize(final VPackSlice vpack, final Type type) throws ArangoDBException { - return deserializer.deserialize(vpack, type); + public T deserialize(byte[] content, Type type) { + return serde.deserialize(content, type); } } diff --git a/src/main/java/com/arangodb/internal/util/InternalSerializationImpl.java b/src/main/java/com/arangodb/internal/util/InternalSerializationImpl.java index 05f249697..681108497 100644 --- a/src/main/java/com/arangodb/internal/util/InternalSerializationImpl.java +++ b/src/main/java/com/arangodb/internal/util/InternalSerializationImpl.java @@ -22,9 +22,7 @@ import com.arangodb.ArangoDBException; import com.arangodb.serde.InternalSerde; -import com.arangodb.util.ArangoDeserializer; import com.arangodb.util.InternalSerialization; -import com.arangodb.velocypack.VPackSlice; import com.fasterxml.jackson.databind.JsonNode; import java.lang.reflect.Type; @@ -34,12 +32,10 @@ */ public class InternalSerializationImpl implements InternalSerialization { - private final ArangoDeserializer deserializer; private final InternalSerde serde; - public InternalSerializationImpl(final ArangoDeserializer deserializer, final InternalSerde serde) { + public InternalSerializationImpl(final InternalSerde serde) { super(); - this.deserializer = deserializer; this.serde = serde; } @@ -59,8 +55,28 @@ public JsonNode parse(byte[] content) { } @Override - public T deserialize(final VPackSlice vpack, final Type type) throws ArangoDBException { - return deserializer.deserialize(vpack, type); + public T deserialize(byte[] content, Type type) { + return serde.deserialize(content, type); + } + + @Override + public T deserialize(JsonNode node, Type type) { + return serde.deserialize(node, type); + } + + @Override + public JsonNode parse(byte[] content, String jsonPointer) { + return serde.parse(content, jsonPointer); + } + + @Override + public T deserialize(byte[] content, String jsonPointer, Type type) { + return serde.deserialize(content, jsonPointer, type); + } + + @Override + public byte[] extract(byte[] content, String jsonPointer) { + return serde.extract(content, jsonPointer); } } diff --git a/src/main/java/com/arangodb/internal/velocypack/VPackDeserializers.java b/src/main/java/com/arangodb/internal/velocypack/VPackDeserializers.java index f2cad52d6..06b5e0878 100644 --- a/src/main/java/com/arangodb/internal/velocypack/VPackDeserializers.java +++ b/src/main/java/com/arangodb/internal/velocypack/VPackDeserializers.java @@ -20,32 +20,11 @@ package com.arangodb.internal.velocypack; -import com.arangodb.entity.BaseDocument; -import com.arangodb.entity.BaseEdgeDocument; -import com.arangodb.entity.CollectionStatus; -import com.arangodb.entity.CollectionType; -import com.arangodb.entity.License; -import com.arangodb.entity.LogLevel; -import com.arangodb.entity.Permissions; -import com.arangodb.entity.QueryExecutionState; -import com.arangodb.entity.ReplicationFactor; -import com.arangodb.entity.ViewEntity; -import com.arangodb.entity.ViewType; -import com.arangodb.entity.arangosearch.AnalyzerType; -import com.arangodb.entity.arangosearch.ArangoSearchCompression; -import com.arangodb.entity.arangosearch.ArangoSearchProperties; -import com.arangodb.entity.arangosearch.ArangoSearchPropertiesEntity; -import com.arangodb.entity.arangosearch.CollectionLink; -import com.arangodb.entity.arangosearch.ConsolidationPolicy; -import com.arangodb.entity.arangosearch.ConsolidationType; -import com.arangodb.entity.arangosearch.FieldLink; -import com.arangodb.entity.arangosearch.PrimarySort; -import com.arangodb.entity.arangosearch.StoreValuesType; -import com.arangodb.entity.arangosearch.StoredValue; +import com.arangodb.entity.*; +import com.arangodb.entity.arangosearch.*; import com.arangodb.entity.arangosearch.analyzer.*; import com.arangodb.model.CollectionSchema; import com.arangodb.model.ZKDIndexOptions; -import com.arangodb.serde.DataType; import com.arangodb.velocypack.VPackDeserializer; import com.arangodb.velocypack.VPackParser; import com.arangodb.velocypack.VPackSlice; @@ -67,7 +46,7 @@ public class VPackDeserializers { private static final String DATE_TIME_FORMAT = "yyyy-MM-dd'T'HH:mm:ss.SSSZ"; public static final VPackDeserializer RESPONSE = (parent, vpack, context) -> { - final Response response = new Response(DataType.VPACK); + final Response response = new Response(); response.setVersion(vpack.get(0).getAsInt()); response.setType(vpack.get(1).getAsInt()); response.setResponseCode(vpack.get(2).getAsInt()); diff --git a/src/main/java/com/arangodb/internal/velocystream/VstCommunication.java b/src/main/java/com/arangodb/internal/velocystream/VstCommunication.java index b76e1971c..81cec8572 100644 --- a/src/main/java/com/arangodb/internal/velocystream/VstCommunication.java +++ b/src/main/java/com/arangodb/internal/velocystream/VstCommunication.java @@ -158,9 +158,9 @@ protected void checkError(final Response response) throws ArangoDBException { } protected Response createResponse(final Message message) throws VPackParserException { - final Response response = util.deserialize(message.getHead(), Response.class); + final Response response = util.deserialize(message.getHead().toByteArray(), Response.class); if (message.getBody() != null) { - response.setBody(message.getBody()); + response.setBody(message.getBody().toByteArray()); } return response; } diff --git a/src/main/java/com/arangodb/mapping/ArangoJack.java b/src/main/java/com/arangodb/mapping/ArangoJack.java index 392548dd8..26f9fd5c4 100644 --- a/src/main/java/com/arangodb/mapping/ArangoJack.java +++ b/src/main/java/com/arangodb/mapping/ArangoJack.java @@ -33,14 +33,11 @@ import com.fasterxml.jackson.annotation.JsonInclude.Include; import com.fasterxml.jackson.annotation.PropertyAccessor; import com.fasterxml.jackson.databind.DeserializationFeature; -import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializationFeature; import com.fasterxml.jackson.databind.module.SimpleModule; -import java.io.IOException; import java.lang.reflect.Type; -import java.util.Arrays; /** * @author Mark Vollmary @@ -116,23 +113,9 @@ public byte[] serialize(final Object entity) throws ArangoDBException { return serde.serialize(entity); } - @SuppressWarnings("unchecked") @Override - public T deserialize(final VPackSlice vpack, final Type type) throws ArangoDBException { - try { - final T doc; - if (type == String.class && !vpack.isString() && !vpack.isNull()) { - final JsonNode node = vpackMapper.readTree( - Arrays.copyOfRange(vpack.getBuffer(), vpack.getStart(), vpack.getStart() + vpack.getByteSize())); - doc = (T) jsonMapper.writeValueAsString(node); - } else { - doc = vpackMapper.readValue(vpack.getBuffer(), vpack.getStart(), vpack.getStart() + vpack.getByteSize(), - (Class) type); - } - return doc; - } catch (final IOException e) { - throw new ArangoDBException(e); - } + public T deserialize(byte[] content, Type type) { + return serde.deserialize(content, type); } } diff --git a/src/main/java/com/arangodb/serde/InternalDeserializers.java b/src/main/java/com/arangodb/serde/InternalDeserializers.java new file mode 100644 index 000000000..f2132a089 --- /dev/null +++ b/src/main/java/com/arangodb/serde/InternalDeserializers.java @@ -0,0 +1,49 @@ +package com.arangodb.serde; + +import com.arangodb.entity.CollectionStatus; +import com.arangodb.entity.CollectionType; +import com.arangodb.velocystream.Response; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonDeserializer; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.node.ArrayNode; + +import java.io.IOException; +import java.util.Iterator; +import java.util.Map; + +public final class InternalDeserializers { + private InternalDeserializers() { + } + + static final JsonDeserializer COLLECTION_STATUS = new JsonDeserializer() { + @Override + public CollectionStatus deserialize(final JsonParser p, final DeserializationContext ctxt) throws IOException { + return CollectionStatus.fromStatus(p.getIntValue()); + } + }; + + static final JsonDeserializer COLLECTION_TYPE = new JsonDeserializer() { + @Override + public CollectionType deserialize(final JsonParser p, final DeserializationContext ctxt) throws IOException { + return CollectionType.fromType(p.getIntValue()); + } + }; + static final JsonDeserializer RESPONSE = new JsonDeserializer() { + @Override + public Response deserialize(final JsonParser p, final DeserializationContext ctxt) throws IOException { + final Response response = new Response(); + Iterator it = ((ArrayNode) p.readValueAsTree()).iterator(); + response.setVersion(it.next().intValue()); + response.setType(it.next().intValue()); + response.setResponseCode(it.next().intValue()); + if (it.hasNext()) { + response.setMeta(ctxt.readTreeAsValue(it.next(), Map.class)); + } + return response; + } + }; + + +} diff --git a/src/main/java/com/arangodb/serde/InternalModule.java b/src/main/java/com/arangodb/serde/InternalModule.java index 2c8d1442d..9f9e25a62 100644 --- a/src/main/java/com/arangodb/serde/InternalModule.java +++ b/src/main/java/com/arangodb/serde/InternalModule.java @@ -1,10 +1,12 @@ package com.arangodb.serde; +import com.arangodb.entity.CollectionStatus; import com.arangodb.entity.CollectionType; import com.arangodb.internal.velocystream.internal.AuthenticationRequest; import com.arangodb.internal.velocystream.internal.JwtAuthenticationRequest; import com.arangodb.velocypack.VPackSlice; import com.arangodb.velocystream.Request; +import com.arangodb.velocystream.Response; import com.fasterxml.jackson.databind.Module; import com.fasterxml.jackson.databind.module.SimpleModule; @@ -17,11 +19,16 @@ enum InternalModule implements Supplier { InternalModule() { module = new SimpleModule(); + module.addSerializer(VPackSlice.class, InternalSerializers.VPACK_SLICE_JSON_SERIALIZER); module.addSerializer(AuthenticationRequest.class, InternalSerializers.AUTHENTICATION_REQUEST); module.addSerializer(JwtAuthenticationRequest.class, InternalSerializers.JWT_AUTHENTICATION_REQUEST); module.addSerializer(Request.class, InternalSerializers.REQUEST); module.addSerializer(CollectionType.class, InternalSerializers.COLLECTION_TYPE); + + module.addDeserializer(CollectionStatus.class, InternalDeserializers.COLLECTION_STATUS); + module.addDeserializer(CollectionType.class, InternalDeserializers.COLLECTION_TYPE); + module.addDeserializer(Response.class, InternalDeserializers.RESPONSE); } @Override diff --git a/src/main/java/com/arangodb/serde/InternalSerde.java b/src/main/java/com/arangodb/serde/InternalSerde.java index 1d13abd2c..e67b4d811 100644 --- a/src/main/java/com/arangodb/serde/InternalSerde.java +++ b/src/main/java/com/arangodb/serde/InternalSerde.java @@ -1,9 +1,12 @@ package com.arangodb.serde; +import com.arangodb.internal.ArangoResponseField; import com.arangodb.jackson.dataformat.velocypack.VPackMapper; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; +import java.lang.reflect.Type; + public interface InternalSerde extends JacksonSerde { /** @@ -42,8 +45,26 @@ static InternalSerde of(final DataType dataType) { /** * TODO - * @param content - * @return */ JsonNode parse(byte[] content); + + /** + * TODO + */ + JsonNode parse(byte[] content, String jsonPointer); + + /** + * TODO + */ + default T deserialize(byte[] content, String jsonPointer, Class clazz){ + return deserialize(content, jsonPointer, (Type) clazz); + } + + /** + * TODO + */ + default T deserialize(byte[] content, String jsonPointer, Type type) { + return deserialize(parse(content, jsonPointer), type); + } + } diff --git a/src/main/java/com/arangodb/serde/InternalSerdeImpl.java b/src/main/java/com/arangodb/serde/InternalSerdeImpl.java index 0dd204379..a779b5cf3 100644 --- a/src/main/java/com/arangodb/serde/InternalSerdeImpl.java +++ b/src/main/java/com/arangodb/serde/InternalSerdeImpl.java @@ -2,10 +2,12 @@ import com.arangodb.ArangoDBException; import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import java.io.IOException; +import java.lang.reflect.Type; import java.nio.charset.StandardCharsets; class InternalSerdeImpl extends JacksonSerdeImpl implements InternalSerde { @@ -14,6 +16,7 @@ class InternalSerdeImpl extends JacksonSerdeImpl implements InternalSerde { super(dataType, mapper); mapper.registerModule(InternalModule.INSTANCE.get()); mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); + mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); } @Override @@ -55,4 +58,13 @@ public JsonNode parse(byte[] content) { } } + @Override + public JsonNode parse(byte[] content, String jsonPointer) { + try { + return mapper.readTree(content).at(jsonPointer); + } catch (IOException e) { + throw new ArangoDBException(e); + } + } + } diff --git a/src/main/java/com/arangodb/util/ArangoSerialization.java b/src/main/java/com/arangodb/util/ArangoSerialization.java index 8efa1b522..d021c9bd7 100644 --- a/src/main/java/com/arangodb/util/ArangoSerialization.java +++ b/src/main/java/com/arangodb/util/ArangoSerialization.java @@ -1,5 +1,8 @@ package com.arangodb.util; -public interface ArangoSerialization extends ArangoDeserializer { +import java.lang.reflect.Type; + +public interface ArangoSerialization { byte[] serialize(final Object entity); + T deserialize(byte[] content, Type type); } diff --git a/src/main/java/com/arangodb/util/InternalSerialization.java b/src/main/java/com/arangodb/util/InternalSerialization.java index 690d02a71..d063a7d3a 100644 --- a/src/main/java/com/arangodb/util/InternalSerialization.java +++ b/src/main/java/com/arangodb/util/InternalSerialization.java @@ -22,12 +22,26 @@ import com.fasterxml.jackson.databind.JsonNode; +import java.lang.reflect.Type; + /** * @author Mark Vollmary */ -public interface InternalSerialization extends ArangoDeserializer { +public interface InternalSerialization { byte[] serialize(final Object entity); + + T deserialize(byte[] content, Type type); + + T deserialize(JsonNode node, Type type); + String toJsonString(byte[] content); + JsonNode parse(byte[] content); + JsonNode parse(byte[] content, String jsonPointer); + + T deserialize(byte[] content, String jsonPointer, Type type); + + byte[] extract(byte[] content, String jsonPointer); + } diff --git a/src/main/java/com/arangodb/velocystream/Response.java b/src/main/java/com/arangodb/velocystream/Response.java index 9c5869869..36021e1c5 100644 --- a/src/main/java/com/arangodb/velocystream/Response.java +++ b/src/main/java/com/arangodb/velocystream/Response.java @@ -20,11 +20,8 @@ package com.arangodb.velocystream; -import com.arangodb.serde.DataType; -import com.arangodb.velocypack.VPackSlice; import com.arangodb.velocypack.annotations.Expose; -import java.nio.charset.StandardCharsets; import java.util.HashMap; import java.util.Map; @@ -38,13 +35,10 @@ public class Response { private int responseCode; private Map meta; @Expose(deserialize = false) - private VPackSlice body = null; + private byte[] body = null; - private final DataType dataType; - - public Response(final DataType dataType) { + public Response() { super(); - this.dataType = dataType; meta = new HashMap<>(); } @@ -80,24 +74,12 @@ public void setMeta(final Map meta) { this.meta = meta; } - public VPackSlice getBody() { + public byte[] getBody() { return body; } - public void setBody(final VPackSlice body) { + public void setBody(final byte[] body) { this.body = body; } - public byte[] getBodyBytes() { - if (body == null) { - return new byte[0]; - } else if (dataType == DataType.JSON) { - return body.toString().getBytes(StandardCharsets.UTF_8); - } else if (dataType == DataType.VPACK) { - return body.toByteArray(); - } else { - throw new IllegalStateException("Unexpected value: " + dataType); - } - } - } diff --git a/src/test/java/com/arangodb/ArangoDBTest.java b/src/test/java/com/arangodb/ArangoDBTest.java index 284ae526e..cc80eacbf 100644 --- a/src/test/java/com/arangodb/ArangoDBTest.java +++ b/src/test/java/com/arangodb/ArangoDBTest.java @@ -395,7 +395,7 @@ void authenticationFailUser() { @MethodSource("arangos") void execute(ArangoDB arangoDB) throws VPackException { final Response response = arangoDB.execute(new Request(DbName.SYSTEM, RequestType.GET, "/_api/version")); - assertThat(response.getBody().get("version").isString()).isTrue(); + assertThat(arangoDB.getInternalSerialization().parse(response.getBody(), "version").isTextual()).isTrue(); } @ParameterizedTest(name = "{index}") diff --git a/src/test/java/com/arangodb/ArangoRouteTest.java b/src/test/java/com/arangodb/ArangoRouteTest.java index 6bcd38f41..ba57d730c 100644 --- a/src/test/java/com/arangodb/ArangoRouteTest.java +++ b/src/test/java/com/arangodb/ArangoRouteTest.java @@ -47,7 +47,7 @@ static void init() { @MethodSource("dbs") void get(ArangoDatabase db) { final Response res = db.route("/_api/version").get(); - assertThat(res.getBody().get("version").isString()).isTrue(); + assertThat(db.arango().getInternalSerialization().parse(res.getBody(), "version").isTextual()).isTrue(); } @ParameterizedTest(name = "{index}") diff --git a/src/test/java/com/arangodb/BaseJunit5.java b/src/test/java/com/arangodb/BaseJunit5.java index 11ee86790..140d52730 100644 --- a/src/test/java/com/arangodb/BaseJunit5.java +++ b/src/test/java/com/arangodb/BaseJunit5.java @@ -1,7 +1,6 @@ package com.arangodb; import com.arangodb.entity.*; -import com.arangodb.mapping.ArangoJack; import com.arangodb.model.CollectionCreateOptions; import com.arangodb.model.GraphCreateOptions; import com.arangodb.util.TestUtils; diff --git a/src/test/java/com/arangodb/async/ArangoDBTest.java b/src/test/java/com/arangodb/async/ArangoDBTest.java index 429f2c643..23732e8f0 100644 --- a/src/test/java/com/arangodb/async/ArangoDBTest.java +++ b/src/test/java/com/arangodb/async/ArangoDBTest.java @@ -441,7 +441,7 @@ void execute() throws VPackException, InterruptedException, ExecutionException { .execute(new Request(DbName.SYSTEM, RequestType.GET, "/_api/version")) .whenComplete((response, ex) -> { assertThat(response.getBody()).isNotNull(); - assertThat(response.getBody().get("version").isString()).isTrue(); + assertThat(arangoDB.getInternalSerialization().parse(response.getBody(), "version").isTextual()).isTrue(); }) .get(); } @@ -453,7 +453,7 @@ void execute_acquireHostList_enabled() throws VPackException, InterruptedExcepti .execute(new Request(DbName.SYSTEM, RequestType.GET, "/_api/version")) .whenComplete((response, ex) -> { assertThat(response.getBody()).isNotNull(); - assertThat(response.getBody().get("version").isString()).isTrue(); + assertThat(arangoDB.getInternalSerialization().parse(response.getBody(), "version").isTextual()).isTrue(); }) .get(); } diff --git a/src/test/java/com/arangodb/mapping/annotations/ArangoAnnotationsTest.java b/src/test/java/com/arangodb/mapping/annotations/ArangoAnnotationsTest.java index 482d1287b..9484b7e30 100644 --- a/src/test/java/com/arangodb/mapping/annotations/ArangoAnnotationsTest.java +++ b/src/test/java/com/arangodb/mapping/annotations/ArangoAnnotationsTest.java @@ -47,7 +47,7 @@ void documentFieldAnnotations() { VPackSlice slice = new VPackSlice(mapper.serialize(e)); System.out.println(slice); - Map deserialized = mapper.deserialize(slice, Object.class); + Map deserialized = mapper.deserialize(slice.toByteArray(), Object.class); assertThat(deserialized) .containsEntry("_id", e.getId()) .containsEntry("_key", e.getKey()) @@ -56,7 +56,7 @@ void documentFieldAnnotations() { .containsEntry("_to", e.getTo()) .hasSize(5); - AnnotatedEntity deserializedEntity = mapper.deserialize(slice, AnnotatedEntity.class); + AnnotatedEntity deserializedEntity = mapper.deserialize(slice.toByteArray(), AnnotatedEntity.class); assertThat(deserializedEntity).isEqualTo(e); } @@ -69,14 +69,14 @@ void serializedName() { VPackSlice slice = new VPackSlice(mapper.serialize(e)); System.out.println(slice); - Map deserialized = mapper.deserialize(slice, Object.class); + Map deserialized = mapper.deserialize(slice.toByteArray(), Object.class); assertThat(deserialized) .containsEntry(SerializedNameEntity.SERIALIZED_NAME_A, e.getA()) .containsEntry(SerializedNameEntity.SERIALIZED_NAME_B, e.getB()) .containsEntry(SerializedNameEntity.SERIALIZED_NAME_C, e.getC()) .hasSize(3); - SerializedNameEntity deserializedEntity = mapper.deserialize(slice, SerializedNameEntity.class); + SerializedNameEntity deserializedEntity = mapper.deserialize(slice.toByteArray(), SerializedNameEntity.class); assertThat(deserializedEntity).isEqualTo(e); } @@ -89,7 +89,7 @@ void serializedNameParameter() { VPackSlice slice = new VPackSlice(mapper.serialize(e)); SerializedNameParameterEntity deserializedEntity = mapper - .deserialize(slice, SerializedNameParameterEntity.class); + .deserialize(slice.toByteArray(), SerializedNameParameterEntity.class); assertThat(deserializedEntity).isEqualTo(new SerializedNameParameterEntity("A", "B", "C")); } @@ -102,7 +102,7 @@ void expose() { e.setIgnored("ignored"); VPackSlice serializedEntity = new VPackSlice(mapper.serialize(e)); - Map deserializedEntity = mapper.deserialize(serializedEntity, Object.class); + Map deserializedEntity = mapper.deserialize(serializedEntity.toByteArray(), Object.class); assertThat(deserializedEntity) .containsEntry("readWrite", "readWrite") .containsEntry("readOnly", "readOnly") @@ -115,7 +115,7 @@ void expose() { map.put("ignored", "ignored"); VPackSlice serializedMap = new VPackSlice(mapper.serialize(map)); - ExposeEntity deserializedMap = mapper.deserialize(serializedMap, ExposeEntity.class); + ExposeEntity deserializedMap = mapper.deserialize(serializedMap.toByteArray(), ExposeEntity.class); assertThat(deserializedMap.getIgnored()).isNull(); assertThat(deserializedMap.getReadOnly()).isNull(); assertThat(deserializedMap.getWriteOnly()).isEqualTo("writeOnly"); diff --git a/src/test/java/com/arangodb/serde/CustomSerdeTest.java b/src/test/java/com/arangodb/serde/CustomSerdeTest.java index 06bbb18c8..dd6b2d5d8 100644 --- a/src/test/java/com/arangodb/serde/CustomSerdeTest.java +++ b/src/test/java/com/arangodb/serde/CustomSerdeTest.java @@ -29,16 +29,11 @@ import com.arangodb.mapping.ArangoJack; import com.arangodb.model.DocumentCreateOptions; import com.arangodb.util.ArangoSerialization; -import com.arangodb.util.InternalSerialization; import com.arangodb.velocypack.VPackBuilder; import com.arangodb.velocypack.VPackSlice; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.core.JsonParser; -import com.fasterxml.jackson.databind.DeserializationContext; -import com.fasterxml.jackson.databind.JsonDeserializer; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.JsonSerializer; -import com.fasterxml.jackson.databind.SerializerProvider; +import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.annotation.JsonSerialize; import com.fasterxml.jackson.databind.module.SimpleModule; import org.junit.jupiter.api.AfterAll; @@ -53,7 +48,6 @@ import static com.fasterxml.jackson.databind.DeserializationFeature.USE_BIG_INTEGER_FOR_INTS; import static com.fasterxml.jackson.databind.SerializationFeature.WRITE_SINGLE_ELEM_ARRAYS_UNWRAPPED; - import static org.assertj.core.api.Assertions.assertThat; @@ -144,7 +138,7 @@ void manualCustomPersonDeserializer() { person.name = "Joe"; ArangoSerialization serialization = arangoDB.getUserSerialization(); VPackSlice serializedPerson = new VPackSlice(serialization.serialize(person)); - Person deserializedPerson = serialization.deserialize(serializedPerson, Person.class); + Person deserializedPerson = serialization.deserialize(serializedPerson.toByteArray(), Person.class); assertThat(deserializedPerson.name).isEqualTo(PERSON_DESERIALIZER_ADDED_PREFIX + PERSON_SERIALIZER_ADDED_PREFIX + person.name); } @@ -236,7 +230,7 @@ void getDocument() { @Test void parseNullString() { - final String json = arangoDB.getUserSerialization().deserialize(new VPackBuilder().add((String) null).slice(), String.class); + final String json = arangoDB.getUserSerialization().deserialize(new VPackBuilder().add((String) null).slice().toByteArray(), String.class); assertThat(json).isNull(); } diff --git a/src/test/java/com/arangodb/util/ArangoSerializationTest.java b/src/test/java/com/arangodb/util/ArangoSerializationTest.java index 7f08a8d81..fc64cd5c9 100644 --- a/src/test/java/com/arangodb/util/ArangoSerializationTest.java +++ b/src/test/java/com/arangodb/util/ArangoSerializationTest.java @@ -53,7 +53,7 @@ static void setup() { @Test void deserialize() { final VPackBuilder builder = new VPackBuilder().add(ValueType.OBJECT).add("foo", "bar").close(); - final BaseDocument doc = internalSer.deserialize(builder.slice(), BaseDocument.class); + final BaseDocument doc = internalSer.deserialize(builder.slice().toByteArray(), BaseDocument.class); assertThat(doc.getAttribute("foo")).isEqualTo("bar"); } @@ -97,13 +97,13 @@ void serializeType() { void parseJsonIncludeNull() { final Map entity = new HashMap<>(); entity.put("value", new String[]{"test", null}); - final String json = internalSer.deserialize(new VPackSlice(internalSer.serialize(entity)), String.class); + final String json = internalSer.deserialize(new VPackSlice(internalSer.serialize(entity)).toByteArray(), String.class); assertThat(json).isEqualTo("{\"value\":[\"test\",null]}"); } @Test void parseNullString() { - final String json = internalSer.deserialize(new VPackBuilder().add((String) null).slice(), String.class); + final String json = internalSer.deserialize(new VPackBuilder().add((String) null).slice().toByteArray(), String.class); assertThat(json).isNull(); } From 075d0ab1552be17eb5f016d794e941b72682b6e4 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Mon, 11 Jul 2022 21:28:31 +0200 Subject: [PATCH 028/254] deserializer refactoring: ArangoSearch --- .../java/com/arangodb/entity/License.java | 8 +- .../arangosearch/ArangoSearchProperties.java | 130 ------------------ .../ArangoSearchPropertiesEntity.java | 55 ++++---- .../entity/arangosearch/CollectionLink.java | 8 +- .../entity/arangosearch/FieldLink.java | 5 +- .../entity/arangosearch/StoredValue.java | 6 +- .../arangosearch/analyzer/SearchAnalyzer.java | 20 +++ .../InternalArangoEdgeCollection.java | 19 ++- .../InternalArangoVertexCollection.java | 21 ++- .../internal/net/ExtendedHostResolver.java | 6 +- .../velocypack/VPackDeserializers.java | 108 --------------- .../velocypack/VPackDriverModule.java | 6 - .../internal/velocypack/VPackSerializers.java | 85 ------------ .../model/VertexCollectionCreateOptions.java | 2 +- .../java/com/arangodb/serde/DataType.java | 2 +- .../arangodb/serde/InternalDeserializers.java | 57 ++++++++ .../com/arangodb/serde/InternalModule.java | 2 + .../com/arangodb/serde/InternalSerde.java | 2 +- .../com/arangodb/serde/InternalSerdeImpl.java | 2 +- .../java/com/arangodb/serde/JacksonSerde.java | 2 +- src/test/java/com/arangodb/ArangoDBTest.java | 2 +- .../java/com/arangodb/ArangoSearchTest.java | 6 +- .../velocypack/VPackSerializersTest.java | 5 +- 23 files changed, 163 insertions(+), 396 deletions(-) delete mode 100644 src/main/java/com/arangodb/entity/arangosearch/ArangoSearchProperties.java diff --git a/src/main/java/com/arangodb/entity/License.java b/src/main/java/com/arangodb/entity/License.java index 053b2ca64..92803eed4 100644 --- a/src/main/java/com/arangodb/entity/License.java +++ b/src/main/java/com/arangodb/entity/License.java @@ -20,11 +20,17 @@ package com.arangodb.entity; +import com.fasterxml.jackson.annotation.JsonProperty; + /** * @author Axel Becker */ public enum License { - ENTERPRISE, COMMUNITY + @JsonProperty("enterprise") + ENTERPRISE, + + @JsonProperty("community") + COMMUNITY } diff --git a/src/main/java/com/arangodb/entity/arangosearch/ArangoSearchProperties.java b/src/main/java/com/arangodb/entity/arangosearch/ArangoSearchProperties.java deleted file mode 100644 index 443ac0dfe..000000000 --- a/src/main/java/com/arangodb/entity/arangosearch/ArangoSearchProperties.java +++ /dev/null @@ -1,130 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2018 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.entity.arangosearch; - -import com.arangodb.serde.InternalSerializers; -import com.fasterxml.jackson.databind.annotation.JsonSerialize; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; - -/** - * @author Mark Vollmary - * @author Heiko Kernbach - * @author Michele Rastelli - * @see API Documentation - */ -public class ArangoSearchProperties { - - private Long consolidationIntervalMsec; - private Long commitIntervalMsec; - private Long cleanupIntervalStep; - private ConsolidationPolicy consolidationPolicy; - private final Collection primarySorts; - private final Collection links; - private ArangoSearchCompression primarySortCompression; - private final Collection storedValues; - - public ArangoSearchProperties() { - super(); - links = new ArrayList<>(); - primarySorts = new ArrayList<>(); - storedValues = new ArrayList<>(); - } - - public Long getCommitIntervalMsec() { - return commitIntervalMsec; - } - - public void setCommitIntervalMsec(final Long commitIntervalMsec) { - this.commitIntervalMsec = commitIntervalMsec; - } - - public Long getConsolidationIntervalMsec() { - return consolidationIntervalMsec; - } - - public void setConsolidationIntervalMsec(final Long consolidationIntervalMsec) { - this.consolidationIntervalMsec = consolidationIntervalMsec; - } - - public Long getCleanupIntervalStep() { - return cleanupIntervalStep; - } - - public void setCleanupIntervalStep(final Long cleanupIntervalStep) { - this.cleanupIntervalStep = cleanupIntervalStep; - } - - public ConsolidationPolicy getConsolidationPolicy() { - return consolidationPolicy; - } - - public void setConsolidationPolicy(final ConsolidationPolicy consolidationPolicy) { - this.consolidationPolicy = consolidationPolicy; - } - - @JsonSerialize(using = InternalSerializers.CollectionLinksSerializer.class) - public Collection getLinks() { - return links; - } - - public void addLink(final CollectionLink... links) { - this.links.addAll(Arrays.asList(links)); - } - - public Collection getPrimarySort() { - return primarySorts; - } - - public void addPrimarySort(final PrimarySort... primarySorts) { - this.primarySorts.addAll(Arrays.asList(primarySorts)); - } - - /** - * @return Defines how to compress the primary sort data (introduced in v3.7.0). ArangoDB v3.5 and v3.6 always - * compress the index using LZ4. - * @since ArangoDB 3.7 - */ - public ArangoSearchCompression getPrimarySortCompression() { - return primarySortCompression; - } - - public void setPrimarySortCompression(ArangoSearchCompression primarySortCompression) { - this.primarySortCompression = primarySortCompression; - } - - /** - * @return An array of objects to describe which document attributes to store in the View index. It can then cover - * search queries, which means the data can be taken from the index directly and accessing the storage engine can be - * avoided. - * @since ArangoDB 3.7 - */ - public Collection getStoredValues() { - return storedValues; - } - - public void addStoredValues(final StoredValue... storedValues) { - this.storedValues.addAll(Arrays.asList(storedValues)); - } - -} diff --git a/src/main/java/com/arangodb/entity/arangosearch/ArangoSearchPropertiesEntity.java b/src/main/java/com/arangodb/entity/arangosearch/ArangoSearchPropertiesEntity.java index 55c6d9afe..d33850aac 100644 --- a/src/main/java/com/arangodb/entity/arangosearch/ArangoSearchPropertiesEntity.java +++ b/src/main/java/com/arangodb/entity/arangosearch/ArangoSearchPropertiesEntity.java @@ -21,7 +21,8 @@ package com.arangodb.entity.arangosearch; import com.arangodb.entity.ViewEntity; -import com.arangodb.entity.ViewType; +import com.arangodb.serde.InternalDeserializers; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import java.util.Collection; @@ -32,24 +33,14 @@ */ public class ArangoSearchPropertiesEntity extends ViewEntity { - private final ArangoSearchProperties properties; - - public ArangoSearchPropertiesEntity(final String id, final String name, final ViewType type, - final ArangoSearchProperties properties) { - super(id, name, type); - this.properties = properties; - } - - /** - * @return Wait at least this many milliseconds between committing index data changes and making them visible to - * queries (default: 60000, to disable use: 0). For the case where there are a lot of inserts/updates, a - * lower value, until commit, will cause the index not to account for them and memory usage would continue - * to grow. For the case where there are a few inserts/updates, a higher value will impact performance and - * waste disk space for each commit call without any added benefits. - */ - public Long getConsolidationIntervalMsec() { - return properties.getConsolidationIntervalMsec(); - } + private Long consolidationIntervalMsec; + private Long commitIntervalMsec; + private Long cleanupIntervalStep; + private ConsolidationPolicy consolidationPolicy; + private Collection primarySort; + private Collection links; + private ArangoSearchCompression primarySortCompression; + private Collection storedValues; /** * @return Wait at least this many milliseconds between committing view data store changes and making documents @@ -65,7 +56,18 @@ public Long getConsolidationIntervalMsec() { * continue to return a repeatable-read state. */ public Long getCommitIntervalMsec() { - return properties.getCommitIntervalMsec(); + return commitIntervalMsec; + } + + /** + * @return Wait at least this many milliseconds between committing index data changes and making them visible to + * queries (default: 60000, to disable use: 0). For the case where there are a lot of inserts/updates, a + * lower value, until commit, will cause the index not to account for them and memory usage would continue + * to grow. For the case where there are a few inserts/updates, a higher value will impact performance and + * waste disk space for each commit call without any added benefits. + */ + public Long getConsolidationIntervalMsec() { + return consolidationIntervalMsec; } /** @@ -76,25 +78,26 @@ public Long getCommitIntervalMsec() { * performance without any added benefits. */ public Long getCleanupIntervalStep() { - return properties.getCleanupIntervalStep(); + return cleanupIntervalStep; } public ConsolidationPolicy getConsolidationPolicy() { - return properties.getConsolidationPolicy(); + return consolidationPolicy; } /** * @return A list of linked collections */ + @JsonDeserialize(using = InternalDeserializers.CollectionLinksDeserializer.class) public Collection getLinks() { - return properties.getLinks(); + return links; } /** * @return A list of primary sort objects */ public Collection getPrimarySort() { - return properties.getPrimarySort(); + return primarySort; } /** @@ -103,7 +106,7 @@ public Collection getPrimarySort() { * @since ArangoDB 3.7 */ public ArangoSearchCompression getPrimarySortCompression() { - return properties.getPrimarySortCompression(); + return primarySortCompression; } /** @@ -113,7 +116,7 @@ public ArangoSearchCompression getPrimarySortCompression() { * @since ArangoDB 3.7 */ public Collection getStoredValues() { - return properties.getStoredValues(); + return storedValues; } } diff --git a/src/main/java/com/arangodb/entity/arangosearch/CollectionLink.java b/src/main/java/com/arangodb/entity/arangosearch/CollectionLink.java index 897119991..f6a471d14 100644 --- a/src/main/java/com/arangodb/entity/arangosearch/CollectionLink.java +++ b/src/main/java/com/arangodb/entity/arangosearch/CollectionLink.java @@ -20,8 +20,12 @@ package com.arangodb.entity.arangosearch; +import com.arangodb.serde.InternalDeserializers; import com.arangodb.serde.InternalSerializers; +import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.fasterxml.jackson.databind.annotation.JsonSerialize; import java.util.ArrayList; @@ -53,7 +57,8 @@ private CollectionLink(final String name) { * @param name Name of a collection * @return new instance of {@code CollectionLink} */ - public static CollectionLink on(final String name) { + @JsonCreator + public static CollectionLink on(@JsonProperty("name") final String name) { return new CollectionLink(name); } @@ -99,6 +104,7 @@ public CollectionLink storeValues(final StoreValuesType storeValues) { * @param fields A list of linked fields * @return link */ + @JsonDeserialize(using = InternalDeserializers.FieldLinksDeserializer.class) public CollectionLink fields(final FieldLink... fields) { this.fields.addAll(Arrays.asList(fields)); return this; diff --git a/src/main/java/com/arangodb/entity/arangosearch/FieldLink.java b/src/main/java/com/arangodb/entity/arangosearch/FieldLink.java index 4027498fe..e41f6cca7 100644 --- a/src/main/java/com/arangodb/entity/arangosearch/FieldLink.java +++ b/src/main/java/com/arangodb/entity/arangosearch/FieldLink.java @@ -1,7 +1,9 @@ package com.arangodb.entity.arangosearch; import com.arangodb.serde.InternalSerializers; +import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.databind.annotation.JsonSerialize; import java.util.ArrayList; @@ -30,7 +32,8 @@ private FieldLink(final String name) { * @param name Name of a field * @return new instance of {@code FieldLink} */ - public static FieldLink on(final String name) { + @JsonCreator + public static FieldLink on(@JsonProperty("name") final String name) { return new FieldLink(name); } diff --git a/src/main/java/com/arangodb/entity/arangosearch/StoredValue.java b/src/main/java/com/arangodb/entity/arangosearch/StoredValue.java index 5d3c2bd36..d6ffb95c9 100644 --- a/src/main/java/com/arangodb/entity/arangosearch/StoredValue.java +++ b/src/main/java/com/arangodb/entity/arangosearch/StoredValue.java @@ -21,6 +21,9 @@ package com.arangodb.entity.arangosearch; +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; + import java.util.List; /** @@ -33,7 +36,8 @@ public class StoredValue { private final List fields; private final ArangoSearchCompression compression; - public StoredValue(List fields, ArangoSearchCompression compression) { + @JsonCreator + public StoredValue(@JsonProperty("fields") List fields, @JsonProperty("compression") ArangoSearchCompression compression) { this.fields = fields; this.compression = compression; } diff --git a/src/main/java/com/arangodb/entity/arangosearch/analyzer/SearchAnalyzer.java b/src/main/java/com/arangodb/entity/arangosearch/analyzer/SearchAnalyzer.java index 2155a39a8..d826b50d3 100644 --- a/src/main/java/com/arangodb/entity/arangosearch/analyzer/SearchAnalyzer.java +++ b/src/main/java/com/arangodb/entity/arangosearch/analyzer/SearchAnalyzer.java @@ -24,6 +24,9 @@ import com.arangodb.entity.Entity; import com.arangodb.entity.arangosearch.AnalyzerFeature; import com.arangodb.entity.arangosearch.AnalyzerType; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonSubTypes; +import com.fasterxml.jackson.annotation.JsonTypeInfo; import java.util.Collection; import java.util.HashSet; @@ -33,6 +36,22 @@ /** * @author Michele Rastelli */ +@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.EXTERNAL_PROPERTY, property = "type") +@JsonSubTypes({ + @JsonSubTypes.Type(name = "identity", value = IdentityAnalyzer.class), + @JsonSubTypes.Type(name = "delimiter", value = DelimiterAnalyzer.class), + @JsonSubTypes.Type(name = "stem", value = StemAnalyzer.class), + @JsonSubTypes.Type(name = "norm", value = NormAnalyzer.class), + @JsonSubTypes.Type(name = "ngram", value = NGramAnalyzer.class), + @JsonSubTypes.Type(name = "text", value = TextAnalyzer.class), + @JsonSubTypes.Type(name = "pipeline", value = PipelineAnalyzer.class), + @JsonSubTypes.Type(name = "stopwords", value = StopwordsAnalyzer.class), + @JsonSubTypes.Type(name = "aql", value = AQLAnalyzer.class), + @JsonSubTypes.Type(name = "geojson", value = GeoJSONAnalyzer.class), + @JsonSubTypes.Type(name = "geopoint", value = GeoPointAnalyzer.class), + @JsonSubTypes.Type(name = "segmentation", value = SegmentationAnalyzer.class), + @JsonSubTypes.Type(name = "collation", value = CollationAnalyzer.class) +}) public abstract class SearchAnalyzer implements Entity { private String name; private AnalyzerType type; @@ -52,6 +71,7 @@ public void setName(String name) { /** * @return The Analyzer type. */ + @JsonIgnore public AnalyzerType getType() { return type; } diff --git a/src/main/java/com/arangodb/internal/InternalArangoEdgeCollection.java b/src/main/java/com/arangodb/internal/InternalArangoEdgeCollection.java index cb24a0730..725141dbd 100644 --- a/src/main/java/com/arangodb/internal/InternalArangoEdgeCollection.java +++ b/src/main/java/com/arangodb/internal/InternalArangoEdgeCollection.java @@ -39,7 +39,6 @@ public abstract class InternalArangoEdgeCollection extends ArangoExecuteable { private static final String PATH_API_GHARIAL = "/_api/gharial"; - private static final String EDGE = "edge"; private static final String TRANSACTION_ID = "x-arango-trx-id"; @@ -61,7 +60,7 @@ public String name() { } protected Request insertEdgeRequest(final T value, final EdgeCreateOptions options) { - final Request request = request(graph.db().dbName(), RequestType.POST, PATH_API_GHARIAL, graph.name(), EDGE, + final Request request = request(graph.db().dbName(), RequestType.POST, PATH_API_GHARIAL, graph.name(), "edge", name); final EdgeCreateOptions params = (options != null ? options : new EdgeCreateOptions()); request.putHeaderParam(TRANSACTION_ID, params.getStreamTransactionId()); @@ -72,7 +71,7 @@ protected Request insertEdgeRequest(final T value, final EdgeCreateOptions o protected ResponseDeserializer insertEdgeResponseDeserializer(final T value) { return response -> { - final EdgeEntity doc = getInternalSerialization().deserialize(response.getBody(), EDGE, EdgeEntity.class); + final EdgeEntity doc = getInternalSerialization().deserialize(response.getBody(), "/edge", EdgeEntity.class); final Map values = new HashMap<>(); values.put(DocumentFields.ID, doc.getId()); values.put(DocumentFields.KEY, doc.getKey()); @@ -83,7 +82,7 @@ protected ResponseDeserializer insertEdgeResponseDeserializer(fi } protected Request getEdgeRequest(final String key, final GraphDocumentReadOptions options) { - final Request request = request(graph.db().dbName(), RequestType.GET, PATH_API_GHARIAL, graph.name(), EDGE, + final Request request = request(graph.db().dbName(), RequestType.GET, PATH_API_GHARIAL, graph.name(), "edge", DocumentUtil.createDocumentHandle(name, key)); final GraphDocumentReadOptions params = (options != null ? options : new GraphDocumentReadOptions()); request.putHeaderParam(TRANSACTION_ID, params.getStreamTransactionId()); @@ -96,11 +95,11 @@ protected Request getEdgeRequest(final String key, final GraphDocumentReadOption } protected ResponseDeserializer getEdgeResponseDeserializer(final Class type) { - return response -> getUserSerialization().deserialize(getInternalSerialization().extract(response.getBody(), EDGE), type); + return response -> getUserSerialization().deserialize(getInternalSerialization().extract(response.getBody(), "/edge"), type); } protected Request replaceEdgeRequest(final String key, final T value, final EdgeReplaceOptions options) { - final Request request = request(graph.db().dbName(), RequestType.PUT, PATH_API_GHARIAL, graph.name(), EDGE, + final Request request = request(graph.db().dbName(), RequestType.PUT, PATH_API_GHARIAL, graph.name(), "edge", DocumentUtil.createDocumentHandle(name, key)); final EdgeReplaceOptions params = (options != null ? options : new EdgeReplaceOptions()); request.putHeaderParam(TRANSACTION_ID, params.getStreamTransactionId()); @@ -112,7 +111,7 @@ protected Request replaceEdgeRequest(final String key, final T value, final protected ResponseDeserializer replaceEdgeResponseDeserializer(final T value) { return response -> { - final EdgeUpdateEntity doc = getInternalSerialization().deserialize(response.getBody(), EDGE, EdgeUpdateEntity.class); + final EdgeUpdateEntity doc = getInternalSerialization().deserialize(response.getBody(), "/edge", EdgeUpdateEntity.class); final Map values = new HashMap<>(); values.put(DocumentFields.REV, doc.getRev()); executor.documentCache().setValues(value, values); @@ -122,7 +121,7 @@ protected ResponseDeserializer replaceEdgeResponseDeserial protected Request updateEdgeRequest(final String key, final T value, final EdgeUpdateOptions options) { final Request request; - request = request(graph.db().dbName(), RequestType.PATCH, PATH_API_GHARIAL, graph.name(), EDGE, + request = request(graph.db().dbName(), RequestType.PATCH, PATH_API_GHARIAL, graph.name(), "edge", DocumentUtil.createDocumentHandle(name, key)); final EdgeUpdateOptions params = (options != null ? options : new EdgeUpdateOptions()); request.putHeaderParam(TRANSACTION_ID, params.getStreamTransactionId()); @@ -135,7 +134,7 @@ protected Request updateEdgeRequest(final String key, final T value, final E protected ResponseDeserializer updateEdgeResponseDeserializer(final T value) { return response -> { - final EdgeUpdateEntity doc = getInternalSerialization().deserialize(response.getBody(), EDGE, EdgeUpdateEntity.class); + final EdgeUpdateEntity doc = getInternalSerialization().deserialize(response.getBody(), "/edge", EdgeUpdateEntity.class); final Map values = new HashMap<>(); values.put(DocumentFields.REV, doc.getRev()); executor.documentCache().setValues(value, values); @@ -144,7 +143,7 @@ protected ResponseDeserializer updateEdgeResponseDeseriali } protected Request deleteEdgeRequest(final String key, final EdgeDeleteOptions options) { - final Request request = request(graph.db().dbName(), RequestType.DELETE, PATH_API_GHARIAL, graph.name(), EDGE, + final Request request = request(graph.db().dbName(), RequestType.DELETE, PATH_API_GHARIAL, graph.name(), "edge", DocumentUtil.createDocumentHandle(name, key)); final EdgeDeleteOptions params = (options != null ? options : new EdgeDeleteOptions()); request.putHeaderParam(TRANSACTION_ID, params.getStreamTransactionId()); diff --git a/src/main/java/com/arangodb/internal/InternalArangoVertexCollection.java b/src/main/java/com/arangodb/internal/InternalArangoVertexCollection.java index 92e03d195..bc9d1e0a4 100644 --- a/src/main/java/com/arangodb/internal/InternalArangoVertexCollection.java +++ b/src/main/java/com/arangodb/internal/InternalArangoVertexCollection.java @@ -40,7 +40,6 @@ public abstract class InternalArangoVertexCollection { private static final String PATH_API_GHARIAL = "/_api/gharial"; - private static final String VERTEX = "vertex"; private static final String TRANSACTION_ID = "x-arango-trx-id"; @@ -62,11 +61,11 @@ public String name() { } protected Request dropRequest() { - return request(graph.db().dbName(), RequestType.DELETE, PATH_API_GHARIAL, graph.name(), VERTEX, name); + return request(graph.db().dbName(), RequestType.DELETE, PATH_API_GHARIAL, graph.name(), "vertex", name); } protected Request insertVertexRequest(final T value, final VertexCreateOptions options) { - final Request request = request(graph.db().dbName(), RequestType.POST, PATH_API_GHARIAL, graph.name(), VERTEX, + final Request request = request(graph.db().dbName(), RequestType.POST, PATH_API_GHARIAL, graph.name(), "vertex", name); final VertexCreateOptions params = (options != null ? options : new VertexCreateOptions()); request.putHeaderParam(TRANSACTION_ID, params.getStreamTransactionId()); @@ -84,7 +83,7 @@ protected Request insertVertexRequest(final T value, final VertexCreateOptio protected ResponseDeserializer insertVertexResponseDeserializer(final T value) { return response -> { - final VertexEntity doc = getInternalSerialization().deserialize(response.getBody(), VERTEX, VertexEntity.class); + final VertexEntity doc = getInternalSerialization().deserialize(response.getBody(), "/vertex", VertexEntity.class); final Map values = new HashMap<>(); values.put(DocumentFields.ID, doc.getId()); values.put(DocumentFields.KEY, doc.getKey()); @@ -95,7 +94,7 @@ protected ResponseDeserializer insertVertexResponseDeserialize } protected Request getVertexRequest(final String key, final GraphDocumentReadOptions options) { - final Request request = request(graph.db().dbName(), RequestType.GET, PATH_API_GHARIAL, graph.name(), VERTEX, + final Request request = request(graph.db().dbName(), RequestType.GET, PATH_API_GHARIAL, graph.name(), "vertex", DocumentUtil.createDocumentHandle(name, key)); final GraphDocumentReadOptions params = (options != null ? options : new GraphDocumentReadOptions()); request.putHeaderParam(TRANSACTION_ID, params.getStreamTransactionId()); @@ -108,11 +107,11 @@ protected Request getVertexRequest(final String key, final GraphDocumentReadOpti } protected ResponseDeserializer getVertexResponseDeserializer(final Class type) { - return response -> getUserSerialization().deserialize(getInternalSerialization().extract(response.getBody(), VERTEX), type); + return response -> getUserSerialization().deserialize(getInternalSerialization().extract(response.getBody(), "/vertex"), type); } protected Request replaceVertexRequest(final String key, final T value, final VertexReplaceOptions options) { - final Request request = request(graph.db().dbName(), RequestType.PUT, PATH_API_GHARIAL, graph.name(), VERTEX, + final Request request = request(graph.db().dbName(), RequestType.PUT, PATH_API_GHARIAL, graph.name(), "vertex", DocumentUtil.createDocumentHandle(name, key)); final VertexReplaceOptions params = (options != null ? options : new VertexReplaceOptions()); request.putHeaderParam(TRANSACTION_ID, params.getStreamTransactionId()); @@ -124,7 +123,7 @@ protected Request replaceVertexRequest(final String key, final T value, fina protected ResponseDeserializer replaceVertexResponseDeserializer(final T value) { return response -> { - final VertexUpdateEntity doc = getInternalSerialization().deserialize(response.getBody(), VERTEX, VertexUpdateEntity.class); + final VertexUpdateEntity doc = getInternalSerialization().deserialize(response.getBody(), "/vertex", VertexUpdateEntity.class); final Map values = new HashMap<>(); values.put(DocumentFields.REV, doc.getRev()); executor.documentCache().setValues(value, values); @@ -134,7 +133,7 @@ protected ResponseDeserializer replaceVertexResponseDese protected Request updateVertexRequest(final String key, final T value, final VertexUpdateOptions options) { final Request request; - request = request(graph.db().dbName(), RequestType.PATCH, PATH_API_GHARIAL, graph.name(), VERTEX, + request = request(graph.db().dbName(), RequestType.PATCH, PATH_API_GHARIAL, graph.name(), "vertex", DocumentUtil.createDocumentHandle(name, key)); final VertexUpdateOptions params = (options != null ? options : new VertexUpdateOptions()); request.putHeaderParam(TRANSACTION_ID, params.getStreamTransactionId()); @@ -147,7 +146,7 @@ protected Request updateVertexRequest(final String key, final T value, final protected ResponseDeserializer updateVertexResponseDeserializer(final T value) { return response -> { - final VertexUpdateEntity doc = getInternalSerialization().deserialize(response.getBody(), VERTEX, VertexUpdateEntity.class); + final VertexUpdateEntity doc = getInternalSerialization().deserialize(response.getBody(), "/vertex", VertexUpdateEntity.class); final Map values = new HashMap<>(); values.put(DocumentFields.REV, doc.getRev()); executor.documentCache().setValues(value, values); @@ -156,7 +155,7 @@ protected ResponseDeserializer updateVertexResponseDeser } protected Request deleteVertexRequest(final String key, final VertexDeleteOptions options) { - final Request request = request(graph.db().dbName(), RequestType.DELETE, PATH_API_GHARIAL, graph.name(), VERTEX, + final Request request = request(graph.db().dbName(), RequestType.DELETE, PATH_API_GHARIAL, graph.name(), "vertex", DocumentUtil.createDocumentHandle(name, key)); final VertexDeleteOptions params = (options != null ? options : new VertexDeleteOptions()); request.putHeaderParam(TRANSACTION_ID, params.getStreamTransactionId()); diff --git a/src/main/java/com/arangodb/internal/net/ExtendedHostResolver.java b/src/main/java/com/arangodb/internal/net/ExtendedHostResolver.java index e0bb05117..42bb7273b 100644 --- a/src/main/java/com/arangodb/internal/net/ExtendedHostResolver.java +++ b/src/main/java/com/arangodb/internal/net/ExtendedHostResolver.java @@ -22,7 +22,6 @@ import com.arangodb.ArangoDBException; import com.arangodb.DbName; -import com.arangodb.entity.CollectionEntity; import com.arangodb.internal.ArangoExecutorSync; import com.arangodb.internal.util.HostUtils; import com.arangodb.util.InternalSerialization; @@ -128,8 +127,9 @@ private Collection resolveFromServer() throws ArangoDBException { response = executor.execute( new Request(DbName.SYSTEM, RequestType.GET, "/_api/cluster/endpoints"), response1 -> { - final Collection> tmp = arangoSerialization.deserialize(response1.getBody(), "/endpoints", new Type>() { - }.getType()); + final Collection> tmp = arangoSerialization.deserialize(response1.getBody(), "/endpoints", + new Type>>() { + }.getType()); Collection endpoints = new ArrayList<>(); for (final Map map : tmp) { endpoints.add(map.get("endpoint")); diff --git a/src/main/java/com/arangodb/internal/velocypack/VPackDeserializers.java b/src/main/java/com/arangodb/internal/velocypack/VPackDeserializers.java index 06b5e0878..b7bbf5e31 100644 --- a/src/main/java/com/arangodb/internal/velocypack/VPackDeserializers.java +++ b/src/main/java/com/arangodb/internal/velocypack/VPackDeserializers.java @@ -130,107 +130,6 @@ public class VPackDeserializers { public static final VPackDeserializer VIEW_TYPE = (parent, vpack, context) -> "arangosearch".equals(vpack.getAsString()) ? ViewType.ARANGO_SEARCH : ViewType.valueOf(vpack.getAsString().toUpperCase(Locale.ENGLISH)); - public static final VPackDeserializer ARANGO_SEARCH_PROPERTIES = (parent, vpack, context) -> { - final ArangoSearchProperties properties = new ArangoSearchProperties(); - final VPackSlice consolidationIntervalMsec = vpack.get("consolidationIntervalMsec"); - if (consolidationIntervalMsec.isInteger()) { - properties.setConsolidationIntervalMsec(consolidationIntervalMsec.getAsLong()); - } - - final VPackSlice commitIntervalMsec = vpack.get("commitIntervalMsec"); - if (commitIntervalMsec.isInteger()) { - properties.setCommitIntervalMsec(commitIntervalMsec.getAsLong()); - } - - final VPackSlice cleanupIntervalStep = vpack.get("cleanupIntervalStep"); - if (cleanupIntervalStep.isInteger()) { - properties.setCleanupIntervalStep(cleanupIntervalStep.getAsLong()); - } - - final VPackSlice consolidationPolicy = vpack.get("consolidationPolicy"); - if (consolidationPolicy.isObject()) { - properties.setConsolidationPolicy( - context.deserialize(consolidationPolicy, ConsolidationPolicy.class)); - } - - final VPackSlice links = vpack.get("links"); - if (links.isObject()) { - final Iterator> collectionIterator = links.objectIterator(); - for (; collectionIterator.hasNext(); ) { - final Entry entry = collectionIterator.next(); - final VPackSlice value = entry.getValue(); - final CollectionLink link = CollectionLink.on(entry.getKey()); - final VPackSlice analyzers = value.get("analyzers"); - if (analyzers.isArray()) { - final Iterator analyzerIterator = analyzers.arrayIterator(); - for (; analyzerIterator.hasNext(); ) { - link.analyzers(analyzerIterator.next().getAsString()); - } - } - final VPackSlice includeAllFields = value.get("includeAllFields"); - if (includeAllFields.isBoolean()) { - link.includeAllFields(includeAllFields.getAsBoolean()); - } - final VPackSlice trackListPositions = value.get("trackListPositions"); - if (trackListPositions.isBoolean()) { - link.trackListPositions(trackListPositions.getAsBoolean()); - } - final VPackSlice storeValues = value.get("storeValues"); - if (storeValues.isString()) { - link.storeValues(StoreValuesType.valueOf(storeValues.getAsString().toUpperCase(Locale.ENGLISH))); - } - final VPackSlice fields = value.get("fields"); - if (fields.isObject()) { - final Iterator> fieldsIterator = fields.objectIterator(); - for (; fieldsIterator.hasNext(); ) { - link.fields(deserializeField(fieldsIterator.next())); - } - } - properties.addLink(link); - } - } - - final VPackSlice primarySorts = vpack.get("primarySort"); - if (primarySorts.isArray()) { - final Iterator primarySortsIterator = primarySorts.arrayIterator(); - for (; primarySortsIterator.hasNext(); ) { - final VPackSlice entry = primarySortsIterator.next(); - if (entry.isObject()) { - if (entry.get("field").isString() && entry.get("asc").isBoolean()) { - final PrimarySort primarySort = PrimarySort.on(entry.get("field").getAsString()); - primarySort.ascending(entry.get("asc").getAsBoolean()); - properties.addPrimarySort(primarySort); - } - } - } - } - - final VPackSlice primarySortCompression = vpack.get("primarySortCompression"); - if (primarySortCompression.isString()) { - properties.setPrimarySortCompression(ArangoSearchCompression.valueOf(primarySortCompression.getAsString())); - } - - final VPackSlice storedValues = vpack.get("storedValues"); - if (storedValues.isArray()) { - final Iterator storedValueIterator = storedValues.arrayIterator(); - for (; storedValueIterator.hasNext(); ) { - final VPackSlice entry = storedValueIterator.next(); - if (entry.isObject()) { - VPackSlice fields = entry.get("fields"); - VPackSlice compression = entry.get("compression"); - if (fields.isArray() && compression.isString()) { - final Iterator fieldsIterator = fields.arrayIterator(); - List fieldsList = new ArrayList<>(); - fieldsIterator.forEachRemaining(it -> fieldsList.add(it.getAsString())); - properties.addStoredValues(new StoredValue(fieldsList, ArangoSearchCompression.valueOf(compression.getAsString()))); - } - } - } - } - - return properties; - }; - protected static FieldLink deserializeField(final Entry field) { final VPackSlice value = field.getValue(); final FieldLink link = FieldLink.on(field.getKey()); @@ -263,13 +162,6 @@ protected static FieldLink deserializeField(final Entry fiel return link; } - public static final VPackDeserializer ARANGO_SEARCH_PROPERTIES_ENTITY = (parent, vpack, context) -> { - final ViewEntity entity = context.deserialize(vpack, ViewEntity.class); - final ArangoSearchProperties properties = context.deserialize(vpack, ArangoSearchProperties.class); - return new ArangoSearchPropertiesEntity(entity.getId(), - entity.getName(), entity.getType(), properties); - }; - public static final VPackDeserializer CONSOLIDATE = (parent, vpack, context) -> { final VPackSlice type = vpack.get("type"); if (type.isString()) { diff --git a/src/main/java/com/arangodb/internal/velocypack/VPackDriverModule.java b/src/main/java/com/arangodb/internal/velocypack/VPackDriverModule.java index 5172f8e3a..cab5b226a 100644 --- a/src/main/java/com/arangodb/internal/velocypack/VPackDriverModule.java +++ b/src/main/java/com/arangodb/internal/velocypack/VPackDriverModule.java @@ -21,8 +21,6 @@ package com.arangodb.internal.velocypack; import com.arangodb.entity.*; -import com.arangodb.entity.arangosearch.ArangoSearchProperties; -import com.arangodb.entity.arangosearch.ArangoSearchPropertiesEntity; import com.arangodb.entity.arangosearch.ConsolidationPolicy; import com.arangodb.entity.arangosearch.ConsolidationType; import com.arangodb.entity.arangosearch.analyzer.SearchAnalyzer; @@ -31,7 +29,6 @@ import com.arangodb.internal.velocystream.internal.JwtAuthenticationRequest; import com.arangodb.model.CollectionSchema; import com.arangodb.model.ZKDIndexOptions; -import com.arangodb.model.arangosearch.ArangoSearchPropertiesOptions; import com.arangodb.velocypack.VPackModule; import com.arangodb.velocypack.VPackParserModule; import com.arangodb.velocypack.VPackParserSetupContext; @@ -74,7 +71,6 @@ public > void setup(final C context) { context.registerSerializer(LogLevel.class, VPackSerializers.LOG_LEVEL); context.registerSerializer(Permissions.class, VPackSerializers.PERMISSIONS); context.registerSerializer(ViewType.class, VPackSerializers.VIEW_TYPE); - context.registerSerializer(ArangoSearchProperties.class, VPackSerializers.ARANGO_SEARCH_PROPERTIES); context.registerSerializer(ConsolidationType.class, VPackSerializers.CONSOLIDATE_TYPE); context.registerSerializer(CollectionSchema.class, VPackSerializers.COLLECTION_VALIDATION); context.registerSerializer(ZKDIndexOptions.FieldValueTypes.class, VPackSerializers.ZKD_FIELD_VALUE_TYPES); @@ -92,8 +88,6 @@ public > void setup(final C context) { context.registerDeserializer(QueryExecutionState.class, VPackDeserializers.QUERY_EXECUTION_STATE); context.registerDeserializer(ReplicationFactor.class, VPackDeserializers.REPLICATION_FACTOR); context.registerDeserializer(ViewType.class, VPackDeserializers.VIEW_TYPE); - context.registerDeserializer(ArangoSearchProperties.class, VPackDeserializers.ARANGO_SEARCH_PROPERTIES); - context.registerDeserializer(ArangoSearchPropertiesEntity.class, VPackDeserializers.ARANGO_SEARCH_PROPERTIES_ENTITY); context.registerDeserializer(ConsolidationPolicy.class, VPackDeserializers.CONSOLIDATE); context.registerDeserializer(CollectionSchema.class, VPackDeserializers.COLLECTION_VALIDATION); context.registerDeserializer(ZKDIndexOptions.FieldValueTypes.class, VPackDeserializers.ZKD_FIELD_VALUE_TYPES); diff --git a/src/main/java/com/arangodb/internal/velocypack/VPackSerializers.java b/src/main/java/com/arangodb/internal/velocypack/VPackSerializers.java index 56494405f..29af7f6c6 100644 --- a/src/main/java/com/arangodb/internal/velocypack/VPackSerializers.java +++ b/src/main/java/com/arangodb/internal/velocypack/VPackSerializers.java @@ -109,91 +109,6 @@ public class VPackSerializers { builder.add(attribute, type); }; - public static final VPackSerializer ARANGO_SEARCH_PROPERTIES = (builder, attribute, value, context) -> { - final Long consolidationIntervalMsec = value.getConsolidationIntervalMsec(); - if (consolidationIntervalMsec != null) { - builder.add("consolidationIntervalMsec", consolidationIntervalMsec); - } - - final Long commitIntervalMsec = value.getCommitIntervalMsec(); - if (commitIntervalMsec != null) { - builder.add("commitIntervalMsec", commitIntervalMsec); - } - - final Long cleanupIntervalStep = value.getCleanupIntervalStep(); - if (cleanupIntervalStep != null) { - builder.add("cleanupIntervalStep", cleanupIntervalStep); - } - context.serialize(builder, "consolidationPolicy", value.getConsolidationPolicy()); - - final Collection links = value.getLinks(); - if (!links.isEmpty()) { - builder.add("links", ValueType.OBJECT); - for (final CollectionLink collectionLink : links) { - builder.add(collectionLink.getName(), ValueType.OBJECT); - final Collection analyzers = collectionLink.getAnalyzers(); - if (!analyzers.isEmpty()) { - builder.add("analyzers", ValueType.ARRAY); - for (final String analyzer : analyzers) { - builder.add(analyzer); - } - builder.close(); - } - final Boolean includeAllFields = collectionLink.getIncludeAllFields(); - if (includeAllFields != null) { - builder.add("includeAllFields", includeAllFields); - } - final Boolean trackListPositions = collectionLink.getTrackListPositions(); - if (trackListPositions != null) { - builder.add("trackListPositions", trackListPositions); - } - final StoreValuesType storeValues = collectionLink.getStoreValues(); - if (storeValues != null) { - builder.add("storeValues", storeValues.name().toLowerCase(Locale.ENGLISH)); - } - serializeFieldLinks(builder, collectionLink.getFields()); - builder.close(); - } - builder.close(); - } - - final Collection primarySorts = value.getPrimarySort(); - if (!primarySorts.isEmpty()) { - builder.add("primarySort", ValueType.ARRAY); // open array - for (final PrimarySort primarySort : primarySorts) { - builder.add(ValueType.OBJECT); // open object - builder.add("field", primarySort.getFieldName()); - builder.add("asc", primarySort.getAscending()); - builder.close(); // close object - } - builder.close(); // close array - } - - final ArangoSearchCompression primarySortCompression = value.getPrimarySortCompression(); - if (primarySortCompression != null) { - builder.add("primarySortCompression", primarySortCompression.getValue()); - } - - final Collection storedValues = value.getStoredValues(); - if (!storedValues.isEmpty()) { - builder.add("storedValues", ValueType.ARRAY); // open array - for (final StoredValue storedValue : storedValues) { - builder.add(ValueType.OBJECT); // open object - builder.add("fields", ValueType.ARRAY); - for (final String field : storedValue.getFields()) { - builder.add(field); - } - builder.close(); - if (storedValue.getCompression() != null) { - builder.add("compression", storedValue.getCompression().getValue()); - } - builder.close(); // close object - } - builder.close(); // close array - } - - }; - private static void serializeFieldLinks(final VPackBuilder builder, final Collection links) { if (!links.isEmpty()) { builder.add("fields", ValueType.OBJECT); diff --git a/src/main/java/com/arangodb/model/VertexCollectionCreateOptions.java b/src/main/java/com/arangodb/model/VertexCollectionCreateOptions.java index 2e4f97a9c..e7132fc64 100644 --- a/src/main/java/com/arangodb/model/VertexCollectionCreateOptions.java +++ b/src/main/java/com/arangodb/model/VertexCollectionCreateOptions.java @@ -29,7 +29,7 @@ public class VertexCollectionCreateOptions { private String collection; - private final Options options = new Options();; + private final Options options = new Options(); public VertexCollectionCreateOptions() { super(); diff --git a/src/main/java/com/arangodb/serde/DataType.java b/src/main/java/com/arangodb/serde/DataType.java index 801e89234..59fc96bcf 100644 --- a/src/main/java/com/arangodb/serde/DataType.java +++ b/src/main/java/com/arangodb/serde/DataType.java @@ -32,7 +32,7 @@ public static DataType of(Protocol protocol) { case VST: return DataType.VPACK; default: - throw new IllegalStateException("Unexpected value: " + protocol); + throw new IllegalArgumentException("Unexpected value: " + protocol); } } } diff --git a/src/main/java/com/arangodb/serde/InternalDeserializers.java b/src/main/java/com/arangodb/serde/InternalDeserializers.java index f2132a089..7f8971f87 100644 --- a/src/main/java/com/arangodb/serde/InternalDeserializers.java +++ b/src/main/java/com/arangodb/serde/InternalDeserializers.java @@ -2,18 +2,62 @@ import com.arangodb.entity.CollectionStatus; import com.arangodb.entity.CollectionType; +import com.arangodb.entity.ReplicationFactor; +import com.arangodb.entity.arangosearch.CollectionLink; +import com.arangodb.entity.arangosearch.FieldLink; import com.arangodb.velocystream.Response; import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.core.TreeNode; import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.JsonDeserializer; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.node.ArrayNode; +import com.fasterxml.jackson.databind.node.NumericNode; +import com.fasterxml.jackson.databind.node.ObjectNode; +import com.fasterxml.jackson.databind.node.TextNode; import java.io.IOException; +import java.util.ArrayList; +import java.util.Collection; import java.util.Iterator; import java.util.Map; public final class InternalDeserializers { + + public static class CollectionLinksDeserializer extends JsonDeserializer> { + + @Override + public Collection deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { + Collection out = new ArrayList<>(); + ObjectNode tree = p.readValueAsTree(); + Iterator> it = tree.fields(); + while (it.hasNext()){ + Map.Entry e = it.next(); + ObjectNode v = (ObjectNode) e.getValue(); + v.put("name", e.getKey()); + out.add(ctxt.readTreeAsValue(v, CollectionLink.class)); + } + return out; + } + } + + public static class FieldLinksDeserializer extends JsonDeserializer { + + @Override + public FieldLink[] deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { + Collection out = new ArrayList<>(); + ObjectNode tree = p.readValueAsTree(); + Iterator> it = tree.fields(); + while (it.hasNext()){ + Map.Entry e = it.next(); + ObjectNode v = (ObjectNode) e.getValue(); + v.put("name", e.getKey()); + out.add(ctxt.readTreeAsValue(v, FieldLink.class)); + } + return out.toArray(new FieldLink[0]); + } + } + private InternalDeserializers() { } @@ -30,6 +74,19 @@ public CollectionType deserialize(final JsonParser p, final DeserializationConte return CollectionType.fromType(p.getIntValue()); } }; + + static final JsonDeserializer REPLICATION_FACTOR = new JsonDeserializer() { + @Override + public ReplicationFactor deserialize(final JsonParser p, final DeserializationContext ctxt) throws IOException { + TreeNode node = p.readValueAsTree(); + if (node instanceof NumericNode) { + return ReplicationFactor.of(((NumericNode) node).intValue()); + } else if (node instanceof TextNode && "satellite".equals(((TextNode) node).textValue())) { + return ReplicationFactor.ofSatellite(); + } else throw new IllegalArgumentException(); + } + }; + static final JsonDeserializer RESPONSE = new JsonDeserializer() { @Override public Response deserialize(final JsonParser p, final DeserializationContext ctxt) throws IOException { diff --git a/src/main/java/com/arangodb/serde/InternalModule.java b/src/main/java/com/arangodb/serde/InternalModule.java index 9f9e25a62..c606daecb 100644 --- a/src/main/java/com/arangodb/serde/InternalModule.java +++ b/src/main/java/com/arangodb/serde/InternalModule.java @@ -2,6 +2,7 @@ import com.arangodb.entity.CollectionStatus; import com.arangodb.entity.CollectionType; +import com.arangodb.entity.ReplicationFactor; import com.arangodb.internal.velocystream.internal.AuthenticationRequest; import com.arangodb.internal.velocystream.internal.JwtAuthenticationRequest; import com.arangodb.velocypack.VPackSlice; @@ -28,6 +29,7 @@ enum InternalModule implements Supplier { module.addDeserializer(CollectionStatus.class, InternalDeserializers.COLLECTION_STATUS); module.addDeserializer(CollectionType.class, InternalDeserializers.COLLECTION_TYPE); + module.addDeserializer(ReplicationFactor.class, InternalDeserializers.REPLICATION_FACTOR); module.addDeserializer(Response.class, InternalDeserializers.RESPONSE); } diff --git a/src/main/java/com/arangodb/serde/InternalSerde.java b/src/main/java/com/arangodb/serde/InternalSerde.java index e67b4d811..70f531c86 100644 --- a/src/main/java/com/arangodb/serde/InternalSerde.java +++ b/src/main/java/com/arangodb/serde/InternalSerde.java @@ -21,7 +21,7 @@ static InternalSerde of(final DataType dataType) { } else if (dataType == DataType.VPACK) { return new InternalSerdeImpl(dataType, new VPackMapper()); } else { - throw new IllegalStateException("Unexpected value: " + dataType); + throw new IllegalArgumentException("Unexpected value: " + dataType); } } diff --git a/src/main/java/com/arangodb/serde/InternalSerdeImpl.java b/src/main/java/com/arangodb/serde/InternalSerdeImpl.java index a779b5cf3..b8e01d8bf 100644 --- a/src/main/java/com/arangodb/serde/InternalSerdeImpl.java +++ b/src/main/java/com/arangodb/serde/InternalSerdeImpl.java @@ -35,7 +35,7 @@ public String toJsonString(final byte[] content) { throw new ArangoDBException(e); } default: - throw new IllegalStateException("Unexpected value: " + dataType); + throw new IllegalArgumentException("Unexpected value: " + dataType); } } diff --git a/src/main/java/com/arangodb/serde/JacksonSerde.java b/src/main/java/com/arangodb/serde/JacksonSerde.java index 91d9ede18..901266c70 100644 --- a/src/main/java/com/arangodb/serde/JacksonSerde.java +++ b/src/main/java/com/arangodb/serde/JacksonSerde.java @@ -26,7 +26,7 @@ static JacksonSerde of(final DataType dataType) { } else if (dataType == DataType.VPACK) { return of(dataType, new VPackMapper()); } else { - throw new IllegalStateException("Unexpected value: " + dataType); + throw new IllegalArgumentException("Unexpected value: " + dataType); } } diff --git a/src/test/java/com/arangodb/ArangoDBTest.java b/src/test/java/com/arangodb/ArangoDBTest.java index cc80eacbf..dfba5e9ce 100644 --- a/src/test/java/com/arangodb/ArangoDBTest.java +++ b/src/test/java/com/arangodb/ArangoDBTest.java @@ -395,7 +395,7 @@ void authenticationFailUser() { @MethodSource("arangos") void execute(ArangoDB arangoDB) throws VPackException { final Response response = arangoDB.execute(new Request(DbName.SYSTEM, RequestType.GET, "/_api/version")); - assertThat(arangoDB.getInternalSerialization().parse(response.getBody(), "version").isTextual()).isTrue(); + assertThat(arangoDB.getInternalSerialization().parse(response.getBody(), "/version").isTextual()).isTrue(); } @ParameterizedTest(name = "{index}") diff --git a/src/test/java/com/arangodb/ArangoSearchTest.java b/src/test/java/com/arangodb/ArangoSearchTest.java index cfbf8a477..59242b3a7 100644 --- a/src/test/java/com/arangodb/ArangoSearchTest.java +++ b/src/test/java/com/arangodb/ArangoSearchTest.java @@ -595,9 +595,9 @@ void stopwordsAnalyzer(ArangoDatabase db) { createGetAndDeleteTypedAnalyzer(db, analyzer); db.createSearchAnalyzer(analyzer); - String res = db.query("RETURN FLATTEN(TOKENS(SPLIT('the fox and the dog and a theater', ' '), @aName))", - Collections.singletonMap("aName", name), String.class).next(); - assertThat(res).isEqualTo("[\"fox\",\"dog\",\"a\",\"theater\"]"); + Collection res = db.query("RETURN FLATTEN(TOKENS(SPLIT('the fox and the dog and a theater', ' '), @aName))", + Collections.singletonMap("aName", name), Collection.class).next(); + assertThat(res).containsExactly("fox", "dog", "a", "theater"); db.deleteSearchAnalyzer(name); } diff --git a/src/test/java/com/arangodb/internal/velocypack/VPackSerializersTest.java b/src/test/java/com/arangodb/internal/velocypack/VPackSerializersTest.java index 5c3880ba6..0b8658a65 100644 --- a/src/test/java/com/arangodb/internal/velocypack/VPackSerializersTest.java +++ b/src/test/java/com/arangodb/internal/velocypack/VPackSerializersTest.java @@ -22,7 +22,6 @@ import com.arangodb.entity.ViewType; import com.arangodb.entity.arangosearch.ArangoSearchCompression; -import com.arangodb.entity.arangosearch.ArangoSearchProperties; import com.arangodb.entity.arangosearch.StoredValue; import com.arangodb.model.arangosearch.ArangoSearchCreateOptions; import com.arangodb.velocypack.VPack; @@ -40,9 +39,7 @@ class VPackSerializersTest { @BeforeEach void init() { - vpack = new VPack.Builder() - .registerSerializer(ArangoSearchProperties.class, VPackSerializers.ARANGO_SEARCH_PROPERTIES) - .build(); + vpack = new VPack.Builder().build(); } @Test From 15c3b02b3890512fc220fdd1af19654e050f66fc Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Tue, 12 Jul 2022 17:30:22 +0200 Subject: [PATCH 029/254] deserializer refactoring: Collections API --- .../internal/ArangoCollectionAsyncImpl.java | 3 +- .../internal/ArangoCollectionImpl.java | 2 +- .../com/arangodb/internal/ArangoExecutor.java | 3 +- .../internal/ArangoResponseField.java | 4 +- .../internal/InternalArangoCollection.java | 186 ++++++++++-------- .../arangodb/internal/InternalArangoDB.java | 8 +- .../internal/InternalArangoDatabase.java | 18 +- .../internal/InternalArangoGraph.java | 6 +- .../com/arangodb/model/CollectionSchema.java | 3 + .../arangodb/serde/InternalDeserializers.java | 18 +- .../com/arangodb/ArangoCollectionTest.java | 4 +- .../graph/AQLActorsAndMoviesExampleTest.java | 19 +- .../graph/AQLActorsAndMoviesExampleTest.java | 24 +-- .../util/ArangoSerializationTest.java | 6 +- 14 files changed, 163 insertions(+), 141 deletions(-) diff --git a/src/main/java/com/arangodb/async/internal/ArangoCollectionAsyncImpl.java b/src/main/java/com/arangodb/async/internal/ArangoCollectionAsyncImpl.java index b5be30c1c..7f444ad9e 100644 --- a/src/main/java/com/arangodb/async/internal/ArangoCollectionAsyncImpl.java +++ b/src/main/java/com/arangodb/async/internal/ArangoCollectionAsyncImpl.java @@ -106,14 +106,13 @@ public CompletableFuture getDocument(final String key, final Class typ } @Override - @SuppressWarnings("unchecked") public CompletableFuture getDocument( final String key, final Class type, final DocumentReadOptions options) throws ArangoDBException { DocumentUtil.validateDocumentKey(key); boolean isCatchException = options != null ? options.isCatchException() : new DocumentReadOptions().isCatchException(); - return (CompletableFuture) executor.execute(getDocumentRequest(key, options), type) + return executor.execute(getDocumentRequest(key, options), getDocumentResponseDeserializer(type)) .exceptionally(ExceptionUtil.catchGetDocumentExceptions(isCatchException)); } diff --git a/src/main/java/com/arangodb/internal/ArangoCollectionImpl.java b/src/main/java/com/arangodb/internal/ArangoCollectionImpl.java index 6dded7789..01fa6d99a 100644 --- a/src/main/java/com/arangodb/internal/ArangoCollectionImpl.java +++ b/src/main/java/com/arangodb/internal/ArangoCollectionImpl.java @@ -102,7 +102,7 @@ public T getDocument(final String key, final Class type, final DocumentRe throws ArangoDBException { DocumentUtil.validateDocumentKey(key); try { - return executor.execute(getDocumentRequest(key, options), type); + return executor.execute(getDocumentRequest(key, options), getDocumentResponseDeserializer(type)); } catch (final ArangoDBException e) { if (LOGGER.isDebugEnabled()) { LOGGER.debug(e.getMessage(), e); diff --git a/src/main/java/com/arangodb/internal/ArangoExecutor.java b/src/main/java/com/arangodb/internal/ArangoExecutor.java index bbdd8d1b1..4c5b08443 100644 --- a/src/main/java/com/arangodb/internal/ArangoExecutor.java +++ b/src/main/java/com/arangodb/internal/ArangoExecutor.java @@ -42,7 +42,8 @@ protected T createResult(final Type type, final Response response) { if (isInternal(type)) { return (T) util.getInternalSerialization().deserialize(response.getBody(), type); } else { - return (T) util.getUserSerialization().deserialize(response.getBody(), type); + throw new RuntimeException("FIXME: this should not never happen"); +// return (T) util.getUserSerialization().deserialize(response.getBody(), type); } } else { return null; diff --git a/src/main/java/com/arangodb/internal/ArangoResponseField.java b/src/main/java/com/arangodb/internal/ArangoResponseField.java index 2a828cc03..5ce43feda 100644 --- a/src/main/java/com/arangodb/internal/ArangoResponseField.java +++ b/src/main/java/com/arangodb/internal/ArangoResponseField.java @@ -29,7 +29,7 @@ private ArangoResponseField() { super(); } - public static final String ERROR = "/error"; - public static final String RESULT = "/result"; + public static final String ERROR_FIELD_NAME = "error"; + public static final String RESULT_JSON_POINTER = "/result"; } diff --git a/src/main/java/com/arangodb/internal/InternalArangoCollection.java b/src/main/java/com/arangodb/internal/InternalArangoCollection.java index 3bb982a51..8e0985314 100644 --- a/src/main/java/com/arangodb/internal/InternalArangoCollection.java +++ b/src/main/java/com/arangodb/internal/InternalArangoCollection.java @@ -107,12 +107,21 @@ protected ResponseDeserializer> insertDocumentRespon final JsonNode body = getInternalSerialization().parse(response.getBody()); final DocumentCreateEntity doc = getInternalSerialization().deserialize(body, DocumentCreateEntity.class); final JsonNode newDoc = body.get(NEW); - if (newDoc.isObject()) { - doc.setNew(getUserSerialization().deserialize(getInternalSerialization().serialize(newDoc), value.getClass())); + Class clazz = value.getClass(); + if (newDoc != null) { + if (String.class.isAssignableFrom(clazz)) { + doc.setNew((T) SerdeUtils.INSTANCE.writeJson(newDoc)); + } else { + doc.setNew(getUserSerialization().deserialize(getInternalSerialization().serialize(newDoc), clazz)); + } } final JsonNode oldDoc = body.get(OLD); - if (oldDoc.isObject()) { - doc.setOld(getUserSerialization().deserialize(getInternalSerialization().serialize(oldDoc), value.getClass())); + if (oldDoc != null) { + if (String.class.isAssignableFrom(clazz)) { + doc.setOld((T) SerdeUtils.INSTANCE.writeJson(oldDoc)); + } else { + doc.setOld(getUserSerialization().deserialize(getInternalSerialization().serialize(oldDoc), clazz)); + } } if (options == null || Boolean.TRUE != options.getSilent()) { final Map values = new HashMap<>(); @@ -156,26 +165,25 @@ protected ResponseDeserializer>> final Collection errors = new ArrayList<>(); final Collection documentsAndErrors = new ArrayList<>(); final JsonNode body = getInternalSerialization().parse(response.getBody()); - if (body.isArray()) { - for (final Iterator iterator = body.iterator(); iterator.hasNext(); ) { - final JsonNode next = iterator.next(); - if (next.get(ArangoResponseField.ERROR).booleanValue()) { - final ErrorEntity error = getInternalSerialization().deserialize(next, ErrorEntity.class); - errors.add(error); - documentsAndErrors.add(error); - } else { - final DocumentCreateEntity doc = getInternalSerialization().deserialize(next, DocumentCreateEntity.class); - final JsonNode newDoc = next.get(NEW); - if (newDoc.isObject()) { - doc.setNew(getUserSerialization().deserialize(getInternalSerialization().serialize(newDoc), type)); - } - final JsonNode oldDoc = next.get(OLD); - if (oldDoc.isObject()) { - doc.setOld(getUserSerialization().deserialize(getInternalSerialization().serialize(oldDoc), type)); - } - docs.add(doc); - documentsAndErrors.add(doc); + for (final Iterator iterator = body.iterator(); iterator.hasNext(); ) { + final JsonNode next = iterator.next(); + JsonNode isError = next.get(ArangoResponseField.ERROR_FIELD_NAME); + if (isError != null && isError.booleanValue()) { + final ErrorEntity error = getInternalSerialization().deserialize(next, ErrorEntity.class); + errors.add(error); + documentsAndErrors.add(error); + } else { + final DocumentCreateEntity doc = getInternalSerialization().deserialize(next, DocumentCreateEntity.class); + final JsonNode newDoc = next.get(NEW); + if (newDoc != null) { + doc.setNew(getUserSerialization().deserialize(getInternalSerialization().serialize(newDoc), type)); } + final JsonNode oldDoc = next.get(OLD); + if (oldDoc != null) { + doc.setOld(getUserSerialization().deserialize(getInternalSerialization().serialize(oldDoc), type)); + } + docs.add(doc); + documentsAndErrors.add(doc); } } multiDocument.setDocuments(docs); @@ -217,6 +225,16 @@ protected Request getDocumentRequest(final String key, final DocumentReadOptions return request; } + protected ResponseDeserializer getDocumentResponseDeserializer(final Class type) { + return response -> { + if (String.class.isAssignableFrom(type)) { + return (T) SerdeUtils.INSTANCE.writeJson(getInternalSerialization().parse(response.getBody())); + } else { + return getUserSerialization().deserialize(response.getBody(), type); + } + }; + } + protected Request getDocumentsRequest(final Collection keys, final DocumentReadOptions options) { final DocumentReadOptions params = (options != null ? options : new DocumentReadOptions()); final Request request = request(db.dbName(), RequestType.PUT, PATH_API_DOCUMENT, name) @@ -240,7 +258,8 @@ protected ResponseDeserializer> getDocumentsResponseD final JsonNode body = getInternalSerialization().parse(response.getBody()); for (final Iterator iterator = body.iterator(); iterator.hasNext(); ) { final JsonNode next = iterator.next(); - if (next.get(ArangoResponseField.ERROR).booleanValue()) { + JsonNode isError = next.get(ArangoResponseField.ERROR_FIELD_NAME); + if (isError != null && isError.booleanValue()) { final ErrorEntity error = getInternalSerialization().deserialize(next, ErrorEntity.class); errors.add(error); documentsAndErrors.add(error); @@ -279,11 +298,11 @@ protected ResponseDeserializer> replaceDocumentRespo final JsonNode body = getInternalSerialization().parse(response.getBody()); final DocumentUpdateEntity doc = getInternalSerialization().deserialize(body, DocumentUpdateEntity.class); final JsonNode newDoc = body.get(NEW); - if (newDoc.isObject()) { + if (newDoc != null) { doc.setNew(getUserSerialization().deserialize(getInternalSerialization().serialize(newDoc), value.getClass())); } final JsonNode oldDoc = body.get(OLD); - if (oldDoc.isObject()) { + if (oldDoc != null) { doc.setOld(getUserSerialization().deserialize(getInternalSerialization().serialize(oldDoc), value.getClass())); } if (options == null || Boolean.TRUE != options.getSilent()) { @@ -326,26 +345,25 @@ protected ResponseDeserializer>> final Collection errors = new ArrayList<>(); final Collection documentsAndErrors = new ArrayList<>(); final JsonNode body = getInternalSerialization().parse(response.getBody()); - if (body.isArray()) { - for (final Iterator iterator = body.iterator(); iterator.hasNext(); ) { - final JsonNode next = iterator.next(); - if (next.get(ArangoResponseField.ERROR).booleanValue()) { - final ErrorEntity error = getInternalSerialization().deserialize(next, ErrorEntity.class); - errors.add(error); - documentsAndErrors.add(error); - } else { - final DocumentUpdateEntity doc = getInternalSerialization().deserialize(next, DocumentUpdateEntity.class); - final JsonNode newDoc = next.get(NEW); - if (newDoc.isObject()) { - doc.setNew(getUserSerialization().deserialize(getInternalSerialization().serialize(newDoc), type)); - } - final JsonNode oldDoc = next.get(OLD); - if (oldDoc.isObject()) { - doc.setOld(getUserSerialization().deserialize(getInternalSerialization().serialize(oldDoc), type)); - } - docs.add(doc); - documentsAndErrors.add(doc); + for (final Iterator iterator = body.iterator(); iterator.hasNext(); ) { + final JsonNode next = iterator.next(); + JsonNode isError = next.get(ArangoResponseField.ERROR_FIELD_NAME); + if (isError != null && isError.booleanValue()) { + final ErrorEntity error = getInternalSerialization().deserialize(next, ErrorEntity.class); + errors.add(error); + documentsAndErrors.add(error); + } else { + final DocumentUpdateEntity doc = getInternalSerialization().deserialize(next, DocumentUpdateEntity.class); + final JsonNode newDoc = next.get(NEW); + if (newDoc != null) { + doc.setNew(getUserSerialization().deserialize(getInternalSerialization().serialize(newDoc), type)); } + final JsonNode oldDoc = next.get(OLD); + if (oldDoc != null) { + doc.setOld(getUserSerialization().deserialize(getInternalSerialization().serialize(oldDoc), type)); + } + docs.add(doc); + documentsAndErrors.add(doc); } } multiDocument.setDocuments(docs); @@ -378,11 +396,11 @@ protected ResponseDeserializer> updateDocumentRes final JsonNode body = getInternalSerialization().parse(response.getBody()); final DocumentUpdateEntity doc = getInternalSerialization().deserialize(body, DocumentUpdateEntity.class); final JsonNode newDoc = body.get(NEW); - if (newDoc.isObject()) { + if (newDoc != null) { doc.setNew(getUserSerialization().deserialize(getInternalSerialization().serialize(newDoc), returnType)); } final JsonNode oldDoc = body.get(OLD); - if (oldDoc.isObject()) { + if (oldDoc != null) { doc.setOld(getUserSerialization().deserialize(getInternalSerialization().serialize(oldDoc), returnType)); } if (options == null || Boolean.TRUE != options.getSilent()) { @@ -422,26 +440,25 @@ protected ResponseDeserializer>> final Collection errors = new ArrayList<>(); final Collection documentsAndErrors = new ArrayList<>(); final JsonNode body = getInternalSerialization().parse(response.getBody()); - if (body.isArray()) { - for (final Iterator iterator = body.iterator(); iterator.hasNext(); ) { - final JsonNode next = iterator.next(); - if (next.get(ArangoResponseField.ERROR).booleanValue()) { - final ErrorEntity error = getInternalSerialization().deserialize(next, ErrorEntity.class); - errors.add(error); - documentsAndErrors.add(error); - } else { - final DocumentUpdateEntity doc = getInternalSerialization().deserialize(next, DocumentUpdateEntity.class); - final JsonNode newDoc = next.get(NEW); - if (newDoc.isObject()) { - doc.setNew(getUserSerialization().deserialize(getInternalSerialization().serialize(newDoc), returnType)); - } - final JsonNode oldDoc = next.get(OLD); - if (oldDoc.isObject()) { - doc.setOld(getUserSerialization().deserialize(getInternalSerialization().serialize(oldDoc), returnType)); - } - docs.add(doc); - documentsAndErrors.add(doc); + for (final Iterator iterator = body.iterator(); iterator.hasNext(); ) { + final JsonNode next = iterator.next(); + JsonNode isError = next.get(ArangoResponseField.ERROR_FIELD_NAME); + if (isError != null && isError.booleanValue()) { + final ErrorEntity error = getInternalSerialization().deserialize(next, ErrorEntity.class); + errors.add(error); + documentsAndErrors.add(error); + } else { + final DocumentUpdateEntity doc = getInternalSerialization().deserialize(next, DocumentUpdateEntity.class); + final JsonNode newDoc = next.get(NEW); + if (newDoc != null) { + doc.setNew(getUserSerialization().deserialize(getInternalSerialization().serialize(newDoc), returnType)); } + final JsonNode oldDoc = next.get(OLD); + if (oldDoc != null) { + doc.setOld(getUserSerialization().deserialize(getInternalSerialization().serialize(oldDoc), returnType)); + } + docs.add(doc); + documentsAndErrors.add(doc); } } multiDocument.setDocuments(docs); @@ -469,7 +486,7 @@ protected ResponseDeserializer> deleteDocumentRespon final JsonNode body = getInternalSerialization().parse(response.getBody()); final DocumentDeleteEntity doc = getInternalSerialization().deserialize(body, DocumentDeleteEntity.class); final JsonNode oldDoc = body.get(OLD); - if (oldDoc.isObject()) { + if (oldDoc != null) { doc.setOld(getUserSerialization().deserialize(getInternalSerialization().serialize(oldDoc), type)); } return doc; @@ -495,22 +512,21 @@ protected ResponseDeserializer>> final Collection errors = new ArrayList<>(); final Collection documentsAndErrors = new ArrayList<>(); final JsonNode body = getInternalSerialization().parse(response.getBody()); - if (body.isArray()) { - for (final Iterator iterator = body.iterator(); iterator.hasNext(); ) { - final JsonNode next = iterator.next(); - if (next.get(ArangoResponseField.ERROR).booleanValue()) { - final ErrorEntity error = getInternalSerialization().deserialize(next, ErrorEntity.class); - errors.add(error); - documentsAndErrors.add(error); - } else { - final DocumentDeleteEntity doc = getInternalSerialization().deserialize(next, DocumentDeleteEntity.class); - final JsonNode oldDoc = next.get(OLD); - if (oldDoc.isObject()) { - doc.setOld(getUserSerialization().deserialize(getInternalSerialization().serialize(oldDoc), type)); - } - docs.add(doc); - documentsAndErrors.add(doc); + for (final Iterator iterator = body.iterator(); iterator.hasNext(); ) { + final JsonNode next = iterator.next(); + JsonNode isError = next.get(ArangoResponseField.ERROR_FIELD_NAME); + if (isError != null && isError.booleanValue()) { + final ErrorEntity error = getInternalSerialization().deserialize(next, ErrorEntity.class); + errors.add(error); + documentsAndErrors.add(error); + } else { + final DocumentDeleteEntity doc = getInternalSerialization().deserialize(next, DocumentDeleteEntity.class); + final JsonNode oldDoc = next.get(OLD); + if (oldDoc != null) { + doc.setOld(getUserSerialization().deserialize(getInternalSerialization().serialize(oldDoc), type)); } + docs.add(doc); + documentsAndErrors.add(doc); } } multiDocument.setDocuments(docs); @@ -539,7 +555,7 @@ protected Request deleteIndexRequest(final String id) { } protected ResponseDeserializer deleteIndexResponseDeserializer() { - return response -> getInternalSerialization().deserialize(response.getBody(), "id", String.class); + return response -> getInternalSerialization().deserialize(response.getBody(), "/id", String.class); } private String createIndexId(final String id) { @@ -621,7 +637,7 @@ protected Request getIndexesRequest() { } protected ResponseDeserializer> getIndexesResponseDeserializer() { - return response -> getInternalSerialization().deserialize(response.getBody(), "indexes", new Type>() { + return response -> getInternalSerialization().deserialize(response.getBody(), "/indexes", new Type>() { }.getType()); } @@ -689,7 +705,7 @@ protected Request getPermissionsRequest(final String user) { } protected ResponseDeserializer getPermissionsResponseDeserialzer() { - return response -> getInternalSerialization().deserialize(response.getBody(), ArangoResponseField.RESULT, Permissions.class); + return response -> getInternalSerialization().deserialize(response.getBody(), ArangoResponseField.RESULT_JSON_POINTER, Permissions.class); } private boolean isStringCollection(final Collection values) { diff --git a/src/main/java/com/arangodb/internal/InternalArangoDB.java b/src/main/java/com/arangodb/internal/InternalArangoDB.java index 49c545c60..584449d30 100644 --- a/src/main/java/com/arangodb/internal/InternalArangoDB.java +++ b/src/main/java/com/arangodb/internal/InternalArangoDB.java @@ -78,7 +78,7 @@ protected Request createDatabaseRequest(final DBCreateOptions options) { } protected ResponseDeserializer createDatabaseResponseDeserializer() { - return response -> getInternalSerialization().deserialize(response.getBody(), ArangoResponseField.RESULT, Boolean.class); + return response -> getInternalSerialization().deserialize(response.getBody(), ArangoResponseField.RESULT_JSON_POINTER, Boolean.class); } protected Request getDatabasesRequest(final DbName dbName) { @@ -86,7 +86,7 @@ protected Request getDatabasesRequest(final DbName dbName) { } protected ResponseDeserializer> getDatabaseResponseDeserializer() { - return response -> getInternalSerialization().deserialize(response.getBody(), ArangoResponseField.RESULT, new Type>() { + return response -> getInternalSerialization().deserialize(response.getBody(), ArangoResponseField.RESULT_JSON_POINTER, new Type>() { }.getType()); } @@ -96,7 +96,7 @@ protected Request getAccessibleDatabasesForRequest(final DbName dbName, final St protected ResponseDeserializer> getAccessibleDatabasesForResponseDeserializer() { return response -> { - Iterator names = getInternalSerialization().parse(response.getBody(), ArangoResponseField.RESULT).fieldNames(); + Iterator names = getInternalSerialization().parse(response.getBody(), ArangoResponseField.RESULT_JSON_POINTER).fieldNames(); final Collection dbs = new ArrayList<>(); while (names.hasNext()) { dbs.add(names.next()); @@ -130,7 +130,7 @@ protected Request getUserRequest(final DbName dbName, final String user) { } protected ResponseDeserializer> getUsersResponseDeserializer() { - return response -> getInternalSerialization().deserialize(response.getBody(), ArangoResponseField.RESULT, new Type>() { + return response -> getInternalSerialization().deserialize(response.getBody(), ArangoResponseField.RESULT_JSON_POINTER, new Type>() { }.getType()); } diff --git a/src/main/java/com/arangodb/internal/InternalArangoDatabase.java b/src/main/java/com/arangodb/internal/InternalArangoDatabase.java index ba23a1c66..4d188d426 100644 --- a/src/main/java/com/arangodb/internal/InternalArangoDatabase.java +++ b/src/main/java/com/arangodb/internal/InternalArangoDatabase.java @@ -111,7 +111,7 @@ protected Request getCollectionsRequest(final CollectionsReadOptions options) { } protected ResponseDeserializer> getCollectionsResponseDeserializer() { - return response -> getInternalSerialization().deserialize(getInternalSerialization().parse(response.getBody(), ArangoResponseField.RESULT), new Type>() { + return response -> getInternalSerialization().deserialize(getInternalSerialization().parse(response.getBody(), ArangoResponseField.RESULT_JSON_POINTER), new Type>() { }.getType()); } @@ -120,7 +120,7 @@ protected Request dropRequest() { } protected ResponseDeserializer createDropResponseDeserializer() { - return response -> getInternalSerialization().deserialize(response.getBody(), ArangoResponseField.RESULT, Boolean.class); + return response -> getInternalSerialization().deserialize(response.getBody(), ArangoResponseField.RESULT_JSON_POINTER, Boolean.class); } protected Request grantAccessRequest(final String user, final Permissions permissions) { @@ -140,7 +140,7 @@ protected Request getPermissionsRequest(final String user) { } protected ResponseDeserializer getPermissionsResponseDeserialzer() { - return response -> getInternalSerialization().deserialize(response.getBody(), ArangoResponseField.RESULT, Permissions.class); + return response -> getInternalSerialization().deserialize(response.getBody(), ArangoResponseField.RESULT_JSON_POINTER, Permissions.class); } protected Request queryRequest(final String query, final Map bindVars, final AqlQueryOptions options) { @@ -257,7 +257,7 @@ protected Request getAqlFunctionsRequest(final AqlFunctionGetOptions options) { } protected ResponseDeserializer> getAqlFunctionsResponseDeserializer() { - return response -> getInternalSerialization().deserialize(response.getBody(), ArangoResponseField.RESULT, new Type>() { + return response -> getInternalSerialization().deserialize(response.getBody(), ArangoResponseField.RESULT_JSON_POINTER, new Type>() { }.getType()); } @@ -283,7 +283,7 @@ protected Request transactionRequest(final String action, final TransactionOptio } protected ResponseDeserializer transactionResponseDeserializer(final Class type) { - return response -> getUserSerialization().deserialize(getInternalSerialization().extract(response.getBody(), ArangoResponseField.RESULT), type); + return response -> getUserSerialization().deserialize(getInternalSerialization().extract(response.getBody(), ArangoResponseField.RESULT_JSON_POINTER), type); } protected Request beginStreamTransactionRequest(final StreamTransactionOptions options) { @@ -312,7 +312,7 @@ protected Request commitStreamTransactionRequest(String id) { } protected ResponseDeserializer streamTransactionResponseDeserializer() { - return response -> getInternalSerialization().deserialize(response.getBody(), ArangoResponseField.RESULT, StreamTransactionEntity.class); + return response -> getInternalSerialization().deserialize(response.getBody(), ArangoResponseField.RESULT_JSON_POINTER, StreamTransactionEntity.class); } protected Request getInfoRequest() { @@ -320,7 +320,7 @@ protected Request getInfoRequest() { } protected ResponseDeserializer getInfoResponseDeserializer() { - return response -> getInternalSerialization().deserialize(response.getBody(), ArangoResponseField.RESULT, DatabaseEntity.class); + return response -> getInternalSerialization().deserialize(response.getBody(), ArangoResponseField.RESULT_JSON_POINTER, DatabaseEntity.class); } protected Request reloadRoutingRequest() { @@ -332,7 +332,7 @@ protected Request getViewsRequest() { } protected ResponseDeserializer> getViewsResponseDeserializer() { - return response -> getInternalSerialization().deserialize(response.getBody(), ArangoResponseField.RESULT, new Type>() { + return response -> getInternalSerialization().deserialize(response.getBody(), ArangoResponseField.RESULT_JSON_POINTER, new Type>() { }.getType()); } @@ -353,7 +353,7 @@ protected Request getAnalyzersRequest() { } protected ResponseDeserializer> getSearchAnalyzersResponseDeserializer() { - return response -> getInternalSerialization().deserialize(response.getBody(), ArangoResponseField.RESULT, new Type>() { + return response -> getInternalSerialization().deserialize(response.getBody(), ArangoResponseField.RESULT_JSON_POINTER, new Type>() { }.getType()); } diff --git a/src/main/java/com/arangodb/internal/InternalArangoGraph.java b/src/main/java/com/arangodb/internal/InternalArangoGraph.java index e65d3a9cb..8108dd57a 100644 --- a/src/main/java/com/arangodb/internal/InternalArangoGraph.java +++ b/src/main/java/com/arangodb/internal/InternalArangoGraph.java @@ -38,7 +38,7 @@ public abstract class InternalArangoGraph, D exten extends ArangoExecuteable { protected static final String PATH_API_GHARIAL = "/_api/gharial"; - private static final String GRAPH = "graph"; + private static final String GRAPH = "/graph"; private static final String VERTEX = "vertex"; private static final String EDGE = "edge"; @@ -84,7 +84,7 @@ protected Request getVertexCollectionsRequest() { } protected ResponseDeserializer> getVertexCollectionsResponseDeserializer() { - return response -> getInternalSerialization().deserialize(response.getBody(), "collections", new Type>() { + return response -> getInternalSerialization().deserialize(response.getBody(), "/collections", new Type>() { }.getType()); } @@ -103,7 +103,7 @@ protected Request getEdgeDefinitionsRequest() { } protected ResponseDeserializer> getEdgeDefinitionsDeserializer() { - return response -> getInternalSerialization().deserialize(response.getBody(), "collections", new Type>() { + return response -> getInternalSerialization().deserialize(response.getBody(), "/collections", new Type>() { }.getType()); } diff --git a/src/main/java/com/arangodb/model/CollectionSchema.java b/src/main/java/com/arangodb/model/CollectionSchema.java index 8aa7bf098..395538c12 100644 --- a/src/main/java/com/arangodb/model/CollectionSchema.java +++ b/src/main/java/com/arangodb/model/CollectionSchema.java @@ -22,8 +22,10 @@ package com.arangodb.model; +import com.arangodb.serde.InternalDeserializers; import com.arangodb.serde.InternalSerializers; import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.fasterxml.jackson.databind.annotation.JsonSerialize; /** @@ -53,6 +55,7 @@ public String getRule() { return rule; } + @JsonDeserialize(using = InternalDeserializers.CollectionSchemaRuleDeserializer.class) public CollectionSchema setRule(String rule) { this.rule = rule; return this; diff --git a/src/main/java/com/arangodb/serde/InternalDeserializers.java b/src/main/java/com/arangodb/serde/InternalDeserializers.java index 7f8971f87..b1666bb7f 100644 --- a/src/main/java/com/arangodb/serde/InternalDeserializers.java +++ b/src/main/java/com/arangodb/serde/InternalDeserializers.java @@ -6,11 +6,11 @@ import com.arangodb.entity.arangosearch.CollectionLink; import com.arangodb.entity.arangosearch.FieldLink; import com.arangodb.velocystream.Response; +import com.fasterxml.jackson.core.JacksonException; +import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.TreeNode; -import com.fasterxml.jackson.databind.DeserializationContext; -import com.fasterxml.jackson.databind.JsonDeserializer; -import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.node.ArrayNode; import com.fasterxml.jackson.databind.node.NumericNode; import com.fasterxml.jackson.databind.node.ObjectNode; @@ -31,7 +31,7 @@ public Collection deserialize(JsonParser p, DeserializationConte Collection out = new ArrayList<>(); ObjectNode tree = p.readValueAsTree(); Iterator> it = tree.fields(); - while (it.hasNext()){ + while (it.hasNext()) { Map.Entry e = it.next(); ObjectNode v = (ObjectNode) e.getValue(); v.put("name", e.getKey()); @@ -48,7 +48,7 @@ public FieldLink[] deserialize(JsonParser p, DeserializationContext ctxt) throws Collection out = new ArrayList<>(); ObjectNode tree = p.readValueAsTree(); Iterator> it = tree.fields(); - while (it.hasNext()){ + while (it.hasNext()) { Map.Entry e = it.next(); ObjectNode v = (ObjectNode) e.getValue(); v.put("name", e.getKey()); @@ -58,6 +58,14 @@ public FieldLink[] deserialize(JsonParser p, DeserializationContext ctxt) throws } } + public static class CollectionSchemaRuleDeserializer extends JsonDeserializer { + @Override + public String deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { + return SerdeUtils.INSTANCE.writeJson(p.readValueAsTree()); + } + } + + private InternalDeserializers() { } diff --git a/src/test/java/com/arangodb/ArangoCollectionTest.java b/src/test/java/com/arangodb/ArangoCollectionTest.java index 2e6ef6278..b1cb16ac3 100644 --- a/src/test/java/com/arangodb/ArangoCollectionTest.java +++ b/src/test/java/com/arangodb/ArangoCollectionTest.java @@ -445,8 +445,8 @@ void getDocumentDirtyRead(ArangoCollection collection) throws InterruptedExcepti final BaseDocument doc = new BaseDocument(); collection.insertDocument(doc, new DocumentCreateOptions()); Thread.sleep(2000); - final VPackSlice document = collection - .getDocument(doc.getKey(), VPackSlice.class, new DocumentReadOptions().allowDirtyRead(true)); + final String document = collection + .getDocument(doc.getKey(), String.class, new DocumentReadOptions().allowDirtyRead(true)); assertThat(document).isNotNull(); } diff --git a/src/test/java/com/arangodb/async/example/graph/AQLActorsAndMoviesExampleTest.java b/src/test/java/com/arangodb/async/example/graph/AQLActorsAndMoviesExampleTest.java index d0e293a62..9667b542c 100644 --- a/src/test/java/com/arangodb/async/example/graph/AQLActorsAndMoviesExampleTest.java +++ b/src/test/java/com/arangodb/async/example/graph/AQLActorsAndMoviesExampleTest.java @@ -31,6 +31,8 @@ import com.arangodb.entity.DocumentCreateEntity; import com.arangodb.mapping.ArangoJack; import com.arangodb.model.CollectionCreateOptions; +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; @@ -484,11 +486,9 @@ public static class Actor { private String actor; private Integer movies; - public Actor() { - super(); - } - public Actor(final String actor, final Integer movies) { + @JsonCreator + public Actor(@JsonProperty("actor") final String actor, @JsonProperty("movies") final Integer movies) { super(); this.actor = actor; this.movies = movies; @@ -531,14 +531,11 @@ public boolean equals(final Object obj) { @SuppressWarnings("WeakerAccess") public static class Movie { - private String movie; - private Integer actors; - - public Movie() { - super(); - } + private final String movie; + private final Integer actors; - public Movie(final String movie, final Integer actors) { + @JsonCreator + public Movie(@JsonProperty("movie") final String movie, @JsonProperty("actors") final Integer actors) { super(); this.movie = movie; this.actors = actors; diff --git a/src/test/java/com/arangodb/example/graph/AQLActorsAndMoviesExampleTest.java b/src/test/java/com/arangodb/example/graph/AQLActorsAndMoviesExampleTest.java index f5283c5aa..ba9cb7cd4 100644 --- a/src/test/java/com/arangodb/example/graph/AQLActorsAndMoviesExampleTest.java +++ b/src/test/java/com/arangodb/example/graph/AQLActorsAndMoviesExampleTest.java @@ -27,6 +27,8 @@ import com.arangodb.entity.DocumentCreateEntity; import com.arangodb.mapping.ArangoJack; import com.arangodb.model.CollectionCreateOptions; +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; @@ -219,14 +221,11 @@ void theNumberOfMoviesActedInBetween2005and2010byActor() { } public static class Actor { - private String actor; - private Integer movies; + private final String actor; + private final Integer movies; - public Actor() { - super(); - } - - Actor(final String actor, final Integer movies) { + @JsonCreator + Actor(@JsonProperty("actor") final String actor, @JsonProperty("movies") final Integer movies) { super(); this.actor = actor; this.movies = movies; @@ -268,14 +267,11 @@ public boolean equals(final Object obj) { } public static class Movie { - private String movie; - private Integer actors; - - public Movie() { - super(); - } + private final String movie; + private final Integer actors; - Movie(final String movie, final Integer actors) { + @JsonCreator + public Movie(@JsonProperty("movie") final String movie, @JsonProperty("actors") final Integer actors) { super(); this.movie = movie; this.actors = actors; diff --git a/src/test/java/com/arangodb/util/ArangoSerializationTest.java b/src/test/java/com/arangodb/util/ArangoSerializationTest.java index fc64cd5c9..61c072a04 100644 --- a/src/test/java/com/arangodb/util/ArangoSerializationTest.java +++ b/src/test/java/com/arangodb/util/ArangoSerializationTest.java @@ -97,8 +97,10 @@ void serializeType() { void parseJsonIncludeNull() { final Map entity = new HashMap<>(); entity.put("value", new String[]{"test", null}); - final String json = internalSer.deserialize(new VPackSlice(internalSer.serialize(entity)).toByteArray(), String.class); - assertThat(json).isEqualTo("{\"value\":[\"test\",null]}"); + final Map res = userSer.deserialize(new VPackSlice(userSer.serialize(entity)).toByteArray(), Map.class); + assertThat(res.get("value")) + .asList() + .containsExactly("test", null); } @Test From a654051495c181b76124c4082b52354d1cb2c4f9 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Tue, 12 Jul 2022 20:15:14 +0200 Subject: [PATCH 030/254] deserializer refactoring: Database API --- .../arangodb/entity/QueryExecutionState.java | 24 +++++++++++++++++ .../com/arangodb/internal/DocumentCache.java | 2 +- .../internal/InternalArangoCollection.java | 6 ++--- .../internal/InternalArangoDatabase.java | 10 ++++++- .../java/com/arangodb/ArangoDatabaseTest.java | 27 ++++++++++--------- .../arangodb/async/ArangoDatabaseTest.java | 13 +++++---- 6 files changed, 59 insertions(+), 23 deletions(-) diff --git a/src/main/java/com/arangodb/entity/QueryExecutionState.java b/src/main/java/com/arangodb/entity/QueryExecutionState.java index 75e75df87..2e1988acb 100644 --- a/src/main/java/com/arangodb/entity/QueryExecutionState.java +++ b/src/main/java/com/arangodb/entity/QueryExecutionState.java @@ -20,19 +20,43 @@ package com.arangodb.entity; +import com.fasterxml.jackson.annotation.JsonProperty; + /** * @author Mark Vollmary */ public enum QueryExecutionState { + @JsonProperty("initializing") INITIALIZING, + + @JsonProperty("parsing") PARSING, + + @JsonProperty("optimizing ast") OPTIMIZING_AST, + + @JsonProperty("loading collections") LOADING_COLLECTIONS, + + @JsonProperty("instantiating plan") INSTANTIATING_PLAN, + + @JsonProperty("optimizing plan") OPTIMIZING_PLAN, + + @JsonProperty("executing") EXECUTING, + + @JsonProperty("finalizing") FINALIZING, + + @JsonProperty("finished") FINISHED, + + @JsonProperty("killed") KILLED, + + @JsonProperty("invalid") INVALID } + diff --git a/src/main/java/com/arangodb/internal/DocumentCache.java b/src/main/java/com/arangodb/internal/DocumentCache.java index 63254a6be..61bef4676 100644 --- a/src/main/java/com/arangodb/internal/DocumentCache.java +++ b/src/main/java/com/arangodb/internal/DocumentCache.java @@ -92,7 +92,7 @@ private void findAnnotation( for (Annotation annotation : field.getAnnotations()) { if (annotation != null && !field.isSynthetic() && !Modifier.isStatic(field.getModifiers()) - && String.class.isAssignableFrom(field.getType())) { + && String.class.equals(field.getType())) { String value = null; if (annotation instanceof Id) { value = DocumentFields.ID; diff --git a/src/main/java/com/arangodb/internal/InternalArangoCollection.java b/src/main/java/com/arangodb/internal/InternalArangoCollection.java index 8e0985314..040186faf 100644 --- a/src/main/java/com/arangodb/internal/InternalArangoCollection.java +++ b/src/main/java/com/arangodb/internal/InternalArangoCollection.java @@ -109,7 +109,7 @@ protected ResponseDeserializer> insertDocumentRespon final JsonNode newDoc = body.get(NEW); Class clazz = value.getClass(); if (newDoc != null) { - if (String.class.isAssignableFrom(clazz)) { + if (String.class.equals(clazz)) { doc.setNew((T) SerdeUtils.INSTANCE.writeJson(newDoc)); } else { doc.setNew(getUserSerialization().deserialize(getInternalSerialization().serialize(newDoc), clazz)); @@ -117,7 +117,7 @@ protected ResponseDeserializer> insertDocumentRespon } final JsonNode oldDoc = body.get(OLD); if (oldDoc != null) { - if (String.class.isAssignableFrom(clazz)) { + if (String.class.equals(clazz)) { doc.setOld((T) SerdeUtils.INSTANCE.writeJson(oldDoc)); } else { doc.setOld(getUserSerialization().deserialize(getInternalSerialization().serialize(oldDoc), clazz)); @@ -227,7 +227,7 @@ protected Request getDocumentRequest(final String key, final DocumentReadOptions protected ResponseDeserializer getDocumentResponseDeserializer(final Class type) { return response -> { - if (String.class.isAssignableFrom(type)) { + if (String.class.equals(type)) { return (T) SerdeUtils.INSTANCE.writeJson(getInternalSerialization().parse(response.getBody())); } else { return getUserSerialization().deserialize(response.getBody(), type); diff --git a/src/main/java/com/arangodb/internal/InternalArangoDatabase.java b/src/main/java/com/arangodb/internal/InternalArangoDatabase.java index 4d188d426..49d5be7fb 100644 --- a/src/main/java/com/arangodb/internal/InternalArangoDatabase.java +++ b/src/main/java/com/arangodb/internal/InternalArangoDatabase.java @@ -29,6 +29,7 @@ import com.arangodb.model.arangosearch.AnalyzerDeleteOptions; import com.arangodb.model.arangosearch.ArangoSearchCreateOptions; import com.arangodb.model.arangosearch.ArangoSearchOptionsBuilder; +import com.arangodb.serde.SerdeUtils; import com.arangodb.velocypack.Type; import com.arangodb.velocypack.VPackSlice; import com.arangodb.velocystream.Request; @@ -283,7 +284,14 @@ protected Request transactionRequest(final String action, final TransactionOptio } protected ResponseDeserializer transactionResponseDeserializer(final Class type) { - return response -> getUserSerialization().deserialize(getInternalSerialization().extract(response.getBody(), ArangoResponseField.RESULT_JSON_POINTER), type); + return response -> { + byte[] userContent = getInternalSerialization().extract(response.getBody(), ArangoResponseField.RESULT_JSON_POINTER); + if (String.class.equals(type)) { + return (T) SerdeUtils.INSTANCE.writeJson(getInternalSerialization().parse(userContent)); + } else { + return getUserSerialization().deserialize(userContent, type); + } + }; } protected Request beginStreamTransactionRequest(final StreamTransactionOptions options) { diff --git a/src/test/java/com/arangodb/ArangoDatabaseTest.java b/src/test/java/com/arangodb/ArangoDatabaseTest.java index 37b7e2efd..d0f513b34 100644 --- a/src/test/java/com/arangodb/ArangoDatabaseTest.java +++ b/src/test/java/com/arangodb/ArangoDatabaseTest.java @@ -30,6 +30,7 @@ import com.arangodb.velocypack.VPackSlice; import com.arangodb.velocypack.ValueType; import com.arangodb.velocypack.exception.VPackException; +import com.fasterxml.jackson.databind.JsonNode; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.MethodSource; @@ -1137,7 +1138,7 @@ void getGraphs(ArangoDatabase db) { void transactionString(ArangoDatabase db) { final TransactionOptions options = new TransactionOptions().params("test"); final String result = db.transaction("function (params) {return params;}", String.class, options); - assertThat(result).isEqualTo("test"); + assertThat(result).isEqualTo("\"test\""); } @ParameterizedTest(name = "{index}") @@ -1152,9 +1153,9 @@ void transactionNumber(ArangoDatabase db) { @MethodSource("dbs") void transactionVPack(ArangoDatabase db) throws VPackException { final TransactionOptions options = new TransactionOptions().params(new VPackBuilder().add("test").slice()); - final VPackSlice result = db.transaction("function (params) {return params;}", VPackSlice.class, options); - assertThat(result.isString()).isTrue(); - assertThat(result.getAsString()).isEqualTo("test"); + final JsonNode result = db.transaction("function (params) {return params;}", JsonNode.class, options); + assertThat(result.isTextual()).isTrue(); + assertThat(result.asText()).isEqualTo("test"); } @ParameterizedTest(name = "{index}") @@ -1165,17 +1166,17 @@ void transactionVPackObject(ArangoDatabase db) throws VPackException { final TransactionOptions options = new TransactionOptions().params(params); final String result = db .transaction("function (params) { return params['foo'] + ' ' + params['bar'];}", String.class, options); - assertThat(result).isEqualTo("hello world"); + assertThat(result).isEqualTo("\"hello world\""); } @ParameterizedTest(name = "{index}") @MethodSource("dbs") - void transactionVPackArray(ArangoDatabase db) throws VPackException { + void transactionJsonArray(ArangoDatabase db) throws VPackException { final VPackSlice params = new VPackBuilder().add(ValueType.ARRAY).add("hello").add("world").close().slice(); final TransactionOptions options = new TransactionOptions().params(params); final String result = db .transaction("function (params) { return params[0] + ' ' + params[1];}", String.class, options); - assertThat(result).isEqualTo("hello world"); + assertThat(result).isEqualTo("\"hello world\""); } @ParameterizedTest(name = "{index}") @@ -1185,7 +1186,7 @@ void transactionMap(ArangoDatabase db) { final TransactionOptions options = new TransactionOptions().params(params); final String result = db .transaction("function (params) { return params['foo'] + ' ' + params['bar'];}", String.class, options); - assertThat(result).isEqualTo("hello world"); + assertThat(result).isEqualTo("\"hello world\""); } @ParameterizedTest(name = "{index}") @@ -1195,7 +1196,7 @@ void transactionArray(ArangoDatabase db) { final TransactionOptions options = new TransactionOptions().params(params); final String result = db .transaction("function (params) { return params[0] + ' ' + params[1];}", String.class, options); - assertThat(result).isEqualTo("hello world"); + assertThat(result).isEqualTo("\"hello world\""); } @ParameterizedTest(name = "{index}") @@ -1207,7 +1208,7 @@ void transactionCollection(ArangoDatabase db) { final TransactionOptions options = new TransactionOptions().params(params); final String result = db .transaction("function (params) { return params[0] + ' ' + params[1];}", String.class, options); - assertThat(result).isEqualTo("hello world"); + assertThat(result).isEqualTo("\"hello world\""); } @ParameterizedTest(name = "{index}") @@ -1240,7 +1241,7 @@ void transactionExclusiveWrite(ArangoDatabase db) { @ParameterizedTest(name = "{index}") @MethodSource("dbs") void transactionEmpty(ArangoDatabase db) { - db.transaction("function () {}", null, null); + db.transaction("function () {}", Void.class, null); } @ParameterizedTest(name = "{index}") @@ -1250,9 +1251,9 @@ void transactionAllowImplicit(ArangoDatabase db) { + "return {'a':db." + CNAME1 + ".all().toArray()[0], 'b':db." + CNAME2 + ".all().toArray()[0]};" + "}"; final TransactionOptions options = new TransactionOptions().readCollections(CNAME1); - db.transaction(action, VPackSlice.class, options); + db.transaction(action, JsonNode.class, options); options.allowImplicit(false); - Throwable thrown = catchThrowable(() -> db.transaction(action, VPackSlice.class, options)); + Throwable thrown = catchThrowable(() -> db.transaction(action, JsonNode.class, options)); assertThat(thrown) .isInstanceOf(ArangoDBException.class) .extracting(it -> ((ArangoDBException) it).getResponseCode()) diff --git a/src/test/java/com/arangodb/async/ArangoDatabaseTest.java b/src/test/java/com/arangodb/async/ArangoDatabaseTest.java index 54df6dedb..206a54703 100644 --- a/src/test/java/com/arangodb/async/ArangoDatabaseTest.java +++ b/src/test/java/com/arangodb/async/ArangoDatabaseTest.java @@ -876,7 +876,7 @@ void getGraphs() throws InterruptedException, ExecutionException { void transactionString() throws InterruptedException, ExecutionException { final TransactionOptions options = new TransactionOptions().params("test"); db.transaction("function (params) {return params;}", String.class, options) - .whenComplete((result, ex) -> assertThat(result).isEqualTo("test")) + .whenComplete((result, ex) -> assertThat(result).isEqualTo("\"test\"")) .get(); } @@ -901,7 +901,7 @@ void transactionVPack() throws VPackException, InterruptedException, ExecutionEx @Test void transactionEmpty() throws InterruptedException, ExecutionException { - db.transaction("function () {}", null, null).get(); + db.transaction("function () {}", Void.class, null).get(); } @Test @@ -1008,12 +1008,15 @@ void reloadRouting() throws InterruptedException, ExecutionException { db.reloadRouting().get(); } - @SuppressWarnings({"WeakerAccess", "unused"}) - static class TransactionTestEntity { + public static class TransactionTestEntity { private String value; - TransactionTestEntity() { + public TransactionTestEntity() { super(); } + + public String getValue() { + return value; + } } } From 390155f1f93af966058570c6cc7f150e111a3cb0 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Tue, 12 Jul 2022 20:38:45 +0200 Subject: [PATCH 031/254] deserializer refactoring: test fixes --- .../arangodb/entity/TransactionEntity.java | 2 +- .../com/arangodb/serde/InternalSerdeImpl.java | 1 - .../com/arangodb/serde/JacksonSerdeImpl.java | 2 + .../java/com/arangodb/ArangoCursorTest.java | 44 +++++++++---------- .../java/com/arangodb/ArangoRouteTest.java | 2 +- .../com/arangodb/StreamTransactionTest.java | 2 +- .../java/com/arangodb/async/ArangoDBTest.java | 4 +- .../arangodb/async/StreamTransactionTest.java | 2 +- .../arangodb/serde/CustomTypeHintTest.java | 5 +-- 9 files changed, 31 insertions(+), 33 deletions(-) diff --git a/src/main/java/com/arangodb/entity/TransactionEntity.java b/src/main/java/com/arangodb/entity/TransactionEntity.java index a700541f2..a517d7882 100644 --- a/src/main/java/com/arangodb/entity/TransactionEntity.java +++ b/src/main/java/com/arangodb/entity/TransactionEntity.java @@ -35,7 +35,7 @@ public String getId() { return id; } - public StreamTransactionStatus getStatus() { + public StreamTransactionStatus getState() { return state; } diff --git a/src/main/java/com/arangodb/serde/InternalSerdeImpl.java b/src/main/java/com/arangodb/serde/InternalSerdeImpl.java index b8e01d8bf..500805004 100644 --- a/src/main/java/com/arangodb/serde/InternalSerdeImpl.java +++ b/src/main/java/com/arangodb/serde/InternalSerdeImpl.java @@ -16,7 +16,6 @@ class InternalSerdeImpl extends JacksonSerdeImpl implements InternalSerde { super(dataType, mapper); mapper.registerModule(InternalModule.INSTANCE.get()); mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); - mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); } @Override diff --git a/src/main/java/com/arangodb/serde/JacksonSerdeImpl.java b/src/main/java/com/arangodb/serde/JacksonSerdeImpl.java index e6c373a04..ece832a30 100644 --- a/src/main/java/com/arangodb/serde/JacksonSerdeImpl.java +++ b/src/main/java/com/arangodb/serde/JacksonSerdeImpl.java @@ -2,6 +2,7 @@ import com.arangodb.ArangoDBException; import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; @@ -17,6 +18,7 @@ class JacksonSerdeImpl implements JacksonSerde { JacksonSerdeImpl(final DataType dataType, final ObjectMapper mapper) { this.dataType = dataType; this.mapper = mapper; + mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); } @Override diff --git a/src/test/java/com/arangodb/ArangoCursorTest.java b/src/test/java/com/arangodb/ArangoCursorTest.java index 41d9d5d99..a1988b132 100644 --- a/src/test/java/com/arangodb/ArangoCursorTest.java +++ b/src/test/java/com/arangodb/ArangoCursorTest.java @@ -21,7 +21,7 @@ package com.arangodb; import com.arangodb.model.AqlQueryOptions; -import com.arangodb.velocypack.VPackSlice; +import com.fasterxml.jackson.databind.JsonNode; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.MethodSource; @@ -46,17 +46,17 @@ static void init() { @ParameterizedTest(name = "{index}") @MethodSource("dbs") void firstStream(ArangoDatabase db) { - final ArangoCursor cursor = db.query("FOR i IN 0..99 RETURN i", VPackSlice.class); - final Optional first = cursor.stream().findFirst(); + final ArangoCursor cursor = db.query("FOR i IN 0..99 RETURN i", JsonNode.class); + final Optional first = cursor.stream().findFirst(); assertThat(first).isPresent(); - assertThat(first.get().isInteger()).isTrue(); - assertThat(first.get().getAsLong()).isZero(); + assertThat(first.get().isInt()).isTrue(); + assertThat(first.get().asLong()).isZero(); } @ParameterizedTest(name = "{index}") @MethodSource("dbs") void next(ArangoDatabase db) { - final ArangoCursor cursor = db.query("FOR i IN 0..99 RETURN i", new AqlQueryOptions().batchSize(5), VPackSlice.class); + final ArangoCursor cursor = db.query("FOR i IN 0..99 RETURN i", new AqlQueryOptions().batchSize(5), JsonNode.class); while (cursor.hasNext()) { cursor.next(); } @@ -65,16 +65,16 @@ void next(ArangoDatabase db) { @ParameterizedTest(name = "{index}") @MethodSource("dbs") void mapFilterCountStream(ArangoDatabase db) { - final ArangoCursor cursor = db.query("FOR i IN 0..99 RETURN i", VPackSlice.class); - final long count = cursor.stream().map(VPackSlice::getAsLong).filter(t -> t < 50).count(); + final ArangoCursor cursor = db.query("FOR i IN 0..99 RETURN i", JsonNode.class); + final long count = cursor.stream().map(JsonNode::asLong).filter(t -> t < 50).count(); assertThat(count).isEqualTo(50L); } @ParameterizedTest(name = "{index}") @MethodSource("dbs") void mapFilterCollectIntoSetStream(ArangoDatabase db) { - final ArangoCursor cursor = db.query("FOR i IN 0..99 RETURN i", VPackSlice.class); - final Set target = cursor.stream().map(VPackSlice::getAsLong).filter(t -> t < 50).collect(Collectors.toSet()); + final ArangoCursor cursor = db.query("FOR i IN 0..99 RETURN i", JsonNode.class); + final Set target = cursor.stream().map(JsonNode::asLong).filter(t -> t < 50).collect(Collectors.toSet()); assertThat(target) .isNotNull() .hasSize(50); @@ -84,47 +84,47 @@ void mapFilterCollectIntoSetStream(ArangoDatabase db) { @MethodSource("dbs") void forEach(ArangoDatabase db) { final AtomicLong i = new AtomicLong(0L); - final ArangoCursor cursor = db.query("FOR i IN 0..99 RETURN i", VPackSlice.class); - cursor.forEach(t -> assertThat(t.getAsLong()).isEqualTo(i.getAndIncrement())); + final ArangoCursor cursor = db.query("FOR i IN 0..99 RETURN i", JsonNode.class); + cursor.forEach(t -> assertThat(t.asLong()).isEqualTo(i.getAndIncrement())); } @ParameterizedTest(name = "{index}") @MethodSource("dbs") void mapForeachStream(ArangoDatabase db) { final AtomicLong i = new AtomicLong(0L); - final ArangoCursor cursor = db.query("FOR i IN 0..99 RETURN i", VPackSlice.class); - cursor.stream().map(VPackSlice::getAsLong).forEach(t -> assertThat(t).isEqualTo(i.getAndIncrement())); + final ArangoCursor cursor = db.query("FOR i IN 0..99 RETURN i", JsonNode.class); + cursor.stream().map(JsonNode::asLong).forEach(t -> assertThat(t).isEqualTo(i.getAndIncrement())); } @ParameterizedTest(name = "{index}") @MethodSource("dbs") void mapFilterForEachStream(ArangoDatabase db) { final AtomicLong i = new AtomicLong(0L); - final ArangoCursor cursor = db.query("FOR i IN 0..99 RETURN i", VPackSlice.class); - cursor.stream().map(VPackSlice::getAsLong).filter(t -> t < 50).forEach(t -> assertThat(t).isEqualTo(i.getAndIncrement())); + final ArangoCursor cursor = db.query("FOR i IN 0..99 RETURN i", JsonNode.class); + cursor.stream().map(JsonNode::asLong).filter(t -> t < 50).forEach(t -> assertThat(t).isEqualTo(i.getAndIncrement())); } @ParameterizedTest(name = "{index}") @MethodSource("dbs") void anyMatchStream(ArangoDatabase db) { - final ArangoCursor cursor = db.query("FOR i IN 0..99 RETURN i", VPackSlice.class); - final boolean match = cursor.stream().anyMatch(t -> t.getAsLong() == 50L); + final ArangoCursor cursor = db.query("FOR i IN 0..99 RETURN i", JsonNode.class); + final boolean match = cursor.stream().anyMatch(t -> t.asLong() == 50L); assertThat(match).isTrue(); } @ParameterizedTest(name = "{index}") @MethodSource("dbs") void noneMatchStream(ArangoDatabase db) { - final ArangoCursor cursor = db.query("FOR i IN 0..99 RETURN i", VPackSlice.class); - final boolean match = cursor.stream().noneMatch(t -> t.getAsLong() == 100L); + final ArangoCursor cursor = db.query("FOR i IN 0..99 RETURN i", JsonNode.class); + final boolean match = cursor.stream().noneMatch(t -> t.asLong() == 100L); assertThat(match).isTrue(); } @ParameterizedTest(name = "{index}") @MethodSource("dbs") void allMatchStream(ArangoDatabase db) { - final ArangoCursor cursor = db.query("FOR i IN 0..99 RETURN i", VPackSlice.class); - final boolean match = cursor.stream().allMatch(t -> t.getAsLong() < 100L); + final ArangoCursor cursor = db.query("FOR i IN 0..99 RETURN i", JsonNode.class); + final boolean match = cursor.stream().allMatch(t -> t.asLong() < 100L); assertThat(match).isTrue(); } diff --git a/src/test/java/com/arangodb/ArangoRouteTest.java b/src/test/java/com/arangodb/ArangoRouteTest.java index ba57d730c..212c654a4 100644 --- a/src/test/java/com/arangodb/ArangoRouteTest.java +++ b/src/test/java/com/arangodb/ArangoRouteTest.java @@ -47,7 +47,7 @@ static void init() { @MethodSource("dbs") void get(ArangoDatabase db) { final Response res = db.route("/_api/version").get(); - assertThat(db.arango().getInternalSerialization().parse(res.getBody(), "version").isTextual()).isTrue(); + assertThat(db.arango().getInternalSerialization().parse(res.getBody(), "/version").isTextual()).isTrue(); } @ParameterizedTest(name = "{index}") diff --git a/src/test/java/com/arangodb/StreamTransactionTest.java b/src/test/java/com/arangodb/StreamTransactionTest.java index 4330b13fd..9ed7d9284 100644 --- a/src/test/java/com/arangodb/StreamTransactionTest.java +++ b/src/test/java/com/arangodb/StreamTransactionTest.java @@ -756,7 +756,7 @@ void getStreamTransactions(ArangoDatabase db) { assertThat(gotTxs).hasSameSizeAs(createdIds); assertThat(gotTxs.stream() - .allMatch(it -> it.getStatus() == StreamTransactionStatus.running)).isTrue(); + .allMatch(it -> it.getState() == StreamTransactionStatus.running)).isTrue(); db.abortStreamTransaction(tx1.getId()); db.abortStreamTransaction(tx2.getId()); diff --git a/src/test/java/com/arangodb/async/ArangoDBTest.java b/src/test/java/com/arangodb/async/ArangoDBTest.java index 23732e8f0..7fb7497c0 100644 --- a/src/test/java/com/arangodb/async/ArangoDBTest.java +++ b/src/test/java/com/arangodb/async/ArangoDBTest.java @@ -441,7 +441,7 @@ void execute() throws VPackException, InterruptedException, ExecutionException { .execute(new Request(DbName.SYSTEM, RequestType.GET, "/_api/version")) .whenComplete((response, ex) -> { assertThat(response.getBody()).isNotNull(); - assertThat(arangoDB.getInternalSerialization().parse(response.getBody(), "version").isTextual()).isTrue(); + assertThat(arangoDB.getInternalSerialization().parse(response.getBody(), "/version").isTextual()).isTrue(); }) .get(); } @@ -453,7 +453,7 @@ void execute_acquireHostList_enabled() throws VPackException, InterruptedExcepti .execute(new Request(DbName.SYSTEM, RequestType.GET, "/_api/version")) .whenComplete((response, ex) -> { assertThat(response.getBody()).isNotNull(); - assertThat(arangoDB.getInternalSerialization().parse(response.getBody(), "version").isTextual()).isTrue(); + assertThat(arangoDB.getInternalSerialization().parse(response.getBody(), "/version").isTextual()).isTrue(); }) .get(); } diff --git a/src/test/java/com/arangodb/async/StreamTransactionTest.java b/src/test/java/com/arangodb/async/StreamTransactionTest.java index 9925a110e..5f6690095 100644 --- a/src/test/java/com/arangodb/async/StreamTransactionTest.java +++ b/src/test/java/com/arangodb/async/StreamTransactionTest.java @@ -350,7 +350,7 @@ void getStreamTransactions() throws ExecutionException, InterruptedException { assertThat(gotTxs).hasSameSizeAs(createdIds); assertThat(gotTxs.stream() - .allMatch(it -> it.getStatus() == StreamTransactionStatus.running)).isTrue(); + .allMatch(it -> it.getState() == StreamTransactionStatus.running)).isTrue(); db.abortStreamTransaction(tx1.getId()).get(); db.abortStreamTransaction(tx2.getId()).get(); diff --git a/src/test/java/com/arangodb/serde/CustomTypeHintTest.java b/src/test/java/com/arangodb/serde/CustomTypeHintTest.java index f3e9bf046..178867aef 100644 --- a/src/test/java/com/arangodb/serde/CustomTypeHintTest.java +++ b/src/test/java/com/arangodb/serde/CustomTypeHintTest.java @@ -21,10 +21,7 @@ package com.arangodb.serde; -import com.arangodb.ArangoCollection; -import com.arangodb.ArangoDB; -import com.arangodb.ArangoDatabase; -import com.arangodb.DbName; +import com.arangodb.*; import com.arangodb.entity.Key; import com.arangodb.mapping.ArangoJack; import com.arangodb.model.DocumentCreateOptions; From 1a0331d893481e6d5217c923118e9877e45836cf Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Tue, 12 Jul 2022 21:09:10 +0200 Subject: [PATCH 032/254] removed usages of VPackSlice --- .../com/arangodb/async/ArangoDBAsync.java | 7 - .../com/arangodb/entity/CursorEntity.java | 1 - .../internal/ArangoCollectionImpl.java | 4 +- .../internal/InternalArangoDBBuilder.java | 13 -- .../mapping/ArangoAnnotationIntrospector.java | 127 ------------ .../internal/mapping/VPackDeserializers.java | 96 --------- .../internal/mapping/VPackSerializers.java | 77 ------- .../internal/util/ArangoDeserializerImpl.java | 61 ------ .../velocypack/VPackDeserializers.java | 196 ------------------ .../velocypack/VPackDriverModule.java | 101 --------- .../internal/velocypack/VPackSerializers.java | 159 -------------- .../java/com/arangodb/mapping/ArangoJack.java | 43 +--- .../com/arangodb/model/AqlQueryOptions.java | 27 +-- .../com/arangodb/util/ArangoDeserializer.java | 43 ---- .../java/com/arangodb/BaseDocumentTest.java | 95 --------- 15 files changed, 8 insertions(+), 1042 deletions(-) delete mode 100644 src/main/java/com/arangodb/internal/mapping/ArangoAnnotationIntrospector.java delete mode 100644 src/main/java/com/arangodb/internal/mapping/VPackDeserializers.java delete mode 100644 src/main/java/com/arangodb/internal/mapping/VPackSerializers.java delete mode 100644 src/main/java/com/arangodb/internal/util/ArangoDeserializerImpl.java delete mode 100644 src/main/java/com/arangodb/internal/velocypack/VPackDeserializers.java delete mode 100644 src/main/java/com/arangodb/internal/velocypack/VPackDriverModule.java delete mode 100644 src/main/java/com/arangodb/internal/velocypack/VPackSerializers.java delete mode 100644 src/main/java/com/arangodb/util/ArangoDeserializer.java delete mode 100644 src/test/java/com/arangodb/BaseDocumentTest.java diff --git a/src/main/java/com/arangodb/async/ArangoDBAsync.java b/src/main/java/com/arangodb/async/ArangoDBAsync.java index 275adf982..3bfa3d046 100644 --- a/src/main/java/com/arangodb/async/ArangoDBAsync.java +++ b/src/main/java/com/arangodb/async/ArangoDBAsync.java @@ -31,7 +31,6 @@ import com.arangodb.internal.net.ConnectionFactory; import com.arangodb.internal.net.HostHandler; import com.arangodb.internal.net.HostResolver; -import com.arangodb.internal.util.ArangoDeserializerImpl; import com.arangodb.internal.util.ArangoSerializationFactory; import com.arangodb.internal.util.ArangoSerializationImpl; import com.arangodb.internal.util.InternalSerializationImpl; @@ -44,10 +43,7 @@ import com.arangodb.serde.DataType; import com.arangodb.serde.InternalSerde; import com.arangodb.serde.JacksonSerde; -import com.arangodb.util.ArangoDeserializer; import com.arangodb.util.ArangoSerialization; -import com.arangodb.velocypack.VPack; -import com.arangodb.velocypack.VPackParser; import com.arangodb.velocystream.Request; import com.arangodb.velocystream.Response; import org.slf4j.Logger; @@ -514,9 +510,6 @@ public synchronized ArangoDBAsync build() { if (hosts.isEmpty()) { hosts.add(host); } - final VPack vpacker = vpackBuilder.serializeNullValues(false).build(); - final VPack vpackerNull = vpackBuilder.serializeNullValues(true).build(); - final VPackParser vpackParser = vpackParserBuilder.build(); final InternalSerde internalSerde = InternalSerde.of(DataType.VPACK); final InternalSerializationImpl internal = new InternalSerializationImpl(internalSerde); final ArangoSerialization custom = customSerializer != null ? customSerializer : new ArangoSerializationImpl(JacksonSerde.of(DataType.VPACK)); diff --git a/src/main/java/com/arangodb/entity/CursorEntity.java b/src/main/java/com/arangodb/entity/CursorEntity.java index 5e73fbe9f..e4aa9f32e 100644 --- a/src/main/java/com/arangodb/entity/CursorEntity.java +++ b/src/main/java/com/arangodb/entity/CursorEntity.java @@ -20,7 +20,6 @@ package com.arangodb.entity; -import com.arangodb.velocypack.VPackSlice; import com.fasterxml.jackson.databind.JsonNode; import java.util.Collection; diff --git a/src/main/java/com/arangodb/internal/ArangoCollectionImpl.java b/src/main/java/com/arangodb/internal/ArangoCollectionImpl.java index 01fa6d99a..7212c2e91 100644 --- a/src/main/java/com/arangodb/internal/ArangoCollectionImpl.java +++ b/src/main/java/com/arangodb/internal/ArangoCollectionImpl.java @@ -25,7 +25,7 @@ import com.arangodb.entity.*; import com.arangodb.internal.util.DocumentUtil; import com.arangodb.model.*; -import com.arangodb.velocypack.VPackSlice; +import com.fasterxml.jackson.databind.JsonNode; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -232,7 +232,7 @@ public Boolean documentExists(final String key) { @Override public Boolean documentExists(final String key, final DocumentExistsOptions options) throws ArangoDBException { try { - executor.execute(documentExistsRequest(key, options), VPackSlice.class); + executor.execute(documentExistsRequest(key, options), JsonNode.class); return true; } catch (final ArangoDBException e) { diff --git a/src/main/java/com/arangodb/internal/InternalArangoDBBuilder.java b/src/main/java/com/arangodb/internal/InternalArangoDBBuilder.java index 0aa1ed9cf..d262e1e12 100644 --- a/src/main/java/com/arangodb/internal/InternalArangoDBBuilder.java +++ b/src/main/java/com/arangodb/internal/InternalArangoDBBuilder.java @@ -25,8 +25,6 @@ import com.arangodb.entity.LoadBalancingStrategy; import com.arangodb.internal.net.*; import com.arangodb.internal.util.HostUtils; -import com.arangodb.internal.velocypack.VPackDriverModule; -import com.arangodb.util.ArangoDeserializer; import com.arangodb.util.ArangoSerialization; import com.arangodb.velocypack.VPack; import com.arangodb.velocypack.VPackParser; @@ -82,9 +80,6 @@ public abstract class InternalArangoDBBuilder { protected Integer maxConnections; protected Long connectionTtl; protected Integer keepAliveInterval; - protected final VPack.Builder vpackBuilder; - protected final VPackParser.Builder vpackParserBuilder; - protected ArangoDeserializer deserializer; protected Boolean acquireHostList; protected Integer acquireHostListInterval; protected LoadBalancingStrategy loadBalancingStrategy; @@ -94,10 +89,6 @@ public abstract class InternalArangoDBBuilder { public InternalArangoDBBuilder() { super(); - vpackBuilder = new VPack.Builder(); - vpackParserBuilder = new VPackParser.Builder(); - vpackBuilder.registerModule(new VPackDriverModule()); - vpackParserBuilder.registerModule(new VPackDriverModule()); host = new HostDescription(ArangoDefaults.DEFAULT_HOST, ArangoDefaults.DEFAULT_PORT); hosts = new ArrayList<>(); user = ArangoDefaults.DEFAULT_USER; @@ -212,10 +203,6 @@ protected void setResponseQueueTimeSamples(final Integer responseQueueTimeSample this.responseQueueTimeSamples = responseQueueTimeSamples; } - protected void deserializer(final ArangoDeserializer deserializer) { - this.deserializer = deserializer; - } - protected void setSerializer(final ArangoSerialization serializer) { this.customSerializer = serializer; } diff --git a/src/main/java/com/arangodb/internal/mapping/ArangoAnnotationIntrospector.java b/src/main/java/com/arangodb/internal/mapping/ArangoAnnotationIntrospector.java deleted file mode 100644 index 6f80f1e01..000000000 --- a/src/main/java/com/arangodb/internal/mapping/ArangoAnnotationIntrospector.java +++ /dev/null @@ -1,127 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.internal.mapping; - - -import com.arangodb.velocypack.annotations.Expose; -import com.arangodb.velocypack.annotations.SerializedName; -import com.fasterxml.jackson.annotation.JsonProperty; -import com.fasterxml.jackson.databind.PropertyName; -import com.fasterxml.jackson.databind.introspect.Annotated; -import com.fasterxml.jackson.databind.introspect.AnnotatedMember; -import com.fasterxml.jackson.databind.introspect.AnnotatedParameter; -import com.fasterxml.jackson.databind.introspect.JacksonAnnotationIntrospector; - -/** - * @author Michele Rastelli - */ -public class ArangoAnnotationIntrospector extends JacksonAnnotationIntrospector { - - @Override - public JsonProperty.Access findPropertyAccess(Annotated m) { - if (!(m instanceof AnnotatedMember)) { - return super.findPropertyAccess(m); - } - - final Expose expose = m.getAnnotation(Expose.class); - if (expose != null) { - final boolean serialize = expose.serialize(); - final boolean deserialize = expose.deserialize(); - - if (serialize && deserialize) { - return JsonProperty.Access.READ_WRITE; - } else if (serialize) { - return JsonProperty.Access.READ_ONLY; - } else if (deserialize) { - return JsonProperty.Access.WRITE_ONLY; - } - } - - return super.findPropertyAccess(m); - } - - @Override - public boolean hasIgnoreMarker(AnnotatedMember m) { - final Expose expose = m.getAnnotation(Expose.class); - if (expose != null && !expose.serialize() && !expose.deserialize()) { - return true; - } - return super.hasIgnoreMarker(m); - } - - @Override - public PropertyName findNameForSerialization(Annotated a) { - PropertyName name = findPropertyName(a); - if (name != null) { - return name; - } else { - return super.findNameForSerialization(a); - } - } - - @Override - public PropertyName findNameForDeserialization(Annotated a) { - PropertyName name = findPropertyName(a); - if (name != null) { - return name; - } else { - return super.findNameForDeserialization(a); - } - } - - @Override - public String findImplicitPropertyName(AnnotatedMember member) { - String name = findParameterName(member); - if (name != null) { - return name; - } else { - return super.findImplicitPropertyName(member); - } - } - - private String findParameterName(Annotated a) { - if (!(a instanceof AnnotatedParameter)) { - return null; - } - - final SerializedName serializedName = a.getAnnotation(SerializedName.class); - if (serializedName != null) { - return serializedName.value(); - } - - return null; - } - - private PropertyName findPropertyName(Annotated a) { - if (!(a instanceof AnnotatedMember)) { - return null; - } - - final SerializedName serializedName = a.getAnnotation(SerializedName.class); - if (serializedName != null) { - return PropertyName.construct(serializedName.value()); - } - - return null; - } - -} - diff --git a/src/main/java/com/arangodb/internal/mapping/VPackDeserializers.java b/src/main/java/com/arangodb/internal/mapping/VPackDeserializers.java deleted file mode 100644 index 6402a9e26..000000000 --- a/src/main/java/com/arangodb/internal/mapping/VPackDeserializers.java +++ /dev/null @@ -1,96 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2017 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.internal.mapping; - -import com.arangodb.entity.BaseDocument; -import com.arangodb.entity.BaseEdgeDocument; -import com.arangodb.jackson.dataformat.velocypack.internal.VPackParser; -import com.arangodb.velocypack.VPackSlice; -import com.arangodb.velocypack.internal.util.DateUtil; -import com.fasterxml.jackson.core.JsonParser; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.DeserializationContext; -import com.fasterxml.jackson.databind.JsonDeserializer; - -import java.io.IOException; -import java.text.ParseException; -import java.util.Map; - -/** - * @author Mark Vollmary - */ -public class VPackDeserializers { - - public static final JsonDeserializer VPACK = new JsonDeserializer() { - @Override - public VPackSlice deserialize(final JsonParser p, final DeserializationContext ctxt) - throws IOException, JsonProcessingException { - if (p instanceof VPackParser) { - final VPackSlice vpack = ((VPackParser) p).getVPack(); - // consume each element - if (vpack.isArray() || vpack.isObject()) { - for (int i = 0; i < vpack.size() + 1; i++) { - p.nextToken(); - } - } - return vpack; - } - return new VPackSlice(p.getBinaryValue()); - } - }; - - public static final JsonDeserializer UTIL_DATE = new JsonDeserializer() { - @Override - public java.util.Date deserialize(final JsonParser p, final DeserializationContext ctxt) - throws IOException, JsonProcessingException { - try { - return DateUtil.parse(p.getValueAsString()); - } catch (final ParseException e) { - throw new IOException(e); - } - } - }; - - public static final JsonDeserializer SQL_DATE = new JsonDeserializer() { - @Override - public java.sql.Date deserialize(final JsonParser p, final DeserializationContext ctxt) - throws IOException, JsonProcessingException { - try { - return new java.sql.Date(DateUtil.parse(p.getValueAsString()).getTime()); - } catch (final ParseException e) { - throw new IOException(e); - } - } - }; - - public static final JsonDeserializer SQL_TIMESTAMP = new JsonDeserializer() { - @Override - public java.sql.Timestamp deserialize(final JsonParser p, final DeserializationContext ctxt) - throws IOException, JsonProcessingException { - try { - return new java.sql.Timestamp(DateUtil.parse(p.getValueAsString()).getTime()); - } catch (final ParseException e) { - throw new IOException(e); - } - } - }; - -} diff --git a/src/main/java/com/arangodb/internal/mapping/VPackSerializers.java b/src/main/java/com/arangodb/internal/mapping/VPackSerializers.java deleted file mode 100644 index 3f8f34577..000000000 --- a/src/main/java/com/arangodb/internal/mapping/VPackSerializers.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2017 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - - -package com.arangodb.internal.mapping; - -import com.arangodb.jackson.dataformat.velocypack.internal.VPackGenerator; -import com.arangodb.velocypack.VPackSlice; -import com.arangodb.velocypack.internal.util.DateUtil; -import com.fasterxml.jackson.core.JsonGenerator; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.JsonSerializer; -import com.fasterxml.jackson.databind.SerializerProvider; - -import java.io.IOException; -import java.sql.Date; -import java.sql.Timestamp; - -/** - * @author Mark Vollmary - */ -public class VPackSerializers { - - public static final JsonSerializer VPACK = new JsonSerializer() { - @Override - public void serialize(final VPackSlice value, final JsonGenerator gen, final SerializerProvider serializers) - throws IOException { - if (gen instanceof VPackGenerator) { - ((VPackGenerator) gen).writeVPack(value); - } else { - gen.writeBinary(value.toByteArray()); - } - } - }; - - public static final JsonSerializer UTIL_DATE = new JsonSerializer() { - @Override - public void serialize(final java.util.Date value, final JsonGenerator gen, final SerializerProvider serializers) - throws IOException, JsonProcessingException { - gen.writeString(DateUtil.format(value)); - } - }; - - public static final JsonSerializer SQL_DATE = new JsonSerializer() { - @Override - public void serialize(final Date value, final JsonGenerator gen, final SerializerProvider serializers) - throws IOException, JsonProcessingException { - gen.writeString(DateUtil.format(value)); - } - }; - - public static final JsonSerializer SQL_TIMESTAMP = new JsonSerializer() { - @Override - public void serialize(final Timestamp value, final JsonGenerator gen, final SerializerProvider serializers) - throws IOException, JsonProcessingException { - gen.writeString(DateUtil.format(value)); - } - }; - -} diff --git a/src/main/java/com/arangodb/internal/util/ArangoDeserializerImpl.java b/src/main/java/com/arangodb/internal/util/ArangoDeserializerImpl.java deleted file mode 100644 index 79fa9025b..000000000 --- a/src/main/java/com/arangodb/internal/util/ArangoDeserializerImpl.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.internal.util; - -import com.arangodb.ArangoDBException; -import com.arangodb.util.ArangoDeserializer; -import com.arangodb.velocypack.VPack; -import com.arangodb.velocypack.VPackParser; -import com.arangodb.velocypack.VPackSlice; -import com.arangodb.velocypack.exception.VPackException; - -import java.lang.reflect.Type; - -/** - * @author Mark Vollmary - */ -public class ArangoDeserializerImpl implements ArangoDeserializer { - - private final VPack vpacker; - private final VPackParser vpackParser; - - public ArangoDeserializerImpl(final VPack vpacker, final VPackParser vpackParser) { - super(); - this.vpacker = vpacker; - this.vpackParser = vpackParser; - } - - @Override - @SuppressWarnings("unchecked") - public T deserialize(final VPackSlice vpack, final Type type) throws ArangoDBException { - try { - final T doc; - if (type == String.class && !vpack.isString() && !vpack.isNull()) { - doc = (T) vpackParser.toJson(vpack, true); - } else { - doc = vpacker.deserialize(vpack, type); - } - return doc; - } catch (final VPackException e) { - throw new ArangoDBException(e); - } - } -} diff --git a/src/main/java/com/arangodb/internal/velocypack/VPackDeserializers.java b/src/main/java/com/arangodb/internal/velocypack/VPackDeserializers.java deleted file mode 100644 index b7bbf5e31..000000000 --- a/src/main/java/com/arangodb/internal/velocypack/VPackDeserializers.java +++ /dev/null @@ -1,196 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.internal.velocypack; - -import com.arangodb.entity.*; -import com.arangodb.entity.arangosearch.*; -import com.arangodb.entity.arangosearch.analyzer.*; -import com.arangodb.model.CollectionSchema; -import com.arangodb.model.ZKDIndexOptions; -import com.arangodb.velocypack.VPackDeserializer; -import com.arangodb.velocypack.VPackParser; -import com.arangodb.velocypack.VPackSlice; -import com.arangodb.velocystream.Response; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.util.*; -import java.util.Map.Entry; - -/** - * @author Mark Vollmary - */ -public class VPackDeserializers { - - private static final Logger LOGGER = LoggerFactory.getLogger(VPackDeserializers.class); - private static final String DATE_TIME_FORMAT = "yyyy-MM-dd'T'HH:mm:ss.SSSZ"; - - public static final VPackDeserializer RESPONSE = (parent, vpack, context) -> { - final Response response = new Response(); - response.setVersion(vpack.get(0).getAsInt()); - response.setType(vpack.get(1).getAsInt()); - response.setResponseCode(vpack.get(2).getAsInt()); - if (vpack.size() > 3) { - response.setMeta(context.deserialize(vpack.get(3), Map.class)); - } - return response; - }; - - public static final VPackDeserializer COLLECTION_TYPE = (parent, vpack, context) -> CollectionType.fromType(vpack.getAsInt()); - - public static final VPackDeserializer COLLECTION_STATUS = (parent, vpack, context) -> CollectionStatus.fromStatus(vpack.getAsInt()); - - @SuppressWarnings("unchecked") - public static final VPackDeserializer BASE_DOCUMENT = (parent, vpack, context) -> new BaseDocument((Map) context.deserialize(vpack, Map.class)); - - public static final VPackDeserializer SEARCH_ANALYZER = (parent, vpack, context) -> { - AnalyzerType type = context.deserialize(vpack.get("type"), AnalyzerType.class); - switch (type) { - case identity: - return context.deserialize(vpack, IdentityAnalyzer.class); - case text: - return context.deserialize(vpack, TextAnalyzer.class); - case ngram: - return context.deserialize(vpack, NGramAnalyzer.class); - case delimiter: - return context.deserialize(vpack, DelimiterAnalyzer.class); - case stem: - return context.deserialize(vpack, StemAnalyzer.class); - case norm: - return context.deserialize(vpack, NormAnalyzer.class); - case pipeline: - return context.deserialize(vpack, PipelineAnalyzer.class); - case stopwords: - return context.deserialize(vpack, StopwordsAnalyzer.class); - case aql: - return context.deserialize(vpack, AQLAnalyzer.class); - case geojson: - return context.deserialize(vpack, GeoJSONAnalyzer.class); - case geopoint: - return context.deserialize(vpack, GeoPointAnalyzer.class); - case segmentation: - return context.deserialize(vpack, SegmentationAnalyzer.class); - case collation: - return context.deserialize(vpack, CollationAnalyzer.class); - default: - throw new IllegalArgumentException("Unknown analyzer type: " + type); - } - }; - - @SuppressWarnings("unchecked") - public static final VPackDeserializer BASE_EDGE_DOCUMENT = (parent, vpack, context) -> new BaseEdgeDocument((Map) context.deserialize(vpack, Map.class)); - - public static final VPackDeserializer DATE_STRING = (parent, vpack, context) -> { - try { - return new SimpleDateFormat(DATE_TIME_FORMAT).parse(vpack.getAsString()); - } catch (final ParseException e) { - if (LOGGER.isDebugEnabled()) { - LOGGER.debug("got ParseException for date string: " + vpack.getAsString()); - } - } - return null; - }; - - public static final VPackDeserializer LOG_LEVEL = (parent, vpack, context) -> LogLevel.fromLevel(vpack.getAsInt()); - - public static final VPackDeserializer LICENSE = (parent, vpack, context) -> License.valueOf(vpack.getAsString().toUpperCase(Locale.ENGLISH)); - - public static final VPackDeserializer PERMISSIONS = (parent, vpack, context) -> Permissions.valueOf(vpack.getAsString().toUpperCase(Locale.ENGLISH)); - - public static final VPackDeserializer QUERY_EXECUTION_STATE = (parent, vpack, context) -> QueryExecutionState.valueOf(vpack.getAsString().toUpperCase(Locale.ENGLISH).replaceAll(" ", "_")); - - public static final VPackDeserializer REPLICATION_FACTOR = (parent, vpack, context) -> { - if (vpack.isString() && vpack.getAsString().equals("satellite")) { - return ReplicationFactor.ofSatellite(); - } else { - return ReplicationFactor.of(vpack.getAsInt()); - } - }; - - public static final VPackDeserializer VIEW_TYPE = (parent, vpack, context) -> "arangosearch".equals(vpack.getAsString()) ? ViewType.ARANGO_SEARCH - : ViewType.valueOf(vpack.getAsString().toUpperCase(Locale.ENGLISH)); - - protected static FieldLink deserializeField(final Entry field) { - final VPackSlice value = field.getValue(); - final FieldLink link = FieldLink.on(field.getKey()); - final VPackSlice analyzers = value.get("analyzers"); - if (analyzers.isArray()) { - final Iterator analyzerIterator = analyzers.arrayIterator(); - for (; analyzerIterator.hasNext(); ) { - link.analyzers(analyzerIterator.next().getAsString()); - } - } - final VPackSlice includeAllFields = value.get("includeAllFields"); - if (includeAllFields.isBoolean()) { - link.includeAllFields(includeAllFields.getAsBoolean()); - } - final VPackSlice trackListPositions = value.get("trackListPositions"); - if (trackListPositions.isBoolean()) { - link.trackListPositions(trackListPositions.getAsBoolean()); - } - final VPackSlice storeValues = value.get("storeValues"); - if (storeValues.isString()) { - link.storeValues(StoreValuesType.valueOf(storeValues.getAsString().toUpperCase(Locale.ENGLISH))); - } - final VPackSlice fields = value.get("fields"); - if (fields.isObject()) { - final Iterator> fieldsIterator = fields.objectIterator(); - for (; fieldsIterator.hasNext(); ) { - link.fields(deserializeField(fieldsIterator.next())); - } - } - return link; - } - - public static final VPackDeserializer CONSOLIDATE = (parent, vpack, context) -> { - final VPackSlice type = vpack.get("type"); - if (type.isString()) { - final ConsolidationPolicy consolidate = ConsolidationPolicy - .of(ConsolidationType.valueOf(type.getAsString().toUpperCase(Locale.ENGLISH))); - final VPackSlice threshold = vpack.get("threshold"); - if (threshold.isNumber()) { - consolidate.threshold(threshold.getAsDouble()); - } - final VPackSlice segmentThreshold = vpack.get("segmentThreshold"); - if (segmentThreshold.isInteger()) { - consolidate.segmentThreshold(segmentThreshold.getAsLong()); - } - return consolidate; - } - return null; - }; - - public static final VPackDeserializer COLLECTION_VALIDATION = (parent, vpack, context) -> { - VPackParser parser = new VPackParser.Builder().build(); - CollectionSchema collectionValidation = new CollectionSchema(); - collectionValidation.setLevel(CollectionSchema.Level.of(vpack.get("level").getAsString())); - collectionValidation.setRule(parser.toJson(vpack.get("rule"), true)); - collectionValidation.setMessage(vpack.get("message").getAsString()); - return collectionValidation; - }; - - public static final VPackDeserializer ZKD_FIELD_VALUE_TYPES = - (parent, vpack, context) -> ZKDIndexOptions.FieldValueTypes.valueOf(vpack.getAsString().toUpperCase(Locale.ENGLISH)); - - -} diff --git a/src/main/java/com/arangodb/internal/velocypack/VPackDriverModule.java b/src/main/java/com/arangodb/internal/velocypack/VPackDriverModule.java deleted file mode 100644 index cab5b226a..000000000 --- a/src/main/java/com/arangodb/internal/velocypack/VPackDriverModule.java +++ /dev/null @@ -1,101 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.internal.velocypack; - -import com.arangodb.entity.*; -import com.arangodb.entity.arangosearch.ConsolidationPolicy; -import com.arangodb.entity.arangosearch.ConsolidationType; -import com.arangodb.entity.arangosearch.analyzer.SearchAnalyzer; -import com.arangodb.internal.DocumentFields; -import com.arangodb.internal.velocystream.internal.AuthenticationRequest; -import com.arangodb.internal.velocystream.internal.JwtAuthenticationRequest; -import com.arangodb.model.CollectionSchema; -import com.arangodb.model.ZKDIndexOptions; -import com.arangodb.velocypack.VPackModule; -import com.arangodb.velocypack.VPackParserModule; -import com.arangodb.velocypack.VPackParserSetupContext; -import com.arangodb.velocypack.VPackSetupContext; -import com.arangodb.velocystream.Request; -import com.arangodb.velocystream.Response; - -import java.lang.annotation.Annotation; -import java.util.Date; - -/** - * @author Mark Vollmary - */ -public class VPackDriverModule implements VPackModule, VPackParserModule { - - @Override - public > void setup(final C context) { - context.fieldNamingStrategy(field -> { - for (Annotation annotation : field.getAnnotations()) { - if (annotation instanceof Id) { - return DocumentFields.ID; - } else if (annotation instanceof Key) { - return DocumentFields.KEY; - } else if (annotation instanceof Rev) { - return DocumentFields.REV; - } else if (annotation instanceof From) { - return DocumentFields.FROM; - } else if (annotation instanceof To) { - return DocumentFields.TO; - } - } - return field.getName(); - }); - context.registerSerializer(Request.class, VPackSerializers.REQUEST); - context.registerSerializer(AuthenticationRequest.class, VPackSerializers.AUTH_REQUEST); - context.registerSerializer(JwtAuthenticationRequest.class, VPackSerializers.JWT_AUTH_REQUEST); - context.registerSerializer(CollectionType.class, VPackSerializers.COLLECTION_TYPE); - context.registerSerializer(BaseDocument.class, VPackSerializers.BASE_DOCUMENT); - context.registerSerializer(BaseEdgeDocument.class, VPackSerializers.BASE_EDGE_DOCUMENT); - context.registerSerializer(LogLevel.class, VPackSerializers.LOG_LEVEL); - context.registerSerializer(Permissions.class, VPackSerializers.PERMISSIONS); - context.registerSerializer(ViewType.class, VPackSerializers.VIEW_TYPE); - context.registerSerializer(ConsolidationType.class, VPackSerializers.CONSOLIDATE_TYPE); - context.registerSerializer(CollectionSchema.class, VPackSerializers.COLLECTION_VALIDATION); - context.registerSerializer(ZKDIndexOptions.FieldValueTypes.class, VPackSerializers.ZKD_FIELD_VALUE_TYPES); - - context.registerDeserializer(Response.class, VPackDeserializers.RESPONSE); - context.registerDeserializer(CollectionType.class, VPackDeserializers.COLLECTION_TYPE); - context.registerDeserializer(CollectionStatus.class, VPackDeserializers.COLLECTION_STATUS); - context.registerDeserializer(BaseDocument.class, VPackDeserializers.BASE_DOCUMENT); - context.registerDeserializer(SearchAnalyzer.class, VPackDeserializers.SEARCH_ANALYZER); - context.registerDeserializer(BaseEdgeDocument.class, VPackDeserializers.BASE_EDGE_DOCUMENT); - context.registerDeserializer(QueryEntity.PROPERTY_STARTED, Date.class, VPackDeserializers.DATE_STRING); - context.registerDeserializer(LogLevel.class, VPackDeserializers.LOG_LEVEL); - context.registerDeserializer(License.class, VPackDeserializers.LICENSE); - context.registerDeserializer(Permissions.class, VPackDeserializers.PERMISSIONS); - context.registerDeserializer(QueryExecutionState.class, VPackDeserializers.QUERY_EXECUTION_STATE); - context.registerDeserializer(ReplicationFactor.class, VPackDeserializers.REPLICATION_FACTOR); - context.registerDeserializer(ViewType.class, VPackDeserializers.VIEW_TYPE); - context.registerDeserializer(ConsolidationPolicy.class, VPackDeserializers.CONSOLIDATE); - context.registerDeserializer(CollectionSchema.class, VPackDeserializers.COLLECTION_VALIDATION); - context.registerDeserializer(ZKDIndexOptions.FieldValueTypes.class, VPackDeserializers.ZKD_FIELD_VALUE_TYPES); - } - - @Override - public > void setup(final C context) { - - } - -} diff --git a/src/main/java/com/arangodb/internal/velocypack/VPackSerializers.java b/src/main/java/com/arangodb/internal/velocypack/VPackSerializers.java deleted file mode 100644 index 29af7f6c6..000000000 --- a/src/main/java/com/arangodb/internal/velocypack/VPackSerializers.java +++ /dev/null @@ -1,159 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.internal.velocypack; - -import com.arangodb.entity.*; -import com.arangodb.entity.arangosearch.*; -import com.arangodb.internal.DocumentFields; -import com.arangodb.internal.velocystream.internal.AuthenticationRequest; -import com.arangodb.internal.velocystream.internal.JwtAuthenticationRequest; -import com.arangodb.model.CollectionSchema; -import com.arangodb.model.ZKDIndexOptions; -import com.arangodb.velocypack.*; -import com.arangodb.velocystream.Request; - -import java.util.Collection; -import java.util.HashMap; -import java.util.Locale; -import java.util.Map; -import java.util.Map.Entry; - -/** - * @author Mark Vollmary - */ -public class VPackSerializers { - - public static final VPackSerializer REQUEST = (builder, attribute, value, context) -> { - builder.add(attribute, ValueType.ARRAY); - builder.add(value.getVersion()); - builder.add(value.getType()); - builder.add(value.getDbName().get()); - builder.add(value.getRequestType().getType()); - builder.add(value.getRequest()); - builder.add(ValueType.OBJECT); - for (final Entry entry : value.getQueryParam().entrySet()) { - builder.add(entry.getKey(), entry.getValue()); - } - builder.close(); - builder.add(ValueType.OBJECT); - for (final Entry entry : value.getHeaderParam().entrySet()) { - builder.add(entry.getKey(), entry.getValue()); - } - builder.close(); - builder.close(); - }; - - public static final VPackSerializer AUTH_REQUEST = (builder, attribute, value, context) -> { - builder.add(attribute, ValueType.ARRAY); - builder.add(value.getVersion()); - builder.add(value.getType()); - builder.add(value.getEncryption()); - builder.add(value.getUser()); - builder.add(value.getPassword()); - builder.close(); - }; - - public static final VPackSerializer JWT_AUTH_REQUEST = (builder, attribute, value, context) -> { - builder.add(attribute, ValueType.ARRAY); - builder.add(value.getVersion()); - builder.add(value.getType()); - builder.add(value.getEncryption()); - builder.add(value.getToken()); - builder.close(); - }; - - public static final VPackSerializer COLLECTION_TYPE = (builder, attribute, value, context) -> builder.add(attribute, value.getType()); - - public static final VPackSerializer BASE_DOCUMENT = (builder, attribute, value, context) -> { - final Map doc = new HashMap<>(value.getProperties()); - doc.put(DocumentFields.ID, value.getId()); - doc.put(DocumentFields.KEY, value.getKey()); - doc.put(DocumentFields.REV, value.getRevision()); - context.serialize(builder, attribute, doc); - }; - - public static final VPackSerializer BASE_EDGE_DOCUMENT = (builder, attribute, value, context) -> { - final Map doc = new HashMap<>(value.getProperties()); - doc.put(DocumentFields.ID, value.getId()); - doc.put(DocumentFields.KEY, value.getKey()); - doc.put(DocumentFields.REV, value.getRevision()); - doc.put(DocumentFields.FROM, value.getFrom()); - doc.put(DocumentFields.TO, value.getTo()); - context.serialize(builder, attribute, doc); - }; - - public static final VPackSerializer LOG_LEVEL = (builder, attribute, value, context) -> builder.add(attribute, value.getLevel()); - - public static final VPackSerializer PERMISSIONS = (builder, attribute, value, context) -> builder.add(attribute, value.toString().toLowerCase(Locale.ENGLISH)); - - public static final VPackSerializer VIEW_TYPE = (builder, attribute, value, context) -> { - final String type = value == ViewType.ARANGO_SEARCH ? "arangosearch" : value.name().toLowerCase(Locale.ENGLISH); - builder.add(attribute, type); - }; - - private static void serializeFieldLinks(final VPackBuilder builder, final Collection links) { - if (!links.isEmpty()) { - builder.add("fields", ValueType.OBJECT); - for (final FieldLink fieldLink : links) { - builder.add(fieldLink.getName(), ValueType.OBJECT); - final Collection analyzers = fieldLink.getAnalyzers(); - if (!analyzers.isEmpty()) { - builder.add("analyzers", ValueType.ARRAY); - for (final String analyzer : analyzers) { - builder.add(analyzer); - } - builder.close(); - } - final Boolean includeAllFields = fieldLink.getIncludeAllFields(); - if (includeAllFields != null) { - builder.add("includeAllFields", includeAllFields); - } - final Boolean trackListPositions = fieldLink.getTrackListPositions(); - if (trackListPositions != null) { - builder.add("trackListPositions", trackListPositions); - } - final StoreValuesType storeValues = fieldLink.getStoreValues(); - if (storeValues != null) { - builder.add("storeValues", storeValues.name().toLowerCase(Locale.ENGLISH)); - } - serializeFieldLinks(builder, fieldLink.getFields()); - builder.close(); - } - builder.close(); - } - } - - public static final VPackSerializer CONSOLIDATE_TYPE = (builder, attribute, value, context) -> builder.add(attribute, value.toString().toLowerCase(Locale.ENGLISH)); - - public static final VPackSerializer COLLECTION_VALIDATION = (builder, attribute, value, context) -> { - VPackParser parser = new VPackParser.Builder().build(); - VPackSlice rule = value.getRule() != null ? parser.fromJson(value.getRule(), true) : null; - final Map doc = new HashMap<>(); - doc.put("message", value.getMessage()); - doc.put("level", value.getLevel() != null ? value.getLevel().getValue() : null); - doc.put("rule", rule); - context.serialize(builder, attribute, doc); - }; - - public static final VPackSerializer ZKD_FIELD_VALUE_TYPES = - (builder, attribute, value, context) -> builder.add(attribute, value.name().toLowerCase(Locale.ENGLISH)); - -} diff --git a/src/main/java/com/arangodb/mapping/ArangoJack.java b/src/main/java/com/arangodb/mapping/ArangoJack.java index 26f9fd5c4..d195ad28d 100644 --- a/src/main/java/com/arangodb/mapping/ArangoJack.java +++ b/src/main/java/com/arangodb/mapping/ArangoJack.java @@ -21,21 +21,15 @@ package com.arangodb.mapping; import com.arangodb.ArangoDBException; -import com.arangodb.internal.mapping.ArangoAnnotationIntrospector; -import com.arangodb.internal.mapping.VPackDeserializers; -import com.arangodb.internal.mapping.VPackSerializers; import com.arangodb.jackson.dataformat.velocypack.VPackMapper; import com.arangodb.serde.DataType; import com.arangodb.serde.JacksonSerde; import com.arangodb.util.ArangoSerialization; -import com.arangodb.velocypack.VPackSlice; import com.fasterxml.jackson.annotation.JsonAutoDetect; -import com.fasterxml.jackson.annotation.JsonInclude.Include; import com.fasterxml.jackson.annotation.PropertyAccessor; import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializationFeature; -import com.fasterxml.jackson.databind.module.SimpleModule; import java.lang.reflect.Type; @@ -48,41 +42,13 @@ public interface ConfigureFunction { void configure(ObjectMapper mapper); } - private final ObjectMapper vpackMapper; - private final ObjectMapper vpackMapperNull; - private final ObjectMapper jsonMapper; - private final JacksonSerde serde; - private static final class ArangoModule extends SimpleModule { - @Override - public void setupModule(SetupContext context) { - super.setupModule(context); - context.insertAnnotationIntrospector(new ArangoAnnotationIntrospector()); - } - } - static VPackMapper createDefaultMapper() { final VPackMapper mapper = new VPackMapper(); mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false); mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); mapper.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY); - return configureDefaultMapper(mapper); - } - - static VPackMapper configureDefaultMapper(final VPackMapper mapper) { - final SimpleModule module = new ArangoJack.ArangoModule(); - module.addSerializer(VPackSlice.class, VPackSerializers.VPACK); - module.addSerializer(java.util.Date.class, VPackSerializers.UTIL_DATE); - module.addSerializer(java.sql.Date.class, VPackSerializers.SQL_DATE); - module.addSerializer(java.sql.Timestamp.class, VPackSerializers.SQL_TIMESTAMP); - - module.addDeserializer(VPackSlice.class, VPackDeserializers.VPACK); - module.addDeserializer(java.util.Date.class, VPackDeserializers.UTIL_DATE); - module.addDeserializer(java.sql.Date.class, VPackDeserializers.SQL_DATE); - module.addDeserializer(java.sql.Timestamp.class, VPackDeserializers.SQL_TIMESTAMP); - - mapper.registerModule(module); return mapper; } @@ -95,16 +61,11 @@ public ArangoJack() { */ public ArangoJack(final VPackMapper mapper) { super(); - vpackMapper = mapper.copy().setSerializationInclusion(Include.NON_NULL); - vpackMapperNull = mapper.copy().setSerializationInclusion(Include.ALWAYS); - jsonMapper = new ObjectMapper().setSerializationInclusion(Include.NON_NULL); - serde = JacksonSerde.of(DataType.VPACK, configureDefaultMapper(new VPackMapper())); + VPackMapper m = mapper != null ? mapper.copy() : new VPackMapper(); + serde = JacksonSerde.of(DataType.VPACK, m); } public void configure(final ArangoJack.ConfigureFunction f) { - f.configure(vpackMapper); - f.configure(vpackMapperNull); - f.configure(jsonMapper); serde.configure(f::configure); } diff --git a/src/main/java/com/arangodb/model/AqlQueryOptions.java b/src/main/java/com/arangodb/model/AqlQueryOptions.java index a83b05cee..eabb084f6 100644 --- a/src/main/java/com/arangodb/model/AqlQueryOptions.java +++ b/src/main/java/com/arangodb/model/AqlQueryOptions.java @@ -21,10 +21,7 @@ package com.arangodb.model; import com.arangodb.serde.InternalSerializers; -import com.arangodb.velocypack.VPackSlice; import com.arangodb.velocypack.annotations.Expose; -import com.fasterxml.jackson.annotation.JsonIgnore; -import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.databind.annotation.JsonSerialize; import java.util.ArrayList; @@ -44,8 +41,7 @@ public class AqlQueryOptions { private Integer batchSize; private Boolean cache; private Long memoryLimit; - private VPackSlice bindVars; - private byte[] bindVarsBytes; + private byte[] bindVars; private String query; private Options options; @Expose(serialize = false) @@ -153,24 +149,9 @@ public AqlQueryOptions fillBlockCache(final Boolean fillBlockCache) { return this; } - @JsonIgnore - public VPackSlice getBindVars() { - return bindVars; - } - - @JsonProperty("bindVars") @JsonSerialize(using = InternalSerializers.AqlParamsSerializer.class) - public byte[] getBindVarsBytes() { - return bindVarsBytes; - } - - /** - * @param bindVars key/value pairs representing the bind parameters - * @return options - */ - protected AqlQueryOptions bindVars(final VPackSlice bindVars) { - this.bindVars = bindVars; - return this; + public byte[] getBindVars() { + return bindVars; } /** @@ -178,7 +159,7 @@ protected AqlQueryOptions bindVars(final VPackSlice bindVars) { * @return options */ protected AqlQueryOptions bindVars(final byte[] bindVarsBytes) { - this.bindVarsBytes = bindVarsBytes; + this.bindVars = bindVarsBytes; return this; } diff --git a/src/main/java/com/arangodb/util/ArangoDeserializer.java b/src/main/java/com/arangodb/util/ArangoDeserializer.java deleted file mode 100644 index 55601faff..000000000 --- a/src/main/java/com/arangodb/util/ArangoDeserializer.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.util; - -import com.arangodb.ArangoDBException; -import com.arangodb.velocypack.VPackSlice; - -import java.lang.reflect.Type; - -/** - * @author Mark Vollmary - */ -public interface ArangoDeserializer { - - /** - * Deserialize a given VelocyPack to an instance of a given type - * - * @param vpack The VelocyPack to deserialize - * @param type The target type to deserialize to. Use String for raw JSON. - * @return The deserialized VelocyPack - * @throws ArangoDBException - */ - T deserialize(final VPackSlice vpack, final Type type) throws ArangoDBException; - -} diff --git a/src/test/java/com/arangodb/BaseDocumentTest.java b/src/test/java/com/arangodb/BaseDocumentTest.java deleted file mode 100644 index 8bb1ed0c4..000000000 --- a/src/test/java/com/arangodb/BaseDocumentTest.java +++ /dev/null @@ -1,95 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb; - -import com.arangodb.entity.BaseDocument; -import com.arangodb.internal.velocypack.VPackDriverModule; -import com.arangodb.velocypack.VPack; -import com.arangodb.velocypack.VPack.Builder; -import com.arangodb.velocypack.VPackBuilder; -import com.arangodb.velocypack.VPackSlice; -import com.arangodb.velocypack.ValueType; -import org.junit.jupiter.api.Test; - -import static org.assertj.core.api.Assertions.assertThat; - - -/** - * @author Mark Vollmary - * @author Michele Rastelli - */ -class BaseDocumentTest { - - @Test - void serialize() { - BaseDocument entity = new BaseDocument(); - entity.setKey("test"); - entity.setRevision("test"); - entity.addAttribute("a", "a"); - - Builder builder = new VPack.Builder(); - builder.registerModule(new VPackDriverModule()); - VPack vpacker = builder.build(); - - VPackSlice vpack = vpacker.serialize(entity); - assertThat(vpack).isNotNull(); - assertThat(vpack.isObject()).isTrue(); - assertThat(vpack.size()).isEqualTo(3); - - VPackSlice key = vpack.get("_key"); - assertThat(key.isString()).isTrue(); - assertThat(key.getAsString()).isEqualTo("test"); - - VPackSlice rev = vpack.get("_rev"); - assertThat(rev.isString()).isTrue(); - assertThat(rev.getAsString()).isEqualTo("test"); - - VPackSlice a = vpack.get("a"); - assertThat(a.isString()).isTrue(); - assertThat(a.getAsString()).isEqualTo("a"); - } - - @Test - void deserialize() { - VPackBuilder builder = new VPackBuilder(); - builder.add(ValueType.OBJECT); - builder.add("_id", "test/test"); - builder.add("_key", "test"); - builder.add("_rev", "test"); - builder.add("a", "a"); - builder.close(); - - VPack.Builder vbuilder = new VPack.Builder(); - vbuilder.registerModule(new VPackDriverModule()); - VPack vpacker = vbuilder.build(); - - BaseDocument entity = vpacker.deserialize(builder.slice(), BaseDocument.class); - assertThat(entity.getId()).isNotNull(); - assertThat(entity.getId()).isEqualTo("test/test"); - assertThat(entity.getKey()).isNotNull(); - assertThat(entity.getKey()).isEqualTo("test"); - assertThat(entity.getRevision()).isNotNull(); - assertThat(entity.getRevision()).isEqualTo("test"); - assertThat(entity.getProperties()).hasSize(1); - assertThat(String.valueOf(entity.getAttribute("a"))).isEqualTo("a"); - } - -} From 4f20c73653838f183b8e1f3906981ade1e04deab Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Tue, 12 Jul 2022 21:35:45 +0200 Subject: [PATCH 033/254] removed velocypack related code --- .../arangodb/entity/DocumentCreateEntity.java | 2 - .../arangodb/entity/DocumentDeleteEntity.java | 1 - .../arangodb/entity/DocumentUpdateEntity.java | 3 - .../com/arangodb/entity/EdgeUpdateEntity.java | 1 - .../arangodb/entity/VertexUpdateEntity.java | 1 - .../analyzer/NormAnalyzerProperties.java | 1 - .../SegmentationAnalyzerProperties.java | 2 - .../analyzer/TextAnalyzerProperties.java | 1 - .../com/arangodb/model/AqlQueryOptions.java | 1 - .../arangodb/model/DocumentReadOptions.java | 1 - .../model/GraphDocumentReadOptions.java | 1 - .../com/arangodb/velocystream/Request.java | 1 - .../com/arangodb/velocystream/Response.java | 1 - .../arangodb/async/ArangoDatabaseTest.java | 9 +- ...ueryWithSpecialReturnTypesExampleTest.java | 27 +- .../document/GetDocumentExampleTest.java | 7 +- .../document/InsertDocumentExampleTest.java | 14 +- ...ueryWithSpecialReturnTypesExampleTest.java | 27 +- .../document/GetDocumentExampleTest.java | 9 +- .../document/InsertDocumentExampleTest.java | 12 +- .../VPackSerializeDeserializeTest.java | 6560 +++++++++-------- .../annotations/ArangoAnnotationsTest.java | 63 - .../mapping/annotations/ExposeEntity.java | 101 - .../annotations/SerializedNameEntity.java | 89 - .../SerializedNameParameterEntity.java | 83 - 25 files changed, 3338 insertions(+), 3680 deletions(-) delete mode 100644 src/test/java/com/arangodb/mapping/annotations/ExposeEntity.java delete mode 100644 src/test/java/com/arangodb/mapping/annotations/SerializedNameEntity.java delete mode 100644 src/test/java/com/arangodb/mapping/annotations/SerializedNameParameterEntity.java diff --git a/src/main/java/com/arangodb/entity/DocumentCreateEntity.java b/src/main/java/com/arangodb/entity/DocumentCreateEntity.java index 9469325bf..aa25d24a0 100644 --- a/src/main/java/com/arangodb/entity/DocumentCreateEntity.java +++ b/src/main/java/com/arangodb/entity/DocumentCreateEntity.java @@ -29,9 +29,7 @@ */ public class DocumentCreateEntity extends DocumentEntity { - @Expose(deserialize = false) private T newDocument; - @Expose(deserialize = false) private T oldDocument; public DocumentCreateEntity() { diff --git a/src/main/java/com/arangodb/entity/DocumentDeleteEntity.java b/src/main/java/com/arangodb/entity/DocumentDeleteEntity.java index 336ec53c1..67de46e97 100644 --- a/src/main/java/com/arangodb/entity/DocumentDeleteEntity.java +++ b/src/main/java/com/arangodb/entity/DocumentDeleteEntity.java @@ -29,7 +29,6 @@ */ public class DocumentDeleteEntity extends DocumentEntity { - @Expose(deserialize = false) private T oldDocument; public DocumentDeleteEntity() { diff --git a/src/main/java/com/arangodb/entity/DocumentUpdateEntity.java b/src/main/java/com/arangodb/entity/DocumentUpdateEntity.java index c2bacbf94..9475a6924 100644 --- a/src/main/java/com/arangodb/entity/DocumentUpdateEntity.java +++ b/src/main/java/com/arangodb/entity/DocumentUpdateEntity.java @@ -33,11 +33,8 @@ public class DocumentUpdateEntity extends DocumentEntity { @JsonProperty("_oldRev") - @SerializedName("_oldRev") private String oldRev; - @Expose(deserialize = false) private T newDocument; - @Expose(deserialize = false) private T oldDocument; public DocumentUpdateEntity() { diff --git a/src/main/java/com/arangodb/entity/EdgeUpdateEntity.java b/src/main/java/com/arangodb/entity/EdgeUpdateEntity.java index ea26e50ed..26d16e468 100644 --- a/src/main/java/com/arangodb/entity/EdgeUpdateEntity.java +++ b/src/main/java/com/arangodb/entity/EdgeUpdateEntity.java @@ -30,7 +30,6 @@ public class EdgeUpdateEntity extends DocumentEntity { @JsonProperty("_oldRev") - @SerializedName("_oldRev") private String oldRev; public EdgeUpdateEntity() { diff --git a/src/main/java/com/arangodb/entity/VertexUpdateEntity.java b/src/main/java/com/arangodb/entity/VertexUpdateEntity.java index 89be57062..f68163121 100644 --- a/src/main/java/com/arangodb/entity/VertexUpdateEntity.java +++ b/src/main/java/com/arangodb/entity/VertexUpdateEntity.java @@ -29,7 +29,6 @@ public class VertexUpdateEntity extends DocumentEntity { @JsonProperty("_oldRev") - @SerializedName("_oldRev") private String oldRev; public VertexUpdateEntity() { diff --git a/src/main/java/com/arangodb/entity/arangosearch/analyzer/NormAnalyzerProperties.java b/src/main/java/com/arangodb/entity/arangosearch/analyzer/NormAnalyzerProperties.java index ec0d7820c..96f848e75 100644 --- a/src/main/java/com/arangodb/entity/arangosearch/analyzer/NormAnalyzerProperties.java +++ b/src/main/java/com/arangodb/entity/arangosearch/analyzer/NormAnalyzerProperties.java @@ -36,7 +36,6 @@ public class NormAnalyzerProperties { private boolean accent; @JsonProperty("case") - @SerializedName("case") private SearchAnalyzerCase analyzerCase; /** diff --git a/src/main/java/com/arangodb/entity/arangosearch/analyzer/SegmentationAnalyzerProperties.java b/src/main/java/com/arangodb/entity/arangosearch/analyzer/SegmentationAnalyzerProperties.java index 0140437c8..76080409e 100644 --- a/src/main/java/com/arangodb/entity/arangosearch/analyzer/SegmentationAnalyzerProperties.java +++ b/src/main/java/com/arangodb/entity/arangosearch/analyzer/SegmentationAnalyzerProperties.java @@ -33,11 +33,9 @@ public class SegmentationAnalyzerProperties { @JsonProperty("break") - @SerializedName("break") private BreakMode breakMode; @JsonProperty("case") - @SerializedName("case") private SearchAnalyzerCase analyzerCase; public BreakMode getBreakMode() { diff --git a/src/main/java/com/arangodb/entity/arangosearch/analyzer/TextAnalyzerProperties.java b/src/main/java/com/arangodb/entity/arangosearch/analyzer/TextAnalyzerProperties.java index 5b68d0247..8dbb6057c 100644 --- a/src/main/java/com/arangodb/entity/arangosearch/analyzer/TextAnalyzerProperties.java +++ b/src/main/java/com/arangodb/entity/arangosearch/analyzer/TextAnalyzerProperties.java @@ -42,7 +42,6 @@ public TextAnalyzerProperties() { private boolean accent; @JsonProperty("case") - @SerializedName("case") private SearchAnalyzerCase analyzerCase; private boolean stemming; diff --git a/src/main/java/com/arangodb/model/AqlQueryOptions.java b/src/main/java/com/arangodb/model/AqlQueryOptions.java index eabb084f6..090d0c393 100644 --- a/src/main/java/com/arangodb/model/AqlQueryOptions.java +++ b/src/main/java/com/arangodb/model/AqlQueryOptions.java @@ -44,7 +44,6 @@ public class AqlQueryOptions { private byte[] bindVars; private String query; private Options options; - @Expose(serialize = false) private Boolean allowDirtyRead; private String streamTransactionId; diff --git a/src/main/java/com/arangodb/model/DocumentReadOptions.java b/src/main/java/com/arangodb/model/DocumentReadOptions.java index b808f6ed4..74c1af550 100644 --- a/src/main/java/com/arangodb/model/DocumentReadOptions.java +++ b/src/main/java/com/arangodb/model/DocumentReadOptions.java @@ -33,7 +33,6 @@ public class DocumentReadOptions { private String ifNoneMatch; private String ifMatch; private boolean catchException; - @Expose(serialize = false) private Boolean allowDirtyRead; private String streamTransactionId; diff --git a/src/main/java/com/arangodb/model/GraphDocumentReadOptions.java b/src/main/java/com/arangodb/model/GraphDocumentReadOptions.java index 1e661f64d..bad03413e 100644 --- a/src/main/java/com/arangodb/model/GraphDocumentReadOptions.java +++ b/src/main/java/com/arangodb/model/GraphDocumentReadOptions.java @@ -30,7 +30,6 @@ public class GraphDocumentReadOptions { private String ifNoneMatch; private String ifMatch; private boolean catchException; - @Expose(serialize = false) private Boolean allowDirtyRead; private String streamTransactionId; diff --git a/src/main/java/com/arangodb/velocystream/Request.java b/src/main/java/com/arangodb/velocystream/Request.java index 872b01cf3..a0ebb0941 100644 --- a/src/main/java/com/arangodb/velocystream/Request.java +++ b/src/main/java/com/arangodb/velocystream/Request.java @@ -38,7 +38,6 @@ public class Request { private final String request; private final Map queryParam; private final Map headerParam; - @Expose(serialize = false) private byte[] body; public Request(final DbName dbName, final RequestType requestType, final String path) { diff --git a/src/main/java/com/arangodb/velocystream/Response.java b/src/main/java/com/arangodb/velocystream/Response.java index 36021e1c5..4d8a27af4 100644 --- a/src/main/java/com/arangodb/velocystream/Response.java +++ b/src/main/java/com/arangodb/velocystream/Response.java @@ -34,7 +34,6 @@ public class Response { private int type = 2; private int responseCode; private Map meta; - @Expose(deserialize = false) private byte[] body = null; public Response() { diff --git a/src/test/java/com/arangodb/async/ArangoDatabaseTest.java b/src/test/java/com/arangodb/async/ArangoDatabaseTest.java index 206a54703..0ff4f81e8 100644 --- a/src/test/java/com/arangodb/async/ArangoDatabaseTest.java +++ b/src/test/java/com/arangodb/async/ArangoDatabaseTest.java @@ -30,6 +30,7 @@ import com.arangodb.velocypack.VPackBuilder; import com.arangodb.velocypack.VPackSlice; import com.arangodb.velocypack.exception.VPackException; +import com.fasterxml.jackson.databind.JsonNode; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; @@ -889,12 +890,12 @@ void transactionNumber() throws InterruptedException, ExecutionException { } @Test - void transactionVPack() throws VPackException, InterruptedException, ExecutionException { + void transactionJsonNode() throws VPackException, InterruptedException, ExecutionException { final TransactionOptions options = new TransactionOptions().params(new VPackBuilder().add("test").slice()); - db.transaction("function (params) {return params;}", VPackSlice.class, options) + db.transaction("function (params) {return params;}", JsonNode.class, options) .whenComplete((result, ex) -> { - assertThat(result.isString()).isEqualTo(true); - assertThat(result.getAsString()).isEqualTo("test"); + assertThat(result.isTextual()).isEqualTo(true); + assertThat(result.asText()).isEqualTo("test"); }) .get(); } diff --git a/src/test/java/com/arangodb/async/example/document/AqlQueryWithSpecialReturnTypesExampleTest.java b/src/test/java/com/arangodb/async/example/document/AqlQueryWithSpecialReturnTypesExampleTest.java index a5ab9ab14..b4e98bc16 100644 --- a/src/test/java/com/arangodb/async/example/document/AqlQueryWithSpecialReturnTypesExampleTest.java +++ b/src/test/java/com/arangodb/async/example/document/AqlQueryWithSpecialReturnTypesExampleTest.java @@ -23,7 +23,8 @@ import com.arangodb.async.example.ExampleBase; import com.arangodb.entity.BaseDocument; import com.arangodb.util.MapBuilder; -import com.arangodb.velocypack.VPackSlice; +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.fasterxml.jackson.databind.node.ObjectNode; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; @@ -55,29 +56,29 @@ private static void createExamples() throws InterruptedException, ExecutionExcep } @Test - void aqlWithLimitQueryAsVPackObject() throws InterruptedException, ExecutionException { + void aqlWithLimitQueryAsJsonObject() throws InterruptedException, ExecutionException { final String query = "FOR t IN " + COLLECTION_NAME + " FILTER t.age >= 20 && t.age < 30 && t.gender == @gender RETURN t"; final Map bindVars = new MapBuilder().put("gender", Gender.FEMALE).get(); - db.query(query, bindVars, null, VPackSlice.class) - .whenComplete((cursor, ex) -> cursor.forEachRemaining(vpack -> { - assertThat(vpack.get("name").getAsString()).isIn("TestUser11", "TestUser13", "TestUser15", "TestUser17", "TestUser19"); - assertThat(vpack.get("gender").getAsString()).isEqualTo(Gender.FEMALE.name()); - assertThat(vpack.get("age").getAsInt()).isIn(21, 23, 25, 27, 29); + db.query(query, bindVars, null, ObjectNode.class) + .whenComplete((cursor, ex) -> cursor.forEachRemaining(node -> { + assertThat(node.get("name").asText()).isIn("TestUser11", "TestUser13", "TestUser15", "TestUser17", "TestUser19"); + assertThat(node.get("gender").asText()).isEqualTo(Gender.FEMALE.name()); + assertThat(node.get("age").asInt()).isIn(21, 23, 25, 27, 29); })) .get(); } @Test - void aqlWithLimitQueryAsVPackArray() throws InterruptedException, ExecutionException { + void aqlWithLimitQueryAsArrayNode() throws InterruptedException, ExecutionException { final String query = "FOR t IN " + COLLECTION_NAME + " FILTER t.age >= 20 && t.age < 30 && t.gender == @gender RETURN [t.name, t.gender, t.age]"; final Map bindVars = new MapBuilder().put("gender", Gender.FEMALE).get(); - db.query(query, bindVars, null, VPackSlice.class) - .whenComplete((cursor, ex) -> cursor.forEachRemaining(vpack -> { - assertThat(vpack.get(0).getAsString()).isIn("TestUser11", "TestUser13", "TestUser15", "TestUser17", "TestUser19"); - assertThat(vpack.get(1).getAsString()).isEqualTo(Gender.FEMALE.name()); - assertThat(vpack.get(2).getAsInt()).isIn(21, 23, 25, 27, 29); + db.query(query, bindVars, null, ArrayNode.class) + .whenComplete((cursor, ex) -> cursor.forEachRemaining(arrNode -> { + assertThat(arrNode.get(0).asText()).isIn("TestUser11", "TestUser13", "TestUser15", "TestUser17", "TestUser19"); + assertThat(arrNode.get(1).asText()).isEqualTo(Gender.FEMALE.name()); + assertThat(arrNode.get(2).asInt()).isIn(21, 23, 25, 27, 29); })) .get(); } diff --git a/src/test/java/com/arangodb/async/example/document/GetDocumentExampleTest.java b/src/test/java/com/arangodb/async/example/document/GetDocumentExampleTest.java index 0e7ae4c72..e2cb01a76 100644 --- a/src/test/java/com/arangodb/async/example/document/GetDocumentExampleTest.java +++ b/src/test/java/com/arangodb/async/example/document/GetDocumentExampleTest.java @@ -24,6 +24,7 @@ import com.arangodb.entity.BaseDocument; import com.arangodb.entity.DocumentCreateEntity; import com.arangodb.velocypack.VPackSlice; +import com.fasterxml.jackson.databind.JsonNode; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; @@ -71,11 +72,11 @@ void getAsBaseDocument() throws InterruptedException, ExecutionException { @Test void getAsVPack() throws InterruptedException, ExecutionException { - collection.getDocument(key, VPackSlice.class) + collection.getDocument(key, JsonNode.class) .whenComplete((doc, ex) -> { assertThat(doc).isNotNull(); - assertThat(doc.get("foo").isString()).isEqualTo(true); - assertThat(doc.get("foo").getAsString()).isEqualTo("bar"); + assertThat(doc.get("foo").isTextual()).isEqualTo(true); + assertThat(doc.get("foo").asText()).isEqualTo("bar"); }) .get(); } diff --git a/src/test/java/com/arangodb/async/example/document/InsertDocumentExampleTest.java b/src/test/java/com/arangodb/async/example/document/InsertDocumentExampleTest.java index abaedab49..cd5a4b889 100644 --- a/src/test/java/com/arangodb/async/example/document/InsertDocumentExampleTest.java +++ b/src/test/java/com/arangodb/async/example/document/InsertDocumentExampleTest.java @@ -22,11 +22,10 @@ import com.arangodb.async.example.ExampleBase; import com.arangodb.entity.BaseDocument; -import com.arangodb.velocypack.VPackBuilder; -import com.arangodb.velocypack.ValueType; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ObjectNode; import org.junit.jupiter.api.Test; - import java.util.concurrent.ExecutionException; import static org.assertj.core.api.Assertions.assertThat; @@ -54,10 +53,11 @@ void insertBaseDocument() throws ExecutionException, InterruptedException { } @Test - void insertVPack() throws ExecutionException, InterruptedException { - final VPackBuilder builder = new VPackBuilder(); - builder.add(ValueType.OBJECT).add("foo", "bar").close(); - collection.insertDocument(builder.slice()) + void insertJsonNode() throws ExecutionException, InterruptedException { + ObjectMapper mapper = new ObjectMapper(); + ObjectNode node = mapper.createObjectNode(); + node.put("foo", "bar"); + collection.insertDocument(node) .whenComplete((doc, ex) -> assertThat(doc.getKey()).isNotNull()) .get(); } diff --git a/src/test/java/com/arangodb/example/document/AqlQueryWithSpecialReturnTypesExampleTest.java b/src/test/java/com/arangodb/example/document/AqlQueryWithSpecialReturnTypesExampleTest.java index 1a46d3a15..1172d4071 100644 --- a/src/test/java/com/arangodb/example/document/AqlQueryWithSpecialReturnTypesExampleTest.java +++ b/src/test/java/com/arangodb/example/document/AqlQueryWithSpecialReturnTypesExampleTest.java @@ -24,7 +24,8 @@ import com.arangodb.entity.BaseDocument; import com.arangodb.example.ExampleBase; import com.arangodb.util.MapBuilder; -import com.arangodb.velocypack.VPackSlice; +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.fasterxml.jackson.databind.node.ObjectNode; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; @@ -59,34 +60,34 @@ private static void createExamples() { } @Test - void aqlWithLimitQueryAsVPackObject() { + void aqlWithLimitQueryAsJsonObject() { final String query = "FOR t IN " + COLLECTION_NAME + " FILTER t.age >= 20 && t.age < 30 && t.gender == @gender RETURN t"; final Map bindVars = new MapBuilder().put("gender", Gender.FEMALE).get(); - final ArangoCursor cursor = db.query(query, bindVars, null, VPackSlice.class); + final ArangoCursor cursor = db.query(query, bindVars, null, ObjectNode.class); assertThat((Object) cursor).isNotNull(); while (cursor.hasNext()) { - final VPackSlice vpack = cursor.next(); - assertThat(vpack.get("name").getAsString()) + final ObjectNode vpack = cursor.next(); + assertThat(vpack.get("name").asText()) .isIn("TestUser11", "TestUser13", "TestUser15", "TestUser17", "TestUser19"); - assertThat(vpack.get("gender").getAsString()).isEqualTo(Gender.FEMALE.name()); - assertThat(vpack.get("age").getAsInt()).isIn(21, 23, 25, 27, 29); + assertThat(vpack.get("gender").asText()).isEqualTo(Gender.FEMALE.name()); + assertThat(vpack.get("age").asInt()).isIn(21, 23, 25, 27, 29); } } @Test - void aqlWithLimitQueryAsVPackArray() { + void aqlWithLimitQueryAsJsonArray() { final String query = "FOR t IN " + COLLECTION_NAME + " FILTER t.age >= 20 && t.age < 30 && t.gender == @gender RETURN [t.name, t.gender, t.age]"; final Map bindVars = new MapBuilder().put("gender", Gender.FEMALE).get(); - final ArangoCursor cursor = db.query(query, bindVars, null, VPackSlice.class); + final ArangoCursor cursor = db.query(query, bindVars, null, ArrayNode.class); assertThat((Object) cursor).isNotNull(); while (cursor.hasNext()) { - final VPackSlice vpack = cursor.next(); - assertThat(vpack.get(0).getAsString()) + final ArrayNode arrNode = cursor.next(); + assertThat(arrNode.get(0).asText()) .isIn("TestUser11", "TestUser13", "TestUser15", "TestUser17", "TestUser19"); - assertThat(vpack.get(1).getAsString()).isEqualTo(Gender.FEMALE.name()); - assertThat(vpack.get(2).getAsInt()).isIn(21, 23, 25, 27, 29); + assertThat(arrNode.get(1).asText()).isEqualTo(Gender.FEMALE.name()); + assertThat(arrNode.get(2).asInt()).isIn(21, 23, 25, 27, 29); } } diff --git a/src/test/java/com/arangodb/example/document/GetDocumentExampleTest.java b/src/test/java/com/arangodb/example/document/GetDocumentExampleTest.java index 10df2972e..d7239a8f0 100644 --- a/src/test/java/com/arangodb/example/document/GetDocumentExampleTest.java +++ b/src/test/java/com/arangodb/example/document/GetDocumentExampleTest.java @@ -24,6 +24,7 @@ import com.arangodb.entity.DocumentCreateEntity; import com.arangodb.example.ExampleBase; import com.arangodb.velocypack.VPackSlice; +import com.fasterxml.jackson.databind.JsonNode; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; @@ -72,11 +73,11 @@ void getAsMap() { } @Test - void getAsVPack() { - final VPackSlice doc = collection.getDocument(key, VPackSlice.class); + void getAsJsonNode() { + final JsonNode doc = collection.getDocument(key, JsonNode.class); assertThat(doc).isNotNull(); - assertThat(doc.get("foo").isString()).isTrue(); - assertThat(doc.get("foo").getAsString()).isEqualTo("bar"); + assertThat(doc.get("foo").isTextual()).isTrue(); + assertThat(doc.get("foo").asText()).isEqualTo("bar"); } @Test diff --git a/src/test/java/com/arangodb/example/document/InsertDocumentExampleTest.java b/src/test/java/com/arangodb/example/document/InsertDocumentExampleTest.java index 016d7f2c3..8a4c38940 100644 --- a/src/test/java/com/arangodb/example/document/InsertDocumentExampleTest.java +++ b/src/test/java/com/arangodb/example/document/InsertDocumentExampleTest.java @@ -26,6 +26,9 @@ import com.arangodb.velocypack.VPackBuilder; import com.arangodb.velocypack.VPackSlice; import com.arangodb.velocypack.ValueType; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ObjectNode; import org.junit.jupiter.api.Test; import static org.assertj.core.api.Assertions.assertThat; @@ -51,10 +54,11 @@ void insertBaseDocument() { } @Test - void insertVPack() { - final VPackBuilder builder = new VPackBuilder(); - builder.add(ValueType.OBJECT).add("foo", "bar").close(); - final DocumentCreateEntity doc = collection.insertDocument(builder.slice()); + void insertJsonNode() { + ObjectMapper mapper = new ObjectMapper(); + ObjectNode node = mapper.createObjectNode(); + node.put("foo", "bar"); + final DocumentCreateEntity doc = collection.insertDocument(node); assertThat(doc.getKey()).isNotNull(); } diff --git a/src/test/java/com/arangodb/mapping/VPackSerializeDeserializeTest.java b/src/test/java/com/arangodb/mapping/VPackSerializeDeserializeTest.java index eed9a8052..ceefb66a0 100644 --- a/src/test/java/com/arangodb/mapping/VPackSerializeDeserializeTest.java +++ b/src/test/java/com/arangodb/mapping/VPackSerializeDeserializeTest.java @@ -21,3282 +21,3284 @@ package com.arangodb.mapping; -import com.arangodb.velocypack.*; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; -import org.junit.jupiter.api.Test; - -import java.io.IOException; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; -import java.math.BigDecimal; -import java.math.BigInteger; -import java.text.DateFormat; -import java.text.SimpleDateFormat; -import java.util.*; -import java.util.Map.Entry; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * @author Mark Vollmary - */ -class VPackSerializeDeserializeTest { - - private static final DateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");// ISO 8601 - - static { - DATE_FORMAT.setTimeZone(TimeZone.getTimeZone("UTC")); - } - - private final ObjectMapper mapper = ArangoJack.createDefaultMapper(); - - public static class TestEntityBoolean { - private boolean a = true; - private boolean b = false; - private Boolean c = Boolean.TRUE; - private Boolean d = Boolean.FALSE; - - public boolean isA() { - return a; - } - - public void setA(final boolean a) { - this.a = a; - } - - public boolean isB() { - return b; - } - - public void setB(final boolean b) { - this.b = b; - } - - public Boolean getC() { - return c; - } - - public void setC(final Boolean c) { - this.c = c; - } - - public Boolean getD() { - return d; - } - - public void setD(final Boolean d) { - this.d = d; - } - } - - @Test - void fromBoolean() throws JsonProcessingException { - final VPackSlice vpack = new VPackSlice(mapper.writeValueAsBytes(new TestEntityBoolean())); - assertThat(vpack).isNotNull(); - assertThat(vpack.isObject()).isTrue(); - { - final VPackSlice a = vpack.get("a"); - assertThat(a.isBoolean()).isTrue(); - assertThat(a.getAsBoolean()).isTrue(); - } - { - final VPackSlice b = vpack.get("b"); - assertThat(b.isBoolean()).isTrue(); - assertThat(b.getAsBoolean()).isFalse(); - } - { - final VPackSlice c = vpack.get("c"); - assertThat(c.isBoolean()).isTrue(); - assertThat(c.getAsBoolean()).isTrue(); - } - { - final VPackSlice d = vpack.get("d"); - assertThat(d.isBoolean()).isTrue(); - assertThat(d.getAsBoolean()).isFalse(); - } - } - - @Test - void toBoolean() throws IOException { - final VPackBuilder builder = new VPackBuilder(); - { - builder.add(ValueType.OBJECT); - builder.add("a", false); - builder.add("b", true); - builder.add("c", Boolean.FALSE); - builder.add("d", Boolean.TRUE); - builder.close(); - } - final VPackSlice vpack = builder.slice(); - final TestEntityBoolean entity = mapper.readValue(vpack.getBuffer(), TestEntityBoolean.class); - assertThat(entity).isNotNull(); - assertThat(entity.a).isFalse(); - assertThat(entity.b).isTrue(); - assertThat(entity.c).isInstanceOf(Boolean.class).isFalse(); - assertThat(entity.d).isInstanceOf(Boolean.class).isTrue(); - } - - public static class TestEntityString { - private String s = "test"; - private Character c1 = 't'; - private char c2 = 't'; - - public String getS() { - return s; - } - - public void setS(final String s) { - this.s = s; - } - - public Character getC1() { - return c1; - } - - public void setC1(final Character c1) { - this.c1 = c1; - } - - public char getC2() { - return c2; - } - - public void setC2(final char c2) { - this.c2 = c2; - } - } - - @Test - void fromStrings() throws JsonProcessingException { - final VPackSlice vpack = new VPackSlice(mapper.writeValueAsBytes(new TestEntityString())); - assertThat(vpack).isNotNull(); - assertThat(vpack.isObject()).isTrue(); - { - final VPackSlice s = vpack.get("s"); - assertThat(s.isString()).isTrue(); - assertThat(s.getAsString()).isEqualTo("test"); - } - { - final VPackSlice c1 = vpack.get("c1"); - assertThat(c1.isString()).isTrue(); - assertThat(c1.getAsChar()).isEqualTo('t'); - } - { - final VPackSlice c2 = vpack.get("c2"); - assertThat(c2.isString()).isTrue(); - assertThat(c2.getAsChar()).isEqualTo('t'); - } - } - - @Test - void toStrings() throws IOException { - final VPackBuilder builder = new VPackBuilder(); - { - builder.add(ValueType.OBJECT); - builder.add("s", "abc"); - builder.add("c1", 'd'); - builder.add("c2", 'd'); - builder.close(); - } - final VPackSlice vpack = builder.slice(); - final TestEntityString entity = mapper.readValue(vpack.getBuffer(), TestEntityString.class); - assertThat(entity).isNotNull(); - assertThat(entity.s).isEqualTo("abc"); - assertThat(entity.c1).isEqualTo(new Character('d')); - } - - public static class TestEntityInteger { - private int i1 = 1; - private Integer i2 = 1; - - public int getI1() { - return i1; - } - - public void setI1(final int i1) { - this.i1 = i1; - } - - public Integer getI2() { - return i2; - } - - public void setI2(final Integer i2) { - this.i2 = i2; - } - } - - @Test - void fromInteger() throws JsonProcessingException { - final VPackSlice vpack = new VPackSlice(mapper.writeValueAsBytes(new TestEntityInteger())); - assertThat(vpack).isNotNull(); - assertThat(vpack.isObject()).isTrue(); - { - final VPackSlice i1 = vpack.get("i1"); - assertThat(i1.isInteger()).isTrue(); - assertThat(i1.getAsInt()).isEqualTo(1); - } - { - final VPackSlice i2 = vpack.get("i2"); - assertThat(i2.isInteger()).isTrue(); - assertThat(i2.getAsInt()).isEqualTo(1); - } - } - - @Test - void fromNegativeInteger() throws JsonProcessingException { - final TestEntityInteger entity = new TestEntityInteger(); - entity.i1 = -50; - entity.i2 = -50; - final VPackSlice vpack = new VPackSlice(mapper.writeValueAsBytes(entity)); - assertThat(vpack).isNotNull(); - assertThat(vpack.isObject()).isTrue(); - { - final VPackSlice i1 = vpack.get("i1"); - assertThat(i1.isInteger()).isTrue(); - assertThat(i1.getAsInt()).isEqualTo(-50); - } - { - final VPackSlice i2 = vpack.get("i2"); - assertThat(i2.isInteger()).isTrue(); - assertThat(i2.getAsInt()).isEqualTo(-50); - } - } - - @Test - void toInteger() throws IOException { - final VPackBuilder builder = new VPackBuilder(); - { - builder.add(ValueType.OBJECT); - builder.add("i1", 2); - builder.add("i2", 3); - builder.close(); - } - final VPackSlice vpack = builder.slice(); - final TestEntityInteger entity = mapper.readValue(vpack.getBuffer(), TestEntityInteger.class); - assertThat(entity).isNotNull(); - assertThat(entity.i1).isEqualTo(2); - assertThat(entity.i2).isEqualTo(Integer.valueOf(3)); - } - - @Test - void toNegativeInteger() throws IOException { - final VPackBuilder builder = new VPackBuilder(); - { - builder.add(ValueType.OBJECT); - builder.add("i1", -50); - builder.add("i2", -50); - builder.close(); - } - final VPackSlice vpack = builder.slice(); - final TestEntityInteger entity = mapper.readValue(vpack.getBuffer(), TestEntityInteger.class); - assertThat(entity).isNotNull(); - assertThat(entity.i1).isEqualTo(-50); - assertThat(entity.i2).isEqualTo(Integer.valueOf(-50)); - } - - public static class TestEntityLong { - private long l1 = 1; - private Long l2 = 1L; - - public long getL1() { - return l1; - } - - public void setL1(final long l1) { - this.l1 = l1; - } - - public Long getL2() { - return l2; - } - - public void setL2(final Long l2) { - this.l2 = l2; - } - } - - @Test - void fromLong() throws JsonProcessingException { - final VPackSlice vpack = new VPackSlice(mapper.writeValueAsBytes(new TestEntityLong())); - assertThat(vpack).isNotNull(); - assertThat(vpack.isObject()).isTrue(); - { - final VPackSlice l1 = vpack.get("l1"); - assertThat(l1.isInteger()).isTrue(); - assertThat(l1.getAsLong()).isEqualTo(1L); - } - { - final VPackSlice l2 = vpack.get("l2"); - assertThat(l2.isInteger()).isTrue(); - assertThat(l2.getAsLong()).isEqualTo(1L); - } - } - - @Test - void fromNegativeLong() throws JsonProcessingException { - final TestEntityLong entity = new TestEntityLong(); - entity.l1 = -100L; - entity.l2 = -300L; - final VPackSlice vpack = new VPackSlice(mapper.writeValueAsBytes(entity)); - assertThat(vpack).isNotNull(); - assertThat(vpack.isObject()).isTrue(); - { - final VPackSlice l1 = vpack.get("l1"); - assertThat(l1.isInteger()).isTrue(); - assertThat(l1.getAsLong()).isEqualTo(-100L); - } - { - final VPackSlice l2 = vpack.get("l2"); - assertThat(l2.isInteger()).isTrue(); - assertThat(l2.getAsLong()).isEqualTo(-300); - } - } - - @Test - void toLong() throws IOException { - final VPackBuilder builder = new VPackBuilder(); - { - builder.add(ValueType.OBJECT); - builder.add("l1", 2); - builder.add("l2", 3); - builder.close(); - } - final VPackSlice vpack = builder.slice(); - final TestEntityLong entity = mapper.readValue(vpack.getBuffer(), TestEntityLong.class); - assertThat(entity).isNotNull(); - assertThat(entity.l1).isEqualTo(2); - assertThat(entity.l2).isEqualTo(Long.valueOf(3)); - } - - @Test - void toNegativeLong() throws IOException { - final VPackBuilder builder = new VPackBuilder(); - { - builder.add(ValueType.OBJECT); - builder.add("l1", -100L); - builder.add("l2", -300L); - builder.close(); - } - final VPackSlice vpack = builder.slice(); - final TestEntityLong entity = mapper.readValue(vpack.getBuffer(), TestEntityLong.class); - assertThat(entity).isNotNull(); - assertThat(entity.l1).isEqualTo(-100L); - assertThat(entity.l2).isEqualTo(Long.valueOf(-300)); - } - - @Test - void negativeLong() { - final TestEntityLong entity = new TestEntityLong(); - entity.l1 = -100L; - entity.l2 = -300L; - final VPack vp = new VPack.Builder().build(); - final TestEntityLong out = vp.deserialize(vp.serialize(entity), TestEntityLong.class); - assertThat(out.l1).isEqualTo(entity.l1); - assertThat(out.l2).isEqualTo(entity.l2); - } - - @Test - void intToLong() throws IOException { - final VPackBuilder builder = new VPackBuilder(); - { - builder.add(ValueType.OBJECT); - builder.add("l1", 100); - builder.add("l2", 300); - builder.close(); - } - final VPackSlice vpack = builder.slice(); - final TestEntityLong entity = mapper.readValue(vpack.getBuffer(), TestEntityLong.class); - assertThat(entity).isNotNull(); - assertThat(entity.l1).isEqualTo(100); - assertThat(entity.l2).isEqualTo(Long.valueOf(300)); - } - - @Test - void negativeIntToLong() throws IOException { - final VPackBuilder builder = new VPackBuilder(); - { - builder.add(ValueType.OBJECT); - builder.add("l1", -100); - builder.add("l2", -300); - builder.close(); - } - final VPackSlice vpack = builder.slice(); - final TestEntityLong entity = mapper.readValue(vpack.getBuffer(), TestEntityLong.class); - assertThat(entity).isNotNull(); - assertThat(entity.l1).isEqualTo(-100L); - assertThat(entity.l2).isEqualTo(Long.valueOf(-300)); - } - - @Test - void negativeLongToInt() throws IOException { - final VPackBuilder builder = new VPackBuilder(); - { - builder.add(ValueType.OBJECT); - builder.add("i1", -100L); - builder.add("i2", -300L); - builder.close(); - } - final VPackSlice vpack = builder.slice(); - final TestEntityInteger entity = mapper.readValue(vpack.getBuffer(), TestEntityInteger.class); - assertThat(entity).isNotNull(); - assertThat(entity.i1).isEqualTo(-100); - assertThat(entity.i2).isEqualTo(Integer.valueOf(-300)); - } - - @Test - void negativeLongToShort() throws IOException { - final VPackBuilder builder = new VPackBuilder(); - { - builder.add(ValueType.OBJECT); - builder.add("s1", -100L); - builder.add("s2", -300L); - builder.close(); - } - final VPackSlice vpack = builder.slice(); - final TestEntityShort entity = mapper.readValue(vpack.getBuffer(), TestEntityShort.class); - assertThat(entity).isNotNull(); - assertThat(entity.s1).isEqualTo((short) -100); - assertThat(entity.s2).isEqualTo(Short.valueOf((short) -300)); - } - - @Test - void negativeShortToLong() throws IOException { - final VPackBuilder builder = new VPackBuilder(); - { - builder.add(ValueType.OBJECT); - builder.add("l1", (short) -100); - builder.add("l2", (short) -300); - builder.close(); - } - final VPackSlice vpack = builder.slice(); - final TestEntityLong entity = mapper.readValue(vpack.getBuffer(), TestEntityLong.class); - assertThat(entity).isNotNull(); - assertThat(entity.l1).isEqualTo(-100L); - assertThat(entity.l2).isEqualTo(Long.valueOf(-300)); - } - - public static class TestEntityFloat { - private float f1 = 1; - private Float f2 = 1F; - - public float getF1() { - return f1; - } - - public void setF1(final float f1) { - this.f1 = f1; - } - - public Float getF2() { - return f2; - } - - public void setF2(final Float f2) { - this.f2 = f2; - } - } - - @Test - void fromFloat() throws JsonProcessingException { - final VPackSlice vpack = new VPackSlice(mapper.writeValueAsBytes(new TestEntityFloat())); - assertThat(vpack).isNotNull(); - assertThat(vpack.isObject()).isTrue(); - { - final VPackSlice f1 = vpack.get("f1"); - assertThat(f1.isDouble()).isTrue(); - assertThat(f1.getAsFloat()).isEqualTo(1.0F); - } - { - final VPackSlice f2 = vpack.get("f2"); - assertThat(f2.isDouble()).isTrue(); - assertThat(f2.getAsFloat()).isEqualTo(1.0F); - } - } - - @Test - void toFloat() throws IOException { - final VPackBuilder builder = new VPackBuilder(); - { - builder.add(ValueType.OBJECT); - builder.add("f1", 2F); - builder.add("f2", 3F); - builder.close(); - } - final VPackSlice vpack = builder.slice(); - final TestEntityFloat entity = mapper.readValue(vpack.getBuffer(), TestEntityFloat.class); - assertThat(entity).isNotNull(); - assertThat(entity.f1).isEqualTo(2F); - assertThat(entity.f2).isEqualTo(new Float(3)); - } - - public static class TestEntityShort { - private short s1 = 1; - private Short s2 = 1; - - public short getS1() { - return s1; - } - - public void setS1(final short s1) { - this.s1 = s1; - } - - public Short getS2() { - return s2; - } - - public void setS2(final Short s2) { - this.s2 = s2; - } - } - - @Test - void fromShort() throws JsonProcessingException { - final VPackSlice vpack = new VPackSlice(mapper.writeValueAsBytes(new TestEntityShort())); - assertThat(vpack).isNotNull(); - assertThat(vpack.isObject()).isTrue(); - { - final VPackSlice s1 = vpack.get("s1"); - assertThat(s1.isInteger()).isTrue(); - assertThat(s1.getAsShort()).isEqualTo((short) 1); - } - { - final VPackSlice s2 = vpack.get("s2"); - assertThat(s2.isInteger()).isTrue(); - assertThat(s2.getAsShort()).isEqualTo((short) 1); - } - } - - @Test - void toShort() throws IOException { - final VPackBuilder builder = new VPackBuilder(); - { - builder.add(ValueType.OBJECT); - builder.add("s1", 2); - builder.add("s2", 3); - builder.close(); - } - final VPackSlice vpack = builder.slice(); - final TestEntityShort entity = mapper.readValue(vpack.getBuffer(), TestEntityShort.class); - assertThat(entity).isNotNull(); - assertThat(entity.s1).isEqualTo((short) 2); - assertThat(entity.s2).isEqualTo(Short.valueOf((short) 3)); - } - - public static class TestEntityByte { - private byte b1 = 1; // short integer path - private Byte b2 = 100; // integer path - - public byte getB1() { - return b1; - } - - public void setB1(final byte b1) { - this.b1 = b1; - } - - public Byte getB2() { - return b2; - } - - public void setB2(final Byte b2) { - this.b2 = b2; - } - } - - @Test - void fromByte() throws JsonProcessingException { - final VPackSlice vpack = new VPackSlice(mapper.writeValueAsBytes(new TestEntityByte())); - assertThat(vpack).isNotNull(); - assertThat(vpack.isObject()).isTrue(); - { - final VPackSlice b1 = vpack.get("b1"); - assertThat(b1.isInteger()).isTrue(); - assertThat(b1.getAsByte()).isEqualTo((byte) 1); - } - { - final VPackSlice b2 = vpack.get("b2"); - assertThat(b2.isInteger()).isTrue(); - assertThat(b2.getAsByte()).isEqualTo((byte) 100); - } - } - - @Test - void toByte() throws IOException { - final VPackBuilder builder = new VPackBuilder(); - { - builder.add(ValueType.OBJECT); - builder.add("b1", 30); // integer path - builder.add("b2", 4); // short integer path - builder.close(); - } - final VPackSlice vpack = builder.slice(); - final TestEntityByte entity = mapper.readValue(vpack.getBuffer(), TestEntityByte.class); - assertThat(entity).isNotNull(); - assertThat(entity.b1).isEqualTo((byte) 30); - assertThat(entity.b2).isEqualTo(Byte.valueOf((byte) 4)); - } - - public static class TestEntityDouble { - private Double d1 = 1.5; - private double d2 = 1.5; - - public Double getD1() { - return d1; - } - - public void setD1(final Double d1) { - this.d1 = d1; - } - - public double getD2() { - return d2; - } - - public void setD2(final double d2) { - this.d2 = d2; - } - } - - @Test - void fromDouble() throws JsonProcessingException { - final VPackSlice vpack = new VPackSlice(mapper.writeValueAsBytes(new TestEntityDouble())); - assertThat(vpack).isNotNull(); - assertThat(vpack.isObject()).isTrue(); - { - final VPackSlice d1 = vpack.get("d1"); - assertThat(d1.isDouble()).isTrue(); - assertThat(d1.getAsDouble()).isEqualTo(1.5); - } - { - final VPackSlice d2 = vpack.get("d2"); - assertThat(d2.isDouble()).isTrue(); - assertThat(d2.getAsDouble()).isEqualTo(1.5); - } - } - - @Test - void toDouble() throws IOException { - final VPackBuilder builder = new VPackBuilder(); - { - builder.add(ValueType.OBJECT); - builder.add("d1", 2.25); - builder.add("d2", 3.75); - builder.close(); - } - final VPackSlice vpack = builder.slice(); - final TestEntityDouble entity = mapper.readValue(vpack.getBuffer(), TestEntityDouble.class); - assertThat(entity).isNotNull(); - assertThat(entity.d1).isEqualTo(2.25); - assertThat(entity.d2).isEqualTo(3.75); - } - - public static class TestEntityBigNumber { - private static final BigInteger BI = BigInteger.valueOf(Long.MAX_VALUE).add(BigInteger.ONE); - private static final BigDecimal BD = BigDecimal.valueOf(Double.MAX_VALUE).add(BigDecimal.ONE); - - private BigInteger bi = BI; - private BigDecimal bd = BD; - - public BigInteger getBi() { - return bi; - } - - public void setBi(final BigInteger bi) { - this.bi = bi; - } - - public BigDecimal getBd() { - return bd; - } - - public void setBd(final BigDecimal bd) { - this.bd = bd; - } - } - - @Test - void fromBigNumbers() throws JsonProcessingException { - final VPackSlice vpack = new VPackSlice(mapper.writeValueAsBytes(new TestEntityBigNumber())); - assertThat(vpack).isNotNull(); - assertThat(vpack.isObject()).isTrue(); - { - final VPackSlice bi = vpack.get("bi"); - assertThat(bi.isString()).isTrue(); - assertThat(bi.getAsBigInteger()).isEqualTo(TestEntityBigNumber.BI); - } - { - final VPackSlice bd = vpack.get("bd"); - assertThat(bd.isString()).isTrue(); - assertThat(bd.getAsBigDecimal()).isEqualTo(TestEntityBigNumber.BD); - } - } - - @Test - void toBigNumbers() throws IOException { - final VPackBuilder builder = new VPackBuilder(); - { - builder.add(ValueType.OBJECT); - builder.add("bi", BigInteger.valueOf(2)); - builder.add("bd", BigDecimal.valueOf(3.75)); - builder.close(); - } - final VPackSlice vpack = builder.slice(); - final TestEntityBigNumber entity = mapper.readValue(vpack.getBuffer(), TestEntityBigNumber.class); - assertThat(entity).isNotNull(); - assertThat(entity.bi).isEqualTo(BigInteger.valueOf(2)); - assertThat(entity.bd).isEqualTo(BigDecimal.valueOf(3.75)); - } - - @Test - void bigDecimal() { - final BigDecimal fromDouble = BigDecimal.valueOf(-710.01); - final BigDecimal fromString = new BigDecimal("-710.01"); - assertThat(fromDouble).isEqualTo(fromString); - assertThat(new VPackBuilder().add(fromDouble).slice().getAsBigDecimal()).isEqualTo(fromDouble); - assertThat(new VPackBuilder().add(fromString).slice().getAsBigDecimal()).isEqualTo(fromDouble); - } - - public static class TestEntityArray { - private String[] a1 = {"a", "b", "cd"}; - private int[] a2 = {1, 2, 3, 4, 5}; - private boolean[] a3 = {true, true, false}; - private TestEnum[] a4 = TestEnum.values(); - - public String[] getA1() { - return a1; - } - - public void setA1(final String[] a1) { - this.a1 = a1; - } - - public int[] getA2() { - return a2; - } - - public void setA2(final int[] a2) { - this.a2 = a2; - } - - public boolean[] getA3() { - return a3; - } - - public void setA3(final boolean[] a3) { - this.a3 = a3; - } - - public TestEnum[] getA4() { - return a4; - } - - public void setA4(final TestEnum[] a4) { - this.a4 = a4; - } - - } - - @Test - void fromArray() throws JsonProcessingException { - final TestEntityArray entity = new TestEntityArray(); - final VPackSlice vpack = new VPackSlice(mapper.writeValueAsBytes(entity)); - assertThat(vpack).isNotNull(); - assertThat(vpack.isObject()).isTrue(); - { - final VPackSlice a1 = vpack.get("a1"); - assertThat(a1.isArray()).isTrue(); - assertThat(a1.getLength()).isEqualTo(entity.a1.length); - for (int i = 0; i < a1.getLength(); i++) { - assertThat(a1.get(i).getAsString()).isEqualTo(entity.a1[i]); - } - } - { - final VPackSlice a2 = vpack.get("a2"); - assertThat(a2.isArray()).isTrue(); - assertThat(a2.getLength()).isEqualTo(entity.a2.length); - for (int i = 0; i < a2.getLength(); i++) { - assertThat(a2.get(i).getAsInt()).isEqualTo(entity.a2[i]); - } - } - { - final VPackSlice a3 = vpack.get("a3"); - assertThat(a3.isArray()).isTrue(); - assertThat(a3.getLength()).isEqualTo(entity.a3.length); - for (int i = 0; i < a3.getLength(); i++) { - assertThat(a3.get(i).getAsBoolean()).isEqualTo(entity.a3[i]); - } - } - { - final VPackSlice a4 = vpack.get("a4"); - assertThat(a4.isArray()).isTrue(); - assertThat(a4.getLength()).isEqualTo(entity.a4.length); - for (int i = 0; i < a4.getLength(); i++) { - assertThat(TestEnum.valueOf(a4.get(i).getAsString())).isEqualTo(entity.a4[i]); - } - } - } - - @Test - void toArray() throws IOException { - final VPackBuilder builder = new VPackBuilder(); - { - builder.add(ValueType.OBJECT); - { - builder.add("a1", ValueType.ARRAY); - builder.add("a"); - builder.add("b"); - builder.add("c"); - builder.close(); - } - { - builder.add("a2", ValueType.ARRAY); - builder.add(1); - builder.add(2); - builder.add(3); - builder.add(4); - builder.close(); - } - { - builder.add("a3", ValueType.ARRAY); - builder.add(false); - builder.add(true); - builder.close(); - } - { - builder.add("a4", ValueType.ARRAY); - builder.add(TestEnum.A.name()); - builder.add(TestEnum.B.name()); - builder.close(); - } - builder.close(); - } - final VPackSlice vpack = builder.slice(); - final TestEntityArray entity = mapper.readValue(vpack.getBuffer(), TestEntityArray.class); - assertThat(entity).isNotNull(); - { - assertThat(entity.a1).hasSize(3); - assertThat(entity.a1[0]).isEqualTo("a"); - assertThat(entity.a1[1]).isEqualTo("b"); - assertThat(entity.a1[2]).isEqualTo("c"); - } - { - assertThat(entity.a2).hasSize(4); - assertThat(entity.a2[0]).isEqualTo(1); - assertThat(entity.a2[1]).isEqualTo(2); - assertThat(entity.a2[2]).isEqualTo(3); - assertThat(entity.a2[3]).isEqualTo(4); - } - { - assertThat(entity.a3).hasSize(2); - assertThat(entity.a3[0]).isFalse(); - assertThat(entity.a3[1]).isTrue(); - } - { - assertThat(entity.a4).hasSize(2); - assertThat(entity.a4[0]).isEqualTo(TestEnum.A); - assertThat(entity.a4[1]).isEqualTo(TestEnum.B); - } - } - - @Test - void fromArrayWithNull() throws JsonProcessingException { - final TestEntityArray entity = new TestEntityArray(); - entity.a1 = new String[]{"foo", null}; - - final VPackSlice vpack = new VPackSlice(mapper.writeValueAsBytes(entity)); - assertThat(vpack).isNotNull(); - assertThat(vpack.isObject()).isTrue(); - - final VPackSlice a1 = vpack.get("a1"); - assertThat(a1.isArray()).isTrue(); - assertThat(a1.size()).isEqualTo(2); - assertThat(a1.get(0).isString()).isTrue(); - assertThat(a1.get(0).getAsString()).isEqualTo("foo"); - assertThat(a1.get(1).isNull()).isTrue(); - } - - protected enum TestEnum { - A, B, C - } - - public static class TestEntityEnum { - private TestEnum e1 = TestEnum.A; - - public TestEnum getE1() { - return e1; - } - - public void setE1(final TestEnum e1) { - this.e1 = e1; - } - } - - @Test - void fromEnum() throws JsonProcessingException { - final VPackSlice vpack = new VPackSlice(mapper.writeValueAsBytes(new TestEntityEnum())); - assertThat(vpack).isNotNull(); - assertThat(vpack.isObject()).isTrue(); - { - final VPackSlice e1 = vpack.get("e1"); - assertThat(e1.isString()).isTrue(); - assertThat(TestEnum.valueOf(e1.getAsString())).isEqualTo(TestEnum.A); - } - } - - @Test - void toEnum() throws IOException { - final VPackBuilder builder = new VPackBuilder(); - { - builder.add(ValueType.OBJECT); - builder.add("e1", TestEnum.B.name()); - builder.close(); - } - final VPackSlice vpack = builder.slice(); - final TestEntityEnum entity = mapper.readValue(vpack.getBuffer(), TestEntityEnum.class); - assertThat(entity).isNotNull(); - assertThat(entity.e1).isEqualTo(TestEnum.B); - } - - public static class TestEntityObject { - private TestEntityLong o1 = new TestEntityLong(); - private TestEntityArray o2 = new TestEntityArray(); - - public TestEntityLong getO1() { - return o1; - } - - public void setO1(final TestEntityLong o1) { - this.o1 = o1; - } - - public TestEntityArray getO2() { - return o2; - } - - public void setO2(final TestEntityArray o2) { - this.o2 = o2; - } - } - - @Test - void fromObject() throws JsonProcessingException { - final TestEntityObject entity = new TestEntityObject(); - final VPackSlice vpack = new VPackSlice(mapper.writeValueAsBytes(entity)); - assertThat(vpack).isNotNull(); - assertThat(vpack.isObject()).isTrue(); - { - final VPackSlice o1 = vpack.get("o1"); - assertThat(o1.isObject()).isTrue(); - { - final VPackSlice l1 = o1.get("l1"); - assertThat(l1.isInteger()).isTrue(); - assertThat(l1.getAsLong()).isEqualTo(1L); - } - { - final VPackSlice l2 = o1.get("l2"); - assertThat(l2.isInteger()).isTrue(); - assertThat(l2.getAsLong()).isEqualTo(1L); - } - } - { - final VPackSlice o2 = vpack.get("o2"); - assertThat(o2.isObject()).isTrue(); - { - final VPackSlice a1 = o2.get("a1"); - assertThat(a1.isArray()).isTrue(); - assertThat(a1.getLength()).isEqualTo(entity.o2.a1.length); - for (int i = 0; i < a1.getLength(); i++) { - assertThat(a1.get(i).getAsString()).isEqualTo(entity.o2.a1[i]); - } - } - { - final VPackSlice a2 = o2.get("a2"); - assertThat(a2.isArray()).isTrue(); - assertThat(a2.getLength()).isEqualTo(entity.o2.a2.length); - for (int i = 0; i < a2.getLength(); i++) { - assertThat(a2.get(i).getAsInt()).isEqualTo(entity.o2.a2[i]); - } - } - { - final VPackSlice a3 = o2.get("a3"); - assertThat(a3.isArray()).isTrue(); - assertThat(a3.getLength()).isEqualTo(entity.o2.a3.length); - for (int i = 0; i < a3.getLength(); i++) { - assertThat(a3.get(i).getAsBoolean()).isEqualTo(entity.o2.a3[i]); - } - } - { - final VPackSlice a4 = o2.get("a4"); - assertThat(a4.isArray()).isTrue(); - assertThat(a4.getLength()).isEqualTo(entity.o2.a4.length); - for (int i = 0; i < a4.getLength(); i++) { - assertThat(TestEnum.valueOf(a4.get(i).getAsString())).isEqualTo(entity.o2.a4[i]); - } - } - } - } - - @Test - void toObject() throws IOException { - final VPackBuilder builder = new VPackBuilder(); - { - builder.add(ValueType.OBJECT); - { - builder.add("o1", ValueType.OBJECT); - builder.add("l1", 5L); - builder.add("l2", 5L); - builder.close(); - } - { - builder.add("o2", ValueType.OBJECT); - { - builder.add("a1", ValueType.ARRAY); - builder.add("a"); - builder.add("b"); - builder.add("c"); - builder.close(); - } - { - builder.add("a2", ValueType.ARRAY); - builder.add(1); - builder.add(2); - builder.add(3); - builder.add(4); - builder.close(); - } - { - builder.add("a3", ValueType.ARRAY); - builder.add(false); - builder.add(true); - builder.close(); - } - { - builder.add("a4", ValueType.ARRAY); - builder.add(TestEnum.A.name()); - builder.add(TestEnum.B.name()); - builder.close(); - } - builder.close(); - } - builder.close(); - } - final VPackSlice vpack = builder.slice(); - final TestEntityObject entity = mapper.readValue(vpack.getBuffer(), TestEntityObject.class); - assertThat(entity).isNotNull(); - { - assertThat(entity.o1.l1).isEqualTo(5L); - assertThat(entity.o1.l2).isEqualTo(Long.valueOf(5)); - } - { - assertThat(entity.o2.a1).hasSize(3); - assertThat(entity.o2.a1[0]).isEqualTo("a"); - assertThat(entity.o2.a1[1]).isEqualTo("b"); - assertThat(entity.o2.a1[2]).isEqualTo("c"); - } - { - assertThat(entity.o2.a2).hasSize(4); - assertThat(entity.o2.a2[0]).isEqualTo(1); - assertThat(entity.o2.a2[1]).isEqualTo(2); - assertThat(entity.o2.a2[2]).isEqualTo(3); - assertThat(entity.o2.a2[3]).isEqualTo(4); - } - { - assertThat(entity.o2.a3).hasSize(2); - assertThat(entity.o2.a3[0]).isFalse(); - assertThat(entity.o2.a3[1]).isTrue(); - } - { - assertThat(entity.o2.a4).hasSize(2); - assertThat(entity.o2.a4[0]).isEqualTo(TestEnum.A); - assertThat(entity.o2.a4[1]).isEqualTo(TestEnum.B); - } - } - - public static class TestEntityArrayInArray { - private long[][] a1; - - public long[][] getA1() { - return a1; - } - - public void setA1(final long[][] a1) { - this.a1 = a1; - } - } - - @Test - void fromArrayInArray() throws JsonProcessingException { - final TestEntityArrayInArray entity = new TestEntityArrayInArray(); - entity.a1 = new long[][]{{1, 2, 3}, {4, 5, 6}}; - final VPackSlice vpack = new VPackSlice(mapper.writeValueAsBytes(entity)); - assertThat(vpack).isNotNull(); - assertThat(vpack.isObject()).isTrue(); - { - final VPackSlice a1 = vpack.get("a1"); - assertThat(a1.isArray()).isTrue(); - assertThat(a1.getLength()).isEqualTo(entity.a1.length); - for (int i = 0; i < a1.getLength(); i++) { - final VPackSlice at = a1.get(i); - assertThat(at.isArray()).isTrue(); - assertThat(at.getLength()).isEqualTo(entity.a1[i].length); - for (int j = 0; j < at.getLength(); j++) { - final VPackSlice atat = at.get(j); - assertThat(atat.isInteger()).isTrue(); - assertThat(atat.getAsLong()).isEqualTo(entity.a1[i][j]); - } - } - } - } - - @Test - void toArrayInArray() throws IOException { - final VPackBuilder builder = new VPackBuilder(); - { - builder.add(ValueType.OBJECT); - { - builder.add("a1", ValueType.ARRAY); - { - builder.add(ValueType.ARRAY); - builder.add(1); - builder.add(2); - builder.add(3); - builder.close(); - } - { - builder.add(ValueType.ARRAY); - builder.add(4); - builder.add(5); - builder.add(6); - builder.close(); - } - builder.close(); - } - builder.close(); - } - final VPackSlice vpack = builder.slice(); - final TestEntityArrayInArray entity = mapper.readValue(vpack.getBuffer(), TestEntityArrayInArray.class); - assertThat(entity).isNotNull(); - assertThat(entity.a1.length).isEqualTo(2); - { - assertThat(entity.a1[0]).hasSize(3); - assertThat(entity.a1[0][0]).isEqualTo(1L); - assertThat(entity.a1[0][1]).isEqualTo(2L); - assertThat(entity.a1[0][2]).isEqualTo(3L); - } - { - assertThat(entity.a1[1]).hasSize(3); - assertThat(entity.a1[1][0]).isEqualTo(4L); - assertThat(entity.a1[1][1]).isEqualTo(5L); - assertThat(entity.a1[1][2]).isEqualTo(6L); - } - } - - @SuppressWarnings("serial") - public static class TestCollection extends LinkedList { - - } - - public static class TestEntityCollectionExtendedWithNulls { - - protected TestCollection a1; - - public TestCollection getA1() { - return a1; - } - - public void setA1(final TestCollection a1) { - this.a1 = a1; - } - - } - - @Test - void fromCollectionExtendedWithNulls() { - - final TestCollection collection = new TestCollection(); - collection.add("one"); - collection.add(null); - collection.add("two"); - - final TestEntityCollectionExtendedWithNulls entity = new TestEntityCollectionExtendedWithNulls(); - entity.setA1(collection); - - final VPackSlice vpack = new VPack.Builder().serializeNullValues(true).build().serialize(entity); - assertThat(vpack).isNotNull(); - assertThat(vpack.isObject()).isTrue(); - { - final VPackSlice a1 = vpack.get("a1"); - assertThat(a1.isArray()).isTrue(); - assertThat(a1.getLength()).isEqualTo(entity.a1.size()); - - VPackSlice at = a1.get(0); - assertThat(at.isString()).isTrue(); - assertThat(at.getAsString()).isEqualTo(entity.a1.get(0)); - at = a1.get(1); - assertThat(at.isNull()).isTrue(); - at = a1.get(2); - assertThat(at.isString()).isTrue(); - assertThat(at.getAsString()).isEqualTo(entity.a1.get(2)); - } - } - - @Test - void toCollectionExtendedWithNulls() throws Exception { - final VPackBuilder builder = new VPackBuilder(); - { - builder.add(ValueType.OBJECT); - { - builder.add("a1", ValueType.ARRAY); - builder.add("one"); - builder.add(ValueType.NULL); - builder.add("two"); - builder.close(); - } - builder.close(); - } - - final VPackSlice vpack = builder.slice(); - final TestEntityCollectionExtendedWithNulls entity = mapper.readValue(vpack.getBuffer(), - TestEntityCollectionExtendedWithNulls.class); - assertThat(entity).isNotNull(); - assertThat(entity.getA1()).isNotNull(); - assertThat(entity.getA1()).hasSize(3); - assertThat(entity.getA1()).contains("one", null, "two"); - } - - public static class TestEntityArrayInArrayInArray { - - private double[][][] a1; - - public double[][][] getA1() { - return a1; - } - - public void setA1(final double[][][] a1) { - this.a1 = a1; - } - - } - - @Test - void fromArrayInArrayInArray() throws JsonProcessingException { - final TestEntityArrayInArrayInArray entity = new TestEntityArrayInArrayInArray(); - entity.setA1(new double[][][]{{{1.5, 2.25}, {10.5, 20.25}}, {{100.5}, {200.25}}}); - final VPackSlice vpack = new VPackSlice(mapper.writeValueAsBytes(entity)); - assertThat(vpack).isNotNull(); - assertThat(vpack.isObject()).isTrue(); - { - final VPackSlice a1 = vpack.get("a1"); - assertThat(a1.isArray()).isTrue(); - assertThat(a1.getLength()).isEqualTo(entity.a1.length); - for (int i = 0; i < a1.getLength(); i++) { - final VPackSlice at = a1.get(i); - assertThat(at.isArray()).isTrue(); - assertThat(at.getLength()).isEqualTo(entity.a1[i].length); - for (int j = 0; j < at.getLength(); j++) { - final VPackSlice atat = at.get(j); - assertThat(atat.isArray()).isTrue(); - assertThat(atat.getLength()).isEqualTo(entity.a1[i][j].length); - for (int k = 0; k < atat.getLength(); k++) { - final VPackSlice atatat = atat.get(k); - assertThat(atatat.isDouble()).isTrue(); - assertThat(atatat.getAsDouble()).isEqualTo(entity.a1[i][j][k]); - } - } - } - } - } - - @Test - void toArrayInArrayInArray() throws IOException { - final VPackBuilder builder = new VPackBuilder(); - { - builder.add(ValueType.OBJECT); - { - builder.add("a1", ValueType.ARRAY); - builder.add(ValueType.ARRAY); - { - builder.add(ValueType.ARRAY); - builder.add(1.5); - builder.add(2.5); - builder.add(3.5); - builder.close(); - } - { - builder.add(ValueType.ARRAY); - builder.add(4.5); - builder.add(5.5); - builder.add(6.5); - builder.close(); - } - { - builder.add(ValueType.ARRAY); - builder.add(7.5); - builder.add(8.5); - builder.add(9.5); - builder.close(); - } - builder.close(); - builder.add(ValueType.ARRAY); - { - builder.add(ValueType.ARRAY); - builder.add(1.5); - builder.add(2.5); - builder.add(3.5); - builder.close(); - } - { - builder.add(ValueType.ARRAY); - builder.add(4.5); - builder.add(5.5); - builder.add(6.5); - builder.close(); - } - { - builder.add(ValueType.ARRAY); - builder.add(7.5); - builder.add(8.5); - builder.add(9.5); - builder.close(); - } - builder.close(); - builder.close(); - } - builder.close(); - } - final VPackSlice vpack = builder.slice(); - final TestEntityArrayInArrayInArray entity = mapper.readValue(vpack.getBuffer(), - TestEntityArrayInArrayInArray.class); - assertThat(entity).isNotNull(); - assertThat(entity.a1.length).isEqualTo(2); - { - assertThat(entity.a1[0].length).isEqualTo(3); - assertThat(entity.a1[0][0]).hasSize(3); - assertThat(entity.a1[0][0][0]).isEqualTo(1.5); - assertThat(entity.a1[0][0][1]).isEqualTo(2.5); - assertThat(entity.a1[0][0][2]).isEqualTo(3.5); - assertThat(entity.a1[0][1]).hasSize(3); - assertThat(entity.a1[0][1][0]).isEqualTo(4.5); - assertThat(entity.a1[0][1][1]).isEqualTo(5.5); - assertThat(entity.a1[0][1][2]).isEqualTo(6.5); - assertThat(entity.a1[0][2]).hasSize(3); - assertThat(entity.a1[0][2][0]).isEqualTo(7.5); - assertThat(entity.a1[0][2][1]).isEqualTo(8.5); - assertThat(entity.a1[0][2][2]).isEqualTo(9.5); - } - { - assertThat(entity.a1[1].length).isEqualTo(3); - assertThat(entity.a1[1][0]).hasSize(3); - assertThat(entity.a1[1][0][0]).isEqualTo(1.5); - assertThat(entity.a1[1][0][1]).isEqualTo(2.5); - assertThat(entity.a1[1][0][2]).isEqualTo(3.5); - assertThat(entity.a1[1][1]).hasSize(3); - assertThat(entity.a1[1][1][0]).isEqualTo(4.5); - assertThat(entity.a1[1][1][1]).isEqualTo(5.5); - assertThat(entity.a1[1][1][2]).isEqualTo(6.5); - assertThat(entity.a1[1][2]).hasSize(3); - assertThat(entity.a1[1][2][0]).isEqualTo(7.5); - assertThat(entity.a1[1][2][1]).isEqualTo(8.5); - assertThat(entity.a1[1][2][2]).isEqualTo(9.5); - } - } - - public static class TestEntityObjectInArray { - private TestEntityString[] a1; - - public TestEntityString[] getA1() { - return a1; - } - - public void setA1(final TestEntityString[] a1) { - this.a1 = a1; - } - } - - @Test - void fromObjectInArray() throws JsonProcessingException { - final TestEntityObjectInArray entity = new TestEntityObjectInArray(); - { - final TestEntityString[] a1 = new TestEntityString[2]; - final TestEntityString s = new TestEntityString(); - s.setS("abc"); - a1[0] = s; - a1[1] = s; - entity.setA1(a1); - } - final VPackSlice vpack = new VPackSlice(mapper.writeValueAsBytes(entity)); - assertThat(vpack).isNotNull(); - assertThat(vpack.isObject()).isTrue(); - { - final VPackSlice a1 = vpack.get("a1"); - assertThat(a1.isArray()).isTrue(); - assertThat(a1.getLength()).isEqualTo(2); - for (int i = 0; i < a1.getLength(); i++) { - final VPackSlice at = a1.get(i); - assertThat(at.isObject()).isTrue(); - final VPackSlice s = at.get("s"); - assertThat(s.isString()).isTrue(); - assertThat(s.getAsString()).isEqualTo("abc"); - } - } - } - - @Test - void toObjectInArray() throws IOException { - final VPackBuilder builder = new VPackBuilder(); - { - builder.add(ValueType.OBJECT); - builder.add("a1", ValueType.ARRAY); - { - builder.add(ValueType.OBJECT); - builder.add("s", "abc"); - builder.close(); - } - builder.close(); - builder.close(); - } - final VPackSlice vpack = builder.slice(); - final TestEntityObjectInArray entity = mapper.readValue(vpack.getBuffer(), TestEntityObjectInArray.class); - assertThat(entity).isNotNull(); - assertThat(entity.a1).hasSize(1); - final TestEntityString st = entity.a1[0]; - assertThat(st).isNotNull(); - assertThat(st.s).isEqualTo("abc"); - } - - public static class TestEntityA { - private String a = "a"; - - public String getA() { - return a; - } - - public void setA(final String a) { - this.a = a; - } - } - - public static class TestEntityB extends TestEntityA { - private String b = "b"; - - public String getB() { - return b; - } - - public void setB(final String b) { - this.b = b; - } - } - - @Test - void fromInheritance() throws JsonProcessingException { - final VPackSlice vpack = new VPackSlice(mapper.writeValueAsBytes(new TestEntityB())); - assertThat(vpack).isNotNull(); - assertThat(vpack.isObject()).isTrue(); - assertThat(vpack.getLength()).isEqualTo(2); - { - final VPackSlice a = vpack.get("a"); - assertThat(a.isString()).isTrue(); - assertThat(a.getAsString()).isEqualTo("a"); - } - { - final VPackSlice b = vpack.get("b"); - assertThat(b.isString()).isTrue(); - assertThat(b.getAsString()).isEqualTo("b"); - } - } - - @Test - void toInheritance() throws IOException { - final VPackBuilder builder = new VPackBuilder(); - { - builder.add(ValueType.OBJECT); - builder.add("a", "test"); - builder.add("b", "test"); - builder.close(); - } - final VPackSlice vpack = builder.slice(); - { - final TestEntityA entity = mapper.readValue(vpack.getBuffer(), TestEntityA.class); - assertThat(entity).isNotNull(); - assertThat(entity.getA()).isEqualTo("test"); - } - { - final TestEntityB entity = mapper.readValue(vpack.getBuffer(), TestEntityB.class); - assertThat(entity).isNotNull(); - assertThat(entity.getA()).isEqualTo("test"); - assertThat(entity.getB()).isEqualTo("test"); - } - } - - public static class TestEntityC { - private TestEntityD d; - - public TestEntityD getD() { - return d; - } - - public void setD(final TestEntityD d) { - this.d = d; - } - } - - protected interface TestEntityD { - String getD(); - - void setD(String d); - } - - public static class TestEntityDImpl implements TestEntityD { - private String d = "d"; - - @Override - public String getD() { - return d; - } - - @Override - public void setD(final String d) { - this.d = d; - } - } - - @Test - void fromInterface() throws JsonProcessingException { - final TestEntityC entity = new TestEntityC(); - entity.setD(new TestEntityDImpl()); - final VPackSlice vpack = new VPackSlice(mapper.writeValueAsBytes(entity)); - assertThat(vpack).isNotNull(); - assertThat(vpack.isObject()).isTrue(); - { - final VPackSlice d = vpack.get("d"); - assertThat(d.isObject()).isTrue(); - final VPackSlice dd = d.get("d"); - assertThat(dd.isString()).isTrue(); - assertThat(dd.getAsString()).isEqualTo("d"); - } - } - - @Test - void toInterface() { - final VPackBuilder builder = new VPackBuilder(); - { - builder.add(ValueType.OBJECT); - builder.add("d", ValueType.OBJECT); - builder.add("d", "test"); - builder.close(); - builder.close(); - } - final VPackSlice slice = builder.slice(); - final VPack vPack = new VPack.Builder() - .registerInstanceCreator(TestEntityD.class, (VPackInstanceCreator) TestEntityDImpl::new).build(); - final TestEntityC entity = vPack.deserialize(slice, TestEntityC.class); - assertThat(entity).isNotNull(); - assertThat(entity.d).isNotNull(); - assertThat(entity.d.getD()).isEqualTo("test"); - } - - public static class TestEntityCollection { - private Collection c1 = new LinkedList<>(); - private List c2 = new ArrayList<>(); - private ArrayList c3 = new ArrayList<>(); - private Set c4 = new LinkedHashSet<>(); - private HashSet c5 = new HashSet<>(); - - public TestEntityCollection() { - super(); - } - - public Collection getC1() { - return c1; - } - - public void setC1(final Collection c1) { - this.c1 = c1; - } - - public List getC2() { - return c2; - } - - public void setC2(final List c2) { - this.c2 = c2; - } - - public ArrayList getC3() { - return c3; - } - - public void setC3(final ArrayList c3) { - this.c3 = c3; - } - - public Set getC4() { - return c4; - } - - public void setC4(final Set c4) { - this.c4 = c4; - } - - public HashSet getC5() { - return c5; - } - - public void setC5(final HashSet c5) { - this.c5 = c5; - } - } - - @Test - void fromCollection() throws JsonProcessingException { - final TestEntityCollection entity = new TestEntityCollection(); - { - entity.c1.add("test"); - entity.c2.add("test"); - entity.c3.add("test"); - entity.c4.add("test"); - entity.c5.add("test"); - } - final VPackSlice vpack = new VPackSlice(mapper.writeValueAsBytes(entity)); - assertThat(vpack).isNotNull(); - assertThat(vpack.isObject()).isTrue(); - { - final VPackSlice c1 = vpack.get("c1"); - assertThat(c1.isArray()).isTrue(); - assertThat(c1.getLength()).isEqualTo(1); - assertThat(c1.get(0).getAsString()).isEqualTo("test"); - } - { - final VPackSlice c2 = vpack.get("c2"); - assertThat(c2.isArray()).isTrue(); - assertThat(c2.getLength()).isEqualTo(1); - assertThat(c2.get(0).getAsString()).isEqualTo("test"); - } - { - final VPackSlice c3 = vpack.get("c3"); - assertThat(c3.isArray()).isTrue(); - assertThat(c3.getLength()).isEqualTo(1); - assertThat(c3.get(0).getAsString()).isEqualTo("test"); - } - { - final VPackSlice c4 = vpack.get("c4"); - assertThat(c4.isArray()).isTrue(); - assertThat(c4.getLength()).isEqualTo(1); - assertThat(c4.get(0).getAsString()).isEqualTo("test"); - } - { - final VPackSlice c5 = vpack.get("c5"); - assertThat(c5.isArray()).isTrue(); - assertThat(c5.getLength()).isEqualTo(1); - assertThat(c5.get(0).getAsString()).isEqualTo("test"); - } - } - - @Test - void toCollection() throws IOException { - final VPackBuilder builder = new VPackBuilder(); - { - builder.add(ValueType.OBJECT); - { - builder.add("c1", ValueType.ARRAY); - builder.add("test1"); - builder.add("test2"); - builder.close(); - } - { - builder.add("c2", ValueType.ARRAY); - builder.add("test1"); - builder.add("test2"); - builder.close(); - } - { - builder.add("c3", ValueType.ARRAY); - builder.add("test1"); - builder.add("test2"); - builder.close(); - } - { - builder.add("c4", ValueType.ARRAY); - builder.add("test1"); - builder.add("test2"); - builder.close(); - } - { - builder.add("c5", ValueType.ARRAY); - builder.add("test1"); - builder.add("test2"); - builder.close(); - } - builder.close(); - } - final VPackSlice vpack = builder.slice(); - final TestEntityCollection entity = mapper.readValue(vpack.getBuffer(), TestEntityCollection.class); - assertThat(entity).isNotNull(); - { - checkCollection(entity.c1); - checkCollection(entity.c2); - checkCollection(entity.c3); - checkCollection(entity.c4); - checkCollection(entity.c5); - } - } - - private void checkCollection(final Collection col) { - assertThat(col).isNotNull(); - assertThat(col).hasSize(2); - for (final String next : col) { - assertThat("test1".equals(next) || "test2".equals(next)).isTrue(); - } - } - - public static class TestEntityCollectionWithObjects { - private Collection c1; - private Set c2; - - public Collection getC1() { - return c1; - } - - public void setC1(final Collection c1) { - this.c1 = c1; - } - - public Set getC2() { - return c2; - } - - public void setC2(final Set c2) { - this.c2 = c2; - } - } - - @Test - void fromCollectionWithObjects() throws JsonProcessingException { - final TestEntityCollectionWithObjects entity = new TestEntityCollectionWithObjects(); - { - final Collection c1 = new ArrayList<>(); - c1.add(new TestEntityString()); - c1.add(new TestEntityString()); - entity.setC1(c1); - final Set c2 = new HashSet<>(); - c2.add(new TestEntityArray()); - entity.setC2(c2); - } - final VPackSlice vpack = new VPackSlice(mapper.writeValueAsBytes(entity)); - assertThat(vpack).isNotNull(); - assertThat(vpack.isObject()).isTrue(); - { - final VPackSlice c1 = vpack.get("c1"); - assertThat(c1.isArray()).isTrue(); - assertThat(c1.getLength()).isEqualTo(2); - assertThat(c1.get(0).isObject()).isTrue(); - assertThat(c1.get(1).isObject()).isTrue(); - { - final VPackSlice s = c1.get(0).get("s"); - assertThat(s.isString()).isTrue(); - assertThat(s.getAsString()).isEqualTo("test"); - } - } - { - final VPackSlice c2 = vpack.get("c2"); - assertThat(c2.isArray()).isTrue(); - assertThat(c2.getLength()).isEqualTo(1); - assertThat(c2.get(0).isObject()).isTrue(); - { - final VPackSlice a2 = c2.get(0).get("a2"); - assertThat(a2.isArray()).isTrue(); - assertThat(a2.getLength()).isEqualTo(5); - for (int i = 0; i < a2.getLength(); i++) { - final VPackSlice at = a2.get(i); - assertThat(at.isInteger()).isTrue(); - assertThat(at.getAsInt()).isEqualTo(i + 1); - } - } - } - } - - @Test - void toCollectionWithObjects() throws IOException { - final VPackBuilder builder = new VPackBuilder(); - { - builder.add(ValueType.OBJECT); - { - builder.add("c1", ValueType.ARRAY); - builder.add(ValueType.OBJECT); - builder.add("s", "abc"); - builder.close(); - builder.close(); - } - { - builder.add("c2", ValueType.ARRAY); - builder.add(ValueType.OBJECT); - builder.add("a2", ValueType.ARRAY); - for (int i = 0; i < 10; i++) { - builder.add(i); - } - builder.close(); - builder.close(); - builder.close(); - } - builder.close(); - } - final VPackSlice vpack = builder.slice(); - final TestEntityCollectionWithObjects entity = mapper.readValue(vpack.getBuffer(), - TestEntityCollectionWithObjects.class); - assertThat(entity).isNotNull(); - { - assertThat(entity.c1).isNotNull(); - assertThat(entity.c1).hasSize(1); - assertThat(entity.c1.iterator().next().s).isEqualTo("abc"); - } - { - assertThat(entity.c2).isNotNull(); - assertThat(entity.c2).hasSize(1); - final int[] array = entity.c2.iterator().next().a2; - for (int i = 0; i < array.length; i++) { - assertThat(array[i]).isEqualTo(i); - } - } - } - - public static class TestEntityMap { - private Map m1; - private HashMap m2; - private Map m3; - - public Map getM1() { - return m1; - } - - public void setM1(final Map m1) { - this.m1 = m1; - } - - public HashMap getM2() { - return m2; - } - - public void setM2(final HashMap m2) { - this.m2 = m2; - } - - public Map getM3() { - return m3; - } - - public void setM3(final Map m3) { - this.m3 = m3; - } - } - - @Test - void fromMap() throws JsonProcessingException { - final TestEntityMap entity = new TestEntityMap(); - { - final Map m1 = new LinkedHashMap<>(); - m1.put("a", "b"); - m1.put("c", "d"); - entity.setM1(m1); - final HashMap m2 = new HashMap<>(); - m2.put(1, "a"); - m2.put(2, "b"); - entity.setM2(m2); - final Map m3 = new HashMap<>(); - final TestEntityString s = new TestEntityString(); - s.setS("abc"); - m3.put("a", s); - entity.setM3(m3); - } - final VPackSlice vpack = new VPackSlice(mapper.writeValueAsBytes(entity)); - assertThat(vpack).isNotNull(); - assertThat(vpack.isObject()).isTrue(); - { - final VPackSlice m1 = vpack.get("m1"); - assertThat(m1.isObject()).isTrue(); - assertThat(m1.getLength()).isEqualTo(2); - { - final VPackSlice a = m1.get("a"); - assertThat(a.isString()).isTrue(); - assertThat(a.getAsString()).isEqualTo("b"); - } - { - final VPackSlice c = m1.get("c"); - assertThat(c.isString()).isTrue(); - assertThat(c.getAsString()).isEqualTo("d"); - } - } - { - final VPackSlice m2 = vpack.get("m2"); - assertThat(m2.isObject()).isTrue(); - assertThat(m2.getLength()).isEqualTo(2); - { - final VPackSlice one = m2.get("1"); - assertThat(one.isString()).isTrue(); - assertThat(one.getAsString()).isEqualTo("a"); - } - { - final VPackSlice two = m2.get("2"); - assertThat(two.isString()).isTrue(); - assertThat(two.getAsString()).isEqualTo("b"); - } - } - { - final VPackSlice m3 = vpack.get("m3"); - assertThat(m3.isObject()).isTrue(); - assertThat(m3.getLength()).isEqualTo(1); - final VPackSlice a = m3.get("a"); - assertThat(a.isObject()).isTrue(); - final VPackSlice s = a.get("s"); - assertThat(s.isString()).isTrue(); - assertThat(s.getAsString()).isEqualTo("abc"); - } - } - - @Test - void toMap() throws IOException { - final VPackBuilder builder = new VPackBuilder(); - { - builder.add(ValueType.OBJECT); - { - builder.add("m1", ValueType.OBJECT); - builder.add("a", "a"); - builder.add("b", "b"); - builder.close(); - } - { - builder.add("m2", ValueType.OBJECT); - builder.add("1", "a"); - builder.add("-1", "a"); - builder.close(); - } - { - builder.add("m3", ValueType.OBJECT); - builder.add("a", ValueType.OBJECT); - builder.add("s", "abc"); - builder.close(); - builder.close(); - } - builder.close(); - } - final VPackSlice vpack = builder.slice(); - final TestEntityMap entity = mapper.readValue(vpack.getBuffer(), TestEntityMap.class); - assertThat(entity).isNotNull(); - { - assertThat(entity.m1).isNotNull(); - assertThat(entity.m1).hasSize(2); - final String a = entity.m1.get("a"); - assertThat(a).isNotNull(); - assertThat(a).isEqualTo("a"); - final String b = entity.m1.get("b"); - assertThat(b).isNotNull(); - assertThat(b).isEqualTo("b"); - } - { - assertThat(entity.m2).isNotNull(); - assertThat(entity.m2).hasSize(2); - final String one = entity.m2.get(1); - assertThat(one).isNotNull(); - assertThat(one).isEqualTo("a"); - final String oneNegative = entity.m2.get(-1); - assertThat(oneNegative).isNotNull(); - assertThat(oneNegative).isEqualTo("a"); - } - { - assertThat(entity.m3).isNotNull(); - assertThat(entity.m3).hasSize(1); - final TestEntityString a = entity.m3.get("a"); - assertThat(a).isNotNull(); - assertThat(a.s).isEqualTo("abc"); - } - } - - public static class TestEntityMapStringableKey { - private Map m1; - private Map m2; - private Map m3; - private Map m4; - private Map m5; - private Map m6; - private Map m7; - private Map m8; - private Map m9; - private Map m10; - private Map m11; - - public Map getM1() { - return m1; - } - - public void setM1(final Map m1) { - this.m1 = m1; - } - - public Map getM2() { - return m2; - } - - public void setM2(final Map m2) { - this.m2 = m2; - } - - public Map getM3() { - return m3; - } - - public void setM3(final Map m3) { - this.m3 = m3; - } - - public Map getM4() { - return m4; - } - - public void setM4(final Map m4) { - this.m4 = m4; - } - - public Map getM5() { - return m5; - } - - public void setM5(final Map m5) { - this.m5 = m5; - } - - public Map getM6() { - return m6; - } - - public void setM6(final Map m6) { - this.m6 = m6; - } - - public Map getM7() { - return m7; - } - - public void setM7(final Map m7) { - this.m7 = m7; - } - - public Map getM8() { - return m8; - } - - public void setM8(final Map m8) { - this.m8 = m8; - } - - public Map getM9() { - return m9; - } - - public void setM9(final Map m9) { - this.m9 = m9; - } - - public Map getM10() { - return m10; - } - - public void setM10(final Map m10) { - this.m10 = m10; - } - - public Map getM11() { - return m11; - } - - public void setM11(final Map m11) { - this.m11 = m11; - } - - } - - @Test - void fromMapStringableKey() throws JsonProcessingException { - final TestEntityMapStringableKey entity = new TestEntityMapStringableKey(); - final String value = "test"; - { - final Map m1 = new HashMap<>(); - m1.put(true, value); - m1.put(false, value); - entity.setM1(m1); - } - { - final Map m2 = new HashMap<>(); - m2.put(1, value); - m2.put(2, value); - entity.setM2(m2); - } - { - final Map m3 = new HashMap<>(); - m3.put(1L, value); - m3.put(2L, value); - entity.setM3(m3); - } - { - final Map m4 = new HashMap<>(); - m4.put(1.5F, value); - m4.put(2.25F, value); - entity.setM4(m4); - } - { - final Map m5 = new HashMap<>(); - m5.put(Short.valueOf("1"), value); - m5.put(Short.valueOf("2"), value); - entity.setM5(m5); - } - { - final Map m6 = new HashMap<>(); - m6.put(1.5, value); - m6.put(2.25, value); - entity.setM6(m6); - } - { - final Map m7 = new HashMap<>(); - m7.put(1.5, value); - m7.put(1L, value); - entity.setM7(m7); - } - { - final Map m8 = new HashMap<>(); - m8.put(new BigInteger("1"), value); - m8.put(new BigInteger("2"), value); - entity.setM8(m8); - } - { - final Map m9 = new HashMap<>(); - m9.put(new BigDecimal("1.5"), value); - m9.put(new BigDecimal("2.25"), value); - entity.setM9(m9); - } - { - final Map m10 = new HashMap<>(); - m10.put('1', value); - m10.put('a', value); - entity.setM10(m10); - } - { - final Map m11 = new HashMap<>(); - m11.put(TestEnum.A, value); - m11.put(TestEnum.B, value); - entity.setM11(m11); - } - final VPackSlice vpack = new VPackSlice(mapper.writeValueAsBytes(entity)); - assertThat(vpack).isNotNull(); - assertThat(vpack.isObject()).isTrue(); - { - final VPackSlice m1 = vpack.get("m1"); - assertThat(m1.isObject()).isTrue(); - assertThat(m1.getLength()).isEqualTo(2); - checkMapAttribute(m1.get("true")); - checkMapAttribute(m1.get("false")); - } - { - final VPackSlice m2 = vpack.get("m2"); - assertThat(m2.isObject()).isTrue(); - assertThat(m2.getLength()).isEqualTo(2); - checkMapAttribute(m2.get("1")); - checkMapAttribute(m2.get("2")); - } - { - final VPackSlice m3 = vpack.get("m3"); - assertThat(m3.isObject()).isTrue(); - assertThat(m3.getLength()).isEqualTo(2); - checkMapAttribute(m3.get("1")); - checkMapAttribute(m3.get("2")); - } - { - final VPackSlice m4 = vpack.get("m4"); - assertThat(m4.isObject()).isTrue(); - assertThat(m4.getLength()).isEqualTo(2); - checkMapAttribute(m4.get("1.5")); - checkMapAttribute(m4.get("2.25")); - } - { - final VPackSlice m5 = vpack.get("m5"); - assertThat(m5.isObject()).isTrue(); - assertThat(m5.getLength()).isEqualTo(2); - checkMapAttribute(m5.get("1")); - checkMapAttribute(m5.get("2")); - } - { - final VPackSlice m6 = vpack.get("m6"); - assertThat(m6.isObject()).isTrue(); - assertThat(m6.getLength()).isEqualTo(2); - checkMapAttribute(m6.get("1.5")); - checkMapAttribute(m6.get("2.25")); - } - { - final VPackSlice m7 = vpack.get("m7"); - assertThat(m7.isObject()).isTrue(); - assertThat(m7.getLength()).isEqualTo(2); - checkMapAttribute(m7.get("1.5")); - checkMapAttribute(m7.get("1")); - } - { - final VPackSlice m8 = vpack.get("m8"); - assertThat(m8.isObject()).isTrue(); - assertThat(m8.getLength()).isEqualTo(2); - checkMapAttribute(m8.get("1")); - checkMapAttribute(m8.get("2")); - } - { - final VPackSlice m9 = vpack.get("m9"); - assertThat(m9.isObject()).isTrue(); - assertThat(m9.getLength()).isEqualTo(2); - checkMapAttribute(m9.get("1.5")); - checkMapAttribute(m9.get("2.25")); - } - { - final VPackSlice m10 = vpack.get("m10"); - assertThat(m10.isObject()).isTrue(); - assertThat(m10.getLength()).isEqualTo(2); - checkMapAttribute(m10.get("1")); - checkMapAttribute(m10.get("a")); - } - { - final VPackSlice m11 = vpack.get("m11"); - assertThat(m11.isObject()).isTrue(); - assertThat(m11.getLength()).isEqualTo(2); - checkMapAttribute(m11.get(TestEnum.A.name())); - checkMapAttribute(m11.get(TestEnum.B.name())); - } - } - - @Test - void toMapSringableKey() { - final VPackBuilder builder = new VPackBuilder(); - builder.add(ValueType.OBJECT); - { - builder.add("m1", ValueType.OBJECT); - builder.add("true", "test"); - builder.add("false", "test"); - builder.close(); - } - { - builder.add("m2", ValueType.OBJECT); - builder.add("1", "test"); - builder.add("2", "test"); - builder.close(); - } - { - builder.add("m3", ValueType.OBJECT); - builder.add("1", "test"); - builder.add("2", "test"); - builder.close(); - } - { - builder.add("m4", ValueType.OBJECT); - builder.add("1.5", "test"); - builder.add("2.25", "test"); - builder.close(); - } - { - builder.add("m5", ValueType.OBJECT); - builder.add("1", "test"); - builder.add("2", "test"); - builder.close(); - } - { - builder.add("m6", ValueType.OBJECT); - builder.add("1.5", "test"); - builder.add("2.25", "test"); - builder.close(); - } - { - builder.add("m7", ValueType.OBJECT); - builder.add("1.5", "test"); - builder.add("1", "test"); - builder.close(); - } - { - builder.add("m8", ValueType.OBJECT); - builder.add("1", "test"); - builder.add("2", "test"); - builder.close(); - } - { - builder.add("m9", ValueType.OBJECT); - builder.add("1.5", "test"); - builder.add("2.25", "test"); - builder.close(); - } - { - builder.add("m10", ValueType.OBJECT); - builder.add("1", "test"); - builder.add("a", "test"); - builder.close(); - } - { - builder.add("m11", ValueType.OBJECT); - builder.add(TestEnum.A.name(), "test"); - builder.add(TestEnum.B.name(), "test"); - builder.close(); - } - builder.close(); - final TestEntityMapStringableKey entity = new VPack.Builder().build().deserialize(builder.slice(), - TestEntityMapStringableKey.class); - { - assertThat(entity.m1).hasSize(2); - checkMapAttribute(entity.m1.get(true)); - checkMapAttribute(entity.m1.get(false)); - } - { - assertThat(entity.m2).hasSize(2); - checkMapAttribute(entity.m2.get(1)); - checkMapAttribute(entity.m2.get(2)); - } - { - assertThat(entity.m3).hasSize(2); - checkMapAttribute(entity.m3.get(1L)); - checkMapAttribute(entity.m3.get(2L)); - } - { - assertThat(entity.m4).hasSize(2); - checkMapAttribute(entity.m4.get(1.5F)); - checkMapAttribute(entity.m4.get(2.25F)); - } - { - assertThat(entity.m5).hasSize(2); - checkMapAttribute(entity.m5.get(Short.valueOf("1"))); - checkMapAttribute(entity.m5.get(Short.valueOf("2"))); - } - { - assertThat(entity.m6).hasSize(2); - checkMapAttribute(entity.m6.get(1.5)); - checkMapAttribute(entity.m6.get(2.25)); - } - { - assertThat(entity.m7).hasSize(2); - checkMapAttribute(entity.m7.get(1.5)); - checkMapAttribute(entity.m7.get((double) 1L)); - } - { - assertThat(entity.m8).hasSize(2); - checkMapAttribute(entity.m8.get(new BigInteger("1"))); - checkMapAttribute(entity.m8.get(new BigInteger("2"))); - } - { - assertThat(entity.m9).hasSize(2); - checkMapAttribute(entity.m9.get(new BigDecimal("1.5"))); - checkMapAttribute(entity.m9.get(new BigDecimal("2.25"))); - } - { - assertThat(entity.m10).hasSize(2); - checkMapAttribute(entity.m10.get('1')); - checkMapAttribute(entity.m10.get('a')); - } - { - assertThat(entity.m11).hasSize(2); - checkMapAttribute(entity.m11.get(TestEnum.A)); - checkMapAttribute(entity.m11.get(TestEnum.B)); - } - } - - private void checkMapAttribute(final VPackSlice attr) { - assertThat(attr.isString()).isTrue(); - assertThat(attr.getAsString()).isEqualTo("test"); - } - - private void checkMapAttribute(final String attr) { - assertThat(attr).isEqualTo("test"); - } - - public static class TestEntityMapWithObjectKey { - private Map m1; - private Map m2; - - public Map getM1() { - return m1; - } - - public void setM1(final Map m1) { - this.m1 = m1; - } - - public Map getM2() { - return m2; - } - - public void setM2(final Map m2) { - this.m2 = m2; - } - } - - @Test - void toMapWithObjectKey() { - final int size = 2; - final VPackBuilder builder = new VPackBuilder(); - builder.add(ValueType.OBJECT); - { - builder.add("m1", ValueType.ARRAY); - for (int i = 0; i < size; i++) { - builder.add(ValueType.OBJECT); - { - builder.add("key", ValueType.OBJECT); - builder.add("l1", 5L); - builder.close(); - } - { - builder.add("value", ValueType.OBJECT); - builder.add("c1", ValueType.ARRAY); - builder.add("test"); - builder.close(); - builder.close(); - } - builder.close(); - } - builder.close(); - } - { - builder.add("m2", ValueType.ARRAY); - for (int i = 0; i < size; i++) { - builder.add(ValueType.OBJECT); - { - builder.add("key", ValueType.OBJECT); - builder.add("l1", 5L); - builder.close(); - } - { - builder.add("value", "test"); - } - builder.close(); - } - builder.close(); - } - builder.close(); - final TestEntityMapWithObjectKey entity = new VPack.Builder().build().deserialize(builder.slice(), - TestEntityMapWithObjectKey.class); - assertThat(entity).isNotNull(); - { - assertThat(entity.m1).isNotNull(); - assertThat(entity.m1).hasSize(size); - for (final Entry entry : entity.m1.entrySet()) { - assertThat(entry.getKey().l1).isEqualTo(5L); - assertThat(entry.getValue().c1).hasSize(1); - assertThat(entry.getValue().c1.iterator().next()).isEqualTo("test"); - } - } - { - assertThat(entity.m2).isNotNull(); - assertThat(entity.m2).hasSize(2); - for (final Entry entry : entity.m2.entrySet()) { - assertThat(entry.getKey().l1).isEqualTo(5L); - assertThat(entry.getValue()).isEqualTo("test"); - } - } - } - - public static class TestEntityEmpty { - - } - - @Test - void fromEmptyObject() throws JsonProcessingException { - final VPackSlice vpack = new VPackSlice(mapper.writeValueAsBytes(new TestEntityEmpty())); - assertThat(vpack).isNotNull(); - assertThat(vpack.isObject()).isTrue(); - assertThat(vpack.getLength()).isZero(); - } - - @Test - void toEmptyObject() { - final VPackBuilder builder = new VPackBuilder(); - builder.add(ValueType.OBJECT); - builder.close(); - final TestEntityEmpty entity = new VPack.Builder().build().deserialize(builder.slice(), TestEntityEmpty.class); - assertThat(entity).isNotNull(); - } - - public static class TestEntityEmptyMap { - private Map m; - - public Map getM() { - return m; - } - - public void setM(final Map m) { - this.m = m; - } - } - - @Test - void fromEmptyMap() throws JsonProcessingException { - final TestEntityEmptyMap entity = new TestEntityEmptyMap(); - entity.setM(new HashMap<>()); - final VPackSlice vpack = new VPackSlice(mapper.writeValueAsBytes(entity)); - assertThat(vpack).isNotNull(); - assertThat(vpack.isObject()).isTrue(); - assertThat(vpack.getLength()).isEqualTo(1); - final VPackSlice m = vpack.get("m"); - assertThat(m.isObject()).isTrue(); - assertThat(m.getLength()).isZero(); - } - - @Test - void toEmptyMap() { - final VPackBuilder builder = new VPackBuilder(); - builder.add(ValueType.OBJECT); - builder.add("m", ValueType.OBJECT); - builder.close(); - builder.close(); - final TestEntityEmptyMap entity = new VPack.Builder().build().deserialize(builder.slice(), - TestEntityEmptyMap.class); - assertThat(entity).isNotNull(); - assertThat(entity.m).isNotNull(); - assertThat(entity.m).isEmpty(); - } - - public static class TestEntityBaseAttributes { - private String _key = "test1"; - private String _rev = "test2"; - private String _id = "test3"; - private String _from = "test4"; - private String _to = "test5"; - - public String get_key() { - return _key; - } - - public void set_key(final String _key) { - this._key = _key; - } - - public String get_rev() { - return _rev; - } - - public void set_rev(final String _rev) { - this._rev = _rev; - } - - public String get_id() { - return _id; - } - - public void set_id(final String _id) { - this._id = _id; - } - - public String get_from() { - return _from; - } - - public void set_from(final String _from) { - this._from = _from; - } - - public String get_to() { - return _to; - } - - public void set_to(final String _to) { - this._to = _to; - } - - } - - @Test - void fromObjectWithAttributeAdapter() throws JsonProcessingException { - final VPackSlice vpack = new VPackSlice(mapper.writeValueAsBytes(new TestEntityBaseAttributes())); - assertThat(vpack.isObject()).isTrue(); - assertThat(vpack.getLength()).isEqualTo(5); - { - final VPackSlice key = vpack.get("_key"); - assertThat(key.isString()).isTrue(); - assertThat(key.getAsString()).isEqualTo("test1"); - } - { - final VPackSlice rev = vpack.get("_rev"); - assertThat(rev.isString()).isTrue(); - assertThat(rev.getAsString()).isEqualTo("test2"); - } - { - final VPackSlice id = vpack.get("_id"); - assertThat(id.isString()).isTrue(); - assertThat(id.getAsString()).isEqualTo("test3"); - } - { - final VPackSlice from = vpack.get("_from"); - assertThat(from.isString()).isTrue(); - assertThat(from.getAsString()).isEqualTo("test4"); - } - { - final VPackSlice to = vpack.get("_to"); - assertThat(to.isString()).isTrue(); - assertThat(to.getAsString()).isEqualTo("test5"); - } - } - - @Test - void toObjectWithAttributeAdapter() { - final VPackBuilder builder = new VPackBuilder(); - { - builder.add(ValueType.OBJECT); - builder.add("_key", "a"); - builder.add("_rev", "b"); - builder.add("_id", "c"); - builder.add("_from", "d"); - builder.add("_to", "e"); - builder.close(); - } - final TestEntityBaseAttributes entity = new VPack.Builder().build().deserialize(builder.slice(), - TestEntityBaseAttributes.class); - assertThat(entity).isNotNull(); - assertThat(entity._key).isEqualTo("a"); - assertThat(entity._rev).isEqualTo("b"); - assertThat(entity._id).isEqualTo("c"); - assertThat(entity._from).isEqualTo("d"); - assertThat(entity._to).isEqualTo("e"); - } - - @Test - void fromMapWithAttributeAdapter() throws JsonProcessingException { - final TestEntityMap entity = new TestEntityMap(); - { - final Map m1 = new HashMap<>(); - m1.put("_key", "test1"); - m1.put("_rev", "test2"); - m1.put("_id", "test3"); - m1.put("_from", "test4"); - m1.put("_to", "test5"); - entity.setM1(m1); - } - final VPackSlice vpack = new VPackSlice(mapper.writeValueAsBytes(entity)); - assertThat(vpack.isObject()).isTrue(); - final VPackSlice m1 = vpack.get("m1"); - assertThat(m1.isObject()).isTrue(); - assertThat(m1.getLength()).isEqualTo(5); - { - final VPackSlice key = m1.get("_key"); - assertThat(key.isString()).isTrue(); - assertThat(key.getAsString()).isEqualTo("test1"); - } - { - final VPackSlice rev = m1.get("_rev"); - assertThat(rev.isString()).isTrue(); - assertThat(rev.getAsString()).isEqualTo("test2"); - } - { - final VPackSlice id = m1.get("_id"); - assertThat(id.isString()).isTrue(); - assertThat(id.getAsString()).isEqualTo("test3"); - } - { - final VPackSlice from = m1.get("_from"); - assertThat(from.isString()).isTrue(); - assertThat(from.getAsString()).isEqualTo("test4"); - } - { - final VPackSlice to = m1.get("_to"); - assertThat(to.isString()).isTrue(); - assertThat(to.getAsString()).isEqualTo("test5"); - } - } - - @Test - void toMapWithAttributeAdapter() { - final VPackBuilder builder = new VPackBuilder(); - { - builder.add(ValueType.OBJECT); - builder.add("m1", ValueType.OBJECT); - builder.add("_key", "a"); - builder.add("_rev", "b"); - builder.add("_id", "c"); - builder.add("_from", "d"); - builder.add("_to", "e"); - builder.close(); - builder.close(); - } - final TestEntityMap entity = new VPack.Builder().build().deserialize(builder.slice(), TestEntityMap.class); - assertThat(entity).isNotNull(); - assertThat(entity.m1).hasSize(5); - } - - @Retention(RetentionPolicy.RUNTIME) - @Target(ElementType.FIELD) - private @interface CustomFilterAnnotation { - boolean serialize() - - default true; - - boolean deserialize() default true; - } - - @Retention(RetentionPolicy.RUNTIME) - @Target(ElementType.FIELD) - private @interface CustomNamingAnnotation { - String name(); - } - - private static class CustomAnEntity { - @CustomFilterAnnotation(serialize = false) - private String a = null; - @CustomFilterAnnotation(deserialize = false) - private String b = null; - @CustomNamingAnnotation(name = "d") - @CustomFilterAnnotation(deserialize = false) - private String c = null; - - CustomAnEntity() { - super(); - } - } - - @Test - void fromCutsomAnnotation() { - final CustomAnEntity entity = new CustomAnEntity(); - entity.a = "1"; - entity.b = "2"; - entity.c = "3"; - final VPackSlice vpack = new VPack.Builder().annotationFieldFilter(CustomFilterAnnotation.class, - new VPackAnnotationFieldFilter() { - - @Override - public boolean serialize(final CustomFilterAnnotation annotation) { - return annotation.serialize(); - } - - @Override - public boolean deserialize(final CustomFilterAnnotation annotation) { - return annotation.deserialize(); - } - }).annotationFieldNaming(CustomNamingAnnotation.class, - CustomNamingAnnotation::name).build().serialize(entity); - assertThat(vpack).isNotNull(); - assertThat(vpack.isObject()).isTrue(); - assertThat(vpack.get("a").isNone()).isTrue(); - assertThat(vpack.get("b").isString()).isTrue(); - assertThat(vpack.get("b").getAsString()).isEqualTo("2"); - assertThat(vpack.get("c").isNone()).isTrue(); - assertThat(vpack.get("d").isString()).isTrue(); - assertThat(vpack.get("d").getAsString()).isEqualTo("3"); - } - - @Test - void directFromCollection() throws JsonProcessingException { - final Collection list = new ArrayList<>(); - list.add("test"); - final VPackSlice vpack = new VPackSlice(mapper.writeValueAsBytes(list)); - assertThat(vpack).isNotNull(); - assertThat(vpack.isArray()).isTrue(); - assertThat(vpack.size()).isEqualTo(1); - final VPackSlice test = vpack.get(0); - assertThat(test.isString()).isTrue(); - assertThat(test.getAsString()).isEqualTo("test"); - } - - @Test - void directFromCollectionWithType() throws JsonProcessingException { - final Collection list = new ArrayList<>(); - list.add(new TestEntityString()); - list.add(new TestEntityString()); - - final VPackSlice vpack = new VPackSlice(mapper.writeValueAsBytes(list)); - assertThat(vpack).isNotNull(); - assertThat(vpack.isArray()).isTrue(); - assertThat(vpack.getLength()).isEqualTo(list.size()); - for (int i = 0; i < list.size(); i++) { - final VPackSlice entry = vpack.get(i); - assertThat(entry.isObject()).isTrue(); - assertThat(entry.getLength()).isEqualTo(3); - final VPackSlice s = entry.get("s"); - assertThat(s.isString()).isTrue(); - assertThat(s.getAsString()).isEqualTo("test"); - } - } - - @Test - void directToCollection() { - final VPackBuilder builder = new VPackBuilder(); - builder.add(ValueType.ARRAY); - builder.add(ValueType.OBJECT); - builder.add("s", "abc"); - builder.close(); - builder.close(); - final List list = new VPack.Builder().build().deserialize(builder.slice(), - new Type>() { - }.getType()); - assertThat(list).hasSize(1); - final TestEntityString entry = list.get(0); - assertThat(entry.s).isEqualTo("abc"); - } - - @Test - void directFromStringMap() throws JsonProcessingException { - final Map map = new HashMap<>(); - map.put("a", new TestEntityString()); - map.put("b", new TestEntityString()); - - final VPackSlice vpack = new VPackSlice(mapper.writeValueAsBytes(map)); - assertThat(vpack).isNotNull(); - assertThat(vpack.isObject()).isTrue(); - assertThat(vpack.getLength()).isEqualTo(2); - final VPackSlice a = vpack.get("a"); - checkStringEntity(a); - } - - @Test - void directToStringMap() { - final VPackBuilder builder = new VPackBuilder(); - builder.add(ValueType.OBJECT); - builder.add("a", ValueType.OBJECT); - builder.add("s", "abc"); - builder.close(); - builder.close(); - final Map map = new VPack.Builder().build().deserialize(builder.slice(), - new Type>() { - }.getType()); - assertThat(map).hasSize(1); - final TestEntityString a = map.get("a"); - assertThat(a).isNotNull(); - assertThat(a.s).isEqualTo("abc"); - } - - @Test - void directFromMap() throws JsonProcessingException { - final Map map = new HashMap<>(); - final TestEntityA entity = new TestEntityA(); - entity.a = "test"; - map.put("test", entity); - final VPackSlice vpack = new VPackSlice(mapper.writeValueAsBytes(map)); - assertThat(vpack).isNotNull(); - assertThat(vpack.isObject()).isTrue(); - final VPackSlice test = vpack.get("test"); - assertThat(test.isObject()).isTrue(); - final VPackSlice a = test.get("a"); - assertThat(a.isString()).isTrue(); - assertThat(a.getAsString()).isEqualTo("test"); - } - - @Test - void directFromMapWithinMap() throws JsonProcessingException { - final Map map = new HashMap<>(); - final Map map2 = new HashMap<>(); - map2.put("b", "test"); - map.put("a", map2); - final VPackSlice vpack = new VPackSlice(mapper.writeValueAsBytes(map)); - assertThat(vpack).isNotNull(); - assertThat(vpack.isObject()).isTrue(); - assertThat(vpack.size()).isEqualTo(1); - final VPackSlice a = vpack.get("a"); - assertThat(a.isObject()).isTrue(); - assertThat(a.size()).isEqualTo(1); - final VPackSlice b = a.get("b"); - assertThat(b.isString()).isTrue(); - assertThat(b.getAsString()).isEqualTo("test"); - } - - private void checkStringEntity(final VPackSlice vpack) { - final TestEntityString expected = new TestEntityString(); - assertThat(vpack.isObject()).isTrue(); - assertThat(vpack.getLength()).isEqualTo(3); - final VPackSlice s = vpack.get("s"); - assertThat(s.isString()).isTrue(); - assertThat(s.getAsString()).isEqualTo(expected.s); - final VPackSlice c1 = vpack.get("c1"); - assertThat(c1.isString()).isTrue(); - assertThat(new Character(c1.getAsChar())).isEqualTo(expected.c1); - final VPackSlice c2 = vpack.get("c2"); - assertThat(c2.isString()).isTrue(); - assertThat(c2.getAsChar()).isEqualTo(expected.c2); - } - - @Test - void directToObjectMap() { - final VPackBuilder builder = new VPackBuilder(); - builder.add(ValueType.ARRAY); - builder.add(ValueType.OBJECT); - builder.add("key", ValueType.OBJECT); - builder.add("s", "abc"); - builder.close(); - builder.add("value", ValueType.OBJECT); - builder.add("s", "abc"); - builder.close(); - builder.close(); - builder.close(); - final Map map = new VPack.Builder().build().deserialize(builder.slice(), - new Type>() { - }.getType()); - assertThat(map).hasSize(1); - for (final Entry entry : map.entrySet()) { - assertThat(entry.getKey().s).isEqualTo("abc"); - assertThat(entry.getValue().s).isEqualTo("abc"); - } - } - - @SuppressWarnings("unchecked") - @Test - void directToMapWithinMap() { - final VPackBuilder builder = new VPackBuilder(); - builder.add(ValueType.OBJECT); - builder.add("a", ValueType.OBJECT); - builder.add("b", "test"); - builder.add("c", true); - builder.add("d", 1L); - builder.add("e", 1.5); - final Date date = new Date(); - builder.add("f", date); - builder.add("g", ValueType.ARRAY); - builder.close(); - builder.close(); - builder.close(); - final Map map = new VPack.Builder().build().deserialize(builder.slice(), Map.class); - assertThat(map).hasSize(1); - final Object a = map.get("a"); - assertThat(Map.class.isAssignableFrom(a.getClass())).isTrue(); - final Map mapA = (Map) a; - assertThat(mapA).hasSize(6); - final Object b = mapA.get("b"); - assertThat(String.class.isAssignableFrom(b.getClass())).isTrue(); - assertThat(b).hasToString("test"); - final Object c = mapA.get("c"); - assertThat(Boolean.class.isAssignableFrom(c.getClass())).isTrue(); - assertThat((Boolean) c).isTrue(); - final Object d = mapA.get("d"); - assertThat(Number.class.isAssignableFrom(d.getClass())).isTrue(); - assertThat(((Number) d).longValue()).isEqualTo(1L); - final Object e = mapA.get("e"); - assertThat(Double.class.isAssignableFrom(e.getClass())).isTrue(); - assertThat((Double) e).isEqualTo(1.5); - final Object f = mapA.get("f"); - assertThat(Date.class.isAssignableFrom(f.getClass())).isTrue(); - assertThat((Date) f).isEqualTo(date); - final Object g = mapA.get("g"); - assertThat(Collection.class.isAssignableFrom(g.getClass())).isTrue(); - assertThat(List.class.isAssignableFrom(g.getClass())).isTrue(); - } - - @Test - void dontSerializeNullValues() { - final VPack serializer = new VPack.Builder().serializeNullValues(false).build(); - final TestEntityString entity = new TestEntityString(); - entity.setS(null); - final VPackSlice vpack = serializer.serialize(entity); - assertThat(vpack).isNotNull(); - assertThat(vpack.isObject()).isTrue(); - final VPackSlice s = vpack.get("s"); - assertThat(s.isNone()).isTrue(); - } - - @Test - void serializeNullValue() { - final VPack serializer = new VPack.Builder().serializeNullValues(true).build(); - final TestEntityString entity = new TestEntityString(); - entity.setS(null); - final VPackSlice vpack = serializer.serialize(entity); - assertThat(vpack).isNotNull(); - final VPackSlice s = vpack.get("s"); - assertThat(s.isNull()).isTrue(); - } - - @Test - void toNullValue() { - final VPackBuilder builder = new VPackBuilder(); - builder.add(ValueType.OBJECT); - builder.add("s", ValueType.NULL); - builder.close(); - final TestEntityString entity = new VPack.Builder().build().deserialize(builder.slice(), - TestEntityString.class); - assertThat(entity).isNotNull(); - assertThat(entity.s).isNull(); - assertThat(entity.c1).isNotNull(); - assertThat(entity.c2).isNotNull(); - } - - @Test - void toSimpleString() { - final VPackBuilder builder = new VPackBuilder(); - builder.add("test"); - final String s = new VPack.Builder().build().deserialize(builder.slice(), String.class); - assertThat(s).isEqualTo("test"); - } - - @Test - void fromSimpleString() throws JsonProcessingException { - final VPackSlice vpack = new VPackSlice(mapper.writeValueAsBytes("test")); - assertThat(vpack).isNotNull(); - assertThat(vpack.isString()).isTrue(); - assertThat(vpack.getAsString()).isEqualTo("test"); - } - - public static class TestEntityTyped { - private T e; - } - - @Test - void fromStringTypedEntity() throws JsonProcessingException { - final TestEntityTyped entity = new TestEntityTyped<>(); - entity.e = "test"; - final VPackSlice vpack = new VPackSlice(mapper.writeValueAsBytes(entity)); - assertThat(vpack).isNotNull(); - assertThat(vpack.isObject()).isTrue(); - final VPackSlice e = vpack.get("e"); - assertThat(e).isNotNull(); - assertThat(e.isString()).isTrue(); - assertThat(e.getAsString()).isEqualTo("test"); - } - - @Test - void fromObjectTypedEntity() throws JsonProcessingException { - final TestEntityTyped entity = new TestEntityTyped<>(); - entity.e = new TestEntityString(); - entity.e.s = "test2"; - final VPackSlice vpack = new VPackSlice(mapper.writeValueAsBytes(entity)); - assertThat(vpack).isNotNull(); - assertThat(vpack.isObject()).isTrue(); - final VPackSlice e = vpack.get("e"); - assertThat(e).isNotNull(); - assertThat(e.isObject()).isTrue(); - final VPackSlice s = e.get("s"); - assertThat(s).isNotNull(); - assertThat(s.isString()).isTrue(); - assertThat(s.getAsString()).isEqualTo("test2"); - } - - @Test - void fromTypedTypedEntity() throws JsonProcessingException { - final TestEntityTyped> entity = new TestEntityTyped<>(); - entity.e = new TestEntityTyped<>(); - entity.e.e = "test"; - final VPackSlice vpack = new VPackSlice(mapper.writeValueAsBytes(entity)); - assertThat(vpack).isNotNull(); - assertThat(vpack.isObject()).isTrue(); - final VPackSlice e = vpack.get("e"); - assertThat(e).isNotNull(); - assertThat(e.isObject()).isTrue(); - final VPackSlice e2 = e.get("e"); - assertThat(e2).isNotNull(); - assertThat(e2.isString()).isTrue(); - assertThat(e2.getAsString()).isEqualTo("test"); - } - - @Test - void fieldNamingStrategySerialize() { - final VPackSlice vpack = new VPack.Builder().fieldNamingStrategy(field -> "bla").build().serialize(new TestEntityA()); - assertThat(vpack).isNotNull(); - assertThat(vpack.isObject()).isTrue(); - final VPackSlice bla = vpack.get("bla"); - assertThat(bla.isString()).isTrue(); - assertThat(bla.getAsString()).isEqualTo("a"); - } - - @Test - void fieldNamingStrategyDeserialize() { - final VPackBuilder builder = new VPackBuilder(); - builder.add(ValueType.OBJECT); - builder.add("bla", "test"); - builder.close(); - final TestEntityA entity = new VPack.Builder().fieldNamingStrategy(field -> "bla").build().deserialize(builder.slice(), TestEntityA.class); - assertThat(entity).isNotNull(); - assertThat(entity.a).isEqualTo("test"); - } - - @Test - void serializeVPack() throws JsonProcessingException { - final VPackBuilder builder = new VPackBuilder(); - builder.add("test"); - final VPackSlice slice = builder.slice(); - final VPackSlice vpack = new VPackSlice(mapper.writeValueAsBytes(slice)); - assertThat(vpack).isNotNull(); - assertThat(vpack.isString()).isTrue(); - assertThat(vpack.getAsString()).isEqualTo("test"); - } - - @Test - void deserializeVPack() { - final VPackBuilder builder = new VPackBuilder(); - builder.add("test"); - final VPackSlice slice = builder.slice(); - final VPackSlice vpack = new VPack.Builder().build().deserialize(slice, slice.getClass()); - assertThat(vpack).isNotNull(); - assertThat(vpack.isString()).isTrue(); - assertThat(vpack.getAsString()).isEqualTo("test"); - } - - public static class TestEntityDate { - private java.util.Date utilDate = new Date(1474988621); - private java.sql.Date sqlDate = new java.sql.Date(1474988621); - private java.sql.Timestamp timestamp = new java.sql.Timestamp(1474988621); - - public java.util.Date getUtilDate() { - return utilDate; - } - - public void setUtilDate(final java.util.Date utilDate) { - this.utilDate = utilDate; - } - - public java.sql.Date getSqlDate() { - return sqlDate; - } - - public void setSqlDate(final java.sql.Date sqlDate) { - this.sqlDate = sqlDate; - } - - public java.sql.Timestamp getTimestamp() { - return timestamp; - } - - public void setTimestamp(final java.sql.Timestamp timestamp) { - this.timestamp = timestamp; - } - - } - - @Test - void fromDate() throws JsonProcessingException { - final VPackSlice vpack = new VPackSlice(mapper.writeValueAsBytes(new TestEntityDate())); - assertThat(vpack).isNotNull(); - assertThat(vpack.isObject()).isTrue(); - { - assertThat(vpack.get("utilDate").isString()).isTrue(); - assertThat(vpack.get("utilDate").getAsString()).isEqualTo(DATE_FORMAT.format(new Date(1474988621))); - } - { - assertThat(vpack.get("sqlDate").isString()).isTrue(); - assertThat(vpack.get("sqlDate").getAsString()).isEqualTo(DATE_FORMAT.format(new java.sql.Date(1474988621))); - } - { - assertThat(vpack.get("timestamp").isString()).isTrue(); - assertThat(vpack.get("timestamp").getAsString()).isEqualTo(DATE_FORMAT.format(new java.sql.Timestamp(1474988621))); - } - } - - @Test - void toDate() { - final VPackBuilder builder = new VPackBuilder(); - builder.add(ValueType.OBJECT); - builder.add("utilDate", new Date(1475062216)); - builder.add("sqlDate", new java.sql.Date(1475062216)); - builder.add("timestamp", new java.sql.Timestamp(1475062216)); - builder.close(); - - final TestEntityDate entity = new VPack.Builder().build().deserialize(builder.slice(), TestEntityDate.class); - assertThat(entity).isNotNull(); - assertThat(entity.utilDate).isEqualTo(new Date(1475062216)); - assertThat(entity.sqlDate).isEqualTo(new java.sql.Date(1475062216)); - assertThat(entity.timestamp).isEqualTo(new java.sql.Timestamp(1475062216)); - } - - @Test - void toDateFromString() { - final VPackBuilder builder = new VPackBuilder(); - builder.add(ValueType.OBJECT); - builder.add("utilDate", DATE_FORMAT.format(new Date(1475062216))); - builder.add("sqlDate", DATE_FORMAT.format(new java.sql.Date(1475062216))); - builder.add("timestamp", DATE_FORMAT.format(new java.sql.Timestamp(1475062216))); - builder.close(); - - final TestEntityDate entity = new VPack.Builder().build().deserialize(builder.slice(), TestEntityDate.class); - assertThat(entity).isNotNull(); - assertThat(entity.utilDate).isEqualTo(new Date(1475062216)); - assertThat(entity.sqlDate).isEqualTo(new java.sql.Date(1475062216)); - assertThat(entity.timestamp).isEqualTo(new java.sql.Timestamp(1475062216)); - } - - public static class TestEntityUUID { - private UUID uuid; - - UUID getUuid() { - return uuid; - } - - void setUuid(final UUID uuid) { - this.uuid = uuid; - } - } - - @Test - void fromUUID() throws IOException { - final TestEntityUUID entity = new TestEntityUUID(); - entity.setUuid(UUID.randomUUID()); - byte[] bytes = mapper.writeValueAsBytes(entity); - final VPackSlice vpack = new VPackSlice(bytes); - assertThat(vpack).isNotNull(); - assertThat(vpack.isObject()).isTrue(); - - final VPackSlice uuid = vpack.get("uuid"); - assertThat(uuid.isString()).isTrue(); - assertThat(uuid.getAsString()).isEqualTo(entity.getUuid().toString()); - assertThat(mapper.readValue(bytes, TestEntityUUID.class).getUuid()).isEqualTo(entity.getUuid()); - } - - @Test - void toUUID() { - final UUID uuid = UUID.randomUUID(); - final VPackBuilder builder = new VPackBuilder(); - builder.add(ValueType.OBJECT); - builder.add("uuid", uuid.toString()); - builder.close(); - - final TestEntityUUID entity = new VPack.Builder().build().deserialize(builder.slice(), TestEntityUUID.class); - assertThat(entity).isNotNull(); - assertThat(entity.uuid).isEqualTo(uuid); - } - - @Test - void uuid() { - final TestEntityUUID entity = new TestEntityUUID(); - entity.setUuid(UUID.randomUUID()); - final VPack vpacker = new VPack.Builder().build(); - final VPackSlice vpack = vpacker.serialize(entity); - final TestEntityUUID entity2 = vpacker.deserialize(vpack, TestEntityUUID.class); - assertThat(entity2).isNotNull(); - assertThat(entity2.getUuid()).isEqualTo(entity.getUuid()); - } - - private static class BinaryEntity { - private byte[] foo; - - BinaryEntity() { - super(); - } - } - - @Test - void fromBinary() throws JsonProcessingException { - final BinaryEntity entity = new BinaryEntity(); - entity.foo = "bar".getBytes(); - final VPackSlice vpack = new VPackSlice(mapper.writeValueAsBytes(entity)); - assertThat(vpack).isNotNull(); - assertThat(vpack.isObject()).isTrue(); - assertThat(vpack.get("foo").isString()).isTrue(); - assertThat(vpack.get("foo").getAsString()).isEqualTo(Base64.getEncoder().encodeToString(entity.foo)); - } - - @Test - void toBinary() throws IOException { - final String value = Base64.getEncoder().encodeToString("bar".getBytes()); - final VPackSlice vpack = new VPackBuilder().add(ValueType.OBJECT).add("foo", value).close().slice(); - final BinaryEntity entity = mapper.readValue(vpack.getBuffer(), BinaryEntity.class); - assertThat(entity).isNotNull(); - assertThat(entity.foo).isEqualTo("bar".getBytes()); - } - - @Test - void asFloatingNumber() { - final VPackSlice vpack = new VPackBuilder().add(ValueType.OBJECT).add("value", 12000).close().slice(); - assertThat(vpack.get("value").getAsInt()).isEqualTo(12000); - assertThat(vpack.get("value").getAsFloat()).isEqualTo(12000F); - assertThat(vpack.get("value").getAsDouble()).isEqualTo(12000.); - } - - @Test - void toVPackSlice() throws IOException { - final VPackSlice value = new VPackBuilder().add(ValueType.OBJECT).add("key", "value").close().slice(); - final VPackSlice entity = mapper.readValue(value.getBuffer(), VPackSlice.class); - assertThat(entity).isEqualTo(value); - } - - -} +// TODO: move these tests to velocypack-java project + +//import com.arangodb.velocypack.*; +//import com.fasterxml.jackson.core.JsonProcessingException; +//import com.fasterxml.jackson.databind.ObjectMapper; +//import org.junit.jupiter.api.Test; +// +//import java.io.IOException; +//import java.lang.annotation.ElementType; +//import java.lang.annotation.Retention; +//import java.lang.annotation.RetentionPolicy; +//import java.lang.annotation.Target; +//import java.math.BigDecimal; +//import java.math.BigInteger; +//import java.text.DateFormat; +//import java.text.SimpleDateFormat; +//import java.util.*; +//import java.util.Map.Entry; +// +//import static org.assertj.core.api.Assertions.assertThat; +// +///** +// * @author Mark Vollmary +// */ +//class VPackSerializeDeserializeTest { +// +// private static final DateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");// ISO 8601 +// +// static { +// DATE_FORMAT.setTimeZone(TimeZone.getTimeZone("UTC")); +// } +// +// private final ObjectMapper mapper = ArangoJack.createDefaultMapper(); +// +// public static class TestEntityBoolean { +// private boolean a = true; +// private boolean b = false; +// private Boolean c = Boolean.TRUE; +// private Boolean d = Boolean.FALSE; +// +// public boolean isA() { +// return a; +// } +// +// public void setA(final boolean a) { +// this.a = a; +// } +// +// public boolean isB() { +// return b; +// } +// +// public void setB(final boolean b) { +// this.b = b; +// } +// +// public Boolean getC() { +// return c; +// } +// +// public void setC(final Boolean c) { +// this.c = c; +// } +// +// public Boolean getD() { +// return d; +// } +// +// public void setD(final Boolean d) { +// this.d = d; +// } +// } +// +// @Test +// void fromBoolean() throws JsonProcessingException { +// final VPackSlice vpack = new VPackSlice(mapper.writeValueAsBytes(new TestEntityBoolean())); +// assertThat(vpack).isNotNull(); +// assertThat(vpack.isObject()).isTrue(); +// { +// final VPackSlice a = vpack.get("a"); +// assertThat(a.isBoolean()).isTrue(); +// assertThat(a.getAsBoolean()).isTrue(); +// } +// { +// final VPackSlice b = vpack.get("b"); +// assertThat(b.isBoolean()).isTrue(); +// assertThat(b.getAsBoolean()).isFalse(); +// } +// { +// final VPackSlice c = vpack.get("c"); +// assertThat(c.isBoolean()).isTrue(); +// assertThat(c.getAsBoolean()).isTrue(); +// } +// { +// final VPackSlice d = vpack.get("d"); +// assertThat(d.isBoolean()).isTrue(); +// assertThat(d.getAsBoolean()).isFalse(); +// } +// } +// +// @Test +// void toBoolean() throws IOException { +// final VPackBuilder builder = new VPackBuilder(); +// { +// builder.add(ValueType.OBJECT); +// builder.add("a", false); +// builder.add("b", true); +// builder.add("c", Boolean.FALSE); +// builder.add("d", Boolean.TRUE); +// builder.close(); +// } +// final VPackSlice vpack = builder.slice(); +// final TestEntityBoolean entity = mapper.readValue(vpack.getBuffer(), TestEntityBoolean.class); +// assertThat(entity).isNotNull(); +// assertThat(entity.a).isFalse(); +// assertThat(entity.b).isTrue(); +// assertThat(entity.c).isInstanceOf(Boolean.class).isFalse(); +// assertThat(entity.d).isInstanceOf(Boolean.class).isTrue(); +// } +// +// public static class TestEntityString { +// private String s = "test"; +// private Character c1 = 't'; +// private char c2 = 't'; +// +// public String getS() { +// return s; +// } +// +// public void setS(final String s) { +// this.s = s; +// } +// +// public Character getC1() { +// return c1; +// } +// +// public void setC1(final Character c1) { +// this.c1 = c1; +// } +// +// public char getC2() { +// return c2; +// } +// +// public void setC2(final char c2) { +// this.c2 = c2; +// } +// } +// +// @Test +// void fromStrings() throws JsonProcessingException { +// final VPackSlice vpack = new VPackSlice(mapper.writeValueAsBytes(new TestEntityString())); +// assertThat(vpack).isNotNull(); +// assertThat(vpack.isObject()).isTrue(); +// { +// final VPackSlice s = vpack.get("s"); +// assertThat(s.isString()).isTrue(); +// assertThat(s.getAsString()).isEqualTo("test"); +// } +// { +// final VPackSlice c1 = vpack.get("c1"); +// assertThat(c1.isString()).isTrue(); +// assertThat(c1.getAsChar()).isEqualTo('t'); +// } +// { +// final VPackSlice c2 = vpack.get("c2"); +// assertThat(c2.isString()).isTrue(); +// assertThat(c2.getAsChar()).isEqualTo('t'); +// } +// } +// +// @Test +// void toStrings() throws IOException { +// final VPackBuilder builder = new VPackBuilder(); +// { +// builder.add(ValueType.OBJECT); +// builder.add("s", "abc"); +// builder.add("c1", 'd'); +// builder.add("c2", 'd'); +// builder.close(); +// } +// final VPackSlice vpack = builder.slice(); +// final TestEntityString entity = mapper.readValue(vpack.getBuffer(), TestEntityString.class); +// assertThat(entity).isNotNull(); +// assertThat(entity.s).isEqualTo("abc"); +// assertThat(entity.c1).isEqualTo(new Character('d')); +// } +// +// public static class TestEntityInteger { +// private int i1 = 1; +// private Integer i2 = 1; +// +// public int getI1() { +// return i1; +// } +// +// public void setI1(final int i1) { +// this.i1 = i1; +// } +// +// public Integer getI2() { +// return i2; +// } +// +// public void setI2(final Integer i2) { +// this.i2 = i2; +// } +// } +// +// @Test +// void fromInteger() throws JsonProcessingException { +// final VPackSlice vpack = new VPackSlice(mapper.writeValueAsBytes(new TestEntityInteger())); +// assertThat(vpack).isNotNull(); +// assertThat(vpack.isObject()).isTrue(); +// { +// final VPackSlice i1 = vpack.get("i1"); +// assertThat(i1.isInteger()).isTrue(); +// assertThat(i1.getAsInt()).isEqualTo(1); +// } +// { +// final VPackSlice i2 = vpack.get("i2"); +// assertThat(i2.isInteger()).isTrue(); +// assertThat(i2.getAsInt()).isEqualTo(1); +// } +// } +// +// @Test +// void fromNegativeInteger() throws JsonProcessingException { +// final TestEntityInteger entity = new TestEntityInteger(); +// entity.i1 = -50; +// entity.i2 = -50; +// final VPackSlice vpack = new VPackSlice(mapper.writeValueAsBytes(entity)); +// assertThat(vpack).isNotNull(); +// assertThat(vpack.isObject()).isTrue(); +// { +// final VPackSlice i1 = vpack.get("i1"); +// assertThat(i1.isInteger()).isTrue(); +// assertThat(i1.getAsInt()).isEqualTo(-50); +// } +// { +// final VPackSlice i2 = vpack.get("i2"); +// assertThat(i2.isInteger()).isTrue(); +// assertThat(i2.getAsInt()).isEqualTo(-50); +// } +// } +// +// @Test +// void toInteger() throws IOException { +// final VPackBuilder builder = new VPackBuilder(); +// { +// builder.add(ValueType.OBJECT); +// builder.add("i1", 2); +// builder.add("i2", 3); +// builder.close(); +// } +// final VPackSlice vpack = builder.slice(); +// final TestEntityInteger entity = mapper.readValue(vpack.getBuffer(), TestEntityInteger.class); +// assertThat(entity).isNotNull(); +// assertThat(entity.i1).isEqualTo(2); +// assertThat(entity.i2).isEqualTo(Integer.valueOf(3)); +// } +// +// @Test +// void toNegativeInteger() throws IOException { +// final VPackBuilder builder = new VPackBuilder(); +// { +// builder.add(ValueType.OBJECT); +// builder.add("i1", -50); +// builder.add("i2", -50); +// builder.close(); +// } +// final VPackSlice vpack = builder.slice(); +// final TestEntityInteger entity = mapper.readValue(vpack.getBuffer(), TestEntityInteger.class); +// assertThat(entity).isNotNull(); +// assertThat(entity.i1).isEqualTo(-50); +// assertThat(entity.i2).isEqualTo(Integer.valueOf(-50)); +// } +// +// public static class TestEntityLong { +// private long l1 = 1; +// private Long l2 = 1L; +// +// public long getL1() { +// return l1; +// } +// +// public void setL1(final long l1) { +// this.l1 = l1; +// } +// +// public Long getL2() { +// return l2; +// } +// +// public void setL2(final Long l2) { +// this.l2 = l2; +// } +// } +// +// @Test +// void fromLong() throws JsonProcessingException { +// final VPackSlice vpack = new VPackSlice(mapper.writeValueAsBytes(new TestEntityLong())); +// assertThat(vpack).isNotNull(); +// assertThat(vpack.isObject()).isTrue(); +// { +// final VPackSlice l1 = vpack.get("l1"); +// assertThat(l1.isInteger()).isTrue(); +// assertThat(l1.getAsLong()).isEqualTo(1L); +// } +// { +// final VPackSlice l2 = vpack.get("l2"); +// assertThat(l2.isInteger()).isTrue(); +// assertThat(l2.getAsLong()).isEqualTo(1L); +// } +// } +// +// @Test +// void fromNegativeLong() throws JsonProcessingException { +// final TestEntityLong entity = new TestEntityLong(); +// entity.l1 = -100L; +// entity.l2 = -300L; +// final VPackSlice vpack = new VPackSlice(mapper.writeValueAsBytes(entity)); +// assertThat(vpack).isNotNull(); +// assertThat(vpack.isObject()).isTrue(); +// { +// final VPackSlice l1 = vpack.get("l1"); +// assertThat(l1.isInteger()).isTrue(); +// assertThat(l1.getAsLong()).isEqualTo(-100L); +// } +// { +// final VPackSlice l2 = vpack.get("l2"); +// assertThat(l2.isInteger()).isTrue(); +// assertThat(l2.getAsLong()).isEqualTo(-300); +// } +// } +// +// @Test +// void toLong() throws IOException { +// final VPackBuilder builder = new VPackBuilder(); +// { +// builder.add(ValueType.OBJECT); +// builder.add("l1", 2); +// builder.add("l2", 3); +// builder.close(); +// } +// final VPackSlice vpack = builder.slice(); +// final TestEntityLong entity = mapper.readValue(vpack.getBuffer(), TestEntityLong.class); +// assertThat(entity).isNotNull(); +// assertThat(entity.l1).isEqualTo(2); +// assertThat(entity.l2).isEqualTo(Long.valueOf(3)); +// } +// +// @Test +// void toNegativeLong() throws IOException { +// final VPackBuilder builder = new VPackBuilder(); +// { +// builder.add(ValueType.OBJECT); +// builder.add("l1", -100L); +// builder.add("l2", -300L); +// builder.close(); +// } +// final VPackSlice vpack = builder.slice(); +// final TestEntityLong entity = mapper.readValue(vpack.getBuffer(), TestEntityLong.class); +// assertThat(entity).isNotNull(); +// assertThat(entity.l1).isEqualTo(-100L); +// assertThat(entity.l2).isEqualTo(Long.valueOf(-300)); +// } +// +// @Test +// void negativeLong() { +// final TestEntityLong entity = new TestEntityLong(); +// entity.l1 = -100L; +// entity.l2 = -300L; +// final VPack vp = new VPack.Builder().build(); +// final TestEntityLong out = vp.deserialize(vp.serialize(entity), TestEntityLong.class); +// assertThat(out.l1).isEqualTo(entity.l1); +// assertThat(out.l2).isEqualTo(entity.l2); +// } +// +// @Test +// void intToLong() throws IOException { +// final VPackBuilder builder = new VPackBuilder(); +// { +// builder.add(ValueType.OBJECT); +// builder.add("l1", 100); +// builder.add("l2", 300); +// builder.close(); +// } +// final VPackSlice vpack = builder.slice(); +// final TestEntityLong entity = mapper.readValue(vpack.getBuffer(), TestEntityLong.class); +// assertThat(entity).isNotNull(); +// assertThat(entity.l1).isEqualTo(100); +// assertThat(entity.l2).isEqualTo(Long.valueOf(300)); +// } +// +// @Test +// void negativeIntToLong() throws IOException { +// final VPackBuilder builder = new VPackBuilder(); +// { +// builder.add(ValueType.OBJECT); +// builder.add("l1", -100); +// builder.add("l2", -300); +// builder.close(); +// } +// final VPackSlice vpack = builder.slice(); +// final TestEntityLong entity = mapper.readValue(vpack.getBuffer(), TestEntityLong.class); +// assertThat(entity).isNotNull(); +// assertThat(entity.l1).isEqualTo(-100L); +// assertThat(entity.l2).isEqualTo(Long.valueOf(-300)); +// } +// +// @Test +// void negativeLongToInt() throws IOException { +// final VPackBuilder builder = new VPackBuilder(); +// { +// builder.add(ValueType.OBJECT); +// builder.add("i1", -100L); +// builder.add("i2", -300L); +// builder.close(); +// } +// final VPackSlice vpack = builder.slice(); +// final TestEntityInteger entity = mapper.readValue(vpack.getBuffer(), TestEntityInteger.class); +// assertThat(entity).isNotNull(); +// assertThat(entity.i1).isEqualTo(-100); +// assertThat(entity.i2).isEqualTo(Integer.valueOf(-300)); +// } +// +// @Test +// void negativeLongToShort() throws IOException { +// final VPackBuilder builder = new VPackBuilder(); +// { +// builder.add(ValueType.OBJECT); +// builder.add("s1", -100L); +// builder.add("s2", -300L); +// builder.close(); +// } +// final VPackSlice vpack = builder.slice(); +// final TestEntityShort entity = mapper.readValue(vpack.getBuffer(), TestEntityShort.class); +// assertThat(entity).isNotNull(); +// assertThat(entity.s1).isEqualTo((short) -100); +// assertThat(entity.s2).isEqualTo(Short.valueOf((short) -300)); +// } +// +// @Test +// void negativeShortToLong() throws IOException { +// final VPackBuilder builder = new VPackBuilder(); +// { +// builder.add(ValueType.OBJECT); +// builder.add("l1", (short) -100); +// builder.add("l2", (short) -300); +// builder.close(); +// } +// final VPackSlice vpack = builder.slice(); +// final TestEntityLong entity = mapper.readValue(vpack.getBuffer(), TestEntityLong.class); +// assertThat(entity).isNotNull(); +// assertThat(entity.l1).isEqualTo(-100L); +// assertThat(entity.l2).isEqualTo(Long.valueOf(-300)); +// } +// +// public static class TestEntityFloat { +// private float f1 = 1; +// private Float f2 = 1F; +// +// public float getF1() { +// return f1; +// } +// +// public void setF1(final float f1) { +// this.f1 = f1; +// } +// +// public Float getF2() { +// return f2; +// } +// +// public void setF2(final Float f2) { +// this.f2 = f2; +// } +// } +// +// @Test +// void fromFloat() throws JsonProcessingException { +// final VPackSlice vpack = new VPackSlice(mapper.writeValueAsBytes(new TestEntityFloat())); +// assertThat(vpack).isNotNull(); +// assertThat(vpack.isObject()).isTrue(); +// { +// final VPackSlice f1 = vpack.get("f1"); +// assertThat(f1.isDouble()).isTrue(); +// assertThat(f1.getAsFloat()).isEqualTo(1.0F); +// } +// { +// final VPackSlice f2 = vpack.get("f2"); +// assertThat(f2.isDouble()).isTrue(); +// assertThat(f2.getAsFloat()).isEqualTo(1.0F); +// } +// } +// +// @Test +// void toFloat() throws IOException { +// final VPackBuilder builder = new VPackBuilder(); +// { +// builder.add(ValueType.OBJECT); +// builder.add("f1", 2F); +// builder.add("f2", 3F); +// builder.close(); +// } +// final VPackSlice vpack = builder.slice(); +// final TestEntityFloat entity = mapper.readValue(vpack.getBuffer(), TestEntityFloat.class); +// assertThat(entity).isNotNull(); +// assertThat(entity.f1).isEqualTo(2F); +// assertThat(entity.f2).isEqualTo(new Float(3)); +// } +// +// public static class TestEntityShort { +// private short s1 = 1; +// private Short s2 = 1; +// +// public short getS1() { +// return s1; +// } +// +// public void setS1(final short s1) { +// this.s1 = s1; +// } +// +// public Short getS2() { +// return s2; +// } +// +// public void setS2(final Short s2) { +// this.s2 = s2; +// } +// } +// +// @Test +// void fromShort() throws JsonProcessingException { +// final VPackSlice vpack = new VPackSlice(mapper.writeValueAsBytes(new TestEntityShort())); +// assertThat(vpack).isNotNull(); +// assertThat(vpack.isObject()).isTrue(); +// { +// final VPackSlice s1 = vpack.get("s1"); +// assertThat(s1.isInteger()).isTrue(); +// assertThat(s1.getAsShort()).isEqualTo((short) 1); +// } +// { +// final VPackSlice s2 = vpack.get("s2"); +// assertThat(s2.isInteger()).isTrue(); +// assertThat(s2.getAsShort()).isEqualTo((short) 1); +// } +// } +// +// @Test +// void toShort() throws IOException { +// final VPackBuilder builder = new VPackBuilder(); +// { +// builder.add(ValueType.OBJECT); +// builder.add("s1", 2); +// builder.add("s2", 3); +// builder.close(); +// } +// final VPackSlice vpack = builder.slice(); +// final TestEntityShort entity = mapper.readValue(vpack.getBuffer(), TestEntityShort.class); +// assertThat(entity).isNotNull(); +// assertThat(entity.s1).isEqualTo((short) 2); +// assertThat(entity.s2).isEqualTo(Short.valueOf((short) 3)); +// } +// +// public static class TestEntityByte { +// private byte b1 = 1; // short integer path +// private Byte b2 = 100; // integer path +// +// public byte getB1() { +// return b1; +// } +// +// public void setB1(final byte b1) { +// this.b1 = b1; +// } +// +// public Byte getB2() { +// return b2; +// } +// +// public void setB2(final Byte b2) { +// this.b2 = b2; +// } +// } +// +// @Test +// void fromByte() throws JsonProcessingException { +// final VPackSlice vpack = new VPackSlice(mapper.writeValueAsBytes(new TestEntityByte())); +// assertThat(vpack).isNotNull(); +// assertThat(vpack.isObject()).isTrue(); +// { +// final VPackSlice b1 = vpack.get("b1"); +// assertThat(b1.isInteger()).isTrue(); +// assertThat(b1.getAsByte()).isEqualTo((byte) 1); +// } +// { +// final VPackSlice b2 = vpack.get("b2"); +// assertThat(b2.isInteger()).isTrue(); +// assertThat(b2.getAsByte()).isEqualTo((byte) 100); +// } +// } +// +// @Test +// void toByte() throws IOException { +// final VPackBuilder builder = new VPackBuilder(); +// { +// builder.add(ValueType.OBJECT); +// builder.add("b1", 30); // integer path +// builder.add("b2", 4); // short integer path +// builder.close(); +// } +// final VPackSlice vpack = builder.slice(); +// final TestEntityByte entity = mapper.readValue(vpack.getBuffer(), TestEntityByte.class); +// assertThat(entity).isNotNull(); +// assertThat(entity.b1).isEqualTo((byte) 30); +// assertThat(entity.b2).isEqualTo(Byte.valueOf((byte) 4)); +// } +// +// public static class TestEntityDouble { +// private Double d1 = 1.5; +// private double d2 = 1.5; +// +// public Double getD1() { +// return d1; +// } +// +// public void setD1(final Double d1) { +// this.d1 = d1; +// } +// +// public double getD2() { +// return d2; +// } +// +// public void setD2(final double d2) { +// this.d2 = d2; +// } +// } +// +// @Test +// void fromDouble() throws JsonProcessingException { +// final VPackSlice vpack = new VPackSlice(mapper.writeValueAsBytes(new TestEntityDouble())); +// assertThat(vpack).isNotNull(); +// assertThat(vpack.isObject()).isTrue(); +// { +// final VPackSlice d1 = vpack.get("d1"); +// assertThat(d1.isDouble()).isTrue(); +// assertThat(d1.getAsDouble()).isEqualTo(1.5); +// } +// { +// final VPackSlice d2 = vpack.get("d2"); +// assertThat(d2.isDouble()).isTrue(); +// assertThat(d2.getAsDouble()).isEqualTo(1.5); +// } +// } +// +// @Test +// void toDouble() throws IOException { +// final VPackBuilder builder = new VPackBuilder(); +// { +// builder.add(ValueType.OBJECT); +// builder.add("d1", 2.25); +// builder.add("d2", 3.75); +// builder.close(); +// } +// final VPackSlice vpack = builder.slice(); +// final TestEntityDouble entity = mapper.readValue(vpack.getBuffer(), TestEntityDouble.class); +// assertThat(entity).isNotNull(); +// assertThat(entity.d1).isEqualTo(2.25); +// assertThat(entity.d2).isEqualTo(3.75); +// } +// +// public static class TestEntityBigNumber { +// private static final BigInteger BI = BigInteger.valueOf(Long.MAX_VALUE).add(BigInteger.ONE); +// private static final BigDecimal BD = BigDecimal.valueOf(Double.MAX_VALUE).add(BigDecimal.ONE); +// +// private BigInteger bi = BI; +// private BigDecimal bd = BD; +// +// public BigInteger getBi() { +// return bi; +// } +// +// public void setBi(final BigInteger bi) { +// this.bi = bi; +// } +// +// public BigDecimal getBd() { +// return bd; +// } +// +// public void setBd(final BigDecimal bd) { +// this.bd = bd; +// } +// } +// +// @Test +// void fromBigNumbers() throws JsonProcessingException { +// final VPackSlice vpack = new VPackSlice(mapper.writeValueAsBytes(new TestEntityBigNumber())); +// assertThat(vpack).isNotNull(); +// assertThat(vpack.isObject()).isTrue(); +// { +// final VPackSlice bi = vpack.get("bi"); +// assertThat(bi.isString()).isTrue(); +// assertThat(bi.getAsBigInteger()).isEqualTo(TestEntityBigNumber.BI); +// } +// { +// final VPackSlice bd = vpack.get("bd"); +// assertThat(bd.isString()).isTrue(); +// assertThat(bd.getAsBigDecimal()).isEqualTo(TestEntityBigNumber.BD); +// } +// } +// +// @Test +// void toBigNumbers() throws IOException { +// final VPackBuilder builder = new VPackBuilder(); +// { +// builder.add(ValueType.OBJECT); +// builder.add("bi", BigInteger.valueOf(2)); +// builder.add("bd", BigDecimal.valueOf(3.75)); +// builder.close(); +// } +// final VPackSlice vpack = builder.slice(); +// final TestEntityBigNumber entity = mapper.readValue(vpack.getBuffer(), TestEntityBigNumber.class); +// assertThat(entity).isNotNull(); +// assertThat(entity.bi).isEqualTo(BigInteger.valueOf(2)); +// assertThat(entity.bd).isEqualTo(BigDecimal.valueOf(3.75)); +// } +// +// @Test +// void bigDecimal() { +// final BigDecimal fromDouble = BigDecimal.valueOf(-710.01); +// final BigDecimal fromString = new BigDecimal("-710.01"); +// assertThat(fromDouble).isEqualTo(fromString); +// assertThat(new VPackBuilder().add(fromDouble).slice().getAsBigDecimal()).isEqualTo(fromDouble); +// assertThat(new VPackBuilder().add(fromString).slice().getAsBigDecimal()).isEqualTo(fromDouble); +// } +// +// public static class TestEntityArray { +// private String[] a1 = {"a", "b", "cd"}; +// private int[] a2 = {1, 2, 3, 4, 5}; +// private boolean[] a3 = {true, true, false}; +// private TestEnum[] a4 = TestEnum.values(); +// +// public String[] getA1() { +// return a1; +// } +// +// public void setA1(final String[] a1) { +// this.a1 = a1; +// } +// +// public int[] getA2() { +// return a2; +// } +// +// public void setA2(final int[] a2) { +// this.a2 = a2; +// } +// +// public boolean[] getA3() { +// return a3; +// } +// +// public void setA3(final boolean[] a3) { +// this.a3 = a3; +// } +// +// public TestEnum[] getA4() { +// return a4; +// } +// +// public void setA4(final TestEnum[] a4) { +// this.a4 = a4; +// } +// +// } +// +// @Test +// void fromArray() throws JsonProcessingException { +// final TestEntityArray entity = new TestEntityArray(); +// final VPackSlice vpack = new VPackSlice(mapper.writeValueAsBytes(entity)); +// assertThat(vpack).isNotNull(); +// assertThat(vpack.isObject()).isTrue(); +// { +// final VPackSlice a1 = vpack.get("a1"); +// assertThat(a1.isArray()).isTrue(); +// assertThat(a1.getLength()).isEqualTo(entity.a1.length); +// for (int i = 0; i < a1.getLength(); i++) { +// assertThat(a1.get(i).getAsString()).isEqualTo(entity.a1[i]); +// } +// } +// { +// final VPackSlice a2 = vpack.get("a2"); +// assertThat(a2.isArray()).isTrue(); +// assertThat(a2.getLength()).isEqualTo(entity.a2.length); +// for (int i = 0; i < a2.getLength(); i++) { +// assertThat(a2.get(i).getAsInt()).isEqualTo(entity.a2[i]); +// } +// } +// { +// final VPackSlice a3 = vpack.get("a3"); +// assertThat(a3.isArray()).isTrue(); +// assertThat(a3.getLength()).isEqualTo(entity.a3.length); +// for (int i = 0; i < a3.getLength(); i++) { +// assertThat(a3.get(i).getAsBoolean()).isEqualTo(entity.a3[i]); +// } +// } +// { +// final VPackSlice a4 = vpack.get("a4"); +// assertThat(a4.isArray()).isTrue(); +// assertThat(a4.getLength()).isEqualTo(entity.a4.length); +// for (int i = 0; i < a4.getLength(); i++) { +// assertThat(TestEnum.valueOf(a4.get(i).getAsString())).isEqualTo(entity.a4[i]); +// } +// } +// } +// +// @Test +// void toArray() throws IOException { +// final VPackBuilder builder = new VPackBuilder(); +// { +// builder.add(ValueType.OBJECT); +// { +// builder.add("a1", ValueType.ARRAY); +// builder.add("a"); +// builder.add("b"); +// builder.add("c"); +// builder.close(); +// } +// { +// builder.add("a2", ValueType.ARRAY); +// builder.add(1); +// builder.add(2); +// builder.add(3); +// builder.add(4); +// builder.close(); +// } +// { +// builder.add("a3", ValueType.ARRAY); +// builder.add(false); +// builder.add(true); +// builder.close(); +// } +// { +// builder.add("a4", ValueType.ARRAY); +// builder.add(TestEnum.A.name()); +// builder.add(TestEnum.B.name()); +// builder.close(); +// } +// builder.close(); +// } +// final VPackSlice vpack = builder.slice(); +// final TestEntityArray entity = mapper.readValue(vpack.getBuffer(), TestEntityArray.class); +// assertThat(entity).isNotNull(); +// { +// assertThat(entity.a1).hasSize(3); +// assertThat(entity.a1[0]).isEqualTo("a"); +// assertThat(entity.a1[1]).isEqualTo("b"); +// assertThat(entity.a1[2]).isEqualTo("c"); +// } +// { +// assertThat(entity.a2).hasSize(4); +// assertThat(entity.a2[0]).isEqualTo(1); +// assertThat(entity.a2[1]).isEqualTo(2); +// assertThat(entity.a2[2]).isEqualTo(3); +// assertThat(entity.a2[3]).isEqualTo(4); +// } +// { +// assertThat(entity.a3).hasSize(2); +// assertThat(entity.a3[0]).isFalse(); +// assertThat(entity.a3[1]).isTrue(); +// } +// { +// assertThat(entity.a4).hasSize(2); +// assertThat(entity.a4[0]).isEqualTo(TestEnum.A); +// assertThat(entity.a4[1]).isEqualTo(TestEnum.B); +// } +// } +// +// @Test +// void fromArrayWithNull() throws JsonProcessingException { +// final TestEntityArray entity = new TestEntityArray(); +// entity.a1 = new String[]{"foo", null}; +// +// final VPackSlice vpack = new VPackSlice(mapper.writeValueAsBytes(entity)); +// assertThat(vpack).isNotNull(); +// assertThat(vpack.isObject()).isTrue(); +// +// final VPackSlice a1 = vpack.get("a1"); +// assertThat(a1.isArray()).isTrue(); +// assertThat(a1.size()).isEqualTo(2); +// assertThat(a1.get(0).isString()).isTrue(); +// assertThat(a1.get(0).getAsString()).isEqualTo("foo"); +// assertThat(a1.get(1).isNull()).isTrue(); +// } +// +// protected enum TestEnum { +// A, B, C +// } +// +// public static class TestEntityEnum { +// private TestEnum e1 = TestEnum.A; +// +// public TestEnum getE1() { +// return e1; +// } +// +// public void setE1(final TestEnum e1) { +// this.e1 = e1; +// } +// } +// +// @Test +// void fromEnum() throws JsonProcessingException { +// final VPackSlice vpack = new VPackSlice(mapper.writeValueAsBytes(new TestEntityEnum())); +// assertThat(vpack).isNotNull(); +// assertThat(vpack.isObject()).isTrue(); +// { +// final VPackSlice e1 = vpack.get("e1"); +// assertThat(e1.isString()).isTrue(); +// assertThat(TestEnum.valueOf(e1.getAsString())).isEqualTo(TestEnum.A); +// } +// } +// +// @Test +// void toEnum() throws IOException { +// final VPackBuilder builder = new VPackBuilder(); +// { +// builder.add(ValueType.OBJECT); +// builder.add("e1", TestEnum.B.name()); +// builder.close(); +// } +// final VPackSlice vpack = builder.slice(); +// final TestEntityEnum entity = mapper.readValue(vpack.getBuffer(), TestEntityEnum.class); +// assertThat(entity).isNotNull(); +// assertThat(entity.e1).isEqualTo(TestEnum.B); +// } +// +// public static class TestEntityObject { +// private TestEntityLong o1 = new TestEntityLong(); +// private TestEntityArray o2 = new TestEntityArray(); +// +// public TestEntityLong getO1() { +// return o1; +// } +// +// public void setO1(final TestEntityLong o1) { +// this.o1 = o1; +// } +// +// public TestEntityArray getO2() { +// return o2; +// } +// +// public void setO2(final TestEntityArray o2) { +// this.o2 = o2; +// } +// } +// +// @Test +// void fromObject() throws JsonProcessingException { +// final TestEntityObject entity = new TestEntityObject(); +// final VPackSlice vpack = new VPackSlice(mapper.writeValueAsBytes(entity)); +// assertThat(vpack).isNotNull(); +// assertThat(vpack.isObject()).isTrue(); +// { +// final VPackSlice o1 = vpack.get("o1"); +// assertThat(o1.isObject()).isTrue(); +// { +// final VPackSlice l1 = o1.get("l1"); +// assertThat(l1.isInteger()).isTrue(); +// assertThat(l1.getAsLong()).isEqualTo(1L); +// } +// { +// final VPackSlice l2 = o1.get("l2"); +// assertThat(l2.isInteger()).isTrue(); +// assertThat(l2.getAsLong()).isEqualTo(1L); +// } +// } +// { +// final VPackSlice o2 = vpack.get("o2"); +// assertThat(o2.isObject()).isTrue(); +// { +// final VPackSlice a1 = o2.get("a1"); +// assertThat(a1.isArray()).isTrue(); +// assertThat(a1.getLength()).isEqualTo(entity.o2.a1.length); +// for (int i = 0; i < a1.getLength(); i++) { +// assertThat(a1.get(i).getAsString()).isEqualTo(entity.o2.a1[i]); +// } +// } +// { +// final VPackSlice a2 = o2.get("a2"); +// assertThat(a2.isArray()).isTrue(); +// assertThat(a2.getLength()).isEqualTo(entity.o2.a2.length); +// for (int i = 0; i < a2.getLength(); i++) { +// assertThat(a2.get(i).getAsInt()).isEqualTo(entity.o2.a2[i]); +// } +// } +// { +// final VPackSlice a3 = o2.get("a3"); +// assertThat(a3.isArray()).isTrue(); +// assertThat(a3.getLength()).isEqualTo(entity.o2.a3.length); +// for (int i = 0; i < a3.getLength(); i++) { +// assertThat(a3.get(i).getAsBoolean()).isEqualTo(entity.o2.a3[i]); +// } +// } +// { +// final VPackSlice a4 = o2.get("a4"); +// assertThat(a4.isArray()).isTrue(); +// assertThat(a4.getLength()).isEqualTo(entity.o2.a4.length); +// for (int i = 0; i < a4.getLength(); i++) { +// assertThat(TestEnum.valueOf(a4.get(i).getAsString())).isEqualTo(entity.o2.a4[i]); +// } +// } +// } +// } +// +// @Test +// void toObject() throws IOException { +// final VPackBuilder builder = new VPackBuilder(); +// { +// builder.add(ValueType.OBJECT); +// { +// builder.add("o1", ValueType.OBJECT); +// builder.add("l1", 5L); +// builder.add("l2", 5L); +// builder.close(); +// } +// { +// builder.add("o2", ValueType.OBJECT); +// { +// builder.add("a1", ValueType.ARRAY); +// builder.add("a"); +// builder.add("b"); +// builder.add("c"); +// builder.close(); +// } +// { +// builder.add("a2", ValueType.ARRAY); +// builder.add(1); +// builder.add(2); +// builder.add(3); +// builder.add(4); +// builder.close(); +// } +// { +// builder.add("a3", ValueType.ARRAY); +// builder.add(false); +// builder.add(true); +// builder.close(); +// } +// { +// builder.add("a4", ValueType.ARRAY); +// builder.add(TestEnum.A.name()); +// builder.add(TestEnum.B.name()); +// builder.close(); +// } +// builder.close(); +// } +// builder.close(); +// } +// final VPackSlice vpack = builder.slice(); +// final TestEntityObject entity = mapper.readValue(vpack.getBuffer(), TestEntityObject.class); +// assertThat(entity).isNotNull(); +// { +// assertThat(entity.o1.l1).isEqualTo(5L); +// assertThat(entity.o1.l2).isEqualTo(Long.valueOf(5)); +// } +// { +// assertThat(entity.o2.a1).hasSize(3); +// assertThat(entity.o2.a1[0]).isEqualTo("a"); +// assertThat(entity.o2.a1[1]).isEqualTo("b"); +// assertThat(entity.o2.a1[2]).isEqualTo("c"); +// } +// { +// assertThat(entity.o2.a2).hasSize(4); +// assertThat(entity.o2.a2[0]).isEqualTo(1); +// assertThat(entity.o2.a2[1]).isEqualTo(2); +// assertThat(entity.o2.a2[2]).isEqualTo(3); +// assertThat(entity.o2.a2[3]).isEqualTo(4); +// } +// { +// assertThat(entity.o2.a3).hasSize(2); +// assertThat(entity.o2.a3[0]).isFalse(); +// assertThat(entity.o2.a3[1]).isTrue(); +// } +// { +// assertThat(entity.o2.a4).hasSize(2); +// assertThat(entity.o2.a4[0]).isEqualTo(TestEnum.A); +// assertThat(entity.o2.a4[1]).isEqualTo(TestEnum.B); +// } +// } +// +// public static class TestEntityArrayInArray { +// private long[][] a1; +// +// public long[][] getA1() { +// return a1; +// } +// +// public void setA1(final long[][] a1) { +// this.a1 = a1; +// } +// } +// +// @Test +// void fromArrayInArray() throws JsonProcessingException { +// final TestEntityArrayInArray entity = new TestEntityArrayInArray(); +// entity.a1 = new long[][]{{1, 2, 3}, {4, 5, 6}}; +// final VPackSlice vpack = new VPackSlice(mapper.writeValueAsBytes(entity)); +// assertThat(vpack).isNotNull(); +// assertThat(vpack.isObject()).isTrue(); +// { +// final VPackSlice a1 = vpack.get("a1"); +// assertThat(a1.isArray()).isTrue(); +// assertThat(a1.getLength()).isEqualTo(entity.a1.length); +// for (int i = 0; i < a1.getLength(); i++) { +// final VPackSlice at = a1.get(i); +// assertThat(at.isArray()).isTrue(); +// assertThat(at.getLength()).isEqualTo(entity.a1[i].length); +// for (int j = 0; j < at.getLength(); j++) { +// final VPackSlice atat = at.get(j); +// assertThat(atat.isInteger()).isTrue(); +// assertThat(atat.getAsLong()).isEqualTo(entity.a1[i][j]); +// } +// } +// } +// } +// +// @Test +// void toArrayInArray() throws IOException { +// final VPackBuilder builder = new VPackBuilder(); +// { +// builder.add(ValueType.OBJECT); +// { +// builder.add("a1", ValueType.ARRAY); +// { +// builder.add(ValueType.ARRAY); +// builder.add(1); +// builder.add(2); +// builder.add(3); +// builder.close(); +// } +// { +// builder.add(ValueType.ARRAY); +// builder.add(4); +// builder.add(5); +// builder.add(6); +// builder.close(); +// } +// builder.close(); +// } +// builder.close(); +// } +// final VPackSlice vpack = builder.slice(); +// final TestEntityArrayInArray entity = mapper.readValue(vpack.getBuffer(), TestEntityArrayInArray.class); +// assertThat(entity).isNotNull(); +// assertThat(entity.a1.length).isEqualTo(2); +// { +// assertThat(entity.a1[0]).hasSize(3); +// assertThat(entity.a1[0][0]).isEqualTo(1L); +// assertThat(entity.a1[0][1]).isEqualTo(2L); +// assertThat(entity.a1[0][2]).isEqualTo(3L); +// } +// { +// assertThat(entity.a1[1]).hasSize(3); +// assertThat(entity.a1[1][0]).isEqualTo(4L); +// assertThat(entity.a1[1][1]).isEqualTo(5L); +// assertThat(entity.a1[1][2]).isEqualTo(6L); +// } +// } +// +// @SuppressWarnings("serial") +// public static class TestCollection extends LinkedList { +// +// } +// +// public static class TestEntityCollectionExtendedWithNulls { +// +// protected TestCollection a1; +// +// public TestCollection getA1() { +// return a1; +// } +// +// public void setA1(final TestCollection a1) { +// this.a1 = a1; +// } +// +// } +// +// @Test +// void fromCollectionExtendedWithNulls() { +// +// final TestCollection collection = new TestCollection(); +// collection.add("one"); +// collection.add(null); +// collection.add("two"); +// +// final TestEntityCollectionExtendedWithNulls entity = new TestEntityCollectionExtendedWithNulls(); +// entity.setA1(collection); +// +// final VPackSlice vpack = new VPack.Builder().serializeNullValues(true).build().serialize(entity); +// assertThat(vpack).isNotNull(); +// assertThat(vpack.isObject()).isTrue(); +// { +// final VPackSlice a1 = vpack.get("a1"); +// assertThat(a1.isArray()).isTrue(); +// assertThat(a1.getLength()).isEqualTo(entity.a1.size()); +// +// VPackSlice at = a1.get(0); +// assertThat(at.isString()).isTrue(); +// assertThat(at.getAsString()).isEqualTo(entity.a1.get(0)); +// at = a1.get(1); +// assertThat(at.isNull()).isTrue(); +// at = a1.get(2); +// assertThat(at.isString()).isTrue(); +// assertThat(at.getAsString()).isEqualTo(entity.a1.get(2)); +// } +// } +// +// @Test +// void toCollectionExtendedWithNulls() throws Exception { +// final VPackBuilder builder = new VPackBuilder(); +// { +// builder.add(ValueType.OBJECT); +// { +// builder.add("a1", ValueType.ARRAY); +// builder.add("one"); +// builder.add(ValueType.NULL); +// builder.add("two"); +// builder.close(); +// } +// builder.close(); +// } +// +// final VPackSlice vpack = builder.slice(); +// final TestEntityCollectionExtendedWithNulls entity = mapper.readValue(vpack.getBuffer(), +// TestEntityCollectionExtendedWithNulls.class); +// assertThat(entity).isNotNull(); +// assertThat(entity.getA1()).isNotNull(); +// assertThat(entity.getA1()).hasSize(3); +// assertThat(entity.getA1()).contains("one", null, "two"); +// } +// +// public static class TestEntityArrayInArrayInArray { +// +// private double[][][] a1; +// +// public double[][][] getA1() { +// return a1; +// } +// +// public void setA1(final double[][][] a1) { +// this.a1 = a1; +// } +// +// } +// +// @Test +// void fromArrayInArrayInArray() throws JsonProcessingException { +// final TestEntityArrayInArrayInArray entity = new TestEntityArrayInArrayInArray(); +// entity.setA1(new double[][][]{{{1.5, 2.25}, {10.5, 20.25}}, {{100.5}, {200.25}}}); +// final VPackSlice vpack = new VPackSlice(mapper.writeValueAsBytes(entity)); +// assertThat(vpack).isNotNull(); +// assertThat(vpack.isObject()).isTrue(); +// { +// final VPackSlice a1 = vpack.get("a1"); +// assertThat(a1.isArray()).isTrue(); +// assertThat(a1.getLength()).isEqualTo(entity.a1.length); +// for (int i = 0; i < a1.getLength(); i++) { +// final VPackSlice at = a1.get(i); +// assertThat(at.isArray()).isTrue(); +// assertThat(at.getLength()).isEqualTo(entity.a1[i].length); +// for (int j = 0; j < at.getLength(); j++) { +// final VPackSlice atat = at.get(j); +// assertThat(atat.isArray()).isTrue(); +// assertThat(atat.getLength()).isEqualTo(entity.a1[i][j].length); +// for (int k = 0; k < atat.getLength(); k++) { +// final VPackSlice atatat = atat.get(k); +// assertThat(atatat.isDouble()).isTrue(); +// assertThat(atatat.getAsDouble()).isEqualTo(entity.a1[i][j][k]); +// } +// } +// } +// } +// } +// +// @Test +// void toArrayInArrayInArray() throws IOException { +// final VPackBuilder builder = new VPackBuilder(); +// { +// builder.add(ValueType.OBJECT); +// { +// builder.add("a1", ValueType.ARRAY); +// builder.add(ValueType.ARRAY); +// { +// builder.add(ValueType.ARRAY); +// builder.add(1.5); +// builder.add(2.5); +// builder.add(3.5); +// builder.close(); +// } +// { +// builder.add(ValueType.ARRAY); +// builder.add(4.5); +// builder.add(5.5); +// builder.add(6.5); +// builder.close(); +// } +// { +// builder.add(ValueType.ARRAY); +// builder.add(7.5); +// builder.add(8.5); +// builder.add(9.5); +// builder.close(); +// } +// builder.close(); +// builder.add(ValueType.ARRAY); +// { +// builder.add(ValueType.ARRAY); +// builder.add(1.5); +// builder.add(2.5); +// builder.add(3.5); +// builder.close(); +// } +// { +// builder.add(ValueType.ARRAY); +// builder.add(4.5); +// builder.add(5.5); +// builder.add(6.5); +// builder.close(); +// } +// { +// builder.add(ValueType.ARRAY); +// builder.add(7.5); +// builder.add(8.5); +// builder.add(9.5); +// builder.close(); +// } +// builder.close(); +// builder.close(); +// } +// builder.close(); +// } +// final VPackSlice vpack = builder.slice(); +// final TestEntityArrayInArrayInArray entity = mapper.readValue(vpack.getBuffer(), +// TestEntityArrayInArrayInArray.class); +// assertThat(entity).isNotNull(); +// assertThat(entity.a1.length).isEqualTo(2); +// { +// assertThat(entity.a1[0].length).isEqualTo(3); +// assertThat(entity.a1[0][0]).hasSize(3); +// assertThat(entity.a1[0][0][0]).isEqualTo(1.5); +// assertThat(entity.a1[0][0][1]).isEqualTo(2.5); +// assertThat(entity.a1[0][0][2]).isEqualTo(3.5); +// assertThat(entity.a1[0][1]).hasSize(3); +// assertThat(entity.a1[0][1][0]).isEqualTo(4.5); +// assertThat(entity.a1[0][1][1]).isEqualTo(5.5); +// assertThat(entity.a1[0][1][2]).isEqualTo(6.5); +// assertThat(entity.a1[0][2]).hasSize(3); +// assertThat(entity.a1[0][2][0]).isEqualTo(7.5); +// assertThat(entity.a1[0][2][1]).isEqualTo(8.5); +// assertThat(entity.a1[0][2][2]).isEqualTo(9.5); +// } +// { +// assertThat(entity.a1[1].length).isEqualTo(3); +// assertThat(entity.a1[1][0]).hasSize(3); +// assertThat(entity.a1[1][0][0]).isEqualTo(1.5); +// assertThat(entity.a1[1][0][1]).isEqualTo(2.5); +// assertThat(entity.a1[1][0][2]).isEqualTo(3.5); +// assertThat(entity.a1[1][1]).hasSize(3); +// assertThat(entity.a1[1][1][0]).isEqualTo(4.5); +// assertThat(entity.a1[1][1][1]).isEqualTo(5.5); +// assertThat(entity.a1[1][1][2]).isEqualTo(6.5); +// assertThat(entity.a1[1][2]).hasSize(3); +// assertThat(entity.a1[1][2][0]).isEqualTo(7.5); +// assertThat(entity.a1[1][2][1]).isEqualTo(8.5); +// assertThat(entity.a1[1][2][2]).isEqualTo(9.5); +// } +// } +// +// public static class TestEntityObjectInArray { +// private TestEntityString[] a1; +// +// public TestEntityString[] getA1() { +// return a1; +// } +// +// public void setA1(final TestEntityString[] a1) { +// this.a1 = a1; +// } +// } +// +// @Test +// void fromObjectInArray() throws JsonProcessingException { +// final TestEntityObjectInArray entity = new TestEntityObjectInArray(); +// { +// final TestEntityString[] a1 = new TestEntityString[2]; +// final TestEntityString s = new TestEntityString(); +// s.setS("abc"); +// a1[0] = s; +// a1[1] = s; +// entity.setA1(a1); +// } +// final VPackSlice vpack = new VPackSlice(mapper.writeValueAsBytes(entity)); +// assertThat(vpack).isNotNull(); +// assertThat(vpack.isObject()).isTrue(); +// { +// final VPackSlice a1 = vpack.get("a1"); +// assertThat(a1.isArray()).isTrue(); +// assertThat(a1.getLength()).isEqualTo(2); +// for (int i = 0; i < a1.getLength(); i++) { +// final VPackSlice at = a1.get(i); +// assertThat(at.isObject()).isTrue(); +// final VPackSlice s = at.get("s"); +// assertThat(s.isString()).isTrue(); +// assertThat(s.getAsString()).isEqualTo("abc"); +// } +// } +// } +// +// @Test +// void toObjectInArray() throws IOException { +// final VPackBuilder builder = new VPackBuilder(); +// { +// builder.add(ValueType.OBJECT); +// builder.add("a1", ValueType.ARRAY); +// { +// builder.add(ValueType.OBJECT); +// builder.add("s", "abc"); +// builder.close(); +// } +// builder.close(); +// builder.close(); +// } +// final VPackSlice vpack = builder.slice(); +// final TestEntityObjectInArray entity = mapper.readValue(vpack.getBuffer(), TestEntityObjectInArray.class); +// assertThat(entity).isNotNull(); +// assertThat(entity.a1).hasSize(1); +// final TestEntityString st = entity.a1[0]; +// assertThat(st).isNotNull(); +// assertThat(st.s).isEqualTo("abc"); +// } +// +// public static class TestEntityA { +// private String a = "a"; +// +// public String getA() { +// return a; +// } +// +// public void setA(final String a) { +// this.a = a; +// } +// } +// +// public static class TestEntityB extends TestEntityA { +// private String b = "b"; +// +// public String getB() { +// return b; +// } +// +// public void setB(final String b) { +// this.b = b; +// } +// } +// +// @Test +// void fromInheritance() throws JsonProcessingException { +// final VPackSlice vpack = new VPackSlice(mapper.writeValueAsBytes(new TestEntityB())); +// assertThat(vpack).isNotNull(); +// assertThat(vpack.isObject()).isTrue(); +// assertThat(vpack.getLength()).isEqualTo(2); +// { +// final VPackSlice a = vpack.get("a"); +// assertThat(a.isString()).isTrue(); +// assertThat(a.getAsString()).isEqualTo("a"); +// } +// { +// final VPackSlice b = vpack.get("b"); +// assertThat(b.isString()).isTrue(); +// assertThat(b.getAsString()).isEqualTo("b"); +// } +// } +// +// @Test +// void toInheritance() throws IOException { +// final VPackBuilder builder = new VPackBuilder(); +// { +// builder.add(ValueType.OBJECT); +// builder.add("a", "test"); +// builder.add("b", "test"); +// builder.close(); +// } +// final VPackSlice vpack = builder.slice(); +// { +// final TestEntityA entity = mapper.readValue(vpack.getBuffer(), TestEntityA.class); +// assertThat(entity).isNotNull(); +// assertThat(entity.getA()).isEqualTo("test"); +// } +// { +// final TestEntityB entity = mapper.readValue(vpack.getBuffer(), TestEntityB.class); +// assertThat(entity).isNotNull(); +// assertThat(entity.getA()).isEqualTo("test"); +// assertThat(entity.getB()).isEqualTo("test"); +// } +// } +// +// public static class TestEntityC { +// private TestEntityD d; +// +// public TestEntityD getD() { +// return d; +// } +// +// public void setD(final TestEntityD d) { +// this.d = d; +// } +// } +// +// protected interface TestEntityD { +// String getD(); +// +// void setD(String d); +// } +// +// public static class TestEntityDImpl implements TestEntityD { +// private String d = "d"; +// +// @Override +// public String getD() { +// return d; +// } +// +// @Override +// public void setD(final String d) { +// this.d = d; +// } +// } +// +// @Test +// void fromInterface() throws JsonProcessingException { +// final TestEntityC entity = new TestEntityC(); +// entity.setD(new TestEntityDImpl()); +// final VPackSlice vpack = new VPackSlice(mapper.writeValueAsBytes(entity)); +// assertThat(vpack).isNotNull(); +// assertThat(vpack.isObject()).isTrue(); +// { +// final VPackSlice d = vpack.get("d"); +// assertThat(d.isObject()).isTrue(); +// final VPackSlice dd = d.get("d"); +// assertThat(dd.isString()).isTrue(); +// assertThat(dd.getAsString()).isEqualTo("d"); +// } +// } +// +// @Test +// void toInterface() { +// final VPackBuilder builder = new VPackBuilder(); +// { +// builder.add(ValueType.OBJECT); +// builder.add("d", ValueType.OBJECT); +// builder.add("d", "test"); +// builder.close(); +// builder.close(); +// } +// final VPackSlice slice = builder.slice(); +// final VPack vPack = new VPack.Builder() +// .registerInstanceCreator(TestEntityD.class, (VPackInstanceCreator) TestEntityDImpl::new).build(); +// final TestEntityC entity = vPack.deserialize(slice, TestEntityC.class); +// assertThat(entity).isNotNull(); +// assertThat(entity.d).isNotNull(); +// assertThat(entity.d.getD()).isEqualTo("test"); +// } +// +// public static class TestEntityCollection { +// private Collection c1 = new LinkedList<>(); +// private List c2 = new ArrayList<>(); +// private ArrayList c3 = new ArrayList<>(); +// private Set c4 = new LinkedHashSet<>(); +// private HashSet c5 = new HashSet<>(); +// +// public TestEntityCollection() { +// super(); +// } +// +// public Collection getC1() { +// return c1; +// } +// +// public void setC1(final Collection c1) { +// this.c1 = c1; +// } +// +// public List getC2() { +// return c2; +// } +// +// public void setC2(final List c2) { +// this.c2 = c2; +// } +// +// public ArrayList getC3() { +// return c3; +// } +// +// public void setC3(final ArrayList c3) { +// this.c3 = c3; +// } +// +// public Set getC4() { +// return c4; +// } +// +// public void setC4(final Set c4) { +// this.c4 = c4; +// } +// +// public HashSet getC5() { +// return c5; +// } +// +// public void setC5(final HashSet c5) { +// this.c5 = c5; +// } +// } +// +// @Test +// void fromCollection() throws JsonProcessingException { +// final TestEntityCollection entity = new TestEntityCollection(); +// { +// entity.c1.add("test"); +// entity.c2.add("test"); +// entity.c3.add("test"); +// entity.c4.add("test"); +// entity.c5.add("test"); +// } +// final VPackSlice vpack = new VPackSlice(mapper.writeValueAsBytes(entity)); +// assertThat(vpack).isNotNull(); +// assertThat(vpack.isObject()).isTrue(); +// { +// final VPackSlice c1 = vpack.get("c1"); +// assertThat(c1.isArray()).isTrue(); +// assertThat(c1.getLength()).isEqualTo(1); +// assertThat(c1.get(0).getAsString()).isEqualTo("test"); +// } +// { +// final VPackSlice c2 = vpack.get("c2"); +// assertThat(c2.isArray()).isTrue(); +// assertThat(c2.getLength()).isEqualTo(1); +// assertThat(c2.get(0).getAsString()).isEqualTo("test"); +// } +// { +// final VPackSlice c3 = vpack.get("c3"); +// assertThat(c3.isArray()).isTrue(); +// assertThat(c3.getLength()).isEqualTo(1); +// assertThat(c3.get(0).getAsString()).isEqualTo("test"); +// } +// { +// final VPackSlice c4 = vpack.get("c4"); +// assertThat(c4.isArray()).isTrue(); +// assertThat(c4.getLength()).isEqualTo(1); +// assertThat(c4.get(0).getAsString()).isEqualTo("test"); +// } +// { +// final VPackSlice c5 = vpack.get("c5"); +// assertThat(c5.isArray()).isTrue(); +// assertThat(c5.getLength()).isEqualTo(1); +// assertThat(c5.get(0).getAsString()).isEqualTo("test"); +// } +// } +// +// @Test +// void toCollection() throws IOException { +// final VPackBuilder builder = new VPackBuilder(); +// { +// builder.add(ValueType.OBJECT); +// { +// builder.add("c1", ValueType.ARRAY); +// builder.add("test1"); +// builder.add("test2"); +// builder.close(); +// } +// { +// builder.add("c2", ValueType.ARRAY); +// builder.add("test1"); +// builder.add("test2"); +// builder.close(); +// } +// { +// builder.add("c3", ValueType.ARRAY); +// builder.add("test1"); +// builder.add("test2"); +// builder.close(); +// } +// { +// builder.add("c4", ValueType.ARRAY); +// builder.add("test1"); +// builder.add("test2"); +// builder.close(); +// } +// { +// builder.add("c5", ValueType.ARRAY); +// builder.add("test1"); +// builder.add("test2"); +// builder.close(); +// } +// builder.close(); +// } +// final VPackSlice vpack = builder.slice(); +// final TestEntityCollection entity = mapper.readValue(vpack.getBuffer(), TestEntityCollection.class); +// assertThat(entity).isNotNull(); +// { +// checkCollection(entity.c1); +// checkCollection(entity.c2); +// checkCollection(entity.c3); +// checkCollection(entity.c4); +// checkCollection(entity.c5); +// } +// } +// +// private void checkCollection(final Collection col) { +// assertThat(col).isNotNull(); +// assertThat(col).hasSize(2); +// for (final String next : col) { +// assertThat("test1".equals(next) || "test2".equals(next)).isTrue(); +// } +// } +// +// public static class TestEntityCollectionWithObjects { +// private Collection c1; +// private Set c2; +// +// public Collection getC1() { +// return c1; +// } +// +// public void setC1(final Collection c1) { +// this.c1 = c1; +// } +// +// public Set getC2() { +// return c2; +// } +// +// public void setC2(final Set c2) { +// this.c2 = c2; +// } +// } +// +// @Test +// void fromCollectionWithObjects() throws JsonProcessingException { +// final TestEntityCollectionWithObjects entity = new TestEntityCollectionWithObjects(); +// { +// final Collection c1 = new ArrayList<>(); +// c1.add(new TestEntityString()); +// c1.add(new TestEntityString()); +// entity.setC1(c1); +// final Set c2 = new HashSet<>(); +// c2.add(new TestEntityArray()); +// entity.setC2(c2); +// } +// final VPackSlice vpack = new VPackSlice(mapper.writeValueAsBytes(entity)); +// assertThat(vpack).isNotNull(); +// assertThat(vpack.isObject()).isTrue(); +// { +// final VPackSlice c1 = vpack.get("c1"); +// assertThat(c1.isArray()).isTrue(); +// assertThat(c1.getLength()).isEqualTo(2); +// assertThat(c1.get(0).isObject()).isTrue(); +// assertThat(c1.get(1).isObject()).isTrue(); +// { +// final VPackSlice s = c1.get(0).get("s"); +// assertThat(s.isString()).isTrue(); +// assertThat(s.getAsString()).isEqualTo("test"); +// } +// } +// { +// final VPackSlice c2 = vpack.get("c2"); +// assertThat(c2.isArray()).isTrue(); +// assertThat(c2.getLength()).isEqualTo(1); +// assertThat(c2.get(0).isObject()).isTrue(); +// { +// final VPackSlice a2 = c2.get(0).get("a2"); +// assertThat(a2.isArray()).isTrue(); +// assertThat(a2.getLength()).isEqualTo(5); +// for (int i = 0; i < a2.getLength(); i++) { +// final VPackSlice at = a2.get(i); +// assertThat(at.isInteger()).isTrue(); +// assertThat(at.getAsInt()).isEqualTo(i + 1); +// } +// } +// } +// } +// +// @Test +// void toCollectionWithObjects() throws IOException { +// final VPackBuilder builder = new VPackBuilder(); +// { +// builder.add(ValueType.OBJECT); +// { +// builder.add("c1", ValueType.ARRAY); +// builder.add(ValueType.OBJECT); +// builder.add("s", "abc"); +// builder.close(); +// builder.close(); +// } +// { +// builder.add("c2", ValueType.ARRAY); +// builder.add(ValueType.OBJECT); +// builder.add("a2", ValueType.ARRAY); +// for (int i = 0; i < 10; i++) { +// builder.add(i); +// } +// builder.close(); +// builder.close(); +// builder.close(); +// } +// builder.close(); +// } +// final VPackSlice vpack = builder.slice(); +// final TestEntityCollectionWithObjects entity = mapper.readValue(vpack.getBuffer(), +// TestEntityCollectionWithObjects.class); +// assertThat(entity).isNotNull(); +// { +// assertThat(entity.c1).isNotNull(); +// assertThat(entity.c1).hasSize(1); +// assertThat(entity.c1.iterator().next().s).isEqualTo("abc"); +// } +// { +// assertThat(entity.c2).isNotNull(); +// assertThat(entity.c2).hasSize(1); +// final int[] array = entity.c2.iterator().next().a2; +// for (int i = 0; i < array.length; i++) { +// assertThat(array[i]).isEqualTo(i); +// } +// } +// } +// +// public static class TestEntityMap { +// private Map m1; +// private HashMap m2; +// private Map m3; +// +// public Map getM1() { +// return m1; +// } +// +// public void setM1(final Map m1) { +// this.m1 = m1; +// } +// +// public HashMap getM2() { +// return m2; +// } +// +// public void setM2(final HashMap m2) { +// this.m2 = m2; +// } +// +// public Map getM3() { +// return m3; +// } +// +// public void setM3(final Map m3) { +// this.m3 = m3; +// } +// } +// +// @Test +// void fromMap() throws JsonProcessingException { +// final TestEntityMap entity = new TestEntityMap(); +// { +// final Map m1 = new LinkedHashMap<>(); +// m1.put("a", "b"); +// m1.put("c", "d"); +// entity.setM1(m1); +// final HashMap m2 = new HashMap<>(); +// m2.put(1, "a"); +// m2.put(2, "b"); +// entity.setM2(m2); +// final Map m3 = new HashMap<>(); +// final TestEntityString s = new TestEntityString(); +// s.setS("abc"); +// m3.put("a", s); +// entity.setM3(m3); +// } +// final VPackSlice vpack = new VPackSlice(mapper.writeValueAsBytes(entity)); +// assertThat(vpack).isNotNull(); +// assertThat(vpack.isObject()).isTrue(); +// { +// final VPackSlice m1 = vpack.get("m1"); +// assertThat(m1.isObject()).isTrue(); +// assertThat(m1.getLength()).isEqualTo(2); +// { +// final VPackSlice a = m1.get("a"); +// assertThat(a.isString()).isTrue(); +// assertThat(a.getAsString()).isEqualTo("b"); +// } +// { +// final VPackSlice c = m1.get("c"); +// assertThat(c.isString()).isTrue(); +// assertThat(c.getAsString()).isEqualTo("d"); +// } +// } +// { +// final VPackSlice m2 = vpack.get("m2"); +// assertThat(m2.isObject()).isTrue(); +// assertThat(m2.getLength()).isEqualTo(2); +// { +// final VPackSlice one = m2.get("1"); +// assertThat(one.isString()).isTrue(); +// assertThat(one.getAsString()).isEqualTo("a"); +// } +// { +// final VPackSlice two = m2.get("2"); +// assertThat(two.isString()).isTrue(); +// assertThat(two.getAsString()).isEqualTo("b"); +// } +// } +// { +// final VPackSlice m3 = vpack.get("m3"); +// assertThat(m3.isObject()).isTrue(); +// assertThat(m3.getLength()).isEqualTo(1); +// final VPackSlice a = m3.get("a"); +// assertThat(a.isObject()).isTrue(); +// final VPackSlice s = a.get("s"); +// assertThat(s.isString()).isTrue(); +// assertThat(s.getAsString()).isEqualTo("abc"); +// } +// } +// +// @Test +// void toMap() throws IOException { +// final VPackBuilder builder = new VPackBuilder(); +// { +// builder.add(ValueType.OBJECT); +// { +// builder.add("m1", ValueType.OBJECT); +// builder.add("a", "a"); +// builder.add("b", "b"); +// builder.close(); +// } +// { +// builder.add("m2", ValueType.OBJECT); +// builder.add("1", "a"); +// builder.add("-1", "a"); +// builder.close(); +// } +// { +// builder.add("m3", ValueType.OBJECT); +// builder.add("a", ValueType.OBJECT); +// builder.add("s", "abc"); +// builder.close(); +// builder.close(); +// } +// builder.close(); +// } +// final VPackSlice vpack = builder.slice(); +// final TestEntityMap entity = mapper.readValue(vpack.getBuffer(), TestEntityMap.class); +// assertThat(entity).isNotNull(); +// { +// assertThat(entity.m1).isNotNull(); +// assertThat(entity.m1).hasSize(2); +// final String a = entity.m1.get("a"); +// assertThat(a).isNotNull(); +// assertThat(a).isEqualTo("a"); +// final String b = entity.m1.get("b"); +// assertThat(b).isNotNull(); +// assertThat(b).isEqualTo("b"); +// } +// { +// assertThat(entity.m2).isNotNull(); +// assertThat(entity.m2).hasSize(2); +// final String one = entity.m2.get(1); +// assertThat(one).isNotNull(); +// assertThat(one).isEqualTo("a"); +// final String oneNegative = entity.m2.get(-1); +// assertThat(oneNegative).isNotNull(); +// assertThat(oneNegative).isEqualTo("a"); +// } +// { +// assertThat(entity.m3).isNotNull(); +// assertThat(entity.m3).hasSize(1); +// final TestEntityString a = entity.m3.get("a"); +// assertThat(a).isNotNull(); +// assertThat(a.s).isEqualTo("abc"); +// } +// } +// +// public static class TestEntityMapStringableKey { +// private Map m1; +// private Map m2; +// private Map m3; +// private Map m4; +// private Map m5; +// private Map m6; +// private Map m7; +// private Map m8; +// private Map m9; +// private Map m10; +// private Map m11; +// +// public Map getM1() { +// return m1; +// } +// +// public void setM1(final Map m1) { +// this.m1 = m1; +// } +// +// public Map getM2() { +// return m2; +// } +// +// public void setM2(final Map m2) { +// this.m2 = m2; +// } +// +// public Map getM3() { +// return m3; +// } +// +// public void setM3(final Map m3) { +// this.m3 = m3; +// } +// +// public Map getM4() { +// return m4; +// } +// +// public void setM4(final Map m4) { +// this.m4 = m4; +// } +// +// public Map getM5() { +// return m5; +// } +// +// public void setM5(final Map m5) { +// this.m5 = m5; +// } +// +// public Map getM6() { +// return m6; +// } +// +// public void setM6(final Map m6) { +// this.m6 = m6; +// } +// +// public Map getM7() { +// return m7; +// } +// +// public void setM7(final Map m7) { +// this.m7 = m7; +// } +// +// public Map getM8() { +// return m8; +// } +// +// public void setM8(final Map m8) { +// this.m8 = m8; +// } +// +// public Map getM9() { +// return m9; +// } +// +// public void setM9(final Map m9) { +// this.m9 = m9; +// } +// +// public Map getM10() { +// return m10; +// } +// +// public void setM10(final Map m10) { +// this.m10 = m10; +// } +// +// public Map getM11() { +// return m11; +// } +// +// public void setM11(final Map m11) { +// this.m11 = m11; +// } +// +// } +// +// @Test +// void fromMapStringableKey() throws JsonProcessingException { +// final TestEntityMapStringableKey entity = new TestEntityMapStringableKey(); +// final String value = "test"; +// { +// final Map m1 = new HashMap<>(); +// m1.put(true, value); +// m1.put(false, value); +// entity.setM1(m1); +// } +// { +// final Map m2 = new HashMap<>(); +// m2.put(1, value); +// m2.put(2, value); +// entity.setM2(m2); +// } +// { +// final Map m3 = new HashMap<>(); +// m3.put(1L, value); +// m3.put(2L, value); +// entity.setM3(m3); +// } +// { +// final Map m4 = new HashMap<>(); +// m4.put(1.5F, value); +// m4.put(2.25F, value); +// entity.setM4(m4); +// } +// { +// final Map m5 = new HashMap<>(); +// m5.put(Short.valueOf("1"), value); +// m5.put(Short.valueOf("2"), value); +// entity.setM5(m5); +// } +// { +// final Map m6 = new HashMap<>(); +// m6.put(1.5, value); +// m6.put(2.25, value); +// entity.setM6(m6); +// } +// { +// final Map m7 = new HashMap<>(); +// m7.put(1.5, value); +// m7.put(1L, value); +// entity.setM7(m7); +// } +// { +// final Map m8 = new HashMap<>(); +// m8.put(new BigInteger("1"), value); +// m8.put(new BigInteger("2"), value); +// entity.setM8(m8); +// } +// { +// final Map m9 = new HashMap<>(); +// m9.put(new BigDecimal("1.5"), value); +// m9.put(new BigDecimal("2.25"), value); +// entity.setM9(m9); +// } +// { +// final Map m10 = new HashMap<>(); +// m10.put('1', value); +// m10.put('a', value); +// entity.setM10(m10); +// } +// { +// final Map m11 = new HashMap<>(); +// m11.put(TestEnum.A, value); +// m11.put(TestEnum.B, value); +// entity.setM11(m11); +// } +// final VPackSlice vpack = new VPackSlice(mapper.writeValueAsBytes(entity)); +// assertThat(vpack).isNotNull(); +// assertThat(vpack.isObject()).isTrue(); +// { +// final VPackSlice m1 = vpack.get("m1"); +// assertThat(m1.isObject()).isTrue(); +// assertThat(m1.getLength()).isEqualTo(2); +// checkMapAttribute(m1.get("true")); +// checkMapAttribute(m1.get("false")); +// } +// { +// final VPackSlice m2 = vpack.get("m2"); +// assertThat(m2.isObject()).isTrue(); +// assertThat(m2.getLength()).isEqualTo(2); +// checkMapAttribute(m2.get("1")); +// checkMapAttribute(m2.get("2")); +// } +// { +// final VPackSlice m3 = vpack.get("m3"); +// assertThat(m3.isObject()).isTrue(); +// assertThat(m3.getLength()).isEqualTo(2); +// checkMapAttribute(m3.get("1")); +// checkMapAttribute(m3.get("2")); +// } +// { +// final VPackSlice m4 = vpack.get("m4"); +// assertThat(m4.isObject()).isTrue(); +// assertThat(m4.getLength()).isEqualTo(2); +// checkMapAttribute(m4.get("1.5")); +// checkMapAttribute(m4.get("2.25")); +// } +// { +// final VPackSlice m5 = vpack.get("m5"); +// assertThat(m5.isObject()).isTrue(); +// assertThat(m5.getLength()).isEqualTo(2); +// checkMapAttribute(m5.get("1")); +// checkMapAttribute(m5.get("2")); +// } +// { +// final VPackSlice m6 = vpack.get("m6"); +// assertThat(m6.isObject()).isTrue(); +// assertThat(m6.getLength()).isEqualTo(2); +// checkMapAttribute(m6.get("1.5")); +// checkMapAttribute(m6.get("2.25")); +// } +// { +// final VPackSlice m7 = vpack.get("m7"); +// assertThat(m7.isObject()).isTrue(); +// assertThat(m7.getLength()).isEqualTo(2); +// checkMapAttribute(m7.get("1.5")); +// checkMapAttribute(m7.get("1")); +// } +// { +// final VPackSlice m8 = vpack.get("m8"); +// assertThat(m8.isObject()).isTrue(); +// assertThat(m8.getLength()).isEqualTo(2); +// checkMapAttribute(m8.get("1")); +// checkMapAttribute(m8.get("2")); +// } +// { +// final VPackSlice m9 = vpack.get("m9"); +// assertThat(m9.isObject()).isTrue(); +// assertThat(m9.getLength()).isEqualTo(2); +// checkMapAttribute(m9.get("1.5")); +// checkMapAttribute(m9.get("2.25")); +// } +// { +// final VPackSlice m10 = vpack.get("m10"); +// assertThat(m10.isObject()).isTrue(); +// assertThat(m10.getLength()).isEqualTo(2); +// checkMapAttribute(m10.get("1")); +// checkMapAttribute(m10.get("a")); +// } +// { +// final VPackSlice m11 = vpack.get("m11"); +// assertThat(m11.isObject()).isTrue(); +// assertThat(m11.getLength()).isEqualTo(2); +// checkMapAttribute(m11.get(TestEnum.A.name())); +// checkMapAttribute(m11.get(TestEnum.B.name())); +// } +// } +// +// @Test +// void toMapSringableKey() { +// final VPackBuilder builder = new VPackBuilder(); +// builder.add(ValueType.OBJECT); +// { +// builder.add("m1", ValueType.OBJECT); +// builder.add("true", "test"); +// builder.add("false", "test"); +// builder.close(); +// } +// { +// builder.add("m2", ValueType.OBJECT); +// builder.add("1", "test"); +// builder.add("2", "test"); +// builder.close(); +// } +// { +// builder.add("m3", ValueType.OBJECT); +// builder.add("1", "test"); +// builder.add("2", "test"); +// builder.close(); +// } +// { +// builder.add("m4", ValueType.OBJECT); +// builder.add("1.5", "test"); +// builder.add("2.25", "test"); +// builder.close(); +// } +// { +// builder.add("m5", ValueType.OBJECT); +// builder.add("1", "test"); +// builder.add("2", "test"); +// builder.close(); +// } +// { +// builder.add("m6", ValueType.OBJECT); +// builder.add("1.5", "test"); +// builder.add("2.25", "test"); +// builder.close(); +// } +// { +// builder.add("m7", ValueType.OBJECT); +// builder.add("1.5", "test"); +// builder.add("1", "test"); +// builder.close(); +// } +// { +// builder.add("m8", ValueType.OBJECT); +// builder.add("1", "test"); +// builder.add("2", "test"); +// builder.close(); +// } +// { +// builder.add("m9", ValueType.OBJECT); +// builder.add("1.5", "test"); +// builder.add("2.25", "test"); +// builder.close(); +// } +// { +// builder.add("m10", ValueType.OBJECT); +// builder.add("1", "test"); +// builder.add("a", "test"); +// builder.close(); +// } +// { +// builder.add("m11", ValueType.OBJECT); +// builder.add(TestEnum.A.name(), "test"); +// builder.add(TestEnum.B.name(), "test"); +// builder.close(); +// } +// builder.close(); +// final TestEntityMapStringableKey entity = new VPack.Builder().build().deserialize(builder.slice(), +// TestEntityMapStringableKey.class); +// { +// assertThat(entity.m1).hasSize(2); +// checkMapAttribute(entity.m1.get(true)); +// checkMapAttribute(entity.m1.get(false)); +// } +// { +// assertThat(entity.m2).hasSize(2); +// checkMapAttribute(entity.m2.get(1)); +// checkMapAttribute(entity.m2.get(2)); +// } +// { +// assertThat(entity.m3).hasSize(2); +// checkMapAttribute(entity.m3.get(1L)); +// checkMapAttribute(entity.m3.get(2L)); +// } +// { +// assertThat(entity.m4).hasSize(2); +// checkMapAttribute(entity.m4.get(1.5F)); +// checkMapAttribute(entity.m4.get(2.25F)); +// } +// { +// assertThat(entity.m5).hasSize(2); +// checkMapAttribute(entity.m5.get(Short.valueOf("1"))); +// checkMapAttribute(entity.m5.get(Short.valueOf("2"))); +// } +// { +// assertThat(entity.m6).hasSize(2); +// checkMapAttribute(entity.m6.get(1.5)); +// checkMapAttribute(entity.m6.get(2.25)); +// } +// { +// assertThat(entity.m7).hasSize(2); +// checkMapAttribute(entity.m7.get(1.5)); +// checkMapAttribute(entity.m7.get((double) 1L)); +// } +// { +// assertThat(entity.m8).hasSize(2); +// checkMapAttribute(entity.m8.get(new BigInteger("1"))); +// checkMapAttribute(entity.m8.get(new BigInteger("2"))); +// } +// { +// assertThat(entity.m9).hasSize(2); +// checkMapAttribute(entity.m9.get(new BigDecimal("1.5"))); +// checkMapAttribute(entity.m9.get(new BigDecimal("2.25"))); +// } +// { +// assertThat(entity.m10).hasSize(2); +// checkMapAttribute(entity.m10.get('1')); +// checkMapAttribute(entity.m10.get('a')); +// } +// { +// assertThat(entity.m11).hasSize(2); +// checkMapAttribute(entity.m11.get(TestEnum.A)); +// checkMapAttribute(entity.m11.get(TestEnum.B)); +// } +// } +// +// private void checkMapAttribute(final VPackSlice attr) { +// assertThat(attr.isString()).isTrue(); +// assertThat(attr.getAsString()).isEqualTo("test"); +// } +// +// private void checkMapAttribute(final String attr) { +// assertThat(attr).isEqualTo("test"); +// } +// +// public static class TestEntityMapWithObjectKey { +// private Map m1; +// private Map m2; +// +// public Map getM1() { +// return m1; +// } +// +// public void setM1(final Map m1) { +// this.m1 = m1; +// } +// +// public Map getM2() { +// return m2; +// } +// +// public void setM2(final Map m2) { +// this.m2 = m2; +// } +// } +// +// @Test +// void toMapWithObjectKey() { +// final int size = 2; +// final VPackBuilder builder = new VPackBuilder(); +// builder.add(ValueType.OBJECT); +// { +// builder.add("m1", ValueType.ARRAY); +// for (int i = 0; i < size; i++) { +// builder.add(ValueType.OBJECT); +// { +// builder.add("key", ValueType.OBJECT); +// builder.add("l1", 5L); +// builder.close(); +// } +// { +// builder.add("value", ValueType.OBJECT); +// builder.add("c1", ValueType.ARRAY); +// builder.add("test"); +// builder.close(); +// builder.close(); +// } +// builder.close(); +// } +// builder.close(); +// } +// { +// builder.add("m2", ValueType.ARRAY); +// for (int i = 0; i < size; i++) { +// builder.add(ValueType.OBJECT); +// { +// builder.add("key", ValueType.OBJECT); +// builder.add("l1", 5L); +// builder.close(); +// } +// { +// builder.add("value", "test"); +// } +// builder.close(); +// } +// builder.close(); +// } +// builder.close(); +// final TestEntityMapWithObjectKey entity = new VPack.Builder().build().deserialize(builder.slice(), +// TestEntityMapWithObjectKey.class); +// assertThat(entity).isNotNull(); +// { +// assertThat(entity.m1).isNotNull(); +// assertThat(entity.m1).hasSize(size); +// for (final Entry entry : entity.m1.entrySet()) { +// assertThat(entry.getKey().l1).isEqualTo(5L); +// assertThat(entry.getValue().c1).hasSize(1); +// assertThat(entry.getValue().c1.iterator().next()).isEqualTo("test"); +// } +// } +// { +// assertThat(entity.m2).isNotNull(); +// assertThat(entity.m2).hasSize(2); +// for (final Entry entry : entity.m2.entrySet()) { +// assertThat(entry.getKey().l1).isEqualTo(5L); +// assertThat(entry.getValue()).isEqualTo("test"); +// } +// } +// } +// +// public static class TestEntityEmpty { +// +// } +// +// @Test +// void fromEmptyObject() throws JsonProcessingException { +// final VPackSlice vpack = new VPackSlice(mapper.writeValueAsBytes(new TestEntityEmpty())); +// assertThat(vpack).isNotNull(); +// assertThat(vpack.isObject()).isTrue(); +// assertThat(vpack.getLength()).isZero(); +// } +// +// @Test +// void toEmptyObject() { +// final VPackBuilder builder = new VPackBuilder(); +// builder.add(ValueType.OBJECT); +// builder.close(); +// final TestEntityEmpty entity = new VPack.Builder().build().deserialize(builder.slice(), TestEntityEmpty.class); +// assertThat(entity).isNotNull(); +// } +// +// public static class TestEntityEmptyMap { +// private Map m; +// +// public Map getM() { +// return m; +// } +// +// public void setM(final Map m) { +// this.m = m; +// } +// } +// +// @Test +// void fromEmptyMap() throws JsonProcessingException { +// final TestEntityEmptyMap entity = new TestEntityEmptyMap(); +// entity.setM(new HashMap<>()); +// final VPackSlice vpack = new VPackSlice(mapper.writeValueAsBytes(entity)); +// assertThat(vpack).isNotNull(); +// assertThat(vpack.isObject()).isTrue(); +// assertThat(vpack.getLength()).isEqualTo(1); +// final VPackSlice m = vpack.get("m"); +// assertThat(m.isObject()).isTrue(); +// assertThat(m.getLength()).isZero(); +// } +// +// @Test +// void toEmptyMap() { +// final VPackBuilder builder = new VPackBuilder(); +// builder.add(ValueType.OBJECT); +// builder.add("m", ValueType.OBJECT); +// builder.close(); +// builder.close(); +// final TestEntityEmptyMap entity = new VPack.Builder().build().deserialize(builder.slice(), +// TestEntityEmptyMap.class); +// assertThat(entity).isNotNull(); +// assertThat(entity.m).isNotNull(); +// assertThat(entity.m).isEmpty(); +// } +// +// public static class TestEntityBaseAttributes { +// private String _key = "test1"; +// private String _rev = "test2"; +// private String _id = "test3"; +// private String _from = "test4"; +// private String _to = "test5"; +// +// public String get_key() { +// return _key; +// } +// +// public void set_key(final String _key) { +// this._key = _key; +// } +// +// public String get_rev() { +// return _rev; +// } +// +// public void set_rev(final String _rev) { +// this._rev = _rev; +// } +// +// public String get_id() { +// return _id; +// } +// +// public void set_id(final String _id) { +// this._id = _id; +// } +// +// public String get_from() { +// return _from; +// } +// +// public void set_from(final String _from) { +// this._from = _from; +// } +// +// public String get_to() { +// return _to; +// } +// +// public void set_to(final String _to) { +// this._to = _to; +// } +// +// } +// +// @Test +// void fromObjectWithAttributeAdapter() throws JsonProcessingException { +// final VPackSlice vpack = new VPackSlice(mapper.writeValueAsBytes(new TestEntityBaseAttributes())); +// assertThat(vpack.isObject()).isTrue(); +// assertThat(vpack.getLength()).isEqualTo(5); +// { +// final VPackSlice key = vpack.get("_key"); +// assertThat(key.isString()).isTrue(); +// assertThat(key.getAsString()).isEqualTo("test1"); +// } +// { +// final VPackSlice rev = vpack.get("_rev"); +// assertThat(rev.isString()).isTrue(); +// assertThat(rev.getAsString()).isEqualTo("test2"); +// } +// { +// final VPackSlice id = vpack.get("_id"); +// assertThat(id.isString()).isTrue(); +// assertThat(id.getAsString()).isEqualTo("test3"); +// } +// { +// final VPackSlice from = vpack.get("_from"); +// assertThat(from.isString()).isTrue(); +// assertThat(from.getAsString()).isEqualTo("test4"); +// } +// { +// final VPackSlice to = vpack.get("_to"); +// assertThat(to.isString()).isTrue(); +// assertThat(to.getAsString()).isEqualTo("test5"); +// } +// } +// +// @Test +// void toObjectWithAttributeAdapter() { +// final VPackBuilder builder = new VPackBuilder(); +// { +// builder.add(ValueType.OBJECT); +// builder.add("_key", "a"); +// builder.add("_rev", "b"); +// builder.add("_id", "c"); +// builder.add("_from", "d"); +// builder.add("_to", "e"); +// builder.close(); +// } +// final TestEntityBaseAttributes entity = new VPack.Builder().build().deserialize(builder.slice(), +// TestEntityBaseAttributes.class); +// assertThat(entity).isNotNull(); +// assertThat(entity._key).isEqualTo("a"); +// assertThat(entity._rev).isEqualTo("b"); +// assertThat(entity._id).isEqualTo("c"); +// assertThat(entity._from).isEqualTo("d"); +// assertThat(entity._to).isEqualTo("e"); +// } +// +// @Test +// void fromMapWithAttributeAdapter() throws JsonProcessingException { +// final TestEntityMap entity = new TestEntityMap(); +// { +// final Map m1 = new HashMap<>(); +// m1.put("_key", "test1"); +// m1.put("_rev", "test2"); +// m1.put("_id", "test3"); +// m1.put("_from", "test4"); +// m1.put("_to", "test5"); +// entity.setM1(m1); +// } +// final VPackSlice vpack = new VPackSlice(mapper.writeValueAsBytes(entity)); +// assertThat(vpack.isObject()).isTrue(); +// final VPackSlice m1 = vpack.get("m1"); +// assertThat(m1.isObject()).isTrue(); +// assertThat(m1.getLength()).isEqualTo(5); +// { +// final VPackSlice key = m1.get("_key"); +// assertThat(key.isString()).isTrue(); +// assertThat(key.getAsString()).isEqualTo("test1"); +// } +// { +// final VPackSlice rev = m1.get("_rev"); +// assertThat(rev.isString()).isTrue(); +// assertThat(rev.getAsString()).isEqualTo("test2"); +// } +// { +// final VPackSlice id = m1.get("_id"); +// assertThat(id.isString()).isTrue(); +// assertThat(id.getAsString()).isEqualTo("test3"); +// } +// { +// final VPackSlice from = m1.get("_from"); +// assertThat(from.isString()).isTrue(); +// assertThat(from.getAsString()).isEqualTo("test4"); +// } +// { +// final VPackSlice to = m1.get("_to"); +// assertThat(to.isString()).isTrue(); +// assertThat(to.getAsString()).isEqualTo("test5"); +// } +// } +// +// @Test +// void toMapWithAttributeAdapter() { +// final VPackBuilder builder = new VPackBuilder(); +// { +// builder.add(ValueType.OBJECT); +// builder.add("m1", ValueType.OBJECT); +// builder.add("_key", "a"); +// builder.add("_rev", "b"); +// builder.add("_id", "c"); +// builder.add("_from", "d"); +// builder.add("_to", "e"); +// builder.close(); +// builder.close(); +// } +// final TestEntityMap entity = new VPack.Builder().build().deserialize(builder.slice(), TestEntityMap.class); +// assertThat(entity).isNotNull(); +// assertThat(entity.m1).hasSize(5); +// } +// +// @Retention(RetentionPolicy.RUNTIME) +// @Target(ElementType.FIELD) +// private @interface CustomFilterAnnotation { +// boolean serialize() +// +// default true; +// +// boolean deserialize() default true; +// } +// +// @Retention(RetentionPolicy.RUNTIME) +// @Target(ElementType.FIELD) +// private @interface CustomNamingAnnotation { +// String name(); +// } +// +// private static class CustomAnEntity { +// @CustomFilterAnnotation(serialize = false) +// private String a = null; +// @CustomFilterAnnotation(deserialize = false) +// private String b = null; +// @CustomNamingAnnotation(name = "d") +// @CustomFilterAnnotation(deserialize = false) +// private String c = null; +// +// CustomAnEntity() { +// super(); +// } +// } +// +// @Test +// void fromCutsomAnnotation() { +// final CustomAnEntity entity = new CustomAnEntity(); +// entity.a = "1"; +// entity.b = "2"; +// entity.c = "3"; +// final VPackSlice vpack = new VPack.Builder().annotationFieldFilter(CustomFilterAnnotation.class, +// new VPackAnnotationFieldFilter() { +// +// @Override +// public boolean serialize(final CustomFilterAnnotation annotation) { +// return annotation.serialize(); +// } +// +// @Override +// public boolean deserialize(final CustomFilterAnnotation annotation) { +// return annotation.deserialize(); +// } +// }).annotationFieldNaming(CustomNamingAnnotation.class, +// CustomNamingAnnotation::name).build().serialize(entity); +// assertThat(vpack).isNotNull(); +// assertThat(vpack.isObject()).isTrue(); +// assertThat(vpack.get("a").isNone()).isTrue(); +// assertThat(vpack.get("b").isString()).isTrue(); +// assertThat(vpack.get("b").getAsString()).isEqualTo("2"); +// assertThat(vpack.get("c").isNone()).isTrue(); +// assertThat(vpack.get("d").isString()).isTrue(); +// assertThat(vpack.get("d").getAsString()).isEqualTo("3"); +// } +// +// @Test +// void directFromCollection() throws JsonProcessingException { +// final Collection list = new ArrayList<>(); +// list.add("test"); +// final VPackSlice vpack = new VPackSlice(mapper.writeValueAsBytes(list)); +// assertThat(vpack).isNotNull(); +// assertThat(vpack.isArray()).isTrue(); +// assertThat(vpack.size()).isEqualTo(1); +// final VPackSlice test = vpack.get(0); +// assertThat(test.isString()).isTrue(); +// assertThat(test.getAsString()).isEqualTo("test"); +// } +// +// @Test +// void directFromCollectionWithType() throws JsonProcessingException { +// final Collection list = new ArrayList<>(); +// list.add(new TestEntityString()); +// list.add(new TestEntityString()); +// +// final VPackSlice vpack = new VPackSlice(mapper.writeValueAsBytes(list)); +// assertThat(vpack).isNotNull(); +// assertThat(vpack.isArray()).isTrue(); +// assertThat(vpack.getLength()).isEqualTo(list.size()); +// for (int i = 0; i < list.size(); i++) { +// final VPackSlice entry = vpack.get(i); +// assertThat(entry.isObject()).isTrue(); +// assertThat(entry.getLength()).isEqualTo(3); +// final VPackSlice s = entry.get("s"); +// assertThat(s.isString()).isTrue(); +// assertThat(s.getAsString()).isEqualTo("test"); +// } +// } +// +// @Test +// void directToCollection() { +// final VPackBuilder builder = new VPackBuilder(); +// builder.add(ValueType.ARRAY); +// builder.add(ValueType.OBJECT); +// builder.add("s", "abc"); +// builder.close(); +// builder.close(); +// final List list = new VPack.Builder().build().deserialize(builder.slice(), +// new Type>() { +// }.getType()); +// assertThat(list).hasSize(1); +// final TestEntityString entry = list.get(0); +// assertThat(entry.s).isEqualTo("abc"); +// } +// +// @Test +// void directFromStringMap() throws JsonProcessingException { +// final Map map = new HashMap<>(); +// map.put("a", new TestEntityString()); +// map.put("b", new TestEntityString()); +// +// final VPackSlice vpack = new VPackSlice(mapper.writeValueAsBytes(map)); +// assertThat(vpack).isNotNull(); +// assertThat(vpack.isObject()).isTrue(); +// assertThat(vpack.getLength()).isEqualTo(2); +// final VPackSlice a = vpack.get("a"); +// checkStringEntity(a); +// } +// +// @Test +// void directToStringMap() { +// final VPackBuilder builder = new VPackBuilder(); +// builder.add(ValueType.OBJECT); +// builder.add("a", ValueType.OBJECT); +// builder.add("s", "abc"); +// builder.close(); +// builder.close(); +// final Map map = new VPack.Builder().build().deserialize(builder.slice(), +// new Type>() { +// }.getType()); +// assertThat(map).hasSize(1); +// final TestEntityString a = map.get("a"); +// assertThat(a).isNotNull(); +// assertThat(a.s).isEqualTo("abc"); +// } +// +// @Test +// void directFromMap() throws JsonProcessingException { +// final Map map = new HashMap<>(); +// final TestEntityA entity = new TestEntityA(); +// entity.a = "test"; +// map.put("test", entity); +// final VPackSlice vpack = new VPackSlice(mapper.writeValueAsBytes(map)); +// assertThat(vpack).isNotNull(); +// assertThat(vpack.isObject()).isTrue(); +// final VPackSlice test = vpack.get("test"); +// assertThat(test.isObject()).isTrue(); +// final VPackSlice a = test.get("a"); +// assertThat(a.isString()).isTrue(); +// assertThat(a.getAsString()).isEqualTo("test"); +// } +// +// @Test +// void directFromMapWithinMap() throws JsonProcessingException { +// final Map map = new HashMap<>(); +// final Map map2 = new HashMap<>(); +// map2.put("b", "test"); +// map.put("a", map2); +// final VPackSlice vpack = new VPackSlice(mapper.writeValueAsBytes(map)); +// assertThat(vpack).isNotNull(); +// assertThat(vpack.isObject()).isTrue(); +// assertThat(vpack.size()).isEqualTo(1); +// final VPackSlice a = vpack.get("a"); +// assertThat(a.isObject()).isTrue(); +// assertThat(a.size()).isEqualTo(1); +// final VPackSlice b = a.get("b"); +// assertThat(b.isString()).isTrue(); +// assertThat(b.getAsString()).isEqualTo("test"); +// } +// +// private void checkStringEntity(final VPackSlice vpack) { +// final TestEntityString expected = new TestEntityString(); +// assertThat(vpack.isObject()).isTrue(); +// assertThat(vpack.getLength()).isEqualTo(3); +// final VPackSlice s = vpack.get("s"); +// assertThat(s.isString()).isTrue(); +// assertThat(s.getAsString()).isEqualTo(expected.s); +// final VPackSlice c1 = vpack.get("c1"); +// assertThat(c1.isString()).isTrue(); +// assertThat(new Character(c1.getAsChar())).isEqualTo(expected.c1); +// final VPackSlice c2 = vpack.get("c2"); +// assertThat(c2.isString()).isTrue(); +// assertThat(c2.getAsChar()).isEqualTo(expected.c2); +// } +// +// @Test +// void directToObjectMap() { +// final VPackBuilder builder = new VPackBuilder(); +// builder.add(ValueType.ARRAY); +// builder.add(ValueType.OBJECT); +// builder.add("key", ValueType.OBJECT); +// builder.add("s", "abc"); +// builder.close(); +// builder.add("value", ValueType.OBJECT); +// builder.add("s", "abc"); +// builder.close(); +// builder.close(); +// builder.close(); +// final Map map = new VPack.Builder().build().deserialize(builder.slice(), +// new Type>() { +// }.getType()); +// assertThat(map).hasSize(1); +// for (final Entry entry : map.entrySet()) { +// assertThat(entry.getKey().s).isEqualTo("abc"); +// assertThat(entry.getValue().s).isEqualTo("abc"); +// } +// } +// +// @SuppressWarnings("unchecked") +// @Test +// void directToMapWithinMap() { +// final VPackBuilder builder = new VPackBuilder(); +// builder.add(ValueType.OBJECT); +// builder.add("a", ValueType.OBJECT); +// builder.add("b", "test"); +// builder.add("c", true); +// builder.add("d", 1L); +// builder.add("e", 1.5); +// final Date date = new Date(); +// builder.add("f", date); +// builder.add("g", ValueType.ARRAY); +// builder.close(); +// builder.close(); +// builder.close(); +// final Map map = new VPack.Builder().build().deserialize(builder.slice(), Map.class); +// assertThat(map).hasSize(1); +// final Object a = map.get("a"); +// assertThat(Map.class.isAssignableFrom(a.getClass())).isTrue(); +// final Map mapA = (Map) a; +// assertThat(mapA).hasSize(6); +// final Object b = mapA.get("b"); +// assertThat(String.class.isAssignableFrom(b.getClass())).isTrue(); +// assertThat(b).hasToString("test"); +// final Object c = mapA.get("c"); +// assertThat(Boolean.class.isAssignableFrom(c.getClass())).isTrue(); +// assertThat((Boolean) c).isTrue(); +// final Object d = mapA.get("d"); +// assertThat(Number.class.isAssignableFrom(d.getClass())).isTrue(); +// assertThat(((Number) d).longValue()).isEqualTo(1L); +// final Object e = mapA.get("e"); +// assertThat(Double.class.isAssignableFrom(e.getClass())).isTrue(); +// assertThat((Double) e).isEqualTo(1.5); +// final Object f = mapA.get("f"); +// assertThat(Date.class.isAssignableFrom(f.getClass())).isTrue(); +// assertThat((Date) f).isEqualTo(date); +// final Object g = mapA.get("g"); +// assertThat(Collection.class.isAssignableFrom(g.getClass())).isTrue(); +// assertThat(List.class.isAssignableFrom(g.getClass())).isTrue(); +// } +// +// @Test +// void dontSerializeNullValues() { +// final VPack serializer = new VPack.Builder().serializeNullValues(false).build(); +// final TestEntityString entity = new TestEntityString(); +// entity.setS(null); +// final VPackSlice vpack = serializer.serialize(entity); +// assertThat(vpack).isNotNull(); +// assertThat(vpack.isObject()).isTrue(); +// final VPackSlice s = vpack.get("s"); +// assertThat(s.isNone()).isTrue(); +// } +// +// @Test +// void serializeNullValue() { +// final VPack serializer = new VPack.Builder().serializeNullValues(true).build(); +// final TestEntityString entity = new TestEntityString(); +// entity.setS(null); +// final VPackSlice vpack = serializer.serialize(entity); +// assertThat(vpack).isNotNull(); +// final VPackSlice s = vpack.get("s"); +// assertThat(s.isNull()).isTrue(); +// } +// +// @Test +// void toNullValue() { +// final VPackBuilder builder = new VPackBuilder(); +// builder.add(ValueType.OBJECT); +// builder.add("s", ValueType.NULL); +// builder.close(); +// final TestEntityString entity = new VPack.Builder().build().deserialize(builder.slice(), +// TestEntityString.class); +// assertThat(entity).isNotNull(); +// assertThat(entity.s).isNull(); +// assertThat(entity.c1).isNotNull(); +// assertThat(entity.c2).isNotNull(); +// } +// +// @Test +// void toSimpleString() { +// final VPackBuilder builder = new VPackBuilder(); +// builder.add("test"); +// final String s = new VPack.Builder().build().deserialize(builder.slice(), String.class); +// assertThat(s).isEqualTo("test"); +// } +// +// @Test +// void fromSimpleString() throws JsonProcessingException { +// final VPackSlice vpack = new VPackSlice(mapper.writeValueAsBytes("test")); +// assertThat(vpack).isNotNull(); +// assertThat(vpack.isString()).isTrue(); +// assertThat(vpack.getAsString()).isEqualTo("test"); +// } +// +// public static class TestEntityTyped { +// private T e; +// } +// +// @Test +// void fromStringTypedEntity() throws JsonProcessingException { +// final TestEntityTyped entity = new TestEntityTyped<>(); +// entity.e = "test"; +// final VPackSlice vpack = new VPackSlice(mapper.writeValueAsBytes(entity)); +// assertThat(vpack).isNotNull(); +// assertThat(vpack.isObject()).isTrue(); +// final VPackSlice e = vpack.get("e"); +// assertThat(e).isNotNull(); +// assertThat(e.isString()).isTrue(); +// assertThat(e.getAsString()).isEqualTo("test"); +// } +// +// @Test +// void fromObjectTypedEntity() throws JsonProcessingException { +// final TestEntityTyped entity = new TestEntityTyped<>(); +// entity.e = new TestEntityString(); +// entity.e.s = "test2"; +// final VPackSlice vpack = new VPackSlice(mapper.writeValueAsBytes(entity)); +// assertThat(vpack).isNotNull(); +// assertThat(vpack.isObject()).isTrue(); +// final VPackSlice e = vpack.get("e"); +// assertThat(e).isNotNull(); +// assertThat(e.isObject()).isTrue(); +// final VPackSlice s = e.get("s"); +// assertThat(s).isNotNull(); +// assertThat(s.isString()).isTrue(); +// assertThat(s.getAsString()).isEqualTo("test2"); +// } +// +// @Test +// void fromTypedTypedEntity() throws JsonProcessingException { +// final TestEntityTyped> entity = new TestEntityTyped<>(); +// entity.e = new TestEntityTyped<>(); +// entity.e.e = "test"; +// final VPackSlice vpack = new VPackSlice(mapper.writeValueAsBytes(entity)); +// assertThat(vpack).isNotNull(); +// assertThat(vpack.isObject()).isTrue(); +// final VPackSlice e = vpack.get("e"); +// assertThat(e).isNotNull(); +// assertThat(e.isObject()).isTrue(); +// final VPackSlice e2 = e.get("e"); +// assertThat(e2).isNotNull(); +// assertThat(e2.isString()).isTrue(); +// assertThat(e2.getAsString()).isEqualTo("test"); +// } +// +// @Test +// void fieldNamingStrategySerialize() { +// final VPackSlice vpack = new VPack.Builder().fieldNamingStrategy(field -> "bla").build().serialize(new TestEntityA()); +// assertThat(vpack).isNotNull(); +// assertThat(vpack.isObject()).isTrue(); +// final VPackSlice bla = vpack.get("bla"); +// assertThat(bla.isString()).isTrue(); +// assertThat(bla.getAsString()).isEqualTo("a"); +// } +// +// @Test +// void fieldNamingStrategyDeserialize() { +// final VPackBuilder builder = new VPackBuilder(); +// builder.add(ValueType.OBJECT); +// builder.add("bla", "test"); +// builder.close(); +// final TestEntityA entity = new VPack.Builder().fieldNamingStrategy(field -> "bla").build().deserialize(builder.slice(), TestEntityA.class); +// assertThat(entity).isNotNull(); +// assertThat(entity.a).isEqualTo("test"); +// } +// +// @Test +// void serializeVPack() throws JsonProcessingException { +// final VPackBuilder builder = new VPackBuilder(); +// builder.add("test"); +// final VPackSlice slice = builder.slice(); +// final VPackSlice vpack = new VPackSlice(mapper.writeValueAsBytes(slice)); +// assertThat(vpack).isNotNull(); +// assertThat(vpack.isString()).isTrue(); +// assertThat(vpack.getAsString()).isEqualTo("test"); +// } +// +// @Test +// void deserializeVPack() { +// final VPackBuilder builder = new VPackBuilder(); +// builder.add("test"); +// final VPackSlice slice = builder.slice(); +// final VPackSlice vpack = new VPack.Builder().build().deserialize(slice, slice.getClass()); +// assertThat(vpack).isNotNull(); +// assertThat(vpack.isString()).isTrue(); +// assertThat(vpack.getAsString()).isEqualTo("test"); +// } +// +// public static class TestEntityDate { +// private java.util.Date utilDate = new Date(1474988621); +// private java.sql.Date sqlDate = new java.sql.Date(1474988621); +// private java.sql.Timestamp timestamp = new java.sql.Timestamp(1474988621); +// +// public java.util.Date getUtilDate() { +// return utilDate; +// } +// +// public void setUtilDate(final java.util.Date utilDate) { +// this.utilDate = utilDate; +// } +// +// public java.sql.Date getSqlDate() { +// return sqlDate; +// } +// +// public void setSqlDate(final java.sql.Date sqlDate) { +// this.sqlDate = sqlDate; +// } +// +// public java.sql.Timestamp getTimestamp() { +// return timestamp; +// } +// +// public void setTimestamp(final java.sql.Timestamp timestamp) { +// this.timestamp = timestamp; +// } +// +// } +// +// @Test +// void fromDate() throws JsonProcessingException { +// final VPackSlice vpack = new VPackSlice(mapper.writeValueAsBytes(new TestEntityDate())); +// assertThat(vpack).isNotNull(); +// assertThat(vpack.isObject()).isTrue(); +// { +// assertThat(vpack.get("utilDate").isString()).isTrue(); +// assertThat(vpack.get("utilDate").getAsString()).isEqualTo(DATE_FORMAT.format(new Date(1474988621))); +// } +// { +// assertThat(vpack.get("sqlDate").isString()).isTrue(); +// assertThat(vpack.get("sqlDate").getAsString()).isEqualTo(DATE_FORMAT.format(new java.sql.Date(1474988621))); +// } +// { +// assertThat(vpack.get("timestamp").isString()).isTrue(); +// assertThat(vpack.get("timestamp").getAsString()).isEqualTo(DATE_FORMAT.format(new java.sql.Timestamp(1474988621))); +// } +// } +// +// @Test +// void toDate() { +// final VPackBuilder builder = new VPackBuilder(); +// builder.add(ValueType.OBJECT); +// builder.add("utilDate", new Date(1475062216)); +// builder.add("sqlDate", new java.sql.Date(1475062216)); +// builder.add("timestamp", new java.sql.Timestamp(1475062216)); +// builder.close(); +// +// final TestEntityDate entity = new VPack.Builder().build().deserialize(builder.slice(), TestEntityDate.class); +// assertThat(entity).isNotNull(); +// assertThat(entity.utilDate).isEqualTo(new Date(1475062216)); +// assertThat(entity.sqlDate).isEqualTo(new java.sql.Date(1475062216)); +// assertThat(entity.timestamp).isEqualTo(new java.sql.Timestamp(1475062216)); +// } +// +// @Test +// void toDateFromString() { +// final VPackBuilder builder = new VPackBuilder(); +// builder.add(ValueType.OBJECT); +// builder.add("utilDate", DATE_FORMAT.format(new Date(1475062216))); +// builder.add("sqlDate", DATE_FORMAT.format(new java.sql.Date(1475062216))); +// builder.add("timestamp", DATE_FORMAT.format(new java.sql.Timestamp(1475062216))); +// builder.close(); +// +// final TestEntityDate entity = new VPack.Builder().build().deserialize(builder.slice(), TestEntityDate.class); +// assertThat(entity).isNotNull(); +// assertThat(entity.utilDate).isEqualTo(new Date(1475062216)); +// assertThat(entity.sqlDate).isEqualTo(new java.sql.Date(1475062216)); +// assertThat(entity.timestamp).isEqualTo(new java.sql.Timestamp(1475062216)); +// } +// +// public static class TestEntityUUID { +// private UUID uuid; +// +// UUID getUuid() { +// return uuid; +// } +// +// void setUuid(final UUID uuid) { +// this.uuid = uuid; +// } +// } +// +// @Test +// void fromUUID() throws IOException { +// final TestEntityUUID entity = new TestEntityUUID(); +// entity.setUuid(UUID.randomUUID()); +// byte[] bytes = mapper.writeValueAsBytes(entity); +// final VPackSlice vpack = new VPackSlice(bytes); +// assertThat(vpack).isNotNull(); +// assertThat(vpack.isObject()).isTrue(); +// +// final VPackSlice uuid = vpack.get("uuid"); +// assertThat(uuid.isString()).isTrue(); +// assertThat(uuid.getAsString()).isEqualTo(entity.getUuid().toString()); +// assertThat(mapper.readValue(bytes, TestEntityUUID.class).getUuid()).isEqualTo(entity.getUuid()); +// } +// +// @Test +// void toUUID() { +// final UUID uuid = UUID.randomUUID(); +// final VPackBuilder builder = new VPackBuilder(); +// builder.add(ValueType.OBJECT); +// builder.add("uuid", uuid.toString()); +// builder.close(); +// +// final TestEntityUUID entity = new VPack.Builder().build().deserialize(builder.slice(), TestEntityUUID.class); +// assertThat(entity).isNotNull(); +// assertThat(entity.uuid).isEqualTo(uuid); +// } +// +// @Test +// void uuid() { +// final TestEntityUUID entity = new TestEntityUUID(); +// entity.setUuid(UUID.randomUUID()); +// final VPack vpacker = new VPack.Builder().build(); +// final VPackSlice vpack = vpacker.serialize(entity); +// final TestEntityUUID entity2 = vpacker.deserialize(vpack, TestEntityUUID.class); +// assertThat(entity2).isNotNull(); +// assertThat(entity2.getUuid()).isEqualTo(entity.getUuid()); +// } +// +// private static class BinaryEntity { +// private byte[] foo; +// +// BinaryEntity() { +// super(); +// } +// } +// +// @Test +// void fromBinary() throws JsonProcessingException { +// final BinaryEntity entity = new BinaryEntity(); +// entity.foo = "bar".getBytes(); +// final VPackSlice vpack = new VPackSlice(mapper.writeValueAsBytes(entity)); +// assertThat(vpack).isNotNull(); +// assertThat(vpack.isObject()).isTrue(); +// assertThat(vpack.get("foo").isString()).isTrue(); +// assertThat(vpack.get("foo").getAsString()).isEqualTo(Base64.getEncoder().encodeToString(entity.foo)); +// } +// +// @Test +// void toBinary() throws IOException { +// final String value = Base64.getEncoder().encodeToString("bar".getBytes()); +// final VPackSlice vpack = new VPackBuilder().add(ValueType.OBJECT).add("foo", value).close().slice(); +// final BinaryEntity entity = mapper.readValue(vpack.getBuffer(), BinaryEntity.class); +// assertThat(entity).isNotNull(); +// assertThat(entity.foo).isEqualTo("bar".getBytes()); +// } +// +// @Test +// void asFloatingNumber() { +// final VPackSlice vpack = new VPackBuilder().add(ValueType.OBJECT).add("value", 12000).close().slice(); +// assertThat(vpack.get("value").getAsInt()).isEqualTo(12000); +// assertThat(vpack.get("value").getAsFloat()).isEqualTo(12000F); +// assertThat(vpack.get("value").getAsDouble()).isEqualTo(12000.); +// } +// +// @Test +// void toVPackSlice() throws IOException { +// final VPackSlice value = new VPackBuilder().add(ValueType.OBJECT).add("key", "value").close().slice(); +// final VPackSlice entity = mapper.readValue(value.getBuffer(), VPackSlice.class); +// assertThat(entity).isEqualTo(value); +// } +// +// +//} diff --git a/src/test/java/com/arangodb/mapping/annotations/ArangoAnnotationsTest.java b/src/test/java/com/arangodb/mapping/annotations/ArangoAnnotationsTest.java index 9484b7e30..cfd5d8124 100644 --- a/src/test/java/com/arangodb/mapping/annotations/ArangoAnnotationsTest.java +++ b/src/test/java/com/arangodb/mapping/annotations/ArangoAnnotationsTest.java @@ -24,7 +24,6 @@ import com.arangodb.velocypack.VPackSlice; import org.junit.jupiter.api.Test; -import java.util.HashMap; import java.util.Map; import static org.assertj.core.api.Assertions.assertThat; @@ -60,66 +59,4 @@ void documentFieldAnnotations() { assertThat(deserializedEntity).isEqualTo(e); } - @Test - void serializedName() { - SerializedNameEntity e = new SerializedNameEntity(); - e.setA("A"); - e.setB("B"); - e.setC("C"); - - VPackSlice slice = new VPackSlice(mapper.serialize(e)); - System.out.println(slice); - Map deserialized = mapper.deserialize(slice.toByteArray(), Object.class); - assertThat(deserialized) - .containsEntry(SerializedNameEntity.SERIALIZED_NAME_A, e.getA()) - .containsEntry(SerializedNameEntity.SERIALIZED_NAME_B, e.getB()) - .containsEntry(SerializedNameEntity.SERIALIZED_NAME_C, e.getC()) - .hasSize(3); - - SerializedNameEntity deserializedEntity = mapper.deserialize(slice.toByteArray(), SerializedNameEntity.class); - assertThat(deserializedEntity).isEqualTo(e); - } - - @Test - void serializedNameParameter() { - Map e = new HashMap<>(); - e.put(SerializedNameParameterEntity.SERIALIZED_NAME_A, "A"); - e.put(SerializedNameParameterEntity.SERIALIZED_NAME_B, "B"); - e.put(SerializedNameParameterEntity.SERIALIZED_NAME_C, "C"); - - VPackSlice slice = new VPackSlice(mapper.serialize(e)); - SerializedNameParameterEntity deserializedEntity = mapper - .deserialize(slice.toByteArray(), SerializedNameParameterEntity.class); - assertThat(deserializedEntity).isEqualTo(new SerializedNameParameterEntity("A", "B", "C")); - } - - @Test - void expose() { - ExposeEntity e = new ExposeEntity(); - e.setReadWrite("readWrite"); - e.setReadOnly("readOnly"); - e.setWriteOnly("writeOnly"); - e.setIgnored("ignored"); - - VPackSlice serializedEntity = new VPackSlice(mapper.serialize(e)); - Map deserializedEntity = mapper.deserialize(serializedEntity.toByteArray(), Object.class); - assertThat(deserializedEntity) - .containsEntry("readWrite", "readWrite") - .containsEntry("readOnly", "readOnly") - .hasSize(2); - - Map map = new HashMap<>(); - map.put("readWrite", "readWrite"); - map.put("readOnly", "readOnly"); - map.put("writeOnly", "writeOnly"); - map.put("ignored", "ignored"); - - VPackSlice serializedMap = new VPackSlice(mapper.serialize(map)); - ExposeEntity deserializedMap = mapper.deserialize(serializedMap.toByteArray(), ExposeEntity.class); - assertThat(deserializedMap.getIgnored()).isNull(); - assertThat(deserializedMap.getReadOnly()).isNull(); - assertThat(deserializedMap.getWriteOnly()).isEqualTo("writeOnly"); - assertThat(deserializedMap.getReadWrite()).isEqualTo("readWrite"); - } - } diff --git a/src/test/java/com/arangodb/mapping/annotations/ExposeEntity.java b/src/test/java/com/arangodb/mapping/annotations/ExposeEntity.java deleted file mode 100644 index 3100f9b38..000000000 --- a/src/test/java/com/arangodb/mapping/annotations/ExposeEntity.java +++ /dev/null @@ -1,101 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.mapping.annotations; - -import com.arangodb.velocypack.annotations.Expose; - -import java.util.Objects; - -/** - * @author Michele Rastelli - */ -public class ExposeEntity { - - @Expose() - private String readWrite; - - @Expose(deserialize = false) - private String readOnly; - - @Expose(serialize = false) - private String writeOnly; - - @Expose(serialize = false, - deserialize = false) - private String ignored; - - public ExposeEntity() { - } - - public String getReadWrite() { - return readWrite; - } - - public void setReadWrite(String readWrite) { - this.readWrite = readWrite; - } - - public String getReadOnly() { - return readOnly; - } - - public void setReadOnly(String readOnly) { - this.readOnly = readOnly; - } - - public String getWriteOnly() { - return writeOnly; - } - - public void setWriteOnly(String writeOnly) { - this.writeOnly = writeOnly; - } - - public String getIgnored() { - return ignored; - } - - public void setIgnored(String ignored) { - this.ignored = ignored; - } - - @Override - public boolean equals(Object o) { - if (this == o) - return true; - if (o == null || getClass() != o.getClass()) - return false; - ExposeEntity that = (ExposeEntity) o; - return Objects.equals(readWrite, that.readWrite) && Objects.equals(readOnly, that.readOnly) && Objects - .equals(writeOnly, that.writeOnly) && Objects.equals(ignored, that.ignored); - } - - @Override - public int hashCode() { - return Objects.hash(readWrite, readOnly, writeOnly, ignored); - } - - @Override - public String toString() { - return "ExposeEntity{" + "readWrite='" + readWrite + '\'' + ", readOnly='" + readOnly + '\'' + ", writeOnly='" - + writeOnly + '\'' + ", ignored='" + ignored + '\'' + '}'; - } -} \ No newline at end of file diff --git a/src/test/java/com/arangodb/mapping/annotations/SerializedNameEntity.java b/src/test/java/com/arangodb/mapping/annotations/SerializedNameEntity.java deleted file mode 100644 index 110d750be..000000000 --- a/src/test/java/com/arangodb/mapping/annotations/SerializedNameEntity.java +++ /dev/null @@ -1,89 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.mapping.annotations; - -import com.arangodb.velocypack.annotations.SerializedName; - -import java.util.Objects; - -/** - * @author Michele Rastelli - */ -public class SerializedNameEntity { - - final static String SERIALIZED_NAME_A = "aSerializedName"; - final static String SERIALIZED_NAME_B = "bSerializedName"; - final static String SERIALIZED_NAME_C = "cSerializedName"; - - @SerializedName(SERIALIZED_NAME_A) - private String a; - private String b; - private String c; - - public SerializedNameEntity() { - } - - public String getA() { - return a; - } - - public void setA(String a) { - this.a = a; - } - - @SerializedName(SERIALIZED_NAME_B) - public String getB() { - return b; - } - - public void setB(String b) { - this.b = b; - } - - public String getC() { - return c; - } - - @SerializedName(SERIALIZED_NAME_C) - public void setC(String c) { - this.c = c; - } - - @Override - public boolean equals(Object o) { - if (this == o) - return true; - if (o == null || getClass() != o.getClass()) - return false; - SerializedNameEntity that = (SerializedNameEntity) o; - return Objects.equals(a, that.a) && Objects.equals(b, that.b) && Objects.equals(c, that.c); - } - - @Override - public int hashCode() { - return Objects.hash(a, b, c); - } - - @Override - public String toString() { - return "SerializedNameEntity{" + "a='" + a + '\'' + ", b='" + b + '\'' + ", c='" + c + '\'' + '}'; - } -} diff --git a/src/test/java/com/arangodb/mapping/annotations/SerializedNameParameterEntity.java b/src/test/java/com/arangodb/mapping/annotations/SerializedNameParameterEntity.java deleted file mode 100644 index 034c00f93..000000000 --- a/src/test/java/com/arangodb/mapping/annotations/SerializedNameParameterEntity.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.mapping.annotations; - -import com.arangodb.velocypack.annotations.SerializedName; - -import java.util.Objects; - -/** - * @author Michele Rastelli - */ -public class SerializedNameParameterEntity { - - final static String SERIALIZED_NAME_A = "aSerializedName"; - final static String SERIALIZED_NAME_B = "bSerializedName"; - final static String SERIALIZED_NAME_C = "cSerializedName"; - - private String a; - private String b; - private String c; - - public SerializedNameParameterEntity( - @SerializedName(SERIALIZED_NAME_A) - String a, - @SerializedName(SERIALIZED_NAME_B) - String b, - @SerializedName(SERIALIZED_NAME_C) - String c) { - this.a = a; - this.b = b; - this.c = c; - } - - public String getA() { - return a; - } - - public String getB() { - return b; - } - - public String getC() { - return c; - } - - @Override - public boolean equals(Object o) { - if (this == o) - return true; - if (o == null || getClass() != o.getClass()) - return false; - SerializedNameParameterEntity that = (SerializedNameParameterEntity) o; - return Objects.equals(a, that.a) && Objects.equals(b, that.b) && Objects.equals(c, that.c); - } - - @Override - public int hashCode() { - return Objects.hash(a, b, c); - } - - @Override - public String toString() { - return "SerializedNameParameterEntity{" + "a='" + a + '\'' + ", b='" + b + '\'' + ", c='" + c + '\'' + '}'; - } -} From 214ffca2d4a7014e45a6fe79d7c58e164f85fa78 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Tue, 19 Jul 2022 12:14:07 +0200 Subject: [PATCH 034/254] reviewed API changes in entity and model packages --- src/main/java/com/arangodb/entity/DocumentCreateEntity.java | 2 -- src/main/java/com/arangodb/entity/DocumentDeleteEntity.java | 2 -- src/main/java/com/arangodb/entity/DocumentUpdateEntity.java | 2 -- src/main/java/com/arangodb/entity/EdgeUpdateEntity.java | 1 - src/main/java/com/arangodb/entity/QueryExecutionState.java | 1 - src/main/java/com/arangodb/entity/VertexUpdateEntity.java | 1 - .../entity/arangosearch/analyzer/NormAnalyzerProperties.java | 1 - .../arangosearch/analyzer/SegmentationAnalyzerProperties.java | 1 - .../entity/arangosearch/analyzer/TextAnalyzerProperties.java | 1 - src/main/java/com/arangodb/model/AqlQueryOptions.java | 1 - src/main/java/com/arangodb/model/CollectionCreateOptions.java | 3 --- src/main/java/com/arangodb/model/GraphDocumentReadOptions.java | 2 -- .../model/arangosearch/ArangoSearchPropertiesOptions.java | 1 - 13 files changed, 19 deletions(-) diff --git a/src/main/java/com/arangodb/entity/DocumentCreateEntity.java b/src/main/java/com/arangodb/entity/DocumentCreateEntity.java index aa25d24a0..6badc51cd 100644 --- a/src/main/java/com/arangodb/entity/DocumentCreateEntity.java +++ b/src/main/java/com/arangodb/entity/DocumentCreateEntity.java @@ -20,8 +20,6 @@ package com.arangodb.entity; -import com.arangodb.velocypack.annotations.Expose; - /** * @author Mark Vollmary * @see API diff --git a/src/main/java/com/arangodb/entity/DocumentDeleteEntity.java b/src/main/java/com/arangodb/entity/DocumentDeleteEntity.java index 67de46e97..2f5a6f098 100644 --- a/src/main/java/com/arangodb/entity/DocumentDeleteEntity.java +++ b/src/main/java/com/arangodb/entity/DocumentDeleteEntity.java @@ -20,8 +20,6 @@ package com.arangodb.entity; -import com.arangodb.velocypack.annotations.Expose; - /** * @author Mark Vollmary * @see API diff --git a/src/main/java/com/arangodb/entity/DocumentUpdateEntity.java b/src/main/java/com/arangodb/entity/DocumentUpdateEntity.java index 9475a6924..8393a7988 100644 --- a/src/main/java/com/arangodb/entity/DocumentUpdateEntity.java +++ b/src/main/java/com/arangodb/entity/DocumentUpdateEntity.java @@ -20,8 +20,6 @@ package com.arangodb.entity; -import com.arangodb.velocypack.annotations.Expose; -import com.arangodb.velocypack.annotations.SerializedName; import com.fasterxml.jackson.annotation.JsonProperty; /** diff --git a/src/main/java/com/arangodb/entity/EdgeUpdateEntity.java b/src/main/java/com/arangodb/entity/EdgeUpdateEntity.java index 26d16e468..ad0a5777f 100644 --- a/src/main/java/com/arangodb/entity/EdgeUpdateEntity.java +++ b/src/main/java/com/arangodb/entity/EdgeUpdateEntity.java @@ -20,7 +20,6 @@ package com.arangodb.entity; -import com.arangodb.velocypack.annotations.SerializedName; import com.fasterxml.jackson.annotation.JsonProperty; /** diff --git a/src/main/java/com/arangodb/entity/QueryExecutionState.java b/src/main/java/com/arangodb/entity/QueryExecutionState.java index 2e1988acb..987044880 100644 --- a/src/main/java/com/arangodb/entity/QueryExecutionState.java +++ b/src/main/java/com/arangodb/entity/QueryExecutionState.java @@ -59,4 +59,3 @@ public enum QueryExecutionState { @JsonProperty("invalid") INVALID } - diff --git a/src/main/java/com/arangodb/entity/VertexUpdateEntity.java b/src/main/java/com/arangodb/entity/VertexUpdateEntity.java index f68163121..b5148338f 100644 --- a/src/main/java/com/arangodb/entity/VertexUpdateEntity.java +++ b/src/main/java/com/arangodb/entity/VertexUpdateEntity.java @@ -20,7 +20,6 @@ package com.arangodb.entity; -import com.arangodb.velocypack.annotations.SerializedName; import com.fasterxml.jackson.annotation.JsonProperty; /** diff --git a/src/main/java/com/arangodb/entity/arangosearch/analyzer/NormAnalyzerProperties.java b/src/main/java/com/arangodb/entity/arangosearch/analyzer/NormAnalyzerProperties.java index 96f848e75..92633f419 100644 --- a/src/main/java/com/arangodb/entity/arangosearch/analyzer/NormAnalyzerProperties.java +++ b/src/main/java/com/arangodb/entity/arangosearch/analyzer/NormAnalyzerProperties.java @@ -21,7 +21,6 @@ package com.arangodb.entity.arangosearch.analyzer; -import com.arangodb.velocypack.annotations.SerializedName; import com.fasterxml.jackson.annotation.JsonProperty; import java.util.Objects; diff --git a/src/main/java/com/arangodb/entity/arangosearch/analyzer/SegmentationAnalyzerProperties.java b/src/main/java/com/arangodb/entity/arangosearch/analyzer/SegmentationAnalyzerProperties.java index 76080409e..7c6ea73c4 100644 --- a/src/main/java/com/arangodb/entity/arangosearch/analyzer/SegmentationAnalyzerProperties.java +++ b/src/main/java/com/arangodb/entity/arangosearch/analyzer/SegmentationAnalyzerProperties.java @@ -21,7 +21,6 @@ package com.arangodb.entity.arangosearch.analyzer; -import com.arangodb.velocypack.annotations.SerializedName; import com.fasterxml.jackson.annotation.JsonProperty; import java.util.Objects; diff --git a/src/main/java/com/arangodb/entity/arangosearch/analyzer/TextAnalyzerProperties.java b/src/main/java/com/arangodb/entity/arangosearch/analyzer/TextAnalyzerProperties.java index 8dbb6057c..566fe8a99 100644 --- a/src/main/java/com/arangodb/entity/arangosearch/analyzer/TextAnalyzerProperties.java +++ b/src/main/java/com/arangodb/entity/arangosearch/analyzer/TextAnalyzerProperties.java @@ -21,7 +21,6 @@ package com.arangodb.entity.arangosearch.analyzer; -import com.arangodb.velocypack.annotations.SerializedName; import com.fasterxml.jackson.annotation.JsonProperty; import java.util.Collections; diff --git a/src/main/java/com/arangodb/model/AqlQueryOptions.java b/src/main/java/com/arangodb/model/AqlQueryOptions.java index 090d0c393..3b4fe5aee 100644 --- a/src/main/java/com/arangodb/model/AqlQueryOptions.java +++ b/src/main/java/com/arangodb/model/AqlQueryOptions.java @@ -21,7 +21,6 @@ package com.arangodb.model; import com.arangodb.serde.InternalSerializers; -import com.arangodb.velocypack.annotations.Expose; import com.fasterxml.jackson.databind.annotation.JsonSerialize; import java.util.ArrayList; diff --git a/src/main/java/com/arangodb/model/CollectionCreateOptions.java b/src/main/java/com/arangodb/model/CollectionCreateOptions.java index 4f98a9dcd..b3433a3d4 100644 --- a/src/main/java/com/arangodb/model/CollectionCreateOptions.java +++ b/src/main/java/com/arangodb/model/CollectionCreateOptions.java @@ -25,8 +25,6 @@ import com.arangodb.entity.KeyType; import com.arangodb.entity.ReplicationFactor; -import java.util.Objects; - /** * @author Mark Vollmary * @see API @@ -163,7 +161,6 @@ public String[] getShardKeys() { * @return options */ public CollectionCreateOptions shardKeys(final String... shardKeys) { - Objects.requireNonNull(shardKeys); this.shardKeys = shardKeys; return this; } diff --git a/src/main/java/com/arangodb/model/GraphDocumentReadOptions.java b/src/main/java/com/arangodb/model/GraphDocumentReadOptions.java index bad03413e..8a7fffa0a 100644 --- a/src/main/java/com/arangodb/model/GraphDocumentReadOptions.java +++ b/src/main/java/com/arangodb/model/GraphDocumentReadOptions.java @@ -20,8 +20,6 @@ package com.arangodb.model; -import com.arangodb.velocypack.annotations.Expose; - /** * @author Mark Vollmary */ diff --git a/src/main/java/com/arangodb/model/arangosearch/ArangoSearchPropertiesOptions.java b/src/main/java/com/arangodb/model/arangosearch/ArangoSearchPropertiesOptions.java index 5283169d3..e4d142b1c 100644 --- a/src/main/java/com/arangodb/model/arangosearch/ArangoSearchPropertiesOptions.java +++ b/src/main/java/com/arangodb/model/arangosearch/ArangoSearchPropertiesOptions.java @@ -28,7 +28,6 @@ import java.util.Arrays; import java.util.Collection; -import java.util.Collections; /** * @author Mark Vollmary From 53dceb464a85e923352d69cedeb83ac73bd29392 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Tue, 19 Jul 2022 14:53:20 +0200 Subject: [PATCH 035/254] remove dependencies on com.arangodb.velocypack --- .../internal/ArangoDatabaseAsyncImpl.java | 30 ++++----------- .../async/internal/ArangoExecutorAsync.java | 6 +-- .../arangodb/internal/ArangoDatabaseImpl.java | 11 +++--- .../com/arangodb/internal/ArangoExecutor.java | 37 ++----------------- .../arangodb/internal/ArangoExecutorSync.java | 23 ++++-------- .../internal/InternalArangoCollection.java | 5 +-- .../arangodb/internal/InternalArangoDB.java | 15 +++----- .../internal/InternalArangoDBBuilder.java | 2 - .../internal/InternalArangoDatabase.java | 35 +++++++++--------- .../internal/InternalArangoGraph.java | 10 ++--- .../internal/http/HttpConnection.java | 7 ---- .../internal/net/ExtendedHostResolver.java | 13 ++----- .../arangodb/internal/util/ResponseUtils.java | 31 +++++++--------- .../model/AqlQueryExplainOptions.java | 10 +++-- .../com/arangodb/model/AqlQueryOptions.java | 2 +- .../arangodb/model/DocumentReadOptions.java | 2 - .../com/arangodb/model/OptionsBuilder.java | 3 +- .../com/arangodb/serde/InternalModule.java | 2 - .../arangodb/serde/InternalSerializers.java | 14 +------ .../java/com/arangodb/serde/SerdeUtils.java | 15 +++++++- .../com/arangodb/velocystream/Request.java | 1 - .../com/arangodb/velocystream/Response.java | 2 - .../java/com/arangodb/ArangoDatabaseTest.java | 28 +++++++++++--- .../arangodb/async/ArangoDatabaseTest.java | 4 +- 24 files changed, 123 insertions(+), 185 deletions(-) diff --git a/src/main/java/com/arangodb/async/internal/ArangoDatabaseAsyncImpl.java b/src/main/java/com/arangodb/async/internal/ArangoDatabaseAsyncImpl.java index 224d80d7c..629783023 100644 --- a/src/main/java/com/arangodb/async/internal/ArangoDatabaseAsyncImpl.java +++ b/src/main/java/com/arangodb/async/internal/ArangoDatabaseAsyncImpl.java @@ -22,13 +22,7 @@ import com.arangodb.ArangoDBException; import com.arangodb.DbName; -import com.arangodb.async.ArangoCollectionAsync; -import com.arangodb.async.ArangoCursorAsync; -import com.arangodb.async.ArangoDatabaseAsync; -import com.arangodb.async.ArangoGraphAsync; -import com.arangodb.async.ArangoRouteAsync; -import com.arangodb.async.ArangoSearchAsync; -import com.arangodb.async.ArangoViewAsync; +import com.arangodb.async.*; import com.arangodb.entity.*; import com.arangodb.entity.arangosearch.analyzer.SearchAnalyzer; import com.arangodb.internal.ArangoCursorExecute; @@ -36,20 +30,10 @@ import com.arangodb.internal.InternalArangoDatabase; import com.arangodb.internal.net.HostHandle; import com.arangodb.internal.util.DocumentUtil; -import com.arangodb.model.AqlFunctionCreateOptions; -import com.arangodb.model.AqlFunctionDeleteOptions; -import com.arangodb.model.AqlFunctionGetOptions; -import com.arangodb.model.AqlQueryExplainOptions; -import com.arangodb.model.AqlQueryOptions; -import com.arangodb.model.CollectionCreateOptions; -import com.arangodb.model.CollectionsReadOptions; -import com.arangodb.model.DocumentReadOptions; -import com.arangodb.model.GraphCreateOptions; -import com.arangodb.model.StreamTransactionOptions; -import com.arangodb.model.TransactionOptions; +import com.arangodb.model.*; import com.arangodb.model.arangosearch.AnalyzerDeleteOptions; import com.arangodb.model.arangosearch.ArangoSearchCreateOptions; -import com.arangodb.velocypack.Type; +import com.arangodb.serde.SerdeUtils; import com.arangodb.velocystream.Request; import java.util.Collection; @@ -296,14 +280,14 @@ public CompletableFuture setQueryTrackingProperti @Override public CompletableFuture> getCurrentlyRunningQueries() { - return executor.execute(getCurrentlyRunningQueriesRequest(), new Type>() { - }.getType()); + return executor.execute(getCurrentlyRunningQueriesRequest(), + SerdeUtils.INSTANCE.constructListType(QueryEntity.class)); } @Override public CompletableFuture> getSlowQueries() { - return executor.execute(getSlowQueriesRequest(), new Type>() { - }.getType()); + return executor.execute(getSlowQueriesRequest(), + SerdeUtils.INSTANCE.constructListType(QueryEntity.class)); } @Override diff --git a/src/main/java/com/arangodb/async/internal/ArangoExecutorAsync.java b/src/main/java/com/arangodb/async/internal/ArangoExecutorAsync.java index 58d7659c5..6a1cea3a1 100644 --- a/src/main/java/com/arangodb/async/internal/ArangoExecutorAsync.java +++ b/src/main/java/com/arangodb/async/internal/ArangoExecutorAsync.java @@ -51,11 +51,11 @@ public ArangoExecutorAsync(final VstCommunicationAsync communication, final Aran } public CompletableFuture execute(final Request request, final Type type) { - return execute(request, (response) -> createResult(type, response)); + return execute(request, response -> createResult(type, response)); } public CompletableFuture execute(final Request request, final Type type, final HostHandle hostHandle) { - return execute(request, (response) -> createResult(type, response), hostHandle); + return execute(request, response -> createResult(type, response), hostHandle); } public CompletableFuture execute(final Request request, final ResponseDeserializer responseDeserializer) { @@ -68,7 +68,7 @@ private CompletableFuture execute( final HostHandle hostHandle) { return CompletableFuture.completedFuture(null) - .thenComposeAsync((it) -> communication.execute(interceptRequest(request), hostHandle), outgoingExecutor) + .thenComposeAsync(it -> communication.execute(interceptRequest(request), hostHandle), outgoingExecutor) .thenApplyAsync(response -> { interceptResponse(response); return responseDeserializer.deserialize(response); diff --git a/src/main/java/com/arangodb/internal/ArangoDatabaseImpl.java b/src/main/java/com/arangodb/internal/ArangoDatabaseImpl.java index e73fa0fa0..2a834d948 100644 --- a/src/main/java/com/arangodb/internal/ArangoDatabaseImpl.java +++ b/src/main/java/com/arangodb/internal/ArangoDatabaseImpl.java @@ -29,12 +29,13 @@ import com.arangodb.model.*; import com.arangodb.model.arangosearch.AnalyzerDeleteOptions; import com.arangodb.model.arangosearch.ArangoSearchCreateOptions; +import com.arangodb.serde.SerdeUtils; import com.arangodb.util.ArangoCursorInitializer; -import com.arangodb.velocypack.Type; import com.arangodb.velocystream.Request; import java.util.Collection; import java.util.Collections; +import java.util.List; import java.util.Map; /** @@ -262,14 +263,14 @@ public QueryTrackingPropertiesEntity setQueryTrackingProperties(final QueryTrack @Override public Collection getCurrentlyRunningQueries() throws ArangoDBException { - return executor.execute(getCurrentlyRunningQueriesRequest(), new Type>() { - }.getType()); + return executor.execute(getCurrentlyRunningQueriesRequest(), + SerdeUtils.INSTANCE.constructListType(QueryEntity.class)); } @Override public Collection getSlowQueries() throws ArangoDBException { - return executor.execute(getSlowQueriesRequest(), new Type>() { - }.getType()); + return executor.execute(getSlowQueriesRequest(), + SerdeUtils.INSTANCE.constructListType(QueryEntity.class)); } @Override diff --git a/src/main/java/com/arangodb/internal/ArangoExecutor.java b/src/main/java/com/arangodb/internal/ArangoExecutor.java index 4c5b08443..d9b0ef91a 100644 --- a/src/main/java/com/arangodb/internal/ArangoExecutor.java +++ b/src/main/java/com/arangodb/internal/ArangoExecutor.java @@ -21,53 +21,22 @@ package com.arangodb.internal; import com.arangodb.QueueTimeMetrics; -import com.arangodb.entity.Entity; import com.arangodb.internal.util.ArangoSerializationFactory; -import com.arangodb.velocypack.exception.VPackException; import com.arangodb.velocystream.Request; import com.arangodb.velocystream.Response; -import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; -import java.util.Map; /** * @author Mark Vollmary */ public abstract class ArangoExecutor { - @SuppressWarnings("unchecked") protected T createResult(final Type type, final Response response) { - if (type != Void.class && response.getBody() != null) { - if (isInternal(type)) { - return (T) util.getInternalSerialization().deserialize(response.getBody(), type); - } else { - throw new RuntimeException("FIXME: this should not never happen"); -// return (T) util.getUserSerialization().deserialize(response.getBody(), type); - } - } else { + if (response.getBody() == null) { return null; } - } - - private boolean isInternal(final Type type) { - if (type instanceof ParameterizedType) { - ParameterizedType pType = ((ParameterizedType) type); - Type rawType = pType.getRawType(); - - if (rawType instanceof Class && ( - Map.class.isAssignableFrom((Class) rawType) || Iterable.class.isAssignableFrom((Class) rawType) - )) { - for (Type arg : pType.getActualTypeArguments()) { - if (!isInternal(arg)) { - return false; - } - } - return true; - } - } - - return type instanceof Class && Entity.class.isAssignableFrom((Class) type); + return util.getInternalSerialization().deserialize(response.getBody(), type); } private final DocumentCache documentCache; @@ -89,7 +58,7 @@ public DocumentCache documentCache() { } public interface ResponseDeserializer { - T deserialize(Response response) throws VPackException; + T deserialize(Response response); } protected final void interceptResponse(Response response) { diff --git a/src/main/java/com/arangodb/internal/ArangoExecutorSync.java b/src/main/java/com/arangodb/internal/ArangoExecutorSync.java index 2f60d2b56..51c683e10 100644 --- a/src/main/java/com/arangodb/internal/ArangoExecutorSync.java +++ b/src/main/java/com/arangodb/internal/ArangoExecutorSync.java @@ -25,7 +25,6 @@ import com.arangodb.internal.net.CommunicationProtocol; import com.arangodb.internal.net.HostHandle; import com.arangodb.internal.util.ArangoSerializationFactory; -import com.arangodb.velocypack.exception.VPackException; import com.arangodb.velocystream.Request; import com.arangodb.velocystream.Response; import org.slf4j.Logger; @@ -66,22 +65,16 @@ public T execute( final ResponseDeserializer responseDeserializer, final HostHandle hostHandle) throws ArangoDBException { - try { - - final Response response = protocol.execute(interceptRequest(request), hostHandle); - interceptResponse(response); - T deserialize = responseDeserializer.deserialize(response); - - if (deserialize instanceof MetaAware) { - LOG.debug("Response is MetaAware " + deserialize.getClass().getName()); - ((MetaAware) deserialize).setMeta(response.getMeta()); - } + final Response response = protocol.execute(interceptRequest(request), hostHandle); + interceptResponse(response); + T deserialize = responseDeserializer.deserialize(response); - return deserialize; - - } catch (final VPackException e) { - throw new ArangoDBException(e); + if (deserialize instanceof MetaAware) { + LOG.debug("Response is MetaAware {}", deserialize.getClass().getName()); + ((MetaAware) deserialize).setMeta(response.getMeta()); } + + return deserialize; } public void disconnect() { diff --git a/src/main/java/com/arangodb/internal/InternalArangoCollection.java b/src/main/java/com/arangodb/internal/InternalArangoCollection.java index 040186faf..4bb014874 100644 --- a/src/main/java/com/arangodb/internal/InternalArangoCollection.java +++ b/src/main/java/com/arangodb/internal/InternalArangoCollection.java @@ -28,7 +28,6 @@ import com.arangodb.internal.util.RequestUtils; import com.arangodb.model.*; import com.arangodb.serde.SerdeUtils; -import com.arangodb.velocypack.Type; import com.arangodb.velocystream.Request; import com.arangodb.velocystream.RequestType; import com.fasterxml.jackson.databind.JsonNode; @@ -637,8 +636,8 @@ protected Request getIndexesRequest() { } protected ResponseDeserializer> getIndexesResponseDeserializer() { - return response -> getInternalSerialization().deserialize(response.getBody(), "/indexes", new Type>() { - }.getType()); + return response -> getInternalSerialization().deserialize(response.getBody(), "/indexes", + SerdeUtils.INSTANCE.constructListType(IndexEntity.class)); } protected Request truncateRequest(final CollectionTruncateOptions options) { diff --git a/src/main/java/com/arangodb/internal/InternalArangoDB.java b/src/main/java/com/arangodb/internal/InternalArangoDB.java index 584449d30..c1b6fcc0f 100644 --- a/src/main/java/com/arangodb/internal/InternalArangoDB.java +++ b/src/main/java/com/arangodb/internal/InternalArangoDB.java @@ -21,14 +21,11 @@ package com.arangodb.internal; import com.arangodb.DbName; -import com.arangodb.entity.LogLevelEntity; -import com.arangodb.entity.Permissions; -import com.arangodb.entity.ServerRole; -import com.arangodb.entity.UserEntity; +import com.arangodb.entity.*; import com.arangodb.internal.ArangoExecutor.ResponseDeserializer; import com.arangodb.internal.util.ArangoSerializationFactory; import com.arangodb.model.*; -import com.arangodb.velocypack.Type; +import com.arangodb.serde.SerdeUtils; import com.arangodb.velocystream.Request; import com.arangodb.velocystream.RequestType; @@ -86,8 +83,8 @@ protected Request getDatabasesRequest(final DbName dbName) { } protected ResponseDeserializer> getDatabaseResponseDeserializer() { - return response -> getInternalSerialization().deserialize(response.getBody(), ArangoResponseField.RESULT_JSON_POINTER, new Type>() { - }.getType()); + return response -> getInternalSerialization().deserialize(response.getBody(), ArangoResponseField.RESULT_JSON_POINTER, + SerdeUtils.INSTANCE.constructListType(String.class)); } protected Request getAccessibleDatabasesForRequest(final DbName dbName, final String user) { @@ -130,8 +127,8 @@ protected Request getUserRequest(final DbName dbName, final String user) { } protected ResponseDeserializer> getUsersResponseDeserializer() { - return response -> getInternalSerialization().deserialize(response.getBody(), ArangoResponseField.RESULT_JSON_POINTER, new Type>() { - }.getType()); + return response -> getInternalSerialization().deserialize(response.getBody(), ArangoResponseField.RESULT_JSON_POINTER, + SerdeUtils.INSTANCE.constructListType(UserEntity.class)); } protected Request updateUserRequest(final DbName dbName, final String user, final UserUpdateOptions options) { diff --git a/src/main/java/com/arangodb/internal/InternalArangoDBBuilder.java b/src/main/java/com/arangodb/internal/InternalArangoDBBuilder.java index d262e1e12..093e6428d 100644 --- a/src/main/java/com/arangodb/internal/InternalArangoDBBuilder.java +++ b/src/main/java/com/arangodb/internal/InternalArangoDBBuilder.java @@ -26,8 +26,6 @@ import com.arangodb.internal.net.*; import com.arangodb.internal.util.HostUtils; import com.arangodb.util.ArangoSerialization; -import com.arangodb.velocypack.VPack; -import com.arangodb.velocypack.VPackParser; import org.apache.http.client.HttpRequestRetryHandler; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/src/main/java/com/arangodb/internal/InternalArangoDatabase.java b/src/main/java/com/arangodb/internal/InternalArangoDatabase.java index 49d5be7fb..5b3739cef 100644 --- a/src/main/java/com/arangodb/internal/InternalArangoDatabase.java +++ b/src/main/java/com/arangodb/internal/InternalArangoDatabase.java @@ -30,8 +30,6 @@ import com.arangodb.model.arangosearch.ArangoSearchCreateOptions; import com.arangodb.model.arangosearch.ArangoSearchOptionsBuilder; import com.arangodb.serde.SerdeUtils; -import com.arangodb.velocypack.Type; -import com.arangodb.velocypack.VPackSlice; import com.arangodb.velocystream.Request; import com.arangodb.velocystream.RequestType; @@ -112,8 +110,8 @@ protected Request getCollectionsRequest(final CollectionsReadOptions options) { } protected ResponseDeserializer> getCollectionsResponseDeserializer() { - return response -> getInternalSerialization().deserialize(getInternalSerialization().parse(response.getBody(), ArangoResponseField.RESULT_JSON_POINTER), new Type>() { - }.getType()); + return response -> getInternalSerialization().deserialize(getInternalSerialization().parse(response.getBody(), ArangoResponseField.RESULT_JSON_POINTER), + SerdeUtils.INSTANCE.constructListType(CollectionEntity.class)); } protected Request dropRequest() { @@ -146,7 +144,8 @@ protected ResponseDeserializer getPermissionsResponseDeserialzer() protected Request queryRequest(final String query, final Map bindVars, final AqlQueryOptions options) { final AqlQueryOptions opt = options != null ? options : new AqlQueryOptions(); - final Request request = request(dbName, RequestType.POST, PATH_API_CURSOR).setBody(getInternalSerialization().serialize(OptionsBuilder.build(opt, query, bindVars != null ? getUserSerialization().serialize(bindVars) : null))); + final Request request = request(dbName, RequestType.POST, PATH_API_CURSOR).setBody(getInternalSerialization().serialize( + OptionsBuilder.build(opt, query, bindVars != null ? getUserSerialization().serialize(bindVars) : null))); if (opt.getAllowDirtyRead() == Boolean.TRUE) { RequestUtils.allowDirtyRead(request); } @@ -189,10 +188,10 @@ protected Request queryCloseRequest(final String id, final AqlQueryOptions optio } protected Request explainQueryRequest(final String query, final Map bindVars, final AqlQueryExplainOptions options) { - final AqlQueryExplainOptions opt = options != null ? options : new AqlQueryExplainOptions(); - - return request(dbName, RequestType.POST, PATH_API_EXPLAIN).setBody(getInternalSerialization().serialize(OptionsBuilder.build(opt, query, bindVars != null ? new VPackSlice(getUserSerialization().serialize(bindVars)) : null))); + return request(dbName, RequestType.POST, PATH_API_EXPLAIN) + .setBody(getInternalSerialization().serialize( + OptionsBuilder.build(opt, query, bindVars != null ? getUserSerialization().serialize(bindVars) : null))); } protected Request parseQueryRequest(final String query) { @@ -258,8 +257,8 @@ protected Request getAqlFunctionsRequest(final AqlFunctionGetOptions options) { } protected ResponseDeserializer> getAqlFunctionsResponseDeserializer() { - return response -> getInternalSerialization().deserialize(response.getBody(), ArangoResponseField.RESULT_JSON_POINTER, new Type>() { - }.getType()); + return response -> getInternalSerialization().deserialize(response.getBody(), ArangoResponseField.RESULT_JSON_POINTER, + SerdeUtils.INSTANCE.constructListType(AqlFunctionEntity.class)); } protected Request createGraphRequest(final String name, final Collection edgeDefinitions, final GraphCreateOptions options) { @@ -275,8 +274,8 @@ protected Request getGraphsRequest() { } protected ResponseDeserializer> getGraphsResponseDeserializer() { - return response -> getInternalSerialization().deserialize(response.getBody(), "/graphs", new Type>() { - }.getType()); + return response -> getInternalSerialization().deserialize(response.getBody(), "/graphs", + SerdeUtils.INSTANCE.constructListType(GraphEntity.class)); } protected Request transactionRequest(final String action, final TransactionOptions options) { @@ -311,8 +310,8 @@ protected Request getStreamTransactionRequest(String id) { } protected ResponseDeserializer> transactionsResponseDeserializer() { - return response -> getInternalSerialization().deserialize(response.getBody(), "/transactions", new Type>() { - }.getType()); + return response -> getInternalSerialization().deserialize(response.getBody(), "/transactions", + SerdeUtils.INSTANCE.constructListType(TransactionEntity.class)); } protected Request commitStreamTransactionRequest(String id) { @@ -340,8 +339,8 @@ protected Request getViewsRequest() { } protected ResponseDeserializer> getViewsResponseDeserializer() { - return response -> getInternalSerialization().deserialize(response.getBody(), ArangoResponseField.RESULT_JSON_POINTER, new Type>() { - }.getType()); + return response -> getInternalSerialization().deserialize(response.getBody(), ArangoResponseField.RESULT_JSON_POINTER, + SerdeUtils.INSTANCE.constructListType(ViewEntity.class)); } protected Request createViewRequest(final String name, final ViewType type) { @@ -361,8 +360,8 @@ protected Request getAnalyzersRequest() { } protected ResponseDeserializer> getSearchAnalyzersResponseDeserializer() { - return response -> getInternalSerialization().deserialize(response.getBody(), ArangoResponseField.RESULT_JSON_POINTER, new Type>() { - }.getType()); + return response -> getInternalSerialization().deserialize(response.getBody(), ArangoResponseField.RESULT_JSON_POINTER, + SerdeUtils.INSTANCE.constructListType(SearchAnalyzer.class)); } protected Request createAnalyzerRequest(final SearchAnalyzer options) { diff --git a/src/main/java/com/arangodb/internal/InternalArangoGraph.java b/src/main/java/com/arangodb/internal/InternalArangoGraph.java index 8108dd57a..f725539ba 100644 --- a/src/main/java/com/arangodb/internal/InternalArangoGraph.java +++ b/src/main/java/com/arangodb/internal/InternalArangoGraph.java @@ -25,7 +25,7 @@ import com.arangodb.internal.ArangoExecutor.ResponseDeserializer; import com.arangodb.model.OptionsBuilder; import com.arangodb.model.VertexCollectionCreateOptions; -import com.arangodb.velocypack.Type; +import com.arangodb.serde.SerdeUtils; import com.arangodb.velocystream.Request; import com.arangodb.velocystream.RequestType; @@ -84,8 +84,8 @@ protected Request getVertexCollectionsRequest() { } protected ResponseDeserializer> getVertexCollectionsResponseDeserializer() { - return response -> getInternalSerialization().deserialize(response.getBody(), "/collections", new Type>() { - }.getType()); + return response -> getInternalSerialization().deserialize(response.getBody(), "/collections", + SerdeUtils.INSTANCE.constructListType(String.class)); } protected Request addVertexCollectionRequest(final String name, final VertexCollectionCreateOptions options) { @@ -103,8 +103,8 @@ protected Request getEdgeDefinitionsRequest() { } protected ResponseDeserializer> getEdgeDefinitionsDeserializer() { - return response -> getInternalSerialization().deserialize(response.getBody(), "/collections", new Type>() { - }.getType()); + return response -> getInternalSerialization().deserialize(response.getBody(), "/collections", + SerdeUtils.INSTANCE.constructListType(String.class)); } protected Request addEdgeDefinitionRequest(final EdgeDefinition definition) { diff --git a/src/main/java/com/arangodb/internal/http/HttpConnection.java b/src/main/java/com/arangodb/internal/http/HttpConnection.java index 3f46c0bd7..8dcfa001f 100644 --- a/src/main/java/com/arangodb/internal/http/HttpConnection.java +++ b/src/main/java/com/arangodb/internal/http/HttpConnection.java @@ -27,9 +27,7 @@ import com.arangodb.internal.net.HostDescription; import com.arangodb.internal.util.IOUtils; import com.arangodb.internal.util.ResponseUtils; -import com.arangodb.serde.DataType; import com.arangodb.util.InternalSerialization; -import com.arangodb.velocypack.VPackParser; import com.arangodb.velocystream.Request; import com.arangodb.velocystream.Response; import org.apache.http.*; @@ -168,7 +166,6 @@ public HttpConnection build() { private final InternalSerialization util; private final Boolean useSsl; private final Protocol contentType; - private final DataType dataType; private final HostDescription host; private HttpConnection(final HostDescription host, final Integer timeout, final String user, final String password, @@ -181,7 +178,6 @@ private HttpConnection(final HostDescription host, final Integer timeout, final this.useSsl = useSsl; this.util = util; this.contentType = contentType; - dataType = contentType == Protocol.HTTP_JSON ? DataType.JSON : DataType.VPACK; final RegistryBuilder registryBuilder = RegistryBuilder .create(); if (Boolean.TRUE == useSsl) { @@ -343,9 +339,6 @@ private static void addHeader(final Request request, final HttpRequestBase httpR } } - // FIXME: remove - private final VPackParser parser = new VPackParser.Builder().build(); - public Response buildResponse(final CloseableHttpResponse httpResponse) throws UnsupportedOperationException, IOException { final Response response = new Response(); diff --git a/src/main/java/com/arangodb/internal/net/ExtendedHostResolver.java b/src/main/java/com/arangodb/internal/net/ExtendedHostResolver.java index 42bb7273b..234c96dd0 100644 --- a/src/main/java/com/arangodb/internal/net/ExtendedHostResolver.java +++ b/src/main/java/com/arangodb/internal/net/ExtendedHostResolver.java @@ -24,19 +24,14 @@ import com.arangodb.DbName; import com.arangodb.internal.ArangoExecutorSync; import com.arangodb.internal.util.HostUtils; +import com.arangodb.serde.SerdeUtils; import com.arangodb.util.InternalSerialization; -import com.arangodb.velocypack.Type; import com.arangodb.velocystream.Request; import com.arangodb.velocystream.RequestType; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.List; -import java.util.Map; +import java.util.*; /** * @author Mark Vollmary @@ -75,7 +70,6 @@ public void init(ArangoExecutorSync executor, InternalSerialization arangoSerial } @Override - public HostSet resolve(boolean initial, boolean closeConnections) { if (!initial && isExpired()) { @@ -128,8 +122,7 @@ private Collection resolveFromServer() throws ArangoDBException { new Request(DbName.SYSTEM, RequestType.GET, "/_api/cluster/endpoints"), response1 -> { final Collection> tmp = arangoSerialization.deserialize(response1.getBody(), "/endpoints", - new Type>>() { - }.getType()); + SerdeUtils.INSTANCE.constructMapType(String.class, String.class)); Collection endpoints = new ArrayList<>(); for (final Map map : tmp) { endpoints.add(map.get("endpoint")); diff --git a/src/main/java/com/arangodb/internal/util/ResponseUtils.java b/src/main/java/com/arangodb/internal/util/ResponseUtils.java index bd181ddb5..16bb4ce86 100644 --- a/src/main/java/com/arangodb/internal/util/ResponseUtils.java +++ b/src/main/java/com/arangodb/internal/util/ResponseUtils.java @@ -25,7 +25,6 @@ import com.arangodb.internal.ArangoErrors; import com.arangodb.internal.net.ArangoDBRedirectException; import com.arangodb.util.InternalSerialization; -import com.arangodb.velocypack.exception.VPackParserException; import com.arangodb.velocystream.Response; import java.util.concurrent.TimeoutException; @@ -44,25 +43,21 @@ private ResponseUtils() { } public static void checkError(final InternalSerialization util, final Response response) throws ArangoDBException { - try { - final int responseCode = response.getResponseCode(); - if (responseCode >= ERROR_STATUS) { - if (responseCode == ERROR_INTERNAL && response.getMeta().containsKey(HEADER_ENDPOINT)) { - throw new ArangoDBRedirectException(String.format("Response Code: %s", responseCode), - response.getMeta().get(HEADER_ENDPOINT)); - } else if (response.getBody() != null) { - final ErrorEntity errorEntity = util.deserialize(response.getBody(), ErrorEntity.class); - ArangoDBException e = new ArangoDBException(errorEntity); - if(ArangoErrors.QUEUE_TIME_VIOLATED.equals(e.getErrorNum())){ - throw new ArangoDBException(new TimeoutException().initCause(e)); - } - throw e; - } else { - throw new ArangoDBException(String.format("Response Code: %s", responseCode), responseCode); + final int responseCode = response.getResponseCode(); + if (responseCode >= ERROR_STATUS) { + if (responseCode == ERROR_INTERNAL && response.getMeta().containsKey(HEADER_ENDPOINT)) { + throw new ArangoDBRedirectException(String.format("Response Code: %s", responseCode), + response.getMeta().get(HEADER_ENDPOINT)); + } else if (response.getBody() != null) { + final ErrorEntity errorEntity = util.deserialize(response.getBody(), ErrorEntity.class); + ArangoDBException e = new ArangoDBException(errorEntity); + if (ArangoErrors.QUEUE_TIME_VIOLATED.equals(e.getErrorNum())) { + throw new ArangoDBException(new TimeoutException().initCause(e)); } + throw e; + } else { + throw new ArangoDBException(String.format("Response Code: %s", responseCode), responseCode); } - } catch (final VPackParserException e) { - throw new ArangoDBException(e); } } } diff --git a/src/main/java/com/arangodb/model/AqlQueryExplainOptions.java b/src/main/java/com/arangodb/model/AqlQueryExplainOptions.java index 7e453a4b7..91e59d9a8 100644 --- a/src/main/java/com/arangodb/model/AqlQueryExplainOptions.java +++ b/src/main/java/com/arangodb/model/AqlQueryExplainOptions.java @@ -20,7 +20,8 @@ package com.arangodb.model; -import com.arangodb.velocypack.VPackSlice; +import com.arangodb.serde.InternalSerializers; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; import java.util.Collection; @@ -31,7 +32,7 @@ */ public class AqlQueryExplainOptions { - private VPackSlice bindVars; + private byte[] bindVars; private String query; private Options options; @@ -39,7 +40,8 @@ public AqlQueryExplainOptions() { super(); } - protected VPackSlice getBindVars() { + @JsonSerialize(using = InternalSerializers.AqlBindVarsSerializer.class) + public byte[] getBindVars() { return bindVars; } @@ -47,7 +49,7 @@ protected VPackSlice getBindVars() { * @param bindVars key/value pairs representing the bind parameters * @return options */ - protected AqlQueryExplainOptions bindVars(final VPackSlice bindVars) { + protected AqlQueryExplainOptions bindVars(final byte[] bindVars) { this.bindVars = bindVars; return this; } diff --git a/src/main/java/com/arangodb/model/AqlQueryOptions.java b/src/main/java/com/arangodb/model/AqlQueryOptions.java index 3b4fe5aee..75e43d189 100644 --- a/src/main/java/com/arangodb/model/AqlQueryOptions.java +++ b/src/main/java/com/arangodb/model/AqlQueryOptions.java @@ -147,7 +147,7 @@ public AqlQueryOptions fillBlockCache(final Boolean fillBlockCache) { return this; } - @JsonSerialize(using = InternalSerializers.AqlParamsSerializer.class) + @JsonSerialize(using = InternalSerializers.AqlBindVarsSerializer.class) public byte[] getBindVars() { return bindVars; } diff --git a/src/main/java/com/arangodb/model/DocumentReadOptions.java b/src/main/java/com/arangodb/model/DocumentReadOptions.java index 74c1af550..2ad9d4dfa 100644 --- a/src/main/java/com/arangodb/model/DocumentReadOptions.java +++ b/src/main/java/com/arangodb/model/DocumentReadOptions.java @@ -20,8 +20,6 @@ package com.arangodb.model; -import com.arangodb.velocypack.annotations.Expose; - /** * @author Mark Vollmary * @author Michele Rastelli diff --git a/src/main/java/com/arangodb/model/OptionsBuilder.java b/src/main/java/com/arangodb/model/OptionsBuilder.java index 52c79b62e..111bfcb1d 100644 --- a/src/main/java/com/arangodb/model/OptionsBuilder.java +++ b/src/main/java/com/arangodb/model/OptionsBuilder.java @@ -23,7 +23,6 @@ import com.arangodb.entity.EdgeDefinition; import com.arangodb.entity.Permissions; import com.arangodb.entity.ViewType; -import com.arangodb.velocypack.VPackSlice; import java.util.Collection; @@ -90,7 +89,7 @@ public static AqlQueryOptions build(final AqlQueryOptions options, final String public static AqlQueryExplainOptions build( final AqlQueryExplainOptions options, final String query, - final VPackSlice bindVars) { + final byte[] bindVars) { return options.query(query).bindVars(bindVars); } diff --git a/src/main/java/com/arangodb/serde/InternalModule.java b/src/main/java/com/arangodb/serde/InternalModule.java index c606daecb..fe7418f17 100644 --- a/src/main/java/com/arangodb/serde/InternalModule.java +++ b/src/main/java/com/arangodb/serde/InternalModule.java @@ -5,7 +5,6 @@ import com.arangodb.entity.ReplicationFactor; import com.arangodb.internal.velocystream.internal.AuthenticationRequest; import com.arangodb.internal.velocystream.internal.JwtAuthenticationRequest; -import com.arangodb.velocypack.VPackSlice; import com.arangodb.velocystream.Request; import com.arangodb.velocystream.Response; import com.fasterxml.jackson.databind.Module; @@ -21,7 +20,6 @@ enum InternalModule implements Supplier { InternalModule() { module = new SimpleModule(); - module.addSerializer(VPackSlice.class, InternalSerializers.VPACK_SLICE_JSON_SERIALIZER); module.addSerializer(AuthenticationRequest.class, InternalSerializers.AUTHENTICATION_REQUEST); module.addSerializer(JwtAuthenticationRequest.class, InternalSerializers.JWT_AUTHENTICATION_REQUEST); module.addSerializer(Request.class, InternalSerializers.REQUEST); diff --git a/src/main/java/com/arangodb/serde/InternalSerializers.java b/src/main/java/com/arangodb/serde/InternalSerializers.java index 635b35991..11aeb9a26 100644 --- a/src/main/java/com/arangodb/serde/InternalSerializers.java +++ b/src/main/java/com/arangodb/serde/InternalSerializers.java @@ -5,8 +5,6 @@ import com.arangodb.entity.arangosearch.FieldLink; import com.arangodb.internal.velocystream.internal.AuthenticationRequest; import com.arangodb.internal.velocystream.internal.JwtAuthenticationRequest; -import com.arangodb.jackson.dataformat.velocypack.VPackMapper; -import com.arangodb.velocypack.VPackSlice; import com.arangodb.velocystream.Request; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.core.JsonParser; @@ -20,10 +18,11 @@ public final class InternalSerializers { - public static class AqlParamsSerializer extends JsonSerializer { + public static class AqlBindVarsSerializer extends JsonSerializer { @Override public void serialize(byte[] value, JsonGenerator gen, SerializerProvider serializers) throws IOException { // TODO: find a way to append raw bytes directly + // see https://github.com/FasterXML/jackson-dataformats-binary/issues/331 try (JsonParser parser = gen.getCodec().getFactory().createParser(value)) { gen.writeTree(parser.readValueAsTree()); } @@ -59,18 +58,9 @@ public void serialize(Collection value, JsonGenerator gen, Seria } } - private static final VPackMapper vPackMapper = new VPackMapper(); - private InternalSerializers() { } - static final JsonSerializer VPACK_SLICE_JSON_SERIALIZER = new JsonSerializer() { - @Override - public void serialize(VPackSlice value, JsonGenerator gen, SerializerProvider serializers) throws IOException { - gen.writeObject(vPackMapper.readTree(value.toByteArray())); - } - }; - static final JsonSerializer AUTHENTICATION_REQUEST = new JsonSerializer() { @Override public void serialize(AuthenticationRequest value, JsonGenerator gen, SerializerProvider serializers) throws IOException { diff --git a/src/main/java/com/arangodb/serde/SerdeUtils.java b/src/main/java/com/arangodb/serde/SerdeUtils.java index 27e0c9eae..52ec7a6b8 100644 --- a/src/main/java/com/arangodb/serde/SerdeUtils.java +++ b/src/main/java/com/arangodb/serde/SerdeUtils.java @@ -4,11 +4,16 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.type.TypeFactory; + +import java.lang.reflect.Type; +import java.util.List; +import java.util.Map; public enum SerdeUtils { INSTANCE; - private ObjectMapper jsonMapper = new ObjectMapper(); + private final ObjectMapper jsonMapper = new ObjectMapper(); /** * Parse a JSON string. @@ -36,4 +41,12 @@ public String writeJson(final JsonNode data) { } } + public Type constructListType(Class clazz) { + return TypeFactory.defaultInstance().constructCollectionType(List.class, clazz); + } + + public Type constructMapType(Class keyClazz, Class valueClazz) { + return TypeFactory.defaultInstance().constructMapType(Map.class, keyClazz, valueClazz); + } + } diff --git a/src/main/java/com/arangodb/velocystream/Request.java b/src/main/java/com/arangodb/velocystream/Request.java index a0ebb0941..678808e59 100644 --- a/src/main/java/com/arangodb/velocystream/Request.java +++ b/src/main/java/com/arangodb/velocystream/Request.java @@ -21,7 +21,6 @@ package com.arangodb.velocystream; import com.arangodb.DbName; -import com.arangodb.velocypack.annotations.Expose; import java.util.HashMap; import java.util.Map; diff --git a/src/main/java/com/arangodb/velocystream/Response.java b/src/main/java/com/arangodb/velocystream/Response.java index 4d8a27af4..1f7b164bd 100644 --- a/src/main/java/com/arangodb/velocystream/Response.java +++ b/src/main/java/com/arangodb/velocystream/Response.java @@ -20,8 +20,6 @@ package com.arangodb.velocystream; -import com.arangodb.velocypack.annotations.Expose; - import java.util.HashMap; import java.util.Map; diff --git a/src/test/java/com/arangodb/ArangoDatabaseTest.java b/src/test/java/com/arangodb/ArangoDatabaseTest.java index d0f513b34..1afda7000 100644 --- a/src/test/java/com/arangodb/ArangoDatabaseTest.java +++ b/src/test/java/com/arangodb/ArangoDatabaseTest.java @@ -31,6 +31,9 @@ import com.arangodb.velocypack.ValueType; import com.arangodb.velocypack.exception.VPackException; import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.fasterxml.jackson.databind.node.JsonNodeFactory; +import com.fasterxml.jackson.databind.node.ObjectNode; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.MethodSource; @@ -907,6 +910,22 @@ void explainQuery(ArangoDatabase db) { assertThat(plan.getNodes()).isNotEmpty(); } + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void explainQueryWithBindVars(ArangoDatabase db) { + final AqlExecutionExplainEntity explain = db.explainQuery("for i in 1..1 return @value", + Collections.singletonMap("value", 11), null); + assertThat(explain).isNotNull(); + assertThat(explain.getPlan()).isNotNull(); + assertThat(explain.getPlans()).isNull(); + final ExecutionPlan plan = explain.getPlan(); + assertThat(plan.getCollections()).isEmpty(); + assertThat(plan.getEstimatedCost()).isPositive(); + assertThat(plan.getEstimatedNrItems()).isPositive(); + assertThat(plan.getVariables()).hasSize(3); + assertThat(plan.getNodes()).isNotEmpty(); + } + @ParameterizedTest(name = "{index}") @MethodSource("dbs") void explainQueryWithIndexNode(ArangoDatabase db) { @@ -1152,7 +1171,7 @@ void transactionNumber(ArangoDatabase db) { @ParameterizedTest(name = "{index}") @MethodSource("dbs") void transactionVPack(ArangoDatabase db) throws VPackException { - final TransactionOptions options = new TransactionOptions().params(new VPackBuilder().add("test").slice()); + final TransactionOptions options = new TransactionOptions().params(JsonNodeFactory.instance.textNode("test")); final JsonNode result = db.transaction("function (params) {return params;}", JsonNode.class, options); assertThat(result.isTextual()).isTrue(); assertThat(result.asText()).isEqualTo("test"); @@ -1160,9 +1179,8 @@ void transactionVPack(ArangoDatabase db) throws VPackException { @ParameterizedTest(name = "{index}") @MethodSource("dbs") - void transactionVPackObject(ArangoDatabase db) throws VPackException { - final VPackSlice params = new VPackBuilder().add(ValueType.OBJECT).add("foo", "hello").add("bar", "world") - .close().slice(); + void transactionJsonObject(ArangoDatabase db) throws VPackException { + ObjectNode params = JsonNodeFactory.instance.objectNode().put("foo", "hello").put("bar", "world"); final TransactionOptions options = new TransactionOptions().params(params); final String result = db .transaction("function (params) { return params['foo'] + ' ' + params['bar'];}", String.class, options); @@ -1172,7 +1190,7 @@ void transactionVPackObject(ArangoDatabase db) throws VPackException { @ParameterizedTest(name = "{index}") @MethodSource("dbs") void transactionJsonArray(ArangoDatabase db) throws VPackException { - final VPackSlice params = new VPackBuilder().add(ValueType.ARRAY).add("hello").add("world").close().slice(); + ArrayNode params = JsonNodeFactory.instance.arrayNode().add("hello").add("world"); final TransactionOptions options = new TransactionOptions().params(params); final String result = db .transaction("function (params) { return params[0] + ' ' + params[1];}", String.class, options); diff --git a/src/test/java/com/arangodb/async/ArangoDatabaseTest.java b/src/test/java/com/arangodb/async/ArangoDatabaseTest.java index 0ff4f81e8..be2fc3eef 100644 --- a/src/test/java/com/arangodb/async/ArangoDatabaseTest.java +++ b/src/test/java/com/arangodb/async/ArangoDatabaseTest.java @@ -31,6 +31,8 @@ import com.arangodb.velocypack.VPackSlice; import com.arangodb.velocypack.exception.VPackException; import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.node.JsonNodeFactory; +import com.fasterxml.jackson.databind.node.ObjectNode; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; @@ -891,7 +893,7 @@ void transactionNumber() throws InterruptedException, ExecutionException { @Test void transactionJsonNode() throws VPackException, InterruptedException, ExecutionException { - final TransactionOptions options = new TransactionOptions().params(new VPackBuilder().add("test").slice()); + final TransactionOptions options = new TransactionOptions().params(JsonNodeFactory.instance.textNode("test")); db.transaction("function (params) {return params;}", JsonNode.class, options) .whenComplete((result, ex) -> { assertThat(result.isTextual()).isEqualTo(true); From df97d318b4758b26edc01d1e390a6a6dc1af8629 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Wed, 20 Jul 2022 14:55:13 +0200 Subject: [PATCH 036/254] remove test dependencies on com.arangodb.velocypack --- .../com/arangodb/ArangoCollectionTest.java | 1 - src/test/java/com/arangodb/ArangoDBTest.java | 3 +- .../java/com/arangodb/ArangoDatabaseTest.java | 16 +-- .../java/com/arangodb/async/ArangoDBTest.java | 5 +- .../arangodb/async/ArangoDatabaseTest.java | 14 +-- .../document/GetDocumentExampleTest.java | 1 - .../example/velocypack/VPackExampleTest.java | 114 ------------------ .../com/arangodb/example/FirstProject.java | 14 +-- .../document/GetDocumentExampleTest.java | 1 - .../document/InsertDocumentExampleTest.java | 3 - .../example/velocypack/VPackExampleTest.java | 113 ----------------- .../velocypack/VPackSerializersTest.java | 76 ------------ .../annotations/ArangoAnnotationsTest.java | 22 ++-- .../com/arangodb/serde/CustomSerdeTest.java | 8 +- .../util/ArangoSerializationTest.java | 112 ----------------- 15 files changed, 36 insertions(+), 467 deletions(-) delete mode 100644 src/test/java/com/arangodb/async/example/velocypack/VPackExampleTest.java delete mode 100644 src/test/java/com/arangodb/example/velocypack/VPackExampleTest.java delete mode 100644 src/test/java/com/arangodb/internal/velocypack/VPackSerializersTest.java delete mode 100644 src/test/java/com/arangodb/util/ArangoSerializationTest.java diff --git a/src/test/java/com/arangodb/ArangoCollectionTest.java b/src/test/java/com/arangodb/ArangoCollectionTest.java index b1cb16ac3..6cf12bb73 100644 --- a/src/test/java/com/arangodb/ArangoCollectionTest.java +++ b/src/test/java/com/arangodb/ArangoCollectionTest.java @@ -38,7 +38,6 @@ import com.arangodb.model.*; import com.arangodb.model.DocumentImportOptions.OnDuplicate; import com.arangodb.util.MapBuilder; -import com.arangodb.velocypack.VPackSlice; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonIncludeProperties; import com.fasterxml.jackson.core.JsonProcessingException; diff --git a/src/test/java/com/arangodb/ArangoDBTest.java b/src/test/java/com/arangodb/ArangoDBTest.java index dfba5e9ce..b2d70b92b 100644 --- a/src/test/java/com/arangodb/ArangoDBTest.java +++ b/src/test/java/com/arangodb/ArangoDBTest.java @@ -25,7 +25,6 @@ import com.arangodb.model.*; import com.arangodb.model.LogOptions.SortOrder; import com.arangodb.util.TestUtils; -import com.arangodb.velocypack.exception.VPackException; import com.arangodb.velocystream.Request; import com.arangodb.velocystream.RequestType; import com.arangodb.velocystream.Response; @@ -393,7 +392,7 @@ void authenticationFailUser() { @ParameterizedTest(name = "{index}") @MethodSource("arangos") - void execute(ArangoDB arangoDB) throws VPackException { + void execute(ArangoDB arangoDB) { final Response response = arangoDB.execute(new Request(DbName.SYSTEM, RequestType.GET, "/_api/version")); assertThat(arangoDB.getInternalSerialization().parse(response.getBody(), "/version").isTextual()).isTrue(); } diff --git a/src/test/java/com/arangodb/ArangoDatabaseTest.java b/src/test/java/com/arangodb/ArangoDatabaseTest.java index 1afda7000..a5996fc39 100644 --- a/src/test/java/com/arangodb/ArangoDatabaseTest.java +++ b/src/test/java/com/arangodb/ArangoDatabaseTest.java @@ -26,10 +26,6 @@ import com.arangodb.entity.QueryCachePropertiesEntity.CacheMode; import com.arangodb.model.*; import com.arangodb.util.MapBuilder; -import com.arangodb.velocypack.VPackBuilder; -import com.arangodb.velocypack.VPackSlice; -import com.arangodb.velocypack.ValueType; -import com.arangodb.velocypack.exception.VPackException; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.node.ArrayNode; import com.fasterxml.jackson.databind.node.JsonNodeFactory; @@ -843,9 +839,9 @@ void queryWithWarning(ArangoDB arangoDB) { @MethodSource("dbs") void queryStream(ArangoDatabase db) { if (isAtLeastVersion(3, 4)) { - final ArangoCursor cursor = db + final ArangoCursor cursor = db .query("FOR i IN 1..2 RETURN i", null, new AqlQueryOptions().stream(true).count(true), - VPackSlice.class); + Void.class); assertThat((Object) cursor).isNotNull(); assertThat(cursor.getCount()).isNull(); } @@ -1170,7 +1166,7 @@ void transactionNumber(ArangoDatabase db) { @ParameterizedTest(name = "{index}") @MethodSource("dbs") - void transactionVPack(ArangoDatabase db) throws VPackException { + void transactionVPack(ArangoDatabase db) { final TransactionOptions options = new TransactionOptions().params(JsonNodeFactory.instance.textNode("test")); final JsonNode result = db.transaction("function (params) {return params;}", JsonNode.class, options); assertThat(result.isTextual()).isTrue(); @@ -1179,7 +1175,7 @@ void transactionVPack(ArangoDatabase db) throws VPackException { @ParameterizedTest(name = "{index}") @MethodSource("dbs") - void transactionJsonObject(ArangoDatabase db) throws VPackException { + void transactionJsonObject(ArangoDatabase db) { ObjectNode params = JsonNodeFactory.instance.objectNode().put("foo", "hello").put("bar", "world"); final TransactionOptions options = new TransactionOptions().params(params); final String result = db @@ -1189,7 +1185,7 @@ void transactionJsonObject(ArangoDatabase db) throws VPackException { @ParameterizedTest(name = "{index}") @MethodSource("dbs") - void transactionJsonArray(ArangoDatabase db) throws VPackException { + void transactionJsonArray(ArangoDatabase db) { ArrayNode params = JsonNodeFactory.instance.arrayNode().add("hello").add("world"); final TransactionOptions options = new TransactionOptions().params(params); final String result = db @@ -1335,7 +1331,7 @@ void shouldIncludeExceptionMessage(ArangoDatabase db) { final String exceptionMessage = "My error context"; final String action = "function (params) {" + "throw '" + exceptionMessage + "';" + "}"; try { - db.transaction(action, VPackSlice.class, null); + db.transaction(action, Void.class, null); fail(); } catch (final ArangoDBException e) { assertThat(e.getErrorMessage()).isEqualTo(exceptionMessage); diff --git a/src/test/java/com/arangodb/async/ArangoDBTest.java b/src/test/java/com/arangodb/async/ArangoDBTest.java index 7fb7497c0..134189fa3 100644 --- a/src/test/java/com/arangodb/async/ArangoDBTest.java +++ b/src/test/java/com/arangodb/async/ArangoDBTest.java @@ -25,7 +25,6 @@ import com.arangodb.mapping.ArangoJack; import com.arangodb.model.*; import com.arangodb.util.TestUtils; -import com.arangodb.velocypack.exception.VPackException; import com.arangodb.velocystream.Request; import com.arangodb.velocystream.RequestType; import org.junit.jupiter.api.Disabled; @@ -436,7 +435,7 @@ void authenticationFailUser() throws InterruptedException { } @Test - void execute() throws VPackException, InterruptedException, ExecutionException { + void execute() throws InterruptedException, ExecutionException { arangoDB .execute(new Request(DbName.SYSTEM, RequestType.GET, "/_api/version")) .whenComplete((response, ex) -> { @@ -447,7 +446,7 @@ void execute() throws VPackException, InterruptedException, ExecutionException { } @Test - void execute_acquireHostList_enabled() throws VPackException, InterruptedException, ExecutionException { + void execute_acquireHostList_enabled() throws InterruptedException, ExecutionException { final ArangoDBAsync arangoDB = new ArangoDBAsync.Builder().acquireHostList(true).serializer(new ArangoJack()).build(); arangoDB .execute(new Request(DbName.SYSTEM, RequestType.GET, "/_api/version")) diff --git a/src/test/java/com/arangodb/async/ArangoDatabaseTest.java b/src/test/java/com/arangodb/async/ArangoDatabaseTest.java index be2fc3eef..65513d2dc 100644 --- a/src/test/java/com/arangodb/async/ArangoDatabaseTest.java +++ b/src/test/java/com/arangodb/async/ArangoDatabaseTest.java @@ -27,12 +27,8 @@ import com.arangodb.entity.AqlParseEntity.AstNode; import com.arangodb.entity.QueryCachePropertiesEntity.CacheMode; import com.arangodb.model.*; -import com.arangodb.velocypack.VPackBuilder; -import com.arangodb.velocypack.VPackSlice; -import com.arangodb.velocypack.exception.VPackException; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.node.JsonNodeFactory; -import com.fasterxml.jackson.databind.node.ObjectNode; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; @@ -892,7 +888,7 @@ void transactionNumber() throws InterruptedException, ExecutionException { } @Test - void transactionJsonNode() throws VPackException, InterruptedException, ExecutionException { + void transactionJsonNode() throws InterruptedException, ExecutionException { final TransactionOptions options = new TransactionOptions().params(JsonNodeFactory.instance.textNode("test")); db.transaction("function (params) {return params;}", JsonNode.class, options) .whenComplete((result, ex) -> { @@ -908,7 +904,7 @@ void transactionEmpty() throws InterruptedException, ExecutionException { } @Test - void transactionallowImplicit() throws InterruptedException, ExecutionException { + void transactionAllowImplicit() throws InterruptedException, ExecutionException { try { db.createCollection("someCollection", null).get(); db.createCollection("someOtherCollection", null).get(); @@ -916,10 +912,10 @@ void transactionallowImplicit() throws InterruptedException, ExecutionException + "return {'a':db.someCollection.all().toArray()[0], 'b':db.someOtherCollection.all().toArray()[0]};" + "}"; final TransactionOptions options = new TransactionOptions().readCollections("someCollection"); - db.transaction(action, VPackSlice.class, options).get(); + db.transaction(action, Void.class, options).get(); try { options.allowImplicit(false); - db.transaction(action, VPackSlice.class, options).get(); + db.transaction(action, Void.class, options).get(); fail(); } catch (final ExecutionException e) { assertThat(e.getCause()).isInstanceOf(ArangoDBException.class); @@ -988,7 +984,7 @@ void shouldIncludeExceptionMessage() throws InterruptedException, ExecutionExcep final String exceptionMessage = "My error context"; final String action = "function (params) {" + "throw '" + exceptionMessage + "';" + "}"; try { - db.transaction(action, VPackSlice.class, null).get(); + db.transaction(action, Void.class, null).get(); fail(); } catch (final ExecutionException e) { assertThat(e.getCause()).isInstanceOf(ArangoDBException.class); diff --git a/src/test/java/com/arangodb/async/example/document/GetDocumentExampleTest.java b/src/test/java/com/arangodb/async/example/document/GetDocumentExampleTest.java index e2cb01a76..404422665 100644 --- a/src/test/java/com/arangodb/async/example/document/GetDocumentExampleTest.java +++ b/src/test/java/com/arangodb/async/example/document/GetDocumentExampleTest.java @@ -23,7 +23,6 @@ import com.arangodb.async.example.ExampleBase; import com.arangodb.entity.BaseDocument; import com.arangodb.entity.DocumentCreateEntity; -import com.arangodb.velocypack.VPackSlice; import com.fasterxml.jackson.databind.JsonNode; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; diff --git a/src/test/java/com/arangodb/async/example/velocypack/VPackExampleTest.java b/src/test/java/com/arangodb/async/example/velocypack/VPackExampleTest.java deleted file mode 100644 index a2a91781b..000000000 --- a/src/test/java/com/arangodb/async/example/velocypack/VPackExampleTest.java +++ /dev/null @@ -1,114 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.async.example.velocypack; - -import com.arangodb.velocypack.VPackBuilder; -import com.arangodb.velocypack.VPackSlice; -import com.arangodb.velocypack.ValueType; -import com.arangodb.velocypack.exception.VPackException; -import org.junit.jupiter.api.Test; - - -import java.util.Iterator; -import java.util.Map.Entry; - -import static org.assertj.core.api.Assertions.assertThat; - - -/** - * @author Mark Vollmary - */ -class VPackExampleTest { - - @Test - void buildObject() throws VPackException { - final VPackBuilder builder = new VPackBuilder(); - builder.add(ValueType.OBJECT);// object start - builder.add("foo", 1); // add field "foo" with value 1 - builder.add("bar", 2); // add field "bar" with value 2 - builder.close();// object end - - final VPackSlice slice = builder.slice(); // create slice - assertThat(slice.isObject()).isTrue(); - assertThat(slice.size()).isEqualTo(2); // number of fields - - final VPackSlice foo = slice.get("foo"); // get field "foo" - assertThat(foo.isInteger()).isTrue(); - assertThat(foo.getAsInt()).isEqualTo(1); - - final VPackSlice bar = slice.get("bar"); // get field "bar" - assertThat(bar.isInteger()).isTrue(); - assertThat(bar.getAsInt()).isEqualTo(2); - - // iterate over the fields - for (final Iterator> iterator = slice.objectIterator(); iterator.hasNext(); ) { - final Entry field = iterator.next(); - assertThat(field.getValue().isInteger()).isTrue(); - } - } - - @Test - void buildArray() throws VPackException { - final VPackBuilder builder = new VPackBuilder(); - builder.add(ValueType.ARRAY); // array start - builder.add(1);// add value 1 - builder.add(2);// add value 2 - builder.add(3);// add value 3 - builder.close(); // array end - - final VPackSlice slice = builder.slice();// create slice - assertThat(slice.isArray()).isTrue(); - assertThat(slice.size()).isEqualTo(3);// number of values - - // iterate over values - for (int i = 0; i < slice.size(); i++) { - final VPackSlice value = slice.get(i); - assertThat(value.isInteger()).isTrue(); - assertThat(value.getAsInt()).isEqualTo(i + 1); - } - - // iterate over values with Iterator - for (final Iterator iterator = slice.arrayIterator(); iterator.hasNext(); ) { - final VPackSlice value = iterator.next(); - assertThat(value.isInteger()).isTrue(); - } - } - - @Test - void buildObjectInObject() throws VPackException { - final VPackBuilder builder = new VPackBuilder(); - builder.add(ValueType.OBJECT);// object start - builder.add("foo", ValueType.OBJECT); // add object in field "foo" - builder.add("bar", 2); // add field "bar" with value 2 to object "foo" - builder.close();// object "foo" end - builder.close();// object end - - final VPackSlice slice = builder.slice(); // create slice - assertThat(slice.isObject()).isTrue(); - - final VPackSlice foo = slice.get("foo"); - assertThat(foo.isObject()).isTrue(); - - final VPackSlice bar = foo.get("bar"); // get field "bar" from "foo" - assertThat(bar.isInteger()).isTrue(); - } - -} diff --git a/src/test/java/com/arangodb/example/FirstProject.java b/src/test/java/com/arangodb/example/FirstProject.java index 63bcf034e..8164c26a3 100644 --- a/src/test/java/com/arangodb/example/FirstProject.java +++ b/src/test/java/com/arangodb/example/FirstProject.java @@ -5,7 +5,7 @@ import com.arangodb.entity.CollectionEntity; import com.arangodb.mapping.ArangoJack; import com.arangodb.util.MapBuilder; -import com.arangodb.velocypack.VPackSlice; +import com.fasterxml.jackson.databind.JsonNode; import java.util.Map; @@ -55,13 +55,13 @@ public static void main(final String[] args) { System.err.println("Failed to get document: myKey; " + e.getMessage()); } - // read a document as VPack + // read a document as JsonNode try { - final VPackSlice myDocument = arangoDB.db(dbName).collection(collectionName).getDocument("myKey", - VPackSlice.class); - System.out.println("Key: " + myDocument.get("_key").getAsString()); - System.out.println("Attribute a: " + myDocument.get("a").getAsString()); - System.out.println("Attribute b: " + myDocument.get("b").getAsInt()); + final JsonNode myDocument = arangoDB.db(dbName).collection(collectionName).getDocument("myKey", + JsonNode.class); + System.out.println("Key: " + myDocument.get("_key").textValue()); + System.out.println("Attribute a: " + myDocument.get("a").textValue()); + System.out.println("Attribute b: " + myDocument.get("b").textValue()); } catch (final ArangoDBException e) { System.err.println("Failed to get document: myKey; " + e.getMessage()); } diff --git a/src/test/java/com/arangodb/example/document/GetDocumentExampleTest.java b/src/test/java/com/arangodb/example/document/GetDocumentExampleTest.java index d7239a8f0..50b8cceea 100644 --- a/src/test/java/com/arangodb/example/document/GetDocumentExampleTest.java +++ b/src/test/java/com/arangodb/example/document/GetDocumentExampleTest.java @@ -23,7 +23,6 @@ import com.arangodb.entity.BaseDocument; import com.arangodb.entity.DocumentCreateEntity; import com.arangodb.example.ExampleBase; -import com.arangodb.velocypack.VPackSlice; import com.fasterxml.jackson.databind.JsonNode; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; diff --git a/src/test/java/com/arangodb/example/document/InsertDocumentExampleTest.java b/src/test/java/com/arangodb/example/document/InsertDocumentExampleTest.java index 8a4c38940..fbe81d69f 100644 --- a/src/test/java/com/arangodb/example/document/InsertDocumentExampleTest.java +++ b/src/test/java/com/arangodb/example/document/InsertDocumentExampleTest.java @@ -23,9 +23,6 @@ import com.arangodb.entity.BaseDocument; import com.arangodb.entity.DocumentCreateEntity; import com.arangodb.example.ExampleBase; -import com.arangodb.velocypack.VPackBuilder; -import com.arangodb.velocypack.VPackSlice; -import com.arangodb.velocypack.ValueType; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.node.ObjectNode; diff --git a/src/test/java/com/arangodb/example/velocypack/VPackExampleTest.java b/src/test/java/com/arangodb/example/velocypack/VPackExampleTest.java deleted file mode 100644 index dd1d1e421..000000000 --- a/src/test/java/com/arangodb/example/velocypack/VPackExampleTest.java +++ /dev/null @@ -1,113 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.example.velocypack; - -import com.arangodb.velocypack.VPackBuilder; -import com.arangodb.velocypack.VPackSlice; -import com.arangodb.velocypack.ValueType; -import com.arangodb.velocypack.exception.VPackException; -import org.junit.jupiter.api.Test; - -import java.util.Iterator; -import java.util.Map.Entry; - -import static org.assertj.core.api.Assertions.assertThat; - - -/** - * @author Mark Vollmary - */ -class VPackExampleTest { - - @Test - void buildObject() throws VPackException { - final VPackBuilder builder = new VPackBuilder(); - builder.add(ValueType.OBJECT);// object start - builder.add("foo", 1); // add field "foo" with value 1 - builder.add("bar", 2); // add field "bar" with value 2 - builder.close();// object end - - final VPackSlice slice = builder.slice(); // create slice - assertThat(slice.isObject()).isTrue(); - assertThat(slice.size()).isEqualTo(2); // number of fields - - final VPackSlice foo = slice.get("foo"); // get field "foo" - assertThat(foo.isInteger()).isTrue(); - assertThat(foo.getAsInt()).isEqualTo(1); - - final VPackSlice bar = slice.get("bar"); // get field "bar" - assertThat(bar.isInteger()).isTrue(); - assertThat(bar.getAsInt()).isEqualTo(2); - - // iterate over the fields - for (final Iterator> iterator = slice.objectIterator(); iterator.hasNext(); ) { - final Entry field = iterator.next(); - assertThat(field.getValue().isInteger()).isTrue(); - } - } - - @Test - void buildArray() throws VPackException { - final VPackBuilder builder = new VPackBuilder(); - builder.add(ValueType.ARRAY); // array start - builder.add(1);// add value 1 - builder.add(2);// add value 2 - builder.add(3);// add value 3 - builder.close(); // array end - - final VPackSlice slice = builder.slice();// create slice - assertThat(slice.isArray()).isTrue(); - assertThat(slice.size()).isEqualTo(3);// number of values - - // iterate over values - for (int i = 0; i < slice.size(); i++) { - final VPackSlice value = slice.get(i); - assertThat(value.isInteger()).isTrue(); - assertThat(value.getAsInt()).isEqualTo(i + 1); - } - - // iterate over values with Iterator - for (final Iterator iterator = slice.arrayIterator(); iterator.hasNext(); ) { - final VPackSlice value = iterator.next(); - assertThat(value.isInteger()).isTrue(); - } - } - - @Test - void buildObjectInObject() throws VPackException { - final VPackBuilder builder = new VPackBuilder(); - builder.add(ValueType.OBJECT);// object start - builder.add("foo", ValueType.OBJECT); // add object in field "foo" - builder.add("bar", 2); // add field "bar" with value 2 to object "foo" - builder.close();// object "foo" end - builder.close();// object end - - final VPackSlice slice = builder.slice(); // create slice - assertThat(slice.isObject()).isTrue(); - - final VPackSlice foo = slice.get("foo"); - assertThat(foo.isObject()).isTrue(); - - final VPackSlice bar = foo.get("bar"); // get field "bar" from "foo" - assertThat(bar.isInteger()).isTrue(); - } - -} diff --git a/src/test/java/com/arangodb/internal/velocypack/VPackSerializersTest.java b/src/test/java/com/arangodb/internal/velocypack/VPackSerializersTest.java deleted file mode 100644 index 0b8658a65..000000000 --- a/src/test/java/com/arangodb/internal/velocypack/VPackSerializersTest.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.internal.velocypack; - -import com.arangodb.entity.ViewType; -import com.arangodb.entity.arangosearch.ArangoSearchCompression; -import com.arangodb.entity.arangosearch.StoredValue; -import com.arangodb.model.arangosearch.ArangoSearchCreateOptions; -import com.arangodb.velocypack.VPack; -import com.arangodb.velocypack.VPackSlice; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -import java.util.Collections; - -import static org.assertj.core.api.Assertions.assertThat; - -class VPackSerializersTest { - - private VPack vpack; - - @BeforeEach - void init() { - vpack = new VPack.Builder().build(); - } - - @Test - void serializeArangoSearchProperties() { - final ArangoSearchCreateOptions opts = new ArangoSearchCreateOptions() - .storedValues(new StoredValue(Collections.singletonList("dummy"), ArangoSearchCompression.lz4)); - - final VPackSlice slice = vpack.serialize(opts); - - assertThat(slice.isObject()).isTrue(); - assertThat(slice.get("type").isString()).isTrue(); - assertThat(slice.get("type").getAsString()).isEqualTo(ViewType.ARANGO_SEARCH.name()); - assertThat(slice.get("storedValues")).isNotNull(); - assertThat(slice.get("storedValues").isArray()).isTrue(); - assertThat(slice.get("storedValues").size()).isEqualTo(1); - assertThat(slice.get("storedValues").get(0).isObject()).isTrue(); - assertThat(slice.get("storedValues").get(0).get("fields").isArray()).isTrue(); - assertThat(slice.get("storedValues").get(0).get("fields").size()).isEqualTo(1); - assertThat(slice.get("storedValues").get(0).get("fields").get(0).isString()).isTrue(); - assertThat(slice.get("storedValues").get(0).get("fields").get(0).getAsString()).isEqualTo("dummy"); - assertThat(slice.get("storedValues").get(0).get("compression").isString()).isTrue(); - assertThat(slice.get("storedValues").get(0).get("compression").getAsString()).isEqualTo(ArangoSearchCompression.lz4.name()); - } - - @Test - void serializeArangoSearchPropertiesWithDefaultCompression() { - final ArangoSearchCreateOptions opts = new ArangoSearchCreateOptions() - .storedValues(new StoredValue(Collections.singletonList("dummy"))); - - final VPackSlice slice = vpack.serialize(opts); - - assertThat(slice.get("storedValues").get(0).get("compression").isNone()).isTrue(); - } -} diff --git a/src/test/java/com/arangodb/mapping/annotations/ArangoAnnotationsTest.java b/src/test/java/com/arangodb/mapping/annotations/ArangoAnnotationsTest.java index cfd5d8124..1e1389b9c 100644 --- a/src/test/java/com/arangodb/mapping/annotations/ArangoAnnotationsTest.java +++ b/src/test/java/com/arangodb/mapping/annotations/ArangoAnnotationsTest.java @@ -20,9 +20,11 @@ package com.arangodb.mapping.annotations; -import com.arangodb.mapping.ArangoJack; -import com.arangodb.velocypack.VPackSlice; -import org.junit.jupiter.api.Test; +import com.arangodb.serde.ArangoSerde; +import com.arangodb.serde.DataType; +import com.arangodb.serde.JacksonSerde; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.EnumSource; import java.util.Map; @@ -33,10 +35,11 @@ */ class ArangoAnnotationsTest { - private final ArangoJack mapper = new ArangoJack(); + @ParameterizedTest + @EnumSource(DataType.class) + void documentFieldAnnotations(DataType dataType) { + ArangoSerde mapper = JacksonSerde.of(dataType); - @Test - void documentFieldAnnotations() { AnnotatedEntity e = new AnnotatedEntity(); e.setId("Id"); e.setKey("Key"); @@ -44,9 +47,8 @@ void documentFieldAnnotations() { e.setFrom("From"); e.setTo("To"); - VPackSlice slice = new VPackSlice(mapper.serialize(e)); - System.out.println(slice); - Map deserialized = mapper.deserialize(slice.toByteArray(), Object.class); + byte[] serialized = mapper.serialize(e); + Map deserialized = mapper.deserialize(serialized, Map.class); assertThat(deserialized) .containsEntry("_id", e.getId()) .containsEntry("_key", e.getKey()) @@ -55,7 +57,7 @@ void documentFieldAnnotations() { .containsEntry("_to", e.getTo()) .hasSize(5); - AnnotatedEntity deserializedEntity = mapper.deserialize(slice.toByteArray(), AnnotatedEntity.class); + AnnotatedEntity deserializedEntity = mapper.deserialize(serialized, AnnotatedEntity.class); assertThat(deserializedEntity).isEqualTo(e); } diff --git a/src/test/java/com/arangodb/serde/CustomSerdeTest.java b/src/test/java/com/arangodb/serde/CustomSerdeTest.java index dd6b2d5d8..94812aac4 100644 --- a/src/test/java/com/arangodb/serde/CustomSerdeTest.java +++ b/src/test/java/com/arangodb/serde/CustomSerdeTest.java @@ -29,8 +29,6 @@ import com.arangodb.mapping.ArangoJack; import com.arangodb.model.DocumentCreateOptions; import com.arangodb.util.ArangoSerialization; -import com.arangodb.velocypack.VPackBuilder; -import com.arangodb.velocypack.VPackSlice; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.databind.*; @@ -137,8 +135,8 @@ void manualCustomPersonDeserializer() { Person person = new Person(); person.name = "Joe"; ArangoSerialization serialization = arangoDB.getUserSerialization(); - VPackSlice serializedPerson = new VPackSlice(serialization.serialize(person)); - Person deserializedPerson = serialization.deserialize(serializedPerson.toByteArray(), Person.class); + byte[] serialized = serialization.serialize(person); + Person deserializedPerson = serialization.deserialize(serialized, Person.class); assertThat(deserializedPerson.name).isEqualTo(PERSON_DESERIALIZER_ADDED_PREFIX + PERSON_SERIALIZER_ADDED_PREFIX + person.name); } @@ -230,7 +228,7 @@ void getDocument() { @Test void parseNullString() { - final String json = arangoDB.getUserSerialization().deserialize(new VPackBuilder().add((String) null).slice().toByteArray(), String.class); + final String json = arangoDB.getUserSerialization().deserialize(arangoDB.getUserSerialization().serialize(null), String.class); assertThat(json).isNull(); } diff --git a/src/test/java/com/arangodb/util/ArangoSerializationTest.java b/src/test/java/com/arangodb/util/ArangoSerializationTest.java deleted file mode 100644 index 61c072a04..000000000 --- a/src/test/java/com/arangodb/util/ArangoSerializationTest.java +++ /dev/null @@ -1,112 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.util; - -import com.arangodb.ArangoDB; -import com.arangodb.entity.BaseDocument; -import com.arangodb.mapping.ArangoJack; -import com.arangodb.velocypack.*; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.Test; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.Map; - -import static org.assertj.core.api.Assertions.assertThat; - - -/** - * @author Mark Vollmary - */ -class ArangoSerializationTest { - - private static InternalSerialization internalSer; - private static ArangoSerialization userSer; - - @BeforeAll - static void setup() { - final ArangoDB arangoDB = new ArangoDB.Builder().serializer(new ArangoJack()).build(); - internalSer = arangoDB.getInternalSerialization(); - userSer = arangoDB.getUserSerialization(); - } - - @Test - void deserialize() { - final VPackBuilder builder = new VPackBuilder().add(ValueType.OBJECT).add("foo", "bar").close(); - final BaseDocument doc = internalSer.deserialize(builder.slice().toByteArray(), BaseDocument.class); - assertThat(doc.getAttribute("foo")).isEqualTo("bar"); - } - - @Test - void serialize() { - final BaseDocument entity = new BaseDocument(); - entity.addAttribute("foo", "bar"); - final VPackSlice vpack = new VPackSlice(internalSer.serialize(entity)); - assertThat(vpack.get("foo").isString()).isTrue(); - assertThat(vpack.get("foo").getAsString()).isEqualTo("bar"); - } - - @Test - void serializeNullValues() { - final BaseDocument entity = new BaseDocument(); - entity.addAttribute("foo", null); - final VPackSlice vpack = new VPackSlice(userSer.serialize(entity)); - assertThat(vpack.get("foo").isNull()).isTrue(); - } - - @Test - void skipSerializeNullValues() { - final BaseDocument entity = new BaseDocument(); - entity.addAttribute("bar", null); - final VPackSlice vpack = new VPackSlice(internalSer.serialize(entity)); - assertThat(vpack.get("bar").isNone()).isTrue(); - } - - @Test - void serializeType() { - final Collection list = new ArrayList<>(); - list.add(new BaseDocument()); - list.add(new BaseDocument()); - - final VPackSlice vpack = new VPackSlice(internalSer.serialize(list)); - assertThat(vpack.isArray()).isTrue(); - assertThat(vpack.getLength()).isEqualTo(list.size()); - } - - @Test - void parseJsonIncludeNull() { - final Map entity = new HashMap<>(); - entity.put("value", new String[]{"test", null}); - final Map res = userSer.deserialize(new VPackSlice(userSer.serialize(entity)).toByteArray(), Map.class); - assertThat(res.get("value")) - .asList() - .containsExactly("test", null); - } - - @Test - void parseNullString() { - final String json = internalSer.deserialize(new VPackBuilder().add((String) null).slice().toByteArray(), String.class); - assertThat(json).isNull(); - } - -} From f56f5c6fe2758f9203abba696f683589d05449e1 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Wed, 20 Jul 2022 15:38:22 +0200 Subject: [PATCH 037/254] removed old serialization classes --- .../java/com/arangodb/ArangoCollection.java | 2 +- src/main/java/com/arangodb/ArangoDB.java | 19 +-- .../java/com/arangodb/ArangoDatabase.java | 2 +- .../com/arangodb/ArangoEdgeCollection.java | 2 +- src/main/java/com/arangodb/ArangoGraph.java | 2 +- src/main/java/com/arangodb/ArangoRoute.java | 2 +- ...Accessor.java => ArangoSerdeAccessor.java} | 14 +- .../com/arangodb/ArangoVertexCollection.java | 2 +- src/main/java/com/arangodb/ArangoView.java | 2 +- .../arangodb/async/ArangoCollectionAsync.java | 4 +- .../com/arangodb/async/ArangoDBAsync.java | 17 +-- .../arangodb/async/ArangoDatabaseAsync.java | 4 +- .../async/ArangoEdgeCollectionAsync.java | 4 +- .../com/arangodb/async/ArangoGraphAsync.java | 4 +- .../com/arangodb/async/ArangoRouteAsync.java | 4 +- .../async/ArangoVertexCollectionAsync.java | 4 +- .../com/arangodb/async/ArangoViewAsync.java | 4 +- .../async/internal/ArangoDBAsyncImpl.java | 12 +- .../async/internal/ArangoExecutorAsync.java | 4 +- .../velocystream/VstCommunicationAsync.java | 6 +- .../com/arangodb/internal/ArangoDBImpl.java | 18 +-- .../arangodb/internal/ArangoExecuteable.java | 20 +-- .../com/arangodb/internal/ArangoExecutor.java | 8 +- .../arangodb/internal/ArangoExecutorSync.java | 4 +- .../internal/InternalArangoCollection.java | 139 +++++++++--------- .../arangodb/internal/InternalArangoDB.java | 30 ++-- .../internal/InternalArangoDBBuilder.java | 6 +- .../internal/InternalArangoDatabase.java | 64 ++++---- .../InternalArangoEdgeCollection.java | 14 +- .../internal/InternalArangoGraph.java | 16 +- .../internal/InternalArangoRoute.java | 2 +- .../internal/InternalArangoSearch.java | 4 +- .../InternalArangoVertexCollection.java | 16 +- .../arangodb/internal/InternalArangoView.java | 2 +- .../internal/cursor/ArangoCursorIterator.java | 4 +- .../arangodb/internal/http/CURLLogger.java | 4 +- .../internal/http/HttpCommunication.java | 4 +- .../internal/http/HttpConnection.java | 10 +- .../internal/http/HttpConnectionFactory.java | 4 +- .../internal/net/ExtendedHostResolver.java | 6 +- .../arangodb/internal/net/HostResolver.java | 4 +- .../internal/net/SimpleHostResolver.java | 4 +- ...onFactory.java => ArangoSerdeFactory.java} | 16 +- .../util/ArangoSerializationImpl.java | 28 ---- .../util/InternalSerializationImpl.java | 82 ----------- .../arangodb/internal/util/ResponseUtils.java | 4 +- .../velocystream/VstCommunication.java | 6 +- .../velocystream/VstCommunicationSync.java | 6 +- .../java/com/arangodb/mapping/ArangoJack.java | 82 ----------- .../arangodb/util/ArangoSerialization.java | 8 - .../arangodb/util/InternalSerialization.java | 47 ------ src/test/java/com/arangodb/ArangoDBTest.java | 11 +- .../java/com/arangodb/ArangoRouteTest.java | 2 +- src/test/java/com/arangodb/ArangoSslTest.java | 5 +- src/test/java/com/arangodb/BaseJunit5.java | 2 - .../java/com/arangodb/ConcurrencyTests.java | 3 +- src/test/java/com/arangodb/JwtAuthTest.java | 9 +- .../java/com/arangodb/async/ArangoDBTest.java | 17 +-- .../java/com/arangodb/async/BaseTest.java | 3 +- .../com/arangodb/async/CommunicationTest.java | 3 +- .../com/arangodb/async/ConcurrencyTest.java | 3 +- .../com/arangodb/async/ConcurrencyTests.java | 3 +- .../java/com/arangodb/async/JwtAuthTest.java | 9 +- .../debug/ConsolidationIntervalMsecTest.java | 2 - .../arangodb/async/example/ExampleBase.java | 3 +- ...ueryWithSpecialReturnTypesExampleTest.java | 10 +- .../graph/AQLActorsAndMoviesExampleTest.java | 3 +- .../async/example/graph/BaseGraphTest.java | 3 +- .../async/example/ssl/SslExampleTest.java | 3 +- .../arangodb/async/serde/CustomSerdeTest.java | 9 +- .../com/arangodb/example/ExampleBase.java | 3 +- .../com/arangodb/example/FirstProject.java | 9 +- ...ueryWithSpecialReturnTypesExampleTest.java | 10 +- .../graph/AQLActorsAndMoviesExampleTest.java | 3 +- .../arangodb/example/graph/BaseGraphTest.java | 3 +- .../arangodb/example/ssl/SslExampleTest.java | 5 +- .../arangodb/internal/HostHandlerTest.java | 6 +- .../velocystream/CommunicationTest.java | 11 +- .../com/arangodb/serde/CustomSerdeTest.java | 12 +- .../arangodb/serde/CustomTypeHintTest.java | 5 +- .../java/com/arangodb/util/MapBuilder.java | 92 ++++++------ src/test/java/perf/SimpleSyncPerfTest.java | 3 +- 82 files changed, 380 insertions(+), 661 deletions(-) rename src/main/java/com/arangodb/{ArangoSerializationAccessor.java => ArangoSerdeAccessor.java} (76%) rename src/main/java/com/arangodb/internal/util/{ArangoSerializationFactory.java => ArangoSerdeFactory.java} (66%) delete mode 100644 src/main/java/com/arangodb/internal/util/ArangoSerializationImpl.java delete mode 100644 src/main/java/com/arangodb/internal/util/InternalSerializationImpl.java delete mode 100644 src/main/java/com/arangodb/mapping/ArangoJack.java delete mode 100644 src/main/java/com/arangodb/util/ArangoSerialization.java delete mode 100644 src/main/java/com/arangodb/util/InternalSerialization.java rename src/{main => test}/java/com/arangodb/util/MapBuilder.java (96%) diff --git a/src/main/java/com/arangodb/ArangoCollection.java b/src/main/java/com/arangodb/ArangoCollection.java index 2073ff689..3af131403 100644 --- a/src/main/java/com/arangodb/ArangoCollection.java +++ b/src/main/java/com/arangodb/ArangoCollection.java @@ -35,7 +35,7 @@ * @see Documents API Documentation */ @SuppressWarnings("UnusedReturnValue") -public interface ArangoCollection extends ArangoSerializationAccessor { +public interface ArangoCollection extends ArangoSerdeAccessor { /** * The the handler of the database the collection is within diff --git a/src/main/java/com/arangodb/ArangoDB.java b/src/main/java/com/arangodb/ArangoDB.java index 5efa9db1e..3ac79ee8d 100644 --- a/src/main/java/com/arangodb/ArangoDB.java +++ b/src/main/java/com/arangodb/ArangoDB.java @@ -28,9 +28,7 @@ import com.arangodb.internal.http.HttpCommunication; import com.arangodb.internal.http.HttpConnectionFactory; import com.arangodb.internal.net.*; -import com.arangodb.internal.util.ArangoSerializationFactory; -import com.arangodb.internal.util.ArangoSerializationImpl; -import com.arangodb.internal.util.InternalSerializationImpl; +import com.arangodb.internal.util.ArangoSerdeFactory; import com.arangodb.internal.velocystream.VstCommunicationSync; import com.arangodb.internal.velocystream.VstConnectionFactorySync; import com.arangodb.model.DBCreateOptions; @@ -41,8 +39,8 @@ import com.arangodb.serde.InternalSerde; import com.arangodb.serde.JacksonSerde; import com.arangodb.util.ArangoCursorInitializer; -import com.arangodb.util.ArangoSerialization; -import com.arangodb.util.InternalSerialization; +import com.arangodb.serde.ArangoSerde; +import com.arangodb.serde.InternalSerde; import com.arangodb.velocystream.Request; import com.arangodb.velocystream.Response; import org.apache.http.client.HttpRequestRetryHandler; @@ -72,7 +70,7 @@ * @author Michele Rastelli */ @SuppressWarnings("UnusedReturnValue") -public interface ArangoDB extends ArangoSerializationAccessor { +public interface ArangoDB extends ArangoSerdeAccessor { /** * Builder class to build an instance of {@link ArangoDB}. @@ -335,7 +333,7 @@ public Builder responseQueueTimeSamples(final Integer responseQueueTimeSamples) * @param serialization custom serializer/deserializer * @return {@link ArangoDB.Builder} */ - public Builder serializer(final ArangoSerialization serialization) { + public Builder serializer(final ArangoSerde serialization) { setSerializer(serialization); return this; } @@ -349,10 +347,9 @@ public synchronized ArangoDB build() { if (hosts.isEmpty()) { hosts.add(host); } - final InternalSerde internalSerde = InternalSerde.of(DataType.of(protocol)); - final InternalSerialization internal = new InternalSerializationImpl(internalSerde); - final ArangoSerialization custom = customSerializer != null ? customSerializer : new ArangoSerializationImpl(JacksonSerde.of(DataType.of(protocol))); - final ArangoSerializationFactory util = new ArangoSerializationFactory(internal, custom); + final InternalSerde internal = InternalSerde.of(DataType.of(protocol)); + final ArangoSerde custom = customSerializer != null ? customSerializer : JacksonSerde.of(DataType.of(protocol)); + final ArangoSerdeFactory util = new ArangoSerdeFactory(internal, custom); int protocolMaxConnections = protocol == Protocol.VST ? ArangoDefaults.MAX_CONNECTIONS_VST_DEFAULT : diff --git a/src/main/java/com/arangodb/ArangoDatabase.java b/src/main/java/com/arangodb/ArangoDatabase.java index 24146626c..826d301fd 100644 --- a/src/main/java/com/arangodb/ArangoDatabase.java +++ b/src/main/java/com/arangodb/ArangoDatabase.java @@ -38,7 +38,7 @@ * @see Query API Documentation */ @SuppressWarnings("UnusedReturnValue") -public interface ArangoDatabase extends ArangoSerializationAccessor { +public interface ArangoDatabase extends ArangoSerdeAccessor { /** * Return the main entry point for the ArangoDB driver diff --git a/src/main/java/com/arangodb/ArangoEdgeCollection.java b/src/main/java/com/arangodb/ArangoEdgeCollection.java index 17d6d054b..702728e99 100644 --- a/src/main/java/com/arangodb/ArangoEdgeCollection.java +++ b/src/main/java/com/arangodb/ArangoEdgeCollection.java @@ -31,7 +31,7 @@ * @see API Documentation */ @SuppressWarnings("UnusedReturnValue") -public interface ArangoEdgeCollection extends ArangoSerializationAccessor { +public interface ArangoEdgeCollection extends ArangoSerdeAccessor { /** * The the handler of the named graph the edge collection is within diff --git a/src/main/java/com/arangodb/ArangoGraph.java b/src/main/java/com/arangodb/ArangoGraph.java index 873405cda..a9b562a68 100644 --- a/src/main/java/com/arangodb/ArangoGraph.java +++ b/src/main/java/com/arangodb/ArangoGraph.java @@ -33,7 +33,7 @@ * @author Mark Vollmary * @see API Documentation */ -public interface ArangoGraph extends ArangoSerializationAccessor { +public interface ArangoGraph extends ArangoSerdeAccessor { /** * The the handler of the database the named graph is within diff --git a/src/main/java/com/arangodb/ArangoRoute.java b/src/main/java/com/arangodb/ArangoRoute.java index fd32eb6e5..a32e09f70 100644 --- a/src/main/java/com/arangodb/ArangoRoute.java +++ b/src/main/java/com/arangodb/ArangoRoute.java @@ -27,7 +27,7 @@ * * @author Mark Vollmary */ -public interface ArangoRoute extends ArangoSerializationAccessor { +public interface ArangoRoute extends ArangoSerdeAccessor { /** * Returns a new {@link ArangoRoute} instance for the given path (relative to the current route) that can be used to diff --git a/src/main/java/com/arangodb/ArangoSerializationAccessor.java b/src/main/java/com/arangodb/ArangoSerdeAccessor.java similarity index 76% rename from src/main/java/com/arangodb/ArangoSerializationAccessor.java rename to src/main/java/com/arangodb/ArangoSerdeAccessor.java index 0f811517c..4c73ef488 100644 --- a/src/main/java/com/arangodb/ArangoSerializationAccessor.java +++ b/src/main/java/com/arangodb/ArangoSerdeAccessor.java @@ -20,26 +20,26 @@ package com.arangodb; -import com.arangodb.util.ArangoSerialization; -import com.arangodb.util.InternalSerialization; +import com.arangodb.serde.ArangoSerde; +import com.arangodb.serde.InternalSerde; /** * @author Mark Vollmary */ -public interface ArangoSerializationAccessor { +public interface ArangoSerdeAccessor { /** * Returns driver internal serialization implementation for serializing and deserializing driver's classes. * - * @return ArangoSerialization + * @return ArangoSerde */ - InternalSerialization getInternalSerialization(); + InternalSerde getInternalSerde(); /** * Returns serialization implementation for serializing and deserializing user's classes. * - * @return ArangoSerialization + * @return ArangoSerde */ - ArangoSerialization getUserSerialization(); + ArangoSerde getUserSerde(); } diff --git a/src/main/java/com/arangodb/ArangoVertexCollection.java b/src/main/java/com/arangodb/ArangoVertexCollection.java index e34705cf4..ffc1a39f0 100644 --- a/src/main/java/com/arangodb/ArangoVertexCollection.java +++ b/src/main/java/com/arangodb/ArangoVertexCollection.java @@ -30,7 +30,7 @@ * @author Mark Vollmary * @see API Documentation */ -public interface ArangoVertexCollection extends ArangoSerializationAccessor { +public interface ArangoVertexCollection extends ArangoSerdeAccessor { /** * The the handler of the named graph the edge collection is within diff --git a/src/main/java/com/arangodb/ArangoView.java b/src/main/java/com/arangodb/ArangoView.java index 56a3a7995..b275d1131 100644 --- a/src/main/java/com/arangodb/ArangoView.java +++ b/src/main/java/com/arangodb/ArangoView.java @@ -30,7 +30,7 @@ * @since ArangoDB 3.4.0 */ @SuppressWarnings("UnusedReturnValue") -public interface ArangoView extends ArangoSerializationAccessor { +public interface ArangoView extends ArangoSerdeAccessor { /** * The the handler of the database the collection is within diff --git a/src/main/java/com/arangodb/async/ArangoCollectionAsync.java b/src/main/java/com/arangodb/async/ArangoCollectionAsync.java index 91837285b..8d2194f43 100644 --- a/src/main/java/com/arangodb/async/ArangoCollectionAsync.java +++ b/src/main/java/com/arangodb/async/ArangoCollectionAsync.java @@ -21,7 +21,7 @@ package com.arangodb.async; import com.arangodb.ArangoDBException; -import com.arangodb.ArangoSerializationAccessor; +import com.arangodb.ArangoSerdeAccessor; import com.arangodb.entity.*; import com.arangodb.model.*; @@ -36,7 +36,7 @@ * @see Documents API Documentation */ @SuppressWarnings("unused") -public interface ArangoCollectionAsync extends ArangoSerializationAccessor { +public interface ArangoCollectionAsync extends ArangoSerdeAccessor { /** * The the handler of the database the collection is within diff --git a/src/main/java/com/arangodb/async/ArangoDBAsync.java b/src/main/java/com/arangodb/async/ArangoDBAsync.java index 3bfa3d046..44a01a679 100644 --- a/src/main/java/com/arangodb/async/ArangoDBAsync.java +++ b/src/main/java/com/arangodb/async/ArangoDBAsync.java @@ -31,9 +31,7 @@ import com.arangodb.internal.net.ConnectionFactory; import com.arangodb.internal.net.HostHandler; import com.arangodb.internal.net.HostResolver; -import com.arangodb.internal.util.ArangoSerializationFactory; -import com.arangodb.internal.util.ArangoSerializationImpl; -import com.arangodb.internal.util.InternalSerializationImpl; +import com.arangodb.internal.util.ArangoSerdeFactory; import com.arangodb.internal.velocystream.VstCommunicationSync; import com.arangodb.internal.velocystream.VstConnectionFactorySync; import com.arangodb.model.DBCreateOptions; @@ -43,7 +41,7 @@ import com.arangodb.serde.DataType; import com.arangodb.serde.InternalSerde; import com.arangodb.serde.JacksonSerde; -import com.arangodb.util.ArangoSerialization; +import com.arangodb.serde.ArangoSerde; import com.arangodb.velocystream.Request; import com.arangodb.velocystream.Response; import org.slf4j.Logger; @@ -68,7 +66,7 @@ * * @author Mark Vollmary */ -public interface ArangoDBAsync extends ArangoSerializationAccessor { +public interface ArangoDBAsync extends ArangoSerdeAccessor { void shutdown() throws ArangoDBException; @@ -496,7 +494,7 @@ public Builder loadBalancingStrategy(final LoadBalancingStrategy loadBalancingSt * @param serialization custom serializer/deserializer * @return {@link ArangoDBAsync.Builder} */ - public Builder serializer(final ArangoSerialization serialization) { + public Builder serializer(final ArangoSerde serialization) { setSerializer(serialization); return this; } @@ -510,10 +508,9 @@ public synchronized ArangoDBAsync build() { if (hosts.isEmpty()) { hosts.add(host); } - final InternalSerde internalSerde = InternalSerde.of(DataType.VPACK); - final InternalSerializationImpl internal = new InternalSerializationImpl(internalSerde); - final ArangoSerialization custom = customSerializer != null ? customSerializer : new ArangoSerializationImpl(JacksonSerde.of(DataType.VPACK)); - final ArangoSerializationFactory util = new ArangoSerializationFactory(internal, custom); + final InternalSerde internal = InternalSerde.of(DataType.VPACK); + final ArangoSerde custom = customSerializer != null ? customSerializer : JacksonSerde.of(DataType.VPACK); + final ArangoSerdeFactory util = new ArangoSerdeFactory(internal, custom); final int max = maxConnections != null ? Math.max(1, maxConnections) : ArangoDefaults.MAX_CONNECTIONS_VST_DEFAULT; diff --git a/src/main/java/com/arangodb/async/ArangoDatabaseAsync.java b/src/main/java/com/arangodb/async/ArangoDatabaseAsync.java index d3ed12c32..0a7648967 100644 --- a/src/main/java/com/arangodb/async/ArangoDatabaseAsync.java +++ b/src/main/java/com/arangodb/async/ArangoDatabaseAsync.java @@ -21,7 +21,7 @@ package com.arangodb.async; import com.arangodb.ArangoDBException; -import com.arangodb.ArangoSerializationAccessor; +import com.arangodb.ArangoSerdeAccessor; import com.arangodb.DbName; import com.arangodb.entity.*; import com.arangodb.entity.arangosearch.analyzer.SearchAnalyzer; @@ -41,7 +41,7 @@ * @see Query API Documentation */ @SuppressWarnings("unused") -public interface ArangoDatabaseAsync extends ArangoSerializationAccessor { +public interface ArangoDatabaseAsync extends ArangoSerdeAccessor { /** * Return the main entry point for the ArangoDB driver diff --git a/src/main/java/com/arangodb/async/ArangoEdgeCollectionAsync.java b/src/main/java/com/arangodb/async/ArangoEdgeCollectionAsync.java index 2dea8807c..f87d1f4c7 100644 --- a/src/main/java/com/arangodb/async/ArangoEdgeCollectionAsync.java +++ b/src/main/java/com/arangodb/async/ArangoEdgeCollectionAsync.java @@ -20,7 +20,7 @@ package com.arangodb.async; -import com.arangodb.ArangoSerializationAccessor; +import com.arangodb.ArangoSerdeAccessor; import com.arangodb.entity.EdgeEntity; import com.arangodb.entity.EdgeUpdateEntity; import com.arangodb.model.*; @@ -34,7 +34,7 @@ * @see API Documentation */ @SuppressWarnings("unused") -public interface ArangoEdgeCollectionAsync extends ArangoSerializationAccessor { +public interface ArangoEdgeCollectionAsync extends ArangoSerdeAccessor { /** * The the handler of the named graph the edge collection is within diff --git a/src/main/java/com/arangodb/async/ArangoGraphAsync.java b/src/main/java/com/arangodb/async/ArangoGraphAsync.java index 17cb45a95..0fae79e0b 100644 --- a/src/main/java/com/arangodb/async/ArangoGraphAsync.java +++ b/src/main/java/com/arangodb/async/ArangoGraphAsync.java @@ -20,7 +20,7 @@ package com.arangodb.async; -import com.arangodb.ArangoSerializationAccessor; +import com.arangodb.ArangoSerdeAccessor; import com.arangodb.entity.EdgeDefinition; import com.arangodb.entity.GraphEntity; import com.arangodb.model.GraphCreateOptions; @@ -36,7 +36,7 @@ * @see API Documentation */ @SuppressWarnings("unused") -public interface ArangoGraphAsync extends ArangoSerializationAccessor { +public interface ArangoGraphAsync extends ArangoSerdeAccessor { /** * The the handler of the database the named graph is within diff --git a/src/main/java/com/arangodb/async/ArangoRouteAsync.java b/src/main/java/com/arangodb/async/ArangoRouteAsync.java index ab384f99b..2605cbf53 100644 --- a/src/main/java/com/arangodb/async/ArangoRouteAsync.java +++ b/src/main/java/com/arangodb/async/ArangoRouteAsync.java @@ -20,7 +20,7 @@ package com.arangodb.async; -import com.arangodb.ArangoSerializationAccessor; +import com.arangodb.ArangoSerdeAccessor; import com.arangodb.velocystream.Response; import java.util.concurrent.CompletableFuture; @@ -31,7 +31,7 @@ * @author Mark Vollmary */ @SuppressWarnings("unused") -public interface ArangoRouteAsync extends ArangoSerializationAccessor { +public interface ArangoRouteAsync extends ArangoSerdeAccessor { /** * Returns a new {@link ArangoRouteAsync} instance for the given path (relative to the current route) that can be diff --git a/src/main/java/com/arangodb/async/ArangoVertexCollectionAsync.java b/src/main/java/com/arangodb/async/ArangoVertexCollectionAsync.java index b610a9796..ed3f98629 100644 --- a/src/main/java/com/arangodb/async/ArangoVertexCollectionAsync.java +++ b/src/main/java/com/arangodb/async/ArangoVertexCollectionAsync.java @@ -20,7 +20,7 @@ package com.arangodb.async; -import com.arangodb.ArangoSerializationAccessor; +import com.arangodb.ArangoSerdeAccessor; import com.arangodb.entity.VertexEntity; import com.arangodb.entity.VertexUpdateEntity; import com.arangodb.model.*; @@ -34,7 +34,7 @@ * @see API Documentation */ @SuppressWarnings("unused") -public interface ArangoVertexCollectionAsync extends ArangoSerializationAccessor { +public interface ArangoVertexCollectionAsync extends ArangoSerdeAccessor { /** * The the handler of the named graph the edge collection is within diff --git a/src/main/java/com/arangodb/async/ArangoViewAsync.java b/src/main/java/com/arangodb/async/ArangoViewAsync.java index fed3da081..c06289cee 100644 --- a/src/main/java/com/arangodb/async/ArangoViewAsync.java +++ b/src/main/java/com/arangodb/async/ArangoViewAsync.java @@ -20,7 +20,7 @@ package com.arangodb.async; -import com.arangodb.ArangoSerializationAccessor; +import com.arangodb.ArangoSerdeAccessor; import com.arangodb.entity.ViewEntity; import java.util.concurrent.CompletableFuture; @@ -33,7 +33,7 @@ * @since ArangoDB 3.4.0 */ @SuppressWarnings("unused") -public interface ArangoViewAsync extends ArangoSerializationAccessor { +public interface ArangoViewAsync extends ArangoSerdeAccessor { /** * The the handler of the database the collection is within diff --git a/src/main/java/com/arangodb/async/internal/ArangoDBAsyncImpl.java b/src/main/java/com/arangodb/async/internal/ArangoDBAsyncImpl.java index 70c2ef595..f670e839e 100644 --- a/src/main/java/com/arangodb/async/internal/ArangoDBAsyncImpl.java +++ b/src/main/java/com/arangodb/async/internal/ArangoDBAsyncImpl.java @@ -31,7 +31,7 @@ import com.arangodb.internal.net.CommunicationProtocol; import com.arangodb.internal.net.HostHandler; import com.arangodb.internal.net.HostResolver; -import com.arangodb.internal.util.ArangoSerializationFactory; +import com.arangodb.internal.util.ArangoSerdeFactory; import com.arangodb.internal.velocystream.VstCommunication; import com.arangodb.internal.velocystream.VstCommunicationSync; import com.arangodb.internal.velocystream.VstProtocol; @@ -62,7 +62,7 @@ public class ArangoDBAsyncImpl extends InternalArangoDB imp public ArangoDBAsyncImpl( final VstCommunicationAsync.Builder asyncCommBuilder, - final ArangoSerializationFactory util, + final ArangoSerdeFactory util, final VstCommunicationSync.Builder syncCommBuilder, final HostResolver asyncHostResolver, final HostResolver syncHostResolver, @@ -73,10 +73,10 @@ public ArangoDBAsyncImpl( final int timeoutMs ) { - super(new ArangoExecutorAsync(asyncCommBuilder.build(util.getInternalSerialization()), util, new DocumentCache(), + super(new ArangoExecutorAsync(asyncCommBuilder.build(util.getInternalSerde()), util, new DocumentCache(), new QueueTimeMetricsImpl(responseQueueTimeSamples), timeoutMs), util, context); - final VstCommunication cacheCom = syncCommBuilder.build(util.getInternalSerialization()); + final VstCommunication cacheCom = syncCommBuilder.build(util.getInternalSerde()); cp = new VstProtocol(cacheCom); this.asyncHostHandler = asyncHostHandler; @@ -84,8 +84,8 @@ public ArangoDBAsyncImpl( ArangoExecutorSync arangoExecutorSync = new ArangoExecutorSync(cp, util, new DocumentCache(), new QueueTimeMetricsImpl(responseQueueTimeSamples), timeoutMs); - asyncHostResolver.init(arangoExecutorSync, util.getInternalSerialization()); - syncHostResolver.init(arangoExecutorSync, util.getInternalSerialization()); + asyncHostResolver.init(arangoExecutorSync, util.getInternalSerde()); + syncHostResolver.init(arangoExecutorSync, util.getInternalSerde()); } diff --git a/src/main/java/com/arangodb/async/internal/ArangoExecutorAsync.java b/src/main/java/com/arangodb/async/internal/ArangoExecutorAsync.java index 6a1cea3a1..ab8ac57e0 100644 --- a/src/main/java/com/arangodb/async/internal/ArangoExecutorAsync.java +++ b/src/main/java/com/arangodb/async/internal/ArangoExecutorAsync.java @@ -26,7 +26,7 @@ import com.arangodb.internal.DocumentCache; import com.arangodb.internal.QueueTimeMetricsImpl; import com.arangodb.internal.net.HostHandle; -import com.arangodb.internal.util.ArangoSerializationFactory; +import com.arangodb.internal.util.ArangoSerdeFactory; import com.arangodb.velocystream.Request; import java.io.IOException; @@ -44,7 +44,7 @@ public class ArangoExecutorAsync extends ArangoExecutor { private final VstCommunicationAsync communication; private final ExecutorService outgoingExecutor = Executors.newSingleThreadExecutor(); - public ArangoExecutorAsync(final VstCommunicationAsync communication, final ArangoSerializationFactory util, + public ArangoExecutorAsync(final VstCommunicationAsync communication, final ArangoSerdeFactory util, final DocumentCache documentCache, final QueueTimeMetricsImpl qtMetrics, final int timeoutMs) { super(util, documentCache, qtMetrics, timeoutMs); this.communication = communication; diff --git a/src/main/java/com/arangodb/async/internal/velocystream/VstCommunicationAsync.java b/src/main/java/com/arangodb/async/internal/velocystream/VstCommunicationAsync.java index 030ebc5f2..410b8dc9a 100644 --- a/src/main/java/com/arangodb/async/internal/velocystream/VstCommunicationAsync.java +++ b/src/main/java/com/arangodb/async/internal/velocystream/VstCommunicationAsync.java @@ -30,7 +30,7 @@ import com.arangodb.internal.velocystream.internal.AuthenticationRequest; import com.arangodb.internal.velocystream.internal.JwtAuthenticationRequest; import com.arangodb.internal.velocystream.internal.Message; -import com.arangodb.util.InternalSerialization; +import com.arangodb.serde.InternalSerde; import com.arangodb.velocypack.exception.VPackException; import com.arangodb.velocypack.exception.VPackParserException; import com.arangodb.velocystream.Request; @@ -50,7 +50,7 @@ public class VstCommunicationAsync extends VstCommunication implement private final HostHandler hostHandler; public ArangoDBImpl(final VstCommunicationSync.Builder vstBuilder, final HttpCommunication.Builder httpBuilder, - final ArangoSerializationFactory util, final Protocol protocol, final HostResolver hostResolver, + final ArangoSerdeFactory util, final Protocol protocol, final HostResolver hostResolver, final HostHandler hostHandler, final ArangoContext context, int responseQueueTimeSamples, final int timeoutMs) { super(new ArangoExecutorSync( - createProtocol(vstBuilder, httpBuilder, util.getInternalSerialization(), protocol), + createProtocol(vstBuilder, httpBuilder, util.getInternalSerde(), protocol), util, new DocumentCache(), new QueueTimeMetricsImpl(responseQueueTimeSamples), timeoutMs), util, @@ -72,11 +72,11 @@ public ArangoDBImpl(final VstCommunicationSync.Builder vstBuilder, final HttpCom cp = createProtocol( new VstCommunicationSync.Builder(vstBuilder).maxConnections(1), new HttpCommunication.Builder(httpBuilder), - util.getInternalSerialization(), + util.getInternalSerde(), protocol); this.hostHandler = hostHandler; - hostResolver.init(this.executor(), getInternalSerialization()); + hostResolver.init(this.executor(), getInternalSerde()); LOGGER.debug("ArangoDB Client is ready to use"); @@ -85,7 +85,7 @@ public ArangoDBImpl(final VstCommunicationSync.Builder vstBuilder, final HttpCom private static CommunicationProtocol createProtocol( final VstCommunicationSync.Builder vstBuilder, final HttpCommunication.Builder httpBuilder, - final InternalSerialization util, + final InternalSerde util, final Protocol protocol) { return (protocol == null || Protocol.VST == protocol) ? createVST(vstBuilder, util) @@ -94,13 +94,13 @@ private static CommunicationProtocol createProtocol( private static CommunicationProtocol createVST( final VstCommunicationSync.Builder builder, - final InternalSerialization util) { + final InternalSerde util) { return new VstProtocol(builder.build(util)); } private static CommunicationProtocol createHTTP( final HttpCommunication.Builder builder, - final InternalSerialization util) { + final InternalSerde util) { return new HttpProtocol(builder.build(util)); } diff --git a/src/main/java/com/arangodb/internal/ArangoExecuteable.java b/src/main/java/com/arangodb/internal/ArangoExecuteable.java index 2410da540..b3b6d958e 100644 --- a/src/main/java/com/arangodb/internal/ArangoExecuteable.java +++ b/src/main/java/com/arangodb/internal/ArangoExecuteable.java @@ -20,12 +20,12 @@ package com.arangodb.internal; -import com.arangodb.ArangoSerializationAccessor; +import com.arangodb.ArangoSerdeAccessor; import com.arangodb.DbName; -import com.arangodb.internal.util.ArangoSerializationFactory; +import com.arangodb.internal.util.ArangoSerdeFactory; import com.arangodb.internal.util.EncodeUtils; -import com.arangodb.util.ArangoSerialization; -import com.arangodb.util.InternalSerialization; +import com.arangodb.serde.ArangoSerde; +import com.arangodb.serde.InternalSerde; import com.arangodb.velocystream.Request; import com.arangodb.velocystream.RequestType; @@ -34,15 +34,15 @@ /** * @author Mark Vollmary */ -public abstract class ArangoExecuteable implements ArangoSerializationAccessor { +public abstract class ArangoExecuteable implements ArangoSerdeAccessor { private static final String SLASH = "/"; protected final E executor; - protected final ArangoSerializationFactory util; + protected final ArangoSerdeFactory util; protected final ArangoContext context; - protected ArangoExecuteable(final E executor, final ArangoSerializationFactory util, final ArangoContext context) { + protected ArangoExecuteable(final E executor, final ArangoSerdeFactory util, final ArangoContext context) { super(); this.executor = executor; this.util = util; @@ -54,12 +54,12 @@ protected E executor() { } @Override - public InternalSerialization getInternalSerialization() { - return util.getInternalSerialization(); + public InternalSerde getInternalSerde() { + return util.getInternalSerde(); } @Override - public ArangoSerialization getUserSerialization() { + public ArangoSerde getUserSerde() { return util.getUserSerialization(); } diff --git a/src/main/java/com/arangodb/internal/ArangoExecutor.java b/src/main/java/com/arangodb/internal/ArangoExecutor.java index d9b0ef91a..c3fb99c40 100644 --- a/src/main/java/com/arangodb/internal/ArangoExecutor.java +++ b/src/main/java/com/arangodb/internal/ArangoExecutor.java @@ -21,7 +21,7 @@ package com.arangodb.internal; import com.arangodb.QueueTimeMetrics; -import com.arangodb.internal.util.ArangoSerializationFactory; +import com.arangodb.internal.util.ArangoSerdeFactory; import com.arangodb.velocystream.Request; import com.arangodb.velocystream.Response; @@ -36,15 +36,15 @@ protected T createResult(final Type type, final Response response) { if (response.getBody() == null) { return null; } - return util.getInternalSerialization().deserialize(response.getBody(), type); + return util.getInternalSerde().deserialize(response.getBody(), type); } private final DocumentCache documentCache; private final QueueTimeMetricsImpl qtMetrics; - private final ArangoSerializationFactory util; + private final ArangoSerdeFactory util; private final String timeoutS; - protected ArangoExecutor(final ArangoSerializationFactory util, final DocumentCache documentCache, + protected ArangoExecutor(final ArangoSerdeFactory util, final DocumentCache documentCache, final QueueTimeMetricsImpl qtMetrics, final int timeoutMs) { super(); this.documentCache = documentCache; diff --git a/src/main/java/com/arangodb/internal/ArangoExecutorSync.java b/src/main/java/com/arangodb/internal/ArangoExecutorSync.java index 51c683e10..e74037140 100644 --- a/src/main/java/com/arangodb/internal/ArangoExecutorSync.java +++ b/src/main/java/com/arangodb/internal/ArangoExecutorSync.java @@ -24,7 +24,7 @@ import com.arangodb.entity.MetaAware; import com.arangodb.internal.net.CommunicationProtocol; import com.arangodb.internal.net.HostHandle; -import com.arangodb.internal.util.ArangoSerializationFactory; +import com.arangodb.internal.util.ArangoSerdeFactory; import com.arangodb.velocystream.Request; import com.arangodb.velocystream.Response; import org.slf4j.Logger; @@ -42,7 +42,7 @@ public class ArangoExecutorSync extends ArangoExecutor { private final CommunicationProtocol protocol; - public ArangoExecutorSync(final CommunicationProtocol protocol, final ArangoSerializationFactory util, + public ArangoExecutorSync(final CommunicationProtocol protocol, final ArangoSerdeFactory util, final DocumentCache documentCache, final QueueTimeMetricsImpl qtMetrics, final int timeoutMs) { super(util, documentCache, qtMetrics, timeoutMs); this.protocol = protocol; diff --git a/src/main/java/com/arangodb/internal/InternalArangoCollection.java b/src/main/java/com/arangodb/internal/InternalArangoCollection.java index 4bb014874..2e6e397e3 100644 --- a/src/main/java/com/arangodb/internal/InternalArangoCollection.java +++ b/src/main/java/com/arangodb/internal/InternalArangoCollection.java @@ -91,9 +91,9 @@ protected Request insertDocumentRequest(final T value, final DocumentCreateO byte[] body; if (value instanceof String) { - body = getInternalSerialization().serialize(SerdeUtils.INSTANCE.parseJson((String) value)); + body = getInternalSerde().serialize(SerdeUtils.INSTANCE.parseJson((String) value)); } else { - body = getUserSerialization().serialize(value); + body = getUserSerde().serialize(value); } request.setBody(body); @@ -103,15 +103,15 @@ protected Request insertDocumentRequest(final T value, final DocumentCreateO protected ResponseDeserializer> insertDocumentResponseDeserializer( final T value, final DocumentCreateOptions options) { return response -> { - final JsonNode body = getInternalSerialization().parse(response.getBody()); - final DocumentCreateEntity doc = getInternalSerialization().deserialize(body, DocumentCreateEntity.class); + final JsonNode body = getInternalSerde().parse(response.getBody()); + final DocumentCreateEntity doc = getInternalSerde().deserialize(body, DocumentCreateEntity.class); final JsonNode newDoc = body.get(NEW); - Class clazz = value.getClass(); + Class clazz = (Class) value.getClass(); if (newDoc != null) { if (String.class.equals(clazz)) { doc.setNew((T) SerdeUtils.INSTANCE.writeJson(newDoc)); } else { - doc.setNew(getUserSerialization().deserialize(getInternalSerialization().serialize(newDoc), clazz)); + doc.setNew(getUserSerde().deserialize(getInternalSerde().serialize(newDoc), clazz)); } } final JsonNode oldDoc = body.get(OLD); @@ -119,7 +119,7 @@ protected ResponseDeserializer> insertDocumentRespon if (String.class.equals(clazz)) { doc.setOld((T) SerdeUtils.INSTANCE.writeJson(oldDoc)); } else { - doc.setOld(getUserSerialization().deserialize(getInternalSerialization().serialize(oldDoc), clazz)); + doc.setOld(getUserSerde().deserialize(getInternalSerde().serialize(oldDoc), clazz)); } } if (options == null || Boolean.TRUE != options.getSilent()) { @@ -143,8 +143,8 @@ protected Request insertDocumentsRequest(final Collection values, final D request.putQueryParam(MERGE_OBJECTS, params.getMergeObjects()); request.putHeaderParam(TRANSACTION_ID, params.getStreamTransactionId()); - byte[] body = isStringCollection(values) ? getInternalSerialization().serialize(stringCollectionToJsonArray((Collection) values)) - : getUserSerialization().serialize(values); + byte[] body = isStringCollection(values) ? getInternalSerde().serialize(stringCollectionToJsonArray((Collection) values)) + : getUserSerde().serialize(values); request.setBody(body); return request; } @@ -163,23 +163,23 @@ protected ResponseDeserializer>> final Collection> docs = new ArrayList<>(); final Collection errors = new ArrayList<>(); final Collection documentsAndErrors = new ArrayList<>(); - final JsonNode body = getInternalSerialization().parse(response.getBody()); + final JsonNode body = getInternalSerde().parse(response.getBody()); for (final Iterator iterator = body.iterator(); iterator.hasNext(); ) { final JsonNode next = iterator.next(); JsonNode isError = next.get(ArangoResponseField.ERROR_FIELD_NAME); if (isError != null && isError.booleanValue()) { - final ErrorEntity error = getInternalSerialization().deserialize(next, ErrorEntity.class); + final ErrorEntity error = getInternalSerde().deserialize(next, ErrorEntity.class); errors.add(error); documentsAndErrors.add(error); } else { - final DocumentCreateEntity doc = getInternalSerialization().deserialize(next, DocumentCreateEntity.class); + final DocumentCreateEntity doc = getInternalSerde().deserialize(next, DocumentCreateEntity.class); final JsonNode newDoc = next.get(NEW); if (newDoc != null) { - doc.setNew(getUserSerialization().deserialize(getInternalSerialization().serialize(newDoc), type)); + doc.setNew(getUserSerde().deserialize(getInternalSerde().serialize(newDoc), type)); } final JsonNode oldDoc = next.get(OLD); if (oldDoc != null) { - doc.setOld(getUserSerialization().deserialize(getInternalSerialization().serialize(oldDoc), type)); + doc.setOld(getUserSerde().deserialize(getInternalSerde().serialize(oldDoc), type)); } docs.add(doc); documentsAndErrors.add(doc); @@ -193,12 +193,12 @@ protected ResponseDeserializer>> } protected Request importDocumentsRequest(final String values, final DocumentImportOptions options) { - return importDocumentsRequest(options).putQueryParam("type", ImportType.auto).setBody(getInternalSerialization().serialize(SerdeUtils.INSTANCE.parseJson(values))); + return importDocumentsRequest(options).putQueryParam("type", ImportType.auto).setBody(getInternalSerde().serialize(SerdeUtils.INSTANCE.parseJson(values))); } protected Request importDocumentsRequest(final Collection values, final DocumentImportOptions options) { - byte[] body = isStringCollection(values) ? getInternalSerialization().serialize(stringCollectionToJsonArray((Collection) values)) - : getUserSerialization().serialize(values); + byte[] body = isStringCollection(values) ? getInternalSerde().serialize(stringCollectionToJsonArray((Collection) values)) + : getUserSerde().serialize(values); return importDocumentsRequest(options).putQueryParam("type", ImportType.list).setBody(body); } @@ -227,9 +227,9 @@ protected Request getDocumentRequest(final String key, final DocumentReadOptions protected ResponseDeserializer getDocumentResponseDeserializer(final Class type) { return response -> { if (String.class.equals(type)) { - return (T) SerdeUtils.INSTANCE.writeJson(getInternalSerialization().parse(response.getBody())); + return (T) SerdeUtils.INSTANCE.writeJson(getInternalSerde().parse(response.getBody())); } else { - return getUserSerialization().deserialize(response.getBody(), type); + return getUserSerde().deserialize(response.getBody(), type); } }; } @@ -239,7 +239,7 @@ protected Request getDocumentsRequest(final Collection keys, final Docum final Request request = request(db.dbName(), RequestType.PUT, PATH_API_DOCUMENT, name) .putQueryParam("onlyget", true) .putHeaderParam(ArangoRequestParam.IF_NONE_MATCH, params.getIfNoneMatch()) - .putHeaderParam(ArangoRequestParam.IF_MATCH, params.getIfMatch()).setBody(getInternalSerialization().serialize(keys)) + .putHeaderParam(ArangoRequestParam.IF_MATCH, params.getIfMatch()).setBody(getInternalSerde().serialize(keys)) .putHeaderParam(TRANSACTION_ID, params.getStreamTransactionId()); if (params.getAllowDirtyRead() == Boolean.TRUE) { RequestUtils.allowDirtyRead(request); @@ -254,16 +254,16 @@ protected ResponseDeserializer> getDocumentsResponseD final Collection docs = new ArrayList<>(); final Collection errors = new ArrayList<>(); final Collection documentsAndErrors = new ArrayList<>(); - final JsonNode body = getInternalSerialization().parse(response.getBody()); + final JsonNode body = getInternalSerde().parse(response.getBody()); for (final Iterator iterator = body.iterator(); iterator.hasNext(); ) { final JsonNode next = iterator.next(); JsonNode isError = next.get(ArangoResponseField.ERROR_FIELD_NAME); if (isError != null && isError.booleanValue()) { - final ErrorEntity error = getInternalSerialization().deserialize(next, ErrorEntity.class); + final ErrorEntity error = getInternalSerde().deserialize(next, ErrorEntity.class); errors.add(error); documentsAndErrors.add(error); } else { - final T doc = getUserSerialization().deserialize(getInternalSerialization().serialize(next), type); + final T doc = getUserSerde().deserialize(getInternalSerde().serialize(next), type); docs.add(doc); documentsAndErrors.add(doc); } @@ -287,22 +287,23 @@ protected Request replaceDocumentRequest( request.putQueryParam(RETURN_NEW, params.getReturnNew()); request.putQueryParam(RETURN_OLD, params.getReturnOld()); request.putQueryParam(SILENT, params.getSilent()); - request.setBody(getUserSerialization().serialize(value)); + request.setBody(getUserSerde().serialize(value)); return request; } protected ResponseDeserializer> replaceDocumentResponseDeserializer( final T value, final DocumentReplaceOptions options) { return response -> { - final JsonNode body = getInternalSerialization().parse(response.getBody()); - final DocumentUpdateEntity doc = getInternalSerialization().deserialize(body, DocumentUpdateEntity.class); + final JsonNode body = getInternalSerde().parse(response.getBody()); + final DocumentUpdateEntity doc = getInternalSerde().deserialize(body, DocumentUpdateEntity.class); final JsonNode newDoc = body.get(NEW); + Class clazz = (Class) value.getClass(); if (newDoc != null) { - doc.setNew(getUserSerialization().deserialize(getInternalSerialization().serialize(newDoc), value.getClass())); + doc.setNew(getUserSerde().deserialize(getInternalSerde().serialize(newDoc), clazz)); } final JsonNode oldDoc = body.get(OLD); if (oldDoc != null) { - doc.setOld(getUserSerialization().deserialize(getInternalSerialization().serialize(oldDoc), value.getClass())); + doc.setOld(getUserSerde().deserialize(getInternalSerde().serialize(oldDoc), clazz)); } if (options == null || Boolean.TRUE != options.getSilent()) { final Map values = new HashMap<>(); @@ -323,8 +324,8 @@ protected Request replaceDocumentsRequest(final Collection values, final request.putQueryParam(RETURN_OLD, params.getReturnOld()); request.putQueryParam(SILENT, params.getSilent()); - byte[] body = isStringCollection(values) ? getInternalSerialization().serialize(stringCollectionToJsonArray((Collection) values)) - : getUserSerialization().serialize(values); + byte[] body = isStringCollection(values) ? getInternalSerde().serialize(stringCollectionToJsonArray((Collection) values)) + : getUserSerde().serialize(values); request.setBody(body); return request; } @@ -343,23 +344,23 @@ protected ResponseDeserializer>> final Collection> docs = new ArrayList<>(); final Collection errors = new ArrayList<>(); final Collection documentsAndErrors = new ArrayList<>(); - final JsonNode body = getInternalSerialization().parse(response.getBody()); + final JsonNode body = getInternalSerde().parse(response.getBody()); for (final Iterator iterator = body.iterator(); iterator.hasNext(); ) { final JsonNode next = iterator.next(); JsonNode isError = next.get(ArangoResponseField.ERROR_FIELD_NAME); if (isError != null && isError.booleanValue()) { - final ErrorEntity error = getInternalSerialization().deserialize(next, ErrorEntity.class); + final ErrorEntity error = getInternalSerde().deserialize(next, ErrorEntity.class); errors.add(error); documentsAndErrors.add(error); } else { - final DocumentUpdateEntity doc = getInternalSerialization().deserialize(next, DocumentUpdateEntity.class); + final DocumentUpdateEntity doc = getInternalSerde().deserialize(next, DocumentUpdateEntity.class); final JsonNode newDoc = next.get(NEW); if (newDoc != null) { - doc.setNew(getUserSerialization().deserialize(getInternalSerialization().serialize(newDoc), type)); + doc.setNew(getUserSerde().deserialize(getInternalSerde().serialize(newDoc), type)); } final JsonNode oldDoc = next.get(OLD); if (oldDoc != null) { - doc.setOld(getUserSerialization().deserialize(getInternalSerialization().serialize(oldDoc), type)); + doc.setOld(getUserSerde().deserialize(getInternalSerde().serialize(oldDoc), type)); } docs.add(doc); documentsAndErrors.add(doc); @@ -385,22 +386,22 @@ protected Request updateDocumentRequest(final String key, final T value, fin request.putQueryParam(RETURN_NEW, params.getReturnNew()); request.putQueryParam(RETURN_OLD, params.getReturnOld()); request.putQueryParam(SILENT, params.getSilent()); - request.setBody(getUserSerialization().serialize(value)); + request.setBody(getUserSerde().serialize(value)); return request; } protected ResponseDeserializer> updateDocumentResponseDeserializer( final T value, final DocumentUpdateOptions options, final Class returnType) { return response -> { - final JsonNode body = getInternalSerialization().parse(response.getBody()); - final DocumentUpdateEntity doc = getInternalSerialization().deserialize(body, DocumentUpdateEntity.class); + final JsonNode body = getInternalSerde().parse(response.getBody()); + final DocumentUpdateEntity doc = getInternalSerde().deserialize(body, DocumentUpdateEntity.class); final JsonNode newDoc = body.get(NEW); if (newDoc != null) { - doc.setNew(getUserSerialization().deserialize(getInternalSerialization().serialize(newDoc), returnType)); + doc.setNew(getUserSerde().deserialize(getInternalSerde().serialize(newDoc), returnType)); } final JsonNode oldDoc = body.get(OLD); if (oldDoc != null) { - doc.setOld(getUserSerialization().deserialize(getInternalSerialization().serialize(oldDoc), returnType)); + doc.setOld(getUserSerde().deserialize(getInternalSerde().serialize(oldDoc), returnType)); } if (options == null || Boolean.TRUE != options.getSilent()) { final Map values = new HashMap<>(); @@ -424,8 +425,8 @@ protected Request updateDocumentsRequest(final Collection values, final D request.putQueryParam(RETURN_OLD, params.getReturnOld()); request.putQueryParam(SILENT, params.getSilent()); - byte[] body = isStringCollection(values) ? getInternalSerialization().serialize(stringCollectionToJsonArray((Collection) values)) - : getUserSerialization().serialize(values); + byte[] body = isStringCollection(values) ? getInternalSerde().serialize(stringCollectionToJsonArray((Collection) values)) + : getUserSerde().serialize(values); request.setBody(body); return request; } @@ -438,23 +439,23 @@ protected ResponseDeserializer>> final Collection> docs = new ArrayList<>(); final Collection errors = new ArrayList<>(); final Collection documentsAndErrors = new ArrayList<>(); - final JsonNode body = getInternalSerialization().parse(response.getBody()); + final JsonNode body = getInternalSerde().parse(response.getBody()); for (final Iterator iterator = body.iterator(); iterator.hasNext(); ) { final JsonNode next = iterator.next(); JsonNode isError = next.get(ArangoResponseField.ERROR_FIELD_NAME); if (isError != null && isError.booleanValue()) { - final ErrorEntity error = getInternalSerialization().deserialize(next, ErrorEntity.class); + final ErrorEntity error = getInternalSerde().deserialize(next, ErrorEntity.class); errors.add(error); documentsAndErrors.add(error); } else { - final DocumentUpdateEntity doc = getInternalSerialization().deserialize(next, DocumentUpdateEntity.class); + final DocumentUpdateEntity doc = getInternalSerde().deserialize(next, DocumentUpdateEntity.class); final JsonNode newDoc = next.get(NEW); if (newDoc != null) { - doc.setNew(getUserSerialization().deserialize(getInternalSerialization().serialize(newDoc), returnType)); + doc.setNew(getUserSerde().deserialize(getInternalSerde().serialize(newDoc), returnType)); } final JsonNode oldDoc = next.get(OLD); if (oldDoc != null) { - doc.setOld(getUserSerialization().deserialize(getInternalSerialization().serialize(oldDoc), returnType)); + doc.setOld(getUserSerde().deserialize(getInternalSerde().serialize(oldDoc), returnType)); } docs.add(doc); documentsAndErrors.add(doc); @@ -482,11 +483,11 @@ protected Request deleteDocumentRequest(final String key, final DocumentDeleteOp protected ResponseDeserializer> deleteDocumentResponseDeserializer( final Class type) { return response -> { - final JsonNode body = getInternalSerialization().parse(response.getBody()); - final DocumentDeleteEntity doc = getInternalSerialization().deserialize(body, DocumentDeleteEntity.class); + final JsonNode body = getInternalSerde().parse(response.getBody()); + final DocumentDeleteEntity doc = getInternalSerde().deserialize(body, DocumentDeleteEntity.class); final JsonNode oldDoc = body.get(OLD); if (oldDoc != null) { - doc.setOld(getUserSerialization().deserialize(getInternalSerialization().serialize(oldDoc), type)); + doc.setOld(getUserSerde().deserialize(getInternalSerde().serialize(oldDoc), type)); } return doc; }; @@ -499,7 +500,7 @@ protected Request deleteDocumentsRequest(final Collection keys, final Doc request.putQueryParam(ArangoRequestParam.WAIT_FOR_SYNC, params.getWaitForSync()); request.putQueryParam(RETURN_OLD, params.getReturnOld()); request.putQueryParam(SILENT, params.getSilent()); - request.setBody(getInternalSerialization().serialize(keys)); + request.setBody(getInternalSerde().serialize(keys)); return request; } @@ -510,19 +511,19 @@ protected ResponseDeserializer>> final Collection> docs = new ArrayList<>(); final Collection errors = new ArrayList<>(); final Collection documentsAndErrors = new ArrayList<>(); - final JsonNode body = getInternalSerialization().parse(response.getBody()); + final JsonNode body = getInternalSerde().parse(response.getBody()); for (final Iterator iterator = body.iterator(); iterator.hasNext(); ) { final JsonNode next = iterator.next(); JsonNode isError = next.get(ArangoResponseField.ERROR_FIELD_NAME); if (isError != null && isError.booleanValue()) { - final ErrorEntity error = getInternalSerialization().deserialize(next, ErrorEntity.class); + final ErrorEntity error = getInternalSerde().deserialize(next, ErrorEntity.class); errors.add(error); documentsAndErrors.add(error); } else { - final DocumentDeleteEntity doc = getInternalSerialization().deserialize(next, DocumentDeleteEntity.class); + final DocumentDeleteEntity doc = getInternalSerde().deserialize(next, DocumentDeleteEntity.class); final JsonNode oldDoc = next.get(OLD); if (oldDoc != null) { - doc.setOld(getUserSerialization().deserialize(getInternalSerialization().serialize(oldDoc), type)); + doc.setOld(getUserSerde().deserialize(getInternalSerde().serialize(oldDoc), type)); } docs.add(doc); documentsAndErrors.add(doc); @@ -554,7 +555,7 @@ protected Request deleteIndexRequest(final String id) { } protected ResponseDeserializer deleteIndexResponseDeserializer() { - return response -> getInternalSerialization().deserialize(response.getBody(), "/id", String.class); + return response -> getInternalSerde().deserialize(response.getBody(), "/id", String.class); } private String createIndexId(final String id) { @@ -574,7 +575,7 @@ protected Request createHashIndexRequest(final Iterable fields, final Ha final Request request = request(db.dbName(), RequestType.POST, PATH_API_INDEX); request.putQueryParam(COLLECTION, name); request.setBody( - getInternalSerialization().serialize(OptionsBuilder.build(options != null ? options : new HashIndexOptions(), fields))); + getInternalSerde().serialize(OptionsBuilder.build(options != null ? options : new HashIndexOptions(), fields))); return request; } @@ -583,7 +584,7 @@ protected Request createSkiplistIndexRequest(final Iterable fields, fina final Request request = request(db.dbName(), RequestType.POST, PATH_API_INDEX); request.putQueryParam(COLLECTION, name); request.setBody( - getInternalSerialization().serialize(OptionsBuilder.build(options != null ? options : new SkiplistIndexOptions(), fields))); + getInternalSerde().serialize(OptionsBuilder.build(options != null ? options : new SkiplistIndexOptions(), fields))); return request; } @@ -591,7 +592,7 @@ protected Request createPersistentIndexRequest( final Iterable fields, final PersistentIndexOptions options) { final Request request = request(db.dbName(), RequestType.POST, PATH_API_INDEX); request.putQueryParam(COLLECTION, name); - request.setBody(getInternalSerialization().serialize( + request.setBody(getInternalSerde().serialize( OptionsBuilder.build(options != null ? options : new PersistentIndexOptions(), fields))); return request; } @@ -600,7 +601,7 @@ protected Request createGeoIndexRequest(final Iterable fields, final Geo final Request request = request(db.dbName(), RequestType.POST, PATH_API_INDEX); request.putQueryParam(COLLECTION, name); request.setBody( - getInternalSerialization().serialize(OptionsBuilder.build(options != null ? options : new GeoIndexOptions(), fields))); + getInternalSerde().serialize(OptionsBuilder.build(options != null ? options : new GeoIndexOptions(), fields))); return request; } @@ -608,7 +609,7 @@ protected Request createFulltextIndexRequest(final Iterable fields, fina final Request request = request(db.dbName(), RequestType.POST, PATH_API_INDEX); request.putQueryParam(COLLECTION, name); request.setBody( - getInternalSerialization().serialize(OptionsBuilder.build(options != null ? options : new FulltextIndexOptions(), fields))); + getInternalSerde().serialize(OptionsBuilder.build(options != null ? options : new FulltextIndexOptions(), fields))); return request; } @@ -616,7 +617,7 @@ protected Request createTtlIndexRequest(final Iterable fields, final Ttl final Request request = request(db.dbName(), RequestType.POST, PATH_API_INDEX); request.putQueryParam(COLLECTION, name); request.setBody( - getInternalSerialization().serialize(OptionsBuilder.build(options != null ? options : new TtlIndexOptions(), fields))); + getInternalSerde().serialize(OptionsBuilder.build(options != null ? options : new TtlIndexOptions(), fields))); return request; } @@ -624,7 +625,7 @@ protected Request createZKDIndexRequest( final Iterable fields, final ZKDIndexOptions options) { final Request request = request(db.dbName(), RequestType.POST, PATH_API_INDEX); request.putQueryParam(COLLECTION, name); - request.setBody(getInternalSerialization().serialize(OptionsBuilder.build(options != null ? options : + request.setBody(getInternalSerde().serialize(OptionsBuilder.build(options != null ? options : new ZKDIndexOptions().fieldValueTypes(ZKDIndexOptions.FieldValueTypes.DOUBLE), fields))); return request; } @@ -636,7 +637,7 @@ protected Request getIndexesRequest() { } protected ResponseDeserializer> getIndexesResponseDeserializer() { - return response -> getInternalSerialization().deserialize(response.getBody(), "/indexes", + return response -> getInternalSerde().deserialize(response.getBody(), "/indexes", SerdeUtils.INSTANCE.constructListType(IndexEntity.class)); } @@ -668,19 +669,19 @@ protected Request getPropertiesRequest() { protected Request changePropertiesRequest(final CollectionPropertiesOptions options) { final Request request = request(db.dbName(), RequestType.PUT, PATH_API_COLLECTION, name, "properties"); - request.setBody(getInternalSerialization().serialize(options != null ? options : new CollectionPropertiesOptions())); + request.setBody(getInternalSerde().serialize(options != null ? options : new CollectionPropertiesOptions())); return request; } protected Request renameRequest(final String newName) { final Request request = request(db.dbName(), RequestType.PUT, PATH_API_COLLECTION, name, "rename"); - request.setBody(getInternalSerialization().serialize(OptionsBuilder.build(new CollectionRenameOptions(), newName))); + request.setBody(getInternalSerde().serialize(OptionsBuilder.build(new CollectionRenameOptions(), newName))); return request; } protected Request responsibleShardRequest(final T value) { final Request request = request(db.dbName(), RequestType.PUT, PATH_API_COLLECTION, name, "responsibleShard"); - request.setBody(getUserSerialization().serialize(value)); + request.setBody(getUserSerde().serialize(value)); return request; } @@ -690,7 +691,7 @@ protected Request getRevisionRequest() { protected Request grantAccessRequest(final String user, final Permissions permissions) { return request(DbName.SYSTEM, RequestType.PUT, PATH_API_USER, user, ArangoRequestParam.DATABASE, - db.dbName().get(), name).setBody(getInternalSerialization().serialize(OptionsBuilder.build(new UserAccessOptions(), permissions))); + db.dbName().get(), name).setBody(getInternalSerde().serialize(OptionsBuilder.build(new UserAccessOptions(), permissions))); } protected Request resetAccessRequest(final String user) { @@ -704,7 +705,7 @@ protected Request getPermissionsRequest(final String user) { } protected ResponseDeserializer getPermissionsResponseDeserialzer() { - return response -> getInternalSerialization().deserialize(response.getBody(), ArangoResponseField.RESULT_JSON_POINTER, Permissions.class); + return response -> getInternalSerde().deserialize(response.getBody(), ArangoResponseField.RESULT_JSON_POINTER, Permissions.class); } private boolean isStringCollection(final Collection values) { diff --git a/src/main/java/com/arangodb/internal/InternalArangoDB.java b/src/main/java/com/arangodb/internal/InternalArangoDB.java index c1b6fcc0f..eb63cb9cb 100644 --- a/src/main/java/com/arangodb/internal/InternalArangoDB.java +++ b/src/main/java/com/arangodb/internal/InternalArangoDB.java @@ -23,7 +23,7 @@ import com.arangodb.DbName; import com.arangodb.entity.*; import com.arangodb.internal.ArangoExecutor.ResponseDeserializer; -import com.arangodb.internal.util.ArangoSerializationFactory; +import com.arangodb.internal.util.ArangoSerdeFactory; import com.arangodb.model.*; import com.arangodb.serde.SerdeUtils; import com.arangodb.velocystream.Request; @@ -47,7 +47,7 @@ public abstract class InternalArangoDB extends ArangoE private static final String PATH_ENDPOINTS = "/_api/cluster/endpoints"; private static final String PATH_API_USER = "/_api/user"; - protected InternalArangoDB(final E executor, final ArangoSerializationFactory util, final ArangoContext context) { + protected InternalArangoDB(final E executor, final ArangoSerdeFactory util, final ArangoContext context) { super(executor, util, context); } @@ -60,22 +60,22 @@ protected Request getServerIdRequest() { } protected ResponseDeserializer getRoleResponseDeserializer() { - return response -> getInternalSerialization().deserialize(response.getBody(), "/role", ServerRole.class); + return response -> getInternalSerde().deserialize(response.getBody(), "/role", ServerRole.class); } protected ResponseDeserializer getServerIdResponseDeserializer() { - return response -> getInternalSerialization().deserialize(response.getBody(), "/id", String.class); + return response -> getInternalSerde().deserialize(response.getBody(), "/id", String.class); } protected Request createDatabaseRequest(final DBCreateOptions options) { final Request request = request(DbName.SYSTEM, RequestType.POST, InternalArangoDatabase.PATH_API_DATABASE); - request.setBody(getInternalSerialization().serialize(options)); + request.setBody(getInternalSerde().serialize(options)); return request; } protected ResponseDeserializer createDatabaseResponseDeserializer() { - return response -> getInternalSerialization().deserialize(response.getBody(), ArangoResponseField.RESULT_JSON_POINTER, Boolean.class); + return response -> getInternalSerde().deserialize(response.getBody(), ArangoResponseField.RESULT_JSON_POINTER, Boolean.class); } protected Request getDatabasesRequest(final DbName dbName) { @@ -83,7 +83,7 @@ protected Request getDatabasesRequest(final DbName dbName) { } protected ResponseDeserializer> getDatabaseResponseDeserializer() { - return response -> getInternalSerialization().deserialize(response.getBody(), ArangoResponseField.RESULT_JSON_POINTER, + return response -> getInternalSerde().deserialize(response.getBody(), ArangoResponseField.RESULT_JSON_POINTER, SerdeUtils.INSTANCE.constructListType(String.class)); } @@ -93,7 +93,7 @@ protected Request getAccessibleDatabasesForRequest(final DbName dbName, final St protected ResponseDeserializer> getAccessibleDatabasesForResponseDeserializer() { return response -> { - Iterator names = getInternalSerialization().parse(response.getBody(), ArangoResponseField.RESULT_JSON_POINTER).fieldNames(); + Iterator names = getInternalSerde().parse(response.getBody(), ArangoResponseField.RESULT_JSON_POINTER).fieldNames(); final Collection dbs = new ArrayList<>(); while (names.hasNext()) { dbs.add(names.next()); @@ -110,7 +110,7 @@ protected Request createUserRequest( final Request request; request = request(dbName, RequestType.POST, PATH_API_USER); request.setBody( - getInternalSerialization().serialize(OptionsBuilder.build(options != null ? options : new UserCreateOptions(), user, passwd))); + getInternalSerde().serialize(OptionsBuilder.build(options != null ? options : new UserCreateOptions(), user, passwd))); return request; } @@ -127,32 +127,32 @@ protected Request getUserRequest(final DbName dbName, final String user) { } protected ResponseDeserializer> getUsersResponseDeserializer() { - return response -> getInternalSerialization().deserialize(response.getBody(), ArangoResponseField.RESULT_JSON_POINTER, + return response -> getInternalSerde().deserialize(response.getBody(), ArangoResponseField.RESULT_JSON_POINTER, SerdeUtils.INSTANCE.constructListType(UserEntity.class)); } protected Request updateUserRequest(final DbName dbName, final String user, final UserUpdateOptions options) { final Request request; request = request(dbName, RequestType.PATCH, PATH_API_USER, user); - request.setBody(getInternalSerialization().serialize(options != null ? options : new UserUpdateOptions())); + request.setBody(getInternalSerde().serialize(options != null ? options : new UserUpdateOptions())); return request; } protected Request replaceUserRequest(final DbName dbName, final String user, final UserUpdateOptions options) { final Request request; request = request(dbName, RequestType.PUT, PATH_API_USER, user); - request.setBody(getInternalSerialization().serialize(options != null ? options : new UserUpdateOptions())); + request.setBody(getInternalSerde().serialize(options != null ? options : new UserUpdateOptions())); return request; } protected Request updateUserDefaultDatabaseAccessRequest(final String user, final Permissions permissions) { return request(DbName.SYSTEM, RequestType.PUT, PATH_API_USER, user, ArangoRequestParam.DATABASE, - "*").setBody(getInternalSerialization().serialize(OptionsBuilder.build(new UserAccessOptions(), permissions))); + "*").setBody(getInternalSerde().serialize(OptionsBuilder.build(new UserAccessOptions(), permissions))); } protected Request updateUserDefaultCollectionAccessRequest(final String user, final Permissions permissions) { return request(DbName.SYSTEM, RequestType.PUT, PATH_API_USER, user, ArangoRequestParam.DATABASE, - "*", "*").setBody(getInternalSerialization().serialize(OptionsBuilder.build(new UserAccessOptions(), permissions))); + "*", "*").setBody(getInternalSerde().serialize(OptionsBuilder.build(new UserAccessOptions(), permissions))); } protected Request getLogEntriesRequest(final LogOptions options) { @@ -173,7 +173,7 @@ protected Request getLogLevelRequest() { protected Request setLogLevelRequest(final LogLevelEntity entity) { return request(DbName.SYSTEM, RequestType.PUT, PATH_API_ADMIN_LOG_LEVEL) - .setBody(getInternalSerialization().serialize(entity)); + .setBody(getInternalSerde().serialize(entity)); } } diff --git a/src/main/java/com/arangodb/internal/InternalArangoDBBuilder.java b/src/main/java/com/arangodb/internal/InternalArangoDBBuilder.java index 093e6428d..9b8821057 100644 --- a/src/main/java/com/arangodb/internal/InternalArangoDBBuilder.java +++ b/src/main/java/com/arangodb/internal/InternalArangoDBBuilder.java @@ -25,7 +25,7 @@ import com.arangodb.entity.LoadBalancingStrategy; import com.arangodb.internal.net.*; import com.arangodb.internal.util.HostUtils; -import com.arangodb.util.ArangoSerialization; +import com.arangodb.serde.ArangoSerde; import org.apache.http.client.HttpRequestRetryHandler; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -81,7 +81,7 @@ public abstract class InternalArangoDBBuilder { protected Boolean acquireHostList; protected Integer acquireHostListInterval; protected LoadBalancingStrategy loadBalancingStrategy; - protected ArangoSerialization customSerializer; + protected ArangoSerde customSerializer; protected Integer responseQueueTimeSamples; @@ -201,7 +201,7 @@ protected void setResponseQueueTimeSamples(final Integer responseQueueTimeSample this.responseQueueTimeSamples = responseQueueTimeSamples; } - protected void setSerializer(final ArangoSerialization serializer) { + protected void setSerializer(final ArangoSerde serializer) { this.customSerializer = serializer; } diff --git a/src/main/java/com/arangodb/internal/InternalArangoDatabase.java b/src/main/java/com/arangodb/internal/InternalArangoDatabase.java index 5b3739cef..8943e5d34 100644 --- a/src/main/java/com/arangodb/internal/InternalArangoDatabase.java +++ b/src/main/java/com/arangodb/internal/InternalArangoDatabase.java @@ -96,7 +96,7 @@ protected Request getEngineRequest() { protected Request createCollectionRequest(final String name, final CollectionCreateOptions options) { - byte[] body = getInternalSerialization().serialize(OptionsBuilder.build(options != null ? options : new CollectionCreateOptions(), name)); + byte[] body = getInternalSerde().serialize(OptionsBuilder.build(options != null ? options : new CollectionCreateOptions(), name)); return request(dbName, RequestType.POST, InternalArangoCollection.PATH_API_COLLECTION).setBody(body); } @@ -110,7 +110,7 @@ protected Request getCollectionsRequest(final CollectionsReadOptions options) { } protected ResponseDeserializer> getCollectionsResponseDeserializer() { - return response -> getInternalSerialization().deserialize(getInternalSerialization().parse(response.getBody(), ArangoResponseField.RESULT_JSON_POINTER), + return response -> getInternalSerde().deserialize(getInternalSerde().parse(response.getBody(), ArangoResponseField.RESULT_JSON_POINTER), SerdeUtils.INSTANCE.constructListType(CollectionEntity.class)); } @@ -119,11 +119,11 @@ protected Request dropRequest() { } protected ResponseDeserializer createDropResponseDeserializer() { - return response -> getInternalSerialization().deserialize(response.getBody(), ArangoResponseField.RESULT_JSON_POINTER, Boolean.class); + return response -> getInternalSerde().deserialize(response.getBody(), ArangoResponseField.RESULT_JSON_POINTER, Boolean.class); } protected Request grantAccessRequest(final String user, final Permissions permissions) { - return request(DbName.SYSTEM, RequestType.PUT, PATH_API_USER, user, ArangoRequestParam.DATABASE, dbName.get()).setBody(getInternalSerialization().serialize(OptionsBuilder.build(new UserAccessOptions(), permissions))); + return request(DbName.SYSTEM, RequestType.PUT, PATH_API_USER, user, ArangoRequestParam.DATABASE, dbName.get()).setBody(getInternalSerde().serialize(OptionsBuilder.build(new UserAccessOptions(), permissions))); } protected Request resetAccessRequest(final String user) { @@ -131,7 +131,7 @@ protected Request resetAccessRequest(final String user) { } protected Request updateUserDefaultCollectionAccessRequest(final String user, final Permissions permissions) { - return request(DbName.SYSTEM, RequestType.PUT, PATH_API_USER, user, ArangoRequestParam.DATABASE, dbName.get(), "*").setBody(getInternalSerialization().serialize(OptionsBuilder.build(new UserAccessOptions(), permissions))); + return request(DbName.SYSTEM, RequestType.PUT, PATH_API_USER, user, ArangoRequestParam.DATABASE, dbName.get(), "*").setBody(getInternalSerde().serialize(OptionsBuilder.build(new UserAccessOptions(), permissions))); } protected Request getPermissionsRequest(final String user) { @@ -139,13 +139,13 @@ protected Request getPermissionsRequest(final String user) { } protected ResponseDeserializer getPermissionsResponseDeserialzer() { - return response -> getInternalSerialization().deserialize(response.getBody(), ArangoResponseField.RESULT_JSON_POINTER, Permissions.class); + return response -> getInternalSerde().deserialize(response.getBody(), ArangoResponseField.RESULT_JSON_POINTER, Permissions.class); } protected Request queryRequest(final String query, final Map bindVars, final AqlQueryOptions options) { final AqlQueryOptions opt = options != null ? options : new AqlQueryOptions(); - final Request request = request(dbName, RequestType.POST, PATH_API_CURSOR).setBody(getInternalSerialization().serialize( - OptionsBuilder.build(opt, query, bindVars != null ? getUserSerialization().serialize(bindVars) : null))); + final Request request = request(dbName, RequestType.POST, PATH_API_CURSOR).setBody(getInternalSerde().serialize( + OptionsBuilder.build(opt, query, bindVars != null ? getUserSerde().serialize(bindVars) : null))); if (opt.getAllowDirtyRead() == Boolean.TRUE) { RequestUtils.allowDirtyRead(request); } @@ -190,12 +190,12 @@ protected Request queryCloseRequest(final String id, final AqlQueryOptions optio protected Request explainQueryRequest(final String query, final Map bindVars, final AqlQueryExplainOptions options) { final AqlQueryExplainOptions opt = options != null ? options : new AqlQueryExplainOptions(); return request(dbName, RequestType.POST, PATH_API_EXPLAIN) - .setBody(getInternalSerialization().serialize( - OptionsBuilder.build(opt, query, bindVars != null ? getUserSerialization().serialize(bindVars) : null))); + .setBody(getInternalSerde().serialize( + OptionsBuilder.build(opt, query, bindVars != null ? getUserSerde().serialize(bindVars) : null))); } protected Request parseQueryRequest(final String query) { - return request(dbName, RequestType.POST, PATH_API_QUERY).setBody(getInternalSerialization().serialize(OptionsBuilder.build(new AqlQueryParseOptions(), query))); + return request(dbName, RequestType.POST, PATH_API_QUERY).setBody(getInternalSerde().serialize(OptionsBuilder.build(new AqlQueryParseOptions(), query))); } protected Request clearQueryCacheRequest() { @@ -207,7 +207,7 @@ protected Request getQueryCachePropertiesRequest() { } protected Request setQueryCachePropertiesRequest(final QueryCachePropertiesEntity properties) { - return request(dbName, RequestType.PUT, PATH_API_QUERY_CACHE_PROPERTIES).setBody(getInternalSerialization().serialize(properties)); + return request(dbName, RequestType.PUT, PATH_API_QUERY_CACHE_PROPERTIES).setBody(getInternalSerde().serialize(properties)); } protected Request getQueryTrackingPropertiesRequest() { @@ -215,7 +215,7 @@ protected Request getQueryTrackingPropertiesRequest() { } protected Request setQueryTrackingPropertiesRequest(final QueryTrackingPropertiesEntity properties) { - return request(dbName, RequestType.PUT, PATH_API_QUERY_PROPERTIES).setBody(getInternalSerialization().serialize(properties)); + return request(dbName, RequestType.PUT, PATH_API_QUERY_PROPERTIES).setBody(getInternalSerde().serialize(properties)); } protected Request getCurrentlyRunningQueriesRequest() { @@ -235,7 +235,7 @@ protected Request killQueryRequest(final String id) { } protected Request createAqlFunctionRequest(final String name, final String code, final AqlFunctionCreateOptions options) { - return request(dbName, RequestType.POST, PATH_API_AQLFUNCTION).setBody(getInternalSerialization().serialize(OptionsBuilder.build(options != null ? options : new AqlFunctionCreateOptions(), name, code))); + return request(dbName, RequestType.POST, PATH_API_AQLFUNCTION).setBody(getInternalSerde().serialize(OptionsBuilder.build(options != null ? options : new AqlFunctionCreateOptions(), name, code))); } protected Request deleteAqlFunctionRequest(final String name, final AqlFunctionDeleteOptions options) { @@ -246,7 +246,7 @@ protected Request deleteAqlFunctionRequest(final String name, final AqlFunctionD } protected ResponseDeserializer deleteAqlFunctionResponseDeserializer() { - return response -> getInternalSerialization().deserialize(response.getBody(), "/deletedCount", Integer.class); + return response -> getInternalSerde().deserialize(response.getBody(), "/deletedCount", Integer.class); } protected Request getAqlFunctionsRequest(final AqlFunctionGetOptions options) { @@ -257,16 +257,16 @@ protected Request getAqlFunctionsRequest(final AqlFunctionGetOptions options) { } protected ResponseDeserializer> getAqlFunctionsResponseDeserializer() { - return response -> getInternalSerialization().deserialize(response.getBody(), ArangoResponseField.RESULT_JSON_POINTER, + return response -> getInternalSerde().deserialize(response.getBody(), ArangoResponseField.RESULT_JSON_POINTER, SerdeUtils.INSTANCE.constructListType(AqlFunctionEntity.class)); } protected Request createGraphRequest(final String name, final Collection edgeDefinitions, final GraphCreateOptions options) { - return request(dbName, RequestType.POST, InternalArangoGraph.PATH_API_GHARIAL).setBody(getInternalSerialization().serialize(OptionsBuilder.build(options != null ? options : new GraphCreateOptions(), name, edgeDefinitions))); + return request(dbName, RequestType.POST, InternalArangoGraph.PATH_API_GHARIAL).setBody(getInternalSerde().serialize(OptionsBuilder.build(options != null ? options : new GraphCreateOptions(), name, edgeDefinitions))); } protected ResponseDeserializer createGraphResponseDeserializer() { - return response -> getInternalSerialization().deserialize(response.getBody(), "/graph", GraphEntity.class); + return response -> getInternalSerde().deserialize(response.getBody(), "/graph", GraphEntity.class); } protected Request getGraphsRequest() { @@ -274,27 +274,27 @@ protected Request getGraphsRequest() { } protected ResponseDeserializer> getGraphsResponseDeserializer() { - return response -> getInternalSerialization().deserialize(response.getBody(), "/graphs", + return response -> getInternalSerde().deserialize(response.getBody(), "/graphs", SerdeUtils.INSTANCE.constructListType(GraphEntity.class)); } protected Request transactionRequest(final String action, final TransactionOptions options) { - return request(dbName, RequestType.POST, PATH_API_TRANSACTION).setBody(getInternalSerialization().serialize(OptionsBuilder.build(options != null ? options : new TransactionOptions(), action))); + return request(dbName, RequestType.POST, PATH_API_TRANSACTION).setBody(getInternalSerde().serialize(OptionsBuilder.build(options != null ? options : new TransactionOptions(), action))); } protected ResponseDeserializer transactionResponseDeserializer(final Class type) { return response -> { - byte[] userContent = getInternalSerialization().extract(response.getBody(), ArangoResponseField.RESULT_JSON_POINTER); + byte[] userContent = getInternalSerde().extract(response.getBody(), ArangoResponseField.RESULT_JSON_POINTER); if (String.class.equals(type)) { - return (T) SerdeUtils.INSTANCE.writeJson(getInternalSerialization().parse(userContent)); + return (T) SerdeUtils.INSTANCE.writeJson(getInternalSerde().parse(userContent)); } else { - return getUserSerialization().deserialize(userContent, type); + return getUserSerde().deserialize(userContent, type); } }; } protected Request beginStreamTransactionRequest(final StreamTransactionOptions options) { - return request(dbName, RequestType.POST, PATH_API_BEGIN_STREAM_TRANSACTION).setBody(getInternalSerialization().serialize(options != null ? options : new StreamTransactionOptions())); + return request(dbName, RequestType.POST, PATH_API_BEGIN_STREAM_TRANSACTION).setBody(getInternalSerde().serialize(options != null ? options : new StreamTransactionOptions())); } protected Request abortStreamTransactionRequest(String id) { @@ -310,7 +310,7 @@ protected Request getStreamTransactionRequest(String id) { } protected ResponseDeserializer> transactionsResponseDeserializer() { - return response -> getInternalSerialization().deserialize(response.getBody(), "/transactions", + return response -> getInternalSerde().deserialize(response.getBody(), "/transactions", SerdeUtils.INSTANCE.constructListType(TransactionEntity.class)); } @@ -319,7 +319,7 @@ protected Request commitStreamTransactionRequest(String id) { } protected ResponseDeserializer streamTransactionResponseDeserializer() { - return response -> getInternalSerialization().deserialize(response.getBody(), ArangoResponseField.RESULT_JSON_POINTER, StreamTransactionEntity.class); + return response -> getInternalSerde().deserialize(response.getBody(), ArangoResponseField.RESULT_JSON_POINTER, StreamTransactionEntity.class); } protected Request getInfoRequest() { @@ -327,7 +327,7 @@ protected Request getInfoRequest() { } protected ResponseDeserializer getInfoResponseDeserializer() { - return response -> getInternalSerialization().deserialize(response.getBody(), ArangoResponseField.RESULT_JSON_POINTER, DatabaseEntity.class); + return response -> getInternalSerde().deserialize(response.getBody(), ArangoResponseField.RESULT_JSON_POINTER, DatabaseEntity.class); } protected Request reloadRoutingRequest() { @@ -339,16 +339,16 @@ protected Request getViewsRequest() { } protected ResponseDeserializer> getViewsResponseDeserializer() { - return response -> getInternalSerialization().deserialize(response.getBody(), ArangoResponseField.RESULT_JSON_POINTER, + return response -> getInternalSerde().deserialize(response.getBody(), ArangoResponseField.RESULT_JSON_POINTER, SerdeUtils.INSTANCE.constructListType(ViewEntity.class)); } protected Request createViewRequest(final String name, final ViewType type) { - return request(dbName, RequestType.POST, InternalArangoView.PATH_API_VIEW).setBody(getInternalSerialization().serialize(OptionsBuilder.build(new ViewCreateOptions(), name, type))); + return request(dbName, RequestType.POST, InternalArangoView.PATH_API_VIEW).setBody(getInternalSerde().serialize(OptionsBuilder.build(new ViewCreateOptions(), name, type))); } protected Request createArangoSearchRequest(final String name, final ArangoSearchCreateOptions options) { - return request(dbName, RequestType.POST, InternalArangoView.PATH_API_VIEW).setBody(getInternalSerialization().serialize(ArangoSearchOptionsBuilder.build(options != null ? options : new ArangoSearchCreateOptions(), name))); + return request(dbName, RequestType.POST, InternalArangoView.PATH_API_VIEW).setBody(getInternalSerde().serialize(ArangoSearchOptionsBuilder.build(options != null ? options : new ArangoSearchCreateOptions(), name))); } protected Request getAnalyzerRequest(final String name) { @@ -360,12 +360,12 @@ protected Request getAnalyzersRequest() { } protected ResponseDeserializer> getSearchAnalyzersResponseDeserializer() { - return response -> getInternalSerialization().deserialize(response.getBody(), ArangoResponseField.RESULT_JSON_POINTER, + return response -> getInternalSerde().deserialize(response.getBody(), ArangoResponseField.RESULT_JSON_POINTER, SerdeUtils.INSTANCE.constructListType(SearchAnalyzer.class)); } protected Request createAnalyzerRequest(final SearchAnalyzer options) { - return request(dbName, RequestType.POST, InternalArangoView.PATH_API_ANALYZER).setBody(getInternalSerialization().serialize(options)); + return request(dbName, RequestType.POST, InternalArangoView.PATH_API_ANALYZER).setBody(getInternalSerde().serialize(options)); } protected Request deleteAnalyzerRequest(final String name, final AnalyzerDeleteOptions options) { diff --git a/src/main/java/com/arangodb/internal/InternalArangoEdgeCollection.java b/src/main/java/com/arangodb/internal/InternalArangoEdgeCollection.java index 725141dbd..ae4b357bf 100644 --- a/src/main/java/com/arangodb/internal/InternalArangoEdgeCollection.java +++ b/src/main/java/com/arangodb/internal/InternalArangoEdgeCollection.java @@ -65,13 +65,13 @@ protected Request insertEdgeRequest(final T value, final EdgeCreateOptions o final EdgeCreateOptions params = (options != null ? options : new EdgeCreateOptions()); request.putHeaderParam(TRANSACTION_ID, params.getStreamTransactionId()); request.putQueryParam(ArangoRequestParam.WAIT_FOR_SYNC, params.getWaitForSync()); - request.setBody(getUserSerialization().serialize(value)); + request.setBody(getUserSerde().serialize(value)); return request; } protected ResponseDeserializer insertEdgeResponseDeserializer(final T value) { return response -> { - final EdgeEntity doc = getInternalSerialization().deserialize(response.getBody(), "/edge", EdgeEntity.class); + final EdgeEntity doc = getInternalSerde().deserialize(response.getBody(), "/edge", EdgeEntity.class); final Map values = new HashMap<>(); values.put(DocumentFields.ID, doc.getId()); values.put(DocumentFields.KEY, doc.getKey()); @@ -95,7 +95,7 @@ protected Request getEdgeRequest(final String key, final GraphDocumentReadOption } protected ResponseDeserializer getEdgeResponseDeserializer(final Class type) { - return response -> getUserSerialization().deserialize(getInternalSerialization().extract(response.getBody(), "/edge"), type); + return response -> getUserSerde().deserialize(getInternalSerde().extract(response.getBody(), "/edge"), type); } protected Request replaceEdgeRequest(final String key, final T value, final EdgeReplaceOptions options) { @@ -105,13 +105,13 @@ protected Request replaceEdgeRequest(final String key, final T value, final request.putHeaderParam(TRANSACTION_ID, params.getStreamTransactionId()); request.putQueryParam(ArangoRequestParam.WAIT_FOR_SYNC, params.getWaitForSync()); request.putHeaderParam(ArangoRequestParam.IF_MATCH, params.getIfMatch()); - request.setBody(getUserSerialization().serialize(value)); + request.setBody(getUserSerde().serialize(value)); return request; } protected ResponseDeserializer replaceEdgeResponseDeserializer(final T value) { return response -> { - final EdgeUpdateEntity doc = getInternalSerialization().deserialize(response.getBody(), "/edge", EdgeUpdateEntity.class); + final EdgeUpdateEntity doc = getInternalSerde().deserialize(response.getBody(), "/edge", EdgeUpdateEntity.class); final Map values = new HashMap<>(); values.put(DocumentFields.REV, doc.getRev()); executor.documentCache().setValues(value, values); @@ -128,13 +128,13 @@ protected Request updateEdgeRequest(final String key, final T value, final E request.putQueryParam(ArangoRequestParam.KEEP_NULL, params.getKeepNull()); request.putQueryParam(ArangoRequestParam.WAIT_FOR_SYNC, params.getWaitForSync()); request.putHeaderParam(ArangoRequestParam.IF_MATCH, params.getIfMatch()); - request.setBody(getUserSerialization().serialize(value)); + request.setBody(getUserSerde().serialize(value)); return request; } protected ResponseDeserializer updateEdgeResponseDeserializer(final T value) { return response -> { - final EdgeUpdateEntity doc = getInternalSerialization().deserialize(response.getBody(), "/edge", EdgeUpdateEntity.class); + final EdgeUpdateEntity doc = getInternalSerde().deserialize(response.getBody(), "/edge", EdgeUpdateEntity.class); final Map values = new HashMap<>(); values.put(DocumentFields.REV, doc.getRev()); executor.documentCache().setValues(value, values); diff --git a/src/main/java/com/arangodb/internal/InternalArangoGraph.java b/src/main/java/com/arangodb/internal/InternalArangoGraph.java index f725539ba..4e74bcf25 100644 --- a/src/main/java/com/arangodb/internal/InternalArangoGraph.java +++ b/src/main/java/com/arangodb/internal/InternalArangoGraph.java @@ -84,13 +84,13 @@ protected Request getVertexCollectionsRequest() { } protected ResponseDeserializer> getVertexCollectionsResponseDeserializer() { - return response -> getInternalSerialization().deserialize(response.getBody(), "/collections", + return response -> getInternalSerde().deserialize(response.getBody(), "/collections", SerdeUtils.INSTANCE.constructListType(String.class)); } protected Request addVertexCollectionRequest(final String name, final VertexCollectionCreateOptions options) { final Request request = request(db.dbName(), RequestType.POST, PATH_API_GHARIAL, name(), VERTEX); - request.setBody(getInternalSerialization().serialize(OptionsBuilder.build(options, name))); + request.setBody(getInternalSerde().serialize(OptionsBuilder.build(options, name))); return request; } @@ -103,29 +103,29 @@ protected Request getEdgeDefinitionsRequest() { } protected ResponseDeserializer> getEdgeDefinitionsDeserializer() { - return response -> getInternalSerialization().deserialize(response.getBody(), "/collections", + return response -> getInternalSerde().deserialize(response.getBody(), "/collections", SerdeUtils.INSTANCE.constructListType(String.class)); } protected Request addEdgeDefinitionRequest(final EdgeDefinition definition) { final Request request = request(db.dbName(), RequestType.POST, PATH_API_GHARIAL, name, EDGE); - request.setBody(getInternalSerialization().serialize(definition)); + request.setBody(getInternalSerde().serialize(definition)); return request; } protected ResponseDeserializer addEdgeDefinitionResponseDeserializer() { - return response -> getInternalSerialization().deserialize(response.getBody(), GRAPH, GraphEntity.class); + return response -> getInternalSerde().deserialize(response.getBody(), GRAPH, GraphEntity.class); } protected Request replaceEdgeDefinitionRequest(final EdgeDefinition definition) { final Request request = request(db.dbName(), RequestType.PUT, PATH_API_GHARIAL, name, EDGE, definition.getCollection()); - request.setBody(getInternalSerialization().serialize(definition)); + request.setBody(getInternalSerde().serialize(definition)); return request; } protected ResponseDeserializer replaceEdgeDefinitionResponseDeserializer() { - return response -> getInternalSerialization().deserialize(response.getBody(), GRAPH, GraphEntity.class); + return response -> getInternalSerde().deserialize(response.getBody(), GRAPH, GraphEntity.class); } protected Request removeEdgeDefinitionRequest(final String definitionName) { @@ -133,7 +133,7 @@ protected Request removeEdgeDefinitionRequest(final String definitionName) { } protected ResponseDeserializer removeEdgeDefinitionResponseDeserializer() { - return response -> getInternalSerialization().deserialize(response.getBody(), GRAPH, GraphEntity.class); + return response -> getInternalSerde().deserialize(response.getBody(), GRAPH, GraphEntity.class); } } diff --git a/src/main/java/com/arangodb/internal/InternalArangoRoute.java b/src/main/java/com/arangodb/internal/InternalArangoRoute.java index f0936eb87..f053c19ce 100644 --- a/src/main/java/com/arangodb/internal/InternalArangoRoute.java +++ b/src/main/java/com/arangodb/internal/InternalArangoRoute.java @@ -74,7 +74,7 @@ protected Request createRequest(final RequestType requestType) { request.putQueryParam(param.getKey(), param.getValue()); } if (body != null) { - request.setBody(getInternalSerialization().serialize(body)); + request.setBody(getInternalSerde().serialize(body)); } return request; } diff --git a/src/main/java/com/arangodb/internal/InternalArangoSearch.java b/src/main/java/com/arangodb/internal/InternalArangoSearch.java index 3bdf9d90f..8e09b414f 100644 --- a/src/main/java/com/arangodb/internal/InternalArangoSearch.java +++ b/src/main/java/com/arangodb/internal/InternalArangoSearch.java @@ -40,13 +40,13 @@ protected Request getPropertiesRequest() { protected Request replacePropertiesRequest(final ArangoSearchPropertiesOptions options) { final Request request = request(db.dbName(), RequestType.PUT, PATH_API_VIEW, name, "properties"); - request.setBody(getInternalSerialization().serialize(options != null ? options : new ArangoSearchPropertiesOptions())); + request.setBody(getInternalSerde().serialize(options != null ? options : new ArangoSearchPropertiesOptions())); return request; } protected Request updatePropertiesRequest(final ArangoSearchPropertiesOptions options) { final Request request = request(db.dbName(), RequestType.PATCH, PATH_API_VIEW, name, "properties"); - request.setBody(getInternalSerialization().serialize(options != null ? options : new ArangoSearchPropertiesOptions())); + request.setBody(getInternalSerde().serialize(options != null ? options : new ArangoSearchPropertiesOptions())); return request; } diff --git a/src/main/java/com/arangodb/internal/InternalArangoVertexCollection.java b/src/main/java/com/arangodb/internal/InternalArangoVertexCollection.java index bc9d1e0a4..f74214086 100644 --- a/src/main/java/com/arangodb/internal/InternalArangoVertexCollection.java +++ b/src/main/java/com/arangodb/internal/InternalArangoVertexCollection.java @@ -73,9 +73,9 @@ protected Request insertVertexRequest(final T value, final VertexCreateOptio byte[] body; if (value instanceof String) { - body = getInternalSerialization().serialize(SerdeUtils.INSTANCE.parseJson((String) value)); + body = getInternalSerde().serialize(SerdeUtils.INSTANCE.parseJson((String) value)); } else { - body = getUserSerialization().serialize(value); + body = getUserSerde().serialize(value); } request.setBody(body); return request; @@ -83,7 +83,7 @@ protected Request insertVertexRequest(final T value, final VertexCreateOptio protected ResponseDeserializer insertVertexResponseDeserializer(final T value) { return response -> { - final VertexEntity doc = getInternalSerialization().deserialize(response.getBody(), "/vertex", VertexEntity.class); + final VertexEntity doc = getInternalSerde().deserialize(response.getBody(), "/vertex", VertexEntity.class); final Map values = new HashMap<>(); values.put(DocumentFields.ID, doc.getId()); values.put(DocumentFields.KEY, doc.getKey()); @@ -107,7 +107,7 @@ protected Request getVertexRequest(final String key, final GraphDocumentReadOpti } protected ResponseDeserializer getVertexResponseDeserializer(final Class type) { - return response -> getUserSerialization().deserialize(getInternalSerialization().extract(response.getBody(), "/vertex"), type); + return response -> getUserSerde().deserialize(getInternalSerde().extract(response.getBody(), "/vertex"), type); } protected Request replaceVertexRequest(final String key, final T value, final VertexReplaceOptions options) { @@ -117,13 +117,13 @@ protected Request replaceVertexRequest(final String key, final T value, fina request.putHeaderParam(TRANSACTION_ID, params.getStreamTransactionId()); request.putQueryParam(ArangoRequestParam.WAIT_FOR_SYNC, params.getWaitForSync()); request.putHeaderParam(ArangoRequestParam.IF_MATCH, params.getIfMatch()); - request.setBody(getUserSerialization().serialize(value)); + request.setBody(getUserSerde().serialize(value)); return request; } protected ResponseDeserializer replaceVertexResponseDeserializer(final T value) { return response -> { - final VertexUpdateEntity doc = getInternalSerialization().deserialize(response.getBody(), "/vertex", VertexUpdateEntity.class); + final VertexUpdateEntity doc = getInternalSerde().deserialize(response.getBody(), "/vertex", VertexUpdateEntity.class); final Map values = new HashMap<>(); values.put(DocumentFields.REV, doc.getRev()); executor.documentCache().setValues(value, values); @@ -140,13 +140,13 @@ protected Request updateVertexRequest(final String key, final T value, final request.putQueryParam(ArangoRequestParam.KEEP_NULL, params.getKeepNull()); request.putQueryParam(ArangoRequestParam.WAIT_FOR_SYNC, params.getWaitForSync()); request.putHeaderParam(ArangoRequestParam.IF_MATCH, params.getIfMatch()); - request.setBody(getUserSerialization().serialize(value)); + request.setBody(getUserSerde().serialize(value)); return request; } protected ResponseDeserializer updateVertexResponseDeserializer(final T value) { return response -> { - final VertexUpdateEntity doc = getInternalSerialization().deserialize(response.getBody(), "/vertex", VertexUpdateEntity.class); + final VertexUpdateEntity doc = getInternalSerde().deserialize(response.getBody(), "/vertex", VertexUpdateEntity.class); final Map values = new HashMap<>(); values.put(DocumentFields.REV, doc.getRev()); executor.documentCache().setValues(value, values); diff --git a/src/main/java/com/arangodb/internal/InternalArangoView.java b/src/main/java/com/arangodb/internal/InternalArangoView.java index 0257e3643..0f4e821e6 100644 --- a/src/main/java/com/arangodb/internal/InternalArangoView.java +++ b/src/main/java/com/arangodb/internal/InternalArangoView.java @@ -58,7 +58,7 @@ protected Request dropRequest() { protected Request renameRequest(final String newName) { final Request request = request(db.dbName(), RequestType.PUT, PATH_API_VIEW, name, "rename"); - request.setBody(getInternalSerialization().serialize(OptionsBuilder.build(new ViewRenameOptions(), newName))); + request.setBody(getInternalSerde().serialize(OptionsBuilder.build(new ViewRenameOptions(), newName))); return request; } diff --git a/src/main/java/com/arangodb/internal/cursor/ArangoCursorIterator.java b/src/main/java/com/arangodb/internal/cursor/ArangoCursorIterator.java index 8b108f8ff..ad9afbac0 100644 --- a/src/main/java/com/arangodb/internal/cursor/ArangoCursorIterator.java +++ b/src/main/java/com/arangodb/internal/cursor/ArangoCursorIterator.java @@ -71,11 +71,11 @@ public T next() { if (!hasNext()) { throw new NoSuchElementException(); } - return deserialize(db.getInternalSerialization().serialize(arrayIterator.next()), cursor.getType()); + return deserialize(db.getInternalSerde().serialize(arrayIterator.next()), cursor.getType()); } protected R deserialize(final byte[] result, final Class type) { - return db.getUserSerialization().deserialize(result, type); + return db.getUserSerde().deserialize(result, type); } @Override diff --git a/src/main/java/com/arangodb/internal/http/CURLLogger.java b/src/main/java/com/arangodb/internal/http/CURLLogger.java index f60039a19..062b30bba 100644 --- a/src/main/java/com/arangodb/internal/http/CURLLogger.java +++ b/src/main/java/com/arangodb/internal/http/CURLLogger.java @@ -20,7 +20,7 @@ package com.arangodb.internal.http; -import com.arangodb.util.InternalSerialization; +import com.arangodb.serde.InternalSerde; import com.arangodb.velocystream.Request; import com.arangodb.velocystream.RequestType; import org.apache.http.auth.Credentials; @@ -44,7 +44,7 @@ public static void log( final Request request, final Credentials credentials, final String jwt, - final InternalSerialization util) { + final InternalSerde util) { final RequestType requestType = request.getRequestType(); final boolean includeBody = (requestType == RequestType.POST || requestType == RequestType.PUT || requestType == RequestType.PATCH || requestType == RequestType.DELETE) && request.getBody() != null; diff --git a/src/main/java/com/arangodb/internal/http/HttpCommunication.java b/src/main/java/com/arangodb/internal/http/HttpCommunication.java index 2d7137128..284a2b45c 100644 --- a/src/main/java/com/arangodb/internal/http/HttpCommunication.java +++ b/src/main/java/com/arangodb/internal/http/HttpCommunication.java @@ -24,7 +24,7 @@ import com.arangodb.internal.net.*; import com.arangodb.internal.util.HostUtils; import com.arangodb.internal.util.RequestUtils; -import com.arangodb.util.InternalSerialization; +import com.arangodb.serde.InternalSerde; import com.arangodb.velocystream.Request; import com.arangodb.velocystream.Response; import org.slf4j.Logger; @@ -55,7 +55,7 @@ public Builder(final Builder builder) { this(builder.hostHandler); } - public HttpCommunication build(final InternalSerialization util) { + public HttpCommunication build(final InternalSerde util) { return new HttpCommunication(hostHandler); } } diff --git a/src/main/java/com/arangodb/internal/http/HttpConnection.java b/src/main/java/com/arangodb/internal/http/HttpConnection.java index 8dcfa001f..1544839dc 100644 --- a/src/main/java/com/arangodb/internal/http/HttpConnection.java +++ b/src/main/java/com/arangodb/internal/http/HttpConnection.java @@ -27,7 +27,7 @@ import com.arangodb.internal.net.HostDescription; import com.arangodb.internal.util.IOUtils; import com.arangodb.internal.util.ResponseUtils; -import com.arangodb.util.InternalSerialization; +import com.arangodb.serde.InternalSerde; import com.arangodb.velocystream.Request; import com.arangodb.velocystream.Response; import org.apache.http.*; @@ -81,7 +81,7 @@ public class HttpConnection implements Connection { public static class Builder { private String user; private String password; - private InternalSerialization util; + private InternalSerde util; private Boolean useSsl; private String httpCookieSpec; private Protocol contentType; @@ -102,7 +102,7 @@ public Builder password(final String password) { return this; } - public Builder serializationUtil(final InternalSerialization util) { + public Builder serializationUtil(final InternalSerde util) { this.util = util; return this; } @@ -163,13 +163,13 @@ public HttpConnection build() { private final String user; private final String password; private volatile String jwt = null; - private final InternalSerialization util; + private final InternalSerde util; private final Boolean useSsl; private final Protocol contentType; private final HostDescription host; private HttpConnection(final HostDescription host, final Integer timeout, final String user, final String password, - final Boolean useSsl, final SSLContext sslContext, final HostnameVerifier hostnameVerifier, final InternalSerialization util, final Protocol contentType, + final Boolean useSsl, final SSLContext sslContext, final HostnameVerifier hostnameVerifier, final InternalSerde util, final Protocol contentType, final Long ttl, final String httpCookieSpec, final HttpRequestRetryHandler httpRequestRetryHandler) { super(); this.host = host; diff --git a/src/main/java/com/arangodb/internal/http/HttpConnectionFactory.java b/src/main/java/com/arangodb/internal/http/HttpConnectionFactory.java index 6ed7bbefb..b0294ad0c 100644 --- a/src/main/java/com/arangodb/internal/http/HttpConnectionFactory.java +++ b/src/main/java/com/arangodb/internal/http/HttpConnectionFactory.java @@ -24,7 +24,7 @@ import com.arangodb.internal.net.Connection; import com.arangodb.internal.net.ConnectionFactory; import com.arangodb.internal.net.HostDescription; -import com.arangodb.util.InternalSerialization; +import com.arangodb.serde.InternalSerde; import org.apache.http.client.HttpRequestRetryHandler; import javax.net.ssl.HostnameVerifier; @@ -39,7 +39,7 @@ public class HttpConnectionFactory implements ConnectionFactory { public HttpConnectionFactory(final Integer timeout, final String user, final String password, final Boolean useSsl, final SSLContext sslContext, final HostnameVerifier hostnameVerifier, - final InternalSerialization util, final Protocol protocol, final Long connectionTtl, + final InternalSerde util, final Protocol protocol, final Long connectionTtl, final String httpCookieSpec, final HttpRequestRetryHandler httpRequestRetryHandler) { super(); builder = new HttpConnection.Builder().timeout(timeout).user(user).password(password).useSsl(useSsl) diff --git a/src/main/java/com/arangodb/internal/net/ExtendedHostResolver.java b/src/main/java/com/arangodb/internal/net/ExtendedHostResolver.java index 234c96dd0..7f4e6a9fa 100644 --- a/src/main/java/com/arangodb/internal/net/ExtendedHostResolver.java +++ b/src/main/java/com/arangodb/internal/net/ExtendedHostResolver.java @@ -25,7 +25,7 @@ import com.arangodb.internal.ArangoExecutorSync; import com.arangodb.internal.util.HostUtils; import com.arangodb.serde.SerdeUtils; -import com.arangodb.util.InternalSerialization; +import com.arangodb.serde.InternalSerde; import com.arangodb.velocystream.Request; import com.arangodb.velocystream.RequestType; import org.slf4j.Logger; @@ -49,7 +49,7 @@ public class ExtendedHostResolver implements HostResolver { private final Integer acquireHostListInterval; private ArangoExecutorSync executor; - private InternalSerialization arangoSerialization; + private InternalSerde arangoSerialization; public ExtendedHostResolver(final List hosts, final Integer maxConnections, @@ -64,7 +64,7 @@ public ExtendedHostResolver(final List hosts, final Integer maxConnections } @Override - public void init(ArangoExecutorSync executor, InternalSerialization arangoSerialization) { + public void init(ArangoExecutorSync executor, InternalSerde arangoSerialization) { this.executor = executor; this.arangoSerialization = arangoSerialization; } diff --git a/src/main/java/com/arangodb/internal/net/HostResolver.java b/src/main/java/com/arangodb/internal/net/HostResolver.java index 3dd9e6e1a..b05f6e419 100644 --- a/src/main/java/com/arangodb/internal/net/HostResolver.java +++ b/src/main/java/com/arangodb/internal/net/HostResolver.java @@ -21,14 +21,14 @@ package com.arangodb.internal.net; import com.arangodb.internal.ArangoExecutorSync; -import com.arangodb.util.InternalSerialization; +import com.arangodb.serde.InternalSerde; /** * @author Mark Vollmary */ public interface HostResolver { - void init(ArangoExecutorSync executorSync, InternalSerialization arangoSerialization); + void init(ArangoExecutorSync executorSync, InternalSerde arangoSerialization); HostSet resolve(boolean initial, boolean closeConnections); diff --git a/src/main/java/com/arangodb/internal/net/SimpleHostResolver.java b/src/main/java/com/arangodb/internal/net/SimpleHostResolver.java index 088189747..23740938d 100644 --- a/src/main/java/com/arangodb/internal/net/SimpleHostResolver.java +++ b/src/main/java/com/arangodb/internal/net/SimpleHostResolver.java @@ -21,7 +21,7 @@ package com.arangodb.internal.net; import com.arangodb.internal.ArangoExecutorSync; -import com.arangodb.util.InternalSerialization; +import com.arangodb.serde.InternalSerde; import java.util.List; @@ -38,7 +38,7 @@ public SimpleHostResolver(final List hosts) { } @Override - public void init(ArangoExecutorSync executor, InternalSerialization arangoSerialization) { + public void init(ArangoExecutorSync executor, InternalSerde arangoSerialization) { } diff --git a/src/main/java/com/arangodb/internal/util/ArangoSerializationFactory.java b/src/main/java/com/arangodb/internal/util/ArangoSerdeFactory.java similarity index 66% rename from src/main/java/com/arangodb/internal/util/ArangoSerializationFactory.java rename to src/main/java/com/arangodb/internal/util/ArangoSerdeFactory.java index c5c3558f9..5edfef0b3 100644 --- a/src/main/java/com/arangodb/internal/util/ArangoSerializationFactory.java +++ b/src/main/java/com/arangodb/internal/util/ArangoSerdeFactory.java @@ -20,28 +20,28 @@ package com.arangodb.internal.util; -import com.arangodb.util.ArangoSerialization; -import com.arangodb.util.InternalSerialization; +import com.arangodb.serde.ArangoSerde; +import com.arangodb.serde.InternalSerde; /** * @author Mark Vollmary */ -public class ArangoSerializationFactory { +public class ArangoSerdeFactory { - private final InternalSerialization internal; - private final ArangoSerialization user; + private final InternalSerde internal; + private final ArangoSerde user; - public ArangoSerializationFactory(final InternalSerialization internal, final ArangoSerialization user) { + public ArangoSerdeFactory(final InternalSerde internal, final ArangoSerde user) { super(); this.internal = internal; this.user = user; } - public InternalSerialization getInternalSerialization() { + public InternalSerde getInternalSerde() { return internal; } - public ArangoSerialization getUserSerialization() { + public ArangoSerde getUserSerialization() { return user; } diff --git a/src/main/java/com/arangodb/internal/util/ArangoSerializationImpl.java b/src/main/java/com/arangodb/internal/util/ArangoSerializationImpl.java deleted file mode 100644 index 3cba46382..000000000 --- a/src/main/java/com/arangodb/internal/util/ArangoSerializationImpl.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.arangodb.internal.util; - -import com.arangodb.ArangoDBException; -import com.arangodb.serde.ArangoSerde; -import com.arangodb.util.ArangoSerialization; - -import java.lang.reflect.Type; - -public class ArangoSerializationImpl implements ArangoSerialization { - - private final ArangoSerde serde; - - public ArangoSerializationImpl(final ArangoSerde serde) { - super(); - this.serde = serde; - } - - @Override - public byte[] serialize(final Object entity) throws ArangoDBException { - return serde.serialize(entity); - } - - @Override - public T deserialize(byte[] content, Type type) { - return serde.deserialize(content, type); - } - -} diff --git a/src/main/java/com/arangodb/internal/util/InternalSerializationImpl.java b/src/main/java/com/arangodb/internal/util/InternalSerializationImpl.java deleted file mode 100644 index 681108497..000000000 --- a/src/main/java/com/arangodb/internal/util/InternalSerializationImpl.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.internal.util; - -import com.arangodb.ArangoDBException; -import com.arangodb.serde.InternalSerde; -import com.arangodb.util.InternalSerialization; -import com.fasterxml.jackson.databind.JsonNode; - -import java.lang.reflect.Type; - -/** - * @author Mark Vollmary - */ -public class InternalSerializationImpl implements InternalSerialization { - - private final InternalSerde serde; - - public InternalSerializationImpl(final InternalSerde serde) { - super(); - this.serde = serde; - } - - @Override - public byte[] serialize(final Object entity) throws ArangoDBException { - return serde.serialize(entity); - } - - @Override - public String toJsonString(byte[] content) { - return serde.toJsonString(content); - } - - @Override - public JsonNode parse(byte[] content) { - return serde.parse(content); - } - - @Override - public T deserialize(byte[] content, Type type) { - return serde.deserialize(content, type); - } - - @Override - public T deserialize(JsonNode node, Type type) { - return serde.deserialize(node, type); - } - - @Override - public JsonNode parse(byte[] content, String jsonPointer) { - return serde.parse(content, jsonPointer); - } - - @Override - public T deserialize(byte[] content, String jsonPointer, Type type) { - return serde.deserialize(content, jsonPointer, type); - } - - @Override - public byte[] extract(byte[] content, String jsonPointer) { - return serde.extract(content, jsonPointer); - } - -} diff --git a/src/main/java/com/arangodb/internal/util/ResponseUtils.java b/src/main/java/com/arangodb/internal/util/ResponseUtils.java index 16bb4ce86..ea70a9272 100644 --- a/src/main/java/com/arangodb/internal/util/ResponseUtils.java +++ b/src/main/java/com/arangodb/internal/util/ResponseUtils.java @@ -24,7 +24,7 @@ import com.arangodb.entity.ErrorEntity; import com.arangodb.internal.ArangoErrors; import com.arangodb.internal.net.ArangoDBRedirectException; -import com.arangodb.util.InternalSerialization; +import com.arangodb.serde.InternalSerde; import com.arangodb.velocystream.Response; import java.util.concurrent.TimeoutException; @@ -42,7 +42,7 @@ private ResponseUtils() { super(); } - public static void checkError(final InternalSerialization util, final Response response) throws ArangoDBException { + public static void checkError(final InternalSerde util, final Response response) throws ArangoDBException { final int responseCode = response.getResponseCode(); if (responseCode >= ERROR_STATUS) { if (responseCode == ERROR_INTERNAL && response.getMeta().containsKey(HEADER_ENDPOINT)) { diff --git a/src/main/java/com/arangodb/internal/velocystream/VstCommunication.java b/src/main/java/com/arangodb/internal/velocystream/VstCommunication.java index 81cec8572..3f6c7267b 100644 --- a/src/main/java/com/arangodb/internal/velocystream/VstCommunication.java +++ b/src/main/java/com/arangodb/internal/velocystream/VstCommunication.java @@ -31,7 +31,7 @@ import com.arangodb.internal.velocystream.internal.Chunk; import com.arangodb.internal.velocystream.internal.Message; import com.arangodb.internal.velocystream.internal.VstConnection; -import com.arangodb.util.InternalSerialization; +import com.arangodb.serde.InternalSerde; import com.arangodb.velocypack.VPackSlice; import com.arangodb.velocypack.exception.VPackParserException; import com.arangodb.velocystream.Request; @@ -56,7 +56,7 @@ public abstract class VstCommunication implements Cl private static final Logger LOGGER = LoggerFactory.getLogger(VstCommunication.class); protected static final AtomicLong mId = new AtomicLong(0L); - protected final InternalSerialization util; + protected final InternalSerde util; protected final String user; protected final String password; @@ -66,7 +66,7 @@ public abstract class VstCommunication implements Cl protected final HostHandler hostHandler; protected VstCommunication(final Integer timeout, final String user, final String password, final String jwt, - final Boolean useSsl, final SSLContext sslContext, final InternalSerialization util, + final Boolean useSsl, final SSLContext sslContext, final InternalSerde util, final Integer chunksize, final HostHandler hostHandler) { this.user = user; this.password = password; diff --git a/src/main/java/com/arangodb/internal/velocystream/VstCommunicationSync.java b/src/main/java/com/arangodb/internal/velocystream/VstCommunicationSync.java index 140882367..84289e60b 100644 --- a/src/main/java/com/arangodb/internal/velocystream/VstCommunicationSync.java +++ b/src/main/java/com/arangodb/internal/velocystream/VstCommunicationSync.java @@ -30,7 +30,7 @@ import com.arangodb.internal.velocystream.internal.JwtAuthenticationRequest; import com.arangodb.internal.velocystream.internal.Message; import com.arangodb.internal.velocystream.internal.VstConnectionSync; -import com.arangodb.util.InternalSerialization; +import com.arangodb.serde.InternalSerde; import com.arangodb.velocypack.exception.VPackParserException; import com.arangodb.velocystream.Request; import com.arangodb.velocystream.Response; @@ -116,7 +116,7 @@ public Builder connectionTtl(final Long connectionTtl) { return this; } - public VstCommunication build(final InternalSerialization util) { + public VstCommunication build(final InternalSerde util) { return new VstCommunicationSync(hostHandler, timeout, user, password, jwt, useSsl, sslContext, util, chunksize, maxConnections, connectionTtl); } @@ -125,7 +125,7 @@ public VstCommunication build(final InternalSeriali protected VstCommunicationSync(final HostHandler hostHandler, final Integer timeout, final String user, final String password, final String jwt, final Boolean useSsl, - final SSLContext sslContext, final InternalSerialization util, + final SSLContext sslContext, final InternalSerde util, final Integer chunksize, final Integer maxConnections, final Long ttl) { super(timeout, user, password, jwt, useSsl, sslContext, util, chunksize, hostHandler); } diff --git a/src/main/java/com/arangodb/mapping/ArangoJack.java b/src/main/java/com/arangodb/mapping/ArangoJack.java deleted file mode 100644 index d195ad28d..000000000 --- a/src/main/java/com/arangodb/mapping/ArangoJack.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2017 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.mapping; - -import com.arangodb.ArangoDBException; -import com.arangodb.jackson.dataformat.velocypack.VPackMapper; -import com.arangodb.serde.DataType; -import com.arangodb.serde.JacksonSerde; -import com.arangodb.util.ArangoSerialization; -import com.fasterxml.jackson.annotation.JsonAutoDetect; -import com.fasterxml.jackson.annotation.PropertyAccessor; -import com.fasterxml.jackson.databind.DeserializationFeature; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.SerializationFeature; - -import java.lang.reflect.Type; - -/** - * @author Mark Vollmary - */ -public class ArangoJack implements ArangoSerialization { - - public interface ConfigureFunction { - void configure(ObjectMapper mapper); - } - - private final JacksonSerde serde; - - static VPackMapper createDefaultMapper() { - final VPackMapper mapper = new VPackMapper(); - mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false); - mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); - mapper.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY); - return mapper; - } - - public ArangoJack() { - this(createDefaultMapper()); - } - - /** - * @param mapper configured VPackMapper to use. A defensive copy is created and used. - */ - public ArangoJack(final VPackMapper mapper) { - super(); - VPackMapper m = mapper != null ? mapper.copy() : new VPackMapper(); - serde = JacksonSerde.of(DataType.VPACK, m); - } - - public void configure(final ArangoJack.ConfigureFunction f) { - serde.configure(f::configure); - } - - @Override - public byte[] serialize(final Object entity) throws ArangoDBException { - return serde.serialize(entity); - } - - @Override - public T deserialize(byte[] content, Type type) { - return serde.deserialize(content, type); - } - -} diff --git a/src/main/java/com/arangodb/util/ArangoSerialization.java b/src/main/java/com/arangodb/util/ArangoSerialization.java deleted file mode 100644 index d021c9bd7..000000000 --- a/src/main/java/com/arangodb/util/ArangoSerialization.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.arangodb.util; - -import java.lang.reflect.Type; - -public interface ArangoSerialization { - byte[] serialize(final Object entity); - T deserialize(byte[] content, Type type); -} diff --git a/src/main/java/com/arangodb/util/InternalSerialization.java b/src/main/java/com/arangodb/util/InternalSerialization.java deleted file mode 100644 index d063a7d3a..000000000 --- a/src/main/java/com/arangodb/util/InternalSerialization.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.util; - -import com.fasterxml.jackson.databind.JsonNode; - -import java.lang.reflect.Type; - -/** - * @author Mark Vollmary - */ -public interface InternalSerialization { - byte[] serialize(final Object entity); - - T deserialize(byte[] content, Type type); - - T deserialize(JsonNode node, Type type); - - String toJsonString(byte[] content); - - JsonNode parse(byte[] content); - - JsonNode parse(byte[] content, String jsonPointer); - - T deserialize(byte[] content, String jsonPointer, Type type); - - byte[] extract(byte[] content, String jsonPointer); - -} diff --git a/src/test/java/com/arangodb/ArangoDBTest.java b/src/test/java/com/arangodb/ArangoDBTest.java index b2d70b92b..5762bf915 100644 --- a/src/test/java/com/arangodb/ArangoDBTest.java +++ b/src/test/java/com/arangodb/ArangoDBTest.java @@ -21,7 +21,6 @@ package com.arangodb; import com.arangodb.entity.*; -import com.arangodb.mapping.ArangoJack; import com.arangodb.model.*; import com.arangodb.model.LogOptions.SortOrder; import com.arangodb.util.TestUtils; @@ -213,7 +212,7 @@ void createDatabaseWithUsers(ArangoDB arangoDB) throws InterruptedException { Thread.sleep(1_000); ArangoDB arangoDBTestUser = new ArangoDB.Builder() - .serializer(new ArangoJack()) + .user("testUser") .password("testPasswd") .build(); @@ -375,7 +374,7 @@ void updateUserDefaultCollectionAccess(ArangoDB arangoDB) { @Test void authenticationFailPassword() { - final ArangoDB arangoDB = new ArangoDB.Builder().password("no").jwt(null).serializer(new ArangoJack()).build(); + final ArangoDB arangoDB = new ArangoDB.Builder().password("no").jwt(null).build(); Throwable thrown = catchThrowable(arangoDB::getVersion); assertThat(thrown).isInstanceOf(ArangoDBException.class); assertThat(((ArangoDBException) thrown).getResponseCode()).isEqualTo(401); @@ -384,7 +383,7 @@ void authenticationFailPassword() { @ParameterizedTest(name = "{index}") @MethodSource("arangos") void authenticationFailUser() { - final ArangoDB arangoDB = new ArangoDB.Builder().user("no").jwt(null).serializer(new ArangoJack()).build(); + final ArangoDB arangoDB = new ArangoDB.Builder().user("no").jwt(null).build(); Throwable thrown = catchThrowable(arangoDB::getVersion); assertThat(thrown).isInstanceOf(ArangoDBException.class); assertThat(((ArangoDBException) thrown).getResponseCode()).isEqualTo(401); @@ -394,7 +393,7 @@ void authenticationFailUser() { @MethodSource("arangos") void execute(ArangoDB arangoDB) { final Response response = arangoDB.execute(new Request(DbName.SYSTEM, RequestType.GET, "/_api/version")); - assertThat(arangoDB.getInternalSerialization().parse(response.getBody(), "/version").isTextual()).isTrue(); + assertThat(arangoDB.getInternalSerde().parse(response.getBody(), "/version").isTextual()).isTrue(); } @ParameterizedTest(name = "{index}") @@ -555,7 +554,7 @@ void arangoDBException(ArangoDB arangoDB) { @ParameterizedTest(name = "{index}") @MethodSource("arangos") void fallbackHost() { - final ArangoDB arangoDB = new ArangoDB.Builder().host("not-accessible", 8529).host("127.0.0.1", 8529).serializer(new ArangoJack()).build(); + final ArangoDB arangoDB = new ArangoDB.Builder().host("not-accessible", 8529).host("127.0.0.1", 8529).build(); final ArangoDBVersion version = arangoDB.getVersion(); assertThat(version).isNotNull(); } diff --git a/src/test/java/com/arangodb/ArangoRouteTest.java b/src/test/java/com/arangodb/ArangoRouteTest.java index 212c654a4..b6866fbea 100644 --- a/src/test/java/com/arangodb/ArangoRouteTest.java +++ b/src/test/java/com/arangodb/ArangoRouteTest.java @@ -47,7 +47,7 @@ static void init() { @MethodSource("dbs") void get(ArangoDatabase db) { final Response res = db.route("/_api/version").get(); - assertThat(db.arango().getInternalSerialization().parse(res.getBody(), "/version").isTextual()).isTrue(); + assertThat(db.arango().getInternalSerde().parse(res.getBody(), "/version").isTextual()).isTrue(); } @ParameterizedTest(name = "{index}") diff --git a/src/test/java/com/arangodb/ArangoSslTest.java b/src/test/java/com/arangodb/ArangoSslTest.java index 613f1632c..b2693dae9 100644 --- a/src/test/java/com/arangodb/ArangoSslTest.java +++ b/src/test/java/com/arangodb/ArangoSslTest.java @@ -21,7 +21,6 @@ package com.arangodb; import com.arangodb.entity.ArangoDBVersion; -import com.arangodb.mapping.ArangoJack; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.condition.EnabledIfSystemProperty; @@ -71,7 +70,7 @@ void connect() throws Exception { final ArangoDB arangoDB = new ArangoDB.Builder() .loadProperties(ArangoSslTest.class.getResourceAsStream("/arangodb-ssl.properties")).useSsl(true) - .sslContext(sc).serializer(new ArangoJack()).build(); + .sslContext(sc).build(); final ArangoDBVersion version = arangoDB.getVersion(); assertThat(version).isNotNull(); } @@ -80,7 +79,7 @@ void connect() throws Exception { void connectWithoutValidSslContext() { final ArangoDB arangoDB = new ArangoDB.Builder() .loadProperties(ArangoSslTest.class.getResourceAsStream("/arangodb-ssl.properties")).useSsl(true) - .serializer(new ArangoJack()).build(); + .build(); Throwable thrown = catchThrowable(arangoDB::getVersion); assertThat(thrown).isInstanceOf(ArangoDBException.class); ArangoDBException ex = (ArangoDBException) thrown; diff --git a/src/test/java/com/arangodb/BaseJunit5.java b/src/test/java/com/arangodb/BaseJunit5.java index 140d52730..b231b4a58 100644 --- a/src/test/java/com/arangodb/BaseJunit5.java +++ b/src/test/java/com/arangodb/BaseJunit5.java @@ -21,8 +21,6 @@ class BaseJunit5 { private static final List adbs = Arrays.stream(Protocol.values()) .map(p -> new ArangoDB.Builder() .useProtocol(p) - // FIXME -// .serializer(new ArangoJack()) .build()) .collect(Collectors.toList()); diff --git a/src/test/java/com/arangodb/ConcurrencyTests.java b/src/test/java/com/arangodb/ConcurrencyTests.java index 16c26ac08..2140a0f07 100644 --- a/src/test/java/com/arangodb/ConcurrencyTests.java +++ b/src/test/java/com/arangodb/ConcurrencyTests.java @@ -1,6 +1,5 @@ package com.arangodb; -import com.arangodb.mapping.ArangoJack; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.EnumSource; @@ -18,7 +17,7 @@ class ConcurrencyTests { @EnumSource(Protocol.class) void concurrentPendingRequests(Protocol protocol) throws ExecutionException, InterruptedException { ExecutorService es = Executors.newFixedThreadPool(10); - ArangoDB adb = new ArangoDB.Builder().useProtocol(protocol).serializer(new ArangoJack()).build(); + ArangoDB adb = new ArangoDB.Builder().useProtocol(protocol).build(); List> futures = IntStream.range(0, 10) .mapToObj(__ -> CompletableFuture.runAsync(() -> adb.db().query("RETURN SLEEP(1)", Void.class), es)) .collect(Collectors.toList()); diff --git a/src/test/java/com/arangodb/JwtAuthTest.java b/src/test/java/com/arangodb/JwtAuthTest.java index 835c2cade..59d12df67 100644 --- a/src/test/java/com/arangodb/JwtAuthTest.java +++ b/src/test/java/com/arangodb/JwtAuthTest.java @@ -1,7 +1,6 @@ package com.arangodb; -import com.arangodb.mapping.ArangoJack; -import com.arangodb.util.InternalSerialization; +import com.arangodb.serde.InternalSerde; import com.arangodb.velocystream.Request; import com.arangodb.velocystream.RequestType; import com.arangodb.velocystream.Response; @@ -25,7 +24,7 @@ class JwtAuthTest { @BeforeAll static void init() { - ArangoDB arangoDB = new ArangoDB.Builder().serializer(new ArangoJack()).build(); + ArangoDB arangoDB = new ArangoDB.Builder().build(); jwt = getJwt(arangoDB); arangoDB.shutdown(); } @@ -76,14 +75,14 @@ void updateJwt(Protocol protocol) { private ArangoDB.Builder getBuilder(Protocol protocol) { return new ArangoDB.Builder() .useProtocol(protocol) - .serializer(new ArangoJack()) + .jwt(null) // unset credentials from properties file .user(null) // unset credentials from properties file .password(null); // unset credentials from properties file } private static String getJwt(ArangoDB arangoDB) { - InternalSerialization serde = arangoDB.getInternalSerialization(); + InternalSerde serde = arangoDB.getInternalSerde(); Map reqBody = new HashMap<>(); reqBody.put("username", "root"); reqBody.put("password", "test"); diff --git a/src/test/java/com/arangodb/async/ArangoDBTest.java b/src/test/java/com/arangodb/async/ArangoDBTest.java index 134189fa3..743b7cc28 100644 --- a/src/test/java/com/arangodb/async/ArangoDBTest.java +++ b/src/test/java/com/arangodb/async/ArangoDBTest.java @@ -22,7 +22,6 @@ import com.arangodb.*; import com.arangodb.entity.*; -import com.arangodb.mapping.ArangoJack; import com.arangodb.model.*; import com.arangodb.util.TestUtils; import com.arangodb.velocystream.Request; @@ -55,8 +54,8 @@ class ArangoDBTest { private static final String PW = "machts der hund"; private static Boolean extendedNames; - private final ArangoDBAsync arangoDB = new ArangoDBAsync.Builder().serializer(new ArangoJack()).build(); - private final ArangoDB arangoDBSync = new ArangoDB.Builder().serializer(new ArangoJack()).build(); + private final ArangoDBAsync arangoDB = new ArangoDBAsync.Builder().build(); + private final ArangoDB arangoDBSync = new ArangoDB.Builder().build(); private boolean isEnterprise() { return arangoDBSync.getVersion().getLicense() == License.ENTERPRISE; @@ -75,7 +74,7 @@ private boolean isLessThanVersion(final int major, final int minor) { } private boolean supportsExtendedNames() { - final ArangoDB arangoDB = new ArangoDB.Builder().serializer(new ArangoJack()).build(); + final ArangoDB arangoDB = new ArangoDB.Builder().build(); if (extendedNames == null) { try { ArangoDatabase testDb = arangoDB.db(DbName.of("test-" + TestUtils.generateRandomDbName(20, true))); @@ -414,7 +413,7 @@ void updateUserDefaultCollectionAccess() throws InterruptedException, ExecutionE @Test void authenticationFailPassword() throws InterruptedException { - final ArangoDBAsync arangoDB = new ArangoDBAsync.Builder().password("no").jwt(null).serializer(new ArangoJack()).build(); + final ArangoDBAsync arangoDB = new ArangoDBAsync.Builder().password("no").jwt(null).build(); try { arangoDB.getVersion().get(); fail(); @@ -425,7 +424,7 @@ void authenticationFailPassword() throws InterruptedException { @Test void authenticationFailUser() throws InterruptedException { - final ArangoDBAsync arangoDB = new ArangoDBAsync.Builder().user("no").jwt(null).serializer(new ArangoJack()).build(); + final ArangoDBAsync arangoDB = new ArangoDBAsync.Builder().user("no").jwt(null).build(); try { arangoDB.getVersion().get(); fail(); @@ -440,19 +439,19 @@ void execute() throws InterruptedException, ExecutionException { .execute(new Request(DbName.SYSTEM, RequestType.GET, "/_api/version")) .whenComplete((response, ex) -> { assertThat(response.getBody()).isNotNull(); - assertThat(arangoDB.getInternalSerialization().parse(response.getBody(), "/version").isTextual()).isTrue(); + assertThat(arangoDB.getInternalSerde().parse(response.getBody(), "/version").isTextual()).isTrue(); }) .get(); } @Test void execute_acquireHostList_enabled() throws InterruptedException, ExecutionException { - final ArangoDBAsync arangoDB = new ArangoDBAsync.Builder().acquireHostList(true).serializer(new ArangoJack()).build(); + final ArangoDBAsync arangoDB = new ArangoDBAsync.Builder().acquireHostList(true).build(); arangoDB .execute(new Request(DbName.SYSTEM, RequestType.GET, "/_api/version")) .whenComplete((response, ex) -> { assertThat(response.getBody()).isNotNull(); - assertThat(arangoDB.getInternalSerialization().parse(response.getBody(), "/version").isTextual()).isTrue(); + assertThat(arangoDB.getInternalSerde().parse(response.getBody(), "/version").isTextual()).isTrue(); }) .get(); } diff --git a/src/test/java/com/arangodb/async/BaseTest.java b/src/test/java/com/arangodb/async/BaseTest.java index db4f312aa..d0c318744 100644 --- a/src/test/java/com/arangodb/async/BaseTest.java +++ b/src/test/java/com/arangodb/async/BaseTest.java @@ -24,7 +24,6 @@ import com.arangodb.DbName; import com.arangodb.entity.License; import com.arangodb.entity.ServerRole; -import com.arangodb.mapping.ArangoJack; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; @@ -44,7 +43,7 @@ public abstract class BaseTest { @BeforeAll static void init() throws InterruptedException, ExecutionException { if (arangoDB == null) { - arangoDB = new ArangoDBAsync.Builder().serializer(new ArangoJack()).build(); + arangoDB = new ArangoDBAsync.Builder().build(); } if (arangoDB.db(TEST_DB).exists().get()) { diff --git a/src/test/java/com/arangodb/async/CommunicationTest.java b/src/test/java/com/arangodb/async/CommunicationTest.java index 744aa0087..ecbfd3a42 100644 --- a/src/test/java/com/arangodb/async/CommunicationTest.java +++ b/src/test/java/com/arangodb/async/CommunicationTest.java @@ -20,7 +20,6 @@ package com.arangodb.async; -import com.arangodb.mapping.ArangoJack; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; @@ -38,7 +37,7 @@ class CommunicationTest { @Test @Disabled void disconnect() { - final ArangoDBAsync arangoDB = new ArangoDBAsync.Builder().serializer(new ArangoJack()).build(); + final ArangoDBAsync arangoDB = new ArangoDBAsync.Builder().build(); final CompletableFuture> result = arangoDB.db().query("return sleep(1)", null, null, null); arangoDB.shutdown(); diff --git a/src/test/java/com/arangodb/async/ConcurrencyTest.java b/src/test/java/com/arangodb/async/ConcurrencyTest.java index 46c6bd552..f0643c2ca 100644 --- a/src/test/java/com/arangodb/async/ConcurrencyTest.java +++ b/src/test/java/com/arangodb/async/ConcurrencyTest.java @@ -23,7 +23,6 @@ import com.arangodb.async.internal.ArangoExecutorAsync; import com.arangodb.entity.ArangoDBVersion; -import com.arangodb.mapping.ArangoJack; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; @@ -47,7 +46,7 @@ class ConcurrencyTest { @BeforeEach void initialize() { - arangoDB = new ArangoDBAsync.Builder().serializer(new ArangoJack()).build(); + arangoDB = new ArangoDBAsync.Builder().build(); } /** diff --git a/src/test/java/com/arangodb/async/ConcurrencyTests.java b/src/test/java/com/arangodb/async/ConcurrencyTests.java index edbad7c81..3219a5f50 100644 --- a/src/test/java/com/arangodb/async/ConcurrencyTests.java +++ b/src/test/java/com/arangodb/async/ConcurrencyTests.java @@ -2,7 +2,6 @@ -import com.arangodb.mapping.ArangoJack; import org.junit.jupiter.api.Test; import java.util.List; @@ -15,7 +14,7 @@ class ConcurrencyTests { @Test void concurrentPendingRequests() throws ExecutionException, InterruptedException { - ArangoDBAsync adb = new ArangoDBAsync.Builder().serializer(new ArangoJack()).build(); + ArangoDBAsync adb = new ArangoDBAsync.Builder().build(); List>> reqs = IntStream.range(0, 10) .mapToObj(__ -> adb.db().query("RETURN SLEEP(1)", Void.class)) .collect(Collectors.toList()); diff --git a/src/test/java/com/arangodb/async/JwtAuthTest.java b/src/test/java/com/arangodb/async/JwtAuthTest.java index a55c23527..640c7a0ee 100644 --- a/src/test/java/com/arangodb/async/JwtAuthTest.java +++ b/src/test/java/com/arangodb/async/JwtAuthTest.java @@ -3,8 +3,7 @@ import com.arangodb.ArangoDB; import com.arangodb.ArangoDBException; import com.arangodb.DbName; -import com.arangodb.mapping.ArangoJack; -import com.arangodb.util.InternalSerialization; +import com.arangodb.serde.InternalSerde; import com.arangodb.velocystream.Request; import com.arangodb.velocystream.RequestType; import com.arangodb.velocystream.Response; @@ -28,7 +27,7 @@ class JwtAuthTest { @BeforeAll static void init() { - ArangoDB arangoDB = new ArangoDB.Builder().serializer(new ArangoJack()).build(); + ArangoDB arangoDB = new ArangoDB.Builder().build(); jwt = getJwt(arangoDB); arangoDB.shutdown(); } @@ -83,14 +82,14 @@ void updateJwt() throws ExecutionException, InterruptedException { private ArangoDBAsync.Builder getBuilder() { return new ArangoDBAsync.Builder() - .serializer(new ArangoJack()) + .jwt(null) // unset credentials from properties file .user(null) // unset credentials from properties file .password(null); // unset credentials from properties file } private static String getJwt(ArangoDB arangoDB) { - InternalSerialization serde = arangoDB.getInternalSerialization(); + InternalSerde serde = arangoDB.getInternalSerde(); Map reqBody = new HashMap<>(); reqBody.put("username", "root"); reqBody.put("password", "test"); diff --git a/src/test/java/com/arangodb/async/debug/ConsolidationIntervalMsecTest.java b/src/test/java/com/arangodb/async/debug/ConsolidationIntervalMsecTest.java index 14f5b7ab3..d6c8ebccd 100644 --- a/src/test/java/com/arangodb/async/debug/ConsolidationIntervalMsecTest.java +++ b/src/test/java/com/arangodb/async/debug/ConsolidationIntervalMsecTest.java @@ -29,7 +29,6 @@ import com.arangodb.entity.arangosearch.ArangoSearchPropertiesEntity; import com.arangodb.entity.arangosearch.CollectionLink; import com.arangodb.entity.arangosearch.FieldLink; -import com.arangodb.mapping.ArangoJack; import com.arangodb.model.arangosearch.ArangoSearchCreateOptions; import org.junit.jupiter.api.Test; @@ -50,7 +49,6 @@ void consolidationIntervalMsec() throws ExecutionException, InterruptedException assumeTrue(isAtLeastVersion(3, 4)); ArangoDBAsync arango = new ArangoDBAsync.Builder() - .serializer(new ArangoJack()) .user("root") .password("test") .build(); diff --git a/src/test/java/com/arangodb/async/example/ExampleBase.java b/src/test/java/com/arangodb/async/example/ExampleBase.java index 9ae6e510a..22ca7f7a8 100644 --- a/src/test/java/com/arangodb/async/example/ExampleBase.java +++ b/src/test/java/com/arangodb/async/example/ExampleBase.java @@ -24,7 +24,6 @@ import com.arangodb.async.ArangoCollectionAsync; import com.arangodb.async.ArangoDBAsync; import com.arangodb.async.ArangoDatabaseAsync; -import com.arangodb.mapping.ArangoJack; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; @@ -43,7 +42,7 @@ public class ExampleBase { @BeforeAll static void setUp() throws InterruptedException, ExecutionException { - arangoDB = new ArangoDBAsync.Builder().serializer(new ArangoJack()).build(); + arangoDB = new ArangoDBAsync.Builder().build(); if (arangoDB.db(DB_NAME).exists().get()) { arangoDB.db(DB_NAME).drop().get(); } diff --git a/src/test/java/com/arangodb/async/example/document/AqlQueryWithSpecialReturnTypesExampleTest.java b/src/test/java/com/arangodb/async/example/document/AqlQueryWithSpecialReturnTypesExampleTest.java index b4e98bc16..b5e9b1f15 100644 --- a/src/test/java/com/arangodb/async/example/document/AqlQueryWithSpecialReturnTypesExampleTest.java +++ b/src/test/java/com/arangodb/async/example/document/AqlQueryWithSpecialReturnTypesExampleTest.java @@ -22,12 +22,12 @@ import com.arangodb.async.example.ExampleBase; import com.arangodb.entity.BaseDocument; -import com.arangodb.util.MapBuilder; import com.fasterxml.jackson.databind.node.ArrayNode; import com.fasterxml.jackson.databind.node.ObjectNode; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; +import java.util.Collections; import java.util.List; import java.util.Map; import java.util.concurrent.ExecutionException; @@ -59,7 +59,7 @@ private static void createExamples() throws InterruptedException, ExecutionExcep void aqlWithLimitQueryAsJsonObject() throws InterruptedException, ExecutionException { final String query = "FOR t IN " + COLLECTION_NAME + " FILTER t.age >= 20 && t.age < 30 && t.gender == @gender RETURN t"; - final Map bindVars = new MapBuilder().put("gender", Gender.FEMALE).get(); + final Map bindVars = Collections.singletonMap("gender", Gender.FEMALE); db.query(query, bindVars, null, ObjectNode.class) .whenComplete((cursor, ex) -> cursor.forEachRemaining(node -> { assertThat(node.get("name").asText()).isIn("TestUser11", "TestUser13", "TestUser15", "TestUser17", "TestUser19"); @@ -73,7 +73,7 @@ void aqlWithLimitQueryAsJsonObject() throws InterruptedException, ExecutionExcep void aqlWithLimitQueryAsArrayNode() throws InterruptedException, ExecutionException { final String query = "FOR t IN " + COLLECTION_NAME + " FILTER t.age >= 20 && t.age < 30 && t.gender == @gender RETURN [t.name, t.gender, t.age]"; - final Map bindVars = new MapBuilder().put("gender", Gender.FEMALE).get(); + final Map bindVars = Collections.singletonMap("gender", Gender.FEMALE); db.query(query, bindVars, null, ArrayNode.class) .whenComplete((cursor, ex) -> cursor.forEachRemaining(arrNode -> { assertThat(arrNode.get(0).asText()).isIn("TestUser11", "TestUser13", "TestUser15", "TestUser17", "TestUser19"); @@ -87,7 +87,7 @@ void aqlWithLimitQueryAsArrayNode() throws InterruptedException, ExecutionExcept void aqlWithLimitQueryAsMap() throws InterruptedException, ExecutionException { final String query = "FOR t IN " + COLLECTION_NAME + " FILTER t.age >= 20 && t.age < 30 && t.gender == @gender RETURN t"; - final Map bindVars = new MapBuilder().put("gender", Gender.FEMALE).get(); + final Map bindVars = Collections.singletonMap("gender", Gender.FEMALE); db.query(query, bindVars, null, Map.class) .whenComplete((cursor, ex) -> cursor.forEachRemaining(map -> { assertThat(map.get("name")).isNotNull(); @@ -104,7 +104,7 @@ void aqlWithLimitQueryAsMap() throws InterruptedException, ExecutionException { void aqlWithLimitQueryAsList() throws InterruptedException, ExecutionException { final String query = "FOR t IN " + COLLECTION_NAME + " FILTER t.age >= 20 && t.age < 30 && t.gender == @gender RETURN [t.name, t.gender, t.age]"; - final Map bindVars = new MapBuilder().put("gender", Gender.FEMALE).get(); + final Map bindVars = Collections.singletonMap("gender", Gender.FEMALE); db.query(query, bindVars, null, List.class) .whenComplete((cursor, ex) -> cursor.forEachRemaining(list -> { assertThat(list.get(0)).isNotNull(); diff --git a/src/test/java/com/arangodb/async/example/graph/AQLActorsAndMoviesExampleTest.java b/src/test/java/com/arangodb/async/example/graph/AQLActorsAndMoviesExampleTest.java index 9667b542c..88bbfb425 100644 --- a/src/test/java/com/arangodb/async/example/graph/AQLActorsAndMoviesExampleTest.java +++ b/src/test/java/com/arangodb/async/example/graph/AQLActorsAndMoviesExampleTest.java @@ -29,7 +29,6 @@ import com.arangodb.entity.BaseEdgeDocument; import com.arangodb.entity.CollectionType; import com.arangodb.entity.DocumentCreateEntity; -import com.arangodb.mapping.ArangoJack; import com.arangodb.model.CollectionCreateOptions; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; @@ -57,7 +56,7 @@ class AQLActorsAndMoviesExampleTest { @BeforeAll static void setUp() throws InterruptedException, ExecutionException { - arangoDB = new ArangoDBAsync.Builder().serializer(new ArangoJack()).build(); + arangoDB = new ArangoDBAsync.Builder().build(); if (arangoDB.db(TEST_DB).exists().get()) { arangoDB.db(TEST_DB).drop().get(); } diff --git a/src/test/java/com/arangodb/async/example/graph/BaseGraphTest.java b/src/test/java/com/arangodb/async/example/graph/BaseGraphTest.java index 5496496f5..7e3c7a190 100644 --- a/src/test/java/com/arangodb/async/example/graph/BaseGraphTest.java +++ b/src/test/java/com/arangodb/async/example/graph/BaseGraphTest.java @@ -25,7 +25,6 @@ import com.arangodb.async.ArangoDatabaseAsync; import com.arangodb.entity.EdgeDefinition; import com.arangodb.entity.VertexEntity; -import com.arangodb.mapping.ArangoJack; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; @@ -48,7 +47,7 @@ public abstract class BaseGraphTest { @BeforeAll static void init() throws InterruptedException, ExecutionException { if (arangoDB == null) { - arangoDB = new ArangoDBAsync.Builder().serializer(new ArangoJack()).build(); + arangoDB = new ArangoDBAsync.Builder().build(); } if (arangoDB.db(TEST_DB).exists().get()) { arangoDB.db(TEST_DB).drop().get(); diff --git a/src/test/java/com/arangodb/async/example/ssl/SslExampleTest.java b/src/test/java/com/arangodb/async/example/ssl/SslExampleTest.java index 68d19f0d6..4c55a0ceb 100644 --- a/src/test/java/com/arangodb/async/example/ssl/SslExampleTest.java +++ b/src/test/java/com/arangodb/async/example/ssl/SslExampleTest.java @@ -22,7 +22,6 @@ import com.arangodb.async.ArangoDBAsync; import com.arangodb.entity.ArangoDBVersion; -import com.arangodb.mapping.ArangoJack; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.condition.EnabledIfSystemProperty; @@ -69,7 +68,7 @@ void connect() throws Exception { final ArangoDBAsync arangoDB = new ArangoDBAsync.Builder() .loadProperties(SslExampleTest.class.getResourceAsStream("/arangodb-ssl.properties")).useSsl(true) - .sslContext(sc).serializer(new ArangoJack()).build(); + .sslContext(sc).build(); final ArangoDBVersion version = arangoDB.getVersion().get(); assertThat(version).isNotNull(); } diff --git a/src/test/java/com/arangodb/async/serde/CustomSerdeTest.java b/src/test/java/com/arangodb/async/serde/CustomSerdeTest.java index 90022a845..2546334bd 100644 --- a/src/test/java/com/arangodb/async/serde/CustomSerdeTest.java +++ b/src/test/java/com/arangodb/async/serde/CustomSerdeTest.java @@ -26,8 +26,9 @@ import com.arangodb.async.ArangoDBAsync; import com.arangodb.async.ArangoDatabaseAsync; import com.arangodb.entity.BaseDocument; -import com.arangodb.mapping.ArangoJack; import com.arangodb.model.DocumentCreateOptions; +import com.arangodb.serde.DataType; +import com.arangodb.serde.JacksonSerde; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -56,12 +57,12 @@ class CustomSerdeTest { @BeforeEach void init() throws ExecutionException, InterruptedException { - ArangoJack arangoJack = new ArangoJack(); - arangoJack.configure((mapper) -> { + JacksonSerde serde = JacksonSerde.of(DataType.VPACK); + serde.configure((mapper) -> { mapper.configure(WRITE_SINGLE_ELEM_ARRAYS_UNWRAPPED, true); mapper.configure(USE_BIG_INTEGER_FOR_INTS, true); }); - ArangoDBAsync arangoDB = new ArangoDBAsync.Builder().serializer(arangoJack).build(); + ArangoDBAsync arangoDB = new ArangoDBAsync.Builder().serializer(serde).build(); DbName TEST_DB = DbName.of("custom-serde-test"); db = arangoDB.db(TEST_DB); diff --git a/src/test/java/com/arangodb/example/ExampleBase.java b/src/test/java/com/arangodb/example/ExampleBase.java index b903a31d5..6267026d5 100644 --- a/src/test/java/com/arangodb/example/ExampleBase.java +++ b/src/test/java/com/arangodb/example/ExampleBase.java @@ -21,7 +21,6 @@ package com.arangodb.example; import com.arangodb.*; -import com.arangodb.mapping.ArangoJack; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; @@ -39,7 +38,7 @@ public class ExampleBase { @BeforeAll static void setUp() { - arangoDB = new ArangoDB.Builder().serializer(new ArangoJack()).build(); + arangoDB = new ArangoDB.Builder().build(); DbName dbName = DbName.of(DB_NAME); if (arangoDB.db(dbName).exists()) arangoDB.db(dbName).drop(); diff --git a/src/test/java/com/arangodb/example/FirstProject.java b/src/test/java/com/arangodb/example/FirstProject.java index 8164c26a3..ca1db29d4 100644 --- a/src/test/java/com/arangodb/example/FirstProject.java +++ b/src/test/java/com/arangodb/example/FirstProject.java @@ -3,16 +3,15 @@ import com.arangodb.*; import com.arangodb.entity.BaseDocument; import com.arangodb.entity.CollectionEntity; -import com.arangodb.mapping.ArangoJack; -import com.arangodb.util.MapBuilder; import com.fasterxml.jackson.databind.JsonNode; +import java.util.Collections; import java.util.Map; public class FirstProject { public static void main(final String[] args) { - final ArangoDB arangoDB = new ArangoDB.Builder().user("root").serializer(new ArangoJack()).build(); + final ArangoDB arangoDB = new ArangoDB.Builder().user("root").build(); // create database final DbName dbName = DbName.of("mydb"); @@ -105,7 +104,7 @@ public static void main(final String[] args) { // execute AQL queries try { final String query = "FOR t IN firstCollection FILTER t.name == @name RETURN t"; - final Map bindVars = new MapBuilder().put("name", "Homer").get(); + final Map bindVars = Collections.singletonMap("name", "Homer"); final ArangoCursor cursor = arangoDB.db(dbName).query(query, bindVars, null, BaseDocument.class); for (; cursor.hasNext(); ) { @@ -119,7 +118,7 @@ public static void main(final String[] args) { try { final String query = "FOR t IN firstCollection FILTER t.name == @name " + "REMOVE t IN firstCollection LET removed = OLD RETURN removed"; - final Map bindVars = new MapBuilder().put("name", "Homer").get(); + final Map bindVars = Collections.singletonMap("name", "Homer"); final ArangoCursor cursor = arangoDB.db(dbName).query(query, bindVars, null, BaseDocument.class); for (; cursor.hasNext(); ) { diff --git a/src/test/java/com/arangodb/example/document/AqlQueryWithSpecialReturnTypesExampleTest.java b/src/test/java/com/arangodb/example/document/AqlQueryWithSpecialReturnTypesExampleTest.java index 1172d4071..f820cdd09 100644 --- a/src/test/java/com/arangodb/example/document/AqlQueryWithSpecialReturnTypesExampleTest.java +++ b/src/test/java/com/arangodb/example/document/AqlQueryWithSpecialReturnTypesExampleTest.java @@ -23,12 +23,12 @@ import com.arangodb.ArangoCursor; import com.arangodb.entity.BaseDocument; import com.arangodb.example.ExampleBase; -import com.arangodb.util.MapBuilder; import com.fasterxml.jackson.databind.node.ArrayNode; import com.fasterxml.jackson.databind.node.ObjectNode; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; +import java.util.Collections; import java.util.List; import java.util.Map; @@ -63,7 +63,7 @@ private static void createExamples() { void aqlWithLimitQueryAsJsonObject() { final String query = "FOR t IN " + COLLECTION_NAME + " FILTER t.age >= 20 && t.age < 30 && t.gender == @gender RETURN t"; - final Map bindVars = new MapBuilder().put("gender", Gender.FEMALE).get(); + final Map bindVars = Collections.singletonMap("gender", Gender.FEMALE); final ArangoCursor cursor = db.query(query, bindVars, null, ObjectNode.class); assertThat((Object) cursor).isNotNull(); while (cursor.hasNext()) { @@ -79,7 +79,7 @@ void aqlWithLimitQueryAsJsonObject() { void aqlWithLimitQueryAsJsonArray() { final String query = "FOR t IN " + COLLECTION_NAME + " FILTER t.age >= 20 && t.age < 30 && t.gender == @gender RETURN [t.name, t.gender, t.age]"; - final Map bindVars = new MapBuilder().put("gender", Gender.FEMALE).get(); + final Map bindVars = Collections.singletonMap("gender", Gender.FEMALE); final ArangoCursor cursor = db.query(query, bindVars, null, ArrayNode.class); assertThat((Object) cursor).isNotNull(); while (cursor.hasNext()) { @@ -96,7 +96,7 @@ void aqlWithLimitQueryAsJsonArray() { void aqlWithLimitQueryAsMap() { final String query = "FOR t IN " + COLLECTION_NAME + " FILTER t.age >= 20 && t.age < 30 && t.gender == @gender RETURN t"; - final Map bindVars = new MapBuilder().put("gender", Gender.FEMALE).get(); + final Map bindVars = Collections.singletonMap("gender", Gender.FEMALE); final ArangoCursor cursor = db.query(query, bindVars, null, Map.class); assertThat((Object) cursor).isNotNull(); while (cursor.hasNext()) { @@ -116,7 +116,7 @@ void aqlWithLimitQueryAsMap() { void aqlWithLimitQueryAsList() { final String query = "FOR t IN " + COLLECTION_NAME + " FILTER t.age >= 20 && t.age < 30 && t.gender == @gender RETURN [t.name, t.gender, t.age]"; - final Map bindVars = new MapBuilder().put("gender", Gender.FEMALE).get(); + final Map bindVars = Collections.singletonMap("gender", Gender.FEMALE); final ArangoCursor cursor = db.query(query, bindVars, null, List.class); assertThat((Object) cursor).isNotNull(); while (cursor.hasNext()) { diff --git a/src/test/java/com/arangodb/example/graph/AQLActorsAndMoviesExampleTest.java b/src/test/java/com/arangodb/example/graph/AQLActorsAndMoviesExampleTest.java index ba9cb7cd4..0bd9b57a3 100644 --- a/src/test/java/com/arangodb/example/graph/AQLActorsAndMoviesExampleTest.java +++ b/src/test/java/com/arangodb/example/graph/AQLActorsAndMoviesExampleTest.java @@ -25,7 +25,6 @@ import com.arangodb.entity.BaseEdgeDocument; import com.arangodb.entity.CollectionType; import com.arangodb.entity.DocumentCreateEntity; -import com.arangodb.mapping.ArangoJack; import com.arangodb.model.CollectionCreateOptions; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; @@ -49,7 +48,7 @@ class AQLActorsAndMoviesExampleTest { @BeforeAll static void setUp() { - arangoDB = new ArangoDB.Builder().serializer(new ArangoJack()).build(); + arangoDB = new ArangoDB.Builder().build(); if (arangoDB.db(TEST_DB).exists()) arangoDB.db(TEST_DB).drop(); arangoDB.createDatabase(TEST_DB); diff --git a/src/test/java/com/arangodb/example/graph/BaseGraphTest.java b/src/test/java/com/arangodb/example/graph/BaseGraphTest.java index f74c4ed42..2a7baa2f1 100644 --- a/src/test/java/com/arangodb/example/graph/BaseGraphTest.java +++ b/src/test/java/com/arangodb/example/graph/BaseGraphTest.java @@ -26,7 +26,6 @@ import com.arangodb.DbName; import com.arangodb.entity.EdgeDefinition; import com.arangodb.entity.VertexEntity; -import com.arangodb.mapping.ArangoJack; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; @@ -48,7 +47,7 @@ abstract class BaseGraphTest { @BeforeAll static void init() { if (arangoDB == null) { - arangoDB = new ArangoDB.Builder().serializer(new ArangoJack()).build(); + arangoDB = new ArangoDB.Builder().build(); } if (arangoDB.db(TEST_DB).exists()) arangoDB.db(TEST_DB).drop(); diff --git a/src/test/java/com/arangodb/example/ssl/SslExampleTest.java b/src/test/java/com/arangodb/example/ssl/SslExampleTest.java index a21384bdd..b2b2ed2bb 100644 --- a/src/test/java/com/arangodb/example/ssl/SslExampleTest.java +++ b/src/test/java/com/arangodb/example/ssl/SslExampleTest.java @@ -23,7 +23,6 @@ import com.arangodb.ArangoDB; import com.arangodb.Protocol; import com.arangodb.entity.ArangoDBVersion; -import com.arangodb.mapping.ArangoJack; import org.apache.http.conn.ssl.NoopHostnameVerifier; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.condition.EnabledIfSystemProperty; @@ -57,7 +56,7 @@ class SslExampleTest { @Test void connect() throws Exception { final ArangoDB arangoDB = new ArangoDB.Builder() - .serializer(new ArangoJack()) + .host("localhost", 8529) .password("test") .useSsl(true) @@ -72,7 +71,7 @@ void connect() throws Exception { @Test void noopHostnameVerifier() throws Exception { final ArangoDB arangoDB = new ArangoDB.Builder() - .serializer(new ArangoJack()) + .host("127.0.0.1", 8529) .password("test") .useSsl(true) diff --git a/src/test/java/com/arangodb/internal/HostHandlerTest.java b/src/test/java/com/arangodb/internal/HostHandlerTest.java index 0fcc2bc92..2aeecec55 100644 --- a/src/test/java/com/arangodb/internal/HostHandlerTest.java +++ b/src/test/java/com/arangodb/internal/HostHandlerTest.java @@ -23,7 +23,7 @@ import com.arangodb.ArangoDBException; import com.arangodb.ArangoDBMultipleException; import com.arangodb.internal.net.*; -import com.arangodb.util.InternalSerialization; +import com.arangodb.serde.InternalSerde; import org.junit.jupiter.api.Test; import java.util.List; @@ -73,7 +73,7 @@ public HostSet resolve(final boolean initial, final boolean closeConnections) { } @Override - public void init(ArangoExecutorSync executor, InternalSerialization arangoSerialization) { + public void init(ArangoExecutorSync executor, InternalSerde arangoSerialization) { } @@ -92,7 +92,7 @@ public HostSet resolve(final boolean initial, final boolean closeConnections) { } @Override - public void init(ArangoExecutorSync executor, InternalSerialization arangoSerialization) { + public void init(ArangoExecutorSync executor, InternalSerde arangoSerialization) { } diff --git a/src/test/java/com/arangodb/internal/velocystream/CommunicationTest.java b/src/test/java/com/arangodb/internal/velocystream/CommunicationTest.java index 0778c58ed..c9034cf9c 100644 --- a/src/test/java/com/arangodb/internal/velocystream/CommunicationTest.java +++ b/src/test/java/com/arangodb/internal/velocystream/CommunicationTest.java @@ -23,7 +23,6 @@ import com.arangodb.ArangoDB; import com.arangodb.ArangoDatabase; import com.arangodb.entity.ArangoDBVersion; -import com.arangodb.mapping.ArangoJack; import org.junit.jupiter.api.Test; import java.util.Collection; @@ -42,14 +41,14 @@ class CommunicationTest { @Test void chunkSizeSmall() { - final ArangoDB arangoDB = new ArangoDB.Builder().chunksize(20).serializer(new ArangoJack()).build(); + final ArangoDB arangoDB = new ArangoDB.Builder().chunksize(20).build(); final ArangoDBVersion version = arangoDB.getVersion(); assertThat(version).isNotNull(); } @Test void multiThread() throws Exception { - final ArangoDB arangoDB = new ArangoDB.Builder().serializer(new ArangoJack()).build(); + final ArangoDB arangoDB = new ArangoDB.Builder().build(); arangoDB.getUsers(); // authentication and active-failover connection redirect to master final Collection result = new ConcurrentLinkedQueue<>(); @@ -75,7 +74,7 @@ void multiThread() throws Exception { @Test void multiThreadSameDatabases() throws Exception { - final ArangoDB arangoDB = new ArangoDB.Builder().serializer(new ArangoJack()).build(); + final ArangoDB arangoDB = new ArangoDB.Builder().build(); arangoDB.getUsers(); // authentication and active-failover connection redirect to master final ArangoDatabase db = arangoDB.db(); @@ -98,14 +97,14 @@ void multiThreadSameDatabases() throws Exception { @Test void minOneConnection() { - final ArangoDB arangoDB = new ArangoDB.Builder().maxConnections(0).serializer(new ArangoJack()).build(); + final ArangoDB arangoDB = new ArangoDB.Builder().maxConnections(0).build(); final ArangoDBVersion version = arangoDB.getVersion(); assertThat(version).isNotNull(); } @Test void defaultMaxConnection() { - final ArangoDB arangoDB = new ArangoDB.Builder().maxConnections(null).serializer(new ArangoJack()).build(); + final ArangoDB arangoDB = new ArangoDB.Builder().maxConnections(null).build(); final ArangoDBVersion version = arangoDB.getVersion(); assertThat(version).isNotNull(); } diff --git a/src/test/java/com/arangodb/serde/CustomSerdeTest.java b/src/test/java/com/arangodb/serde/CustomSerdeTest.java index 94812aac4..f00656d43 100644 --- a/src/test/java/com/arangodb/serde/CustomSerdeTest.java +++ b/src/test/java/com/arangodb/serde/CustomSerdeTest.java @@ -26,9 +26,7 @@ import com.arangodb.ArangoDatabase; import com.arangodb.DbName; import com.arangodb.entity.BaseDocument; -import com.arangodb.mapping.ArangoJack; import com.arangodb.model.DocumentCreateOptions; -import com.arangodb.util.ArangoSerialization; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.databind.*; @@ -92,15 +90,15 @@ static class Person { @BeforeAll static void init() { - ArangoJack arangoJack = new ArangoJack(); - arangoJack.configure((mapper) -> { + JacksonSerde serde = JacksonSerde.of(DataType.VPACK); + serde.configure((mapper) -> { mapper.configure(WRITE_SINGLE_ELEM_ARRAYS_UNWRAPPED, true); mapper.configure(USE_BIG_INTEGER_FOR_INTS, true); SimpleModule module = new SimpleModule("PersonModule"); module.addDeserializer(Person.class, new PersonDeserializer()); mapper.registerModule(module); }); - arangoDB = new ArangoDB.Builder().serializer(arangoJack).build(); + arangoDB = new ArangoDB.Builder().serializer(serde).build(); db = arangoDB.db(DbName.of("custom-serde-test")); if (!db.exists()) { @@ -134,7 +132,7 @@ void customPersonDeserializer() { void manualCustomPersonDeserializer() { Person person = new Person(); person.name = "Joe"; - ArangoSerialization serialization = arangoDB.getUserSerialization(); + ArangoSerde serialization = arangoDB.getUserSerde(); byte[] serialized = serialization.serialize(person); Person deserializedPerson = serialization.deserialize(serialized, Person.class); assertThat(deserializedPerson.name).isEqualTo(PERSON_DESERIALIZER_ADDED_PREFIX + PERSON_SERIALIZER_ADDED_PREFIX + person.name); @@ -228,7 +226,7 @@ void getDocument() { @Test void parseNullString() { - final String json = arangoDB.getUserSerialization().deserialize(arangoDB.getUserSerialization().serialize(null), String.class); + final String json = arangoDB.getUserSerde().deserialize(arangoDB.getUserSerde().serialize(null), String.class); assertThat(json).isNull(); } diff --git a/src/test/java/com/arangodb/serde/CustomTypeHintTest.java b/src/test/java/com/arangodb/serde/CustomTypeHintTest.java index 178867aef..d2144e0ee 100644 --- a/src/test/java/com/arangodb/serde/CustomTypeHintTest.java +++ b/src/test/java/com/arangodb/serde/CustomTypeHintTest.java @@ -23,7 +23,6 @@ import com.arangodb.*; import com.arangodb.entity.Key; -import com.arangodb.mapping.ArangoJack; import com.arangodb.model.DocumentCreateOptions; import com.fasterxml.jackson.annotation.JsonTypeInfo; import org.junit.jupiter.api.AfterEach; @@ -87,9 +86,7 @@ public void setAnimal(Animal animal) { @BeforeEach void init() { - ArangoDB arangoDB = new ArangoDB.Builder() - .serializer(new ArangoJack()) - .build(); + ArangoDB arangoDB = new ArangoDB.Builder().build(); db = arangoDB.db(DbName.of("custom-serde-test")); if (!db.exists()) { diff --git a/src/main/java/com/arangodb/util/MapBuilder.java b/src/test/java/com/arangodb/util/MapBuilder.java similarity index 96% rename from src/main/java/com/arangodb/util/MapBuilder.java rename to src/test/java/com/arangodb/util/MapBuilder.java index 955bbe24e..61d05865e 100644 --- a/src/main/java/com/arangodb/util/MapBuilder.java +++ b/src/test/java/com/arangodb/util/MapBuilder.java @@ -1,46 +1,46 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.util; - -import java.util.LinkedHashMap; -import java.util.Map; - -/** - * @author Mark Vollmary - */ -public class MapBuilder { - - private final Map map; - - public MapBuilder() { - super(); - map = new LinkedHashMap<>(); - } - - public MapBuilder put(final String key, final Object value) { - map.put(key, value); - return this; - } - - public Map get() { - return map; - } -} +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed 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. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.util; + +import java.util.LinkedHashMap; +import java.util.Map; + +/** + * @author Mark Vollmary + */ +public class MapBuilder { + + private final Map map; + + public MapBuilder() { + super(); + map = new LinkedHashMap<>(); + } + + public MapBuilder put(final String key, final Object value) { + map.put(key, value); + return this; + } + + public Map get() { + return map; + } +} diff --git a/src/test/java/perf/SimpleSyncPerfTest.java b/src/test/java/perf/SimpleSyncPerfTest.java index e801659ab..2d230779f 100644 --- a/src/test/java/perf/SimpleSyncPerfTest.java +++ b/src/test/java/perf/SimpleSyncPerfTest.java @@ -22,7 +22,6 @@ import com.arangodb.ArangoDB; import com.arangodb.Protocol; -import com.arangodb.mapping.ArangoJack; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.EnumSource; @@ -45,7 +44,7 @@ private void doGetVersion(ArangoDB arangoDB) { @ParameterizedTest @EnumSource(Protocol.class) void getVersion(Protocol protocol) throws InterruptedException { - ArangoDB arangoDB = new ArangoDB.Builder().useProtocol(protocol).serializer(new ArangoJack()).build(); + ArangoDB arangoDB = new ArangoDB.Builder().useProtocol(protocol).build(); // warmup doGetVersion(arangoDB); From ed192e67314a42872e8ad48ee097d4630eb81b64 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Thu, 21 Jul 2022 10:04:47 +0200 Subject: [PATCH 038/254] made data definition classes final --- .../entity/AqlExecutionExplainEntity.java | 14 +++++----- .../arangodb/entity/AqlFunctionEntity.java | 2 +- .../com/arangodb/entity/AqlParseEntity.java | 4 +-- .../com/arangodb/entity/ArangoDBEngine.java | 2 +- .../com/arangodb/entity/ArangoDBVersion.java | 2 +- .../com/arangodb/entity/BaseEdgeDocument.java | 2 +- .../com/arangodb/entity/CollectionEntity.java | 2 +- .../entity/CollectionPropertiesEntity.java | 2 +- .../entity/CollectionRevisionEntity.java | 2 +- .../com/arangodb/entity/CursorEntity.java | 8 +++--- .../com/arangodb/entity/DatabaseEntity.java | 2 +- .../arangodb/entity/DocumentCreateEntity.java | 2 +- .../arangodb/entity/DocumentDeleteEntity.java | 2 +- .../com/arangodb/entity/DocumentEntity.java | 2 +- .../arangodb/entity/DocumentImportEntity.java | 2 +- .../arangodb/entity/DocumentUpdateEntity.java | 2 +- .../com/arangodb/entity/EdgeDefinition.java | 4 +-- .../java/com/arangodb/entity/EdgeEntity.java | 2 +- .../com/arangodb/entity/EdgeUpdateEntity.java | 2 +- src/main/java/com/arangodb/entity/Entity.java | 28 ------------------- .../java/com/arangodb/entity/ErrorEntity.java | 2 +- .../java/com/arangodb/entity/GraphEntity.java | 2 +- .../java/com/arangodb/entity/IndexEntity.java | 2 +- .../java/com/arangodb/entity/KeyOptions.java | 2 +- .../com/arangodb/entity/LogEntriesEntity.java | 4 +-- .../com/arangodb/entity/LogLevelEntity.java | 2 +- .../arangodb/entity/MultiDocumentEntity.java | 2 +- .../entity/QueryCachePropertiesEntity.java | 2 +- .../java/com/arangodb/entity/QueryEntity.java | 2 +- .../entity/QueryTrackingPropertiesEntity.java | 2 +- .../arangodb/entity/ReplicationFactor.java | 2 +- .../java/com/arangodb/entity/ShardEntity.java | 2 +- .../entity/StreamTransactionEntity.java | 2 +- .../arangodb/entity/TransactionEntity.java | 2 +- .../java/com/arangodb/entity/UserEntity.java | 2 +- .../com/arangodb/entity/VertexEntity.java | 2 +- .../arangodb/entity/VertexUpdateEntity.java | 2 +- .../java/com/arangodb/entity/ViewEntity.java | 2 +- .../ArangoSearchPropertiesEntity.java | 2 +- .../entity/arangosearch/CollectionLink.java | 2 +- .../arangosearch/ConsolidationPolicy.java | 2 +- .../entity/arangosearch/FieldLink.java | 2 +- .../entity/arangosearch/PrimarySort.java | 2 +- .../entity/arangosearch/StoredValue.java | 2 +- .../arangosearch/analyzer/AQLAnalyzer.java | 2 +- .../analyzer/AQLAnalyzerProperties.java | 2 +- .../analyzer/CollationAnalyzer.java | 2 +- .../analyzer/CollationAnalyzerProperties.java | 2 +- .../analyzer/DelimiterAnalyzer.java | 2 +- .../analyzer/DelimiterAnalyzerProperties.java | 2 +- .../arangosearch/analyzer/EdgeNgram.java | 2 +- .../analyzer/GeoAnalyzerOptions.java | 2 +- .../analyzer/GeoJSONAnalyzer.java | 2 +- .../analyzer/GeoJSONAnalyzerProperties.java | 2 +- .../analyzer/GeoPointAnalyzer.java | 2 +- .../analyzer/GeoPointAnalyzerProperties.java | 2 +- .../analyzer/IdentityAnalyzer.java | 2 +- .../arangosearch/analyzer/NGramAnalyzer.java | 2 +- .../analyzer/NGramAnalyzerProperties.java | 2 +- .../arangosearch/analyzer/NormAnalyzer.java | 2 +- .../analyzer/NormAnalyzerProperties.java | 2 +- .../analyzer/PipelineAnalyzer.java | 2 +- .../analyzer/PipelineAnalyzerProperties.java | 2 +- .../arangosearch/analyzer/SearchAnalyzer.java | 3 +- .../analyzer/SegmentationAnalyzer.java | 2 +- .../SegmentationAnalyzerProperties.java | 2 +- .../arangosearch/analyzer/StemAnalyzer.java | 2 +- .../analyzer/StemAnalyzerProperties.java | 2 +- .../analyzer/StopwordsAnalyzer.java | 2 +- .../analyzer/StopwordsAnalyzerProperties.java | 2 +- .../arangosearch/analyzer/TextAnalyzer.java | 2 +- .../analyzer/TextAnalyzerProperties.java | 2 +- .../model/AqlFunctionCreateOptions.java | 6 ++-- .../model/AqlFunctionDeleteOptions.java | 2 +- .../arangodb/model/AqlFunctionGetOptions.java | 2 +- .../model/AqlQueryExplainOptions.java | 10 +++---- .../com/arangodb/model/AqlQueryOptions.java | 8 +++--- .../arangodb/model/AqlQueryParseOptions.java | 4 +-- .../model/CollectionCountOptions.java | 2 +- .../model/CollectionCreateOptions.java | 4 +-- .../model/CollectionPropertiesOptions.java | 2 +- .../model/CollectionRenameOptions.java | 4 +-- .../com/arangodb/model/CollectionSchema.java | 2 +- .../model/CollectionTruncateOptions.java | 2 +- .../model/CollectionsReadOptions.java | 2 +- .../com/arangodb/model/DBCreateOptions.java | 2 +- .../com/arangodb/model/DatabaseOptions.java | 2 +- .../arangodb/model/DatabaseUsersOptions.java | 2 +- .../arangodb/model/DocumentCreateOptions.java | 2 +- .../arangodb/model/DocumentDeleteOptions.java | 2 +- .../arangodb/model/DocumentExistsOptions.java | 2 +- .../arangodb/model/DocumentImportOptions.java | 2 +- .../arangodb/model/DocumentReadOptions.java | 2 +- .../model/DocumentReplaceOptions.java | 2 +- .../arangodb/model/DocumentUpdateOptions.java | 2 +- .../com/arangodb/model/EdgeCreateOptions.java | 2 +- .../com/arangodb/model/EdgeDeleteOptions.java | 2 +- .../arangodb/model/EdgeReplaceOptions.java | 2 +- .../com/arangodb/model/EdgeUpdateOptions.java | 2 +- .../arangodb/model/FulltextIndexOptions.java | 6 ++-- .../com/arangodb/model/GeoIndexOptions.java | 6 ++-- .../arangodb/model/GraphCreateOptions.java | 8 +++--- .../model/GraphDocumentReadOptions.java | 2 +- .../com/arangodb/model/HashIndexOptions.java | 6 ++-- .../java/com/arangodb/model/IndexOptions.java | 4 +-- .../java/com/arangodb/model/LogOptions.java | 2 +- .../com/arangodb/model/OptionsBuilder.java | 2 +- .../model/PersistentIndexOptions.java | 6 ++-- .../com/arangodb/model/QueueTimeSample.java | 2 +- .../arangodb/model/SkiplistIndexOptions.java | 6 ++-- .../model/StreamTransactionOptions.java | 2 +- .../model/TransactionCollectionOptions.java | 2 +- .../arangodb/model/TransactionOptions.java | 4 +-- .../com/arangodb/model/TtlIndexOptions.java | 6 ++-- .../com/arangodb/model/UserAccessOptions.java | 4 +-- .../com/arangodb/model/UserCreateOptions.java | 6 ++-- .../com/arangodb/model/UserUpdateOptions.java | 2 +- .../model/VertexCollectionCreateOptions.java | 6 ++-- .../arangodb/model/VertexCreateOptions.java | 2 +- .../arangodb/model/VertexDeleteOptions.java | 2 +- .../arangodb/model/VertexReplaceOptions.java | 2 +- .../arangodb/model/VertexUpdateOptions.java | 2 +- .../com/arangodb/model/ViewCreateOptions.java | 6 ++-- .../com/arangodb/model/ViewRenameOptions.java | 4 +-- .../com/arangodb/model/ZKDIndexOptions.java | 8 +++--- .../arangosearch/AnalyzerDeleteOptions.java | 2 +- .../ArangoSearchCreateOptions.java | 4 +-- .../ArangoSearchPropertiesOptions.java | 2 +- 128 files changed, 180 insertions(+), 209 deletions(-) delete mode 100644 src/main/java/com/arangodb/entity/Entity.java diff --git a/src/main/java/com/arangodb/entity/AqlExecutionExplainEntity.java b/src/main/java/com/arangodb/entity/AqlExecutionExplainEntity.java index b913a267c..c95613764 100644 --- a/src/main/java/com/arangodb/entity/AqlExecutionExplainEntity.java +++ b/src/main/java/com/arangodb/entity/AqlExecutionExplainEntity.java @@ -26,9 +26,9 @@ * @author Mark Vollmary * @see API Documentation */ -public class AqlExecutionExplainEntity implements Entity { +public final class AqlExecutionExplainEntity { - public static class ExecutionPlan { + public static final class ExecutionPlan { private Collection nodes; private Collection rules; private Collection collections; @@ -61,7 +61,7 @@ public Integer getEstimatedNrItems() { } } - public static class ExecutionNode { + public static final class ExecutionNode { private String type; private Collection dependencies; private Long id; @@ -179,7 +179,7 @@ public Boolean getReverse() { } } - public static class ExecutionVariable { + public static final class ExecutionVariable { private Long id; private String name; @@ -192,7 +192,7 @@ public String getName() { } } - public static class ExecutionExpression { + public static final class ExecutionExpression { private String type; private String name; private Long id; @@ -235,7 +235,7 @@ public Collection getSubNodes() { } } - public static class ExecutionCollection { + public static final class ExecutionCollection { private String name; private String type; @@ -248,7 +248,7 @@ public String getType() { } } - public static class ExecutionStats { + public static final class ExecutionStats { private Integer rulesExecuted; private Integer rulesSkipped; private Integer plansCreated; diff --git a/src/main/java/com/arangodb/entity/AqlFunctionEntity.java b/src/main/java/com/arangodb/entity/AqlFunctionEntity.java index 57f5d78c4..cd0d52f5f 100644 --- a/src/main/java/com/arangodb/entity/AqlFunctionEntity.java +++ b/src/main/java/com/arangodb/entity/AqlFunctionEntity.java @@ -26,7 +26,7 @@ * "https://www.arangodb.com/docs/stable/http/aql-user-functions.html#return-registered-aql-user-functions">API * Documentation */ -public class AqlFunctionEntity implements Entity { +public final class AqlFunctionEntity { private String name; private String code; diff --git a/src/main/java/com/arangodb/entity/AqlParseEntity.java b/src/main/java/com/arangodb/entity/AqlParseEntity.java index f5f16e059..9047a23e7 100644 --- a/src/main/java/com/arangodb/entity/AqlParseEntity.java +++ b/src/main/java/com/arangodb/entity/AqlParseEntity.java @@ -26,9 +26,9 @@ * @author Mark Vollmary * @see API Documentation */ -public class AqlParseEntity implements Entity { +public final class AqlParseEntity { - public static class AstNode { + public static final class AstNode { private String type; private Collection subNodes; private String name; diff --git a/src/main/java/com/arangodb/entity/ArangoDBEngine.java b/src/main/java/com/arangodb/entity/ArangoDBEngine.java index 37ea0bfc8..0cd2898d3 100644 --- a/src/main/java/com/arangodb/entity/ArangoDBEngine.java +++ b/src/main/java/com/arangodb/entity/ArangoDBEngine.java @@ -25,7 +25,7 @@ * @see API * Documentation */ -public class ArangoDBEngine implements Entity { +public final class ArangoDBEngine { public enum StorageEngineName { mmfiles, rocksdb diff --git a/src/main/java/com/arangodb/entity/ArangoDBVersion.java b/src/main/java/com/arangodb/entity/ArangoDBVersion.java index db339bd88..878980e32 100644 --- a/src/main/java/com/arangodb/entity/ArangoDBVersion.java +++ b/src/main/java/com/arangodb/entity/ArangoDBVersion.java @@ -25,7 +25,7 @@ * @see API * Documentation */ -public class ArangoDBVersion implements Entity { +public final class ArangoDBVersion { private String server; private String version; diff --git a/src/main/java/com/arangodb/entity/BaseEdgeDocument.java b/src/main/java/com/arangodb/entity/BaseEdgeDocument.java index c76831b0a..9a82420da 100644 --- a/src/main/java/com/arangodb/entity/BaseEdgeDocument.java +++ b/src/main/java/com/arangodb/entity/BaseEdgeDocument.java @@ -27,7 +27,7 @@ /** * @author Mark Vollmary */ -public class BaseEdgeDocument extends BaseDocument { +public final class BaseEdgeDocument extends BaseDocument { private static final long serialVersionUID = 6904923804449368783L; diff --git a/src/main/java/com/arangodb/entity/CollectionEntity.java b/src/main/java/com/arangodb/entity/CollectionEntity.java index 72530c808..6f9fff3aa 100644 --- a/src/main/java/com/arangodb/entity/CollectionEntity.java +++ b/src/main/java/com/arangodb/entity/CollectionEntity.java @@ -26,7 +26,7 @@ * @author Mark Vollmary * @see API Documentation */ -public class CollectionEntity implements Entity { +public class CollectionEntity { private String id; private String name; diff --git a/src/main/java/com/arangodb/entity/CollectionPropertiesEntity.java b/src/main/java/com/arangodb/entity/CollectionPropertiesEntity.java index 050104ffe..9e9388bc3 100644 --- a/src/main/java/com/arangodb/entity/CollectionPropertiesEntity.java +++ b/src/main/java/com/arangodb/entity/CollectionPropertiesEntity.java @@ -27,7 +27,7 @@ * @see API * Documentation */ -public class CollectionPropertiesEntity extends CollectionEntity { +public final class CollectionPropertiesEntity extends CollectionEntity { private KeyOptions keyOptions; private Long count; diff --git a/src/main/java/com/arangodb/entity/CollectionRevisionEntity.java b/src/main/java/com/arangodb/entity/CollectionRevisionEntity.java index d04ec000d..a65db6d7a 100644 --- a/src/main/java/com/arangodb/entity/CollectionRevisionEntity.java +++ b/src/main/java/com/arangodb/entity/CollectionRevisionEntity.java @@ -25,7 +25,7 @@ * @see API * Documentation */ -public class CollectionRevisionEntity extends CollectionEntity { +public final class CollectionRevisionEntity extends CollectionEntity { private String revision; diff --git a/src/main/java/com/arangodb/entity/CursorEntity.java b/src/main/java/com/arangodb/entity/CursorEntity.java index e4aa9f32e..e205a2d79 100644 --- a/src/main/java/com/arangodb/entity/CursorEntity.java +++ b/src/main/java/com/arangodb/entity/CursorEntity.java @@ -31,7 +31,7 @@ * @see API * Documentation */ -public class CursorEntity implements Entity, MetaAware { +public final class CursorEntity implements MetaAware { private String id; private Integer count; @@ -105,7 +105,7 @@ public void setMeta(Map meta) { this.meta = cleanupMeta(meta); } - public static class Warning { + public static final class Warning { private Integer code; private String message; @@ -120,7 +120,7 @@ public String getMessage() { } - public static class Extras { + public static final class Extras { private Stats stats; private Collection warnings = Collections.emptyList(); @@ -134,7 +134,7 @@ public Collection getWarnings() { } - public static class Stats { + public static final class Stats { private Long writesExecuted; private Long writesIgnored; private Long scannedFull; diff --git a/src/main/java/com/arangodb/entity/DatabaseEntity.java b/src/main/java/com/arangodb/entity/DatabaseEntity.java index 524db2c63..3b996d033 100644 --- a/src/main/java/com/arangodb/entity/DatabaseEntity.java +++ b/src/main/java/com/arangodb/entity/DatabaseEntity.java @@ -24,7 +24,7 @@ * @author Mark Vollmary * @see API Documentation */ -public class DatabaseEntity implements Entity { +public final class DatabaseEntity { private String id; private String name; diff --git a/src/main/java/com/arangodb/entity/DocumentCreateEntity.java b/src/main/java/com/arangodb/entity/DocumentCreateEntity.java index 6badc51cd..64c8a53af 100644 --- a/src/main/java/com/arangodb/entity/DocumentCreateEntity.java +++ b/src/main/java/com/arangodb/entity/DocumentCreateEntity.java @@ -25,7 +25,7 @@ * @see API * Documentation */ -public class DocumentCreateEntity extends DocumentEntity { +public final class DocumentCreateEntity extends DocumentEntity { private T newDocument; private T oldDocument; diff --git a/src/main/java/com/arangodb/entity/DocumentDeleteEntity.java b/src/main/java/com/arangodb/entity/DocumentDeleteEntity.java index 2f5a6f098..612494d66 100644 --- a/src/main/java/com/arangodb/entity/DocumentDeleteEntity.java +++ b/src/main/java/com/arangodb/entity/DocumentDeleteEntity.java @@ -25,7 +25,7 @@ * @see API * Documentation */ -public class DocumentDeleteEntity extends DocumentEntity { +public final class DocumentDeleteEntity extends DocumentEntity { private T oldDocument; diff --git a/src/main/java/com/arangodb/entity/DocumentEntity.java b/src/main/java/com/arangodb/entity/DocumentEntity.java index 1b973e32d..fe3ddda5b 100644 --- a/src/main/java/com/arangodb/entity/DocumentEntity.java +++ b/src/main/java/com/arangodb/entity/DocumentEntity.java @@ -23,7 +23,7 @@ /** * @author Mark Vollmary */ -public class DocumentEntity implements Entity { +public class DocumentEntity { @Key private String key; diff --git a/src/main/java/com/arangodb/entity/DocumentImportEntity.java b/src/main/java/com/arangodb/entity/DocumentImportEntity.java index bd57c65fc..b4f6a469f 100644 --- a/src/main/java/com/arangodb/entity/DocumentImportEntity.java +++ b/src/main/java/com/arangodb/entity/DocumentImportEntity.java @@ -26,7 +26,7 @@ /** * @author Mark Vollmary */ -public class DocumentImportEntity implements Entity { +public final class DocumentImportEntity { private Integer created; private Integer errors; diff --git a/src/main/java/com/arangodb/entity/DocumentUpdateEntity.java b/src/main/java/com/arangodb/entity/DocumentUpdateEntity.java index 8393a7988..3567bd10e 100644 --- a/src/main/java/com/arangodb/entity/DocumentUpdateEntity.java +++ b/src/main/java/com/arangodb/entity/DocumentUpdateEntity.java @@ -28,7 +28,7 @@ * @see API * Documentation */ -public class DocumentUpdateEntity extends DocumentEntity { +public final class DocumentUpdateEntity extends DocumentEntity { @JsonProperty("_oldRev") private String oldRev; diff --git a/src/main/java/com/arangodb/entity/EdgeDefinition.java b/src/main/java/com/arangodb/entity/EdgeDefinition.java index 8fc808428..cd39c9a3b 100644 --- a/src/main/java/com/arangodb/entity/EdgeDefinition.java +++ b/src/main/java/com/arangodb/entity/EdgeDefinition.java @@ -28,7 +28,7 @@ * @author Mark Vollmary * @see API Documentation */ -public class EdgeDefinition { +public final class EdgeDefinition { private String collection; private Collection from; @@ -82,7 +82,7 @@ public EdgeDefinition satellites(final String... satellites) { return this; } - public static class Options { + public static final class Options { private Collection satellites = Collections.emptyList(); public Collection getSatellites() { diff --git a/src/main/java/com/arangodb/entity/EdgeEntity.java b/src/main/java/com/arangodb/entity/EdgeEntity.java index c62f7d131..48107a1e1 100644 --- a/src/main/java/com/arangodb/entity/EdgeEntity.java +++ b/src/main/java/com/arangodb/entity/EdgeEntity.java @@ -23,7 +23,7 @@ /** * @author Mark Vollmary */ -public class EdgeEntity extends DocumentEntity { +public final class EdgeEntity extends DocumentEntity { public EdgeEntity() { super(); diff --git a/src/main/java/com/arangodb/entity/EdgeUpdateEntity.java b/src/main/java/com/arangodb/entity/EdgeUpdateEntity.java index ad0a5777f..67b72e76b 100644 --- a/src/main/java/com/arangodb/entity/EdgeUpdateEntity.java +++ b/src/main/java/com/arangodb/entity/EdgeUpdateEntity.java @@ -26,7 +26,7 @@ * @author Mark Vollmary * @see API Documentation */ -public class EdgeUpdateEntity extends DocumentEntity { +public final class EdgeUpdateEntity extends DocumentEntity { @JsonProperty("_oldRev") private String oldRev; diff --git a/src/main/java/com/arangodb/entity/Entity.java b/src/main/java/com/arangodb/entity/Entity.java deleted file mode 100644 index 146e561ae..000000000 --- a/src/main/java/com/arangodb/entity/Entity.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2018 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.entity; - -/** - * @author Mark Vollmary - */ -public interface Entity { - -} diff --git a/src/main/java/com/arangodb/entity/ErrorEntity.java b/src/main/java/com/arangodb/entity/ErrorEntity.java index 48a1c582b..5677d2301 100644 --- a/src/main/java/com/arangodb/entity/ErrorEntity.java +++ b/src/main/java/com/arangodb/entity/ErrorEntity.java @@ -25,7 +25,7 @@ /** * @author Mark Vollmary */ -public class ErrorEntity implements Serializable, Entity { +public final class ErrorEntity implements Serializable { private static final long serialVersionUID = -5918898261563691261L; diff --git a/src/main/java/com/arangodb/entity/GraphEntity.java b/src/main/java/com/arangodb/entity/GraphEntity.java index 858a60acd..07145ee60 100644 --- a/src/main/java/com/arangodb/entity/GraphEntity.java +++ b/src/main/java/com/arangodb/entity/GraphEntity.java @@ -26,7 +26,7 @@ * @author Mark Vollmary * @see API Documentation */ -public class GraphEntity implements Entity { +public final class GraphEntity { private String name; /** diff --git a/src/main/java/com/arangodb/entity/IndexEntity.java b/src/main/java/com/arangodb/entity/IndexEntity.java index b359a5146..a379ed161 100644 --- a/src/main/java/com/arangodb/entity/IndexEntity.java +++ b/src/main/java/com/arangodb/entity/IndexEntity.java @@ -25,7 +25,7 @@ /** * @author Mark Vollmary */ -public class IndexEntity implements Entity { +public final class IndexEntity { private String id; private String name; diff --git a/src/main/java/com/arangodb/entity/KeyOptions.java b/src/main/java/com/arangodb/entity/KeyOptions.java index 261450638..65bd435e5 100644 --- a/src/main/java/com/arangodb/entity/KeyOptions.java +++ b/src/main/java/com/arangodb/entity/KeyOptions.java @@ -23,7 +23,7 @@ /** * @author Mark Vollmary */ -public class KeyOptions { +public final class KeyOptions { private Boolean allowUserKeys; private KeyType type; diff --git a/src/main/java/com/arangodb/entity/LogEntriesEntity.java b/src/main/java/com/arangodb/entity/LogEntriesEntity.java index 43d0954b5..e43d44713 100644 --- a/src/main/java/com/arangodb/entity/LogEntriesEntity.java +++ b/src/main/java/com/arangodb/entity/LogEntriesEntity.java @@ -28,7 +28,7 @@ * Documentation * @since ArangoDB 3.8 */ -public class LogEntriesEntity implements Entity { +public final class LogEntriesEntity { private Long total; private List messages; @@ -41,7 +41,7 @@ public List getMessages() { return messages; } - public static class Message { + public static final class Message { Long id; String topic; String level; diff --git a/src/main/java/com/arangodb/entity/LogLevelEntity.java b/src/main/java/com/arangodb/entity/LogLevelEntity.java index 1801d0cea..a6e9ae702 100644 --- a/src/main/java/com/arangodb/entity/LogLevelEntity.java +++ b/src/main/java/com/arangodb/entity/LogLevelEntity.java @@ -23,7 +23,7 @@ /** * @author Mark Vollmary */ -public class LogLevelEntity implements Entity { +public final class LogLevelEntity { public enum LogLevel { FATAL, ERROR, WARNING, INFO, DEBUG, TRACE, DEFAULT diff --git a/src/main/java/com/arangodb/entity/MultiDocumentEntity.java b/src/main/java/com/arangodb/entity/MultiDocumentEntity.java index bd619c4f9..edf154696 100644 --- a/src/main/java/com/arangodb/entity/MultiDocumentEntity.java +++ b/src/main/java/com/arangodb/entity/MultiDocumentEntity.java @@ -25,7 +25,7 @@ /** * @author Mark Vollmary */ -public class MultiDocumentEntity implements Entity { +public final class MultiDocumentEntity { private Collection documents; private Collection errors; diff --git a/src/main/java/com/arangodb/entity/QueryCachePropertiesEntity.java b/src/main/java/com/arangodb/entity/QueryCachePropertiesEntity.java index d820aa0c9..67000290e 100644 --- a/src/main/java/com/arangodb/entity/QueryCachePropertiesEntity.java +++ b/src/main/java/com/arangodb/entity/QueryCachePropertiesEntity.java @@ -26,7 +26,7 @@ * "https://www.arangodb.com/docs/stable/http/aql-query-cache.html">API * Documentation */ -public class QueryCachePropertiesEntity implements Entity { +public final class QueryCachePropertiesEntity { public enum CacheMode { off, on, demand diff --git a/src/main/java/com/arangodb/entity/QueryEntity.java b/src/main/java/com/arangodb/entity/QueryEntity.java index 2e78b1ed4..04cff2fe0 100644 --- a/src/main/java/com/arangodb/entity/QueryEntity.java +++ b/src/main/java/com/arangodb/entity/QueryEntity.java @@ -26,7 +26,7 @@ /** * @author Mark Vollmary */ -public class QueryEntity implements Entity { +public final class QueryEntity { public static final String PROPERTY_STARTED = "started"; diff --git a/src/main/java/com/arangodb/entity/QueryTrackingPropertiesEntity.java b/src/main/java/com/arangodb/entity/QueryTrackingPropertiesEntity.java index dc82e447d..f8054ec32 100644 --- a/src/main/java/com/arangodb/entity/QueryTrackingPropertiesEntity.java +++ b/src/main/java/com/arangodb/entity/QueryTrackingPropertiesEntity.java @@ -23,7 +23,7 @@ /** * @author Mark Vollmary */ -public class QueryTrackingPropertiesEntity implements Entity { +public final class QueryTrackingPropertiesEntity { private Boolean enabled; private Boolean trackSlowQueries; diff --git a/src/main/java/com/arangodb/entity/ReplicationFactor.java b/src/main/java/com/arangodb/entity/ReplicationFactor.java index 9b84bbf4f..853aad4bb 100644 --- a/src/main/java/com/arangodb/entity/ReplicationFactor.java +++ b/src/main/java/com/arangodb/entity/ReplicationFactor.java @@ -35,7 +35,7 @@ static SatelliteReplicationFactor ofSatellite() { @JsonValue Object getValue(); - class NumericReplicationFactor implements ReplicationFactor { + final class NumericReplicationFactor implements ReplicationFactor { private Integer value; diff --git a/src/main/java/com/arangodb/entity/ShardEntity.java b/src/main/java/com/arangodb/entity/ShardEntity.java index deeb49db3..8b853a623 100644 --- a/src/main/java/com/arangodb/entity/ShardEntity.java +++ b/src/main/java/com/arangodb/entity/ShardEntity.java @@ -23,7 +23,7 @@ /** * @author Michele Rastelli */ -public class ShardEntity implements Entity { +public final class ShardEntity { private String shardId; diff --git a/src/main/java/com/arangodb/entity/StreamTransactionEntity.java b/src/main/java/com/arangodb/entity/StreamTransactionEntity.java index b7fee3817..4dbafa475 100644 --- a/src/main/java/com/arangodb/entity/StreamTransactionEntity.java +++ b/src/main/java/com/arangodb/entity/StreamTransactionEntity.java @@ -26,7 +26,7 @@ * "https://www.arangodb.com/docs/stable/http/transaction-stream-transaction.html">API Documentation * @since ArangoDB 3.5.0 */ -public class StreamTransactionEntity implements Entity { +public final class StreamTransactionEntity { private String id; private StreamTransactionStatus status; diff --git a/src/main/java/com/arangodb/entity/TransactionEntity.java b/src/main/java/com/arangodb/entity/TransactionEntity.java index a517d7882..f9925927d 100644 --- a/src/main/java/com/arangodb/entity/TransactionEntity.java +++ b/src/main/java/com/arangodb/entity/TransactionEntity.java @@ -26,7 +26,7 @@ * "https://www.arangodb.com/docs/stable/http/transaction-stream-transaction.html#list-currently-ongoing-transactions * @since ArangoDB 3.5.0 */ -public class TransactionEntity implements Entity { +public final class TransactionEntity { private String id; private StreamTransactionStatus state; diff --git a/src/main/java/com/arangodb/entity/UserEntity.java b/src/main/java/com/arangodb/entity/UserEntity.java index fa082c5c7..244da2d55 100644 --- a/src/main/java/com/arangodb/entity/UserEntity.java +++ b/src/main/java/com/arangodb/entity/UserEntity.java @@ -26,7 +26,7 @@ * @author Mark Vollmary * @see API Documentation */ -public class UserEntity implements Entity { +public final class UserEntity { private String user; private Boolean active; diff --git a/src/main/java/com/arangodb/entity/VertexEntity.java b/src/main/java/com/arangodb/entity/VertexEntity.java index 161ed9fd4..e8348336a 100644 --- a/src/main/java/com/arangodb/entity/VertexEntity.java +++ b/src/main/java/com/arangodb/entity/VertexEntity.java @@ -23,7 +23,7 @@ /** * @author Mark Vollmary */ -public class VertexEntity extends DocumentEntity { +public final class VertexEntity extends DocumentEntity { public VertexEntity() { super(); diff --git a/src/main/java/com/arangodb/entity/VertexUpdateEntity.java b/src/main/java/com/arangodb/entity/VertexUpdateEntity.java index b5148338f..c5e8f0ff2 100644 --- a/src/main/java/com/arangodb/entity/VertexUpdateEntity.java +++ b/src/main/java/com/arangodb/entity/VertexUpdateEntity.java @@ -25,7 +25,7 @@ /** * @author Mark Vollmary */ -public class VertexUpdateEntity extends DocumentEntity { +public final class VertexUpdateEntity extends DocumentEntity { @JsonProperty("_oldRev") private String oldRev; diff --git a/src/main/java/com/arangodb/entity/ViewEntity.java b/src/main/java/com/arangodb/entity/ViewEntity.java index 07da45f88..e5eb28299 100644 --- a/src/main/java/com/arangodb/entity/ViewEntity.java +++ b/src/main/java/com/arangodb/entity/ViewEntity.java @@ -23,7 +23,7 @@ /** * @author Mark Vollmary */ -public class ViewEntity implements Entity { +public class ViewEntity { private String id; private String name; diff --git a/src/main/java/com/arangodb/entity/arangosearch/ArangoSearchPropertiesEntity.java b/src/main/java/com/arangodb/entity/arangosearch/ArangoSearchPropertiesEntity.java index d33850aac..4c5f3073b 100644 --- a/src/main/java/com/arangodb/entity/arangosearch/ArangoSearchPropertiesEntity.java +++ b/src/main/java/com/arangodb/entity/arangosearch/ArangoSearchPropertiesEntity.java @@ -31,7 +31,7 @@ * @author Michele Rastelli * @see API Documentation */ -public class ArangoSearchPropertiesEntity extends ViewEntity { +public final class ArangoSearchPropertiesEntity extends ViewEntity { private Long consolidationIntervalMsec; private Long commitIntervalMsec; diff --git a/src/main/java/com/arangodb/entity/arangosearch/CollectionLink.java b/src/main/java/com/arangodb/entity/arangosearch/CollectionLink.java index f6a471d14..0e8b3c2d9 100644 --- a/src/main/java/com/arangodb/entity/arangosearch/CollectionLink.java +++ b/src/main/java/com/arangodb/entity/arangosearch/CollectionLink.java @@ -35,7 +35,7 @@ /** * @author Mark Vollmary */ -public class CollectionLink { +public final class CollectionLink { private final String name; private final Collection analyzers; diff --git a/src/main/java/com/arangodb/entity/arangosearch/ConsolidationPolicy.java b/src/main/java/com/arangodb/entity/arangosearch/ConsolidationPolicy.java index b0cb50a0a..63bf7483c 100644 --- a/src/main/java/com/arangodb/entity/arangosearch/ConsolidationPolicy.java +++ b/src/main/java/com/arangodb/entity/arangosearch/ConsolidationPolicy.java @@ -23,7 +23,7 @@ /** * @author Mark Vollmary */ -public class ConsolidationPolicy { +public final class ConsolidationPolicy { private ConsolidationType type; private Double threshold; diff --git a/src/main/java/com/arangodb/entity/arangosearch/FieldLink.java b/src/main/java/com/arangodb/entity/arangosearch/FieldLink.java index e41f6cca7..f4374f52e 100644 --- a/src/main/java/com/arangodb/entity/arangosearch/FieldLink.java +++ b/src/main/java/com/arangodb/entity/arangosearch/FieldLink.java @@ -10,7 +10,7 @@ import java.util.Arrays; import java.util.Collection; -public class FieldLink { +public final class FieldLink { private final String name; private final Collection analyzers; diff --git a/src/main/java/com/arangodb/entity/arangosearch/PrimarySort.java b/src/main/java/com/arangodb/entity/arangosearch/PrimarySort.java index 32c3a34a3..ab0d7c872 100644 --- a/src/main/java/com/arangodb/entity/arangosearch/PrimarySort.java +++ b/src/main/java/com/arangodb/entity/arangosearch/PrimarySort.java @@ -23,7 +23,7 @@ /** * @author Heiko Kernbach */ -public class PrimarySort { +public final class PrimarySort { private final String fieldName; private Boolean ascending; diff --git a/src/main/java/com/arangodb/entity/arangosearch/StoredValue.java b/src/main/java/com/arangodb/entity/arangosearch/StoredValue.java index d6ffb95c9..d44df7a6d 100644 --- a/src/main/java/com/arangodb/entity/arangosearch/StoredValue.java +++ b/src/main/java/com/arangodb/entity/arangosearch/StoredValue.java @@ -31,7 +31,7 @@ * @see API Documentation * @since ArangoDB 3.7 */ -public class StoredValue { +public final class StoredValue { private final List fields; private final ArangoSearchCompression compression; diff --git a/src/main/java/com/arangodb/entity/arangosearch/analyzer/AQLAnalyzer.java b/src/main/java/com/arangodb/entity/arangosearch/analyzer/AQLAnalyzer.java index 2677d0de4..4f453cdf2 100644 --- a/src/main/java/com/arangodb/entity/arangosearch/analyzer/AQLAnalyzer.java +++ b/src/main/java/com/arangodb/entity/arangosearch/analyzer/AQLAnalyzer.java @@ -32,7 +32,7 @@ * @see API Documentation * @since ArangoDB 3.8 */ -public class AQLAnalyzer extends SearchAnalyzer { +public final class AQLAnalyzer extends SearchAnalyzer { public AQLAnalyzer() { setType(AnalyzerType.aql); } diff --git a/src/main/java/com/arangodb/entity/arangosearch/analyzer/AQLAnalyzerProperties.java b/src/main/java/com/arangodb/entity/arangosearch/analyzer/AQLAnalyzerProperties.java index 6118d2c3b..aaa497dd6 100644 --- a/src/main/java/com/arangodb/entity/arangosearch/analyzer/AQLAnalyzerProperties.java +++ b/src/main/java/com/arangodb/entity/arangosearch/analyzer/AQLAnalyzerProperties.java @@ -27,7 +27,7 @@ /** * @author Michele Rastelli */ -public class AQLAnalyzerProperties { +public final class AQLAnalyzerProperties { private String queryString; private Boolean collapsePositions; diff --git a/src/main/java/com/arangodb/entity/arangosearch/analyzer/CollationAnalyzer.java b/src/main/java/com/arangodb/entity/arangosearch/analyzer/CollationAnalyzer.java index e07d820a3..47a588dc0 100644 --- a/src/main/java/com/arangodb/entity/arangosearch/analyzer/CollationAnalyzer.java +++ b/src/main/java/com/arangodb/entity/arangosearch/analyzer/CollationAnalyzer.java @@ -33,7 +33,7 @@ * @see API Documentation * @since ArangoDB 3.9 */ -public class CollationAnalyzer extends SearchAnalyzer { +public final class CollationAnalyzer extends SearchAnalyzer { public CollationAnalyzer() { setType(AnalyzerType.collation); } diff --git a/src/main/java/com/arangodb/entity/arangosearch/analyzer/CollationAnalyzerProperties.java b/src/main/java/com/arangodb/entity/arangosearch/analyzer/CollationAnalyzerProperties.java index d056dbaa2..bbfb0581b 100644 --- a/src/main/java/com/arangodb/entity/arangosearch/analyzer/CollationAnalyzerProperties.java +++ b/src/main/java/com/arangodb/entity/arangosearch/analyzer/CollationAnalyzerProperties.java @@ -27,7 +27,7 @@ * @author Michele Rastelli * @since ArangoDB 3.9 */ -public class CollationAnalyzerProperties { +public final class CollationAnalyzerProperties { private String locale; diff --git a/src/main/java/com/arangodb/entity/arangosearch/analyzer/DelimiterAnalyzer.java b/src/main/java/com/arangodb/entity/arangosearch/analyzer/DelimiterAnalyzer.java index 764096619..78306f0c1 100644 --- a/src/main/java/com/arangodb/entity/arangosearch/analyzer/DelimiterAnalyzer.java +++ b/src/main/java/com/arangodb/entity/arangosearch/analyzer/DelimiterAnalyzer.java @@ -31,7 +31,7 @@ * @author Michele Rastelli * @see API Documentation */ -public class DelimiterAnalyzer extends SearchAnalyzer { +public final class DelimiterAnalyzer extends SearchAnalyzer { public DelimiterAnalyzer() { setType(AnalyzerType.delimiter); } diff --git a/src/main/java/com/arangodb/entity/arangosearch/analyzer/DelimiterAnalyzerProperties.java b/src/main/java/com/arangodb/entity/arangosearch/analyzer/DelimiterAnalyzerProperties.java index c67f05428..21c8ef741 100644 --- a/src/main/java/com/arangodb/entity/arangosearch/analyzer/DelimiterAnalyzerProperties.java +++ b/src/main/java/com/arangodb/entity/arangosearch/analyzer/DelimiterAnalyzerProperties.java @@ -26,7 +26,7 @@ /** * @author Michele Rastelli */ -public class DelimiterAnalyzerProperties { +public final class DelimiterAnalyzerProperties { private String delimiter; diff --git a/src/main/java/com/arangodb/entity/arangosearch/analyzer/EdgeNgram.java b/src/main/java/com/arangodb/entity/arangosearch/analyzer/EdgeNgram.java index 018fc2eac..35c4536da 100644 --- a/src/main/java/com/arangodb/entity/arangosearch/analyzer/EdgeNgram.java +++ b/src/main/java/com/arangodb/entity/arangosearch/analyzer/EdgeNgram.java @@ -26,7 +26,7 @@ /** * @author Michele Rastelli */ -public class EdgeNgram { +public final class EdgeNgram { private long min; private long max; private boolean preserveOriginal; diff --git a/src/main/java/com/arangodb/entity/arangosearch/analyzer/GeoAnalyzerOptions.java b/src/main/java/com/arangodb/entity/arangosearch/analyzer/GeoAnalyzerOptions.java index 5b48d1c69..a6a2f6762 100644 --- a/src/main/java/com/arangodb/entity/arangosearch/analyzer/GeoAnalyzerOptions.java +++ b/src/main/java/com/arangodb/entity/arangosearch/analyzer/GeoAnalyzerOptions.java @@ -27,7 +27,7 @@ /** * @author Michele Rastelli */ -public class GeoAnalyzerOptions { +public final class GeoAnalyzerOptions { private Integer maxCells; private Integer minLevel; diff --git a/src/main/java/com/arangodb/entity/arangosearch/analyzer/GeoJSONAnalyzer.java b/src/main/java/com/arangodb/entity/arangosearch/analyzer/GeoJSONAnalyzer.java index a5005b676..ea8fc9a70 100644 --- a/src/main/java/com/arangodb/entity/arangosearch/analyzer/GeoJSONAnalyzer.java +++ b/src/main/java/com/arangodb/entity/arangosearch/analyzer/GeoJSONAnalyzer.java @@ -33,7 +33,7 @@ * @see API Documentation * @since ArangoDB 3.8 */ -public class GeoJSONAnalyzer extends SearchAnalyzer { +public final class GeoJSONAnalyzer extends SearchAnalyzer { public GeoJSONAnalyzer() { setType(AnalyzerType.geojson); } diff --git a/src/main/java/com/arangodb/entity/arangosearch/analyzer/GeoJSONAnalyzerProperties.java b/src/main/java/com/arangodb/entity/arangosearch/analyzer/GeoJSONAnalyzerProperties.java index 7c2289666..3ef1cfb7f 100644 --- a/src/main/java/com/arangodb/entity/arangosearch/analyzer/GeoJSONAnalyzerProperties.java +++ b/src/main/java/com/arangodb/entity/arangosearch/analyzer/GeoJSONAnalyzerProperties.java @@ -26,7 +26,7 @@ /** * @author Michele Rastelli */ -public class GeoJSONAnalyzerProperties { +public final class GeoJSONAnalyzerProperties { public enum GeoJSONAnalyzerType { diff --git a/src/main/java/com/arangodb/entity/arangosearch/analyzer/GeoPointAnalyzer.java b/src/main/java/com/arangodb/entity/arangosearch/analyzer/GeoPointAnalyzer.java index e4ead1855..af1890582 100644 --- a/src/main/java/com/arangodb/entity/arangosearch/analyzer/GeoPointAnalyzer.java +++ b/src/main/java/com/arangodb/entity/arangosearch/analyzer/GeoPointAnalyzer.java @@ -33,7 +33,7 @@ * @see API Documentation * @since ArangoDB 3.8 */ -public class GeoPointAnalyzer extends SearchAnalyzer { +public final class GeoPointAnalyzer extends SearchAnalyzer { public GeoPointAnalyzer() { setType(AnalyzerType.geopoint); } diff --git a/src/main/java/com/arangodb/entity/arangosearch/analyzer/GeoPointAnalyzerProperties.java b/src/main/java/com/arangodb/entity/arangosearch/analyzer/GeoPointAnalyzerProperties.java index f90953421..a0c148216 100644 --- a/src/main/java/com/arangodb/entity/arangosearch/analyzer/GeoPointAnalyzerProperties.java +++ b/src/main/java/com/arangodb/entity/arangosearch/analyzer/GeoPointAnalyzerProperties.java @@ -27,7 +27,7 @@ /** * @author Michele Rastelli */ -public class GeoPointAnalyzerProperties { +public final class GeoPointAnalyzerProperties { private String[] latitude; private String[] longitude; diff --git a/src/main/java/com/arangodb/entity/arangosearch/analyzer/IdentityAnalyzer.java b/src/main/java/com/arangodb/entity/arangosearch/analyzer/IdentityAnalyzer.java index ad096e669..e658ea327 100644 --- a/src/main/java/com/arangodb/entity/arangosearch/analyzer/IdentityAnalyzer.java +++ b/src/main/java/com/arangodb/entity/arangosearch/analyzer/IdentityAnalyzer.java @@ -29,7 +29,7 @@ * @author Michele Rastelli * @see API Documentation */ -public class IdentityAnalyzer extends SearchAnalyzer { +public final class IdentityAnalyzer extends SearchAnalyzer { public IdentityAnalyzer() { setType(AnalyzerType.identity); } diff --git a/src/main/java/com/arangodb/entity/arangosearch/analyzer/NGramAnalyzer.java b/src/main/java/com/arangodb/entity/arangosearch/analyzer/NGramAnalyzer.java index 7e76429fd..83125fa0f 100644 --- a/src/main/java/com/arangodb/entity/arangosearch/analyzer/NGramAnalyzer.java +++ b/src/main/java/com/arangodb/entity/arangosearch/analyzer/NGramAnalyzer.java @@ -36,7 +36,7 @@ * @author Michele Rastelli * @see API Documentation */ -public class NGramAnalyzer extends SearchAnalyzer { +public final class NGramAnalyzer extends SearchAnalyzer { public NGramAnalyzer() { setType(AnalyzerType.ngram); } diff --git a/src/main/java/com/arangodb/entity/arangosearch/analyzer/NGramAnalyzerProperties.java b/src/main/java/com/arangodb/entity/arangosearch/analyzer/NGramAnalyzerProperties.java index 534c38916..90b577225 100644 --- a/src/main/java/com/arangodb/entity/arangosearch/analyzer/NGramAnalyzerProperties.java +++ b/src/main/java/com/arangodb/entity/arangosearch/analyzer/NGramAnalyzerProperties.java @@ -34,7 +34,7 @@ * @author Michele Rastelli * @see API Documentation */ -public class NGramAnalyzerProperties { +public final class NGramAnalyzerProperties { private long min; private long max; diff --git a/src/main/java/com/arangodb/entity/arangosearch/analyzer/NormAnalyzer.java b/src/main/java/com/arangodb/entity/arangosearch/analyzer/NormAnalyzer.java index 4673ccb1b..43ac0a335 100644 --- a/src/main/java/com/arangodb/entity/arangosearch/analyzer/NormAnalyzer.java +++ b/src/main/java/com/arangodb/entity/arangosearch/analyzer/NormAnalyzer.java @@ -31,7 +31,7 @@ * @author Michele Rastelli * @see API Documentation */ -public class NormAnalyzer extends SearchAnalyzer { +public final class NormAnalyzer extends SearchAnalyzer { public NormAnalyzer() { setType(AnalyzerType.norm); } diff --git a/src/main/java/com/arangodb/entity/arangosearch/analyzer/NormAnalyzerProperties.java b/src/main/java/com/arangodb/entity/arangosearch/analyzer/NormAnalyzerProperties.java index 92633f419..72258ea83 100644 --- a/src/main/java/com/arangodb/entity/arangosearch/analyzer/NormAnalyzerProperties.java +++ b/src/main/java/com/arangodb/entity/arangosearch/analyzer/NormAnalyzerProperties.java @@ -28,7 +28,7 @@ /** * @author Michele Rastelli */ -public class NormAnalyzerProperties { +public final class NormAnalyzerProperties { private String locale; diff --git a/src/main/java/com/arangodb/entity/arangosearch/analyzer/PipelineAnalyzer.java b/src/main/java/com/arangodb/entity/arangosearch/analyzer/PipelineAnalyzer.java index 6616d3845..9319f38e6 100644 --- a/src/main/java/com/arangodb/entity/arangosearch/analyzer/PipelineAnalyzer.java +++ b/src/main/java/com/arangodb/entity/arangosearch/analyzer/PipelineAnalyzer.java @@ -36,7 +36,7 @@ * @see API Documentation * @since ArangoDB 3.8 */ -public class PipelineAnalyzer extends SearchAnalyzer { +public final class PipelineAnalyzer extends SearchAnalyzer { public PipelineAnalyzer() { setType(AnalyzerType.pipeline); diff --git a/src/main/java/com/arangodb/entity/arangosearch/analyzer/PipelineAnalyzerProperties.java b/src/main/java/com/arangodb/entity/arangosearch/analyzer/PipelineAnalyzerProperties.java index 5cc686d9f..bdcf4a91d 100644 --- a/src/main/java/com/arangodb/entity/arangosearch/analyzer/PipelineAnalyzerProperties.java +++ b/src/main/java/com/arangodb/entity/arangosearch/analyzer/PipelineAnalyzerProperties.java @@ -28,7 +28,7 @@ /** * @author Michele Rastelli */ -public class PipelineAnalyzerProperties { +public final class PipelineAnalyzerProperties { private List pipeline = new LinkedList<>(); /** diff --git a/src/main/java/com/arangodb/entity/arangosearch/analyzer/SearchAnalyzer.java b/src/main/java/com/arangodb/entity/arangosearch/analyzer/SearchAnalyzer.java index d826b50d3..8963a365f 100644 --- a/src/main/java/com/arangodb/entity/arangosearch/analyzer/SearchAnalyzer.java +++ b/src/main/java/com/arangodb/entity/arangosearch/analyzer/SearchAnalyzer.java @@ -21,7 +21,6 @@ package com.arangodb.entity.arangosearch.analyzer; -import com.arangodb.entity.Entity; import com.arangodb.entity.arangosearch.AnalyzerFeature; import com.arangodb.entity.arangosearch.AnalyzerType; import com.fasterxml.jackson.annotation.JsonIgnore; @@ -52,7 +51,7 @@ @JsonSubTypes.Type(name = "segmentation", value = SegmentationAnalyzer.class), @JsonSubTypes.Type(name = "collation", value = CollationAnalyzer.class) }) -public abstract class SearchAnalyzer implements Entity { +public abstract class SearchAnalyzer { private String name; private AnalyzerType type; private Collection features; diff --git a/src/main/java/com/arangodb/entity/arangosearch/analyzer/SegmentationAnalyzer.java b/src/main/java/com/arangodb/entity/arangosearch/analyzer/SegmentationAnalyzer.java index 70ce2f4cf..6b2f449b3 100644 --- a/src/main/java/com/arangodb/entity/arangosearch/analyzer/SegmentationAnalyzer.java +++ b/src/main/java/com/arangodb/entity/arangosearch/analyzer/SegmentationAnalyzer.java @@ -35,7 +35,7 @@ * @see API Documentation * @since ArangoDB 3.9 */ -public class SegmentationAnalyzer extends SearchAnalyzer { +public final class SegmentationAnalyzer extends SearchAnalyzer { public SegmentationAnalyzer() { setType(AnalyzerType.segmentation); } diff --git a/src/main/java/com/arangodb/entity/arangosearch/analyzer/SegmentationAnalyzerProperties.java b/src/main/java/com/arangodb/entity/arangosearch/analyzer/SegmentationAnalyzerProperties.java index 7c6ea73c4..a98b39b76 100644 --- a/src/main/java/com/arangodb/entity/arangosearch/analyzer/SegmentationAnalyzerProperties.java +++ b/src/main/java/com/arangodb/entity/arangosearch/analyzer/SegmentationAnalyzerProperties.java @@ -29,7 +29,7 @@ * @author Michele Rastelli * @since ArangoDB 3.9 */ -public class SegmentationAnalyzerProperties { +public final class SegmentationAnalyzerProperties { @JsonProperty("break") private BreakMode breakMode; diff --git a/src/main/java/com/arangodb/entity/arangosearch/analyzer/StemAnalyzer.java b/src/main/java/com/arangodb/entity/arangosearch/analyzer/StemAnalyzer.java index 6e3166c64..0e4fb9cb0 100644 --- a/src/main/java/com/arangodb/entity/arangosearch/analyzer/StemAnalyzer.java +++ b/src/main/java/com/arangodb/entity/arangosearch/analyzer/StemAnalyzer.java @@ -31,7 +31,7 @@ * @author Michele Rastelli * @see API Documentation */ -public class StemAnalyzer extends SearchAnalyzer { +public final class StemAnalyzer extends SearchAnalyzer { public StemAnalyzer() { setType(AnalyzerType.stem); } diff --git a/src/main/java/com/arangodb/entity/arangosearch/analyzer/StemAnalyzerProperties.java b/src/main/java/com/arangodb/entity/arangosearch/analyzer/StemAnalyzerProperties.java index b58634f6a..600ffa5a1 100644 --- a/src/main/java/com/arangodb/entity/arangosearch/analyzer/StemAnalyzerProperties.java +++ b/src/main/java/com/arangodb/entity/arangosearch/analyzer/StemAnalyzerProperties.java @@ -26,7 +26,7 @@ /** * @author Michele Rastelli */ -public class StemAnalyzerProperties { +public final class StemAnalyzerProperties { private String locale; diff --git a/src/main/java/com/arangodb/entity/arangosearch/analyzer/StopwordsAnalyzer.java b/src/main/java/com/arangodb/entity/arangosearch/analyzer/StopwordsAnalyzer.java index 264b48d54..c1041e293 100644 --- a/src/main/java/com/arangodb/entity/arangosearch/analyzer/StopwordsAnalyzer.java +++ b/src/main/java/com/arangodb/entity/arangosearch/analyzer/StopwordsAnalyzer.java @@ -32,7 +32,7 @@ * @see API Documentation * @since ArangoDB 3.8 */ -public class StopwordsAnalyzer extends SearchAnalyzer { +public final class StopwordsAnalyzer extends SearchAnalyzer { public StopwordsAnalyzer() { setType(AnalyzerType.stopwords); } diff --git a/src/main/java/com/arangodb/entity/arangosearch/analyzer/StopwordsAnalyzerProperties.java b/src/main/java/com/arangodb/entity/arangosearch/analyzer/StopwordsAnalyzerProperties.java index d00809337..b6f570267 100644 --- a/src/main/java/com/arangodb/entity/arangosearch/analyzer/StopwordsAnalyzerProperties.java +++ b/src/main/java/com/arangodb/entity/arangosearch/analyzer/StopwordsAnalyzerProperties.java @@ -31,7 +31,7 @@ /** * @author Michele Rastelli */ -public class StopwordsAnalyzerProperties { +public final class StopwordsAnalyzerProperties { private static String stringToHex(String str) { final StringBuilder hex = new StringBuilder(); diff --git a/src/main/java/com/arangodb/entity/arangosearch/analyzer/TextAnalyzer.java b/src/main/java/com/arangodb/entity/arangosearch/analyzer/TextAnalyzer.java index edc70b858..8bde16668 100644 --- a/src/main/java/com/arangodb/entity/arangosearch/analyzer/TextAnalyzer.java +++ b/src/main/java/com/arangodb/entity/arangosearch/analyzer/TextAnalyzer.java @@ -32,7 +32,7 @@ * @author Michele Rastelli * @see API Documentation */ -public class TextAnalyzer extends SearchAnalyzer { +public final class TextAnalyzer extends SearchAnalyzer { public TextAnalyzer() { setType(AnalyzerType.text); } diff --git a/src/main/java/com/arangodb/entity/arangosearch/analyzer/TextAnalyzerProperties.java b/src/main/java/com/arangodb/entity/arangosearch/analyzer/TextAnalyzerProperties.java index 566fe8a99..38cbebe89 100644 --- a/src/main/java/com/arangodb/entity/arangosearch/analyzer/TextAnalyzerProperties.java +++ b/src/main/java/com/arangodb/entity/arangosearch/analyzer/TextAnalyzerProperties.java @@ -30,7 +30,7 @@ /** * @author Michele Rastelli */ -public class TextAnalyzerProperties { +public final class TextAnalyzerProperties { public TextAnalyzerProperties() { stopwords = Collections.emptyList(); diff --git a/src/main/java/com/arangodb/model/AqlFunctionCreateOptions.java b/src/main/java/com/arangodb/model/AqlFunctionCreateOptions.java index d9c578804..ebd50373e 100644 --- a/src/main/java/com/arangodb/model/AqlFunctionCreateOptions.java +++ b/src/main/java/com/arangodb/model/AqlFunctionCreateOptions.java @@ -25,7 +25,7 @@ * @see API * Documentation */ -public class AqlFunctionCreateOptions { +public final class AqlFunctionCreateOptions { private String name; private String code; @@ -39,7 +39,7 @@ public AqlFunctionCreateOptions() { * @param name the fully qualified name of the user functions * @return options */ - protected AqlFunctionCreateOptions name(final String name) { + AqlFunctionCreateOptions name(final String name) { this.name = name; return this; } @@ -52,7 +52,7 @@ public String getName() { * @param code a string representation of the function body * @return options */ - protected AqlFunctionCreateOptions code(final String code) { + AqlFunctionCreateOptions code(final String code) { this.code = code; return this; } diff --git a/src/main/java/com/arangodb/model/AqlFunctionDeleteOptions.java b/src/main/java/com/arangodb/model/AqlFunctionDeleteOptions.java index dd3cd2901..f821c7e78 100644 --- a/src/main/java/com/arangodb/model/AqlFunctionDeleteOptions.java +++ b/src/main/java/com/arangodb/model/AqlFunctionDeleteOptions.java @@ -26,7 +26,7 @@ * "https://www.arangodb.com/docs/stable/http/aql-user-functions.html#remove-existing-aql-user-function">API * Documentation */ -public class AqlFunctionDeleteOptions { +public final class AqlFunctionDeleteOptions { private Boolean group; diff --git a/src/main/java/com/arangodb/model/AqlFunctionGetOptions.java b/src/main/java/com/arangodb/model/AqlFunctionGetOptions.java index 2b4713ddb..e5c5dcd95 100644 --- a/src/main/java/com/arangodb/model/AqlFunctionGetOptions.java +++ b/src/main/java/com/arangodb/model/AqlFunctionGetOptions.java @@ -26,7 +26,7 @@ * "https://www.arangodb.com/docs/stable/http/aql-user-functions.html#return-registered-aql-user-functions">API * Documentation */ -public class AqlFunctionGetOptions { +public final class AqlFunctionGetOptions { private String namespace; diff --git a/src/main/java/com/arangodb/model/AqlQueryExplainOptions.java b/src/main/java/com/arangodb/model/AqlQueryExplainOptions.java index 91e59d9a8..45cb189a6 100644 --- a/src/main/java/com/arangodb/model/AqlQueryExplainOptions.java +++ b/src/main/java/com/arangodb/model/AqlQueryExplainOptions.java @@ -30,7 +30,7 @@ * @author Michele Rastelli * @see API Documentation */ -public class AqlQueryExplainOptions { +public final class AqlQueryExplainOptions { private byte[] bindVars; private String query; @@ -49,7 +49,7 @@ public byte[] getBindVars() { * @param bindVars key/value pairs representing the bind parameters * @return options */ - protected AqlQueryExplainOptions bindVars(final byte[] bindVars) { + AqlQueryExplainOptions bindVars(final byte[] bindVars) { this.bindVars = bindVars; return this; } @@ -62,7 +62,7 @@ public String getQuery() { * @param query the query which you want explained * @return options */ - protected AqlQueryExplainOptions query(final String query) { + AqlQueryExplainOptions query(final String query) { this.query = query; return this; } @@ -116,7 +116,7 @@ private Options getOptions() { return options; } - public static class Options { + public static final class Options { private Optimizer optimizer; private Integer maxNumberOfPlans; private Boolean allPlans; @@ -129,7 +129,7 @@ public Optimizer getOptimizer() { } } - public static class Optimizer { + public static final class Optimizer { private Collection rules; } } diff --git a/src/main/java/com/arangodb/model/AqlQueryOptions.java b/src/main/java/com/arangodb/model/AqlQueryOptions.java index 75e43d189..7d646b700 100644 --- a/src/main/java/com/arangodb/model/AqlQueryOptions.java +++ b/src/main/java/com/arangodb/model/AqlQueryOptions.java @@ -33,7 +33,7 @@ * @see API * Documentation */ -public class AqlQueryOptions { +public final class AqlQueryOptions { private Boolean count; private Integer ttl; @@ -156,7 +156,7 @@ public byte[] getBindVars() { * @param bindVarsBytes serialized bind parameters * @return options */ - protected AqlQueryOptions bindVars(final byte[] bindVarsBytes) { + AqlQueryOptions bindVars(final byte[] bindVarsBytes) { this.bindVars = bindVarsBytes; return this; } @@ -406,7 +406,7 @@ public Options getOptions() { return options; } - public static class Options { + public static final class Options { private Boolean failOnWarning; private Boolean profile; @@ -492,7 +492,7 @@ public Collection getShardIds() { } - public static class Optimizer { + public static final class Optimizer { private Collection rules; public Collection getRules() { diff --git a/src/main/java/com/arangodb/model/AqlQueryParseOptions.java b/src/main/java/com/arangodb/model/AqlQueryParseOptions.java index 2059415e2..a5a4b22b1 100644 --- a/src/main/java/com/arangodb/model/AqlQueryParseOptions.java +++ b/src/main/java/com/arangodb/model/AqlQueryParseOptions.java @@ -24,7 +24,7 @@ * @author Mark Vollmary * @see API Documentation */ -public class AqlQueryParseOptions { +public final class AqlQueryParseOptions { private String query; @@ -40,7 +40,7 @@ public String getQuery() { * @param query the query which you want parse * @return options */ - protected AqlQueryParseOptions query(final String query) { + AqlQueryParseOptions query(final String query) { this.query = query; return this; } diff --git a/src/main/java/com/arangodb/model/CollectionCountOptions.java b/src/main/java/com/arangodb/model/CollectionCountOptions.java index 6030f1db8..edfc64eaa 100644 --- a/src/main/java/com/arangodb/model/CollectionCountOptions.java +++ b/src/main/java/com/arangodb/model/CollectionCountOptions.java @@ -23,7 +23,7 @@ /** * @author Michele Rastelli */ -public class CollectionCountOptions { +public final class CollectionCountOptions { private String streamTransactionId; diff --git a/src/main/java/com/arangodb/model/CollectionCreateOptions.java b/src/main/java/com/arangodb/model/CollectionCreateOptions.java index b3433a3d4..4acf37754 100644 --- a/src/main/java/com/arangodb/model/CollectionCreateOptions.java +++ b/src/main/java/com/arangodb/model/CollectionCreateOptions.java @@ -30,7 +30,7 @@ * @see API * Documentation */ -public class CollectionCreateOptions { +public final class CollectionCreateOptions { private String name; private ReplicationFactor replicationFactor; @@ -60,7 +60,7 @@ public String getName() { * @param name The name of the collection * @return options */ - protected CollectionCreateOptions name(final String name) { + CollectionCreateOptions name(final String name) { this.name = name; return this; } diff --git a/src/main/java/com/arangodb/model/CollectionPropertiesOptions.java b/src/main/java/com/arangodb/model/CollectionPropertiesOptions.java index d4ca9ac8e..c10909e65 100644 --- a/src/main/java/com/arangodb/model/CollectionPropertiesOptions.java +++ b/src/main/java/com/arangodb/model/CollectionPropertiesOptions.java @@ -25,7 +25,7 @@ * @see API * Documentation */ -public class CollectionPropertiesOptions { +public final class CollectionPropertiesOptions { private Boolean waitForSync; private CollectionSchema schema; diff --git a/src/main/java/com/arangodb/model/CollectionRenameOptions.java b/src/main/java/com/arangodb/model/CollectionRenameOptions.java index 1c7896c79..11f531e28 100644 --- a/src/main/java/com/arangodb/model/CollectionRenameOptions.java +++ b/src/main/java/com/arangodb/model/CollectionRenameOptions.java @@ -23,7 +23,7 @@ /** * @author Mark Vollmary */ -public class CollectionRenameOptions { +public final class CollectionRenameOptions { private String name; @@ -39,7 +39,7 @@ public String getName() { * @param name The new name * @return options */ - protected CollectionRenameOptions name(final String name) { + CollectionRenameOptions name(final String name) { this.name = name; return this; } diff --git a/src/main/java/com/arangodb/model/CollectionSchema.java b/src/main/java/com/arangodb/model/CollectionSchema.java index 395538c12..231d19616 100644 --- a/src/main/java/com/arangodb/model/CollectionSchema.java +++ b/src/main/java/com/arangodb/model/CollectionSchema.java @@ -33,7 +33,7 @@ * @see API Documentation * @since ArangoDB 3.7 */ -public class CollectionSchema { +public final class CollectionSchema { /** * Value to unset the collection schema on properties update {@link com.arangodb.ArangoCollection#changeProperties(CollectionPropertiesOptions)}. diff --git a/src/main/java/com/arangodb/model/CollectionTruncateOptions.java b/src/main/java/com/arangodb/model/CollectionTruncateOptions.java index dff681273..1b089533e 100644 --- a/src/main/java/com/arangodb/model/CollectionTruncateOptions.java +++ b/src/main/java/com/arangodb/model/CollectionTruncateOptions.java @@ -23,7 +23,7 @@ /** * @author Michele Rastelli */ -public class CollectionTruncateOptions { +public final class CollectionTruncateOptions { private String streamTransactionId; diff --git a/src/main/java/com/arangodb/model/CollectionsReadOptions.java b/src/main/java/com/arangodb/model/CollectionsReadOptions.java index cea7750d0..18f3ce42c 100644 --- a/src/main/java/com/arangodb/model/CollectionsReadOptions.java +++ b/src/main/java/com/arangodb/model/CollectionsReadOptions.java @@ -25,7 +25,7 @@ * @see API * Documentation */ -public class CollectionsReadOptions { +public final class CollectionsReadOptions { private Boolean excludeSystem; diff --git a/src/main/java/com/arangodb/model/DBCreateOptions.java b/src/main/java/com/arangodb/model/DBCreateOptions.java index 1c9d6ed07..9b018c3fa 100644 --- a/src/main/java/com/arangodb/model/DBCreateOptions.java +++ b/src/main/java/com/arangodb/model/DBCreateOptions.java @@ -27,7 +27,7 @@ /** * @author Mark Vollmary */ -public class DBCreateOptions { +public final class DBCreateOptions { private Collection users; private String name; diff --git a/src/main/java/com/arangodb/model/DatabaseOptions.java b/src/main/java/com/arangodb/model/DatabaseOptions.java index df5cca03b..68cfd83d0 100644 --- a/src/main/java/com/arangodb/model/DatabaseOptions.java +++ b/src/main/java/com/arangodb/model/DatabaseOptions.java @@ -26,7 +26,7 @@ * @author Michele Rastelli * @since ArangoDB 3.6.0 */ -public class DatabaseOptions { +public final class DatabaseOptions { private ReplicationFactor replicationFactor; private Integer writeConcern; diff --git a/src/main/java/com/arangodb/model/DatabaseUsersOptions.java b/src/main/java/com/arangodb/model/DatabaseUsersOptions.java index edc9175da..63d11e6c8 100644 --- a/src/main/java/com/arangodb/model/DatabaseUsersOptions.java +++ b/src/main/java/com/arangodb/model/DatabaseUsersOptions.java @@ -25,7 +25,7 @@ /** * @author Michele Rastelli */ -public class DatabaseUsersOptions { +public final class DatabaseUsersOptions { private String username; private Map extra; diff --git a/src/main/java/com/arangodb/model/DocumentCreateOptions.java b/src/main/java/com/arangodb/model/DocumentCreateOptions.java index 057a382e7..8d796966a 100644 --- a/src/main/java/com/arangodb/model/DocumentCreateOptions.java +++ b/src/main/java/com/arangodb/model/DocumentCreateOptions.java @@ -26,7 +26,7 @@ * @see API * Documentation */ -public class DocumentCreateOptions { +public final class DocumentCreateOptions { private Boolean waitForSync; private Boolean returnNew; diff --git a/src/main/java/com/arangodb/model/DocumentDeleteOptions.java b/src/main/java/com/arangodb/model/DocumentDeleteOptions.java index e0e566952..ba59aaf5e 100644 --- a/src/main/java/com/arangodb/model/DocumentDeleteOptions.java +++ b/src/main/java/com/arangodb/model/DocumentDeleteOptions.java @@ -26,7 +26,7 @@ * @see API * Documentation */ -public class DocumentDeleteOptions { +public final class DocumentDeleteOptions { private Boolean waitForSync; private String ifMatch; diff --git a/src/main/java/com/arangodb/model/DocumentExistsOptions.java b/src/main/java/com/arangodb/model/DocumentExistsOptions.java index a790bf201..ec2a47c45 100644 --- a/src/main/java/com/arangodb/model/DocumentExistsOptions.java +++ b/src/main/java/com/arangodb/model/DocumentExistsOptions.java @@ -26,7 +26,7 @@ * @see API * Documentation */ -public class DocumentExistsOptions { +public final class DocumentExistsOptions { private String ifNoneMatch; private String ifMatch; diff --git a/src/main/java/com/arangodb/model/DocumentImportOptions.java b/src/main/java/com/arangodb/model/DocumentImportOptions.java index b8a55e3ed..4cd40b71b 100644 --- a/src/main/java/com/arangodb/model/DocumentImportOptions.java +++ b/src/main/java/com/arangodb/model/DocumentImportOptions.java @@ -23,7 +23,7 @@ /** * @author Mark Vollmary */ -public class DocumentImportOptions { +public final class DocumentImportOptions { public enum OnDuplicate { error, update, replace, ignore diff --git a/src/main/java/com/arangodb/model/DocumentReadOptions.java b/src/main/java/com/arangodb/model/DocumentReadOptions.java index 2ad9d4dfa..1041b786c 100644 --- a/src/main/java/com/arangodb/model/DocumentReadOptions.java +++ b/src/main/java/com/arangodb/model/DocumentReadOptions.java @@ -26,7 +26,7 @@ * @see API * Documentation */ -public class DocumentReadOptions { +public final class DocumentReadOptions { private String ifNoneMatch; private String ifMatch; diff --git a/src/main/java/com/arangodb/model/DocumentReplaceOptions.java b/src/main/java/com/arangodb/model/DocumentReplaceOptions.java index 2646f847d..d32fb56c5 100644 --- a/src/main/java/com/arangodb/model/DocumentReplaceOptions.java +++ b/src/main/java/com/arangodb/model/DocumentReplaceOptions.java @@ -26,7 +26,7 @@ * @see API * Documentation */ -public class DocumentReplaceOptions { +public final class DocumentReplaceOptions { private Boolean waitForSync; private Boolean ignoreRevs; diff --git a/src/main/java/com/arangodb/model/DocumentUpdateOptions.java b/src/main/java/com/arangodb/model/DocumentUpdateOptions.java index 4ca261670..c1d74b837 100644 --- a/src/main/java/com/arangodb/model/DocumentUpdateOptions.java +++ b/src/main/java/com/arangodb/model/DocumentUpdateOptions.java @@ -26,7 +26,7 @@ * @see API * Documentation */ -public class DocumentUpdateOptions { +public final class DocumentUpdateOptions { private Boolean keepNull; private Boolean mergeObjects; diff --git a/src/main/java/com/arangodb/model/EdgeCreateOptions.java b/src/main/java/com/arangodb/model/EdgeCreateOptions.java index 3f335cfb1..7e340bc25 100644 --- a/src/main/java/com/arangodb/model/EdgeCreateOptions.java +++ b/src/main/java/com/arangodb/model/EdgeCreateOptions.java @@ -24,7 +24,7 @@ * @author Mark Vollmary * @see API Documentation */ -public class EdgeCreateOptions { +public final class EdgeCreateOptions { private Boolean waitForSync; private String streamTransactionId; diff --git a/src/main/java/com/arangodb/model/EdgeDeleteOptions.java b/src/main/java/com/arangodb/model/EdgeDeleteOptions.java index 30d13c117..a82d68ec1 100644 --- a/src/main/java/com/arangodb/model/EdgeDeleteOptions.java +++ b/src/main/java/com/arangodb/model/EdgeDeleteOptions.java @@ -24,7 +24,7 @@ * @author Mark Vollmary * @see API Documentation */ -public class EdgeDeleteOptions { +public final class EdgeDeleteOptions { private Boolean waitForSync; private String ifMatch; diff --git a/src/main/java/com/arangodb/model/EdgeReplaceOptions.java b/src/main/java/com/arangodb/model/EdgeReplaceOptions.java index 81f021ea0..e30b64ffc 100644 --- a/src/main/java/com/arangodb/model/EdgeReplaceOptions.java +++ b/src/main/java/com/arangodb/model/EdgeReplaceOptions.java @@ -24,7 +24,7 @@ * @author Mark Vollmary * @see API Documentation */ -public class EdgeReplaceOptions { +public final class EdgeReplaceOptions { private Boolean waitForSync; private String ifMatch; diff --git a/src/main/java/com/arangodb/model/EdgeUpdateOptions.java b/src/main/java/com/arangodb/model/EdgeUpdateOptions.java index cb95ddd85..2ff7611fe 100644 --- a/src/main/java/com/arangodb/model/EdgeUpdateOptions.java +++ b/src/main/java/com/arangodb/model/EdgeUpdateOptions.java @@ -24,7 +24,7 @@ * @author Mark Vollmary * @see API Documentation */ -public class EdgeUpdateOptions { +public final class EdgeUpdateOptions { private Boolean keepNull; private Boolean waitForSync; diff --git a/src/main/java/com/arangodb/model/FulltextIndexOptions.java b/src/main/java/com/arangodb/model/FulltextIndexOptions.java index 607e1b908..89bb478e3 100644 --- a/src/main/java/com/arangodb/model/FulltextIndexOptions.java +++ b/src/main/java/com/arangodb/model/FulltextIndexOptions.java @@ -27,7 +27,7 @@ * @see API * Documentation */ -public class FulltextIndexOptions extends IndexOptions { +public final class FulltextIndexOptions extends IndexOptions { private Iterable fields; private final IndexType type = IndexType.fulltext; @@ -38,7 +38,7 @@ public FulltextIndexOptions() { } @Override - protected FulltextIndexOptions getThis() { + FulltextIndexOptions getThis() { return this; } @@ -50,7 +50,7 @@ public Iterable getFields() { * @param fields A list of attribute paths * @return options */ - protected FulltextIndexOptions fields(final Iterable fields) { + FulltextIndexOptions fields(final Iterable fields) { this.fields = fields; return this; } diff --git a/src/main/java/com/arangodb/model/GeoIndexOptions.java b/src/main/java/com/arangodb/model/GeoIndexOptions.java index c55ba0c70..3b2fb9446 100644 --- a/src/main/java/com/arangodb/model/GeoIndexOptions.java +++ b/src/main/java/com/arangodb/model/GeoIndexOptions.java @@ -26,7 +26,7 @@ * @author Mark Vollmary * @see API Documentation */ -public class GeoIndexOptions extends IndexOptions { +public final class GeoIndexOptions extends IndexOptions { private Iterable fields; private final IndexType type = IndexType.geo; @@ -37,7 +37,7 @@ public GeoIndexOptions() { } @Override - protected GeoIndexOptions getThis() { + GeoIndexOptions getThis() { return this; } @@ -49,7 +49,7 @@ public Iterable getFields() { * @param fields A list of attribute paths * @return options */ - protected GeoIndexOptions fields(final Iterable fields) { + GeoIndexOptions fields(final Iterable fields) { this.fields = fields; return this; } diff --git a/src/main/java/com/arangodb/model/GraphCreateOptions.java b/src/main/java/com/arangodb/model/GraphCreateOptions.java index f6453a4e1..7261065b7 100644 --- a/src/main/java/com/arangodb/model/GraphCreateOptions.java +++ b/src/main/java/com/arangodb/model/GraphCreateOptions.java @@ -31,7 +31,7 @@ * @author Mark Vollmary * @see API Documentation */ -public class GraphCreateOptions { +public final class GraphCreateOptions { private String name; private Collection edgeDefinitions = Collections.emptyList(); @@ -51,7 +51,7 @@ public String getName() { * @param name Name of the graph * @return options */ - protected GraphCreateOptions name(final String name) { + GraphCreateOptions name(final String name) { this.name = name; return this; } @@ -64,7 +64,7 @@ public Collection getEdgeDefinitions() { * @param edgeDefinitions An array of definitions for the edge * @return options */ - protected GraphCreateOptions edgeDefinitions(final Collection edgeDefinitions) { + GraphCreateOptions edgeDefinitions(final Collection edgeDefinitions) { this.edgeDefinitions = edgeDefinitions; return this; } @@ -206,7 +206,7 @@ public SmartOptions getOptions() { return options; } - public static class SmartOptions { + public static final class SmartOptions { private ReplicationFactor replicationFactor; private Integer writeConcern; private Integer numberOfShards; diff --git a/src/main/java/com/arangodb/model/GraphDocumentReadOptions.java b/src/main/java/com/arangodb/model/GraphDocumentReadOptions.java index 8a7fffa0a..7277b10df 100644 --- a/src/main/java/com/arangodb/model/GraphDocumentReadOptions.java +++ b/src/main/java/com/arangodb/model/GraphDocumentReadOptions.java @@ -23,7 +23,7 @@ /** * @author Mark Vollmary */ -public class GraphDocumentReadOptions { +public final class GraphDocumentReadOptions { private String ifNoneMatch; private String ifMatch; diff --git a/src/main/java/com/arangodb/model/HashIndexOptions.java b/src/main/java/com/arangodb/model/HashIndexOptions.java index 6268a3718..1192f601c 100644 --- a/src/main/java/com/arangodb/model/HashIndexOptions.java +++ b/src/main/java/com/arangodb/model/HashIndexOptions.java @@ -29,7 +29,7 @@ * index. */ @Deprecated -public class HashIndexOptions extends IndexOptions { +public final class HashIndexOptions extends IndexOptions { private Iterable fields; private final IndexType type = IndexType.hash; @@ -43,7 +43,7 @@ public HashIndexOptions() { } @Override - protected HashIndexOptions getThis() { + HashIndexOptions getThis() { return this; } @@ -55,7 +55,7 @@ public Iterable getFields() { * @param fields A list of attribute paths * @return options */ - protected HashIndexOptions fields(final Iterable fields) { + HashIndexOptions fields(final Iterable fields) { this.fields = fields; return this; } diff --git a/src/main/java/com/arangodb/model/IndexOptions.java b/src/main/java/com/arangodb/model/IndexOptions.java index 7cafad173..afd7240c1 100644 --- a/src/main/java/com/arangodb/model/IndexOptions.java +++ b/src/main/java/com/arangodb/model/IndexOptions.java @@ -23,7 +23,7 @@ /** * @author Heiko Kernbach *

- * This class is used for all index similarities + * This final class is used for all index similarities */ public abstract class IndexOptions { @@ -34,7 +34,7 @@ public IndexOptions() { super(); } - protected abstract T getThis(); + abstract T getThis(); /** * @param inBackground create the the index in the background diff --git a/src/main/java/com/arangodb/model/LogOptions.java b/src/main/java/com/arangodb/model/LogOptions.java index 9a37cdf08..944305f3e 100644 --- a/src/main/java/com/arangodb/model/LogOptions.java +++ b/src/main/java/com/arangodb/model/LogOptions.java @@ -28,7 +28,7 @@ * "https://www.arangodb.com/docs/stable/http/administration-and-monitoring.html#read-global-logs-from-the-server">API * Documentation */ -public class LogOptions { +public final class LogOptions { public static final String PROPERTY_UPTO = "upto"; public static final String PROPERTY_LEVEL = "level"; diff --git a/src/main/java/com/arangodb/model/OptionsBuilder.java b/src/main/java/com/arangodb/model/OptionsBuilder.java index 111bfcb1d..6bf13ae4e 100644 --- a/src/main/java/com/arangodb/model/OptionsBuilder.java +++ b/src/main/java/com/arangodb/model/OptionsBuilder.java @@ -30,7 +30,7 @@ * @author Mark Vollmary * @author Michele Rastelli */ -public class OptionsBuilder { +public final class OptionsBuilder { private OptionsBuilder() { super(); diff --git a/src/main/java/com/arangodb/model/PersistentIndexOptions.java b/src/main/java/com/arangodb/model/PersistentIndexOptions.java index d7a752cd2..598054551 100644 --- a/src/main/java/com/arangodb/model/PersistentIndexOptions.java +++ b/src/main/java/com/arangodb/model/PersistentIndexOptions.java @@ -27,7 +27,7 @@ * @see API * Documentation */ -public class PersistentIndexOptions extends IndexOptions { +public final class PersistentIndexOptions extends IndexOptions { private Iterable fields; private final IndexType type = IndexType.persistent; @@ -41,7 +41,7 @@ public PersistentIndexOptions() { } @Override - protected PersistentIndexOptions getThis() { + PersistentIndexOptions getThis() { return this; } @@ -53,7 +53,7 @@ public Iterable getFields() { * @param fields A list of attribute paths * @return options */ - protected PersistentIndexOptions fields(final Iterable fields) { + PersistentIndexOptions fields(final Iterable fields) { this.fields = fields; return this; } diff --git a/src/main/java/com/arangodb/model/QueueTimeSample.java b/src/main/java/com/arangodb/model/QueueTimeSample.java index 841221761..bfc1f2496 100644 --- a/src/main/java/com/arangodb/model/QueueTimeSample.java +++ b/src/main/java/com/arangodb/model/QueueTimeSample.java @@ -10,7 +10,7 @@ * @author Michele Rastelli * @see API Documentation */ -public class QueueTimeSample { +public final class QueueTimeSample { /** * Unix-timestamp in milliseconds, recorded at client side. */ diff --git a/src/main/java/com/arangodb/model/SkiplistIndexOptions.java b/src/main/java/com/arangodb/model/SkiplistIndexOptions.java index 981d7fa62..1ab9babb5 100644 --- a/src/main/java/com/arangodb/model/SkiplistIndexOptions.java +++ b/src/main/java/com/arangodb/model/SkiplistIndexOptions.java @@ -29,7 +29,7 @@ * persistent index. */ @Deprecated -public class SkiplistIndexOptions extends IndexOptions { +public final class SkiplistIndexOptions extends IndexOptions { private Iterable fields; private final IndexType type = IndexType.skiplist; @@ -43,7 +43,7 @@ public SkiplistIndexOptions() { } @Override - protected SkiplistIndexOptions getThis() { + SkiplistIndexOptions getThis() { return this; } @@ -55,7 +55,7 @@ public Iterable getFields() { * @param fields A list of attribute paths * @return options */ - protected SkiplistIndexOptions fields(final Iterable fields) { + SkiplistIndexOptions fields(final Iterable fields) { this.fields = fields; return this; } diff --git a/src/main/java/com/arangodb/model/StreamTransactionOptions.java b/src/main/java/com/arangodb/model/StreamTransactionOptions.java index 52cae19d2..9bcf5000e 100644 --- a/src/main/java/com/arangodb/model/StreamTransactionOptions.java +++ b/src/main/java/com/arangodb/model/StreamTransactionOptions.java @@ -26,7 +26,7 @@ * @see API Documentation * @since ArangoDB 3.5.0 */ -public class StreamTransactionOptions { +public final class StreamTransactionOptions { private final TransactionCollectionOptions collections; private Integer lockTimeout; diff --git a/src/main/java/com/arangodb/model/TransactionCollectionOptions.java b/src/main/java/com/arangodb/model/TransactionCollectionOptions.java index e16060a33..ade09ba96 100644 --- a/src/main/java/com/arangodb/model/TransactionCollectionOptions.java +++ b/src/main/java/com/arangodb/model/TransactionCollectionOptions.java @@ -28,7 +28,7 @@ * @author Mark Vollmary * @author Michele Rastelli */ -public class TransactionCollectionOptions { +public final class TransactionCollectionOptions { private Collection read = Collections.emptyList(); private Collection write = Collections.emptyList(); diff --git a/src/main/java/com/arangodb/model/TransactionOptions.java b/src/main/java/com/arangodb/model/TransactionOptions.java index ebe31c7d9..19b5b2599 100644 --- a/src/main/java/com/arangodb/model/TransactionOptions.java +++ b/src/main/java/com/arangodb/model/TransactionOptions.java @@ -26,7 +26,7 @@ * @see API * Documentation */ -public class TransactionOptions { +public final class TransactionOptions { private String action; private Object params; @@ -52,7 +52,7 @@ public String getAction() { * @param action the actual transaction operations to be executed, in the form of stringified JavaScript code * @return options */ - protected TransactionOptions action(final String action) { + TransactionOptions action(final String action) { this.action = action; return this; } diff --git a/src/main/java/com/arangodb/model/TtlIndexOptions.java b/src/main/java/com/arangodb/model/TtlIndexOptions.java index a12e45ceb..c599a614e 100644 --- a/src/main/java/com/arangodb/model/TtlIndexOptions.java +++ b/src/main/java/com/arangodb/model/TtlIndexOptions.java @@ -26,7 +26,7 @@ * @author Heiko Kernbach * @see API Documentation */ -public class TtlIndexOptions extends IndexOptions { +public final class TtlIndexOptions extends IndexOptions { private Iterable fields; private final IndexType type = IndexType.ttl; @@ -37,7 +37,7 @@ public TtlIndexOptions() { } @Override - protected TtlIndexOptions getThis() { + TtlIndexOptions getThis() { return this; } @@ -49,7 +49,7 @@ public Iterable getFields() { * @param fields A list of attribute paths * @return options */ - protected TtlIndexOptions fields(final Iterable fields) { + TtlIndexOptions fields(final Iterable fields) { this.fields = fields; return this; } diff --git a/src/main/java/com/arangodb/model/UserAccessOptions.java b/src/main/java/com/arangodb/model/UserAccessOptions.java index 12355c642..19c597ab7 100644 --- a/src/main/java/com/arangodb/model/UserAccessOptions.java +++ b/src/main/java/com/arangodb/model/UserAccessOptions.java @@ -25,7 +25,7 @@ /** * @author Mark Vollmary */ -public class UserAccessOptions { +public final class UserAccessOptions { private Permissions grant; @@ -37,7 +37,7 @@ public Permissions getGrant() { return grant; } - protected UserAccessOptions grant(final Permissions grant) { + UserAccessOptions grant(final Permissions grant) { this.grant = grant; return this; } diff --git a/src/main/java/com/arangodb/model/UserCreateOptions.java b/src/main/java/com/arangodb/model/UserCreateOptions.java index f4808da27..4279e60d6 100644 --- a/src/main/java/com/arangodb/model/UserCreateOptions.java +++ b/src/main/java/com/arangodb/model/UserCreateOptions.java @@ -26,7 +26,7 @@ * @author Mark Vollmary * @see API Documentation */ -public class UserCreateOptions { +public final class UserCreateOptions { private String user; private String passwd; @@ -45,7 +45,7 @@ public String getUser() { * @param user The name of the user * @return options */ - protected UserCreateOptions user(final String user) { + UserCreateOptions user(final String user) { this.user = user; return this; } @@ -58,7 +58,7 @@ public String getPasswd() { * @param passwd The user password * @return options */ - protected UserCreateOptions passwd(final String passwd) { + UserCreateOptions passwd(final String passwd) { this.passwd = passwd; return this; } diff --git a/src/main/java/com/arangodb/model/UserUpdateOptions.java b/src/main/java/com/arangodb/model/UserUpdateOptions.java index eec7fa2f4..09c3786c8 100644 --- a/src/main/java/com/arangodb/model/UserUpdateOptions.java +++ b/src/main/java/com/arangodb/model/UserUpdateOptions.java @@ -26,7 +26,7 @@ * @author Mark Vollmary * @see API Documentation */ -public class UserUpdateOptions { +public final class UserUpdateOptions { private String passwd; private Boolean active; diff --git a/src/main/java/com/arangodb/model/VertexCollectionCreateOptions.java b/src/main/java/com/arangodb/model/VertexCollectionCreateOptions.java index e7132fc64..86fa34067 100644 --- a/src/main/java/com/arangodb/model/VertexCollectionCreateOptions.java +++ b/src/main/java/com/arangodb/model/VertexCollectionCreateOptions.java @@ -26,7 +26,7 @@ /** * @author Mark Vollmary */ -public class VertexCollectionCreateOptions { +public final class VertexCollectionCreateOptions { private String collection; private final Options options = new Options(); @@ -43,7 +43,7 @@ public String getCollection() { * @param collection The name of the collection * @return options */ - protected VertexCollectionCreateOptions collection(final String collection) { + VertexCollectionCreateOptions collection(final String collection) { this.collection = collection; return this; } @@ -68,7 +68,7 @@ public VertexCollectionCreateOptions satellites(final String... satellites) { return this; } - public static class Options { + public static final class Options { private Collection satellites; public Collection getSatellites() { diff --git a/src/main/java/com/arangodb/model/VertexCreateOptions.java b/src/main/java/com/arangodb/model/VertexCreateOptions.java index d998aa590..156476a93 100644 --- a/src/main/java/com/arangodb/model/VertexCreateOptions.java +++ b/src/main/java/com/arangodb/model/VertexCreateOptions.java @@ -24,7 +24,7 @@ * @author Mark Vollmary * @see API Documentation */ -public class VertexCreateOptions { +public final class VertexCreateOptions { private Boolean waitForSync; private String streamTransactionId; diff --git a/src/main/java/com/arangodb/model/VertexDeleteOptions.java b/src/main/java/com/arangodb/model/VertexDeleteOptions.java index d52f58347..e43c6d016 100644 --- a/src/main/java/com/arangodb/model/VertexDeleteOptions.java +++ b/src/main/java/com/arangodb/model/VertexDeleteOptions.java @@ -24,7 +24,7 @@ * @author Mark Vollmary * @see API Documentation */ -public class VertexDeleteOptions { +public final class VertexDeleteOptions { private Boolean waitForSync; private String ifMatch; diff --git a/src/main/java/com/arangodb/model/VertexReplaceOptions.java b/src/main/java/com/arangodb/model/VertexReplaceOptions.java index 5957b7235..9111f11e0 100644 --- a/src/main/java/com/arangodb/model/VertexReplaceOptions.java +++ b/src/main/java/com/arangodb/model/VertexReplaceOptions.java @@ -24,7 +24,7 @@ * @author Mark Vollmary * @see API Documentation */ -public class VertexReplaceOptions { +public final class VertexReplaceOptions { private Boolean waitForSync; private String ifMatch; diff --git a/src/main/java/com/arangodb/model/VertexUpdateOptions.java b/src/main/java/com/arangodb/model/VertexUpdateOptions.java index 1e0478692..a66e9b450 100644 --- a/src/main/java/com/arangodb/model/VertexUpdateOptions.java +++ b/src/main/java/com/arangodb/model/VertexUpdateOptions.java @@ -24,7 +24,7 @@ * @author Mark Vollmary * @see API Documentation */ -public class VertexUpdateOptions { +public final class VertexUpdateOptions { private Boolean keepNull; private Boolean waitForSync; diff --git a/src/main/java/com/arangodb/model/ViewCreateOptions.java b/src/main/java/com/arangodb/model/ViewCreateOptions.java index 0fa34d0aa..8c11dd343 100644 --- a/src/main/java/com/arangodb/model/ViewCreateOptions.java +++ b/src/main/java/com/arangodb/model/ViewCreateOptions.java @@ -25,7 +25,7 @@ /** * @author Mark Vollmary */ -public class ViewCreateOptions { +public final class ViewCreateOptions { @SuppressWarnings("unused") private String name; @@ -36,12 +36,12 @@ public ViewCreateOptions() { super(); } - protected ViewCreateOptions name(final String name) { + ViewCreateOptions name(final String name) { this.name = name; return this; } - protected ViewCreateOptions type(final ViewType type) { + ViewCreateOptions type(final ViewType type) { this.type = type; return this; } diff --git a/src/main/java/com/arangodb/model/ViewRenameOptions.java b/src/main/java/com/arangodb/model/ViewRenameOptions.java index d67c5bf54..2f0ed5faf 100644 --- a/src/main/java/com/arangodb/model/ViewRenameOptions.java +++ b/src/main/java/com/arangodb/model/ViewRenameOptions.java @@ -23,7 +23,7 @@ /** * @author Mark Vollmary */ -public class ViewRenameOptions { +public final class ViewRenameOptions { private String name; @@ -39,7 +39,7 @@ public String getName() { * @param name The new name * @return options */ - protected ViewRenameOptions name(final String name) { + ViewRenameOptions name(final String name) { this.name = name; return this; } diff --git a/src/main/java/com/arangodb/model/ZKDIndexOptions.java b/src/main/java/com/arangodb/model/ZKDIndexOptions.java index 6f17e5b87..aad739d86 100644 --- a/src/main/java/com/arangodb/model/ZKDIndexOptions.java +++ b/src/main/java/com/arangodb/model/ZKDIndexOptions.java @@ -28,10 +28,10 @@ * @see API Documentation * @since ArangoDB 3.9 */ -public class ZKDIndexOptions extends IndexOptions { +public final class ZKDIndexOptions extends IndexOptions { private Iterable fields; - protected final IndexType type = IndexType.zkd; + final IndexType type = IndexType.zkd; private Boolean unique; private FieldValueTypes fieldValueTypes; @@ -40,7 +40,7 @@ public ZKDIndexOptions() { } @Override - protected ZKDIndexOptions getThis() { + ZKDIndexOptions getThis() { return this; } @@ -52,7 +52,7 @@ public Iterable getFields() { * @param fields A list of attribute paths * @return options */ - protected ZKDIndexOptions fields(final Iterable fields) { + ZKDIndexOptions fields(final Iterable fields) { this.fields = fields; return this; } diff --git a/src/main/java/com/arangodb/model/arangosearch/AnalyzerDeleteOptions.java b/src/main/java/com/arangodb/model/arangosearch/AnalyzerDeleteOptions.java index 62be6902c..776d3def1 100644 --- a/src/main/java/com/arangodb/model/arangosearch/AnalyzerDeleteOptions.java +++ b/src/main/java/com/arangodb/model/arangosearch/AnalyzerDeleteOptions.java @@ -23,7 +23,7 @@ /** * @author Michele Rastelli */ -public class AnalyzerDeleteOptions { +public final class AnalyzerDeleteOptions { private Boolean force; diff --git a/src/main/java/com/arangodb/model/arangosearch/ArangoSearchCreateOptions.java b/src/main/java/com/arangodb/model/arangosearch/ArangoSearchCreateOptions.java index 66653bd5d..5d810507a 100644 --- a/src/main/java/com/arangodb/model/arangosearch/ArangoSearchCreateOptions.java +++ b/src/main/java/com/arangodb/model/arangosearch/ArangoSearchCreateOptions.java @@ -31,7 +31,7 @@ /** * @author Mark Vollmary */ -public class ArangoSearchCreateOptions { +public final class ArangoSearchCreateOptions { @SuppressWarnings("unused") private String name; @@ -51,7 +51,7 @@ public ArangoSearchCreateOptions() { type = ViewType.ARANGO_SEARCH; } - protected ArangoSearchCreateOptions name(final String name) { + ArangoSearchCreateOptions name(final String name) { this.name = name; return this; } diff --git a/src/main/java/com/arangodb/model/arangosearch/ArangoSearchPropertiesOptions.java b/src/main/java/com/arangodb/model/arangosearch/ArangoSearchPropertiesOptions.java index e4d142b1c..7be061b87 100644 --- a/src/main/java/com/arangodb/model/arangosearch/ArangoSearchPropertiesOptions.java +++ b/src/main/java/com/arangodb/model/arangosearch/ArangoSearchPropertiesOptions.java @@ -32,7 +32,7 @@ /** * @author Mark Vollmary */ -public class ArangoSearchPropertiesOptions { +public final class ArangoSearchPropertiesOptions { private Long consolidationIntervalMsec; private Long cleanupIntervalStep; From 291445c4c743cce6fac246aa5a528b27a2ba9089 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Thu, 21 Jul 2022 10:16:43 +0200 Subject: [PATCH 039/254] removed VPackSlice from javadoc --- .../java/com/arangodb/ArangoCollection.java | 40 +++++++++---------- .../java/com/arangodb/ArangoDatabase.java | 16 ++++---- .../com/arangodb/ArangoEdgeCollection.java | 16 ++++---- src/main/java/com/arangodb/ArangoRoute.java | 2 +- .../com/arangodb/ArangoVertexCollection.java | 16 ++++---- .../arangodb/async/ArangoCollectionAsync.java | 40 +++++++++---------- .../arangodb/async/ArangoDatabaseAsync.java | 16 ++++---- .../async/ArangoEdgeCollectionAsync.java | 8 ++-- .../com/arangodb/async/ArangoRouteAsync.java | 2 +- .../async/ArangoVertexCollectionAsync.java | 8 ++-- .../java/com/arangodb/serde/ArangoSerde.java | 4 +- .../arangodb/serde/InternalDeserializers.java | 2 - .../com/arangodb/serde/InternalSerde.java | 1 - .../com/arangodb/serde/InternalSerdeImpl.java | 2 - 14 files changed, 83 insertions(+), 90 deletions(-) diff --git a/src/main/java/com/arangodb/ArangoCollection.java b/src/main/java/com/arangodb/ArangoCollection.java index 3af131403..ebd00fad5 100644 --- a/src/main/java/com/arangodb/ArangoCollection.java +++ b/src/main/java/com/arangodb/ArangoCollection.java @@ -55,7 +55,7 @@ public interface ArangoCollection extends ArangoSerdeAccessor { * Creates a new document from the given document, unless there is already a document with the _key given. If no * _key is given, a new unique _key is generated automatically. * - * @param value A representation of a single document (POJO, VPackSlice or String for JSON) + * @param value A representation of a single document (POJO or String for JSON) * @return information about the document * @throws ArangoDBException * @see API @@ -67,7 +67,7 @@ public interface ArangoCollection extends ArangoSerdeAccessor { * Creates a new document from the given document, unless there is already a document with the _key given. If no * _key is given, a new unique _key is generated automatically. * - * @param value A representation of a single document (POJO, VPackSlice or String for JSON) + * @param value A representation of a single document (POJO or String for JSON) * @param options Additional options, can be null * @return information about the document * @throws ArangoDBException @@ -83,7 +83,7 @@ public interface ArangoCollection extends ArangoSerdeAccessor { * Limitations: * - the fields having {@code null} value are always removed during serialization * - * @param values A List of documents (POJO, VPackSlice or String for JSON) + * @param values A List of documents (POJO or String for JSON) * @return information about the documents * @throws ArangoDBException * @see API @@ -98,7 +98,7 @@ public interface ArangoCollection extends ArangoSerdeAccessor { * Limitations: * - the fields having {@code null} value are always removed during serialization * - * @param values A List of documents (POJO, VPackSlice or String for JSON) + * @param values A List of documents (POJO or String for JSON) * @param options Additional options, can be null * @return information about the documents * @throws ArangoDBException @@ -162,7 +162,7 @@ MultiDocumentEntity> insertDocuments( * Retrieves the document with the given {@code key} from the collection. * * @param key The key of the document - * @param type The type of the document (POJO class, VPackSlice or String for JSON) + * @param type The type of the document (POJO class or String for JSON) * @return the document identified by the key * @throws ArangoDBException * @see API @@ -174,7 +174,7 @@ MultiDocumentEntity> insertDocuments( * Retrieves the document with the given {@code key} from the collection. * * @param key The key of the document - * @param type The type of the document (POJO class, VPackSlice or String for JSON) + * @param type The type of the document (POJO class or String for JSON) * @param options Additional options, can be null * @return the document identified by the key * @throws ArangoDBException @@ -187,7 +187,7 @@ MultiDocumentEntity> insertDocuments( * Retrieves multiple documents with the given {@code _key} from the collection. * * @param keys The keys of the documents - * @param type The type of the documents (POJO class, VPackSlice or String for JSON) + * @param type The type of the documents (POJO class or String for JSON) * @return the documents and possible errors * @throws ArangoDBException */ @@ -197,7 +197,7 @@ MultiDocumentEntity> insertDocuments( * Retrieves multiple documents with the given {@code _key} from the collection. * * @param keys The keys of the documents - * @param type The type of the documents (POJO class, VPackSlice or String for JSON) + * @param type The type of the documents (POJO class or String for JSON) * @param options Additional options, can be null * @return the documents and possible errors * @throws ArangoDBException @@ -210,7 +210,7 @@ MultiDocumentEntity getDocuments(Collection keys, Class type, * precondition is violated * * @param key The key of the document - * @param value A representation of a single document (POJO, VPackSlice or String for JSON) + * @param value A representation of a single document (POJO or String for JSON) * @return information about the document * @throws ArangoDBException * @see API @@ -223,7 +223,7 @@ MultiDocumentEntity getDocuments(Collection keys, Class type, * precondition is violated * * @param key The key of the document - * @param value A representation of a single document (POJO, VPackSlice or String for JSON) + * @param value A representation of a single document (POJO or String for JSON) * @param options Additional options, can be null * @return information about the document * @throws ArangoDBException @@ -240,7 +240,7 @@ DocumentUpdateEntity replaceDocument(String key, T value, DocumentReplace * Limitations: * - the fields having {@code null} value are always removed during serialization * - * @param values A List of documents (POJO, VPackSlice or String for JSON) + * @param values A List of documents (POJO or String for JSON) * @return information about the documents * @throws ArangoDBException * @see API @@ -255,7 +255,7 @@ DocumentUpdateEntity replaceDocument(String key, T value, DocumentReplace * Limitations: * - the fields having {@code null} value are always removed during serialization * - * @param values A List of documents (POJO, VPackSlice or String for JSON) + * @param values A List of documents (POJO or String for JSON) * @param options Additional options, can be null * @return information about the documents * @throws ArangoDBException @@ -271,7 +271,7 @@ MultiDocumentEntity> replaceDocuments( * they do not yet exist, and overwritten in the existing document if they do exist there. * * @param key The key of the document - * @param value A representation of a single document (POJO, VPackSlice or String for JSON) + * @param value A representation of a single document (POJO or String for JSON) * @return information about the document * @throws ArangoDBException * @see API @@ -285,7 +285,7 @@ MultiDocumentEntity> replaceDocuments( * they do not yet exist, and overwritten in the existing document if they do exist there. * * @param key The key of the document - * @param value A representation of a single document (POJO, VPackSlice or String for JSON) + * @param value A representation of a single document (POJO or String for JSON) * @param options Additional options, can be null * @return information about the document * @throws ArangoDBException @@ -301,7 +301,7 @@ DocumentUpdateEntity updateDocument(String key, T value, DocumentUpdateOp * they do not yet exist, and overwritten in the existing document if they do exist there. * * @param key The key of the document - * @param value A representation of a single document (POJO, VPackSlice or String for JSON) + * @param value A representation of a single document (POJO or String for JSON) * @param options Additional options, can be null * @param returnType Type of the returned newDocument and/or oldDocument * @return information about the document @@ -318,7 +318,7 @@ DocumentUpdateEntity updateDocument(String key, T value, DocumentUpdat * attributes from the patch documents will be added to the existing documents if they do not yet exist, and * overwritten in the existing documents if they do exist there. * - * @param values A list of documents (POJO, VPackSlice or String for JSON) + * @param values A list of documents (POJO or String for JSON) * @return information about the documents * @throws ArangoDBException * @see API @@ -332,7 +332,7 @@ DocumentUpdateEntity updateDocument(String key, T value, DocumentUpdat * attributes from the patch documents will be added to the existing documents if they do not yet exist, and * overwritten in the existing documents if they do exist there. * - * @param values A list of documents (POJO, VPackSlice or String for JSON) + * @param values A list of documents (POJO or String for JSON) * @param options Additional options, can be null * @return information about the documents * @throws ArangoDBException @@ -348,7 +348,7 @@ MultiDocumentEntity> updateDocuments( * attributes from the patch documents will be added to the existing documents if they do not yet exist, and * overwritten in the existing documents if they do exist there. * - * @param values A list of documents (POJO, VPackSlice or String for JSON) + * @param values A list of documents (POJO or String for JSON) * @param options Additional options, can be null * @param returnType Type of the returned newDocument and/or oldDocument * @return information about the documents @@ -374,7 +374,7 @@ MultiDocumentEntity> updateDocuments( * Deletes the document with the given {@code key} from the collection. * * @param key The key of the document - * @param type The type of the document (POJO class, VPackSlice or String for JSON). Only necessary if + * @param type The type of the document (POJO class or String for JSON). Only necessary if * options.returnOld is set to true, otherwise can be null. * @param options Additional options, can be null * @return information about the document @@ -401,7 +401,7 @@ DocumentDeleteEntity deleteDocument(String key, Class type, DocumentDe * Deletes multiple documents from the collection. * * @param values The keys of the documents or the documents themselves - * @param type The type of the documents (POJO class, VPackSlice or String for JSON). Only necessary if + * @param type The type of the documents (POJO class or String for JSON). Only necessary if * options.returnOld is set to true, otherwise can be null. * @param options Additional options, can be null * @return information about the documents diff --git a/src/main/java/com/arangodb/ArangoDatabase.java b/src/main/java/com/arangodb/ArangoDatabase.java index 826d301fd..6aaf3ff26 100644 --- a/src/main/java/com/arangodb/ArangoDatabase.java +++ b/src/main/java/com/arangodb/ArangoDatabase.java @@ -260,7 +260,7 @@ public interface ArangoDatabase extends ArangoSerdeAccessor { * @param query An AQL query string * @param bindVars key/value pairs defining the variables to bind the query to * @param options Additional options that will be passed to the query API, can be null - * @param type The type of the result (POJO class, VPackSlice, String for JSON, or Collection/List/Map) + * @param type The type of the result (POJO class, String for JSON, or Collection/List/Map) * @return cursor of the results * @throws ArangoDBException * @see API @@ -275,7 +275,7 @@ ArangoCursor query(String query, Map bindVars, AqlQueryOp * * @param query An AQL query string * @param options Additional options that will be passed to the query API, can be null - * @param type The type of the result (POJO class, VPackSlice, String for JSON, or Collection/List/Map) + * @param type The type of the result (POJO class, String for JSON, or Collection/List/Map) * @return cursor of the results * @throws ArangoDBException * @see API @@ -289,7 +289,7 @@ ArangoCursor query(String query, Map bindVars, AqlQueryOp * * @param query An AQL query string * @param bindVars key/value pairs defining the variables to bind the query to - * @param type The type of the result (POJO class, VPackSlice, String for JSON, or Collection/List/Map) + * @param type The type of the result (POJO class, String for JSON, or Collection/List/Map) * @return cursor of the results * @throws ArangoDBException * @see API @@ -302,7 +302,7 @@ ArangoCursor query(String query, Map bindVars, AqlQueryOp * result list. * * @param query An AQL query string - * @param type The type of the result (POJO class, VPackSlice, String for JSON, or Collection/List/Map) + * @param type The type of the result (POJO class, String for JSON, or Collection/List/Map) * @return cursor of the results * @throws ArangoDBException * @see API @@ -314,7 +314,7 @@ ArangoCursor query(String query, Map bindVars, AqlQueryOp * Return an cursor from the given cursor-ID if still existing * * @param cursorId The ID of the cursor - * @param type The type of the result (POJO class, VPackSlice, String for JSON, or Collection/List/Map) + * @param type The type of the result (POJO class, String for JSON, or Collection/List/Map) * @return cursor of the results * @throws ArangoDBException * @see edgeDefinitions, * Performs a server-side transaction and returns its return value. * * @param action A String evaluating to a JavaScript function to be executed on the server. - * @param type The type of the result (POJO class, VPackSlice or String for JSON) + * @param type The type of the result (POJO class or String for JSON) * @param options Additional options, can be null * @return the result of the transaction if it succeeded * @throws ArangoDBException @@ -615,7 +615,7 @@ GraphEntity createGraph(String name, Collection edgeDefinitions, * Reads a single document * * @param id The id of the document - * @param type The type of the document (POJO class, VPackSlice or String for JSON) + * @param type The type of the document (POJO class or String for JSON) * @return the document identified by the id * @throws ArangoDBException * @see API @@ -627,7 +627,7 @@ GraphEntity createGraph(String name, Collection edgeDefinitions, * Reads a single document * * @param id The id of the document - * @param type The type of the document (POJO class, VPackSlice or String for JSON) + * @param type The type of the document (POJO class or String for JSON) * @param options Additional options, can be null * @return the document identified by the id * @throws ArangoDBException diff --git a/src/main/java/com/arangodb/ArangoEdgeCollection.java b/src/main/java/com/arangodb/ArangoEdgeCollection.java index 702728e99..569d5d561 100644 --- a/src/main/java/com/arangodb/ArangoEdgeCollection.java +++ b/src/main/java/com/arangodb/ArangoEdgeCollection.java @@ -50,7 +50,7 @@ public interface ArangoEdgeCollection extends ArangoSerdeAccessor { /** * Creates a new edge in the collection * - * @param value A representation of a single edge (POJO, VPackSlice or String for JSON) + * @param value A representation of a single edge (POJO or String for JSON) * @return information about the edge * @throws ArangoDBException * @see API Documentation @@ -60,7 +60,7 @@ public interface ArangoEdgeCollection extends ArangoSerdeAccessor { /** * Creates a new edge in the collection * - * @param value A representation of a single edge (POJO, VPackSlice or String for JSON) + * @param value A representation of a single edge (POJO or String for JSON) * @param options Additional options, can be null * @return information about the edge * @throws ArangoDBException @@ -72,7 +72,7 @@ public interface ArangoEdgeCollection extends ArangoSerdeAccessor { * Fetches an existing edge * * @param key The key of the edge - * @param type The type of the edge-document (POJO class, VPackSlice or String for JSON) + * @param type The type of the edge-document (POJO class or String for JSON) * @return the edge identified by the key * @throws ArangoDBException * @see API Documentation @@ -83,7 +83,7 @@ public interface ArangoEdgeCollection extends ArangoSerdeAccessor { * Fetches an existing edge * * @param key The key of the edge - * @param type The type of the edge-document (POJO class, VPackSlice or String for JSON) + * @param type The type of the edge-document (POJO class or String for JSON) * @param options Additional options, can be null * @return the edge identified by the key * @throws ArangoDBException @@ -96,7 +96,7 @@ public interface ArangoEdgeCollection extends ArangoSerdeAccessor { * violated * * @param key The key of the edge - * @param The type of the edge-document (POJO class, VPackSlice or String for JSON) + * @param The type of the edge-document (POJO class or String for JSON) * @return information about the edge * @throws ArangoDBException * @see API Documentation @@ -108,7 +108,7 @@ public interface ArangoEdgeCollection extends ArangoSerdeAccessor { * violated * * @param key The key of the edge - * @param The type of the edge-document (POJO class, VPackSlice or String for JSON) + * @param The type of the edge-document (POJO class or String for JSON) * @param options Additional options, can be null * @return information about the edge * @throws ArangoDBException @@ -122,7 +122,7 @@ public interface ArangoEdgeCollection extends ArangoSerdeAccessor { * do not yet exist, and overwritten in the existing document if they do exist there. * * @param key The key of the edge - * @param The type of the edge-document (POJO class, VPackSlice or String for JSON) + * @param The type of the edge-document (POJO class or String for JSON) * @return information about the edge * @throws ArangoDBException * @see API Documentation @@ -135,7 +135,7 @@ public interface ArangoEdgeCollection extends ArangoSerdeAccessor { * do not yet exist, and overwritten in the existing document if they do exist there. * * @param key The key of the edge - * @param The type of the edge-document (POJO class, VPackSlice or String for JSON) + * @param The type of the edge-document (POJO class or String for JSON) * @param options Additional options, can be null * @return information about the edge * @throws ArangoDBException diff --git a/src/main/java/com/arangodb/ArangoRoute.java b/src/main/java/com/arangodb/ArangoRoute.java index a32e09f70..b9a393add 100644 --- a/src/main/java/com/arangodb/ArangoRoute.java +++ b/src/main/java/com/arangodb/ArangoRoute.java @@ -57,7 +57,7 @@ public interface ArangoRoute extends ArangoSerdeAccessor { ArangoRoute withQueryParam(String key, Object value); /** - * The response body. The body will be serialized to {@link com.arangodb.velocypack.VPackSlice}. + * The response body. * * @param body The request body * @return {@link ArangoRoute} diff --git a/src/main/java/com/arangodb/ArangoVertexCollection.java b/src/main/java/com/arangodb/ArangoVertexCollection.java index ffc1a39f0..a8f5b5727 100644 --- a/src/main/java/com/arangodb/ArangoVertexCollection.java +++ b/src/main/java/com/arangodb/ArangoVertexCollection.java @@ -59,7 +59,7 @@ public interface ArangoVertexCollection extends ArangoSerdeAccessor { /** * Creates a new vertex in the collection * - * @param value A representation of a single vertex (POJO, VPackSlice or String for JSON) + * @param value A representation of a single vertex (POJO or String for JSON) * @return information about the vertex * @throws ArangoDBException * @see API Documentation @@ -69,7 +69,7 @@ public interface ArangoVertexCollection extends ArangoSerdeAccessor { /** * Creates a new vertex in the collection * - * @param value A representation of a single vertex (POJO, VPackSlice or String for JSON) + * @param value A representation of a single vertex (POJO or String for JSON) * @param options Additional options, can be null * @return information about the vertex * @throws ArangoDBException @@ -81,7 +81,7 @@ public interface ArangoVertexCollection extends ArangoSerdeAccessor { * Retrieves the vertex document with the given {@code key} from the collection. * * @param key The key of the vertex - * @param type The type of the vertex-document (POJO class, VPackSlice or String for JSON) + * @param type The type of the vertex-document (POJO class or String for JSON) * @return the vertex identified by the key * @throws ArangoDBException * @see API Documentation @@ -92,7 +92,7 @@ public interface ArangoVertexCollection extends ArangoSerdeAccessor { * Retrieves the vertex document with the given {@code key} from the collection. * * @param key The key of the vertex - * @param type The type of the vertex-document (POJO class, VPackSlice or String for JSON) + * @param type The type of the vertex-document (POJO class or String for JSON) * @param options Additional options, can be null * @return the vertex identified by the key * @throws ArangoDBException @@ -105,7 +105,7 @@ public interface ArangoVertexCollection extends ArangoSerdeAccessor { * violated * * @param key The key of the vertex - * @param value A representation of a single vertex (POJO, VPackSlice or String for JSON) + * @param value A representation of a single vertex (POJO or String for JSON) * @return information about the vertex * @throws ArangoDBException * @see API @@ -118,7 +118,7 @@ public interface ArangoVertexCollection extends ArangoSerdeAccessor { * violated * * @param key The key of the vertex - * @param value A representation of a single vertex (POJO, VPackSlice or String for JSON) + * @param value A representation of a single vertex (POJO or String for JSON) * @param options Additional options, can be null * @return information about the vertex * @throws ArangoDBException @@ -133,7 +133,7 @@ public interface ArangoVertexCollection extends ArangoSerdeAccessor { * do not yet exist, and overwritten in the existing document if they do exist there. * * @param key The key of the vertex - * @param The type of the vertex-document (POJO class, VPackSlice or String for JSON) + * @param The type of the vertex-document (POJO class or String for JSON) * @return information about the vertex * @throws ArangoDBException * @see API Documentation @@ -146,7 +146,7 @@ public interface ArangoVertexCollection extends ArangoSerdeAccessor { * do not yet exist, and overwritten in the existing document if they do exist there. * * @param key The key of the vertex - * @param The type of the vertex-document (POJO class, VPackSlice or String for JSON) + * @param The type of the vertex-document (POJO class or String for JSON) * @param options Additional options, can be null * @return information about the vertex * @throws ArangoDBException diff --git a/src/main/java/com/arangodb/async/ArangoCollectionAsync.java b/src/main/java/com/arangodb/async/ArangoCollectionAsync.java index 8d2194f43..d2da44236 100644 --- a/src/main/java/com/arangodb/async/ArangoCollectionAsync.java +++ b/src/main/java/com/arangodb/async/ArangoCollectionAsync.java @@ -56,7 +56,7 @@ public interface ArangoCollectionAsync extends ArangoSerdeAccessor { * Creates a new document from the given document, unless there is already a document with the _key given. If no * _key is given, a new unique _key is generated automatically. * - * @param value A representation of a single document (POJO, VPackSlice or String for Json) + * @param value A representation of a single document (POJO or String for Json) * @return information about the document * @see API * Documentation @@ -67,7 +67,7 @@ public interface ArangoCollectionAsync extends ArangoSerdeAccessor { * Creates a new document from the given document, unless there is already a document with the _key given. If no * _key is given, a new unique _key is generated automatically. * - * @param value A representation of a single document (POJO, VPackSlice or String for Json) + * @param value A representation of a single document (POJO or String for Json) * @param options Additional options, can be null * @return information about the document * @see API @@ -79,7 +79,7 @@ public interface ArangoCollectionAsync extends ArangoSerdeAccessor { * Creates new documents from the given documents, unless there is already a document with the _key given. If no * _key is given, a new unique _key is generated automatically. * - * @param values A List of documents (POJO, VPackSlice or String for Json) + * @param values A List of documents (POJO or String for Json) * @return information about the documents * @see API * Documentation @@ -90,7 +90,7 @@ public interface ArangoCollectionAsync extends ArangoSerdeAccessor { * Creates new documents from the given documents, unless there is already a document with the _key given. If no * _key is given, a new unique _key is generated automatically. * - * @param values A List of documents (POJO, VPackSlice or String for Json) + * @param values A List of documents (POJO or String for Json) * @param options Additional options, can be null * @return information about the documents * @see API @@ -140,7 +140,7 @@ CompletableFuture importDocuments( * Reads a single document * * @param key The key of the document - * @param type The type of the document (POJO class, VPackSlice or String for Json) + * @param type The type of the document (POJO class or String for Json) * @return the document identified by the key * @see API * Documentation @@ -151,7 +151,7 @@ CompletableFuture importDocuments( * Reads a single document * * @param key The key of the document - * @param type The type of the document (POJO class, VPackSlice or String for Json) + * @param type The type of the document (POJO class or String for Json) * @param options Additional options, can be null * @return the document identified by the key * @see API @@ -164,7 +164,7 @@ CompletableFuture getDocument(final String key, final Class type, fina * Reads multiple documents * * @param keys The keys of the documents - * @param type The type of the documents (POJO class, VPackSlice or String for Json) + * @param type The type of the documents (POJO class or String for Json) * @return the documents and possible errors */ CompletableFuture> getDocuments(final Collection keys, final Class type); @@ -173,7 +173,7 @@ CompletableFuture getDocument(final String key, final Class type, fina * Reads multiple documents * * @param keys The keys of the documents - * @param type The type of the documents (POJO class, VPackSlice or String for Json) + * @param type The type of the documents (POJO class or String for Json) * @param options Additional options, can be null * @return the documents and possible errors */ @@ -187,7 +187,7 @@ CompletableFuture> getDocuments( * violated * * @param key The key of the document - * @param value A representation of a single document (POJO, VPackSlice or String for Json) + * @param value A representation of a single document (POJO or String for Json) * @return information about the document * @see API * Documentation @@ -199,7 +199,7 @@ CompletableFuture> getDocuments( * violated * * @param key The key of the document - * @param value A representation of a single document (POJO, VPackSlice or String for Json) + * @param value A representation of a single document (POJO or String for Json) * @param options Additional options, can be null * @return information about the document * @see API @@ -214,7 +214,7 @@ CompletableFuture> replaceDocument( * Replaces multiple documents in the specified collection with the ones in the values, the replaced documents are * specified by the _key attributes in the documents in values. * - * @param values A List of documents (POJO, VPackSlice or String for Json) + * @param values A List of documents (POJO or String for Json) * @return information about the documents * @see API * Documentation @@ -225,7 +225,7 @@ CompletableFuture> replaceDocument( * Replaces multiple documents in the specified collection with the ones in the values, the replaced documents are * specified by the _key attributes in the documents in values. * - * @param values A List of documents (POJO, VPackSlice or String for Json) + * @param values A List of documents (POJO or String for Json) * @param options Additional options, can be null * @return information about the documents * @see API @@ -241,7 +241,7 @@ CompletableFuture>> replaceDocum * they do not yet exist, and overwritten in the existing document if they do exist there. * * @param key The key of the document - * @param value A representation of a single document (POJO, VPackSlice or String for Json) + * @param value A representation of a single document (POJO or String for Json) * @return information about the document * @see API * Documentation @@ -254,7 +254,7 @@ CompletableFuture>> replaceDocum * they do not yet exist, and overwritten in the existing document if they do exist there. * * @param key The key of the document - * @param value A representation of a single document (POJO, VPackSlice or String for Json) + * @param value A representation of a single document (POJO or String for Json) * @param options Additional options, can be null * @return information about the document * @see API @@ -271,7 +271,7 @@ CompletableFuture> updateDocument( * they do not yet exist, and overwritten in the existing document if they do exist there. * * @param key The key of the document - * @param value A representation of a single document (POJO, VPackSlice or String for Json) + * @param value A representation of a single document (POJO or String for Json) * @param options Additional options, can be null * @param returnType Type of the returned newDocument and/or oldDocument * @return information about the document @@ -290,7 +290,7 @@ CompletableFuture> updateDocument( * attributes from the patch documents will be added to the existing documents if they do not yet exist, and * overwritten in the existing documents if they do exist there. * - * @param values A list of documents (POJO, VPackSlice or String for Json) + * @param values A list of documents (POJO or String for Json) * @return information about the documents * @see API * Documentation @@ -303,7 +303,7 @@ CompletableFuture> updateDocument( * attributes from the patch documents will be added to the existing documents if they do not yet exist, and * overwritten in the existing documents if they do exist there. * - * @param values A list of documents (POJO, VPackSlice or String for Json) + * @param values A list of documents (POJO or String for Json) * @param options Additional options, can be null * @return information about the documents * @see API @@ -319,7 +319,7 @@ CompletableFuture>> updateDocume * attributes from the patch documents will be added to the existing documents if they do not yet exist, and * overwritten in the existing documents if they do exist there. * - * @param values A list of documents (POJO, VPackSlice or String for Json) + * @param values A list of documents (POJO or String for Json) * @param options Additional options, can be null * @param returnType Type of the returned newDocument and/or oldDocument * @return information about the documents @@ -345,7 +345,7 @@ CompletableFuture>> updateDoc * Removes a document * * @param key The key of the document - * @param type The type of the document (POJO class, VPackSlice or String for Json). Only necessary if + * @param type The type of the document (POJO class or String for Json). Only necessary if * options.returnOld is set to true, otherwise can be null. * @param options Additional options, can be null * @return information about the document @@ -372,7 +372,7 @@ CompletableFuture> deleteDocument( * Removes multiple document * * @param values The keys of the documents or the documents themselves - * @param type The type of the documents (POJO class, VPackSlice or String for Json). Only necessary if + * @param type The type of the documents (POJO class or String for Json). Only necessary if * options.returnOld is set to true, otherwise can be null. * @param options Additional options, can be null * @return information about the documents diff --git a/src/main/java/com/arangodb/async/ArangoDatabaseAsync.java b/src/main/java/com/arangodb/async/ArangoDatabaseAsync.java index 0a7648967..4531c7cba 100644 --- a/src/main/java/com/arangodb/async/ArangoDatabaseAsync.java +++ b/src/main/java/com/arangodb/async/ArangoDatabaseAsync.java @@ -249,7 +249,7 @@ public interface ArangoDatabaseAsync extends ArangoSerdeAccessor { * @param query contains the query string to be executed * @param bindVars key/value pairs representing the bind parameters * @param options Additional options, can be null - * @param type The type of the result (POJO class, VPackSlice, String for Json, or Collection/List/Map) + * @param type The type of the result (POJO class, String for Json, or Collection/List/Map) * @return cursor of the results * @see API * Documentation @@ -266,7 +266,7 @@ CompletableFuture> query( * * @param query contains the query string to be executed * @param options Additional options, can be null - * @param type The type of the result (POJO class, VPackSlice, String for Json, or Collection/List/Map) + * @param type The type of the result (POJO class, String for Json, or Collection/List/Map) * @return cursor of the results * @see API * Documentation @@ -282,7 +282,7 @@ CompletableFuture> query( * * @param query contains the query string to be executed * @param bindVars key/value pairs representing the bind parameters - * @param type The type of the result (POJO class, VPackSlice, String for Json, or Collection/List/Map) + * @param type The type of the result (POJO class, String for Json, or Collection/List/Map) * @return cursor of the results * @see API * Documentation @@ -297,7 +297,7 @@ CompletableFuture> query( * result list. * * @param query contains the query string to be executed - * @param type The type of the result (POJO class, VPackSlice, String for Json, or Collection/List/Map) + * @param type The type of the result (POJO class, String for Json, or Collection/List/Map) * @return cursor of the results * @see API * Documentation @@ -308,7 +308,7 @@ CompletableFuture> query( * Return an cursor from the given cursor-ID if still existing * * @param cursorId The ID of the cursor - * @param type The type of the result (POJO class, VPackSlice, String for Json, or Collection/List/Map) + * @param type The type of the result (POJO class, String for Json, or Collection/List/Map) * @return cursor of the results * @see API @@ -523,7 +523,7 @@ CompletableFuture createGraph( * Execute a server-side transaction * * @param action the actual transaction operations to be executed, in the form of stringified JavaScript code - * @param type The type of the result (POJO class, VPackSlice or String for Json) + * @param type The type of the result (POJO class or String for Json) * @param options Additional options, can be null * @return the result of the transaction if it succeeded * @see API @@ -595,7 +595,7 @@ CompletableFuture createGraph( * Reads a single document * * @param id The id of the document - * @param type The type of the document (POJO class, VPackSlice or String for Json) + * @param type The type of the document (POJO class or String for Json) * @return the document identified by the id * @see API * Documentation @@ -606,7 +606,7 @@ CompletableFuture createGraph( * Reads a single document * * @param id The id of the document - * @param type The type of the document (POJO class, VPackSlice or String for Json) + * @param type The type of the document (POJO class or String for Json) * @param options Additional options, can be null * @return the document identified by the id * @see API diff --git a/src/main/java/com/arangodb/async/ArangoEdgeCollectionAsync.java b/src/main/java/com/arangodb/async/ArangoEdgeCollectionAsync.java index f87d1f4c7..cff6747f0 100644 --- a/src/main/java/com/arangodb/async/ArangoEdgeCollectionAsync.java +++ b/src/main/java/com/arangodb/async/ArangoEdgeCollectionAsync.java @@ -53,7 +53,7 @@ public interface ArangoEdgeCollectionAsync extends ArangoSerdeAccessor { /** * Creates a new edge in the collection * - * @param value A representation of a single edge (POJO, VPackSlice or String for Json) + * @param value A representation of a single edge (POJO or String for Json) * @return information about the edge * @see API Documentation */ @@ -62,7 +62,7 @@ public interface ArangoEdgeCollectionAsync extends ArangoSerdeAccessor { /** * Creates a new edge in the collection * - * @param value A representation of a single edge (POJO, VPackSlice or String for Json) + * @param value A representation of a single edge (POJO or String for Json) * @param options Additional options, can be null * @return information about the edge * @see API Documentation @@ -73,7 +73,7 @@ public interface ArangoEdgeCollectionAsync extends ArangoSerdeAccessor { * Fetches an existing edge * * @param key The key of the edge - * @param type The type of the edge-document (POJO class, VPackSlice or String for Json) + * @param type The type of the edge-document (POJO class or String for Json) * @return the edge identified by the key * @see API Documentation */ @@ -83,7 +83,7 @@ public interface ArangoEdgeCollectionAsync extends ArangoSerdeAccessor { * Fetches an existing edge * * @param key The key of the edge - * @param type The type of the edge-document (POJO class, VPackSlice or String for Json) + * @param type The type of the edge-document (POJO class or String for Json) * @param options Additional options, can be null * @return the edge identified by the key * @see API Documentation diff --git a/src/main/java/com/arangodb/async/ArangoRouteAsync.java b/src/main/java/com/arangodb/async/ArangoRouteAsync.java index 2605cbf53..e79d9ca13 100644 --- a/src/main/java/com/arangodb/async/ArangoRouteAsync.java +++ b/src/main/java/com/arangodb/async/ArangoRouteAsync.java @@ -61,7 +61,7 @@ public interface ArangoRouteAsync extends ArangoSerdeAccessor { ArangoRouteAsync withQueryParam(String key, Object value); /** - * The response body. The body will be serialized to {@link com.arangodb.velocypack.VPackSlice}. + * The response body. * * @param body The response body * @return {@link ArangoRouteAsync} diff --git a/src/main/java/com/arangodb/async/ArangoVertexCollectionAsync.java b/src/main/java/com/arangodb/async/ArangoVertexCollectionAsync.java index ed3f98629..e9ad701de 100644 --- a/src/main/java/com/arangodb/async/ArangoVertexCollectionAsync.java +++ b/src/main/java/com/arangodb/async/ArangoVertexCollectionAsync.java @@ -63,7 +63,7 @@ public interface ArangoVertexCollectionAsync extends ArangoSerdeAccessor { /** * Creates a new vertex in the collection * - * @param value A representation of a single vertex (POJO, VPackSlice or String for Json) + * @param value A representation of a single vertex (POJO or String for Json) * @return information about the vertex * @see API Documentation */ @@ -72,7 +72,7 @@ public interface ArangoVertexCollectionAsync extends ArangoSerdeAccessor { /** * Creates a new vertex in the collection * - * @param value A representation of a single vertex (POJO, VPackSlice or String for Json) + * @param value A representation of a single vertex (POJO or String for Json) * @param options Additional options, can be null * @return information about the vertex * @see API Documentation @@ -83,7 +83,7 @@ public interface ArangoVertexCollectionAsync extends ArangoSerdeAccessor { * Fetches an existing vertex * * @param key The key of the vertex - * @param type The type of the vertex-document (POJO class, VPackSlice or String for Json) + * @param type The type of the vertex-document (POJO class or String for Json) * @return the vertex identified by the key * @see API Documentation */ @@ -93,7 +93,7 @@ public interface ArangoVertexCollectionAsync extends ArangoSerdeAccessor { * Fetches an existing vertex * * @param key The key of the vertex - * @param type The type of the vertex-document (POJO class, VPackSlice or String for Json) + * @param type The type of the vertex-document (POJO class or String for Json) * @param options Additional options, can be null * @return the vertex identified by the key * @see API Documentation diff --git a/src/main/java/com/arangodb/serde/ArangoSerde.java b/src/main/java/com/arangodb/serde/ArangoSerde.java index ce56485d2..211d55422 100644 --- a/src/main/java/com/arangodb/serde/ArangoSerde.java +++ b/src/main/java/com/arangodb/serde/ArangoSerde.java @@ -1,7 +1,5 @@ package com.arangodb.serde; -import com.fasterxml.jackson.databind.ObjectMapper; - import java.lang.reflect.Type; /** @@ -17,7 +15,7 @@ * custom implementations based on Jackson Databind is by extending {@link JacksonSerde}, which exposes additional * methods based on Jackson's types. * Furthermore, existing {@link JacksonSerde} implementations can be instantiated providing a custom configured Jackson - * ObjectMapper, see {@link JacksonSerde#of(DataType, ObjectMapper)}. + * ObjectMapper, see {@link JacksonSerde#of(DataType, com.fasterxml.jackson.databind.ObjectMapper)}. */ public interface ArangoSerde { diff --git a/src/main/java/com/arangodb/serde/InternalDeserializers.java b/src/main/java/com/arangodb/serde/InternalDeserializers.java index b1666bb7f..e364988ca 100644 --- a/src/main/java/com/arangodb/serde/InternalDeserializers.java +++ b/src/main/java/com/arangodb/serde/InternalDeserializers.java @@ -6,8 +6,6 @@ import com.arangodb.entity.arangosearch.CollectionLink; import com.arangodb.entity.arangosearch.FieldLink; import com.arangodb.velocystream.Response; -import com.fasterxml.jackson.core.JacksonException; -import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.TreeNode; import com.fasterxml.jackson.databind.*; diff --git a/src/main/java/com/arangodb/serde/InternalSerde.java b/src/main/java/com/arangodb/serde/InternalSerde.java index 70f531c86..ace96b5fe 100644 --- a/src/main/java/com/arangodb/serde/InternalSerde.java +++ b/src/main/java/com/arangodb/serde/InternalSerde.java @@ -1,6 +1,5 @@ package com.arangodb.serde; -import com.arangodb.internal.ArangoResponseField; import com.arangodb.jackson.dataformat.velocypack.VPackMapper; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; diff --git a/src/main/java/com/arangodb/serde/InternalSerdeImpl.java b/src/main/java/com/arangodb/serde/InternalSerdeImpl.java index 500805004..53de21719 100644 --- a/src/main/java/com/arangodb/serde/InternalSerdeImpl.java +++ b/src/main/java/com/arangodb/serde/InternalSerdeImpl.java @@ -2,12 +2,10 @@ import com.arangodb.ArangoDBException; import com.fasterxml.jackson.annotation.JsonInclude; -import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import java.io.IOException; -import java.lang.reflect.Type; import java.nio.charset.StandardCharsets; class InternalSerdeImpl extends JacksonSerdeImpl implements InternalSerde { From 9c9d210ce601827222545984f00b96b07cfd5268 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Thu, 21 Jul 2022 15:32:17 +0200 Subject: [PATCH 040/254] simplified serde API --- .../java/com/arangodb/serde/ArangoSerde.java | 20 +++---- .../com/arangodb/serde/InternalSerde.java | 55 ++++++++++++++++--- .../com/arangodb/serde/InternalSerdeImpl.java | 36 ++++++------ .../java/com/arangodb/serde/JacksonSerde.java | 33 ++--------- .../com/arangodb/serde/JacksonSerdeImpl.java | 19 +------ 5 files changed, 76 insertions(+), 87 deletions(-) diff --git a/src/main/java/com/arangodb/serde/ArangoSerde.java b/src/main/java/com/arangodb/serde/ArangoSerde.java index 211d55422..f682ec35a 100644 --- a/src/main/java/com/arangodb/serde/ArangoSerde.java +++ b/src/main/java/com/arangodb/serde/ArangoSerde.java @@ -1,29 +1,23 @@ package com.arangodb.serde; import java.lang.reflect.Type; +import java.util.function.Consumer; /** * Contract for serialization/deserialization of user data. * Implementations of this interface could be used for customizing serialization/deserialization of user related data - * using serialization/deserialization libraries other than Jackson Databind, like: + * using serialization/deserialization libraries like: * - serialization libraries for specific JVM languages (e.g. Scala, Kotlin, ...) * - serialization libraries already in use in frameworks (e.g. JSON-B, Micronaut Serialization, ...) - * - high performance serialization libraries (e.g. supporting compile-time databinding code generation) - * - lower level libraries without support to data binding + * - high performance serialization libraries (e.g. supporting compile-time data binding code generation) + * - low-level libraries without support to data binding *

- * This interface should not be directly implemented as an adapter to Jackson Databind. A more performant way to provide - * custom implementations based on Jackson Databind is by extending {@link JacksonSerde}, which exposes additional - * methods based on Jackson's types. - * Furthermore, existing {@link JacksonSerde} implementations can be instantiated providing a custom configured Jackson - * ObjectMapper, see {@link JacksonSerde#of(DataType, com.fasterxml.jackson.databind.ObjectMapper)}. + * To create a custom serde based on Jackson, existing {@link JacksonSerde} can be reused and instantiated providing a + * custom configured ObjectMapper ({@link JacksonSerde#of(com.fasterxml.jackson.databind.ObjectMapper)}) or configured + * after creation through {@link JacksonSerde#configure(Consumer)}. */ public interface ArangoSerde { - /** - * @return the data type supported by this implementation - */ - DataType getDataType(); - /** * Serializes the object into the target data type. For data type {@link DataType#JSON}, the serialized JSON string * must be encoded into a byte array using the UTF-8 charset. diff --git a/src/main/java/com/arangodb/serde/InternalSerde.java b/src/main/java/com/arangodb/serde/InternalSerde.java index ace96b5fe..d7f161b29 100644 --- a/src/main/java/com/arangodb/serde/InternalSerde.java +++ b/src/main/java/com/arangodb/serde/InternalSerde.java @@ -16,9 +16,9 @@ public interface InternalSerde extends JacksonSerde { */ static InternalSerde of(final DataType dataType) { if (dataType == DataType.JSON) { - return new InternalSerdeImpl(dataType, new ObjectMapper()); + return new InternalSerdeImpl(new ObjectMapper()); } else if (dataType == DataType.VPACK) { - return new InternalSerdeImpl(dataType, new VPackMapper()); + return new InternalSerdeImpl(new VPackMapper()); } else { throw new IllegalArgumentException("Unexpected value: " + dataType); } @@ -37,30 +37,69 @@ static InternalSerde of(final DataType dataType) { * Used for extracting nested user data. * * @param content byte array - * @param jsonPointer location of user data + * @param jsonPointer location of data to be extracted * @return byte array */ byte[] extract(byte[] content, String jsonPointer); /** - * TODO + * Deserializes the parsed json node and binds it to the target data type. + * + * @param node parsed json node + * @param clazz class of target data type + * @return deserialized object + */ + default T deserialize(JsonNode node, Class clazz) { + return deserialize(node, (Type) clazz); + } + + /** + * Deserializes the parsed json node and binds it to the target data type. + * + * @param node parsed json node + * @param type target data type + * @return deserialized object + */ + T deserialize(JsonNode node, Type type); + + /** + * Parses the content. + * + * @param content VPack or byte encoded JSON string + * @return root of the parsed tree */ JsonNode parse(byte[] content); /** - * TODO + * Parses the content at json pointer. + * + * @param content VPack or byte encoded JSON string + * @param jsonPointer location of data to be parsed + * @return root of the parsed tree */ JsonNode parse(byte[] content, String jsonPointer); /** - * TODO + * Deserializes the content at json pointer and binds it to the target data type. + * For data type {@link DataType#JSON}, the byte array is the JSON string encoded using the UTF-8 charset. + * + * @param content byte array to deserialize + * @param jsonPointer location of data to be deserialized + * @param clazz class of target data type + * @return deserialized object */ - default T deserialize(byte[] content, String jsonPointer, Class clazz){ + default T deserialize(byte[] content, String jsonPointer, Class clazz) { return deserialize(content, jsonPointer, (Type) clazz); } /** - * TODO + * Deserializes the content at json pointer and binds it to the target data type. + * For data type {@link DataType#JSON}, the byte array is the JSON string encoded using the UTF-8 charset. + * + * @param content byte array to deserialize + * @param jsonPointer location of data to be deserialized + * @param type target data type + * @return deserialized object */ default T deserialize(byte[] content, String jsonPointer, Type type) { return deserialize(parse(content, jsonPointer), type); diff --git a/src/main/java/com/arangodb/serde/InternalSerdeImpl.java b/src/main/java/com/arangodb/serde/InternalSerdeImpl.java index 53de21719..996c9a373 100644 --- a/src/main/java/com/arangodb/serde/InternalSerdeImpl.java +++ b/src/main/java/com/arangodb/serde/InternalSerdeImpl.java @@ -6,33 +6,22 @@ import com.fasterxml.jackson.databind.ObjectMapper; import java.io.IOException; -import java.nio.charset.StandardCharsets; +import java.lang.reflect.Type; -class InternalSerdeImpl extends JacksonSerdeImpl implements InternalSerde { +final class InternalSerdeImpl extends JacksonSerdeImpl implements InternalSerde { - InternalSerdeImpl(DataType dataType, ObjectMapper mapper) { - super(dataType, mapper); + InternalSerdeImpl(ObjectMapper mapper) { + super(mapper); mapper.registerModule(InternalModule.INSTANCE.get()); mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); } @Override - // FIXME: refactor to: - // return SerdeUtils.INSTANCE.writeJson(mapper.readTree(content)); - // afterwards dataType should not be needed anymore public String toJsonString(final byte[] content) { - switch (dataType) { - case JSON: - return new String(content, StandardCharsets.UTF_8); - case VPACK: - try { - JsonNode tree = mapper.readTree(content); - return SerdeUtils.INSTANCE.writeJson(tree); - } catch (IOException e) { - throw new ArangoDBException(e); - } - default: - throw new IllegalArgumentException("Unexpected value: " + dataType); + try { + return SerdeUtils.INSTANCE.writeJson(mapper.readTree(content)); + } catch (IOException e) { + throw new ArangoDBException(e); } } @@ -64,4 +53,13 @@ public JsonNode parse(byte[] content, String jsonPointer) { } } + @Override + public T deserialize(final JsonNode node, final Type type) { + try { + return mapper.readerFor(mapper.constructType(type)).readValue(node); + } catch (IOException e) { + throw new ArangoDBException(e); + } + } + } diff --git a/src/main/java/com/arangodb/serde/JacksonSerde.java b/src/main/java/com/arangodb/serde/JacksonSerde.java index 901266c70..c7c0ae2f0 100644 --- a/src/main/java/com/arangodb/serde/JacksonSerde.java +++ b/src/main/java/com/arangodb/serde/JacksonSerde.java @@ -1,16 +1,12 @@ package com.arangodb.serde; import com.arangodb.jackson.dataformat.velocypack.VPackMapper; -import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; -import java.lang.reflect.Type; import java.util.function.Consumer; /** * Contract for serialization/deserialization of user data, based on Jackson Databind. - * In comparison to {@link ArangoSerde}, this API improves the deserialization performance by allowing reusing the JSON - * tree already parsed by the root deserializer. */ public interface JacksonSerde extends ArangoSerde { @@ -22,9 +18,9 @@ public interface JacksonSerde extends ArangoSerde { */ static JacksonSerde of(final DataType dataType) { if (dataType == DataType.JSON) { - return of(dataType, new ObjectMapper()); + return of(new ObjectMapper()); } else if (dataType == DataType.VPACK) { - return of(dataType, new VPackMapper()); + return of(new VPackMapper()); } else { throw new IllegalArgumentException("Unexpected value: " + dataType); } @@ -33,12 +29,11 @@ static JacksonSerde of(final DataType dataType) { /** * Creates a new JacksonSerde using the provided ObjectMapper. * - * @param dataType serialization target data type * @param mapper Jackson ObjectMapper to use * @return the created JacksonSerde */ - static JacksonSerde of(final DataType dataType, final ObjectMapper mapper) { - return new JacksonSerdeImpl(dataType, mapper); + static JacksonSerde of(final ObjectMapper mapper) { + return new JacksonSerdeImpl(mapper); } /** @@ -47,24 +42,4 @@ static JacksonSerde of(final DataType dataType, final ObjectMapper mapper) { */ void configure(final Consumer configureFunction); - /** - * Deserializes the parsed json node and binds it to the target data type. - * - * @param node parsed json node - * @param clazz class of target data type - * @return deserialized object - */ - default T deserialize(JsonNode node, Class clazz) { - return deserialize(node, (Type) clazz); - } - - /** - * Deserializes the parsed json node and binds it to the target data type. - * - * @param node parsed json node - * @param type target data type - * @return deserialized object - */ - T deserialize(JsonNode node, Type type); - } diff --git a/src/main/java/com/arangodb/serde/JacksonSerdeImpl.java b/src/main/java/com/arangodb/serde/JacksonSerdeImpl.java index ece832a30..11f56ab1f 100644 --- a/src/main/java/com/arangodb/serde/JacksonSerdeImpl.java +++ b/src/main/java/com/arangodb/serde/JacksonSerdeImpl.java @@ -3,7 +3,6 @@ import com.arangodb.ArangoDBException; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.DeserializationFeature; -import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import java.io.IOException; @@ -12,20 +11,13 @@ class JacksonSerdeImpl implements JacksonSerde { - protected final DataType dataType; protected final ObjectMapper mapper; - JacksonSerdeImpl(final DataType dataType, final ObjectMapper mapper) { - this.dataType = dataType; + JacksonSerdeImpl(final ObjectMapper mapper) { this.mapper = mapper; mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); } - @Override - public DataType getDataType() { - return dataType; - } - @Override public byte[] serialize(final Object value) { try { @@ -49,13 +41,4 @@ public void configure(Consumer configureFunction) { configureFunction.accept(mapper); } - @Override - public T deserialize(final JsonNode node, final Type type) { - try { - return mapper.readerFor(mapper.constructType(type)).readValue(node); - } catch (IOException e) { - throw new ArangoDBException(e); - } - } - } From 821e4d7a25ee48ec3e454954074a8632c0668e40 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Fri, 22 Jul 2022 10:17:00 +0200 Subject: [PATCH 041/254] removed CursorEntity from public API --- src/main/java/com/arangodb/ArangoCursor.java | 8 +- .../async/internal/ArangoCursorAsyncImpl.java | 4 +- .../internal/ArangoDatabaseAsyncImpl.java | 13 ++-- .../java/com/arangodb/entity/CursorStats.java | 44 +++++++++++ .../com/arangodb/entity/CursorWarning.java | 16 ++++ .../internal/ArangoCursorExecute.java | 4 +- .../arangodb/internal/ArangoDatabaseImpl.java | 14 ++-- .../internal/cursor/ArangoCursorImpl.java | 15 ++-- .../internal/cursor/ArangoCursorIterator.java | 7 +- .../cursor/InternalCursorEntity.java} | 75 +++---------------- .../util/ArangoCursorInitializer.java | 4 +- .../java/com/arangodb/ArangoDatabaseTest.java | 3 +- 12 files changed, 106 insertions(+), 101 deletions(-) create mode 100644 src/main/java/com/arangodb/entity/CursorStats.java create mode 100644 src/main/java/com/arangodb/entity/CursorWarning.java rename src/main/java/com/arangodb/{entity/CursorEntity.java => internal/cursor/InternalCursorEntity.java} (66%) diff --git a/src/main/java/com/arangodb/ArangoCursor.java b/src/main/java/com/arangodb/ArangoCursor.java index eab1e2a88..928f14239 100644 --- a/src/main/java/com/arangodb/ArangoCursor.java +++ b/src/main/java/com/arangodb/ArangoCursor.java @@ -20,8 +20,8 @@ package com.arangodb; -import com.arangodb.entity.CursorEntity.Stats; -import com.arangodb.entity.CursorEntity.Warning; +import com.arangodb.entity.CursorStats; +import com.arangodb.entity.CursorWarning; import java.io.Closeable; import java.util.Collection; @@ -53,12 +53,12 @@ public interface ArangoCursor extends ArangoIterable, ArangoIterator, C * number of modified documents and the number of documents that could not be modified due to an error (if * ignoreErrors query option is specified) */ - Stats getStats(); + CursorStats getStats(); /** * @return warnings which the query could have been produced */ - Collection getWarnings(); + Collection getWarnings(); /** * @return indicating whether the query result was served from the query cache or not diff --git a/src/main/java/com/arangodb/async/internal/ArangoCursorAsyncImpl.java b/src/main/java/com/arangodb/async/internal/ArangoCursorAsyncImpl.java index 14988eca3..f2ac9c93b 100644 --- a/src/main/java/com/arangodb/async/internal/ArangoCursorAsyncImpl.java +++ b/src/main/java/com/arangodb/async/internal/ArangoCursorAsyncImpl.java @@ -21,7 +21,7 @@ package com.arangodb.async.internal; import com.arangodb.async.ArangoCursorAsync; -import com.arangodb.entity.CursorEntity; +import com.arangodb.internal.cursor.InternalCursorEntity; import com.arangodb.internal.ArangoCursorExecute; import com.arangodb.internal.InternalArangoDatabase; import com.arangodb.internal.cursor.ArangoCursorImpl; @@ -37,7 +37,7 @@ public class ArangoCursorAsyncImpl extends ArangoCursorImpl implements ArangoCursorAsync { ArangoCursorAsyncImpl(final InternalArangoDatabase db, final ArangoCursorExecute execute, - final Class type, final CursorEntity result) { + final Class type, final InternalCursorEntity result) { super(db, execute, type, result); } diff --git a/src/main/java/com/arangodb/async/internal/ArangoDatabaseAsyncImpl.java b/src/main/java/com/arangodb/async/internal/ArangoDatabaseAsyncImpl.java index 629783023..22f300325 100644 --- a/src/main/java/com/arangodb/async/internal/ArangoDatabaseAsyncImpl.java +++ b/src/main/java/com/arangodb/async/internal/ArangoDatabaseAsyncImpl.java @@ -28,6 +28,7 @@ import com.arangodb.internal.ArangoCursorExecute; import com.arangodb.internal.ArangoErrors; import com.arangodb.internal.InternalArangoDatabase; +import com.arangodb.internal.cursor.InternalCursorEntity; import com.arangodb.internal.net.HostHandle; import com.arangodb.internal.util.DocumentUtil; import com.arangodb.model.*; @@ -178,7 +179,7 @@ public CompletableFuture> query( final Class type) { final Request request = queryRequest(query, bindVars, options); final HostHandle hostHandle = new HostHandle(); - final CompletableFuture execution = executor.execute(request, CursorEntity.class, hostHandle); + final CompletableFuture execution = executor.execute(request, InternalCursorEntity.class, hostHandle); return execution.thenApply(result -> createCursor(result, type, options, hostHandle)); } @@ -206,20 +207,20 @@ public CompletableFuture> query(final String query, fin @Override public CompletableFuture> cursor(final String cursorId, final Class type) { final HostHandle hostHandle = new HostHandle(); - final CompletableFuture execution = executor.execute(queryNextRequest(cursorId, null, null), CursorEntity.class, hostHandle); + final CompletableFuture execution = executor.execute(queryNextRequest(cursorId, null, null), InternalCursorEntity.class, hostHandle); return execution.thenApply(result -> createCursor(result, type, null, hostHandle)); } private ArangoCursorAsync createCursor( - final CursorEntity result, + final InternalCursorEntity result, final Class type, final AqlQueryOptions options, final HostHandle hostHandle) { return new ArangoCursorAsyncImpl<>(this, new ArangoCursorExecute() { @Override - public CursorEntity next(final String id, Map meta) { - final CompletableFuture result = executor.execute(queryNextRequest(id, options, meta), - CursorEntity.class, hostHandle); + public InternalCursorEntity next(final String id, Map meta) { + final CompletableFuture result = executor.execute(queryNextRequest(id, options, meta), + InternalCursorEntity.class, hostHandle); try { return result.get(); } catch (InterruptedException | ExecutionException e) { diff --git a/src/main/java/com/arangodb/entity/CursorStats.java b/src/main/java/com/arangodb/entity/CursorStats.java new file mode 100644 index 000000000..2bf822561 --- /dev/null +++ b/src/main/java/com/arangodb/entity/CursorStats.java @@ -0,0 +1,44 @@ +package com.arangodb.entity; + +public final class CursorStats { + private Long writesExecuted; + private Long writesIgnored; + private Long scannedFull; + private Long scannedIndex; + private Long filtered; + private Long fullCount; + private Double executionTime; + private Long peakMemoryUsage; + + public Long getWritesExecuted() { + return writesExecuted; + } + + public Long getWritesIgnored() { + return writesIgnored; + } + + public Long getScannedFull() { + return scannedFull; + } + + public Long getScannedIndex() { + return scannedIndex; + } + + public Long getFiltered() { + return filtered; + } + + public Long getFullCount() { + return fullCount; + } + + public Double getExecutionTime() { + return executionTime; + } + + public Long getPeakMemoryUsage() { + return peakMemoryUsage; + } +} diff --git a/src/main/java/com/arangodb/entity/CursorWarning.java b/src/main/java/com/arangodb/entity/CursorWarning.java new file mode 100644 index 000000000..72dc8ff1c --- /dev/null +++ b/src/main/java/com/arangodb/entity/CursorWarning.java @@ -0,0 +1,16 @@ +package com.arangodb.entity; + +public final class CursorWarning { + + private Integer code; + private String message; + + public Integer getCode() { + return code; + } + + public String getMessage() { + return message; + } + +} diff --git a/src/main/java/com/arangodb/internal/ArangoCursorExecute.java b/src/main/java/com/arangodb/internal/ArangoCursorExecute.java index 455844113..b9462b076 100644 --- a/src/main/java/com/arangodb/internal/ArangoCursorExecute.java +++ b/src/main/java/com/arangodb/internal/ArangoCursorExecute.java @@ -21,7 +21,7 @@ package com.arangodb.internal; import com.arangodb.ArangoDBException; -import com.arangodb.entity.CursorEntity; +import com.arangodb.internal.cursor.InternalCursorEntity; import java.util.Map; @@ -30,7 +30,7 @@ */ public interface ArangoCursorExecute { - CursorEntity next(String id, Map meta) throws ArangoDBException; + InternalCursorEntity next(String id, Map meta) throws ArangoDBException; void close(String id, Map meta) throws ArangoDBException; diff --git a/src/main/java/com/arangodb/internal/ArangoDatabaseImpl.java b/src/main/java/com/arangodb/internal/ArangoDatabaseImpl.java index 2a834d948..3c1ad65e2 100644 --- a/src/main/java/com/arangodb/internal/ArangoDatabaseImpl.java +++ b/src/main/java/com/arangodb/internal/ArangoDatabaseImpl.java @@ -24,6 +24,7 @@ import com.arangodb.entity.*; import com.arangodb.entity.arangosearch.analyzer.SearchAnalyzer; import com.arangodb.internal.cursor.ArangoCursorImpl; +import com.arangodb.internal.cursor.InternalCursorEntity; import com.arangodb.internal.net.HostHandle; import com.arangodb.internal.util.DocumentUtil; import com.arangodb.model.*; @@ -35,7 +36,6 @@ import java.util.Collection; import java.util.Collections; -import java.util.List; import java.util.Map; /** @@ -168,7 +168,7 @@ public ArangoCursor query( final Request request = queryRequest(query, bindVars, options); final HostHandle hostHandle = new HostHandle(); - final CursorEntity result = executor.execute(request, CursorEntity.class, hostHandle); + final InternalCursorEntity result = executor.execute(request, InternalCursorEntity.class, hostHandle); return createCursor(result, type, options, hostHandle); @@ -194,21 +194,21 @@ public ArangoCursor query(final String query, final Class type) throws @Override public ArangoCursor cursor(final String cursorId, final Class type) throws ArangoDBException { final HostHandle hostHandle = new HostHandle(); - final CursorEntity result = executor - .execute(queryNextRequest(cursorId, null, null), CursorEntity.class, hostHandle); + final InternalCursorEntity result = executor + .execute(queryNextRequest(cursorId, null, null), InternalCursorEntity.class, hostHandle); return createCursor(result, type, null, hostHandle); } private ArangoCursor createCursor( - final CursorEntity result, + final InternalCursorEntity result, final Class type, final AqlQueryOptions options, final HostHandle hostHandle) { final ArangoCursorExecute execute = new ArangoCursorExecute() { @Override - public CursorEntity next(final String id, Map meta) { - return executor.execute(queryNextRequest(id, options, meta), CursorEntity.class, hostHandle); + public InternalCursorEntity next(final String id, Map meta) { + return executor.execute(queryNextRequest(id, options, meta), InternalCursorEntity.class, hostHandle); } @Override diff --git a/src/main/java/com/arangodb/internal/cursor/ArangoCursorImpl.java b/src/main/java/com/arangodb/internal/cursor/ArangoCursorImpl.java index 1de76a083..40ece0f7d 100644 --- a/src/main/java/com/arangodb/internal/cursor/ArangoCursorImpl.java +++ b/src/main/java/com/arangodb/internal/cursor/ArangoCursorImpl.java @@ -22,10 +22,9 @@ import com.arangodb.ArangoCursor; import com.arangodb.ArangoIterator; -import com.arangodb.entity.CursorEntity; -import com.arangodb.entity.CursorEntity.Extras; -import com.arangodb.entity.CursorEntity.Stats; -import com.arangodb.entity.CursorEntity.Warning; +import com.arangodb.entity.CursorStats; +import com.arangodb.entity.CursorWarning; +import com.arangodb.internal.cursor.InternalCursorEntity.Extras; import com.arangodb.internal.ArangoCursorExecute; import com.arangodb.internal.InternalArangoDatabase; @@ -44,7 +43,7 @@ public class ArangoCursorImpl extends AbstractArangoIterable implements Ar private final ArangoCursorExecute execute; public ArangoCursorImpl(final InternalArangoDatabase db, final ArangoCursorExecute execute, - final Class type, final CursorEntity result) { + final Class type, final InternalCursorEntity result) { super(); this.execute = execute; this.type = type; @@ -56,7 +55,7 @@ protected ArangoCursorIterator createIterator( final ArangoCursor cursor, final InternalArangoDatabase db, final ArangoCursorExecute execute, - final CursorEntity result) { + final InternalCursorEntity result) { return new ArangoCursorIterator<>(cursor, execute, db, result); } @@ -76,13 +75,13 @@ public Integer getCount() { } @Override - public Stats getStats() { + public CursorStats getStats() { final Extras extra = iterator.getResult().getExtra(); return extra != null ? extra.getStats() : null; } @Override - public Collection getWarnings() { + public Collection getWarnings() { final Extras extra = iterator.getResult().getExtra(); return extra != null ? extra.getWarnings() : null; } diff --git a/src/main/java/com/arangodb/internal/cursor/ArangoCursorIterator.java b/src/main/java/com/arangodb/internal/cursor/ArangoCursorIterator.java index ad9afbac0..a89191cb8 100644 --- a/src/main/java/com/arangodb/internal/cursor/ArangoCursorIterator.java +++ b/src/main/java/com/arangodb/internal/cursor/ArangoCursorIterator.java @@ -22,7 +22,6 @@ import com.arangodb.ArangoCursor; import com.arangodb.ArangoIterator; -import com.arangodb.entity.CursorEntity; import com.arangodb.internal.ArangoCursorExecute; import com.arangodb.internal.InternalArangoDatabase; import com.fasterxml.jackson.databind.JsonNode; @@ -36,7 +35,7 @@ */ public class ArangoCursorIterator implements ArangoIterator { - private CursorEntity result; + private InternalCursorEntity result; private Iterator arrayIterator; private final ArangoCursor cursor; @@ -44,7 +43,7 @@ public class ArangoCursorIterator implements ArangoIterator { private final ArangoCursorExecute execute; protected ArangoCursorIterator(final ArangoCursor cursor, final ArangoCursorExecute execute, - final InternalArangoDatabase db, final CursorEntity result) { + final InternalArangoDatabase db, final InternalCursorEntity result) { super(); this.cursor = cursor; this.execute = execute; @@ -53,7 +52,7 @@ protected ArangoCursorIterator(final ArangoCursor cursor, final ArangoCursorE arrayIterator = result.getResult().iterator(); } - public CursorEntity getResult() { + public InternalCursorEntity getResult() { return result; } diff --git a/src/main/java/com/arangodb/entity/CursorEntity.java b/src/main/java/com/arangodb/internal/cursor/InternalCursorEntity.java similarity index 66% rename from src/main/java/com/arangodb/entity/CursorEntity.java rename to src/main/java/com/arangodb/internal/cursor/InternalCursorEntity.java index e205a2d79..a85999902 100644 --- a/src/main/java/com/arangodb/entity/CursorEntity.java +++ b/src/main/java/com/arangodb/internal/cursor/InternalCursorEntity.java @@ -18,8 +18,11 @@ * Copyright holder is ArangoDB GmbH, Cologne, Germany */ -package com.arangodb.entity; +package com.arangodb.internal.cursor; +import com.arangodb.entity.CursorStats; +import com.arangodb.entity.CursorWarning; +import com.arangodb.entity.MetaAware; import com.fasterxml.jackson.databind.JsonNode; import java.util.Collection; @@ -31,7 +34,7 @@ * @see API * Documentation */ -public final class CursorEntity implements MetaAware { +public final class InternalCursorEntity implements MetaAware { private String id; private Integer count; @@ -81,7 +84,7 @@ public Boolean getHasMore() { } /** - * @return an vpack-array of result documents (might be empty if query has no results) + * @return an array of result documents (might be empty if query has no results) */ public JsonNode getResult() { return result; @@ -105,75 +108,19 @@ public void setMeta(Map meta) { this.meta = cleanupMeta(meta); } - public static final class Warning { - - private Integer code; - private String message; - - public Integer getCode() { - return code; - } - - public String getMessage() { - return message; - } - - } - public static final class Extras { - private Stats stats; - private Collection warnings = Collections.emptyList(); + private CursorStats stats; + private Collection warnings = Collections.emptyList(); - public Stats getStats() { + public CursorStats getStats() { return stats; } - public Collection getWarnings() { + public Collection getWarnings() { return warnings; } } - public static final class Stats { - private Long writesExecuted; - private Long writesIgnored; - private Long scannedFull; - private Long scannedIndex; - private Long filtered; - private Long fullCount; - private Double executionTime; - private Long peakMemoryUsage; - - public Long getWritesExecuted() { - return writesExecuted; - } - - public Long getWritesIgnored() { - return writesIgnored; - } - - public Long getScannedFull() { - return scannedFull; - } - - public Long getScannedIndex() { - return scannedIndex; - } - - public Long getFiltered() { - return filtered; - } - - public Long getFullCount() { - return fullCount; - } - - public Double getExecutionTime() { - return executionTime; - } - - public Long getPeakMemoryUsage() { - return peakMemoryUsage; - } - } } + diff --git a/src/main/java/com/arangodb/util/ArangoCursorInitializer.java b/src/main/java/com/arangodb/util/ArangoCursorInitializer.java index bc2da8378..9d0b2169c 100644 --- a/src/main/java/com/arangodb/util/ArangoCursorInitializer.java +++ b/src/main/java/com/arangodb/util/ArangoCursorInitializer.java @@ -21,7 +21,7 @@ package com.arangodb.util; import com.arangodb.ArangoCursor; -import com.arangodb.entity.CursorEntity; +import com.arangodb.internal.cursor.InternalCursorEntity; import com.arangodb.internal.ArangoCursorExecute; import com.arangodb.internal.InternalArangoDatabase; @@ -34,6 +34,6 @@ ArangoCursor createInstance( final InternalArangoDatabase db, final ArangoCursorExecute execute, final Class type, - final CursorEntity result); + final InternalCursorEntity result); } diff --git a/src/test/java/com/arangodb/ArangoDatabaseTest.java b/src/test/java/com/arangodb/ArangoDatabaseTest.java index a5996fc39..da017d860 100644 --- a/src/test/java/com/arangodb/ArangoDatabaseTest.java +++ b/src/test/java/com/arangodb/ArangoDatabaseTest.java @@ -22,7 +22,6 @@ import com.arangodb.entity.*; import com.arangodb.entity.AqlExecutionExplainEntity.ExecutionPlan; -import com.arangodb.entity.CursorEntity.Warning; import com.arangodb.entity.QueryCachePropertiesEntity.CacheMode; import com.arangodb.model.*; import com.arangodb.util.MapBuilder; @@ -751,7 +750,7 @@ void queryWithMaxWarningCount(ArangoDatabase db) { assertThat(cursorWithWarnings.getWarnings()).hasSize(1); final ArangoCursor cursorWithLimitedWarnings = db .query("RETURN 1 / 0", null, new AqlQueryOptions().maxWarningCount(0L), String.class); - final Collection warnings = cursorWithLimitedWarnings.getWarnings(); + final Collection warnings = cursorWithLimitedWarnings.getWarnings(); assertThat(warnings).isNullOrEmpty(); } From 9e10e8cf5149db171b6b4d5892324ec16c417dba Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Fri, 22 Jul 2022 12:17:56 +0200 Subject: [PATCH 042/254] RawJson and RawBytes --- .../arangodb/serde/InternalDeserializers.java | 24 ++++++++++ .../com/arangodb/serde/InternalModule.java | 6 +++ .../arangodb/serde/InternalSerializers.java | 20 ++++++++ src/main/java/com/arangodb/util/RawBytes.java | 47 +++++++++++++++++++ src/main/java/com/arangodb/util/RawJson.java | 41 ++++++++++++++++ .../java/com/arangodb/serde/SerdeTest.java | 38 +++++++++++++++ 6 files changed, 176 insertions(+) create mode 100644 src/main/java/com/arangodb/util/RawBytes.java create mode 100644 src/main/java/com/arangodb/util/RawJson.java create mode 100644 src/test/java/com/arangodb/serde/SerdeTest.java diff --git a/src/main/java/com/arangodb/serde/InternalDeserializers.java b/src/main/java/com/arangodb/serde/InternalDeserializers.java index e364988ca..0a33aa444 100644 --- a/src/main/java/com/arangodb/serde/InternalDeserializers.java +++ b/src/main/java/com/arangodb/serde/InternalDeserializers.java @@ -5,7 +5,10 @@ import com.arangodb.entity.ReplicationFactor; import com.arangodb.entity.arangosearch.CollectionLink; import com.arangodb.entity.arangosearch.FieldLink; +import com.arangodb.util.RawBytes; +import com.arangodb.util.RawJson; import com.arangodb.velocystream.Response; +import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.TreeNode; import com.fasterxml.jackson.databind.*; @@ -14,6 +17,7 @@ import com.fasterxml.jackson.databind.node.ObjectNode; import com.fasterxml.jackson.databind.node.TextNode; +import java.io.ByteArrayOutputStream; import java.io.IOException; import java.util.ArrayList; import java.util.Collection; @@ -67,6 +71,26 @@ public String deserialize(JsonParser p, DeserializationContext ctxt) throws IOEx private InternalDeserializers() { } + static final JsonDeserializer RAW_JSON_DESERIALIZER = new JsonDeserializer() { + @Override + public RawJson deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { + // TODO: find a way to access raw bytes directly + return RawJson.of(SerdeUtils.INSTANCE.writeJson(p.readValueAsTree())); + } + }; + + static final JsonDeserializer RAW_BYTES_DESERIALIZER = new JsonDeserializer() { + @Override + public RawBytes deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { + // TODO: find a way to access raw bytes directly + ByteArrayOutputStream os = new ByteArrayOutputStream(); + try (JsonGenerator g = p.getCodec().getFactory().createGenerator(os)) { + g.writeTree(p.readValueAsTree()); + } + return RawBytes.of(os.toByteArray()); + } + }; + static final JsonDeserializer COLLECTION_STATUS = new JsonDeserializer() { @Override public CollectionStatus deserialize(final JsonParser p, final DeserializationContext ctxt) throws IOException { diff --git a/src/main/java/com/arangodb/serde/InternalModule.java b/src/main/java/com/arangodb/serde/InternalModule.java index fe7418f17..407590d7a 100644 --- a/src/main/java/com/arangodb/serde/InternalModule.java +++ b/src/main/java/com/arangodb/serde/InternalModule.java @@ -5,6 +5,8 @@ import com.arangodb.entity.ReplicationFactor; import com.arangodb.internal.velocystream.internal.AuthenticationRequest; import com.arangodb.internal.velocystream.internal.JwtAuthenticationRequest; +import com.arangodb.util.RawBytes; +import com.arangodb.util.RawJson; import com.arangodb.velocystream.Request; import com.arangodb.velocystream.Response; import com.fasterxml.jackson.databind.Module; @@ -20,11 +22,15 @@ enum InternalModule implements Supplier { InternalModule() { module = new SimpleModule(); + module.addSerializer(RawJson.class, InternalSerializers.RAW_JSON_SERIALIZER); + module.addSerializer(RawBytes.class, InternalSerializers.RAW_BYTES_SERIALIZER); module.addSerializer(AuthenticationRequest.class, InternalSerializers.AUTHENTICATION_REQUEST); module.addSerializer(JwtAuthenticationRequest.class, InternalSerializers.JWT_AUTHENTICATION_REQUEST); module.addSerializer(Request.class, InternalSerializers.REQUEST); module.addSerializer(CollectionType.class, InternalSerializers.COLLECTION_TYPE); + module.addDeserializer(RawJson.class, InternalDeserializers.RAW_JSON_DESERIALIZER); + module.addDeserializer(RawBytes.class, InternalDeserializers.RAW_BYTES_DESERIALIZER); module.addDeserializer(CollectionStatus.class, InternalDeserializers.COLLECTION_STATUS); module.addDeserializer(CollectionType.class, InternalDeserializers.COLLECTION_TYPE); module.addDeserializer(ReplicationFactor.class, InternalDeserializers.REPLICATION_FACTOR); diff --git a/src/main/java/com/arangodb/serde/InternalSerializers.java b/src/main/java/com/arangodb/serde/InternalSerializers.java index 11aeb9a26..6d951e2d5 100644 --- a/src/main/java/com/arangodb/serde/InternalSerializers.java +++ b/src/main/java/com/arangodb/serde/InternalSerializers.java @@ -5,6 +5,8 @@ import com.arangodb.entity.arangosearch.FieldLink; import com.arangodb.internal.velocystream.internal.AuthenticationRequest; import com.arangodb.internal.velocystream.internal.JwtAuthenticationRequest; +import com.arangodb.util.RawBytes; +import com.arangodb.util.RawJson; import com.arangodb.velocystream.Request; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.core.JsonParser; @@ -61,6 +63,24 @@ public void serialize(Collection value, JsonGenerator gen, Seria private InternalSerializers() { } + static final JsonSerializer RAW_JSON_SERIALIZER = new JsonSerializer() { + @Override + public void serialize(RawJson value, JsonGenerator gen, SerializerProvider serializers) throws IOException { + gen.writeTree(SerdeUtils.INSTANCE.parseJson(value.getValue())); + } + }; + + static final JsonSerializer RAW_BYTES_SERIALIZER = new JsonSerializer() { + @Override + public void serialize(RawBytes value, JsonGenerator gen, SerializerProvider serializers) throws IOException { + // TODO: find a way to append raw bytes directly + // see https://github.com/FasterXML/jackson-dataformats-binary/issues/331 + try (JsonParser parser = gen.getCodec().getFactory().createParser(value.getValue())) { + gen.writeTree(parser.readValueAsTree()); + } + } + }; + static final JsonSerializer AUTHENTICATION_REQUEST = new JsonSerializer() { @Override public void serialize(AuthenticationRequest value, JsonGenerator gen, SerializerProvider serializers) throws IOException { diff --git a/src/main/java/com/arangodb/util/RawBytes.java b/src/main/java/com/arangodb/util/RawBytes.java new file mode 100644 index 000000000..249713075 --- /dev/null +++ b/src/main/java/com/arangodb/util/RawBytes.java @@ -0,0 +1,47 @@ +package com.arangodb.util; + +import java.util.Arrays; + +/** + * Helper class used to encapsulate raw value serialized as byte array. + * It can be used: + * - in serialization to append an already serialized raw value as is + * - in deserialization as target wrapper type for the raw value + *

+ * No validation is performed, the user is responsible for providing a valid byte array for the used content type. + *

+ * The raw value byte array can represent either: + * - a valid VPack + * - a valid JSON UTF-8 encoded string + *

+ * The driver's {@link com.arangodb.serde.InternalSerde} supports serializing and deserializing to and from + * {@code RawBytes}. + */ +public class RawBytes { + private final byte[] value; + + public static RawBytes of(final byte[] value) { + return new RawBytes(value); + } + + protected RawBytes(final byte[] value) { + this.value = value; + } + + public byte[] getValue() { + return value; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + RawBytes rawBytes = (RawBytes) o; + return Arrays.equals(getValue(), rawBytes.getValue()); + } + + @Override + public int hashCode() { + return Arrays.hashCode(getValue()); + } +} diff --git a/src/main/java/com/arangodb/util/RawJson.java b/src/main/java/com/arangodb/util/RawJson.java new file mode 100644 index 000000000..8aec5b9a3 --- /dev/null +++ b/src/main/java/com/arangodb/util/RawJson.java @@ -0,0 +1,41 @@ +package com.arangodb.util; + +import java.util.Objects; + +/** + * Helper class used to encapsulate raw JSON string. + * It can be used: + * - in serialization to append a raw JSON node + * - in deserialization as target wrapper type for the raw JSON string + *

+ * The driver's {@link com.arangodb.serde.InternalSerde} supports serializing and deserializing to and from + * {@code RawJson}. + */ +public class RawJson { + private final String value; + + public static RawJson of(final String value) { + return new RawJson(value); + } + + protected RawJson(final String value) { + this.value = value; + } + + public String getValue() { + return value; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + RawJson rawJson = (RawJson) o; + return Objects.equals(getValue(), rawJson.getValue()); + } + + @Override + public int hashCode() { + return Objects.hash(getValue()); + } +} diff --git a/src/test/java/com/arangodb/serde/SerdeTest.java b/src/test/java/com/arangodb/serde/SerdeTest.java new file mode 100644 index 000000000..d1e315ff6 --- /dev/null +++ b/src/test/java/com/arangodb/serde/SerdeTest.java @@ -0,0 +1,38 @@ +package com.arangodb.serde; + +import com.arangodb.util.RawBytes; +import com.arangodb.util.RawJson; +import com.fasterxml.jackson.databind.node.JsonNodeFactory; +import com.fasterxml.jackson.databind.node.ObjectNode; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.EnumSource; + + +import static org.assertj.core.api.Assertions.assertThat; + + +class SerdeTest { + + @ParameterizedTest + @EnumSource(DataType.class) + void rawJsonSerde(DataType type) { + InternalSerde s = InternalSerde.of(type); + ObjectNode node = JsonNodeFactory.instance.objectNode().put("foo", "bar"); + RawJson raw = RawJson.of(SerdeUtils.INSTANCE.writeJson(node)); + byte[] serialized = s.serialize(raw); + RawJson deserialized = s.deserialize(serialized, RawJson.class); + assertThat(deserialized).isEqualTo(raw); + } + + @ParameterizedTest + @EnumSource(DataType.class) + void rawBytesSerde(DataType type) { + InternalSerde s = InternalSerde.of(type); + ObjectNode node = JsonNodeFactory.instance.objectNode().put("foo", "bar"); + RawBytes raw = RawBytes.of(s.serialize(node)); + byte[] serialized = s.serialize(raw); + RawBytes deserialized = s.deserialize(serialized, RawBytes.class); + assertThat(deserialized).isEqualTo(raw); + } + +} From 9bf180822e48df48d8e2f29981b804a81119b3e2 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Fri, 22 Jul 2022 14:30:22 +0200 Subject: [PATCH 043/254] refactoring: user serde inside internal serde --- src/main/java/com/arangodb/ArangoDB.java | 11 +- .../com/arangodb/ArangoSerdeAccessor.java | 2 +- .../com/arangodb/async/ArangoDBAsync.java | 9 +- .../async/internal/ArangoDBAsyncImpl.java | 12 +- .../async/internal/ArangoExecutorAsync.java | 4 +- .../com/arangodb/internal/ArangoDBImpl.java | 10 +- .../arangodb/internal/ArangoExecuteable.java | 13 +- .../com/arangodb/internal/ArangoExecutor.java | 13 +- .../arangodb/internal/ArangoExecutorSync.java | 4 +- .../internal/InternalArangoCollection.java | 138 +++++++++--------- .../arangodb/internal/InternalArangoDB.java | 30 ++-- .../internal/InternalArangoDatabase.java | 66 ++++----- .../InternalArangoEdgeCollection.java | 16 +- .../internal/InternalArangoGraph.java | 18 +-- .../internal/InternalArangoRoute.java | 4 +- .../internal/InternalArangoSearch.java | 4 +- .../InternalArangoVertexCollection.java | 18 +-- .../arangodb/internal/InternalArangoView.java | 4 +- .../internal/cursor/ArangoCursorIterator.java | 4 +- .../internal/util/ArangoSerdeFactory.java | 48 ------ .../com/arangodb/serde/InternalSerde.java | 38 ++++- .../com/arangodb/serde/InternalSerdeImpl.java | 38 ++++- src/test/java/com/arangodb/ArangoDBTest.java | 2 +- .../java/com/arangodb/ArangoRouteTest.java | 2 +- src/test/java/com/arangodb/JwtAuthTest.java | 2 +- .../java/com/arangodb/async/ArangoDBTest.java | 4 +- .../java/com/arangodb/async/JwtAuthTest.java | 2 +- .../java/com/arangodb/serde/SerdeTest.java | 4 +- 28 files changed, 267 insertions(+), 253 deletions(-) delete mode 100644 src/main/java/com/arangodb/internal/util/ArangoSerdeFactory.java diff --git a/src/main/java/com/arangodb/ArangoDB.java b/src/main/java/com/arangodb/ArangoDB.java index 3ac79ee8d..9b112c97e 100644 --- a/src/main/java/com/arangodb/ArangoDB.java +++ b/src/main/java/com/arangodb/ArangoDB.java @@ -28,7 +28,7 @@ import com.arangodb.internal.http.HttpCommunication; import com.arangodb.internal.http.HttpConnectionFactory; import com.arangodb.internal.net.*; -import com.arangodb.internal.util.ArangoSerdeFactory; +import com.arangodb.serde.InternalSerde; import com.arangodb.internal.velocystream.VstCommunicationSync; import com.arangodb.internal.velocystream.VstConnectionFactorySync; import com.arangodb.model.DBCreateOptions; @@ -347,9 +347,8 @@ public synchronized ArangoDB build() { if (hosts.isEmpty()) { hosts.add(host); } - final InternalSerde internal = InternalSerde.of(DataType.of(protocol)); - final ArangoSerde custom = customSerializer != null ? customSerializer : JacksonSerde.of(DataType.of(protocol)); - final ArangoSerdeFactory util = new ArangoSerdeFactory(internal, custom); + final ArangoSerde userSerde = customSerializer != null ? customSerializer : JacksonSerde.of(DataType.of(protocol)); + final InternalSerde serde = InternalSerde.of(DataType.of(protocol), userSerde); int protocolMaxConnections = protocol == Protocol.VST ? ArangoDefaults.MAX_CONNECTIONS_VST_DEFAULT : @@ -358,7 +357,7 @@ public synchronized ArangoDB build() { final ConnectionFactory connectionFactory = (protocol == null || Protocol.VST == protocol) ? new VstConnectionFactorySync(host, timeout, connectionTtl, keepAliveInterval, useSsl, sslContext) - : new HttpConnectionFactory(timeout, user, password, useSsl, sslContext, hostnameVerifier, internal, + : new HttpConnectionFactory(timeout, user, password, useSsl, sslContext, hostnameVerifier, serde, protocol, connectionTtl, httpCookieSpec, httpRequestRetryHandler); final Collection hostList = createHostList(max, connectionFactory); @@ -371,7 +370,7 @@ public synchronized ArangoDB build() { .jwt(jwt).useSsl(useSsl).sslContext(sslContext).chunksize(chunksize) .maxConnections(maxConnections).connectionTtl(connectionTtl), new HttpCommunication.Builder(hostHandler), - util, + serde, protocol, hostResolver, hostHandler, diff --git a/src/main/java/com/arangodb/ArangoSerdeAccessor.java b/src/main/java/com/arangodb/ArangoSerdeAccessor.java index 4c73ef488..c3075a1b4 100644 --- a/src/main/java/com/arangodb/ArangoSerdeAccessor.java +++ b/src/main/java/com/arangodb/ArangoSerdeAccessor.java @@ -33,7 +33,7 @@ public interface ArangoSerdeAccessor { * * @return ArangoSerde */ - InternalSerde getInternalSerde(); + InternalSerde getSerde(); /** * Returns serialization implementation for serializing and deserializing user's classes. diff --git a/src/main/java/com/arangodb/async/ArangoDBAsync.java b/src/main/java/com/arangodb/async/ArangoDBAsync.java index 44a01a679..77a3bdabd 100644 --- a/src/main/java/com/arangodb/async/ArangoDBAsync.java +++ b/src/main/java/com/arangodb/async/ArangoDBAsync.java @@ -31,7 +31,7 @@ import com.arangodb.internal.net.ConnectionFactory; import com.arangodb.internal.net.HostHandler; import com.arangodb.internal.net.HostResolver; -import com.arangodb.internal.util.ArangoSerdeFactory; +import com.arangodb.serde.InternalSerde; import com.arangodb.internal.velocystream.VstCommunicationSync; import com.arangodb.internal.velocystream.VstConnectionFactorySync; import com.arangodb.model.DBCreateOptions; @@ -508,9 +508,8 @@ public synchronized ArangoDBAsync build() { if (hosts.isEmpty()) { hosts.add(host); } - final InternalSerde internal = InternalSerde.of(DataType.VPACK); - final ArangoSerde custom = customSerializer != null ? customSerializer : JacksonSerde.of(DataType.VPACK); - final ArangoSerdeFactory util = new ArangoSerdeFactory(internal, custom); + final ArangoSerde userSerde = customSerializer != null ? customSerializer : JacksonSerde.of(DataType.VPACK); + final InternalSerde serde = InternalSerde.of(DataType.VPACK, userSerde); final int max = maxConnections != null ? Math.max(1, maxConnections) : ArangoDefaults.MAX_CONNECTIONS_VST_DEFAULT; @@ -526,7 +525,7 @@ public synchronized ArangoDBAsync build() { final HostHandler asyncHostHandler = createHostHandler(asyncHostResolver); return new ArangoDBAsyncImpl( asyncBuilder(asyncHostHandler), - util, + serde, syncBuilder(syncHostHandler), asyncHostResolver, syncHostResolver, diff --git a/src/main/java/com/arangodb/async/internal/ArangoDBAsyncImpl.java b/src/main/java/com/arangodb/async/internal/ArangoDBAsyncImpl.java index f670e839e..e6a56e137 100644 --- a/src/main/java/com/arangodb/async/internal/ArangoDBAsyncImpl.java +++ b/src/main/java/com/arangodb/async/internal/ArangoDBAsyncImpl.java @@ -31,7 +31,7 @@ import com.arangodb.internal.net.CommunicationProtocol; import com.arangodb.internal.net.HostHandler; import com.arangodb.internal.net.HostResolver; -import com.arangodb.internal.util.ArangoSerdeFactory; +import com.arangodb.serde.InternalSerde; import com.arangodb.internal.velocystream.VstCommunication; import com.arangodb.internal.velocystream.VstCommunicationSync; import com.arangodb.internal.velocystream.VstProtocol; @@ -62,7 +62,7 @@ public class ArangoDBAsyncImpl extends InternalArangoDB imp public ArangoDBAsyncImpl( final VstCommunicationAsync.Builder asyncCommBuilder, - final ArangoSerdeFactory util, + final InternalSerde util, final VstCommunicationSync.Builder syncCommBuilder, final HostResolver asyncHostResolver, final HostResolver syncHostResolver, @@ -73,10 +73,10 @@ public ArangoDBAsyncImpl( final int timeoutMs ) { - super(new ArangoExecutorAsync(asyncCommBuilder.build(util.getInternalSerde()), util, new DocumentCache(), + super(new ArangoExecutorAsync(asyncCommBuilder.build(util), util, new DocumentCache(), new QueueTimeMetricsImpl(responseQueueTimeSamples), timeoutMs), util, context); - final VstCommunication cacheCom = syncCommBuilder.build(util.getInternalSerde()); + final VstCommunication cacheCom = syncCommBuilder.build(util); cp = new VstProtocol(cacheCom); this.asyncHostHandler = asyncHostHandler; @@ -84,8 +84,8 @@ public ArangoDBAsyncImpl( ArangoExecutorSync arangoExecutorSync = new ArangoExecutorSync(cp, util, new DocumentCache(), new QueueTimeMetricsImpl(responseQueueTimeSamples), timeoutMs); - asyncHostResolver.init(arangoExecutorSync, util.getInternalSerde()); - syncHostResolver.init(arangoExecutorSync, util.getInternalSerde()); + asyncHostResolver.init(arangoExecutorSync, util); + syncHostResolver.init(arangoExecutorSync, util); } diff --git a/src/main/java/com/arangodb/async/internal/ArangoExecutorAsync.java b/src/main/java/com/arangodb/async/internal/ArangoExecutorAsync.java index ab8ac57e0..fc7372da9 100644 --- a/src/main/java/com/arangodb/async/internal/ArangoExecutorAsync.java +++ b/src/main/java/com/arangodb/async/internal/ArangoExecutorAsync.java @@ -26,7 +26,7 @@ import com.arangodb.internal.DocumentCache; import com.arangodb.internal.QueueTimeMetricsImpl; import com.arangodb.internal.net.HostHandle; -import com.arangodb.internal.util.ArangoSerdeFactory; +import com.arangodb.serde.InternalSerde; import com.arangodb.velocystream.Request; import java.io.IOException; @@ -44,7 +44,7 @@ public class ArangoExecutorAsync extends ArangoExecutor { private final VstCommunicationAsync communication; private final ExecutorService outgoingExecutor = Executors.newSingleThreadExecutor(); - public ArangoExecutorAsync(final VstCommunicationAsync communication, final ArangoSerdeFactory util, + public ArangoExecutorAsync(final VstCommunicationAsync communication, final InternalSerde util, final DocumentCache documentCache, final QueueTimeMetricsImpl qtMetrics, final int timeoutMs) { super(util, documentCache, qtMetrics, timeoutMs); this.communication = communication; diff --git a/src/main/java/com/arangodb/internal/ArangoDBImpl.java b/src/main/java/com/arangodb/internal/ArangoDBImpl.java index cfdeff208..cdefb0d3a 100644 --- a/src/main/java/com/arangodb/internal/ArangoDBImpl.java +++ b/src/main/java/com/arangodb/internal/ArangoDBImpl.java @@ -28,7 +28,7 @@ import com.arangodb.internal.net.HostHandle; import com.arangodb.internal.net.HostHandler; import com.arangodb.internal.net.HostResolver; -import com.arangodb.internal.util.ArangoSerdeFactory; +import com.arangodb.serde.InternalSerde; import com.arangodb.internal.velocystream.VstCommunicationSync; import com.arangodb.internal.velocystream.VstProtocol; import com.arangodb.model.DBCreateOptions; @@ -59,11 +59,11 @@ public class ArangoDBImpl extends InternalArangoDB implement private final HostHandler hostHandler; public ArangoDBImpl(final VstCommunicationSync.Builder vstBuilder, final HttpCommunication.Builder httpBuilder, - final ArangoSerdeFactory util, final Protocol protocol, final HostResolver hostResolver, + final InternalSerde util, final Protocol protocol, final HostResolver hostResolver, final HostHandler hostHandler, final ArangoContext context, int responseQueueTimeSamples, final int timeoutMs) { super(new ArangoExecutorSync( - createProtocol(vstBuilder, httpBuilder, util.getInternalSerde(), protocol), + createProtocol(vstBuilder, httpBuilder, util, protocol), util, new DocumentCache(), new QueueTimeMetricsImpl(responseQueueTimeSamples), timeoutMs), util, @@ -72,11 +72,11 @@ public ArangoDBImpl(final VstCommunicationSync.Builder vstBuilder, final HttpCom cp = createProtocol( new VstCommunicationSync.Builder(vstBuilder).maxConnections(1), new HttpCommunication.Builder(httpBuilder), - util.getInternalSerde(), + util, protocol); this.hostHandler = hostHandler; - hostResolver.init(this.executor(), getInternalSerde()); + hostResolver.init(this.executor(), getSerde()); LOGGER.debug("ArangoDB Client is ready to use"); diff --git a/src/main/java/com/arangodb/internal/ArangoExecuteable.java b/src/main/java/com/arangodb/internal/ArangoExecuteable.java index b3b6d958e..e56d0bc51 100644 --- a/src/main/java/com/arangodb/internal/ArangoExecuteable.java +++ b/src/main/java/com/arangodb/internal/ArangoExecuteable.java @@ -22,7 +22,6 @@ import com.arangodb.ArangoSerdeAccessor; import com.arangodb.DbName; -import com.arangodb.internal.util.ArangoSerdeFactory; import com.arangodb.internal.util.EncodeUtils; import com.arangodb.serde.ArangoSerde; import com.arangodb.serde.InternalSerde; @@ -39,13 +38,13 @@ public abstract class ArangoExecuteable implements Ara private static final String SLASH = "/"; protected final E executor; - protected final ArangoSerdeFactory util; + protected final InternalSerde serde; protected final ArangoContext context; - protected ArangoExecuteable(final E executor, final ArangoSerdeFactory util, final ArangoContext context) { + protected ArangoExecuteable(final E executor, final InternalSerde serde, final ArangoContext context) { super(); this.executor = executor; - this.util = util; + this.serde = serde; this.context = context; } @@ -54,13 +53,13 @@ protected E executor() { } @Override - public InternalSerde getInternalSerde() { - return util.getInternalSerde(); + public InternalSerde getSerde() { + return serde; } @Override public ArangoSerde getUserSerde() { - return util.getUserSerialization(); + return serde.getUserSerde(); } protected Request request(final DbName dbName, final RequestType requestType, final String... path) { diff --git a/src/main/java/com/arangodb/internal/ArangoExecutor.java b/src/main/java/com/arangodb/internal/ArangoExecutor.java index c3fb99c40..8a0555009 100644 --- a/src/main/java/com/arangodb/internal/ArangoExecutor.java +++ b/src/main/java/com/arangodb/internal/ArangoExecutor.java @@ -21,7 +21,7 @@ package com.arangodb.internal; import com.arangodb.QueueTimeMetrics; -import com.arangodb.internal.util.ArangoSerdeFactory; +import com.arangodb.serde.InternalSerde; import com.arangodb.velocystream.Request; import com.arangodb.velocystream.Response; @@ -33,23 +33,20 @@ public abstract class ArangoExecutor { protected T createResult(final Type type, final Response response) { - if (response.getBody() == null) { - return null; - } - return util.getInternalSerde().deserialize(response.getBody(), type); + return serde.deserialize(response.getBody(), type); } private final DocumentCache documentCache; private final QueueTimeMetricsImpl qtMetrics; - private final ArangoSerdeFactory util; + private final InternalSerde serde; private final String timeoutS; - protected ArangoExecutor(final ArangoSerdeFactory util, final DocumentCache documentCache, + protected ArangoExecutor(final InternalSerde serde, final DocumentCache documentCache, final QueueTimeMetricsImpl qtMetrics, final int timeoutMs) { super(); this.documentCache = documentCache; this.qtMetrics = qtMetrics; - this.util = util; + this.serde = serde; timeoutS = timeoutMs >= 1000 ? Integer.toString(timeoutMs / 1000) : null; } diff --git a/src/main/java/com/arangodb/internal/ArangoExecutorSync.java b/src/main/java/com/arangodb/internal/ArangoExecutorSync.java index e74037140..4d9d5875d 100644 --- a/src/main/java/com/arangodb/internal/ArangoExecutorSync.java +++ b/src/main/java/com/arangodb/internal/ArangoExecutorSync.java @@ -24,7 +24,7 @@ import com.arangodb.entity.MetaAware; import com.arangodb.internal.net.CommunicationProtocol; import com.arangodb.internal.net.HostHandle; -import com.arangodb.internal.util.ArangoSerdeFactory; +import com.arangodb.serde.InternalSerde; import com.arangodb.velocystream.Request; import com.arangodb.velocystream.Response; import org.slf4j.Logger; @@ -42,7 +42,7 @@ public class ArangoExecutorSync extends ArangoExecutor { private final CommunicationProtocol protocol; - public ArangoExecutorSync(final CommunicationProtocol protocol, final ArangoSerdeFactory util, + public ArangoExecutorSync(final CommunicationProtocol protocol, final InternalSerde util, final DocumentCache documentCache, final QueueTimeMetricsImpl qtMetrics, final int timeoutMs) { super(util, documentCache, qtMetrics, timeoutMs); this.protocol = protocol; diff --git a/src/main/java/com/arangodb/internal/InternalArangoCollection.java b/src/main/java/com/arangodb/internal/InternalArangoCollection.java index 2e6e397e3..5655cbafa 100644 --- a/src/main/java/com/arangodb/internal/InternalArangoCollection.java +++ b/src/main/java/com/arangodb/internal/InternalArangoCollection.java @@ -65,7 +65,7 @@ public abstract class InternalArangoCollection, D protected volatile String name; protected InternalArangoCollection(final D db, final String name) { - super(db.executor, db.util, db.context); + super(db.executor, db.serde, db.context); this.db = db; this.name = name; } @@ -91,9 +91,9 @@ protected Request insertDocumentRequest(final T value, final DocumentCreateO byte[] body; if (value instanceof String) { - body = getInternalSerde().serialize(SerdeUtils.INSTANCE.parseJson((String) value)); + body = getSerde().serialize(SerdeUtils.INSTANCE.parseJson((String) value)); } else { - body = getUserSerde().serialize(value); + body = getSerde().serializeUserData(value); } request.setBody(body); @@ -103,15 +103,15 @@ protected Request insertDocumentRequest(final T value, final DocumentCreateO protected ResponseDeserializer> insertDocumentResponseDeserializer( final T value, final DocumentCreateOptions options) { return response -> { - final JsonNode body = getInternalSerde().parse(response.getBody()); - final DocumentCreateEntity doc = getInternalSerde().deserialize(body, DocumentCreateEntity.class); + final JsonNode body = getSerde().parse(response.getBody()); + final DocumentCreateEntity doc = getSerde().deserialize(body, DocumentCreateEntity.class); final JsonNode newDoc = body.get(NEW); Class clazz = (Class) value.getClass(); if (newDoc != null) { if (String.class.equals(clazz)) { doc.setNew((T) SerdeUtils.INSTANCE.writeJson(newDoc)); } else { - doc.setNew(getUserSerde().deserialize(getInternalSerde().serialize(newDoc), clazz)); + doc.setNew(getSerde().deserializeUserData(getSerde().serialize(newDoc), clazz)); } } final JsonNode oldDoc = body.get(OLD); @@ -119,7 +119,7 @@ protected ResponseDeserializer> insertDocumentRespon if (String.class.equals(clazz)) { doc.setOld((T) SerdeUtils.INSTANCE.writeJson(oldDoc)); } else { - doc.setOld(getUserSerde().deserialize(getInternalSerde().serialize(oldDoc), clazz)); + doc.setOld(getSerde().deserializeUserData(getSerde().serialize(oldDoc), clazz)); } } if (options == null || Boolean.TRUE != options.getSilent()) { @@ -143,8 +143,8 @@ protected Request insertDocumentsRequest(final Collection values, final D request.putQueryParam(MERGE_OBJECTS, params.getMergeObjects()); request.putHeaderParam(TRANSACTION_ID, params.getStreamTransactionId()); - byte[] body = isStringCollection(values) ? getInternalSerde().serialize(stringCollectionToJsonArray((Collection) values)) - : getUserSerde().serialize(values); + byte[] body = isStringCollection(values) ? getSerde().serialize(stringCollectionToJsonArray((Collection) values)) + : getSerde().serializeUserData(values); request.setBody(body); return request; } @@ -163,23 +163,23 @@ protected ResponseDeserializer>> final Collection> docs = new ArrayList<>(); final Collection errors = new ArrayList<>(); final Collection documentsAndErrors = new ArrayList<>(); - final JsonNode body = getInternalSerde().parse(response.getBody()); + final JsonNode body = getSerde().parse(response.getBody()); for (final Iterator iterator = body.iterator(); iterator.hasNext(); ) { final JsonNode next = iterator.next(); JsonNode isError = next.get(ArangoResponseField.ERROR_FIELD_NAME); if (isError != null && isError.booleanValue()) { - final ErrorEntity error = getInternalSerde().deserialize(next, ErrorEntity.class); + final ErrorEntity error = getSerde().deserialize(next, ErrorEntity.class); errors.add(error); documentsAndErrors.add(error); } else { - final DocumentCreateEntity doc = getInternalSerde().deserialize(next, DocumentCreateEntity.class); + final DocumentCreateEntity doc = getSerde().deserialize(next, DocumentCreateEntity.class); final JsonNode newDoc = next.get(NEW); if (newDoc != null) { - doc.setNew(getUserSerde().deserialize(getInternalSerde().serialize(newDoc), type)); + doc.setNew(getSerde().deserializeUserData(getSerde().serialize(newDoc), type)); } final JsonNode oldDoc = next.get(OLD); if (oldDoc != null) { - doc.setOld(getUserSerde().deserialize(getInternalSerde().serialize(oldDoc), type)); + doc.setOld(getSerde().deserializeUserData(getSerde().serialize(oldDoc), type)); } docs.add(doc); documentsAndErrors.add(doc); @@ -193,12 +193,12 @@ protected ResponseDeserializer>> } protected Request importDocumentsRequest(final String values, final DocumentImportOptions options) { - return importDocumentsRequest(options).putQueryParam("type", ImportType.auto).setBody(getInternalSerde().serialize(SerdeUtils.INSTANCE.parseJson(values))); + return importDocumentsRequest(options).putQueryParam("type", ImportType.auto).setBody(getSerde().serialize(SerdeUtils.INSTANCE.parseJson(values))); } protected Request importDocumentsRequest(final Collection values, final DocumentImportOptions options) { - byte[] body = isStringCollection(values) ? getInternalSerde().serialize(stringCollectionToJsonArray((Collection) values)) - : getUserSerde().serialize(values); + byte[] body = isStringCollection(values) ? getSerde().serialize(stringCollectionToJsonArray((Collection) values)) + : getSerde().serializeUserData(values); return importDocumentsRequest(options).putQueryParam("type", ImportType.list).setBody(body); } @@ -227,9 +227,9 @@ protected Request getDocumentRequest(final String key, final DocumentReadOptions protected ResponseDeserializer getDocumentResponseDeserializer(final Class type) { return response -> { if (String.class.equals(type)) { - return (T) SerdeUtils.INSTANCE.writeJson(getInternalSerde().parse(response.getBody())); + return (T) SerdeUtils.INSTANCE.writeJson(getSerde().parse(response.getBody())); } else { - return getUserSerde().deserialize(response.getBody(), type); + return getSerde().deserializeUserData(response.getBody(), type); } }; } @@ -239,7 +239,7 @@ protected Request getDocumentsRequest(final Collection keys, final Docum final Request request = request(db.dbName(), RequestType.PUT, PATH_API_DOCUMENT, name) .putQueryParam("onlyget", true) .putHeaderParam(ArangoRequestParam.IF_NONE_MATCH, params.getIfNoneMatch()) - .putHeaderParam(ArangoRequestParam.IF_MATCH, params.getIfMatch()).setBody(getInternalSerde().serialize(keys)) + .putHeaderParam(ArangoRequestParam.IF_MATCH, params.getIfMatch()).setBody(getSerde().serialize(keys)) .putHeaderParam(TRANSACTION_ID, params.getStreamTransactionId()); if (params.getAllowDirtyRead() == Boolean.TRUE) { RequestUtils.allowDirtyRead(request); @@ -254,16 +254,16 @@ protected ResponseDeserializer> getDocumentsResponseD final Collection docs = new ArrayList<>(); final Collection errors = new ArrayList<>(); final Collection documentsAndErrors = new ArrayList<>(); - final JsonNode body = getInternalSerde().parse(response.getBody()); + final JsonNode body = getSerde().parse(response.getBody()); for (final Iterator iterator = body.iterator(); iterator.hasNext(); ) { final JsonNode next = iterator.next(); JsonNode isError = next.get(ArangoResponseField.ERROR_FIELD_NAME); if (isError != null && isError.booleanValue()) { - final ErrorEntity error = getInternalSerde().deserialize(next, ErrorEntity.class); + final ErrorEntity error = getSerde().deserialize(next, ErrorEntity.class); errors.add(error); documentsAndErrors.add(error); } else { - final T doc = getUserSerde().deserialize(getInternalSerde().serialize(next), type); + final T doc = getSerde().deserializeUserData(getSerde().serialize(next), type); docs.add(doc); documentsAndErrors.add(doc); } @@ -287,23 +287,23 @@ protected Request replaceDocumentRequest( request.putQueryParam(RETURN_NEW, params.getReturnNew()); request.putQueryParam(RETURN_OLD, params.getReturnOld()); request.putQueryParam(SILENT, params.getSilent()); - request.setBody(getUserSerde().serialize(value)); + request.setBody(getSerde().serializeUserData(value)); return request; } protected ResponseDeserializer> replaceDocumentResponseDeserializer( final T value, final DocumentReplaceOptions options) { return response -> { - final JsonNode body = getInternalSerde().parse(response.getBody()); - final DocumentUpdateEntity doc = getInternalSerde().deserialize(body, DocumentUpdateEntity.class); + final JsonNode body = getSerde().parse(response.getBody()); + final DocumentUpdateEntity doc = getSerde().deserialize(body, DocumentUpdateEntity.class); final JsonNode newDoc = body.get(NEW); Class clazz = (Class) value.getClass(); if (newDoc != null) { - doc.setNew(getUserSerde().deserialize(getInternalSerde().serialize(newDoc), clazz)); + doc.setNew(getSerde().deserializeUserData(getSerde().serialize(newDoc), clazz)); } final JsonNode oldDoc = body.get(OLD); if (oldDoc != null) { - doc.setOld(getUserSerde().deserialize(getInternalSerde().serialize(oldDoc), clazz)); + doc.setOld(getSerde().deserializeUserData(getSerde().serialize(oldDoc), clazz)); } if (options == null || Boolean.TRUE != options.getSilent()) { final Map values = new HashMap<>(); @@ -324,8 +324,8 @@ protected Request replaceDocumentsRequest(final Collection values, final request.putQueryParam(RETURN_OLD, params.getReturnOld()); request.putQueryParam(SILENT, params.getSilent()); - byte[] body = isStringCollection(values) ? getInternalSerde().serialize(stringCollectionToJsonArray((Collection) values)) - : getUserSerde().serialize(values); + byte[] body = isStringCollection(values) ? getSerde().serialize(stringCollectionToJsonArray((Collection) values)) + : getSerde().serializeUserData(values); request.setBody(body); return request; } @@ -344,23 +344,23 @@ protected ResponseDeserializer>> final Collection> docs = new ArrayList<>(); final Collection errors = new ArrayList<>(); final Collection documentsAndErrors = new ArrayList<>(); - final JsonNode body = getInternalSerde().parse(response.getBody()); + final JsonNode body = getSerde().parse(response.getBody()); for (final Iterator iterator = body.iterator(); iterator.hasNext(); ) { final JsonNode next = iterator.next(); JsonNode isError = next.get(ArangoResponseField.ERROR_FIELD_NAME); if (isError != null && isError.booleanValue()) { - final ErrorEntity error = getInternalSerde().deserialize(next, ErrorEntity.class); + final ErrorEntity error = getSerde().deserialize(next, ErrorEntity.class); errors.add(error); documentsAndErrors.add(error); } else { - final DocumentUpdateEntity doc = getInternalSerde().deserialize(next, DocumentUpdateEntity.class); + final DocumentUpdateEntity doc = getSerde().deserialize(next, DocumentUpdateEntity.class); final JsonNode newDoc = next.get(NEW); if (newDoc != null) { - doc.setNew(getUserSerde().deserialize(getInternalSerde().serialize(newDoc), type)); + doc.setNew(getSerde().deserializeUserData(getSerde().serialize(newDoc), type)); } final JsonNode oldDoc = next.get(OLD); if (oldDoc != null) { - doc.setOld(getUserSerde().deserialize(getInternalSerde().serialize(oldDoc), type)); + doc.setOld(getSerde().deserializeUserData(getSerde().serialize(oldDoc), type)); } docs.add(doc); documentsAndErrors.add(doc); @@ -386,22 +386,22 @@ protected Request updateDocumentRequest(final String key, final T value, fin request.putQueryParam(RETURN_NEW, params.getReturnNew()); request.putQueryParam(RETURN_OLD, params.getReturnOld()); request.putQueryParam(SILENT, params.getSilent()); - request.setBody(getUserSerde().serialize(value)); + request.setBody(getSerde().serializeUserData(value)); return request; } protected ResponseDeserializer> updateDocumentResponseDeserializer( final T value, final DocumentUpdateOptions options, final Class returnType) { return response -> { - final JsonNode body = getInternalSerde().parse(response.getBody()); - final DocumentUpdateEntity doc = getInternalSerde().deserialize(body, DocumentUpdateEntity.class); + final JsonNode body = getSerde().parse(response.getBody()); + final DocumentUpdateEntity doc = getSerde().deserialize(body, DocumentUpdateEntity.class); final JsonNode newDoc = body.get(NEW); if (newDoc != null) { - doc.setNew(getUserSerde().deserialize(getInternalSerde().serialize(newDoc), returnType)); + doc.setNew(getSerde().deserializeUserData(getSerde().serialize(newDoc), returnType)); } final JsonNode oldDoc = body.get(OLD); if (oldDoc != null) { - doc.setOld(getUserSerde().deserialize(getInternalSerde().serialize(oldDoc), returnType)); + doc.setOld(getSerde().deserializeUserData(getSerde().serialize(oldDoc), returnType)); } if (options == null || Boolean.TRUE != options.getSilent()) { final Map values = new HashMap<>(); @@ -425,8 +425,8 @@ protected Request updateDocumentsRequest(final Collection values, final D request.putQueryParam(RETURN_OLD, params.getReturnOld()); request.putQueryParam(SILENT, params.getSilent()); - byte[] body = isStringCollection(values) ? getInternalSerde().serialize(stringCollectionToJsonArray((Collection) values)) - : getUserSerde().serialize(values); + byte[] body = isStringCollection(values) ? getSerde().serialize(stringCollectionToJsonArray((Collection) values)) + : getSerde().serializeUserData(values); request.setBody(body); return request; } @@ -439,23 +439,23 @@ protected ResponseDeserializer>> final Collection> docs = new ArrayList<>(); final Collection errors = new ArrayList<>(); final Collection documentsAndErrors = new ArrayList<>(); - final JsonNode body = getInternalSerde().parse(response.getBody()); + final JsonNode body = getSerde().parse(response.getBody()); for (final Iterator iterator = body.iterator(); iterator.hasNext(); ) { final JsonNode next = iterator.next(); JsonNode isError = next.get(ArangoResponseField.ERROR_FIELD_NAME); if (isError != null && isError.booleanValue()) { - final ErrorEntity error = getInternalSerde().deserialize(next, ErrorEntity.class); + final ErrorEntity error = getSerde().deserialize(next, ErrorEntity.class); errors.add(error); documentsAndErrors.add(error); } else { - final DocumentUpdateEntity doc = getInternalSerde().deserialize(next, DocumentUpdateEntity.class); + final DocumentUpdateEntity doc = getSerde().deserialize(next, DocumentUpdateEntity.class); final JsonNode newDoc = next.get(NEW); if (newDoc != null) { - doc.setNew(getUserSerde().deserialize(getInternalSerde().serialize(newDoc), returnType)); + doc.setNew(getSerde().deserializeUserData(getSerde().serialize(newDoc), returnType)); } final JsonNode oldDoc = next.get(OLD); if (oldDoc != null) { - doc.setOld(getUserSerde().deserialize(getInternalSerde().serialize(oldDoc), returnType)); + doc.setOld(getSerde().deserializeUserData(getSerde().serialize(oldDoc), returnType)); } docs.add(doc); documentsAndErrors.add(doc); @@ -483,11 +483,11 @@ protected Request deleteDocumentRequest(final String key, final DocumentDeleteOp protected ResponseDeserializer> deleteDocumentResponseDeserializer( final Class type) { return response -> { - final JsonNode body = getInternalSerde().parse(response.getBody()); - final DocumentDeleteEntity doc = getInternalSerde().deserialize(body, DocumentDeleteEntity.class); + final JsonNode body = getSerde().parse(response.getBody()); + final DocumentDeleteEntity doc = getSerde().deserialize(body, DocumentDeleteEntity.class); final JsonNode oldDoc = body.get(OLD); if (oldDoc != null) { - doc.setOld(getUserSerde().deserialize(getInternalSerde().serialize(oldDoc), type)); + doc.setOld(getSerde().deserializeUserData(getSerde().serialize(oldDoc), type)); } return doc; }; @@ -500,7 +500,7 @@ protected Request deleteDocumentsRequest(final Collection keys, final Doc request.putQueryParam(ArangoRequestParam.WAIT_FOR_SYNC, params.getWaitForSync()); request.putQueryParam(RETURN_OLD, params.getReturnOld()); request.putQueryParam(SILENT, params.getSilent()); - request.setBody(getInternalSerde().serialize(keys)); + request.setBody(getSerde().serialize(keys)); return request; } @@ -511,19 +511,19 @@ protected ResponseDeserializer>> final Collection> docs = new ArrayList<>(); final Collection errors = new ArrayList<>(); final Collection documentsAndErrors = new ArrayList<>(); - final JsonNode body = getInternalSerde().parse(response.getBody()); + final JsonNode body = getSerde().parse(response.getBody()); for (final Iterator iterator = body.iterator(); iterator.hasNext(); ) { final JsonNode next = iterator.next(); JsonNode isError = next.get(ArangoResponseField.ERROR_FIELD_NAME); if (isError != null && isError.booleanValue()) { - final ErrorEntity error = getInternalSerde().deserialize(next, ErrorEntity.class); + final ErrorEntity error = getSerde().deserialize(next, ErrorEntity.class); errors.add(error); documentsAndErrors.add(error); } else { - final DocumentDeleteEntity doc = getInternalSerde().deserialize(next, DocumentDeleteEntity.class); + final DocumentDeleteEntity doc = getSerde().deserialize(next, DocumentDeleteEntity.class); final JsonNode oldDoc = next.get(OLD); if (oldDoc != null) { - doc.setOld(getUserSerde().deserialize(getInternalSerde().serialize(oldDoc), type)); + doc.setOld(getSerde().deserializeUserData(getSerde().serialize(oldDoc), type)); } docs.add(doc); documentsAndErrors.add(doc); @@ -555,7 +555,7 @@ protected Request deleteIndexRequest(final String id) { } protected ResponseDeserializer deleteIndexResponseDeserializer() { - return response -> getInternalSerde().deserialize(response.getBody(), "/id", String.class); + return response -> getSerde().deserialize(response.getBody(), "/id", String.class); } private String createIndexId(final String id) { @@ -575,7 +575,7 @@ protected Request createHashIndexRequest(final Iterable fields, final Ha final Request request = request(db.dbName(), RequestType.POST, PATH_API_INDEX); request.putQueryParam(COLLECTION, name); request.setBody( - getInternalSerde().serialize(OptionsBuilder.build(options != null ? options : new HashIndexOptions(), fields))); + getSerde().serialize(OptionsBuilder.build(options != null ? options : new HashIndexOptions(), fields))); return request; } @@ -584,7 +584,7 @@ protected Request createSkiplistIndexRequest(final Iterable fields, fina final Request request = request(db.dbName(), RequestType.POST, PATH_API_INDEX); request.putQueryParam(COLLECTION, name); request.setBody( - getInternalSerde().serialize(OptionsBuilder.build(options != null ? options : new SkiplistIndexOptions(), fields))); + getSerde().serialize(OptionsBuilder.build(options != null ? options : new SkiplistIndexOptions(), fields))); return request; } @@ -592,7 +592,7 @@ protected Request createPersistentIndexRequest( final Iterable fields, final PersistentIndexOptions options) { final Request request = request(db.dbName(), RequestType.POST, PATH_API_INDEX); request.putQueryParam(COLLECTION, name); - request.setBody(getInternalSerde().serialize( + request.setBody(getSerde().serialize( OptionsBuilder.build(options != null ? options : new PersistentIndexOptions(), fields))); return request; } @@ -601,7 +601,7 @@ protected Request createGeoIndexRequest(final Iterable fields, final Geo final Request request = request(db.dbName(), RequestType.POST, PATH_API_INDEX); request.putQueryParam(COLLECTION, name); request.setBody( - getInternalSerde().serialize(OptionsBuilder.build(options != null ? options : new GeoIndexOptions(), fields))); + getSerde().serialize(OptionsBuilder.build(options != null ? options : new GeoIndexOptions(), fields))); return request; } @@ -609,7 +609,7 @@ protected Request createFulltextIndexRequest(final Iterable fields, fina final Request request = request(db.dbName(), RequestType.POST, PATH_API_INDEX); request.putQueryParam(COLLECTION, name); request.setBody( - getInternalSerde().serialize(OptionsBuilder.build(options != null ? options : new FulltextIndexOptions(), fields))); + getSerde().serialize(OptionsBuilder.build(options != null ? options : new FulltextIndexOptions(), fields))); return request; } @@ -617,7 +617,7 @@ protected Request createTtlIndexRequest(final Iterable fields, final Ttl final Request request = request(db.dbName(), RequestType.POST, PATH_API_INDEX); request.putQueryParam(COLLECTION, name); request.setBody( - getInternalSerde().serialize(OptionsBuilder.build(options != null ? options : new TtlIndexOptions(), fields))); + getSerde().serialize(OptionsBuilder.build(options != null ? options : new TtlIndexOptions(), fields))); return request; } @@ -625,7 +625,7 @@ protected Request createZKDIndexRequest( final Iterable fields, final ZKDIndexOptions options) { final Request request = request(db.dbName(), RequestType.POST, PATH_API_INDEX); request.putQueryParam(COLLECTION, name); - request.setBody(getInternalSerde().serialize(OptionsBuilder.build(options != null ? options : + request.setBody(getSerde().serialize(OptionsBuilder.build(options != null ? options : new ZKDIndexOptions().fieldValueTypes(ZKDIndexOptions.FieldValueTypes.DOUBLE), fields))); return request; } @@ -637,7 +637,7 @@ protected Request getIndexesRequest() { } protected ResponseDeserializer> getIndexesResponseDeserializer() { - return response -> getInternalSerde().deserialize(response.getBody(), "/indexes", + return response -> getSerde().deserialize(response.getBody(), "/indexes", SerdeUtils.INSTANCE.constructListType(IndexEntity.class)); } @@ -669,19 +669,19 @@ protected Request getPropertiesRequest() { protected Request changePropertiesRequest(final CollectionPropertiesOptions options) { final Request request = request(db.dbName(), RequestType.PUT, PATH_API_COLLECTION, name, "properties"); - request.setBody(getInternalSerde().serialize(options != null ? options : new CollectionPropertiesOptions())); + request.setBody(getSerde().serialize(options != null ? options : new CollectionPropertiesOptions())); return request; } protected Request renameRequest(final String newName) { final Request request = request(db.dbName(), RequestType.PUT, PATH_API_COLLECTION, name, "rename"); - request.setBody(getInternalSerde().serialize(OptionsBuilder.build(new CollectionRenameOptions(), newName))); + request.setBody(getSerde().serialize(OptionsBuilder.build(new CollectionRenameOptions(), newName))); return request; } protected Request responsibleShardRequest(final T value) { final Request request = request(db.dbName(), RequestType.PUT, PATH_API_COLLECTION, name, "responsibleShard"); - request.setBody(getUserSerde().serialize(value)); + request.setBody(getSerde().serializeUserData(value)); return request; } @@ -691,7 +691,7 @@ protected Request getRevisionRequest() { protected Request grantAccessRequest(final String user, final Permissions permissions) { return request(DbName.SYSTEM, RequestType.PUT, PATH_API_USER, user, ArangoRequestParam.DATABASE, - db.dbName().get(), name).setBody(getInternalSerde().serialize(OptionsBuilder.build(new UserAccessOptions(), permissions))); + db.dbName().get(), name).setBody(getSerde().serialize(OptionsBuilder.build(new UserAccessOptions(), permissions))); } protected Request resetAccessRequest(final String user) { @@ -705,7 +705,7 @@ protected Request getPermissionsRequest(final String user) { } protected ResponseDeserializer getPermissionsResponseDeserialzer() { - return response -> getInternalSerde().deserialize(response.getBody(), ArangoResponseField.RESULT_JSON_POINTER, Permissions.class); + return response -> getSerde().deserialize(response.getBody(), ArangoResponseField.RESULT_JSON_POINTER, Permissions.class); } private boolean isStringCollection(final Collection values) { diff --git a/src/main/java/com/arangodb/internal/InternalArangoDB.java b/src/main/java/com/arangodb/internal/InternalArangoDB.java index eb63cb9cb..862c4d90c 100644 --- a/src/main/java/com/arangodb/internal/InternalArangoDB.java +++ b/src/main/java/com/arangodb/internal/InternalArangoDB.java @@ -23,8 +23,8 @@ import com.arangodb.DbName; import com.arangodb.entity.*; import com.arangodb.internal.ArangoExecutor.ResponseDeserializer; -import com.arangodb.internal.util.ArangoSerdeFactory; import com.arangodb.model.*; +import com.arangodb.serde.InternalSerde; import com.arangodb.serde.SerdeUtils; import com.arangodb.velocystream.Request; import com.arangodb.velocystream.RequestType; @@ -47,7 +47,7 @@ public abstract class InternalArangoDB extends ArangoE private static final String PATH_ENDPOINTS = "/_api/cluster/endpoints"; private static final String PATH_API_USER = "/_api/user"; - protected InternalArangoDB(final E executor, final ArangoSerdeFactory util, final ArangoContext context) { + protected InternalArangoDB(final E executor, final InternalSerde util, final ArangoContext context) { super(executor, util, context); } @@ -60,22 +60,22 @@ protected Request getServerIdRequest() { } protected ResponseDeserializer getRoleResponseDeserializer() { - return response -> getInternalSerde().deserialize(response.getBody(), "/role", ServerRole.class); + return response -> getSerde().deserialize(response.getBody(), "/role", ServerRole.class); } protected ResponseDeserializer getServerIdResponseDeserializer() { - return response -> getInternalSerde().deserialize(response.getBody(), "/id", String.class); + return response -> getSerde().deserialize(response.getBody(), "/id", String.class); } protected Request createDatabaseRequest(final DBCreateOptions options) { final Request request = request(DbName.SYSTEM, RequestType.POST, InternalArangoDatabase.PATH_API_DATABASE); - request.setBody(getInternalSerde().serialize(options)); + request.setBody(getSerde().serialize(options)); return request; } protected ResponseDeserializer createDatabaseResponseDeserializer() { - return response -> getInternalSerde().deserialize(response.getBody(), ArangoResponseField.RESULT_JSON_POINTER, Boolean.class); + return response -> getSerde().deserialize(response.getBody(), ArangoResponseField.RESULT_JSON_POINTER, Boolean.class); } protected Request getDatabasesRequest(final DbName dbName) { @@ -83,7 +83,7 @@ protected Request getDatabasesRequest(final DbName dbName) { } protected ResponseDeserializer> getDatabaseResponseDeserializer() { - return response -> getInternalSerde().deserialize(response.getBody(), ArangoResponseField.RESULT_JSON_POINTER, + return response -> getSerde().deserialize(response.getBody(), ArangoResponseField.RESULT_JSON_POINTER, SerdeUtils.INSTANCE.constructListType(String.class)); } @@ -93,7 +93,7 @@ protected Request getAccessibleDatabasesForRequest(final DbName dbName, final St protected ResponseDeserializer> getAccessibleDatabasesForResponseDeserializer() { return response -> { - Iterator names = getInternalSerde().parse(response.getBody(), ArangoResponseField.RESULT_JSON_POINTER).fieldNames(); + Iterator names = getSerde().parse(response.getBody(), ArangoResponseField.RESULT_JSON_POINTER).fieldNames(); final Collection dbs = new ArrayList<>(); while (names.hasNext()) { dbs.add(names.next()); @@ -110,7 +110,7 @@ protected Request createUserRequest( final Request request; request = request(dbName, RequestType.POST, PATH_API_USER); request.setBody( - getInternalSerde().serialize(OptionsBuilder.build(options != null ? options : new UserCreateOptions(), user, passwd))); + getSerde().serialize(OptionsBuilder.build(options != null ? options : new UserCreateOptions(), user, passwd))); return request; } @@ -127,32 +127,32 @@ protected Request getUserRequest(final DbName dbName, final String user) { } protected ResponseDeserializer> getUsersResponseDeserializer() { - return response -> getInternalSerde().deserialize(response.getBody(), ArangoResponseField.RESULT_JSON_POINTER, + return response -> getSerde().deserialize(response.getBody(), ArangoResponseField.RESULT_JSON_POINTER, SerdeUtils.INSTANCE.constructListType(UserEntity.class)); } protected Request updateUserRequest(final DbName dbName, final String user, final UserUpdateOptions options) { final Request request; request = request(dbName, RequestType.PATCH, PATH_API_USER, user); - request.setBody(getInternalSerde().serialize(options != null ? options : new UserUpdateOptions())); + request.setBody(getSerde().serialize(options != null ? options : new UserUpdateOptions())); return request; } protected Request replaceUserRequest(final DbName dbName, final String user, final UserUpdateOptions options) { final Request request; request = request(dbName, RequestType.PUT, PATH_API_USER, user); - request.setBody(getInternalSerde().serialize(options != null ? options : new UserUpdateOptions())); + request.setBody(getSerde().serialize(options != null ? options : new UserUpdateOptions())); return request; } protected Request updateUserDefaultDatabaseAccessRequest(final String user, final Permissions permissions) { return request(DbName.SYSTEM, RequestType.PUT, PATH_API_USER, user, ArangoRequestParam.DATABASE, - "*").setBody(getInternalSerde().serialize(OptionsBuilder.build(new UserAccessOptions(), permissions))); + "*").setBody(getSerde().serialize(OptionsBuilder.build(new UserAccessOptions(), permissions))); } protected Request updateUserDefaultCollectionAccessRequest(final String user, final Permissions permissions) { return request(DbName.SYSTEM, RequestType.PUT, PATH_API_USER, user, ArangoRequestParam.DATABASE, - "*", "*").setBody(getInternalSerde().serialize(OptionsBuilder.build(new UserAccessOptions(), permissions))); + "*", "*").setBody(getSerde().serialize(OptionsBuilder.build(new UserAccessOptions(), permissions))); } protected Request getLogEntriesRequest(final LogOptions options) { @@ -173,7 +173,7 @@ protected Request getLogLevelRequest() { protected Request setLogLevelRequest(final LogLevelEntity entity) { return request(DbName.SYSTEM, RequestType.PUT, PATH_API_ADMIN_LOG_LEVEL) - .setBody(getInternalSerde().serialize(entity)); + .setBody(getSerde().serialize(entity)); } } diff --git a/src/main/java/com/arangodb/internal/InternalArangoDatabase.java b/src/main/java/com/arangodb/internal/InternalArangoDatabase.java index 8943e5d34..a94042aab 100644 --- a/src/main/java/com/arangodb/internal/InternalArangoDatabase.java +++ b/src/main/java/com/arangodb/internal/InternalArangoDatabase.java @@ -65,7 +65,7 @@ public abstract class InternalArangoDatabase> getCollectionsResponseDeserializer() { - return response -> getInternalSerde().deserialize(getInternalSerde().parse(response.getBody(), ArangoResponseField.RESULT_JSON_POINTER), + return response -> getSerde().deserialize(getSerde().parse(response.getBody(), ArangoResponseField.RESULT_JSON_POINTER), SerdeUtils.INSTANCE.constructListType(CollectionEntity.class)); } @@ -119,11 +119,11 @@ protected Request dropRequest() { } protected ResponseDeserializer createDropResponseDeserializer() { - return response -> getInternalSerde().deserialize(response.getBody(), ArangoResponseField.RESULT_JSON_POINTER, Boolean.class); + return response -> getSerde().deserialize(response.getBody(), ArangoResponseField.RESULT_JSON_POINTER, Boolean.class); } protected Request grantAccessRequest(final String user, final Permissions permissions) { - return request(DbName.SYSTEM, RequestType.PUT, PATH_API_USER, user, ArangoRequestParam.DATABASE, dbName.get()).setBody(getInternalSerde().serialize(OptionsBuilder.build(new UserAccessOptions(), permissions))); + return request(DbName.SYSTEM, RequestType.PUT, PATH_API_USER, user, ArangoRequestParam.DATABASE, dbName.get()).setBody(getSerde().serialize(OptionsBuilder.build(new UserAccessOptions(), permissions))); } protected Request resetAccessRequest(final String user) { @@ -131,7 +131,7 @@ protected Request resetAccessRequest(final String user) { } protected Request updateUserDefaultCollectionAccessRequest(final String user, final Permissions permissions) { - return request(DbName.SYSTEM, RequestType.PUT, PATH_API_USER, user, ArangoRequestParam.DATABASE, dbName.get(), "*").setBody(getInternalSerde().serialize(OptionsBuilder.build(new UserAccessOptions(), permissions))); + return request(DbName.SYSTEM, RequestType.PUT, PATH_API_USER, user, ArangoRequestParam.DATABASE, dbName.get(), "*").setBody(getSerde().serialize(OptionsBuilder.build(new UserAccessOptions(), permissions))); } protected Request getPermissionsRequest(final String user) { @@ -139,13 +139,13 @@ protected Request getPermissionsRequest(final String user) { } protected ResponseDeserializer getPermissionsResponseDeserialzer() { - return response -> getInternalSerde().deserialize(response.getBody(), ArangoResponseField.RESULT_JSON_POINTER, Permissions.class); + return response -> getSerde().deserialize(response.getBody(), ArangoResponseField.RESULT_JSON_POINTER, Permissions.class); } protected Request queryRequest(final String query, final Map bindVars, final AqlQueryOptions options) { final AqlQueryOptions opt = options != null ? options : new AqlQueryOptions(); - final Request request = request(dbName, RequestType.POST, PATH_API_CURSOR).setBody(getInternalSerde().serialize( - OptionsBuilder.build(opt, query, bindVars != null ? getUserSerde().serialize(bindVars) : null))); + final Request request = request(dbName, RequestType.POST, PATH_API_CURSOR).setBody(getSerde().serialize( + OptionsBuilder.build(opt, query, bindVars != null ? getSerde().serializeUserData(bindVars) : null))); if (opt.getAllowDirtyRead() == Boolean.TRUE) { RequestUtils.allowDirtyRead(request); } @@ -190,12 +190,12 @@ protected Request queryCloseRequest(final String id, final AqlQueryOptions optio protected Request explainQueryRequest(final String query, final Map bindVars, final AqlQueryExplainOptions options) { final AqlQueryExplainOptions opt = options != null ? options : new AqlQueryExplainOptions(); return request(dbName, RequestType.POST, PATH_API_EXPLAIN) - .setBody(getInternalSerde().serialize( - OptionsBuilder.build(opt, query, bindVars != null ? getUserSerde().serialize(bindVars) : null))); + .setBody(getSerde().serialize( + OptionsBuilder.build(opt, query, bindVars != null ? getSerde().serializeUserData(bindVars) : null))); } protected Request parseQueryRequest(final String query) { - return request(dbName, RequestType.POST, PATH_API_QUERY).setBody(getInternalSerde().serialize(OptionsBuilder.build(new AqlQueryParseOptions(), query))); + return request(dbName, RequestType.POST, PATH_API_QUERY).setBody(getSerde().serialize(OptionsBuilder.build(new AqlQueryParseOptions(), query))); } protected Request clearQueryCacheRequest() { @@ -207,7 +207,7 @@ protected Request getQueryCachePropertiesRequest() { } protected Request setQueryCachePropertiesRequest(final QueryCachePropertiesEntity properties) { - return request(dbName, RequestType.PUT, PATH_API_QUERY_CACHE_PROPERTIES).setBody(getInternalSerde().serialize(properties)); + return request(dbName, RequestType.PUT, PATH_API_QUERY_CACHE_PROPERTIES).setBody(getSerde().serialize(properties)); } protected Request getQueryTrackingPropertiesRequest() { @@ -215,7 +215,7 @@ protected Request getQueryTrackingPropertiesRequest() { } protected Request setQueryTrackingPropertiesRequest(final QueryTrackingPropertiesEntity properties) { - return request(dbName, RequestType.PUT, PATH_API_QUERY_PROPERTIES).setBody(getInternalSerde().serialize(properties)); + return request(dbName, RequestType.PUT, PATH_API_QUERY_PROPERTIES).setBody(getSerde().serialize(properties)); } protected Request getCurrentlyRunningQueriesRequest() { @@ -235,7 +235,7 @@ protected Request killQueryRequest(final String id) { } protected Request createAqlFunctionRequest(final String name, final String code, final AqlFunctionCreateOptions options) { - return request(dbName, RequestType.POST, PATH_API_AQLFUNCTION).setBody(getInternalSerde().serialize(OptionsBuilder.build(options != null ? options : new AqlFunctionCreateOptions(), name, code))); + return request(dbName, RequestType.POST, PATH_API_AQLFUNCTION).setBody(getSerde().serialize(OptionsBuilder.build(options != null ? options : new AqlFunctionCreateOptions(), name, code))); } protected Request deleteAqlFunctionRequest(final String name, final AqlFunctionDeleteOptions options) { @@ -246,7 +246,7 @@ protected Request deleteAqlFunctionRequest(final String name, final AqlFunctionD } protected ResponseDeserializer deleteAqlFunctionResponseDeserializer() { - return response -> getInternalSerde().deserialize(response.getBody(), "/deletedCount", Integer.class); + return response -> getSerde().deserialize(response.getBody(), "/deletedCount", Integer.class); } protected Request getAqlFunctionsRequest(final AqlFunctionGetOptions options) { @@ -257,16 +257,16 @@ protected Request getAqlFunctionsRequest(final AqlFunctionGetOptions options) { } protected ResponseDeserializer> getAqlFunctionsResponseDeserializer() { - return response -> getInternalSerde().deserialize(response.getBody(), ArangoResponseField.RESULT_JSON_POINTER, + return response -> getSerde().deserialize(response.getBody(), ArangoResponseField.RESULT_JSON_POINTER, SerdeUtils.INSTANCE.constructListType(AqlFunctionEntity.class)); } protected Request createGraphRequest(final String name, final Collection edgeDefinitions, final GraphCreateOptions options) { - return request(dbName, RequestType.POST, InternalArangoGraph.PATH_API_GHARIAL).setBody(getInternalSerde().serialize(OptionsBuilder.build(options != null ? options : new GraphCreateOptions(), name, edgeDefinitions))); + return request(dbName, RequestType.POST, InternalArangoGraph.PATH_API_GHARIAL).setBody(getSerde().serialize(OptionsBuilder.build(options != null ? options : new GraphCreateOptions(), name, edgeDefinitions))); } protected ResponseDeserializer createGraphResponseDeserializer() { - return response -> getInternalSerde().deserialize(response.getBody(), "/graph", GraphEntity.class); + return response -> getSerde().deserialize(response.getBody(), "/graph", GraphEntity.class); } protected Request getGraphsRequest() { @@ -274,27 +274,27 @@ protected Request getGraphsRequest() { } protected ResponseDeserializer> getGraphsResponseDeserializer() { - return response -> getInternalSerde().deserialize(response.getBody(), "/graphs", + return response -> getSerde().deserialize(response.getBody(), "/graphs", SerdeUtils.INSTANCE.constructListType(GraphEntity.class)); } protected Request transactionRequest(final String action, final TransactionOptions options) { - return request(dbName, RequestType.POST, PATH_API_TRANSACTION).setBody(getInternalSerde().serialize(OptionsBuilder.build(options != null ? options : new TransactionOptions(), action))); + return request(dbName, RequestType.POST, PATH_API_TRANSACTION).setBody(getSerde().serialize(OptionsBuilder.build(options != null ? options : new TransactionOptions(), action))); } protected ResponseDeserializer transactionResponseDeserializer(final Class type) { return response -> { - byte[] userContent = getInternalSerde().extract(response.getBody(), ArangoResponseField.RESULT_JSON_POINTER); + byte[] userContent = getSerde().extract(response.getBody(), ArangoResponseField.RESULT_JSON_POINTER); if (String.class.equals(type)) { - return (T) SerdeUtils.INSTANCE.writeJson(getInternalSerde().parse(userContent)); + return (T) SerdeUtils.INSTANCE.writeJson(getSerde().parse(userContent)); } else { - return getUserSerde().deserialize(userContent, type); + return getSerde().deserializeUserData(userContent, type); } }; } protected Request beginStreamTransactionRequest(final StreamTransactionOptions options) { - return request(dbName, RequestType.POST, PATH_API_BEGIN_STREAM_TRANSACTION).setBody(getInternalSerde().serialize(options != null ? options : new StreamTransactionOptions())); + return request(dbName, RequestType.POST, PATH_API_BEGIN_STREAM_TRANSACTION).setBody(getSerde().serialize(options != null ? options : new StreamTransactionOptions())); } protected Request abortStreamTransactionRequest(String id) { @@ -310,7 +310,7 @@ protected Request getStreamTransactionRequest(String id) { } protected ResponseDeserializer> transactionsResponseDeserializer() { - return response -> getInternalSerde().deserialize(response.getBody(), "/transactions", + return response -> getSerde().deserialize(response.getBody(), "/transactions", SerdeUtils.INSTANCE.constructListType(TransactionEntity.class)); } @@ -319,7 +319,7 @@ protected Request commitStreamTransactionRequest(String id) { } protected ResponseDeserializer streamTransactionResponseDeserializer() { - return response -> getInternalSerde().deserialize(response.getBody(), ArangoResponseField.RESULT_JSON_POINTER, StreamTransactionEntity.class); + return response -> getSerde().deserialize(response.getBody(), ArangoResponseField.RESULT_JSON_POINTER, StreamTransactionEntity.class); } protected Request getInfoRequest() { @@ -327,7 +327,7 @@ protected Request getInfoRequest() { } protected ResponseDeserializer getInfoResponseDeserializer() { - return response -> getInternalSerde().deserialize(response.getBody(), ArangoResponseField.RESULT_JSON_POINTER, DatabaseEntity.class); + return response -> getSerde().deserialize(response.getBody(), ArangoResponseField.RESULT_JSON_POINTER, DatabaseEntity.class); } protected Request reloadRoutingRequest() { @@ -339,16 +339,16 @@ protected Request getViewsRequest() { } protected ResponseDeserializer> getViewsResponseDeserializer() { - return response -> getInternalSerde().deserialize(response.getBody(), ArangoResponseField.RESULT_JSON_POINTER, + return response -> getSerde().deserialize(response.getBody(), ArangoResponseField.RESULT_JSON_POINTER, SerdeUtils.INSTANCE.constructListType(ViewEntity.class)); } protected Request createViewRequest(final String name, final ViewType type) { - return request(dbName, RequestType.POST, InternalArangoView.PATH_API_VIEW).setBody(getInternalSerde().serialize(OptionsBuilder.build(new ViewCreateOptions(), name, type))); + return request(dbName, RequestType.POST, InternalArangoView.PATH_API_VIEW).setBody(getSerde().serialize(OptionsBuilder.build(new ViewCreateOptions(), name, type))); } protected Request createArangoSearchRequest(final String name, final ArangoSearchCreateOptions options) { - return request(dbName, RequestType.POST, InternalArangoView.PATH_API_VIEW).setBody(getInternalSerde().serialize(ArangoSearchOptionsBuilder.build(options != null ? options : new ArangoSearchCreateOptions(), name))); + return request(dbName, RequestType.POST, InternalArangoView.PATH_API_VIEW).setBody(getSerde().serialize(ArangoSearchOptionsBuilder.build(options != null ? options : new ArangoSearchCreateOptions(), name))); } protected Request getAnalyzerRequest(final String name) { @@ -360,12 +360,12 @@ protected Request getAnalyzersRequest() { } protected ResponseDeserializer> getSearchAnalyzersResponseDeserializer() { - return response -> getInternalSerde().deserialize(response.getBody(), ArangoResponseField.RESULT_JSON_POINTER, + return response -> getSerde().deserialize(response.getBody(), ArangoResponseField.RESULT_JSON_POINTER, SerdeUtils.INSTANCE.constructListType(SearchAnalyzer.class)); } protected Request createAnalyzerRequest(final SearchAnalyzer options) { - return request(dbName, RequestType.POST, InternalArangoView.PATH_API_ANALYZER).setBody(getInternalSerde().serialize(options)); + return request(dbName, RequestType.POST, InternalArangoView.PATH_API_ANALYZER).setBody(getSerde().serialize(options)); } protected Request deleteAnalyzerRequest(final String name, final AnalyzerDeleteOptions options) { diff --git a/src/main/java/com/arangodb/internal/InternalArangoEdgeCollection.java b/src/main/java/com/arangodb/internal/InternalArangoEdgeCollection.java index ae4b357bf..01e6b5e68 100644 --- a/src/main/java/com/arangodb/internal/InternalArangoEdgeCollection.java +++ b/src/main/java/com/arangodb/internal/InternalArangoEdgeCollection.java @@ -46,7 +46,7 @@ public abstract class InternalArangoEdgeCollection private final String name; protected InternalArangoEdgeCollection(final G graph, final String name) { - super(graph.executor, graph.util, graph.context); + super(graph.executor, graph.serde, graph.context); this.graph = graph; this.name = name; } @@ -65,13 +65,13 @@ protected Request insertEdgeRequest(final T value, final EdgeCreateOptions o final EdgeCreateOptions params = (options != null ? options : new EdgeCreateOptions()); request.putHeaderParam(TRANSACTION_ID, params.getStreamTransactionId()); request.putQueryParam(ArangoRequestParam.WAIT_FOR_SYNC, params.getWaitForSync()); - request.setBody(getUserSerde().serialize(value)); + request.setBody(getSerde().serializeUserData(value)); return request; } protected ResponseDeserializer insertEdgeResponseDeserializer(final T value) { return response -> { - final EdgeEntity doc = getInternalSerde().deserialize(response.getBody(), "/edge", EdgeEntity.class); + final EdgeEntity doc = getSerde().deserialize(response.getBody(), "/edge", EdgeEntity.class); final Map values = new HashMap<>(); values.put(DocumentFields.ID, doc.getId()); values.put(DocumentFields.KEY, doc.getKey()); @@ -95,7 +95,7 @@ protected Request getEdgeRequest(final String key, final GraphDocumentReadOption } protected ResponseDeserializer getEdgeResponseDeserializer(final Class type) { - return response -> getUserSerde().deserialize(getInternalSerde().extract(response.getBody(), "/edge"), type); + return response -> getSerde().deserializeUserData(getSerde().extract(response.getBody(), "/edge"), type); } protected Request replaceEdgeRequest(final String key, final T value, final EdgeReplaceOptions options) { @@ -105,13 +105,13 @@ protected Request replaceEdgeRequest(final String key, final T value, final request.putHeaderParam(TRANSACTION_ID, params.getStreamTransactionId()); request.putQueryParam(ArangoRequestParam.WAIT_FOR_SYNC, params.getWaitForSync()); request.putHeaderParam(ArangoRequestParam.IF_MATCH, params.getIfMatch()); - request.setBody(getUserSerde().serialize(value)); + request.setBody(getSerde().serializeUserData(value)); return request; } protected ResponseDeserializer replaceEdgeResponseDeserializer(final T value) { return response -> { - final EdgeUpdateEntity doc = getInternalSerde().deserialize(response.getBody(), "/edge", EdgeUpdateEntity.class); + final EdgeUpdateEntity doc = getSerde().deserialize(response.getBody(), "/edge", EdgeUpdateEntity.class); final Map values = new HashMap<>(); values.put(DocumentFields.REV, doc.getRev()); executor.documentCache().setValues(value, values); @@ -128,13 +128,13 @@ protected Request updateEdgeRequest(final String key, final T value, final E request.putQueryParam(ArangoRequestParam.KEEP_NULL, params.getKeepNull()); request.putQueryParam(ArangoRequestParam.WAIT_FOR_SYNC, params.getWaitForSync()); request.putHeaderParam(ArangoRequestParam.IF_MATCH, params.getIfMatch()); - request.setBody(getUserSerde().serialize(value)); + request.setBody(getSerde().serializeUserData(value)); return request; } protected ResponseDeserializer updateEdgeResponseDeserializer(final T value) { return response -> { - final EdgeUpdateEntity doc = getInternalSerde().deserialize(response.getBody(), "/edge", EdgeUpdateEntity.class); + final EdgeUpdateEntity doc = getSerde().deserialize(response.getBody(), "/edge", EdgeUpdateEntity.class); final Map values = new HashMap<>(); values.put(DocumentFields.REV, doc.getRev()); executor.documentCache().setValues(value, values); diff --git a/src/main/java/com/arangodb/internal/InternalArangoGraph.java b/src/main/java/com/arangodb/internal/InternalArangoGraph.java index 4e74bcf25..46e3ff8d1 100644 --- a/src/main/java/com/arangodb/internal/InternalArangoGraph.java +++ b/src/main/java/com/arangodb/internal/InternalArangoGraph.java @@ -46,7 +46,7 @@ public abstract class InternalArangoGraph, D exten private final String name; protected InternalArangoGraph(final D db, final String name) { - super(db.executor, db.util, db.context); + super(db.executor, db.serde, db.context); this.db = db; this.name = name; } @@ -84,13 +84,13 @@ protected Request getVertexCollectionsRequest() { } protected ResponseDeserializer> getVertexCollectionsResponseDeserializer() { - return response -> getInternalSerde().deserialize(response.getBody(), "/collections", + return response -> getSerde().deserialize(response.getBody(), "/collections", SerdeUtils.INSTANCE.constructListType(String.class)); } protected Request addVertexCollectionRequest(final String name, final VertexCollectionCreateOptions options) { final Request request = request(db.dbName(), RequestType.POST, PATH_API_GHARIAL, name(), VERTEX); - request.setBody(getInternalSerde().serialize(OptionsBuilder.build(options, name))); + request.setBody(getSerde().serialize(OptionsBuilder.build(options, name))); return request; } @@ -103,29 +103,29 @@ protected Request getEdgeDefinitionsRequest() { } protected ResponseDeserializer> getEdgeDefinitionsDeserializer() { - return response -> getInternalSerde().deserialize(response.getBody(), "/collections", + return response -> getSerde().deserialize(response.getBody(), "/collections", SerdeUtils.INSTANCE.constructListType(String.class)); } protected Request addEdgeDefinitionRequest(final EdgeDefinition definition) { final Request request = request(db.dbName(), RequestType.POST, PATH_API_GHARIAL, name, EDGE); - request.setBody(getInternalSerde().serialize(definition)); + request.setBody(getSerde().serialize(definition)); return request; } protected ResponseDeserializer addEdgeDefinitionResponseDeserializer() { - return response -> getInternalSerde().deserialize(response.getBody(), GRAPH, GraphEntity.class); + return response -> getSerde().deserialize(response.getBody(), GRAPH, GraphEntity.class); } protected Request replaceEdgeDefinitionRequest(final EdgeDefinition definition) { final Request request = request(db.dbName(), RequestType.PUT, PATH_API_GHARIAL, name, EDGE, definition.getCollection()); - request.setBody(getInternalSerde().serialize(definition)); + request.setBody(getSerde().serialize(definition)); return request; } protected ResponseDeserializer replaceEdgeDefinitionResponseDeserializer() { - return response -> getInternalSerde().deserialize(response.getBody(), GRAPH, GraphEntity.class); + return response -> getSerde().deserialize(response.getBody(), GRAPH, GraphEntity.class); } protected Request removeEdgeDefinitionRequest(final String definitionName) { @@ -133,7 +133,7 @@ protected Request removeEdgeDefinitionRequest(final String definitionName) { } protected ResponseDeserializer removeEdgeDefinitionResponseDeserializer() { - return response -> getInternalSerde().deserialize(response.getBody(), GRAPH, GraphEntity.class); + return response -> getSerde().deserialize(response.getBody(), GRAPH, GraphEntity.class); } } diff --git a/src/main/java/com/arangodb/internal/InternalArangoRoute.java b/src/main/java/com/arangodb/internal/InternalArangoRoute.java index f053c19ce..7e0f11949 100644 --- a/src/main/java/com/arangodb/internal/InternalArangoRoute.java +++ b/src/main/java/com/arangodb/internal/InternalArangoRoute.java @@ -41,7 +41,7 @@ public abstract class InternalArangoRoute, D exten protected Object body; protected InternalArangoRoute(final D db, final String path, final Map headerParam) { - super(db.executor, db.util, db.context); + super(db.executor, db.serde, db.context); this.db = db; this.path = path; this.queryParam = new HashMap<>(); @@ -74,7 +74,7 @@ protected Request createRequest(final RequestType requestType) { request.putQueryParam(param.getKey(), param.getValue()); } if (body != null) { - request.setBody(getInternalSerde().serialize(body)); + request.setBody(getSerde().serialize(body)); } return request; } diff --git a/src/main/java/com/arangodb/internal/InternalArangoSearch.java b/src/main/java/com/arangodb/internal/InternalArangoSearch.java index 8e09b414f..cb836c9de 100644 --- a/src/main/java/com/arangodb/internal/InternalArangoSearch.java +++ b/src/main/java/com/arangodb/internal/InternalArangoSearch.java @@ -40,13 +40,13 @@ protected Request getPropertiesRequest() { protected Request replacePropertiesRequest(final ArangoSearchPropertiesOptions options) { final Request request = request(db.dbName(), RequestType.PUT, PATH_API_VIEW, name, "properties"); - request.setBody(getInternalSerde().serialize(options != null ? options : new ArangoSearchPropertiesOptions())); + request.setBody(getSerde().serialize(options != null ? options : new ArangoSearchPropertiesOptions())); return request; } protected Request updatePropertiesRequest(final ArangoSearchPropertiesOptions options) { final Request request = request(db.dbName(), RequestType.PATCH, PATH_API_VIEW, name, "properties"); - request.setBody(getInternalSerde().serialize(options != null ? options : new ArangoSearchPropertiesOptions())); + request.setBody(getSerde().serialize(options != null ? options : new ArangoSearchPropertiesOptions())); return request; } diff --git a/src/main/java/com/arangodb/internal/InternalArangoVertexCollection.java b/src/main/java/com/arangodb/internal/InternalArangoVertexCollection.java index f74214086..6cd10c0d7 100644 --- a/src/main/java/com/arangodb/internal/InternalArangoVertexCollection.java +++ b/src/main/java/com/arangodb/internal/InternalArangoVertexCollection.java @@ -47,7 +47,7 @@ public abstract class InternalArangoVertexCollection Request insertVertexRequest(final T value, final VertexCreateOptio byte[] body; if (value instanceof String) { - body = getInternalSerde().serialize(SerdeUtils.INSTANCE.parseJson((String) value)); + body = getSerde().serialize(SerdeUtils.INSTANCE.parseJson((String) value)); } else { - body = getUserSerde().serialize(value); + body = getSerde().serializeUserData(value); } request.setBody(body); return request; @@ -83,7 +83,7 @@ protected Request insertVertexRequest(final T value, final VertexCreateOptio protected ResponseDeserializer insertVertexResponseDeserializer(final T value) { return response -> { - final VertexEntity doc = getInternalSerde().deserialize(response.getBody(), "/vertex", VertexEntity.class); + final VertexEntity doc = getSerde().deserialize(response.getBody(), "/vertex", VertexEntity.class); final Map values = new HashMap<>(); values.put(DocumentFields.ID, doc.getId()); values.put(DocumentFields.KEY, doc.getKey()); @@ -107,7 +107,7 @@ protected Request getVertexRequest(final String key, final GraphDocumentReadOpti } protected ResponseDeserializer getVertexResponseDeserializer(final Class type) { - return response -> getUserSerde().deserialize(getInternalSerde().extract(response.getBody(), "/vertex"), type); + return response -> getSerde().deserializeUserData(getSerde().extract(response.getBody(), "/vertex"), type); } protected Request replaceVertexRequest(final String key, final T value, final VertexReplaceOptions options) { @@ -117,13 +117,13 @@ protected Request replaceVertexRequest(final String key, final T value, fina request.putHeaderParam(TRANSACTION_ID, params.getStreamTransactionId()); request.putQueryParam(ArangoRequestParam.WAIT_FOR_SYNC, params.getWaitForSync()); request.putHeaderParam(ArangoRequestParam.IF_MATCH, params.getIfMatch()); - request.setBody(getUserSerde().serialize(value)); + request.setBody(getSerde().serializeUserData(value)); return request; } protected ResponseDeserializer replaceVertexResponseDeserializer(final T value) { return response -> { - final VertexUpdateEntity doc = getInternalSerde().deserialize(response.getBody(), "/vertex", VertexUpdateEntity.class); + final VertexUpdateEntity doc = getSerde().deserialize(response.getBody(), "/vertex", VertexUpdateEntity.class); final Map values = new HashMap<>(); values.put(DocumentFields.REV, doc.getRev()); executor.documentCache().setValues(value, values); @@ -140,13 +140,13 @@ protected Request updateVertexRequest(final String key, final T value, final request.putQueryParam(ArangoRequestParam.KEEP_NULL, params.getKeepNull()); request.putQueryParam(ArangoRequestParam.WAIT_FOR_SYNC, params.getWaitForSync()); request.putHeaderParam(ArangoRequestParam.IF_MATCH, params.getIfMatch()); - request.setBody(getUserSerde().serialize(value)); + request.setBody(getSerde().serializeUserData(value)); return request; } protected ResponseDeserializer updateVertexResponseDeserializer(final T value) { return response -> { - final VertexUpdateEntity doc = getInternalSerde().deserialize(response.getBody(), "/vertex", VertexUpdateEntity.class); + final VertexUpdateEntity doc = getSerde().deserialize(response.getBody(), "/vertex", VertexUpdateEntity.class); final Map values = new HashMap<>(); values.put(DocumentFields.REV, doc.getRev()); executor.documentCache().setValues(value, values); diff --git a/src/main/java/com/arangodb/internal/InternalArangoView.java b/src/main/java/com/arangodb/internal/InternalArangoView.java index 0f4e821e6..fde7cfa64 100644 --- a/src/main/java/com/arangodb/internal/InternalArangoView.java +++ b/src/main/java/com/arangodb/internal/InternalArangoView.java @@ -39,7 +39,7 @@ public abstract class InternalArangoView, D extend protected volatile String name; protected InternalArangoView(final D db, final String name) { - super(db.executor, db.util, db.context); + super(db.executor, db.serde, db.context); this.db = db; this.name = name; } @@ -58,7 +58,7 @@ protected Request dropRequest() { protected Request renameRequest(final String newName) { final Request request = request(db.dbName(), RequestType.PUT, PATH_API_VIEW, name, "rename"); - request.setBody(getInternalSerde().serialize(OptionsBuilder.build(new ViewRenameOptions(), newName))); + request.setBody(getSerde().serialize(OptionsBuilder.build(new ViewRenameOptions(), newName))); return request; } diff --git a/src/main/java/com/arangodb/internal/cursor/ArangoCursorIterator.java b/src/main/java/com/arangodb/internal/cursor/ArangoCursorIterator.java index a89191cb8..b3b048158 100644 --- a/src/main/java/com/arangodb/internal/cursor/ArangoCursorIterator.java +++ b/src/main/java/com/arangodb/internal/cursor/ArangoCursorIterator.java @@ -70,11 +70,11 @@ public T next() { if (!hasNext()) { throw new NoSuchElementException(); } - return deserialize(db.getInternalSerde().serialize(arrayIterator.next()), cursor.getType()); + return deserialize(db.getSerde().serialize(arrayIterator.next()), cursor.getType()); } protected R deserialize(final byte[] result, final Class type) { - return db.getUserSerde().deserialize(result, type); + return db.getSerde().deserializeUserData(result, type); } @Override diff --git a/src/main/java/com/arangodb/internal/util/ArangoSerdeFactory.java b/src/main/java/com/arangodb/internal/util/ArangoSerdeFactory.java deleted file mode 100644 index 5edfef0b3..000000000 --- a/src/main/java/com/arangodb/internal/util/ArangoSerdeFactory.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2018 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.internal.util; - -import com.arangodb.serde.ArangoSerde; -import com.arangodb.serde.InternalSerde; - -/** - * @author Mark Vollmary - */ -public class ArangoSerdeFactory { - - private final InternalSerde internal; - private final ArangoSerde user; - - public ArangoSerdeFactory(final InternalSerde internal, final ArangoSerde user) { - super(); - this.internal = internal; - this.user = user; - } - - public InternalSerde getInternalSerde() { - return internal; - } - - public ArangoSerde getUserSerialization() { - return user; - } - -} diff --git a/src/main/java/com/arangodb/serde/InternalSerde.java b/src/main/java/com/arangodb/serde/InternalSerde.java index d7f161b29..fb7e0626b 100644 --- a/src/main/java/com/arangodb/serde/InternalSerde.java +++ b/src/main/java/com/arangodb/serde/InternalSerde.java @@ -14,11 +14,11 @@ public interface InternalSerde extends JacksonSerde { * @param dataType serialization target data type * @return the created InternalSerde */ - static InternalSerde of(final DataType dataType) { + static InternalSerde of(final DataType dataType, ArangoSerde userSerde) { if (dataType == DataType.JSON) { - return new InternalSerdeImpl(new ObjectMapper()); + return new InternalSerdeImpl(new ObjectMapper(), userSerde); } else if (dataType == DataType.VPACK) { - return new InternalSerdeImpl(new VPackMapper()); + return new InternalSerdeImpl(new VPackMapper(), userSerde); } else { throw new IllegalArgumentException("Unexpected value: " + dataType); } @@ -105,4 +105,36 @@ default T deserialize(byte[] content, String jsonPointer, Type type) { return deserialize(parse(content, jsonPointer), type); } + /** + * Serializes the object into the target data type, using the user serde. + * + * @param value object to serialize + * @return serialized byte array + */ + byte[] serializeUserData(Object value); + + /** + * Deserializes the content and binds it to the target data type, using the user serde. + * + * @param content byte array to deserialize + * @param clazz class of target data type + * @return deserialized object + */ + default T deserializeUserData(byte[] content, Class clazz) { + return deserializeUserData(content, (Type) clazz); + } + + /** + * Deserializes the content and binds it to the target data type, using the user serde. + * + * @param content byte array to deserialize + * @param type target data type + * @return deserialized object + */ + T deserializeUserData(byte[] content, Type type); + + /** + * @return the user serde + */ + ArangoSerde getUserSerde(); } diff --git a/src/main/java/com/arangodb/serde/InternalSerdeImpl.java b/src/main/java/com/arangodb/serde/InternalSerdeImpl.java index 996c9a373..b5b9f01d3 100644 --- a/src/main/java/com/arangodb/serde/InternalSerdeImpl.java +++ b/src/main/java/com/arangodb/serde/InternalSerdeImpl.java @@ -1,6 +1,8 @@ package com.arangodb.serde; import com.arangodb.ArangoDBException; +import com.arangodb.util.RawBytes; +import com.arangodb.util.RawJson; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; @@ -10,8 +12,11 @@ final class InternalSerdeImpl extends JacksonSerdeImpl implements InternalSerde { - InternalSerdeImpl(ObjectMapper mapper) { + private final ArangoSerde userSerde; + + InternalSerdeImpl(final ObjectMapper mapper, final ArangoSerde userSerde) { super(mapper); + this.userSerde = userSerde; mapper.registerModule(InternalModule.INSTANCE.get()); mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); } @@ -53,6 +58,29 @@ public JsonNode parse(byte[] content, String jsonPointer) { } } + @Override + public byte[] serializeUserData(Object value) { + if (RawJson.class.equals(value.getClass()) || RawBytes.class.equals(value.getClass())) { + return serialize(value); + } else { + return userSerde.serialize(value); + } + } + + @Override + public T deserializeUserData(byte[] content, Type type) { + if (RawJson.class.equals(type) || RawBytes.class.equals(type)) { + return deserialize(content, type); + } else { + return userSerde.deserialize(content, type); + } + } + + @Override + public ArangoSerde getUserSerde() { + return userSerde; + } + @Override public T deserialize(final JsonNode node, final Type type) { try { @@ -62,4 +90,12 @@ public T deserialize(final JsonNode node, final Type type) { } } + @Override + public T deserialize(final byte[] content, final Type type) { + if (content == null) { + return null; + } + return super.deserialize(content, type); + } + } diff --git a/src/test/java/com/arangodb/ArangoDBTest.java b/src/test/java/com/arangodb/ArangoDBTest.java index 5762bf915..c51a12272 100644 --- a/src/test/java/com/arangodb/ArangoDBTest.java +++ b/src/test/java/com/arangodb/ArangoDBTest.java @@ -393,7 +393,7 @@ void authenticationFailUser() { @MethodSource("arangos") void execute(ArangoDB arangoDB) { final Response response = arangoDB.execute(new Request(DbName.SYSTEM, RequestType.GET, "/_api/version")); - assertThat(arangoDB.getInternalSerde().parse(response.getBody(), "/version").isTextual()).isTrue(); + assertThat(arangoDB.getSerde().parse(response.getBody(), "/version").isTextual()).isTrue(); } @ParameterizedTest(name = "{index}") diff --git a/src/test/java/com/arangodb/ArangoRouteTest.java b/src/test/java/com/arangodb/ArangoRouteTest.java index b6866fbea..613b8e3b8 100644 --- a/src/test/java/com/arangodb/ArangoRouteTest.java +++ b/src/test/java/com/arangodb/ArangoRouteTest.java @@ -47,7 +47,7 @@ static void init() { @MethodSource("dbs") void get(ArangoDatabase db) { final Response res = db.route("/_api/version").get(); - assertThat(db.arango().getInternalSerde().parse(res.getBody(), "/version").isTextual()).isTrue(); + assertThat(db.arango().getSerde().parse(res.getBody(), "/version").isTextual()).isTrue(); } @ParameterizedTest(name = "{index}") diff --git a/src/test/java/com/arangodb/JwtAuthTest.java b/src/test/java/com/arangodb/JwtAuthTest.java index 59d12df67..71bf4da0e 100644 --- a/src/test/java/com/arangodb/JwtAuthTest.java +++ b/src/test/java/com/arangodb/JwtAuthTest.java @@ -82,7 +82,7 @@ private ArangoDB.Builder getBuilder(Protocol protocol) { } private static String getJwt(ArangoDB arangoDB) { - InternalSerde serde = arangoDB.getInternalSerde(); + InternalSerde serde = arangoDB.getSerde(); Map reqBody = new HashMap<>(); reqBody.put("username", "root"); reqBody.put("password", "test"); diff --git a/src/test/java/com/arangodb/async/ArangoDBTest.java b/src/test/java/com/arangodb/async/ArangoDBTest.java index 743b7cc28..2169914d4 100644 --- a/src/test/java/com/arangodb/async/ArangoDBTest.java +++ b/src/test/java/com/arangodb/async/ArangoDBTest.java @@ -439,7 +439,7 @@ void execute() throws InterruptedException, ExecutionException { .execute(new Request(DbName.SYSTEM, RequestType.GET, "/_api/version")) .whenComplete((response, ex) -> { assertThat(response.getBody()).isNotNull(); - assertThat(arangoDB.getInternalSerde().parse(response.getBody(), "/version").isTextual()).isTrue(); + assertThat(arangoDB.getSerde().parse(response.getBody(), "/version").isTextual()).isTrue(); }) .get(); } @@ -451,7 +451,7 @@ void execute_acquireHostList_enabled() throws InterruptedException, ExecutionEx .execute(new Request(DbName.SYSTEM, RequestType.GET, "/_api/version")) .whenComplete((response, ex) -> { assertThat(response.getBody()).isNotNull(); - assertThat(arangoDB.getInternalSerde().parse(response.getBody(), "/version").isTextual()).isTrue(); + assertThat(arangoDB.getSerde().parse(response.getBody(), "/version").isTextual()).isTrue(); }) .get(); } diff --git a/src/test/java/com/arangodb/async/JwtAuthTest.java b/src/test/java/com/arangodb/async/JwtAuthTest.java index 640c7a0ee..13ac28bc6 100644 --- a/src/test/java/com/arangodb/async/JwtAuthTest.java +++ b/src/test/java/com/arangodb/async/JwtAuthTest.java @@ -89,7 +89,7 @@ private ArangoDBAsync.Builder getBuilder() { } private static String getJwt(ArangoDB arangoDB) { - InternalSerde serde = arangoDB.getInternalSerde(); + InternalSerde serde = arangoDB.getSerde(); Map reqBody = new HashMap<>(); reqBody.put("username", "root"); reqBody.put("password", "test"); diff --git a/src/test/java/com/arangodb/serde/SerdeTest.java b/src/test/java/com/arangodb/serde/SerdeTest.java index d1e315ff6..6e924e4fb 100644 --- a/src/test/java/com/arangodb/serde/SerdeTest.java +++ b/src/test/java/com/arangodb/serde/SerdeTest.java @@ -16,7 +16,7 @@ class SerdeTest { @ParameterizedTest @EnumSource(DataType.class) void rawJsonSerde(DataType type) { - InternalSerde s = InternalSerde.of(type); + InternalSerde s = InternalSerde.of(type, null); ObjectNode node = JsonNodeFactory.instance.objectNode().put("foo", "bar"); RawJson raw = RawJson.of(SerdeUtils.INSTANCE.writeJson(node)); byte[] serialized = s.serialize(raw); @@ -27,7 +27,7 @@ void rawJsonSerde(DataType type) { @ParameterizedTest @EnumSource(DataType.class) void rawBytesSerde(DataType type) { - InternalSerde s = InternalSerde.of(type); + InternalSerde s = InternalSerde.of(type, null); ObjectNode node = JsonNodeFactory.instance.objectNode().put("foo", "bar"); RawBytes raw = RawBytes.of(s.serialize(node)); byte[] serialized = s.serialize(raw); From af633ae7d14cd22c94be130bb1a9c859384465a3 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Fri, 22 Jul 2022 23:32:56 +0200 Subject: [PATCH 044/254] removed support for raw json strings in favor of RawJson and RawBytes wrappers --- .../java/com/arangodb/ArangoCollection.java | 40 +- .../java/com/arangodb/ArangoDatabase.java | 16 +- .../com/arangodb/ArangoEdgeCollection.java | 16 +- .../com/arangodb/ArangoVertexCollection.java | 16 +- .../arangodb/async/ArangoCollectionAsync.java | 40 +- .../arangodb/async/ArangoDatabaseAsync.java | 16 +- .../async/ArangoEdgeCollectionAsync.java | 8 +- .../async/ArangoVertexCollectionAsync.java | 8 +- .../internal/InternalArangoCollection.java | 30 +- .../internal/InternalArangoDatabase.java | 6 +- .../InternalArangoVertexCollection.java | 9 +- .../com/arangodb/serde/InternalSerde.java | 20 + .../com/arangodb/serde/InternalSerdeImpl.java | 5 + .../com/arangodb/ArangoCollectionTest.java | 708 ++++++------------ .../java/com/arangodb/ArangoDatabaseTest.java | 39 +- .../arangodb/ArangoVertexCollectionTest.java | 5 +- src/test/java/com/arangodb/DocumentTest.java | 8 +- .../arangodb/async/ArangoCollectionTest.java | 27 +- .../arangodb/async/ArangoDatabaseTest.java | 5 +- .../document/GetDocumentExampleTest.java | 10 +- .../document/InsertDocumentExampleTest.java | 3 +- .../document/GetDocumentExampleTest.java | 18 +- .../document/InsertDocumentExampleTest.java | 3 +- 23 files changed, 406 insertions(+), 650 deletions(-) diff --git a/src/main/java/com/arangodb/ArangoCollection.java b/src/main/java/com/arangodb/ArangoCollection.java index ebd00fad5..c77a228f4 100644 --- a/src/main/java/com/arangodb/ArangoCollection.java +++ b/src/main/java/com/arangodb/ArangoCollection.java @@ -55,7 +55,7 @@ public interface ArangoCollection extends ArangoSerdeAccessor { * Creates a new document from the given document, unless there is already a document with the _key given. If no * _key is given, a new unique _key is generated automatically. * - * @param value A representation of a single document (POJO or String for JSON) + * @param value A representation of a single document (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) * @return information about the document * @throws ArangoDBException * @see API @@ -67,7 +67,7 @@ public interface ArangoCollection extends ArangoSerdeAccessor { * Creates a new document from the given document, unless there is already a document with the _key given. If no * _key is given, a new unique _key is generated automatically. * - * @param value A representation of a single document (POJO or String for JSON) + * @param value A representation of a single document (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) * @param options Additional options, can be null * @return information about the document * @throws ArangoDBException @@ -83,7 +83,7 @@ public interface ArangoCollection extends ArangoSerdeAccessor { * Limitations: * - the fields having {@code null} value are always removed during serialization * - * @param values A List of documents (POJO or String for JSON) + * @param values A List of documents (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) * @return information about the documents * @throws ArangoDBException * @see API @@ -98,7 +98,7 @@ public interface ArangoCollection extends ArangoSerdeAccessor { * Limitations: * - the fields having {@code null} value are always removed during serialization * - * @param values A List of documents (POJO or String for JSON) + * @param values A List of documents (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) * @param options Additional options, can be null * @return information about the documents * @throws ArangoDBException @@ -162,7 +162,7 @@ MultiDocumentEntity> insertDocuments( * Retrieves the document with the given {@code key} from the collection. * * @param key The key of the document - * @param type The type of the document (POJO class or String for JSON) + * @param type The type of the document (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) * @return the document identified by the key * @throws ArangoDBException * @see API @@ -174,7 +174,7 @@ MultiDocumentEntity> insertDocuments( * Retrieves the document with the given {@code key} from the collection. * * @param key The key of the document - * @param type The type of the document (POJO class or String for JSON) + * @param type The type of the document (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) * @param options Additional options, can be null * @return the document identified by the key * @throws ArangoDBException @@ -187,7 +187,7 @@ MultiDocumentEntity> insertDocuments( * Retrieves multiple documents with the given {@code _key} from the collection. * * @param keys The keys of the documents - * @param type The type of the documents (POJO class or String for JSON) + * @param type The type of the documents (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) * @return the documents and possible errors * @throws ArangoDBException */ @@ -197,7 +197,7 @@ MultiDocumentEntity> insertDocuments( * Retrieves multiple documents with the given {@code _key} from the collection. * * @param keys The keys of the documents - * @param type The type of the documents (POJO class or String for JSON) + * @param type The type of the documents (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) * @param options Additional options, can be null * @return the documents and possible errors * @throws ArangoDBException @@ -210,7 +210,7 @@ MultiDocumentEntity getDocuments(Collection keys, Class type, * precondition is violated * * @param key The key of the document - * @param value A representation of a single document (POJO or String for JSON) + * @param value A representation of a single document (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) * @return information about the document * @throws ArangoDBException * @see API @@ -223,7 +223,7 @@ MultiDocumentEntity getDocuments(Collection keys, Class type, * precondition is violated * * @param key The key of the document - * @param value A representation of a single document (POJO or String for JSON) + * @param value A representation of a single document (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) * @param options Additional options, can be null * @return information about the document * @throws ArangoDBException @@ -240,7 +240,7 @@ DocumentUpdateEntity replaceDocument(String key, T value, DocumentReplace * Limitations: * - the fields having {@code null} value are always removed during serialization * - * @param values A List of documents (POJO or String for JSON) + * @param values A List of documents (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) * @return information about the documents * @throws ArangoDBException * @see API @@ -255,7 +255,7 @@ DocumentUpdateEntity replaceDocument(String key, T value, DocumentReplace * Limitations: * - the fields having {@code null} value are always removed during serialization * - * @param values A List of documents (POJO or String for JSON) + * @param values A List of documents (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) * @param options Additional options, can be null * @return information about the documents * @throws ArangoDBException @@ -271,7 +271,7 @@ MultiDocumentEntity> replaceDocuments( * they do not yet exist, and overwritten in the existing document if they do exist there. * * @param key The key of the document - * @param value A representation of a single document (POJO or String for JSON) + * @param value A representation of a single document (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) * @return information about the document * @throws ArangoDBException * @see API @@ -285,7 +285,7 @@ MultiDocumentEntity> replaceDocuments( * they do not yet exist, and overwritten in the existing document if they do exist there. * * @param key The key of the document - * @param value A representation of a single document (POJO or String for JSON) + * @param value A representation of a single document (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) * @param options Additional options, can be null * @return information about the document * @throws ArangoDBException @@ -301,7 +301,7 @@ DocumentUpdateEntity updateDocument(String key, T value, DocumentUpdateOp * they do not yet exist, and overwritten in the existing document if they do exist there. * * @param key The key of the document - * @param value A representation of a single document (POJO or String for JSON) + * @param value A representation of a single document (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) * @param options Additional options, can be null * @param returnType Type of the returned newDocument and/or oldDocument * @return information about the document @@ -318,7 +318,7 @@ DocumentUpdateEntity updateDocument(String key, T value, DocumentUpdat * attributes from the patch documents will be added to the existing documents if they do not yet exist, and * overwritten in the existing documents if they do exist there. * - * @param values A list of documents (POJO or String for JSON) + * @param values A list of documents (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) * @return information about the documents * @throws ArangoDBException * @see API @@ -332,7 +332,7 @@ DocumentUpdateEntity updateDocument(String key, T value, DocumentUpdat * attributes from the patch documents will be added to the existing documents if they do not yet exist, and * overwritten in the existing documents if they do exist there. * - * @param values A list of documents (POJO or String for JSON) + * @param values A list of documents (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) * @param options Additional options, can be null * @return information about the documents * @throws ArangoDBException @@ -348,7 +348,7 @@ MultiDocumentEntity> updateDocuments( * attributes from the patch documents will be added to the existing documents if they do not yet exist, and * overwritten in the existing documents if they do exist there. * - * @param values A list of documents (POJO or String for JSON) + * @param values A list of documents (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) * @param options Additional options, can be null * @param returnType Type of the returned newDocument and/or oldDocument * @return information about the documents @@ -374,7 +374,7 @@ MultiDocumentEntity> updateDocuments( * Deletes the document with the given {@code key} from the collection. * * @param key The key of the document - * @param type The type of the document (POJO class or String for JSON). Only necessary if + * @param type The type of the document (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}). Only necessary if * options.returnOld is set to true, otherwise can be null. * @param options Additional options, can be null * @return information about the document @@ -401,7 +401,7 @@ DocumentDeleteEntity deleteDocument(String key, Class type, DocumentDe * Deletes multiple documents from the collection. * * @param values The keys of the documents or the documents themselves - * @param type The type of the documents (POJO class or String for JSON). Only necessary if + * @param type The type of the documents (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}). Only necessary if * options.returnOld is set to true, otherwise can be null. * @param options Additional options, can be null * @return information about the documents diff --git a/src/main/java/com/arangodb/ArangoDatabase.java b/src/main/java/com/arangodb/ArangoDatabase.java index 6aaf3ff26..58d055418 100644 --- a/src/main/java/com/arangodb/ArangoDatabase.java +++ b/src/main/java/com/arangodb/ArangoDatabase.java @@ -260,7 +260,7 @@ public interface ArangoDatabase extends ArangoSerdeAccessor { * @param query An AQL query string * @param bindVars key/value pairs defining the variables to bind the query to * @param options Additional options that will be passed to the query API, can be null - * @param type The type of the result (POJO class, String for JSON, or Collection/List/Map) + * @param type The type of the result (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) * @return cursor of the results * @throws ArangoDBException * @see API @@ -275,7 +275,7 @@ ArangoCursor query(String query, Map bindVars, AqlQueryOp * * @param query An AQL query string * @param options Additional options that will be passed to the query API, can be null - * @param type The type of the result (POJO class, String for JSON, or Collection/List/Map) + * @param type The type of the result (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) * @return cursor of the results * @throws ArangoDBException * @see API @@ -289,7 +289,7 @@ ArangoCursor query(String query, Map bindVars, AqlQueryOp * * @param query An AQL query string * @param bindVars key/value pairs defining the variables to bind the query to - * @param type The type of the result (POJO class, String for JSON, or Collection/List/Map) + * @param type The type of the result (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) * @return cursor of the results * @throws ArangoDBException * @see API @@ -302,7 +302,7 @@ ArangoCursor query(String query, Map bindVars, AqlQueryOp * result list. * * @param query An AQL query string - * @param type The type of the result (POJO class, String for JSON, or Collection/List/Map) + * @param type The type of the result (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) * @return cursor of the results * @throws ArangoDBException * @see API @@ -314,7 +314,7 @@ ArangoCursor query(String query, Map bindVars, AqlQueryOp * Return an cursor from the given cursor-ID if still existing * * @param cursorId The ID of the cursor - * @param type The type of the result (POJO class, String for JSON, or Collection/List/Map) + * @param type The type of the result (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) * @return cursor of the results * @throws ArangoDBException * @see edgeDefinitions, * Performs a server-side transaction and returns its return value. * * @param action A String evaluating to a JavaScript function to be executed on the server. - * @param type The type of the result (POJO class or String for JSON) + * @param type The type of the result (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) * @param options Additional options, can be null * @return the result of the transaction if it succeeded * @throws ArangoDBException @@ -615,7 +615,7 @@ GraphEntity createGraph(String name, Collection edgeDefinitions, * Reads a single document * * @param id The id of the document - * @param type The type of the document (POJO class or String for JSON) + * @param type The type of the document (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) * @return the document identified by the id * @throws ArangoDBException * @see API @@ -627,7 +627,7 @@ GraphEntity createGraph(String name, Collection edgeDefinitions, * Reads a single document * * @param id The id of the document - * @param type The type of the document (POJO class or String for JSON) + * @param type The type of the document (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) * @param options Additional options, can be null * @return the document identified by the id * @throws ArangoDBException diff --git a/src/main/java/com/arangodb/ArangoEdgeCollection.java b/src/main/java/com/arangodb/ArangoEdgeCollection.java index 569d5d561..0c8bbc45d 100644 --- a/src/main/java/com/arangodb/ArangoEdgeCollection.java +++ b/src/main/java/com/arangodb/ArangoEdgeCollection.java @@ -50,7 +50,7 @@ public interface ArangoEdgeCollection extends ArangoSerdeAccessor { /** * Creates a new edge in the collection * - * @param value A representation of a single edge (POJO or String for JSON) + * @param value A representation of a single edge (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) * @return information about the edge * @throws ArangoDBException * @see API Documentation @@ -60,7 +60,7 @@ public interface ArangoEdgeCollection extends ArangoSerdeAccessor { /** * Creates a new edge in the collection * - * @param value A representation of a single edge (POJO or String for JSON) + * @param value A representation of a single edge (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) * @param options Additional options, can be null * @return information about the edge * @throws ArangoDBException @@ -72,7 +72,7 @@ public interface ArangoEdgeCollection extends ArangoSerdeAccessor { * Fetches an existing edge * * @param key The key of the edge - * @param type The type of the edge-document (POJO class or String for JSON) + * @param type The type of the edge-document (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) * @return the edge identified by the key * @throws ArangoDBException * @see API Documentation @@ -83,7 +83,7 @@ public interface ArangoEdgeCollection extends ArangoSerdeAccessor { * Fetches an existing edge * * @param key The key of the edge - * @param type The type of the edge-document (POJO class or String for JSON) + * @param type The type of the edge-document (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) * @param options Additional options, can be null * @return the edge identified by the key * @throws ArangoDBException @@ -96,7 +96,7 @@ public interface ArangoEdgeCollection extends ArangoSerdeAccessor { * violated * * @param key The key of the edge - * @param The type of the edge-document (POJO class or String for JSON) + * @param The type of the edge-document (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) * @return information about the edge * @throws ArangoDBException * @see API Documentation @@ -108,7 +108,7 @@ public interface ArangoEdgeCollection extends ArangoSerdeAccessor { * violated * * @param key The key of the edge - * @param The type of the edge-document (POJO class or String for JSON) + * @param The type of the edge-document (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) * @param options Additional options, can be null * @return information about the edge * @throws ArangoDBException @@ -122,7 +122,7 @@ public interface ArangoEdgeCollection extends ArangoSerdeAccessor { * do not yet exist, and overwritten in the existing document if they do exist there. * * @param key The key of the edge - * @param The type of the edge-document (POJO class or String for JSON) + * @param The type of the edge-document (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) * @return information about the edge * @throws ArangoDBException * @see API Documentation @@ -135,7 +135,7 @@ public interface ArangoEdgeCollection extends ArangoSerdeAccessor { * do not yet exist, and overwritten in the existing document if they do exist there. * * @param key The key of the edge - * @param The type of the edge-document (POJO class or String for JSON) + * @param The type of the edge-document (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) * @param options Additional options, can be null * @return information about the edge * @throws ArangoDBException diff --git a/src/main/java/com/arangodb/ArangoVertexCollection.java b/src/main/java/com/arangodb/ArangoVertexCollection.java index a8f5b5727..0d514a9fc 100644 --- a/src/main/java/com/arangodb/ArangoVertexCollection.java +++ b/src/main/java/com/arangodb/ArangoVertexCollection.java @@ -59,7 +59,7 @@ public interface ArangoVertexCollection extends ArangoSerdeAccessor { /** * Creates a new vertex in the collection * - * @param value A representation of a single vertex (POJO or String for JSON) + * @param value A representation of a single vertex (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) * @return information about the vertex * @throws ArangoDBException * @see API Documentation @@ -69,7 +69,7 @@ public interface ArangoVertexCollection extends ArangoSerdeAccessor { /** * Creates a new vertex in the collection * - * @param value A representation of a single vertex (POJO or String for JSON) + * @param value A representation of a single vertex (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) * @param options Additional options, can be null * @return information about the vertex * @throws ArangoDBException @@ -81,7 +81,7 @@ public interface ArangoVertexCollection extends ArangoSerdeAccessor { * Retrieves the vertex document with the given {@code key} from the collection. * * @param key The key of the vertex - * @param type The type of the vertex-document (POJO class or String for JSON) + * @param type The type of the vertex-document (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) * @return the vertex identified by the key * @throws ArangoDBException * @see API Documentation @@ -92,7 +92,7 @@ public interface ArangoVertexCollection extends ArangoSerdeAccessor { * Retrieves the vertex document with the given {@code key} from the collection. * * @param key The key of the vertex - * @param type The type of the vertex-document (POJO class or String for JSON) + * @param type The type of the vertex-document (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) * @param options Additional options, can be null * @return the vertex identified by the key * @throws ArangoDBException @@ -105,7 +105,7 @@ public interface ArangoVertexCollection extends ArangoSerdeAccessor { * violated * * @param key The key of the vertex - * @param value A representation of a single vertex (POJO or String for JSON) + * @param value A representation of a single vertex (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) * @return information about the vertex * @throws ArangoDBException * @see API @@ -118,7 +118,7 @@ public interface ArangoVertexCollection extends ArangoSerdeAccessor { * violated * * @param key The key of the vertex - * @param value A representation of a single vertex (POJO or String for JSON) + * @param value A representation of a single vertex (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) * @param options Additional options, can be null * @return information about the vertex * @throws ArangoDBException @@ -133,7 +133,7 @@ public interface ArangoVertexCollection extends ArangoSerdeAccessor { * do not yet exist, and overwritten in the existing document if they do exist there. * * @param key The key of the vertex - * @param The type of the vertex-document (POJO class or String for JSON) + * @param The type of the vertex-document (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) * @return information about the vertex * @throws ArangoDBException * @see API Documentation @@ -146,7 +146,7 @@ public interface ArangoVertexCollection extends ArangoSerdeAccessor { * do not yet exist, and overwritten in the existing document if they do exist there. * * @param key The key of the vertex - * @param The type of the vertex-document (POJO class or String for JSON) + * @param The type of the vertex-document (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) * @param options Additional options, can be null * @return information about the vertex * @throws ArangoDBException diff --git a/src/main/java/com/arangodb/async/ArangoCollectionAsync.java b/src/main/java/com/arangodb/async/ArangoCollectionAsync.java index d2da44236..1df9efcd3 100644 --- a/src/main/java/com/arangodb/async/ArangoCollectionAsync.java +++ b/src/main/java/com/arangodb/async/ArangoCollectionAsync.java @@ -56,7 +56,7 @@ public interface ArangoCollectionAsync extends ArangoSerdeAccessor { * Creates a new document from the given document, unless there is already a document with the _key given. If no * _key is given, a new unique _key is generated automatically. * - * @param value A representation of a single document (POJO or String for Json) + * @param value A representation of a single document (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) * @return information about the document * @see API * Documentation @@ -67,7 +67,7 @@ public interface ArangoCollectionAsync extends ArangoSerdeAccessor { * Creates a new document from the given document, unless there is already a document with the _key given. If no * _key is given, a new unique _key is generated automatically. * - * @param value A representation of a single document (POJO or String for Json) + * @param value A representation of a single document (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) * @param options Additional options, can be null * @return information about the document * @see API @@ -79,7 +79,7 @@ public interface ArangoCollectionAsync extends ArangoSerdeAccessor { * Creates new documents from the given documents, unless there is already a document with the _key given. If no * _key is given, a new unique _key is generated automatically. * - * @param values A List of documents (POJO or String for Json) + * @param values A List of documents (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) * @return information about the documents * @see API * Documentation @@ -90,7 +90,7 @@ public interface ArangoCollectionAsync extends ArangoSerdeAccessor { * Creates new documents from the given documents, unless there is already a document with the _key given. If no * _key is given, a new unique _key is generated automatically. * - * @param values A List of documents (POJO or String for Json) + * @param values A List of documents (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) * @param options Additional options, can be null * @return information about the documents * @see API @@ -140,7 +140,7 @@ CompletableFuture importDocuments( * Reads a single document * * @param key The key of the document - * @param type The type of the document (POJO class or String for Json) + * @param type The type of the document (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) * @return the document identified by the key * @see API * Documentation @@ -151,7 +151,7 @@ CompletableFuture importDocuments( * Reads a single document * * @param key The key of the document - * @param type The type of the document (POJO class or String for Json) + * @param type The type of the document (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) * @param options Additional options, can be null * @return the document identified by the key * @see API @@ -164,7 +164,7 @@ CompletableFuture getDocument(final String key, final Class type, fina * Reads multiple documents * * @param keys The keys of the documents - * @param type The type of the documents (POJO class or String for Json) + * @param type The type of the documents (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) * @return the documents and possible errors */ CompletableFuture> getDocuments(final Collection keys, final Class type); @@ -173,7 +173,7 @@ CompletableFuture getDocument(final String key, final Class type, fina * Reads multiple documents * * @param keys The keys of the documents - * @param type The type of the documents (POJO class or String for Json) + * @param type The type of the documents (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) * @param options Additional options, can be null * @return the documents and possible errors */ @@ -187,7 +187,7 @@ CompletableFuture> getDocuments( * violated * * @param key The key of the document - * @param value A representation of a single document (POJO or String for Json) + * @param value A representation of a single document (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) * @return information about the document * @see API * Documentation @@ -199,7 +199,7 @@ CompletableFuture> getDocuments( * violated * * @param key The key of the document - * @param value A representation of a single document (POJO or String for Json) + * @param value A representation of a single document (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) * @param options Additional options, can be null * @return information about the document * @see API @@ -214,7 +214,7 @@ CompletableFuture> replaceDocument( * Replaces multiple documents in the specified collection with the ones in the values, the replaced documents are * specified by the _key attributes in the documents in values. * - * @param values A List of documents (POJO or String for Json) + * @param values A List of documents (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) * @return information about the documents * @see API * Documentation @@ -225,7 +225,7 @@ CompletableFuture> replaceDocument( * Replaces multiple documents in the specified collection with the ones in the values, the replaced documents are * specified by the _key attributes in the documents in values. * - * @param values A List of documents (POJO or String for Json) + * @param values A List of documents (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) * @param options Additional options, can be null * @return information about the documents * @see API @@ -241,7 +241,7 @@ CompletableFuture>> replaceDocum * they do not yet exist, and overwritten in the existing document if they do exist there. * * @param key The key of the document - * @param value A representation of a single document (POJO or String for Json) + * @param value A representation of a single document (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) * @return information about the document * @see API * Documentation @@ -254,7 +254,7 @@ CompletableFuture>> replaceDocum * they do not yet exist, and overwritten in the existing document if they do exist there. * * @param key The key of the document - * @param value A representation of a single document (POJO or String for Json) + * @param value A representation of a single document (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) * @param options Additional options, can be null * @return information about the document * @see API @@ -271,7 +271,7 @@ CompletableFuture> updateDocument( * they do not yet exist, and overwritten in the existing document if they do exist there. * * @param key The key of the document - * @param value A representation of a single document (POJO or String for Json) + * @param value A representation of a single document (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) * @param options Additional options, can be null * @param returnType Type of the returned newDocument and/or oldDocument * @return information about the document @@ -290,7 +290,7 @@ CompletableFuture> updateDocument( * attributes from the patch documents will be added to the existing documents if they do not yet exist, and * overwritten in the existing documents if they do exist there. * - * @param values A list of documents (POJO or String for Json) + * @param values A list of documents (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) * @return information about the documents * @see API * Documentation @@ -303,7 +303,7 @@ CompletableFuture> updateDocument( * attributes from the patch documents will be added to the existing documents if they do not yet exist, and * overwritten in the existing documents if they do exist there. * - * @param values A list of documents (POJO or String for Json) + * @param values A list of documents (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) * @param options Additional options, can be null * @return information about the documents * @see API @@ -319,7 +319,7 @@ CompletableFuture>> updateDocume * attributes from the patch documents will be added to the existing documents if they do not yet exist, and * overwritten in the existing documents if they do exist there. * - * @param values A list of documents (POJO or String for Json) + * @param values A list of documents (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) * @param options Additional options, can be null * @param returnType Type of the returned newDocument and/or oldDocument * @return information about the documents @@ -345,7 +345,7 @@ CompletableFuture>> updateDoc * Removes a document * * @param key The key of the document - * @param type The type of the document (POJO class or String for Json). Only necessary if + * @param type The type of the document (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}). Only necessary if * options.returnOld is set to true, otherwise can be null. * @param options Additional options, can be null * @return information about the document @@ -372,7 +372,7 @@ CompletableFuture> deleteDocument( * Removes multiple document * * @param values The keys of the documents or the documents themselves - * @param type The type of the documents (POJO class or String for Json). Only necessary if + * @param type The type of the documents (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}). Only necessary if * options.returnOld is set to true, otherwise can be null. * @param options Additional options, can be null * @return information about the documents diff --git a/src/main/java/com/arangodb/async/ArangoDatabaseAsync.java b/src/main/java/com/arangodb/async/ArangoDatabaseAsync.java index 4531c7cba..4f525c838 100644 --- a/src/main/java/com/arangodb/async/ArangoDatabaseAsync.java +++ b/src/main/java/com/arangodb/async/ArangoDatabaseAsync.java @@ -249,7 +249,7 @@ public interface ArangoDatabaseAsync extends ArangoSerdeAccessor { * @param query contains the query string to be executed * @param bindVars key/value pairs representing the bind parameters * @param options Additional options, can be null - * @param type The type of the result (POJO class, String for Json, or Collection/List/Map) + * @param type The type of the result (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) * @return cursor of the results * @see API * Documentation @@ -266,7 +266,7 @@ CompletableFuture> query( * * @param query contains the query string to be executed * @param options Additional options, can be null - * @param type The type of the result (POJO class, String for Json, or Collection/List/Map) + * @param type The type of the result (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) * @return cursor of the results * @see API * Documentation @@ -282,7 +282,7 @@ CompletableFuture> query( * * @param query contains the query string to be executed * @param bindVars key/value pairs representing the bind parameters - * @param type The type of the result (POJO class, String for Json, or Collection/List/Map) + * @param type The type of the result (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) * @return cursor of the results * @see API * Documentation @@ -297,7 +297,7 @@ CompletableFuture> query( * result list. * * @param query contains the query string to be executed - * @param type The type of the result (POJO class, String for Json, or Collection/List/Map) + * @param type The type of the result (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) * @return cursor of the results * @see API * Documentation @@ -308,7 +308,7 @@ CompletableFuture> query( * Return an cursor from the given cursor-ID if still existing * * @param cursorId The ID of the cursor - * @param type The type of the result (POJO class, String for Json, or Collection/List/Map) + * @param type The type of the result (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) * @return cursor of the results * @see API @@ -523,7 +523,7 @@ CompletableFuture createGraph( * Execute a server-side transaction * * @param action the actual transaction operations to be executed, in the form of stringified JavaScript code - * @param type The type of the result (POJO class or String for Json) + * @param type The type of the result (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) * @param options Additional options, can be null * @return the result of the transaction if it succeeded * @see API @@ -595,7 +595,7 @@ CompletableFuture createGraph( * Reads a single document * * @param id The id of the document - * @param type The type of the document (POJO class or String for Json) + * @param type The type of the document (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) * @return the document identified by the id * @see API * Documentation @@ -606,7 +606,7 @@ CompletableFuture createGraph( * Reads a single document * * @param id The id of the document - * @param type The type of the document (POJO class or String for Json) + * @param type The type of the document (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) * @param options Additional options, can be null * @return the document identified by the id * @see API diff --git a/src/main/java/com/arangodb/async/ArangoEdgeCollectionAsync.java b/src/main/java/com/arangodb/async/ArangoEdgeCollectionAsync.java index cff6747f0..39a8a3a0d 100644 --- a/src/main/java/com/arangodb/async/ArangoEdgeCollectionAsync.java +++ b/src/main/java/com/arangodb/async/ArangoEdgeCollectionAsync.java @@ -53,7 +53,7 @@ public interface ArangoEdgeCollectionAsync extends ArangoSerdeAccessor { /** * Creates a new edge in the collection * - * @param value A representation of a single edge (POJO or String for Json) + * @param value A representation of a single edge (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) * @return information about the edge * @see API Documentation */ @@ -62,7 +62,7 @@ public interface ArangoEdgeCollectionAsync extends ArangoSerdeAccessor { /** * Creates a new edge in the collection * - * @param value A representation of a single edge (POJO or String for Json) + * @param value A representation of a single edge (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) * @param options Additional options, can be null * @return information about the edge * @see API Documentation @@ -73,7 +73,7 @@ public interface ArangoEdgeCollectionAsync extends ArangoSerdeAccessor { * Fetches an existing edge * * @param key The key of the edge - * @param type The type of the edge-document (POJO class or String for Json) + * @param type The type of the edge-document (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) * @return the edge identified by the key * @see API Documentation */ @@ -83,7 +83,7 @@ public interface ArangoEdgeCollectionAsync extends ArangoSerdeAccessor { * Fetches an existing edge * * @param key The key of the edge - * @param type The type of the edge-document (POJO class or String for Json) + * @param type The type of the edge-document (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) * @param options Additional options, can be null * @return the edge identified by the key * @see API Documentation diff --git a/src/main/java/com/arangodb/async/ArangoVertexCollectionAsync.java b/src/main/java/com/arangodb/async/ArangoVertexCollectionAsync.java index e9ad701de..38eb462cd 100644 --- a/src/main/java/com/arangodb/async/ArangoVertexCollectionAsync.java +++ b/src/main/java/com/arangodb/async/ArangoVertexCollectionAsync.java @@ -63,7 +63,7 @@ public interface ArangoVertexCollectionAsync extends ArangoSerdeAccessor { /** * Creates a new vertex in the collection * - * @param value A representation of a single vertex (POJO or String for Json) + * @param value A representation of a single vertex (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) * @return information about the vertex * @see API Documentation */ @@ -72,7 +72,7 @@ public interface ArangoVertexCollectionAsync extends ArangoSerdeAccessor { /** * Creates a new vertex in the collection * - * @param value A representation of a single vertex (POJO or String for Json) + * @param value A representation of a single vertex (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) * @param options Additional options, can be null * @return information about the vertex * @see API Documentation @@ -83,7 +83,7 @@ public interface ArangoVertexCollectionAsync extends ArangoSerdeAccessor { * Fetches an existing vertex * * @param key The key of the vertex - * @param type The type of the vertex-document (POJO class or String for Json) + * @param type The type of the vertex-document (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) * @return the vertex identified by the key * @see API Documentation */ @@ -93,7 +93,7 @@ public interface ArangoVertexCollectionAsync extends ArangoSerdeAccessor { * Fetches an existing vertex * * @param key The key of the vertex - * @param type The type of the vertex-document (POJO class or String for Json) + * @param type The type of the vertex-document (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) * @param options Additional options, can be null * @return the vertex identified by the key * @see API Documentation diff --git a/src/main/java/com/arangodb/internal/InternalArangoCollection.java b/src/main/java/com/arangodb/internal/InternalArangoCollection.java index 5655cbafa..2016b4373 100644 --- a/src/main/java/com/arangodb/internal/InternalArangoCollection.java +++ b/src/main/java/com/arangodb/internal/InternalArangoCollection.java @@ -88,15 +88,7 @@ protected Request insertDocumentRequest(final T value, final DocumentCreateO request.putQueryParam(OVERWRITE_MODE, params.getOverwriteMode() != null ? params.getOverwriteMode().getValue() : null); request.putQueryParam(MERGE_OBJECTS, params.getMergeObjects()); request.putHeaderParam(TRANSACTION_ID, params.getStreamTransactionId()); - - byte[] body; - if (value instanceof String) { - body = getSerde().serialize(SerdeUtils.INSTANCE.parseJson((String) value)); - } else { - body = getSerde().serializeUserData(value); - } - request.setBody(body); - + request.setBody(getSerde().serializeUserData(value)); return request; } @@ -108,19 +100,11 @@ protected ResponseDeserializer> insertDocumentRespon final JsonNode newDoc = body.get(NEW); Class clazz = (Class) value.getClass(); if (newDoc != null) { - if (String.class.equals(clazz)) { - doc.setNew((T) SerdeUtils.INSTANCE.writeJson(newDoc)); - } else { - doc.setNew(getSerde().deserializeUserData(getSerde().serialize(newDoc), clazz)); - } + doc.setNew(getSerde().deserializeUserData(newDoc, clazz)); } final JsonNode oldDoc = body.get(OLD); if (oldDoc != null) { - if (String.class.equals(clazz)) { - doc.setOld((T) SerdeUtils.INSTANCE.writeJson(oldDoc)); - } else { - doc.setOld(getSerde().deserializeUserData(getSerde().serialize(oldDoc), clazz)); - } + doc.setOld(getSerde().deserializeUserData(oldDoc, clazz)); } if (options == null || Boolean.TRUE != options.getSilent()) { final Map values = new HashMap<>(); @@ -225,13 +209,7 @@ protected Request getDocumentRequest(final String key, final DocumentReadOptions } protected ResponseDeserializer getDocumentResponseDeserializer(final Class type) { - return response -> { - if (String.class.equals(type)) { - return (T) SerdeUtils.INSTANCE.writeJson(getSerde().parse(response.getBody())); - } else { - return getSerde().deserializeUserData(response.getBody(), type); - } - }; + return response -> getSerde().deserializeUserData(response.getBody(), type); } protected Request getDocumentsRequest(final Collection keys, final DocumentReadOptions options) { diff --git a/src/main/java/com/arangodb/internal/InternalArangoDatabase.java b/src/main/java/com/arangodb/internal/InternalArangoDatabase.java index a94042aab..9a8761600 100644 --- a/src/main/java/com/arangodb/internal/InternalArangoDatabase.java +++ b/src/main/java/com/arangodb/internal/InternalArangoDatabase.java @@ -285,11 +285,7 @@ protected Request transactionRequest(final String action, final TransactionOptio protected ResponseDeserializer transactionResponseDeserializer(final Class type) { return response -> { byte[] userContent = getSerde().extract(response.getBody(), ArangoResponseField.RESULT_JSON_POINTER); - if (String.class.equals(type)) { - return (T) SerdeUtils.INSTANCE.writeJson(getSerde().parse(userContent)); - } else { - return getSerde().deserializeUserData(userContent, type); - } + return getSerde().deserializeUserData(userContent, type); }; } diff --git a/src/main/java/com/arangodb/internal/InternalArangoVertexCollection.java b/src/main/java/com/arangodb/internal/InternalArangoVertexCollection.java index 6cd10c0d7..d7c9ebb8d 100644 --- a/src/main/java/com/arangodb/internal/InternalArangoVertexCollection.java +++ b/src/main/java/com/arangodb/internal/InternalArangoVertexCollection.java @@ -70,14 +70,7 @@ protected Request insertVertexRequest(final T value, final VertexCreateOptio final VertexCreateOptions params = (options != null ? options : new VertexCreateOptions()); request.putHeaderParam(TRANSACTION_ID, params.getStreamTransactionId()); request.putQueryParam(ArangoRequestParam.WAIT_FOR_SYNC, params.getWaitForSync()); - - byte[] body; - if (value instanceof String) { - body = getSerde().serialize(SerdeUtils.INSTANCE.parseJson((String) value)); - } else { - body = getSerde().serializeUserData(value); - } - request.setBody(body); + request.setBody(getSerde().serializeUserData(value)); return request; } diff --git a/src/main/java/com/arangodb/serde/InternalSerde.java b/src/main/java/com/arangodb/serde/InternalSerde.java index fb7e0626b..be850da3f 100644 --- a/src/main/java/com/arangodb/serde/InternalSerde.java +++ b/src/main/java/com/arangodb/serde/InternalSerde.java @@ -133,6 +133,26 @@ default T deserializeUserData(byte[] content, Class clazz) { */ T deserializeUserData(byte[] content, Type type); + /** + * Deserializes the parsed json node and binds it to the target data type, using the user serde. + * + * @param node parsed json node + * @param clazz class of target data type + * @return deserialized object + */ + default T deserializeUserData(JsonNode node, Class clazz) { + return deserializeUserData(node, (Type) clazz); + } + + /** + * Deserializes the parsed json node and binds it to the target data type, using the user serde. + * + * @param node parsed json node + * @param type target data type + * @return deserialized object + */ + T deserializeUserData(JsonNode node, Type type); + /** * @return the user serde */ diff --git a/src/main/java/com/arangodb/serde/InternalSerdeImpl.java b/src/main/java/com/arangodb/serde/InternalSerdeImpl.java index b5b9f01d3..d321f3743 100644 --- a/src/main/java/com/arangodb/serde/InternalSerdeImpl.java +++ b/src/main/java/com/arangodb/serde/InternalSerdeImpl.java @@ -76,6 +76,11 @@ public T deserializeUserData(byte[] content, Type type) { } } + @Override + public T deserializeUserData(JsonNode node, Type type) { + return deserializeUserData(serialize(node), type); + } + @Override public ArangoSerde getUserSerde() { return userSerde; diff --git a/src/test/java/com/arangodb/ArangoCollectionTest.java b/src/test/java/com/arangodb/ArangoCollectionTest.java index 6cf12bb73..a23f182af 100644 --- a/src/test/java/com/arangodb/ArangoCollectionTest.java +++ b/src/test/java/com/arangodb/ArangoCollectionTest.java @@ -38,6 +38,8 @@ import com.arangodb.model.*; import com.arangodb.model.DocumentImportOptions.OnDuplicate; import com.arangodb.util.MapBuilder; +import com.arangodb.util.RawBytes; +import com.arangodb.util.RawJson; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonIncludeProperties; import com.fasterxml.jackson.core.JsonProcessingException; @@ -92,8 +94,7 @@ static void init() { @ParameterizedTest(name = "{index}") @MethodSource("cols") void insertDocument(ArangoCollection collection) { - final DocumentCreateEntity doc = collection - .insertDocument(new BaseDocument(), null); + final DocumentCreateEntity doc = collection.insertDocument(new BaseDocument(), null); assertThat(doc).isNotNull(); assertThat(doc.getId()).isNotNull(); assertThat(doc.getKey()).isNotNull(); @@ -112,8 +113,7 @@ void insertDocumentWithArrayWithNullValues(ArangoCollection collection) { BaseDocument doc = new BaseDocument(); doc.addAttribute("arr", arr); - final DocumentCreateEntity insertedDoc = collection - .insertDocument(doc, new DocumentCreateOptions().returnNew(true)); + final DocumentCreateEntity insertedDoc = collection.insertDocument(doc, new DocumentCreateOptions().returnNew(true)); assertThat(insertedDoc).isNotNull(); assertThat(insertedDoc.getId()).isNotNull(); assertThat(insertedDoc.getKey()).isNotNull(); @@ -131,8 +131,7 @@ void insertDocumentWithNullValues(ArangoCollection collection) { BaseDocument doc = new BaseDocument(); doc.addAttribute("null", null); - final DocumentCreateEntity insertedDoc = collection - .insertDocument(doc, new DocumentCreateOptions().returnNew(true)); + final DocumentCreateEntity insertedDoc = collection.insertDocument(doc, new DocumentCreateOptions().returnNew(true)); assertThat(insertedDoc).isNotNull(); assertThat(insertedDoc.getId()).isNotNull(); assertThat(insertedDoc.getKey()).isNotNull(); @@ -145,8 +144,7 @@ void insertDocumentWithNullValues(ArangoCollection collection) { @MethodSource("cols") void insertDocumentUpdateRev(ArangoCollection collection) { final BaseDocument doc = new BaseDocument(); - final DocumentCreateEntity createResult = collection - .insertDocument(doc, null); + final DocumentCreateEntity createResult = collection.insertDocument(doc, null); assertThat(doc.getRevision()).isEqualTo(createResult.getRev()); } @@ -154,8 +152,7 @@ void insertDocumentUpdateRev(ArangoCollection collection) { @MethodSource("cols") void insertDocumentReturnNew(ArangoCollection collection) { final DocumentCreateOptions options = new DocumentCreateOptions().returnNew(true); - final DocumentCreateEntity doc = collection - .insertDocument(new BaseDocument(), options); + final DocumentCreateEntity doc = collection.insertDocument(new BaseDocument(), options); assertThat(doc).isNotNull(); assertThat(doc.getId()).isNotNull(); assertThat(doc.getKey()).isNotNull(); @@ -175,8 +172,7 @@ void insertDocumentOverwriteModeIgnore(ArangoCollection collection) { final BaseDocument doc2 = new BaseDocument(key); doc2.addAttribute("bar", "b"); - final DocumentCreateEntity insertIgnore = collection - .insertDocument(doc2, new DocumentCreateOptions().overwriteMode(OverwriteMode.ignore)); + final DocumentCreateEntity insertIgnore = collection.insertDocument(doc2, new DocumentCreateOptions().overwriteMode(OverwriteMode.ignore)); assertThat(insertIgnore).isNotNull(); assertThat(insertIgnore.getRev()).isEqualTo(meta.getRev()); @@ -193,8 +189,7 @@ void insertDocumentOverwriteModeConflict(ArangoCollection collection) { collection.insertDocument(doc); final BaseDocument doc2 = new BaseDocument(key); - Throwable thrown = catchThrowable(() -> - collection.insertDocument(doc2, new DocumentCreateOptions().overwriteMode(OverwriteMode.conflict))); + Throwable thrown = catchThrowable(() -> collection.insertDocument(doc2, new DocumentCreateOptions().overwriteMode(OverwriteMode.conflict))); assertThat(thrown).isInstanceOf(ArangoDBException.class); ArangoDBException e = (ArangoDBException) thrown; assertThat(e.getResponseCode()).isEqualTo(409); @@ -213,8 +208,7 @@ void insertDocumentOverwriteModeReplace(ArangoCollection collection) { final BaseDocument doc2 = new BaseDocument(key); doc2.addAttribute("bar", "b"); - final DocumentCreateEntity repsert = collection - .insertDocument(doc2, new DocumentCreateOptions().overwriteMode(OverwriteMode.replace).returnNew(true)); + final DocumentCreateEntity repsert = collection.insertDocument(doc2, new DocumentCreateOptions().overwriteMode(OverwriteMode.replace).returnNew(true)); assertThat(repsert).isNotNull(); assertThat(repsert.getRev()).isNotEqualTo(meta.getRev()); @@ -232,8 +226,7 @@ void insertDocumentOverwriteModeUpdate(ArangoCollection collection) { final DocumentCreateEntity meta = collection.insertDocument(doc); doc.addAttribute("bar", "b"); - final DocumentCreateEntity updated = collection - .insertDocument(doc, new DocumentCreateOptions().overwriteMode(OverwriteMode.update).returnNew(true)); + final DocumentCreateEntity updated = collection.insertDocument(doc, new DocumentCreateOptions().overwriteMode(OverwriteMode.update).returnNew(true)); assertThat(updated).isNotNull(); assertThat(updated.getRev()).isNotEqualTo(meta.getRev()); @@ -253,11 +246,7 @@ void insertDocumentOverwriteModeUpdateMergeObjectsFalse(ArangoCollection collect Map fieldB = Collections.singletonMap("b", "b"); doc.addAttribute("foo", fieldB); - final DocumentCreateEntity updated = collection - .insertDocument(doc, new DocumentCreateOptions() - .overwriteMode(OverwriteMode.update) - .mergeObjects(false) - .returnNew(true)); + final DocumentCreateEntity updated = collection.insertDocument(doc, new DocumentCreateOptions().overwriteMode(OverwriteMode.update).mergeObjects(false).returnNew(true)); assertThat(updated).isNotNull(); assertThat(updated.getRev()).isNotEqualTo(meta.getRev()); @@ -268,8 +257,7 @@ void insertDocumentOverwriteModeUpdateMergeObjectsFalse(ArangoCollection collect @MethodSource("cols") void insertDocumentWaitForSync(ArangoCollection collection) { final DocumentCreateOptions options = new DocumentCreateOptions().waitForSync(true); - final DocumentCreateEntity doc = collection - .insertDocument(new BaseDocument(), options); + final DocumentCreateEntity doc = collection.insertDocument(new BaseDocument(), options); assertThat(doc).isNotNull(); assertThat(doc.getId()).isNotNull(); assertThat(doc.getKey()).isNotNull(); @@ -281,20 +269,38 @@ void insertDocumentWaitForSync(ArangoCollection collection) { @MethodSource("cols") void insertDocumentAsJson(ArangoCollection collection) { String key = "doc-" + UUID.randomUUID(); - final DocumentCreateEntity doc = collection - .insertDocument("{\"_key\":\"" + key + "\",\"a\":\"test\"}", null); + RawJson rawJson = RawJson.of("{\"_key\":\"" + key + "\",\"a\":\"test\"}"); + final DocumentCreateEntity doc = collection.insertDocument(rawJson); assertThat(doc).isNotNull(); assertThat(doc.getId()).isEqualTo(collection.name() + "/" + key); assertThat(doc.getKey()).isEqualTo(key); assertThat(doc.getRev()).isNotNull(); } + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void insertDocumentAsBytes(ArangoCollection collection) { + String key = "doc-" + UUID.randomUUID(); + Map doc = new HashMap<>(); + doc.put("_key", key); + doc.put("a", "test"); + byte[] bytes = collection.getSerde().serializeUserData(doc); + RawBytes rawJson = RawBytes.of(bytes); + final DocumentCreateEntity createEntity = collection.insertDocument(rawJson, new DocumentCreateOptions().returnNew(true)); + assertThat(createEntity).isNotNull(); + assertThat(createEntity.getId()).isEqualTo(collection.name() + "/" + key); + assertThat(createEntity.getKey()).isEqualTo(key); + assertThat(createEntity.getRev()).isNotNull(); + assertThat(createEntity.getNew()).isNotNull().isInstanceOf(RawBytes.class); + Map newDoc = collection.getSerde().deserializeUserData(createEntity.getNew().getValue(), Map.class); + assertThat(newDoc).containsAllEntriesOf(doc); + } + @ParameterizedTest(name = "{index}") @MethodSource("cols") void insertDocumentSilent(ArangoCollection collection) { assumeTrue(isSingleServer()); - final DocumentCreateEntity meta = collection - .insertDocument(new BaseDocument(), new DocumentCreateOptions().silent(true)); + final DocumentCreateEntity meta = collection.insertDocument(new BaseDocument(), new DocumentCreateOptions().silent(true)); assertThat(meta).isNotNull(); assertThat(meta.getId()).isNull(); assertThat(meta.getKey()).isNull(); @@ -308,8 +314,7 @@ void insertDocumentSilentDontTouchInstance(ArangoCollection collection) { final BaseDocument doc = new BaseDocument(); final String key = "testkey-" + UUID.randomUUID(); doc.setKey(key); - final DocumentCreateEntity meta = collection - .insertDocument(doc, new DocumentCreateOptions().silent(true)); + final DocumentCreateEntity meta = collection.insertDocument(doc, new DocumentCreateOptions().silent(true)); assertThat(meta).isNotNull(); assertThat(meta.getKey()).isNull(); assertThat(doc.getKey()).isEqualTo(key); @@ -319,9 +324,7 @@ void insertDocumentSilentDontTouchInstance(ArangoCollection collection) { @MethodSource("cols") void insertDocumentsSilent(ArangoCollection collection) { assumeTrue(isSingleServer()); - final MultiDocumentEntity> info = collection - .insertDocuments(Arrays.asList(new BaseDocument(), new BaseDocument()), - new DocumentCreateOptions().silent(true)); + final MultiDocumentEntity> info = collection.insertDocuments(Arrays.asList(new BaseDocument(), new BaseDocument()), new DocumentCreateOptions().silent(true)); assertThat(info).isNotNull(); assertThat(info.getDocuments()).isEmpty(); assertThat(info.getDocumentsAndErrors()).isEmpty(); @@ -331,11 +334,9 @@ void insertDocumentsSilent(ArangoCollection collection) { @ParameterizedTest(name = "{index}") @MethodSource("cols") void getDocument(ArangoCollection collection) { - final DocumentCreateEntity createResult = collection - .insertDocument(new BaseDocument(), null); + final DocumentCreateEntity createResult = collection.insertDocument(new BaseDocument(), null); assertThat(createResult.getKey()).isNotNull(); - final BaseDocument readResult = collection - .getDocument(createResult.getKey(), BaseDocument.class, null); + final BaseDocument readResult = collection.getDocument(createResult.getKey(), BaseDocument.class, null); assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); assertThat(readResult.getId()).isEqualTo(COLLECTION_NAME + "/" + createResult.getKey()); } @@ -343,12 +344,10 @@ void getDocument(ArangoCollection collection) { @ParameterizedTest(name = "{index}") @MethodSource("cols") void getDocumentIfMatch(ArangoCollection collection) { - final DocumentCreateEntity createResult = collection - .insertDocument(new BaseDocument(), null); + final DocumentCreateEntity createResult = collection.insertDocument(new BaseDocument(), null); assertThat(createResult.getKey()).isNotNull(); final DocumentReadOptions options = new DocumentReadOptions().ifMatch(createResult.getRev()); - final BaseDocument readResult = collection - .getDocument(createResult.getKey(), BaseDocument.class, options); + final BaseDocument readResult = collection.getDocument(createResult.getKey(), BaseDocument.class, options); assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); assertThat(readResult.getId()).isEqualTo(COLLECTION_NAME + "/" + createResult.getKey()); } @@ -356,24 +355,20 @@ void getDocumentIfMatch(ArangoCollection collection) { @ParameterizedTest(name = "{index}") @MethodSource("cols") void getDocumentIfMatchFail(ArangoCollection collection) { - final DocumentCreateEntity createResult = collection - .insertDocument(new BaseDocument(), null); + final DocumentCreateEntity createResult = collection.insertDocument(new BaseDocument(), null); assertThat(createResult.getKey()).isNotNull(); final DocumentReadOptions options = new DocumentReadOptions().ifMatch("no"); - final BaseDocument document = collection - .getDocument(createResult.getKey(), BaseDocument.class, options); + final BaseDocument document = collection.getDocument(createResult.getKey(), BaseDocument.class, options); assertThat(document).isNull(); } @ParameterizedTest(name = "{index}") @MethodSource("cols") void getDocumentIfNoneMatch(ArangoCollection collection) { - final DocumentCreateEntity createResult = collection - .insertDocument(new BaseDocument(), null); + final DocumentCreateEntity createResult = collection.insertDocument(new BaseDocument(), null); assertThat(createResult.getKey()).isNotNull(); final DocumentReadOptions options = new DocumentReadOptions().ifNoneMatch("no"); - final BaseDocument readResult = collection - .getDocument(createResult.getKey(), BaseDocument.class, options); + final BaseDocument readResult = collection.getDocument(createResult.getKey(), BaseDocument.class, options); assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); assertThat(readResult.getId()).isEqualTo(COLLECTION_NAME + "/" + createResult.getKey()); } @@ -381,12 +376,10 @@ void getDocumentIfNoneMatch(ArangoCollection collection) { @ParameterizedTest(name = "{index}") @MethodSource("cols") void getDocumentIfNoneMatchFail(ArangoCollection collection) { - final DocumentCreateEntity createResult = collection - .insertDocument(new BaseDocument(), null); + final DocumentCreateEntity createResult = collection.insertDocument(new BaseDocument(), null); assertThat(createResult.getKey()).isNotNull(); final DocumentReadOptions options = new DocumentReadOptions().ifNoneMatch(createResult.getRev()); - final BaseDocument document = collection - .getDocument(createResult.getKey(), BaseDocument.class, options); + final BaseDocument document = collection.getDocument(createResult.getKey(), BaseDocument.class, options); assertThat(document).isNull(); } @@ -394,11 +387,10 @@ void getDocumentIfNoneMatchFail(ArangoCollection collection) { @MethodSource("cols") void getDocumentAsJson(ArangoCollection collection) { String key = rnd(); - collection.insertDocument("{\"_key\":\"" + key + "\",\"a\":\"test\"}", null); - final String readResult = collection.getDocument(key, String.class, null); - assertThat(readResult) - .contains("\"_key\":\"" + key + "\"") - .contains("\"_id\":\"" + COLLECTION_NAME + "/" + key + "\""); + RawJson rawJson = RawJson.of("{\"_key\":\"" + key + "\",\"a\":\"test\"}"); + collection.insertDocument(rawJson); + final RawJson readResult = collection.getDocument(key, RawJson.class); + assertThat(readResult.getValue()).contains("\"_key\":\"" + key + "\"").contains("\"_id\":\"" + COLLECTION_NAME + "/" + key + "\""); } @ParameterizedTest(name = "{index}") @@ -411,8 +403,7 @@ void getDocumentNotFound(ArangoCollection collection) { @ParameterizedTest(name = "{index}") @MethodSource("cols") void getDocumentNotFoundOptionsDefault(ArangoCollection collection) { - final BaseDocument document = collection - .getDocument("no", BaseDocument.class, new DocumentReadOptions()); + final BaseDocument document = collection.getDocument("no", BaseDocument.class, new DocumentReadOptions()); assertThat(document).isNull(); } @@ -426,8 +417,7 @@ void getDocumentNotFoundOptionsNull(ArangoCollection collection) { @ParameterizedTest(name = "{index}") @MethodSource("cols") void getDocumentNotFoundThrowException(ArangoCollection collection) { - Throwable thrown = catchThrowable(() -> - collection.getDocument("no", BaseDocument.class, new DocumentReadOptions().catchException(false))); + Throwable thrown = catchThrowable(() -> collection.getDocument("no", BaseDocument.class, new DocumentReadOptions().catchException(false))); assertThat(thrown).isInstanceOf(ArangoDBException.class); } @@ -444,8 +434,7 @@ void getDocumentDirtyRead(ArangoCollection collection) throws InterruptedExcepti final BaseDocument doc = new BaseDocument(); collection.insertDocument(doc, new DocumentCreateOptions()); Thread.sleep(2000); - final String document = collection - .getDocument(doc.getKey(), String.class, new DocumentReadOptions().allowDirtyRead(true)); + final RawJson document = collection.getDocument(doc.getKey(), RawJson.class, new DocumentReadOptions().allowDirtyRead(true)); assertThat(document).isNotNull(); } @@ -457,8 +446,7 @@ void getDocuments(ArangoCollection collection) { values.add(new BaseDocument("2")); values.add(new BaseDocument("3")); collection.insertDocuments(values); - final MultiDocumentEntity documents = collection - .getDocuments(Arrays.asList("1", "2", "3"), BaseDocument.class); + final MultiDocumentEntity documents = collection.getDocuments(Arrays.asList("1", "2", "3"), BaseDocument.class); assertThat(documents).isNotNull(); assertThat(documents.getDocuments()).hasSize(3); for (final BaseDocument document : documents.getDocuments()) { @@ -470,24 +458,16 @@ void getDocuments(ArangoCollection collection) { @MethodSource("cols") void getDocumentsWithCustomShardingKey(ArangoCollection c) { ArangoCollection collection = c.db().collection("customShardingKeyCollection"); - if (collection.exists()) - collection.drop(); + if (collection.exists()) collection.drop(); - collection.create(new CollectionCreateOptions() - .shardKeys("customField") - .numberOfShards(10) - ); + collection.create(new CollectionCreateOptions().shardKeys("customField").numberOfShards(10)); - List values = IntStream.range(0, 10) - .mapToObj(String::valueOf).map(key -> new BaseDocument()) - .peek(it -> it.addAttribute("customField", rnd())) - .collect(Collectors.toList()); + List values = IntStream.range(0, 10).mapToObj(String::valueOf).map(key -> new BaseDocument()).peek(it -> it.addAttribute("customField", rnd())).collect(Collectors.toList()); MultiDocumentEntity> inserted = collection.insertDocuments(values); List insertedKeys = inserted.getDocuments().stream().map(DocumentEntity::getKey).collect(Collectors.toList()); - final Collection documents = collection - .getDocuments(insertedKeys, BaseDocument.class).getDocuments(); + final Collection documents = collection.getDocuments(insertedKeys, BaseDocument.class).getDocuments(); assertThat(documents).hasSize(10); } @@ -500,9 +480,7 @@ void getDocumentsDirtyRead(ArangoCollection collection) { values.add(new BaseDocument("2")); values.add(new BaseDocument("3")); collection.insertDocuments(values); - final MultiDocumentEntity documents = collection - .getDocuments(Arrays.asList("1", "2", "3"), BaseDocument.class, - new DocumentReadOptions().allowDirtyRead(true)); + final MultiDocumentEntity documents = collection.getDocuments(Arrays.asList("1", "2", "3"), BaseDocument.class, new DocumentReadOptions().allowDirtyRead(true)); assertThat(documents).isNotNull(); assertThat(documents.getDocuments()).hasSize(3); for (final BaseDocument document : documents.getDocuments()) { @@ -513,8 +491,7 @@ void getDocumentsDirtyRead(ArangoCollection collection) { @ParameterizedTest(name = "{index}") @MethodSource("cols") void getDocumentsNotFound(ArangoCollection collection) { - final MultiDocumentEntity readResult = collection - .getDocuments(Collections.singleton("no"), BaseDocument.class); + final MultiDocumentEntity readResult = collection.getDocuments(Collections.singleton("no"), BaseDocument.class); assertThat(readResult).isNotNull(); assertThat(readResult.getDocuments()).isEmpty(); assertThat(readResult.getErrors()).hasSize(1); @@ -523,8 +500,7 @@ void getDocumentsNotFound(ArangoCollection collection) { @ParameterizedTest(name = "{index}") @MethodSource("cols") void getDocumentsWrongKey(ArangoCollection collection) { - final MultiDocumentEntity readResult = collection - .getDocuments(Collections.singleton("no/no"), BaseDocument.class); + final MultiDocumentEntity readResult = collection.getDocuments(Collections.singleton("no/no"), BaseDocument.class); assertThat(readResult).isNotNull(); assertThat(readResult.getDocuments()).isEmpty(); assertThat(readResult.getErrors()).hasSize(1); @@ -536,13 +512,11 @@ void updateDocument(ArangoCollection collection) { final BaseDocument doc = new BaseDocument(); doc.addAttribute("a", "test"); doc.addAttribute("c", "test"); - final DocumentCreateEntity createResult = collection - .insertDocument(doc, null); + final DocumentCreateEntity createResult = collection.insertDocument(doc, null); doc.updateAttribute("a", "test1"); doc.addAttribute("b", "test"); doc.updateAttribute("c", null); - final DocumentUpdateEntity updateResult = collection - .updateDocument(createResult.getKey(), doc, null); + final DocumentUpdateEntity updateResult = collection.updateDocument(createResult.getKey(), doc, null); assertThat(updateResult).isNotNull(); assertThat(updateResult.getId()).isEqualTo(createResult.getId()); assertThat(updateResult.getNew()).isNull(); @@ -550,8 +524,7 @@ void updateDocument(ArangoCollection collection) { assertThat(updateResult.getRev()).isNotEqualTo(updateResult.getOldRev()); assertThat(updateResult.getOldRev()).isEqualTo(createResult.getRev()); - final BaseDocument readResult = collection - .getDocument(createResult.getKey(), BaseDocument.class, null); + final BaseDocument readResult = collection.getDocument(createResult.getKey(), BaseDocument.class, null); assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); assertThat(readResult.getAttribute("a")).isNotNull(); assertThat(String.valueOf(readResult.getAttribute("a"))).isEqualTo("test1"); @@ -569,8 +542,7 @@ void updateDocumentWithDifferentReturnType(ArangoCollection collection) { doc.addAttribute("a", "test"); collection.insertDocument(doc); - final DocumentUpdateEntity updateResult = collection - .updateDocument(key, Collections.singletonMap("b", "test"), new DocumentUpdateOptions().returnNew(true), BaseDocument.class); + final DocumentUpdateEntity updateResult = collection.updateDocument(key, Collections.singletonMap("b", "test"), new DocumentUpdateOptions().returnNew(true), BaseDocument.class); assertThat(updateResult).isNotNull(); assertThat(updateResult.getKey()).isEqualTo(key); BaseDocument updated = updateResult.getNew(); @@ -583,11 +555,9 @@ void updateDocumentWithDifferentReturnType(ArangoCollection collection) { @MethodSource("cols") void updateDocumentUpdateRev(ArangoCollection collection) { final BaseDocument doc = new BaseDocument(); - final DocumentCreateEntity createResult = collection - .insertDocument(doc, null); + final DocumentCreateEntity createResult = collection.insertDocument(doc, null); assertThat(doc.getRevision()).isEqualTo(createResult.getRev()); - final DocumentUpdateEntity updateResult = collection - .updateDocument(createResult.getKey(), doc, null); + final DocumentUpdateEntity updateResult = collection.updateDocument(createResult.getKey(), doc, null); assertThat(doc.getRevision()).isEqualTo(updateResult.getRev()); } @@ -597,21 +567,18 @@ void updateDocumentIfMatch(ArangoCollection collection) { final BaseDocument doc = new BaseDocument(); doc.addAttribute("a", "test"); doc.addAttribute("c", "test"); - final DocumentCreateEntity createResult = collection - .insertDocument(doc, null); + final DocumentCreateEntity createResult = collection.insertDocument(doc, null); doc.updateAttribute("a", "test1"); doc.addAttribute("b", "test"); doc.updateAttribute("c", null); final DocumentUpdateOptions options = new DocumentUpdateOptions().ifMatch(createResult.getRev()); - final DocumentUpdateEntity updateResult = collection - .updateDocument(createResult.getKey(), doc, options); + final DocumentUpdateEntity updateResult = collection.updateDocument(createResult.getKey(), doc, options); assertThat(updateResult).isNotNull(); assertThat(updateResult.getId()).isEqualTo(createResult.getId()); assertThat(updateResult.getRev()).isNotEqualTo(updateResult.getOldRev()); assertThat(updateResult.getOldRev()).isEqualTo(createResult.getRev()); - final BaseDocument readResult = collection - .getDocument(createResult.getKey(), BaseDocument.class, null); + final BaseDocument readResult = collection.getDocument(createResult.getKey(), BaseDocument.class, null); assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); assertThat(readResult.getAttribute("a")).isNotNull(); assertThat(String.valueOf(readResult.getAttribute("a"))).isEqualTo("test1"); @@ -627,8 +594,7 @@ void updateDocumentIfMatchFail(ArangoCollection collection) { final BaseDocument doc = new BaseDocument(); doc.addAttribute("a", "test"); doc.addAttribute("c", "test"); - final DocumentCreateEntity createResult = collection - .insertDocument(doc, null); + final DocumentCreateEntity createResult = collection.insertDocument(doc, null); doc.updateAttribute("a", "test1"); doc.addAttribute("b", "test"); doc.updateAttribute("c", null); @@ -643,13 +609,11 @@ void updateDocumentIfMatchFail(ArangoCollection collection) { void updateDocumentReturnNew(ArangoCollection collection) { final BaseDocument doc = new BaseDocument(); doc.addAttribute("a", "test"); - final DocumentCreateEntity createResult = collection - .insertDocument(doc, null); + final DocumentCreateEntity createResult = collection.insertDocument(doc, null); doc.updateAttribute("a", "test1"); doc.addAttribute("b", "test"); final DocumentUpdateOptions options = new DocumentUpdateOptions().returnNew(true); - final DocumentUpdateEntity updateResult = collection - .updateDocument(createResult.getKey(), doc, options); + final DocumentUpdateEntity updateResult = collection.updateDocument(createResult.getKey(), doc, options); assertThat(updateResult).isNotNull(); assertThat(updateResult.getId()).isEqualTo(createResult.getId()); assertThat(updateResult.getOldRev()).isEqualTo(createResult.getRev()); @@ -667,13 +631,11 @@ void updateDocumentReturnNew(ArangoCollection collection) { void updateDocumentReturnOld(ArangoCollection collection) { final BaseDocument doc = new BaseDocument(); doc.addAttribute("a", "test"); - final DocumentCreateEntity createResult = collection - .insertDocument(doc, null); + final DocumentCreateEntity createResult = collection.insertDocument(doc, null); doc.updateAttribute("a", "test1"); doc.addAttribute("b", "test"); final DocumentUpdateOptions options = new DocumentUpdateOptions().returnOld(true); - final DocumentUpdateEntity updateResult = collection - .updateDocument(createResult.getKey(), doc, options); + final DocumentUpdateEntity updateResult = collection.updateDocument(createResult.getKey(), doc, options); assertThat(updateResult).isNotNull(); assertThat(updateResult.getId()).isEqualTo(createResult.getId()); assertThat(updateResult.getOldRev()).isEqualTo(createResult.getRev()); @@ -690,19 +652,16 @@ void updateDocumentReturnOld(ArangoCollection collection) { void updateDocumentKeepNullTrue(ArangoCollection collection) { final BaseDocument doc = new BaseDocument(); doc.addAttribute("a", "test"); - final DocumentCreateEntity createResult = collection - .insertDocument(doc, null); + final DocumentCreateEntity createResult = collection.insertDocument(doc, null); doc.updateAttribute("a", null); final DocumentUpdateOptions options = new DocumentUpdateOptions().keepNull(true); - final DocumentUpdateEntity updateResult = collection - .updateDocument(createResult.getKey(), doc, options); + final DocumentUpdateEntity updateResult = collection.updateDocument(createResult.getKey(), doc, options); assertThat(updateResult).isNotNull(); assertThat(updateResult.getId()).isEqualTo(createResult.getId()); assertThat(updateResult.getRev()).isNotEqualTo(updateResult.getOldRev()); assertThat(updateResult.getOldRev()).isEqualTo(createResult.getRev()); - final BaseDocument readResult = collection - .getDocument(createResult.getKey(), BaseDocument.class, null); + final BaseDocument readResult = collection.getDocument(createResult.getKey(), BaseDocument.class, null); assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); assertThat(readResult.getProperties()).containsKey("a"); } @@ -712,19 +671,16 @@ void updateDocumentKeepNullTrue(ArangoCollection collection) { void updateDocumentKeepNullFalse(ArangoCollection collection) { final BaseDocument doc = new BaseDocument(); doc.addAttribute("a", "test"); - final DocumentCreateEntity createResult = collection - .insertDocument(doc, null); + final DocumentCreateEntity createResult = collection.insertDocument(doc, null); doc.updateAttribute("a", null); final DocumentUpdateOptions options = new DocumentUpdateOptions().keepNull(false); - final DocumentUpdateEntity updateResult = collection - .updateDocument(createResult.getKey(), doc, options); + final DocumentUpdateEntity updateResult = collection.updateDocument(createResult.getKey(), doc, options); assertThat(updateResult).isNotNull(); assertThat(updateResult.getId()).isEqualTo(createResult.getId()); assertThat(updateResult.getRev()).isNotEqualTo(updateResult.getOldRev()); assertThat(updateResult.getOldRev()).isEqualTo(createResult.getRev()); - final BaseDocument readResult = collection - .getDocument(createResult.getKey(), BaseDocument.class, null); + final BaseDocument readResult = collection.getDocument(createResult.getKey(), BaseDocument.class, null); assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); assertThat(readResult.getId()).isEqualTo(createResult.getId()); assertThat(readResult.getRevision()).isNotNull(); @@ -768,13 +724,11 @@ void updateDocumentSerializeNullTrue(ArangoCollection collection) { final DocumentCreateEntity createResult = collection.insertDocument(doc); final TestUpdateEntity patchDoc = new TestUpdateEntity(); patchDoc.a = "bar"; - final DocumentUpdateEntity updateResult = collection - .updateDocument(createResult.getKey(), patchDoc); + final DocumentUpdateEntity updateResult = collection.updateDocument(createResult.getKey(), patchDoc); assertThat(updateResult).isNotNull(); assertThat(updateResult.getKey()).isEqualTo(createResult.getKey()); - final BaseDocument readResult = collection - .getDocument(createResult.getKey(), BaseDocument.class); + final BaseDocument readResult = collection.getDocument(createResult.getKey(), BaseDocument.class); assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); assertThat(readResult.getProperties()).containsKey("a"); assertThat(readResult.getAttribute("a")).isEqualTo("bar"); @@ -789,13 +743,11 @@ void updateDocumentSerializeNullFalse(ArangoCollection collection) { final DocumentCreateEntity createResult = collection.insertDocument(doc); final TestUpdateEntitySerializeNullFalse patchDoc = new TestUpdateEntitySerializeNullFalse(); patchDoc.a = "bar"; - final DocumentUpdateEntity updateResult = collection - .updateDocument(createResult.getKey(), patchDoc); + final DocumentUpdateEntity updateResult = collection.updateDocument(createResult.getKey(), patchDoc); assertThat(updateResult).isNotNull(); assertThat(updateResult.getKey()).isEqualTo(createResult.getKey()); - final BaseDocument readResult = collection - .getDocument(createResult.getKey(), BaseDocument.class); + final BaseDocument readResult = collection.getDocument(createResult.getKey(), BaseDocument.class); assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); assertThat(readResult.getProperties()).containsKeys("a", "b"); assertThat(readResult.getAttribute("a")).isEqualTo("bar"); @@ -810,21 +762,18 @@ void updateDocumentMergeObjectsTrue(ArangoCollection collection) { final Map a = new HashMap<>(); a.put("a", "test"); doc.addAttribute("a", a); - final DocumentCreateEntity createResult = collection - .insertDocument(doc, null); + final DocumentCreateEntity createResult = collection.insertDocument(doc, null); a.clear(); a.put("b", "test"); doc.updateAttribute("a", a); final DocumentUpdateOptions options = new DocumentUpdateOptions().mergeObjects(true); - final DocumentUpdateEntity updateResult = collection - .updateDocument(createResult.getKey(), doc, options); + final DocumentUpdateEntity updateResult = collection.updateDocument(createResult.getKey(), doc, options); assertThat(updateResult).isNotNull(); assertThat(updateResult.getId()).isEqualTo(createResult.getId()); assertThat(updateResult.getRev()).isNotEqualTo(updateResult.getOldRev()); assertThat(updateResult.getOldRev()).isEqualTo(createResult.getRev()); - final BaseDocument readResult = collection - .getDocument(createResult.getKey(), BaseDocument.class, null); + final BaseDocument readResult = collection.getDocument(createResult.getKey(), BaseDocument.class, null); assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); final Object aResult = readResult.getAttribute("a"); assertThat(aResult).isInstanceOf(Map.class); @@ -840,21 +789,18 @@ void updateDocumentMergeObjectsFalse(ArangoCollection collection) { final Map a = new HashMap<>(); a.put("a", "test"); doc.addAttribute("a", a); - final DocumentCreateEntity createResult = collection - .insertDocument(doc, null); + final DocumentCreateEntity createResult = collection.insertDocument(doc, null); a.clear(); a.put("b", "test"); doc.updateAttribute("a", a); final DocumentUpdateOptions options = new DocumentUpdateOptions().mergeObjects(false); - final DocumentUpdateEntity updateResult = collection - .updateDocument(createResult.getKey(), doc, options); + final DocumentUpdateEntity updateResult = collection.updateDocument(createResult.getKey(), doc, options); assertThat(updateResult).isNotNull(); assertThat(updateResult.getId()).isEqualTo(createResult.getId()); assertThat(updateResult.getRev()).isNotEqualTo(updateResult.getOldRev()); assertThat(updateResult.getOldRev()).isEqualTo(createResult.getRev()); - final BaseDocument readResult = collection - .getDocument(createResult.getKey(), BaseDocument.class, null); + final BaseDocument readResult = collection.getDocument(createResult.getKey(), BaseDocument.class, null); assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); final Object aResult = readResult.getAttribute("a"); assertThat(aResult).isInstanceOf(Map.class); @@ -868,8 +814,7 @@ void updateDocumentMergeObjectsFalse(ArangoCollection collection) { void updateDocumentIgnoreRevsFalse(ArangoCollection collection) { final BaseDocument doc = new BaseDocument(); doc.addAttribute("a", "test"); - final DocumentCreateEntity createResult = collection - .insertDocument(doc, null); + final DocumentCreateEntity createResult = collection.insertDocument(doc, null); doc.updateAttribute("a", "test1"); doc.setRevision("no"); @@ -882,10 +827,8 @@ void updateDocumentIgnoreRevsFalse(ArangoCollection collection) { @MethodSource("cols") void updateDocumentSilent(ArangoCollection collection) { assumeTrue(isSingleServer()); - final DocumentCreateEntity createResult = collection - .insertDocument(new BaseDocument()); - final DocumentUpdateEntity meta = collection - .updateDocument(createResult.getKey(), new BaseDocument(), new DocumentUpdateOptions().silent(true)); + final DocumentCreateEntity createResult = collection.insertDocument(new BaseDocument()); + final DocumentUpdateEntity meta = collection.updateDocument(createResult.getKey(), new BaseDocument(), new DocumentUpdateOptions().silent(true)); assertThat(meta).isNotNull(); assertThat(meta.getId()).isNull(); assertThat(meta.getKey()).isNull(); @@ -896,11 +839,8 @@ void updateDocumentSilent(ArangoCollection collection) { @MethodSource("cols") void updateDocumentsSilent(ArangoCollection collection) { assumeTrue(isSingleServer()); - final DocumentCreateEntity createResult = collection - .insertDocument(new BaseDocument()); - final MultiDocumentEntity> info = collection - .updateDocuments(Collections.singletonList(new BaseDocument(createResult.getKey())), - new DocumentUpdateOptions().silent(true)); + final DocumentCreateEntity createResult = collection.insertDocument(new BaseDocument()); + final MultiDocumentEntity> info = collection.updateDocuments(Collections.singletonList(new BaseDocument(createResult.getKey())), new DocumentUpdateOptions().silent(true)); assertThat(info).isNotNull(); assertThat(info.getDocuments()).isEmpty(); assertThat(info.getDocumentsAndErrors()).isEmpty(); @@ -926,15 +866,13 @@ void updateNonExistingDocument(ArangoCollection collection) { void updateDocumentPreconditionFailed(ArangoCollection collection) { final BaseDocument doc = new BaseDocument("test-" + rnd()); doc.addAttribute("foo", "a"); - final DocumentCreateEntity createResult = collection - .insertDocument(doc, null); + final DocumentCreateEntity createResult = collection.insertDocument(doc, null); doc.updateAttribute("foo", "b"); collection.updateDocument(doc.getKey(), doc, null); doc.updateAttribute("foo", "c"); - Throwable thrown = catchThrowable(() -> - collection.updateDocument(doc.getKey(), doc, new DocumentUpdateOptions().ifMatch(createResult.getRev()))); + Throwable thrown = catchThrowable(() -> collection.updateDocument(doc.getKey(), doc, new DocumentUpdateOptions().ifMatch(createResult.getRev()))); assertThat(thrown).isInstanceOf(ArangoDBException.class); ArangoDBException e = (ArangoDBException) thrown; assertThat(e.getResponseCode()).isEqualTo(412); @@ -948,12 +886,10 @@ void updateDocumentPreconditionFailed(ArangoCollection collection) { void replaceDocument(ArangoCollection collection) { final BaseDocument doc = new BaseDocument(); doc.addAttribute("a", "test"); - final DocumentCreateEntity createResult = collection - .insertDocument(doc, null); + final DocumentCreateEntity createResult = collection.insertDocument(doc, null); doc.getProperties().clear(); doc.addAttribute("b", "test"); - final DocumentUpdateEntity replaceResult = collection - .replaceDocument(createResult.getKey(), doc, null); + final DocumentUpdateEntity replaceResult = collection.replaceDocument(createResult.getKey(), doc, null); assertThat(replaceResult).isNotNull(); assertThat(replaceResult.getId()).isEqualTo(createResult.getId()); assertThat(replaceResult.getNew()).isNull(); @@ -961,8 +897,7 @@ void replaceDocument(ArangoCollection collection) { assertThat(replaceResult.getRev()).isNotEqualTo(replaceResult.getOldRev()); assertThat(replaceResult.getOldRev()).isEqualTo(createResult.getRev()); - final BaseDocument readResult = collection - .getDocument(createResult.getKey(), BaseDocument.class, null); + final BaseDocument readResult = collection.getDocument(createResult.getKey(), BaseDocument.class, null); assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); assertThat(readResult.getRevision()).isEqualTo(replaceResult.getRev()); assertThat(readResult.getProperties().keySet()).doesNotContain("a"); @@ -974,11 +909,9 @@ void replaceDocument(ArangoCollection collection) { @MethodSource("cols") void replaceDocumentUpdateRev(ArangoCollection collection) { final BaseDocument doc = new BaseDocument(); - final DocumentCreateEntity createResult = collection - .insertDocument(doc, null); + final DocumentCreateEntity createResult = collection.insertDocument(doc, null); assertThat(doc.getRevision()).isEqualTo(createResult.getRev()); - final DocumentUpdateEntity replaceResult = collection - .replaceDocument(createResult.getKey(), doc, null); + final DocumentUpdateEntity replaceResult = collection.replaceDocument(createResult.getKey(), doc, null); assertThat(doc.getRevision()).isEqualTo(replaceResult.getRev()); } @@ -987,20 +920,17 @@ void replaceDocumentUpdateRev(ArangoCollection collection) { void replaceDocumentIfMatch(ArangoCollection collection) { final BaseDocument doc = new BaseDocument(); doc.addAttribute("a", "test"); - final DocumentCreateEntity createResult = collection - .insertDocument(doc, null); + final DocumentCreateEntity createResult = collection.insertDocument(doc, null); doc.getProperties().clear(); doc.addAttribute("b", "test"); final DocumentReplaceOptions options = new DocumentReplaceOptions().ifMatch(createResult.getRev()); - final DocumentUpdateEntity replaceResult = collection - .replaceDocument(createResult.getKey(), doc, options); + final DocumentUpdateEntity replaceResult = collection.replaceDocument(createResult.getKey(), doc, options); assertThat(replaceResult).isNotNull(); assertThat(replaceResult.getId()).isEqualTo(createResult.getId()); assertThat(replaceResult.getRev()).isNotEqualTo(replaceResult.getOldRev()); assertThat(replaceResult.getOldRev()).isEqualTo(createResult.getRev()); - final BaseDocument readResult = collection - .getDocument(createResult.getKey(), BaseDocument.class, null); + final BaseDocument readResult = collection.getDocument(createResult.getKey(), BaseDocument.class, null); assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); assertThat(readResult.getRevision()).isEqualTo(replaceResult.getRev()); assertThat(readResult.getProperties().keySet()).doesNotContain("a"); @@ -1013,8 +943,7 @@ void replaceDocumentIfMatch(ArangoCollection collection) { void replaceDocumentIfMatchFail(ArangoCollection collection) { final BaseDocument doc = new BaseDocument(); doc.addAttribute("a", "test"); - final DocumentCreateEntity createResult = collection - .insertDocument(doc, null); + final DocumentCreateEntity createResult = collection.insertDocument(doc, null); doc.getProperties().clear(); doc.addAttribute("b", "test"); @@ -1029,8 +958,7 @@ void replaceDocumentIfMatchFail(ArangoCollection collection) { void replaceDocumentIgnoreRevsFalse(ArangoCollection collection) { final BaseDocument doc = new BaseDocument(); doc.addAttribute("a", "test"); - final DocumentCreateEntity createResult = collection - .insertDocument(doc, null); + final DocumentCreateEntity createResult = collection.insertDocument(doc, null); doc.getProperties().clear(); doc.addAttribute("b", "test"); doc.setRevision("no"); @@ -1045,13 +973,11 @@ void replaceDocumentIgnoreRevsFalse(ArangoCollection collection) { void replaceDocumentReturnNew(ArangoCollection collection) { final BaseDocument doc = new BaseDocument(); doc.addAttribute("a", "test"); - final DocumentCreateEntity createResult = collection - .insertDocument(doc, null); + final DocumentCreateEntity createResult = collection.insertDocument(doc, null); doc.getProperties().clear(); doc.addAttribute("b", "test"); final DocumentReplaceOptions options = new DocumentReplaceOptions().returnNew(true); - final DocumentUpdateEntity replaceResult = collection - .replaceDocument(createResult.getKey(), doc, options); + final DocumentUpdateEntity replaceResult = collection.replaceDocument(createResult.getKey(), doc, options); assertThat(replaceResult).isNotNull(); assertThat(replaceResult.getId()).isEqualTo(createResult.getId()); assertThat(replaceResult.getOldRev()).isEqualTo(createResult.getRev()); @@ -1068,13 +994,11 @@ void replaceDocumentReturnNew(ArangoCollection collection) { void replaceDocumentReturnOld(ArangoCollection collection) { final BaseDocument doc = new BaseDocument(); doc.addAttribute("a", "test"); - final DocumentCreateEntity createResult = collection - .insertDocument(doc, null); + final DocumentCreateEntity createResult = collection.insertDocument(doc, null); doc.getProperties().clear(); doc.addAttribute("b", "test"); final DocumentReplaceOptions options = new DocumentReplaceOptions().returnOld(true); - final DocumentUpdateEntity replaceResult = collection - .replaceDocument(createResult.getKey(), doc, options); + final DocumentUpdateEntity replaceResult = collection.replaceDocument(createResult.getKey(), doc, options); assertThat(replaceResult).isNotNull(); assertThat(replaceResult.getId()).isEqualTo(createResult.getId()); assertThat(replaceResult.getOldRev()).isEqualTo(createResult.getRev()); @@ -1090,10 +1014,8 @@ void replaceDocumentReturnOld(ArangoCollection collection) { @MethodSource("cols") void replaceDocumentSilent(ArangoCollection collection) { assumeTrue(isSingleServer()); - final DocumentCreateEntity createResult = collection - .insertDocument(new BaseDocument()); - final DocumentUpdateEntity meta = collection - .replaceDocument(createResult.getKey(), new BaseDocument(), new DocumentReplaceOptions().silent(true)); + final DocumentCreateEntity createResult = collection.insertDocument(new BaseDocument()); + final DocumentUpdateEntity meta = collection.replaceDocument(createResult.getKey(), new BaseDocument(), new DocumentReplaceOptions().silent(true)); assertThat(meta).isNotNull(); assertThat(meta.getId()).isNull(); assertThat(meta.getKey()).isNull(); @@ -1108,8 +1030,7 @@ void replaceDocumentSilentDontTouchInstance(ArangoCollection collection) { final DocumentCreateEntity createResult = collection.insertDocument(doc); final String revision = doc.getRevision(); assertThat(revision).isNotNull(); - final DocumentUpdateEntity meta = collection - .replaceDocument(createResult.getKey(), doc, new DocumentReplaceOptions().silent(true)); + final DocumentUpdateEntity meta = collection.replaceDocument(createResult.getKey(), doc, new DocumentReplaceOptions().silent(true)); assertThat(meta.getRev()).isNull(); assertThat(doc.getRevision()).isEqualTo(revision); } @@ -1118,11 +1039,8 @@ void replaceDocumentSilentDontTouchInstance(ArangoCollection collection) { @MethodSource("cols") void replaceDocumentsSilent(ArangoCollection collection) { assumeTrue(isSingleServer()); - final DocumentCreateEntity createResult = collection - .insertDocument(new BaseDocument()); - final MultiDocumentEntity> info = collection - .replaceDocuments(Collections.singletonList(new BaseDocument(createResult.getKey())), - new DocumentReplaceOptions().silent(true)); + final DocumentCreateEntity createResult = collection.insertDocument(new BaseDocument()); + final MultiDocumentEntity> info = collection.replaceDocuments(Collections.singletonList(new BaseDocument(createResult.getKey())), new DocumentReplaceOptions().silent(true)); assertThat(info).isNotNull(); assertThat(info.getDocuments()).isEmpty(); assertThat(info.getDocumentsAndErrors()).isEmpty(); @@ -1133,11 +1051,9 @@ void replaceDocumentsSilent(ArangoCollection collection) { @MethodSource("cols") void deleteDocument(ArangoCollection collection) { final BaseDocument doc = new BaseDocument(); - final DocumentCreateEntity createResult = collection - .insertDocument(doc, null); + final DocumentCreateEntity createResult = collection.insertDocument(doc, null); collection.deleteDocument(createResult.getKey(), null, null); - final BaseDocument document = collection - .getDocument(createResult.getKey(), BaseDocument.class, null); + final BaseDocument document = collection.getDocument(createResult.getKey(), BaseDocument.class, null); assertThat(document).isNull(); } @@ -1146,11 +1062,9 @@ void deleteDocument(ArangoCollection collection) { void deleteDocumentReturnOld(ArangoCollection collection) { final BaseDocument doc = new BaseDocument(); doc.addAttribute("a", "test"); - final DocumentCreateEntity createResult = collection - .insertDocument(doc, null); + final DocumentCreateEntity createResult = collection.insertDocument(doc, null); final DocumentDeleteOptions options = new DocumentDeleteOptions().returnOld(true); - final DocumentDeleteEntity deleteResult = collection - .deleteDocument(createResult.getKey(), BaseDocument.class, options); + final DocumentDeleteEntity deleteResult = collection.deleteDocument(createResult.getKey(), BaseDocument.class, options); assertThat(deleteResult.getOld()).isNotNull(); assertThat(deleteResult.getOld()).isInstanceOf(BaseDocument.class); assertThat(deleteResult.getOld().getAttribute("a")).isNotNull(); @@ -1161,12 +1075,10 @@ void deleteDocumentReturnOld(ArangoCollection collection) { @MethodSource("cols") void deleteDocumentIfMatch(ArangoCollection collection) { final BaseDocument doc = new BaseDocument(); - final DocumentCreateEntity createResult = collection - .insertDocument(doc, null); + final DocumentCreateEntity createResult = collection.insertDocument(doc, null); final DocumentDeleteOptions options = new DocumentDeleteOptions().ifMatch(createResult.getRev()); collection.deleteDocument(createResult.getKey(), null, options); - final BaseDocument document = collection - .getDocument(createResult.getKey(), BaseDocument.class, null); + final BaseDocument document = collection.getDocument(createResult.getKey(), BaseDocument.class, null); assertThat(document).isNull(); } @@ -1174,8 +1086,7 @@ void deleteDocumentIfMatch(ArangoCollection collection) { @MethodSource("cols") void deleteDocumentIfMatchFail(ArangoCollection collection) { final BaseDocument doc = new BaseDocument(); - final DocumentCreateEntity createResult = collection - .insertDocument(doc, null); + final DocumentCreateEntity createResult = collection.insertDocument(doc, null); final DocumentDeleteOptions options = new DocumentDeleteOptions().ifMatch("no"); Throwable thrown = catchThrowable(() -> collection.deleteDocument(createResult.getKey(), null, options)); assertThat(thrown).isInstanceOf(ArangoDBException.class); @@ -1185,10 +1096,8 @@ void deleteDocumentIfMatchFail(ArangoCollection collection) { @MethodSource("cols") void deleteDocumentSilent(ArangoCollection collection) { assumeTrue(isSingleServer()); - final DocumentCreateEntity createResult = collection - .insertDocument(new BaseDocument()); - final DocumentDeleteEntity meta = collection - .deleteDocument(createResult.getKey(), BaseDocument.class, new DocumentDeleteOptions().silent(true)); + final DocumentCreateEntity createResult = collection.insertDocument(new BaseDocument()); + final DocumentDeleteEntity meta = collection.deleteDocument(createResult.getKey(), BaseDocument.class, new DocumentDeleteOptions().silent(true)); assertThat(meta).isNotNull(); assertThat(meta.getId()).isNull(); assertThat(meta.getKey()).isNull(); @@ -1199,11 +1108,8 @@ void deleteDocumentSilent(ArangoCollection collection) { @MethodSource("cols") void deleteDocumentsSilent(ArangoCollection collection) { assumeTrue(isSingleServer()); - final DocumentCreateEntity createResult = collection - .insertDocument(new BaseDocument()); - final MultiDocumentEntity> info = collection - .deleteDocuments(Collections.singletonList(createResult.getKey()), BaseDocument.class, - new DocumentDeleteOptions().silent(true)); + final DocumentCreateEntity createResult = collection.insertDocument(new BaseDocument()); + final MultiDocumentEntity> info = collection.deleteDocuments(Collections.singletonList(createResult.getKey()), BaseDocument.class, new DocumentDeleteOptions().silent(true)); assertThat(info).isNotNull(); assertThat(info.getDocuments()).isEmpty(); assertThat(info.getDocumentsAndErrors()).isEmpty(); @@ -1530,9 +1436,7 @@ void createZKDIndexWithOptions(ArangoCollection collection) { collection.truncate(); String name = "ZKDIndex-" + rnd(); - final ZKDIndexOptions options = new ZKDIndexOptions() - .name(name) - .fieldValueTypes(ZKDIndexOptions.FieldValueTypes.DOUBLE); + final ZKDIndexOptions options = new ZKDIndexOptions().name(name).fieldValueTypes(ZKDIndexOptions.FieldValueTypes.DOUBLE); String f1 = "field-" + rnd(); String f2 = "field-" + rnd(); @@ -1718,10 +1622,7 @@ void getIndexes(ArangoCollection collection) { String f1 = "field-" + rnd(); final Collection fields = Collections.singletonList(f1); collection.ensureHashIndex(fields, null); - long matchingIndexes = collection.getIndexes().stream() - .filter(i -> i.getType() == IndexType.hash) - .filter(i -> i.getFields().contains(f1)) - .count(); + long matchingIndexes = collection.getIndexes().stream().filter(i -> i.getType() == IndexType.hash).filter(i -> i.getFields().contains(f1)).count(); assertThat(matchingIndexes).isEqualTo(1L); } @@ -1747,14 +1648,12 @@ void exists(ArangoCollection collection) { void truncate(ArangoCollection collection) { final BaseDocument doc = new BaseDocument(); collection.insertDocument(doc, null); - final BaseDocument readResult = collection - .getDocument(doc.getKey(), BaseDocument.class, null); + final BaseDocument readResult = collection.getDocument(doc.getKey(), BaseDocument.class, null); assertThat(readResult.getKey()).isEqualTo(doc.getKey()); final CollectionEntity truncateResult = collection.truncate(); assertThat(truncateResult).isNotNull(); assertThat(truncateResult.getId()).isNotNull(); - final BaseDocument document = collection - .getDocument(doc.getKey(), BaseDocument.class, null); + final BaseDocument document = collection.getDocument(doc.getKey(), BaseDocument.class, null); assertThat(document).isNull(); } @@ -1762,19 +1661,20 @@ void truncate(ArangoCollection collection) { @MethodSource("cols") void getCount(ArangoCollection collection) { Long initialCount = collection.count().getCount(); - collection.insertDocument("{}", null); + collection.insertDocument(RawJson.of("{}")); final CollectionPropertiesEntity count = collection.count(); assertThat(count.getCount()).isEqualTo(initialCount + 1L); } @ParameterizedTest(name = "{index}") @MethodSource("cols") - void documentExists(ArangoCollection collection) throws JsonProcessingException { + void documentExists(ArangoCollection collection) { final Boolean existsNot = collection.documentExists(rnd(), null); assertThat(existsNot).isFalse(); String key = rnd(); - collection.insertDocument(mapper.writeValueAsString(Collections.singletonMap("_key", key)), null); + RawJson rawJson = RawJson.of("{\"_key\":\"" + key + "\"}"); + collection.insertDocument(rawJson); final Boolean exists = collection.documentExists(key, null); assertThat(exists).isTrue(); } @@ -1788,9 +1688,10 @@ void documentExistsThrowExcpetion(ArangoCollection collection) { @ParameterizedTest(name = "{index}") @MethodSource("cols") - void documentExistsIfMatch(ArangoCollection collection) throws JsonProcessingException { + void documentExistsIfMatch(ArangoCollection collection) { String key = rnd(); - final DocumentCreateEntity createResult = collection.insertDocument(mapper.writeValueAsString(Collections.singletonMap("_key", key)), null); + RawJson rawJson = RawJson.of("{\"_key\":\"" + key + "\"}"); + final DocumentCreateEntity createResult = collection.insertDocument(rawJson); final DocumentExistsOptions options = new DocumentExistsOptions().ifMatch(createResult.getRev()); final Boolean exists = collection.documentExists(key, options); assertThat(exists).isTrue(); @@ -1798,9 +1699,10 @@ void documentExistsIfMatch(ArangoCollection collection) throws JsonProcessingExc @ParameterizedTest(name = "{index}") @MethodSource("cols") - void documentExistsIfMatchFail(ArangoCollection collection) throws JsonProcessingException { + void documentExistsIfMatchFail(ArangoCollection collection) { String key = rnd(); - collection.insertDocument(mapper.writeValueAsString(Collections.singletonMap("_key", key)), null); + RawJson rawJson = RawJson.of("{\"_key\":\"" + key + "\"}"); + collection.insertDocument(rawJson); final DocumentExistsOptions options = new DocumentExistsOptions().ifMatch("no"); final Boolean exists = collection.documentExists(key, options); assertThat(exists).isFalse(); @@ -1808,9 +1710,10 @@ void documentExistsIfMatchFail(ArangoCollection collection) throws JsonProcessin @ParameterizedTest(name = "{index}") @MethodSource("cols") - void documentExistsIfNoneMatch(ArangoCollection collection) throws JsonProcessingException { + void documentExistsIfNoneMatch(ArangoCollection collection) { String key = rnd(); - collection.insertDocument(mapper.writeValueAsString(Collections.singletonMap("_key", key)), null); + RawJson rawJson = RawJson.of("{\"_key\":\"" + key + "\"}"); + collection.insertDocument(rawJson); final DocumentExistsOptions options = new DocumentExistsOptions().ifNoneMatch("no"); final Boolean exists = collection.documentExists(key, options); assertThat(exists).isTrue(); @@ -1818,9 +1721,10 @@ void documentExistsIfNoneMatch(ArangoCollection collection) throws JsonProcessin @ParameterizedTest(name = "{index}") @MethodSource("cols") - void documentExistsIfNoneMatchFail(ArangoCollection collection) throws JsonProcessingException { + void documentExistsIfNoneMatchFail(ArangoCollection collection) { String key = rnd(); - final DocumentCreateEntity createResult = collection.insertDocument(mapper.writeValueAsString(Collections.singletonMap("_key", key)), null); + RawJson rawJson = RawJson.of("{\"_key\":\"" + key + "\"}"); + final DocumentCreateEntity createResult = collection.insertDocument(rawJson); final DocumentExistsOptions options = new DocumentExistsOptions().ifNoneMatch(createResult.getRev()); final Boolean exists = collection.documentExists(key, options); assertThat(exists).isFalse(); @@ -1829,14 +1733,9 @@ void documentExistsIfNoneMatchFail(ArangoCollection collection) throws JsonProce @ParameterizedTest(name = "{index}") @MethodSource("cols") void insertDocuments(ArangoCollection collection) { - final Collection values = Arrays.asList( - new BaseDocument(), - new BaseDocument(), - new BaseDocument() - ); - - final MultiDocumentEntity> docs = collection - .insertDocuments(values, null); + final Collection values = Arrays.asList(new BaseDocument(), new BaseDocument(), new BaseDocument()); + + final MultiDocumentEntity> docs = collection.insertDocuments(values, null); assertThat(docs).isNotNull(); assertThat(docs.getDocuments()).isNotNull(); assertThat(docs.getDocuments()).hasSize(3); @@ -1860,9 +1759,7 @@ void insertDocumentsOverwriteModeUpdate(ArangoCollection collection) { doc1.addAttribute("bar", "b"); doc2.addAttribute("bar", "b"); - final MultiDocumentEntity> repsert = collection - .insertDocuments(Arrays.asList(doc1, doc2), - new DocumentCreateOptions().overwriteMode(OverwriteMode.update).returnNew(true)); + final MultiDocumentEntity> repsert = collection.insertDocuments(Arrays.asList(doc1, doc2), new DocumentCreateOptions().overwriteMode(OverwriteMode.update).returnNew(true)); assertThat(repsert).isNotNull(); assertThat(repsert.getDocuments()).hasSize(2); assertThat(repsert.getErrors()).isEmpty(); @@ -1881,8 +1778,7 @@ void insertDocumentsJson(ArangoCollection collection) { values.add("{}"); values.add("{}"); values.add("{}"); - final MultiDocumentEntity> docs = collection - .insertDocuments(values); + final MultiDocumentEntity> docs = collection.insertDocuments(values); assertThat(docs).isNotNull(); assertThat(docs.getDocuments()).isNotNull(); assertThat(docs.getDocuments()).hasSize(3); @@ -1895,8 +1791,7 @@ void insertDocumentsJson(ArangoCollection collection) { void insertDocumentsOne(ArangoCollection collection) { final Collection values = new ArrayList<>(); values.add(new BaseDocument()); - final MultiDocumentEntity> docs = collection - .insertDocuments(values, null); + final MultiDocumentEntity> docs = collection.insertDocuments(values, null); assertThat(docs).isNotNull(); assertThat(docs.getDocuments()).isNotNull(); assertThat(docs.getDocuments()).hasSize(1); @@ -1908,8 +1803,7 @@ void insertDocumentsOne(ArangoCollection collection) { @MethodSource("cols") void insertDocumentsEmpty(ArangoCollection collection) { final Collection values = new ArrayList<>(); - final MultiDocumentEntity> docs = collection - .insertDocuments(values, null); + final MultiDocumentEntity> docs = collection.insertDocuments(values, null); assertThat(docs).isNotNull(); assertThat(docs.getDocuments()).isNotNull(); assertThat(docs.getDocuments()).isEmpty(); @@ -1925,8 +1819,7 @@ void insertDocumentsReturnNew(ArangoCollection collection) { values.add(new BaseDocument()); values.add(new BaseDocument()); final DocumentCreateOptions options = new DocumentCreateOptions().returnNew(true); - final MultiDocumentEntity> docs = collection - .insertDocuments(values, options); + final MultiDocumentEntity> docs = collection.insertDocuments(values, options); assertThat(docs).isNotNull(); assertThat(docs.getDocuments()).isNotNull(); assertThat(docs.getDocuments()).hasSize(3); @@ -1945,14 +1838,9 @@ void insertDocumentsReturnNew(ArangoCollection collection) { void insertDocumentsFail(ArangoCollection collection) { String k1 = rnd(); String k2 = rnd(); - final Collection values = Arrays.asList( - new BaseDocument(k1), - new BaseDocument(k2), - new BaseDocument(k2) - ); - - final MultiDocumentEntity> docs = collection - .insertDocuments(values); + final Collection values = Arrays.asList(new BaseDocument(k1), new BaseDocument(k2), new BaseDocument(k2)); + + final MultiDocumentEntity> docs = collection.insertDocuments(values); assertThat(docs).isNotNull(); assertThat(docs.getDocuments()).isNotNull(); assertThat(docs.getDocuments()).hasSize(2); @@ -1964,11 +1852,7 @@ void insertDocumentsFail(ArangoCollection collection) { @ParameterizedTest(name = "{index}") @MethodSource("cols") void importDocuments(ArangoCollection collection) { - final Collection values = Arrays.asList( - new BaseDocument(), - new BaseDocument(), - new BaseDocument() - ); + final Collection values = Arrays.asList(new BaseDocument(), new BaseDocument(), new BaseDocument()); final DocumentImportEntity docs = collection.importDocuments(values); assertThat(docs).isNotNull(); @@ -1983,11 +1867,7 @@ void importDocuments(ArangoCollection collection) { @ParameterizedTest(name = "{index}") @MethodSource("cols") void importDocumentsJsonList(ArangoCollection collection) { - final Collection values = Arrays.asList( - "{}", - "{}", - "{}" - ); + final Collection values = Arrays.asList("{}", "{}", "{}"); final DocumentImportEntity docs = collection.importDocuments(values); assertThat(docs).isNotNull(); @@ -2005,11 +1885,7 @@ void importDocumentsDuplicateDefaultError(ArangoCollection collection) { String k1 = rnd(); String k2 = rnd(); - final Collection values = Arrays.asList( - new BaseDocument(k1), - new BaseDocument(k2), - new BaseDocument(k2) - ); + final Collection values = Arrays.asList(new BaseDocument(k1), new BaseDocument(k2), new BaseDocument(k2)); final DocumentImportEntity docs = collection.importDocuments(values); assertThat(docs).isNotNull(); @@ -2027,14 +1903,9 @@ void importDocumentsDuplicateError(ArangoCollection collection) { String k1 = rnd(); String k2 = rnd(); - final Collection values = Arrays.asList( - new BaseDocument(k1), - new BaseDocument(k2), - new BaseDocument(k2) - ); + final Collection values = Arrays.asList(new BaseDocument(k1), new BaseDocument(k2), new BaseDocument(k2)); - final DocumentImportEntity docs = collection - .importDocuments(values, new DocumentImportOptions().onDuplicate(OnDuplicate.error)); + final DocumentImportEntity docs = collection.importDocuments(values, new DocumentImportOptions().onDuplicate(OnDuplicate.error)); assertThat(docs).isNotNull(); assertThat(docs.getCreated()).isEqualTo(2); assertThat(docs.getEmpty()).isZero(); @@ -2050,14 +1921,9 @@ void importDocumentsDuplicateIgnore(ArangoCollection collection) { String k1 = rnd(); String k2 = rnd(); - final Collection values = Arrays.asList( - new BaseDocument(k1), - new BaseDocument(k2), - new BaseDocument(k2) - ); + final Collection values = Arrays.asList(new BaseDocument(k1), new BaseDocument(k2), new BaseDocument(k2)); - final DocumentImportEntity docs = collection - .importDocuments(values, new DocumentImportOptions().onDuplicate(OnDuplicate.ignore)); + final DocumentImportEntity docs = collection.importDocuments(values, new DocumentImportOptions().onDuplicate(OnDuplicate.ignore)); assertThat(docs).isNotNull(); assertThat(docs.getCreated()).isEqualTo(2); assertThat(docs.getEmpty()).isZero(); @@ -2073,14 +1939,9 @@ void importDocumentsDuplicateReplace(ArangoCollection collection) { String k1 = rnd(); String k2 = rnd(); - final Collection values = Arrays.asList( - new BaseDocument(k1), - new BaseDocument(k2), - new BaseDocument(k2) - ); + final Collection values = Arrays.asList(new BaseDocument(k1), new BaseDocument(k2), new BaseDocument(k2)); - final DocumentImportEntity docs = collection - .importDocuments(values, new DocumentImportOptions().onDuplicate(OnDuplicate.replace)); + final DocumentImportEntity docs = collection.importDocuments(values, new DocumentImportOptions().onDuplicate(OnDuplicate.replace)); assertThat(docs).isNotNull(); assertThat(docs.getCreated()).isEqualTo(2); assertThat(docs.getEmpty()).isZero(); @@ -2096,14 +1957,9 @@ void importDocumentsDuplicateUpdate(ArangoCollection collection) { String k1 = rnd(); String k2 = rnd(); - final Collection values = Arrays.asList( - new BaseDocument(k1), - new BaseDocument(k2), - new BaseDocument(k2) - ); + final Collection values = Arrays.asList(new BaseDocument(k1), new BaseDocument(k2), new BaseDocument(k2)); - final DocumentImportEntity docs = collection - .importDocuments(values, new DocumentImportOptions().onDuplicate(OnDuplicate.update)); + final DocumentImportEntity docs = collection.importDocuments(values, new DocumentImportOptions().onDuplicate(OnDuplicate.update)); assertThat(docs).isNotNull(); assertThat(docs.getCreated()).isEqualTo(2); assertThat(docs.getEmpty()).isZero(); @@ -2119,11 +1975,7 @@ void importDocumentsCompleteFail(ArangoCollection collection) { String k1 = rnd(); String k2 = rnd(); - final Collection values = Arrays.asList( - new BaseDocument(k1), - new BaseDocument(k2), - new BaseDocument(k2) - ); + final Collection values = Arrays.asList(new BaseDocument(k1), new BaseDocument(k2), new BaseDocument(k2)); Throwable thrown = catchThrowable(() -> collection.importDocuments(values, new DocumentImportOptions().complete(true))); assertThat(thrown).isInstanceOf(ArangoDBException.class); @@ -2137,14 +1989,9 @@ void importDocumentsDetails(ArangoCollection collection) { String k1 = rnd(); String k2 = rnd(); - final Collection values = Arrays.asList( - new BaseDocument(k1), - new BaseDocument(k2), - new BaseDocument(k2) - ); + final Collection values = Arrays.asList(new BaseDocument(k1), new BaseDocument(k2), new BaseDocument(k2)); - final DocumentImportEntity docs = collection - .importDocuments(values, new DocumentImportOptions().details(true)); + final DocumentImportEntity docs = collection.importDocuments(values, new DocumentImportOptions().details(true)); assertThat(docs).isNotNull(); assertThat(docs.getCreated()).isEqualTo(2); assertThat(docs.getEmpty()).isZero(); @@ -2184,17 +2031,13 @@ void importDocumentsOverwriteTrue(ArangoCollection collection) { @MethodSource("edges") void importDocumentsFromToPrefix(ArangoCollection edgeCollection) { final Collection values = new ArrayList<>(); - final String[] keys = { - rnd(), - rnd() - }; + final String[] keys = {rnd(), rnd()}; for (String s : keys) { values.add(new BaseEdgeDocument(s, "from", "to")); } assertThat(values).hasSize(keys.length); - final DocumentImportEntity importResult = edgeCollection - .importDocuments(values, new DocumentImportOptions().fromPrefix("foo").toPrefix("bar")); + final DocumentImportEntity importResult = edgeCollection.importDocuments(values, new DocumentImportOptions().fromPrefix("foo").toPrefix("bar")); assertThat(importResult).isNotNull(); assertThat(importResult.getCreated()).isEqualTo(values.size()); for (String key : keys) { @@ -2208,10 +2051,7 @@ void importDocumentsFromToPrefix(ArangoCollection edgeCollection) { @ParameterizedTest(name = "{index}") @MethodSource("cols") void importDocumentsJson(ArangoCollection collection) throws JsonProcessingException { - final String values = mapper.writeValueAsString(Arrays.asList( - Collections.singletonMap("_key", rnd()), - Collections.singletonMap("_key", rnd()) - )); + final String values = mapper.writeValueAsString(Arrays.asList(Collections.singletonMap("_key", rnd()), Collections.singletonMap("_key", rnd()))); final DocumentImportEntity docs = collection.importDocuments(values); assertThat(docs).isNotNull(); @@ -2229,11 +2069,7 @@ void importDocumentsJsonDuplicateDefaultError(ArangoCollection collection) throw String k1 = rnd(); String k2 = rnd(); - final String values = mapper.writeValueAsString(Arrays.asList( - Collections.singletonMap("_key", k1), - Collections.singletonMap("_key", k2), - Collections.singletonMap("_key", k2) - )); + final String values = mapper.writeValueAsString(Arrays.asList(Collections.singletonMap("_key", k1), Collections.singletonMap("_key", k2), Collections.singletonMap("_key", k2))); final DocumentImportEntity docs = collection.importDocuments(values); assertThat(docs).isNotNull(); @@ -2251,14 +2087,9 @@ void importDocumentsJsonDuplicateError(ArangoCollection collection) throws JsonP String k1 = rnd(); String k2 = rnd(); - final String values = mapper.writeValueAsString(Arrays.asList( - Collections.singletonMap("_key", k1), - Collections.singletonMap("_key", k2), - Collections.singletonMap("_key", k2) - )); + final String values = mapper.writeValueAsString(Arrays.asList(Collections.singletonMap("_key", k1), Collections.singletonMap("_key", k2), Collections.singletonMap("_key", k2))); - final DocumentImportEntity docs = collection - .importDocuments(values, new DocumentImportOptions().onDuplicate(OnDuplicate.error)); + final DocumentImportEntity docs = collection.importDocuments(values, new DocumentImportOptions().onDuplicate(OnDuplicate.error)); assertThat(docs).isNotNull(); assertThat(docs.getCreated()).isEqualTo(2); assertThat(docs.getEmpty()).isZero(); @@ -2274,13 +2105,8 @@ void importDocumentsJsonDuplicateIgnore(ArangoCollection collection) throws Json String k1 = rnd(); String k2 = rnd(); - final String values = mapper.writeValueAsString(Arrays.asList( - Collections.singletonMap("_key", k1), - Collections.singletonMap("_key", k2), - Collections.singletonMap("_key", k2) - )); - final DocumentImportEntity docs = collection - .importDocuments(values, new DocumentImportOptions().onDuplicate(OnDuplicate.ignore)); + final String values = mapper.writeValueAsString(Arrays.asList(Collections.singletonMap("_key", k1), Collections.singletonMap("_key", k2), Collections.singletonMap("_key", k2))); + final DocumentImportEntity docs = collection.importDocuments(values, new DocumentImportOptions().onDuplicate(OnDuplicate.ignore)); assertThat(docs).isNotNull(); assertThat(docs.getCreated()).isEqualTo(2); assertThat(docs.getEmpty()).isZero(); @@ -2296,14 +2122,9 @@ void importDocumentsJsonDuplicateReplace(ArangoCollection collection) throws Jso String k1 = rnd(); String k2 = rnd(); - final String values = mapper.writeValueAsString(Arrays.asList( - Collections.singletonMap("_key", k1), - Collections.singletonMap("_key", k2), - Collections.singletonMap("_key", k2) - )); + final String values = mapper.writeValueAsString(Arrays.asList(Collections.singletonMap("_key", k1), Collections.singletonMap("_key", k2), Collections.singletonMap("_key", k2))); - final DocumentImportEntity docs = collection - .importDocuments(values, new DocumentImportOptions().onDuplicate(OnDuplicate.replace)); + final DocumentImportEntity docs = collection.importDocuments(values, new DocumentImportOptions().onDuplicate(OnDuplicate.replace)); assertThat(docs).isNotNull(); assertThat(docs.getCreated()).isEqualTo(2); assertThat(docs.getEmpty()).isZero(); @@ -2319,14 +2140,9 @@ void importDocumentsJsonDuplicateUpdate(ArangoCollection collection) throws Json String k1 = rnd(); String k2 = rnd(); - final String values = mapper.writeValueAsString(Arrays.asList( - Collections.singletonMap("_key", k1), - Collections.singletonMap("_key", k2), - Collections.singletonMap("_key", k2) - )); + final String values = mapper.writeValueAsString(Arrays.asList(Collections.singletonMap("_key", k1), Collections.singletonMap("_key", k2), Collections.singletonMap("_key", k2))); - final DocumentImportEntity docs = collection - .importDocuments(values, new DocumentImportOptions().onDuplicate(OnDuplicate.update)); + final DocumentImportEntity docs = collection.importDocuments(values, new DocumentImportOptions().onDuplicate(OnDuplicate.update)); assertThat(docs).isNotNull(); assertThat(docs.getCreated()).isEqualTo(2); assertThat(docs.getEmpty()).isZero(); @@ -2352,14 +2168,9 @@ void importDocumentsJsonDetails(ArangoCollection collection) throws JsonProcessi String k1 = rnd(); String k2 = rnd(); - final String values = mapper.writeValueAsString(Arrays.asList( - Collections.singletonMap("_key", k1), - Collections.singletonMap("_key", k2), - Collections.singletonMap("_key", k2) - )); + final String values = mapper.writeValueAsString(Arrays.asList(Collections.singletonMap("_key", k1), Collections.singletonMap("_key", k2), Collections.singletonMap("_key", k2))); - final DocumentImportEntity docs = collection - .importDocuments(values, new DocumentImportOptions().details(true)); + final DocumentImportEntity docs = collection.importDocuments(values, new DocumentImportOptions().details(true)); assertThat(docs).isNotNull(); assertThat(docs.getCreated()).isEqualTo(2); assertThat(docs.getEmpty()).isZero(); @@ -2376,10 +2187,7 @@ void importDocumentsJsonOverwriteFalse(ArangoCollection collection) throws JsonP collection.insertDocument(new BaseDocument()); Long initialCount = collection.count().getCount(); - final String values = mapper.writeValueAsString(Arrays.asList( - Collections.singletonMap("_key", rnd()), - Collections.singletonMap("_key", rnd()) - )); + final String values = mapper.writeValueAsString(Arrays.asList(Collections.singletonMap("_key", rnd()), Collections.singletonMap("_key", rnd()))); collection.importDocuments(values, new DocumentImportOptions().overwrite(false)); assertThat(collection.count().getCount()).isEqualTo(initialCount + 2L); } @@ -2389,10 +2197,7 @@ void importDocumentsJsonOverwriteFalse(ArangoCollection collection) throws JsonP void importDocumentsJsonOverwriteTrue(ArangoCollection collection) throws JsonProcessingException { collection.insertDocument(new BaseDocument()); - final String values = mapper.writeValueAsString(Arrays.asList( - Collections.singletonMap("_key", rnd()), - Collections.singletonMap("_key", rnd()) - )); + final String values = mapper.writeValueAsString(Arrays.asList(Collections.singletonMap("_key", rnd()), Collections.singletonMap("_key", rnd()))); collection.importDocuments(values, new DocumentImportOptions().overwrite(true)); assertThat(collection.count().getCount()).isEqualTo(2L); } @@ -2405,21 +2210,9 @@ void importDocumentsJsonFromToPrefix(ArangoCollection edgeCollection) throws Jso final String[] keys = {k1, k2}; - final String values = mapper.writeValueAsString(Arrays.asList( - new MapBuilder() - .put("_key", k1) - .put("_from", "from") - .put("_to", "to") - .get(), - new MapBuilder() - .put("_key", k2) - .put("_from", "from") - .put("_to", "to") - .get() - )); - - final DocumentImportEntity importResult = edgeCollection - .importDocuments(values, new DocumentImportOptions().fromPrefix("foo").toPrefix("bar")); + final String values = mapper.writeValueAsString(Arrays.asList(new MapBuilder().put("_key", k1).put("_from", "from").put("_to", "to").get(), new MapBuilder().put("_key", k2).put("_from", "from").put("_to", "to").get())); + + final DocumentImportEntity importResult = edgeCollection.importDocuments(values, new DocumentImportOptions().fromPrefix("foo").toPrefix("bar")); assertThat(importResult).isNotNull(); assertThat(importResult.getCreated()).isEqualTo(2); for (String key : keys) { @@ -2448,8 +2241,7 @@ void deleteDocumentsByKey(ArangoCollection collection) { final Collection keys = new ArrayList<>(); keys.add("1"); keys.add("2"); - final MultiDocumentEntity> deleteResult = collection - .deleteDocuments(keys, null, null); + final MultiDocumentEntity> deleteResult = collection.deleteDocuments(keys, null, null); assertThat(deleteResult).isNotNull(); assertThat(deleteResult.getDocuments()).hasSize(2); for (final DocumentDeleteEntity i : deleteResult.getDocuments()) { @@ -2473,8 +2265,7 @@ void deleteDocumentsByDocuments(ArangoCollection collection) { values.add(e); } collection.insertDocuments(values, null); - final MultiDocumentEntity> deleteResult = collection - .deleteDocuments(values, null, null); + final MultiDocumentEntity> deleteResult = collection.deleteDocuments(values, null, null); assertThat(deleteResult).isNotNull(); assertThat(deleteResult.getDocuments()).hasSize(2); for (final DocumentDeleteEntity i : deleteResult.getDocuments()) { @@ -2495,8 +2286,7 @@ void deleteDocumentsByKeyOne(ArangoCollection collection) { collection.insertDocuments(values, null); final Collection keys = new ArrayList<>(); keys.add("1"); - final MultiDocumentEntity> deleteResult = collection - .deleteDocuments(keys, null, null); + final MultiDocumentEntity> deleteResult = collection.deleteDocuments(keys, null, null); assertThat(deleteResult).isNotNull(); assertThat(deleteResult.getDocuments()).hasSize(1); for (final DocumentDeleteEntity i : deleteResult.getDocuments()) { @@ -2515,8 +2305,7 @@ void deleteDocumentsByDocumentOne(ArangoCollection collection) { values.add(e); } collection.insertDocuments(values, null); - final MultiDocumentEntity> deleteResult = collection - .deleteDocuments(values, null, null); + final MultiDocumentEntity> deleteResult = collection.deleteDocuments(values, null, null); assertThat(deleteResult).isNotNull(); assertThat(deleteResult.getDocuments()).hasSize(1); for (final DocumentDeleteEntity i : deleteResult.getDocuments()) { @@ -2531,8 +2320,7 @@ void deleteDocumentsEmpty(ArangoCollection collection) { final Collection values = new ArrayList<>(); collection.insertDocuments(values, null); final Collection keys = new ArrayList<>(); - final MultiDocumentEntity> deleteResult = collection - .deleteDocuments(keys, null, null); + final MultiDocumentEntity> deleteResult = collection.deleteDocuments(keys, null, null); assertThat(deleteResult).isNotNull(); assertThat(deleteResult.getDocuments()).isEmpty(); assertThat(deleteResult.getErrors()).isEmpty(); @@ -2543,13 +2331,9 @@ void deleteDocumentsEmpty(ArangoCollection collection) { void deleteDocumentsByKeyNotExisting(ArangoCollection collection) { final Collection values = new ArrayList<>(); collection.insertDocuments(values, null); - final Collection keys = Arrays.asList( - rnd(), - rnd() - ); + final Collection keys = Arrays.asList(rnd(), rnd()); - final MultiDocumentEntity> deleteResult = collection - .deleteDocuments(keys, null, null); + final MultiDocumentEntity> deleteResult = collection.deleteDocuments(keys, null, null); assertThat(deleteResult).isNotNull(); assertThat(deleteResult.getDocuments()).isEmpty(); assertThat(deleteResult.getErrors()).hasSize(2); @@ -2569,8 +2353,7 @@ void deleteDocumentsByDocumentsNotExisting(ArangoCollection collection) { e.setKey("2"); values.add(e); } - final MultiDocumentEntity> deleteResult = collection - .deleteDocuments(values, null, null); + final MultiDocumentEntity> deleteResult = collection.deleteDocuments(values, null, null); assertThat(deleteResult).isNotNull(); assertThat(deleteResult.getDocuments()).isEmpty(); assertThat(deleteResult.getErrors()).hasSize(2); @@ -2579,15 +2362,11 @@ void deleteDocumentsByDocumentsNotExisting(ArangoCollection collection) { @ParameterizedTest(name = "{index}") @MethodSource("cols") void updateDocuments(ArangoCollection collection) { - final Collection values = Arrays.asList( - new BaseDocument(rnd()), - new BaseDocument(rnd()) - ); + final Collection values = Arrays.asList(new BaseDocument(rnd()), new BaseDocument(rnd())); collection.insertDocuments(values, null); values.forEach(it -> it.addAttribute("a", "test")); - final MultiDocumentEntity> updateResult = collection - .updateDocuments(values, null); + final MultiDocumentEntity> updateResult = collection.updateDocuments(values, null); assertThat(updateResult.getDocuments()).hasSize(2); assertThat(updateResult.getErrors()).isEmpty(); } @@ -2596,32 +2375,22 @@ void updateDocuments(ArangoCollection collection) { @MethodSource("cols") void updateDocumentsWithDifferentReturnType(ArangoCollection collection) { List keys = IntStream.range(0, 3).mapToObj(it -> "key-" + UUID.randomUUID()).collect(Collectors.toList()); - List docs = keys.stream() - .map(BaseDocument::new) - .peek(it -> it.addAttribute("a", "test")) - .collect(Collectors.toList()); + List docs = keys.stream().map(BaseDocument::new).peek(it -> it.addAttribute("a", "test")).collect(Collectors.toList()); collection.insertDocuments(docs); - List> modifiedDocs = docs.stream() - .peek(it -> it.addAttribute("b", "test")) - .map(it -> { - Map map = new HashMap<>(); - map.put("_key", it.getKey()); - map.put("a", it.getAttribute("a")); - map.put("b", it.getAttribute("b")); - return map; - }) - .collect(Collectors.toList()); - - final MultiDocumentEntity> updateResult = collection - .updateDocuments(modifiedDocs, new DocumentUpdateOptions().returnNew(true), BaseDocument.class); + List> modifiedDocs = docs.stream().peek(it -> it.addAttribute("b", "test")).map(it -> { + Map map = new HashMap<>(); + map.put("_key", it.getKey()); + map.put("a", it.getAttribute("a")); + map.put("b", it.getAttribute("b")); + return map; + }).collect(Collectors.toList()); + + final MultiDocumentEntity> updateResult = collection.updateDocuments(modifiedDocs, new DocumentUpdateOptions().returnNew(true), BaseDocument.class); assertThat(updateResult.getDocuments()).hasSize(3); assertThat(updateResult.getErrors()).isEmpty(); - assertThat(updateResult.getDocuments().stream()) - .map(DocumentUpdateEntity::getNew) - .allMatch(it -> it.getAttribute("a").equals("test")) - .allMatch(it -> it.getAttribute("b").equals("test")); + assertThat(updateResult.getDocuments().stream()).map(DocumentUpdateEntity::getNew).allMatch(it -> it.getAttribute("a").equals("test")).allMatch(it -> it.getAttribute("b").equals("test")); } @ParameterizedTest(name = "{index}") @@ -2638,8 +2407,7 @@ void updateDocumentsOne(ArangoCollection collection) { final BaseDocument first = values.iterator().next(); first.addAttribute("a", "test"); updatedValues.add(first); - final MultiDocumentEntity> updateResult = collection - .updateDocuments(updatedValues, null); + final MultiDocumentEntity> updateResult = collection.updateDocuments(updatedValues, null); assertThat(updateResult.getDocuments()).hasSize(1); assertThat(updateResult.getErrors()).isEmpty(); } @@ -2648,8 +2416,7 @@ void updateDocumentsOne(ArangoCollection collection) { @MethodSource("cols") void updateDocumentsEmpty(ArangoCollection collection) { final Collection values = new ArrayList<>(); - final MultiDocumentEntity> updateResult = collection - .updateDocuments(values, null); + final MultiDocumentEntity> updateResult = collection.updateDocuments(values, null); assertThat(updateResult.getDocuments()).isEmpty(); assertThat(updateResult.getErrors()).isEmpty(); } @@ -2668,8 +2435,7 @@ void updateDocumentsWithoutKey(ArangoCollection collection) { updatedValues.add(i); } updatedValues.add(new BaseDocument()); - final MultiDocumentEntity> updateResult = collection - .updateDocuments(updatedValues, null); + final MultiDocumentEntity> updateResult = collection.updateDocuments(updatedValues, null); assertThat(updateResult.getDocuments()).hasSize(1); assertThat(updateResult.getErrors()).hasSize(1); } @@ -2685,8 +2451,7 @@ void updateDocumentsJson(ArangoCollection collection) { final Collection updatedValues = new ArrayList<>(); updatedValues.add("{\"_key\":\"1\", \"foo\":\"bar\"}"); updatedValues.add("{\"_key\":\"2\", \"foo\":\"bar\"}"); - final MultiDocumentEntity> updateResult = collection - .updateDocuments(updatedValues); + final MultiDocumentEntity> updateResult = collection.updateDocuments(updatedValues); assertThat(updateResult.getDocuments()).hasSize(2); assertThat(updateResult.getErrors()).isEmpty(); } @@ -2705,8 +2470,7 @@ void replaceDocuments(ArangoCollection collection) { i.addAttribute("a", "test"); updatedValues.add(i); } - final MultiDocumentEntity> updateResult = collection - .replaceDocuments(updatedValues, null); + final MultiDocumentEntity> updateResult = collection.replaceDocuments(updatedValues, null); assertThat(updateResult.getDocuments()).hasSize(2); assertThat(updateResult.getErrors()).isEmpty(); } @@ -2725,8 +2489,7 @@ void replaceDocumentsOne(ArangoCollection collection) { final BaseDocument first = values.iterator().next(); first.addAttribute("a", "test"); updatedValues.add(first); - final MultiDocumentEntity> updateResult = collection - .updateDocuments(updatedValues, null); + final MultiDocumentEntity> updateResult = collection.updateDocuments(updatedValues, null); assertThat(updateResult.getDocuments()).hasSize(1); assertThat(updateResult.getErrors()).isEmpty(); } @@ -2735,8 +2498,7 @@ void replaceDocumentsOne(ArangoCollection collection) { @MethodSource("cols") void replaceDocumentsEmpty(ArangoCollection collection) { final Collection values = new ArrayList<>(); - final MultiDocumentEntity> updateResult = collection - .updateDocuments(values, null); + final MultiDocumentEntity> updateResult = collection.updateDocuments(values, null); assertThat(updateResult.getDocuments()).isEmpty(); assertThat(updateResult.getErrors()).isEmpty(); } @@ -2755,8 +2517,7 @@ void replaceDocumentsWithoutKey(ArangoCollection collection) { updatedValues.add(i); } updatedValues.add(new BaseDocument()); - final MultiDocumentEntity> updateResult = collection - .updateDocuments(updatedValues, null); + final MultiDocumentEntity> updateResult = collection.updateDocuments(updatedValues, null); assertThat(updateResult.getDocuments()).hasSize(1); assertThat(updateResult.getErrors()).hasSize(1); } @@ -2772,8 +2533,7 @@ void replaceDocumentsJson(ArangoCollection collection) { final Collection updatedValues = new ArrayList<>(); updatedValues.add("{\"_key\":\"1\", \"foo\":\"bar\"}"); updatedValues.add("{\"_key\":\"2\", \"foo\":\"bar\"}"); - final MultiDocumentEntity> updateResult = collection - .replaceDocuments(updatedValues); + final MultiDocumentEntity> updateResult = collection.replaceDocuments(updatedValues); assertThat(updateResult.getDocuments()).hasSize(2); assertThat(updateResult.getErrors()).isEmpty(); } @@ -2802,23 +2562,10 @@ void changeProperties(ArangoCollection collection) { assertThat(properties.getSchema()).isNull(); } - String schemaRule = ("{ " + - " \"properties\": {" + - " \"number\": {" + - " \"type\": \"number\"" + - " }" + - " }" + - " }") - .replaceAll("\\s", ""); + String schemaRule = ("{ " + " \"properties\": {" + " \"number\": {" + " \"type\": \"number\"" + " }" + " }" + " }").replaceAll("\\s", ""); String schemaMessage = "The document has problems!"; - CollectionPropertiesOptions updatedOptions = new CollectionPropertiesOptions() - .waitForSync(!properties.getWaitForSync()) - .schema(new CollectionSchema() - .setLevel(CollectionSchema.Level.NEW) - .setMessage(schemaMessage) - .setRule(schemaRule) - ); + CollectionPropertiesOptions updatedOptions = new CollectionPropertiesOptions().waitForSync(!properties.getWaitForSync()).schema(new CollectionSchema().setLevel(CollectionSchema.Level.NEW).setMessage(schemaMessage).setRule(schemaRule)); final CollectionPropertiesEntity changedProperties = collection.changeProperties(updatedOptions); assertThat(changedProperties.getWaitForSync()).isNotNull(); @@ -2831,10 +2578,7 @@ void changeProperties(ArangoCollection collection) { } // revert changes - CollectionPropertiesEntity revertedProperties = collection.changeProperties(new CollectionPropertiesOptions() - .waitForSync(properties.getWaitForSync()) - .schema(CollectionSchema.NULL_SCHEMA) - ); + CollectionPropertiesEntity revertedProperties = collection.changeProperties(new CollectionPropertiesOptions().waitForSync(properties.getWaitForSync()).schema(CollectionSchema.NULL_SCHEMA)); if (isAtLeastVersion(3, 7)) { assertThat(revertedProperties.getSchema()).isNull(); } diff --git a/src/test/java/com/arangodb/ArangoDatabaseTest.java b/src/test/java/com/arangodb/ArangoDatabaseTest.java index da017d860..beb25d244 100644 --- a/src/test/java/com/arangodb/ArangoDatabaseTest.java +++ b/src/test/java/com/arangodb/ArangoDatabaseTest.java @@ -25,6 +25,7 @@ import com.arangodb.entity.QueryCachePropertiesEntity.CacheMode; import com.arangodb.model.*; import com.arangodb.util.MapBuilder; +import com.arangodb.util.RawJson; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.node.ArrayNode; import com.fasterxml.jackson.databind.node.JsonNodeFactory; @@ -1151,8 +1152,8 @@ void getGraphs(ArangoDatabase db) { @MethodSource("dbs") void transactionString(ArangoDatabase db) { final TransactionOptions options = new TransactionOptions().params("test"); - final String result = db.transaction("function (params) {return params;}", String.class, options); - assertThat(result).isEqualTo("\"test\""); + final RawJson result = db.transaction("function (params) {return params;}", RawJson.class, options); + assertThat(result.getValue()).isEqualTo("\"test\""); } @ParameterizedTest(name = "{index}") @@ -1177,9 +1178,9 @@ void transactionVPack(ArangoDatabase db) { void transactionJsonObject(ArangoDatabase db) { ObjectNode params = JsonNodeFactory.instance.objectNode().put("foo", "hello").put("bar", "world"); final TransactionOptions options = new TransactionOptions().params(params); - final String result = db - .transaction("function (params) { return params['foo'] + ' ' + params['bar'];}", String.class, options); - assertThat(result).isEqualTo("\"hello world\""); + final RawJson result = db + .transaction("function (params) { return params['foo'] + ' ' + params['bar'];}", RawJson.class, options); + assertThat(result.getValue()).isEqualTo("\"hello world\""); } @ParameterizedTest(name = "{index}") @@ -1187,9 +1188,9 @@ void transactionJsonObject(ArangoDatabase db) { void transactionJsonArray(ArangoDatabase db) { ArrayNode params = JsonNodeFactory.instance.arrayNode().add("hello").add("world"); final TransactionOptions options = new TransactionOptions().params(params); - final String result = db - .transaction("function (params) { return params[0] + ' ' + params[1];}", String.class, options); - assertThat(result).isEqualTo("\"hello world\""); + final RawJson result = db + .transaction("function (params) { return params[0] + ' ' + params[1];}", RawJson.class, options); + assertThat(result.getValue()).isEqualTo("\"hello world\""); } @ParameterizedTest(name = "{index}") @@ -1197,9 +1198,9 @@ void transactionJsonArray(ArangoDatabase db) { void transactionMap(ArangoDatabase db) { final Map params = new MapBuilder().put("foo", "hello").put("bar", "world").get(); final TransactionOptions options = new TransactionOptions().params(params); - final String result = db - .transaction("function (params) { return params['foo'] + ' ' + params['bar'];}", String.class, options); - assertThat(result).isEqualTo("\"hello world\""); + final RawJson result = db + .transaction("function (params) { return params['foo'] + ' ' + params['bar'];}", RawJson.class, options); + assertThat(result.getValue()).isEqualTo("\"hello world\""); } @ParameterizedTest(name = "{index}") @@ -1207,9 +1208,9 @@ void transactionMap(ArangoDatabase db) { void transactionArray(ArangoDatabase db) { final String[] params = new String[]{"hello", "world"}; final TransactionOptions options = new TransactionOptions().params(params); - final String result = db - .transaction("function (params) { return params[0] + ' ' + params[1];}", String.class, options); - assertThat(result).isEqualTo("\"hello world\""); + final RawJson result = db + .transaction("function (params) { return params[0] + ' ' + params[1];}", RawJson.class, options); + assertThat(result.getValue()).isEqualTo("\"hello world\""); } @ParameterizedTest(name = "{index}") @@ -1219,9 +1220,9 @@ void transactionCollection(ArangoDatabase db) { params.add("hello"); params.add("world"); final TransactionOptions options = new TransactionOptions().params(params); - final String result = db - .transaction("function (params) { return params[0] + ' ' + params[1];}", String.class, options); - assertThat(result).isEqualTo("\"hello world\""); + final RawJson result = db + .transaction("function (params) { return params[0] + ' ' + params[1];}", RawJson.class, options); + assertThat(result.getValue()).isEqualTo("\"hello world\""); } @ParameterizedTest(name = "{index}") @@ -1234,7 +1235,7 @@ void transactionInsertJson(ArangoDatabase db) { + "var db = require('internal').db;" + "db." + CNAME1 + ".save(JSON.parse(params));" + "}", Void.class, options); - assertThat(db.collection(CNAME1).getDocument(key, String.class)).isNotNull(); + assertThat(db.collection(CNAME1).getDocument(key, RawJson.class)).isNotNull(); } @ParameterizedTest(name = "{index}") @@ -1248,7 +1249,7 @@ void transactionExclusiveWrite(ArangoDatabase db) { + "var db = require('internal').db;" + "db." + CNAME1 + ".save(JSON.parse(params));" + "}", Void.class, options); - assertThat(db.collection(CNAME1).getDocument(key, String.class)).isNotNull(); + assertThat(db.collection(CNAME1).getDocument(key, RawJson.class)).isNotNull(); } @ParameterizedTest(name = "{index}") diff --git a/src/test/java/com/arangodb/ArangoVertexCollectionTest.java b/src/test/java/com/arangodb/ArangoVertexCollectionTest.java index 84283f19f..ed202b7dc 100644 --- a/src/test/java/com/arangodb/ArangoVertexCollectionTest.java +++ b/src/test/java/com/arangodb/ArangoVertexCollectionTest.java @@ -24,6 +24,7 @@ import com.arangodb.entity.VertexEntity; import com.arangodb.entity.VertexUpdateEntity; import com.arangodb.model.*; +import com.arangodb.util.RawJson; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; @@ -95,10 +96,10 @@ void insertVertexViolatingUniqueConstraint(ArangoVertexCollection vertices) { collection .ensureSkiplistIndex(Collections.singletonList("field"), new SkiplistIndexOptions().unique(true).sparse(true)); - VertexEntity inserted = vertices.insertVertex("{\"field\": 99}", null); + VertexEntity inserted = vertices.insertVertex(RawJson.of("{\"field\": 99}")); try { - vertices.insertVertex("{\"field\": 99}", null); + vertices.insertVertex(RawJson.of("{\"field\": 99}")); } catch (ArangoDBException e) { assertThat(e.getResponseCode()).isEqualTo(409); assertThat(e.getErrorNum()).isEqualTo(1210); diff --git a/src/test/java/com/arangodb/DocumentTest.java b/src/test/java/com/arangodb/DocumentTest.java index 327f07bb8..e9f471d41 100644 --- a/src/test/java/com/arangodb/DocumentTest.java +++ b/src/test/java/com/arangodb/DocumentTest.java @@ -22,6 +22,7 @@ import com.arangodb.entity.BaseDocument; import com.arangodb.entity.DocumentCreateEntity; +import com.arangodb.util.RawJson; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; @@ -59,7 +60,7 @@ static void init() { @MethodSource("cols") void insertAsJson(ArangoCollection collection) { //@formatter:off - final String json = + final RawJson json = RawJson.of( "{" + "\"article\": {" + "\"artist\": \"PREGARDIEN/RHEINISCHE KANTOREI/DAS\"," @@ -79,9 +80,10 @@ void insertAsJson(ArangoCollection collection) { + "\"status\": \"RMV\"," + "\"lastUpdate\": \"2016-11-01 00:00\"" + "}" - + "}"; + + "}" + ); //@formatter:on - final DocumentCreateEntity createResult = collection.insertDocument(json); + final DocumentCreateEntity createResult = collection.insertDocument(json); final BaseDocument doc = collection.getDocument(createResult.getKey(), BaseDocument.class); assertThat(doc).isNotNull(); final Object article = doc.getAttribute("article"); diff --git a/src/test/java/com/arangodb/async/ArangoCollectionTest.java b/src/test/java/com/arangodb/async/ArangoCollectionTest.java index d7dfbdec2..015a7a170 100644 --- a/src/test/java/com/arangodb/async/ArangoCollectionTest.java +++ b/src/test/java/com/arangodb/async/ArangoCollectionTest.java @@ -24,6 +24,7 @@ import com.arangodb.entity.*; import com.arangodb.model.*; import com.arangodb.model.DocumentImportOptions.OnDuplicate; +import com.arangodb.util.RawJson; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; @@ -120,7 +121,7 @@ void insertDocumentWaitForSync() throws InterruptedException, ExecutionException @Test void insertDocumentAsJson() throws InterruptedException, ExecutionException { db.collection(COLLECTION_NAME) - .insertDocument("{\"_key\":\"docRaw\",\"a\":\"test\"}", null) + .insertDocument(RawJson.of("{\"_key\":\"docRaw\",\"a\":\"test\"}"), null) .whenComplete((doc, ex) -> { assertThat(doc).isNotNull(); assertThat(doc.getId()).isNotNull(); @@ -195,11 +196,11 @@ void getDocumentIfNoneMatchFail() throws InterruptedException, ExecutionExceptio @Test void getDocumentAsJson() throws InterruptedException, ExecutionException { - db.collection(COLLECTION_NAME).insertDocument("{\"_key\":\"docRaw\",\"a\":\"test\"}", null).get(); - db.collection(COLLECTION_NAME).getDocument("docRaw", String.class, null) + db.collection(COLLECTION_NAME).insertDocument(RawJson.of("{\"_key\":\"docRaw\",\"a\":\"test\"}")).get(); + db.collection(COLLECTION_NAME).getDocument("docRaw", RawJson.class) .whenComplete((readResult, ex) -> { - assertThat(readResult.contains("\"_key\":\"docRaw\"")).isEqualTo(true); - assertThat(readResult.contains("\"_id\":\"db_collection_test/docRaw\"")).isEqualTo(true); + assertThat(readResult.getValue().contains("\"_key\":\"docRaw\"")).isEqualTo(true); + assertThat(readResult.getValue().contains("\"_id\":\"db_collection_test/docRaw\"")).isEqualTo(true); }) .get(); } @@ -1250,7 +1251,7 @@ void getCount() throws InterruptedException, ExecutionException { }) .get(); - db.collection(COLLECTION_NAME).insertDocument("{}", null).get(); + db.collection(COLLECTION_NAME).insertDocument(RawJson.of("{}"), null).get(); db.collection(COLLECTION_NAME).count() .whenComplete((count, ex) -> assertThat(count.getCount()).isEqualTo(1L)) @@ -1263,7 +1264,7 @@ void documentExists() throws InterruptedException, ExecutionException { .whenComplete((existsNot, ex) -> assertThat(existsNot).isEqualTo(false)) .get(); - db.collection(COLLECTION_NAME).insertDocument("{\"_key\":\"abc\"}", null).get(); + db.collection(COLLECTION_NAME).insertDocument(RawJson.of("{\"_key\":\"abc\"}")).get(); db.collection(COLLECTION_NAME).documentExists("abc", null) .whenComplete((exists, ex) -> assertThat(exists).isEqualTo(true)) @@ -1272,8 +1273,8 @@ void documentExists() throws InterruptedException, ExecutionException { @Test void documentExistsIfMatch() throws InterruptedException, ExecutionException { - final DocumentCreateEntity createResult = db.collection(COLLECTION_NAME) - .insertDocument("{\"_key\":\"abc\"}", null).get(); + final DocumentCreateEntity createResult = db.collection(COLLECTION_NAME) + .insertDocument(RawJson.of("{\"_key\":\"abc\"}")).get(); final DocumentExistsOptions options = new DocumentExistsOptions().ifMatch(createResult.getRev()); db.collection(COLLECTION_NAME).documentExists("abc", options) .whenComplete((exists, ex) -> assertThat(exists).isEqualTo(true)) @@ -1282,7 +1283,7 @@ void documentExistsIfMatch() throws InterruptedException, ExecutionException { @Test void documentExistsIfMatchFail() throws InterruptedException, ExecutionException { - db.collection(COLLECTION_NAME).insertDocument("{\"_key\":\"abc\"}", null).get(); + db.collection(COLLECTION_NAME).insertDocument(RawJson.of("{\"_key\":\"abc\"}")).get(); final DocumentExistsOptions options = new DocumentExistsOptions().ifMatch("no"); db.collection(COLLECTION_NAME).documentExists("abc", options) .whenComplete((exists, ex) -> assertThat(exists).isEqualTo(false)) @@ -1291,7 +1292,7 @@ void documentExistsIfMatchFail() throws InterruptedException, ExecutionException @Test void documentExistsIfNoneMatch() throws InterruptedException, ExecutionException { - db.collection(COLLECTION_NAME).insertDocument("{\"_key\":\"abc\"}", null).get(); + db.collection(COLLECTION_NAME).insertDocument(RawJson.of("{\"_key\":\"abc\"}")).get(); final DocumentExistsOptions options = new DocumentExistsOptions().ifNoneMatch("no"); db.collection(COLLECTION_NAME).documentExists("abc", options) .whenComplete((exists, ex) -> assertThat(exists).isEqualTo(true)) @@ -1300,8 +1301,8 @@ void documentExistsIfNoneMatch() throws InterruptedException, ExecutionException @Test void documentExistsIfNoneMatchFail() throws InterruptedException, ExecutionException { - final DocumentCreateEntity createResult = db.collection(COLLECTION_NAME) - .insertDocument("{\"_key\":\"abc\"}", null).get(); + final DocumentCreateEntity createResult = db.collection(COLLECTION_NAME) + .insertDocument(RawJson.of("{\"_key\":\"abc\"}")).get(); final DocumentExistsOptions options = new DocumentExistsOptions().ifNoneMatch(createResult.getRev()); db.collection(COLLECTION_NAME).documentExists("abc", options) .whenComplete((exists, ex) -> assertThat(exists).isEqualTo(false)) diff --git a/src/test/java/com/arangodb/async/ArangoDatabaseTest.java b/src/test/java/com/arangodb/async/ArangoDatabaseTest.java index 65513d2dc..565185563 100644 --- a/src/test/java/com/arangodb/async/ArangoDatabaseTest.java +++ b/src/test/java/com/arangodb/async/ArangoDatabaseTest.java @@ -27,6 +27,7 @@ import com.arangodb.entity.AqlParseEntity.AstNode; import com.arangodb.entity.QueryCachePropertiesEntity.CacheMode; import com.arangodb.model.*; +import com.arangodb.util.RawJson; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.node.JsonNodeFactory; import org.junit.jupiter.api.Disabled; @@ -874,8 +875,8 @@ void getGraphs() throws InterruptedException, ExecutionException { @Test void transactionString() throws InterruptedException, ExecutionException { final TransactionOptions options = new TransactionOptions().params("test"); - db.transaction("function (params) {return params;}", String.class, options) - .whenComplete((result, ex) -> assertThat(result).isEqualTo("\"test\"")) + db.transaction("function (params) {return params;}", RawJson.class, options) + .whenComplete((result, ex) -> assertThat(result.getValue()).isEqualTo("\"test\"")) .get(); } diff --git a/src/test/java/com/arangodb/async/example/document/GetDocumentExampleTest.java b/src/test/java/com/arangodb/async/example/document/GetDocumentExampleTest.java index 404422665..835017668 100644 --- a/src/test/java/com/arangodb/async/example/document/GetDocumentExampleTest.java +++ b/src/test/java/com/arangodb/async/example/document/GetDocumentExampleTest.java @@ -23,6 +23,7 @@ import com.arangodb.async.example.ExampleBase; import com.arangodb.entity.BaseDocument; import com.arangodb.entity.DocumentCreateEntity; +import com.arangodb.util.RawJson; import com.fasterxml.jackson.databind.JsonNode; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; @@ -82,11 +83,12 @@ void getAsVPack() throws InterruptedException, ExecutionException { @Test void getAsJson() throws InterruptedException, ExecutionException { - collection.getDocument(key, String.class) + collection.getDocument(key, RawJson.class) .whenComplete((doc, ex) -> { - assertThat(doc).isNotNull(); - assertThat(doc.contains("foo")).isEqualTo(true); - assertThat(doc.contains("bar")).isEqualTo(true); + assertThat(doc.getValue()) + .isNotNull() + .contains("foo") + .contains("bar"); }) .get(); } diff --git a/src/test/java/com/arangodb/async/example/document/InsertDocumentExampleTest.java b/src/test/java/com/arangodb/async/example/document/InsertDocumentExampleTest.java index cd5a4b889..be3a2a1da 100644 --- a/src/test/java/com/arangodb/async/example/document/InsertDocumentExampleTest.java +++ b/src/test/java/com/arangodb/async/example/document/InsertDocumentExampleTest.java @@ -22,6 +22,7 @@ import com.arangodb.async.example.ExampleBase; import com.arangodb.entity.BaseDocument; +import com.arangodb.util.RawJson; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.node.ObjectNode; import org.junit.jupiter.api.Test; @@ -64,7 +65,7 @@ void insertJsonNode() throws ExecutionException, InterruptedException { @Test void insertJson() throws ExecutionException, InterruptedException { - collection.insertDocument("{\"foo\":\"bar\"}") + collection.insertDocument(RawJson.of("{\"foo\":\"bar\"}")) .whenComplete((doc, ex) -> assertThat(doc.getKey()).isNotNull()) .get(); } diff --git a/src/test/java/com/arangodb/example/document/GetDocumentExampleTest.java b/src/test/java/com/arangodb/example/document/GetDocumentExampleTest.java index 50b8cceea..51cd6f9f3 100644 --- a/src/test/java/com/arangodb/example/document/GetDocumentExampleTest.java +++ b/src/test/java/com/arangodb/example/document/GetDocumentExampleTest.java @@ -23,6 +23,8 @@ import com.arangodb.entity.BaseDocument; import com.arangodb.entity.DocumentCreateEntity; import com.arangodb.example.ExampleBase; +import com.arangodb.util.RawBytes; +import com.arangodb.util.RawJson; import com.fasterxml.jackson.databind.JsonNode; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; @@ -81,10 +83,18 @@ void getAsJsonNode() { @Test void getAsJson() { - final String doc = collection.getDocument(key, String.class); - assertThat(doc).isNotNull(); - assertThat(doc).contains("foo"); - assertThat(doc).contains("bar"); + final RawJson doc = collection.getDocument(key, RawJson.class); + assertThat(doc.getValue()).isNotNull() + .contains("foo") + .contains("bar"); + } + + @Test + void getAsBytes() { + final RawBytes doc = collection.getDocument(key, RawBytes.class); + assertThat(doc.getValue()).isNotNull(); + Map mapDoc = collection.getSerde().deserializeUserData(doc.getValue(), Map.class); + assertThat(mapDoc).containsEntry("foo", "bar"); } } diff --git a/src/test/java/com/arangodb/example/document/InsertDocumentExampleTest.java b/src/test/java/com/arangodb/example/document/InsertDocumentExampleTest.java index fbe81d69f..e12949537 100644 --- a/src/test/java/com/arangodb/example/document/InsertDocumentExampleTest.java +++ b/src/test/java/com/arangodb/example/document/InsertDocumentExampleTest.java @@ -23,6 +23,7 @@ import com.arangodb.entity.BaseDocument; import com.arangodb.entity.DocumentCreateEntity; import com.arangodb.example.ExampleBase; +import com.arangodb.util.RawJson; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.node.ObjectNode; @@ -61,7 +62,7 @@ void insertJsonNode() { @Test void insertJson() { - final DocumentCreateEntity doc = collection.insertDocument("{\"foo\":\"bar\"}"); + final DocumentCreateEntity doc = collection.insertDocument(RawJson.of("{\"foo\":\"bar\"}")); assertThat(doc.getKey()).isNotNull(); } From 3f10d510cd92cb1c65b9c2ff7cfe24c07194dfa8 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Mon, 25 Jul 2022 13:49:03 +0200 Subject: [PATCH 045/254] @UserData and @UserDataInside annotations --- .../arangodb/entity/DocumentCreateEntity.java | 4 ++ .../arangodb/entity/DocumentDeleteEntity.java | 3 ++ .../arangodb/entity/DocumentUpdateEntity.java | 3 ++ .../internal/InternalArangoCollection.java | 28 +++--------- .../internal/InternalArangoDatabase.java | 7 ++- .../model/AqlQueryExplainOptions.java | 12 ++--- .../com/arangodb/model/AqlQueryOptions.java | 12 ++--- .../com/arangodb/model/OptionsBuilder.java | 5 ++- .../serde/InternalAnnotationIntrospector.java | 32 ++++++++++++++ .../com/arangodb/serde/InternalSerde.java | 9 ++++ .../com/arangodb/serde/InternalSerdeImpl.java | 15 ++++++- .../arangodb/serde/InternalSerializers.java | 11 ----- .../java/com/arangodb/serde/UserData.java | 14 ++++++ .../com/arangodb/serde/UserDataInside.java | 19 ++++++++ .../arangodb/serde/UserDataSerializer.java | 25 +++++++++++ .../com/arangodb/ArangoCollectionTest.java | 44 ++++++++++--------- .../java/com/arangodb/ArangoDatabaseTest.java | 20 +++++++-- 17 files changed, 187 insertions(+), 76 deletions(-) create mode 100644 src/main/java/com/arangodb/serde/InternalAnnotationIntrospector.java create mode 100644 src/main/java/com/arangodb/serde/UserData.java create mode 100644 src/main/java/com/arangodb/serde/UserDataInside.java create mode 100644 src/main/java/com/arangodb/serde/UserDataSerializer.java diff --git a/src/main/java/com/arangodb/entity/DocumentCreateEntity.java b/src/main/java/com/arangodb/entity/DocumentCreateEntity.java index 64c8a53af..e857c5179 100644 --- a/src/main/java/com/arangodb/entity/DocumentCreateEntity.java +++ b/src/main/java/com/arangodb/entity/DocumentCreateEntity.java @@ -20,6 +20,8 @@ package com.arangodb.entity; +import com.fasterxml.jackson.annotation.JsonIgnore; + /** * @author Mark Vollmary * @see API @@ -41,6 +43,7 @@ public T getNew() { return newDocument; } + @JsonIgnore public void setNew(final T newDocument) { this.newDocument = newDocument; } @@ -53,6 +56,7 @@ public T getOld() { return oldDocument; } + @JsonIgnore public void setOld(final T oldDocument) { this.oldDocument = oldDocument; } diff --git a/src/main/java/com/arangodb/entity/DocumentDeleteEntity.java b/src/main/java/com/arangodb/entity/DocumentDeleteEntity.java index 612494d66..7a91b6b95 100644 --- a/src/main/java/com/arangodb/entity/DocumentDeleteEntity.java +++ b/src/main/java/com/arangodb/entity/DocumentDeleteEntity.java @@ -20,6 +20,8 @@ package com.arangodb.entity; +import com.fasterxml.jackson.annotation.JsonIgnore; + /** * @author Mark Vollmary * @see API @@ -41,6 +43,7 @@ public T getOld() { return oldDocument; } + @JsonIgnore public void setOld(final T oldDocument) { this.oldDocument = oldDocument; } diff --git a/src/main/java/com/arangodb/entity/DocumentUpdateEntity.java b/src/main/java/com/arangodb/entity/DocumentUpdateEntity.java index 3567bd10e..593b62a90 100644 --- a/src/main/java/com/arangodb/entity/DocumentUpdateEntity.java +++ b/src/main/java/com/arangodb/entity/DocumentUpdateEntity.java @@ -20,6 +20,7 @@ package com.arangodb.entity; +import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonProperty; /** @@ -50,6 +51,7 @@ public T getNew() { return newDocument; } + @JsonIgnore public void setNew(final T newDocument) { this.newDocument = newDocument; } @@ -62,6 +64,7 @@ public T getOld() { return oldDocument; } + @JsonIgnore public void setOld(final T oldDocument) { this.oldDocument = oldDocument; } diff --git a/src/main/java/com/arangodb/internal/InternalArangoCollection.java b/src/main/java/com/arangodb/internal/InternalArangoCollection.java index 2016b4373..b9048da21 100644 --- a/src/main/java/com/arangodb/internal/InternalArangoCollection.java +++ b/src/main/java/com/arangodb/internal/InternalArangoCollection.java @@ -126,10 +126,7 @@ protected Request insertDocumentsRequest(final Collection values, final D request.putQueryParam(OVERWRITE_MODE, params.getOverwriteMode() != null ? params.getOverwriteMode().getValue() : null); request.putQueryParam(MERGE_OBJECTS, params.getMergeObjects()); request.putHeaderParam(TRANSACTION_ID, params.getStreamTransactionId()); - - byte[] body = isStringCollection(values) ? getSerde().serialize(stringCollectionToJsonArray((Collection) values)) - : getSerde().serializeUserData(values); - request.setBody(body); + request.setBody(getSerde().serializeCollectionUserData(values)); return request; } @@ -181,9 +178,8 @@ protected Request importDocumentsRequest(final String values, final DocumentImpo } protected Request importDocumentsRequest(final Collection values, final DocumentImportOptions options) { - byte[] body = isStringCollection(values) ? getSerde().serialize(stringCollectionToJsonArray((Collection) values)) - : getSerde().serializeUserData(values); - return importDocumentsRequest(options).putQueryParam("type", ImportType.list).setBody(body); + return importDocumentsRequest(options).putQueryParam("type", ImportType.list) + .setBody(getSerde().serializeCollectionUserData(values)); } protected Request importDocumentsRequest(final DocumentImportOptions options) { @@ -301,10 +297,7 @@ protected Request replaceDocumentsRequest(final Collection values, final request.putQueryParam(RETURN_NEW, params.getReturnNew()); request.putQueryParam(RETURN_OLD, params.getReturnOld()); request.putQueryParam(SILENT, params.getSilent()); - - byte[] body = isStringCollection(values) ? getSerde().serialize(stringCollectionToJsonArray((Collection) values)) - : getSerde().serializeUserData(values); - request.setBody(body); + request.setBody(getSerde().serializeCollectionUserData(values)); return request; } @@ -402,10 +395,7 @@ protected Request updateDocumentsRequest(final Collection values, final D request.putQueryParam(RETURN_NEW, params.getReturnNew()); request.putQueryParam(RETURN_OLD, params.getReturnOld()); request.putQueryParam(SILENT, params.getSilent()); - - byte[] body = isStringCollection(values) ? getSerde().serialize(stringCollectionToJsonArray((Collection) values)) - : getSerde().serializeUserData(values); - request.setBody(body); + request.setBody(getSerde().serializeCollectionUserData(values)); return request; } @@ -686,12 +676,4 @@ protected ResponseDeserializer getPermissionsResponseDeserialzer() return response -> getSerde().deserialize(response.getBody(), ArangoResponseField.RESULT_JSON_POINTER, Permissions.class); } - private boolean isStringCollection(final Collection values) { - return values.stream().allMatch(String.class::isInstance); - } - - private JsonNode stringCollectionToJsonArray(final Collection values) { - return SerdeUtils.INSTANCE.parseJson("[" + String.join(",", values) + "]"); - } - } diff --git a/src/main/java/com/arangodb/internal/InternalArangoDatabase.java b/src/main/java/com/arangodb/internal/InternalArangoDatabase.java index 9a8761600..2f36609cb 100644 --- a/src/main/java/com/arangodb/internal/InternalArangoDatabase.java +++ b/src/main/java/com/arangodb/internal/InternalArangoDatabase.java @@ -144,8 +144,8 @@ protected ResponseDeserializer getPermissionsResponseDeserialzer() protected Request queryRequest(final String query, final Map bindVars, final AqlQueryOptions options) { final AqlQueryOptions opt = options != null ? options : new AqlQueryOptions(); - final Request request = request(dbName, RequestType.POST, PATH_API_CURSOR).setBody(getSerde().serialize( - OptionsBuilder.build(opt, query, bindVars != null ? getSerde().serializeUserData(bindVars) : null))); + final Request request = request(dbName, RequestType.POST, PATH_API_CURSOR) + .setBody(getSerde().serialize(OptionsBuilder.build(opt, query, bindVars))); if (opt.getAllowDirtyRead() == Boolean.TRUE) { RequestUtils.allowDirtyRead(request); } @@ -190,8 +190,7 @@ protected Request queryCloseRequest(final String id, final AqlQueryOptions optio protected Request explainQueryRequest(final String query, final Map bindVars, final AqlQueryExplainOptions options) { final AqlQueryExplainOptions opt = options != null ? options : new AqlQueryExplainOptions(); return request(dbName, RequestType.POST, PATH_API_EXPLAIN) - .setBody(getSerde().serialize( - OptionsBuilder.build(opt, query, bindVars != null ? getSerde().serializeUserData(bindVars) : null))); + .setBody(getSerde().serialize(OptionsBuilder.build(opt, query, bindVars))); } protected Request parseQueryRequest(final String query) { diff --git a/src/main/java/com/arangodb/model/AqlQueryExplainOptions.java b/src/main/java/com/arangodb/model/AqlQueryExplainOptions.java index 45cb189a6..7a1b9b448 100644 --- a/src/main/java/com/arangodb/model/AqlQueryExplainOptions.java +++ b/src/main/java/com/arangodb/model/AqlQueryExplainOptions.java @@ -20,10 +20,10 @@ package com.arangodb.model; -import com.arangodb.serde.InternalSerializers; -import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.arangodb.serde.UserDataInside; import java.util.Collection; +import java.util.Map; /** * @author Mark Vollmary @@ -32,7 +32,7 @@ */ public final class AqlQueryExplainOptions { - private byte[] bindVars; + private Map bindVars; private String query; private Options options; @@ -40,8 +40,8 @@ public AqlQueryExplainOptions() { super(); } - @JsonSerialize(using = InternalSerializers.AqlBindVarsSerializer.class) - public byte[] getBindVars() { + @UserDataInside + public Map getBindVars() { return bindVars; } @@ -49,7 +49,7 @@ public byte[] getBindVars() { * @param bindVars key/value pairs representing the bind parameters * @return options */ - AqlQueryExplainOptions bindVars(final byte[] bindVars) { + AqlQueryExplainOptions bindVars(final Map bindVars) { this.bindVars = bindVars; return this; } diff --git a/src/main/java/com/arangodb/model/AqlQueryOptions.java b/src/main/java/com/arangodb/model/AqlQueryOptions.java index 7d646b700..dd85a40b1 100644 --- a/src/main/java/com/arangodb/model/AqlQueryOptions.java +++ b/src/main/java/com/arangodb/model/AqlQueryOptions.java @@ -20,12 +20,12 @@ package com.arangodb.model; -import com.arangodb.serde.InternalSerializers; -import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.arangodb.serde.UserDataInside; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; +import java.util.Map; /** * @author Mark Vollmary @@ -40,7 +40,7 @@ public final class AqlQueryOptions { private Integer batchSize; private Boolean cache; private Long memoryLimit; - private byte[] bindVars; + private Map bindVars; private String query; private Options options; private Boolean allowDirtyRead; @@ -147,8 +147,8 @@ public AqlQueryOptions fillBlockCache(final Boolean fillBlockCache) { return this; } - @JsonSerialize(using = InternalSerializers.AqlBindVarsSerializer.class) - public byte[] getBindVars() { + @UserDataInside + public Map getBindVars() { return bindVars; } @@ -156,7 +156,7 @@ public byte[] getBindVars() { * @param bindVarsBytes serialized bind parameters * @return options */ - AqlQueryOptions bindVars(final byte[] bindVarsBytes) { + AqlQueryOptions bindVars(final Map bindVarsBytes) { this.bindVars = bindVarsBytes; return this; } diff --git a/src/main/java/com/arangodb/model/OptionsBuilder.java b/src/main/java/com/arangodb/model/OptionsBuilder.java index 6bf13ae4e..f62a45d19 100644 --- a/src/main/java/com/arangodb/model/OptionsBuilder.java +++ b/src/main/java/com/arangodb/model/OptionsBuilder.java @@ -25,6 +25,7 @@ import com.arangodb.entity.ViewType; import java.util.Collection; +import java.util.Map; /** * @author Mark Vollmary @@ -82,14 +83,14 @@ public static CollectionCreateOptions build(final CollectionCreateOptions option return options.name(name); } - public static AqlQueryOptions build(final AqlQueryOptions options, final String query, final byte[] bindVars) { + public static AqlQueryOptions build(final AqlQueryOptions options, final String query, final Map bindVars) { return options.query(query).bindVars(bindVars); } public static AqlQueryExplainOptions build( final AqlQueryExplainOptions options, final String query, - final byte[] bindVars) { + final Map bindVars) { return options.query(query).bindVars(bindVars); } diff --git a/src/main/java/com/arangodb/serde/InternalAnnotationIntrospector.java b/src/main/java/com/arangodb/serde/InternalAnnotationIntrospector.java new file mode 100644 index 000000000..92b1e2fdd --- /dev/null +++ b/src/main/java/com/arangodb/serde/InternalAnnotationIntrospector.java @@ -0,0 +1,32 @@ +package com.arangodb.serde; + +import com.fasterxml.jackson.databind.introspect.Annotated; +import com.fasterxml.jackson.databind.introspect.JacksonAnnotationIntrospector; + +class InternalAnnotationIntrospector extends JacksonAnnotationIntrospector { + + private final UserDataSerializer userDataSerializer; + + InternalAnnotationIntrospector(final UserDataSerializer userDataSerializer) { + this.userDataSerializer = userDataSerializer; + } + + @Override + public Object findSerializer(Annotated a) { + if (a.getAnnotation(UserData.class) != null) { + return userDataSerializer; + } else { + return super.findSerializer(a); + } + } + + @Override + public Object findContentSerializer(Annotated a) { + if (a.getAnnotation(UserDataInside.class) != null) { + return userDataSerializer; + } else { + return super.findContentSerializer(a); + } + } + +} diff --git a/src/main/java/com/arangodb/serde/InternalSerde.java b/src/main/java/com/arangodb/serde/InternalSerde.java index be850da3f..04215e6ee 100644 --- a/src/main/java/com/arangodb/serde/InternalSerde.java +++ b/src/main/java/com/arangodb/serde/InternalSerde.java @@ -5,6 +5,7 @@ import com.fasterxml.jackson.databind.ObjectMapper; import java.lang.reflect.Type; +import java.util.Collection; public interface InternalSerde extends JacksonSerde { @@ -113,6 +114,14 @@ default T deserialize(byte[] content, String jsonPointer, Type type) { */ byte[] serializeUserData(Object value); + /** + * Serializes each element in the collection using the user serde. + * + * @param value objects to serialize + * @return serialized byte array + */ + byte[] serializeCollectionUserData(Collection value); + /** * Deserializes the content and binds it to the target data type, using the user serde. * diff --git a/src/main/java/com/arangodb/serde/InternalSerdeImpl.java b/src/main/java/com/arangodb/serde/InternalSerdeImpl.java index d321f3743..f27f7164b 100644 --- a/src/main/java/com/arangodb/serde/InternalSerdeImpl.java +++ b/src/main/java/com/arangodb/serde/InternalSerdeImpl.java @@ -9,6 +9,9 @@ import java.io.IOException; import java.lang.reflect.Type; +import java.util.Collection; +import java.util.List; +import java.util.stream.Collectors; final class InternalSerdeImpl extends JacksonSerdeImpl implements InternalSerde { @@ -19,6 +22,7 @@ final class InternalSerdeImpl extends JacksonSerdeImpl implements InternalSerde this.userSerde = userSerde; mapper.registerModule(InternalModule.INSTANCE.get()); mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); + mapper.setAnnotationIntrospector(new InternalAnnotationIntrospector(new UserDataSerializer(this))); } @Override @@ -60,13 +64,22 @@ public JsonNode parse(byte[] content, String jsonPointer) { @Override public byte[] serializeUserData(Object value) { - if (RawJson.class.equals(value.getClass()) || RawBytes.class.equals(value.getClass())) { + if (value != null && (RawJson.class.equals(value.getClass()) || RawBytes.class.equals(value.getClass()))) { return serialize(value); } else { return userSerde.serialize(value); } } + @Override + public byte[] serializeCollectionUserData(Collection value) { + List jsonNodeCollection = value.stream() + .map(this::serializeUserData) + .map(this::parse) + .collect(Collectors.toList()); + return serialize(jsonNodeCollection); + } + @Override public T deserializeUserData(byte[] content, Type type) { if (RawJson.class.equals(type) || RawBytes.class.equals(type)) { diff --git a/src/main/java/com/arangodb/serde/InternalSerializers.java b/src/main/java/com/arangodb/serde/InternalSerializers.java index 6d951e2d5..454b1a4bc 100644 --- a/src/main/java/com/arangodb/serde/InternalSerializers.java +++ b/src/main/java/com/arangodb/serde/InternalSerializers.java @@ -20,17 +20,6 @@ public final class InternalSerializers { - public static class AqlBindVarsSerializer extends JsonSerializer { - @Override - public void serialize(byte[] value, JsonGenerator gen, SerializerProvider serializers) throws IOException { - // TODO: find a way to append raw bytes directly - // see https://github.com/FasterXML/jackson-dataformats-binary/issues/331 - try (JsonParser parser = gen.getCodec().getFactory().createParser(value)) { - gen.writeTree(parser.readValueAsTree()); - } - } - } - public static class CollectionSchemaRuleSerializer extends JsonSerializer { @Override public void serialize(String value, JsonGenerator gen, SerializerProvider serializers) throws IOException { diff --git a/src/main/java/com/arangodb/serde/UserData.java b/src/main/java/com/arangodb/serde/UserData.java new file mode 100644 index 000000000..8e53d2048 --- /dev/null +++ b/src/main/java/com/arangodb/serde/UserData.java @@ -0,0 +1,14 @@ +package com.arangodb.serde; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Marker annotation for fields that need to be serialized/deserialized using the user serde. + */ +@Target({ElementType.METHOD, ElementType.FIELD}) +@Retention(RetentionPolicy.RUNTIME) +public @interface UserData { +} diff --git a/src/main/java/com/arangodb/serde/UserDataInside.java b/src/main/java/com/arangodb/serde/UserDataInside.java new file mode 100644 index 000000000..6e03165f5 --- /dev/null +++ b/src/main/java/com/arangodb/serde/UserDataInside.java @@ -0,0 +1,19 @@ +package com.arangodb.serde; + +import com.fasterxml.jackson.annotation.JacksonAnnotationsInside; +import com.fasterxml.jackson.annotation.JsonInclude; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Marker annotation for collections or map fields whose values need to be serialized/deserialized using the user serde. + */ +@Target({ElementType.METHOD, ElementType.FIELD}) +@Retention(RetentionPolicy.RUNTIME) +@JsonInclude(value = JsonInclude.Include.NON_NULL) +@JacksonAnnotationsInside +public @interface UserDataInside { +} diff --git a/src/main/java/com/arangodb/serde/UserDataSerializer.java b/src/main/java/com/arangodb/serde/UserDataSerializer.java new file mode 100644 index 000000000..9f3067db9 --- /dev/null +++ b/src/main/java/com/arangodb/serde/UserDataSerializer.java @@ -0,0 +1,25 @@ +package com.arangodb.serde; + +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.databind.JsonSerializer; +import com.fasterxml.jackson.databind.SerializerProvider; + +import java.io.IOException; + +class UserDataSerializer extends JsonSerializer { + private final InternalSerde serde; + + UserDataSerializer(InternalSerde serde) { + this.serde = serde; + } + + @Override + public void serialize(Object value, JsonGenerator gen, SerializerProvider serializers) throws IOException { + // TODO: find a way to append raw bytes directly + // see https://github.com/FasterXML/jackson-dataformats-binary/issues/331 + try (JsonParser parser = gen.getCodec().getFactory().createParser(serde.serializeUserData(value))) { + gen.writeTree(parser.readValueAsTree()); + } + } +} diff --git a/src/test/java/com/arangodb/ArangoCollectionTest.java b/src/test/java/com/arangodb/ArangoCollectionTest.java index a23f182af..843bd6c18 100644 --- a/src/test/java/com/arangodb/ArangoCollectionTest.java +++ b/src/test/java/com/arangodb/ArangoCollectionTest.java @@ -1774,11 +1774,11 @@ void insertDocumentsOverwriteModeUpdate(ArangoCollection collection) { @ParameterizedTest(name = "{index}") @MethodSource("cols") void insertDocumentsJson(ArangoCollection collection) { - final Collection values = new ArrayList<>(); - values.add("{}"); - values.add("{}"); - values.add("{}"); - final MultiDocumentEntity> docs = collection.insertDocuments(values); + final Collection values = new ArrayList<>(); + values.add(RawJson.of("{}")); + values.add(RawJson.of("{}")); + values.add(RawJson.of("{}")); + final MultiDocumentEntity> docs = collection.insertDocuments(values); assertThat(docs).isNotNull(); assertThat(docs.getDocuments()).isNotNull(); assertThat(docs.getDocuments()).hasSize(3); @@ -1867,7 +1867,11 @@ void importDocuments(ArangoCollection collection) { @ParameterizedTest(name = "{index}") @MethodSource("cols") void importDocumentsJsonList(ArangoCollection collection) { - final Collection values = Arrays.asList("{}", "{}", "{}"); + final Collection values = Arrays.asList( + RawJson.of("{}"), + RawJson.of("{}"), + RawJson.of("{}") + ); final DocumentImportEntity docs = collection.importDocuments(values); assertThat(docs).isNotNull(); @@ -2443,15 +2447,15 @@ void updateDocumentsWithoutKey(ArangoCollection collection) { @ParameterizedTest(name = "{index}") @MethodSource("cols") void updateDocumentsJson(ArangoCollection collection) { - final Collection values = new ArrayList<>(); - values.add("{\"_key\":\"1\"}"); - values.add("{\"_key\":\"2\"}"); + final Collection values = new ArrayList<>(); + values.add(RawJson.of("{\"_key\":\"1\"}")); + values.add(RawJson.of("{\"_key\":\"2\"}")); collection.insertDocuments(values); - final Collection updatedValues = new ArrayList<>(); - updatedValues.add("{\"_key\":\"1\", \"foo\":\"bar\"}"); - updatedValues.add("{\"_key\":\"2\", \"foo\":\"bar\"}"); - final MultiDocumentEntity> updateResult = collection.updateDocuments(updatedValues); + final Collection updatedValues = new ArrayList<>(); + updatedValues.add(RawJson.of("{\"_key\":\"1\", \"foo\":\"bar\"}")); + updatedValues.add(RawJson.of("{\"_key\":\"2\", \"foo\":\"bar\"}")); + final MultiDocumentEntity> updateResult = collection.updateDocuments(updatedValues); assertThat(updateResult.getDocuments()).hasSize(2); assertThat(updateResult.getErrors()).isEmpty(); } @@ -2525,15 +2529,15 @@ void replaceDocumentsWithoutKey(ArangoCollection collection) { @ParameterizedTest(name = "{index}") @MethodSource("cols") void replaceDocumentsJson(ArangoCollection collection) { - final Collection values = new ArrayList<>(); - values.add("{\"_key\":\"1\"}"); - values.add("{\"_key\":\"2\"}"); + final Collection values = new ArrayList<>(); + values.add(RawJson.of("{\"_key\":\"1\"}")); + values.add(RawJson.of("{\"_key\":\"2\"}")); collection.insertDocuments(values); - final Collection updatedValues = new ArrayList<>(); - updatedValues.add("{\"_key\":\"1\", \"foo\":\"bar\"}"); - updatedValues.add("{\"_key\":\"2\", \"foo\":\"bar\"}"); - final MultiDocumentEntity> updateResult = collection.replaceDocuments(updatedValues); + final Collection updatedValues = new ArrayList<>(); + updatedValues.add(RawJson.of("{\"_key\":\"1\", \"foo\":\"bar\"}")); + updatedValues.add(RawJson.of("{\"_key\":\"2\", \"foo\":\"bar\"}")); + final MultiDocumentEntity> updateResult = collection.replaceDocuments(updatedValues); assertThat(updateResult.getDocuments()).hasSize(2); assertThat(updateResult.getErrors()).isEmpty(); } diff --git a/src/test/java/com/arangodb/ArangoDatabaseTest.java b/src/test/java/com/arangodb/ArangoDatabaseTest.java index beb25d244..1e4054984 100644 --- a/src/test/java/com/arangodb/ArangoDatabaseTest.java +++ b/src/test/java/com/arangodb/ArangoDatabaseTest.java @@ -25,6 +25,7 @@ import com.arangodb.entity.QueryCachePropertiesEntity.CacheMode; import com.arangodb.model.*; import com.arangodb.util.MapBuilder; +import com.arangodb.util.RawBytes; import com.arangodb.util.RawJson; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.node.ArrayNode; @@ -826,6 +827,19 @@ void queryWithBindVars(ArangoDatabase db) { } } + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void queryWithRawBindVars(ArangoDatabase db) { + final Map bindVars = new HashMap<>(); + bindVars.put("foo", RawJson.of("\"fooValue\"")); + bindVars.put("bar", RawBytes.of(db.getSerde().serializeUserData(11))); + + final JsonNode res = db.query("RETURN {foo: @foo, bar: @bar}", bindVars, null,JsonNode.class).next(); + + assertThat(res.get("foo").textValue()).isEqualTo("fooValue"); + assertThat(res.get("bar").intValue()).isEqualTo(11); + } + @ParameterizedTest(name = "{index}") @MethodSource("arangos") void queryWithWarning(ArangoDB arangoDB) { @@ -1166,7 +1180,7 @@ void transactionNumber(ArangoDatabase db) { @ParameterizedTest(name = "{index}") @MethodSource("dbs") - void transactionVPack(ArangoDatabase db) { + void transactionVPack(ArangoDatabase db) { final TransactionOptions options = new TransactionOptions().params(JsonNodeFactory.instance.textNode("test")); final JsonNode result = db.transaction("function (params) {return params;}", JsonNode.class, options); assertThat(result.isTextual()).isTrue(); @@ -1175,7 +1189,7 @@ void transactionVPack(ArangoDatabase db) { @ParameterizedTest(name = "{index}") @MethodSource("dbs") - void transactionJsonObject(ArangoDatabase db) { + void transactionJsonObject(ArangoDatabase db) { ObjectNode params = JsonNodeFactory.instance.objectNode().put("foo", "hello").put("bar", "world"); final TransactionOptions options = new TransactionOptions().params(params); final RawJson result = db @@ -1185,7 +1199,7 @@ void transactionJsonObject(ArangoDatabase db) { @ParameterizedTest(name = "{index}") @MethodSource("dbs") - void transactionJsonArray(ArangoDatabase db) { + void transactionJsonArray(ArangoDatabase db) { ArrayNode params = JsonNodeFactory.instance.arrayNode().add("hello").add("world"); final TransactionOptions options = new TransactionOptions().params(params); final RawJson result = db From 1143b8d57375f79b6d018741f4158eb3fe849ba9 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Tue, 26 Jul 2022 13:46:09 +0200 Subject: [PATCH 046/254] @UserData and @UserDataInside deserialization --- .../arangodb/entity/DocumentCreateEntity.java | 6 +- .../arangodb/entity/DocumentDeleteEntity.java | 4 +- .../arangodb/entity/DocumentUpdateEntity.java | 6 +- .../internal/InternalArangoCollection.java | 118 +++++------------- .../serde/InternalAnnotationIntrospector.java | 25 +++- .../serde/InternalParameterizedType.java | 31 +++++ .../com/arangodb/serde/InternalSerdeImpl.java | 5 +- .../java/com/arangodb/serde/SerdeUtils.java | 19 +++ .../arangodb/serde/UserDataDeserializer.java | 42 +++++++ 9 files changed, 160 insertions(+), 96 deletions(-) create mode 100644 src/main/java/com/arangodb/serde/InternalParameterizedType.java create mode 100644 src/main/java/com/arangodb/serde/UserDataDeserializer.java diff --git a/src/main/java/com/arangodb/entity/DocumentCreateEntity.java b/src/main/java/com/arangodb/entity/DocumentCreateEntity.java index e857c5179..c2d07bc8c 100644 --- a/src/main/java/com/arangodb/entity/DocumentCreateEntity.java +++ b/src/main/java/com/arangodb/entity/DocumentCreateEntity.java @@ -20,7 +20,7 @@ package com.arangodb.entity; -import com.fasterxml.jackson.annotation.JsonIgnore; +import com.arangodb.serde.UserData; /** * @author Mark Vollmary @@ -43,7 +43,7 @@ public T getNew() { return newDocument; } - @JsonIgnore + @UserData public void setNew(final T newDocument) { this.newDocument = newDocument; } @@ -56,7 +56,7 @@ public T getOld() { return oldDocument; } - @JsonIgnore + @UserData public void setOld(final T oldDocument) { this.oldDocument = oldDocument; } diff --git a/src/main/java/com/arangodb/entity/DocumentDeleteEntity.java b/src/main/java/com/arangodb/entity/DocumentDeleteEntity.java index 7a91b6b95..46fa34c56 100644 --- a/src/main/java/com/arangodb/entity/DocumentDeleteEntity.java +++ b/src/main/java/com/arangodb/entity/DocumentDeleteEntity.java @@ -20,7 +20,7 @@ package com.arangodb.entity; -import com.fasterxml.jackson.annotation.JsonIgnore; +import com.arangodb.serde.UserData; /** * @author Mark Vollmary @@ -43,7 +43,7 @@ public T getOld() { return oldDocument; } - @JsonIgnore + @UserData public void setOld(final T oldDocument) { this.oldDocument = oldDocument; } diff --git a/src/main/java/com/arangodb/entity/DocumentUpdateEntity.java b/src/main/java/com/arangodb/entity/DocumentUpdateEntity.java index 593b62a90..61b9b1f62 100644 --- a/src/main/java/com/arangodb/entity/DocumentUpdateEntity.java +++ b/src/main/java/com/arangodb/entity/DocumentUpdateEntity.java @@ -20,7 +20,7 @@ package com.arangodb.entity; -import com.fasterxml.jackson.annotation.JsonIgnore; +import com.arangodb.serde.UserData; import com.fasterxml.jackson.annotation.JsonProperty; /** @@ -51,7 +51,7 @@ public T getNew() { return newDocument; } - @JsonIgnore + @UserData public void setNew(final T newDocument) { this.newDocument = newDocument; } @@ -64,7 +64,7 @@ public T getOld() { return oldDocument; } - @JsonIgnore + @UserData public void setOld(final T oldDocument) { this.oldDocument = oldDocument; } diff --git a/src/main/java/com/arangodb/internal/InternalArangoCollection.java b/src/main/java/com/arangodb/internal/InternalArangoCollection.java index b9048da21..3bfd2d792 100644 --- a/src/main/java/com/arangodb/internal/InternalArangoCollection.java +++ b/src/main/java/com/arangodb/internal/InternalArangoCollection.java @@ -32,6 +32,7 @@ import com.arangodb.velocystream.RequestType; import com.fasterxml.jackson.databind.JsonNode; +import java.lang.reflect.Type; import java.util.*; /** @@ -96,16 +97,8 @@ protected ResponseDeserializer> insertDocumentRespon final T value, final DocumentCreateOptions options) { return response -> { final JsonNode body = getSerde().parse(response.getBody()); - final DocumentCreateEntity doc = getSerde().deserialize(body, DocumentCreateEntity.class); - final JsonNode newDoc = body.get(NEW); - Class clazz = (Class) value.getClass(); - if (newDoc != null) { - doc.setNew(getSerde().deserializeUserData(newDoc, clazz)); - } - final JsonNode oldDoc = body.get(OLD); - if (oldDoc != null) { - doc.setOld(getSerde().deserializeUserData(oldDoc, clazz)); - } + Type type = SerdeUtils.INSTANCE.constructParametricType(DocumentCreateEntity.class, value.getClass()); + final DocumentCreateEntity doc = getSerde().deserialize(body, type); if (options == null || Boolean.TRUE != options.getSilent()) { final Map values = new HashMap<>(); values.put(DocumentFields.ID, doc.getId()); @@ -130,16 +123,10 @@ protected Request insertDocumentsRequest(final Collection values, final D return request; } - @SuppressWarnings("unchecked") protected ResponseDeserializer>> insertDocumentsResponseDeserializer( final Collection values, final DocumentCreateOptions params) { return response -> { - Class type = null; - if (Boolean.TRUE == params.getReturnNew()) { - if (!values.isEmpty()) { - type = (Class) values.iterator().next().getClass(); - } - } + Class userDataClass = getCollectionContentClass(values); final MultiDocumentEntity> multiDocument = new MultiDocumentEntity<>(); final Collection> docs = new ArrayList<>(); final Collection errors = new ArrayList<>(); @@ -153,15 +140,8 @@ protected ResponseDeserializer>> errors.add(error); documentsAndErrors.add(error); } else { - final DocumentCreateEntity doc = getSerde().deserialize(next, DocumentCreateEntity.class); - final JsonNode newDoc = next.get(NEW); - if (newDoc != null) { - doc.setNew(getSerde().deserializeUserData(getSerde().serialize(newDoc), type)); - } - final JsonNode oldDoc = next.get(OLD); - if (oldDoc != null) { - doc.setOld(getSerde().deserializeUserData(getSerde().serialize(oldDoc), type)); - } + Type type = SerdeUtils.INSTANCE.constructParametricType(DocumentCreateEntity.class, userDataClass); + final DocumentCreateEntity doc = getSerde().deserialize(next, type); docs.add(doc); documentsAndErrors.add(doc); } @@ -269,16 +249,8 @@ protected ResponseDeserializer> replaceDocumentRespo final T value, final DocumentReplaceOptions options) { return response -> { final JsonNode body = getSerde().parse(response.getBody()); - final DocumentUpdateEntity doc = getSerde().deserialize(body, DocumentUpdateEntity.class); - final JsonNode newDoc = body.get(NEW); - Class clazz = (Class) value.getClass(); - if (newDoc != null) { - doc.setNew(getSerde().deserializeUserData(getSerde().serialize(newDoc), clazz)); - } - final JsonNode oldDoc = body.get(OLD); - if (oldDoc != null) { - doc.setOld(getSerde().deserializeUserData(getSerde().serialize(oldDoc), clazz)); - } + Type type = SerdeUtils.INSTANCE.constructParametricType(DocumentUpdateEntity.class, value.getClass()); + final DocumentUpdateEntity doc = getSerde().deserialize(body, type); if (options == null || Boolean.TRUE != options.getSilent()) { final Map values = new HashMap<>(); values.put(DocumentFields.REV, doc.getRev()); @@ -301,16 +273,10 @@ protected Request replaceDocumentsRequest(final Collection values, final return request; } - @SuppressWarnings("unchecked") protected ResponseDeserializer>> replaceDocumentsResponseDeserializer( final Collection values, final DocumentReplaceOptions params) { return response -> { - Class type = null; - if (Boolean.TRUE == params.getReturnNew() || Boolean.TRUE == params.getReturnOld()) { - if (!values.isEmpty()) { - type = (Class) values.iterator().next().getClass(); - } - } + Class userDataClass = getCollectionContentClass(values); final MultiDocumentEntity> multiDocument = new MultiDocumentEntity<>(); final Collection> docs = new ArrayList<>(); final Collection errors = new ArrayList<>(); @@ -324,15 +290,8 @@ protected ResponseDeserializer>> errors.add(error); documentsAndErrors.add(error); } else { - final DocumentUpdateEntity doc = getSerde().deserialize(next, DocumentUpdateEntity.class); - final JsonNode newDoc = next.get(NEW); - if (newDoc != null) { - doc.setNew(getSerde().deserializeUserData(getSerde().serialize(newDoc), type)); - } - final JsonNode oldDoc = next.get(OLD); - if (oldDoc != null) { - doc.setOld(getSerde().deserializeUserData(getSerde().serialize(oldDoc), type)); - } + Type type = SerdeUtils.INSTANCE.constructParametricType(DocumentUpdateEntity.class, userDataClass); + final DocumentUpdateEntity doc = getSerde().deserialize(next, type); docs.add(doc); documentsAndErrors.add(doc); } @@ -364,16 +323,8 @@ protected Request updateDocumentRequest(final String key, final T value, fin protected ResponseDeserializer> updateDocumentResponseDeserializer( final T value, final DocumentUpdateOptions options, final Class returnType) { return response -> { - final JsonNode body = getSerde().parse(response.getBody()); - final DocumentUpdateEntity doc = getSerde().deserialize(body, DocumentUpdateEntity.class); - final JsonNode newDoc = body.get(NEW); - if (newDoc != null) { - doc.setNew(getSerde().deserializeUserData(getSerde().serialize(newDoc), returnType)); - } - final JsonNode oldDoc = body.get(OLD); - if (oldDoc != null) { - doc.setOld(getSerde().deserializeUserData(getSerde().serialize(oldDoc), returnType)); - } + Type type = SerdeUtils.INSTANCE.constructParametricType(DocumentUpdateEntity.class, returnType); + final DocumentUpdateEntity doc = getSerde().deserialize(response.getBody(), type); if (options == null || Boolean.TRUE != options.getSilent()) { final Map values = new HashMap<>(); values.put(DocumentFields.REV, doc.getRev()); @@ -399,7 +350,6 @@ protected Request updateDocumentsRequest(final Collection values, final D return request; } - @SuppressWarnings("unchecked") protected ResponseDeserializer>> updateDocumentsResponseDeserializer( final Class returnType) { return response -> { @@ -416,15 +366,8 @@ protected ResponseDeserializer>> errors.add(error); documentsAndErrors.add(error); } else { - final DocumentUpdateEntity doc = getSerde().deserialize(next, DocumentUpdateEntity.class); - final JsonNode newDoc = next.get(NEW); - if (newDoc != null) { - doc.setNew(getSerde().deserializeUserData(getSerde().serialize(newDoc), returnType)); - } - final JsonNode oldDoc = next.get(OLD); - if (oldDoc != null) { - doc.setOld(getSerde().deserializeUserData(getSerde().serialize(oldDoc), returnType)); - } + Type type = SerdeUtils.INSTANCE.constructParametricType(DocumentUpdateEntity.class, returnType); + final DocumentUpdateEntity doc = getSerde().deserialize(next, type); docs.add(doc); documentsAndErrors.add(doc); } @@ -449,15 +392,10 @@ protected Request deleteDocumentRequest(final String key, final DocumentDeleteOp } protected ResponseDeserializer> deleteDocumentResponseDeserializer( - final Class type) { + final Class userDataClass) { return response -> { - final JsonNode body = getSerde().parse(response.getBody()); - final DocumentDeleteEntity doc = getSerde().deserialize(body, DocumentDeleteEntity.class); - final JsonNode oldDoc = body.get(OLD); - if (oldDoc != null) { - doc.setOld(getSerde().deserializeUserData(getSerde().serialize(oldDoc), type)); - } - return doc; + Type type = SerdeUtils.INSTANCE.constructParametricType(DocumentDeleteEntity.class, userDataClass); + return getSerde().deserialize(response.getBody(), type); }; } @@ -473,7 +411,7 @@ protected Request deleteDocumentsRequest(final Collection keys, final Doc } protected ResponseDeserializer>> deleteDocumentsResponseDeserializer( - final Class type) { + final Class userDataClass) { return response -> { final MultiDocumentEntity> multiDocument = new MultiDocumentEntity<>(); final Collection> docs = new ArrayList<>(); @@ -488,11 +426,8 @@ protected ResponseDeserializer>> errors.add(error); documentsAndErrors.add(error); } else { - final DocumentDeleteEntity doc = getSerde().deserialize(next, DocumentDeleteEntity.class); - final JsonNode oldDoc = next.get(OLD); - if (oldDoc != null) { - doc.setOld(getSerde().deserializeUserData(getSerde().serialize(oldDoc), type)); - } + Type type = SerdeUtils.INSTANCE.constructParametricType(DocumentDeleteEntity.class, userDataClass); + final DocumentDeleteEntity doc = getSerde().deserialize(next, type); docs.add(doc); documentsAndErrors.add(doc); } @@ -676,4 +611,15 @@ protected ResponseDeserializer getPermissionsResponseDeserialzer() return response -> getSerde().deserialize(response.getBody(), ArangoResponseField.RESULT_JSON_POINTER, Permissions.class); } + private Class getCollectionContentClass(Collection c) { + if (c == null || c.isEmpty()) { + return null; + } + Object v = c.iterator().next(); + if (v == null) { + return null; + } + return v.getClass(); + } + } diff --git a/src/main/java/com/arangodb/serde/InternalAnnotationIntrospector.java b/src/main/java/com/arangodb/serde/InternalAnnotationIntrospector.java index 92b1e2fdd..cfaa5b417 100644 --- a/src/main/java/com/arangodb/serde/InternalAnnotationIntrospector.java +++ b/src/main/java/com/arangodb/serde/InternalAnnotationIntrospector.java @@ -6,9 +6,14 @@ class InternalAnnotationIntrospector extends JacksonAnnotationIntrospector { private final UserDataSerializer userDataSerializer; + private final UserDataDeserializer userDataDeserializer; - InternalAnnotationIntrospector(final UserDataSerializer userDataSerializer) { + InternalAnnotationIntrospector( + final UserDataSerializer userDataSerializer, + final UserDataDeserializer userDataDeserializer + ) { this.userDataSerializer = userDataSerializer; + this.userDataDeserializer = userDataDeserializer; } @Override @@ -29,4 +34,22 @@ public Object findContentSerializer(Annotated a) { } } + @Override + public Object findDeserializer(Annotated a) { + if (a.getAnnotation(UserData.class) != null) { + return userDataDeserializer; + } else { + return super.findDeserializer(a); + } + } + + @Override + public Object findContentDeserializer(Annotated a) { + if (a.getAnnotation(UserDataInside.class) != null) { + return userDataDeserializer; + } else { + return super.findContentDeserializer(a); + } + } + } diff --git a/src/main/java/com/arangodb/serde/InternalParameterizedType.java b/src/main/java/com/arangodb/serde/InternalParameterizedType.java new file mode 100644 index 000000000..40086b74f --- /dev/null +++ b/src/main/java/com/arangodb/serde/InternalParameterizedType.java @@ -0,0 +1,31 @@ +package com.arangodb.serde; + +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; + +class InternalParameterizedType implements ParameterizedType { + + private final Class rawType; + private final Type[] actualRawArguments; + + InternalParameterizedType(final Class rawType, final Type[] actualRawArguments) { + this.rawType = rawType; + this.actualRawArguments = actualRawArguments; + } + + @Override + public Type getRawType() { + return rawType; + } + + @Override + public Type[] getActualTypeArguments() { + return actualRawArguments; + } + + @Override + public Type getOwnerType() { + return null; + } + +} diff --git a/src/main/java/com/arangodb/serde/InternalSerdeImpl.java b/src/main/java/com/arangodb/serde/InternalSerdeImpl.java index f27f7164b..ae978c7fd 100644 --- a/src/main/java/com/arangodb/serde/InternalSerdeImpl.java +++ b/src/main/java/com/arangodb/serde/InternalSerdeImpl.java @@ -22,7 +22,10 @@ final class InternalSerdeImpl extends JacksonSerdeImpl implements InternalSerde this.userSerde = userSerde; mapper.registerModule(InternalModule.INSTANCE.get()); mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); - mapper.setAnnotationIntrospector(new InternalAnnotationIntrospector(new UserDataSerializer(this))); + mapper.setAnnotationIntrospector(new InternalAnnotationIntrospector( + new UserDataSerializer(this), + new UserDataDeserializer(this) + )); } @Override diff --git a/src/main/java/com/arangodb/serde/SerdeUtils.java b/src/main/java/com/arangodb/serde/SerdeUtils.java index 52ec7a6b8..c93677825 100644 --- a/src/main/java/com/arangodb/serde/SerdeUtils.java +++ b/src/main/java/com/arangodb/serde/SerdeUtils.java @@ -2,11 +2,13 @@ import com.arangodb.ArangoDBException; import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JavaType; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.type.TypeFactory; import java.lang.reflect.Type; +import java.util.ArrayList; import java.util.List; import java.util.Map; @@ -49,4 +51,21 @@ public Type constructMapType(Class keyClazz, Class valueClazz) { return TypeFactory.defaultInstance().constructMapType(Map.class, keyClazz, valueClazz); } + public Type constructParametricType(Class rawType, Type... rawArgs) { + if (rawArgs == null || rawArgs.length == 0 || rawArgs[0] == null) { + return rawType; + } else { + return new InternalParameterizedType(rawType, rawArgs); + } + } + + public Type convertToType(final JavaType javaType) { + List args = new ArrayList<>(); + for (JavaType it : javaType.getBindings().getTypeParameters()) { + Type type = convertToType(it); + args.add(type); + } + return constructParametricType(javaType.getRawClass(), args.toArray(new Type[0])); + } + } diff --git a/src/main/java/com/arangodb/serde/UserDataDeserializer.java b/src/main/java/com/arangodb/serde/UserDataDeserializer.java new file mode 100644 index 000000000..5be515eb5 --- /dev/null +++ b/src/main/java/com/arangodb/serde/UserDataDeserializer.java @@ -0,0 +1,42 @@ +package com.arangodb.serde; + +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.databind.BeanProperty; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JavaType; +import com.fasterxml.jackson.databind.JsonDeserializer; +import com.fasterxml.jackson.databind.deser.ContextualDeserializer; +import com.fasterxml.jackson.databind.jsontype.TypeDeserializer; + +import java.io.IOException; +import java.lang.reflect.Type; + +class UserDataDeserializer extends JsonDeserializer implements ContextualDeserializer { + private final Type targetType; + private final InternalSerde serde; + + UserDataDeserializer(final InternalSerde serde) { + targetType = null; + this.serde = serde; + } + + private UserDataDeserializer(final JavaType targetType, final InternalSerde serde) { + this.targetType = SerdeUtils.INSTANCE.convertToType(targetType); + this.serde = serde; + } + + @Override + public Object deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { + return serde.deserializeUserData(p.readValueAsTree(), targetType); + } + + @Override + public Object deserializeWithType(JsonParser p, DeserializationContext ctxt, TypeDeserializer typeDeserializer) throws IOException { + return deserialize(p, ctxt); + } + + @Override + public JsonDeserializer createContextual(DeserializationContext ctxt, BeanProperty property) { + return new UserDataDeserializer(ctxt.getContextualType(), serde); + } +} From f89eb881b30f92799d020e5528e1371c72704af5 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Tue, 26 Jul 2022 21:58:19 +0200 Subject: [PATCH 047/254] fix cluster tests --- .../java/com/arangodb/internal/ArangoCollectionImpl.java | 3 +-- .../com/arangodb/internal/InternalArangoCollection.java | 6 ++---- .../java/com/arangodb/internal/InternalArangoDatabase.java | 2 +- .../com/arangodb/internal/net/ExtendedHostResolver.java | 5 +++-- 4 files changed, 7 insertions(+), 9 deletions(-) diff --git a/src/main/java/com/arangodb/internal/ArangoCollectionImpl.java b/src/main/java/com/arangodb/internal/ArangoCollectionImpl.java index 7212c2e91..a97bd4955 100644 --- a/src/main/java/com/arangodb/internal/ArangoCollectionImpl.java +++ b/src/main/java/com/arangodb/internal/ArangoCollectionImpl.java @@ -25,7 +25,6 @@ import com.arangodb.entity.*; import com.arangodb.internal.util.DocumentUtil; import com.arangodb.model.*; -import com.fasterxml.jackson.databind.JsonNode; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -232,7 +231,7 @@ public Boolean documentExists(final String key) { @Override public Boolean documentExists(final String key, final DocumentExistsOptions options) throws ArangoDBException { try { - executor.execute(documentExistsRequest(key, options), JsonNode.class); + executor.execute(documentExistsRequest(key, options), Void.class); return true; } catch (final ArangoDBException e) { diff --git a/src/main/java/com/arangodb/internal/InternalArangoCollection.java b/src/main/java/com/arangodb/internal/InternalArangoCollection.java index 3bfd2d792..3840fd7a2 100644 --- a/src/main/java/com/arangodb/internal/InternalArangoCollection.java +++ b/src/main/java/com/arangodb/internal/InternalArangoCollection.java @@ -96,9 +96,8 @@ protected Request insertDocumentRequest(final T value, final DocumentCreateO protected ResponseDeserializer> insertDocumentResponseDeserializer( final T value, final DocumentCreateOptions options) { return response -> { - final JsonNode body = getSerde().parse(response.getBody()); Type type = SerdeUtils.INSTANCE.constructParametricType(DocumentCreateEntity.class, value.getClass()); - final DocumentCreateEntity doc = getSerde().deserialize(body, type); + final DocumentCreateEntity doc = getSerde().deserialize(response.getBody(), type); if (options == null || Boolean.TRUE != options.getSilent()) { final Map values = new HashMap<>(); values.put(DocumentFields.ID, doc.getId()); @@ -248,9 +247,8 @@ protected Request replaceDocumentRequest( protected ResponseDeserializer> replaceDocumentResponseDeserializer( final T value, final DocumentReplaceOptions options) { return response -> { - final JsonNode body = getSerde().parse(response.getBody()); Type type = SerdeUtils.INSTANCE.constructParametricType(DocumentUpdateEntity.class, value.getClass()); - final DocumentUpdateEntity doc = getSerde().deserialize(body, type); + final DocumentUpdateEntity doc = getSerde().deserialize(response.getBody(), type); if (options == null || Boolean.TRUE != options.getSilent()) { final Map values = new HashMap<>(); values.put(DocumentFields.REV, doc.getRev()); diff --git a/src/main/java/com/arangodb/internal/InternalArangoDatabase.java b/src/main/java/com/arangodb/internal/InternalArangoDatabase.java index 2f36609cb..97d9707af 100644 --- a/src/main/java/com/arangodb/internal/InternalArangoDatabase.java +++ b/src/main/java/com/arangodb/internal/InternalArangoDatabase.java @@ -110,7 +110,7 @@ protected Request getCollectionsRequest(final CollectionsReadOptions options) { } protected ResponseDeserializer> getCollectionsResponseDeserializer() { - return response -> getSerde().deserialize(getSerde().parse(response.getBody(), ArangoResponseField.RESULT_JSON_POINTER), + return response -> getSerde().deserialize(response.getBody(), ArangoResponseField.RESULT_JSON_POINTER, SerdeUtils.INSTANCE.constructListType(CollectionEntity.class)); } diff --git a/src/main/java/com/arangodb/internal/net/ExtendedHostResolver.java b/src/main/java/com/arangodb/internal/net/ExtendedHostResolver.java index 7f4e6a9fa..5d617c942 100644 --- a/src/main/java/com/arangodb/internal/net/ExtendedHostResolver.java +++ b/src/main/java/com/arangodb/internal/net/ExtendedHostResolver.java @@ -121,8 +121,9 @@ private Collection resolveFromServer() throws ArangoDBException { response = executor.execute( new Request(DbName.SYSTEM, RequestType.GET, "/_api/cluster/endpoints"), response1 -> { - final Collection> tmp = arangoSerialization.deserialize(response1.getBody(), "/endpoints", - SerdeUtils.INSTANCE.constructMapType(String.class, String.class)); + final List> tmp = arangoSerialization.deserialize(response1.getBody(), "/endpoints", + SerdeUtils.INSTANCE.constructParametricType(List.class, + SerdeUtils.INSTANCE.constructParametricType(Map.class, String.class, String.class))); Collection endpoints = new ArrayList<>(); for (final Map map : tmp) { endpoints.add(map.get("endpoint")); From 8792566a035ab9bed25e0ac75372269ddfe3daf4 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Wed, 27 Jul 2022 10:25:33 +0200 Subject: [PATCH 048/254] replaced model arrays with collections --- .../entity/arangosearch/CollectionLink.java | 11 +++--- .../entity/arangosearch/FieldLink.java | 11 +++--- .../com/arangodb/model/AqlQueryOptions.java | 34 ++++++++----------- .../model/CollectionCreateOptions.java | 9 +++-- .../com/arangodb/model/CollectionSchema.java | 8 ----- .../arangodb/model/GraphCreateOptions.java | 5 ++- .../model/TransactionCollectionOptions.java | 7 ++-- .../com/arangodb/ArangoCollectionTest.java | 3 +- 8 files changed, 36 insertions(+), 52 deletions(-) diff --git a/src/main/java/com/arangodb/entity/arangosearch/CollectionLink.java b/src/main/java/com/arangodb/entity/arangosearch/CollectionLink.java index 0e8b3c2d9..d358e24d0 100644 --- a/src/main/java/com/arangodb/entity/arangosearch/CollectionLink.java +++ b/src/main/java/com/arangodb/entity/arangosearch/CollectionLink.java @@ -28,7 +28,6 @@ import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.fasterxml.jackson.databind.annotation.JsonSerialize; -import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; @@ -38,17 +37,15 @@ public final class CollectionLink { private final String name; - private final Collection analyzers; + private Collection analyzers; private Boolean includeAllFields; private Boolean trackListPositions; private StoreValuesType storeValues; - private final Collection fields; + private Collection fields; private CollectionLink(final String name) { super(); this.name = name; - fields = new ArrayList<>(); - analyzers = new ArrayList<>(); } /** @@ -67,7 +64,7 @@ public static CollectionLink on(@JsonProperty("name") final String name) { * @return link */ public CollectionLink analyzers(final String... analyzers) { - this.analyzers.addAll(Arrays.asList(analyzers)); + this.analyzers = Arrays.asList(analyzers); return this; } @@ -106,7 +103,7 @@ public CollectionLink storeValues(final StoreValuesType storeValues) { */ @JsonDeserialize(using = InternalDeserializers.FieldLinksDeserializer.class) public CollectionLink fields(final FieldLink... fields) { - this.fields.addAll(Arrays.asList(fields)); + this.fields = Arrays.asList(fields); return this; } diff --git a/src/main/java/com/arangodb/entity/arangosearch/FieldLink.java b/src/main/java/com/arangodb/entity/arangosearch/FieldLink.java index f4374f52e..cb3a851dc 100644 --- a/src/main/java/com/arangodb/entity/arangosearch/FieldLink.java +++ b/src/main/java/com/arangodb/entity/arangosearch/FieldLink.java @@ -6,24 +6,21 @@ import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.databind.annotation.JsonSerialize; -import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; public final class FieldLink { private final String name; - private final Collection analyzers; + private Collection analyzers; private Boolean includeAllFields; private Boolean trackListPositions; private StoreValuesType storeValues; - private final Collection fields; + private Collection fields; private FieldLink(final String name) { super(); this.name = name; - fields = new ArrayList<>(); - analyzers = new ArrayList<>(); } /** @@ -42,7 +39,7 @@ public static FieldLink on(@JsonProperty("name") final String name) { * @return link */ public FieldLink analyzers(final String... analyzers) { - this.analyzers.addAll(Arrays.asList(analyzers)); + this.analyzers = Arrays.asList(analyzers); return this; } @@ -80,7 +77,7 @@ public FieldLink storeValues(final StoreValuesType storeValues) { * @return link */ public FieldLink fields(final FieldLink... fields) { - this.fields.addAll(Arrays.asList(fields)); + this.fields = Arrays.asList(fields); return this; } diff --git a/src/main/java/com/arangodb/model/AqlQueryOptions.java b/src/main/java/com/arangodb/model/AqlQueryOptions.java index dd85a40b1..9fe1e4a65 100644 --- a/src/main/java/com/arangodb/model/AqlQueryOptions.java +++ b/src/main/java/com/arangodb/model/AqlQueryOptions.java @@ -22,7 +22,6 @@ import com.arangodb.serde.UserDataInside; -import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Map; @@ -128,7 +127,7 @@ public AqlQueryOptions cache(final Boolean cache) { } public Boolean getFillBlockCache() { - return options != null ? options.fillBlockCache : null; + return getOptions().fillBlockCache; } /** @@ -175,7 +174,7 @@ public AqlQueryOptions query(final String query) { } public Boolean getFailOnWarning() { - return options != null ? options.failOnWarning : null; + return getOptions().failOnWarning; } /** @@ -206,7 +205,7 @@ public AqlQueryOptions maxRuntime(final Double timeout) { * profile of the extra return attribute if the query result is not served from the query cache. */ public Boolean getProfile() { - return options != null ? options.profile : null; + return getOptions().profile; } /** @@ -220,7 +219,7 @@ public AqlQueryOptions profile(final Boolean profile) { } public Long getMaxTransactionSize() { - return options != null ? options.maxTransactionSize : null; + return getOptions().maxTransactionSize; } /** @@ -234,7 +233,7 @@ public AqlQueryOptions maxTransactionSize(final Long maxTransactionSize) { } public Long getMaxWarningCount() { - return options != null ? options.maxWarningCount : null; + return getOptions().maxWarningCount; } /** @@ -249,7 +248,7 @@ public AqlQueryOptions maxWarningCount(final Long maxWarningCount) { } public Long getIntermediateCommitCount() { - return options != null ? options.intermediateCommitCount : null; + return getOptions().intermediateCommitCount; } /** @@ -264,7 +263,7 @@ public AqlQueryOptions intermediateCommitCount(final Long intermediateCommitCoun } public Long getIntermediateCommitSize() { - return options != null ? options.intermediateCommitSize : null; + return getOptions().intermediateCommitSize; } /** @@ -279,7 +278,7 @@ public AqlQueryOptions intermediateCommitSize(final Long intermediateCommitSize) } public Double getSatelliteSyncWait() { - return options != null ? options.satelliteSyncWait : null; + return getOptions().satelliteSyncWait; } /** @@ -295,7 +294,7 @@ public AqlQueryOptions satelliteSyncWait(final Double satelliteSyncWait) { } public Boolean getSkipInaccessibleCollections() { - return options != null ? options.skipInaccessibleCollections : null; + return getOptions().skipInaccessibleCollections; } /** @@ -314,7 +313,7 @@ public AqlQueryOptions skipInaccessibleCollections(final Boolean skipInaccessibl } public Boolean getFullCount() { - return options != null ? options.fullCount : null; + return getOptions().fullCount; } /** @@ -335,7 +334,7 @@ public AqlQueryOptions fullCount(final Boolean fullCount) { } public Integer getMaxPlans() { - return options != null ? options.maxPlans : null; + return getOptions().maxPlans; } /** @@ -348,7 +347,7 @@ public AqlQueryOptions maxPlans(final Integer maxPlans) { } public Collection getRules() { - return options != null ? options.optimizer != null ? options.optimizer.rules : null : null; + return getOptions().getOptimizer().rules; } /** @@ -363,7 +362,7 @@ public AqlQueryOptions rules(final Collection rules) { } public Boolean getStream() { - return options != null ? options.stream : null; + return getOptions().stream; } /** @@ -385,7 +384,7 @@ public AqlQueryOptions stream(final Boolean stream) { } public Collection getShardIds() { - return options != null ? options.shardIds : null; + return getOptions().shardIds; } /** @@ -395,7 +394,7 @@ public Collection getShardIds() { * @return options */ public AqlQueryOptions shardIds(final String... shardIds) { - getOptions().getShardIds().addAll(Arrays.asList(shardIds)); + getOptions().shardIds = Arrays.asList(shardIds); return this; } @@ -484,9 +483,6 @@ public Optimizer getOptimizer() { } public Collection getShardIds() { - if (shardIds == null) { - shardIds = new ArrayList<>(); - } return shardIds; } diff --git a/src/main/java/com/arangodb/model/CollectionCreateOptions.java b/src/main/java/com/arangodb/model/CollectionCreateOptions.java index 4acf37754..fa7ebc9db 100644 --- a/src/main/java/com/arangodb/model/CollectionCreateOptions.java +++ b/src/main/java/com/arangodb/model/CollectionCreateOptions.java @@ -25,6 +25,9 @@ import com.arangodb.entity.KeyType; import com.arangodb.entity.ReplicationFactor; +import java.util.Arrays; +import java.util.Collection; + /** * @author Mark Vollmary * @see API @@ -37,7 +40,7 @@ public final class CollectionCreateOptions { private Integer writeConcern; private KeyOptions keyOptions; private Boolean waitForSync; - private String[] shardKeys = new String[]{}; + private Collection shardKeys; private Integer numberOfShards; private Boolean isSystem; private CollectionType type; @@ -148,7 +151,7 @@ public CollectionCreateOptions waitForSync(final Boolean waitForSync) { return this; } - public String[] getShardKeys() { + public Collection getShardKeys() { return shardKeys; } @@ -161,7 +164,7 @@ public String[] getShardKeys() { * @return options */ public CollectionCreateOptions shardKeys(final String... shardKeys) { - this.shardKeys = shardKeys; + this.shardKeys = Arrays.asList(shardKeys); return this; } diff --git a/src/main/java/com/arangodb/model/CollectionSchema.java b/src/main/java/com/arangodb/model/CollectionSchema.java index 231d19616..40c5c539b 100644 --- a/src/main/java/com/arangodb/model/CollectionSchema.java +++ b/src/main/java/com/arangodb/model/CollectionSchema.java @@ -35,14 +35,6 @@ */ public final class CollectionSchema { - /** - * Value to unset the collection schema on properties update {@link com.arangodb.ArangoCollection#changeProperties(CollectionPropertiesOptions)}. - */ - public static final CollectionSchema NULL_SCHEMA = new CollectionSchema() - .setLevel(null) - .setMessage(null) - .setRule(null); - private String rule; private Level level; private String message; diff --git a/src/main/java/com/arangodb/model/GraphCreateOptions.java b/src/main/java/com/arangodb/model/GraphCreateOptions.java index 7261065b7..83cb05363 100644 --- a/src/main/java/com/arangodb/model/GraphCreateOptions.java +++ b/src/main/java/com/arangodb/model/GraphCreateOptions.java @@ -25,7 +25,6 @@ import java.util.Arrays; import java.util.Collection; -import java.util.Collections; /** * @author Mark Vollmary @@ -34,8 +33,8 @@ public final class GraphCreateOptions { private String name; - private Collection edgeDefinitions = Collections.emptyList(); - private Collection orphanCollections = Collections.emptyList(); + private Collection edgeDefinitions; + private Collection orphanCollections; private Boolean isSmart; private SmartOptions options; diff --git a/src/main/java/com/arangodb/model/TransactionCollectionOptions.java b/src/main/java/com/arangodb/model/TransactionCollectionOptions.java index ade09ba96..ce1d4e466 100644 --- a/src/main/java/com/arangodb/model/TransactionCollectionOptions.java +++ b/src/main/java/com/arangodb/model/TransactionCollectionOptions.java @@ -22,7 +22,6 @@ import java.util.Arrays; import java.util.Collection; -import java.util.Collections; /** * @author Mark Vollmary @@ -30,9 +29,9 @@ */ public final class TransactionCollectionOptions { - private Collection read = Collections.emptyList(); - private Collection write = Collections.emptyList(); - private Collection exclusive = Collections.emptyList(); + private Collection read; + private Collection write; + private Collection exclusive; private Boolean allowImplicit; public Collection getRead() { diff --git a/src/test/java/com/arangodb/ArangoCollectionTest.java b/src/test/java/com/arangodb/ArangoCollectionTest.java index 843bd6c18..8e58b4c8b 100644 --- a/src/test/java/com/arangodb/ArangoCollectionTest.java +++ b/src/test/java/com/arangodb/ArangoCollectionTest.java @@ -2582,7 +2582,8 @@ void changeProperties(ArangoCollection collection) { } // revert changes - CollectionPropertiesEntity revertedProperties = collection.changeProperties(new CollectionPropertiesOptions().waitForSync(properties.getWaitForSync()).schema(CollectionSchema.NULL_SCHEMA)); + CollectionPropertiesEntity revertedProperties = collection.changeProperties(new CollectionPropertiesOptions() + .waitForSync(properties.getWaitForSync()).schema(new CollectionSchema())); if (isAtLeastVersion(3, 7)) { assertThat(revertedProperties.getSchema()).isNull(); } From 7124cf09cb29c8df7b500af74542275d295494b3 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Wed, 27 Jul 2022 13:48:50 +0200 Subject: [PATCH 049/254] native image support --- pom.xml | 3 +- .../async/internal/ArangoCursorAsyncImpl.java | 2 +- .../internal/ArangoDatabaseAsyncImpl.java | 2 +- .../internal/ArangoCursorExecute.java | 2 +- .../arangodb/internal/ArangoDatabaseImpl.java | 2 +- .../internal/cursor/ArangoCursorImpl.java | 3 +- .../internal/cursor/ArangoCursorIterator.java | 1 + .../{ => entity}/InternalCursorEntity.java | 2 +- .../util/ArangoCursorInitializer.java | 2 +- .../arangodb-java-driver/reflect-config.json | 1558 +++++++---------- src/test/java/helper/NativeImageHelper.java | 54 +- .../META-INF/native-image/reflect-config.json | 351 +--- 12 files changed, 683 insertions(+), 1299 deletions(-) rename src/main/java/com/arangodb/internal/cursor/{ => entity}/InternalCursorEntity.java (98%) diff --git a/pom.xml b/pom.xml index 649739b52..fa82b22d5 100644 --- a/pom.xml +++ b/pom.xml @@ -89,7 +89,7 @@ org.graalvm.buildtools native-maven-plugin - 0.9.11 + 0.9.13 true @@ -102,6 +102,7 @@ + true false --no-fallback diff --git a/src/main/java/com/arangodb/async/internal/ArangoCursorAsyncImpl.java b/src/main/java/com/arangodb/async/internal/ArangoCursorAsyncImpl.java index f2ac9c93b..284a576b8 100644 --- a/src/main/java/com/arangodb/async/internal/ArangoCursorAsyncImpl.java +++ b/src/main/java/com/arangodb/async/internal/ArangoCursorAsyncImpl.java @@ -21,7 +21,7 @@ package com.arangodb.async.internal; import com.arangodb.async.ArangoCursorAsync; -import com.arangodb.internal.cursor.InternalCursorEntity; +import com.arangodb.internal.cursor.entity.InternalCursorEntity; import com.arangodb.internal.ArangoCursorExecute; import com.arangodb.internal.InternalArangoDatabase; import com.arangodb.internal.cursor.ArangoCursorImpl; diff --git a/src/main/java/com/arangodb/async/internal/ArangoDatabaseAsyncImpl.java b/src/main/java/com/arangodb/async/internal/ArangoDatabaseAsyncImpl.java index 22f300325..0e390e736 100644 --- a/src/main/java/com/arangodb/async/internal/ArangoDatabaseAsyncImpl.java +++ b/src/main/java/com/arangodb/async/internal/ArangoDatabaseAsyncImpl.java @@ -28,7 +28,7 @@ import com.arangodb.internal.ArangoCursorExecute; import com.arangodb.internal.ArangoErrors; import com.arangodb.internal.InternalArangoDatabase; -import com.arangodb.internal.cursor.InternalCursorEntity; +import com.arangodb.internal.cursor.entity.InternalCursorEntity; import com.arangodb.internal.net.HostHandle; import com.arangodb.internal.util.DocumentUtil; import com.arangodb.model.*; diff --git a/src/main/java/com/arangodb/internal/ArangoCursorExecute.java b/src/main/java/com/arangodb/internal/ArangoCursorExecute.java index b9462b076..8e501d66a 100644 --- a/src/main/java/com/arangodb/internal/ArangoCursorExecute.java +++ b/src/main/java/com/arangodb/internal/ArangoCursorExecute.java @@ -21,7 +21,7 @@ package com.arangodb.internal; import com.arangodb.ArangoDBException; -import com.arangodb.internal.cursor.InternalCursorEntity; +import com.arangodb.internal.cursor.entity.InternalCursorEntity; import java.util.Map; diff --git a/src/main/java/com/arangodb/internal/ArangoDatabaseImpl.java b/src/main/java/com/arangodb/internal/ArangoDatabaseImpl.java index 3c1ad65e2..f02e8c516 100644 --- a/src/main/java/com/arangodb/internal/ArangoDatabaseImpl.java +++ b/src/main/java/com/arangodb/internal/ArangoDatabaseImpl.java @@ -24,7 +24,7 @@ import com.arangodb.entity.*; import com.arangodb.entity.arangosearch.analyzer.SearchAnalyzer; import com.arangodb.internal.cursor.ArangoCursorImpl; -import com.arangodb.internal.cursor.InternalCursorEntity; +import com.arangodb.internal.cursor.entity.InternalCursorEntity; import com.arangodb.internal.net.HostHandle; import com.arangodb.internal.util.DocumentUtil; import com.arangodb.model.*; diff --git a/src/main/java/com/arangodb/internal/cursor/ArangoCursorImpl.java b/src/main/java/com/arangodb/internal/cursor/ArangoCursorImpl.java index 40ece0f7d..1af8097fb 100644 --- a/src/main/java/com/arangodb/internal/cursor/ArangoCursorImpl.java +++ b/src/main/java/com/arangodb/internal/cursor/ArangoCursorImpl.java @@ -24,7 +24,8 @@ import com.arangodb.ArangoIterator; import com.arangodb.entity.CursorStats; import com.arangodb.entity.CursorWarning; -import com.arangodb.internal.cursor.InternalCursorEntity.Extras; +import com.arangodb.internal.cursor.entity.InternalCursorEntity; +import com.arangodb.internal.cursor.entity.InternalCursorEntity.Extras; import com.arangodb.internal.ArangoCursorExecute; import com.arangodb.internal.InternalArangoDatabase; diff --git a/src/main/java/com/arangodb/internal/cursor/ArangoCursorIterator.java b/src/main/java/com/arangodb/internal/cursor/ArangoCursorIterator.java index b3b048158..f34f3203a 100644 --- a/src/main/java/com/arangodb/internal/cursor/ArangoCursorIterator.java +++ b/src/main/java/com/arangodb/internal/cursor/ArangoCursorIterator.java @@ -24,6 +24,7 @@ import com.arangodb.ArangoIterator; import com.arangodb.internal.ArangoCursorExecute; import com.arangodb.internal.InternalArangoDatabase; +import com.arangodb.internal.cursor.entity.InternalCursorEntity; import com.fasterxml.jackson.databind.JsonNode; import java.util.Iterator; diff --git a/src/main/java/com/arangodb/internal/cursor/InternalCursorEntity.java b/src/main/java/com/arangodb/internal/cursor/entity/InternalCursorEntity.java similarity index 98% rename from src/main/java/com/arangodb/internal/cursor/InternalCursorEntity.java rename to src/main/java/com/arangodb/internal/cursor/entity/InternalCursorEntity.java index a85999902..56f428f67 100644 --- a/src/main/java/com/arangodb/internal/cursor/InternalCursorEntity.java +++ b/src/main/java/com/arangodb/internal/cursor/entity/InternalCursorEntity.java @@ -18,7 +18,7 @@ * Copyright holder is ArangoDB GmbH, Cologne, Germany */ -package com.arangodb.internal.cursor; +package com.arangodb.internal.cursor.entity; import com.arangodb.entity.CursorStats; import com.arangodb.entity.CursorWarning; diff --git a/src/main/java/com/arangodb/util/ArangoCursorInitializer.java b/src/main/java/com/arangodb/util/ArangoCursorInitializer.java index 9d0b2169c..6344bf2d3 100644 --- a/src/main/java/com/arangodb/util/ArangoCursorInitializer.java +++ b/src/main/java/com/arangodb/util/ArangoCursorInitializer.java @@ -21,7 +21,7 @@ package com.arangodb.util; import com.arangodb.ArangoCursor; -import com.arangodb.internal.cursor.InternalCursorEntity; +import com.arangodb.internal.cursor.entity.InternalCursorEntity; import com.arangodb.internal.ArangoCursorExecute; import com.arangodb.internal.InternalArangoDatabase; diff --git a/src/main/resources/META-INF/native-image/com.arangodb/arangodb-java-driver/reflect-config.json b/src/main/resources/META-INF/native-image/com.arangodb/arangodb-java-driver/reflect-config.json index eac1dd6cd..09cda49c3 100644 --- a/src/main/resources/META-INF/native-image/com.arangodb/arangodb-java-driver/reflect-config.json +++ b/src/main/resources/META-INF/native-image/com.arangodb/arangodb-java-driver/reflect-config.json @@ -1,1492 +1,1172 @@ [ + { + "name": "com.arangodb.serde.InternalSerializers$CollectionSchemaRuleSerializer", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.serde.InternalSerializers$FieldLinksSerializer", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.serde.InternalSerializers$CollectionLinksSerializer", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.serde.InternalDeserializers$CollectionLinksDeserializer", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.serde.InternalDeserializers$FieldLinksDeserializer", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.serde.InternalDeserializers$CollectionSchemaRuleDeserializer", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, { "name": "com.arangodb.entity.DocumentCreateEntity", "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.ReplicationFactor$SatelliteReplicationFactor", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true }, { "name": "com.arangodb.entity.arangosearch.analyzer.GeoPointAnalyzerProperties", "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] + "allDeclaredMethods": true, + "allDeclaredConstructors": true }, { "name": "com.arangodb.entity.arangosearch.analyzer.GeoJSONAnalyzerProperties", "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] + "allDeclaredMethods": true, + "allDeclaredConstructors": true }, { - "name": "com.arangodb.entity.CursorEntity", + "name": "com.arangodb.entity.Rev", "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] + "allDeclaredMethods": true, + "allDeclaredConstructors": true }, { - "name": "com.arangodb.entity.TraversalEntity", + "name": "com.arangodb.entity.MetaAware", "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] + "allDeclaredMethods": true, + "allDeclaredConstructors": true }, { "name": "com.arangodb.entity.IndexEntity", "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] + "allDeclaredMethods": true, + "allDeclaredConstructors": true }, { "name": "com.arangodb.entity.VertexEntity", "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] + "allDeclaredMethods": true, + "allDeclaredConstructors": true }, { "name": "com.arangodb.entity.AqlExecutionExplainEntity", "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] + "allDeclaredMethods": true, + "allDeclaredConstructors": true }, { "name": "com.arangodb.entity.AqlParseEntity", "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] + "allDeclaredMethods": true, + "allDeclaredConstructors": true }, { "name": "com.arangodb.entity.EdgeDefinition", "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] + "allDeclaredMethods": true, + "allDeclaredConstructors": true }, { "name": "com.arangodb.entity.CollectionEntity", "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "com.arangodb.entity.CursorEntity$Stats", - "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] + "allDeclaredMethods": true, + "allDeclaredConstructors": true }, { "name": "com.arangodb.entity.MultiDocumentEntity", "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] + "allDeclaredMethods": true, + "allDeclaredConstructors": true }, { "name": "com.arangodb.entity.arangosearch.analyzer.StopwordsAnalyzerProperties", "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] + "allDeclaredMethods": true, + "allDeclaredConstructors": true }, { "name": "com.arangodb.entity.AqlExecutionExplainEntity$ExecutionVariable", "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] + "allDeclaredMethods": true, + "allDeclaredConstructors": true }, { "name": "com.arangodb.entity.arangosearch.analyzer.StopwordsAnalyzer", "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] + "allDeclaredMethods": true, + "allDeclaredConstructors": true }, { "name": "com.arangodb.entity.CollectionPropertiesEntity", "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] + "allDeclaredMethods": true, + "allDeclaredConstructors": true }, { "name": "com.arangodb.entity.EdgeUpdateEntity", "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] + "allDeclaredMethods": true, + "allDeclaredConstructors": true }, { "name": "com.arangodb.entity.QueryCachePropertiesEntity", "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] + "allDeclaredMethods": true, + "allDeclaredConstructors": true }, { "name": "com.arangodb.entity.DocumentUpdateEntity", "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.CursorStats", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true }, { "name": "com.arangodb.entity.arangosearch.analyzer.AQLAnalyzer", "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] + "allDeclaredMethods": true, + "allDeclaredConstructors": true }, { "name": "com.arangodb.entity.GraphEntity", "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] + "allDeclaredMethods": true, + "allDeclaredConstructors": true }, { "name": "com.arangodb.entity.arangosearch.analyzer.GeoJSONAnalyzer", "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] + "allDeclaredMethods": true, + "allDeclaredConstructors": true }, { "name": "com.arangodb.entity.AqlFunctionEntity", "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.PrimarySort", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true }, { "name": "com.arangodb.entity.DatabaseEntity", "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] + "allDeclaredMethods": true, + "allDeclaredConstructors": true }, { "name": "com.arangodb.entity.EdgeEntity", "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] + "allDeclaredMethods": true, + "allDeclaredConstructors": true }, { "name": "com.arangodb.entity.ViewEntity", "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] + "allDeclaredMethods": true, + "allDeclaredConstructors": true }, { "name": "com.arangodb.entity.arangosearch.analyzer.EdgeNgram", "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] + "allDeclaredMethods": true, + "allDeclaredConstructors": true }, { "name": "com.arangodb.entity.AqlExecutionExplainEntity$ExecutionNode", "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] + "allDeclaredMethods": true, + "allDeclaredConstructors": true }, { "name": "com.arangodb.entity.BaseDocument", "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] + "allDeclaredMethods": true, + "allDeclaredConstructors": true }, { "name": "com.arangodb.entity.TransactionEntity", "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] + "allDeclaredMethods": true, + "allDeclaredConstructors": true }, { "name": "com.arangodb.entity.ArangoDBEngine", "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] + "allDeclaredMethods": true, + "allDeclaredConstructors": true }, { "name": "com.arangodb.entity.UserEntity", "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "com.arangodb.entity.LogEntity", - "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] + "allDeclaredMethods": true, + "allDeclaredConstructors": true }, { "name": "com.arangodb.entity.ErrorEntity", "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] + "allDeclaredMethods": true, + "allDeclaredConstructors": true }, { - "name": "com.arangodb.entity.arangosearch.analyzer.NormAnalyzer", + "name": "com.arangodb.entity.arangosearch.analyzer.DelimiterAnalyzerProperties", "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] + "allDeclaredMethods": true, + "allDeclaredConstructors": true }, { - "name": "com.arangodb.entity.arangosearch.analyzer.DelimiterAnalyzerProperties", + "name": "com.arangodb.entity.AqlExecutionExplainEntity$ExecutionStats", "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] + "allDeclaredMethods": true, + "allDeclaredConstructors": true }, { - "name": "com.arangodb.entity.CursorEntity$Warning", + "name": "com.arangodb.entity.arangosearch.analyzer.NormAnalyzer", "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] + "allDeclaredMethods": true, + "allDeclaredConstructors": true }, { - "name": "com.arangodb.entity.AqlExecutionExplainEntity$ExecutionStats", + "name": "com.arangodb.entity.arangosearch.FieldLink", "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] + "allDeclaredMethods": true, + "allDeclaredConstructors": true }, { - "name": "com.arangodb.entity.arangosearch.analyzer.GeoAnalyzerOptions", + "name": "com.arangodb.entity.To", "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] + "allDeclaredMethods": true, + "allDeclaredConstructors": true }, { - "name": "com.arangodb.entity.arangosearch.analyzer.NGramAnalyzer", + "name": "com.arangodb.entity.arangosearch.analyzer.GeoAnalyzerOptions", "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] + "allDeclaredMethods": true, + "allDeclaredConstructors": true }, { "name": "com.arangodb.entity.AqlParseEntity$AstNode", "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] + "allDeclaredMethods": true, + "allDeclaredConstructors": true }, { - "name": "com.arangodb.entity.arangosearch.ArangoSearchProperties", + "name": "com.arangodb.entity.arangosearch.analyzer.NGramAnalyzer", "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] + "allDeclaredMethods": true, + "allDeclaredConstructors": true }, { "name": "com.arangodb.entity.ShardEntity", "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] + "allDeclaredMethods": true, + "allDeclaredConstructors": true }, { "name": "com.arangodb.entity.AqlExecutionExplainEntity$ExecutionCollection", "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] + "allDeclaredMethods": true, + "allDeclaredConstructors": true }, { "name": "com.arangodb.entity.arangosearch.analyzer.PipelineAnalyzerProperties", "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.ReplicationFactor$NumericReplicationFactor", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.Key", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true }, { "name": "com.arangodb.entity.arangosearch.analyzer.TextAnalyzerProperties", "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] + "allDeclaredMethods": true, + "allDeclaredConstructors": true }, { "name": "com.arangodb.entity.arangosearch.analyzer.SegmentationAnalyzer", "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] + "allDeclaredMethods": true, + "allDeclaredConstructors": true }, { "name": "com.arangodb.entity.DocumentDeleteEntity", "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] + "allDeclaredMethods": true, + "allDeclaredConstructors": true }, { "name": "com.arangodb.entity.EdgeDefinition$Options", "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "com.arangodb.entity.arangosearch.AnalyzerEntity", - "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] + "allDeclaredMethods": true, + "allDeclaredConstructors": true }, { "name": "com.arangodb.entity.ArangoDBVersion", "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] + "allDeclaredMethods": true, + "allDeclaredConstructors": true }, { "name": "com.arangodb.entity.arangosearch.analyzer.AQLAnalyzerProperties", "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] + "allDeclaredMethods": true, + "allDeclaredConstructors": true }, { "name": "com.arangodb.entity.arangosearch.analyzer.SegmentationAnalyzerProperties", "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] + "allDeclaredMethods": true, + "allDeclaredConstructors": true }, { "name": "com.arangodb.entity.BaseEdgeDocument", "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] + "allDeclaredMethods": true, + "allDeclaredConstructors": true }, { "name": "com.arangodb.entity.arangosearch.ConsolidationPolicy", "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] + "allDeclaredMethods": true, + "allDeclaredConstructors": true }, { "name": "com.arangodb.entity.VertexUpdateEntity", "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] + "allDeclaredMethods": true, + "allDeclaredConstructors": true }, { "name": "com.arangodb.entity.arangosearch.analyzer.NormAnalyzerProperties", "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] + "allDeclaredMethods": true, + "allDeclaredConstructors": true }, { "name": "com.arangodb.entity.KeyOptions", "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] + "allDeclaredMethods": true, + "allDeclaredConstructors": true }, { "name": "com.arangodb.entity.AqlExecutionExplainEntity$ExecutionPlan", "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] + "allDeclaredMethods": true, + "allDeclaredConstructors": true }, { "name": "com.arangodb.entity.LogLevelEntity", "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] + "allDeclaredMethods": true, + "allDeclaredConstructors": true }, { "name": "com.arangodb.entity.ReplicationFactor", "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.Id", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true }, { "name": "com.arangodb.entity.arangosearch.analyzer.DelimiterAnalyzer", "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] + "allDeclaredMethods": true, + "allDeclaredConstructors": true }, { "name": "com.arangodb.entity.DocumentEntity", "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] + "allDeclaredMethods": true, + "allDeclaredConstructors": true }, { "name": "com.arangodb.entity.arangosearch.analyzer.NGramAnalyzerProperties", "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.CursorWarning", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true }, { "name": "com.arangodb.entity.arangosearch.analyzer.StemAnalyzerProperties", "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] + "allDeclaredMethods": true, + "allDeclaredConstructors": true }, { "name": "com.arangodb.entity.arangosearch.analyzer.IdentityAnalyzer", "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] + "allDeclaredMethods": true, + "allDeclaredConstructors": true }, { "name": "com.arangodb.entity.StreamTransactionEntity", "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.LogEntriesEntity", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true }, { "name": "com.arangodb.entity.arangosearch.analyzer.GeoPointAnalyzer", "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] + "allDeclaredMethods": true, + "allDeclaredConstructors": true }, { - "name": "com.arangodb.entity.LogEntriesEntity", + "name": "com.arangodb.entity.QueryEntity", "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] + "allDeclaredMethods": true, + "allDeclaredConstructors": true }, { - "name": "com.arangodb.entity.PathEntity", + "name": "com.arangodb.entity.arangosearch.CollectionLink", "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] + "allDeclaredMethods": true, + "allDeclaredConstructors": true }, { - "name": "com.arangodb.entity.QueryEntity", + "name": "com.arangodb.entity.arangosearch.StoredValue", "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] + "allDeclaredMethods": true, + "allDeclaredConstructors": true }, { "name": "com.arangodb.entity.DocumentImportEntity", "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] + "allDeclaredMethods": true, + "allDeclaredConstructors": true }, { "name": "com.arangodb.entity.arangosearch.analyzer.PipelineAnalyzer", "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] + "allDeclaredMethods": true, + "allDeclaredConstructors": true }, { "name": "com.arangodb.entity.arangosearch.analyzer.CollationAnalyzerProperties", "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "com.arangodb.entity.MinReplicationFactor", - "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] + "allDeclaredMethods": true, + "allDeclaredConstructors": true }, { "name": "com.arangodb.entity.arangosearch.analyzer.StemAnalyzer", "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] + "allDeclaredMethods": true, + "allDeclaredConstructors": true }, { "name": "com.arangodb.entity.QueryTrackingPropertiesEntity", "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] + "allDeclaredMethods": true, + "allDeclaredConstructors": true }, { "name": "com.arangodb.entity.CollectionRevisionEntity", "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "com.arangodb.entity.CursorEntity$Extras", - "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] + "allDeclaredMethods": true, + "allDeclaredConstructors": true }, { "name": "com.arangodb.entity.LogEntriesEntity$Message", "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] + "allDeclaredMethods": true, + "allDeclaredConstructors": true }, { - "name": "java.lang.Object", + "name": "com.arangodb.entity.arangosearch.ArangoSearchPropertiesEntity", "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] + "allDeclaredMethods": true, + "allDeclaredConstructors": true }, { "name": "com.arangodb.entity.arangosearch.analyzer.CollationAnalyzer", "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] + "allDeclaredMethods": true, + "allDeclaredConstructors": true }, { "name": "com.arangodb.entity.arangosearch.analyzer.TextAnalyzer", "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] + "allDeclaredMethods": true, + "allDeclaredConstructors": true }, { "name": "com.arangodb.entity.arangosearch.analyzer.SearchAnalyzer", "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.From", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true }, { "name": "com.arangodb.entity.AqlExecutionExplainEntity$ExecutionExpression", "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.ServerRole", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.analyzer.SegmentationAnalyzerProperties$BreakMode", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.AnalyzerFeature", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.ReplicationFactor$SatelliteReplicationFactor", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.ArangoDBEngine$StorageEngineName", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.StreamTransactionStatus", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.QueryExecutionState", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.LogLevel", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.QueryCachePropertiesEntity$CacheMode", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.LogLevelEntity$LogLevel", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.StoreValuesType", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.LoadBalancingStrategy", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.IndexType", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.ArangoSearchCompression", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.License", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.CollectionStatus", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.analyzer.SearchAnalyzerCase", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.analyzer.StreamType", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.analyzer.AQLAnalyzerProperties$ReturnType", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.CollectionType", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.KeyType", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.ViewType", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.ServerMode", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.AnalyzerType", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.analyzer.GeoJSONAnalyzerProperties$GeoJSONAnalyzerType", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.ShardingStrategy", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.ConsolidationType", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.Permissions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true }, { "name": "com.arangodb.model.GeoIndexOptions", "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] + "allDeclaredMethods": true, + "allDeclaredConstructors": true }, { "name": "com.arangodb.model.TtlIndexOptions", "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] + "allDeclaredMethods": true, + "allDeclaredConstructors": true }, { "name": "com.arangodb.model.DocumentReadOptions", "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] + "allDeclaredMethods": true, + "allDeclaredConstructors": true }, { "name": "com.arangodb.model.AqlQueryOptions$Optimizer", "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] + "allDeclaredMethods": true, + "allDeclaredConstructors": true }, { "name": "com.arangodb.model.DBCreateOptions", "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] + "allDeclaredMethods": true, + "allDeclaredConstructors": true }, { "name": "com.arangodb.model.VertexCreateOptions", "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] + "allDeclaredMethods": true, + "allDeclaredConstructors": true }, { "name": "com.arangodb.model.AqlFunctionDeleteOptions", "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] + "allDeclaredMethods": true, + "allDeclaredConstructors": true }, { "name": "com.arangodb.model.arangosearch.AnalyzerDeleteOptions", "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] + "allDeclaredMethods": true, + "allDeclaredConstructors": true }, { "name": "com.arangodb.model.AqlQueryOptions", "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] + "allDeclaredMethods": true, + "allDeclaredConstructors": true }, { "name": "com.arangodb.model.FulltextIndexOptions", "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] + "allDeclaredMethods": true, + "allDeclaredConstructors": true }, { "name": "com.arangodb.model.UserUpdateOptions", "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] + "allDeclaredMethods": true, + "allDeclaredConstructors": true }, { "name": "com.arangodb.model.StreamTransactionOptions", "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "com.arangodb.model.TraversalOptions$Uniqueness", - "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] + "allDeclaredMethods": true, + "allDeclaredConstructors": true }, { "name": "com.arangodb.model.DocumentReplaceOptions", "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] + "allDeclaredMethods": true, + "allDeclaredConstructors": true }, { "name": "com.arangodb.model.DatabaseUsersOptions", "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] + "allDeclaredMethods": true, + "allDeclaredConstructors": true }, { "name": "com.arangodb.model.ViewRenameOptions", "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] + "allDeclaredMethods": true, + "allDeclaredConstructors": true }, { "name": "com.arangodb.model.CollectionCreateOptions", "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] + "allDeclaredMethods": true, + "allDeclaredConstructors": true }, { "name": "com.arangodb.model.AqlQueryExplainOptions$Options", "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] + "allDeclaredMethods": true, + "allDeclaredConstructors": true }, { "name": "com.arangodb.model.ViewCreateOptions", "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] + "allDeclaredMethods": true, + "allDeclaredConstructors": true }, { "name": "com.arangodb.model.VertexCollectionCreateOptions$Options", "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.arangosearch.ArangoSearchOptionsBuilder", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true }, { "name": "com.arangodb.model.AqlQueryParseOptions", "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] + "allDeclaredMethods": true, + "allDeclaredConstructors": true }, { "name": "com.arangodb.model.UserAccessOptions", "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] + "allDeclaredMethods": true, + "allDeclaredConstructors": true }, { "name": "com.arangodb.model.HashIndexOptions", "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] + "allDeclaredMethods": true, + "allDeclaredConstructors": true }, { "name": "com.arangodb.model.arangosearch.ArangoSearchPropertiesOptions", "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] + "allDeclaredMethods": true, + "allDeclaredConstructors": true }, { "name": "com.arangodb.model.EdgeUpdateOptions", "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] + "allDeclaredMethods": true, + "allDeclaredConstructors": true }, { "name": "com.arangodb.model.VertexCollectionCreateOptions", "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] + "allDeclaredMethods": true, + "allDeclaredConstructors": true }, { "name": "com.arangodb.model.arangosearch.ArangoSearchCreateOptions", "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] + "allDeclaredMethods": true, + "allDeclaredConstructors": true }, { "name": "com.arangodb.model.VertexDeleteOptions", "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] + "allDeclaredMethods": true, + "allDeclaredConstructors": true }, { "name": "com.arangodb.model.EdgeCreateOptions", "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] + "allDeclaredMethods": true, + "allDeclaredConstructors": true }, { "name": "com.arangodb.model.GraphCreateOptions", "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] + "allDeclaredMethods": true, + "allDeclaredConstructors": true }, { "name": "com.arangodb.model.CollectionsReadOptions", "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] + "allDeclaredMethods": true, + "allDeclaredConstructors": true }, { "name": "com.arangodb.model.TransactionOptions", "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] + "allDeclaredMethods": true, + "allDeclaredConstructors": true }, { "name": "com.arangodb.model.CollectionTruncateOptions", "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] + "allDeclaredMethods": true, + "allDeclaredConstructors": true }, { "name": "com.arangodb.model.PersistentIndexOptions", "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] + "allDeclaredMethods": true, + "allDeclaredConstructors": true }, { "name": "com.arangodb.model.SkiplistIndexOptions", "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] + "allDeclaredMethods": true, + "allDeclaredConstructors": true }, { "name": "com.arangodb.model.ZKDIndexOptions", "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] + "allDeclaredMethods": true, + "allDeclaredConstructors": true }, { "name": "com.arangodb.model.CollectionSchema", "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] + "allDeclaredMethods": true, + "allDeclaredConstructors": true }, { "name": "com.arangodb.model.DocumentImportOptions", "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] + "allDeclaredMethods": true, + "allDeclaredConstructors": true }, { "name": "com.arangodb.model.DocumentDeleteOptions", "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] + "allDeclaredMethods": true, + "allDeclaredConstructors": true }, { "name": "com.arangodb.model.AqlQueryOptions$Options", "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] + "allDeclaredMethods": true, + "allDeclaredConstructors": true }, { "name": "com.arangodb.model.EdgeReplaceOptions", "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] + "allDeclaredMethods": true, + "allDeclaredConstructors": true }, { "name": "com.arangodb.model.VertexReplaceOptions", "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] + "allDeclaredMethods": true, + "allDeclaredConstructors": true }, { "name": "com.arangodb.model.DocumentUpdateOptions", "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] + "allDeclaredMethods": true, + "allDeclaredConstructors": true }, { "name": "com.arangodb.model.GraphDocumentReadOptions", "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] + "allDeclaredMethods": true, + "allDeclaredConstructors": true }, { "name": "com.arangodb.model.VertexUpdateOptions", "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.OptionsBuilder", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true }, { "name": "com.arangodb.model.TransactionCollectionOptions", "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] + "allDeclaredMethods": true, + "allDeclaredConstructors": true }, { "name": "com.arangodb.model.LogOptions", "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] + "allDeclaredMethods": true, + "allDeclaredConstructors": true }, { "name": "com.arangodb.model.UserCreateOptions", "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] + "allDeclaredMethods": true, + "allDeclaredConstructors": true }, { "name": "com.arangodb.model.CollectionPropertiesOptions", "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] + "allDeclaredMethods": true, + "allDeclaredConstructors": true }, { "name": "com.arangodb.model.DatabaseOptions", "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] + "allDeclaredMethods": true, + "allDeclaredConstructors": true }, { "name": "com.arangodb.model.DocumentCreateOptions", "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "com.arangodb.model.TraversalOptions", - "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] + "allDeclaredMethods": true, + "allDeclaredConstructors": true }, { "name": "com.arangodb.model.GraphCreateOptions$SmartOptions", "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] + "allDeclaredMethods": true, + "allDeclaredConstructors": true }, { "name": "com.arangodb.model.CollectionCountOptions", "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] + "allDeclaredMethods": true, + "allDeclaredConstructors": true }, { "name": "com.arangodb.model.EdgeDeleteOptions", "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] + "allDeclaredMethods": true, + "allDeclaredConstructors": true }, { "name": "com.arangodb.model.IndexOptions", "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] + "allDeclaredMethods": true, + "allDeclaredConstructors": true }, { "name": "com.arangodb.model.CollectionRenameOptions", "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] + "allDeclaredMethods": true, + "allDeclaredConstructors": true }, { "name": "com.arangodb.model.DocumentExistsOptions", "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] + "allDeclaredMethods": true, + "allDeclaredConstructors": true }, { "name": "com.arangodb.model.AqlFunctionGetOptions", "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "java.lang.Object", - "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] + "allDeclaredMethods": true, + "allDeclaredConstructors": true }, { "name": "com.arangodb.model.AqlFunctionCreateOptions", "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] + "allDeclaredMethods": true, + "allDeclaredConstructors": true }, { "name": "com.arangodb.model.AqlQueryExplainOptions$Optimizer", "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] + "allDeclaredMethods": true, + "allDeclaredConstructors": true }, { "name": "com.arangodb.model.AqlQueryExplainOptions", "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.QueueTimeSample", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.DocumentImportOptions$OnDuplicate", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.OverwriteMode", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.ImportType", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.LogOptions$SortOrder", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.CollectionSchema$Level", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.ZKDIndexOptions$FieldValueTypes", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.internal.cursor.entity.InternalCursorEntity", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.internal.cursor.entity.InternalCursorEntity$Extras", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true } ] diff --git a/src/test/java/helper/NativeImageHelper.java b/src/test/java/helper/NativeImageHelper.java index 39bb227e5..5ec356589 100644 --- a/src/test/java/helper/NativeImageHelper.java +++ b/src/test/java/helper/NativeImageHelper.java @@ -1,19 +1,20 @@ package helper; import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonDeserializer; +import com.fasterxml.jackson.databind.JsonSerializer; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.node.ArrayNode; import com.fasterxml.jackson.databind.node.ObjectNode; import org.reflections.Reflections; -import org.reflections.scanners.MethodParameterScanner; +import org.reflections.scanners.SubTypesScanner; import org.reflections.util.ClasspathHelper; import org.reflections.util.ConfigurationBuilder; import org.reflections.util.FilterBuilder; -import java.lang.reflect.Constructor; -import java.lang.reflect.Modifier; import java.util.Arrays; import java.util.List; +import java.util.stream.Stream; /** * Helper scripts to generate GraalVM native image configuration @@ -30,33 +31,52 @@ private static void generateReflectConfig() throws JsonProcessingException { System.out.println("--- reflect-config.json ---"); System.out.println("---------------------------"); - List packages = Arrays.asList("com.arangodb.entity", "com.arangodb.model"); + List packages = Arrays.asList( + "com.arangodb.entity", + "com.arangodb.model", + "com.arangodb.internal.cursor.entity" + ); ObjectMapper mapper = new ObjectMapper(); ArrayNode rootNode = mapper.createArrayNode(); - ObjectNode noArgConstructor = mapper.createObjectNode(); - noArgConstructor.put("name", ""); - noArgConstructor.set("parameterTypes", mapper.createArrayNode()); - ArrayNode methods = mapper.createArrayNode(); - methods.add(noArgConstructor); - packages.stream() + String serdePackage = "com.arangodb.serde"; + Reflections r = new Reflections(new ConfigurationBuilder() + .setScanners(new SubTypesScanner(false)) + .setUrls(ClasspathHelper.forPackage(serdePackage)) + .filterInputsBy(new FilterBuilder().includePackage(serdePackage))); + Stream serializers = r.getSubTypesOf(JsonSerializer.class).stream() + .filter(it -> !it.isAnonymousClass()) + .map(Class::getName); + Stream deserializers = r.getSubTypesOf(JsonDeserializer.class).stream() + .filter(it -> !it.isAnonymousClass()) + .map(Class::getName); + Stream serdeClasses = Stream.concat(serializers, deserializers) + .filter(it -> it.contains("InternalSerializers") || it.contains("InternalDeserializers")); + + Stream entityClasses = packages.stream() .flatMap(p -> { final ConfigurationBuilder config = new ConfigurationBuilder() - .setScanners(new MethodParameterScanner()) + .setScanners(new SubTypesScanner(false)) .setUrls(ClasspathHelper.forPackage(p)) .filterInputsBy(new FilterBuilder().includePackage(p)); - return new Reflections(config).getConstructorsMatchParams().stream(); - }) - .filter((it -> Modifier.isPublic(it.getDeclaringClass().getModifiers()))) - .filter(it -> Modifier.isPublic(it.getModifiers())) - .map(Constructor::getName) + Reflections reflections = new Reflections(config); + return Stream.concat( + reflections.getAllTypes().stream(), + reflections + .getSubTypesOf(Enum.class) + .stream() + .map(Class::getName) + ); + }); + Stream.concat(serdeClasses, entityClasses) .map(className -> { ObjectNode entry = mapper.createObjectNode(); entry.put("name", className); entry.put("allDeclaredFields", true); - entry.set("methods", methods); + entry.put("allDeclaredMethods", true); + entry.put("allDeclaredConstructors", true); return entry; }) .forEach(rootNode::add); diff --git a/src/test/resources/META-INF/native-image/reflect-config.json b/src/test/resources/META-INF/native-image/reflect-config.json index f3181a2c9..717f0a566 100644 --- a/src/test/resources/META-INF/native-image/reflect-config.json +++ b/src/test/resources/META-INF/native-image/reflect-config.json @@ -74,12 +74,16 @@ ] }, { - "name": "com.arangodb.ArangoCollectionTest$TestUpdateEntity", - "allDeclaredFields": true, - "allDeclaredMethods": true, - "allPublicMethods": true, - "allDeclaredConstructors": true, - "allDeclaredClasses": true + "name":"com.arangodb.ArangoCollectionTest$TestUpdateEntity", + "allDeclaredFields":true, + "allDeclaredMethods":true, + "allDeclaredConstructors":true + }, + { + "name":"com.arangodb.ArangoCollectionTest$TestUpdateEntitySerializeNullFalse", + "allDeclaredFields":true, + "allDeclaredMethods":true, + "allDeclaredConstructors":true }, { "name": "com.arangodb.ArangoDatabaseTest$TransactionTestEntity", @@ -207,335 +211,6 @@ "allDeclaredConstructors": true, "allDeclaredClasses": true }, - { - "name": "com.arangodb.mapping.VPackSerializeDeserializeTest$BinaryEntity", - "allDeclaredFields": true, - "allDeclaredMethods": true, - "allDeclaredConstructors": true - }, - { - "name": "com.arangodb.mapping.VPackSerializeDeserializeTest$CustomAnEntity", - "allDeclaredFields": true, - "allDeclaredMethods": true, - "allDeclaredConstructors": true, - "allDeclaredClasses": true - }, - { - "name": "com.arangodb.mapping.VPackSerializeDeserializeTest$CustomFilterAnnotation" - }, - { - "name": "com.arangodb.mapping.VPackSerializeDeserializeTest$CustomNamingAnnotation" - }, - { - "name": "com.arangodb.mapping.VPackSerializeDeserializeTest$TestCollection", - "allDeclaredFields": true, - "allDeclaredMethods": true, - "allPublicMethods": true, - "allDeclaredConstructors": true, - "allDeclaredClasses": true - }, - { - "name": "com.arangodb.mapping.VPackSerializeDeserializeTest$TestEntityA", - "allDeclaredFields": true, - "allDeclaredMethods": true, - "allPublicMethods": true, - "allDeclaredConstructors": true, - "allDeclaredClasses": true - }, - { - "name": "com.arangodb.mapping.VPackSerializeDeserializeTest$TestEntityArray", - "allDeclaredFields": true, - "allDeclaredMethods": true, - "allPublicMethods": true, - "allDeclaredConstructors": true, - "allDeclaredClasses": true - }, - { - "name": "com.arangodb.mapping.VPackSerializeDeserializeTest$TestEntityArrayInArray", - "allDeclaredFields": true, - "allDeclaredMethods": true, - "allPublicMethods": true, - "allDeclaredConstructors": true, - "allDeclaredClasses": true - }, - { - "name": "com.arangodb.mapping.VPackSerializeDeserializeTest$TestEntityArrayInArrayInArray", - "allDeclaredFields": true, - "allDeclaredMethods": true, - "allPublicMethods": true, - "allDeclaredConstructors": true, - "allDeclaredClasses": true - }, - { - "name": "com.arangodb.mapping.VPackSerializeDeserializeTest$TestEntityB", - "allDeclaredFields": true, - "allDeclaredMethods": true, - "allPublicMethods": true, - "allDeclaredConstructors": true, - "allDeclaredClasses": true - }, - { - "name": "com.arangodb.mapping.VPackSerializeDeserializeTest$TestEntityBaseAttributes", - "allDeclaredFields": true, - "allDeclaredMethods": true, - "allPublicMethods": true, - "allDeclaredConstructors": true, - "allDeclaredClasses": true - }, - { - "name": "com.arangodb.mapping.VPackSerializeDeserializeTest$TestEntityBigNumber", - "allDeclaredFields": true, - "allDeclaredMethods": true, - "allPublicMethods": true, - "allDeclaredConstructors": true, - "allDeclaredClasses": true - }, - { - "name": "com.arangodb.mapping.VPackSerializeDeserializeTest$TestEntityBoolean", - "allDeclaredFields": true, - "allDeclaredMethods": true, - "allPublicMethods": true, - "allDeclaredConstructors": true, - "allDeclaredClasses": true - }, - { - "name": "com.arangodb.mapping.VPackSerializeDeserializeTest$TestEntityByte", - "allDeclaredFields": true, - "allDeclaredMethods": true, - "allPublicMethods": true, - "allDeclaredConstructors": true, - "allDeclaredClasses": true - }, - { - "name": "com.arangodb.mapping.VPackSerializeDeserializeTest$TestEntityC", - "allDeclaredFields": true, - "allDeclaredMethods": true, - "allPublicMethods": true, - "allDeclaredConstructors": true, - "allDeclaredClasses": true - }, - { - "name": "com.arangodb.mapping.VPackSerializeDeserializeTest$TestEntityCollection", - "allDeclaredFields": true, - "allDeclaredMethods": true, - "allPublicMethods": true, - "allDeclaredConstructors": true, - "allDeclaredClasses": true - }, - { - "name": "com.arangodb.mapping.VPackSerializeDeserializeTest$TestEntityCollectionExtendedWithNulls", - "allDeclaredFields": true, - "allDeclaredMethods": true, - "allPublicMethods": true, - "allDeclaredConstructors": true, - "allDeclaredClasses": true - }, - { - "name": "com.arangodb.mapping.VPackSerializeDeserializeTest$TestEntityCollectionWithObjects", - "allDeclaredFields": true, - "allDeclaredMethods": true, - "allPublicMethods": true, - "allDeclaredConstructors": true, - "allDeclaredClasses": true - }, - { - "name": "com.arangodb.mapping.VPackSerializeDeserializeTest$TestEntityD", - "allDeclaredMethods": true, - "allPublicMethods": true, - "allDeclaredConstructors": true, - "allDeclaredClasses": true - }, - { - "name": "com.arangodb.mapping.VPackSerializeDeserializeTest$TestEntityDImpl", - "allDeclaredFields": true, - "allDeclaredMethods": true, - "allPublicMethods": true, - "allDeclaredConstructors": true, - "allDeclaredClasses": true - }, - { - "name": "com.arangodb.mapping.VPackSerializeDeserializeTest$TestEntityDate", - "allDeclaredFields": true, - "allDeclaredMethods": true, - "allPublicMethods": true, - "allDeclaredConstructors": true, - "allDeclaredClasses": true - }, - { - "name": "com.arangodb.mapping.VPackSerializeDeserializeTest$TestEntityDouble", - "allDeclaredFields": true, - "allDeclaredMethods": true, - "allPublicMethods": true, - "allDeclaredConstructors": true, - "allDeclaredClasses": true - }, - { - "name": "com.arangodb.mapping.VPackSerializeDeserializeTest$TestEntityEmpty", - "allDeclaredFields": true, - "allDeclaredMethods": true, - "allPublicMethods": true, - "allDeclaredConstructors": true, - "allDeclaredClasses": true - }, - { - "name": "com.arangodb.mapping.VPackSerializeDeserializeTest$TestEntityEmptyMap", - "allDeclaredFields": true, - "allDeclaredMethods": true, - "allPublicMethods": true, - "allDeclaredConstructors": true, - "allDeclaredClasses": true - }, - { - "name": "com.arangodb.mapping.VPackSerializeDeserializeTest$TestEntityEnum", - "allDeclaredFields": true, - "allDeclaredMethods": true, - "allPublicMethods": true, - "allDeclaredConstructors": true, - "allDeclaredClasses": true - }, - { - "name": "com.arangodb.mapping.VPackSerializeDeserializeTest$TestEntityFloat", - "allDeclaredFields": true, - "allDeclaredMethods": true, - "allPublicMethods": true, - "allDeclaredConstructors": true, - "allDeclaredClasses": true - }, - { - "name": "com.arangodb.mapping.VPackSerializeDeserializeTest$TestEntityInteger", - "allDeclaredFields": true, - "allDeclaredMethods": true, - "allPublicMethods": true, - "allDeclaredConstructors": true, - "allDeclaredClasses": true - }, - { - "name": "com.arangodb.mapping.VPackSerializeDeserializeTest$TestEntityLong", - "allDeclaredFields": true, - "allDeclaredMethods": true, - "allPublicMethods": true, - "allDeclaredConstructors": true, - "allDeclaredClasses": true - }, - { - "name": "com.arangodb.mapping.VPackSerializeDeserializeTest$TestEntityMap", - "allDeclaredFields": true, - "allDeclaredMethods": true, - "allPublicMethods": true, - "allDeclaredConstructors": true, - "allDeclaredClasses": true - }, - { - "name": "com.arangodb.mapping.VPackSerializeDeserializeTest$TestEntityMapStringableKey", - "allDeclaredFields": true, - "allDeclaredMethods": true, - "allPublicMethods": true, - "allDeclaredConstructors": true, - "allDeclaredClasses": true - }, - { - "name": "com.arangodb.mapping.VPackSerializeDeserializeTest$TestEntityMapWithObjectKey", - "allDeclaredFields": true, - "allDeclaredMethods": true, - "allPublicMethods": true, - "allDeclaredConstructors": true, - "allDeclaredClasses": true - }, - { - "name": "com.arangodb.mapping.VPackSerializeDeserializeTest$TestEntityObject", - "allDeclaredFields": true, - "allDeclaredMethods": true, - "allPublicMethods": true, - "allDeclaredConstructors": true, - "allDeclaredClasses": true - }, - { - "name": "com.arangodb.mapping.VPackSerializeDeserializeTest$TestEntityObjectInArray", - "allDeclaredFields": true, - "allDeclaredMethods": true, - "allPublicMethods": true, - "allDeclaredConstructors": true, - "allDeclaredClasses": true - }, - { - "name": "com.arangodb.mapping.VPackSerializeDeserializeTest$TestEntityShort", - "allDeclaredFields": true, - "allDeclaredMethods": true, - "allPublicMethods": true, - "allDeclaredConstructors": true, - "allDeclaredClasses": true - }, - { - "name": "com.arangodb.mapping.VPackSerializeDeserializeTest$TestEntityString", - "allDeclaredFields": true, - "allDeclaredMethods": true, - "allPublicMethods": true, - "allDeclaredConstructors": true, - "allDeclaredClasses": true - }, - { - "name": "com.arangodb.mapping.VPackSerializeDeserializeTest$TestEntityTyped", - "allDeclaredFields": true, - "allDeclaredMethods": true, - "allPublicMethods": true, - "allDeclaredConstructors": true, - "allDeclaredClasses": true - }, - { - "name": "com.arangodb.mapping.VPackSerializeDeserializeTest$TestEntityUUID", - "allDeclaredFields": true, - "allDeclaredMethods": true, - "allPublicMethods": true, - "allDeclaredConstructors": true, - "allDeclaredClasses": true - }, - { - "name": "com.arangodb.mapping.VPackSerializeDeserializeTest$TestEnum", - "allDeclaredFields": true, - "allDeclaredMethods": true, - "allPublicMethods": true, - "allDeclaredClasses": true - }, - { - "name": "com.arangodb.mapping.annotations.DocumentFieldEntity", - "allDeclaredFields": true, - "allDeclaredMethods": true, - "allPublicMethods": true, - "allDeclaredConstructors": true, - "allDeclaredClasses": true - }, - { - "name": "com.arangodb.mapping.annotations.AnnotatedEntity", - "allDeclaredFields": true, - "allDeclaredMethods": true, - "allPublicMethods": true, - "allDeclaredConstructors": true, - "allDeclaredClasses": true - }, - { - "name": "com.arangodb.mapping.annotations.ExposeEntity", - "allDeclaredFields": true, - "allDeclaredMethods": true, - "allPublicMethods": true, - "allDeclaredConstructors": true, - "allDeclaredClasses": true - }, - { - "name": "com.arangodb.mapping.annotations.SerializedNameEntity", - "allDeclaredFields": true, - "allDeclaredMethods": true, - "allPublicMethods": true, - "allDeclaredConstructors": true, - "allDeclaredClasses": true - }, - { - "name": "com.arangodb.mapping.annotations.SerializedNameParameterEntity", - "allDeclaredFields": true, - "allDeclaredMethods": true, - "allPublicMethods": true, - "allDeclaredConstructors": true, - "allDeclaredClasses": true - }, { "name": "com.arangodb.serde.CustomSerdeTest$Person", "allDeclaredFields": true, @@ -587,5 +262,11 @@ "name": "java.util.HashSet", "allDeclaredMethods": true, "allDeclaredConstructors": true + }, + { + "name":"com.arangodb.mapping.annotations.AnnotatedEntity", + "allDeclaredFields":true, + "allDeclaredMethods":true, + "allDeclaredConstructors":true } ] From 4b69a2f6dda45e8603430f2f6371e9a05b012619 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Thu, 28 Jul 2022 10:04:10 +0200 Subject: [PATCH 050/254] removed VPack tests --- .../VPackSerializeDeserializeTest.java | 3304 ----------------- 1 file changed, 3304 deletions(-) delete mode 100644 src/test/java/com/arangodb/mapping/VPackSerializeDeserializeTest.java diff --git a/src/test/java/com/arangodb/mapping/VPackSerializeDeserializeTest.java b/src/test/java/com/arangodb/mapping/VPackSerializeDeserializeTest.java deleted file mode 100644 index ceefb66a0..000000000 --- a/src/test/java/com/arangodb/mapping/VPackSerializeDeserializeTest.java +++ /dev/null @@ -1,3304 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - - -package com.arangodb.mapping; - -// TODO: move these tests to velocypack-java project - -//import com.arangodb.velocypack.*; -//import com.fasterxml.jackson.core.JsonProcessingException; -//import com.fasterxml.jackson.databind.ObjectMapper; -//import org.junit.jupiter.api.Test; -// -//import java.io.IOException; -//import java.lang.annotation.ElementType; -//import java.lang.annotation.Retention; -//import java.lang.annotation.RetentionPolicy; -//import java.lang.annotation.Target; -//import java.math.BigDecimal; -//import java.math.BigInteger; -//import java.text.DateFormat; -//import java.text.SimpleDateFormat; -//import java.util.*; -//import java.util.Map.Entry; -// -//import static org.assertj.core.api.Assertions.assertThat; -// -///** -// * @author Mark Vollmary -// */ -//class VPackSerializeDeserializeTest { -// -// private static final DateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");// ISO 8601 -// -// static { -// DATE_FORMAT.setTimeZone(TimeZone.getTimeZone("UTC")); -// } -// -// private final ObjectMapper mapper = ArangoJack.createDefaultMapper(); -// -// public static class TestEntityBoolean { -// private boolean a = true; -// private boolean b = false; -// private Boolean c = Boolean.TRUE; -// private Boolean d = Boolean.FALSE; -// -// public boolean isA() { -// return a; -// } -// -// public void setA(final boolean a) { -// this.a = a; -// } -// -// public boolean isB() { -// return b; -// } -// -// public void setB(final boolean b) { -// this.b = b; -// } -// -// public Boolean getC() { -// return c; -// } -// -// public void setC(final Boolean c) { -// this.c = c; -// } -// -// public Boolean getD() { -// return d; -// } -// -// public void setD(final Boolean d) { -// this.d = d; -// } -// } -// -// @Test -// void fromBoolean() throws JsonProcessingException { -// final VPackSlice vpack = new VPackSlice(mapper.writeValueAsBytes(new TestEntityBoolean())); -// assertThat(vpack).isNotNull(); -// assertThat(vpack.isObject()).isTrue(); -// { -// final VPackSlice a = vpack.get("a"); -// assertThat(a.isBoolean()).isTrue(); -// assertThat(a.getAsBoolean()).isTrue(); -// } -// { -// final VPackSlice b = vpack.get("b"); -// assertThat(b.isBoolean()).isTrue(); -// assertThat(b.getAsBoolean()).isFalse(); -// } -// { -// final VPackSlice c = vpack.get("c"); -// assertThat(c.isBoolean()).isTrue(); -// assertThat(c.getAsBoolean()).isTrue(); -// } -// { -// final VPackSlice d = vpack.get("d"); -// assertThat(d.isBoolean()).isTrue(); -// assertThat(d.getAsBoolean()).isFalse(); -// } -// } -// -// @Test -// void toBoolean() throws IOException { -// final VPackBuilder builder = new VPackBuilder(); -// { -// builder.add(ValueType.OBJECT); -// builder.add("a", false); -// builder.add("b", true); -// builder.add("c", Boolean.FALSE); -// builder.add("d", Boolean.TRUE); -// builder.close(); -// } -// final VPackSlice vpack = builder.slice(); -// final TestEntityBoolean entity = mapper.readValue(vpack.getBuffer(), TestEntityBoolean.class); -// assertThat(entity).isNotNull(); -// assertThat(entity.a).isFalse(); -// assertThat(entity.b).isTrue(); -// assertThat(entity.c).isInstanceOf(Boolean.class).isFalse(); -// assertThat(entity.d).isInstanceOf(Boolean.class).isTrue(); -// } -// -// public static class TestEntityString { -// private String s = "test"; -// private Character c1 = 't'; -// private char c2 = 't'; -// -// public String getS() { -// return s; -// } -// -// public void setS(final String s) { -// this.s = s; -// } -// -// public Character getC1() { -// return c1; -// } -// -// public void setC1(final Character c1) { -// this.c1 = c1; -// } -// -// public char getC2() { -// return c2; -// } -// -// public void setC2(final char c2) { -// this.c2 = c2; -// } -// } -// -// @Test -// void fromStrings() throws JsonProcessingException { -// final VPackSlice vpack = new VPackSlice(mapper.writeValueAsBytes(new TestEntityString())); -// assertThat(vpack).isNotNull(); -// assertThat(vpack.isObject()).isTrue(); -// { -// final VPackSlice s = vpack.get("s"); -// assertThat(s.isString()).isTrue(); -// assertThat(s.getAsString()).isEqualTo("test"); -// } -// { -// final VPackSlice c1 = vpack.get("c1"); -// assertThat(c1.isString()).isTrue(); -// assertThat(c1.getAsChar()).isEqualTo('t'); -// } -// { -// final VPackSlice c2 = vpack.get("c2"); -// assertThat(c2.isString()).isTrue(); -// assertThat(c2.getAsChar()).isEqualTo('t'); -// } -// } -// -// @Test -// void toStrings() throws IOException { -// final VPackBuilder builder = new VPackBuilder(); -// { -// builder.add(ValueType.OBJECT); -// builder.add("s", "abc"); -// builder.add("c1", 'd'); -// builder.add("c2", 'd'); -// builder.close(); -// } -// final VPackSlice vpack = builder.slice(); -// final TestEntityString entity = mapper.readValue(vpack.getBuffer(), TestEntityString.class); -// assertThat(entity).isNotNull(); -// assertThat(entity.s).isEqualTo("abc"); -// assertThat(entity.c1).isEqualTo(new Character('d')); -// } -// -// public static class TestEntityInteger { -// private int i1 = 1; -// private Integer i2 = 1; -// -// public int getI1() { -// return i1; -// } -// -// public void setI1(final int i1) { -// this.i1 = i1; -// } -// -// public Integer getI2() { -// return i2; -// } -// -// public void setI2(final Integer i2) { -// this.i2 = i2; -// } -// } -// -// @Test -// void fromInteger() throws JsonProcessingException { -// final VPackSlice vpack = new VPackSlice(mapper.writeValueAsBytes(new TestEntityInteger())); -// assertThat(vpack).isNotNull(); -// assertThat(vpack.isObject()).isTrue(); -// { -// final VPackSlice i1 = vpack.get("i1"); -// assertThat(i1.isInteger()).isTrue(); -// assertThat(i1.getAsInt()).isEqualTo(1); -// } -// { -// final VPackSlice i2 = vpack.get("i2"); -// assertThat(i2.isInteger()).isTrue(); -// assertThat(i2.getAsInt()).isEqualTo(1); -// } -// } -// -// @Test -// void fromNegativeInteger() throws JsonProcessingException { -// final TestEntityInteger entity = new TestEntityInteger(); -// entity.i1 = -50; -// entity.i2 = -50; -// final VPackSlice vpack = new VPackSlice(mapper.writeValueAsBytes(entity)); -// assertThat(vpack).isNotNull(); -// assertThat(vpack.isObject()).isTrue(); -// { -// final VPackSlice i1 = vpack.get("i1"); -// assertThat(i1.isInteger()).isTrue(); -// assertThat(i1.getAsInt()).isEqualTo(-50); -// } -// { -// final VPackSlice i2 = vpack.get("i2"); -// assertThat(i2.isInteger()).isTrue(); -// assertThat(i2.getAsInt()).isEqualTo(-50); -// } -// } -// -// @Test -// void toInteger() throws IOException { -// final VPackBuilder builder = new VPackBuilder(); -// { -// builder.add(ValueType.OBJECT); -// builder.add("i1", 2); -// builder.add("i2", 3); -// builder.close(); -// } -// final VPackSlice vpack = builder.slice(); -// final TestEntityInteger entity = mapper.readValue(vpack.getBuffer(), TestEntityInteger.class); -// assertThat(entity).isNotNull(); -// assertThat(entity.i1).isEqualTo(2); -// assertThat(entity.i2).isEqualTo(Integer.valueOf(3)); -// } -// -// @Test -// void toNegativeInteger() throws IOException { -// final VPackBuilder builder = new VPackBuilder(); -// { -// builder.add(ValueType.OBJECT); -// builder.add("i1", -50); -// builder.add("i2", -50); -// builder.close(); -// } -// final VPackSlice vpack = builder.slice(); -// final TestEntityInteger entity = mapper.readValue(vpack.getBuffer(), TestEntityInteger.class); -// assertThat(entity).isNotNull(); -// assertThat(entity.i1).isEqualTo(-50); -// assertThat(entity.i2).isEqualTo(Integer.valueOf(-50)); -// } -// -// public static class TestEntityLong { -// private long l1 = 1; -// private Long l2 = 1L; -// -// public long getL1() { -// return l1; -// } -// -// public void setL1(final long l1) { -// this.l1 = l1; -// } -// -// public Long getL2() { -// return l2; -// } -// -// public void setL2(final Long l2) { -// this.l2 = l2; -// } -// } -// -// @Test -// void fromLong() throws JsonProcessingException { -// final VPackSlice vpack = new VPackSlice(mapper.writeValueAsBytes(new TestEntityLong())); -// assertThat(vpack).isNotNull(); -// assertThat(vpack.isObject()).isTrue(); -// { -// final VPackSlice l1 = vpack.get("l1"); -// assertThat(l1.isInteger()).isTrue(); -// assertThat(l1.getAsLong()).isEqualTo(1L); -// } -// { -// final VPackSlice l2 = vpack.get("l2"); -// assertThat(l2.isInteger()).isTrue(); -// assertThat(l2.getAsLong()).isEqualTo(1L); -// } -// } -// -// @Test -// void fromNegativeLong() throws JsonProcessingException { -// final TestEntityLong entity = new TestEntityLong(); -// entity.l1 = -100L; -// entity.l2 = -300L; -// final VPackSlice vpack = new VPackSlice(mapper.writeValueAsBytes(entity)); -// assertThat(vpack).isNotNull(); -// assertThat(vpack.isObject()).isTrue(); -// { -// final VPackSlice l1 = vpack.get("l1"); -// assertThat(l1.isInteger()).isTrue(); -// assertThat(l1.getAsLong()).isEqualTo(-100L); -// } -// { -// final VPackSlice l2 = vpack.get("l2"); -// assertThat(l2.isInteger()).isTrue(); -// assertThat(l2.getAsLong()).isEqualTo(-300); -// } -// } -// -// @Test -// void toLong() throws IOException { -// final VPackBuilder builder = new VPackBuilder(); -// { -// builder.add(ValueType.OBJECT); -// builder.add("l1", 2); -// builder.add("l2", 3); -// builder.close(); -// } -// final VPackSlice vpack = builder.slice(); -// final TestEntityLong entity = mapper.readValue(vpack.getBuffer(), TestEntityLong.class); -// assertThat(entity).isNotNull(); -// assertThat(entity.l1).isEqualTo(2); -// assertThat(entity.l2).isEqualTo(Long.valueOf(3)); -// } -// -// @Test -// void toNegativeLong() throws IOException { -// final VPackBuilder builder = new VPackBuilder(); -// { -// builder.add(ValueType.OBJECT); -// builder.add("l1", -100L); -// builder.add("l2", -300L); -// builder.close(); -// } -// final VPackSlice vpack = builder.slice(); -// final TestEntityLong entity = mapper.readValue(vpack.getBuffer(), TestEntityLong.class); -// assertThat(entity).isNotNull(); -// assertThat(entity.l1).isEqualTo(-100L); -// assertThat(entity.l2).isEqualTo(Long.valueOf(-300)); -// } -// -// @Test -// void negativeLong() { -// final TestEntityLong entity = new TestEntityLong(); -// entity.l1 = -100L; -// entity.l2 = -300L; -// final VPack vp = new VPack.Builder().build(); -// final TestEntityLong out = vp.deserialize(vp.serialize(entity), TestEntityLong.class); -// assertThat(out.l1).isEqualTo(entity.l1); -// assertThat(out.l2).isEqualTo(entity.l2); -// } -// -// @Test -// void intToLong() throws IOException { -// final VPackBuilder builder = new VPackBuilder(); -// { -// builder.add(ValueType.OBJECT); -// builder.add("l1", 100); -// builder.add("l2", 300); -// builder.close(); -// } -// final VPackSlice vpack = builder.slice(); -// final TestEntityLong entity = mapper.readValue(vpack.getBuffer(), TestEntityLong.class); -// assertThat(entity).isNotNull(); -// assertThat(entity.l1).isEqualTo(100); -// assertThat(entity.l2).isEqualTo(Long.valueOf(300)); -// } -// -// @Test -// void negativeIntToLong() throws IOException { -// final VPackBuilder builder = new VPackBuilder(); -// { -// builder.add(ValueType.OBJECT); -// builder.add("l1", -100); -// builder.add("l2", -300); -// builder.close(); -// } -// final VPackSlice vpack = builder.slice(); -// final TestEntityLong entity = mapper.readValue(vpack.getBuffer(), TestEntityLong.class); -// assertThat(entity).isNotNull(); -// assertThat(entity.l1).isEqualTo(-100L); -// assertThat(entity.l2).isEqualTo(Long.valueOf(-300)); -// } -// -// @Test -// void negativeLongToInt() throws IOException { -// final VPackBuilder builder = new VPackBuilder(); -// { -// builder.add(ValueType.OBJECT); -// builder.add("i1", -100L); -// builder.add("i2", -300L); -// builder.close(); -// } -// final VPackSlice vpack = builder.slice(); -// final TestEntityInteger entity = mapper.readValue(vpack.getBuffer(), TestEntityInteger.class); -// assertThat(entity).isNotNull(); -// assertThat(entity.i1).isEqualTo(-100); -// assertThat(entity.i2).isEqualTo(Integer.valueOf(-300)); -// } -// -// @Test -// void negativeLongToShort() throws IOException { -// final VPackBuilder builder = new VPackBuilder(); -// { -// builder.add(ValueType.OBJECT); -// builder.add("s1", -100L); -// builder.add("s2", -300L); -// builder.close(); -// } -// final VPackSlice vpack = builder.slice(); -// final TestEntityShort entity = mapper.readValue(vpack.getBuffer(), TestEntityShort.class); -// assertThat(entity).isNotNull(); -// assertThat(entity.s1).isEqualTo((short) -100); -// assertThat(entity.s2).isEqualTo(Short.valueOf((short) -300)); -// } -// -// @Test -// void negativeShortToLong() throws IOException { -// final VPackBuilder builder = new VPackBuilder(); -// { -// builder.add(ValueType.OBJECT); -// builder.add("l1", (short) -100); -// builder.add("l2", (short) -300); -// builder.close(); -// } -// final VPackSlice vpack = builder.slice(); -// final TestEntityLong entity = mapper.readValue(vpack.getBuffer(), TestEntityLong.class); -// assertThat(entity).isNotNull(); -// assertThat(entity.l1).isEqualTo(-100L); -// assertThat(entity.l2).isEqualTo(Long.valueOf(-300)); -// } -// -// public static class TestEntityFloat { -// private float f1 = 1; -// private Float f2 = 1F; -// -// public float getF1() { -// return f1; -// } -// -// public void setF1(final float f1) { -// this.f1 = f1; -// } -// -// public Float getF2() { -// return f2; -// } -// -// public void setF2(final Float f2) { -// this.f2 = f2; -// } -// } -// -// @Test -// void fromFloat() throws JsonProcessingException { -// final VPackSlice vpack = new VPackSlice(mapper.writeValueAsBytes(new TestEntityFloat())); -// assertThat(vpack).isNotNull(); -// assertThat(vpack.isObject()).isTrue(); -// { -// final VPackSlice f1 = vpack.get("f1"); -// assertThat(f1.isDouble()).isTrue(); -// assertThat(f1.getAsFloat()).isEqualTo(1.0F); -// } -// { -// final VPackSlice f2 = vpack.get("f2"); -// assertThat(f2.isDouble()).isTrue(); -// assertThat(f2.getAsFloat()).isEqualTo(1.0F); -// } -// } -// -// @Test -// void toFloat() throws IOException { -// final VPackBuilder builder = new VPackBuilder(); -// { -// builder.add(ValueType.OBJECT); -// builder.add("f1", 2F); -// builder.add("f2", 3F); -// builder.close(); -// } -// final VPackSlice vpack = builder.slice(); -// final TestEntityFloat entity = mapper.readValue(vpack.getBuffer(), TestEntityFloat.class); -// assertThat(entity).isNotNull(); -// assertThat(entity.f1).isEqualTo(2F); -// assertThat(entity.f2).isEqualTo(new Float(3)); -// } -// -// public static class TestEntityShort { -// private short s1 = 1; -// private Short s2 = 1; -// -// public short getS1() { -// return s1; -// } -// -// public void setS1(final short s1) { -// this.s1 = s1; -// } -// -// public Short getS2() { -// return s2; -// } -// -// public void setS2(final Short s2) { -// this.s2 = s2; -// } -// } -// -// @Test -// void fromShort() throws JsonProcessingException { -// final VPackSlice vpack = new VPackSlice(mapper.writeValueAsBytes(new TestEntityShort())); -// assertThat(vpack).isNotNull(); -// assertThat(vpack.isObject()).isTrue(); -// { -// final VPackSlice s1 = vpack.get("s1"); -// assertThat(s1.isInteger()).isTrue(); -// assertThat(s1.getAsShort()).isEqualTo((short) 1); -// } -// { -// final VPackSlice s2 = vpack.get("s2"); -// assertThat(s2.isInteger()).isTrue(); -// assertThat(s2.getAsShort()).isEqualTo((short) 1); -// } -// } -// -// @Test -// void toShort() throws IOException { -// final VPackBuilder builder = new VPackBuilder(); -// { -// builder.add(ValueType.OBJECT); -// builder.add("s1", 2); -// builder.add("s2", 3); -// builder.close(); -// } -// final VPackSlice vpack = builder.slice(); -// final TestEntityShort entity = mapper.readValue(vpack.getBuffer(), TestEntityShort.class); -// assertThat(entity).isNotNull(); -// assertThat(entity.s1).isEqualTo((short) 2); -// assertThat(entity.s2).isEqualTo(Short.valueOf((short) 3)); -// } -// -// public static class TestEntityByte { -// private byte b1 = 1; // short integer path -// private Byte b2 = 100; // integer path -// -// public byte getB1() { -// return b1; -// } -// -// public void setB1(final byte b1) { -// this.b1 = b1; -// } -// -// public Byte getB2() { -// return b2; -// } -// -// public void setB2(final Byte b2) { -// this.b2 = b2; -// } -// } -// -// @Test -// void fromByte() throws JsonProcessingException { -// final VPackSlice vpack = new VPackSlice(mapper.writeValueAsBytes(new TestEntityByte())); -// assertThat(vpack).isNotNull(); -// assertThat(vpack.isObject()).isTrue(); -// { -// final VPackSlice b1 = vpack.get("b1"); -// assertThat(b1.isInteger()).isTrue(); -// assertThat(b1.getAsByte()).isEqualTo((byte) 1); -// } -// { -// final VPackSlice b2 = vpack.get("b2"); -// assertThat(b2.isInteger()).isTrue(); -// assertThat(b2.getAsByte()).isEqualTo((byte) 100); -// } -// } -// -// @Test -// void toByte() throws IOException { -// final VPackBuilder builder = new VPackBuilder(); -// { -// builder.add(ValueType.OBJECT); -// builder.add("b1", 30); // integer path -// builder.add("b2", 4); // short integer path -// builder.close(); -// } -// final VPackSlice vpack = builder.slice(); -// final TestEntityByte entity = mapper.readValue(vpack.getBuffer(), TestEntityByte.class); -// assertThat(entity).isNotNull(); -// assertThat(entity.b1).isEqualTo((byte) 30); -// assertThat(entity.b2).isEqualTo(Byte.valueOf((byte) 4)); -// } -// -// public static class TestEntityDouble { -// private Double d1 = 1.5; -// private double d2 = 1.5; -// -// public Double getD1() { -// return d1; -// } -// -// public void setD1(final Double d1) { -// this.d1 = d1; -// } -// -// public double getD2() { -// return d2; -// } -// -// public void setD2(final double d2) { -// this.d2 = d2; -// } -// } -// -// @Test -// void fromDouble() throws JsonProcessingException { -// final VPackSlice vpack = new VPackSlice(mapper.writeValueAsBytes(new TestEntityDouble())); -// assertThat(vpack).isNotNull(); -// assertThat(vpack.isObject()).isTrue(); -// { -// final VPackSlice d1 = vpack.get("d1"); -// assertThat(d1.isDouble()).isTrue(); -// assertThat(d1.getAsDouble()).isEqualTo(1.5); -// } -// { -// final VPackSlice d2 = vpack.get("d2"); -// assertThat(d2.isDouble()).isTrue(); -// assertThat(d2.getAsDouble()).isEqualTo(1.5); -// } -// } -// -// @Test -// void toDouble() throws IOException { -// final VPackBuilder builder = new VPackBuilder(); -// { -// builder.add(ValueType.OBJECT); -// builder.add("d1", 2.25); -// builder.add("d2", 3.75); -// builder.close(); -// } -// final VPackSlice vpack = builder.slice(); -// final TestEntityDouble entity = mapper.readValue(vpack.getBuffer(), TestEntityDouble.class); -// assertThat(entity).isNotNull(); -// assertThat(entity.d1).isEqualTo(2.25); -// assertThat(entity.d2).isEqualTo(3.75); -// } -// -// public static class TestEntityBigNumber { -// private static final BigInteger BI = BigInteger.valueOf(Long.MAX_VALUE).add(BigInteger.ONE); -// private static final BigDecimal BD = BigDecimal.valueOf(Double.MAX_VALUE).add(BigDecimal.ONE); -// -// private BigInteger bi = BI; -// private BigDecimal bd = BD; -// -// public BigInteger getBi() { -// return bi; -// } -// -// public void setBi(final BigInteger bi) { -// this.bi = bi; -// } -// -// public BigDecimal getBd() { -// return bd; -// } -// -// public void setBd(final BigDecimal bd) { -// this.bd = bd; -// } -// } -// -// @Test -// void fromBigNumbers() throws JsonProcessingException { -// final VPackSlice vpack = new VPackSlice(mapper.writeValueAsBytes(new TestEntityBigNumber())); -// assertThat(vpack).isNotNull(); -// assertThat(vpack.isObject()).isTrue(); -// { -// final VPackSlice bi = vpack.get("bi"); -// assertThat(bi.isString()).isTrue(); -// assertThat(bi.getAsBigInteger()).isEqualTo(TestEntityBigNumber.BI); -// } -// { -// final VPackSlice bd = vpack.get("bd"); -// assertThat(bd.isString()).isTrue(); -// assertThat(bd.getAsBigDecimal()).isEqualTo(TestEntityBigNumber.BD); -// } -// } -// -// @Test -// void toBigNumbers() throws IOException { -// final VPackBuilder builder = new VPackBuilder(); -// { -// builder.add(ValueType.OBJECT); -// builder.add("bi", BigInteger.valueOf(2)); -// builder.add("bd", BigDecimal.valueOf(3.75)); -// builder.close(); -// } -// final VPackSlice vpack = builder.slice(); -// final TestEntityBigNumber entity = mapper.readValue(vpack.getBuffer(), TestEntityBigNumber.class); -// assertThat(entity).isNotNull(); -// assertThat(entity.bi).isEqualTo(BigInteger.valueOf(2)); -// assertThat(entity.bd).isEqualTo(BigDecimal.valueOf(3.75)); -// } -// -// @Test -// void bigDecimal() { -// final BigDecimal fromDouble = BigDecimal.valueOf(-710.01); -// final BigDecimal fromString = new BigDecimal("-710.01"); -// assertThat(fromDouble).isEqualTo(fromString); -// assertThat(new VPackBuilder().add(fromDouble).slice().getAsBigDecimal()).isEqualTo(fromDouble); -// assertThat(new VPackBuilder().add(fromString).slice().getAsBigDecimal()).isEqualTo(fromDouble); -// } -// -// public static class TestEntityArray { -// private String[] a1 = {"a", "b", "cd"}; -// private int[] a2 = {1, 2, 3, 4, 5}; -// private boolean[] a3 = {true, true, false}; -// private TestEnum[] a4 = TestEnum.values(); -// -// public String[] getA1() { -// return a1; -// } -// -// public void setA1(final String[] a1) { -// this.a1 = a1; -// } -// -// public int[] getA2() { -// return a2; -// } -// -// public void setA2(final int[] a2) { -// this.a2 = a2; -// } -// -// public boolean[] getA3() { -// return a3; -// } -// -// public void setA3(final boolean[] a3) { -// this.a3 = a3; -// } -// -// public TestEnum[] getA4() { -// return a4; -// } -// -// public void setA4(final TestEnum[] a4) { -// this.a4 = a4; -// } -// -// } -// -// @Test -// void fromArray() throws JsonProcessingException { -// final TestEntityArray entity = new TestEntityArray(); -// final VPackSlice vpack = new VPackSlice(mapper.writeValueAsBytes(entity)); -// assertThat(vpack).isNotNull(); -// assertThat(vpack.isObject()).isTrue(); -// { -// final VPackSlice a1 = vpack.get("a1"); -// assertThat(a1.isArray()).isTrue(); -// assertThat(a1.getLength()).isEqualTo(entity.a1.length); -// for (int i = 0; i < a1.getLength(); i++) { -// assertThat(a1.get(i).getAsString()).isEqualTo(entity.a1[i]); -// } -// } -// { -// final VPackSlice a2 = vpack.get("a2"); -// assertThat(a2.isArray()).isTrue(); -// assertThat(a2.getLength()).isEqualTo(entity.a2.length); -// for (int i = 0; i < a2.getLength(); i++) { -// assertThat(a2.get(i).getAsInt()).isEqualTo(entity.a2[i]); -// } -// } -// { -// final VPackSlice a3 = vpack.get("a3"); -// assertThat(a3.isArray()).isTrue(); -// assertThat(a3.getLength()).isEqualTo(entity.a3.length); -// for (int i = 0; i < a3.getLength(); i++) { -// assertThat(a3.get(i).getAsBoolean()).isEqualTo(entity.a3[i]); -// } -// } -// { -// final VPackSlice a4 = vpack.get("a4"); -// assertThat(a4.isArray()).isTrue(); -// assertThat(a4.getLength()).isEqualTo(entity.a4.length); -// for (int i = 0; i < a4.getLength(); i++) { -// assertThat(TestEnum.valueOf(a4.get(i).getAsString())).isEqualTo(entity.a4[i]); -// } -// } -// } -// -// @Test -// void toArray() throws IOException { -// final VPackBuilder builder = new VPackBuilder(); -// { -// builder.add(ValueType.OBJECT); -// { -// builder.add("a1", ValueType.ARRAY); -// builder.add("a"); -// builder.add("b"); -// builder.add("c"); -// builder.close(); -// } -// { -// builder.add("a2", ValueType.ARRAY); -// builder.add(1); -// builder.add(2); -// builder.add(3); -// builder.add(4); -// builder.close(); -// } -// { -// builder.add("a3", ValueType.ARRAY); -// builder.add(false); -// builder.add(true); -// builder.close(); -// } -// { -// builder.add("a4", ValueType.ARRAY); -// builder.add(TestEnum.A.name()); -// builder.add(TestEnum.B.name()); -// builder.close(); -// } -// builder.close(); -// } -// final VPackSlice vpack = builder.slice(); -// final TestEntityArray entity = mapper.readValue(vpack.getBuffer(), TestEntityArray.class); -// assertThat(entity).isNotNull(); -// { -// assertThat(entity.a1).hasSize(3); -// assertThat(entity.a1[0]).isEqualTo("a"); -// assertThat(entity.a1[1]).isEqualTo("b"); -// assertThat(entity.a1[2]).isEqualTo("c"); -// } -// { -// assertThat(entity.a2).hasSize(4); -// assertThat(entity.a2[0]).isEqualTo(1); -// assertThat(entity.a2[1]).isEqualTo(2); -// assertThat(entity.a2[2]).isEqualTo(3); -// assertThat(entity.a2[3]).isEqualTo(4); -// } -// { -// assertThat(entity.a3).hasSize(2); -// assertThat(entity.a3[0]).isFalse(); -// assertThat(entity.a3[1]).isTrue(); -// } -// { -// assertThat(entity.a4).hasSize(2); -// assertThat(entity.a4[0]).isEqualTo(TestEnum.A); -// assertThat(entity.a4[1]).isEqualTo(TestEnum.B); -// } -// } -// -// @Test -// void fromArrayWithNull() throws JsonProcessingException { -// final TestEntityArray entity = new TestEntityArray(); -// entity.a1 = new String[]{"foo", null}; -// -// final VPackSlice vpack = new VPackSlice(mapper.writeValueAsBytes(entity)); -// assertThat(vpack).isNotNull(); -// assertThat(vpack.isObject()).isTrue(); -// -// final VPackSlice a1 = vpack.get("a1"); -// assertThat(a1.isArray()).isTrue(); -// assertThat(a1.size()).isEqualTo(2); -// assertThat(a1.get(0).isString()).isTrue(); -// assertThat(a1.get(0).getAsString()).isEqualTo("foo"); -// assertThat(a1.get(1).isNull()).isTrue(); -// } -// -// protected enum TestEnum { -// A, B, C -// } -// -// public static class TestEntityEnum { -// private TestEnum e1 = TestEnum.A; -// -// public TestEnum getE1() { -// return e1; -// } -// -// public void setE1(final TestEnum e1) { -// this.e1 = e1; -// } -// } -// -// @Test -// void fromEnum() throws JsonProcessingException { -// final VPackSlice vpack = new VPackSlice(mapper.writeValueAsBytes(new TestEntityEnum())); -// assertThat(vpack).isNotNull(); -// assertThat(vpack.isObject()).isTrue(); -// { -// final VPackSlice e1 = vpack.get("e1"); -// assertThat(e1.isString()).isTrue(); -// assertThat(TestEnum.valueOf(e1.getAsString())).isEqualTo(TestEnum.A); -// } -// } -// -// @Test -// void toEnum() throws IOException { -// final VPackBuilder builder = new VPackBuilder(); -// { -// builder.add(ValueType.OBJECT); -// builder.add("e1", TestEnum.B.name()); -// builder.close(); -// } -// final VPackSlice vpack = builder.slice(); -// final TestEntityEnum entity = mapper.readValue(vpack.getBuffer(), TestEntityEnum.class); -// assertThat(entity).isNotNull(); -// assertThat(entity.e1).isEqualTo(TestEnum.B); -// } -// -// public static class TestEntityObject { -// private TestEntityLong o1 = new TestEntityLong(); -// private TestEntityArray o2 = new TestEntityArray(); -// -// public TestEntityLong getO1() { -// return o1; -// } -// -// public void setO1(final TestEntityLong o1) { -// this.o1 = o1; -// } -// -// public TestEntityArray getO2() { -// return o2; -// } -// -// public void setO2(final TestEntityArray o2) { -// this.o2 = o2; -// } -// } -// -// @Test -// void fromObject() throws JsonProcessingException { -// final TestEntityObject entity = new TestEntityObject(); -// final VPackSlice vpack = new VPackSlice(mapper.writeValueAsBytes(entity)); -// assertThat(vpack).isNotNull(); -// assertThat(vpack.isObject()).isTrue(); -// { -// final VPackSlice o1 = vpack.get("o1"); -// assertThat(o1.isObject()).isTrue(); -// { -// final VPackSlice l1 = o1.get("l1"); -// assertThat(l1.isInteger()).isTrue(); -// assertThat(l1.getAsLong()).isEqualTo(1L); -// } -// { -// final VPackSlice l2 = o1.get("l2"); -// assertThat(l2.isInteger()).isTrue(); -// assertThat(l2.getAsLong()).isEqualTo(1L); -// } -// } -// { -// final VPackSlice o2 = vpack.get("o2"); -// assertThat(o2.isObject()).isTrue(); -// { -// final VPackSlice a1 = o2.get("a1"); -// assertThat(a1.isArray()).isTrue(); -// assertThat(a1.getLength()).isEqualTo(entity.o2.a1.length); -// for (int i = 0; i < a1.getLength(); i++) { -// assertThat(a1.get(i).getAsString()).isEqualTo(entity.o2.a1[i]); -// } -// } -// { -// final VPackSlice a2 = o2.get("a2"); -// assertThat(a2.isArray()).isTrue(); -// assertThat(a2.getLength()).isEqualTo(entity.o2.a2.length); -// for (int i = 0; i < a2.getLength(); i++) { -// assertThat(a2.get(i).getAsInt()).isEqualTo(entity.o2.a2[i]); -// } -// } -// { -// final VPackSlice a3 = o2.get("a3"); -// assertThat(a3.isArray()).isTrue(); -// assertThat(a3.getLength()).isEqualTo(entity.o2.a3.length); -// for (int i = 0; i < a3.getLength(); i++) { -// assertThat(a3.get(i).getAsBoolean()).isEqualTo(entity.o2.a3[i]); -// } -// } -// { -// final VPackSlice a4 = o2.get("a4"); -// assertThat(a4.isArray()).isTrue(); -// assertThat(a4.getLength()).isEqualTo(entity.o2.a4.length); -// for (int i = 0; i < a4.getLength(); i++) { -// assertThat(TestEnum.valueOf(a4.get(i).getAsString())).isEqualTo(entity.o2.a4[i]); -// } -// } -// } -// } -// -// @Test -// void toObject() throws IOException { -// final VPackBuilder builder = new VPackBuilder(); -// { -// builder.add(ValueType.OBJECT); -// { -// builder.add("o1", ValueType.OBJECT); -// builder.add("l1", 5L); -// builder.add("l2", 5L); -// builder.close(); -// } -// { -// builder.add("o2", ValueType.OBJECT); -// { -// builder.add("a1", ValueType.ARRAY); -// builder.add("a"); -// builder.add("b"); -// builder.add("c"); -// builder.close(); -// } -// { -// builder.add("a2", ValueType.ARRAY); -// builder.add(1); -// builder.add(2); -// builder.add(3); -// builder.add(4); -// builder.close(); -// } -// { -// builder.add("a3", ValueType.ARRAY); -// builder.add(false); -// builder.add(true); -// builder.close(); -// } -// { -// builder.add("a4", ValueType.ARRAY); -// builder.add(TestEnum.A.name()); -// builder.add(TestEnum.B.name()); -// builder.close(); -// } -// builder.close(); -// } -// builder.close(); -// } -// final VPackSlice vpack = builder.slice(); -// final TestEntityObject entity = mapper.readValue(vpack.getBuffer(), TestEntityObject.class); -// assertThat(entity).isNotNull(); -// { -// assertThat(entity.o1.l1).isEqualTo(5L); -// assertThat(entity.o1.l2).isEqualTo(Long.valueOf(5)); -// } -// { -// assertThat(entity.o2.a1).hasSize(3); -// assertThat(entity.o2.a1[0]).isEqualTo("a"); -// assertThat(entity.o2.a1[1]).isEqualTo("b"); -// assertThat(entity.o2.a1[2]).isEqualTo("c"); -// } -// { -// assertThat(entity.o2.a2).hasSize(4); -// assertThat(entity.o2.a2[0]).isEqualTo(1); -// assertThat(entity.o2.a2[1]).isEqualTo(2); -// assertThat(entity.o2.a2[2]).isEqualTo(3); -// assertThat(entity.o2.a2[3]).isEqualTo(4); -// } -// { -// assertThat(entity.o2.a3).hasSize(2); -// assertThat(entity.o2.a3[0]).isFalse(); -// assertThat(entity.o2.a3[1]).isTrue(); -// } -// { -// assertThat(entity.o2.a4).hasSize(2); -// assertThat(entity.o2.a4[0]).isEqualTo(TestEnum.A); -// assertThat(entity.o2.a4[1]).isEqualTo(TestEnum.B); -// } -// } -// -// public static class TestEntityArrayInArray { -// private long[][] a1; -// -// public long[][] getA1() { -// return a1; -// } -// -// public void setA1(final long[][] a1) { -// this.a1 = a1; -// } -// } -// -// @Test -// void fromArrayInArray() throws JsonProcessingException { -// final TestEntityArrayInArray entity = new TestEntityArrayInArray(); -// entity.a1 = new long[][]{{1, 2, 3}, {4, 5, 6}}; -// final VPackSlice vpack = new VPackSlice(mapper.writeValueAsBytes(entity)); -// assertThat(vpack).isNotNull(); -// assertThat(vpack.isObject()).isTrue(); -// { -// final VPackSlice a1 = vpack.get("a1"); -// assertThat(a1.isArray()).isTrue(); -// assertThat(a1.getLength()).isEqualTo(entity.a1.length); -// for (int i = 0; i < a1.getLength(); i++) { -// final VPackSlice at = a1.get(i); -// assertThat(at.isArray()).isTrue(); -// assertThat(at.getLength()).isEqualTo(entity.a1[i].length); -// for (int j = 0; j < at.getLength(); j++) { -// final VPackSlice atat = at.get(j); -// assertThat(atat.isInteger()).isTrue(); -// assertThat(atat.getAsLong()).isEqualTo(entity.a1[i][j]); -// } -// } -// } -// } -// -// @Test -// void toArrayInArray() throws IOException { -// final VPackBuilder builder = new VPackBuilder(); -// { -// builder.add(ValueType.OBJECT); -// { -// builder.add("a1", ValueType.ARRAY); -// { -// builder.add(ValueType.ARRAY); -// builder.add(1); -// builder.add(2); -// builder.add(3); -// builder.close(); -// } -// { -// builder.add(ValueType.ARRAY); -// builder.add(4); -// builder.add(5); -// builder.add(6); -// builder.close(); -// } -// builder.close(); -// } -// builder.close(); -// } -// final VPackSlice vpack = builder.slice(); -// final TestEntityArrayInArray entity = mapper.readValue(vpack.getBuffer(), TestEntityArrayInArray.class); -// assertThat(entity).isNotNull(); -// assertThat(entity.a1.length).isEqualTo(2); -// { -// assertThat(entity.a1[0]).hasSize(3); -// assertThat(entity.a1[0][0]).isEqualTo(1L); -// assertThat(entity.a1[0][1]).isEqualTo(2L); -// assertThat(entity.a1[0][2]).isEqualTo(3L); -// } -// { -// assertThat(entity.a1[1]).hasSize(3); -// assertThat(entity.a1[1][0]).isEqualTo(4L); -// assertThat(entity.a1[1][1]).isEqualTo(5L); -// assertThat(entity.a1[1][2]).isEqualTo(6L); -// } -// } -// -// @SuppressWarnings("serial") -// public static class TestCollection extends LinkedList { -// -// } -// -// public static class TestEntityCollectionExtendedWithNulls { -// -// protected TestCollection a1; -// -// public TestCollection getA1() { -// return a1; -// } -// -// public void setA1(final TestCollection a1) { -// this.a1 = a1; -// } -// -// } -// -// @Test -// void fromCollectionExtendedWithNulls() { -// -// final TestCollection collection = new TestCollection(); -// collection.add("one"); -// collection.add(null); -// collection.add("two"); -// -// final TestEntityCollectionExtendedWithNulls entity = new TestEntityCollectionExtendedWithNulls(); -// entity.setA1(collection); -// -// final VPackSlice vpack = new VPack.Builder().serializeNullValues(true).build().serialize(entity); -// assertThat(vpack).isNotNull(); -// assertThat(vpack.isObject()).isTrue(); -// { -// final VPackSlice a1 = vpack.get("a1"); -// assertThat(a1.isArray()).isTrue(); -// assertThat(a1.getLength()).isEqualTo(entity.a1.size()); -// -// VPackSlice at = a1.get(0); -// assertThat(at.isString()).isTrue(); -// assertThat(at.getAsString()).isEqualTo(entity.a1.get(0)); -// at = a1.get(1); -// assertThat(at.isNull()).isTrue(); -// at = a1.get(2); -// assertThat(at.isString()).isTrue(); -// assertThat(at.getAsString()).isEqualTo(entity.a1.get(2)); -// } -// } -// -// @Test -// void toCollectionExtendedWithNulls() throws Exception { -// final VPackBuilder builder = new VPackBuilder(); -// { -// builder.add(ValueType.OBJECT); -// { -// builder.add("a1", ValueType.ARRAY); -// builder.add("one"); -// builder.add(ValueType.NULL); -// builder.add("two"); -// builder.close(); -// } -// builder.close(); -// } -// -// final VPackSlice vpack = builder.slice(); -// final TestEntityCollectionExtendedWithNulls entity = mapper.readValue(vpack.getBuffer(), -// TestEntityCollectionExtendedWithNulls.class); -// assertThat(entity).isNotNull(); -// assertThat(entity.getA1()).isNotNull(); -// assertThat(entity.getA1()).hasSize(3); -// assertThat(entity.getA1()).contains("one", null, "two"); -// } -// -// public static class TestEntityArrayInArrayInArray { -// -// private double[][][] a1; -// -// public double[][][] getA1() { -// return a1; -// } -// -// public void setA1(final double[][][] a1) { -// this.a1 = a1; -// } -// -// } -// -// @Test -// void fromArrayInArrayInArray() throws JsonProcessingException { -// final TestEntityArrayInArrayInArray entity = new TestEntityArrayInArrayInArray(); -// entity.setA1(new double[][][]{{{1.5, 2.25}, {10.5, 20.25}}, {{100.5}, {200.25}}}); -// final VPackSlice vpack = new VPackSlice(mapper.writeValueAsBytes(entity)); -// assertThat(vpack).isNotNull(); -// assertThat(vpack.isObject()).isTrue(); -// { -// final VPackSlice a1 = vpack.get("a1"); -// assertThat(a1.isArray()).isTrue(); -// assertThat(a1.getLength()).isEqualTo(entity.a1.length); -// for (int i = 0; i < a1.getLength(); i++) { -// final VPackSlice at = a1.get(i); -// assertThat(at.isArray()).isTrue(); -// assertThat(at.getLength()).isEqualTo(entity.a1[i].length); -// for (int j = 0; j < at.getLength(); j++) { -// final VPackSlice atat = at.get(j); -// assertThat(atat.isArray()).isTrue(); -// assertThat(atat.getLength()).isEqualTo(entity.a1[i][j].length); -// for (int k = 0; k < atat.getLength(); k++) { -// final VPackSlice atatat = atat.get(k); -// assertThat(atatat.isDouble()).isTrue(); -// assertThat(atatat.getAsDouble()).isEqualTo(entity.a1[i][j][k]); -// } -// } -// } -// } -// } -// -// @Test -// void toArrayInArrayInArray() throws IOException { -// final VPackBuilder builder = new VPackBuilder(); -// { -// builder.add(ValueType.OBJECT); -// { -// builder.add("a1", ValueType.ARRAY); -// builder.add(ValueType.ARRAY); -// { -// builder.add(ValueType.ARRAY); -// builder.add(1.5); -// builder.add(2.5); -// builder.add(3.5); -// builder.close(); -// } -// { -// builder.add(ValueType.ARRAY); -// builder.add(4.5); -// builder.add(5.5); -// builder.add(6.5); -// builder.close(); -// } -// { -// builder.add(ValueType.ARRAY); -// builder.add(7.5); -// builder.add(8.5); -// builder.add(9.5); -// builder.close(); -// } -// builder.close(); -// builder.add(ValueType.ARRAY); -// { -// builder.add(ValueType.ARRAY); -// builder.add(1.5); -// builder.add(2.5); -// builder.add(3.5); -// builder.close(); -// } -// { -// builder.add(ValueType.ARRAY); -// builder.add(4.5); -// builder.add(5.5); -// builder.add(6.5); -// builder.close(); -// } -// { -// builder.add(ValueType.ARRAY); -// builder.add(7.5); -// builder.add(8.5); -// builder.add(9.5); -// builder.close(); -// } -// builder.close(); -// builder.close(); -// } -// builder.close(); -// } -// final VPackSlice vpack = builder.slice(); -// final TestEntityArrayInArrayInArray entity = mapper.readValue(vpack.getBuffer(), -// TestEntityArrayInArrayInArray.class); -// assertThat(entity).isNotNull(); -// assertThat(entity.a1.length).isEqualTo(2); -// { -// assertThat(entity.a1[0].length).isEqualTo(3); -// assertThat(entity.a1[0][0]).hasSize(3); -// assertThat(entity.a1[0][0][0]).isEqualTo(1.5); -// assertThat(entity.a1[0][0][1]).isEqualTo(2.5); -// assertThat(entity.a1[0][0][2]).isEqualTo(3.5); -// assertThat(entity.a1[0][1]).hasSize(3); -// assertThat(entity.a1[0][1][0]).isEqualTo(4.5); -// assertThat(entity.a1[0][1][1]).isEqualTo(5.5); -// assertThat(entity.a1[0][1][2]).isEqualTo(6.5); -// assertThat(entity.a1[0][2]).hasSize(3); -// assertThat(entity.a1[0][2][0]).isEqualTo(7.5); -// assertThat(entity.a1[0][2][1]).isEqualTo(8.5); -// assertThat(entity.a1[0][2][2]).isEqualTo(9.5); -// } -// { -// assertThat(entity.a1[1].length).isEqualTo(3); -// assertThat(entity.a1[1][0]).hasSize(3); -// assertThat(entity.a1[1][0][0]).isEqualTo(1.5); -// assertThat(entity.a1[1][0][1]).isEqualTo(2.5); -// assertThat(entity.a1[1][0][2]).isEqualTo(3.5); -// assertThat(entity.a1[1][1]).hasSize(3); -// assertThat(entity.a1[1][1][0]).isEqualTo(4.5); -// assertThat(entity.a1[1][1][1]).isEqualTo(5.5); -// assertThat(entity.a1[1][1][2]).isEqualTo(6.5); -// assertThat(entity.a1[1][2]).hasSize(3); -// assertThat(entity.a1[1][2][0]).isEqualTo(7.5); -// assertThat(entity.a1[1][2][1]).isEqualTo(8.5); -// assertThat(entity.a1[1][2][2]).isEqualTo(9.5); -// } -// } -// -// public static class TestEntityObjectInArray { -// private TestEntityString[] a1; -// -// public TestEntityString[] getA1() { -// return a1; -// } -// -// public void setA1(final TestEntityString[] a1) { -// this.a1 = a1; -// } -// } -// -// @Test -// void fromObjectInArray() throws JsonProcessingException { -// final TestEntityObjectInArray entity = new TestEntityObjectInArray(); -// { -// final TestEntityString[] a1 = new TestEntityString[2]; -// final TestEntityString s = new TestEntityString(); -// s.setS("abc"); -// a1[0] = s; -// a1[1] = s; -// entity.setA1(a1); -// } -// final VPackSlice vpack = new VPackSlice(mapper.writeValueAsBytes(entity)); -// assertThat(vpack).isNotNull(); -// assertThat(vpack.isObject()).isTrue(); -// { -// final VPackSlice a1 = vpack.get("a1"); -// assertThat(a1.isArray()).isTrue(); -// assertThat(a1.getLength()).isEqualTo(2); -// for (int i = 0; i < a1.getLength(); i++) { -// final VPackSlice at = a1.get(i); -// assertThat(at.isObject()).isTrue(); -// final VPackSlice s = at.get("s"); -// assertThat(s.isString()).isTrue(); -// assertThat(s.getAsString()).isEqualTo("abc"); -// } -// } -// } -// -// @Test -// void toObjectInArray() throws IOException { -// final VPackBuilder builder = new VPackBuilder(); -// { -// builder.add(ValueType.OBJECT); -// builder.add("a1", ValueType.ARRAY); -// { -// builder.add(ValueType.OBJECT); -// builder.add("s", "abc"); -// builder.close(); -// } -// builder.close(); -// builder.close(); -// } -// final VPackSlice vpack = builder.slice(); -// final TestEntityObjectInArray entity = mapper.readValue(vpack.getBuffer(), TestEntityObjectInArray.class); -// assertThat(entity).isNotNull(); -// assertThat(entity.a1).hasSize(1); -// final TestEntityString st = entity.a1[0]; -// assertThat(st).isNotNull(); -// assertThat(st.s).isEqualTo("abc"); -// } -// -// public static class TestEntityA { -// private String a = "a"; -// -// public String getA() { -// return a; -// } -// -// public void setA(final String a) { -// this.a = a; -// } -// } -// -// public static class TestEntityB extends TestEntityA { -// private String b = "b"; -// -// public String getB() { -// return b; -// } -// -// public void setB(final String b) { -// this.b = b; -// } -// } -// -// @Test -// void fromInheritance() throws JsonProcessingException { -// final VPackSlice vpack = new VPackSlice(mapper.writeValueAsBytes(new TestEntityB())); -// assertThat(vpack).isNotNull(); -// assertThat(vpack.isObject()).isTrue(); -// assertThat(vpack.getLength()).isEqualTo(2); -// { -// final VPackSlice a = vpack.get("a"); -// assertThat(a.isString()).isTrue(); -// assertThat(a.getAsString()).isEqualTo("a"); -// } -// { -// final VPackSlice b = vpack.get("b"); -// assertThat(b.isString()).isTrue(); -// assertThat(b.getAsString()).isEqualTo("b"); -// } -// } -// -// @Test -// void toInheritance() throws IOException { -// final VPackBuilder builder = new VPackBuilder(); -// { -// builder.add(ValueType.OBJECT); -// builder.add("a", "test"); -// builder.add("b", "test"); -// builder.close(); -// } -// final VPackSlice vpack = builder.slice(); -// { -// final TestEntityA entity = mapper.readValue(vpack.getBuffer(), TestEntityA.class); -// assertThat(entity).isNotNull(); -// assertThat(entity.getA()).isEqualTo("test"); -// } -// { -// final TestEntityB entity = mapper.readValue(vpack.getBuffer(), TestEntityB.class); -// assertThat(entity).isNotNull(); -// assertThat(entity.getA()).isEqualTo("test"); -// assertThat(entity.getB()).isEqualTo("test"); -// } -// } -// -// public static class TestEntityC { -// private TestEntityD d; -// -// public TestEntityD getD() { -// return d; -// } -// -// public void setD(final TestEntityD d) { -// this.d = d; -// } -// } -// -// protected interface TestEntityD { -// String getD(); -// -// void setD(String d); -// } -// -// public static class TestEntityDImpl implements TestEntityD { -// private String d = "d"; -// -// @Override -// public String getD() { -// return d; -// } -// -// @Override -// public void setD(final String d) { -// this.d = d; -// } -// } -// -// @Test -// void fromInterface() throws JsonProcessingException { -// final TestEntityC entity = new TestEntityC(); -// entity.setD(new TestEntityDImpl()); -// final VPackSlice vpack = new VPackSlice(mapper.writeValueAsBytes(entity)); -// assertThat(vpack).isNotNull(); -// assertThat(vpack.isObject()).isTrue(); -// { -// final VPackSlice d = vpack.get("d"); -// assertThat(d.isObject()).isTrue(); -// final VPackSlice dd = d.get("d"); -// assertThat(dd.isString()).isTrue(); -// assertThat(dd.getAsString()).isEqualTo("d"); -// } -// } -// -// @Test -// void toInterface() { -// final VPackBuilder builder = new VPackBuilder(); -// { -// builder.add(ValueType.OBJECT); -// builder.add("d", ValueType.OBJECT); -// builder.add("d", "test"); -// builder.close(); -// builder.close(); -// } -// final VPackSlice slice = builder.slice(); -// final VPack vPack = new VPack.Builder() -// .registerInstanceCreator(TestEntityD.class, (VPackInstanceCreator) TestEntityDImpl::new).build(); -// final TestEntityC entity = vPack.deserialize(slice, TestEntityC.class); -// assertThat(entity).isNotNull(); -// assertThat(entity.d).isNotNull(); -// assertThat(entity.d.getD()).isEqualTo("test"); -// } -// -// public static class TestEntityCollection { -// private Collection c1 = new LinkedList<>(); -// private List c2 = new ArrayList<>(); -// private ArrayList c3 = new ArrayList<>(); -// private Set c4 = new LinkedHashSet<>(); -// private HashSet c5 = new HashSet<>(); -// -// public TestEntityCollection() { -// super(); -// } -// -// public Collection getC1() { -// return c1; -// } -// -// public void setC1(final Collection c1) { -// this.c1 = c1; -// } -// -// public List getC2() { -// return c2; -// } -// -// public void setC2(final List c2) { -// this.c2 = c2; -// } -// -// public ArrayList getC3() { -// return c3; -// } -// -// public void setC3(final ArrayList c3) { -// this.c3 = c3; -// } -// -// public Set getC4() { -// return c4; -// } -// -// public void setC4(final Set c4) { -// this.c4 = c4; -// } -// -// public HashSet getC5() { -// return c5; -// } -// -// public void setC5(final HashSet c5) { -// this.c5 = c5; -// } -// } -// -// @Test -// void fromCollection() throws JsonProcessingException { -// final TestEntityCollection entity = new TestEntityCollection(); -// { -// entity.c1.add("test"); -// entity.c2.add("test"); -// entity.c3.add("test"); -// entity.c4.add("test"); -// entity.c5.add("test"); -// } -// final VPackSlice vpack = new VPackSlice(mapper.writeValueAsBytes(entity)); -// assertThat(vpack).isNotNull(); -// assertThat(vpack.isObject()).isTrue(); -// { -// final VPackSlice c1 = vpack.get("c1"); -// assertThat(c1.isArray()).isTrue(); -// assertThat(c1.getLength()).isEqualTo(1); -// assertThat(c1.get(0).getAsString()).isEqualTo("test"); -// } -// { -// final VPackSlice c2 = vpack.get("c2"); -// assertThat(c2.isArray()).isTrue(); -// assertThat(c2.getLength()).isEqualTo(1); -// assertThat(c2.get(0).getAsString()).isEqualTo("test"); -// } -// { -// final VPackSlice c3 = vpack.get("c3"); -// assertThat(c3.isArray()).isTrue(); -// assertThat(c3.getLength()).isEqualTo(1); -// assertThat(c3.get(0).getAsString()).isEqualTo("test"); -// } -// { -// final VPackSlice c4 = vpack.get("c4"); -// assertThat(c4.isArray()).isTrue(); -// assertThat(c4.getLength()).isEqualTo(1); -// assertThat(c4.get(0).getAsString()).isEqualTo("test"); -// } -// { -// final VPackSlice c5 = vpack.get("c5"); -// assertThat(c5.isArray()).isTrue(); -// assertThat(c5.getLength()).isEqualTo(1); -// assertThat(c5.get(0).getAsString()).isEqualTo("test"); -// } -// } -// -// @Test -// void toCollection() throws IOException { -// final VPackBuilder builder = new VPackBuilder(); -// { -// builder.add(ValueType.OBJECT); -// { -// builder.add("c1", ValueType.ARRAY); -// builder.add("test1"); -// builder.add("test2"); -// builder.close(); -// } -// { -// builder.add("c2", ValueType.ARRAY); -// builder.add("test1"); -// builder.add("test2"); -// builder.close(); -// } -// { -// builder.add("c3", ValueType.ARRAY); -// builder.add("test1"); -// builder.add("test2"); -// builder.close(); -// } -// { -// builder.add("c4", ValueType.ARRAY); -// builder.add("test1"); -// builder.add("test2"); -// builder.close(); -// } -// { -// builder.add("c5", ValueType.ARRAY); -// builder.add("test1"); -// builder.add("test2"); -// builder.close(); -// } -// builder.close(); -// } -// final VPackSlice vpack = builder.slice(); -// final TestEntityCollection entity = mapper.readValue(vpack.getBuffer(), TestEntityCollection.class); -// assertThat(entity).isNotNull(); -// { -// checkCollection(entity.c1); -// checkCollection(entity.c2); -// checkCollection(entity.c3); -// checkCollection(entity.c4); -// checkCollection(entity.c5); -// } -// } -// -// private void checkCollection(final Collection col) { -// assertThat(col).isNotNull(); -// assertThat(col).hasSize(2); -// for (final String next : col) { -// assertThat("test1".equals(next) || "test2".equals(next)).isTrue(); -// } -// } -// -// public static class TestEntityCollectionWithObjects { -// private Collection c1; -// private Set c2; -// -// public Collection getC1() { -// return c1; -// } -// -// public void setC1(final Collection c1) { -// this.c1 = c1; -// } -// -// public Set getC2() { -// return c2; -// } -// -// public void setC2(final Set c2) { -// this.c2 = c2; -// } -// } -// -// @Test -// void fromCollectionWithObjects() throws JsonProcessingException { -// final TestEntityCollectionWithObjects entity = new TestEntityCollectionWithObjects(); -// { -// final Collection c1 = new ArrayList<>(); -// c1.add(new TestEntityString()); -// c1.add(new TestEntityString()); -// entity.setC1(c1); -// final Set c2 = new HashSet<>(); -// c2.add(new TestEntityArray()); -// entity.setC2(c2); -// } -// final VPackSlice vpack = new VPackSlice(mapper.writeValueAsBytes(entity)); -// assertThat(vpack).isNotNull(); -// assertThat(vpack.isObject()).isTrue(); -// { -// final VPackSlice c1 = vpack.get("c1"); -// assertThat(c1.isArray()).isTrue(); -// assertThat(c1.getLength()).isEqualTo(2); -// assertThat(c1.get(0).isObject()).isTrue(); -// assertThat(c1.get(1).isObject()).isTrue(); -// { -// final VPackSlice s = c1.get(0).get("s"); -// assertThat(s.isString()).isTrue(); -// assertThat(s.getAsString()).isEqualTo("test"); -// } -// } -// { -// final VPackSlice c2 = vpack.get("c2"); -// assertThat(c2.isArray()).isTrue(); -// assertThat(c2.getLength()).isEqualTo(1); -// assertThat(c2.get(0).isObject()).isTrue(); -// { -// final VPackSlice a2 = c2.get(0).get("a2"); -// assertThat(a2.isArray()).isTrue(); -// assertThat(a2.getLength()).isEqualTo(5); -// for (int i = 0; i < a2.getLength(); i++) { -// final VPackSlice at = a2.get(i); -// assertThat(at.isInteger()).isTrue(); -// assertThat(at.getAsInt()).isEqualTo(i + 1); -// } -// } -// } -// } -// -// @Test -// void toCollectionWithObjects() throws IOException { -// final VPackBuilder builder = new VPackBuilder(); -// { -// builder.add(ValueType.OBJECT); -// { -// builder.add("c1", ValueType.ARRAY); -// builder.add(ValueType.OBJECT); -// builder.add("s", "abc"); -// builder.close(); -// builder.close(); -// } -// { -// builder.add("c2", ValueType.ARRAY); -// builder.add(ValueType.OBJECT); -// builder.add("a2", ValueType.ARRAY); -// for (int i = 0; i < 10; i++) { -// builder.add(i); -// } -// builder.close(); -// builder.close(); -// builder.close(); -// } -// builder.close(); -// } -// final VPackSlice vpack = builder.slice(); -// final TestEntityCollectionWithObjects entity = mapper.readValue(vpack.getBuffer(), -// TestEntityCollectionWithObjects.class); -// assertThat(entity).isNotNull(); -// { -// assertThat(entity.c1).isNotNull(); -// assertThat(entity.c1).hasSize(1); -// assertThat(entity.c1.iterator().next().s).isEqualTo("abc"); -// } -// { -// assertThat(entity.c2).isNotNull(); -// assertThat(entity.c2).hasSize(1); -// final int[] array = entity.c2.iterator().next().a2; -// for (int i = 0; i < array.length; i++) { -// assertThat(array[i]).isEqualTo(i); -// } -// } -// } -// -// public static class TestEntityMap { -// private Map m1; -// private HashMap m2; -// private Map m3; -// -// public Map getM1() { -// return m1; -// } -// -// public void setM1(final Map m1) { -// this.m1 = m1; -// } -// -// public HashMap getM2() { -// return m2; -// } -// -// public void setM2(final HashMap m2) { -// this.m2 = m2; -// } -// -// public Map getM3() { -// return m3; -// } -// -// public void setM3(final Map m3) { -// this.m3 = m3; -// } -// } -// -// @Test -// void fromMap() throws JsonProcessingException { -// final TestEntityMap entity = new TestEntityMap(); -// { -// final Map m1 = new LinkedHashMap<>(); -// m1.put("a", "b"); -// m1.put("c", "d"); -// entity.setM1(m1); -// final HashMap m2 = new HashMap<>(); -// m2.put(1, "a"); -// m2.put(2, "b"); -// entity.setM2(m2); -// final Map m3 = new HashMap<>(); -// final TestEntityString s = new TestEntityString(); -// s.setS("abc"); -// m3.put("a", s); -// entity.setM3(m3); -// } -// final VPackSlice vpack = new VPackSlice(mapper.writeValueAsBytes(entity)); -// assertThat(vpack).isNotNull(); -// assertThat(vpack.isObject()).isTrue(); -// { -// final VPackSlice m1 = vpack.get("m1"); -// assertThat(m1.isObject()).isTrue(); -// assertThat(m1.getLength()).isEqualTo(2); -// { -// final VPackSlice a = m1.get("a"); -// assertThat(a.isString()).isTrue(); -// assertThat(a.getAsString()).isEqualTo("b"); -// } -// { -// final VPackSlice c = m1.get("c"); -// assertThat(c.isString()).isTrue(); -// assertThat(c.getAsString()).isEqualTo("d"); -// } -// } -// { -// final VPackSlice m2 = vpack.get("m2"); -// assertThat(m2.isObject()).isTrue(); -// assertThat(m2.getLength()).isEqualTo(2); -// { -// final VPackSlice one = m2.get("1"); -// assertThat(one.isString()).isTrue(); -// assertThat(one.getAsString()).isEqualTo("a"); -// } -// { -// final VPackSlice two = m2.get("2"); -// assertThat(two.isString()).isTrue(); -// assertThat(two.getAsString()).isEqualTo("b"); -// } -// } -// { -// final VPackSlice m3 = vpack.get("m3"); -// assertThat(m3.isObject()).isTrue(); -// assertThat(m3.getLength()).isEqualTo(1); -// final VPackSlice a = m3.get("a"); -// assertThat(a.isObject()).isTrue(); -// final VPackSlice s = a.get("s"); -// assertThat(s.isString()).isTrue(); -// assertThat(s.getAsString()).isEqualTo("abc"); -// } -// } -// -// @Test -// void toMap() throws IOException { -// final VPackBuilder builder = new VPackBuilder(); -// { -// builder.add(ValueType.OBJECT); -// { -// builder.add("m1", ValueType.OBJECT); -// builder.add("a", "a"); -// builder.add("b", "b"); -// builder.close(); -// } -// { -// builder.add("m2", ValueType.OBJECT); -// builder.add("1", "a"); -// builder.add("-1", "a"); -// builder.close(); -// } -// { -// builder.add("m3", ValueType.OBJECT); -// builder.add("a", ValueType.OBJECT); -// builder.add("s", "abc"); -// builder.close(); -// builder.close(); -// } -// builder.close(); -// } -// final VPackSlice vpack = builder.slice(); -// final TestEntityMap entity = mapper.readValue(vpack.getBuffer(), TestEntityMap.class); -// assertThat(entity).isNotNull(); -// { -// assertThat(entity.m1).isNotNull(); -// assertThat(entity.m1).hasSize(2); -// final String a = entity.m1.get("a"); -// assertThat(a).isNotNull(); -// assertThat(a).isEqualTo("a"); -// final String b = entity.m1.get("b"); -// assertThat(b).isNotNull(); -// assertThat(b).isEqualTo("b"); -// } -// { -// assertThat(entity.m2).isNotNull(); -// assertThat(entity.m2).hasSize(2); -// final String one = entity.m2.get(1); -// assertThat(one).isNotNull(); -// assertThat(one).isEqualTo("a"); -// final String oneNegative = entity.m2.get(-1); -// assertThat(oneNegative).isNotNull(); -// assertThat(oneNegative).isEqualTo("a"); -// } -// { -// assertThat(entity.m3).isNotNull(); -// assertThat(entity.m3).hasSize(1); -// final TestEntityString a = entity.m3.get("a"); -// assertThat(a).isNotNull(); -// assertThat(a.s).isEqualTo("abc"); -// } -// } -// -// public static class TestEntityMapStringableKey { -// private Map m1; -// private Map m2; -// private Map m3; -// private Map m4; -// private Map m5; -// private Map m6; -// private Map m7; -// private Map m8; -// private Map m9; -// private Map m10; -// private Map m11; -// -// public Map getM1() { -// return m1; -// } -// -// public void setM1(final Map m1) { -// this.m1 = m1; -// } -// -// public Map getM2() { -// return m2; -// } -// -// public void setM2(final Map m2) { -// this.m2 = m2; -// } -// -// public Map getM3() { -// return m3; -// } -// -// public void setM3(final Map m3) { -// this.m3 = m3; -// } -// -// public Map getM4() { -// return m4; -// } -// -// public void setM4(final Map m4) { -// this.m4 = m4; -// } -// -// public Map getM5() { -// return m5; -// } -// -// public void setM5(final Map m5) { -// this.m5 = m5; -// } -// -// public Map getM6() { -// return m6; -// } -// -// public void setM6(final Map m6) { -// this.m6 = m6; -// } -// -// public Map getM7() { -// return m7; -// } -// -// public void setM7(final Map m7) { -// this.m7 = m7; -// } -// -// public Map getM8() { -// return m8; -// } -// -// public void setM8(final Map m8) { -// this.m8 = m8; -// } -// -// public Map getM9() { -// return m9; -// } -// -// public void setM9(final Map m9) { -// this.m9 = m9; -// } -// -// public Map getM10() { -// return m10; -// } -// -// public void setM10(final Map m10) { -// this.m10 = m10; -// } -// -// public Map getM11() { -// return m11; -// } -// -// public void setM11(final Map m11) { -// this.m11 = m11; -// } -// -// } -// -// @Test -// void fromMapStringableKey() throws JsonProcessingException { -// final TestEntityMapStringableKey entity = new TestEntityMapStringableKey(); -// final String value = "test"; -// { -// final Map m1 = new HashMap<>(); -// m1.put(true, value); -// m1.put(false, value); -// entity.setM1(m1); -// } -// { -// final Map m2 = new HashMap<>(); -// m2.put(1, value); -// m2.put(2, value); -// entity.setM2(m2); -// } -// { -// final Map m3 = new HashMap<>(); -// m3.put(1L, value); -// m3.put(2L, value); -// entity.setM3(m3); -// } -// { -// final Map m4 = new HashMap<>(); -// m4.put(1.5F, value); -// m4.put(2.25F, value); -// entity.setM4(m4); -// } -// { -// final Map m5 = new HashMap<>(); -// m5.put(Short.valueOf("1"), value); -// m5.put(Short.valueOf("2"), value); -// entity.setM5(m5); -// } -// { -// final Map m6 = new HashMap<>(); -// m6.put(1.5, value); -// m6.put(2.25, value); -// entity.setM6(m6); -// } -// { -// final Map m7 = new HashMap<>(); -// m7.put(1.5, value); -// m7.put(1L, value); -// entity.setM7(m7); -// } -// { -// final Map m8 = new HashMap<>(); -// m8.put(new BigInteger("1"), value); -// m8.put(new BigInteger("2"), value); -// entity.setM8(m8); -// } -// { -// final Map m9 = new HashMap<>(); -// m9.put(new BigDecimal("1.5"), value); -// m9.put(new BigDecimal("2.25"), value); -// entity.setM9(m9); -// } -// { -// final Map m10 = new HashMap<>(); -// m10.put('1', value); -// m10.put('a', value); -// entity.setM10(m10); -// } -// { -// final Map m11 = new HashMap<>(); -// m11.put(TestEnum.A, value); -// m11.put(TestEnum.B, value); -// entity.setM11(m11); -// } -// final VPackSlice vpack = new VPackSlice(mapper.writeValueAsBytes(entity)); -// assertThat(vpack).isNotNull(); -// assertThat(vpack.isObject()).isTrue(); -// { -// final VPackSlice m1 = vpack.get("m1"); -// assertThat(m1.isObject()).isTrue(); -// assertThat(m1.getLength()).isEqualTo(2); -// checkMapAttribute(m1.get("true")); -// checkMapAttribute(m1.get("false")); -// } -// { -// final VPackSlice m2 = vpack.get("m2"); -// assertThat(m2.isObject()).isTrue(); -// assertThat(m2.getLength()).isEqualTo(2); -// checkMapAttribute(m2.get("1")); -// checkMapAttribute(m2.get("2")); -// } -// { -// final VPackSlice m3 = vpack.get("m3"); -// assertThat(m3.isObject()).isTrue(); -// assertThat(m3.getLength()).isEqualTo(2); -// checkMapAttribute(m3.get("1")); -// checkMapAttribute(m3.get("2")); -// } -// { -// final VPackSlice m4 = vpack.get("m4"); -// assertThat(m4.isObject()).isTrue(); -// assertThat(m4.getLength()).isEqualTo(2); -// checkMapAttribute(m4.get("1.5")); -// checkMapAttribute(m4.get("2.25")); -// } -// { -// final VPackSlice m5 = vpack.get("m5"); -// assertThat(m5.isObject()).isTrue(); -// assertThat(m5.getLength()).isEqualTo(2); -// checkMapAttribute(m5.get("1")); -// checkMapAttribute(m5.get("2")); -// } -// { -// final VPackSlice m6 = vpack.get("m6"); -// assertThat(m6.isObject()).isTrue(); -// assertThat(m6.getLength()).isEqualTo(2); -// checkMapAttribute(m6.get("1.5")); -// checkMapAttribute(m6.get("2.25")); -// } -// { -// final VPackSlice m7 = vpack.get("m7"); -// assertThat(m7.isObject()).isTrue(); -// assertThat(m7.getLength()).isEqualTo(2); -// checkMapAttribute(m7.get("1.5")); -// checkMapAttribute(m7.get("1")); -// } -// { -// final VPackSlice m8 = vpack.get("m8"); -// assertThat(m8.isObject()).isTrue(); -// assertThat(m8.getLength()).isEqualTo(2); -// checkMapAttribute(m8.get("1")); -// checkMapAttribute(m8.get("2")); -// } -// { -// final VPackSlice m9 = vpack.get("m9"); -// assertThat(m9.isObject()).isTrue(); -// assertThat(m9.getLength()).isEqualTo(2); -// checkMapAttribute(m9.get("1.5")); -// checkMapAttribute(m9.get("2.25")); -// } -// { -// final VPackSlice m10 = vpack.get("m10"); -// assertThat(m10.isObject()).isTrue(); -// assertThat(m10.getLength()).isEqualTo(2); -// checkMapAttribute(m10.get("1")); -// checkMapAttribute(m10.get("a")); -// } -// { -// final VPackSlice m11 = vpack.get("m11"); -// assertThat(m11.isObject()).isTrue(); -// assertThat(m11.getLength()).isEqualTo(2); -// checkMapAttribute(m11.get(TestEnum.A.name())); -// checkMapAttribute(m11.get(TestEnum.B.name())); -// } -// } -// -// @Test -// void toMapSringableKey() { -// final VPackBuilder builder = new VPackBuilder(); -// builder.add(ValueType.OBJECT); -// { -// builder.add("m1", ValueType.OBJECT); -// builder.add("true", "test"); -// builder.add("false", "test"); -// builder.close(); -// } -// { -// builder.add("m2", ValueType.OBJECT); -// builder.add("1", "test"); -// builder.add("2", "test"); -// builder.close(); -// } -// { -// builder.add("m3", ValueType.OBJECT); -// builder.add("1", "test"); -// builder.add("2", "test"); -// builder.close(); -// } -// { -// builder.add("m4", ValueType.OBJECT); -// builder.add("1.5", "test"); -// builder.add("2.25", "test"); -// builder.close(); -// } -// { -// builder.add("m5", ValueType.OBJECT); -// builder.add("1", "test"); -// builder.add("2", "test"); -// builder.close(); -// } -// { -// builder.add("m6", ValueType.OBJECT); -// builder.add("1.5", "test"); -// builder.add("2.25", "test"); -// builder.close(); -// } -// { -// builder.add("m7", ValueType.OBJECT); -// builder.add("1.5", "test"); -// builder.add("1", "test"); -// builder.close(); -// } -// { -// builder.add("m8", ValueType.OBJECT); -// builder.add("1", "test"); -// builder.add("2", "test"); -// builder.close(); -// } -// { -// builder.add("m9", ValueType.OBJECT); -// builder.add("1.5", "test"); -// builder.add("2.25", "test"); -// builder.close(); -// } -// { -// builder.add("m10", ValueType.OBJECT); -// builder.add("1", "test"); -// builder.add("a", "test"); -// builder.close(); -// } -// { -// builder.add("m11", ValueType.OBJECT); -// builder.add(TestEnum.A.name(), "test"); -// builder.add(TestEnum.B.name(), "test"); -// builder.close(); -// } -// builder.close(); -// final TestEntityMapStringableKey entity = new VPack.Builder().build().deserialize(builder.slice(), -// TestEntityMapStringableKey.class); -// { -// assertThat(entity.m1).hasSize(2); -// checkMapAttribute(entity.m1.get(true)); -// checkMapAttribute(entity.m1.get(false)); -// } -// { -// assertThat(entity.m2).hasSize(2); -// checkMapAttribute(entity.m2.get(1)); -// checkMapAttribute(entity.m2.get(2)); -// } -// { -// assertThat(entity.m3).hasSize(2); -// checkMapAttribute(entity.m3.get(1L)); -// checkMapAttribute(entity.m3.get(2L)); -// } -// { -// assertThat(entity.m4).hasSize(2); -// checkMapAttribute(entity.m4.get(1.5F)); -// checkMapAttribute(entity.m4.get(2.25F)); -// } -// { -// assertThat(entity.m5).hasSize(2); -// checkMapAttribute(entity.m5.get(Short.valueOf("1"))); -// checkMapAttribute(entity.m5.get(Short.valueOf("2"))); -// } -// { -// assertThat(entity.m6).hasSize(2); -// checkMapAttribute(entity.m6.get(1.5)); -// checkMapAttribute(entity.m6.get(2.25)); -// } -// { -// assertThat(entity.m7).hasSize(2); -// checkMapAttribute(entity.m7.get(1.5)); -// checkMapAttribute(entity.m7.get((double) 1L)); -// } -// { -// assertThat(entity.m8).hasSize(2); -// checkMapAttribute(entity.m8.get(new BigInteger("1"))); -// checkMapAttribute(entity.m8.get(new BigInteger("2"))); -// } -// { -// assertThat(entity.m9).hasSize(2); -// checkMapAttribute(entity.m9.get(new BigDecimal("1.5"))); -// checkMapAttribute(entity.m9.get(new BigDecimal("2.25"))); -// } -// { -// assertThat(entity.m10).hasSize(2); -// checkMapAttribute(entity.m10.get('1')); -// checkMapAttribute(entity.m10.get('a')); -// } -// { -// assertThat(entity.m11).hasSize(2); -// checkMapAttribute(entity.m11.get(TestEnum.A)); -// checkMapAttribute(entity.m11.get(TestEnum.B)); -// } -// } -// -// private void checkMapAttribute(final VPackSlice attr) { -// assertThat(attr.isString()).isTrue(); -// assertThat(attr.getAsString()).isEqualTo("test"); -// } -// -// private void checkMapAttribute(final String attr) { -// assertThat(attr).isEqualTo("test"); -// } -// -// public static class TestEntityMapWithObjectKey { -// private Map m1; -// private Map m2; -// -// public Map getM1() { -// return m1; -// } -// -// public void setM1(final Map m1) { -// this.m1 = m1; -// } -// -// public Map getM2() { -// return m2; -// } -// -// public void setM2(final Map m2) { -// this.m2 = m2; -// } -// } -// -// @Test -// void toMapWithObjectKey() { -// final int size = 2; -// final VPackBuilder builder = new VPackBuilder(); -// builder.add(ValueType.OBJECT); -// { -// builder.add("m1", ValueType.ARRAY); -// for (int i = 0; i < size; i++) { -// builder.add(ValueType.OBJECT); -// { -// builder.add("key", ValueType.OBJECT); -// builder.add("l1", 5L); -// builder.close(); -// } -// { -// builder.add("value", ValueType.OBJECT); -// builder.add("c1", ValueType.ARRAY); -// builder.add("test"); -// builder.close(); -// builder.close(); -// } -// builder.close(); -// } -// builder.close(); -// } -// { -// builder.add("m2", ValueType.ARRAY); -// for (int i = 0; i < size; i++) { -// builder.add(ValueType.OBJECT); -// { -// builder.add("key", ValueType.OBJECT); -// builder.add("l1", 5L); -// builder.close(); -// } -// { -// builder.add("value", "test"); -// } -// builder.close(); -// } -// builder.close(); -// } -// builder.close(); -// final TestEntityMapWithObjectKey entity = new VPack.Builder().build().deserialize(builder.slice(), -// TestEntityMapWithObjectKey.class); -// assertThat(entity).isNotNull(); -// { -// assertThat(entity.m1).isNotNull(); -// assertThat(entity.m1).hasSize(size); -// for (final Entry entry : entity.m1.entrySet()) { -// assertThat(entry.getKey().l1).isEqualTo(5L); -// assertThat(entry.getValue().c1).hasSize(1); -// assertThat(entry.getValue().c1.iterator().next()).isEqualTo("test"); -// } -// } -// { -// assertThat(entity.m2).isNotNull(); -// assertThat(entity.m2).hasSize(2); -// for (final Entry entry : entity.m2.entrySet()) { -// assertThat(entry.getKey().l1).isEqualTo(5L); -// assertThat(entry.getValue()).isEqualTo("test"); -// } -// } -// } -// -// public static class TestEntityEmpty { -// -// } -// -// @Test -// void fromEmptyObject() throws JsonProcessingException { -// final VPackSlice vpack = new VPackSlice(mapper.writeValueAsBytes(new TestEntityEmpty())); -// assertThat(vpack).isNotNull(); -// assertThat(vpack.isObject()).isTrue(); -// assertThat(vpack.getLength()).isZero(); -// } -// -// @Test -// void toEmptyObject() { -// final VPackBuilder builder = new VPackBuilder(); -// builder.add(ValueType.OBJECT); -// builder.close(); -// final TestEntityEmpty entity = new VPack.Builder().build().deserialize(builder.slice(), TestEntityEmpty.class); -// assertThat(entity).isNotNull(); -// } -// -// public static class TestEntityEmptyMap { -// private Map m; -// -// public Map getM() { -// return m; -// } -// -// public void setM(final Map m) { -// this.m = m; -// } -// } -// -// @Test -// void fromEmptyMap() throws JsonProcessingException { -// final TestEntityEmptyMap entity = new TestEntityEmptyMap(); -// entity.setM(new HashMap<>()); -// final VPackSlice vpack = new VPackSlice(mapper.writeValueAsBytes(entity)); -// assertThat(vpack).isNotNull(); -// assertThat(vpack.isObject()).isTrue(); -// assertThat(vpack.getLength()).isEqualTo(1); -// final VPackSlice m = vpack.get("m"); -// assertThat(m.isObject()).isTrue(); -// assertThat(m.getLength()).isZero(); -// } -// -// @Test -// void toEmptyMap() { -// final VPackBuilder builder = new VPackBuilder(); -// builder.add(ValueType.OBJECT); -// builder.add("m", ValueType.OBJECT); -// builder.close(); -// builder.close(); -// final TestEntityEmptyMap entity = new VPack.Builder().build().deserialize(builder.slice(), -// TestEntityEmptyMap.class); -// assertThat(entity).isNotNull(); -// assertThat(entity.m).isNotNull(); -// assertThat(entity.m).isEmpty(); -// } -// -// public static class TestEntityBaseAttributes { -// private String _key = "test1"; -// private String _rev = "test2"; -// private String _id = "test3"; -// private String _from = "test4"; -// private String _to = "test5"; -// -// public String get_key() { -// return _key; -// } -// -// public void set_key(final String _key) { -// this._key = _key; -// } -// -// public String get_rev() { -// return _rev; -// } -// -// public void set_rev(final String _rev) { -// this._rev = _rev; -// } -// -// public String get_id() { -// return _id; -// } -// -// public void set_id(final String _id) { -// this._id = _id; -// } -// -// public String get_from() { -// return _from; -// } -// -// public void set_from(final String _from) { -// this._from = _from; -// } -// -// public String get_to() { -// return _to; -// } -// -// public void set_to(final String _to) { -// this._to = _to; -// } -// -// } -// -// @Test -// void fromObjectWithAttributeAdapter() throws JsonProcessingException { -// final VPackSlice vpack = new VPackSlice(mapper.writeValueAsBytes(new TestEntityBaseAttributes())); -// assertThat(vpack.isObject()).isTrue(); -// assertThat(vpack.getLength()).isEqualTo(5); -// { -// final VPackSlice key = vpack.get("_key"); -// assertThat(key.isString()).isTrue(); -// assertThat(key.getAsString()).isEqualTo("test1"); -// } -// { -// final VPackSlice rev = vpack.get("_rev"); -// assertThat(rev.isString()).isTrue(); -// assertThat(rev.getAsString()).isEqualTo("test2"); -// } -// { -// final VPackSlice id = vpack.get("_id"); -// assertThat(id.isString()).isTrue(); -// assertThat(id.getAsString()).isEqualTo("test3"); -// } -// { -// final VPackSlice from = vpack.get("_from"); -// assertThat(from.isString()).isTrue(); -// assertThat(from.getAsString()).isEqualTo("test4"); -// } -// { -// final VPackSlice to = vpack.get("_to"); -// assertThat(to.isString()).isTrue(); -// assertThat(to.getAsString()).isEqualTo("test5"); -// } -// } -// -// @Test -// void toObjectWithAttributeAdapter() { -// final VPackBuilder builder = new VPackBuilder(); -// { -// builder.add(ValueType.OBJECT); -// builder.add("_key", "a"); -// builder.add("_rev", "b"); -// builder.add("_id", "c"); -// builder.add("_from", "d"); -// builder.add("_to", "e"); -// builder.close(); -// } -// final TestEntityBaseAttributes entity = new VPack.Builder().build().deserialize(builder.slice(), -// TestEntityBaseAttributes.class); -// assertThat(entity).isNotNull(); -// assertThat(entity._key).isEqualTo("a"); -// assertThat(entity._rev).isEqualTo("b"); -// assertThat(entity._id).isEqualTo("c"); -// assertThat(entity._from).isEqualTo("d"); -// assertThat(entity._to).isEqualTo("e"); -// } -// -// @Test -// void fromMapWithAttributeAdapter() throws JsonProcessingException { -// final TestEntityMap entity = new TestEntityMap(); -// { -// final Map m1 = new HashMap<>(); -// m1.put("_key", "test1"); -// m1.put("_rev", "test2"); -// m1.put("_id", "test3"); -// m1.put("_from", "test4"); -// m1.put("_to", "test5"); -// entity.setM1(m1); -// } -// final VPackSlice vpack = new VPackSlice(mapper.writeValueAsBytes(entity)); -// assertThat(vpack.isObject()).isTrue(); -// final VPackSlice m1 = vpack.get("m1"); -// assertThat(m1.isObject()).isTrue(); -// assertThat(m1.getLength()).isEqualTo(5); -// { -// final VPackSlice key = m1.get("_key"); -// assertThat(key.isString()).isTrue(); -// assertThat(key.getAsString()).isEqualTo("test1"); -// } -// { -// final VPackSlice rev = m1.get("_rev"); -// assertThat(rev.isString()).isTrue(); -// assertThat(rev.getAsString()).isEqualTo("test2"); -// } -// { -// final VPackSlice id = m1.get("_id"); -// assertThat(id.isString()).isTrue(); -// assertThat(id.getAsString()).isEqualTo("test3"); -// } -// { -// final VPackSlice from = m1.get("_from"); -// assertThat(from.isString()).isTrue(); -// assertThat(from.getAsString()).isEqualTo("test4"); -// } -// { -// final VPackSlice to = m1.get("_to"); -// assertThat(to.isString()).isTrue(); -// assertThat(to.getAsString()).isEqualTo("test5"); -// } -// } -// -// @Test -// void toMapWithAttributeAdapter() { -// final VPackBuilder builder = new VPackBuilder(); -// { -// builder.add(ValueType.OBJECT); -// builder.add("m1", ValueType.OBJECT); -// builder.add("_key", "a"); -// builder.add("_rev", "b"); -// builder.add("_id", "c"); -// builder.add("_from", "d"); -// builder.add("_to", "e"); -// builder.close(); -// builder.close(); -// } -// final TestEntityMap entity = new VPack.Builder().build().deserialize(builder.slice(), TestEntityMap.class); -// assertThat(entity).isNotNull(); -// assertThat(entity.m1).hasSize(5); -// } -// -// @Retention(RetentionPolicy.RUNTIME) -// @Target(ElementType.FIELD) -// private @interface CustomFilterAnnotation { -// boolean serialize() -// -// default true; -// -// boolean deserialize() default true; -// } -// -// @Retention(RetentionPolicy.RUNTIME) -// @Target(ElementType.FIELD) -// private @interface CustomNamingAnnotation { -// String name(); -// } -// -// private static class CustomAnEntity { -// @CustomFilterAnnotation(serialize = false) -// private String a = null; -// @CustomFilterAnnotation(deserialize = false) -// private String b = null; -// @CustomNamingAnnotation(name = "d") -// @CustomFilterAnnotation(deserialize = false) -// private String c = null; -// -// CustomAnEntity() { -// super(); -// } -// } -// -// @Test -// void fromCutsomAnnotation() { -// final CustomAnEntity entity = new CustomAnEntity(); -// entity.a = "1"; -// entity.b = "2"; -// entity.c = "3"; -// final VPackSlice vpack = new VPack.Builder().annotationFieldFilter(CustomFilterAnnotation.class, -// new VPackAnnotationFieldFilter() { -// -// @Override -// public boolean serialize(final CustomFilterAnnotation annotation) { -// return annotation.serialize(); -// } -// -// @Override -// public boolean deserialize(final CustomFilterAnnotation annotation) { -// return annotation.deserialize(); -// } -// }).annotationFieldNaming(CustomNamingAnnotation.class, -// CustomNamingAnnotation::name).build().serialize(entity); -// assertThat(vpack).isNotNull(); -// assertThat(vpack.isObject()).isTrue(); -// assertThat(vpack.get("a").isNone()).isTrue(); -// assertThat(vpack.get("b").isString()).isTrue(); -// assertThat(vpack.get("b").getAsString()).isEqualTo("2"); -// assertThat(vpack.get("c").isNone()).isTrue(); -// assertThat(vpack.get("d").isString()).isTrue(); -// assertThat(vpack.get("d").getAsString()).isEqualTo("3"); -// } -// -// @Test -// void directFromCollection() throws JsonProcessingException { -// final Collection list = new ArrayList<>(); -// list.add("test"); -// final VPackSlice vpack = new VPackSlice(mapper.writeValueAsBytes(list)); -// assertThat(vpack).isNotNull(); -// assertThat(vpack.isArray()).isTrue(); -// assertThat(vpack.size()).isEqualTo(1); -// final VPackSlice test = vpack.get(0); -// assertThat(test.isString()).isTrue(); -// assertThat(test.getAsString()).isEqualTo("test"); -// } -// -// @Test -// void directFromCollectionWithType() throws JsonProcessingException { -// final Collection list = new ArrayList<>(); -// list.add(new TestEntityString()); -// list.add(new TestEntityString()); -// -// final VPackSlice vpack = new VPackSlice(mapper.writeValueAsBytes(list)); -// assertThat(vpack).isNotNull(); -// assertThat(vpack.isArray()).isTrue(); -// assertThat(vpack.getLength()).isEqualTo(list.size()); -// for (int i = 0; i < list.size(); i++) { -// final VPackSlice entry = vpack.get(i); -// assertThat(entry.isObject()).isTrue(); -// assertThat(entry.getLength()).isEqualTo(3); -// final VPackSlice s = entry.get("s"); -// assertThat(s.isString()).isTrue(); -// assertThat(s.getAsString()).isEqualTo("test"); -// } -// } -// -// @Test -// void directToCollection() { -// final VPackBuilder builder = new VPackBuilder(); -// builder.add(ValueType.ARRAY); -// builder.add(ValueType.OBJECT); -// builder.add("s", "abc"); -// builder.close(); -// builder.close(); -// final List list = new VPack.Builder().build().deserialize(builder.slice(), -// new Type>() { -// }.getType()); -// assertThat(list).hasSize(1); -// final TestEntityString entry = list.get(0); -// assertThat(entry.s).isEqualTo("abc"); -// } -// -// @Test -// void directFromStringMap() throws JsonProcessingException { -// final Map map = new HashMap<>(); -// map.put("a", new TestEntityString()); -// map.put("b", new TestEntityString()); -// -// final VPackSlice vpack = new VPackSlice(mapper.writeValueAsBytes(map)); -// assertThat(vpack).isNotNull(); -// assertThat(vpack.isObject()).isTrue(); -// assertThat(vpack.getLength()).isEqualTo(2); -// final VPackSlice a = vpack.get("a"); -// checkStringEntity(a); -// } -// -// @Test -// void directToStringMap() { -// final VPackBuilder builder = new VPackBuilder(); -// builder.add(ValueType.OBJECT); -// builder.add("a", ValueType.OBJECT); -// builder.add("s", "abc"); -// builder.close(); -// builder.close(); -// final Map map = new VPack.Builder().build().deserialize(builder.slice(), -// new Type>() { -// }.getType()); -// assertThat(map).hasSize(1); -// final TestEntityString a = map.get("a"); -// assertThat(a).isNotNull(); -// assertThat(a.s).isEqualTo("abc"); -// } -// -// @Test -// void directFromMap() throws JsonProcessingException { -// final Map map = new HashMap<>(); -// final TestEntityA entity = new TestEntityA(); -// entity.a = "test"; -// map.put("test", entity); -// final VPackSlice vpack = new VPackSlice(mapper.writeValueAsBytes(map)); -// assertThat(vpack).isNotNull(); -// assertThat(vpack.isObject()).isTrue(); -// final VPackSlice test = vpack.get("test"); -// assertThat(test.isObject()).isTrue(); -// final VPackSlice a = test.get("a"); -// assertThat(a.isString()).isTrue(); -// assertThat(a.getAsString()).isEqualTo("test"); -// } -// -// @Test -// void directFromMapWithinMap() throws JsonProcessingException { -// final Map map = new HashMap<>(); -// final Map map2 = new HashMap<>(); -// map2.put("b", "test"); -// map.put("a", map2); -// final VPackSlice vpack = new VPackSlice(mapper.writeValueAsBytes(map)); -// assertThat(vpack).isNotNull(); -// assertThat(vpack.isObject()).isTrue(); -// assertThat(vpack.size()).isEqualTo(1); -// final VPackSlice a = vpack.get("a"); -// assertThat(a.isObject()).isTrue(); -// assertThat(a.size()).isEqualTo(1); -// final VPackSlice b = a.get("b"); -// assertThat(b.isString()).isTrue(); -// assertThat(b.getAsString()).isEqualTo("test"); -// } -// -// private void checkStringEntity(final VPackSlice vpack) { -// final TestEntityString expected = new TestEntityString(); -// assertThat(vpack.isObject()).isTrue(); -// assertThat(vpack.getLength()).isEqualTo(3); -// final VPackSlice s = vpack.get("s"); -// assertThat(s.isString()).isTrue(); -// assertThat(s.getAsString()).isEqualTo(expected.s); -// final VPackSlice c1 = vpack.get("c1"); -// assertThat(c1.isString()).isTrue(); -// assertThat(new Character(c1.getAsChar())).isEqualTo(expected.c1); -// final VPackSlice c2 = vpack.get("c2"); -// assertThat(c2.isString()).isTrue(); -// assertThat(c2.getAsChar()).isEqualTo(expected.c2); -// } -// -// @Test -// void directToObjectMap() { -// final VPackBuilder builder = new VPackBuilder(); -// builder.add(ValueType.ARRAY); -// builder.add(ValueType.OBJECT); -// builder.add("key", ValueType.OBJECT); -// builder.add("s", "abc"); -// builder.close(); -// builder.add("value", ValueType.OBJECT); -// builder.add("s", "abc"); -// builder.close(); -// builder.close(); -// builder.close(); -// final Map map = new VPack.Builder().build().deserialize(builder.slice(), -// new Type>() { -// }.getType()); -// assertThat(map).hasSize(1); -// for (final Entry entry : map.entrySet()) { -// assertThat(entry.getKey().s).isEqualTo("abc"); -// assertThat(entry.getValue().s).isEqualTo("abc"); -// } -// } -// -// @SuppressWarnings("unchecked") -// @Test -// void directToMapWithinMap() { -// final VPackBuilder builder = new VPackBuilder(); -// builder.add(ValueType.OBJECT); -// builder.add("a", ValueType.OBJECT); -// builder.add("b", "test"); -// builder.add("c", true); -// builder.add("d", 1L); -// builder.add("e", 1.5); -// final Date date = new Date(); -// builder.add("f", date); -// builder.add("g", ValueType.ARRAY); -// builder.close(); -// builder.close(); -// builder.close(); -// final Map map = new VPack.Builder().build().deserialize(builder.slice(), Map.class); -// assertThat(map).hasSize(1); -// final Object a = map.get("a"); -// assertThat(Map.class.isAssignableFrom(a.getClass())).isTrue(); -// final Map mapA = (Map) a; -// assertThat(mapA).hasSize(6); -// final Object b = mapA.get("b"); -// assertThat(String.class.isAssignableFrom(b.getClass())).isTrue(); -// assertThat(b).hasToString("test"); -// final Object c = mapA.get("c"); -// assertThat(Boolean.class.isAssignableFrom(c.getClass())).isTrue(); -// assertThat((Boolean) c).isTrue(); -// final Object d = mapA.get("d"); -// assertThat(Number.class.isAssignableFrom(d.getClass())).isTrue(); -// assertThat(((Number) d).longValue()).isEqualTo(1L); -// final Object e = mapA.get("e"); -// assertThat(Double.class.isAssignableFrom(e.getClass())).isTrue(); -// assertThat((Double) e).isEqualTo(1.5); -// final Object f = mapA.get("f"); -// assertThat(Date.class.isAssignableFrom(f.getClass())).isTrue(); -// assertThat((Date) f).isEqualTo(date); -// final Object g = mapA.get("g"); -// assertThat(Collection.class.isAssignableFrom(g.getClass())).isTrue(); -// assertThat(List.class.isAssignableFrom(g.getClass())).isTrue(); -// } -// -// @Test -// void dontSerializeNullValues() { -// final VPack serializer = new VPack.Builder().serializeNullValues(false).build(); -// final TestEntityString entity = new TestEntityString(); -// entity.setS(null); -// final VPackSlice vpack = serializer.serialize(entity); -// assertThat(vpack).isNotNull(); -// assertThat(vpack.isObject()).isTrue(); -// final VPackSlice s = vpack.get("s"); -// assertThat(s.isNone()).isTrue(); -// } -// -// @Test -// void serializeNullValue() { -// final VPack serializer = new VPack.Builder().serializeNullValues(true).build(); -// final TestEntityString entity = new TestEntityString(); -// entity.setS(null); -// final VPackSlice vpack = serializer.serialize(entity); -// assertThat(vpack).isNotNull(); -// final VPackSlice s = vpack.get("s"); -// assertThat(s.isNull()).isTrue(); -// } -// -// @Test -// void toNullValue() { -// final VPackBuilder builder = new VPackBuilder(); -// builder.add(ValueType.OBJECT); -// builder.add("s", ValueType.NULL); -// builder.close(); -// final TestEntityString entity = new VPack.Builder().build().deserialize(builder.slice(), -// TestEntityString.class); -// assertThat(entity).isNotNull(); -// assertThat(entity.s).isNull(); -// assertThat(entity.c1).isNotNull(); -// assertThat(entity.c2).isNotNull(); -// } -// -// @Test -// void toSimpleString() { -// final VPackBuilder builder = new VPackBuilder(); -// builder.add("test"); -// final String s = new VPack.Builder().build().deserialize(builder.slice(), String.class); -// assertThat(s).isEqualTo("test"); -// } -// -// @Test -// void fromSimpleString() throws JsonProcessingException { -// final VPackSlice vpack = new VPackSlice(mapper.writeValueAsBytes("test")); -// assertThat(vpack).isNotNull(); -// assertThat(vpack.isString()).isTrue(); -// assertThat(vpack.getAsString()).isEqualTo("test"); -// } -// -// public static class TestEntityTyped { -// private T e; -// } -// -// @Test -// void fromStringTypedEntity() throws JsonProcessingException { -// final TestEntityTyped entity = new TestEntityTyped<>(); -// entity.e = "test"; -// final VPackSlice vpack = new VPackSlice(mapper.writeValueAsBytes(entity)); -// assertThat(vpack).isNotNull(); -// assertThat(vpack.isObject()).isTrue(); -// final VPackSlice e = vpack.get("e"); -// assertThat(e).isNotNull(); -// assertThat(e.isString()).isTrue(); -// assertThat(e.getAsString()).isEqualTo("test"); -// } -// -// @Test -// void fromObjectTypedEntity() throws JsonProcessingException { -// final TestEntityTyped entity = new TestEntityTyped<>(); -// entity.e = new TestEntityString(); -// entity.e.s = "test2"; -// final VPackSlice vpack = new VPackSlice(mapper.writeValueAsBytes(entity)); -// assertThat(vpack).isNotNull(); -// assertThat(vpack.isObject()).isTrue(); -// final VPackSlice e = vpack.get("e"); -// assertThat(e).isNotNull(); -// assertThat(e.isObject()).isTrue(); -// final VPackSlice s = e.get("s"); -// assertThat(s).isNotNull(); -// assertThat(s.isString()).isTrue(); -// assertThat(s.getAsString()).isEqualTo("test2"); -// } -// -// @Test -// void fromTypedTypedEntity() throws JsonProcessingException { -// final TestEntityTyped> entity = new TestEntityTyped<>(); -// entity.e = new TestEntityTyped<>(); -// entity.e.e = "test"; -// final VPackSlice vpack = new VPackSlice(mapper.writeValueAsBytes(entity)); -// assertThat(vpack).isNotNull(); -// assertThat(vpack.isObject()).isTrue(); -// final VPackSlice e = vpack.get("e"); -// assertThat(e).isNotNull(); -// assertThat(e.isObject()).isTrue(); -// final VPackSlice e2 = e.get("e"); -// assertThat(e2).isNotNull(); -// assertThat(e2.isString()).isTrue(); -// assertThat(e2.getAsString()).isEqualTo("test"); -// } -// -// @Test -// void fieldNamingStrategySerialize() { -// final VPackSlice vpack = new VPack.Builder().fieldNamingStrategy(field -> "bla").build().serialize(new TestEntityA()); -// assertThat(vpack).isNotNull(); -// assertThat(vpack.isObject()).isTrue(); -// final VPackSlice bla = vpack.get("bla"); -// assertThat(bla.isString()).isTrue(); -// assertThat(bla.getAsString()).isEqualTo("a"); -// } -// -// @Test -// void fieldNamingStrategyDeserialize() { -// final VPackBuilder builder = new VPackBuilder(); -// builder.add(ValueType.OBJECT); -// builder.add("bla", "test"); -// builder.close(); -// final TestEntityA entity = new VPack.Builder().fieldNamingStrategy(field -> "bla").build().deserialize(builder.slice(), TestEntityA.class); -// assertThat(entity).isNotNull(); -// assertThat(entity.a).isEqualTo("test"); -// } -// -// @Test -// void serializeVPack() throws JsonProcessingException { -// final VPackBuilder builder = new VPackBuilder(); -// builder.add("test"); -// final VPackSlice slice = builder.slice(); -// final VPackSlice vpack = new VPackSlice(mapper.writeValueAsBytes(slice)); -// assertThat(vpack).isNotNull(); -// assertThat(vpack.isString()).isTrue(); -// assertThat(vpack.getAsString()).isEqualTo("test"); -// } -// -// @Test -// void deserializeVPack() { -// final VPackBuilder builder = new VPackBuilder(); -// builder.add("test"); -// final VPackSlice slice = builder.slice(); -// final VPackSlice vpack = new VPack.Builder().build().deserialize(slice, slice.getClass()); -// assertThat(vpack).isNotNull(); -// assertThat(vpack.isString()).isTrue(); -// assertThat(vpack.getAsString()).isEqualTo("test"); -// } -// -// public static class TestEntityDate { -// private java.util.Date utilDate = new Date(1474988621); -// private java.sql.Date sqlDate = new java.sql.Date(1474988621); -// private java.sql.Timestamp timestamp = new java.sql.Timestamp(1474988621); -// -// public java.util.Date getUtilDate() { -// return utilDate; -// } -// -// public void setUtilDate(final java.util.Date utilDate) { -// this.utilDate = utilDate; -// } -// -// public java.sql.Date getSqlDate() { -// return sqlDate; -// } -// -// public void setSqlDate(final java.sql.Date sqlDate) { -// this.sqlDate = sqlDate; -// } -// -// public java.sql.Timestamp getTimestamp() { -// return timestamp; -// } -// -// public void setTimestamp(final java.sql.Timestamp timestamp) { -// this.timestamp = timestamp; -// } -// -// } -// -// @Test -// void fromDate() throws JsonProcessingException { -// final VPackSlice vpack = new VPackSlice(mapper.writeValueAsBytes(new TestEntityDate())); -// assertThat(vpack).isNotNull(); -// assertThat(vpack.isObject()).isTrue(); -// { -// assertThat(vpack.get("utilDate").isString()).isTrue(); -// assertThat(vpack.get("utilDate").getAsString()).isEqualTo(DATE_FORMAT.format(new Date(1474988621))); -// } -// { -// assertThat(vpack.get("sqlDate").isString()).isTrue(); -// assertThat(vpack.get("sqlDate").getAsString()).isEqualTo(DATE_FORMAT.format(new java.sql.Date(1474988621))); -// } -// { -// assertThat(vpack.get("timestamp").isString()).isTrue(); -// assertThat(vpack.get("timestamp").getAsString()).isEqualTo(DATE_FORMAT.format(new java.sql.Timestamp(1474988621))); -// } -// } -// -// @Test -// void toDate() { -// final VPackBuilder builder = new VPackBuilder(); -// builder.add(ValueType.OBJECT); -// builder.add("utilDate", new Date(1475062216)); -// builder.add("sqlDate", new java.sql.Date(1475062216)); -// builder.add("timestamp", new java.sql.Timestamp(1475062216)); -// builder.close(); -// -// final TestEntityDate entity = new VPack.Builder().build().deserialize(builder.slice(), TestEntityDate.class); -// assertThat(entity).isNotNull(); -// assertThat(entity.utilDate).isEqualTo(new Date(1475062216)); -// assertThat(entity.sqlDate).isEqualTo(new java.sql.Date(1475062216)); -// assertThat(entity.timestamp).isEqualTo(new java.sql.Timestamp(1475062216)); -// } -// -// @Test -// void toDateFromString() { -// final VPackBuilder builder = new VPackBuilder(); -// builder.add(ValueType.OBJECT); -// builder.add("utilDate", DATE_FORMAT.format(new Date(1475062216))); -// builder.add("sqlDate", DATE_FORMAT.format(new java.sql.Date(1475062216))); -// builder.add("timestamp", DATE_FORMAT.format(new java.sql.Timestamp(1475062216))); -// builder.close(); -// -// final TestEntityDate entity = new VPack.Builder().build().deserialize(builder.slice(), TestEntityDate.class); -// assertThat(entity).isNotNull(); -// assertThat(entity.utilDate).isEqualTo(new Date(1475062216)); -// assertThat(entity.sqlDate).isEqualTo(new java.sql.Date(1475062216)); -// assertThat(entity.timestamp).isEqualTo(new java.sql.Timestamp(1475062216)); -// } -// -// public static class TestEntityUUID { -// private UUID uuid; -// -// UUID getUuid() { -// return uuid; -// } -// -// void setUuid(final UUID uuid) { -// this.uuid = uuid; -// } -// } -// -// @Test -// void fromUUID() throws IOException { -// final TestEntityUUID entity = new TestEntityUUID(); -// entity.setUuid(UUID.randomUUID()); -// byte[] bytes = mapper.writeValueAsBytes(entity); -// final VPackSlice vpack = new VPackSlice(bytes); -// assertThat(vpack).isNotNull(); -// assertThat(vpack.isObject()).isTrue(); -// -// final VPackSlice uuid = vpack.get("uuid"); -// assertThat(uuid.isString()).isTrue(); -// assertThat(uuid.getAsString()).isEqualTo(entity.getUuid().toString()); -// assertThat(mapper.readValue(bytes, TestEntityUUID.class).getUuid()).isEqualTo(entity.getUuid()); -// } -// -// @Test -// void toUUID() { -// final UUID uuid = UUID.randomUUID(); -// final VPackBuilder builder = new VPackBuilder(); -// builder.add(ValueType.OBJECT); -// builder.add("uuid", uuid.toString()); -// builder.close(); -// -// final TestEntityUUID entity = new VPack.Builder().build().deserialize(builder.slice(), TestEntityUUID.class); -// assertThat(entity).isNotNull(); -// assertThat(entity.uuid).isEqualTo(uuid); -// } -// -// @Test -// void uuid() { -// final TestEntityUUID entity = new TestEntityUUID(); -// entity.setUuid(UUID.randomUUID()); -// final VPack vpacker = new VPack.Builder().build(); -// final VPackSlice vpack = vpacker.serialize(entity); -// final TestEntityUUID entity2 = vpacker.deserialize(vpack, TestEntityUUID.class); -// assertThat(entity2).isNotNull(); -// assertThat(entity2.getUuid()).isEqualTo(entity.getUuid()); -// } -// -// private static class BinaryEntity { -// private byte[] foo; -// -// BinaryEntity() { -// super(); -// } -// } -// -// @Test -// void fromBinary() throws JsonProcessingException { -// final BinaryEntity entity = new BinaryEntity(); -// entity.foo = "bar".getBytes(); -// final VPackSlice vpack = new VPackSlice(mapper.writeValueAsBytes(entity)); -// assertThat(vpack).isNotNull(); -// assertThat(vpack.isObject()).isTrue(); -// assertThat(vpack.get("foo").isString()).isTrue(); -// assertThat(vpack.get("foo").getAsString()).isEqualTo(Base64.getEncoder().encodeToString(entity.foo)); -// } -// -// @Test -// void toBinary() throws IOException { -// final String value = Base64.getEncoder().encodeToString("bar".getBytes()); -// final VPackSlice vpack = new VPackBuilder().add(ValueType.OBJECT).add("foo", value).close().slice(); -// final BinaryEntity entity = mapper.readValue(vpack.getBuffer(), BinaryEntity.class); -// assertThat(entity).isNotNull(); -// assertThat(entity.foo).isEqualTo("bar".getBytes()); -// } -// -// @Test -// void asFloatingNumber() { -// final VPackSlice vpack = new VPackBuilder().add(ValueType.OBJECT).add("value", 12000).close().slice(); -// assertThat(vpack.get("value").getAsInt()).isEqualTo(12000); -// assertThat(vpack.get("value").getAsFloat()).isEqualTo(12000F); -// assertThat(vpack.get("value").getAsDouble()).isEqualTo(12000.); -// } -// -// @Test -// void toVPackSlice() throws IOException { -// final VPackSlice value = new VPackBuilder().add(ValueType.OBJECT).add("key", "value").close().slice(); -// final VPackSlice entity = mapper.readValue(value.getBuffer(), VPackSlice.class); -// assertThat(entity).isEqualTo(value); -// } -// -// -//} From e6930c681fa8be8f10c631c793a8762832dd9f5d Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Thu, 28 Jul 2022 10:06:56 +0200 Subject: [PATCH 051/254] removed dep on velocypack --- pom.xml | 9 --------- 1 file changed, 9 deletions(-) diff --git a/pom.xml b/pom.xml index fa82b22d5..a7893e292 100644 --- a/pom.xml +++ b/pom.xml @@ -234,10 +234,6 @@ - - com.arangodb - velocypack - org.slf4j slf4j-api @@ -318,11 +314,6 @@ commons-logging 1.2 - - com.arangodb - velocypack - 2.5.4 - org.slf4j slf4j-api From 6b5930c799eb35c0948c48ae66fee44a6809d8eb Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Thu, 28 Jul 2022 13:46:13 +0200 Subject: [PATCH 052/254] implemented MapperProvider to isolate references to optional VPackMapper --- .../java/com/arangodb/serde/InternalSerde.java | 10 +--------- .../java/com/arangodb/serde/JacksonSerde.java | 9 +-------- .../com/arangodb/serde/JsonMapperProvider.java | 12 ++++++++++++ .../java/com/arangodb/serde/MapperProvider.java | 17 +++++++++++++++++ .../com/arangodb/serde/VPackMapperProvider.java | 13 +++++++++++++ 5 files changed, 44 insertions(+), 17 deletions(-) create mode 100644 src/main/java/com/arangodb/serde/JsonMapperProvider.java create mode 100644 src/main/java/com/arangodb/serde/MapperProvider.java create mode 100644 src/main/java/com/arangodb/serde/VPackMapperProvider.java diff --git a/src/main/java/com/arangodb/serde/InternalSerde.java b/src/main/java/com/arangodb/serde/InternalSerde.java index 04215e6ee..05b175276 100644 --- a/src/main/java/com/arangodb/serde/InternalSerde.java +++ b/src/main/java/com/arangodb/serde/InternalSerde.java @@ -1,8 +1,6 @@ package com.arangodb.serde; -import com.arangodb.jackson.dataformat.velocypack.VPackMapper; import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; import java.lang.reflect.Type; import java.util.Collection; @@ -16,13 +14,7 @@ public interface InternalSerde extends JacksonSerde { * @return the created InternalSerde */ static InternalSerde of(final DataType dataType, ArangoSerde userSerde) { - if (dataType == DataType.JSON) { - return new InternalSerdeImpl(new ObjectMapper(), userSerde); - } else if (dataType == DataType.VPACK) { - return new InternalSerdeImpl(new VPackMapper(), userSerde); - } else { - throw new IllegalArgumentException("Unexpected value: " + dataType); - } + return new InternalSerdeImpl(MapperProvider.of(dataType), userSerde); } /** diff --git a/src/main/java/com/arangodb/serde/JacksonSerde.java b/src/main/java/com/arangodb/serde/JacksonSerde.java index c7c0ae2f0..c6fe4b1ed 100644 --- a/src/main/java/com/arangodb/serde/JacksonSerde.java +++ b/src/main/java/com/arangodb/serde/JacksonSerde.java @@ -1,6 +1,5 @@ package com.arangodb.serde; -import com.arangodb.jackson.dataformat.velocypack.VPackMapper; import com.fasterxml.jackson.databind.ObjectMapper; import java.util.function.Consumer; @@ -17,13 +16,7 @@ public interface JacksonSerde extends ArangoSerde { * @return the created JacksonSerde */ static JacksonSerde of(final DataType dataType) { - if (dataType == DataType.JSON) { - return of(new ObjectMapper()); - } else if (dataType == DataType.VPACK) { - return of(new VPackMapper()); - } else { - throw new IllegalArgumentException("Unexpected value: " + dataType); - } + return of(MapperProvider.of(dataType)); } /** diff --git a/src/main/java/com/arangodb/serde/JsonMapperProvider.java b/src/main/java/com/arangodb/serde/JsonMapperProvider.java new file mode 100644 index 000000000..033deef2f --- /dev/null +++ b/src/main/java/com/arangodb/serde/JsonMapperProvider.java @@ -0,0 +1,12 @@ +package com.arangodb.serde; + +import com.fasterxml.jackson.databind.ObjectMapper; + +enum JsonMapperProvider implements MapperProvider { + INSTANCE; + + @Override + public ObjectMapper get() { + return new ObjectMapper(); + } +} diff --git a/src/main/java/com/arangodb/serde/MapperProvider.java b/src/main/java/com/arangodb/serde/MapperProvider.java new file mode 100644 index 000000000..be5759a54 --- /dev/null +++ b/src/main/java/com/arangodb/serde/MapperProvider.java @@ -0,0 +1,17 @@ +package com.arangodb.serde; + +import com.fasterxml.jackson.databind.ObjectMapper; + +import java.util.function.Supplier; + +interface MapperProvider extends Supplier { + static ObjectMapper of(final DataType dataType) { + if (dataType == DataType.JSON) { + return JsonMapperProvider.INSTANCE.get(); + } else if (dataType == DataType.VPACK) { + return VPackMapperProvider.INSTANCE.get(); + } else { + throw new IllegalArgumentException("Unexpected value: " + dataType); + } + } +} diff --git a/src/main/java/com/arangodb/serde/VPackMapperProvider.java b/src/main/java/com/arangodb/serde/VPackMapperProvider.java new file mode 100644 index 000000000..95f4e1a7d --- /dev/null +++ b/src/main/java/com/arangodb/serde/VPackMapperProvider.java @@ -0,0 +1,13 @@ +package com.arangodb.serde; + +import com.arangodb.jackson.dataformat.velocypack.VPackMapper; +import com.fasterxml.jackson.databind.ObjectMapper; + +enum VPackMapperProvider implements MapperProvider { + INSTANCE; + + @Override + public ObjectMapper get() { + return new VPackMapper(); + } +} From 4a1778b930b2c11f2d98203da0bf4255c26595cf Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Thu, 28 Jul 2022 14:31:20 +0200 Subject: [PATCH 053/254] serialize/deserialize JsonNode with internal serde --- .../java/com/arangodb/serde/InternalSerde.java | 4 +--- .../com/arangodb/serde/InternalSerdeImpl.java | 16 +++++++++++++--- .../java/com/arangodb/ArangoDatabaseTest.java | 8 ++++++++ 3 files changed, 22 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/arangodb/serde/InternalSerde.java b/src/main/java/com/arangodb/serde/InternalSerde.java index 05b175276..2fcafb358 100644 --- a/src/main/java/com/arangodb/serde/InternalSerde.java +++ b/src/main/java/com/arangodb/serde/InternalSerde.java @@ -121,9 +121,7 @@ default T deserialize(byte[] content, String jsonPointer, Type type) { * @param clazz class of target data type * @return deserialized object */ - default T deserializeUserData(byte[] content, Class clazz) { - return deserializeUserData(content, (Type) clazz); - } + T deserializeUserData(byte[] content, Class clazz); /** * Deserializes the content and binds it to the target data type, using the user serde. diff --git a/src/main/java/com/arangodb/serde/InternalSerdeImpl.java b/src/main/java/com/arangodb/serde/InternalSerdeImpl.java index ae978c7fd..f5f1b097a 100644 --- a/src/main/java/com/arangodb/serde/InternalSerdeImpl.java +++ b/src/main/java/com/arangodb/serde/InternalSerdeImpl.java @@ -67,7 +67,8 @@ public JsonNode parse(byte[] content, String jsonPointer) { @Override public byte[] serializeUserData(Object value) { - if (value != null && (RawJson.class.equals(value.getClass()) || RawBytes.class.equals(value.getClass()))) { + Class clazz = value.getClass(); + if (RawJson.class.equals(clazz) || RawBytes.class.equals(clazz) || JsonNode.class.isAssignableFrom(clazz)) { return serialize(value); } else { return userSerde.serialize(value); @@ -83,10 +84,19 @@ public byte[] serializeCollectionUserData(Collection value) { return serialize(jsonNodeCollection); } + @Override + public T deserializeUserData(byte[] content, Class clazz) { + if (RawJson.class.isAssignableFrom(clazz) || RawBytes.class.isAssignableFrom(clazz) || JsonNode.class.isAssignableFrom(clazz)) { + return deserialize(content, clazz); + } else { + return userSerde.deserialize(content, clazz); + } + } + @Override public T deserializeUserData(byte[] content, Type type) { - if (RawJson.class.equals(type) || RawBytes.class.equals(type)) { - return deserialize(content, type); + if (type instanceof Class) { + return deserializeUserData(content, (Class) type); } else { return userSerde.deserialize(content, type); } diff --git a/src/test/java/com/arangodb/ArangoDatabaseTest.java b/src/test/java/com/arangodb/ArangoDatabaseTest.java index 1e4054984..ce781e18e 100644 --- a/src/test/java/com/arangodb/ArangoDatabaseTest.java +++ b/src/test/java/com/arangodb/ArangoDatabaseTest.java @@ -536,6 +536,14 @@ void query(ArangoDatabase db) { } } + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void queryWithNullBindVar(ArangoDatabase db) { + final ArangoCursor cursor = db.query("return @foo", Collections.singletonMap("foo", null), null, Object.class); + assertThat(cursor.hasNext()).isTrue(); + assertThat(cursor.next()).isNull(); + } + @ParameterizedTest(name = "{index}") @MethodSource("dbs") void queryForEach(ArangoDatabase db) { From d43f90021f6c0048a43295d8695b4cca915d3eca Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Thu, 28 Jul 2022 14:49:24 +0200 Subject: [PATCH 054/254] date serde tests --- .../java/com/arangodb/serde/SerdeTest.java | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/src/test/java/com/arangodb/serde/SerdeTest.java b/src/test/java/com/arangodb/serde/SerdeTest.java index 6e924e4fb..75c374659 100644 --- a/src/test/java/com/arangodb/serde/SerdeTest.java +++ b/src/test/java/com/arangodb/serde/SerdeTest.java @@ -2,12 +2,15 @@ import com.arangodb.util.RawBytes; import com.arangodb.util.RawJson; +import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.node.JsonNodeFactory; import com.fasterxml.jackson.databind.node.ObjectNode; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.EnumSource; +import java.sql.Date; + import static org.assertj.core.api.Assertions.assertThat; @@ -35,4 +38,32 @@ void rawBytesSerde(DataType type) { assertThat(deserialized).isEqualTo(raw); } + @ParameterizedTest + @EnumSource(DataType.class) + void utilDateSerde(DataType type) { + InternalSerde s = InternalSerde.of(type, null); + long ts = 1000000000000L; + java.util.Date date = new java.util.Date(ts); + byte[] ser = s.serialize(date); + JsonNode node = s.parse(ser); + assertThat(node.isLong()).isTrue(); + assertThat(node.longValue()).isEqualTo(ts); + java.util.Date deser = s.deserialize(ser, java.util.Date.class); + assertThat(deser).isEqualTo(date); + } + + @ParameterizedTest + @EnumSource(DataType.class) + void sqlDateSerde(DataType type) { + InternalSerde s = InternalSerde.of(type, null); + long ts = 1000000000000L; + java.sql.Date date = new Date(ts); + byte[] ser = s.serialize(date); + JsonNode node = s.parse(ser); + assertThat(node.isLong()).isTrue(); + assertThat(node.longValue()).isEqualTo(ts); + java.sql.Date deser = s.deserialize(ser, java.sql.Date.class); + assertThat(deser).isEqualTo(date); + } + } From 680e7fe7015c536e2eff5047e7f99ead9ca0c1ef Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Thu, 28 Jul 2022 17:42:52 +0200 Subject: [PATCH 055/254] test with different jackson versions --- .github/workflows/maven.yml | 43 +++++++++++++++++++ pom.xml | 20 +++++++++ .../arangodb/serde/InternalDeserializers.java | 22 ++++++---- .../com/arangodb/serde/InternalSerdeImpl.java | 4 ++ .../java/com/arangodb/serde/SerdeUtils.java | 18 ++++++++ .../com/arangodb/ArangoCollectionTest.java | 1 - 6 files changed, 99 insertions(+), 9 deletions(-) diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index 896069eb4..52114c15d 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -129,3 +129,46 @@ jobs: run: mvn -version - name: Test run: mvn --no-transfer-progress test -DargLine="-Duser.language=${{matrix.user-language}}" + + jackson-test: + timeout-minutes: 20 + runs-on: ubuntu-latest + + strategy: + fail-fast: false + matrix: + jackson-version: + - 2.13.3 + - 2.12.7 + - 2.11.4 + - 2.10.5 + docker-img: + - docker.io/arangodb/arangodb:3.9.1 + topology: + - single + db-ext-names: + - false + java-version: + - 17 + user-language: + - en + + steps: + - uses: actions/checkout@v2 + - name: Set up JDK + uses: actions/setup-java@v2 + with: + java-version: ${{matrix.java-version}} + distribution: 'adopt' + cache: maven + - name: Start Database + run: ./docker/start_db.sh + env: + ARANGO_LICENSE_KEY: ${{ secrets.ARANGO_LICENSE_KEY }} + STARTER_MODE: ${{matrix.topology}} + DOCKER_IMAGE: ${{matrix.docker-img}} + DATABASE_EXTENDED_NAMES: ${{matrix.db-ext-names}} + - name: Info + run: mvn -version + - name: Test + run: mvn --no-transfer-progress test -Djackson.version=${{jackson-version}} diff --git a/pom.xml b/pom.xml index a7893e292..1f59e16d8 100644 --- a/pom.xml +++ b/pom.xml @@ -23,6 +23,7 @@ UTF-8 + 2.13.3 @@ -242,6 +243,18 @@ org.apache.httpcomponents httpclient + + com.fasterxml.jackson.core + jackson-databind + + + com.fasterxml.jackson.core + jackson-core + + + com.fasterxml.jackson.core + jackson-annotations + com.arangodb jackson-dataformat-velocypack @@ -289,6 +302,13 @@ + + com.fasterxml.jackson + jackson-bom + ${jackson.version} + import + pom + com.arangodb jackson-dataformat-velocypack diff --git a/src/main/java/com/arangodb/serde/InternalDeserializers.java b/src/main/java/com/arangodb/serde/InternalDeserializers.java index 0a33aa444..f571b5f5b 100644 --- a/src/main/java/com/arangodb/serde/InternalDeserializers.java +++ b/src/main/java/com/arangodb/serde/InternalDeserializers.java @@ -11,11 +11,10 @@ import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.TreeNode; -import com.fasterxml.jackson.databind.*; -import com.fasterxml.jackson.databind.node.ArrayNode; -import com.fasterxml.jackson.databind.node.NumericNode; -import com.fasterxml.jackson.databind.node.ObjectNode; -import com.fasterxml.jackson.databind.node.TextNode; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonDeserializer; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.node.*; import java.io.ByteArrayOutputStream; import java.io.IOException; @@ -26,6 +25,13 @@ public final class InternalDeserializers { + private static T readTreeAsValue(JsonParser p, DeserializationContext ctxt, JsonNode n, Class targetType) throws IOException { + try (TreeTraversingParser t = new TreeTraversingParser(n, p.getCodec())) { + t.nextToken(); + return ctxt.readValue(t, targetType); + } + } + public static class CollectionLinksDeserializer extends JsonDeserializer> { @Override @@ -37,7 +43,7 @@ public Collection deserialize(JsonParser p, DeserializationConte Map.Entry e = it.next(); ObjectNode v = (ObjectNode) e.getValue(); v.put("name", e.getKey()); - out.add(ctxt.readTreeAsValue(v, CollectionLink.class)); + out.add(readTreeAsValue(p, ctxt, v, CollectionLink.class)); } return out; } @@ -54,7 +60,7 @@ public FieldLink[] deserialize(JsonParser p, DeserializationContext ctxt) throws Map.Entry e = it.next(); ObjectNode v = (ObjectNode) e.getValue(); v.put("name", e.getKey()); - out.add(ctxt.readTreeAsValue(v, FieldLink.class)); + out.add(readTreeAsValue(p, ctxt, v, FieldLink.class)); } return out.toArray(new FieldLink[0]); } @@ -126,7 +132,7 @@ public Response deserialize(final JsonParser p, final DeserializationContext ctx response.setType(it.next().intValue()); response.setResponseCode(it.next().intValue()); if (it.hasNext()) { - response.setMeta(ctxt.readTreeAsValue(it.next(), Map.class)); + response.setMeta(readTreeAsValue(p, ctxt, it.next(), Map.class)); } return response; } diff --git a/src/main/java/com/arangodb/serde/InternalSerdeImpl.java b/src/main/java/com/arangodb/serde/InternalSerdeImpl.java index f5f1b097a..68fa1a1d3 100644 --- a/src/main/java/com/arangodb/serde/InternalSerdeImpl.java +++ b/src/main/java/com/arangodb/serde/InternalSerdeImpl.java @@ -17,6 +17,10 @@ final class InternalSerdeImpl extends JacksonSerdeImpl implements InternalSerde private final ArangoSerde userSerde; + static { + SerdeUtils.INSTANCE.checkSupportedJacksonVersion(); + } + InternalSerdeImpl(final ObjectMapper mapper, final ArangoSerde userSerde) { super(mapper); this.userSerde = userSerde; diff --git a/src/main/java/com/arangodb/serde/SerdeUtils.java b/src/main/java/com/arangodb/serde/SerdeUtils.java index c93677825..87eb13d3d 100644 --- a/src/main/java/com/arangodb/serde/SerdeUtils.java +++ b/src/main/java/com/arangodb/serde/SerdeUtils.java @@ -1,6 +1,7 @@ package com.arangodb.serde; import com.arangodb.ArangoDBException; +import com.arangodb.jackson.dataformat.velocypack.VPackMapper; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.JavaType; import com.fasterxml.jackson.databind.JsonNode; @@ -9,8 +10,11 @@ import java.lang.reflect.Type; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import java.util.Map; +import java.util.logging.Level; +import java.util.logging.Logger; public enum SerdeUtils { INSTANCE; @@ -68,4 +72,18 @@ public Type convertToType(final JavaType javaType) { return constructParametricType(javaType.getRawClass(), args.toArray(new Type[0])); } + void checkSupportedJacksonVersion() { + Arrays.asList( + com.fasterxml.jackson.databind.cfg.PackageVersion.VERSION, + com.fasterxml.jackson.core.json.PackageVersion.VERSION + ).forEach(version -> { + int major = version.getMajorVersion(); + int minor = version.getMinorVersion(); + if (major != 2 || minor < 10 || minor > 13) { + Logger.getLogger(VPackMapper.class.getName()) + .log(Level.WARNING, "Unsupported Jackson version: {0}", version); + } + }); + } + } diff --git a/src/test/java/com/arangodb/ArangoCollectionTest.java b/src/test/java/com/arangodb/ArangoCollectionTest.java index 8e58b4c8b..07e173e79 100644 --- a/src/test/java/com/arangodb/ArangoCollectionTest.java +++ b/src/test/java/com/arangodb/ArangoCollectionTest.java @@ -41,7 +41,6 @@ import com.arangodb.util.RawBytes; import com.arangodb.util.RawJson; import com.fasterxml.jackson.annotation.JsonInclude; -import com.fasterxml.jackson.annotation.JsonIncludeProperties; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import org.junit.jupiter.api.BeforeAll; From 49dcdd5061349324d1bbf62ff218bac50acb9166 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Fri, 29 Jul 2022 14:29:40 +0200 Subject: [PATCH 056/254] JSON-B serde --- pom.xml | 11 +++ .../com/arangodb/entity/BaseDocument.java | 3 + src/main/java/com/arangodb/entity/From.java | 4 + src/main/java/com/arangodb/entity/Id.java | 4 + src/main/java/com/arangodb/entity/Key.java | 4 + src/main/java/com/arangodb/entity/Rev.java | 4 + src/main/java/com/arangodb/entity/To.java | 4 + .../java/com/arangodb/serde/ArangoSerde.java | 2 +- .../com/arangodb/serde/InternalSerdeImpl.java | 13 +++- .../java/com/arangodb/serde/JacksonSerde.java | 6 +- .../java/com/arangodb/serde/JsonbSerde.java | 29 +++++++ .../com/arangodb/serde/JsonbSerdeImpl.java | 32 ++++++++ .../com/arangodb/ArangoCollectionTest.java | 4 +- .../java/com/arangodb/ArangoDatabaseTest.java | 8 +- src/test/java/com/arangodb/BaseJunit5.java | 13 ++-- .../arangodb/async/serde/CustomSerdeTest.java | 76 ++++++++++--------- .../com/arangodb/serde/CustomSerdeTest.java | 76 ++++++++++--------- 17 files changed, 203 insertions(+), 90 deletions(-) create mode 100644 src/main/java/com/arangodb/serde/JsonbSerde.java create mode 100644 src/main/java/com/arangodb/serde/JsonbSerdeImpl.java diff --git a/pom.xml b/pom.xml index 1f59e16d8..355b4c4dc 100644 --- a/pom.xml +++ b/pom.xml @@ -260,6 +260,11 @@ jackson-dataformat-velocypack true + + jakarta.json.bind + jakarta.json.bind-api + 3.0.0 + ch.qos.logback logback-classic @@ -298,6 +303,12 @@ 22.1.0 test + + org.eclipse + yasson + 3.0.0 + test + diff --git a/src/main/java/com/arangodb/entity/BaseDocument.java b/src/main/java/com/arangodb/entity/BaseDocument.java index 72ea06cdc..1946afda1 100644 --- a/src/main/java/com/arangodb/entity/BaseDocument.java +++ b/src/main/java/com/arangodb/entity/BaseDocument.java @@ -23,6 +23,7 @@ import com.arangodb.internal.DocumentFields; import com.fasterxml.jackson.annotation.JsonAnyGetter; import com.fasterxml.jackson.annotation.JsonAnySetter; +import com.fasterxml.jackson.annotation.JsonInclude; import java.io.Serializable; import java.util.HashMap; @@ -94,6 +95,7 @@ public void setRevision(final String revision) { this.revision = revision; } + @JsonInclude @JsonAnyGetter public Map getProperties() { return properties; @@ -103,6 +105,7 @@ public void setProperties(final Map properties) { this.properties = properties; } + @JsonInclude @JsonAnySetter public void addAttribute(final String key, final Object value) { properties.put(key, value); diff --git a/src/main/java/com/arangodb/entity/From.java b/src/main/java/com/arangodb/entity/From.java index 056c1e1c6..4d3b63ca0 100644 --- a/src/main/java/com/arangodb/entity/From.java +++ b/src/main/java/com/arangodb/entity/From.java @@ -4,6 +4,8 @@ import com.fasterxml.jackson.annotation.JacksonAnnotationsInside; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; +import jakarta.json.bind.annotation.JsonbAnnotation; +import jakarta.json.bind.annotation.JsonbProperty; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; @@ -19,5 +21,7 @@ @JacksonAnnotationsInside @JsonProperty(DocumentFields.FROM) @JsonInclude(JsonInclude.Include.NON_NULL) +@JsonbAnnotation +@JsonbProperty("_from") public @interface From { } diff --git a/src/main/java/com/arangodb/entity/Id.java b/src/main/java/com/arangodb/entity/Id.java index f4333438d..5ebd39d46 100644 --- a/src/main/java/com/arangodb/entity/Id.java +++ b/src/main/java/com/arangodb/entity/Id.java @@ -4,6 +4,8 @@ import com.fasterxml.jackson.annotation.JacksonAnnotationsInside; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; +import jakarta.json.bind.annotation.JsonbAnnotation; +import jakarta.json.bind.annotation.JsonbProperty; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; @@ -19,5 +21,7 @@ @JacksonAnnotationsInside @JsonProperty(DocumentFields.ID) @JsonInclude(JsonInclude.Include.NON_NULL) +@JsonbAnnotation +@JsonbProperty("_id") public @interface Id { } diff --git a/src/main/java/com/arangodb/entity/Key.java b/src/main/java/com/arangodb/entity/Key.java index f510a2c65..2afc552a3 100644 --- a/src/main/java/com/arangodb/entity/Key.java +++ b/src/main/java/com/arangodb/entity/Key.java @@ -4,6 +4,8 @@ import com.fasterxml.jackson.annotation.JacksonAnnotationsInside; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; +import jakarta.json.bind.annotation.JsonbAnnotation; +import jakarta.json.bind.annotation.JsonbProperty; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; @@ -19,5 +21,7 @@ @JacksonAnnotationsInside @JsonProperty(DocumentFields.KEY) @JsonInclude(JsonInclude.Include.NON_NULL) +@JsonbAnnotation +@JsonbProperty("_key") public @interface Key { } diff --git a/src/main/java/com/arangodb/entity/Rev.java b/src/main/java/com/arangodb/entity/Rev.java index bd5aa7600..08dfa5c22 100644 --- a/src/main/java/com/arangodb/entity/Rev.java +++ b/src/main/java/com/arangodb/entity/Rev.java @@ -4,6 +4,8 @@ import com.fasterxml.jackson.annotation.JacksonAnnotationsInside; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; +import jakarta.json.bind.annotation.JsonbAnnotation; +import jakarta.json.bind.annotation.JsonbProperty; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; @@ -19,5 +21,7 @@ @JacksonAnnotationsInside @JsonProperty(DocumentFields.REV) @JsonInclude(JsonInclude.Include.NON_NULL) +@JsonbAnnotation +@JsonbProperty("_rev") public @interface Rev { } diff --git a/src/main/java/com/arangodb/entity/To.java b/src/main/java/com/arangodb/entity/To.java index a58db8604..deb60769c 100644 --- a/src/main/java/com/arangodb/entity/To.java +++ b/src/main/java/com/arangodb/entity/To.java @@ -4,6 +4,8 @@ import com.fasterxml.jackson.annotation.JacksonAnnotationsInside; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; +import jakarta.json.bind.annotation.JsonbAnnotation; +import jakarta.json.bind.annotation.JsonbProperty; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; @@ -19,5 +21,7 @@ @JacksonAnnotationsInside @JsonProperty(DocumentFields.TO) @JsonInclude(JsonInclude.Include.NON_NULL) +@JsonbAnnotation +@JsonbProperty("_to") public @interface To { } diff --git a/src/main/java/com/arangodb/serde/ArangoSerde.java b/src/main/java/com/arangodb/serde/ArangoSerde.java index f682ec35a..f09e1d2f6 100644 --- a/src/main/java/com/arangodb/serde/ArangoSerde.java +++ b/src/main/java/com/arangodb/serde/ArangoSerde.java @@ -13,7 +13,7 @@ * - low-level libraries without support to data binding *

* To create a custom serde based on Jackson, existing {@link JacksonSerde} can be reused and instantiated providing a - * custom configured ObjectMapper ({@link JacksonSerde#of(com.fasterxml.jackson.databind.ObjectMapper)}) or configured + * custom configured ObjectMapper ({@link JacksonSerde#create(com.fasterxml.jackson.databind.ObjectMapper)}) or configured * after creation through {@link JacksonSerde#configure(Consumer)}. */ public interface ArangoSerde { diff --git a/src/main/java/com/arangodb/serde/InternalSerdeImpl.java b/src/main/java/com/arangodb/serde/InternalSerdeImpl.java index 68fa1a1d3..2922c6544 100644 --- a/src/main/java/com/arangodb/serde/InternalSerdeImpl.java +++ b/src/main/java/com/arangodb/serde/InternalSerdeImpl.java @@ -1,6 +1,7 @@ package com.arangodb.serde; import com.arangodb.ArangoDBException; +import com.arangodb.entity.BaseDocument; import com.arangodb.util.RawBytes; import com.arangodb.util.RawJson; import com.fasterxml.jackson.annotation.JsonInclude; @@ -72,7 +73,11 @@ public JsonNode parse(byte[] content, String jsonPointer) { @Override public byte[] serializeUserData(Object value) { Class clazz = value.getClass(); - if (RawJson.class.equals(clazz) || RawBytes.class.equals(clazz) || JsonNode.class.isAssignableFrom(clazz)) { + if ( RawJson.class.equals(clazz) || + RawBytes.class.equals(clazz) || + JsonNode.class.isAssignableFrom(clazz) || + BaseDocument.class.isAssignableFrom(clazz) + ) { return serialize(value); } else { return userSerde.serialize(value); @@ -90,7 +95,11 @@ public byte[] serializeCollectionUserData(Collection value) { @Override public T deserializeUserData(byte[] content, Class clazz) { - if (RawJson.class.isAssignableFrom(clazz) || RawBytes.class.isAssignableFrom(clazz) || JsonNode.class.isAssignableFrom(clazz)) { + if ( RawJson.class.isAssignableFrom(clazz) || + RawBytes.class.isAssignableFrom(clazz) || + JsonNode.class.isAssignableFrom(clazz) || + BaseDocument.class.isAssignableFrom(clazz) + ) { return deserialize(content, clazz); } else { return userSerde.deserialize(content, clazz); diff --git a/src/main/java/com/arangodb/serde/JacksonSerde.java b/src/main/java/com/arangodb/serde/JacksonSerde.java index c6fe4b1ed..122601dcf 100644 --- a/src/main/java/com/arangodb/serde/JacksonSerde.java +++ b/src/main/java/com/arangodb/serde/JacksonSerde.java @@ -5,7 +5,7 @@ import java.util.function.Consumer; /** - * Contract for serialization/deserialization of user data, based on Jackson Databind. + * User data serde based on Jackson Databind. */ public interface JacksonSerde extends ArangoSerde { @@ -16,7 +16,7 @@ public interface JacksonSerde extends ArangoSerde { * @return the created JacksonSerde */ static JacksonSerde of(final DataType dataType) { - return of(MapperProvider.of(dataType)); + return create(MapperProvider.of(dataType)); } /** @@ -25,7 +25,7 @@ static JacksonSerde of(final DataType dataType) { * @param mapper Jackson ObjectMapper to use * @return the created JacksonSerde */ - static JacksonSerde of(final ObjectMapper mapper) { + static JacksonSerde create(final ObjectMapper mapper) { return new JacksonSerdeImpl(mapper); } diff --git a/src/main/java/com/arangodb/serde/JsonbSerde.java b/src/main/java/com/arangodb/serde/JsonbSerde.java new file mode 100644 index 000000000..c6dac0dcc --- /dev/null +++ b/src/main/java/com/arangodb/serde/JsonbSerde.java @@ -0,0 +1,29 @@ +package com.arangodb.serde; + +import jakarta.json.bind.JsonbConfig; + +/** + * User data serde based on Jakarta JSON Binding (JSON-B). + */ +public interface JsonbSerde extends ArangoSerde { + + /** + * Creates a new JsonbSerde with default settings. + * + * @return the created JsonbSerde + */ + static JsonbSerde create() { + return new JsonbSerdeImpl(); + } + + /** + * Creates a new JsonbSerde using the provided . + * + * @param config JsonbConfig to use + * @return the created JsonbSerde + */ + static JsonbSerde of(final JsonbConfig config) { + return new JsonbSerdeImpl(config); + } + +} diff --git a/src/main/java/com/arangodb/serde/JsonbSerdeImpl.java b/src/main/java/com/arangodb/serde/JsonbSerdeImpl.java new file mode 100644 index 000000000..17993ca2b --- /dev/null +++ b/src/main/java/com/arangodb/serde/JsonbSerdeImpl.java @@ -0,0 +1,32 @@ +package com.arangodb.serde; + +import jakarta.json.bind.Jsonb; +import jakarta.json.bind.JsonbBuilder; +import jakarta.json.bind.JsonbConfig; + +import java.lang.reflect.Type; +import java.nio.charset.StandardCharsets; + +class JsonbSerdeImpl implements JsonbSerde { + + private final Jsonb jsonb; + + JsonbSerdeImpl() { + jsonb = JsonbBuilder.create(); + } + + JsonbSerdeImpl(final JsonbConfig config) { + jsonb = JsonbBuilder.create(config); + } + + @Override + public byte[] serialize(Object value) { + return jsonb.toJson(value).getBytes(StandardCharsets.UTF_8); + } + + @Override + public T deserialize(byte[] content, Type type) { + return jsonb.fromJson(new String(content, StandardCharsets.UTF_8), type); + } + +} diff --git a/src/test/java/com/arangodb/ArangoCollectionTest.java b/src/test/java/com/arangodb/ArangoCollectionTest.java index 07e173e79..ad980df47 100644 --- a/src/test/java/com/arangodb/ArangoCollectionTest.java +++ b/src/test/java/com/arangodb/ArangoCollectionTest.java @@ -686,7 +686,7 @@ void updateDocumentKeepNullFalse(ArangoCollection collection) { assertThat(readResult.getProperties().keySet()).doesNotContain("a"); } - static class TestUpdateEntity { + public static class TestUpdateEntity { @SuppressWarnings("unused") private String a, b; @@ -699,7 +699,7 @@ public String getB() { } } - static class TestUpdateEntitySerializeNullFalse { + public static class TestUpdateEntitySerializeNullFalse { @SuppressWarnings("unused") private String a, b; diff --git a/src/test/java/com/arangodb/ArangoDatabaseTest.java b/src/test/java/com/arangodb/ArangoDatabaseTest.java index ce781e18e..a63eefd24 100644 --- a/src/test/java/com/arangodb/ArangoDatabaseTest.java +++ b/src/test/java/com/arangodb/ArangoDatabaseTest.java @@ -1299,13 +1299,13 @@ void transactionAllowImplicit(ArangoDatabase db) { public static class TransactionTestEntity { private String value; - public TransactionTestEntity() { - super(); - } - public String getValue() { return value; } + + public void setValue(String value) { + this.value = value; + } } @ParameterizedTest(name = "{index}") diff --git a/src/test/java/com/arangodb/BaseJunit5.java b/src/test/java/com/arangodb/BaseJunit5.java index b231b4a58..506bba0ef 100644 --- a/src/test/java/com/arangodb/BaseJunit5.java +++ b/src/test/java/com/arangodb/BaseJunit5.java @@ -3,6 +3,7 @@ import com.arangodb.entity.*; import com.arangodb.model.CollectionCreateOptions; import com.arangodb.model.GraphCreateOptions; +import com.arangodb.serde.JsonbSerde; import com.arangodb.util.TestUtils; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; @@ -12,17 +13,17 @@ import java.util.Collection; import java.util.List; import java.util.UUID; -import java.util.stream.Collectors; import java.util.stream.Stream; class BaseJunit5 { protected static final DbName TEST_DB = DbName.of("java_driver_test_db"); - private static final List adbs = Arrays.stream(Protocol.values()) - .map(p -> new ArangoDB.Builder() - .useProtocol(p) - .build()) - .collect(Collectors.toList()); + private static final List adbs = Arrays.asList( + new ArangoDB.Builder().useProtocol(Protocol.VST).build(), + new ArangoDB.Builder().useProtocol(Protocol.HTTP_VPACK).build(), + new ArangoDB.Builder().useProtocol(Protocol.HTTP_JSON).build(), + new ArangoDB.Builder().useProtocol(Protocol.HTTP_JSON).serializer(JsonbSerde.create()).build() + ); protected static Stream dbsStream() { return adbs.stream().map(adb -> adb.db(TEST_DB)); diff --git a/src/test/java/com/arangodb/async/serde/CustomSerdeTest.java b/src/test/java/com/arangodb/async/serde/CustomSerdeTest.java index 2546334bd..16816ec0b 100644 --- a/src/test/java/com/arangodb/async/serde/CustomSerdeTest.java +++ b/src/test/java/com/arangodb/async/serde/CustomSerdeTest.java @@ -25,7 +25,6 @@ import com.arangodb.async.ArangoCollectionAsync; import com.arangodb.async.ArangoDBAsync; import com.arangodb.async.ArangoDatabaseAsync; -import com.arangodb.entity.BaseDocument; import com.arangodb.model.DocumentCreateOptions; import com.arangodb.serde.DataType; import com.arangodb.serde.JacksonSerde; @@ -37,6 +36,7 @@ import java.math.BigInteger; import java.util.Collections; import java.util.HashMap; +import java.util.Map; import java.util.UUID; import java.util.concurrent.ExecutionException; @@ -85,86 +85,90 @@ void shutdown() throws ExecutionException, InterruptedException { void aqlSerialization() throws ExecutionException, InterruptedException { String key = "test-" + UUID.randomUUID(); - BaseDocument doc = new BaseDocument(key); - doc.addAttribute("arr", Collections.singletonList("hello")); - doc.addAttribute("int", 10); + Map doc = new HashMap<>(); + doc.put("_key", key); + doc.put("arr", Collections.singletonList("hello")); + doc.put("int", 10); HashMap params = new HashMap<>(); params.put("doc", doc); params.put("@collection", COLLECTION_NAME); - BaseDocument result = db.query( + Map result = db.query( "INSERT @doc INTO @@collection RETURN NEW", params, - BaseDocument.class + Map.class ).get().next(); - assertThat(result.getAttribute("arr")).isInstanceOf(String.class); - assertThat(result.getAttribute("arr")).isEqualTo("hello"); - assertThat(result.getAttribute("int")).isInstanceOf(BigInteger.class); - assertThat(result.getAttribute("int")).isEqualTo(BigInteger.valueOf(10)); + assertThat(result.get("arr")).isInstanceOf(String.class); + assertThat(result.get("arr")).isEqualTo("hello"); + assertThat(result.get("int")).isInstanceOf(BigInteger.class); + assertThat(result.get("int")).isEqualTo(BigInteger.valueOf(10)); } @Test void aqlDeserialization() throws ExecutionException, InterruptedException { String key = "test-" + UUID.randomUUID(); - BaseDocument doc = new BaseDocument(key); - doc.addAttribute("arr", Collections.singletonList("hello")); - doc.addAttribute("int", 10); + Map doc = new HashMap<>(); + doc.put("_key", key); + doc.put("arr", Collections.singletonList("hello")); + doc.put("int", 10); collection.insertDocument(doc, null).get(); - final BaseDocument result = db.query( + final Map result = db.query( "RETURN DOCUMENT(@docId)", Collections.singletonMap("docId", COLLECTION_NAME + "/" + key), - BaseDocument.class + Map.class ).get().next(); - assertThat(result.getAttribute("arr")).isInstanceOf(String.class); - assertThat(result.getAttribute("arr")).isEqualTo("hello"); - assertThat(result.getAttribute("int")).isInstanceOf(BigInteger.class); - assertThat(result.getAttribute("int")).isEqualTo(BigInteger.valueOf(10)); + assertThat(result.get("arr")).isInstanceOf(String.class); + assertThat(result.get("arr")).isEqualTo("hello"); + assertThat(result.get("int")).isInstanceOf(BigInteger.class); + assertThat(result.get("int")).isEqualTo(BigInteger.valueOf(10)); } @Test void insertDocument() throws ExecutionException, InterruptedException { String key = "test-" + UUID.randomUUID(); - BaseDocument doc = new BaseDocument(key); - doc.addAttribute("arr", Collections.singletonList("hello")); - doc.addAttribute("int", 10); + Map doc = new HashMap<>(); + doc.put("_key", key); + doc.put("arr", Collections.singletonList("hello")); + doc.put("int", 10); - BaseDocument result = collection.insertDocument( + Map result = collection.insertDocument( doc, new DocumentCreateOptions().returnNew(true) ).get().getNew(); - assertThat(result.getAttribute("arr")).isInstanceOf(String.class); - assertThat(result.getAttribute("arr")).isEqualTo("hello"); - assertThat(result.getAttribute("int")).isInstanceOf(BigInteger.class); - assertThat(result.getAttribute("int")).isEqualTo(BigInteger.valueOf(10)); + assertThat(result.get("arr")).isInstanceOf(String.class); + assertThat(result.get("arr")).isEqualTo("hello"); + assertThat(result.get("int")).isInstanceOf(BigInteger.class); + assertThat(result.get("int")).isEqualTo(BigInteger.valueOf(10)); } @Test void getDocument() throws ExecutionException, InterruptedException { String key = "test-" + UUID.randomUUID(); - BaseDocument doc = new BaseDocument(key); - doc.addAttribute("arr", Collections.singletonList("hello")); - doc.addAttribute("int", 10); + Map doc = new HashMap<>(); + doc.put("_key", key); + doc.put("arr", Collections.singletonList("hello")); + doc.put("int", 10); collection.insertDocument(doc, null).get(); - final BaseDocument result = db.collection(COLLECTION_NAME).getDocument( + final Map result = db.collection(COLLECTION_NAME).getDocument( key, - BaseDocument.class, + Map.class, null).get(); - assertThat(result.getAttribute("arr")).isInstanceOf(String.class); - assertThat(result.getAttribute("arr")).isEqualTo("hello"); - assertThat(result.getAttribute("int")).isInstanceOf(BigInteger.class); - assertThat(result.getAttribute("int")).isEqualTo(BigInteger.valueOf(10)); + assertThat(result.get("arr")).isInstanceOf(String.class); + assertThat(result.get("arr")).isEqualTo("hello"); + assertThat(result.get("int")).isInstanceOf(BigInteger.class); + assertThat(result.get("int")).isEqualTo(BigInteger.valueOf(10)); } } diff --git a/src/test/java/com/arangodb/serde/CustomSerdeTest.java b/src/test/java/com/arangodb/serde/CustomSerdeTest.java index f00656d43..5fae2ba2f 100644 --- a/src/test/java/com/arangodb/serde/CustomSerdeTest.java +++ b/src/test/java/com/arangodb/serde/CustomSerdeTest.java @@ -25,7 +25,6 @@ import com.arangodb.ArangoDB; import com.arangodb.ArangoDatabase; import com.arangodb.DbName; -import com.arangodb.entity.BaseDocument; import com.arangodb.model.DocumentCreateOptions; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.core.JsonParser; @@ -40,6 +39,7 @@ import java.math.BigInteger; import java.util.Collections; import java.util.HashMap; +import java.util.Map; import java.util.UUID; import static com.fasterxml.jackson.databind.DeserializationFeature.USE_BIG_INTEGER_FOR_INTS; @@ -142,86 +142,90 @@ void manualCustomPersonDeserializer() { void aqlSerialization() { String key = "test-" + UUID.randomUUID(); - BaseDocument doc = new BaseDocument(key); - doc.addAttribute("arr", Collections.singletonList("hello")); - doc.addAttribute("int", 10); + Map doc = new HashMap<>(); + doc.put("_key", key); + doc.put("arr", Collections.singletonList("hello")); + doc.put("int", 10); HashMap params = new HashMap<>(); params.put("doc", doc); params.put("@collection", COLLECTION_NAME); - BaseDocument result = db.query( + Map result = db.query( "INSERT @doc INTO @@collection RETURN NEW", params, - BaseDocument.class + Map.class ).next(); - assertThat(result.getAttribute("arr")).isInstanceOf(String.class); - assertThat(result.getAttribute("arr")).isEqualTo("hello"); - assertThat(result.getAttribute("int")).isInstanceOf(BigInteger.class); - assertThat(result.getAttribute("int")).isEqualTo(BigInteger.valueOf(10)); + assertThat(result.get("arr")).isInstanceOf(String.class); + assertThat(result.get("arr")).isEqualTo("hello"); + assertThat(result.get("int")).isInstanceOf(BigInteger.class); + assertThat(result.get("int")).isEqualTo(BigInteger.valueOf(10)); } @Test void aqlDeserialization() { String key = "test-" + UUID.randomUUID(); - BaseDocument doc = new BaseDocument(key); - doc.addAttribute("arr", Collections.singletonList("hello")); - doc.addAttribute("int", 10); + Map doc = new HashMap<>(); + doc.put("_key", key); + doc.put("arr", Collections.singletonList("hello")); + doc.put("int", 10); collection.insertDocument(doc, null); - final BaseDocument result = db.query( + final Map result = db.query( "RETURN DOCUMENT(@docId)", Collections.singletonMap("docId", COLLECTION_NAME + "/" + key), - BaseDocument.class + Map.class ).next(); - assertThat(result.getAttribute("arr")).isInstanceOf(String.class); - assertThat(result.getAttribute("arr")).isEqualTo("hello"); - assertThat(result.getAttribute("int")).isInstanceOf(BigInteger.class); - assertThat(result.getAttribute("int")).isEqualTo(BigInteger.valueOf(10)); + assertThat(result.get("arr")).isInstanceOf(String.class); + assertThat(result.get("arr")).isEqualTo("hello"); + assertThat(result.get("int")).isInstanceOf(BigInteger.class); + assertThat(result.get("int")).isEqualTo(BigInteger.valueOf(10)); } @Test void insertDocument() { String key = "test-" + UUID.randomUUID(); - BaseDocument doc = new BaseDocument(key); - doc.addAttribute("arr", Collections.singletonList("hello")); - doc.addAttribute("int", 10); + Map doc = new HashMap<>(); + doc.put("_key", key); + doc.put("arr", Collections.singletonList("hello")); + doc.put("int", 10); - BaseDocument result = collection.insertDocument( + Map result = collection.insertDocument( doc, new DocumentCreateOptions().returnNew(true) ).getNew(); - assertThat(result.getAttribute("arr")).isInstanceOf(String.class); - assertThat(result.getAttribute("arr")).isEqualTo("hello"); - assertThat(result.getAttribute("int")).isInstanceOf(BigInteger.class); - assertThat(result.getAttribute("int")).isEqualTo(BigInteger.valueOf(10)); + assertThat(result.get("arr")).isInstanceOf(String.class); + assertThat(result.get("arr")).isEqualTo("hello"); + assertThat(result.get("int")).isInstanceOf(BigInteger.class); + assertThat(result.get("int")).isEqualTo(BigInteger.valueOf(10)); } @Test void getDocument() { String key = "test-" + UUID.randomUUID(); - BaseDocument doc = new BaseDocument(key); - doc.addAttribute("arr", Collections.singletonList("hello")); - doc.addAttribute("int", 10); + Map doc = new HashMap<>(); + doc.put("_key", key); + doc.put("arr", Collections.singletonList("hello")); + doc.put("int", 10); collection.insertDocument(doc, null); - final BaseDocument result = db.collection(COLLECTION_NAME).getDocument( + final Map result = db.collection(COLLECTION_NAME).getDocument( key, - BaseDocument.class, + Map.class, null); - assertThat(result.getAttribute("arr")).isInstanceOf(String.class); - assertThat(result.getAttribute("arr")).isEqualTo("hello"); - assertThat(result.getAttribute("int")).isInstanceOf(BigInteger.class); - assertThat(result.getAttribute("int")).isEqualTo(BigInteger.valueOf(10)); + assertThat(result.get("arr")).isInstanceOf(String.class); + assertThat(result.get("arr")).isEqualTo("hello"); + assertThat(result.get("int")).isInstanceOf(BigInteger.class); + assertThat(result.get("int")).isEqualTo(BigInteger.valueOf(10)); } @Test From c4fe60389792ea771db9086a79bfac4504aadede Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Mon, 1 Aug 2022 11:59:21 +0200 Subject: [PATCH 057/254] fixed native tests --- .../META-INF/native-image/reflect-config.json | 42 +++++++++++++------ 1 file changed, 30 insertions(+), 12 deletions(-) diff --git a/src/test/resources/META-INF/native-image/reflect-config.json b/src/test/resources/META-INF/native-image/reflect-config.json index 717f0a566..a7c217b64 100644 --- a/src/test/resources/META-INF/native-image/reflect-config.json +++ b/src/test/resources/META-INF/native-image/reflect-config.json @@ -74,16 +74,16 @@ ] }, { - "name":"com.arangodb.ArangoCollectionTest$TestUpdateEntity", - "allDeclaredFields":true, - "allDeclaredMethods":true, - "allDeclaredConstructors":true + "name": "com.arangodb.ArangoCollectionTest$TestUpdateEntity", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true }, { - "name":"com.arangodb.ArangoCollectionTest$TestUpdateEntitySerializeNullFalse", - "allDeclaredFields":true, - "allDeclaredMethods":true, - "allDeclaredConstructors":true + "name": "com.arangodb.ArangoCollectionTest$TestUpdateEntitySerializeNullFalse", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true }, { "name": "com.arangodb.ArangoDatabaseTest$TransactionTestEntity", @@ -264,9 +264,27 @@ "allDeclaredConstructors": true }, { - "name":"com.arangodb.mapping.annotations.AnnotatedEntity", - "allDeclaredFields":true, - "allDeclaredMethods":true, - "allDeclaredConstructors":true + "name": "com.arangodb.mapping.annotations.AnnotatedEntity", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.fasterxml.jackson.databind.deser.std.DateDeserializers$SqlDateDeserializer", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + }, + { + "name": "com.fasterxml.jackson.databind.ser.std.SqlDateSerializer", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] } ] From 27775bea9fd78d7a96b2d990096b7c436fe4e6f8 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Mon, 1 Aug 2022 12:54:09 +0200 Subject: [PATCH 058/254] CI fixes --- .github/workflows/maven.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index 52114c15d..ade8cdd60 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -171,4 +171,4 @@ jobs: - name: Info run: mvn -version - name: Test - run: mvn --no-transfer-progress test -Djackson.version=${{jackson-version}} + run: mvn --no-transfer-progress test -Djackson.version=${{matrix.jackson-version}} From 0c0478e3cec241132b5f260b88e328f8b39a2b54 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Mon, 1 Aug 2022 13:24:46 +0200 Subject: [PATCH 059/254] set JSON-B version 2.0.0 to be compatible with Java 8 --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 355b4c4dc..ba2b0d4db 100644 --- a/pom.xml +++ b/pom.xml @@ -263,7 +263,7 @@ jakarta.json.bind jakarta.json.bind-api - 3.0.0 + 2.0.0 ch.qos.logback @@ -306,7 +306,7 @@ org.eclipse yasson - 3.0.0 + 2.0.4 test From 272d4a655cd30542cce8b52041fdaf300628c7c7 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Mon, 1 Aug 2022 13:30:47 +0200 Subject: [PATCH 060/254] set info log level for tests --- src/test/resources/logback-test.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/resources/logback-test.xml b/src/test/resources/logback-test.xml index 579f1b9db..f67855e9c 100644 --- a/src/test/resources/logback-test.xml +++ b/src/test/resources/logback-test.xml @@ -8,7 +8,7 @@ - + From 35db02461c31990cceedb0f9b913afbc9bb8ea04 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Mon, 1 Aug 2022 13:36:24 +0200 Subject: [PATCH 061/254] fixed GraalVM tests --- .github/workflows/maven.yml | 1 + .github/workflows/native.yml | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index ade8cdd60..2d81eb74a 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -78,6 +78,7 @@ jobs: version: 'latest' java-version: '11' github-token: ${{ secrets.GITHUB_TOKEN }} + components: 'js' - name: Info run: mvn -version - name: Test diff --git a/.github/workflows/native.yml b/.github/workflows/native.yml index 2649ed0de..08882d850 100644 --- a/.github/workflows/native.yml +++ b/.github/workflows/native.yml @@ -29,7 +29,7 @@ jobs: version: 'latest' java-version: ${{matrix.java-version}} github-token: ${{ secrets.GITHUB_TOKEN }} - components: 'native-image' + components: 'native-image,js' - name: Start Database run: ./docker/start_db.sh env: From 8d92c4023526dc53d87e86f046132b95267646c1 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Mon, 1 Aug 2022 15:04:35 +0200 Subject: [PATCH 062/254] deps upd --- pom.xml | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/pom.xml b/pom.xml index ba2b0d4db..2c699fc5f 100644 --- a/pom.xml +++ b/pom.xml @@ -120,7 +120,7 @@ org.apache.maven.plugins maven-enforcer-plugin - 3.0.0-M3 + 3.1.0 enforce @@ -130,6 +130,9 @@ + + 3.6 + @@ -138,7 +141,7 @@ org.sonatype.plugins nexus-staging-maven-plugin - 1.6.8 + 1.6.13 true ossrh @@ -150,7 +153,7 @@ org.apache.maven.plugins maven-compiler-plugin - 3.8.1 + 3.10.1 -Xlint:unchecked @@ -164,7 +167,7 @@ org.apache.maven.plugins maven-resources-plugin - 3.1.0 + 3.3.0 UTF-8 @@ -172,7 +175,7 @@ org.apache.maven.plugins maven-source-plugin - 3.2.0 + 3.2.1 @@ -184,7 +187,7 @@ org.apache.maven.plugins maven-javadoc-plugin - 3.2.0 + 3.4.0 attach-javadocs @@ -200,7 +203,7 @@ org.apache.maven.plugins maven-surefire-plugin - 3.0.0-M5 + 3.0.0-M7 **/*Test.java @@ -211,16 +214,15 @@ org.apache.maven.plugins maven-deploy-plugin - 2.8.2 + 3.0.0 - false 10 org.apache.maven.plugins maven-gpg-plugin - 1.6 + 3.0.1 sign-artifacts @@ -288,19 +290,19 @@ org.assertj assertj-core - 3.22.0 + 3.23.1 test org.reflections reflections - 0.9.12 + 0.10.2 test org.graalvm.sdk graal-sdk - 22.1.0 + 22.2.0 test @@ -353,12 +355,12 @@ ch.qos.logback logback-classic - 1.2.9 + 1.2.11 org.junit junit-bom - 5.8.2 + 5.9.0 pom import From 8e7651f341277ef73b5de66f78ae1403e74a5f79 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Mon, 1 Aug 2022 15:29:16 +0200 Subject: [PATCH 063/254] maven flatten plugin --- pom.xml | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/pom.xml b/pom.xml index 2c699fc5f..88778cd5f 100644 --- a/pom.xml +++ b/pom.xml @@ -233,6 +233,32 @@ + + org.codehaus.mojo + flatten-maven-plugin + 1.2.7 + + oss + + + + + flatten + process-resources + + flatten + + + + + flatten.clean + clean + + clean + + + + From 69b3aaedd21266a2534ba87fc3358f78ecaa1ac6 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Mon, 1 Aug 2022 15:46:31 +0200 Subject: [PATCH 064/254] removed travis tests --- .travis.yml | 15 --------- tests/travis/server.pem | 29 ------------------ tests/travis/setup_arangodb.sh | 56 ---------------------------------- 3 files changed, 100 deletions(-) delete mode 100644 .travis.yml delete mode 100644 tests/travis/server.pem delete mode 100755 tests/travis/setup_arangodb.sh diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index b1ec09396..000000000 --- a/.travis.yml +++ /dev/null @@ -1,15 +0,0 @@ -language: java - -before_script: - - chmod 777 ./tests/travis/setup_arangodb.sh - - ./tests/travis/setup_arangodb.sh - -after_script: - - killall -9 arangod_x86_64 - -install: mvn install -DskipTests=true -Dgpg.skip=true -Dmaven.javadoc.skip=true -B -V - -jdk: - - oraclejdk8 - -sudo: false diff --git a/tests/travis/server.pem b/tests/travis/server.pem deleted file mode 100644 index 108998782..000000000 --- a/tests/travis/server.pem +++ /dev/null @@ -1,29 +0,0 @@ ------BEGIN CERTIFICATE----- -MIICKTCCAZICCQDrch/8O8H4PTANBgkqhkiG9w0BAQUFADBZMQswCQYDVQQGEwJE -RTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0 -cyBQdHkgTHRkMRIwEAYDVQQDDAlsb2NhbGhvc3QwHhcNMTIwNzI0MDYxNzUwWhcN -MTMwNzI0MDYxNzUwWjBZMQswCQYDVQQGEwJERTETMBEGA1UECAwKU29tZS1TdGF0 -ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMRIwEAYDVQQDDAls -b2NhbGhvc3QwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMDwRweF75H+BFBY -m9c4V/AZyWehxQ+pRfy6d+oPiUbOByqLDEQBdiMamQ0acJX9sn+MsFixEDRC1Y8r -ef49k1hb9V/pPtSFPVl5y8Db4FiDabKD9juUvNRqCXAzu99dwJwFZU2Ldq4BiCmf -8V0SO+nHJHs3+HNgbYU+g77Fax7dAgMBAAEwDQYJKoZIhvcNAQEFBQADgYEASYfI -Afq5lRn+XoESn+PQ89XJ83Jr5mJhDkT7ebw+w1CQsnR9uYIeAYNxOyb3bfHOntnz -3irGYJWkrewVYjNkID8jhZSYEOZkfC4jxNLigg7QXyw/XWwwCIEr8/ZW+cnci43G -+IhSspyoJnljELM99ZsW0IaBLT+tgHzep4bIh0Y= ------END CERTIFICATE----- ------BEGIN RSA PRIVATE KEY----- -MIICXgIBAAKBgQDA8EcHhe+R/gRQWJvXOFfwGclnocUPqUX8unfqD4lGzgcqiwxE -AXYjGpkNGnCV/bJ/jLBYsRA0QtWPK3n+PZNYW/Vf6T7UhT1ZecvA2+BYg2myg/Y7 -lLzUaglwM7vfXcCcBWVNi3auAYgpn/FdEjvpxyR7N/hzYG2FPoO+xWse3QIDAQAB -AoGBALsP+34C0M02gI456xbXDQPArLJqePp/P1kSnbL0zz80AGSyHflNhXHxltTK -fsAeElNyX4QOYEybRB2kpInov5KrL3lR926GY++otHpSAue+PfLJHH8OU8qjartw -KGlzdnFFYQVLNc0qYGl/h0MxH6+Ce8JV0y1zI4J3nwMwCZwBAkEA6uqluGj4SXIj -6W+FefuHlHXgFn+TZgsGNNmmCMhLJPUUP7auIagtG1n12mN47kWqhLu3asLEVq4+ -YnCEa0hF3QJBANJBKN/zyfmvkiET33cY03282gSN0YLyibMYoNDOOYMFEW2b+3oF -x0d40FfEkYS0R4rJiR1HI8xWw8uQEWsXLQECQQDRx1DN6Q8vpznij7BGShO8w7ak -4LAkA9w6/dGDLjnMev7mFqBRdfkx35foucOYI6YueeNE90CVl2wmRAw8MYIRAkEA -qUUgPTyuDMCWqt6u99ka243hD+2FESFmTrOzNKfykVLRNydvDEv+pcHUKfTtGqNx -PYEHTHTrkyT/OLFh9I+SAQJAOntw15vhgKiy0DUvjSvXGJziBDPsu/MCZ2CZbaVx -ipkUZQCZLd/HvMphAiirLV+mAJQC732KKlR9/HWRzDDFEQ== ------END RSA PRIVATE KEY----- diff --git a/tests/travis/setup_arangodb.sh b/tests/travis/setup_arangodb.sh deleted file mode 100755 index 5613ad035..000000000 --- a/tests/travis/setup_arangodb.sh +++ /dev/null @@ -1,56 +0,0 @@ -#!/bin/bash - -DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -cd $DIR - -VERSION=devel -NAME=ArangoDB-$VERSION - -if [ ! -d "$DIR/$NAME" ]; then - # download ArangoDB - echo "wget https://www.arangodb.com/repositories/travisCI/$NAME.tar.gz" - wget https://www.arangodb.com/repositories/travisCI/$NAME.tar.gz - echo "tar zxf $NAME.tar.gz" - tar zvxf $NAME.tar.gz -fi - -ARCH=$(arch) -PID=$(echo $PPID) -TMP_DIR="/tmp/arangodb.$PID" -PID_FILE="/tmp/arangodb.$PID.pid" -ARANGODB_DIR="$DIR/$NAME" -ARANGOD="${ARANGODB_DIR}/bin/arangod_x86_64" - -# create database directory -mkdir ${TMP_DIR} - -echo "Starting ArangoDB '${ARANGOD}'" - -${ARANGOD} \ - --database.directory ${TMP_DIR} \ - --configuration none \ - --server.endpoint tcp://127.0.0.1:8529 \ - --server.endpoint ssl://127.0.0.1:8530 \ - --ssl.keyfile ./server.pem \ - --javascript.app-path ${ARANGODB_DIR}/js/apps \ - --javascript.startup-directory ${ARANGODB_DIR}/js \ - --server.authentication=true & - -sleep 2 - -echo "Check for arangod process" -process=$(ps auxww | grep "bin/arangod" | grep -v grep) - -if [ "x$process" == "x" ]; then - echo "no 'arangod' process found" - echo "ARCH = $ARCH" - exit 1 -fi - -echo "Waiting until ArangoDB is ready on port 8529" -while [[ -z $(curl -uroot: -s 'http://127.0.0.1:8529/_api/version') ]]; do - echo -n "." - sleep 2s -done - -echo "ArangoDB is up" From 0e9086856a61d99776c0aafdd8e815e44671327c Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Mon, 1 Aug 2022 16:11:36 +0200 Subject: [PATCH 065/254] set default protocol to HTTP_JSON --- src/main/java/com/arangodb/internal/ArangoDefaults.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/arangodb/internal/ArangoDefaults.java b/src/main/java/com/arangodb/internal/ArangoDefaults.java index 64ab6468b..43a2f1ba3 100644 --- a/src/main/java/com/arangodb/internal/ArangoDefaults.java +++ b/src/main/java/com/arangodb/internal/ArangoDefaults.java @@ -46,7 +46,7 @@ private ArangoDefaults() { public static final int MAX_CONNECTIONS_VST_DEFAULT = 1; public static final Integer CONNECTION_TTL_VST_DEFAULT = null; public static final int MAX_CONNECTIONS_HTTP_DEFAULT = 20; - public static final Protocol DEFAULT_NETWORK_PROTOCOL = Protocol.HTTP_VPACK; + public static final Protocol DEFAULT_NETWORK_PROTOCOL = Protocol.HTTP_JSON; public static final boolean DEFAULT_ACQUIRE_HOST_LIST = false; public static final int DEFAULT_ACQUIRE_HOST_LIST_INTERVAL = 60 * 60 * 1000; // hour public static final LoadBalancingStrategy DEFAULT_LOAD_BALANCING_STRATEGY = LoadBalancingStrategy.NONE; From da8dc41bea00e85cde04566cc53f8042d0f5afec Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Mon, 1 Aug 2022 20:31:50 +0200 Subject: [PATCH 066/254] [DE-295] removed DocumentCache --- .../async/internal/ArangoDBAsyncImpl.java | 4 +- .../async/internal/ArangoExecutorAsync.java | 5 +- .../com/arangodb/internal/ArangoDBImpl.java | 4 +- .../com/arangodb/internal/ArangoExecutor.java | 9 +- .../arangodb/internal/ArangoExecutorSync.java | 4 +- .../com/arangodb/internal/DocumentCache.java | 117 ------------------ .../internal/InternalArangoCollection.java | 41 ++---- .../InternalArangoEdgeCollection.java | 29 +---- .../InternalArangoVertexCollection.java | 30 +---- .../com/arangodb/ArangoCollectionTest.java | 26 ++-- .../arangodb/ArangoEdgeCollectionTest.java | 17 ++- .../java/com/arangodb/ArangoRouteTest.java | 14 ++- .../arangodb/ArangoVertexCollectionTest.java | 17 ++- .../arangodb/async/ArangoCollectionTest.java | 2 +- .../arangodb/internal/DocumentCacheTest.java | 70 ----------- .../com/arangodb/serde/CustomSerdeTest.java | 9 +- 16 files changed, 75 insertions(+), 323 deletions(-) delete mode 100644 src/main/java/com/arangodb/internal/DocumentCache.java delete mode 100644 src/test/java/com/arangodb/internal/DocumentCacheTest.java diff --git a/src/main/java/com/arangodb/async/internal/ArangoDBAsyncImpl.java b/src/main/java/com/arangodb/async/internal/ArangoDBAsyncImpl.java index e6a56e137..dc9ab39fc 100644 --- a/src/main/java/com/arangodb/async/internal/ArangoDBAsyncImpl.java +++ b/src/main/java/com/arangodb/async/internal/ArangoDBAsyncImpl.java @@ -73,7 +73,7 @@ public ArangoDBAsyncImpl( final int timeoutMs ) { - super(new ArangoExecutorAsync(asyncCommBuilder.build(util), util, new DocumentCache(), + super(new ArangoExecutorAsync(asyncCommBuilder.build(util), util, new QueueTimeMetricsImpl(responseQueueTimeSamples), timeoutMs), util, context); final VstCommunication cacheCom = syncCommBuilder.build(util); @@ -82,7 +82,7 @@ public ArangoDBAsyncImpl( this.asyncHostHandler = asyncHostHandler; this.syncHostHandler = syncHostHandler; - ArangoExecutorSync arangoExecutorSync = new ArangoExecutorSync(cp, util, new DocumentCache(), + ArangoExecutorSync arangoExecutorSync = new ArangoExecutorSync(cp, util, new QueueTimeMetricsImpl(responseQueueTimeSamples), timeoutMs); asyncHostResolver.init(arangoExecutorSync, util); syncHostResolver.init(arangoExecutorSync, util); diff --git a/src/main/java/com/arangodb/async/internal/ArangoExecutorAsync.java b/src/main/java/com/arangodb/async/internal/ArangoExecutorAsync.java index fc7372da9..0ae625493 100644 --- a/src/main/java/com/arangodb/async/internal/ArangoExecutorAsync.java +++ b/src/main/java/com/arangodb/async/internal/ArangoExecutorAsync.java @@ -23,7 +23,6 @@ import com.arangodb.ArangoDBException; import com.arangodb.async.internal.velocystream.VstCommunicationAsync; import com.arangodb.internal.ArangoExecutor; -import com.arangodb.internal.DocumentCache; import com.arangodb.internal.QueueTimeMetricsImpl; import com.arangodb.internal.net.HostHandle; import com.arangodb.serde.InternalSerde; @@ -45,8 +44,8 @@ public class ArangoExecutorAsync extends ArangoExecutor { private final ExecutorService outgoingExecutor = Executors.newSingleThreadExecutor(); public ArangoExecutorAsync(final VstCommunicationAsync communication, final InternalSerde util, - final DocumentCache documentCache, final QueueTimeMetricsImpl qtMetrics, final int timeoutMs) { - super(util, documentCache, qtMetrics, timeoutMs); + final QueueTimeMetricsImpl qtMetrics, final int timeoutMs) { + super(util, qtMetrics, timeoutMs); this.communication = communication; } diff --git a/src/main/java/com/arangodb/internal/ArangoDBImpl.java b/src/main/java/com/arangodb/internal/ArangoDBImpl.java index cdefb0d3a..3a77b239f 100644 --- a/src/main/java/com/arangodb/internal/ArangoDBImpl.java +++ b/src/main/java/com/arangodb/internal/ArangoDBImpl.java @@ -36,7 +36,6 @@ import com.arangodb.model.UserCreateOptions; import com.arangodb.model.UserUpdateOptions; import com.arangodb.util.ArangoCursorInitializer; -import com.arangodb.serde.InternalSerde; import com.arangodb.velocystream.Request; import com.arangodb.velocystream.Response; import org.slf4j.Logger; @@ -64,8 +63,7 @@ public ArangoDBImpl(final VstCommunicationSync.Builder vstBuilder, final HttpCom super(new ArangoExecutorSync( createProtocol(vstBuilder, httpBuilder, util, protocol), - util, - new DocumentCache(), new QueueTimeMetricsImpl(responseQueueTimeSamples), timeoutMs), + util, new QueueTimeMetricsImpl(responseQueueTimeSamples), timeoutMs), util, context); diff --git a/src/main/java/com/arangodb/internal/ArangoExecutor.java b/src/main/java/com/arangodb/internal/ArangoExecutor.java index 8a0555009..1aad9a93d 100644 --- a/src/main/java/com/arangodb/internal/ArangoExecutor.java +++ b/src/main/java/com/arangodb/internal/ArangoExecutor.java @@ -36,24 +36,17 @@ protected T createResult(final Type type, final Response response) { return serde.deserialize(response.getBody(), type); } - private final DocumentCache documentCache; private final QueueTimeMetricsImpl qtMetrics; private final InternalSerde serde; private final String timeoutS; - protected ArangoExecutor(final InternalSerde serde, final DocumentCache documentCache, - final QueueTimeMetricsImpl qtMetrics, final int timeoutMs) { + protected ArangoExecutor(final InternalSerde serde, final QueueTimeMetricsImpl qtMetrics, final int timeoutMs) { super(); - this.documentCache = documentCache; this.qtMetrics = qtMetrics; this.serde = serde; timeoutS = timeoutMs >= 1000 ? Integer.toString(timeoutMs / 1000) : null; } - public DocumentCache documentCache() { - return documentCache; - } - public interface ResponseDeserializer { T deserialize(Response response); } diff --git a/src/main/java/com/arangodb/internal/ArangoExecutorSync.java b/src/main/java/com/arangodb/internal/ArangoExecutorSync.java index 4d9d5875d..b9f1cecee 100644 --- a/src/main/java/com/arangodb/internal/ArangoExecutorSync.java +++ b/src/main/java/com/arangodb/internal/ArangoExecutorSync.java @@ -43,8 +43,8 @@ public class ArangoExecutorSync extends ArangoExecutor { private final CommunicationProtocol protocol; public ArangoExecutorSync(final CommunicationProtocol protocol, final InternalSerde util, - final DocumentCache documentCache, final QueueTimeMetricsImpl qtMetrics, final int timeoutMs) { - super(util, documentCache, qtMetrics, timeoutMs); + final QueueTimeMetricsImpl qtMetrics, final int timeoutMs) { + super(util, qtMetrics, timeoutMs); this.protocol = protocol; } diff --git a/src/main/java/com/arangodb/internal/DocumentCache.java b/src/main/java/com/arangodb/internal/DocumentCache.java deleted file mode 100644 index 61bef4676..000000000 --- a/src/main/java/com/arangodb/internal/DocumentCache.java +++ /dev/null @@ -1,117 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.internal; - -import com.arangodb.ArangoDBException; -import com.arangodb.entity.*; - -import java.lang.annotation.Annotation; -import java.lang.reflect.Field; -import java.lang.reflect.Modifier; -import java.util.*; -import java.util.Map.Entry; - -/** - * @author Mark Vollmary - */ -public class DocumentCache { - - private final Map, Map> cache; - - public DocumentCache() { - super(); - cache = new HashMap<>(); - } - - public void setValues(final Object doc, final Map values) throws ArangoDBException { - try { - final Map fields = getFields(doc.getClass()); - for (final Entry value : values.entrySet()) { - final Field field = fields.get(value.getKey()); - if (field != null) { - field.set(doc, value.getValue()); - } - } - } catch (final IllegalArgumentException | IllegalAccessException e) { - throw new ArangoDBException(e); - } - } - - private Map getFields(final Class clazz) { - Map fields = new HashMap<>(); - if (!isTypeRestricted(clazz)) { - fields = cache.get(clazz); - if (fields == null) { - fields = createFields(clazz); - cache.put(clazz, fields); - } - } - return fields; - } - - private boolean isTypeRestricted(final Class type) { - return Map.class.isAssignableFrom(type) || Collection.class.isAssignableFrom(type); - } - - private Map createFields(final Class clazz) { - final Map fields = new HashMap<>(); - Class tmp = clazz; - final Collection values = new ArrayList<>(DocumentFields.values()); - while (tmp != null && tmp != Object.class && values.size() > 0) { - final Field[] declaredFields = tmp.getDeclaredFields(); - for (int i = 0; i < declaredFields.length && values.size() > 0; i++) { - findAnnotation(values, fields, declaredFields[i]); - } - tmp = tmp.getSuperclass(); - } - return fields; - } - - private void findAnnotation( - final Collection values, - final Map fields, - final Field field) { - - for (Annotation annotation : field.getAnnotations()) { - if (annotation != null && !field.isSynthetic() && !Modifier.isStatic(field.getModifiers()) - && String.class.equals(field.getType())) { - String value = null; - if (annotation instanceof Id) { - value = DocumentFields.ID; - } else if (annotation instanceof Key) { - value = DocumentFields.KEY; - } else if (annotation instanceof Rev) { - value = DocumentFields.REV; - } else if (annotation instanceof From) { - value = DocumentFields.FROM; - } else if (annotation instanceof To) { - value = DocumentFields.TO; - } - - if (values.contains(value)) { - field.setAccessible(true); - fields.put(value, field); - values.remove(value); - } - } - } - } -} diff --git a/src/main/java/com/arangodb/internal/InternalArangoCollection.java b/src/main/java/com/arangodb/internal/InternalArangoCollection.java index 3840fd7a2..e9ed2a026 100644 --- a/src/main/java/com/arangodb/internal/InternalArangoCollection.java +++ b/src/main/java/com/arangodb/internal/InternalArangoCollection.java @@ -97,15 +97,7 @@ protected ResponseDeserializer> insertDocumentRespon final T value, final DocumentCreateOptions options) { return response -> { Type type = SerdeUtils.INSTANCE.constructParametricType(DocumentCreateEntity.class, value.getClass()); - final DocumentCreateEntity doc = getSerde().deserialize(response.getBody(), type); - if (options == null || Boolean.TRUE != options.getSilent()) { - final Map values = new HashMap<>(); - values.put(DocumentFields.ID, doc.getId()); - values.put(DocumentFields.KEY, doc.getKey()); - values.put(DocumentFields.REV, doc.getRev()); - executor.documentCache().setValues(value, values); - } - return doc; + return getSerde().deserialize(response.getBody(), type); }; } @@ -131,8 +123,7 @@ protected ResponseDeserializer>> final Collection errors = new ArrayList<>(); final Collection documentsAndErrors = new ArrayList<>(); final JsonNode body = getSerde().parse(response.getBody()); - for (final Iterator iterator = body.iterator(); iterator.hasNext(); ) { - final JsonNode next = iterator.next(); + for (final JsonNode next : body) { JsonNode isError = next.get(ArangoResponseField.ERROR_FIELD_NAME); if (isError != null && isError.booleanValue()) { final ErrorEntity error = getSerde().deserialize(next, ErrorEntity.class); @@ -208,8 +199,7 @@ protected ResponseDeserializer> getDocumentsResponseD final Collection errors = new ArrayList<>(); final Collection documentsAndErrors = new ArrayList<>(); final JsonNode body = getSerde().parse(response.getBody()); - for (final Iterator iterator = body.iterator(); iterator.hasNext(); ) { - final JsonNode next = iterator.next(); + for (final JsonNode next : body) { JsonNode isError = next.get(ArangoResponseField.ERROR_FIELD_NAME); if (isError != null && isError.booleanValue()) { final ErrorEntity error = getSerde().deserialize(next, ErrorEntity.class); @@ -248,13 +238,7 @@ protected ResponseDeserializer> replaceDocumentRespo final T value, final DocumentReplaceOptions options) { return response -> { Type type = SerdeUtils.INSTANCE.constructParametricType(DocumentUpdateEntity.class, value.getClass()); - final DocumentUpdateEntity doc = getSerde().deserialize(response.getBody(), type); - if (options == null || Boolean.TRUE != options.getSilent()) { - final Map values = new HashMap<>(); - values.put(DocumentFields.REV, doc.getRev()); - executor.documentCache().setValues(value, values); - } - return doc; + return getSerde().deserialize(response.getBody(), type); }; } @@ -280,8 +264,7 @@ protected ResponseDeserializer>> final Collection errors = new ArrayList<>(); final Collection documentsAndErrors = new ArrayList<>(); final JsonNode body = getSerde().parse(response.getBody()); - for (final Iterator iterator = body.iterator(); iterator.hasNext(); ) { - final JsonNode next = iterator.next(); + for (final JsonNode next : body) { JsonNode isError = next.get(ArangoResponseField.ERROR_FIELD_NAME); if (isError != null && isError.booleanValue()) { final ErrorEntity error = getSerde().deserialize(next, ErrorEntity.class); @@ -322,13 +305,7 @@ protected ResponseDeserializer> updateDocumentRes final T value, final DocumentUpdateOptions options, final Class returnType) { return response -> { Type type = SerdeUtils.INSTANCE.constructParametricType(DocumentUpdateEntity.class, returnType); - final DocumentUpdateEntity doc = getSerde().deserialize(response.getBody(), type); - if (options == null || Boolean.TRUE != options.getSilent()) { - final Map values = new HashMap<>(); - values.put(DocumentFields.REV, doc.getRev()); - executor.documentCache().setValues(value, values); - } - return doc; + return getSerde().deserialize(response.getBody(), type); }; } @@ -356,8 +333,7 @@ protected ResponseDeserializer>> final Collection errors = new ArrayList<>(); final Collection documentsAndErrors = new ArrayList<>(); final JsonNode body = getSerde().parse(response.getBody()); - for (final Iterator iterator = body.iterator(); iterator.hasNext(); ) { - final JsonNode next = iterator.next(); + for (final JsonNode next : body) { JsonNode isError = next.get(ArangoResponseField.ERROR_FIELD_NAME); if (isError != null && isError.booleanValue()) { final ErrorEntity error = getSerde().deserialize(next, ErrorEntity.class); @@ -416,8 +392,7 @@ protected ResponseDeserializer>> final Collection errors = new ArrayList<>(); final Collection documentsAndErrors = new ArrayList<>(); final JsonNode body = getSerde().parse(response.getBody()); - for (final Iterator iterator = body.iterator(); iterator.hasNext(); ) { - final JsonNode next = iterator.next(); + for (final JsonNode next : body) { JsonNode isError = next.get(ArangoResponseField.ERROR_FIELD_NAME); if (isError != null && isError.booleanValue()) { final ErrorEntity error = getSerde().deserialize(next, ErrorEntity.class); diff --git a/src/main/java/com/arangodb/internal/InternalArangoEdgeCollection.java b/src/main/java/com/arangodb/internal/InternalArangoEdgeCollection.java index 01e6b5e68..701ed3a74 100644 --- a/src/main/java/com/arangodb/internal/InternalArangoEdgeCollection.java +++ b/src/main/java/com/arangodb/internal/InternalArangoEdgeCollection.java @@ -29,9 +29,6 @@ import com.arangodb.velocystream.Request; import com.arangodb.velocystream.RequestType; -import java.util.HashMap; -import java.util.Map; - /** * @author Mark Vollmary */ @@ -70,15 +67,7 @@ protected Request insertEdgeRequest(final T value, final EdgeCreateOptions o } protected ResponseDeserializer insertEdgeResponseDeserializer(final T value) { - return response -> { - final EdgeEntity doc = getSerde().deserialize(response.getBody(), "/edge", EdgeEntity.class); - final Map values = new HashMap<>(); - values.put(DocumentFields.ID, doc.getId()); - values.put(DocumentFields.KEY, doc.getKey()); - values.put(DocumentFields.REV, doc.getRev()); - executor.documentCache().setValues(value, values); - return doc; - }; + return response -> getSerde().deserialize(response.getBody(), "/edge", EdgeEntity.class); } protected Request getEdgeRequest(final String key, final GraphDocumentReadOptions options) { @@ -110,13 +99,7 @@ protected Request replaceEdgeRequest(final String key, final T value, final } protected ResponseDeserializer replaceEdgeResponseDeserializer(final T value) { - return response -> { - final EdgeUpdateEntity doc = getSerde().deserialize(response.getBody(), "/edge", EdgeUpdateEntity.class); - final Map values = new HashMap<>(); - values.put(DocumentFields.REV, doc.getRev()); - executor.documentCache().setValues(value, values); - return doc; - }; + return response -> getSerde().deserialize(response.getBody(), "/edge", EdgeUpdateEntity.class); } protected Request updateEdgeRequest(final String key, final T value, final EdgeUpdateOptions options) { @@ -133,13 +116,7 @@ protected Request updateEdgeRequest(final String key, final T value, final E } protected ResponseDeserializer updateEdgeResponseDeserializer(final T value) { - return response -> { - final EdgeUpdateEntity doc = getSerde().deserialize(response.getBody(), "/edge", EdgeUpdateEntity.class); - final Map values = new HashMap<>(); - values.put(DocumentFields.REV, doc.getRev()); - executor.documentCache().setValues(value, values); - return doc; - }; + return response -> getSerde().deserialize(response.getBody(), "/edge", EdgeUpdateEntity.class); } protected Request deleteEdgeRequest(final String key, final EdgeDeleteOptions options) { diff --git a/src/main/java/com/arangodb/internal/InternalArangoVertexCollection.java b/src/main/java/com/arangodb/internal/InternalArangoVertexCollection.java index d7c9ebb8d..dd7f1140e 100644 --- a/src/main/java/com/arangodb/internal/InternalArangoVertexCollection.java +++ b/src/main/java/com/arangodb/internal/InternalArangoVertexCollection.java @@ -26,13 +26,9 @@ import com.arangodb.internal.util.DocumentUtil; import com.arangodb.internal.util.RequestUtils; import com.arangodb.model.*; -import com.arangodb.serde.SerdeUtils; import com.arangodb.velocystream.Request; import com.arangodb.velocystream.RequestType; -import java.util.HashMap; -import java.util.Map; - /** * @author Mark Vollmary */ @@ -75,15 +71,7 @@ protected Request insertVertexRequest(final T value, final VertexCreateOptio } protected ResponseDeserializer insertVertexResponseDeserializer(final T value) { - return response -> { - final VertexEntity doc = getSerde().deserialize(response.getBody(), "/vertex", VertexEntity.class); - final Map values = new HashMap<>(); - values.put(DocumentFields.ID, doc.getId()); - values.put(DocumentFields.KEY, doc.getKey()); - values.put(DocumentFields.REV, doc.getRev()); - executor.documentCache().setValues(value, values); - return doc; - }; + return response -> getSerde().deserialize(response.getBody(), "/vertex", VertexEntity.class); } protected Request getVertexRequest(final String key, final GraphDocumentReadOptions options) { @@ -115,13 +103,7 @@ protected Request replaceVertexRequest(final String key, final T value, fina } protected ResponseDeserializer replaceVertexResponseDeserializer(final T value) { - return response -> { - final VertexUpdateEntity doc = getSerde().deserialize(response.getBody(), "/vertex", VertexUpdateEntity.class); - final Map values = new HashMap<>(); - values.put(DocumentFields.REV, doc.getRev()); - executor.documentCache().setValues(value, values); - return doc; - }; + return response -> getSerde().deserialize(response.getBody(), "/vertex", VertexUpdateEntity.class); } protected Request updateVertexRequest(final String key, final T value, final VertexUpdateOptions options) { @@ -138,13 +120,7 @@ protected Request updateVertexRequest(final String key, final T value, final } protected ResponseDeserializer updateVertexResponseDeserializer(final T value) { - return response -> { - final VertexUpdateEntity doc = getSerde().deserialize(response.getBody(), "/vertex", VertexUpdateEntity.class); - final Map values = new HashMap<>(); - values.put(DocumentFields.REV, doc.getRev()); - executor.documentCache().setValues(value, values); - return doc; - }; + return response -> getSerde().deserialize(response.getBody(), "/vertex", VertexUpdateEntity.class); } protected Request deleteVertexRequest(final String key, final VertexDeleteOptions options) { diff --git a/src/test/java/com/arangodb/ArangoCollectionTest.java b/src/test/java/com/arangodb/ArangoCollectionTest.java index ad980df47..d404c4329 100644 --- a/src/test/java/com/arangodb/ArangoCollectionTest.java +++ b/src/test/java/com/arangodb/ArangoCollectionTest.java @@ -144,7 +144,8 @@ void insertDocumentWithNullValues(ArangoCollection collection) { void insertDocumentUpdateRev(ArangoCollection collection) { final BaseDocument doc = new BaseDocument(); final DocumentCreateEntity createResult = collection.insertDocument(doc, null); - assertThat(doc.getRevision()).isEqualTo(createResult.getRev()); + assertThat(doc.getRevision()).isNull(); + assertThat(createResult.getRev()).isNotNull(); } @ParameterizedTest(name = "{index}") @@ -430,7 +431,7 @@ void getDocumentWrongKey(ArangoCollection collection) { @ParameterizedTest(name = "{index}") @MethodSource("cols") void getDocumentDirtyRead(ArangoCollection collection) throws InterruptedException { - final BaseDocument doc = new BaseDocument(); + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); collection.insertDocument(doc, new DocumentCreateOptions()); Thread.sleep(2000); final RawJson document = collection.getDocument(doc.getKey(), RawJson.class, new DocumentReadOptions().allowDirtyRead(true)); @@ -555,9 +556,12 @@ void updateDocumentWithDifferentReturnType(ArangoCollection collection) { void updateDocumentUpdateRev(ArangoCollection collection) { final BaseDocument doc = new BaseDocument(); final DocumentCreateEntity createResult = collection.insertDocument(doc, null); - assertThat(doc.getRevision()).isEqualTo(createResult.getRev()); final DocumentUpdateEntity updateResult = collection.updateDocument(createResult.getKey(), doc, null); - assertThat(doc.getRevision()).isEqualTo(updateResult.getRev()); + assertThat(doc.getRevision()).isNull(); + assertThat(createResult.getRev()).isNotNull(); + assertThat(updateResult.getRev()) + .isNotNull() + .isNotEqualTo(createResult.getRev()); } @ParameterizedTest(name = "{index}") @@ -909,9 +913,12 @@ void replaceDocument(ArangoCollection collection) { void replaceDocumentUpdateRev(ArangoCollection collection) { final BaseDocument doc = new BaseDocument(); final DocumentCreateEntity createResult = collection.insertDocument(doc, null); - assertThat(doc.getRevision()).isEqualTo(createResult.getRev()); final DocumentUpdateEntity replaceResult = collection.replaceDocument(createResult.getKey(), doc, null); - assertThat(doc.getRevision()).isEqualTo(replaceResult.getRev()); + assertThat(doc.getRevision()).isNull(); + assertThat(createResult.getRev()).isNotNull(); + assertThat(replaceResult.getRev()) + .isNotNull() + .isNotEqualTo(createResult.getRev()); } @ParameterizedTest(name = "{index}") @@ -1027,11 +1034,10 @@ void replaceDocumentSilentDontTouchInstance(ArangoCollection collection) { assumeTrue(isSingleServer()); final BaseDocument doc = new BaseDocument(); final DocumentCreateEntity createResult = collection.insertDocument(doc); - final String revision = doc.getRevision(); - assertThat(revision).isNotNull(); final DocumentUpdateEntity meta = collection.replaceDocument(createResult.getKey(), doc, new DocumentReplaceOptions().silent(true)); assertThat(meta.getRev()).isNull(); - assertThat(doc.getRevision()).isEqualTo(revision); + assertThat(doc.getRevision()).isNull(); + assertThat(createResult.getRev()).isNotNull(); } @ParameterizedTest(name = "{index}") @@ -1645,7 +1651,7 @@ void exists(ArangoCollection collection) { @ParameterizedTest(name = "{index}") @MethodSource("cols") void truncate(ArangoCollection collection) { - final BaseDocument doc = new BaseDocument(); + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); collection.insertDocument(doc, null); final BaseDocument readResult = collection.getDocument(doc.getKey(), BaseDocument.class, null); assertThat(readResult.getKey()).isEqualTo(doc.getKey()); diff --git a/src/test/java/com/arangodb/ArangoEdgeCollectionTest.java b/src/test/java/com/arangodb/ArangoEdgeCollectionTest.java index 3baaab078..2c6e277ae 100644 --- a/src/test/java/com/arangodb/ArangoEdgeCollectionTest.java +++ b/src/test/java/com/arangodb/ArangoEdgeCollectionTest.java @@ -98,7 +98,8 @@ void insertEdge(ArangoVertexCollection vertices, ArangoEdgeCollection edges) { void insertEdgeUpdateRev(ArangoVertexCollection vertices, ArangoEdgeCollection edges) { final BaseEdgeDocument value = createEdgeValue(vertices); final EdgeEntity edge = edges.insertEdge(value); - assertThat(value.getRevision()).isEqualTo(edge.getRev()); + assertThat(value.getRevision()).isNull(); + assertThat(edge.getRev()).isNotNull(); } @ParameterizedTest(name = "{index}") @@ -206,10 +207,13 @@ void replaceEdge(ArangoVertexCollection vertices, ArangoEdgeCollection edges) { void replaceEdgeUpdateRev(ArangoVertexCollection vertices, ArangoEdgeCollection edges) { final BaseEdgeDocument doc = createEdgeValue(vertices); final EdgeEntity createResult = edges.insertEdge(doc); - assertThat(doc.getRevision()).isEqualTo(createResult.getRev()); final EdgeUpdateEntity replaceResult = edges .replaceEdge(createResult.getKey(), doc); - assertThat(doc.getRevision()).isEqualTo(replaceResult.getRev()); + assertThat(doc.getRevision()).isNull(); + assertThat(createResult.getRev()).isNotNull(); + assertThat(replaceResult.getRev()) + .isNotNull() + .isNotEqualTo(createResult.getRev()); } @ParameterizedTest(name = "{index}") @@ -287,10 +291,13 @@ void updateEdge(ArangoVertexCollection vertices, ArangoEdgeCollection edges) { void updateEdgeUpdateRev(ArangoVertexCollection vertices, ArangoEdgeCollection edges) { final BaseEdgeDocument doc = createEdgeValue(vertices); final EdgeEntity createResult = edges.insertEdge(doc); - assertThat(doc.getRevision()).isEqualTo(createResult.getRev()); final EdgeUpdateEntity updateResult = edges .updateEdge(createResult.getKey(), doc); - assertThat(doc.getRevision()).isEqualTo(updateResult.getRev()); + assertThat(doc.getRevision()).isNull(); + assertThat(createResult.getRev()).isNotNull(); + assertThat(updateResult.getRev()) + .isNotNull() + .isNotEqualTo(createResult.getRev()); } @ParameterizedTest(name = "{index}") diff --git a/src/test/java/com/arangodb/ArangoRouteTest.java b/src/test/java/com/arangodb/ArangoRouteTest.java index 613b8e3b8..3334d9461 100644 --- a/src/test/java/com/arangodb/ArangoRouteTest.java +++ b/src/test/java/com/arangodb/ArangoRouteTest.java @@ -27,6 +27,8 @@ import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.MethodSource; +import java.util.UUID; + import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.catchThrowable; @@ -53,10 +55,10 @@ void get(ArangoDatabase db) { @ParameterizedTest(name = "{index}") @MethodSource("dbs") void withHeader(ArangoDatabase db) { - final BaseDocument doc = new BaseDocument(); - db.collection(COLLECTION_NAME).insertDocument(doc); + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); + String rev = db.collection(COLLECTION_NAME).insertDocument(doc).getRev(); Throwable thrown = catchThrowable(() -> - db.route("/_api/document", doc.getId()).withHeader(ArangoRequestParam.IF_NONE_MATCH, doc.getRevision()).get()); + db.route("/_api/document", COLLECTION_NAME, doc.getKey()).withHeader(ArangoRequestParam.IF_NONE_MATCH, rev).get()); assertThat(thrown).isInstanceOf(ArangoDBException.class); ArangoDBException e = (ArangoDBException) thrown; assertThat(e.getResponseCode()).isEqualTo(304); @@ -65,10 +67,10 @@ void withHeader(ArangoDatabase db) { @ParameterizedTest(name = "{index}") @MethodSource("dbs") void withParentHeader(ArangoDatabase db) { - final BaseDocument doc = new BaseDocument(); - db.collection(COLLECTION_NAME).insertDocument(doc); + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); + String rev = db.collection(COLLECTION_NAME).insertDocument(doc).getRev(); Throwable thrown = catchThrowable(() -> - db.route("/_api/document").withHeader(ArangoRequestParam.IF_NONE_MATCH, doc.getRevision()).route(doc.getId()).get()); + db.route("/_api/document").withHeader(ArangoRequestParam.IF_NONE_MATCH, rev).route(COLLECTION_NAME, doc.getKey()).get()); assertThat(thrown).isInstanceOf(ArangoDBException.class); ArangoDBException e = (ArangoDBException) thrown; assertThat(e.getResponseCode()).isEqualTo(304); diff --git a/src/test/java/com/arangodb/ArangoVertexCollectionTest.java b/src/test/java/com/arangodb/ArangoVertexCollectionTest.java index ed202b7dc..a0e79031f 100644 --- a/src/test/java/com/arangodb/ArangoVertexCollectionTest.java +++ b/src/test/java/com/arangodb/ArangoVertexCollectionTest.java @@ -137,7 +137,8 @@ void duplicateInsertSameObjectVertex(ArangoVertexCollection vertices) { void insertVertexUpdateRev(ArangoVertexCollection vertices) { final BaseDocument doc = new BaseDocument(); final VertexEntity vertex = vertices.insertVertex(doc, null); - assertThat(doc.getRevision()).isEqualTo(vertex.getRev()); + assertThat(doc.getRevision()).isNull(); + assertThat(vertex.getRev()).isNotNull(); } @ParameterizedTest(name = "{index}") @@ -228,10 +229,13 @@ void replaceVertexUpdateRev(ArangoVertexCollection vertices) { final BaseDocument doc = new BaseDocument(); final VertexEntity createResult = vertices .insertVertex(doc, null); - assertThat(doc.getRevision()).isEqualTo(createResult.getRev()); final VertexUpdateEntity replaceResult = vertices .replaceVertex(createResult.getKey(), doc, null); - assertThat(doc.getRevision()).isEqualTo(replaceResult.getRev()); + assertThat(doc.getRevision()).isNull(); + assertThat(createResult.getRev()).isNotNull(); + assertThat(replaceResult.getRev()) + .isNotNull() + .isNotEqualTo(createResult.getRev()); } @ParameterizedTest(name = "{index}") @@ -313,10 +317,13 @@ void updateVertexUpdateRev(ArangoVertexCollection vertices) { final BaseDocument doc = new BaseDocument(); final VertexEntity createResult = vertices .insertVertex(doc, null); - assertThat(doc.getRevision()).isEqualTo(createResult.getRev()); final VertexUpdateEntity updateResult = vertices .updateVertex(createResult.getKey(), doc, null); - assertThat(doc.getRevision()).isEqualTo(updateResult.getRev()); + assertThat(doc.getRevision()).isNull(); + assertThat(createResult.getRev()).isNotNull(); + assertThat(updateResult.getRev()) + .isNotNull() + .isNotEqualTo(createResult.getRev()); } @ParameterizedTest(name = "{index}") diff --git a/src/test/java/com/arangodb/async/ArangoCollectionTest.java b/src/test/java/com/arangodb/async/ArangoCollectionTest.java index 015a7a170..5265ad47f 100644 --- a/src/test/java/com/arangodb/async/ArangoCollectionTest.java +++ b/src/test/java/com/arangodb/async/ArangoCollectionTest.java @@ -1226,7 +1226,7 @@ void exists() throws InterruptedException, ExecutionException { @Test void truncate() throws InterruptedException, ExecutionException { - final BaseDocument doc = new BaseDocument(); + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); db.collection(COLLECTION_NAME).insertDocument(doc, null).get(); final BaseDocument readResult = db.collection(COLLECTION_NAME) .getDocument(doc.getKey(), BaseDocument.class, null).get(); diff --git a/src/test/java/com/arangodb/internal/DocumentCacheTest.java b/src/test/java/com/arangodb/internal/DocumentCacheTest.java deleted file mode 100644 index 474cd6882..000000000 --- a/src/test/java/com/arangodb/internal/DocumentCacheTest.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.internal; - -import com.arangodb.entity.BaseDocument; -import org.junit.jupiter.api.Test; - -import java.util.HashMap; -import java.util.Map; - -import static org.assertj.core.api.Assertions.assertThat; - - -/** - * @author Mark Vollmary - */ -class DocumentCacheTest { - - @Test - void setValues() { - final DocumentCache cache = new DocumentCache(); - final BaseDocument doc = new BaseDocument(); - - assertThat(doc.getId()).isNull(); - assertThat(doc.getKey()).isNull(); - assertThat(doc.getRevision()).isNull(); - - final Map values = new HashMap<>(); - values.put(DocumentFields.ID, "testId"); - values.put(DocumentFields.KEY, "testKey"); - values.put(DocumentFields.REV, "testRev"); - cache.setValues(doc, values); - - assertThat(doc.getId()).isEqualTo("testId"); - assertThat(doc.getKey()).isEqualTo("testKey"); - assertThat(doc.getRevision()).isEqualTo("testRev"); - } - - @Test - void setValuesMap() { - final DocumentCache cache = new DocumentCache(); - final Map map = new HashMap<>(); - - final Map values = new HashMap<>(); - values.put(DocumentFields.ID, "testId"); - values.put(DocumentFields.KEY, "testKey"); - values.put(DocumentFields.REV, "testRev"); - cache.setValues(map, values); - - assertThat(map.isEmpty()).isTrue(); - } -} diff --git a/src/test/java/com/arangodb/serde/CustomSerdeTest.java b/src/test/java/com/arangodb/serde/CustomSerdeTest.java index 5fae2ba2f..04bf68b74 100644 --- a/src/test/java/com/arangodb/serde/CustomSerdeTest.java +++ b/src/test/java/com/arangodb/serde/CustomSerdeTest.java @@ -21,10 +21,7 @@ package com.arangodb.serde; -import com.arangodb.ArangoCollection; -import com.arangodb.ArangoDB; -import com.arangodb.ArangoDatabase; -import com.arangodb.DbName; +import com.arangodb.*; import com.arangodb.model.DocumentCreateOptions; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.core.JsonParser; @@ -98,7 +95,9 @@ static void init() { module.addDeserializer(Person.class, new PersonDeserializer()); mapper.registerModule(module); }); - arangoDB = new ArangoDB.Builder().serializer(serde).build(); + arangoDB = new ArangoDB.Builder() + .useProtocol(Protocol.VST) + .serializer(serde).build(); db = arangoDB.db(DbName.of("custom-serde-test")); if (!db.exists()) { From cb327d453ee7a35e72d4f2d94a4a95372fb4fc59 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Tue, 2 Aug 2022 09:37:55 +0200 Subject: [PATCH 067/254] fixed maven variables clash --- .github/workflows/maven.yml | 2 +- .gitignore | 1 + pom.xml | 4 ++-- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index 2d81eb74a..c667a2e16 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -172,4 +172,4 @@ jobs: - name: Info run: mvn -version - name: Test - run: mvn --no-transfer-progress test -Djackson.version=${{matrix.jackson-version}} + run: mvn --no-transfer-progress test -Dadb.jackson.version=${{matrix.jackson-version}} diff --git a/.gitignore b/.gitignore index 04451cf5c..bdc7bc636 100644 --- a/.gitignore +++ b/.gitignore @@ -11,3 +11,4 @@ /docker/data /test-results-native/ +.flattened-pom.xml diff --git a/pom.xml b/pom.xml index 88778cd5f..92b2b5e1d 100644 --- a/pom.xml +++ b/pom.xml @@ -23,7 +23,7 @@ UTF-8 - 2.13.3 + 2.13.3 @@ -344,7 +344,7 @@ com.fasterxml.jackson jackson-bom - ${jackson.version} + ${adb.jackson.version} import pom From 2d543ea4ee1d93e1e77a56819e27720bde156c73 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Tue, 2 Aug 2022 11:21:50 +0200 Subject: [PATCH 068/254] [DE-296] refactor BaseDocument --- .../com/arangodb/entity/BaseDocument.java | 149 +++++++----------- .../com/arangodb/entity/BaseEdgeDocument.java | 88 +++-------- .../com/arangodb/ArangoCollectionTest.java | 94 +++++------ .../java/com/arangodb/ArangoDatabaseTest.java | 6 +- .../arangodb/ArangoEdgeCollectionTest.java | 8 +- .../arangodb/ArangoVertexCollectionTest.java | 40 ++--- src/test/java/com/arangodb/DocumentTest.java | 6 +- .../arangodb/StreamTransactionGraphTest.java | 17 +- .../com/arangodb/StreamTransactionTest.java | 16 +- .../arangodb/async/ArangoCollectionTest.java | 76 ++++----- .../arangodb/async/ArangoDatabaseTest.java | 4 +- .../async/ArangoEdgeCollectionTest.java | 8 +- .../com/arangodb/async/ArangoRouteTest.java | 5 +- .../async/ArangoVertexCollectionTest.java | 31 ++-- .../async/StreamTransactionGraphTest.java | 17 +- ...ueryWithSpecialReturnTypesExampleTest.java | 3 +- .../document/GetDocumentExampleTest.java | 3 +- .../document/InsertDocumentExampleTest.java | 3 +- .../graph/AQLActorsAndMoviesExampleTest.java | 5 +- .../com/arangodb/example/FirstProject.java | 5 +- ...ueryWithSpecialReturnTypesExampleTest.java | 3 +- .../document/GetDocumentExampleTest.java | 3 +- .../document/InsertDocumentExampleTest.java | 4 +- .../graph/AQLActorsAndMoviesExampleTest.java | 6 +- src/test/resources/logback-test.xml | 2 +- 25 files changed, 264 insertions(+), 338 deletions(-) diff --git a/src/main/java/com/arangodb/entity/BaseDocument.java b/src/main/java/com/arangodb/entity/BaseDocument.java index 1946afda1..d4be3df7c 100644 --- a/src/main/java/com/arangodb/entity/BaseDocument.java +++ b/src/main/java/com/arangodb/entity/BaseDocument.java @@ -20,167 +20,130 @@ package com.arangodb.entity; -import com.arangodb.internal.DocumentFields; import com.fasterxml.jackson.annotation.JsonAnyGetter; import com.fasterxml.jackson.annotation.JsonAnySetter; +import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonInclude; -import java.io.Serializable; +import java.util.Collections; import java.util.HashMap; import java.util.Map; +import java.util.Objects; /** * @author Mark Vollmary */ -public class BaseDocument implements Serializable { +public class BaseDocument { - private static final long serialVersionUID = -1824742667228719116L; - - @Id - protected String id; - @Key - protected String key; - @Rev - protected String revision; - protected Map properties; + private static final String[] META_PROPS = new String[]{"_id", "_key", "_rev"}; + private final Map properties; public BaseDocument() { - super(); properties = new HashMap<>(); } public BaseDocument(final String key) { this(); - this.key = key; + setKey(key); } public BaseDocument(final Map properties) { this(); - final Object tmpId = properties.remove(DocumentFields.ID); - if (tmpId != null) { - id = tmpId.toString(); - } - final Object tmpKey = properties.remove(DocumentFields.KEY); - if (tmpKey != null) { - key = tmpKey.toString(); - } - final Object tmpRev = properties.remove(DocumentFields.REV); - if (tmpRev != null) { - revision = tmpRev.toString(); - } - this.properties = properties; + setProperties(properties); } + @JsonIgnore public String getId() { - return id; + return (String) getAttribute("_id"); } public void setId(final String id) { - this.id = id; + addAttribute("_id", id); } + @JsonIgnore public String getKey() { - return key; + return (String) getAttribute("_key"); } public void setKey(final String key) { - this.key = key; + addAttribute("_key", key); } + @JsonIgnore public String getRevision() { - return revision; + return (String) getAttribute("_rev"); } - public void setRevision(final String revision) { - this.revision = revision; + public void setRevision(final String rev) { + addAttribute("_rev", rev); } @JsonInclude @JsonAnyGetter public Map getProperties() { - return properties; + return Collections.unmodifiableMap(properties); } - public void setProperties(final Map properties) { - this.properties = properties; + public void setProperties(final Map props) { + for (String f : getMetaProps()) { + requireString(f, props.get(f)); + } + this.properties.putAll(props); + } + + public Object getAttribute(final String key) { + return properties.get(key); } @JsonInclude @JsonAnySetter public void addAttribute(final String key, final Object value) { + for (String f : getMetaProps()) { + if (f.equals(key)) { + requireString(key, value); + } + } properties.put(key, value); } public void updateAttribute(final String key, final Object value) { if (properties.containsKey(key)) { - properties.put(key, value); + addAttribute(key, value); } } - public Object getAttribute(final String key) { - return properties.get(key); + public void removeAttribute(final String key) { + properties.remove(key); + } + + protected String[] getMetaProps() { + return META_PROPS; + } + + private void requireString(final String k, final Object v) { + if (v != null && !(v instanceof String)) { + throw new IllegalArgumentException(k + " must be a String"); + } } @Override public String toString() { - return "BaseDocument [documentRevision=" + - revision + - ", documentHandle=" + - id + - ", documentKey=" + - key + - ", properties=" + - properties + - "]"; + return "BaseDocument{" + + "properties=" + properties + + '}'; } @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((id == null) ? 0 : id.hashCode()); - result = prime * result + ((key == null) ? 0 : key.hashCode()); - result = prime * result + ((properties == null) ? 0 : properties.hashCode()); - result = prime * result + ((revision == null) ? 0 : revision.hashCode()); - return result; + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + BaseDocument that = (BaseDocument) o; + return properties.equals(that.properties); } @Override - public boolean equals(final Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (getClass() != obj.getClass()) { - return false; - } - final BaseDocument other = (BaseDocument) obj; - if (id == null) { - if (other.id != null) { - return false; - } - } else if (!id.equals(other.id)) { - return false; - } - if (key == null) { - if (other.key != null) { - return false; - } - } else if (!key.equals(other.key)) { - return false; - } - if (properties == null) { - if (other.properties != null) { - return false; - } - } else if (!properties.equals(other.properties)) { - return false; - } - if (revision == null) { - return other.revision == null; - } else return revision.equals(other.revision); + public int hashCode() { + return Objects.hash(properties); } - } diff --git a/src/main/java/com/arangodb/entity/BaseEdgeDocument.java b/src/main/java/com/arangodb/entity/BaseEdgeDocument.java index 9a82420da..21dad292c 100644 --- a/src/main/java/com/arangodb/entity/BaseEdgeDocument.java +++ b/src/main/java/com/arangodb/entity/BaseEdgeDocument.java @@ -20,7 +20,7 @@ package com.arangodb.entity; -import com.arangodb.internal.DocumentFields; +import com.fasterxml.jackson.annotation.JsonIgnore; import java.util.Map; @@ -29,12 +29,7 @@ */ public final class BaseEdgeDocument extends BaseDocument { - private static final long serialVersionUID = 6904923804449368783L; - - @From - private String from; - @To - private String to; + private static final String[] META_PROPS = new String[]{"_id", "_key", "_rev", "_from", "_to"}; public BaseEdgeDocument() { super(); @@ -42,92 +37,57 @@ public BaseEdgeDocument() { public BaseEdgeDocument(final String from, final String to) { super(); - this.from = from; - this.to = to; + setFrom(from); + setTo(to); } public BaseEdgeDocument(final String key, final String from, final String to) { super(key); - this.from = from; - this.to = to; + setFrom(from); + setTo(to); } public BaseEdgeDocument(final Map properties) { super(properties); - final Object tmpFrom = properties.remove(DocumentFields.FROM); - if (tmpFrom != null) { - from = tmpFrom.toString(); - } - final Object tmpTo = properties.remove(DocumentFields.TO); - if (tmpTo != null) { - to = tmpTo.toString(); - } } + @JsonIgnore public String getFrom() { - return from; + return (String) getAttribute("_from"); } public void setFrom(final String from) { - this.from = from; + addAttribute("_from", from); } + @JsonIgnore public String getTo() { - return to; + return (String) getAttribute("_to"); } public void setTo(final String to) { - this.to = to; + addAttribute("_to", to); } @Override - public String toString() { - return "BaseDocument [documentRevision=" + - revision + - ", documentHandle=" + - id + - ", documentKey=" + - key + - ", from=" + - from + - ", to=" + - to + - ", properties=" + - properties + - "]"; + protected String[] getMetaProps() { + return META_PROPS; } @Override - public int hashCode() { - final int prime = 31; - int result = super.hashCode(); - result = prime * result + ((from == null) ? 0 : from.hashCode()); - result = prime * result + ((to == null) ? 0 : to.hashCode()); - return result; + public String toString() { + return "BaseEdgeDocument{properties=" + getProperties() + '}'; } @Override - public boolean equals(final Object obj) { - if (this == obj) { - return true; - } - if (!super.equals(obj)) { - return false; - } - if (getClass() != obj.getClass()) { - return false; - } - final BaseEdgeDocument other = (BaseEdgeDocument) obj; - if (from == null) { - if (other.from != null) { - return false; - } - } else if (!from.equals(other.from)) { - return false; - } - if (to == null) { - return other.to == null; - } else return to.equals(other.to); + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + return super.equals(o); } + @Override + public int hashCode() { + return super.hashCode(); + } } diff --git a/src/test/java/com/arangodb/ArangoCollectionTest.java b/src/test/java/com/arangodb/ArangoCollectionTest.java index d404c4329..5bb82657d 100644 --- a/src/test/java/com/arangodb/ArangoCollectionTest.java +++ b/src/test/java/com/arangodb/ArangoCollectionTest.java @@ -109,7 +109,7 @@ void insertDocument(ArangoCollection collection) { @SuppressWarnings("unchecked") void insertDocumentWithArrayWithNullValues(ArangoCollection collection) { List arr = Arrays.asList("a", null); - BaseDocument doc = new BaseDocument(); + BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); doc.addAttribute("arr", arr); final DocumentCreateEntity insertedDoc = collection.insertDocument(doc, new DocumentCreateOptions().returnNew(true)); @@ -127,7 +127,7 @@ void insertDocumentWithArrayWithNullValues(ArangoCollection collection) { @MethodSource("cols") @Disabled void insertDocumentWithNullValues(ArangoCollection collection) { - BaseDocument doc = new BaseDocument(); + BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); doc.addAttribute("null", null); final DocumentCreateEntity insertedDoc = collection.insertDocument(doc, new DocumentCreateOptions().returnNew(true)); @@ -142,7 +142,7 @@ void insertDocumentWithNullValues(ArangoCollection collection) { @ParameterizedTest(name = "{index}") @MethodSource("cols") void insertDocumentUpdateRev(ArangoCollection collection) { - final BaseDocument doc = new BaseDocument(); + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); final DocumentCreateEntity createResult = collection.insertDocument(doc, null); assertThat(doc.getRevision()).isNull(); assertThat(createResult.getRev()).isNotNull(); @@ -221,7 +221,7 @@ void insertDocumentOverwriteModeReplace(ArangoCollection collection) { void insertDocumentOverwriteModeUpdate(ArangoCollection collection) { assumeTrue(isAtLeastVersion(3, 7)); - final BaseDocument doc = new BaseDocument(); + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); doc.addAttribute("foo", "a"); final DocumentCreateEntity meta = collection.insertDocument(doc); @@ -239,7 +239,7 @@ void insertDocumentOverwriteModeUpdate(ArangoCollection collection) { void insertDocumentOverwriteModeUpdateMergeObjectsFalse(ArangoCollection collection) { assumeTrue(isAtLeastVersion(3, 7)); - final BaseDocument doc = new BaseDocument(); + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); Map fieldA = Collections.singletonMap("a", "a"); doc.addAttribute("foo", fieldA); final DocumentCreateEntity meta = collection.insertDocument(doc); @@ -311,7 +311,7 @@ void insertDocumentSilent(ArangoCollection collection) { @MethodSource("cols") void insertDocumentSilentDontTouchInstance(ArangoCollection collection) { assumeTrue(isSingleServer()); - final BaseDocument doc = new BaseDocument(); + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); final String key = "testkey-" + UUID.randomUUID(); doc.setKey(key); final DocumentCreateEntity meta = collection.insertDocument(doc, new DocumentCreateOptions().silent(true)); @@ -509,7 +509,7 @@ void getDocumentsWrongKey(ArangoCollection collection) { @ParameterizedTest(name = "{index}") @MethodSource("cols") void updateDocument(ArangoCollection collection) { - final BaseDocument doc = new BaseDocument(); + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); doc.addAttribute("a", "test"); doc.addAttribute("c", "test"); final DocumentCreateEntity createResult = collection.insertDocument(doc, null); @@ -554,7 +554,7 @@ void updateDocumentWithDifferentReturnType(ArangoCollection collection) { @ParameterizedTest(name = "{index}") @MethodSource("cols") void updateDocumentUpdateRev(ArangoCollection collection) { - final BaseDocument doc = new BaseDocument(); + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); final DocumentCreateEntity createResult = collection.insertDocument(doc, null); final DocumentUpdateEntity updateResult = collection.updateDocument(createResult.getKey(), doc, null); assertThat(doc.getRevision()).isNull(); @@ -567,7 +567,7 @@ void updateDocumentUpdateRev(ArangoCollection collection) { @ParameterizedTest(name = "{index}") @MethodSource("cols") void updateDocumentIfMatch(ArangoCollection collection) { - final BaseDocument doc = new BaseDocument(); + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); doc.addAttribute("a", "test"); doc.addAttribute("c", "test"); final DocumentCreateEntity createResult = collection.insertDocument(doc, null); @@ -594,7 +594,7 @@ void updateDocumentIfMatch(ArangoCollection collection) { @ParameterizedTest(name = "{index}") @MethodSource("cols") void updateDocumentIfMatchFail(ArangoCollection collection) { - final BaseDocument doc = new BaseDocument(); + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); doc.addAttribute("a", "test"); doc.addAttribute("c", "test"); final DocumentCreateEntity createResult = collection.insertDocument(doc, null); @@ -610,7 +610,7 @@ void updateDocumentIfMatchFail(ArangoCollection collection) { @ParameterizedTest(name = "{index}") @MethodSource("cols") void updateDocumentReturnNew(ArangoCollection collection) { - final BaseDocument doc = new BaseDocument(); + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); doc.addAttribute("a", "test"); final DocumentCreateEntity createResult = collection.insertDocument(doc, null); doc.updateAttribute("a", "test1"); @@ -632,7 +632,7 @@ void updateDocumentReturnNew(ArangoCollection collection) { @ParameterizedTest(name = "{index}") @MethodSource("cols") void updateDocumentReturnOld(ArangoCollection collection) { - final BaseDocument doc = new BaseDocument(); + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); doc.addAttribute("a", "test"); final DocumentCreateEntity createResult = collection.insertDocument(doc, null); doc.updateAttribute("a", "test1"); @@ -653,7 +653,7 @@ void updateDocumentReturnOld(ArangoCollection collection) { @ParameterizedTest(name = "{index}") @MethodSource("cols") void updateDocumentKeepNullTrue(ArangoCollection collection) { - final BaseDocument doc = new BaseDocument(); + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); doc.addAttribute("a", "test"); final DocumentCreateEntity createResult = collection.insertDocument(doc, null); doc.updateAttribute("a", null); @@ -672,7 +672,7 @@ void updateDocumentKeepNullTrue(ArangoCollection collection) { @ParameterizedTest(name = "{index}") @MethodSource("cols") void updateDocumentKeepNullFalse(ArangoCollection collection) { - final BaseDocument doc = new BaseDocument(); + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); doc.addAttribute("a", "test"); final DocumentCreateEntity createResult = collection.insertDocument(doc, null); doc.updateAttribute("a", null); @@ -761,7 +761,7 @@ void updateDocumentSerializeNullFalse(ArangoCollection collection) { @ParameterizedTest(name = "{index}") @MethodSource("cols") void updateDocumentMergeObjectsTrue(ArangoCollection collection) { - final BaseDocument doc = new BaseDocument(); + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); final Map a = new HashMap<>(); a.put("a", "test"); doc.addAttribute("a", a); @@ -788,7 +788,7 @@ void updateDocumentMergeObjectsTrue(ArangoCollection collection) { @ParameterizedTest(name = "{index}") @MethodSource("cols") void updateDocumentMergeObjectsFalse(ArangoCollection collection) { - final BaseDocument doc = new BaseDocument(); + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); final Map a = new HashMap<>(); a.put("a", "test"); doc.addAttribute("a", a); @@ -815,7 +815,7 @@ void updateDocumentMergeObjectsFalse(ArangoCollection collection) { @ParameterizedTest(name = "{index}") @MethodSource("cols") void updateDocumentIgnoreRevsFalse(ArangoCollection collection) { - final BaseDocument doc = new BaseDocument(); + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); doc.addAttribute("a", "test"); final DocumentCreateEntity createResult = collection.insertDocument(doc, null); doc.updateAttribute("a", "test1"); @@ -887,10 +887,10 @@ void updateDocumentPreconditionFailed(ArangoCollection collection) { @ParameterizedTest(name = "{index}") @MethodSource("cols") void replaceDocument(ArangoCollection collection) { - final BaseDocument doc = new BaseDocument(); + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); doc.addAttribute("a", "test"); final DocumentCreateEntity createResult = collection.insertDocument(doc, null); - doc.getProperties().clear(); + doc.removeAttribute("a"); doc.addAttribute("b", "test"); final DocumentUpdateEntity replaceResult = collection.replaceDocument(createResult.getKey(), doc, null); assertThat(replaceResult).isNotNull(); @@ -911,7 +911,7 @@ void replaceDocument(ArangoCollection collection) { @ParameterizedTest(name = "{index}") @MethodSource("cols") void replaceDocumentUpdateRev(ArangoCollection collection) { - final BaseDocument doc = new BaseDocument(); + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); final DocumentCreateEntity createResult = collection.insertDocument(doc, null); final DocumentUpdateEntity replaceResult = collection.replaceDocument(createResult.getKey(), doc, null); assertThat(doc.getRevision()).isNull(); @@ -924,10 +924,10 @@ void replaceDocumentUpdateRev(ArangoCollection collection) { @ParameterizedTest(name = "{index}") @MethodSource("cols") void replaceDocumentIfMatch(ArangoCollection collection) { - final BaseDocument doc = new BaseDocument(); + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); doc.addAttribute("a", "test"); final DocumentCreateEntity createResult = collection.insertDocument(doc, null); - doc.getProperties().clear(); + doc.removeAttribute("a"); doc.addAttribute("b", "test"); final DocumentReplaceOptions options = new DocumentReplaceOptions().ifMatch(createResult.getRev()); final DocumentUpdateEntity replaceResult = collection.replaceDocument(createResult.getKey(), doc, options); @@ -947,10 +947,10 @@ void replaceDocumentIfMatch(ArangoCollection collection) { @ParameterizedTest(name = "{index}") @MethodSource("cols") void replaceDocumentIfMatchFail(ArangoCollection collection) { - final BaseDocument doc = new BaseDocument(); + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); doc.addAttribute("a", "test"); final DocumentCreateEntity createResult = collection.insertDocument(doc, null); - doc.getProperties().clear(); + doc.removeAttribute("a"); doc.addAttribute("b", "test"); final DocumentReplaceOptions options = new DocumentReplaceOptions().ifMatch("no"); @@ -962,10 +962,10 @@ void replaceDocumentIfMatchFail(ArangoCollection collection) { @ParameterizedTest(name = "{index}") @MethodSource("cols") void replaceDocumentIgnoreRevsFalse(ArangoCollection collection) { - final BaseDocument doc = new BaseDocument(); + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); doc.addAttribute("a", "test"); final DocumentCreateEntity createResult = collection.insertDocument(doc, null); - doc.getProperties().clear(); + doc.removeAttribute("a"); doc.addAttribute("b", "test"); doc.setRevision("no"); @@ -977,10 +977,10 @@ void replaceDocumentIgnoreRevsFalse(ArangoCollection collection) { @ParameterizedTest(name = "{index}") @MethodSource("cols") void replaceDocumentReturnNew(ArangoCollection collection) { - final BaseDocument doc = new BaseDocument(); + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); doc.addAttribute("a", "test"); final DocumentCreateEntity createResult = collection.insertDocument(doc, null); - doc.getProperties().clear(); + doc.removeAttribute("a"); doc.addAttribute("b", "test"); final DocumentReplaceOptions options = new DocumentReplaceOptions().returnNew(true); final DocumentUpdateEntity replaceResult = collection.replaceDocument(createResult.getKey(), doc, options); @@ -998,10 +998,10 @@ void replaceDocumentReturnNew(ArangoCollection collection) { @ParameterizedTest(name = "{index}") @MethodSource("cols") void replaceDocumentReturnOld(ArangoCollection collection) { - final BaseDocument doc = new BaseDocument(); + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); doc.addAttribute("a", "test"); final DocumentCreateEntity createResult = collection.insertDocument(doc, null); - doc.getProperties().clear(); + doc.removeAttribute("a"); doc.addAttribute("b", "test"); final DocumentReplaceOptions options = new DocumentReplaceOptions().returnOld(true); final DocumentUpdateEntity replaceResult = collection.replaceDocument(createResult.getKey(), doc, options); @@ -1032,7 +1032,7 @@ void replaceDocumentSilent(ArangoCollection collection) { @MethodSource("cols") void replaceDocumentSilentDontTouchInstance(ArangoCollection collection) { assumeTrue(isSingleServer()); - final BaseDocument doc = new BaseDocument(); + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); final DocumentCreateEntity createResult = collection.insertDocument(doc); final DocumentUpdateEntity meta = collection.replaceDocument(createResult.getKey(), doc, new DocumentReplaceOptions().silent(true)); assertThat(meta.getRev()).isNull(); @@ -1055,7 +1055,7 @@ void replaceDocumentsSilent(ArangoCollection collection) { @ParameterizedTest(name = "{index}") @MethodSource("cols") void deleteDocument(ArangoCollection collection) { - final BaseDocument doc = new BaseDocument(); + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); final DocumentCreateEntity createResult = collection.insertDocument(doc, null); collection.deleteDocument(createResult.getKey(), null, null); final BaseDocument document = collection.getDocument(createResult.getKey(), BaseDocument.class, null); @@ -1065,7 +1065,7 @@ void deleteDocument(ArangoCollection collection) { @ParameterizedTest(name = "{index}") @MethodSource("cols") void deleteDocumentReturnOld(ArangoCollection collection) { - final BaseDocument doc = new BaseDocument(); + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); doc.addAttribute("a", "test"); final DocumentCreateEntity createResult = collection.insertDocument(doc, null); final DocumentDeleteOptions options = new DocumentDeleteOptions().returnOld(true); @@ -1079,7 +1079,7 @@ void deleteDocumentReturnOld(ArangoCollection collection) { @ParameterizedTest(name = "{index}") @MethodSource("cols") void deleteDocumentIfMatch(ArangoCollection collection) { - final BaseDocument doc = new BaseDocument(); + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); final DocumentCreateEntity createResult = collection.insertDocument(doc, null); final DocumentDeleteOptions options = new DocumentDeleteOptions().ifMatch(createResult.getRev()); collection.deleteDocument(createResult.getKey(), null, options); @@ -1090,7 +1090,7 @@ void deleteDocumentIfMatch(ArangoCollection collection) { @ParameterizedTest(name = "{index}") @MethodSource("cols") void deleteDocumentIfMatchFail(ArangoCollection collection) { - final BaseDocument doc = new BaseDocument(); + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); final DocumentCreateEntity createResult = collection.insertDocument(doc, null); final DocumentDeleteOptions options = new DocumentDeleteOptions().ifMatch("no"); Throwable thrown = catchThrowable(() -> collection.deleteDocument(createResult.getKey(), null, options)); @@ -1753,11 +1753,11 @@ void insertDocuments(ArangoCollection collection) { void insertDocumentsOverwriteModeUpdate(ArangoCollection collection) { assumeTrue(isAtLeastVersion(3, 7)); - final BaseDocument doc1 = new BaseDocument(); + final BaseDocument doc1 = new BaseDocument(UUID.randomUUID().toString()); doc1.addAttribute("foo", "a"); final DocumentCreateEntity meta1 = collection.insertDocument(doc1); - final BaseDocument doc2 = new BaseDocument(); + final BaseDocument doc2 = new BaseDocument(UUID.randomUUID().toString()); doc2.addAttribute("foo", "a"); final DocumentCreateEntity meta2 = collection.insertDocument(doc2); @@ -2237,12 +2237,12 @@ void importDocumentsJsonFromToPrefix(ArangoCollection edgeCollection) throws Jso void deleteDocumentsByKey(ArangoCollection collection) { final Collection values = new ArrayList<>(); { - final BaseDocument e = new BaseDocument(); + final BaseDocument e = new BaseDocument(UUID.randomUUID().toString()); e.setKey("1"); values.add(e); } { - final BaseDocument e = new BaseDocument(); + final BaseDocument e = new BaseDocument(UUID.randomUUID().toString()); e.setKey("2"); values.add(e); } @@ -2264,12 +2264,12 @@ void deleteDocumentsByKey(ArangoCollection collection) { void deleteDocumentsByDocuments(ArangoCollection collection) { final Collection values = new ArrayList<>(); { - final BaseDocument e = new BaseDocument(); + final BaseDocument e = new BaseDocument(UUID.randomUUID().toString()); e.setKey("1"); values.add(e); } { - final BaseDocument e = new BaseDocument(); + final BaseDocument e = new BaseDocument(UUID.randomUUID().toString()); e.setKey("2"); values.add(e); } @@ -2288,7 +2288,7 @@ void deleteDocumentsByDocuments(ArangoCollection collection) { void deleteDocumentsByKeyOne(ArangoCollection collection) { final Collection values = new ArrayList<>(); { - final BaseDocument e = new BaseDocument(); + final BaseDocument e = new BaseDocument(UUID.randomUUID().toString()); e.setKey("1"); values.add(e); } @@ -2309,7 +2309,7 @@ void deleteDocumentsByKeyOne(ArangoCollection collection) { void deleteDocumentsByDocumentOne(ArangoCollection collection) { final Collection values = new ArrayList<>(); { - final BaseDocument e = new BaseDocument(); + final BaseDocument e = new BaseDocument(UUID.randomUUID().toString()); e.setKey("1"); values.add(e); } @@ -2353,12 +2353,12 @@ void deleteDocumentsByKeyNotExisting(ArangoCollection collection) { void deleteDocumentsByDocumentsNotExisting(ArangoCollection collection) { final Collection values = new ArrayList<>(); { - final BaseDocument e = new BaseDocument(); + final BaseDocument e = new BaseDocument(UUID.randomUUID().toString()); e.setKey("1"); values.add(e); } { - final BaseDocument e = new BaseDocument(); + final BaseDocument e = new BaseDocument(UUID.randomUUID().toString()); e.setKey("2"); values.add(e); } @@ -2407,7 +2407,7 @@ void updateDocumentsWithDifferentReturnType(ArangoCollection collection) { void updateDocumentsOne(ArangoCollection collection) { final Collection values = new ArrayList<>(); { - final BaseDocument e = new BaseDocument(); + final BaseDocument e = new BaseDocument(UUID.randomUUID().toString()); e.setKey("1"); values.add(e); } @@ -2489,7 +2489,7 @@ void replaceDocuments(ArangoCollection collection) { void replaceDocumentsOne(ArangoCollection collection) { final Collection values = new ArrayList<>(); { - final BaseDocument e = new BaseDocument(); + final BaseDocument e = new BaseDocument(UUID.randomUUID().toString()); e.setKey("1"); values.add(e); } diff --git a/src/test/java/com/arangodb/ArangoDatabaseTest.java b/src/test/java/com/arangodb/ArangoDatabaseTest.java index a63eefd24..60986b452 100644 --- a/src/test/java/com/arangodb/ArangoDatabaseTest.java +++ b/src/test/java/com/arangodb/ArangoDatabaseTest.java @@ -333,11 +333,11 @@ void createCollectionWithJsonSchema(ArangoDatabase db) { assertThat(props.getSchema().getRule()).isEqualTo(rule); assertThat(props.getSchema().getMessage()).isEqualTo(message); - BaseDocument doc = new BaseDocument(); + BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); doc.addAttribute("number", 33); db.collection(name).insertDocument(doc); - BaseDocument wrongDoc = new BaseDocument(); + BaseDocument wrongDoc = new BaseDocument(UUID.randomUUID().toString()); wrongDoc.addAttribute("number", "notANumber"); Throwable thrown = catchThrowable(() -> db.collection(name).insertDocument(wrongDoc)); assertThat(thrown).isInstanceOf(ArangoDBException.class); @@ -816,7 +816,7 @@ void changeQueryTrackingProperties(ArangoDatabase db) { @MethodSource("dbs") void queryWithBindVars(ArangoDatabase db) { for (int i = 0; i < 10; i++) { - final BaseDocument baseDocument = new BaseDocument(); + final BaseDocument baseDocument = new BaseDocument(UUID.randomUUID().toString()); baseDocument.addAttribute("age", 20 + i); db.collection(CNAME1).insertDocument(baseDocument, null); } diff --git a/src/test/java/com/arangodb/ArangoEdgeCollectionTest.java b/src/test/java/com/arangodb/ArangoEdgeCollectionTest.java index 2c6e277ae..c68e4a38f 100644 --- a/src/test/java/com/arangodb/ArangoEdgeCollectionTest.java +++ b/src/test/java/com/arangodb/ArangoEdgeCollectionTest.java @@ -184,7 +184,7 @@ void replaceEdge(ArangoVertexCollection vertices, ArangoEdgeCollection edges) { final BaseEdgeDocument doc = createEdgeValue(vertices); doc.addAttribute("a", "test"); final EdgeEntity createResult = edges.insertEdge(doc); - doc.getProperties().clear(); + doc.removeAttribute("a"); doc.addAttribute("b", "test"); final EdgeUpdateEntity replaceResult = edges .replaceEdge(createResult.getKey(), doc); @@ -222,7 +222,7 @@ void replaceEdgeIfMatch(ArangoVertexCollection vertices, ArangoEdgeCollection ed final BaseEdgeDocument doc = createEdgeValue(vertices); doc.addAttribute("a", "test"); final EdgeEntity createResult = edges.insertEdge(doc); - doc.getProperties().clear(); + doc.removeAttribute("a"); doc.addAttribute("b", "test"); final EdgeReplaceOptions options = new EdgeReplaceOptions().ifMatch(createResult.getRev()); final EdgeUpdateEntity replaceResult = edges @@ -247,7 +247,7 @@ void replaceEdgeIfMatchFail(ArangoVertexCollection vertices, ArangoEdgeCollectio final BaseEdgeDocument doc = createEdgeValue(vertices); doc.addAttribute("a", "test"); final EdgeEntity createResult = edges.insertEdge(doc); - doc.getProperties().clear(); + doc.removeAttribute("a"); doc.addAttribute("b", "test"); final EdgeReplaceOptions options = new EdgeReplaceOptions().ifMatch("no"); Throwable thrown = catchThrowable(() -> edges.replaceEdge(createResult.getKey(), doc, options)); @@ -366,7 +366,7 @@ void updateEdgeKeepNullTrue(ArangoVertexCollection vertices, ArangoEdgeCollectio final BaseEdgeDocument readResult = edges .getEdge(createResult.getKey(), BaseEdgeDocument.class); assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); - assertThat(readResult.getProperties().keySet()).hasSize(1); + assertThat(readResult.getProperties().keySet()).hasSize(6); assertThat(readResult.getProperties()).containsKey("a"); } diff --git a/src/test/java/com/arangodb/ArangoVertexCollectionTest.java b/src/test/java/com/arangodb/ArangoVertexCollectionTest.java index a0e79031f..3c51d8ded 100644 --- a/src/test/java/com/arangodb/ArangoVertexCollectionTest.java +++ b/src/test/java/com/arangodb/ArangoVertexCollectionTest.java @@ -118,14 +118,14 @@ void duplicateInsertSameObjectVertex(ArangoVertexCollection vertices) { // ######################################################### UUID uuid = UUID.randomUUID(); - BaseDocument bd = new BaseDocument(); + BaseDocument bd = new BaseDocument(UUID.randomUUID().toString()); bd.setKey(uuid.toString()); bd.addAttribute("name", "Paul"); vertices.insertVertex(bd); UUID uuid2 = UUID.randomUUID(); - BaseDocument bd2 = new BaseDocument(); + BaseDocument bd2 = new BaseDocument(UUID.randomUUID().toString()); bd2.setKey(uuid2.toString()); bd2.addAttribute("name", "Paul"); @@ -135,7 +135,7 @@ void duplicateInsertSameObjectVertex(ArangoVertexCollection vertices) { @ParameterizedTest(name = "{index}") @MethodSource("vertices") void insertVertexUpdateRev(ArangoVertexCollection vertices) { - final BaseDocument doc = new BaseDocument(); + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); final VertexEntity vertex = vertices.insertVertex(doc, null); assertThat(doc.getRevision()).isNull(); assertThat(vertex.getRev()).isNotNull(); @@ -201,11 +201,11 @@ void getVertexIfNoneMatchFail(ArangoVertexCollection vertices) { @ParameterizedTest(name = "{index}") @MethodSource("vertices") void replaceVertex(ArangoVertexCollection vertices) { - final BaseDocument doc = new BaseDocument(); + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); doc.addAttribute("a", "test"); final VertexEntity createResult = vertices .insertVertex(doc, null); - doc.getProperties().clear(); + doc.removeAttribute("a"); doc.addAttribute("b", "test"); final VertexUpdateEntity replaceResult = vertices .replaceVertex(createResult.getKey(), doc, null); @@ -226,7 +226,7 @@ void replaceVertex(ArangoVertexCollection vertices) { @ParameterizedTest(name = "{index}") @MethodSource("vertices") void replaceVertexUpdateRev(ArangoVertexCollection vertices) { - final BaseDocument doc = new BaseDocument(); + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); final VertexEntity createResult = vertices .insertVertex(doc, null); final VertexUpdateEntity replaceResult = vertices @@ -241,11 +241,11 @@ void replaceVertexUpdateRev(ArangoVertexCollection vertices) { @ParameterizedTest(name = "{index}") @MethodSource("vertices") void replaceVertexIfMatch(ArangoVertexCollection vertices) { - final BaseDocument doc = new BaseDocument(); + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); doc.addAttribute("a", "test"); final VertexEntity createResult = vertices .insertVertex(doc, null); - doc.getProperties().clear(); + doc.removeAttribute("a"); doc.addAttribute("b", "test"); final VertexReplaceOptions options = new VertexReplaceOptions().ifMatch(createResult.getRev()); final VertexUpdateEntity replaceResult = vertices @@ -267,11 +267,11 @@ void replaceVertexIfMatch(ArangoVertexCollection vertices) { @ParameterizedTest(name = "{index}") @MethodSource("vertices") void replaceVertexIfMatchFail(ArangoVertexCollection vertices) { - final BaseDocument doc = new BaseDocument(); + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); doc.addAttribute("a", "test"); final VertexEntity createResult = vertices .insertVertex(doc, null); - doc.getProperties().clear(); + doc.removeAttribute("a"); doc.addAttribute("b", "test"); final VertexReplaceOptions options = new VertexReplaceOptions().ifMatch("no"); Throwable thrown = catchThrowable(() -> vertices.replaceVertex(createResult.getKey(), doc, options)); @@ -285,7 +285,7 @@ void replaceVertexIfMatchFail(ArangoVertexCollection vertices) { @ParameterizedTest(name = "{index}") @MethodSource("vertices") void updateVertex(ArangoVertexCollection vertices) { - final BaseDocument doc = new BaseDocument(); + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); doc.addAttribute("a", "test"); doc.addAttribute("c", "test"); final VertexEntity createResult = vertices @@ -314,7 +314,7 @@ void updateVertex(ArangoVertexCollection vertices) { @ParameterizedTest(name = "{index}") @MethodSource("vertices") void updateVertexUpdateRev(ArangoVertexCollection vertices) { - final BaseDocument doc = new BaseDocument(); + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); final VertexEntity createResult = vertices .insertVertex(doc, null); final VertexUpdateEntity updateResult = vertices @@ -329,7 +329,7 @@ void updateVertexUpdateRev(ArangoVertexCollection vertices) { @ParameterizedTest(name = "{index}") @MethodSource("vertices") void updateVertexIfMatch(ArangoVertexCollection vertices) { - final BaseDocument doc = new BaseDocument(); + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); doc.addAttribute("a", "test"); doc.addAttribute("c", "test"); final VertexEntity createResult = vertices @@ -359,7 +359,7 @@ void updateVertexIfMatch(ArangoVertexCollection vertices) { @ParameterizedTest(name = "{index}") @MethodSource("vertices") void updateVertexIfMatchFail(ArangoVertexCollection vertices) { - final BaseDocument doc = new BaseDocument(); + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); doc.addAttribute("a", "test"); doc.addAttribute("c", "test"); final VertexEntity createResult = vertices @@ -380,7 +380,7 @@ void updateVertexIfMatchFail(ArangoVertexCollection vertices) { @ParameterizedTest(name = "{index}") @MethodSource("vertices") void updateVertexKeepNullTrue(ArangoVertexCollection vertices) { - final BaseDocument doc = new BaseDocument(); + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); doc.addAttribute("a", "test"); final VertexEntity createResult = vertices .insertVertex(doc, null); @@ -396,14 +396,14 @@ void updateVertexKeepNullTrue(ArangoVertexCollection vertices) { final BaseDocument readResult = vertices .getVertex(createResult.getKey(), BaseDocument.class, null); assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); - assertThat(readResult.getProperties().keySet()).hasSize(1); + assertThat(readResult.getProperties().keySet()).hasSize(4); assertThat(readResult.getProperties()).containsKey("a"); } @ParameterizedTest(name = "{index}") @MethodSource("vertices") void updateVertexKeepNullFalse(ArangoVertexCollection vertices) { - final BaseDocument doc = new BaseDocument(); + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); doc.addAttribute("a", "test"); final VertexEntity createResult = vertices .insertVertex(doc, null); @@ -427,7 +427,7 @@ void updateVertexKeepNullFalse(ArangoVertexCollection vertices) { @ParameterizedTest(name = "{index}") @MethodSource("vertices") void deleteVertex(ArangoVertexCollection vertices) { - final BaseDocument doc = new BaseDocument(); + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); final VertexEntity createResult = vertices .insertVertex(doc, null); vertices.deleteVertex(createResult.getKey(), null); @@ -439,7 +439,7 @@ void deleteVertex(ArangoVertexCollection vertices) { @ParameterizedTest(name = "{index}") @MethodSource("vertices") void deleteVertexIfMatch(ArangoVertexCollection vertices) { - final BaseDocument doc = new BaseDocument(); + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); final VertexEntity createResult = vertices .insertVertex(doc, null); final VertexDeleteOptions options = new VertexDeleteOptions().ifMatch(createResult.getRev()); @@ -452,7 +452,7 @@ void deleteVertexIfMatch(ArangoVertexCollection vertices) { @ParameterizedTest(name = "{index}") @MethodSource("vertices") void deleteVertexIfMatchFail(ArangoVertexCollection vertices) { - final BaseDocument doc = new BaseDocument(); + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); final VertexEntity createResult = vertices .insertVertex(doc, null); final VertexDeleteOptions options = new VertexDeleteOptions().ifMatch("no"); diff --git a/src/test/java/com/arangodb/DocumentTest.java b/src/test/java/com/arangodb/DocumentTest.java index e9f471d41..55f0724f0 100644 --- a/src/test/java/com/arangodb/DocumentTest.java +++ b/src/test/java/com/arangodb/DocumentTest.java @@ -97,9 +97,9 @@ void insertAsJson(ArangoCollection collection) { @ParameterizedTest(name = "{index}") @MethodSource("cols") void insertAsBaseDocument(ArangoCollection collection) { - final BaseDocument document = new BaseDocument(); + final BaseDocument document = new BaseDocument(UUID.randomUUID().toString()); { - final BaseDocument article = new BaseDocument(); + final BaseDocument article = new BaseDocument(UUID.randomUUID().toString()); document.addAttribute("article", article); article.addAttribute("artist", "PREGARDIEN/RHEINISCHE KANTOREI/DAS"); article.addAttribute("releaseDate", "1970-01-01"); @@ -111,7 +111,7 @@ void insertAsBaseDocument(ArangoCollection collection) { article.addAttribute("title", "BACH ST MATTHEW PASSION BWV244"); article.addAttribute("barcode", new String[]{"4006408600466"}); article.addAttribute("conductor", "MAX, H."); - final BaseDocument stock = new BaseDocument(); + final BaseDocument stock = new BaseDocument(UUID.randomUUID().toString()); document.addAttribute("stock", stock); stock.addAttribute("status", "RMV"); stock.addAttribute("lastUpdate", "2016-11-01 00:00"); diff --git a/src/test/java/com/arangodb/StreamTransactionGraphTest.java b/src/test/java/com/arangodb/StreamTransactionGraphTest.java index 039d2d86c..58264d620 100644 --- a/src/test/java/com/arangodb/StreamTransactionGraphTest.java +++ b/src/test/java/com/arangodb/StreamTransactionGraphTest.java @@ -28,6 +28,7 @@ import org.junit.jupiter.params.provider.MethodSource; import java.util.Collections; +import java.util.UUID; import java.util.stream.Stream; import static org.assertj.core.api.Assertions.assertThat; @@ -135,7 +136,7 @@ void replaceVertex(ArangoVertexCollection vertexCollection1) { assumeTrue(isAtLeastVersion(3, 5)); assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); - BaseDocument doc = new BaseDocument(); + BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); doc.addAttribute("test", "foo"); VertexEntity createdVertex = vertexCollection1.insertVertex(doc, null); @@ -147,8 +148,7 @@ void replaceVertex(ArangoVertexCollection vertexCollection1) { .writeCollections(VERTEX_COLLECTION_1, VERTEX_COLLECTION_2, EDGE_COLLECTION)); // replace vertex from within the tx - doc.getProperties().clear(); - doc.addAttribute("test", "bar"); + doc.updateAttribute("test", "bar"); vertexCollection1.replaceVertex(createdVertex.getKey(), doc, new VertexReplaceOptions().streamTransactionId(tx.getId())); @@ -174,7 +174,7 @@ void updateVertex(ArangoVertexCollection vertexCollection1) { assumeTrue(isAtLeastVersion(3, 5)); assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); - BaseDocument doc = new BaseDocument(); + BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); doc.addAttribute("test", "foo"); VertexEntity createdDoc = vertexCollection1.insertVertex(doc, null); @@ -186,8 +186,7 @@ void updateVertex(ArangoVertexCollection vertexCollection1) { .writeCollections(VERTEX_COLLECTION_1, VERTEX_COLLECTION_2, EDGE_COLLECTION)); // update vertex from within the tx - doc.getProperties().clear(); - doc.addAttribute("test", "bar"); + doc.updateAttribute("test", "bar"); vertexCollection1.updateVertex(createdDoc.getKey(), doc, new VertexUpdateOptions().streamTransactionId(tx.getId())); // assert that the vertex has not been updated from outside the tx @@ -309,8 +308,7 @@ void replaceEdge(ArangoEdgeCollection edgeCollection) { .writeCollections(VERTEX_COLLECTION_1, VERTEX_COLLECTION_2, EDGE_COLLECTION)); // replace edge from within the tx - doc.getProperties().clear(); - doc.addAttribute("test", "bar"); + doc.updateAttribute("test", "bar"); edgeCollection.replaceEdge(createdEdge.getKey(), doc, new EdgeReplaceOptions().streamTransactionId(tx.getId())); @@ -348,8 +346,7 @@ void updateEdge(ArangoEdgeCollection edgeCollection) { .writeCollections(VERTEX_COLLECTION_1, VERTEX_COLLECTION_2, EDGE_COLLECTION)); // update edge from within the tx - doc.getProperties().clear(); - doc.addAttribute("test", "bar"); + doc.updateAttribute("test", "bar"); edgeCollection.updateEdge(createdDoc.getKey(), doc, new EdgeUpdateOptions().streamTransactionId(tx.getId())); // assert that the edge has not been updated from outside the tx diff --git a/src/test/java/com/arangodb/StreamTransactionTest.java b/src/test/java/com/arangodb/StreamTransactionTest.java index 9ed7d9284..d17d9e6d7 100644 --- a/src/test/java/com/arangodb/StreamTransactionTest.java +++ b/src/test/java/com/arangodb/StreamTransactionTest.java @@ -375,7 +375,7 @@ void replaceDocument(ArangoDatabase db) { assumeTrue(isAtLeastVersion(3, 5)); assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); - BaseDocument doc = new BaseDocument(); + BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); doc.addAttribute("test", "foo"); ArangoCollection collection = db.collection(COLLECTION_NAME); @@ -385,8 +385,7 @@ void replaceDocument(ArangoDatabase db) { new StreamTransactionOptions().readCollections(COLLECTION_NAME).writeCollections(COLLECTION_NAME)); // replace document from within the tx - doc.getProperties().clear(); - doc.addAttribute("test", "bar"); + doc.updateAttribute("test", "bar"); collection.replaceDocument(createdDoc.getKey(), doc, new DocumentReplaceOptions().streamTransactionId(tx.getId())); @@ -426,8 +425,7 @@ void replaceDocuments(ArangoDatabase db) { new StreamTransactionOptions().readCollections(COLLECTION_NAME).writeCollections(COLLECTION_NAME)); List modifiedDocs = createdDocs.stream().peek(doc -> { - doc.getProperties().clear(); - doc.addAttribute("test", "bar"); + doc.updateAttribute("test", "bar"); }).collect(Collectors.toList()); // replace document from within the tx @@ -460,7 +458,7 @@ void updateDocument(ArangoDatabase db) { assumeTrue(isAtLeastVersion(3, 5)); assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); - BaseDocument doc = new BaseDocument(); + BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); doc.addAttribute("test", "foo"); ArangoCollection collection = db.collection(COLLECTION_NAME); @@ -470,8 +468,7 @@ void updateDocument(ArangoDatabase db) { new StreamTransactionOptions().readCollections(COLLECTION_NAME).writeCollections(COLLECTION_NAME)); // update document from within the tx - doc.getProperties().clear(); - doc.addAttribute("test", "bar"); + doc.updateAttribute("test", "bar"); collection .updateDocument(createdDoc.getKey(), doc, new DocumentUpdateOptions().streamTransactionId(tx.getId())); @@ -513,8 +510,7 @@ void updateDocuments(ArangoDatabase db) { new StreamTransactionOptions().readCollections(COLLECTION_NAME).writeCollections(COLLECTION_NAME)); List modifiedDocs = createdDocs.stream().peek(doc -> { - doc.getProperties().clear(); - doc.addAttribute("test", "bar"); + doc.updateAttribute("test", "bar"); }).collect(Collectors.toList()); // update documents from within the tx diff --git a/src/test/java/com/arangodb/async/ArangoCollectionTest.java b/src/test/java/com/arangodb/async/ArangoCollectionTest.java index 5265ad47f..db72e4e42 100644 --- a/src/test/java/com/arangodb/async/ArangoCollectionTest.java +++ b/src/test/java/com/arangodb/async/ArangoCollectionTest.java @@ -254,7 +254,7 @@ void getDocumentsWrongKey() throws InterruptedException, ExecutionException { @Test void updateDocument() throws InterruptedException, ExecutionException { - final BaseDocument doc = new BaseDocument(); + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); doc.addAttribute("a", "test"); doc.addAttribute("c", "test"); final DocumentCreateEntity createResult = db.collection(COLLECTION_NAME).insertDocument(doc, null) @@ -306,7 +306,7 @@ void updateDocumentWithDifferentReturnType() throws ExecutionException, Interrup @Test void updateDocumentIfMatch() throws InterruptedException, ExecutionException { - final BaseDocument doc = new BaseDocument(); + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); doc.addAttribute("a", "test"); doc.addAttribute("c", "test"); final DocumentCreateEntity createResult = db.collection(COLLECTION_NAME).insertDocument(doc, null) @@ -339,7 +339,7 @@ void updateDocumentIfMatch() throws InterruptedException, ExecutionException { @Test void updateDocumentIfMatchFail() throws InterruptedException, ExecutionException { - final BaseDocument doc = new BaseDocument(); + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); doc.addAttribute("a", "test"); doc.addAttribute("c", "test"); final DocumentCreateEntity createResult = db.collection(COLLECTION_NAME).insertDocument(doc, null) @@ -358,7 +358,7 @@ void updateDocumentIfMatchFail() throws InterruptedException, ExecutionException @Test void updateDocumentReturnNew() throws InterruptedException, ExecutionException { - final BaseDocument doc = new BaseDocument(); + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); doc.addAttribute("a", "test"); final DocumentCreateEntity createResult = db.collection(COLLECTION_NAME).insertDocument(doc, null) .get(); @@ -383,7 +383,7 @@ void updateDocumentReturnNew() throws InterruptedException, ExecutionException { @Test void updateDocumentReturnOld() throws InterruptedException, ExecutionException { - final BaseDocument doc = new BaseDocument(); + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); doc.addAttribute("a", "test"); final DocumentCreateEntity createResult = db.collection(COLLECTION_NAME).insertDocument(doc, null) .get(); @@ -407,7 +407,7 @@ void updateDocumentReturnOld() throws InterruptedException, ExecutionException { @Test void updateDocumentKeepNullTrue() throws InterruptedException, ExecutionException { - final BaseDocument doc = new BaseDocument(); + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); doc.addAttribute("a", "test"); final DocumentCreateEntity createResult = db.collection(COLLECTION_NAME).insertDocument(doc, null) .get(); @@ -430,7 +430,7 @@ void updateDocumentKeepNullTrue() throws InterruptedException, ExecutionExceptio @Test void updateDocumentKeepNullFalse() throws InterruptedException, ExecutionException { - final BaseDocument doc = new BaseDocument(); + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); doc.addAttribute("a", "test"); final DocumentCreateEntity createResult = db.collection(COLLECTION_NAME).insertDocument(doc, null) .get(); @@ -456,7 +456,7 @@ void updateDocumentKeepNullFalse() throws InterruptedException, ExecutionExcepti @SuppressWarnings("unchecked") @Test void updateDocumentMergeObjectsTrue() throws InterruptedException, ExecutionException { - final BaseDocument doc = new BaseDocument(); + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); final Map a = new HashMap<>(); a.put("a", "test"); doc.addAttribute("a", a); @@ -488,7 +488,7 @@ void updateDocumentMergeObjectsTrue() throws InterruptedException, ExecutionExce @SuppressWarnings("unchecked") @Test void updateDocumentMergeObjectsFalse() throws InterruptedException, ExecutionException { - final BaseDocument doc = new BaseDocument(); + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); final Map a = new HashMap<>(); a.put("a", "test"); doc.addAttribute("a", a); @@ -519,7 +519,7 @@ void updateDocumentMergeObjectsFalse() throws InterruptedException, ExecutionExc @Test void updateDocumentIgnoreRevsFalse() throws InterruptedException, ExecutionException { - final BaseDocument doc = new BaseDocument(); + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); doc.addAttribute("a", "test"); final DocumentCreateEntity createResult = db.collection(COLLECTION_NAME).insertDocument(doc, null) .get(); @@ -536,11 +536,11 @@ void updateDocumentIgnoreRevsFalse() throws InterruptedException, ExecutionExcep @Test void replaceDocument() throws InterruptedException, ExecutionException { - final BaseDocument doc = new BaseDocument(); + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); doc.addAttribute("a", "test"); final DocumentCreateEntity createResult = db.collection(COLLECTION_NAME).insertDocument(doc, null) .get(); - doc.getProperties().clear(); + doc.removeAttribute("a"); doc.addAttribute("b", "test"); final CompletableFuture> f = db.collection(COLLECTION_NAME) .replaceDocument(createResult.getKey(), doc, null); @@ -565,11 +565,11 @@ void replaceDocument() throws InterruptedException, ExecutionException { @Test void replaceDocumentIfMatch() throws InterruptedException, ExecutionException { - final BaseDocument doc = new BaseDocument(); + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); doc.addAttribute("a", "test"); final DocumentCreateEntity createResult = db.collection(COLLECTION_NAME).insertDocument(doc, null) .get(); - doc.getProperties().clear(); + doc.removeAttribute("a"); doc.addAttribute("b", "test"); final DocumentReplaceOptions options = new DocumentReplaceOptions().ifMatch(createResult.getRev()); final CompletableFuture> f = db.collection(COLLECTION_NAME) @@ -593,11 +593,11 @@ void replaceDocumentIfMatch() throws InterruptedException, ExecutionException { @Test void replaceDocumentIfMatchFail() throws InterruptedException, ExecutionException { - final BaseDocument doc = new BaseDocument(); + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); doc.addAttribute("a", "test"); final DocumentCreateEntity createResult = db.collection(COLLECTION_NAME).insertDocument(doc, null) .get(); - doc.getProperties().clear(); + doc.removeAttribute("a"); doc.addAttribute("b", "test"); try { final DocumentReplaceOptions options = new DocumentReplaceOptions().ifMatch("no"); @@ -610,11 +610,11 @@ void replaceDocumentIfMatchFail() throws InterruptedException, ExecutionExceptio @Test void replaceDocumentIgnoreRevsFalse() throws InterruptedException, ExecutionException { - final BaseDocument doc = new BaseDocument(); + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); doc.addAttribute("a", "test"); final DocumentCreateEntity createResult = db.collection(COLLECTION_NAME).insertDocument(doc, null) .get(); - doc.getProperties().clear(); + doc.removeAttribute("a"); doc.addAttribute("b", "test"); doc.setRevision("no"); try { @@ -628,11 +628,11 @@ void replaceDocumentIgnoreRevsFalse() throws InterruptedException, ExecutionExce @Test void replaceDocumentReturnNew() throws InterruptedException, ExecutionException { - final BaseDocument doc = new BaseDocument(); + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); doc.addAttribute("a", "test"); final DocumentCreateEntity createResult = db.collection(COLLECTION_NAME).insertDocument(doc, null) .get(); - doc.getProperties().clear(); + doc.removeAttribute("a"); doc.addAttribute("b", "test"); final DocumentReplaceOptions options = new DocumentReplaceOptions().returnNew(true); db.collection(COLLECTION_NAME).replaceDocument(createResult.getKey(), doc, options) @@ -652,11 +652,11 @@ void replaceDocumentReturnNew() throws InterruptedException, ExecutionException @Test void replaceDocumentReturnOld() throws InterruptedException, ExecutionException { - final BaseDocument doc = new BaseDocument(); + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); doc.addAttribute("a", "test"); final DocumentCreateEntity createResult = db.collection(COLLECTION_NAME).insertDocument(doc, null) .get(); - doc.getProperties().clear(); + doc.removeAttribute("a"); doc.addAttribute("b", "test"); final DocumentReplaceOptions options = new DocumentReplaceOptions().returnOld(true); db.collection(COLLECTION_NAME).replaceDocument(createResult.getKey(), doc, options) @@ -676,7 +676,7 @@ void replaceDocumentReturnOld() throws InterruptedException, ExecutionException @Test void deleteDocument() throws InterruptedException, ExecutionException { - final BaseDocument doc = new BaseDocument(); + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); final DocumentCreateEntity createResult = db.collection(COLLECTION_NAME).insertDocument(doc, null) .get(); db.collection(COLLECTION_NAME).deleteDocument(createResult.getKey(), null, null).get(); @@ -687,7 +687,7 @@ void deleteDocument() throws InterruptedException, ExecutionException { @Test void deleteDocumentReturnOld() throws InterruptedException, ExecutionException { - final BaseDocument doc = new BaseDocument(); + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); doc.addAttribute("a", "test"); final DocumentCreateEntity createResult = db.collection(COLLECTION_NAME).insertDocument(doc, null) .get(); @@ -704,7 +704,7 @@ void deleteDocumentReturnOld() throws InterruptedException, ExecutionException { @Test void deleteDocumentIfMatch() throws InterruptedException, ExecutionException { - final BaseDocument doc = new BaseDocument(); + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); final DocumentCreateEntity createResult = db.collection(COLLECTION_NAME).insertDocument(doc, null) .get(); final DocumentDeleteOptions options = new DocumentDeleteOptions().ifMatch(createResult.getRev()); @@ -716,7 +716,7 @@ void deleteDocumentIfMatch() throws InterruptedException, ExecutionException { @Test void deleteDocumentIfMatchFail() throws InterruptedException, ExecutionException { - final BaseDocument doc = new BaseDocument(); + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); final DocumentCreateEntity createResult = db.collection(COLLECTION_NAME).insertDocument(doc, null) .get(); final DocumentDeleteOptions options = new DocumentDeleteOptions().ifMatch("no"); @@ -1774,12 +1774,12 @@ void importDocumentsJsonFromToPrefix() throws InterruptedException, ExecutionExc void deleteDocumentsByKey() throws InterruptedException, ExecutionException { final Collection values = new ArrayList<>(); { - final BaseDocument e = new BaseDocument(); + final BaseDocument e = new BaseDocument(UUID.randomUUID().toString()); e.setKey("1"); values.add(e); } { - final BaseDocument e = new BaseDocument(); + final BaseDocument e = new BaseDocument(UUID.randomUUID().toString()); e.setKey("2"); values.add(e); } @@ -1803,12 +1803,12 @@ void deleteDocumentsByKey() throws InterruptedException, ExecutionException { void deleteDocumentsByDocuments() throws InterruptedException, ExecutionException { final Collection values = new ArrayList<>(); { - final BaseDocument e = new BaseDocument(); + final BaseDocument e = new BaseDocument(UUID.randomUUID().toString()); e.setKey("1"); values.add(e); } { - final BaseDocument e = new BaseDocument(); + final BaseDocument e = new BaseDocument(UUID.randomUUID().toString()); e.setKey("2"); values.add(e); } @@ -1829,7 +1829,7 @@ void deleteDocumentsByDocuments() throws InterruptedException, ExecutionExceptio void deleteDocumentsByKeyOne() throws InterruptedException, ExecutionException { final Collection values = new ArrayList<>(); { - final BaseDocument e = new BaseDocument(); + final BaseDocument e = new BaseDocument(UUID.randomUUID().toString()); e.setKey("1"); values.add(e); } @@ -1852,7 +1852,7 @@ void deleteDocumentsByKeyOne() throws InterruptedException, ExecutionException { void deleteDocumentsByDocumentOne() throws InterruptedException, ExecutionException { final Collection values = new ArrayList<>(); { - final BaseDocument e = new BaseDocument(); + final BaseDocument e = new BaseDocument(UUID.randomUUID().toString()); e.setKey("1"); values.add(e); } @@ -1903,12 +1903,12 @@ void deleteDocumentsByKeyNotExisting() throws InterruptedException, ExecutionExc void deleteDocumentsByDocumentsNotExisting() throws InterruptedException, ExecutionException { final Collection values = new ArrayList<>(); { - final BaseDocument e = new BaseDocument(); + final BaseDocument e = new BaseDocument(UUID.randomUUID().toString()); e.setKey("1"); values.add(e); } { - final BaseDocument e = new BaseDocument(); + final BaseDocument e = new BaseDocument(UUID.randomUUID().toString()); e.setKey("2"); values.add(e); } @@ -1925,12 +1925,12 @@ void deleteDocumentsByDocumentsNotExisting() throws InterruptedException, Execut void updateDocuments() throws InterruptedException, ExecutionException { final Collection values = new ArrayList<>(); { - final BaseDocument e = new BaseDocument(); + final BaseDocument e = new BaseDocument(UUID.randomUUID().toString()); e.setKey("1"); values.add(e); } { - final BaseDocument e = new BaseDocument(); + final BaseDocument e = new BaseDocument(UUID.randomUUID().toString()); e.setKey("2"); values.add(e); } @@ -1983,7 +1983,7 @@ void updateDocumentsWithDifferentReturnType() throws ExecutionException, Interru void updateDocumentsOne() throws InterruptedException, ExecutionException { final Collection values = new ArrayList<>(); { - final BaseDocument e = new BaseDocument(); + final BaseDocument e = new BaseDocument(UUID.randomUUID().toString()); e.setKey("1"); values.add(e); } @@ -2057,7 +2057,7 @@ void replaceDocuments() throws InterruptedException, ExecutionException { void replaceDocumentsOne() throws InterruptedException, ExecutionException { final Collection values = new ArrayList<>(); { - final BaseDocument e = new BaseDocument(); + final BaseDocument e = new BaseDocument(UUID.randomUUID().toString()); e.setKey("1"); values.add(e); } diff --git a/src/test/java/com/arangodb/async/ArangoDatabaseTest.java b/src/test/java/com/arangodb/async/ArangoDatabaseTest.java index 565185563..d9c2a14ef 100644 --- a/src/test/java/com/arangodb/async/ArangoDatabaseTest.java +++ b/src/test/java/com/arangodb/async/ArangoDatabaseTest.java @@ -677,7 +677,7 @@ void queryWithBindVars() throws InterruptedException, ExecutionException { try { db.createCollection(COLLECTION_NAME, null).get(); for (int i = 0; i < 10; i++) { - final BaseDocument baseDocument = new BaseDocument(); + final BaseDocument baseDocument = new BaseDocument(UUID.randomUUID().toString()); baseDocument.addAttribute("age", 20 + i); db.collection(COLLECTION_NAME).insertDocument(baseDocument, null).get(); } @@ -968,7 +968,7 @@ void getInfo() throws InterruptedException, ExecutionException { void getDocument() throws InterruptedException, ExecutionException { String collectionName = COLLECTION_NAME + "getDocument"; db.createCollection(collectionName).get(); - final BaseDocument value = new BaseDocument(); + final BaseDocument value = new BaseDocument(UUID.randomUUID().toString()); value.setKey("123"); db.collection(collectionName).insertDocument(value).get(); db.getDocument(collectionName + "/123", BaseDocument.class) diff --git a/src/test/java/com/arangodb/async/ArangoEdgeCollectionTest.java b/src/test/java/com/arangodb/async/ArangoEdgeCollectionTest.java index 4424451e9..7f89c48b4 100644 --- a/src/test/java/com/arangodb/async/ArangoEdgeCollectionTest.java +++ b/src/test/java/com/arangodb/async/ArangoEdgeCollectionTest.java @@ -155,7 +155,7 @@ void replaceEdge() throws InterruptedException, ExecutionException { doc.addAttribute("a", "test"); final EdgeEntity createResult = db.graph(GRAPH_NAME).edgeCollection(EDGE_COLLECTION_NAME).insertEdge(doc, null) .get(); - doc.getProperties().clear(); + doc.removeAttribute("a"); doc.addAttribute("b", "test"); final EdgeUpdateEntity replaceResult = db.graph(GRAPH_NAME).edgeCollection(EDGE_COLLECTION_NAME) .replaceEdge(createResult.getKey(), doc, null).get(); @@ -179,7 +179,7 @@ void replaceEdgeIfMatch() throws InterruptedException, ExecutionException { doc.addAttribute("a", "test"); final EdgeEntity createResult = db.graph(GRAPH_NAME).edgeCollection(EDGE_COLLECTION_NAME).insertEdge(doc, null) .get(); - doc.getProperties().clear(); + doc.removeAttribute("a"); doc.addAttribute("b", "test"); final EdgeReplaceOptions options = new EdgeReplaceOptions().ifMatch(createResult.getRev()); final EdgeUpdateEntity replaceResult = db.graph(GRAPH_NAME).edgeCollection(EDGE_COLLECTION_NAME) @@ -204,7 +204,7 @@ void replaceEdgeIfMatchFail() throws InterruptedException, ExecutionException { doc.addAttribute("a", "test"); final EdgeEntity createResult = db.graph(GRAPH_NAME).edgeCollection(EDGE_COLLECTION_NAME).insertEdge(doc, null) .get(); - doc.getProperties().clear(); + doc.removeAttribute("a"); doc.addAttribute("b", "test"); try { final EdgeReplaceOptions options = new EdgeReplaceOptions().ifMatch("no"); @@ -311,7 +311,7 @@ void updateEdgeKeepNullTrue() throws InterruptedException, ExecutionException { final BaseEdgeDocument readResult = db.graph(GRAPH_NAME).edgeCollection(EDGE_COLLECTION_NAME) .getEdge(createResult.getKey(), BaseEdgeDocument.class, null).get(); assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); - assertThat(readResult.getProperties().keySet()).hasSize(1); + assertThat(readResult.getProperties().keySet()).hasSize(6); assertThat(readResult.getProperties()).containsKey("a"); } diff --git a/src/test/java/com/arangodb/async/ArangoRouteTest.java b/src/test/java/com/arangodb/async/ArangoRouteTest.java index d01b3ad11..5a3dbbf4b 100644 --- a/src/test/java/com/arangodb/async/ArangoRouteTest.java +++ b/src/test/java/com/arangodb/async/ArangoRouteTest.java @@ -26,6 +26,7 @@ import org.junit.jupiter.api.Test; +import java.util.UUID; import java.util.concurrent.ExecutionException; @@ -50,7 +51,7 @@ void withHeader() throws InterruptedException, ExecutionException { final ArangoCollectionAsync collection = db.collection("route-test-col"); try { collection.create(); - final BaseDocument doc = new BaseDocument(); + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); collection.insertDocument(doc).get(); db.route("/_api/document", doc.getId()).withHeader(ArangoRequestParam.IF_NONE_MATCH, doc.getRevision()) .get().get(); @@ -68,7 +69,7 @@ void withParentHeader() throws InterruptedException, ExecutionException { final ArangoCollectionAsync collection = db.collection("route-test-col"); try { collection.create().get(); - final BaseDocument doc = new BaseDocument(); + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); collection.insertDocument(doc).get(); db.route("/_api/document").withHeader(ArangoRequestParam.IF_NONE_MATCH, doc.getRevision()) .route(doc.getId()).get().get(); diff --git a/src/test/java/com/arangodb/async/ArangoVertexCollectionTest.java b/src/test/java/com/arangodb/async/ArangoVertexCollectionTest.java index cdaa860c8..ca1a02515 100644 --- a/src/test/java/com/arangodb/async/ArangoVertexCollectionTest.java +++ b/src/test/java/com/arangodb/async/ArangoVertexCollectionTest.java @@ -31,6 +31,7 @@ import java.util.Collection; +import java.util.UUID; import java.util.concurrent.ExecutionException; @@ -139,11 +140,11 @@ void getVertexIfNoneMatchFail() throws InterruptedException, ExecutionException @Test void replaceVertex() throws InterruptedException, ExecutionException { - final BaseDocument doc = new BaseDocument(); + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); doc.addAttribute("a", "test"); final VertexEntity createResult = db.graph(GRAPH_NAME).vertexCollection(COLLECTION_NAME).insertVertex(doc, null) .get(); - doc.getProperties().clear(); + doc.removeAttribute("a"); doc.addAttribute("b", "test"); final VertexUpdateEntity replaceResult = db.graph(GRAPH_NAME).vertexCollection(COLLECTION_NAME) .replaceVertex(createResult.getKey(), doc, null).get(); @@ -163,11 +164,11 @@ void replaceVertex() throws InterruptedException, ExecutionException { @Test void replaceVertexIfMatch() throws InterruptedException, ExecutionException { - final BaseDocument doc = new BaseDocument(); + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); doc.addAttribute("a", "test"); final VertexEntity createResult = db.graph(GRAPH_NAME).vertexCollection(COLLECTION_NAME).insertVertex(doc, null) .get(); - doc.getProperties().clear(); + doc.removeAttribute("a"); doc.addAttribute("b", "test"); final VertexReplaceOptions options = new VertexReplaceOptions().ifMatch(createResult.getRev()); final VertexUpdateEntity replaceResult = db.graph(GRAPH_NAME).vertexCollection(COLLECTION_NAME) @@ -188,11 +189,11 @@ void replaceVertexIfMatch() throws InterruptedException, ExecutionException { @Test void replaceVertexIfMatchFail() throws InterruptedException, ExecutionException { - final BaseDocument doc = new BaseDocument(); + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); doc.addAttribute("a", "test"); final VertexEntity createResult = db.graph(GRAPH_NAME).vertexCollection(COLLECTION_NAME).insertVertex(doc, null) .get(); - doc.getProperties().clear(); + doc.removeAttribute("a"); doc.addAttribute("b", "test"); try { final VertexReplaceOptions options = new VertexReplaceOptions().ifMatch("no"); @@ -206,7 +207,7 @@ void replaceVertexIfMatchFail() throws InterruptedException, ExecutionException @Test void updateVertex() throws InterruptedException, ExecutionException { - final BaseDocument doc = new BaseDocument(); + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); doc.addAttribute("a", "test"); doc.addAttribute("c", "test"); final VertexEntity createResult = db.graph(GRAPH_NAME).vertexCollection(COLLECTION_NAME).insertVertex(doc, null) @@ -234,7 +235,7 @@ void updateVertex() throws InterruptedException, ExecutionException { @Test void updateVertexIfMatch() throws InterruptedException, ExecutionException { - final BaseDocument doc = new BaseDocument(); + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); doc.addAttribute("a", "test"); doc.addAttribute("c", "test"); final VertexEntity createResult = db.graph(GRAPH_NAME).vertexCollection(COLLECTION_NAME).insertVertex(doc, null) @@ -263,7 +264,7 @@ void updateVertexIfMatch() throws InterruptedException, ExecutionException { @Test void updateVertexIfMatchFail() throws InterruptedException, ExecutionException { - final BaseDocument doc = new BaseDocument(); + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); doc.addAttribute("a", "test"); doc.addAttribute("c", "test"); final VertexEntity createResult = db.graph(GRAPH_NAME).vertexCollection(COLLECTION_NAME).insertVertex(doc, null) @@ -283,7 +284,7 @@ void updateVertexIfMatchFail() throws InterruptedException, ExecutionException { @Test void updateVertexKeepNullTrue() throws InterruptedException, ExecutionException { - final BaseDocument doc = new BaseDocument(); + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); doc.addAttribute("a", "test"); final VertexEntity createResult = db.graph(GRAPH_NAME).vertexCollection(COLLECTION_NAME).insertVertex(doc, null) .get(); @@ -299,13 +300,13 @@ void updateVertexKeepNullTrue() throws InterruptedException, ExecutionException final BaseDocument readResult = db.graph(GRAPH_NAME).vertexCollection(COLLECTION_NAME) .getVertex(createResult.getKey(), BaseDocument.class, null).get(); assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); - assertThat(readResult.getProperties().keySet()).hasSize(1); + assertThat(readResult.getProperties().keySet()).hasSize(4); assertThat(readResult.getProperties()).containsKey("a"); } @Test void updateVertexKeepNullFalse() throws InterruptedException, ExecutionException { - final BaseDocument doc = new BaseDocument(); + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); doc.addAttribute("a", "test"); final VertexEntity createResult = db.graph(GRAPH_NAME).vertexCollection(COLLECTION_NAME).insertVertex(doc, null) .get(); @@ -328,7 +329,7 @@ void updateVertexKeepNullFalse() throws InterruptedException, ExecutionException @Test void deleteVertex() throws InterruptedException, ExecutionException { - final BaseDocument doc = new BaseDocument(); + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); final VertexEntity createResult = db.graph(GRAPH_NAME).vertexCollection(COLLECTION_NAME).insertVertex(doc, null) .get(); db.graph(GRAPH_NAME).vertexCollection(COLLECTION_NAME).deleteVertex(createResult.getKey(), null).get(); @@ -343,7 +344,7 @@ void deleteVertex() throws InterruptedException, ExecutionException { @Test void deleteVertexIfMatch() throws InterruptedException, ExecutionException { - final BaseDocument doc = new BaseDocument(); + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); final VertexEntity createResult = db.graph(GRAPH_NAME).vertexCollection(COLLECTION_NAME).insertVertex(doc, null) .get(); final VertexDeleteOptions options = new VertexDeleteOptions().ifMatch(createResult.getRev()); @@ -359,7 +360,7 @@ void deleteVertexIfMatch() throws InterruptedException, ExecutionException { @Test void deleteVertexIfMatchFail() throws InterruptedException, ExecutionException { - final BaseDocument doc = new BaseDocument(); + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); final VertexEntity createResult = db.graph(GRAPH_NAME).vertexCollection(COLLECTION_NAME).insertVertex(doc, null) .get(); final VertexDeleteOptions options = new VertexDeleteOptions().ifMatch("no"); diff --git a/src/test/java/com/arangodb/async/StreamTransactionGraphTest.java b/src/test/java/com/arangodb/async/StreamTransactionGraphTest.java index cb62b8f8f..0083e4802 100644 --- a/src/test/java/com/arangodb/async/StreamTransactionGraphTest.java +++ b/src/test/java/com/arangodb/async/StreamTransactionGraphTest.java @@ -42,6 +42,7 @@ import org.junit.jupiter.api.Test; import java.util.Collections; +import java.util.UUID; import java.util.concurrent.ExecutionException; import static org.assertj.core.api.Assertions.assertThat; @@ -153,7 +154,7 @@ void replaceVertex() throws ExecutionException, InterruptedException { assumeTrue(isAtLeastVersion(3, 5)); assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); - BaseDocument doc = new BaseDocument(); + BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); doc.addAttribute("test", "foo"); VertexEntity createdVertex = vertexCollection1.insertVertex(doc, null).get(); @@ -164,8 +165,7 @@ void replaceVertex() throws ExecutionException, InterruptedException { .writeCollections(VERTEX_COLLECTION_1, VERTEX_COLLECTION_2, EDGE_COLLECTION)).get(); // replace vertex from within the tx - doc.getProperties().clear(); - doc.addAttribute("test", "bar"); + doc.updateAttribute("test", "bar"); vertexCollection1.replaceVertex(createdVertex.getKey(), doc, new VertexReplaceOptions().streamTransactionId(tx.getId())).get(); @@ -190,7 +190,7 @@ void updateVertex() throws ExecutionException, InterruptedException { assumeTrue(isAtLeastVersion(3, 5)); assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); - BaseDocument doc = new BaseDocument(); + BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); doc.addAttribute("test", "foo"); VertexEntity createdDoc = vertexCollection1.insertVertex(doc, null).get(); @@ -201,8 +201,7 @@ void updateVertex() throws ExecutionException, InterruptedException { .writeCollections(VERTEX_COLLECTION_1, VERTEX_COLLECTION_2, EDGE_COLLECTION)).get(); // update vertex from within the tx - doc.getProperties().clear(); - doc.addAttribute("test", "bar"); + doc.updateAttribute("test", "bar"); vertexCollection1.updateVertex(createdDoc.getKey(), doc, new VertexUpdateOptions().streamTransactionId(tx.getId())).get(); // assert that the vertex has not been updated from outside the tx @@ -316,8 +315,7 @@ void replaceEdge() throws ExecutionException, InterruptedException { .writeCollections(VERTEX_COLLECTION_1, VERTEX_COLLECTION_2, EDGE_COLLECTION)).get(); // replace edge from within the tx - doc.getProperties().clear(); - doc.addAttribute("test", "bar"); + doc.updateAttribute("test", "bar"); edgeCollection.replaceEdge(createdEdge.getKey(), doc, new EdgeReplaceOptions().streamTransactionId(tx.getId())).get(); @@ -353,8 +351,7 @@ void updateEdge() throws ExecutionException, InterruptedException { .writeCollections(VERTEX_COLLECTION_1, VERTEX_COLLECTION_2, EDGE_COLLECTION)).get(); // update edge from within the tx - doc.getProperties().clear(); - doc.addAttribute("test", "bar"); + doc.updateAttribute("test", "bar"); edgeCollection.updateEdge(createdDoc.getKey(), doc, new EdgeUpdateOptions().streamTransactionId(tx.getId())) .get(); diff --git a/src/test/java/com/arangodb/async/example/document/AqlQueryWithSpecialReturnTypesExampleTest.java b/src/test/java/com/arangodb/async/example/document/AqlQueryWithSpecialReturnTypesExampleTest.java index b5e9b1f15..7358ae8ed 100644 --- a/src/test/java/com/arangodb/async/example/document/AqlQueryWithSpecialReturnTypesExampleTest.java +++ b/src/test/java/com/arangodb/async/example/document/AqlQueryWithSpecialReturnTypesExampleTest.java @@ -30,6 +30,7 @@ import java.util.Collections; import java.util.List; import java.util.Map; +import java.util.UUID; import java.util.concurrent.ExecutionException; import static org.assertj.core.api.Assertions.assertThat; @@ -47,7 +48,7 @@ static void before() throws InterruptedException, ExecutionException { private static void createExamples() throws InterruptedException, ExecutionException { for (int i = 0; i < 100; i++) { - final BaseDocument value = new BaseDocument(); + final BaseDocument value = new BaseDocument(UUID.randomUUID().toString()); value.addAttribute("name", "TestUser" + i); value.addAttribute("gender", (i % 2) == 0 ? Gender.MALE : Gender.FEMALE); value.addAttribute("age", i + 10); diff --git a/src/test/java/com/arangodb/async/example/document/GetDocumentExampleTest.java b/src/test/java/com/arangodb/async/example/document/GetDocumentExampleTest.java index 835017668..6251385a8 100644 --- a/src/test/java/com/arangodb/async/example/document/GetDocumentExampleTest.java +++ b/src/test/java/com/arangodb/async/example/document/GetDocumentExampleTest.java @@ -29,6 +29,7 @@ import org.junit.jupiter.api.Test; +import java.util.UUID; import java.util.concurrent.ExecutionException; import static org.assertj.core.api.Assertions.assertThat; @@ -43,7 +44,7 @@ class GetDocumentExampleTest extends ExampleBase { @BeforeAll static void before() throws InterruptedException, ExecutionException { - final BaseDocument value = new BaseDocument(); + final BaseDocument value = new BaseDocument(UUID.randomUUID().toString()); value.addAttribute("foo", "bar"); final DocumentCreateEntity doc = collection.insertDocument(value).get(); key = doc.getKey(); diff --git a/src/test/java/com/arangodb/async/example/document/InsertDocumentExampleTest.java b/src/test/java/com/arangodb/async/example/document/InsertDocumentExampleTest.java index be3a2a1da..e55eda546 100644 --- a/src/test/java/com/arangodb/async/example/document/InsertDocumentExampleTest.java +++ b/src/test/java/com/arangodb/async/example/document/InsertDocumentExampleTest.java @@ -27,6 +27,7 @@ import com.fasterxml.jackson.databind.node.ObjectNode; import org.junit.jupiter.api.Test; +import java.util.UUID; import java.util.concurrent.ExecutionException; import static org.assertj.core.api.Assertions.assertThat; @@ -46,7 +47,7 @@ void insertBean() throws ExecutionException, InterruptedException { @Test void insertBaseDocument() throws ExecutionException, InterruptedException { - final BaseDocument value = new BaseDocument(); + final BaseDocument value = new BaseDocument(UUID.randomUUID().toString()); value.addAttribute("foo", "bar"); collection.insertDocument(value) .whenComplete((doc, ex) -> assertThat(doc.getKey()).isNotNull()) diff --git a/src/test/java/com/arangodb/async/example/graph/AQLActorsAndMoviesExampleTest.java b/src/test/java/com/arangodb/async/example/graph/AQLActorsAndMoviesExampleTest.java index 88bbfb425..0b5fbb50a 100644 --- a/src/test/java/com/arangodb/async/example/graph/AQLActorsAndMoviesExampleTest.java +++ b/src/test/java/com/arangodb/async/example/graph/AQLActorsAndMoviesExampleTest.java @@ -36,6 +36,7 @@ import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; +import java.util.UUID; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; @@ -77,7 +78,7 @@ private static DocumentCreateEntity saveMovie( final String title, final int released, final String tagline) throws InterruptedException, ExecutionException { - final BaseDocument value = new BaseDocument(); + final BaseDocument value = new BaseDocument(UUID.randomUUID().toString()); value.setKey(key); value.addAttribute("title", title); value.addAttribute("released", released); @@ -90,7 +91,7 @@ private static DocumentCreateEntity saveActor( final String key, final String name, final int born) throws InterruptedException, ExecutionException { - final BaseDocument value = new BaseDocument(); + final BaseDocument value = new BaseDocument(UUID.randomUUID().toString()); value.setKey(key); value.addAttribute("name", name); value.addAttribute("born", born); diff --git a/src/test/java/com/arangodb/example/FirstProject.java b/src/test/java/com/arangodb/example/FirstProject.java index ca1db29d4..9cda94573 100644 --- a/src/test/java/com/arangodb/example/FirstProject.java +++ b/src/test/java/com/arangodb/example/FirstProject.java @@ -7,6 +7,7 @@ import java.util.Collections; import java.util.Map; +import java.util.UUID; public class FirstProject { @@ -32,7 +33,7 @@ public static void main(final String[] args) { } // creating a document - final BaseDocument myObject = new BaseDocument(); + final BaseDocument myObject = new BaseDocument(UUID.randomUUID().toString()); myObject.setKey("myKey"); myObject.addAttribute("a", "Foo"); myObject.addAttribute("b", 42); @@ -95,7 +96,7 @@ public static void main(final String[] args) { // create some documents for the next step final ArangoCollection collection = arangoDB.db(dbName).collection(collectionName); for (int i = 0; i < 10; i++) { - final BaseDocument value = new BaseDocument(); + final BaseDocument value = new BaseDocument(UUID.randomUUID().toString()); value.setKey(String.valueOf(i)); value.addAttribute("name", "Homer"); collection.insertDocument(value); diff --git a/src/test/java/com/arangodb/example/document/AqlQueryWithSpecialReturnTypesExampleTest.java b/src/test/java/com/arangodb/example/document/AqlQueryWithSpecialReturnTypesExampleTest.java index f820cdd09..c55ab5ed0 100644 --- a/src/test/java/com/arangodb/example/document/AqlQueryWithSpecialReturnTypesExampleTest.java +++ b/src/test/java/com/arangodb/example/document/AqlQueryWithSpecialReturnTypesExampleTest.java @@ -31,6 +31,7 @@ import java.util.Collections; import java.util.List; import java.util.Map; +import java.util.UUID; import static org.assertj.core.api.Assertions.assertThat; @@ -51,7 +52,7 @@ enum Gender { private static void createExamples() { for (int i = 0; i < 100; i++) { - final BaseDocument value = new BaseDocument(); + final BaseDocument value = new BaseDocument(UUID.randomUUID().toString()); value.addAttribute("name", "TestUser" + i); value.addAttribute("gender", (i % 2) == 0 ? Gender.MALE : Gender.FEMALE); value.addAttribute("age", i + 10); diff --git a/src/test/java/com/arangodb/example/document/GetDocumentExampleTest.java b/src/test/java/com/arangodb/example/document/GetDocumentExampleTest.java index 51cd6f9f3..21885281f 100644 --- a/src/test/java/com/arangodb/example/document/GetDocumentExampleTest.java +++ b/src/test/java/com/arangodb/example/document/GetDocumentExampleTest.java @@ -30,6 +30,7 @@ import org.junit.jupiter.api.Test; import java.util.Map; +import java.util.UUID; import static org.assertj.core.api.Assertions.assertThat; @@ -43,7 +44,7 @@ class GetDocumentExampleTest extends ExampleBase { @BeforeAll static void before() { - final BaseDocument value = new BaseDocument(); + final BaseDocument value = new BaseDocument(UUID.randomUUID().toString()); value.addAttribute("foo", "bar"); final DocumentCreateEntity doc = collection.insertDocument(value); key = doc.getKey(); diff --git a/src/test/java/com/arangodb/example/document/InsertDocumentExampleTest.java b/src/test/java/com/arangodb/example/document/InsertDocumentExampleTest.java index e12949537..1594b4f91 100644 --- a/src/test/java/com/arangodb/example/document/InsertDocumentExampleTest.java +++ b/src/test/java/com/arangodb/example/document/InsertDocumentExampleTest.java @@ -29,6 +29,8 @@ import com.fasterxml.jackson.databind.node.ObjectNode; import org.junit.jupiter.api.Test; +import java.util.UUID; + import static org.assertj.core.api.Assertions.assertThat; @@ -45,7 +47,7 @@ void insertBean() { @Test void insertBaseDocument() { - final BaseDocument value = new BaseDocument(); + final BaseDocument value = new BaseDocument(UUID.randomUUID().toString()); value.addAttribute("foo", "bar"); final DocumentCreateEntity doc = collection.insertDocument(value); assertThat(doc.getKey()).isNotNull(); diff --git a/src/test/java/com/arangodb/example/graph/AQLActorsAndMoviesExampleTest.java b/src/test/java/com/arangodb/example/graph/AQLActorsAndMoviesExampleTest.java index 0bd9b57a3..cf8f67ddc 100644 --- a/src/test/java/com/arangodb/example/graph/AQLActorsAndMoviesExampleTest.java +++ b/src/test/java/com/arangodb/example/graph/AQLActorsAndMoviesExampleTest.java @@ -32,6 +32,8 @@ import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; +import java.util.UUID; + import static org.assertj.core.api.Assertions.assertThat; @@ -317,7 +319,7 @@ private static DocumentCreateEntity saveMovie( final String title, final int released, final String tagline) { - final BaseDocument value = new BaseDocument(); + final BaseDocument value = new BaseDocument(UUID.randomUUID().toString()); value.setKey(key); value.addAttribute("title", title); value.addAttribute("released", released); @@ -330,7 +332,7 @@ private static DocumentCreateEntity saveActor( final String key, final String name, final int born) { - final BaseDocument value = new BaseDocument(); + final BaseDocument value = new BaseDocument(UUID.randomUUID().toString()); value.setKey(key); value.addAttribute("name", name); value.addAttribute("born", born); diff --git a/src/test/resources/logback-test.xml b/src/test/resources/logback-test.xml index f67855e9c..579f1b9db 100644 --- a/src/test/resources/logback-test.xml +++ b/src/test/resources/logback-test.xml @@ -8,7 +8,7 @@ - + From f0e33cf5b773848f8ac45e9e1e7d1da738be10b3 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Tue, 2 Aug 2022 16:09:36 +0200 Subject: [PATCH 069/254] fixed (de)serialize null user data --- src/main/java/com/arangodb/ArangoSerdeAccessor.java | 8 -------- .../java/com/arangodb/internal/ArangoExecuteable.java | 6 ------ src/main/java/com/arangodb/serde/InternalSerdeImpl.java | 9 ++++++--- src/test/java/com/arangodb/serde/CustomSerdeTest.java | 8 ++++---- 4 files changed, 10 insertions(+), 21 deletions(-) diff --git a/src/main/java/com/arangodb/ArangoSerdeAccessor.java b/src/main/java/com/arangodb/ArangoSerdeAccessor.java index c3075a1b4..e00c86204 100644 --- a/src/main/java/com/arangodb/ArangoSerdeAccessor.java +++ b/src/main/java/com/arangodb/ArangoSerdeAccessor.java @@ -20,7 +20,6 @@ package com.arangodb; -import com.arangodb.serde.ArangoSerde; import com.arangodb.serde.InternalSerde; /** @@ -35,11 +34,4 @@ public interface ArangoSerdeAccessor { */ InternalSerde getSerde(); - /** - * Returns serialization implementation for serializing and deserializing user's classes. - * - * @return ArangoSerde - */ - ArangoSerde getUserSerde(); - } diff --git a/src/main/java/com/arangodb/internal/ArangoExecuteable.java b/src/main/java/com/arangodb/internal/ArangoExecuteable.java index e56d0bc51..24b52a45d 100644 --- a/src/main/java/com/arangodb/internal/ArangoExecuteable.java +++ b/src/main/java/com/arangodb/internal/ArangoExecuteable.java @@ -23,7 +23,6 @@ import com.arangodb.ArangoSerdeAccessor; import com.arangodb.DbName; import com.arangodb.internal.util.EncodeUtils; -import com.arangodb.serde.ArangoSerde; import com.arangodb.serde.InternalSerde; import com.arangodb.velocystream.Request; import com.arangodb.velocystream.RequestType; @@ -57,11 +56,6 @@ public InternalSerde getSerde() { return serde; } - @Override - public ArangoSerde getUserSerde() { - return serde.getUserSerde(); - } - protected Request request(final DbName dbName, final RequestType requestType, final String... path) { final Request request = new Request(dbName, requestType, createPath(path)); for (final Entry header : context.getHeaderParam().entrySet()) { diff --git a/src/main/java/com/arangodb/serde/InternalSerdeImpl.java b/src/main/java/com/arangodb/serde/InternalSerdeImpl.java index 2922c6544..dcf63af8e 100644 --- a/src/main/java/com/arangodb/serde/InternalSerdeImpl.java +++ b/src/main/java/com/arangodb/serde/InternalSerdeImpl.java @@ -72,9 +72,12 @@ public JsonNode parse(byte[] content, String jsonPointer) { @Override public byte[] serializeUserData(Object value) { + if (value == null) { + return serialize(null); + } Class clazz = value.getClass(); - if ( RawJson.class.equals(clazz) || - RawBytes.class.equals(clazz) || + if (RawJson.class.isAssignableFrom(clazz) || + RawBytes.class.isAssignableFrom(clazz) || JsonNode.class.isAssignableFrom(clazz) || BaseDocument.class.isAssignableFrom(clazz) ) { @@ -95,7 +98,7 @@ public byte[] serializeCollectionUserData(Collection value) { @Override public T deserializeUserData(byte[] content, Class clazz) { - if ( RawJson.class.isAssignableFrom(clazz) || + if (RawJson.class.isAssignableFrom(clazz) || RawBytes.class.isAssignableFrom(clazz) || JsonNode.class.isAssignableFrom(clazz) || BaseDocument.class.isAssignableFrom(clazz) diff --git a/src/test/java/com/arangodb/serde/CustomSerdeTest.java b/src/test/java/com/arangodb/serde/CustomSerdeTest.java index 04bf68b74..ae2cd1e6e 100644 --- a/src/test/java/com/arangodb/serde/CustomSerdeTest.java +++ b/src/test/java/com/arangodb/serde/CustomSerdeTest.java @@ -131,9 +131,9 @@ void customPersonDeserializer() { void manualCustomPersonDeserializer() { Person person = new Person(); person.name = "Joe"; - ArangoSerde serialization = arangoDB.getUserSerde(); - byte[] serialized = serialization.serialize(person); - Person deserializedPerson = serialization.deserialize(serialized, Person.class); + InternalSerde serialization = arangoDB.getSerde(); + byte[] serialized = serialization.serializeUserData(person); + Person deserializedPerson = serialization.deserializeUserData(serialized, Person.class); assertThat(deserializedPerson.name).isEqualTo(PERSON_DESERIALIZER_ADDED_PREFIX + PERSON_SERIALIZER_ADDED_PREFIX + person.name); } @@ -229,7 +229,7 @@ void getDocument() { @Test void parseNullString() { - final String json = arangoDB.getUserSerde().deserialize(arangoDB.getUserSerde().serialize(null), String.class); + final String json = arangoDB.getSerde().deserializeUserData(arangoDB.getSerde().serializeUserData(null), String.class); assertThat(json).isNull(); } From 364604972e3646480f9ade9a990f1833c793f86d Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Tue, 2 Aug 2022 20:42:48 +0200 Subject: [PATCH 070/254] removed --allow-incomplete-classpath from native image configuration --- .../arangodb-java-driver/native-image.properties | 1 - .../resources/META-INF/native-image/reflect-config.json | 9 +++++++++ src/test/resources/logback-test.xml | 2 +- 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/main/resources/META-INF/native-image/com.arangodb/arangodb-java-driver/native-image.properties b/src/main/resources/META-INF/native-image/com.arangodb/arangodb-java-driver/native-image.properties index 20f45594f..c4b6a9e8f 100644 --- a/src/main/resources/META-INF/native-image/com.arangodb/arangodb-java-driver/native-image.properties +++ b/src/main/resources/META-INF/native-image/com.arangodb/arangodb-java-driver/native-image.properties @@ -1,3 +1,2 @@ Args= -H:ReflectionConfigurationResources=${.}/reflect-config.json,${.}/http-reflect-config.json \ - --allow-incomplete-classpath \ --initialize-at-run-time=org.apache.http.impl.auth.NTLMEngineImpl,org.apache.http.conn.ssl.SSLConnectionSocketFactory diff --git a/src/test/resources/META-INF/native-image/reflect-config.json b/src/test/resources/META-INF/native-image/reflect-config.json index a7c217b64..a71ddaf2c 100644 --- a/src/test/resources/META-INF/native-image/reflect-config.json +++ b/src/test/resources/META-INF/native-image/reflect-config.json @@ -1,4 +1,13 @@ [ + { + "name": "org.junit.jupiter.engine.extension.TimeoutInvocationFactory$SingleThreadExecutorResource", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + }, { "name": "ch.qos.logback.classic.encoder.PatternLayoutEncoder", "allPublicMethods": true, diff --git a/src/test/resources/logback-test.xml b/src/test/resources/logback-test.xml index 579f1b9db..f67855e9c 100644 --- a/src/test/resources/logback-test.xml +++ b/src/test/resources/logback-test.xml @@ -8,7 +8,7 @@ - + From 4bc5ced99c0812f6202c6cd0abaa016aa9d87ca3 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Wed, 3 Aug 2022 10:15:46 +0200 Subject: [PATCH 071/254] code cleanup --- src/main/java/com/arangodb/entity/ReplicationFactor.java | 2 +- .../arangodb/internal/cursor/entity/InternalCursorEntity.java | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/arangodb/entity/ReplicationFactor.java b/src/main/java/com/arangodb/entity/ReplicationFactor.java index 853aad4bb..f4278e972 100644 --- a/src/main/java/com/arangodb/entity/ReplicationFactor.java +++ b/src/main/java/com/arangodb/entity/ReplicationFactor.java @@ -37,7 +37,7 @@ static SatelliteReplicationFactor ofSatellite() { final class NumericReplicationFactor implements ReplicationFactor { - private Integer value; + private final Integer value; public NumericReplicationFactor(Integer value) { this.value = value; diff --git a/src/main/java/com/arangodb/internal/cursor/entity/InternalCursorEntity.java b/src/main/java/com/arangodb/internal/cursor/entity/InternalCursorEntity.java index 56f428f67..97d461116 100644 --- a/src/main/java/com/arangodb/internal/cursor/entity/InternalCursorEntity.java +++ b/src/main/java/com/arangodb/internal/cursor/entity/InternalCursorEntity.java @@ -38,7 +38,7 @@ public final class InternalCursorEntity implements MetaAware { private String id; private Integer count; - private Extras extra = new Extras(); + private final Extras extra = new Extras(); private Boolean cached; private Boolean hasMore; private JsonNode result; @@ -110,7 +110,7 @@ public void setMeta(Map meta) { public static final class Extras { private CursorStats stats; - private Collection warnings = Collections.emptyList(); + private final Collection warnings = Collections.emptyList(); public CursorStats getStats() { return stats; From 0e45426c5c4c672dff7d54c53210aebb05d14dbf Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Wed, 10 Aug 2022 11:59:22 +0200 Subject: [PATCH 072/254] removed unecessary deserializers --- .../internal/ArangoCollectionAsyncImpl.java | 25 ++++++---- .../internal/ArangoDatabaseAsyncImpl.java | 6 ++- .../internal/ArangoCollectionImpl.java | 22 ++++++--- .../arangodb/internal/ArangoDatabaseImpl.java | 6 ++- .../internal/InternalArangoCollection.java | 49 ++++--------------- .../arangodb/internal/InternalArangoDB.java | 6 ++- .../internal/InternalArangoDatabase.java | 14 +++--- .../internal/InternalArangoGraph.java | 6 ++- .../internal/net/ExtendedHostResolver.java | 6 ++- .../arangodb/serde/InternalDeserializers.java | 1 + .../com/arangodb/serde/InternalSerdeImpl.java | 5 +- .../java/com/arangodb/serde/SerdeUtils.java | 13 ++--- .../arangodb/serde/UserDataDeserializer.java | 4 +- 13 files changed, 79 insertions(+), 84 deletions(-) diff --git a/src/main/java/com/arangodb/async/internal/ArangoCollectionAsyncImpl.java b/src/main/java/com/arangodb/async/internal/ArangoCollectionAsyncImpl.java index 7f444ad9e..90c9bfab0 100644 --- a/src/main/java/com/arangodb/async/internal/ArangoCollectionAsyncImpl.java +++ b/src/main/java/com/arangodb/async/internal/ArangoCollectionAsyncImpl.java @@ -31,6 +31,8 @@ import java.util.Objects; import java.util.concurrent.CompletableFuture; +import static com.arangodb.serde.SerdeUtils.constructParametricType; + /** * @author Mark Vollmary * @author Michele Rastelli @@ -47,7 +49,7 @@ public class ArangoCollectionAsyncImpl public CompletableFuture> insertDocument(final T value) { final DocumentCreateOptions options = new DocumentCreateOptions(); return executor.execute(insertDocumentRequest(value, options), - insertDocumentResponseDeserializer(value, options)); + constructParametricType(DocumentCreateEntity.class, value.getClass())); } @Override @@ -55,7 +57,7 @@ public CompletableFuture> insertDocument( final T value, final DocumentCreateOptions options) { return executor.execute(insertDocumentRequest(value, options), - insertDocumentResponseDeserializer(value, options)); + constructParametricType(DocumentCreateEntity.class, value.getClass())); } @Override @@ -135,7 +137,7 @@ public CompletableFuture> getDocuments( public CompletableFuture> replaceDocument(final String key, final T value) { final DocumentReplaceOptions options = new DocumentReplaceOptions(); return executor.execute(replaceDocumentRequest(key, value, options), - replaceDocumentResponseDeserializer(value, options)); + constructParametricType(DocumentUpdateEntity.class, value.getClass())); } @Override @@ -144,7 +146,7 @@ public CompletableFuture> replaceDocument( final T value, final DocumentReplaceOptions options) { return executor.execute(replaceDocumentRequest(key, value, options), - replaceDocumentResponseDeserializer(value, options)); + constructParametricType(DocumentUpdateEntity.class, value.getClass())); } @Override @@ -152,7 +154,7 @@ public CompletableFuture>> repla final Collection values) { final DocumentReplaceOptions params = new DocumentReplaceOptions(); return executor.execute(replaceDocumentsRequest(values, params), - replaceDocumentsResponseDeserializer(values, params)); + replaceDocumentsResponseDeserializer(values)); } @Override @@ -161,7 +163,7 @@ public CompletableFuture>> repla final DocumentReplaceOptions options) { final DocumentReplaceOptions params = (options != null ? options : new DocumentReplaceOptions()); return executor.execute(replaceDocumentsRequest(values, params), - replaceDocumentsResponseDeserializer(values, params)); + replaceDocumentsResponseDeserializer(values)); } @Override @@ -170,6 +172,7 @@ public CompletableFuture> updateDocument(final Strin } @Override + @SuppressWarnings("unchecked") public CompletableFuture> updateDocument( final String key, final T value, @@ -184,7 +187,7 @@ public CompletableFuture> updateDocument( final DocumentUpdateOptions options, final Class returnType) { return executor.execute(updateDocumentRequest(key, value, options), - updateDocumentResponseDeserializer(value, options, returnType)); + constructParametricType(DocumentUpdateEntity.class, returnType)); } @Override @@ -194,10 +197,11 @@ public CompletableFuture>> updat } @Override + @SuppressWarnings("unchecked") public CompletableFuture>> updateDocuments( final Collection values, final DocumentUpdateOptions options) { - return updateDocuments(values, options, values.isEmpty() ? null : (Class) values.iterator().next().getClass()); + return updateDocuments(values, options, values.isEmpty() ? null : (Class) getCollectionContentClass(values)); } @Override @@ -213,7 +217,7 @@ public CompletableFuture>> up @Override public CompletableFuture> deleteDocument(final String key) { return executor.execute(deleteDocumentRequest(key, new DocumentDeleteOptions()), - deleteDocumentResponseDeserializer(Void.class)); + constructParametricType(DocumentDeleteEntity.class, Void.class)); } @Override @@ -221,7 +225,8 @@ public CompletableFuture> deleteDocument( final String key, final Class type, final DocumentDeleteOptions options) { - return executor.execute(deleteDocumentRequest(key, options), deleteDocumentResponseDeserializer(type)); + return executor.execute(deleteDocumentRequest(key, options), + constructParametricType(DocumentDeleteEntity.class, type)); } @Override diff --git a/src/main/java/com/arangodb/async/internal/ArangoDatabaseAsyncImpl.java b/src/main/java/com/arangodb/async/internal/ArangoDatabaseAsyncImpl.java index 0e390e736..24598853f 100644 --- a/src/main/java/com/arangodb/async/internal/ArangoDatabaseAsyncImpl.java +++ b/src/main/java/com/arangodb/async/internal/ArangoDatabaseAsyncImpl.java @@ -44,6 +44,8 @@ import java.util.concurrent.CompletionException; import java.util.concurrent.ExecutionException; +import static com.arangodb.serde.SerdeUtils.constructListType; + /** * @author Mark Vollmary * @author Michele Rastelli @@ -282,13 +284,13 @@ public CompletableFuture setQueryTrackingProperti @Override public CompletableFuture> getCurrentlyRunningQueries() { return executor.execute(getCurrentlyRunningQueriesRequest(), - SerdeUtils.INSTANCE.constructListType(QueryEntity.class)); + constructListType(QueryEntity.class)); } @Override public CompletableFuture> getSlowQueries() { return executor.execute(getSlowQueriesRequest(), - SerdeUtils.INSTANCE.constructListType(QueryEntity.class)); + constructListType(QueryEntity.class)); } @Override diff --git a/src/main/java/com/arangodb/internal/ArangoCollectionImpl.java b/src/main/java/com/arangodb/internal/ArangoCollectionImpl.java index a97bd4955..625182c86 100644 --- a/src/main/java/com/arangodb/internal/ArangoCollectionImpl.java +++ b/src/main/java/com/arangodb/internal/ArangoCollectionImpl.java @@ -25,11 +25,14 @@ import com.arangodb.entity.*; import com.arangodb.internal.util.DocumentUtil; import com.arangodb.model.*; +import com.arangodb.serde.SerdeUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.Collection; +import static com.arangodb.serde.SerdeUtils.constructParametricType; + /** * @author Mark Vollmary * @author Michele Rastelli @@ -51,8 +54,8 @@ public DocumentCreateEntity insertDocument(final T value) throws ArangoDB @Override public DocumentCreateEntity insertDocument(final T value, final DocumentCreateOptions options) throws ArangoDBException { - return executor - .execute(insertDocumentRequest(value, options), insertDocumentResponseDeserializer(value, options)); + return executor.execute(insertDocumentRequest(value, options), + constructParametricType(DocumentCreateEntity.class, value.getClass())); } @Override @@ -142,7 +145,7 @@ public DocumentUpdateEntity replaceDocument(final String key, final T val public DocumentUpdateEntity replaceDocument( final String key, final T value, final DocumentReplaceOptions options) throws ArangoDBException { return executor.execute(replaceDocumentRequest(key, value, options), - replaceDocumentResponseDeserializer(value, options)); + constructParametricType(DocumentUpdateEntity.class, value.getClass())); } @Override @@ -156,7 +159,7 @@ public MultiDocumentEntity> replaceDocuments( final Collection values, final DocumentReplaceOptions options) throws ArangoDBException { final DocumentReplaceOptions params = (options != null ? options : new DocumentReplaceOptions()); return executor - .execute(replaceDocumentsRequest(values, params), replaceDocumentsResponseDeserializer(values, params)); + .execute(replaceDocumentsRequest(values, params), replaceDocumentsResponseDeserializer(values)); } @Override @@ -165,6 +168,7 @@ public DocumentUpdateEntity updateDocument(final String key, final T valu } @Override + @SuppressWarnings("unchecked") public DocumentUpdateEntity updateDocument( final String key, final T value, final DocumentUpdateOptions options) throws ArangoDBException { return updateDocument(key, value, options, (Class) value.getClass()); @@ -174,7 +178,7 @@ public DocumentUpdateEntity updateDocument( public DocumentUpdateEntity updateDocument( final String key, final T value, final DocumentUpdateOptions options, final Class returnType) throws ArangoDBException { return executor.execute(updateDocumentRequest(key, value, options), - updateDocumentResponseDeserializer(value, options, returnType)); + constructParametricType(DocumentUpdateEntity.class, returnType)); } @Override @@ -184,9 +188,10 @@ public MultiDocumentEntity> updateDocuments(final Co } @Override + @SuppressWarnings("unchecked") public MultiDocumentEntity> updateDocuments( final Collection values, final DocumentUpdateOptions options) throws ArangoDBException { - return updateDocuments(values, options, values.isEmpty() ? null : (Class) values.iterator().next().getClass()); + return updateDocuments(values, options, values.isEmpty() ? null : (Class) getCollectionContentClass(values)); } @Override @@ -200,13 +205,14 @@ public MultiDocumentEntity> updateDocuments( @Override public DocumentDeleteEntity deleteDocument(final String key) throws ArangoDBException { return executor.execute(deleteDocumentRequest(key, new DocumentDeleteOptions()), - deleteDocumentResponseDeserializer(Void.class)); + constructParametricType(DocumentDeleteEntity.class, Void.class)); } @Override public DocumentDeleteEntity deleteDocument( final String key, final Class type, final DocumentDeleteOptions options) throws ArangoDBException { - return executor.execute(deleteDocumentRequest(key, options), deleteDocumentResponseDeserializer(type)); + return executor.execute(deleteDocumentRequest(key, options), + constructParametricType(DocumentDeleteEntity.class, type)); } @Override diff --git a/src/main/java/com/arangodb/internal/ArangoDatabaseImpl.java b/src/main/java/com/arangodb/internal/ArangoDatabaseImpl.java index f02e8c516..5f2cab658 100644 --- a/src/main/java/com/arangodb/internal/ArangoDatabaseImpl.java +++ b/src/main/java/com/arangodb/internal/ArangoDatabaseImpl.java @@ -38,6 +38,8 @@ import java.util.Collections; import java.util.Map; +import static com.arangodb.serde.SerdeUtils.constructListType; + /** * @author Mark Vollmary * @author Michele Rastelli @@ -264,13 +266,13 @@ public QueryTrackingPropertiesEntity setQueryTrackingProperties(final QueryTrack @Override public Collection getCurrentlyRunningQueries() throws ArangoDBException { return executor.execute(getCurrentlyRunningQueriesRequest(), - SerdeUtils.INSTANCE.constructListType(QueryEntity.class)); + constructListType(QueryEntity.class)); } @Override public Collection getSlowQueries() throws ArangoDBException { return executor.execute(getSlowQueriesRequest(), - SerdeUtils.INSTANCE.constructListType(QueryEntity.class)); + constructListType(QueryEntity.class)); } @Override diff --git a/src/main/java/com/arangodb/internal/InternalArangoCollection.java b/src/main/java/com/arangodb/internal/InternalArangoCollection.java index e9ed2a026..0a46a5c12 100644 --- a/src/main/java/com/arangodb/internal/InternalArangoCollection.java +++ b/src/main/java/com/arangodb/internal/InternalArangoCollection.java @@ -35,6 +35,9 @@ import java.lang.reflect.Type; import java.util.*; +import static com.arangodb.serde.SerdeUtils.constructListType; +import static com.arangodb.serde.SerdeUtils.constructParametricType; + /** * @author Mark Vollmary * @author Michele Rastelli @@ -93,14 +96,6 @@ protected Request insertDocumentRequest(final T value, final DocumentCreateO return request; } - protected ResponseDeserializer> insertDocumentResponseDeserializer( - final T value, final DocumentCreateOptions options) { - return response -> { - Type type = SerdeUtils.INSTANCE.constructParametricType(DocumentCreateEntity.class, value.getClass()); - return getSerde().deserialize(response.getBody(), type); - }; - } - protected Request insertDocumentsRequest(final Collection values, final DocumentCreateOptions params) { final Request request = request(db.dbName(), RequestType.POST, PATH_API_DOCUMENT, name); request.putQueryParam(ArangoRequestParam.WAIT_FOR_SYNC, params.getWaitForSync()); @@ -130,7 +125,7 @@ protected ResponseDeserializer>> errors.add(error); documentsAndErrors.add(error); } else { - Type type = SerdeUtils.INSTANCE.constructParametricType(DocumentCreateEntity.class, userDataClass); + Type type = constructParametricType(DocumentCreateEntity.class, userDataClass); final DocumentCreateEntity doc = getSerde().deserialize(next, type); docs.add(doc); documentsAndErrors.add(doc); @@ -234,14 +229,6 @@ protected Request replaceDocumentRequest( return request; } - protected ResponseDeserializer> replaceDocumentResponseDeserializer( - final T value, final DocumentReplaceOptions options) { - return response -> { - Type type = SerdeUtils.INSTANCE.constructParametricType(DocumentUpdateEntity.class, value.getClass()); - return getSerde().deserialize(response.getBody(), type); - }; - } - protected Request replaceDocumentsRequest(final Collection values, final DocumentReplaceOptions params) { final Request request = request(db.dbName(), RequestType.PUT, PATH_API_DOCUMENT, name); request.putHeaderParam(ArangoRequestParam.IF_MATCH, params.getIfMatch()); @@ -256,7 +243,7 @@ protected Request replaceDocumentsRequest(final Collection values, final } protected ResponseDeserializer>> replaceDocumentsResponseDeserializer( - final Collection values, final DocumentReplaceOptions params) { + final Collection values) { return response -> { Class userDataClass = getCollectionContentClass(values); final MultiDocumentEntity> multiDocument = new MultiDocumentEntity<>(); @@ -271,7 +258,7 @@ protected ResponseDeserializer>> errors.add(error); documentsAndErrors.add(error); } else { - Type type = SerdeUtils.INSTANCE.constructParametricType(DocumentUpdateEntity.class, userDataClass); + Type type = constructParametricType(DocumentUpdateEntity.class, userDataClass); final DocumentUpdateEntity doc = getSerde().deserialize(next, type); docs.add(doc); documentsAndErrors.add(doc); @@ -301,14 +288,6 @@ protected Request updateDocumentRequest(final String key, final T value, fin return request; } - protected ResponseDeserializer> updateDocumentResponseDeserializer( - final T value, final DocumentUpdateOptions options, final Class returnType) { - return response -> { - Type type = SerdeUtils.INSTANCE.constructParametricType(DocumentUpdateEntity.class, returnType); - return getSerde().deserialize(response.getBody(), type); - }; - } - protected Request updateDocumentsRequest(final Collection values, final DocumentUpdateOptions params) { final Request request = request(db.dbName(), RequestType.PATCH, PATH_API_DOCUMENT, name); final Boolean keepNull = params.getKeepNull(); @@ -340,7 +319,7 @@ protected ResponseDeserializer>> errors.add(error); documentsAndErrors.add(error); } else { - Type type = SerdeUtils.INSTANCE.constructParametricType(DocumentUpdateEntity.class, returnType); + Type type = constructParametricType(DocumentUpdateEntity.class, returnType); final DocumentUpdateEntity doc = getSerde().deserialize(next, type); docs.add(doc); documentsAndErrors.add(doc); @@ -365,14 +344,6 @@ protected Request deleteDocumentRequest(final String key, final DocumentDeleteOp return request; } - protected ResponseDeserializer> deleteDocumentResponseDeserializer( - final Class userDataClass) { - return response -> { - Type type = SerdeUtils.INSTANCE.constructParametricType(DocumentDeleteEntity.class, userDataClass); - return getSerde().deserialize(response.getBody(), type); - }; - } - protected Request deleteDocumentsRequest(final Collection keys, final DocumentDeleteOptions options) { final Request request = request(db.dbName(), RequestType.DELETE, PATH_API_DOCUMENT, name); final DocumentDeleteOptions params = (options != null ? options : new DocumentDeleteOptions()); @@ -399,7 +370,7 @@ protected ResponseDeserializer>> errors.add(error); documentsAndErrors.add(error); } else { - Type type = SerdeUtils.INSTANCE.constructParametricType(DocumentDeleteEntity.class, userDataClass); + Type type = constructParametricType(DocumentDeleteEntity.class, userDataClass); final DocumentDeleteEntity doc = getSerde().deserialize(next, type); docs.add(doc); documentsAndErrors.add(doc); @@ -514,7 +485,7 @@ protected Request getIndexesRequest() { protected ResponseDeserializer> getIndexesResponseDeserializer() { return response -> getSerde().deserialize(response.getBody(), "/indexes", - SerdeUtils.INSTANCE.constructListType(IndexEntity.class)); + constructListType(IndexEntity.class)); } protected Request truncateRequest(final CollectionTruncateOptions options) { @@ -584,7 +555,7 @@ protected ResponseDeserializer getPermissionsResponseDeserialzer() return response -> getSerde().deserialize(response.getBody(), ArangoResponseField.RESULT_JSON_POINTER, Permissions.class); } - private Class getCollectionContentClass(Collection c) { + protected Class getCollectionContentClass(Collection c) { if (c == null || c.isEmpty()) { return null; } diff --git a/src/main/java/com/arangodb/internal/InternalArangoDB.java b/src/main/java/com/arangodb/internal/InternalArangoDB.java index 862c4d90c..c8cbba05b 100644 --- a/src/main/java/com/arangodb/internal/InternalArangoDB.java +++ b/src/main/java/com/arangodb/internal/InternalArangoDB.java @@ -33,6 +33,8 @@ import java.util.Collection; import java.util.Iterator; +import static com.arangodb.serde.SerdeUtils.constructListType; + /** * @author Mark Vollmary * @author Heiko Kernbach @@ -84,7 +86,7 @@ protected Request getDatabasesRequest(final DbName dbName) { protected ResponseDeserializer> getDatabaseResponseDeserializer() { return response -> getSerde().deserialize(response.getBody(), ArangoResponseField.RESULT_JSON_POINTER, - SerdeUtils.INSTANCE.constructListType(String.class)); + constructListType(String.class)); } protected Request getAccessibleDatabasesForRequest(final DbName dbName, final String user) { @@ -128,7 +130,7 @@ protected Request getUserRequest(final DbName dbName, final String user) { protected ResponseDeserializer> getUsersResponseDeserializer() { return response -> getSerde().deserialize(response.getBody(), ArangoResponseField.RESULT_JSON_POINTER, - SerdeUtils.INSTANCE.constructListType(UserEntity.class)); + constructListType(UserEntity.class)); } protected Request updateUserRequest(final DbName dbName, final String user, final UserUpdateOptions options) { diff --git a/src/main/java/com/arangodb/internal/InternalArangoDatabase.java b/src/main/java/com/arangodb/internal/InternalArangoDatabase.java index 97d9707af..a2e49e983 100644 --- a/src/main/java/com/arangodb/internal/InternalArangoDatabase.java +++ b/src/main/java/com/arangodb/internal/InternalArangoDatabase.java @@ -36,6 +36,8 @@ import java.util.Collection; import java.util.Map; +import static com.arangodb.serde.SerdeUtils.constructListType; + /** * @author Mark Vollmary * @author Michele Rastelli @@ -111,7 +113,7 @@ protected Request getCollectionsRequest(final CollectionsReadOptions options) { protected ResponseDeserializer> getCollectionsResponseDeserializer() { return response -> getSerde().deserialize(response.getBody(), ArangoResponseField.RESULT_JSON_POINTER, - SerdeUtils.INSTANCE.constructListType(CollectionEntity.class)); + constructListType(CollectionEntity.class)); } protected Request dropRequest() { @@ -257,7 +259,7 @@ protected Request getAqlFunctionsRequest(final AqlFunctionGetOptions options) { protected ResponseDeserializer> getAqlFunctionsResponseDeserializer() { return response -> getSerde().deserialize(response.getBody(), ArangoResponseField.RESULT_JSON_POINTER, - SerdeUtils.INSTANCE.constructListType(AqlFunctionEntity.class)); + constructListType(AqlFunctionEntity.class)); } protected Request createGraphRequest(final String name, final Collection edgeDefinitions, final GraphCreateOptions options) { @@ -274,7 +276,7 @@ protected Request getGraphsRequest() { protected ResponseDeserializer> getGraphsResponseDeserializer() { return response -> getSerde().deserialize(response.getBody(), "/graphs", - SerdeUtils.INSTANCE.constructListType(GraphEntity.class)); + constructListType(GraphEntity.class)); } protected Request transactionRequest(final String action, final TransactionOptions options) { @@ -306,7 +308,7 @@ protected Request getStreamTransactionRequest(String id) { protected ResponseDeserializer> transactionsResponseDeserializer() { return response -> getSerde().deserialize(response.getBody(), "/transactions", - SerdeUtils.INSTANCE.constructListType(TransactionEntity.class)); + constructListType(TransactionEntity.class)); } protected Request commitStreamTransactionRequest(String id) { @@ -335,7 +337,7 @@ protected Request getViewsRequest() { protected ResponseDeserializer> getViewsResponseDeserializer() { return response -> getSerde().deserialize(response.getBody(), ArangoResponseField.RESULT_JSON_POINTER, - SerdeUtils.INSTANCE.constructListType(ViewEntity.class)); + constructListType(ViewEntity.class)); } protected Request createViewRequest(final String name, final ViewType type) { @@ -356,7 +358,7 @@ protected Request getAnalyzersRequest() { protected ResponseDeserializer> getSearchAnalyzersResponseDeserializer() { return response -> getSerde().deserialize(response.getBody(), ArangoResponseField.RESULT_JSON_POINTER, - SerdeUtils.INSTANCE.constructListType(SearchAnalyzer.class)); + constructListType(SearchAnalyzer.class)); } protected Request createAnalyzerRequest(final SearchAnalyzer options) { diff --git a/src/main/java/com/arangodb/internal/InternalArangoGraph.java b/src/main/java/com/arangodb/internal/InternalArangoGraph.java index 46e3ff8d1..8bafa815e 100644 --- a/src/main/java/com/arangodb/internal/InternalArangoGraph.java +++ b/src/main/java/com/arangodb/internal/InternalArangoGraph.java @@ -31,6 +31,8 @@ import java.util.Collection; +import static com.arangodb.serde.SerdeUtils.constructListType; + /** * @author Mark Vollmary */ @@ -85,7 +87,7 @@ protected Request getVertexCollectionsRequest() { protected ResponseDeserializer> getVertexCollectionsResponseDeserializer() { return response -> getSerde().deserialize(response.getBody(), "/collections", - SerdeUtils.INSTANCE.constructListType(String.class)); + constructListType(String.class)); } protected Request addVertexCollectionRequest(final String name, final VertexCollectionCreateOptions options) { @@ -104,7 +106,7 @@ protected Request getEdgeDefinitionsRequest() { protected ResponseDeserializer> getEdgeDefinitionsDeserializer() { return response -> getSerde().deserialize(response.getBody(), "/collections", - SerdeUtils.INSTANCE.constructListType(String.class)); + constructListType(String.class)); } protected Request addEdgeDefinitionRequest(final EdgeDefinition definition) { diff --git a/src/main/java/com/arangodb/internal/net/ExtendedHostResolver.java b/src/main/java/com/arangodb/internal/net/ExtendedHostResolver.java index 5d617c942..02181767c 100644 --- a/src/main/java/com/arangodb/internal/net/ExtendedHostResolver.java +++ b/src/main/java/com/arangodb/internal/net/ExtendedHostResolver.java @@ -33,6 +33,8 @@ import java.util.*; +import static com.arangodb.serde.SerdeUtils.constructParametricType; + /** * @author Mark Vollmary */ @@ -122,8 +124,8 @@ private Collection resolveFromServer() throws ArangoDBException { new Request(DbName.SYSTEM, RequestType.GET, "/_api/cluster/endpoints"), response1 -> { final List> tmp = arangoSerialization.deserialize(response1.getBody(), "/endpoints", - SerdeUtils.INSTANCE.constructParametricType(List.class, - SerdeUtils.INSTANCE.constructParametricType(Map.class, String.class, String.class))); + constructParametricType(List.class, + constructParametricType(Map.class, String.class, String.class))); Collection endpoints = new ArrayList<>(); for (final Map map : tmp) { endpoints.add(map.get("endpoint")); diff --git a/src/main/java/com/arangodb/serde/InternalDeserializers.java b/src/main/java/com/arangodb/serde/InternalDeserializers.java index f571b5f5b..31f41cf46 100644 --- a/src/main/java/com/arangodb/serde/InternalDeserializers.java +++ b/src/main/java/com/arangodb/serde/InternalDeserializers.java @@ -123,6 +123,7 @@ public ReplicationFactor deserialize(final JsonParser p, final DeserializationCo } }; + @SuppressWarnings("unchecked") static final JsonDeserializer RESPONSE = new JsonDeserializer() { @Override public Response deserialize(final JsonParser p, final DeserializationContext ctxt) throws IOException { diff --git a/src/main/java/com/arangodb/serde/InternalSerdeImpl.java b/src/main/java/com/arangodb/serde/InternalSerdeImpl.java index dcf63af8e..1f206ef8c 100644 --- a/src/main/java/com/arangodb/serde/InternalSerdeImpl.java +++ b/src/main/java/com/arangodb/serde/InternalSerdeImpl.java @@ -14,12 +14,14 @@ import java.util.List; import java.util.stream.Collectors; +import static com.arangodb.serde.SerdeUtils.checkSupportedJacksonVersion; + final class InternalSerdeImpl extends JacksonSerdeImpl implements InternalSerde { private final ArangoSerde userSerde; static { - SerdeUtils.INSTANCE.checkSupportedJacksonVersion(); + checkSupportedJacksonVersion(); } InternalSerdeImpl(final ObjectMapper mapper, final ArangoSerde userSerde) { @@ -110,6 +112,7 @@ public T deserializeUserData(byte[] content, Class clazz) { } @Override + @SuppressWarnings("unchecked") public T deserializeUserData(byte[] content, Type type) { if (type instanceof Class) { return deserializeUserData(content, (Class) type); diff --git a/src/main/java/com/arangodb/serde/SerdeUtils.java b/src/main/java/com/arangodb/serde/SerdeUtils.java index 87eb13d3d..b16433285 100644 --- a/src/main/java/com/arangodb/serde/SerdeUtils.java +++ b/src/main/java/com/arangodb/serde/SerdeUtils.java @@ -12,7 +12,6 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; -import java.util.Map; import java.util.logging.Level; import java.util.logging.Logger; @@ -47,15 +46,11 @@ public String writeJson(final JsonNode data) { } } - public Type constructListType(Class clazz) { + public static Type constructListType(Class clazz) { return TypeFactory.defaultInstance().constructCollectionType(List.class, clazz); } - public Type constructMapType(Class keyClazz, Class valueClazz) { - return TypeFactory.defaultInstance().constructMapType(Map.class, keyClazz, valueClazz); - } - - public Type constructParametricType(Class rawType, Type... rawArgs) { + public static Type constructParametricType(Class rawType, Type... rawArgs) { if (rawArgs == null || rawArgs.length == 0 || rawArgs[0] == null) { return rawType; } else { @@ -63,7 +58,7 @@ public Type constructParametricType(Class rawType, Type... rawArgs) { } } - public Type convertToType(final JavaType javaType) { + public static Type convertToType(final JavaType javaType) { List args = new ArrayList<>(); for (JavaType it : javaType.getBindings().getTypeParameters()) { Type type = convertToType(it); @@ -72,7 +67,7 @@ public Type convertToType(final JavaType javaType) { return constructParametricType(javaType.getRawClass(), args.toArray(new Type[0])); } - void checkSupportedJacksonVersion() { + static void checkSupportedJacksonVersion() { Arrays.asList( com.fasterxml.jackson.databind.cfg.PackageVersion.VERSION, com.fasterxml.jackson.core.json.PackageVersion.VERSION diff --git a/src/main/java/com/arangodb/serde/UserDataDeserializer.java b/src/main/java/com/arangodb/serde/UserDataDeserializer.java index 5be515eb5..4f5ac9f2e 100644 --- a/src/main/java/com/arangodb/serde/UserDataDeserializer.java +++ b/src/main/java/com/arangodb/serde/UserDataDeserializer.java @@ -11,6 +11,8 @@ import java.io.IOException; import java.lang.reflect.Type; +import static com.arangodb.serde.SerdeUtils.convertToType; + class UserDataDeserializer extends JsonDeserializer implements ContextualDeserializer { private final Type targetType; private final InternalSerde serde; @@ -21,7 +23,7 @@ class UserDataDeserializer extends JsonDeserializer implements Contextua } private UserDataDeserializer(final JavaType targetType, final InternalSerde serde) { - this.targetType = SerdeUtils.INSTANCE.convertToType(targetType); + this.targetType = convertToType(targetType); this.serde = serde; } From 3bca4a769cc1d73690c44f284f87070b141a6329 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Thu, 11 Aug 2022 15:25:34 +0200 Subject: [PATCH 073/254] [DE-313] Allow specifying the return type in CRUD document operations (#448) * typed ArangoCollection#insertDocument * typed ArangoCollection#updateDocument * typed ArangoCollection#replaceDocument * typed ArangoCollection#insertDocuments * typed ArangoCollection#deleteDocument * typed ArangoCollection#updateDocuments * typed ArangoCollection#replaceDocuments * typed ArangoCollection#deleteDocuments --- .../java/com/arangodb/ArangoCollection.java | 127 ++++++--- .../arangodb/async/ArangoCollectionAsync.java | 110 +++++++- .../internal/ArangoCollectionAsyncImpl.java | 108 +++++--- .../internal/ArangoCollectionImpl.java | 92 +++++-- .../internal/InternalArangoCollection.java | 9 +- .../arangodb/model/DocumentCreateOptions.java | 5 - .../com/arangodb/ArangoCollectionTest.java | 259 ++++++++++++------ src/test/java/com/arangodb/DocumentTest.java | 6 +- .../com/arangodb/StreamTransactionTest.java | 6 +- .../arangodb/async/ArangoCollectionTest.java | 192 ++++++++++--- .../document/GetDocumentExampleTest.java | 3 +- .../graph/AQLActorsAndMoviesExampleTest.java | 4 +- .../arangodb/async/serde/CustomSerdeTest.java | 4 +- .../document/GetDocumentExampleTest.java | 3 +- .../document/InsertDocumentExampleTest.java | 9 +- .../graph/AQLActorsAndMoviesExampleTest.java | 4 +- .../com/arangodb/serde/CustomSerdeTest.java | 4 +- 17 files changed, 678 insertions(+), 267 deletions(-) diff --git a/src/main/java/com/arangodb/ArangoCollection.java b/src/main/java/com/arangodb/ArangoCollection.java index c77a228f4..b2d332760 100644 --- a/src/main/java/com/arangodb/ArangoCollection.java +++ b/src/main/java/com/arangodb/ArangoCollection.java @@ -61,7 +61,7 @@ public interface ArangoCollection extends ArangoSerdeAccessor { * @see API * Documentation */ - DocumentCreateEntity insertDocument(T value) throws ArangoDBException; + DocumentCreateEntity insertDocument(Object value) throws ArangoDBException; /** * Creates a new document from the given document, unless there is already a document with the _key given. If no @@ -76,12 +76,23 @@ public interface ArangoCollection extends ArangoSerdeAccessor { */ DocumentCreateEntity insertDocument(T value, DocumentCreateOptions options) throws ArangoDBException; + /** + * Creates a new document from the given document, unless there is already a document with the _key given. If no + * _key is given, a new unique _key is generated automatically. + * + * @param value A representation of a single document (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) + * @param options Additional options, can be null + * @param type Deserialization target type for the returned documents. + * @return information about the document + * @throws ArangoDBException + * @see API + * Documentation + */ + DocumentCreateEntity insertDocument(T value, DocumentCreateOptions options, Class type) throws ArangoDBException; + /** * Creates new documents from the given documents, unless there is already a document with the _key given. If no * _key is given, a new unique _key is generated automatically. - *

- * Limitations: - * - the fields having {@code null} value are always removed during serialization * * @param values A List of documents (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) * @return information about the documents @@ -89,14 +100,11 @@ public interface ArangoCollection extends ArangoSerdeAccessor { * @see API * Documentation */ - MultiDocumentEntity> insertDocuments(Collection values) throws ArangoDBException; + MultiDocumentEntity> insertDocuments(Collection values) throws ArangoDBException; /** * Creates new documents from the given documents, unless there is already a document with the _key given. If no * _key is given, a new unique _key is generated automatically. - *

- * Limitations: - * - the fields having {@code null} value are always removed during serialization * * @param values A List of documents (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) * @param options Additional options, can be null @@ -108,11 +116,23 @@ public interface ArangoCollection extends ArangoSerdeAccessor { MultiDocumentEntity> insertDocuments( Collection values, DocumentCreateOptions options) throws ArangoDBException; + /** + * Creates new documents from the given documents, unless there is already a document with the _key given. If no + * _key is given, a new unique _key is generated automatically. + * + * @param values A List of documents (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) + * @param options Additional options, can be null + * @param type Deserialization target type for the returned documents. + * @return information about the documents + * @throws ArangoDBException + * @see API + * Documentation + */ + MultiDocumentEntity> insertDocuments( + Collection values, DocumentCreateOptions options, Class type) throws ArangoDBException; + /** * Bulk imports the given values into the collection. - *

- * Limitations: - * - the fields having {@code null} value are always removed during serialization * * @param values a list of Objects that will be stored as documents * @return information about the import @@ -122,9 +142,6 @@ MultiDocumentEntity> insertDocuments( /** * Bulk imports the given values into the collection. - *

- * Limitations: - * - the fields having {@code null} value are always removed during serialization * * @param values a list of Objects that will be stored as documents * @param options Additional options, can be null @@ -135,9 +152,6 @@ MultiDocumentEntity> insertDocuments( /** * Bulk imports the given values into the collection. - *

- * Limitations: - * - the fields having {@code null} value are always removed during serialization * * @param values JSON-encoded array of objects that will be stored as documents * @return information about the import @@ -147,9 +161,6 @@ MultiDocumentEntity> insertDocuments( /** * Bulk imports the given values into the collection. - *

- * Limitations: - * - the fields having {@code null} value are always removed during serialization * * @param values JSON-encoded array of objects that will be stored as documents * @param options Additional options, can be null @@ -216,7 +227,7 @@ MultiDocumentEntity getDocuments(Collection keys, Class type, * @see API * Documentation */ - DocumentUpdateEntity replaceDocument(String key, T value) throws ArangoDBException; + DocumentUpdateEntity replaceDocument(String key, Object value) throws ArangoDBException; /** * Replaces the document with {@code key} with the one in the body, provided there is such a document and no @@ -233,12 +244,25 @@ MultiDocumentEntity getDocuments(Collection keys, Class type, DocumentUpdateEntity replaceDocument(String key, T value, DocumentReplaceOptions options) throws ArangoDBException; + /** + * Replaces the document with {@code key} with the one in the body, provided there is such a document and no + * precondition is violated + * + * @param key The key of the document + * @param value A representation of a single document (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) + * @param options Additional options, can be null + * @param type Deserialization target type for the returned documents. + * @return information about the document + * @throws ArangoDBException + * @see API + * Documentation + */ + DocumentUpdateEntity replaceDocument(String key, T value, DocumentReplaceOptions options, Class type) + throws ArangoDBException; + /** * Replaces multiple documents in the specified collection with the ones in the values, the replaced documents are * specified by the _key attributes in the documents in values. - *

- * Limitations: - * - the fields having {@code null} value are always removed during serialization * * @param values A List of documents (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) * @return information about the documents @@ -246,14 +270,11 @@ DocumentUpdateEntity replaceDocument(String key, T value, DocumentReplace * @see API * Documentation */ - MultiDocumentEntity> replaceDocuments(Collection values) throws ArangoDBException; + MultiDocumentEntity> replaceDocuments(Collection values) throws ArangoDBException; /** * Replaces multiple documents in the specified collection with the ones in the values, the replaced documents are * specified by the _key attributes in the documents in values. - *

- * Limitations: - * - the fields having {@code null} value are always removed during serialization * * @param values A List of documents (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) * @param options Additional options, can be null @@ -265,6 +286,21 @@ DocumentUpdateEntity replaceDocument(String key, T value, DocumentReplace MultiDocumentEntity> replaceDocuments( Collection values, DocumentReplaceOptions options) throws ArangoDBException; + /** + * Replaces multiple documents in the specified collection with the ones in the values, the replaced documents are + * specified by the _key attributes in the documents in values. + * + * @param values A List of documents (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) + * @param options Additional options, can be null + * @param type Deserialization target type for the returned documents. + * @return information about the documents + * @throws ArangoDBException + * @see API + * Documentation + */ + MultiDocumentEntity> replaceDocuments( + Collection values, DocumentReplaceOptions options, Class type) throws ArangoDBException; + /** * Partially updates the document identified by document-key. The value must contain a document with the attributes * to patch (the patch document). All attributes from the patch document will be added to the existing document if @@ -277,7 +313,7 @@ MultiDocumentEntity> replaceDocuments( * @see API * Documentation */ - DocumentUpdateEntity updateDocument(String key, T value) throws ArangoDBException; + DocumentUpdateEntity updateDocument(String key, Object value) throws ArangoDBException; /** * Partially updates the document identified by document-key. The value must contain a document with the attributes @@ -324,7 +360,7 @@ DocumentUpdateEntity updateDocument(String key, T value, DocumentUpdat * @see API * Documentation */ - MultiDocumentEntity> updateDocuments(Collection values) throws ArangoDBException; + MultiDocumentEntity> updateDocuments(Collection values) throws ArangoDBException; /** * Partially updates documents, the documents to update are specified by the _key attributes in the objects on @@ -370,6 +406,19 @@ MultiDocumentEntity> updateDocuments( */ DocumentDeleteEntity deleteDocument(String key) throws ArangoDBException; + /** + * Deletes the document with the given {@code key} from the collection. + * + * @param key The key of the document + * @param options Additional options, can be null + * @return information about the document + * @throws ArangoDBException + * @see API + * Documentation + */ + DocumentDeleteEntity deleteDocument(String key, DocumentDeleteOptions options) + throws ArangoDBException; + /** * Deletes the document with the given {@code key} from the collection. * @@ -382,7 +431,7 @@ MultiDocumentEntity> updateDocuments( * @see API * Documentation */ - DocumentDeleteEntity deleteDocument(String key, Class type, DocumentDeleteOptions options) + DocumentDeleteEntity deleteDocument(String key, DocumentDeleteOptions options, Class type) throws ArangoDBException; /** @@ -397,6 +446,20 @@ DocumentDeleteEntity deleteDocument(String key, Class type, DocumentDe */ MultiDocumentEntity> deleteDocuments(Collection values) throws ArangoDBException; + /** + * Deletes multiple documents from the collection. + * + * @param values The keys of the documents or the documents themselves + * @param options Additional options, can be null + * @return information about the documents + * @throws ArangoDBException + * @see API + * Documentation + */ + MultiDocumentEntity> deleteDocuments( + Collection values, DocumentDeleteOptions options) throws ArangoDBException; + /** * Deletes multiple documents from the collection. * @@ -411,7 +474,7 @@ DocumentDeleteEntity deleteDocument(String key, Class type, DocumentDe * Documentation */ MultiDocumentEntity> deleteDocuments( - Collection values, Class type, DocumentDeleteOptions options) throws ArangoDBException; + Collection values, DocumentDeleteOptions options, Class type) throws ArangoDBException; /** * Checks if the document exists by reading a single document head diff --git a/src/main/java/com/arangodb/async/ArangoCollectionAsync.java b/src/main/java/com/arangodb/async/ArangoCollectionAsync.java index 1df9efcd3..2869b5f82 100644 --- a/src/main/java/com/arangodb/async/ArangoCollectionAsync.java +++ b/src/main/java/com/arangodb/async/ArangoCollectionAsync.java @@ -61,7 +61,7 @@ public interface ArangoCollectionAsync extends ArangoSerdeAccessor { * @see API * Documentation */ - CompletableFuture> insertDocument(final T value); + CompletableFuture> insertDocument(final Object value); /** * Creates a new document from the given document, unless there is already a document with the _key given. If no @@ -75,6 +75,19 @@ public interface ArangoCollectionAsync extends ArangoSerdeAccessor { */ CompletableFuture> insertDocument(final T value, final DocumentCreateOptions options); + /** + * Creates a new document from the given document, unless there is already a document with the _key given. If no + * _key is given, a new unique _key is generated automatically. + * + * @param value A representation of a single document (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) + * @param options Additional options, can be null + * @param type Deserialization target type for the returned documents. + * @return information about the document + * @see API + * Documentation + */ + CompletableFuture> insertDocument(final T value, final DocumentCreateOptions options, Class type); + /** * Creates new documents from the given documents, unless there is already a document with the _key given. If no * _key is given, a new unique _key is generated automatically. @@ -84,7 +97,7 @@ public interface ArangoCollectionAsync extends ArangoSerdeAccessor { * @see API * Documentation */ - CompletableFuture>> insertDocuments(final Collection values); + CompletableFuture>> insertDocuments(final Collection values); /** * Creates new documents from the given documents, unless there is already a document with the _key given. If no @@ -100,6 +113,22 @@ CompletableFuture>> insertDocume final Collection values, final DocumentCreateOptions options); + /** + * Creates new documents from the given documents, unless there is already a document with the _key given. If no + * _key is given, a new unique _key is generated automatically. + * + * @param values A List of documents (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) + * @param options Additional options, can be null + * @param type Deserialization target type for the returned documents. + * @return information about the documents + * @see API + * Documentation + */ + CompletableFuture>> insertDocuments( + final Collection values, + final DocumentCreateOptions options, + final Class type); + /** * Imports documents * @@ -192,7 +221,7 @@ CompletableFuture> getDocuments( * @see API * Documentation */ - CompletableFuture> replaceDocument(final String key, final T value); + CompletableFuture> replaceDocument(final String key, final Object value); /** * Replaces the document with key with the one in the body, provided there is such a document and no precondition is @@ -210,6 +239,24 @@ CompletableFuture> replaceDocument( final T value, final DocumentReplaceOptions options); + /** + * Replaces the document with key with the one in the body, provided there is such a document and no precondition is + * violated + * + * @param key The key of the document + * @param value A representation of a single document (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) + * @param options Additional options, can be null + * @param type Deserialization target type for the returned documents. + * @return information about the document + * @see API + * Documentation + */ + CompletableFuture> replaceDocument( + final String key, + final T value, + final DocumentReplaceOptions options, + final Class type); + /** * Replaces multiple documents in the specified collection with the ones in the values, the replaced documents are * specified by the _key attributes in the documents in values. @@ -219,7 +266,7 @@ CompletableFuture> replaceDocument( * @see API * Documentation */ - CompletableFuture>> replaceDocuments(final Collection values); + CompletableFuture>> replaceDocuments(final Collection values); /** * Replaces multiple documents in the specified collection with the ones in the values, the replaced documents are @@ -235,6 +282,22 @@ CompletableFuture>> replaceDocum final Collection values, final DocumentReplaceOptions options); + /** + * Replaces multiple documents in the specified collection with the ones in the values, the replaced documents are + * specified by the _key attributes in the documents in values. + * + * @param values A List of documents (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) + * @param options Additional options, can be null + * @param type Deserialization target type for the returned documents. + * @return information about the documents + * @see API + * Documentation + */ + CompletableFuture>> replaceDocuments( + final Collection values, + final DocumentReplaceOptions options, + final Class type); + /** * Partially updates the document identified by document-key. The value must contain a document with the attributes * to patch (the patch document). All attributes from the patch document will be added to the existing document if @@ -246,7 +309,7 @@ CompletableFuture>> replaceDocum * @see API * Documentation */ - CompletableFuture> updateDocument(final String key, final T value); + CompletableFuture> updateDocument(final String key, final Object value); /** * Partially updates the document identified by document-key. The value must contain a document with the attributes @@ -295,7 +358,7 @@ CompletableFuture> updateDocument( * @see API * Documentation */ - CompletableFuture>> updateDocuments(final Collection values); + CompletableFuture>> updateDocuments(final Collection values); /** * Partially updates documents, the documents to update are specified by the _key attributes in the objects on @@ -341,6 +404,19 @@ CompletableFuture>> updateDoc */ CompletableFuture> deleteDocument(final String key); + /** + * Removes a document + * + * @param key The key of the document + * @param options Additional options, can be null + * @return information about the document + * @see API + * Documentation + */ + CompletableFuture> deleteDocument( + final String key, + final DocumentDeleteOptions options); + /** * Removes a document * @@ -354,8 +430,8 @@ CompletableFuture>> updateDoc */ CompletableFuture> deleteDocument( final String key, - final Class type, - final DocumentDeleteOptions options); + final DocumentDeleteOptions options, + final Class type); /** * Removes multiple document @@ -368,6 +444,20 @@ CompletableFuture> deleteDocument( */ CompletableFuture>> deleteDocuments(final Collection values); + /** + * Removes multiple document + * + * @param values The keys of the documents or the documents themselves + * @param options Additional options, can be null + * @return information about the documents + * @see API + * Documentation + */ + CompletableFuture>> deleteDocuments( + final Collection values, + final DocumentDeleteOptions options); + /** * Removes multiple document * @@ -382,8 +472,8 @@ CompletableFuture> deleteDocument( */ CompletableFuture>> deleteDocuments( final Collection values, - final Class type, - final DocumentDeleteOptions options); + final DocumentDeleteOptions options, + final Class type); /** * Checks if the document exists by reading a single document head diff --git a/src/main/java/com/arangodb/async/internal/ArangoCollectionAsyncImpl.java b/src/main/java/com/arangodb/async/internal/ArangoCollectionAsyncImpl.java index 90c9bfab0..3544d2298 100644 --- a/src/main/java/com/arangodb/async/internal/ArangoCollectionAsyncImpl.java +++ b/src/main/java/com/arangodb/async/internal/ArangoCollectionAsyncImpl.java @@ -46,35 +46,44 @@ public class ArangoCollectionAsyncImpl } @Override - public CompletableFuture> insertDocument(final T value) { - final DocumentCreateOptions options = new DocumentCreateOptions(); - return executor.execute(insertDocumentRequest(value, options), - constructParametricType(DocumentCreateEntity.class, value.getClass())); + public CompletableFuture> insertDocument(final Object value) { + return executor.execute(insertDocumentRequest(value, new DocumentCreateOptions()), + constructParametricType(DocumentCreateEntity.class, Void.class)); } @Override + @SuppressWarnings("unchecked") public CompletableFuture> insertDocument( final T value, final DocumentCreateOptions options) { + return insertDocument(value, options, (Class) value.getClass()); + } + + @Override + public CompletableFuture> insertDocument(T value, DocumentCreateOptions options, Class type) { return executor.execute(insertDocumentRequest(value, options), - constructParametricType(DocumentCreateEntity.class, value.getClass())); + constructParametricType(DocumentCreateEntity.class, type)); } @Override - public CompletableFuture>> insertDocuments( - final Collection values) { - final DocumentCreateOptions params = new DocumentCreateOptions(); - return executor.execute(insertDocumentsRequest(values, params), - insertDocumentsResponseDeserializer(values, params)); + public CompletableFuture>> insertDocuments( + final Collection values) { + return executor + .execute(insertDocumentsRequest(values, new DocumentCreateOptions()), insertDocumentsResponseDeserializer(Void.class)); } @Override + @SuppressWarnings("unchecked") public CompletableFuture>> insertDocuments( final Collection values, final DocumentCreateOptions options) { - final DocumentCreateOptions params = (options != null ? options : new DocumentCreateOptions()); - return executor.execute(insertDocumentsRequest(values, params), - insertDocumentsResponseDeserializer(values, params)); + return insertDocuments(values, options, (Class) getCollectionContentClass(values)); + } + + @Override + public CompletableFuture>> insertDocuments(Collection values, DocumentCreateOptions options, Class type) { + return executor + .execute(insertDocumentsRequest(values, options), insertDocumentsResponseDeserializer(type)); } @Override @@ -134,41 +143,49 @@ public CompletableFuture> getDocuments( } @Override - public CompletableFuture> replaceDocument(final String key, final T value) { + public CompletableFuture> replaceDocument(final String key, final Object value) { final DocumentReplaceOptions options = new DocumentReplaceOptions(); return executor.execute(replaceDocumentRequest(key, value, options), - constructParametricType(DocumentUpdateEntity.class, value.getClass())); + constructParametricType(DocumentUpdateEntity.class, Void.class)); } @Override + @SuppressWarnings("unchecked") public CompletableFuture> replaceDocument( final String key, final T value, final DocumentReplaceOptions options) { + return replaceDocument(key, value, options, (Class) value.getClass()); + } + + @Override + public CompletableFuture> replaceDocument(String key, T value, DocumentReplaceOptions options, Class type) { return executor.execute(replaceDocumentRequest(key, value, options), - constructParametricType(DocumentUpdateEntity.class, value.getClass())); + constructParametricType(DocumentUpdateEntity.class, type)); } @Override - public CompletableFuture>> replaceDocuments( - final Collection values) { - final DocumentReplaceOptions params = new DocumentReplaceOptions(); - return executor.execute(replaceDocumentsRequest(values, params), - replaceDocumentsResponseDeserializer(values)); + public CompletableFuture>> replaceDocuments( + final Collection values) { + return executor.execute(replaceDocumentsRequest(values, new DocumentReplaceOptions()), replaceDocumentsResponseDeserializer(Void.class)); } @Override + @SuppressWarnings("unchecked") public CompletableFuture>> replaceDocuments( final Collection values, final DocumentReplaceOptions options) { - final DocumentReplaceOptions params = (options != null ? options : new DocumentReplaceOptions()); - return executor.execute(replaceDocumentsRequest(values, params), - replaceDocumentsResponseDeserializer(values)); + return replaceDocuments(values, options, (Class) getCollectionContentClass(values)); } @Override - public CompletableFuture> updateDocument(final String key, final T value) { - return updateDocument(key, value, new DocumentUpdateOptions()); + public CompletableFuture>> replaceDocuments(Collection values, DocumentReplaceOptions options, Class type) { + return executor.execute(replaceDocumentsRequest(values, options), replaceDocumentsResponseDeserializer(type)); + } + + @Override + public CompletableFuture> updateDocument(final String key, final Object value) { + return updateDocument(key, value, new DocumentUpdateOptions(), Void.class); } @Override @@ -191,9 +208,9 @@ public CompletableFuture> updateDocument( } @Override - public CompletableFuture>> updateDocuments( - final Collection values) { - return updateDocuments(values, new DocumentUpdateOptions()); + public CompletableFuture>> updateDocuments( + final Collection values) { + return updateDocuments(values, new DocumentUpdateOptions(), Void.class); } @Override @@ -201,7 +218,7 @@ public CompletableFuture>> updat public CompletableFuture>> updateDocuments( final Collection values, final DocumentUpdateOptions options) { - return updateDocuments(values, options, values.isEmpty() ? null : (Class) getCollectionContentClass(values)); + return updateDocuments(values, options, (Class) getCollectionContentClass(values)); } @Override @@ -209,22 +226,26 @@ public CompletableFuture>> up final Collection values, final DocumentUpdateOptions options, final Class returnType) { - final DocumentUpdateOptions params = (options != null ? options : new DocumentUpdateOptions()); - return executor.execute(updateDocumentsRequest(values, params), - updateDocumentsResponseDeserializer(returnType)); + return executor + .execute(updateDocumentsRequest(values, options), updateDocumentsResponseDeserializer(returnType)); } @Override public CompletableFuture> deleteDocument(final String key) { - return executor.execute(deleteDocumentRequest(key, new DocumentDeleteOptions()), - constructParametricType(DocumentDeleteEntity.class, Void.class)); + return deleteDocument(key, new DocumentDeleteOptions()); + } + + @Override + @SuppressWarnings("unchecked") + public CompletableFuture> deleteDocument(String key, DocumentDeleteOptions options) { + return deleteDocument(key, options, (Class) Void.class); } @Override public CompletableFuture> deleteDocument( final String key, - final Class type, - final DocumentDeleteOptions options) { + final DocumentDeleteOptions options, + final Class type) { return executor.execute(deleteDocumentRequest(key, options), constructParametricType(DocumentDeleteEntity.class, type)); } @@ -232,15 +253,20 @@ public CompletableFuture> deleteDocument( @Override public CompletableFuture>> deleteDocuments( final Collection values) { - return executor.execute(deleteDocumentsRequest(values, new DocumentDeleteOptions()), - deleteDocumentsResponseDeserializer(Void.class)); + return deleteDocuments(values, new DocumentDeleteOptions(), Void.class); + } + + @Override + @SuppressWarnings("unchecked") + public CompletableFuture>> deleteDocuments(Collection values, DocumentDeleteOptions options) { + return deleteDocuments(values, options, (Class) getCollectionContentClass(values)); } @Override public CompletableFuture>> deleteDocuments( final Collection values, - final Class type, - final DocumentDeleteOptions options) { + final DocumentDeleteOptions options, + final Class type) { return executor.execute(deleteDocumentsRequest(values, options), deleteDocumentsResponseDeserializer(type)); } diff --git a/src/main/java/com/arangodb/internal/ArangoCollectionImpl.java b/src/main/java/com/arangodb/internal/ArangoCollectionImpl.java index 625182c86..e57dda57d 100644 --- a/src/main/java/com/arangodb/internal/ArangoCollectionImpl.java +++ b/src/main/java/com/arangodb/internal/ArangoCollectionImpl.java @@ -25,7 +25,6 @@ import com.arangodb.entity.*; import com.arangodb.internal.util.DocumentUtil; import com.arangodb.model.*; -import com.arangodb.serde.SerdeUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -47,29 +46,42 @@ protected ArangoCollectionImpl(final ArangoDatabaseImpl db, final String name) { } @Override - public DocumentCreateEntity insertDocument(final T value) throws ArangoDBException { - return insertDocument(value, new DocumentCreateOptions()); + public DocumentCreateEntity insertDocument(final Object value) throws ArangoDBException { + return executor.execute(insertDocumentRequest(value, new DocumentCreateOptions()), + constructParametricType(DocumentCreateEntity.class, Void.class)); } @Override + @SuppressWarnings("unchecked") public DocumentCreateEntity insertDocument(final T value, final DocumentCreateOptions options) throws ArangoDBException { + return insertDocument(value, options, (Class) value.getClass()); + } + + @Override + public DocumentCreateEntity insertDocument(final T value, final DocumentCreateOptions options, final Class type) throws ArangoDBException { return executor.execute(insertDocumentRequest(value, options), - constructParametricType(DocumentCreateEntity.class, value.getClass())); + constructParametricType(DocumentCreateEntity.class, type)); } @Override - public MultiDocumentEntity> insertDocuments(final Collection values) + public MultiDocumentEntity> insertDocuments(final Collection values) throws ArangoDBException { - return insertDocuments(values, new DocumentCreateOptions()); + return executor + .execute(insertDocumentsRequest(values, new DocumentCreateOptions()), insertDocumentsResponseDeserializer(Void.class)); } @Override + @SuppressWarnings("unchecked") public MultiDocumentEntity> insertDocuments( final Collection values, final DocumentCreateOptions options) throws ArangoDBException { - final DocumentCreateOptions params = (options != null ? options : new DocumentCreateOptions()); + return insertDocuments(values, options, (Class) getCollectionContentClass(values)); + } + + @Override + public MultiDocumentEntity> insertDocuments(Collection values, DocumentCreateOptions options, Class type) throws ArangoDBException { return executor - .execute(insertDocumentsRequest(values, params), insertDocumentsResponseDeserializer(values, params)); + .execute(insertDocumentsRequest(values, options), insertDocumentsResponseDeserializer(type)); } @Override @@ -137,34 +149,45 @@ public MultiDocumentEntity getDocuments( } @Override - public DocumentUpdateEntity replaceDocument(final String key, final T value) throws ArangoDBException { - return replaceDocument(key, value, new DocumentReplaceOptions()); + public DocumentUpdateEntity replaceDocument(final String key, final Object value) throws ArangoDBException { + return executor.execute(replaceDocumentRequest(key, value, new DocumentReplaceOptions()), + constructParametricType(DocumentUpdateEntity.class, Void.class)); } @Override + @SuppressWarnings("unchecked") public DocumentUpdateEntity replaceDocument( final String key, final T value, final DocumentReplaceOptions options) throws ArangoDBException { + return replaceDocument(key, value, options, (Class) value.getClass()); + } + + @Override + public DocumentUpdateEntity replaceDocument(String key, T value, DocumentReplaceOptions options, Class type) throws ArangoDBException { return executor.execute(replaceDocumentRequest(key, value, options), - constructParametricType(DocumentUpdateEntity.class, value.getClass())); + constructParametricType(DocumentUpdateEntity.class, type)); } @Override - public MultiDocumentEntity> replaceDocuments(final Collection values) + public MultiDocumentEntity> replaceDocuments(final Collection values) throws ArangoDBException { - return replaceDocuments(values, new DocumentReplaceOptions()); + return executor.execute(replaceDocumentsRequest(values, new DocumentReplaceOptions()), replaceDocumentsResponseDeserializer(Void.class)); } @Override + @SuppressWarnings("unchecked") public MultiDocumentEntity> replaceDocuments( final Collection values, final DocumentReplaceOptions options) throws ArangoDBException { - final DocumentReplaceOptions params = (options != null ? options : new DocumentReplaceOptions()); - return executor - .execute(replaceDocumentsRequest(values, params), replaceDocumentsResponseDeserializer(values)); + return replaceDocuments(values, options, (Class) getCollectionContentClass(values)); + } + + @Override + public MultiDocumentEntity> replaceDocuments(Collection values, DocumentReplaceOptions options, Class type) throws ArangoDBException { + return executor.execute(replaceDocumentsRequest(values, options), replaceDocumentsResponseDeserializer(type)); } @Override - public DocumentUpdateEntity updateDocument(final String key, final T value) throws ArangoDBException { - return updateDocument(key, value, new DocumentUpdateOptions()); + public DocumentUpdateEntity updateDocument(final String key, final Object value) throws ArangoDBException { + return updateDocument(key, value, new DocumentUpdateOptions(), Void.class); } @Override @@ -182,35 +205,39 @@ public DocumentUpdateEntity updateDocument( } @Override - public MultiDocumentEntity> updateDocuments(final Collection values) + public MultiDocumentEntity> updateDocuments(final Collection values) throws ArangoDBException { - return updateDocuments(values, new DocumentUpdateOptions()); + return updateDocuments(values, new DocumentUpdateOptions(), Void.class); } @Override @SuppressWarnings("unchecked") public MultiDocumentEntity> updateDocuments( final Collection values, final DocumentUpdateOptions options) throws ArangoDBException { - return updateDocuments(values, options, values.isEmpty() ? null : (Class) getCollectionContentClass(values)); + return updateDocuments(values, options, (Class) getCollectionContentClass(values)); } @Override public MultiDocumentEntity> updateDocuments( final Collection values, final DocumentUpdateOptions options, final Class returnType) throws ArangoDBException { - final DocumentUpdateOptions params = (options != null ? options : new DocumentUpdateOptions()); return executor - .execute(updateDocumentsRequest(values, params), updateDocumentsResponseDeserializer(returnType)); + .execute(updateDocumentsRequest(values, options), updateDocumentsResponseDeserializer(returnType)); } @Override public DocumentDeleteEntity deleteDocument(final String key) throws ArangoDBException { - return executor.execute(deleteDocumentRequest(key, new DocumentDeleteOptions()), - constructParametricType(DocumentDeleteEntity.class, Void.class)); + return deleteDocument(key, new DocumentDeleteOptions()); + } + + @Override + @SuppressWarnings("unchecked") + public DocumentDeleteEntity deleteDocument(String key, DocumentDeleteOptions options) throws ArangoDBException { + return deleteDocument(key, options, (Class) Void.class); } @Override public DocumentDeleteEntity deleteDocument( - final String key, final Class type, final DocumentDeleteOptions options) throws ArangoDBException { + final String key, final DocumentDeleteOptions options, final Class type) throws ArangoDBException { return executor.execute(deleteDocumentRequest(key, options), constructParametricType(DocumentDeleteEntity.class, type)); } @@ -218,13 +245,20 @@ public DocumentDeleteEntity deleteDocument( @Override public MultiDocumentEntity> deleteDocuments(final Collection values) throws ArangoDBException { - return executor.execute(deleteDocumentsRequest(values, new DocumentDeleteOptions()), - deleteDocumentsResponseDeserializer(Void.class)); + return deleteDocuments(values, new DocumentDeleteOptions(), Void.class); + } + + @Override + @SuppressWarnings("unchecked") + public MultiDocumentEntity> deleteDocuments( + final Collection values, final DocumentDeleteOptions options) + throws ArangoDBException { + return deleteDocuments(values, options, (Class) getCollectionContentClass(values)); } @Override public MultiDocumentEntity> deleteDocuments( - final Collection values, final Class type, final DocumentDeleteOptions options) + final Collection values, final DocumentDeleteOptions options, final Class type) throws ArangoDBException { return executor.execute(deleteDocumentsRequest(values, options), deleteDocumentsResponseDeserializer(type)); } diff --git a/src/main/java/com/arangodb/internal/InternalArangoCollection.java b/src/main/java/com/arangodb/internal/InternalArangoCollection.java index 0a46a5c12..55b4a993f 100644 --- a/src/main/java/com/arangodb/internal/InternalArangoCollection.java +++ b/src/main/java/com/arangodb/internal/InternalArangoCollection.java @@ -109,10 +109,8 @@ protected Request insertDocumentsRequest(final Collection values, final D return request; } - protected ResponseDeserializer>> insertDocumentsResponseDeserializer( - final Collection values, final DocumentCreateOptions params) { + protected ResponseDeserializer>> insertDocumentsResponseDeserializer(Class userDataClass) { return response -> { - Class userDataClass = getCollectionContentClass(values); final MultiDocumentEntity> multiDocument = new MultiDocumentEntity<>(); final Collection> docs = new ArrayList<>(); final Collection errors = new ArrayList<>(); @@ -243,9 +241,8 @@ protected Request replaceDocumentsRequest(final Collection values, final } protected ResponseDeserializer>> replaceDocumentsResponseDeserializer( - final Collection values) { + final Class returnType) { return response -> { - Class userDataClass = getCollectionContentClass(values); final MultiDocumentEntity> multiDocument = new MultiDocumentEntity<>(); final Collection> docs = new ArrayList<>(); final Collection errors = new ArrayList<>(); @@ -258,7 +255,7 @@ protected ResponseDeserializer>> errors.add(error); documentsAndErrors.add(error); } else { - Type type = constructParametricType(DocumentUpdateEntity.class, userDataClass); + Type type = constructParametricType(DocumentUpdateEntity.class, returnType); final DocumentUpdateEntity doc = getSerde().deserialize(next, type); docs.add(doc); documentsAndErrors.add(doc); diff --git a/src/main/java/com/arangodb/model/DocumentCreateOptions.java b/src/main/java/com/arangodb/model/DocumentCreateOptions.java index 8d796966a..b0722c541 100644 --- a/src/main/java/com/arangodb/model/DocumentCreateOptions.java +++ b/src/main/java/com/arangodb/model/DocumentCreateOptions.java @@ -86,11 +86,6 @@ public OverwriteMode getOverwriteMode() { } /** - * Limitations: - * - {@code keepNull} parameter is not supported - * - the fields having {@code null} value are always removed during serialization - * Therefore in case of {@link OverwriteMode#update}, existing attributes cannot be removed. - * * @param overwriteMode This parameter can be set to replace or update. If given it sets implicitly the overwrite * flag. In case it is set to update, the replace-insert becomes an update-insert. Otherwise * this option follows the rules of the overwrite parameter. diff --git a/src/test/java/com/arangodb/ArangoCollectionTest.java b/src/test/java/com/arangodb/ArangoCollectionTest.java index 5bb82657d..bf2196786 100644 --- a/src/test/java/com/arangodb/ArangoCollectionTest.java +++ b/src/test/java/com/arangodb/ArangoCollectionTest.java @@ -20,27 +20,15 @@ package com.arangodb; -import com.arangodb.entity.BaseDocument; -import com.arangodb.entity.BaseEdgeDocument; -import com.arangodb.entity.CollectionEntity; -import com.arangodb.entity.CollectionPropertiesEntity; -import com.arangodb.entity.CollectionRevisionEntity; -import com.arangodb.entity.DocumentCreateEntity; -import com.arangodb.entity.DocumentDeleteEntity; -import com.arangodb.entity.DocumentEntity; -import com.arangodb.entity.DocumentImportEntity; -import com.arangodb.entity.DocumentUpdateEntity; -import com.arangodb.entity.IndexEntity; -import com.arangodb.entity.IndexType; -import com.arangodb.entity.MultiDocumentEntity; -import com.arangodb.entity.Permissions; -import com.arangodb.entity.ShardEntity; +import com.arangodb.entity.*; import com.arangodb.model.*; import com.arangodb.model.DocumentImportOptions.OnDuplicate; +import com.arangodb.serde.JacksonSerde; import com.arangodb.util.MapBuilder; import com.arangodb.util.RawBytes; import com.arangodb.util.RawJson; import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonTypeInfo; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import org.junit.jupiter.api.BeforeAll; @@ -90,6 +78,78 @@ static void init() { initEdgeCollections(EDGE_COLLECTION_NAME); } + @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, property = "type") + public interface Animal { + String getKey(); + + String getName(); + } + + public static class Dog implements Animal { + + @Key + private String key; + private String name; + + public Dog() { + } + + public Dog(String key, String name) { + this.key = key; + this.name = name; + } + + @Override + public String getKey() { + return key; + } + + public void setKey(String key) { + this.key = key; + } + + @Override + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + } + + public static class Cat implements Animal { + @Key + private String key; + private String name; + + public Cat() { + } + + public Cat(String key, String name) { + this.key = key; + this.name = name; + } + + @Override + public String getKey() { + return key; + } + + public void setKey(String key) { + this.key = key; + } + + @Override + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + } + @ParameterizedTest(name = "{index}") @MethodSource("cols") void insertDocument(ArangoCollection collection) { @@ -160,6 +220,40 @@ void insertDocumentReturnNew(ArangoCollection collection) { assertThat(doc.getNew()).isNotNull(); } + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void insertDocumentWithTypeOverwriteModeReplace(ArangoCollection collection) { + assumeTrue(isAtLeastVersion(3, 7)); + assumeTrue(collection.getSerde().getUserSerde() instanceof JacksonSerde, "polymorphic deserialization support required"); + + String key = UUID.randomUUID().toString(); + Dog dog = new Dog(key, "Teddy"); + Cat cat = new Cat(key, "Luna"); + + final DocumentCreateOptions options = new DocumentCreateOptions() + .returnNew(true) + .returnOld(true) + .overwriteMode(OverwriteMode.replace); + collection.insertDocument(dog, options); + final DocumentCreateEntity doc = collection.insertDocument(cat, options, Animal.class); + assertThat(doc).isNotNull(); + assertThat(doc.getId()).isNotNull(); + assertThat(doc.getKey()).isNotNull().isEqualTo(key); + assertThat(doc.getRev()).isNotNull(); + + assertThat(doc.getOld()) + .isNotNull() + .isInstanceOf(Dog.class); + assertThat(doc.getOld().getKey()).isEqualTo(key); + assertThat(doc.getOld().getName()).isEqualTo("Teddy"); + + assertThat(doc.getNew()) + .isNotNull() + .isInstanceOf(Cat.class); + assertThat(doc.getNew().getKey()).isEqualTo(key); + assertThat(doc.getNew().getName()).isEqualTo("Luna"); + } + @ParameterizedTest(name = "{index}") @MethodSource("cols") void insertDocumentOverwriteModeIgnore(ArangoCollection collection) { @@ -168,7 +262,7 @@ void insertDocumentOverwriteModeIgnore(ArangoCollection collection) { String key = "key-" + UUID.randomUUID(); final BaseDocument doc = new BaseDocument(key); doc.addAttribute("foo", "a"); - final DocumentCreateEntity meta = collection.insertDocument(doc); + final DocumentCreateEntity meta = collection.insertDocument(doc); final BaseDocument doc2 = new BaseDocument(key); doc2.addAttribute("bar", "b"); @@ -204,7 +298,7 @@ void insertDocumentOverwriteModeReplace(ArangoCollection collection) { String key = "key-" + UUID.randomUUID(); final BaseDocument doc = new BaseDocument(key); doc.addAttribute("foo", "a"); - final DocumentCreateEntity meta = collection.insertDocument(doc); + final DocumentCreateEntity meta = collection.insertDocument(doc); final BaseDocument doc2 = new BaseDocument(key); doc2.addAttribute("bar", "b"); @@ -223,7 +317,7 @@ void insertDocumentOverwriteModeUpdate(ArangoCollection collection) { final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); doc.addAttribute("foo", "a"); - final DocumentCreateEntity meta = collection.insertDocument(doc); + final DocumentCreateEntity meta = collection.insertDocument(doc); doc.addAttribute("bar", "b"); final DocumentCreateEntity updated = collection.insertDocument(doc, new DocumentCreateOptions().overwriteMode(OverwriteMode.update).returnNew(true)); @@ -242,7 +336,7 @@ void insertDocumentOverwriteModeUpdateMergeObjectsFalse(ArangoCollection collect final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); Map fieldA = Collections.singletonMap("a", "a"); doc.addAttribute("foo", fieldA); - final DocumentCreateEntity meta = collection.insertDocument(doc); + final DocumentCreateEntity meta = collection.insertDocument(doc); Map fieldB = Collections.singletonMap("b", "b"); doc.addAttribute("foo", fieldB); @@ -270,7 +364,7 @@ void insertDocumentWaitForSync(ArangoCollection collection) { void insertDocumentAsJson(ArangoCollection collection) { String key = "doc-" + UUID.randomUUID(); RawJson rawJson = RawJson.of("{\"_key\":\"" + key + "\",\"a\":\"test\"}"); - final DocumentCreateEntity doc = collection.insertDocument(rawJson); + final DocumentCreateEntity doc = collection.insertDocument(rawJson); assertThat(doc).isNotNull(); assertThat(doc.getId()).isEqualTo(collection.name() + "/" + key); assertThat(doc.getKey()).isEqualTo(key); @@ -464,7 +558,7 @@ void getDocumentsWithCustomShardingKey(ArangoCollection c) { List values = IntStream.range(0, 10).mapToObj(String::valueOf).map(key -> new BaseDocument()).peek(it -> it.addAttribute("customField", rnd())).collect(Collectors.toList()); - MultiDocumentEntity> inserted = collection.insertDocuments(values); + MultiDocumentEntity> inserted = collection.insertDocuments(values); List insertedKeys = inserted.getDocuments().stream().map(DocumentEntity::getKey).collect(Collectors.toList()); final Collection documents = collection.getDocuments(insertedKeys, BaseDocument.class).getDocuments(); @@ -724,10 +818,10 @@ void updateDocumentSerializeNullTrue(ArangoCollection collection) { final TestUpdateEntity doc = new TestUpdateEntity(); doc.a = "foo"; doc.b = "foo"; - final DocumentCreateEntity createResult = collection.insertDocument(doc); + final DocumentCreateEntity createResult = collection.insertDocument(doc); final TestUpdateEntity patchDoc = new TestUpdateEntity(); patchDoc.a = "bar"; - final DocumentUpdateEntity updateResult = collection.updateDocument(createResult.getKey(), patchDoc); + final DocumentUpdateEntity updateResult = collection.updateDocument(createResult.getKey(), patchDoc); assertThat(updateResult).isNotNull(); assertThat(updateResult.getKey()).isEqualTo(createResult.getKey()); @@ -743,10 +837,10 @@ void updateDocumentSerializeNullFalse(ArangoCollection collection) { final TestUpdateEntitySerializeNullFalse doc = new TestUpdateEntitySerializeNullFalse(); doc.a = "foo"; doc.b = "foo"; - final DocumentCreateEntity createResult = collection.insertDocument(doc); + final DocumentCreateEntity createResult = collection.insertDocument(doc); final TestUpdateEntitySerializeNullFalse patchDoc = new TestUpdateEntitySerializeNullFalse(); patchDoc.a = "bar"; - final DocumentUpdateEntity updateResult = collection.updateDocument(createResult.getKey(), patchDoc); + final DocumentUpdateEntity updateResult = collection.updateDocument(createResult.getKey(), patchDoc); assertThat(updateResult).isNotNull(); assertThat(updateResult.getKey()).isEqualTo(createResult.getKey()); @@ -830,7 +924,7 @@ void updateDocumentIgnoreRevsFalse(ArangoCollection collection) { @MethodSource("cols") void updateDocumentSilent(ArangoCollection collection) { assumeTrue(isSingleServer()); - final DocumentCreateEntity createResult = collection.insertDocument(new BaseDocument()); + final DocumentCreateEntity createResult = collection.insertDocument(new BaseDocument()); final DocumentUpdateEntity meta = collection.updateDocument(createResult.getKey(), new BaseDocument(), new DocumentUpdateOptions().silent(true)); assertThat(meta).isNotNull(); assertThat(meta.getId()).isNull(); @@ -842,7 +936,7 @@ void updateDocumentSilent(ArangoCollection collection) { @MethodSource("cols") void updateDocumentsSilent(ArangoCollection collection) { assumeTrue(isSingleServer()); - final DocumentCreateEntity createResult = collection.insertDocument(new BaseDocument()); + final DocumentCreateEntity createResult = collection.insertDocument(new BaseDocument()); final MultiDocumentEntity> info = collection.updateDocuments(Collections.singletonList(new BaseDocument(createResult.getKey())), new DocumentUpdateOptions().silent(true)); assertThat(info).isNotNull(); assertThat(info.getDocuments()).isEmpty(); @@ -1020,7 +1114,7 @@ void replaceDocumentReturnOld(ArangoCollection collection) { @MethodSource("cols") void replaceDocumentSilent(ArangoCollection collection) { assumeTrue(isSingleServer()); - final DocumentCreateEntity createResult = collection.insertDocument(new BaseDocument()); + final DocumentCreateEntity createResult = collection.insertDocument(new BaseDocument()); final DocumentUpdateEntity meta = collection.replaceDocument(createResult.getKey(), new BaseDocument(), new DocumentReplaceOptions().silent(true)); assertThat(meta).isNotNull(); assertThat(meta.getId()).isNull(); @@ -1033,7 +1127,7 @@ void replaceDocumentSilent(ArangoCollection collection) { void replaceDocumentSilentDontTouchInstance(ArangoCollection collection) { assumeTrue(isSingleServer()); final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); - final DocumentCreateEntity createResult = collection.insertDocument(doc); + final DocumentCreateEntity createResult = collection.insertDocument(doc); final DocumentUpdateEntity meta = collection.replaceDocument(createResult.getKey(), doc, new DocumentReplaceOptions().silent(true)); assertThat(meta.getRev()).isNull(); assertThat(doc.getRevision()).isNull(); @@ -1044,7 +1138,7 @@ void replaceDocumentSilentDontTouchInstance(ArangoCollection collection) { @MethodSource("cols") void replaceDocumentsSilent(ArangoCollection collection) { assumeTrue(isSingleServer()); - final DocumentCreateEntity createResult = collection.insertDocument(new BaseDocument()); + final DocumentCreateEntity createResult = collection.insertDocument(new BaseDocument()); final MultiDocumentEntity> info = collection.replaceDocuments(Collections.singletonList(new BaseDocument(createResult.getKey())), new DocumentReplaceOptions().silent(true)); assertThat(info).isNotNull(); assertThat(info.getDocuments()).isEmpty(); @@ -1057,7 +1151,7 @@ void replaceDocumentsSilent(ArangoCollection collection) { void deleteDocument(ArangoCollection collection) { final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); final DocumentCreateEntity createResult = collection.insertDocument(doc, null); - collection.deleteDocument(createResult.getKey(), null, null); + collection.deleteDocument(createResult.getKey()); final BaseDocument document = collection.getDocument(createResult.getKey(), BaseDocument.class, null); assertThat(document).isNull(); } @@ -1069,7 +1163,7 @@ void deleteDocumentReturnOld(ArangoCollection collection) { doc.addAttribute("a", "test"); final DocumentCreateEntity createResult = collection.insertDocument(doc, null); final DocumentDeleteOptions options = new DocumentDeleteOptions().returnOld(true); - final DocumentDeleteEntity deleteResult = collection.deleteDocument(createResult.getKey(), BaseDocument.class, options); + final DocumentDeleteEntity deleteResult = collection.deleteDocument(createResult.getKey(), options, BaseDocument.class); assertThat(deleteResult.getOld()).isNotNull(); assertThat(deleteResult.getOld()).isInstanceOf(BaseDocument.class); assertThat(deleteResult.getOld().getAttribute("a")).isNotNull(); @@ -1082,7 +1176,7 @@ void deleteDocumentIfMatch(ArangoCollection collection) { final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); final DocumentCreateEntity createResult = collection.insertDocument(doc, null); final DocumentDeleteOptions options = new DocumentDeleteOptions().ifMatch(createResult.getRev()); - collection.deleteDocument(createResult.getKey(), null, options); + collection.deleteDocument(createResult.getKey(), options); final BaseDocument document = collection.getDocument(createResult.getKey(), BaseDocument.class, null); assertThat(document).isNull(); } @@ -1091,9 +1185,9 @@ void deleteDocumentIfMatch(ArangoCollection collection) { @MethodSource("cols") void deleteDocumentIfMatchFail(ArangoCollection collection) { final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); - final DocumentCreateEntity createResult = collection.insertDocument(doc, null); + final DocumentCreateEntity createResult = collection.insertDocument(doc); final DocumentDeleteOptions options = new DocumentDeleteOptions().ifMatch("no"); - Throwable thrown = catchThrowable(() -> collection.deleteDocument(createResult.getKey(), null, options)); + Throwable thrown = catchThrowable(() -> collection.deleteDocument(createResult.getKey(), options)); assertThat(thrown).isInstanceOf(ArangoDBException.class); } @@ -1101,8 +1195,8 @@ void deleteDocumentIfMatchFail(ArangoCollection collection) { @MethodSource("cols") void deleteDocumentSilent(ArangoCollection collection) { assumeTrue(isSingleServer()); - final DocumentCreateEntity createResult = collection.insertDocument(new BaseDocument()); - final DocumentDeleteEntity meta = collection.deleteDocument(createResult.getKey(), BaseDocument.class, new DocumentDeleteOptions().silent(true)); + final DocumentCreateEntity createResult = collection.insertDocument(new BaseDocument()); + final DocumentDeleteEntity meta = collection.deleteDocument(createResult.getKey(), new DocumentDeleteOptions().silent(true), BaseDocument.class); assertThat(meta).isNotNull(); assertThat(meta.getId()).isNull(); assertThat(meta.getKey()).isNull(); @@ -1113,8 +1207,11 @@ void deleteDocumentSilent(ArangoCollection collection) { @MethodSource("cols") void deleteDocumentsSilent(ArangoCollection collection) { assumeTrue(isSingleServer()); - final DocumentCreateEntity createResult = collection.insertDocument(new BaseDocument()); - final MultiDocumentEntity> info = collection.deleteDocuments(Collections.singletonList(createResult.getKey()), BaseDocument.class, new DocumentDeleteOptions().silent(true)); + final DocumentCreateEntity createResult = collection.insertDocument(new BaseDocument()); + final MultiDocumentEntity> info = collection.deleteDocuments( + Collections.singletonList(createResult.getKey()), + new DocumentDeleteOptions().silent(true), + BaseDocument.class); assertThat(info).isNotNull(); assertThat(info.getDocuments()).isEmpty(); assertThat(info.getDocumentsAndErrors()).isEmpty(); @@ -1696,7 +1793,7 @@ void documentExistsThrowExcpetion(ArangoCollection collection) { void documentExistsIfMatch(ArangoCollection collection) { String key = rnd(); RawJson rawJson = RawJson.of("{\"_key\":\"" + key + "\"}"); - final DocumentCreateEntity createResult = collection.insertDocument(rawJson); + final DocumentCreateEntity createResult = collection.insertDocument(rawJson); final DocumentExistsOptions options = new DocumentExistsOptions().ifMatch(createResult.getRev()); final Boolean exists = collection.documentExists(key, options); assertThat(exists).isTrue(); @@ -1729,7 +1826,7 @@ void documentExistsIfNoneMatch(ArangoCollection collection) { void documentExistsIfNoneMatchFail(ArangoCollection collection) { String key = rnd(); RawJson rawJson = RawJson.of("{\"_key\":\"" + key + "\"}"); - final DocumentCreateEntity createResult = collection.insertDocument(rawJson); + final DocumentCreateEntity createResult = collection.insertDocument(rawJson); final DocumentExistsOptions options = new DocumentExistsOptions().ifNoneMatch(createResult.getRev()); final Boolean exists = collection.documentExists(key, options); assertThat(exists).isFalse(); @@ -1740,7 +1837,7 @@ void documentExistsIfNoneMatchFail(ArangoCollection collection) { void insertDocuments(ArangoCollection collection) { final Collection values = Arrays.asList(new BaseDocument(), new BaseDocument(), new BaseDocument()); - final MultiDocumentEntity> docs = collection.insertDocuments(values, null); + final MultiDocumentEntity docs = collection.insertDocuments(values); assertThat(docs).isNotNull(); assertThat(docs.getDocuments()).isNotNull(); assertThat(docs.getDocuments()).hasSize(3); @@ -1755,11 +1852,11 @@ void insertDocumentsOverwriteModeUpdate(ArangoCollection collection) { final BaseDocument doc1 = new BaseDocument(UUID.randomUUID().toString()); doc1.addAttribute("foo", "a"); - final DocumentCreateEntity meta1 = collection.insertDocument(doc1); + final DocumentCreateEntity meta1 = collection.insertDocument(doc1); final BaseDocument doc2 = new BaseDocument(UUID.randomUUID().toString()); doc2.addAttribute("foo", "a"); - final DocumentCreateEntity meta2 = collection.insertDocument(doc2); + final DocumentCreateEntity meta2 = collection.insertDocument(doc2); doc1.addAttribute("bar", "b"); doc2.addAttribute("bar", "b"); @@ -1783,7 +1880,7 @@ void insertDocumentsJson(ArangoCollection collection) { values.add(RawJson.of("{}")); values.add(RawJson.of("{}")); values.add(RawJson.of("{}")); - final MultiDocumentEntity> docs = collection.insertDocuments(values); + final MultiDocumentEntity docs = collection.insertDocuments(values); assertThat(docs).isNotNull(); assertThat(docs.getDocuments()).isNotNull(); assertThat(docs.getDocuments()).hasSize(3); @@ -1796,7 +1893,7 @@ void insertDocumentsJson(ArangoCollection collection) { void insertDocumentsOne(ArangoCollection collection) { final Collection values = new ArrayList<>(); values.add(new BaseDocument()); - final MultiDocumentEntity> docs = collection.insertDocuments(values, null); + final MultiDocumentEntity docs = collection.insertDocuments(values); assertThat(docs).isNotNull(); assertThat(docs.getDocuments()).isNotNull(); assertThat(docs.getDocuments()).hasSize(1); @@ -1808,7 +1905,7 @@ void insertDocumentsOne(ArangoCollection collection) { @MethodSource("cols") void insertDocumentsEmpty(ArangoCollection collection) { final Collection values = new ArrayList<>(); - final MultiDocumentEntity> docs = collection.insertDocuments(values, null); + final MultiDocumentEntity docs = collection.insertDocuments(values); assertThat(docs).isNotNull(); assertThat(docs.getDocuments()).isNotNull(); assertThat(docs.getDocuments()).isEmpty(); @@ -1845,7 +1942,7 @@ void insertDocumentsFail(ArangoCollection collection) { String k2 = rnd(); final Collection values = Arrays.asList(new BaseDocument(k1), new BaseDocument(k2), new BaseDocument(k2)); - final MultiDocumentEntity> docs = collection.insertDocuments(values); + final MultiDocumentEntity docs = collection.insertDocuments(values); assertThat(docs).isNotNull(); assertThat(docs.getDocuments()).isNotNull(); assertThat(docs.getDocuments()).hasSize(2); @@ -2246,14 +2343,14 @@ void deleteDocumentsByKey(ArangoCollection collection) { e.setKey("2"); values.add(e); } - collection.insertDocuments(values, null); + collection.insertDocuments(values); final Collection keys = new ArrayList<>(); keys.add("1"); keys.add("2"); - final MultiDocumentEntity> deleteResult = collection.deleteDocuments(keys, null, null); + final MultiDocumentEntity> deleteResult = collection.deleteDocuments(keys); assertThat(deleteResult).isNotNull(); assertThat(deleteResult.getDocuments()).hasSize(2); - for (final DocumentDeleteEntity i : deleteResult.getDocuments()) { + for (final DocumentDeleteEntity i : deleteResult.getDocuments()) { assertThat(i.getKey()).isIn("1", "2"); } assertThat(deleteResult.getErrors()).isEmpty(); @@ -2273,11 +2370,11 @@ void deleteDocumentsByDocuments(ArangoCollection collection) { e.setKey("2"); values.add(e); } - collection.insertDocuments(values, null); - final MultiDocumentEntity> deleteResult = collection.deleteDocuments(values, null, null); + collection.insertDocuments(values); + MultiDocumentEntity> deleteResult = collection.deleteDocuments(values); assertThat(deleteResult).isNotNull(); assertThat(deleteResult.getDocuments()).hasSize(2); - for (final DocumentDeleteEntity i : deleteResult.getDocuments()) { + for (final DocumentDeleteEntity i : deleteResult.getDocuments()) { assertThat(i.getKey()).isIn("1", "2"); } assertThat(deleteResult.getErrors()).isEmpty(); @@ -2292,13 +2389,13 @@ void deleteDocumentsByKeyOne(ArangoCollection collection) { e.setKey("1"); values.add(e); } - collection.insertDocuments(values, null); + collection.insertDocuments(values); final Collection keys = new ArrayList<>(); keys.add("1"); - final MultiDocumentEntity> deleteResult = collection.deleteDocuments(keys, null, null); + final MultiDocumentEntity> deleteResult = collection.deleteDocuments(keys); assertThat(deleteResult).isNotNull(); assertThat(deleteResult.getDocuments()).hasSize(1); - for (final DocumentDeleteEntity i : deleteResult.getDocuments()) { + for (final DocumentDeleteEntity i : deleteResult.getDocuments()) { assertThat(i.getKey()).isEqualTo("1"); } assertThat(deleteResult.getErrors()).isEmpty(); @@ -2313,11 +2410,11 @@ void deleteDocumentsByDocumentOne(ArangoCollection collection) { e.setKey("1"); values.add(e); } - collection.insertDocuments(values, null); - final MultiDocumentEntity> deleteResult = collection.deleteDocuments(values, null, null); + collection.insertDocuments(values); + final MultiDocumentEntity> deleteResult = collection.deleteDocuments(values); assertThat(deleteResult).isNotNull(); assertThat(deleteResult.getDocuments()).hasSize(1); - for (final DocumentDeleteEntity i : deleteResult.getDocuments()) { + for (final DocumentDeleteEntity i : deleteResult.getDocuments()) { assertThat(i.getKey()).isEqualTo("1"); } assertThat(deleteResult.getErrors()).isEmpty(); @@ -2327,9 +2424,9 @@ void deleteDocumentsByDocumentOne(ArangoCollection collection) { @MethodSource("cols") void deleteDocumentsEmpty(ArangoCollection collection) { final Collection values = new ArrayList<>(); - collection.insertDocuments(values, null); + collection.insertDocuments(values); final Collection keys = new ArrayList<>(); - final MultiDocumentEntity> deleteResult = collection.deleteDocuments(keys, null, null); + final MultiDocumentEntity deleteResult = collection.deleteDocuments(keys); assertThat(deleteResult).isNotNull(); assertThat(deleteResult.getDocuments()).isEmpty(); assertThat(deleteResult.getErrors()).isEmpty(); @@ -2339,10 +2436,10 @@ void deleteDocumentsEmpty(ArangoCollection collection) { @MethodSource("cols") void deleteDocumentsByKeyNotExisting(ArangoCollection collection) { final Collection values = new ArrayList<>(); - collection.insertDocuments(values, null); + collection.insertDocuments(values); final Collection keys = Arrays.asList(rnd(), rnd()); - final MultiDocumentEntity> deleteResult = collection.deleteDocuments(keys, null, null); + final MultiDocumentEntity deleteResult = collection.deleteDocuments(keys); assertThat(deleteResult).isNotNull(); assertThat(deleteResult.getDocuments()).isEmpty(); assertThat(deleteResult.getErrors()).hasSize(2); @@ -2362,7 +2459,7 @@ void deleteDocumentsByDocumentsNotExisting(ArangoCollection collection) { e.setKey("2"); values.add(e); } - final MultiDocumentEntity> deleteResult = collection.deleteDocuments(values, null, null); + final MultiDocumentEntity deleteResult = collection.deleteDocuments(values); assertThat(deleteResult).isNotNull(); assertThat(deleteResult.getDocuments()).isEmpty(); assertThat(deleteResult.getErrors()).hasSize(2); @@ -2372,10 +2469,10 @@ void deleteDocumentsByDocumentsNotExisting(ArangoCollection collection) { @MethodSource("cols") void updateDocuments(ArangoCollection collection) { final Collection values = Arrays.asList(new BaseDocument(rnd()), new BaseDocument(rnd())); - collection.insertDocuments(values, null); + collection.insertDocuments(values); values.forEach(it -> it.addAttribute("a", "test")); - final MultiDocumentEntity> updateResult = collection.updateDocuments(values, null); + final MultiDocumentEntity updateResult = collection.updateDocuments(values); assertThat(updateResult.getDocuments()).hasSize(2); assertThat(updateResult.getErrors()).isEmpty(); } @@ -2411,12 +2508,12 @@ void updateDocumentsOne(ArangoCollection collection) { e.setKey("1"); values.add(e); } - collection.insertDocuments(values, null); + collection.insertDocuments(values); final Collection updatedValues = new ArrayList<>(); final BaseDocument first = values.iterator().next(); first.addAttribute("a", "test"); updatedValues.add(first); - final MultiDocumentEntity> updateResult = collection.updateDocuments(updatedValues, null); + final MultiDocumentEntity updateResult = collection.updateDocuments(updatedValues); assertThat(updateResult.getDocuments()).hasSize(1); assertThat(updateResult.getErrors()).isEmpty(); } @@ -2425,7 +2522,7 @@ void updateDocumentsOne(ArangoCollection collection) { @MethodSource("cols") void updateDocumentsEmpty(ArangoCollection collection) { final Collection values = new ArrayList<>(); - final MultiDocumentEntity> updateResult = collection.updateDocuments(values, null); + final MultiDocumentEntity updateResult = collection.updateDocuments(values); assertThat(updateResult.getDocuments()).isEmpty(); assertThat(updateResult.getErrors()).isEmpty(); } @@ -2437,14 +2534,14 @@ void updateDocumentsWithoutKey(ArangoCollection collection) { { values.add(new BaseDocument("1")); } - collection.insertDocuments(values, null); + collection.insertDocuments(values); final Collection updatedValues = new ArrayList<>(); for (final BaseDocument i : values) { i.addAttribute("a", "test"); updatedValues.add(i); } updatedValues.add(new BaseDocument()); - final MultiDocumentEntity> updateResult = collection.updateDocuments(updatedValues, null); + final MultiDocumentEntity updateResult = collection.updateDocuments(updatedValues); assertThat(updateResult.getDocuments()).hasSize(1); assertThat(updateResult.getErrors()).hasSize(1); } @@ -2460,7 +2557,7 @@ void updateDocumentsJson(ArangoCollection collection) { final Collection updatedValues = new ArrayList<>(); updatedValues.add(RawJson.of("{\"_key\":\"1\", \"foo\":\"bar\"}")); updatedValues.add(RawJson.of("{\"_key\":\"2\", \"foo\":\"bar\"}")); - final MultiDocumentEntity> updateResult = collection.updateDocuments(updatedValues); + final MultiDocumentEntity updateResult = collection.updateDocuments(updatedValues); assertThat(updateResult.getDocuments()).hasSize(2); assertThat(updateResult.getErrors()).isEmpty(); } @@ -2473,13 +2570,13 @@ void replaceDocuments(ArangoCollection collection) { values.add(new BaseDocument("1")); values.add(new BaseDocument("2")); } - collection.insertDocuments(values, null); + collection.insertDocuments(values); final Collection updatedValues = new ArrayList<>(); for (final BaseDocument i : values) { i.addAttribute("a", "test"); updatedValues.add(i); } - final MultiDocumentEntity> updateResult = collection.replaceDocuments(updatedValues, null); + final MultiDocumentEntity updateResult = collection.replaceDocuments(updatedValues); assertThat(updateResult.getDocuments()).hasSize(2); assertThat(updateResult.getErrors()).isEmpty(); } @@ -2493,12 +2590,12 @@ void replaceDocumentsOne(ArangoCollection collection) { e.setKey("1"); values.add(e); } - collection.insertDocuments(values, null); + collection.insertDocuments(values); final Collection updatedValues = new ArrayList<>(); final BaseDocument first = values.iterator().next(); first.addAttribute("a", "test"); updatedValues.add(first); - final MultiDocumentEntity> updateResult = collection.updateDocuments(updatedValues, null); + final MultiDocumentEntity updateResult = collection.updateDocuments(updatedValues); assertThat(updateResult.getDocuments()).hasSize(1); assertThat(updateResult.getErrors()).isEmpty(); } @@ -2507,7 +2604,7 @@ void replaceDocumentsOne(ArangoCollection collection) { @MethodSource("cols") void replaceDocumentsEmpty(ArangoCollection collection) { final Collection values = new ArrayList<>(); - final MultiDocumentEntity> updateResult = collection.updateDocuments(values, null); + final MultiDocumentEntity updateResult = collection.updateDocuments(values); assertThat(updateResult.getDocuments()).isEmpty(); assertThat(updateResult.getErrors()).isEmpty(); } @@ -2519,14 +2616,14 @@ void replaceDocumentsWithoutKey(ArangoCollection collection) { { values.add(new BaseDocument("1")); } - collection.insertDocuments(values, null); + collection.insertDocuments(values); final Collection updatedValues = new ArrayList<>(); for (final BaseDocument i : values) { i.addAttribute("a", "test"); updatedValues.add(i); } updatedValues.add(new BaseDocument()); - final MultiDocumentEntity> updateResult = collection.updateDocuments(updatedValues, null); + final MultiDocumentEntity updateResult = collection.updateDocuments(updatedValues); assertThat(updateResult.getDocuments()).hasSize(1); assertThat(updateResult.getErrors()).hasSize(1); } @@ -2542,7 +2639,7 @@ void replaceDocumentsJson(ArangoCollection collection) { final Collection updatedValues = new ArrayList<>(); updatedValues.add(RawJson.of("{\"_key\":\"1\", \"foo\":\"bar\"}")); updatedValues.add(RawJson.of("{\"_key\":\"2\", \"foo\":\"bar\"}")); - final MultiDocumentEntity> updateResult = collection.replaceDocuments(updatedValues); + final MultiDocumentEntity updateResult = collection.replaceDocuments(updatedValues); assertThat(updateResult.getDocuments()).hasSize(2); assertThat(updateResult.getErrors()).isEmpty(); } diff --git a/src/test/java/com/arangodb/DocumentTest.java b/src/test/java/com/arangodb/DocumentTest.java index 55f0724f0..a921a213d 100644 --- a/src/test/java/com/arangodb/DocumentTest.java +++ b/src/test/java/com/arangodb/DocumentTest.java @@ -83,7 +83,7 @@ void insertAsJson(ArangoCollection collection) { + "}" ); //@formatter:on - final DocumentCreateEntity createResult = collection.insertDocument(json); + final DocumentCreateEntity createResult = collection.insertDocument(json); final BaseDocument doc = collection.getDocument(createResult.getKey(), BaseDocument.class); assertThat(doc).isNotNull(); final Object article = doc.getAttribute("article"); @@ -116,7 +116,7 @@ void insertAsBaseDocument(ArangoCollection collection) { stock.addAttribute("status", "RMV"); stock.addAttribute("lastUpdate", "2016-11-01 00:00"); } - final DocumentCreateEntity createResult = collection.insertDocument(document); + final DocumentCreateEntity createResult = collection.insertDocument(document); final BaseDocument doc = collection.getDocument(createResult.getKey(), BaseDocument.class); assertThat(doc).isNotNull(); final Object article = doc.getAttribute("article"); @@ -131,7 +131,7 @@ void insertAsBaseDocument(ArangoCollection collection) { void documentKeyWithSpecialChars(ArangoCollection collection) { final String key = "_-:.@()+,=;$!*'%" + UUID.randomUUID(); final BaseDocument document = new BaseDocument(key); - final DocumentCreateEntity createResult = collection.insertDocument(document); + final DocumentCreateEntity createResult = collection.insertDocument(document); final BaseDocument doc = collection.getDocument(createResult.getKey(), BaseDocument.class); assertThat(doc).isNotNull(); assertThat(doc.getKey()).isEqualTo(key); diff --git a/src/test/java/com/arangodb/StreamTransactionTest.java b/src/test/java/com/arangodb/StreamTransactionTest.java index d17d9e6d7..bc52a0673 100644 --- a/src/test/java/com/arangodb/StreamTransactionTest.java +++ b/src/test/java/com/arangodb/StreamTransactionTest.java @@ -552,7 +552,7 @@ void deleteDocument(ArangoDatabase db) { // delete document from within the tx collection - .deleteDocument(createdDoc.getKey(), null, new DocumentDeleteOptions().streamTransactionId(tx.getId())); + .deleteDocument(createdDoc.getKey(), new DocumentDeleteOptions().streamTransactionId(tx.getId())); // assert that the document has not been deleted from outside the tx assertThat(collection.getDocument(createdDoc.getKey(), BaseDocument.class, null)).isNotNull(); @@ -576,7 +576,7 @@ void deleteDocuments(ArangoDatabase db) { ArangoCollection collection = db.collection(COLLECTION_NAME); List keys = collection - .insertDocuments(Arrays.asList(new BaseDocument(), new BaseDocument(), new BaseDocument()), null) + .insertDocuments(Arrays.asList(new BaseDocument(), new BaseDocument(), new BaseDocument())) .getDocuments().stream().map(DocumentEntity::getKey).collect(Collectors.toList()); StreamTransactionEntity tx = db.beginStreamTransaction( @@ -584,7 +584,7 @@ void deleteDocuments(ArangoDatabase db) { // delete document from within the tx collection - .deleteDocuments(keys, null, new DocumentDeleteOptions().streamTransactionId(tx.getId())); + .deleteDocuments(keys, new DocumentDeleteOptions().streamTransactionId(tx.getId())); // assert that the documents has not been deleted from outside the tx assertThat(collection.getDocuments(keys, BaseDocument.class, null).getDocuments()).hasSize(keys.size()); diff --git a/src/test/java/com/arangodb/async/ArangoCollectionTest.java b/src/test/java/com/arangodb/async/ArangoCollectionTest.java index db72e4e42..1024dc609 100644 --- a/src/test/java/com/arangodb/async/ArangoCollectionTest.java +++ b/src/test/java/com/arangodb/async/ArangoCollectionTest.java @@ -20,14 +20,19 @@ package com.arangodb.async; +import com.arangodb.ArangoCollection; import com.arangodb.ArangoDBException; import com.arangodb.entity.*; import com.arangodb.model.*; import com.arangodb.model.DocumentImportOptions.OnDuplicate; +import com.arangodb.serde.JacksonSerde; import com.arangodb.util.RawJson; +import com.fasterxml.jackson.annotation.JsonTypeInfo; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; import java.util.*; import java.util.concurrent.CompletableFuture; @@ -48,6 +53,78 @@ class ArangoCollectionTest extends BaseTest { private static final String COLLECTION_NAME = "db_collection_test"; + @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, property = "type") + public interface Animal { + String getKey(); + + String getName(); + } + + public static class Dog implements Animal { + + @Key + private String key; + private String name; + + public Dog() { + } + + public Dog(String key, String name) { + this.key = key; + this.name = name; + } + + @Override + public String getKey() { + return key; + } + + public void setKey(String key) { + this.key = key; + } + + @Override + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + } + + public static class Cat implements Animal { + @Key + private String key; + private String name; + + public Cat() { + } + + public Cat(String key, String name) { + this.key = key; + this.name = name; + } + + @Override + public String getKey() { + return key; + } + + public void setKey(String key) { + this.key = key; + } + + @Override + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + } + ArangoCollectionTest() throws ExecutionException, InterruptedException { ArangoCollectionAsync collection = db.collection(COLLECTION_NAME); if (!collection.exists().get()) { @@ -103,6 +180,41 @@ void insertDocumentReturnNew() throws InterruptedException, ExecutionException { .get(); } + + @Test + void insertDocumentWithTypeOverwriteModeReplace() throws InterruptedException, ExecutionException { + assumeTrue(isAtLeastVersion(3, 7)); + assumeTrue(db.getSerde().getUserSerde() instanceof JacksonSerde, "polymorphic deserialization support required"); + ArangoCollectionAsync collection = db.collection(COLLECTION_NAME); + String key = UUID.randomUUID().toString(); + Dog dog = new Dog(key, "Teddy"); + Cat cat = new Cat(key, "Luna"); + + final DocumentCreateOptions options = new DocumentCreateOptions() + .returnNew(true) + .returnOld(true) + .overwriteMode(OverwriteMode.replace); + collection.insertDocument(dog, options).get(); + final DocumentCreateEntity doc = collection.insertDocument(cat, options, Animal.class).get(); + assertThat(doc).isNotNull(); + assertThat(doc.getId()).isNotNull(); + assertThat(doc.getKey()).isNotNull().isEqualTo(key); + assertThat(doc.getRev()).isNotNull(); + + assertThat(doc.getOld()) + .isNotNull() + .isInstanceOf(Dog.class); + assertThat(doc.getOld().getKey()).isEqualTo(key); + assertThat(doc.getOld().getName()).isEqualTo("Teddy"); + + assertThat(doc.getNew()) + .isNotNull() + .isInstanceOf(Cat.class); + assertThat(doc.getNew().getKey()).isEqualTo(key); + assertThat(doc.getNew().getName()).isEqualTo("Luna"); + } + + @Test void insertDocumentWaitForSync() throws InterruptedException, ExecutionException { final DocumentCreateOptions options = new DocumentCreateOptions().waitForSync(true); @@ -679,7 +791,7 @@ void deleteDocument() throws InterruptedException, ExecutionException { final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); final DocumentCreateEntity createResult = db.collection(COLLECTION_NAME).insertDocument(doc, null) .get(); - db.collection(COLLECTION_NAME).deleteDocument(createResult.getKey(), null, null).get(); + db.collection(COLLECTION_NAME).deleteDocument(createResult.getKey()).get(); db.collection(COLLECTION_NAME).getDocument(createResult.getKey(), BaseDocument.class, null) .whenComplete((document, ex) -> assertThat(document).isNull()) .get(); @@ -692,7 +804,7 @@ void deleteDocumentReturnOld() throws InterruptedException, ExecutionException { final DocumentCreateEntity createResult = db.collection(COLLECTION_NAME).insertDocument(doc, null) .get(); final DocumentDeleteOptions options = new DocumentDeleteOptions().returnOld(true); - db.collection(COLLECTION_NAME).deleteDocument(createResult.getKey(), BaseDocument.class, options) + db.collection(COLLECTION_NAME).deleteDocument(createResult.getKey(), options, BaseDocument.class) .whenComplete((deleteResult, ex) -> { assertThat(deleteResult.getOld()).isNotNull(); assertThat(deleteResult.getOld()).isInstanceOf(BaseDocument.class); @@ -708,7 +820,7 @@ void deleteDocumentIfMatch() throws InterruptedException, ExecutionException { final DocumentCreateEntity createResult = db.collection(COLLECTION_NAME).insertDocument(doc, null) .get(); final DocumentDeleteOptions options = new DocumentDeleteOptions().ifMatch(createResult.getRev()); - db.collection(COLLECTION_NAME).deleteDocument(createResult.getKey(), null, options).get(); + db.collection(COLLECTION_NAME).deleteDocument(createResult.getKey(), options).get(); db.collection(COLLECTION_NAME).getDocument(createResult.getKey(), BaseDocument.class, null) .whenComplete((document, ex) -> assertThat(document).isNull()) .get(); @@ -721,7 +833,7 @@ void deleteDocumentIfMatchFail() throws InterruptedException, ExecutionException .get(); final DocumentDeleteOptions options = new DocumentDeleteOptions().ifMatch("no"); try { - db.collection(COLLECTION_NAME).deleteDocument(createResult.getKey(), null, options).get(); + db.collection(COLLECTION_NAME).deleteDocument(createResult.getKey(), options).get(); fail(); } catch (final ExecutionException e) { assertThat(e.getCause()).isInstanceOf(ArangoDBException.class); @@ -1273,7 +1385,7 @@ void documentExists() throws InterruptedException, ExecutionException { @Test void documentExistsIfMatch() throws InterruptedException, ExecutionException { - final DocumentCreateEntity createResult = db.collection(COLLECTION_NAME) + final DocumentCreateEntity createResult = db.collection(COLLECTION_NAME) .insertDocument(RawJson.of("{\"_key\":\"abc\"}")).get(); final DocumentExistsOptions options = new DocumentExistsOptions().ifMatch(createResult.getRev()); db.collection(COLLECTION_NAME).documentExists("abc", options) @@ -1301,7 +1413,7 @@ void documentExistsIfNoneMatch() throws InterruptedException, ExecutionException @Test void documentExistsIfNoneMatchFail() throws InterruptedException, ExecutionException { - final DocumentCreateEntity createResult = db.collection(COLLECTION_NAME) + final DocumentCreateEntity createResult = db.collection(COLLECTION_NAME) .insertDocument(RawJson.of("{\"_key\":\"abc\"}")).get(); final DocumentExistsOptions options = new DocumentExistsOptions().ifNoneMatch(createResult.getRev()); db.collection(COLLECTION_NAME).documentExists("abc", options) @@ -1315,7 +1427,7 @@ void insertDocuments() throws InterruptedException, ExecutionException { values.add(new BaseDocument()); values.add(new BaseDocument()); values.add(new BaseDocument()); - db.collection(COLLECTION_NAME).insertDocuments(values, null) + db.collection(COLLECTION_NAME).insertDocuments(values) .whenComplete((docs, ex) -> { assertThat(docs).isNotNull(); assertThat(docs.getDocuments()).isNotNull(); @@ -1330,7 +1442,7 @@ void insertDocuments() throws InterruptedException, ExecutionException { void insertDocumentsOne() throws InterruptedException, ExecutionException { final Collection values = new ArrayList<>(); values.add(new BaseDocument()); - db.collection(COLLECTION_NAME).insertDocuments(values, null) + db.collection(COLLECTION_NAME).insertDocuments(values) .whenComplete((docs, ex) -> { assertThat(docs).isNotNull(); assertThat(docs.getDocuments()).isNotNull(); @@ -1344,7 +1456,7 @@ void insertDocumentsOne() throws InterruptedException, ExecutionException { @Test void insertDocumentsEmpty() throws InterruptedException, ExecutionException { final Collection values = new ArrayList<>(); - db.collection(COLLECTION_NAME).insertDocuments(values, null) + db.collection(COLLECTION_NAME).insertDocuments(values) .whenComplete((docs, ex) -> { assertThat(docs).isNotNull(); assertThat(docs.getDocuments()).isNotNull(); @@ -1783,15 +1895,15 @@ void deleteDocumentsByKey() throws InterruptedException, ExecutionException { e.setKey("2"); values.add(e); } - db.collection(COLLECTION_NAME).insertDocuments(values, null).get(); + db.collection(COLLECTION_NAME).insertDocuments(values).get(); final Collection keys = new ArrayList<>(); keys.add("1"); keys.add("2"); - db.collection(COLLECTION_NAME).deleteDocuments(keys, null, null) + db.collection(COLLECTION_NAME).deleteDocuments(keys) .whenComplete((deleteResult, ex) -> { assertThat(deleteResult).isNotNull(); assertThat(deleteResult.getDocuments().size()).isEqualTo(2); - for (final DocumentDeleteEntity i : deleteResult.getDocuments()) { + for (final DocumentDeleteEntity i : deleteResult.getDocuments()) { assertThat(i.getKey()).isIn("1", "2"); } assertThat(deleteResult.getErrors().size()).isEqualTo(0); @@ -1812,12 +1924,12 @@ void deleteDocumentsByDocuments() throws InterruptedException, ExecutionExceptio e.setKey("2"); values.add(e); } - db.collection(COLLECTION_NAME).insertDocuments(values, null).get(); - db.collection(COLLECTION_NAME).deleteDocuments(values, null, null) + db.collection(COLLECTION_NAME).insertDocuments(values).get(); + db.collection(COLLECTION_NAME).deleteDocuments(values) .whenComplete((deleteResult, ex) -> { assertThat(deleteResult).isNotNull(); assertThat(deleteResult.getDocuments().size()).isEqualTo(2); - for (final DocumentDeleteEntity i : deleteResult.getDocuments()) { + for (final DocumentDeleteEntity i : deleteResult.getDocuments()) { assertThat(i.getKey()).isIn("1", "2"); } assertThat(deleteResult.getErrors().size()).isEqualTo(0); @@ -1833,14 +1945,14 @@ void deleteDocumentsByKeyOne() throws InterruptedException, ExecutionException { e.setKey("1"); values.add(e); } - db.collection(COLLECTION_NAME).insertDocuments(values, null).get(); + db.collection(COLLECTION_NAME).insertDocuments(values).get(); final Collection keys = new ArrayList<>(); keys.add("1"); - db.collection(COLLECTION_NAME).deleteDocuments(keys, null, null) + db.collection(COLLECTION_NAME).deleteDocuments(keys) .whenComplete((deleteResult, ex) -> { assertThat(deleteResult).isNotNull(); assertThat(deleteResult.getDocuments().size()).isEqualTo(1); - for (final DocumentDeleteEntity i : deleteResult.getDocuments()) { + for (final DocumentDeleteEntity i : deleteResult.getDocuments()) { assertThat(i.getKey()).isEqualTo("1"); } assertThat(deleteResult.getErrors().size()).isEqualTo(0); @@ -1856,12 +1968,12 @@ void deleteDocumentsByDocumentOne() throws InterruptedException, ExecutionExcept e.setKey("1"); values.add(e); } - db.collection(COLLECTION_NAME).insertDocuments(values, null).get(); - db.collection(COLLECTION_NAME).deleteDocuments(values, null, null) + db.collection(COLLECTION_NAME).insertDocuments(values).get(); + db.collection(COLLECTION_NAME).deleteDocuments(values) .whenComplete((deleteResult, ex) -> { assertThat(deleteResult).isNotNull(); assertThat(deleteResult.getDocuments().size()).isEqualTo(1); - for (final DocumentDeleteEntity i : deleteResult.getDocuments()) { + for (final DocumentDeleteEntity i : deleteResult.getDocuments()) { assertThat(i.getKey()).isEqualTo("1"); } assertThat(deleteResult.getErrors().size()).isEqualTo(0); @@ -1872,9 +1984,9 @@ void deleteDocumentsByDocumentOne() throws InterruptedException, ExecutionExcept @Test void deleteDocumentsEmpty() throws InterruptedException, ExecutionException { final Collection values = new ArrayList<>(); - db.collection(COLLECTION_NAME).insertDocuments(values, null).get(); + db.collection(COLLECTION_NAME).insertDocuments(values).get(); final Collection keys = new ArrayList<>(); - db.collection(COLLECTION_NAME).deleteDocuments(keys, null, null) + db.collection(COLLECTION_NAME).deleteDocuments(keys) .whenComplete((deleteResult, ex) -> { assertThat(deleteResult).isNotNull(); assertThat(deleteResult.getDocuments().size()).isEqualTo(0); @@ -1886,11 +1998,11 @@ void deleteDocumentsEmpty() throws InterruptedException, ExecutionException { @Test void deleteDocumentsByKeyNotExisting() throws InterruptedException, ExecutionException { final Collection values = new ArrayList<>(); - db.collection(COLLECTION_NAME).insertDocuments(values, null).get(); + db.collection(COLLECTION_NAME).insertDocuments(values).get(); final Collection keys = new ArrayList<>(); keys.add("1"); keys.add("2"); - db.collection(COLLECTION_NAME).deleteDocuments(keys, null, null) + db.collection(COLLECTION_NAME).deleteDocuments(keys) .whenComplete((deleteResult, ex) -> { assertThat(deleteResult).isNotNull(); assertThat(deleteResult.getDocuments().size()).isEqualTo(0); @@ -1912,7 +2024,7 @@ void deleteDocumentsByDocumentsNotExisting() throws InterruptedException, Execut e.setKey("2"); values.add(e); } - db.collection(COLLECTION_NAME).deleteDocuments(values, null, null) + db.collection(COLLECTION_NAME).deleteDocuments(values) .whenComplete((deleteResult, ex) -> { assertThat(deleteResult).isNotNull(); assertThat(deleteResult.getDocuments().size()).isEqualTo(0); @@ -1934,13 +2046,13 @@ void updateDocuments() throws InterruptedException, ExecutionException { e.setKey("2"); values.add(e); } - db.collection(COLLECTION_NAME).insertDocuments(values, null).get(); + db.collection(COLLECTION_NAME).insertDocuments(values).get(); final Collection updatedValues = new ArrayList<>(); for (final BaseDocument i : values) { i.addAttribute("a", "test"); updatedValues.add(i); } - db.collection(COLLECTION_NAME).updateDocuments(updatedValues, null) + db.collection(COLLECTION_NAME).updateDocuments(updatedValues) .whenComplete((updateResult, ex) -> { assertThat(updateResult.getDocuments().size()).isEqualTo(2); assertThat(updateResult.getErrors().size()).isEqualTo(0); @@ -1987,12 +2099,12 @@ void updateDocumentsOne() throws InterruptedException, ExecutionException { e.setKey("1"); values.add(e); } - db.collection(COLLECTION_NAME).insertDocuments(values, null).get(); + db.collection(COLLECTION_NAME).insertDocuments(values).get(); final Collection updatedValues = new ArrayList<>(); final BaseDocument first = values.iterator().next(); first.addAttribute("a", "test"); updatedValues.add(first); - db.collection(COLLECTION_NAME).updateDocuments(updatedValues, null) + db.collection(COLLECTION_NAME).updateDocuments(updatedValues) .whenComplete((updateResult, ex) -> { assertThat(updateResult.getDocuments().size()).isEqualTo(1); assertThat(updateResult.getErrors().size()).isEqualTo(0); @@ -2003,7 +2115,7 @@ void updateDocumentsOne() throws InterruptedException, ExecutionException { @Test void updateDocumentsEmpty() throws InterruptedException, ExecutionException { final Collection values = new ArrayList<>(); - db.collection(COLLECTION_NAME).updateDocuments(values, null) + db.collection(COLLECTION_NAME).updateDocuments(values) .whenComplete((updateResult, ex) -> { assertThat(updateResult.getDocuments().size()).isEqualTo(0); assertThat(updateResult.getErrors().size()).isEqualTo(0); @@ -2017,14 +2129,14 @@ void updateDocumentsWithoutKey() throws InterruptedException, ExecutionException { values.add(new BaseDocument("1")); } - db.collection(COLLECTION_NAME).insertDocuments(values, null).get(); + db.collection(COLLECTION_NAME).insertDocuments(values).get(); final Collection updatedValues = new ArrayList<>(); for (final BaseDocument i : values) { i.addAttribute("a", "test"); updatedValues.add(i); } updatedValues.add(new BaseDocument()); - db.collection(COLLECTION_NAME).updateDocuments(updatedValues, null) + db.collection(COLLECTION_NAME).updateDocuments(updatedValues) .whenComplete((updateResult, ex) -> { assertThat(updateResult.getDocuments().size()).isEqualTo(1); assertThat(updateResult.getErrors().size()).isEqualTo(1); @@ -2039,13 +2151,13 @@ void replaceDocuments() throws InterruptedException, ExecutionException { values.add(new BaseDocument("1")); values.add(new BaseDocument("2")); } - db.collection(COLLECTION_NAME).insertDocuments(values, null).get(); + db.collection(COLLECTION_NAME).insertDocuments(values).get(); final Collection updatedValues = new ArrayList<>(); for (final BaseDocument i : values) { i.addAttribute("a", "test"); updatedValues.add(i); } - db.collection(COLLECTION_NAME).replaceDocuments(updatedValues, null) + db.collection(COLLECTION_NAME).replaceDocuments(updatedValues) .whenComplete((updateResult, ex) -> { assertThat(updateResult.getDocuments().size()).isEqualTo(2); assertThat(updateResult.getErrors().size()).isEqualTo(0); @@ -2061,12 +2173,12 @@ void replaceDocumentsOne() throws InterruptedException, ExecutionException { e.setKey("1"); values.add(e); } - db.collection(COLLECTION_NAME).insertDocuments(values, null).get(); + db.collection(COLLECTION_NAME).insertDocuments(values).get(); final Collection updatedValues = new ArrayList<>(); final BaseDocument first = values.iterator().next(); first.addAttribute("a", "test"); updatedValues.add(first); - db.collection(COLLECTION_NAME).updateDocuments(updatedValues, null) + db.collection(COLLECTION_NAME).updateDocuments(updatedValues) .whenComplete((updateResult, ex) -> { assertThat(updateResult.getDocuments().size()).isEqualTo(1); assertThat(updateResult.getErrors().size()).isEqualTo(0); @@ -2077,7 +2189,7 @@ void replaceDocumentsOne() throws InterruptedException, ExecutionException { @Test void replaceDocumentsEmpty() throws InterruptedException, ExecutionException { final Collection values = new ArrayList<>(); - db.collection(COLLECTION_NAME).updateDocuments(values, null) + db.collection(COLLECTION_NAME).updateDocuments(values) .whenComplete((updateResult, ex) -> { assertThat(updateResult.getDocuments().size()).isEqualTo(0); assertThat(updateResult.getErrors().size()).isEqualTo(0); @@ -2091,14 +2203,14 @@ void replaceDocumentsWithoutKey() throws InterruptedException, ExecutionExceptio { values.add(new BaseDocument("1")); } - db.collection(COLLECTION_NAME).insertDocuments(values, null).get(); + db.collection(COLLECTION_NAME).insertDocuments(values).get(); final Collection updatedValues = new ArrayList<>(); for (final BaseDocument i : values) { i.addAttribute("a", "test"); updatedValues.add(i); } updatedValues.add(new BaseDocument()); - db.collection(COLLECTION_NAME).updateDocuments(updatedValues, null) + db.collection(COLLECTION_NAME).updateDocuments(updatedValues) .whenComplete((updateResult, ex) -> { assertThat(updateResult.getDocuments().size()).isEqualTo(1); assertThat(updateResult.getErrors().size()).isEqualTo(1); diff --git a/src/test/java/com/arangodb/async/example/document/GetDocumentExampleTest.java b/src/test/java/com/arangodb/async/example/document/GetDocumentExampleTest.java index 6251385a8..2b74c8ad2 100644 --- a/src/test/java/com/arangodb/async/example/document/GetDocumentExampleTest.java +++ b/src/test/java/com/arangodb/async/example/document/GetDocumentExampleTest.java @@ -46,8 +46,7 @@ class GetDocumentExampleTest extends ExampleBase { static void before() throws InterruptedException, ExecutionException { final BaseDocument value = new BaseDocument(UUID.randomUUID().toString()); value.addAttribute("foo", "bar"); - final DocumentCreateEntity doc = collection.insertDocument(value).get(); - key = doc.getKey(); + key = collection.insertDocument(value).get().getKey(); } @Test diff --git a/src/test/java/com/arangodb/async/example/graph/AQLActorsAndMoviesExampleTest.java b/src/test/java/com/arangodb/async/example/graph/AQLActorsAndMoviesExampleTest.java index 0b5fbb50a..be78c92a1 100644 --- a/src/test/java/com/arangodb/async/example/graph/AQLActorsAndMoviesExampleTest.java +++ b/src/test/java/com/arangodb/async/example/graph/AQLActorsAndMoviesExampleTest.java @@ -72,7 +72,7 @@ static void tearDown() throws InterruptedException, ExecutionException { arangoDB.shutdown(); } - private static DocumentCreateEntity saveMovie( + private static DocumentCreateEntity saveMovie( final ArangoCollectionAsync movies, final String key, final String title, @@ -86,7 +86,7 @@ private static DocumentCreateEntity saveMovie( return movies.insertDocument(value).get(); } - private static DocumentCreateEntity saveActor( + private static DocumentCreateEntity saveActor( final ArangoCollectionAsync actors, final String key, final String name, diff --git a/src/test/java/com/arangodb/async/serde/CustomSerdeTest.java b/src/test/java/com/arangodb/async/serde/CustomSerdeTest.java index 16816ec0b..231f6a1e7 100644 --- a/src/test/java/com/arangodb/async/serde/CustomSerdeTest.java +++ b/src/test/java/com/arangodb/async/serde/CustomSerdeTest.java @@ -115,7 +115,7 @@ void aqlDeserialization() throws ExecutionException, InterruptedException { doc.put("arr", Collections.singletonList("hello")); doc.put("int", 10); - collection.insertDocument(doc, null).get(); + collection.insertDocument(doc).get(); final Map result = db.query( "RETURN DOCUMENT(@docId)", @@ -158,7 +158,7 @@ void getDocument() throws ExecutionException, InterruptedException { doc.put("arr", Collections.singletonList("hello")); doc.put("int", 10); - collection.insertDocument(doc, null).get(); + collection.insertDocument(doc).get(); final Map result = db.collection(COLLECTION_NAME).getDocument( key, diff --git a/src/test/java/com/arangodb/example/document/GetDocumentExampleTest.java b/src/test/java/com/arangodb/example/document/GetDocumentExampleTest.java index 21885281f..26fee1747 100644 --- a/src/test/java/com/arangodb/example/document/GetDocumentExampleTest.java +++ b/src/test/java/com/arangodb/example/document/GetDocumentExampleTest.java @@ -46,8 +46,7 @@ class GetDocumentExampleTest extends ExampleBase { static void before() { final BaseDocument value = new BaseDocument(UUID.randomUUID().toString()); value.addAttribute("foo", "bar"); - final DocumentCreateEntity doc = collection.insertDocument(value); - key = doc.getKey(); + key = collection.insertDocument(value).getKey(); } @Test diff --git a/src/test/java/com/arangodb/example/document/InsertDocumentExampleTest.java b/src/test/java/com/arangodb/example/document/InsertDocumentExampleTest.java index 1594b4f91..000b6ddd6 100644 --- a/src/test/java/com/arangodb/example/document/InsertDocumentExampleTest.java +++ b/src/test/java/com/arangodb/example/document/InsertDocumentExampleTest.java @@ -24,7 +24,6 @@ import com.arangodb.entity.DocumentCreateEntity; import com.arangodb.example.ExampleBase; import com.arangodb.util.RawJson; -import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.node.ObjectNode; import org.junit.jupiter.api.Test; @@ -41,7 +40,7 @@ class InsertDocumentExampleTest extends ExampleBase { @Test void insertBean() { - final DocumentCreateEntity doc = collection.insertDocument(new TestEntity("bar")); + final DocumentCreateEntity doc = collection.insertDocument(new TestEntity("bar")); assertThat(doc.getKey()).isNotNull(); } @@ -49,7 +48,7 @@ void insertBean() { void insertBaseDocument() { final BaseDocument value = new BaseDocument(UUID.randomUUID().toString()); value.addAttribute("foo", "bar"); - final DocumentCreateEntity doc = collection.insertDocument(value); + final DocumentCreateEntity doc = collection.insertDocument(value); assertThat(doc.getKey()).isNotNull(); } @@ -58,13 +57,13 @@ void insertJsonNode() { ObjectMapper mapper = new ObjectMapper(); ObjectNode node = mapper.createObjectNode(); node.put("foo", "bar"); - final DocumentCreateEntity doc = collection.insertDocument(node); + final DocumentCreateEntity doc = collection.insertDocument(node); assertThat(doc.getKey()).isNotNull(); } @Test void insertJson() { - final DocumentCreateEntity doc = collection.insertDocument(RawJson.of("{\"foo\":\"bar\"}")); + final DocumentCreateEntity doc = collection.insertDocument(RawJson.of("{\"foo\":\"bar\"}")); assertThat(doc.getKey()).isNotNull(); } diff --git a/src/test/java/com/arangodb/example/graph/AQLActorsAndMoviesExampleTest.java b/src/test/java/com/arangodb/example/graph/AQLActorsAndMoviesExampleTest.java index cf8f67ddc..da93131f1 100644 --- a/src/test/java/com/arangodb/example/graph/AQLActorsAndMoviesExampleTest.java +++ b/src/test/java/com/arangodb/example/graph/AQLActorsAndMoviesExampleTest.java @@ -313,7 +313,7 @@ public boolean equals(final Object obj) { } - private static DocumentCreateEntity saveMovie( + private static DocumentCreateEntity saveMovie( final ArangoCollection movies, final String key, final String title, @@ -327,7 +327,7 @@ private static DocumentCreateEntity saveMovie( return movies.insertDocument(value); } - private static DocumentCreateEntity saveActor( + private static DocumentCreateEntity saveActor( final ArangoCollection actors, final String key, final String name, diff --git a/src/test/java/com/arangodb/serde/CustomSerdeTest.java b/src/test/java/com/arangodb/serde/CustomSerdeTest.java index ae2cd1e6e..de4301b44 100644 --- a/src/test/java/com/arangodb/serde/CustomSerdeTest.java +++ b/src/test/java/com/arangodb/serde/CustomSerdeTest.java @@ -171,7 +171,7 @@ void aqlDeserialization() { doc.put("arr", Collections.singletonList("hello")); doc.put("int", 10); - collection.insertDocument(doc, null); + collection.insertDocument(doc); final Map result = db.query( "RETURN DOCUMENT(@docId)", @@ -214,7 +214,7 @@ void getDocument() { doc.put("arr", Collections.singletonList("hello")); doc.put("int", 10); - collection.insertDocument(doc, null); + collection.insertDocument(doc); final Map result = db.collection(COLLECTION_NAME).getDocument( key, From d99b124f9972aacb78755eb438ca909dea20be32 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Thu, 11 Aug 2022 15:41:36 +0200 Subject: [PATCH 074/254] deleteDocuments javadoc upd --- src/main/java/com/arangodb/ArangoCollection.java | 6 ++---- src/main/java/com/arangodb/async/ArangoCollectionAsync.java | 6 ++---- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/src/main/java/com/arangodb/ArangoCollection.java b/src/main/java/com/arangodb/ArangoCollection.java index b2d332760..329e0204b 100644 --- a/src/main/java/com/arangodb/ArangoCollection.java +++ b/src/main/java/com/arangodb/ArangoCollection.java @@ -423,8 +423,7 @@ DocumentDeleteEntity deleteDocument(String key, DocumentDeleteOptions opt * Deletes the document with the given {@code key} from the collection. * * @param key The key of the document - * @param type The type of the document (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}). Only necessary if - * options.returnOld is set to true, otherwise can be null. + * @param type Deserialization target type for the returned documents. * @param options Additional options, can be null * @return information about the document * @throws ArangoDBException @@ -464,8 +463,7 @@ MultiDocumentEntity> deleteDocuments( * Deletes multiple documents from the collection. * * @param values The keys of the documents or the documents themselves - * @param type The type of the documents (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}). Only necessary if - * options.returnOld is set to true, otherwise can be null. + * @param type Deserialization target type for the returned documents. * @param options Additional options, can be null * @return information about the documents * @throws ArangoDBException diff --git a/src/main/java/com/arangodb/async/ArangoCollectionAsync.java b/src/main/java/com/arangodb/async/ArangoCollectionAsync.java index 2869b5f82..30dfbbb46 100644 --- a/src/main/java/com/arangodb/async/ArangoCollectionAsync.java +++ b/src/main/java/com/arangodb/async/ArangoCollectionAsync.java @@ -421,8 +421,7 @@ CompletableFuture> deleteDocument( * Removes a document * * @param key The key of the document - * @param type The type of the document (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}). Only necessary if - * options.returnOld is set to true, otherwise can be null. + * @param type Deserialization target type for the returned documents. * @param options Additional options, can be null * @return information about the document * @see API @@ -462,8 +461,7 @@ CompletableFuture>> deleteDocume * Removes multiple document * * @param values The keys of the documents or the documents themselves - * @param type The type of the documents (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}). Only necessary if - * options.returnOld is set to true, otherwise can be null. + * @param type Deserialization target type for the returned documents. * @param options Additional options, can be null * @return information about the documents * @see Date: Thu, 11 Aug 2022 15:48:32 +0200 Subject: [PATCH 075/254] CRUD operations javadoc upd --- .../java/com/arangodb/ArangoCollection.java | 32 +++++++++---------- .../arangodb/async/ArangoCollectionAsync.java | 32 +++++++++---------- 2 files changed, 32 insertions(+), 32 deletions(-) diff --git a/src/main/java/com/arangodb/ArangoCollection.java b/src/main/java/com/arangodb/ArangoCollection.java index 329e0204b..b4d63b929 100644 --- a/src/main/java/com/arangodb/ArangoCollection.java +++ b/src/main/java/com/arangodb/ArangoCollection.java @@ -68,7 +68,7 @@ public interface ArangoCollection extends ArangoSerdeAccessor { * _key is given, a new unique _key is generated automatically. * * @param value A representation of a single document (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) - * @param options Additional options, can be null + * @param options Additional options * @return information about the document * @throws ArangoDBException * @see API @@ -81,7 +81,7 @@ public interface ArangoCollection extends ArangoSerdeAccessor { * _key is given, a new unique _key is generated automatically. * * @param value A representation of a single document (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) - * @param options Additional options, can be null + * @param options Additional options * @param type Deserialization target type for the returned documents. * @return information about the document * @throws ArangoDBException @@ -107,7 +107,7 @@ public interface ArangoCollection extends ArangoSerdeAccessor { * _key is given, a new unique _key is generated automatically. * * @param values A List of documents (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) - * @param options Additional options, can be null + * @param options Additional options * @return information about the documents * @throws ArangoDBException * @see API @@ -121,7 +121,7 @@ MultiDocumentEntity> insertDocuments( * _key is given, a new unique _key is generated automatically. * * @param values A List of documents (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) - * @param options Additional options, can be null + * @param options Additional options * @param type Deserialization target type for the returned documents. * @return information about the documents * @throws ArangoDBException @@ -235,7 +235,7 @@ MultiDocumentEntity getDocuments(Collection keys, Class type, * * @param key The key of the document * @param value A representation of a single document (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) - * @param options Additional options, can be null + * @param options Additional options * @return information about the document * @throws ArangoDBException * @see API @@ -250,7 +250,7 @@ DocumentUpdateEntity replaceDocument(String key, T value, DocumentReplace * * @param key The key of the document * @param value A representation of a single document (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) - * @param options Additional options, can be null + * @param options Additional options * @param type Deserialization target type for the returned documents. * @return information about the document * @throws ArangoDBException @@ -277,7 +277,7 @@ DocumentUpdateEntity replaceDocument(String key, T value, DocumentReplace * specified by the _key attributes in the documents in values. * * @param values A List of documents (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) - * @param options Additional options, can be null + * @param options Additional options * @return information about the documents * @throws ArangoDBException * @see API @@ -291,7 +291,7 @@ MultiDocumentEntity> replaceDocuments( * specified by the _key attributes in the documents in values. * * @param values A List of documents (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) - * @param options Additional options, can be null + * @param options Additional options * @param type Deserialization target type for the returned documents. * @return information about the documents * @throws ArangoDBException @@ -322,7 +322,7 @@ MultiDocumentEntity> replaceDocuments( * * @param key The key of the document * @param value A representation of a single document (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) - * @param options Additional options, can be null + * @param options Additional options * @return information about the document * @throws ArangoDBException * @see API @@ -338,7 +338,7 @@ DocumentUpdateEntity updateDocument(String key, T value, DocumentUpdateOp * * @param key The key of the document * @param value A representation of a single document (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) - * @param options Additional options, can be null + * @param options Additional options * @param returnType Type of the returned newDocument and/or oldDocument * @return information about the document * @throws ArangoDBException @@ -369,7 +369,7 @@ DocumentUpdateEntity updateDocument(String key, T value, DocumentUpdat * overwritten in the existing documents if they do exist there. * * @param values A list of documents (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) - * @param options Additional options, can be null + * @param options Additional options * @return information about the documents * @throws ArangoDBException * @see API @@ -385,7 +385,7 @@ MultiDocumentEntity> updateDocuments( * overwritten in the existing documents if they do exist there. * * @param values A list of documents (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) - * @param options Additional options, can be null + * @param options Additional options * @param returnType Type of the returned newDocument and/or oldDocument * @return information about the documents * @throws ArangoDBException @@ -410,7 +410,7 @@ MultiDocumentEntity> updateDocuments( * Deletes the document with the given {@code key} from the collection. * * @param key The key of the document - * @param options Additional options, can be null + * @param options Additional options * @return information about the document * @throws ArangoDBException * @see API @@ -424,7 +424,7 @@ DocumentDeleteEntity deleteDocument(String key, DocumentDeleteOptions opt * * @param key The key of the document * @param type Deserialization target type for the returned documents. - * @param options Additional options, can be null + * @param options Additional options * @return information about the document * @throws ArangoDBException * @see API @@ -449,7 +449,7 @@ DocumentDeleteEntity deleteDocument(String key, DocumentDeleteOptions opt * Deletes multiple documents from the collection. * * @param values The keys of the documents or the documents themselves - * @param options Additional options, can be null + * @param options Additional options * @return information about the documents * @throws ArangoDBException * @see MultiDocumentEntity> deleteDocuments( * * @param values The keys of the documents or the documents themselves * @param type Deserialization target type for the returned documents. - * @param options Additional options, can be null + * @param options Additional options * @return information about the documents * @throws ArangoDBException * @see API * Documentation @@ -80,7 +80,7 @@ public interface ArangoCollectionAsync extends ArangoSerdeAccessor { * _key is given, a new unique _key is generated automatically. * * @param value A representation of a single document (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) - * @param options Additional options, can be null + * @param options Additional options * @param type Deserialization target type for the returned documents. * @return information about the document * @see API @@ -104,7 +104,7 @@ public interface ArangoCollectionAsync extends ArangoSerdeAccessor { * _key is given, a new unique _key is generated automatically. * * @param values A List of documents (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) - * @param options Additional options, can be null + * @param options Additional options * @return information about the documents * @see API * Documentation @@ -118,7 +118,7 @@ CompletableFuture>> insertDocume * _key is given, a new unique _key is generated automatically. * * @param values A List of documents (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) - * @param options Additional options, can be null + * @param options Additional options * @param type Deserialization target type for the returned documents. * @return information about the documents * @see API @@ -229,7 +229,7 @@ CompletableFuture> getDocuments( * * @param key The key of the document * @param value A representation of a single document (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) - * @param options Additional options, can be null + * @param options Additional options * @return information about the document * @see API * Documentation @@ -245,7 +245,7 @@ CompletableFuture> replaceDocument( * * @param key The key of the document * @param value A representation of a single document (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) - * @param options Additional options, can be null + * @param options Additional options * @param type Deserialization target type for the returned documents. * @return information about the document * @see API @@ -273,7 +273,7 @@ CompletableFuture> replaceDocument( * specified by the _key attributes in the documents in values. * * @param values A List of documents (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) - * @param options Additional options, can be null + * @param options Additional options * @return information about the documents * @see API * Documentation @@ -287,7 +287,7 @@ CompletableFuture>> replaceDocum * specified by the _key attributes in the documents in values. * * @param values A List of documents (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) - * @param options Additional options, can be null + * @param options Additional options * @param type Deserialization target type for the returned documents. * @return information about the documents * @see API @@ -318,7 +318,7 @@ CompletableFuture>> replaceDocum * * @param key The key of the document * @param value A representation of a single document (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) - * @param options Additional options, can be null + * @param options Additional options * @return information about the document * @see API * Documentation @@ -335,7 +335,7 @@ CompletableFuture> updateDocument( * * @param key The key of the document * @param value A representation of a single document (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) - * @param options Additional options, can be null + * @param options Additional options * @param returnType Type of the returned newDocument and/or oldDocument * @return information about the document * @see API @@ -367,7 +367,7 @@ CompletableFuture> updateDocument( * overwritten in the existing documents if they do exist there. * * @param values A list of documents (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) - * @param options Additional options, can be null + * @param options Additional options * @return information about the documents * @see API * Documentation @@ -383,7 +383,7 @@ CompletableFuture>> updateDocume * overwritten in the existing documents if they do exist there. * * @param values A list of documents (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) - * @param options Additional options, can be null + * @param options Additional options * @param returnType Type of the returned newDocument and/or oldDocument * @return information about the documents * @see API @@ -408,7 +408,7 @@ CompletableFuture>> updateDoc * Removes a document * * @param key The key of the document - * @param options Additional options, can be null + * @param options Additional options * @return information about the document * @see API * Documentation @@ -422,7 +422,7 @@ CompletableFuture> deleteDocument( * * @param key The key of the document * @param type Deserialization target type for the returned documents. - * @param options Additional options, can be null + * @param options Additional options * @return information about the document * @see API * Documentation @@ -447,7 +447,7 @@ CompletableFuture> deleteDocument( * Removes multiple document * * @param values The keys of the documents or the documents themselves - * @param options Additional options, can be null + * @param options Additional options * @return information about the documents * @see API @@ -462,7 +462,7 @@ CompletableFuture>> deleteDocume * * @param values The keys of the documents or the documents themselves * @param type Deserialization target type for the returned documents. - * @param options Additional options, can be null + * @param options Additional options * @return information about the documents * @see API From 63f21bd7251355f0b8e106baac5a9092af9fd55b Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Mon, 15 Aug 2022 13:51:45 +0200 Subject: [PATCH 076/254] removed unnecessary generics --- .../java/com/arangodb/ArangoCollection.java | 12 +++++----- .../arangodb/async/ArangoCollectionAsync.java | 22 +++++++++---------- .../internal/ArangoCollectionAsyncImpl.java | 17 +++++++------- .../internal/ArangoCollectionImpl.java | 13 +++++------ 4 files changed, 31 insertions(+), 33 deletions(-) diff --git a/src/main/java/com/arangodb/ArangoCollection.java b/src/main/java/com/arangodb/ArangoCollection.java index b4d63b929..ef178b820 100644 --- a/src/main/java/com/arangodb/ArangoCollection.java +++ b/src/main/java/com/arangodb/ArangoCollection.java @@ -122,7 +122,7 @@ MultiDocumentEntity> insertDocuments( * * @param values A List of documents (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) * @param options Additional options - * @param type Deserialization target type for the returned documents. + * @param type Deserialization target type for the returned documents. * @return information about the documents * @throws ArangoDBException * @see API @@ -292,7 +292,7 @@ MultiDocumentEntity> replaceDocuments( * * @param values A List of documents (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) * @param options Additional options - * @param type Deserialization target type for the returned documents. + * @param type Deserialization target type for the returned documents. * @return information about the documents * @throws ArangoDBException * @see API @@ -345,7 +345,7 @@ DocumentUpdateEntity updateDocument(String key, T value, DocumentUpdateOp * @see API * Documentation */ - DocumentUpdateEntity updateDocument(String key, T value, DocumentUpdateOptions options, Class returnType) + DocumentUpdateEntity updateDocument(String key, Object value, DocumentUpdateOptions options, Class returnType) throws ArangoDBException; /** @@ -392,8 +392,8 @@ MultiDocumentEntity> updateDocuments( * @see API * Documentation */ - MultiDocumentEntity> updateDocuments( - Collection values, DocumentUpdateOptions options, Class returnType) throws ArangoDBException; + MultiDocumentEntity> updateDocuments( + Collection values, DocumentUpdateOptions options, Class returnType) throws ArangoDBException; /** * Deletes the document with the given {@code key} from the collection. @@ -416,7 +416,7 @@ MultiDocumentEntity> updateDocuments( * @see API * Documentation */ - DocumentDeleteEntity deleteDocument(String key, DocumentDeleteOptions options) + DocumentDeleteEntity deleteDocument(String key, DocumentDeleteOptions options) throws ArangoDBException; /** diff --git a/src/main/java/com/arangodb/async/ArangoCollectionAsync.java b/src/main/java/com/arangodb/async/ArangoCollectionAsync.java index 17aa7175a..ea15c98fe 100644 --- a/src/main/java/com/arangodb/async/ArangoCollectionAsync.java +++ b/src/main/java/com/arangodb/async/ArangoCollectionAsync.java @@ -81,7 +81,7 @@ public interface ArangoCollectionAsync extends ArangoSerdeAccessor { * * @param value A representation of a single document (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) * @param options Additional options - * @param type Deserialization target type for the returned documents. + * @param type Deserialization target type for the returned documents. * @return information about the document * @see API * Documentation @@ -119,7 +119,7 @@ CompletableFuture>> insertDocume * * @param values A List of documents (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) * @param options Additional options - * @param type Deserialization target type for the returned documents. + * @param type Deserialization target type for the returned documents. * @return information about the documents * @see API * Documentation @@ -246,7 +246,7 @@ CompletableFuture> replaceDocument( * @param key The key of the document * @param value A representation of a single document (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) * @param options Additional options - * @param type Deserialization target type for the returned documents. + * @param type Deserialization target type for the returned documents. * @return information about the document * @see API * Documentation @@ -288,7 +288,7 @@ CompletableFuture>> replaceDocum * * @param values A List of documents (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) * @param options Additional options - * @param type Deserialization target type for the returned documents. + * @param type Deserialization target type for the returned documents. * @return information about the documents * @see API * Documentation @@ -341,11 +341,11 @@ CompletableFuture> updateDocument( * @see API * Documentation */ - CompletableFuture> updateDocument( + CompletableFuture> updateDocument( final String key, - final T value, + final Object value, final DocumentUpdateOptions options, - final Class returnType); + final Class returnType); /** * Partially updates documents, the documents to update are specified by the _key attributes in the objects on @@ -389,10 +389,10 @@ CompletableFuture>> updateDocume * @see API * Documentation */ - CompletableFuture>> updateDocuments( - final Collection values, + CompletableFuture>> updateDocuments( + final Collection values, final DocumentUpdateOptions options, - final Class returnType); + final Class returnType); /** * Removes a document @@ -413,7 +413,7 @@ CompletableFuture>> updateDoc * @see API * Documentation */ - CompletableFuture> deleteDocument( + CompletableFuture> deleteDocument( final String key, final DocumentDeleteOptions options); diff --git a/src/main/java/com/arangodb/async/internal/ArangoCollectionAsyncImpl.java b/src/main/java/com/arangodb/async/internal/ArangoCollectionAsyncImpl.java index 3544d2298..500ad89bd 100644 --- a/src/main/java/com/arangodb/async/internal/ArangoCollectionAsyncImpl.java +++ b/src/main/java/com/arangodb/async/internal/ArangoCollectionAsyncImpl.java @@ -198,11 +198,11 @@ public CompletableFuture> updateDocument( } @Override - public CompletableFuture> updateDocument( + public CompletableFuture> updateDocument( final String key, - final T value, + final Object value, final DocumentUpdateOptions options, - final Class returnType) { + final Class returnType) { return executor.execute(updateDocumentRequest(key, value, options), constructParametricType(DocumentUpdateEntity.class, returnType)); } @@ -222,10 +222,10 @@ public CompletableFuture>> updat } @Override - public CompletableFuture>> updateDocuments( - final Collection values, + public CompletableFuture>> updateDocuments( + final Collection values, final DocumentUpdateOptions options, - final Class returnType) { + final Class returnType) { return executor .execute(updateDocumentsRequest(values, options), updateDocumentsResponseDeserializer(returnType)); } @@ -236,9 +236,8 @@ public CompletableFuture> deleteDocument(final String } @Override - @SuppressWarnings("unchecked") - public CompletableFuture> deleteDocument(String key, DocumentDeleteOptions options) { - return deleteDocument(key, options, (Class) Void.class); + public CompletableFuture> deleteDocument(String key, DocumentDeleteOptions options) { + return deleteDocument(key, options, Void.class); } @Override diff --git a/src/main/java/com/arangodb/internal/ArangoCollectionImpl.java b/src/main/java/com/arangodb/internal/ArangoCollectionImpl.java index e57dda57d..a6c7d5441 100644 --- a/src/main/java/com/arangodb/internal/ArangoCollectionImpl.java +++ b/src/main/java/com/arangodb/internal/ArangoCollectionImpl.java @@ -198,8 +198,8 @@ public DocumentUpdateEntity updateDocument( } @Override - public DocumentUpdateEntity updateDocument( - final String key, final T value, final DocumentUpdateOptions options, final Class returnType) throws ArangoDBException { + public DocumentUpdateEntity updateDocument( + final String key, final Object value, final DocumentUpdateOptions options, final Class returnType) throws ArangoDBException { return executor.execute(updateDocumentRequest(key, value, options), constructParametricType(DocumentUpdateEntity.class, returnType)); } @@ -218,8 +218,8 @@ public MultiDocumentEntity> updateDocuments( } @Override - public MultiDocumentEntity> updateDocuments( - final Collection values, final DocumentUpdateOptions options, final Class returnType) throws ArangoDBException { + public MultiDocumentEntity> updateDocuments( + final Collection values, final DocumentUpdateOptions options, final Class returnType) throws ArangoDBException { return executor .execute(updateDocumentsRequest(values, options), updateDocumentsResponseDeserializer(returnType)); } @@ -230,9 +230,8 @@ public DocumentDeleteEntity deleteDocument(final String key) throws Arango } @Override - @SuppressWarnings("unchecked") - public DocumentDeleteEntity deleteDocument(String key, DocumentDeleteOptions options) throws ArangoDBException { - return deleteDocument(key, options, (Class) Void.class); + public DocumentDeleteEntity deleteDocument(String key, DocumentDeleteOptions options) throws ArangoDBException { + return deleteDocument(key, options, Void.class); } @Override From 2900beb32ec7b66dba55f48189dea767af6245c0 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Mon, 15 Aug 2022 14:36:57 +0200 Subject: [PATCH 077/254] [DE-218] removed catchException API params --- .../internal/ArangoCollectionAsyncImpl.java | 6 +-- .../ArangoEdgeCollectionAsyncImpl.java | 3 +- .../ArangoVertexCollectionAsyncImpl.java | 3 +- .../async/internal/ExceptionUtil.java | 9 ++-- .../internal/ArangoCollectionImpl.java | 6 +-- .../arangodb/model/DocumentExistsOptions.java | 15 ------- .../arangodb/model/DocumentReadOptions.java | 15 ------- .../model/GraphDocumentReadOptions.java | 15 ------- .../com/arangodb/ArangoCollectionTest.java | 12 ----- .../async/ArangoEdgeCollectionTest.java | 44 ++++++------------- .../async/ArangoVertexCollectionTest.java | 44 ++++++------------- 11 files changed, 40 insertions(+), 132 deletions(-) diff --git a/src/main/java/com/arangodb/async/internal/ArangoCollectionAsyncImpl.java b/src/main/java/com/arangodb/async/internal/ArangoCollectionAsyncImpl.java index 500ad89bd..9c4b03b6c 100644 --- a/src/main/java/com/arangodb/async/internal/ArangoCollectionAsyncImpl.java +++ b/src/main/java/com/arangodb/async/internal/ArangoCollectionAsyncImpl.java @@ -122,9 +122,8 @@ public CompletableFuture getDocument( final Class type, final DocumentReadOptions options) throws ArangoDBException { DocumentUtil.validateDocumentKey(key); - boolean isCatchException = options != null ? options.isCatchException() : new DocumentReadOptions().isCatchException(); return executor.execute(getDocumentRequest(key, options), getDocumentResponseDeserializer(type)) - .exceptionally(ExceptionUtil.catchGetDocumentExceptions(isCatchException)); + .exceptionally(ExceptionUtil.catchGetDocumentExceptions()); } @Override @@ -276,9 +275,8 @@ public CompletableFuture documentExists(final String key) { @Override public CompletableFuture documentExists(final String key, final DocumentExistsOptions options) { - boolean isCatchException = options != null ? options.isCatchException() : new DocumentExistsOptions().isCatchException(); return executor.execute(documentExistsRequest(key, options), response -> response) - .exceptionally(ExceptionUtil.catchGetDocumentExceptions(isCatchException)) + .exceptionally(ExceptionUtil.catchGetDocumentExceptions()) .thenApply(Objects::nonNull); } diff --git a/src/main/java/com/arangodb/async/internal/ArangoEdgeCollectionAsyncImpl.java b/src/main/java/com/arangodb/async/internal/ArangoEdgeCollectionAsyncImpl.java index 4ea3ee725..84b43da97 100644 --- a/src/main/java/com/arangodb/async/internal/ArangoEdgeCollectionAsyncImpl.java +++ b/src/main/java/com/arangodb/async/internal/ArangoEdgeCollectionAsyncImpl.java @@ -57,9 +57,8 @@ public CompletableFuture getEdge(final String key, final Class type) { @Override public CompletableFuture getEdge(final String key, final Class type, final GraphDocumentReadOptions options) { - boolean isCatchException = options != null ? options.isCatchException() : new GraphDocumentReadOptions().isCatchException(); return executor.execute(getEdgeRequest(key, options), getEdgeResponseDeserializer(type)) - .exceptionally(ExceptionUtil.catchGetDocumentExceptions(isCatchException)); + .exceptionally(ExceptionUtil.catchGetDocumentExceptions()); } @Override diff --git a/src/main/java/com/arangodb/async/internal/ArangoVertexCollectionAsyncImpl.java b/src/main/java/com/arangodb/async/internal/ArangoVertexCollectionAsyncImpl.java index e988b6436..3cadf4eba 100644 --- a/src/main/java/com/arangodb/async/internal/ArangoVertexCollectionAsyncImpl.java +++ b/src/main/java/com/arangodb/async/internal/ArangoVertexCollectionAsyncImpl.java @@ -65,9 +65,8 @@ public CompletableFuture getVertex( final String key, final Class type, final GraphDocumentReadOptions options) { - boolean isCatchException = options != null ? options.isCatchException() : new GraphDocumentReadOptions().isCatchException(); return executor.execute(getVertexRequest(key, options), getVertexResponseDeserializer(type)) - .exceptionally(ExceptionUtil.catchGetDocumentExceptions(isCatchException)); + .exceptionally(ExceptionUtil.catchGetDocumentExceptions()); } @Override diff --git a/src/main/java/com/arangodb/async/internal/ExceptionUtil.java b/src/main/java/com/arangodb/async/internal/ExceptionUtil.java index b76cdc21d..d31c2000d 100644 --- a/src/main/java/com/arangodb/async/internal/ExceptionUtil.java +++ b/src/main/java/com/arangodb/async/internal/ExceptionUtil.java @@ -1,4 +1,4 @@ -package com.arangodb.async.internal;/* +/* * DISCLAIMER * * Copyright 2016 ArangoDB GmbH, Cologne, Germany @@ -18,6 +18,7 @@ * Copyright holder is ArangoDB GmbH, Cologne, Germany */ +package com.arangodb.async.internal; import com.arangodb.ArangoDBException; @@ -28,7 +29,7 @@ * @author Michele Rastelli */ class ExceptionUtil { - static Function catchGetDocumentExceptions(Boolean isCatchException) { + static Function catchGetDocumentExceptions() { return throwable -> { if (throwable instanceof CompletionException) { if (throwable.getCause() instanceof ArangoDBException) { @@ -39,8 +40,8 @@ static Function catchGetDocumentExceptions(Boolean isCatchExce throw (CompletionException) throwable; } - if ((arangoDBException.getResponseCode() != null && (arangoDBException.getResponseCode() == 404 || arangoDBException.getResponseCode() == 304 - || arangoDBException.getResponseCode() == 412)) && isCatchException) { + if ((arangoDBException.getResponseCode() != null && + (arangoDBException.getResponseCode() == 404 || arangoDBException.getResponseCode() == 304 || arangoDBException.getResponseCode() == 412))) { return null; } } diff --git a/src/main/java/com/arangodb/internal/ArangoCollectionImpl.java b/src/main/java/com/arangodb/internal/ArangoCollectionImpl.java index a6c7d5441..765c3b224 100644 --- a/src/main/java/com/arangodb/internal/ArangoCollectionImpl.java +++ b/src/main/java/com/arangodb/internal/ArangoCollectionImpl.java @@ -128,7 +128,7 @@ public T getDocument(final String key, final Class type, final DocumentRe } if ((e.getResponseCode() != null && (e.getResponseCode() == 404 || e.getResponseCode() == 304 - || e.getResponseCode() == 412)) && (options == null || options.isCatchException())) { + || e.getResponseCode() == 412))) { return null; } throw e; @@ -279,8 +279,8 @@ public Boolean documentExists(final String key, final DocumentExistsOptions opti throw e; } - if ((e.getResponseCode() != null && (e.getResponseCode() == 404 || e.getResponseCode() == 304 - || e.getResponseCode() == 412)) && (options == null || options.isCatchException())) { + if ((e.getResponseCode() != null && + (e.getResponseCode() == 404 || e.getResponseCode() == 304 || e.getResponseCode() == 412))) { return false; } throw e; diff --git a/src/main/java/com/arangodb/model/DocumentExistsOptions.java b/src/main/java/com/arangodb/model/DocumentExistsOptions.java index ec2a47c45..06c3a44d5 100644 --- a/src/main/java/com/arangodb/model/DocumentExistsOptions.java +++ b/src/main/java/com/arangodb/model/DocumentExistsOptions.java @@ -30,12 +30,10 @@ public final class DocumentExistsOptions { private String ifNoneMatch; private String ifMatch; - private boolean catchException; private String streamTransactionId; public DocumentExistsOptions() { super(); - catchException = true; } public String getIfNoneMatch() { @@ -64,19 +62,6 @@ public DocumentExistsOptions ifMatch(final String ifMatch) { return this; } - public boolean isCatchException() { - return catchException; - } - - /** - * @param catchException whether or not catch possible thrown exceptions - * @return options - */ - public DocumentExistsOptions catchException(final boolean catchException) { - this.catchException = catchException; - return this; - } - public String getStreamTransactionId() { return streamTransactionId; } diff --git a/src/main/java/com/arangodb/model/DocumentReadOptions.java b/src/main/java/com/arangodb/model/DocumentReadOptions.java index 1041b786c..ec711724e 100644 --- a/src/main/java/com/arangodb/model/DocumentReadOptions.java +++ b/src/main/java/com/arangodb/model/DocumentReadOptions.java @@ -30,13 +30,11 @@ public final class DocumentReadOptions { private String ifNoneMatch; private String ifMatch; - private boolean catchException; private Boolean allowDirtyRead; private String streamTransactionId; public DocumentReadOptions() { super(); - catchException = true; } public String getIfNoneMatch() { @@ -65,19 +63,6 @@ public DocumentReadOptions ifMatch(final String ifMatch) { return this; } - public boolean isCatchException() { - return catchException; - } - - /** - * @param catchException whether or not catch possible thrown exceptions - * @return options - */ - public DocumentReadOptions catchException(final boolean catchException) { - this.catchException = catchException; - return this; - } - /** * @param allowDirtyRead Set to {@code true} allows reading from followers in an active-failover setup. * @return options diff --git a/src/main/java/com/arangodb/model/GraphDocumentReadOptions.java b/src/main/java/com/arangodb/model/GraphDocumentReadOptions.java index 7277b10df..6e3e803a0 100644 --- a/src/main/java/com/arangodb/model/GraphDocumentReadOptions.java +++ b/src/main/java/com/arangodb/model/GraphDocumentReadOptions.java @@ -27,13 +27,11 @@ public final class GraphDocumentReadOptions { private String ifNoneMatch; private String ifMatch; - private boolean catchException; private Boolean allowDirtyRead; private String streamTransactionId; public GraphDocumentReadOptions() { super(); - catchException = true; } public String getIfNoneMatch() { @@ -62,19 +60,6 @@ public GraphDocumentReadOptions ifMatch(final String ifMatch) { return this; } - public boolean isCatchException() { - return catchException; - } - - /** - * @param catchException whether or not catch possible thrown exceptions - * @return options - */ - public GraphDocumentReadOptions catchException(final boolean catchException) { - this.catchException = catchException; - return this; - } - /** * @param allowDirtyRead Set to {@code true} allows reading from followers in an active-failover setup. * @return options diff --git a/src/test/java/com/arangodb/ArangoCollectionTest.java b/src/test/java/com/arangodb/ArangoCollectionTest.java index bf2196786..64cf485bc 100644 --- a/src/test/java/com/arangodb/ArangoCollectionTest.java +++ b/src/test/java/com/arangodb/ArangoCollectionTest.java @@ -508,12 +508,6 @@ void getDocumentNotFoundOptionsNull(ArangoCollection collection) { assertThat(document).isNull(); } - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void getDocumentNotFoundThrowException(ArangoCollection collection) { - Throwable thrown = catchThrowable(() -> collection.getDocument("no", BaseDocument.class, new DocumentReadOptions().catchException(false))); - assertThat(thrown).isInstanceOf(ArangoDBException.class); - } @ParameterizedTest(name = "{index}") @MethodSource("cols") @@ -1781,12 +1775,6 @@ void documentExists(ArangoCollection collection) { assertThat(exists).isTrue(); } - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void documentExistsThrowExcpetion(ArangoCollection collection) { - Throwable thrown = catchThrowable(() -> collection.documentExists("no", new DocumentExistsOptions().catchException(false))); - assertThat(thrown).isInstanceOf(ArangoDBException.class); - } @ParameterizedTest(name = "{index}") @MethodSource("cols") diff --git a/src/test/java/com/arangodb/async/ArangoEdgeCollectionTest.java b/src/test/java/com/arangodb/async/ArangoEdgeCollectionTest.java index 7f89c48b4..e089cd415 100644 --- a/src/test/java/com/arangodb/async/ArangoEdgeCollectionTest.java +++ b/src/test/java/com/arangodb/async/ArangoEdgeCollectionTest.java @@ -114,14 +114,10 @@ void getEdgeIfMatch() throws InterruptedException, ExecutionException { void getEdgeIfMatchFail() throws InterruptedException, ExecutionException { final BaseEdgeDocument value = createEdgeValue(); final EdgeEntity edge = db.graph(GRAPH_NAME).edgeCollection(EDGE_COLLECTION_NAME).insertEdge(value, null).get(); - final GraphDocumentReadOptions options = new GraphDocumentReadOptions().ifMatch("no").catchException(false); - try { - db.graph(GRAPH_NAME).edgeCollection(EDGE_COLLECTION_NAME) - .getEdge(edge.getKey(), BaseEdgeDocument.class, options).get(); - fail(); - } catch (final ExecutionException e) { - assertThat(e.getCause()).isInstanceOf(ArangoDBException.class); - } + final GraphDocumentReadOptions options = new GraphDocumentReadOptions().ifMatch("no"); + BaseEdgeDocument doc = db.graph(GRAPH_NAME).edgeCollection(EDGE_COLLECTION_NAME) + .getEdge(edge.getKey(), BaseEdgeDocument.class, options).get(); + assertThat(doc).isNull(); } @Test @@ -139,14 +135,10 @@ void getEdgeIfNoneMatch() throws InterruptedException, ExecutionException { void getEdgeIfNoneMatchFail() throws InterruptedException, ExecutionException { final BaseEdgeDocument value = createEdgeValue(); final EdgeEntity edge = db.graph(GRAPH_NAME).edgeCollection(EDGE_COLLECTION_NAME).insertEdge(value, null).get(); - final GraphDocumentReadOptions options = new GraphDocumentReadOptions().ifNoneMatch(edge.getRev()).catchException(false); - try { - db.graph(GRAPH_NAME).edgeCollection(EDGE_COLLECTION_NAME) - .getEdge(edge.getKey(), BaseEdgeDocument.class, options).get(); - fail(); - } catch (final ExecutionException e) { - assertThat(e.getCause()).isInstanceOf(ArangoDBException.class); - } + final GraphDocumentReadOptions options = new GraphDocumentReadOptions().ifNoneMatch(edge.getRev()); + BaseEdgeDocument doc = db.graph(GRAPH_NAME).edgeCollection(EDGE_COLLECTION_NAME) + .getEdge(edge.getKey(), BaseEdgeDocument.class, options).get(); + assertThat(doc).isNull(); } @Test @@ -344,13 +336,9 @@ void deleteEdge() throws InterruptedException, ExecutionException { final EdgeEntity createResult = db.graph(GRAPH_NAME).edgeCollection(EDGE_COLLECTION_NAME).insertEdge(doc, null) .get(); db.graph(GRAPH_NAME).edgeCollection(EDGE_COLLECTION_NAME).deleteEdge(createResult.getKey(), null).get(); - try { - db.graph(GRAPH_NAME).edgeCollection(EDGE_COLLECTION_NAME) - .getEdge(createResult.getKey(), BaseEdgeDocument.class, new GraphDocumentReadOptions().catchException(false)).get(); - fail(); - } catch (final ExecutionException e) { - assertThat(e.getCause()).isInstanceOf(ArangoDBException.class); - } + BaseEdgeDocument res = db.graph(GRAPH_NAME).edgeCollection(EDGE_COLLECTION_NAME) + .getEdge(createResult.getKey(), BaseEdgeDocument.class, new GraphDocumentReadOptions()).get(); + assertThat(res).isNull(); } @Test @@ -360,13 +348,9 @@ void deleteEdgeIfMatch() throws InterruptedException, ExecutionException { .get(); final EdgeDeleteOptions options = new EdgeDeleteOptions().ifMatch(createResult.getRev()); db.graph(GRAPH_NAME).edgeCollection(EDGE_COLLECTION_NAME).deleteEdge(createResult.getKey(), options).get(); - try { - db.graph(GRAPH_NAME).edgeCollection(EDGE_COLLECTION_NAME) - .getEdge(createResult.getKey(), BaseEdgeDocument.class, new GraphDocumentReadOptions().catchException(false)).get(); - fail(); - } catch (final ExecutionException e) { - assertThat(e.getCause()).isInstanceOf(ArangoDBException.class); - } + BaseEdgeDocument res = db.graph(GRAPH_NAME).edgeCollection(EDGE_COLLECTION_NAME) + .getEdge(createResult.getKey(), BaseEdgeDocument.class, new GraphDocumentReadOptions()).get(); + assertThat(res).isNull(); } @Test diff --git a/src/test/java/com/arangodb/async/ArangoVertexCollectionTest.java b/src/test/java/com/arangodb/async/ArangoVertexCollectionTest.java index ca1a02515..164201137 100644 --- a/src/test/java/com/arangodb/async/ArangoVertexCollectionTest.java +++ b/src/test/java/com/arangodb/async/ArangoVertexCollectionTest.java @@ -103,14 +103,10 @@ void getVertexIfMatch() throws InterruptedException, ExecutionException { void getVertexIfMatchFail() throws InterruptedException, ExecutionException { final VertexEntity vertex = db.graph(GRAPH_NAME).vertexCollection(COLLECTION_NAME) .insertVertex(new BaseDocument(), null).get(); - final GraphDocumentReadOptions options = new GraphDocumentReadOptions().ifMatch("no").catchException(false); - try { - db.graph(GRAPH_NAME).vertexCollection(COLLECTION_NAME) - .getVertex(vertex.getKey(), BaseDocument.class, options).get(); - fail(); - } catch (final ExecutionException e) { - assertThat(e.getCause()).isInstanceOf(ArangoDBException.class); - } + final GraphDocumentReadOptions options = new GraphDocumentReadOptions().ifMatch("no"); + BaseDocument res = db.graph(GRAPH_NAME).vertexCollection(COLLECTION_NAME) + .getVertex(vertex.getKey(), BaseDocument.class, options).get(); + assertThat(res).isNull(); } @Test @@ -128,14 +124,10 @@ void getVertexIfNoneMatch() throws InterruptedException, ExecutionException { void getVertexIfNoneMatchFail() throws InterruptedException, ExecutionException { final VertexEntity vertex = db.graph(GRAPH_NAME).vertexCollection(COLLECTION_NAME) .insertVertex(new BaseDocument(), null).get(); - final GraphDocumentReadOptions options = new GraphDocumentReadOptions().ifNoneMatch(vertex.getRev()).catchException(false); - try { - db.graph(GRAPH_NAME).vertexCollection(COLLECTION_NAME) - .getVertex(vertex.getKey(), BaseDocument.class, options).get(); - fail(); - } catch (final ExecutionException e) { - assertThat(e.getCause()).isInstanceOf(ArangoDBException.class); - } + final GraphDocumentReadOptions options = new GraphDocumentReadOptions().ifNoneMatch(vertex.getRev()); + BaseDocument res = db.graph(GRAPH_NAME).vertexCollection(COLLECTION_NAME) + .getVertex(vertex.getKey(), BaseDocument.class, options).get(); + assertThat(res).isNull(); } @Test @@ -333,13 +325,9 @@ void deleteVertex() throws InterruptedException, ExecutionException { final VertexEntity createResult = db.graph(GRAPH_NAME).vertexCollection(COLLECTION_NAME).insertVertex(doc, null) .get(); db.graph(GRAPH_NAME).vertexCollection(COLLECTION_NAME).deleteVertex(createResult.getKey(), null).get(); - try { - db.graph(GRAPH_NAME).vertexCollection(COLLECTION_NAME) - .getVertex(createResult.getKey(), BaseDocument.class, new GraphDocumentReadOptions().catchException(false)).get(); - fail(); - } catch (final ExecutionException e) { - assertThat(e.getCause()).isInstanceOf(ArangoDBException.class); - } + BaseDocument res = db.graph(GRAPH_NAME).vertexCollection(COLLECTION_NAME) + .getVertex(createResult.getKey(), BaseDocument.class, new GraphDocumentReadOptions()).get(); + assertThat(res).isNull(); } @Test @@ -349,13 +337,9 @@ void deleteVertexIfMatch() throws InterruptedException, ExecutionException { .get(); final VertexDeleteOptions options = new VertexDeleteOptions().ifMatch(createResult.getRev()); db.graph(GRAPH_NAME).vertexCollection(COLLECTION_NAME).deleteVertex(createResult.getKey(), options).get(); - try { - db.graph(GRAPH_NAME).vertexCollection(COLLECTION_NAME) - .getVertex(createResult.getKey(), BaseDocument.class, new GraphDocumentReadOptions().catchException(false)).get(); - fail(); - } catch (final ExecutionException e) { - assertThat(e.getCause()).isInstanceOf(ArangoDBException.class); - } + BaseDocument res = db.graph(GRAPH_NAME).vertexCollection(COLLECTION_NAME) + .getVertex(createResult.getKey(), BaseDocument.class, new GraphDocumentReadOptions()).get(); + assertThat(res).isNull(); } @Test From 452a1b4e98d51c244299fd24d6ab56dbd55ec6d5 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Mon, 15 Aug 2022 15:33:05 +0200 Subject: [PATCH 078/254] [DE-315] replace cursor stats with untyped map --- src/main/java/com/arangodb/ArangoCursor.java | 4 +- .../java/com/arangodb/entity/CursorStats.java | 44 ------------------- .../internal/cursor/ArangoCursorImpl.java | 4 +- .../cursor/entity/InternalCursorEntity.java | 6 +-- .../java/com/arangodb/ArangoDatabaseTest.java | 3 +- .../arangodb/async/ArangoDatabaseTest.java | 5 ++- 6 files changed, 12 insertions(+), 54 deletions(-) delete mode 100644 src/main/java/com/arangodb/entity/CursorStats.java diff --git a/src/main/java/com/arangodb/ArangoCursor.java b/src/main/java/com/arangodb/ArangoCursor.java index 928f14239..bbccfc068 100644 --- a/src/main/java/com/arangodb/ArangoCursor.java +++ b/src/main/java/com/arangodb/ArangoCursor.java @@ -20,12 +20,12 @@ package com.arangodb; -import com.arangodb.entity.CursorStats; import com.arangodb.entity.CursorWarning; import java.io.Closeable; import java.util.Collection; import java.util.List; +import java.util.Map; /** * @author Mark Vollmary @@ -53,7 +53,7 @@ public interface ArangoCursor extends ArangoIterable, ArangoIterator, C * number of modified documents and the number of documents that could not be modified due to an error (if * ignoreErrors query option is specified) */ - CursorStats getStats(); + Map getStats(); /** * @return warnings which the query could have been produced diff --git a/src/main/java/com/arangodb/entity/CursorStats.java b/src/main/java/com/arangodb/entity/CursorStats.java deleted file mode 100644 index 2bf822561..000000000 --- a/src/main/java/com/arangodb/entity/CursorStats.java +++ /dev/null @@ -1,44 +0,0 @@ -package com.arangodb.entity; - -public final class CursorStats { - private Long writesExecuted; - private Long writesIgnored; - private Long scannedFull; - private Long scannedIndex; - private Long filtered; - private Long fullCount; - private Double executionTime; - private Long peakMemoryUsage; - - public Long getWritesExecuted() { - return writesExecuted; - } - - public Long getWritesIgnored() { - return writesIgnored; - } - - public Long getScannedFull() { - return scannedFull; - } - - public Long getScannedIndex() { - return scannedIndex; - } - - public Long getFiltered() { - return filtered; - } - - public Long getFullCount() { - return fullCount; - } - - public Double getExecutionTime() { - return executionTime; - } - - public Long getPeakMemoryUsage() { - return peakMemoryUsage; - } -} diff --git a/src/main/java/com/arangodb/internal/cursor/ArangoCursorImpl.java b/src/main/java/com/arangodb/internal/cursor/ArangoCursorImpl.java index 1af8097fb..973e7a8c2 100644 --- a/src/main/java/com/arangodb/internal/cursor/ArangoCursorImpl.java +++ b/src/main/java/com/arangodb/internal/cursor/ArangoCursorImpl.java @@ -22,7 +22,6 @@ import com.arangodb.ArangoCursor; import com.arangodb.ArangoIterator; -import com.arangodb.entity.CursorStats; import com.arangodb.entity.CursorWarning; import com.arangodb.internal.cursor.entity.InternalCursorEntity; import com.arangodb.internal.cursor.entity.InternalCursorEntity.Extras; @@ -32,6 +31,7 @@ import java.util.ArrayList; import java.util.Collection; import java.util.List; +import java.util.Map; /** * @author Mark Vollmary @@ -76,7 +76,7 @@ public Integer getCount() { } @Override - public CursorStats getStats() { + public Map getStats() { final Extras extra = iterator.getResult().getExtra(); return extra != null ? extra.getStats() : null; } diff --git a/src/main/java/com/arangodb/internal/cursor/entity/InternalCursorEntity.java b/src/main/java/com/arangodb/internal/cursor/entity/InternalCursorEntity.java index 97d461116..e65aa5c48 100644 --- a/src/main/java/com/arangodb/internal/cursor/entity/InternalCursorEntity.java +++ b/src/main/java/com/arangodb/internal/cursor/entity/InternalCursorEntity.java @@ -20,9 +20,9 @@ package com.arangodb.internal.cursor.entity; -import com.arangodb.entity.CursorStats; import com.arangodb.entity.CursorWarning; import com.arangodb.entity.MetaAware; +import com.fasterxml.jackson.annotation.JsonAnySetter; import com.fasterxml.jackson.databind.JsonNode; import java.util.Collection; @@ -109,10 +109,10 @@ public void setMeta(Map meta) { } public static final class Extras { - private CursorStats stats; + private Map stats; private final Collection warnings = Collections.emptyList(); - public CursorStats getStats() { + public Map getStats() { return stats; } diff --git a/src/test/java/com/arangodb/ArangoDatabaseTest.java b/src/test/java/com/arangodb/ArangoDatabaseTest.java index 60986b452..6af8f64e1 100644 --- a/src/test/java/com/arangodb/ArangoDatabaseTest.java +++ b/src/test/java/com/arangodb/ArangoDatabaseTest.java @@ -593,7 +593,8 @@ void queryWithLimitAndFullCount(ArangoDatabase db) { assertThat((Iterator) cursor).hasNext(); } assertThat(cursor.getStats()).isNotNull(); - assertThat(cursor.getStats().getFullCount()).isGreaterThanOrEqualTo(10L); + assertThat((Integer) cursor.getStats().get("fullCount")) + .isGreaterThanOrEqualTo(10); } @ParameterizedTest(name = "{index}") diff --git a/src/test/java/com/arangodb/async/ArangoDatabaseTest.java b/src/test/java/com/arangodb/async/ArangoDatabaseTest.java index d9c2a14ef..54bade719 100644 --- a/src/test/java/com/arangodb/async/ArangoDatabaseTest.java +++ b/src/test/java/com/arangodb/async/ArangoDatabaseTest.java @@ -493,7 +493,8 @@ void queryWithLimitAndFullCount() throws InterruptedException, ExecutionExceptio assertThat(cursor.hasNext()).isEqualTo(true); } assertThat(cursor.getStats()).isNotNull(); - assertThat(cursor.getStats().getFullCount()).isEqualTo(10L); + assertThat((Integer) cursor.getStats().get("fullCount")) + .isGreaterThanOrEqualTo(10); }) .get(); } finally { @@ -889,7 +890,7 @@ void transactionNumber() throws InterruptedException, ExecutionException { } @Test - void transactionJsonNode() throws InterruptedException, ExecutionException { + void transactionJsonNode() throws InterruptedException, ExecutionException { final TransactionOptions options = new TransactionOptions().params(JsonNodeFactory.instance.textNode("test")); db.transaction("function (params) {return params;}", JsonNode.class, options) .whenComplete((result, ex) -> { From cdb57b7df9a29399ac68a8319d79b5bfd02681f1 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Mon, 15 Aug 2022 17:20:33 +0200 Subject: [PATCH 079/254] [DE-319] removed throws ArangoDBException declarations from API method signatures --- .../java/com/arangodb/ArangoCollection.java | 184 ++++++------------ src/main/java/com/arangodb/ArangoDB.java | 73 +++---- .../java/com/arangodb/ArangoDatabase.java | 173 ++++++---------- .../com/arangodb/ArangoEdgeCollection.java | 30 +-- src/main/java/com/arangodb/ArangoGraph.java | 38 ++-- src/main/java/com/arangodb/ArangoRoute.java | 18 +- src/main/java/com/arangodb/ArangoSearch.java | 15 +- .../com/arangodb/ArangoVertexCollection.java | 33 ++-- src/main/java/com/arangodb/ArangoView.java | 12 +- .../arangodb/async/ArangoCollectionAsync.java | 4 +- .../com/arangodb/async/ArangoDBAsync.java | 4 +- .../arangodb/async/ArangoDatabaseAsync.java | 9 +- .../internal/ArangoCollectionAsyncImpl.java | 4 +- .../async/internal/ArangoDBAsyncImpl.java | 2 +- .../internal/ArangoDatabaseAsyncImpl.java | 4 +- .../internal/ArangoCollectionImpl.java | 124 ++++++------ .../internal/ArangoCursorExecute.java | 4 +- .../com/arangodb/internal/ArangoDBImpl.java | 48 ++--- .../arangodb/internal/ArangoDatabaseImpl.java | 116 +++++------ .../internal/ArangoEdgeCollectionImpl.java | 20 +- .../arangodb/internal/ArangoExecutorSync.java | 8 +- .../arangodb/internal/ArangoGraphImpl.java | 26 +-- .../arangodb/internal/ArangoRouteImpl.java | 12 +- .../arangodb/internal/ArangoSearchImpl.java | 18 +- .../internal/ArangoVertexCollectionImpl.java | 22 +-- .../com/arangodb/internal/ArangoViewImpl.java | 8 +- .../internal/InternalArangoDBBuilder.java | 2 +- .../internal/http/HttpCommunication.java | 4 +- .../internal/http/HttpConnection.java | 4 +- .../arangodb/internal/http/HttpProtocol.java | 2 +- .../internal/net/CommunicationProtocol.java | 2 +- .../internal/net/ExtendedHostResolver.java | 2 +- .../arangodb/internal/util/DocumentUtil.java | 6 +- .../arangodb/internal/util/ResponseUtils.java | 2 +- .../velocystream/VstCommunication.java | 10 +- .../velocystream/VstCommunicationSync.java | 6 +- .../internal/velocystream/VstProtocol.java | 2 +- .../velocystream/internal/MessageStore.java | 2 +- .../velocystream/internal/VstConnection.java | 2 +- .../internal/VstConnectionSync.java | 2 +- 40 files changed, 432 insertions(+), 625 deletions(-) diff --git a/src/main/java/com/arangodb/ArangoCollection.java b/src/main/java/com/arangodb/ArangoCollection.java index ef178b820..9c6117989 100644 --- a/src/main/java/com/arangodb/ArangoCollection.java +++ b/src/main/java/com/arangodb/ArangoCollection.java @@ -57,11 +57,10 @@ public interface ArangoCollection extends ArangoSerdeAccessor { * * @param value A representation of a single document (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) * @return information about the document - * @throws ArangoDBException * @see API * Documentation */ - DocumentCreateEntity insertDocument(Object value) throws ArangoDBException; + DocumentCreateEntity insertDocument(Object value) ; /** * Creates a new document from the given document, unless there is already a document with the _key given. If no @@ -70,11 +69,10 @@ public interface ArangoCollection extends ArangoSerdeAccessor { * @param value A representation of a single document (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) * @param options Additional options * @return information about the document - * @throws ArangoDBException * @see API * Documentation */ - DocumentCreateEntity insertDocument(T value, DocumentCreateOptions options) throws ArangoDBException; + DocumentCreateEntity insertDocument(T value, DocumentCreateOptions options) ; /** * Creates a new document from the given document, unless there is already a document with the _key given. If no @@ -84,11 +82,10 @@ public interface ArangoCollection extends ArangoSerdeAccessor { * @param options Additional options * @param type Deserialization target type for the returned documents. * @return information about the document - * @throws ArangoDBException * @see API * Documentation */ - DocumentCreateEntity insertDocument(T value, DocumentCreateOptions options, Class type) throws ArangoDBException; + DocumentCreateEntity insertDocument(T value, DocumentCreateOptions options, Class type) ; /** * Creates new documents from the given documents, unless there is already a document with the _key given. If no @@ -96,11 +93,10 @@ public interface ArangoCollection extends ArangoSerdeAccessor { * * @param values A List of documents (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) * @return information about the documents - * @throws ArangoDBException * @see API * Documentation */ - MultiDocumentEntity> insertDocuments(Collection values) throws ArangoDBException; + MultiDocumentEntity> insertDocuments(Collection values) ; /** * Creates new documents from the given documents, unless there is already a document with the _key given. If no @@ -109,12 +105,11 @@ public interface ArangoCollection extends ArangoSerdeAccessor { * @param values A List of documents (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) * @param options Additional options * @return information about the documents - * @throws ArangoDBException * @see API * Documentation */ MultiDocumentEntity> insertDocuments( - Collection values, DocumentCreateOptions options) throws ArangoDBException; + Collection values, DocumentCreateOptions options) ; /** * Creates new documents from the given documents, unless there is already a document with the _key given. If no @@ -124,21 +119,19 @@ MultiDocumentEntity> insertDocuments( * @param options Additional options * @param type Deserialization target type for the returned documents. * @return information about the documents - * @throws ArangoDBException * @see API * Documentation */ MultiDocumentEntity> insertDocuments( - Collection values, DocumentCreateOptions options, Class type) throws ArangoDBException; + Collection values, DocumentCreateOptions options, Class type) ; /** * Bulk imports the given values into the collection. * * @param values a list of Objects that will be stored as documents * @return information about the import - * @throws ArangoDBException */ - DocumentImportEntity importDocuments(Collection values) throws ArangoDBException; + DocumentImportEntity importDocuments(Collection values) ; /** * Bulk imports the given values into the collection. @@ -146,18 +139,16 @@ MultiDocumentEntity> insertDocuments( * @param values a list of Objects that will be stored as documents * @param options Additional options, can be null * @return information about the import - * @throws ArangoDBException */ - DocumentImportEntity importDocuments(Collection values, DocumentImportOptions options) throws ArangoDBException; + DocumentImportEntity importDocuments(Collection values, DocumentImportOptions options) ; /** * Bulk imports the given values into the collection. * * @param values JSON-encoded array of objects that will be stored as documents * @return information about the import - * @throws ArangoDBException */ - DocumentImportEntity importDocuments(String values) throws ArangoDBException; + DocumentImportEntity importDocuments(String values) ; /** * Bulk imports the given values into the collection. @@ -165,9 +156,8 @@ MultiDocumentEntity> insertDocuments( * @param values JSON-encoded array of objects that will be stored as documents * @param options Additional options, can be null * @return information about the import - * @throws ArangoDBException */ - DocumentImportEntity importDocuments(String values, DocumentImportOptions options) throws ArangoDBException; + DocumentImportEntity importDocuments(String values, DocumentImportOptions options) ; /** * Retrieves the document with the given {@code key} from the collection. @@ -175,11 +165,10 @@ MultiDocumentEntity> insertDocuments( * @param key The key of the document * @param type The type of the document (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) * @return the document identified by the key - * @throws ArangoDBException * @see API * Documentation */ - T getDocument(String key, Class type) throws ArangoDBException; + T getDocument(String key, Class type) ; /** * Retrieves the document with the given {@code key} from the collection. @@ -188,11 +177,10 @@ MultiDocumentEntity> insertDocuments( * @param type The type of the document (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) * @param options Additional options, can be null * @return the document identified by the key - * @throws ArangoDBException * @see API * Documentation */ - T getDocument(String key, Class type, DocumentReadOptions options) throws ArangoDBException; + T getDocument(String key, Class type, DocumentReadOptions options) ; /** * Retrieves multiple documents with the given {@code _key} from the collection. @@ -200,9 +188,8 @@ MultiDocumentEntity> insertDocuments( * @param keys The keys of the documents * @param type The type of the documents (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) * @return the documents and possible errors - * @throws ArangoDBException */ - MultiDocumentEntity getDocuments(Collection keys, Class type) throws ArangoDBException; + MultiDocumentEntity getDocuments(Collection keys, Class type) ; /** * Retrieves multiple documents with the given {@code _key} from the collection. @@ -211,10 +198,9 @@ MultiDocumentEntity> insertDocuments( * @param type The type of the documents (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) * @param options Additional options, can be null * @return the documents and possible errors - * @throws ArangoDBException */ MultiDocumentEntity getDocuments(Collection keys, Class type, DocumentReadOptions options) - throws ArangoDBException; + ; /** * Replaces the document with {@code key} with the one in the body, provided there is such a document and no @@ -223,11 +209,10 @@ MultiDocumentEntity getDocuments(Collection keys, Class type, * @param key The key of the document * @param value A representation of a single document (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) * @return information about the document - * @throws ArangoDBException * @see API * Documentation */ - DocumentUpdateEntity replaceDocument(String key, Object value) throws ArangoDBException; + DocumentUpdateEntity replaceDocument(String key, Object value) ; /** * Replaces the document with {@code key} with the one in the body, provided there is such a document and no @@ -237,12 +222,11 @@ MultiDocumentEntity getDocuments(Collection keys, Class type, * @param value A representation of a single document (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) * @param options Additional options * @return information about the document - * @throws ArangoDBException * @see API * Documentation */ DocumentUpdateEntity replaceDocument(String key, T value, DocumentReplaceOptions options) - throws ArangoDBException; + ; /** * Replaces the document with {@code key} with the one in the body, provided there is such a document and no @@ -253,12 +237,11 @@ DocumentUpdateEntity replaceDocument(String key, T value, DocumentReplace * @param options Additional options * @param type Deserialization target type for the returned documents. * @return information about the document - * @throws ArangoDBException * @see API * Documentation */ DocumentUpdateEntity replaceDocument(String key, T value, DocumentReplaceOptions options, Class type) - throws ArangoDBException; + ; /** * Replaces multiple documents in the specified collection with the ones in the values, the replaced documents are @@ -266,11 +249,10 @@ DocumentUpdateEntity replaceDocument(String key, T value, DocumentReplace * * @param values A List of documents (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) * @return information about the documents - * @throws ArangoDBException * @see API * Documentation */ - MultiDocumentEntity> replaceDocuments(Collection values) throws ArangoDBException; + MultiDocumentEntity> replaceDocuments(Collection values) ; /** * Replaces multiple documents in the specified collection with the ones in the values, the replaced documents are @@ -279,12 +261,11 @@ DocumentUpdateEntity replaceDocument(String key, T value, DocumentReplace * @param values A List of documents (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) * @param options Additional options * @return information about the documents - * @throws ArangoDBException * @see API * Documentation */ MultiDocumentEntity> replaceDocuments( - Collection values, DocumentReplaceOptions options) throws ArangoDBException; + Collection values, DocumentReplaceOptions options) ; /** * Replaces multiple documents in the specified collection with the ones in the values, the replaced documents are @@ -294,12 +275,11 @@ MultiDocumentEntity> replaceDocuments( * @param options Additional options * @param type Deserialization target type for the returned documents. * @return information about the documents - * @throws ArangoDBException * @see API * Documentation */ MultiDocumentEntity> replaceDocuments( - Collection values, DocumentReplaceOptions options, Class type) throws ArangoDBException; + Collection values, DocumentReplaceOptions options, Class type) ; /** * Partially updates the document identified by document-key. The value must contain a document with the attributes @@ -309,11 +289,10 @@ MultiDocumentEntity> replaceDocuments( * @param key The key of the document * @param value A representation of a single document (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) * @return information about the document - * @throws ArangoDBException * @see API * Documentation */ - DocumentUpdateEntity updateDocument(String key, Object value) throws ArangoDBException; + DocumentUpdateEntity updateDocument(String key, Object value) ; /** * Partially updates the document identified by document-key. The value must contain a document with the attributes @@ -324,12 +303,11 @@ MultiDocumentEntity> replaceDocuments( * @param value A representation of a single document (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) * @param options Additional options * @return information about the document - * @throws ArangoDBException * @see API * Documentation */ DocumentUpdateEntity updateDocument(String key, T value, DocumentUpdateOptions options) - throws ArangoDBException; + ; /** * Partially updates the document identified by document-key. The value must contain a document with the attributes @@ -341,12 +319,11 @@ DocumentUpdateEntity updateDocument(String key, T value, DocumentUpdateOp * @param options Additional options * @param returnType Type of the returned newDocument and/or oldDocument * @return information about the document - * @throws ArangoDBException * @see API * Documentation */ DocumentUpdateEntity updateDocument(String key, Object value, DocumentUpdateOptions options, Class returnType) - throws ArangoDBException; + ; /** * Partially updates documents, the documents to update are specified by the _key attributes in the objects on @@ -356,11 +333,10 @@ DocumentUpdateEntity updateDocument(String key, Object value, DocumentUpd * * @param values A list of documents (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) * @return information about the documents - * @throws ArangoDBException * @see API * Documentation */ - MultiDocumentEntity> updateDocuments(Collection values) throws ArangoDBException; + MultiDocumentEntity> updateDocuments(Collection values) ; /** * Partially updates documents, the documents to update are specified by the _key attributes in the objects on @@ -371,12 +347,11 @@ DocumentUpdateEntity updateDocument(String key, Object value, DocumentUpd * @param values A list of documents (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) * @param options Additional options * @return information about the documents - * @throws ArangoDBException * @see API * Documentation */ MultiDocumentEntity> updateDocuments( - Collection values, DocumentUpdateOptions options) throws ArangoDBException; + Collection values, DocumentUpdateOptions options) ; /** * Partially updates documents, the documents to update are specified by the _key attributes in the objects on @@ -388,23 +363,21 @@ MultiDocumentEntity> updateDocuments( * @param options Additional options * @param returnType Type of the returned newDocument and/or oldDocument * @return information about the documents - * @throws ArangoDBException * @see API * Documentation */ MultiDocumentEntity> updateDocuments( - Collection values, DocumentUpdateOptions options, Class returnType) throws ArangoDBException; + Collection values, DocumentUpdateOptions options, Class returnType) ; /** * Deletes the document with the given {@code key} from the collection. * * @param key The key of the document * @return information about the document - * @throws ArangoDBException * @see API * Documentation */ - DocumentDeleteEntity deleteDocument(String key) throws ArangoDBException; + DocumentDeleteEntity deleteDocument(String key) ; /** * Deletes the document with the given {@code key} from the collection. @@ -412,12 +385,11 @@ MultiDocumentEntity> updateDocuments( * @param key The key of the document * @param options Additional options * @return information about the document - * @throws ArangoDBException * @see API * Documentation */ DocumentDeleteEntity deleteDocument(String key, DocumentDeleteOptions options) - throws ArangoDBException; + ; /** * Deletes the document with the given {@code key} from the collection. @@ -426,24 +398,22 @@ DocumentDeleteEntity deleteDocument(String key, DocumentDeleteOptions opti * @param type Deserialization target type for the returned documents. * @param options Additional options * @return information about the document - * @throws ArangoDBException * @see API * Documentation */ DocumentDeleteEntity deleteDocument(String key, DocumentDeleteOptions options, Class type) - throws ArangoDBException; + ; /** * Deletes multiple documents from the collection. * * @param values The keys of the documents or the documents themselves * @return information about the documents - * @throws ArangoDBException * @see API * Documentation */ - MultiDocumentEntity> deleteDocuments(Collection values) throws ArangoDBException; + MultiDocumentEntity> deleteDocuments(Collection values) ; /** * Deletes multiple documents from the collection. @@ -451,13 +421,12 @@ DocumentDeleteEntity deleteDocument(String key, DocumentDeleteOptions opt * @param values The keys of the documents or the documents themselves * @param options Additional options * @return information about the documents - * @throws ArangoDBException * @see API * Documentation */ MultiDocumentEntity> deleteDocuments( - Collection values, DocumentDeleteOptions options) throws ArangoDBException; + Collection values, DocumentDeleteOptions options) ; /** * Deletes multiple documents from the collection. @@ -466,13 +435,12 @@ MultiDocumentEntity> deleteDocuments( * @param type Deserialization target type for the returned documents. * @param options Additional options * @return information about the documents - * @throws ArangoDBException * @see API * Documentation */ MultiDocumentEntity> deleteDocuments( - Collection values, DocumentDeleteOptions options, Class type) throws ArangoDBException; + Collection values, DocumentDeleteOptions options, Class type) ; /** * Checks if the document exists by reading a single document head @@ -491,32 +459,30 @@ MultiDocumentEntity> deleteDocuments( * @param key The key of the document * @param options Additional options, can be null * @return true if the document was found, otherwise false - * @throws ArangoDBException only thrown when {@link DocumentExistsOptions#isCatchException()} == false + * only thrown when {@link DocumentExistsOptions#isCatchException()} == false * @see API * Documentation */ - Boolean documentExists(String key, DocumentExistsOptions options) throws ArangoDBException; + Boolean documentExists(String key, DocumentExistsOptions options) ; /** * Fetches information about the index with the given {@code id} and returns it. * * @param id The index-handle * @return information about the index - * @throws ArangoDBException * @see API Documentation */ - IndexEntity getIndex(String id) throws ArangoDBException; + IndexEntity getIndex(String id) ; /** * Deletes the index with the given {@code id} from the collection. * * @param id The index-handle * @return the id of the index - * @throws ArangoDBException * @see API Documentation */ - String deleteIndex(String id) throws ArangoDBException; + String deleteIndex(String id) ; /** * Creates a hash index for the collection if it does not already exist. @@ -524,13 +490,12 @@ MultiDocumentEntity> deleteDocuments( * @param fields A list of attribute paths * @param options Additional options, can be null * @return information about the index - * @throws ArangoDBException * @see API Documentation * @deprecated use {@link #ensurePersistentIndex(Iterable, PersistentIndexOptions)} instead. Since ArangoDB 3.7 a * hash index is an alias for a persistent index. */ @Deprecated - IndexEntity ensureHashIndex(Iterable fields, HashIndexOptions options) throws ArangoDBException; + IndexEntity ensureHashIndex(Iterable fields, HashIndexOptions options) ; /** * Creates a skip-list index for the collection, if it does not already exist. @@ -538,14 +503,13 @@ MultiDocumentEntity> deleteDocuments( * @param fields A list of attribute paths * @param options Additional options, can be null * @return information about the index - * @throws ArangoDBException * @see API * Documentation * @deprecated use {@link #ensurePersistentIndex(Iterable, PersistentIndexOptions)} instead. Since ArangoDB 3.7 a * skiplist index is an alias for a persistent index. */ @Deprecated - IndexEntity ensureSkiplistIndex(Iterable fields, SkiplistIndexOptions options) throws ArangoDBException; + IndexEntity ensureSkiplistIndex(Iterable fields, SkiplistIndexOptions options) ; /** * Creates a persistent index for the collection, if it does not already exist. @@ -553,11 +517,10 @@ MultiDocumentEntity> deleteDocuments( * @param fields A list of attribute paths * @param options Additional options, can be null * @return information about the index - * @throws ArangoDBException * @see API * Documentation */ - IndexEntity ensurePersistentIndex(Iterable fields, PersistentIndexOptions options) throws ArangoDBException; + IndexEntity ensurePersistentIndex(Iterable fields, PersistentIndexOptions options) ; /** * Creates a geo-spatial index for the collection, if it does not already exist. @@ -565,11 +528,10 @@ MultiDocumentEntity> deleteDocuments( * @param fields A list of attribute paths * @param options Additional options, can be null * @return information about the index - * @throws ArangoDBException * @see API * Documentation */ - IndexEntity ensureGeoIndex(Iterable fields, GeoIndexOptions options) throws ArangoDBException; + IndexEntity ensureGeoIndex(Iterable fields, GeoIndexOptions options) ; /** * Creates a fulltext index for the collection, if it does not already exist. @@ -577,11 +539,10 @@ MultiDocumentEntity> deleteDocuments( * @param fields A list of attribute paths * @param options Additional options, can be null * @return information about the index - * @throws ArangoDBException * @see API * Documentation */ - IndexEntity ensureFulltextIndex(Iterable fields, FulltextIndexOptions options) throws ArangoDBException; + IndexEntity ensureFulltextIndex(Iterable fields, FulltextIndexOptions options) ; /** * Creates a ttl index for the collection, if it does not already exist. @@ -589,11 +550,10 @@ MultiDocumentEntity> deleteDocuments( * @param fields A list of attribute paths * @param options Additional options, can be null * @return information about the index - * @throws ArangoDBException * @see API * Documentation */ - IndexEntity ensureTtlIndex(Iterable fields, TtlIndexOptions options) throws ArangoDBException; + IndexEntity ensureTtlIndex(Iterable fields, TtlIndexOptions options) ; /** * Creates a ZKD multi-dimensional index for the collection, if it does not already exist. @@ -602,85 +562,78 @@ MultiDocumentEntity> deleteDocuments( * @param fields A list of attribute paths * @param options Additional options, can be null * @return information about the index - * @throws ArangoDBException * @see API Documentation * @since ArangoDB 3.9 */ - IndexEntity ensureZKDIndex(Iterable fields, ZKDIndexOptions options) throws ArangoDBException; + IndexEntity ensureZKDIndex(Iterable fields, ZKDIndexOptions options) ; /** * Fetches a list of all indexes on this collection. * * @return information about the indexes - * @throws ArangoDBException * @see API * Documentation */ - Collection getIndexes() throws ArangoDBException; + Collection getIndexes() ; /** * Checks whether the collection exists * * @return true if the collection exists, otherwise false */ - boolean exists() throws ArangoDBException; + boolean exists() ; /** * Removes all documents from the collection, but leaves the indexes intact * * @return information about the collection - * @throws ArangoDBException * @see API * Documentation */ - CollectionEntity truncate() throws ArangoDBException; + CollectionEntity truncate() ; /** * Removes all documents from the collection, but leaves the indexes intact * * @param options * @return information about the collection - * @throws ArangoDBException * @see API * Documentation * @since ArangoDB 3.5.0 */ - CollectionEntity truncate(CollectionTruncateOptions options) throws ArangoDBException; + CollectionEntity truncate(CollectionTruncateOptions options) ; /** * Counts the documents in a collection * * @return information about the collection, including the number of documents - * @throws ArangoDBException * @see API * Documentation */ - CollectionPropertiesEntity count() throws ArangoDBException; + CollectionPropertiesEntity count() ; /** * Counts the documents in a collection * * @param options * @return information about the collection, including the number of documents - * @throws ArangoDBException * @see API * Documentation * @since ArangoDB 3.5.0 */ - CollectionPropertiesEntity count(CollectionCountOptions options) throws ArangoDBException; + CollectionPropertiesEntity count(CollectionCountOptions options) ; /** * Creates a collection for this collection's name, then returns collection information from the server. * * @return information about the collection - * @throws ArangoDBException * @see API * Documentation */ - CollectionEntity create() throws ArangoDBException; + CollectionEntity create() ; /** * Creates a collection with the given {@code options} for this collection's name, then returns collection @@ -688,77 +641,70 @@ MultiDocumentEntity> deleteDocuments( * * @param options Additional options, can be null * @return information about the collection - * @throws ArangoDBException * @see API * Documentation */ - CollectionEntity create(CollectionCreateOptions options) throws ArangoDBException; + CollectionEntity create(CollectionCreateOptions options) ; /** * Deletes the collection from the database. * - * @throws ArangoDBException * @see API * Documentation */ - void drop() throws ArangoDBException; + void drop() ; /** * Deletes the collection from the database. * * @param isSystem Whether or not the collection to drop is a system collection. This parameter must be set to true in * order to drop a system collection. - * @throws ArangoDBException * @see API * Documentation * @since ArangoDB 3.1.0 */ - void drop(boolean isSystem) throws ArangoDBException; + void drop(boolean isSystem) ; /** * Returns information about the collection * * @return information about the collection - * @throws ArangoDBException * @see API * Documentation */ - CollectionEntity getInfo() throws ArangoDBException; + CollectionEntity getInfo() ; /** * Reads the properties of the specified collection * * @return properties of the collection - * @throws ArangoDBException * @see API * Documentation */ - CollectionPropertiesEntity getProperties() throws ArangoDBException; + CollectionPropertiesEntity getProperties() ; /** * Changes the properties of the collection * * @param options Additional options, can be null * @return properties of the collection - * @throws ArangoDBException * @see API * Documentation */ - CollectionPropertiesEntity changeProperties(CollectionPropertiesOptions options) throws ArangoDBException; + CollectionPropertiesEntity changeProperties(CollectionPropertiesOptions options) ; /** * Renames the collection * * @param newName The new name * @return information about the collection - * @throws ArangoDBException * @see API * Documentation */ - CollectionEntity rename(String newName) throws ArangoDBException; + CollectionEntity rename(String newName) ; /** * Returns the responsible shard for the document. @@ -767,7 +713,6 @@ MultiDocumentEntity> deleteDocuments( * @param value A projection of the document containing at least the shard key (_key or a custom attribute) for * which the responsible shard should be determined * @return information about the responsible shard - * @throws ArangoDBException * @see * API Documentation * @since ArangoDB 3.5.0 @@ -778,11 +723,10 @@ MultiDocumentEntity> deleteDocuments( * Retrieve the collections revision * * @return information about the collection, including the collections revision - * @throws ArangoDBException * @see API * Documentation */ - CollectionRevisionEntity getRevision() throws ArangoDBException; + CollectionRevisionEntity getRevision() ; /** * Grants or revoke access to the collection for user user. You need permission to the _system database in order to @@ -790,47 +734,43 @@ MultiDocumentEntity> deleteDocuments( * * @param user The name of the user * @param permissions The permissions the user grant - * @throws ArangoDBException * @see API * Documentation */ - void grantAccess(String user, Permissions permissions) throws ArangoDBException; + void grantAccess(String user, Permissions permissions) ; /** * Revokes access to the collection for user user. You need permission to the _system database in order to execute * this call. * * @param user The name of the user - * @throws ArangoDBException * @see API * Documentation */ - void revokeAccess(String user) throws ArangoDBException; + void revokeAccess(String user) ; /** * Clear the collection access level, revert back to the default access level. * * @param user The name of the user - * @throws ArangoDBException * @see API * Documentation * @since ArangoDB 3.2.0 */ - void resetAccess(String user) throws ArangoDBException; + void resetAccess(String user) ; /** * Get the collection access level * * @param user The name of the user * @return permissions of the user - * @throws ArangoDBException * @see * API Documentation * @since ArangoDB 3.2.0 */ - Permissions getPermissions(String user) throws ArangoDBException; + Permissions getPermissions(String user) ; } diff --git a/src/main/java/com/arangodb/ArangoDB.java b/src/main/java/com/arangodb/ArangoDB.java index 9b112c97e..899771d58 100644 --- a/src/main/java/com/arangodb/ArangoDB.java +++ b/src/main/java/com/arangodb/ArangoDB.java @@ -105,7 +105,7 @@ public Builder useProtocol(final Protocol protocol) { } @Override - public Builder loadProperties(final InputStream in) throws ArangoDBException { + public Builder loadProperties(final InputStream in) { super.loadProperties(in); return this; } @@ -383,9 +383,8 @@ public synchronized ArangoDB build() { /** * Releases all connections to the server and clear the connection pool. * - * @throws ArangoDBException */ - void shutdown() throws ArangoDBException; + void shutdown() ; /** * Updates the JWT used for requests authorization. It does not change already existing VST connections, since VST @@ -420,94 +419,85 @@ public synchronized ArangoDB build() { * * @param dbName Name of the database to create * @return true if the database was created successfully. - * @throws ArangoDBException * @see API * Documentation */ - Boolean createDatabase(DbName dbName) throws ArangoDBException; + Boolean createDatabase(DbName dbName) ; /** * Creates a new database with the given name. * * @param options Creation options * @return true if the database was created successfully. - * @throws ArangoDBException * @see API * Documentation * @since ArangoDB 3.6.0 */ - Boolean createDatabase(DBCreateOptions options) throws ArangoDBException; + Boolean createDatabase(DBCreateOptions options) ; /** * Retrieves a list of all existing databases * * @return a list of all existing databases - * @throws ArangoDBException * @see API * Documentation */ - Collection getDatabases() throws ArangoDBException; + Collection getDatabases() ; /** * Retrieves a list of all databases the current user can access * * @return a list of all databases the current user can access - * @throws ArangoDBException * @see API * Documentation */ - Collection getAccessibleDatabases() throws ArangoDBException; + Collection getAccessibleDatabases() ; /** * List available database to the specified user * * @param user The name of the user for which you want to query the databases * @return list of database names which are available for the specified user - * @throws ArangoDBException * @see API * Documentation */ - Collection getAccessibleDatabasesFor(String user) throws ArangoDBException; + Collection getAccessibleDatabasesFor(String user) ; /** * Returns the server name and version number. * * @return the server version, number - * @throws ArangoDBException * @see API * Documentation */ - ArangoDBVersion getVersion() throws ArangoDBException; + ArangoDBVersion getVersion() ; /** * Returns the server storage engine. * * @return the storage engine name - * @throws ArangoDBException * @see API * Documentation */ - ArangoDBEngine getEngine() throws ArangoDBException; + ArangoDBEngine getEngine() ; /** * Returns the server role. * * @return the server role - * @throws ArangoDBException */ - ServerRole getRole() throws ArangoDBException; + ServerRole getRole() ; /** * Returns the id of a server in a cluster. * * @return the server id - * @throws ArangoDBException * @see API * Documentation */ - String getServerId() throws ArangoDBException; + String getServerId() ; /** * Create a new user. This user will not have access to any database. You need permission to the _system database in @@ -516,10 +506,9 @@ public synchronized ArangoDB build() { * @param user The name of the user * @param passwd The user password * @return information about the user - * @throws ArangoDBException * @see API Documentation */ - UserEntity createUser(String user, String passwd) throws ArangoDBException; + UserEntity createUser(String user, String passwd) ; /** * Create a new user. This user will not have access to any database. You need permission to the _system database in @@ -529,19 +518,17 @@ public synchronized ArangoDB build() { * @param passwd The user password * @param options Additional options, can be null * @return information about the user - * @throws ArangoDBException * @see API Documentation */ - UserEntity createUser(String user, String passwd, UserCreateOptions options) throws ArangoDBException; + UserEntity createUser(String user, String passwd, UserCreateOptions options) ; /** * Removes an existing user, identified by user. You need access to the _system database. * * @param user The name of the user - * @throws ArangoDBException * @see API Documentation */ - void deleteUser(String user) throws ArangoDBException; + void deleteUser(String user) ; /** * Fetches data about the specified user. You can fetch information about yourself or you need permission to the @@ -549,20 +536,18 @@ public synchronized ArangoDB build() { * * @param user The name of the user * @return information about the user - * @throws ArangoDBException * @see API Documentation */ - UserEntity getUser(String user) throws ArangoDBException; + UserEntity getUser(String user) ; /** * Fetches data about all users. You can only execute this call if you have access to the _system database. * * @return informations about all users - * @throws ArangoDBException * @see API * Documentation */ - Collection getUsers() throws ArangoDBException; + Collection getUsers() ; /** * Partially updates the data of an existing user. The name of an existing user must be specified in user. You can @@ -571,10 +556,9 @@ public synchronized ArangoDB build() { * @param user The name of the user * @param options Properties of the user to be changed * @return information about the user - * @throws ArangoDBException * @see API Documentation */ - UserEntity updateUser(String user, UserUpdateOptions options) throws ArangoDBException; + UserEntity updateUser(String user, UserUpdateOptions options) ; /** * Replaces the data of an existing user. The name of an existing user must be specified in user. You can only @@ -583,11 +567,10 @@ public synchronized ArangoDB build() { * @param user The name of the user * @param options Additional properties of the user, can be null * @return information about the user - * @throws ArangoDBException * @see API * Documentation */ - UserEntity replaceUser(String user, UserUpdateOptions options) throws ArangoDBException; + UserEntity replaceUser(String user, UserUpdateOptions options) ; /** * Sets the default access level for databases for the user {@code user}. You need permission to the _system @@ -595,10 +578,9 @@ public synchronized ArangoDB build() { * * @param user The name of the user * @param permissions The permissions the user grant - * @throws ArangoDBException * @since ArangoDB 3.2.0 */ - void grantDefaultDatabaseAccess(String user, Permissions permissions) throws ArangoDBException; + void grantDefaultDatabaseAccess(String user, Permissions permissions) ; /** * Sets the default access level for collections for the user {@code user}. You need permission to the _system @@ -606,19 +588,17 @@ public synchronized ArangoDB build() { * * @param user The name of the user * @param permissions The permissions the user grant - * @throws ArangoDBException * @since ArangoDB 3.2.0 */ - void grantDefaultCollectionAccess(String user, Permissions permissions) throws ArangoDBException; + void grantDefaultCollectionAccess(String user, Permissions permissions) ; /** * Generic Execute. Use this method to execute custom FOXX services. * * @param request VelocyStream request * @return VelocyStream response - * @throws ArangoDBException */ - Response execute(Request request) throws ArangoDBException; + Response execute(Request request) ; /** * Generic Execute. Use this method to execute custom FOXX services. @@ -626,9 +606,8 @@ public synchronized ArangoDB build() { * @param request VelocyStream request * @param hostHandle Used to stick to a specific host when using {@link LoadBalancingStrategy#ROUND_ROBIN} * @return VelocyStream response - * @throws ArangoDBException */ - Response execute(Request request, HostHandle hostHandle) throws ArangoDBException; + Response execute(Request request, HostHandle hostHandle) ; /** * Returns the server logs @@ -639,26 +618,24 @@ public synchronized ArangoDB build() { * Documentation * @since ArangoDB 3.8 */ - LogEntriesEntity getLogEntries(LogOptions options) throws ArangoDBException; + LogEntriesEntity getLogEntries(LogOptions options) ; /** * Returns the server's current loglevel settings. * * @return the server's current loglevel settings - * @throws ArangoDBException * @since ArangoDB 3.1.0 */ - LogLevelEntity getLogLevel() throws ArangoDBException; + LogLevelEntity getLogLevel() ; /** * Modifies and returns the server's current loglevel settings. * * @param entity loglevel settings * @return the server's current loglevel settings - * @throws ArangoDBException * @since ArangoDB 3.1.0 */ - LogLevelEntity setLogLevel(LogLevelEntity entity) throws ArangoDBException; + LogLevelEntity setLogLevel(LogLevelEntity entity) ; /** * Attention: Please do not use! diff --git a/src/main/java/com/arangodb/ArangoDatabase.java b/src/main/java/com/arangodb/ArangoDatabase.java index 58d055418..82db21d82 100644 --- a/src/main/java/com/arangodb/ArangoDatabase.java +++ b/src/main/java/com/arangodb/ArangoDatabase.java @@ -58,39 +58,36 @@ public interface ArangoDatabase extends ArangoSerdeAccessor { * Returns the server name and version number. * * @return the server version, number - * @throws ArangoDBException * @see API * Documentation */ - ArangoDBVersion getVersion() throws ArangoDBException; + ArangoDBVersion getVersion() ; /** * Returns the name of the used storage engine. * * @return the storage engine name - * @throws ArangoDBException * @see API * Documentation */ - ArangoDBEngine getEngine() throws ArangoDBException; + ArangoDBEngine getEngine() ; /** * Checks whether the database exists * * @return true if the database exists, otherwise false */ - boolean exists() throws ArangoDBException; + boolean exists() ; /** * Retrieves a list of all databases the current user can access * * @return a list of all databases the current user can access - * @throws ArangoDBException * @see API * Documentation */ - Collection getAccessibleDatabases() throws ArangoDBException; + Collection getAccessibleDatabases() ; /** * Returns a {@code ArangoCollection} instance for the given collection name. @@ -105,11 +102,10 @@ public interface ArangoDatabase extends ArangoSerdeAccessor { * * @param name The name of the collection * @return information about the collection - * @throws ArangoDBException * @see API * Documentation */ - CollectionEntity createCollection(String name) throws ArangoDBException; + CollectionEntity createCollection(String name) ; /** * Creates a collection with the given {@code options} for this collection's name, then returns collection @@ -118,72 +114,65 @@ public interface ArangoDatabase extends ArangoSerdeAccessor { * @param name The name of the collection * @param options Additional options, can be null * @return information about the collection - * @throws ArangoDBException * @see API * Documentation */ - CollectionEntity createCollection(String name, CollectionCreateOptions options) throws ArangoDBException; + CollectionEntity createCollection(String name, CollectionCreateOptions options) ; /** * Fetches all collections from the database and returns an list of collection descriptions. * * @return list of information about all collections - * @throws ArangoDBException * @see API * Documentation */ - Collection getCollections() throws ArangoDBException; + Collection getCollections() ; /** * Fetches all collections from the database and returns an list of collection descriptions. * * @param options Additional options, can be null * @return list of information about all collections - * @throws ArangoDBException * @see API * Documentation */ - Collection getCollections(CollectionsReadOptions options) throws ArangoDBException; + Collection getCollections(CollectionsReadOptions options) ; /** * Returns an index * * @param id The index-handle * @return information about the index - * @throws ArangoDBException * @see API Documentation */ - IndexEntity getIndex(String id) throws ArangoDBException; + IndexEntity getIndex(String id) ; /** * Deletes an index * * @param id The index-handle * @return the id of the index - * @throws ArangoDBException * @see API Documentation */ - String deleteIndex(String id) throws ArangoDBException; + String deleteIndex(String id) ; /** * Creates the database * * @return true if the database was created successfully. - * @throws ArangoDBException * @see API * Documentation */ - Boolean create() throws ArangoDBException; + Boolean create() ; /** * Deletes the database from the server. * * @return true if the database was dropped successfully - * @throws ArangoDBException * @see API * Documentation */ - Boolean drop() throws ArangoDBException; + Boolean drop() ; /** * Grants or revoke access to the database for user {@code user}. You need permission to the _system database in @@ -191,44 +180,40 @@ public interface ArangoDatabase extends ArangoSerdeAccessor { * * @param user The name of the user * @param permissions The permissions the user grant - * @throws ArangoDBException * @see * API Documentation */ - void grantAccess(String user, Permissions permissions) throws ArangoDBException; + void grantAccess(String user, Permissions permissions) ; /** * Grants access to the database for user {@code user}. You need permission to the _system database in order to * execute this call. * * @param user The name of the user - * @throws ArangoDBException * @see * API Documentation */ - void grantAccess(String user) throws ArangoDBException; + void grantAccess(String user) ; /** * Revokes access to the database dbname for user {@code user}. You need permission to the _system database in order * to execute this call. * * @param user The name of the user - * @throws ArangoDBException * @see * API Documentation */ - void revokeAccess(String user) throws ArangoDBException; + void revokeAccess(String user) ; /** * Clear the database access level, revert back to the default access level. * * @param user The name of the user - * @throws ArangoDBException * @see * API Documentation * @since ArangoDB 3.2.0 */ - void resetAccess(String user) throws ArangoDBException; + void resetAccess(String user) ; /** * Sets the default access level for collections within this database for the user {@code user}. You need permission @@ -236,22 +221,20 @@ public interface ArangoDatabase extends ArangoSerdeAccessor { * * @param user The name of the user * @param permissions The permissions the user grant - * @throws ArangoDBException * @since ArangoDB 3.2.0 */ - void grantDefaultCollectionAccess(String user, Permissions permissions) throws ArangoDBException; + void grantDefaultCollectionAccess(String user, Permissions permissions) ; /** * Get specific database access level * * @param user The name of the user * @return permissions of the user - * @throws ArangoDBException * @see API * Documentation * @since ArangoDB 3.2.0 */ - Permissions getPermissions(String user) throws ArangoDBException; + Permissions getPermissions(String user) ; /** * Performs a database query using the given {@code query} and {@code bindVars}, then returns a new @@ -262,12 +245,11 @@ public interface ArangoDatabase extends ArangoSerdeAccessor { * @param options Additional options that will be passed to the query API, can be null * @param type The type of the result (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) * @return cursor of the results - * @throws ArangoDBException * @see API * Documentation */ ArangoCursor query(String query, Map bindVars, AqlQueryOptions options, Class type) - throws ArangoDBException; + ; /** * Performs a database query using the given {@code query}, then returns a new {@code ArangoCursor} instance for the @@ -277,11 +259,10 @@ ArangoCursor query(String query, Map bindVars, AqlQueryOp * @param options Additional options that will be passed to the query API, can be null * @param type The type of the result (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) * @return cursor of the results - * @throws ArangoDBException * @see API * Documentation */ - ArangoCursor query(String query, AqlQueryOptions options, Class type) throws ArangoDBException; + ArangoCursor query(String query, AqlQueryOptions options, Class type) ; /** * Performs a database query using the given {@code query} and {@code bindVars}, then returns a new @@ -291,11 +272,10 @@ ArangoCursor query(String query, Map bindVars, AqlQueryOp * @param bindVars key/value pairs defining the variables to bind the query to * @param type The type of the result (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) * @return cursor of the results - * @throws ArangoDBException * @see API * Documentation */ - ArangoCursor query(String query, Map bindVars, Class type) throws ArangoDBException; + ArangoCursor query(String query, Map bindVars, Class type) ; /** * Performs a database query using the given {@code query}, then returns a new {@code ArangoCursor} instance for the @@ -304,11 +284,10 @@ ArangoCursor query(String query, Map bindVars, AqlQueryOp * @param query An AQL query string * @param type The type of the result (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) * @return cursor of the results - * @throws ArangoDBException * @see API * Documentation */ - ArangoCursor query(String query, Class type) throws ArangoDBException; + ArangoCursor query(String query, Class type) ; /** * Return an cursor from the given cursor-ID if still existing @@ -316,12 +295,11 @@ ArangoCursor query(String query, Map bindVars, AqlQueryOp * @param cursorId The ID of the cursor * @param type The type of the result (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) * @return cursor of the results - * @throws ArangoDBException * @see API * Documentation */ - ArangoCursor cursor(String cursorId, Class type) throws ArangoDBException; + ArangoCursor cursor(String cursorId, Class type) ; /** * Explain an AQL query and return information about it @@ -330,12 +308,11 @@ ArangoCursor query(String query, Map bindVars, AqlQueryOp * @param bindVars key/value pairs representing the bind parameters * @param options Additional options, can be null * @return information about the query - * @throws ArangoDBException * @see API * Documentation */ AqlExecutionExplainEntity explainQuery(String query, Map bindVars, AqlQueryExplainOptions options) - throws ArangoDBException; + ; /** * Parse an AQL query and return information about it This method is for query validation only. To actually query @@ -343,32 +320,29 @@ AqlExecutionExplainEntity explainQuery(String query, Map bindVar * * @param query the query which you want parse * @return imformation about the query - * @throws ArangoDBException * @see API * Documentation */ - AqlParseEntity parseQuery(String query) throws ArangoDBException; + AqlParseEntity parseQuery(String query) ; /** * Clears the AQL query cache * - * @throws ArangoDBException * @see API * Documentation */ - void clearQueryCache() throws ArangoDBException; + void clearQueryCache() ; /** * Returns the global configuration for the AQL query cache * * @return configuration for the AQL query cache - * @throws ArangoDBException * @see API * Documentation */ - QueryCachePropertiesEntity getQueryCacheProperties() throws ArangoDBException; + QueryCachePropertiesEntity getQueryCacheProperties() ; /** * Changes the configuration for the AQL query cache. Note: changing the properties may invalidate all results in @@ -376,78 +350,71 @@ AqlExecutionExplainEntity explainQuery(String query, Map bindVar * * @param properties properties to be set * @return current set of properties - * @throws ArangoDBException * @see API * Documentation */ - QueryCachePropertiesEntity setQueryCacheProperties(QueryCachePropertiesEntity properties) throws ArangoDBException; + QueryCachePropertiesEntity setQueryCacheProperties(QueryCachePropertiesEntity properties) ; /** * Returns the configuration for the AQL query tracking * * @return configuration for the AQL query tracking - * @throws ArangoDBException * @see API * Documentation */ - QueryTrackingPropertiesEntity getQueryTrackingProperties() throws ArangoDBException; + QueryTrackingPropertiesEntity getQueryTrackingProperties() ; /** * Changes the configuration for the AQL query tracking * * @param properties properties to be set * @return current set of properties - * @throws ArangoDBException * @see API * Documentation */ QueryTrackingPropertiesEntity setQueryTrackingProperties(QueryTrackingPropertiesEntity properties) - throws ArangoDBException; + ; /** * Returns a list of currently running AQL queries * * @return a list of currently running AQL queries - * @throws ArangoDBException * @see API * Documentation */ - Collection getCurrentlyRunningQueries() throws ArangoDBException; + Collection getCurrentlyRunningQueries() ; /** * Returns a list of slow running AQL queries * * @return a list of slow running AQL queries - * @throws ArangoDBException * @see API * Documentation */ - Collection getSlowQueries() throws ArangoDBException; + Collection getSlowQueries() ; /** * Clears the list of slow AQL queries * - * @throws ArangoDBException * @see API * Documentation */ - void clearSlowQueries() throws ArangoDBException; + void clearSlowQueries() ; /** * Kills a running query. The query will be terminated at the next cancelation point. * * @param id The id of the query - * @throws ArangoDBException * @see API * Documentation */ - void killQuery(String id) throws ArangoDBException; + void killQuery(String id) ; /** * Create a new AQL user function @@ -455,11 +422,10 @@ QueryTrackingPropertiesEntity setQueryTrackingProperties(QueryTrackingProperties * @param name A valid AQL function name, e.g.: `"myfuncs::accounting::calculate_vat"` * @param code A String evaluating to a JavaScript function * @param options Additional options, can be null - * @throws ArangoDBException * @see API * Documentation */ - void createAqlFunction(String name, String code, AqlFunctionCreateOptions options) throws ArangoDBException; + void createAqlFunction(String name, String code, AqlFunctionCreateOptions options) ; /** * Deletes the AQL user function with the given name from the database. @@ -467,24 +433,22 @@ QueryTrackingPropertiesEntity setQueryTrackingProperties(QueryTrackingProperties * @param name The name of the user function to delete * @param options Additional options, can be null * @return number of deleted functions (since ArangoDB 3.4.0) - * @throws ArangoDBException * @see API * Documentation */ - Integer deleteAqlFunction(String name, AqlFunctionDeleteOptions options) throws ArangoDBException; + Integer deleteAqlFunction(String name, AqlFunctionDeleteOptions options) ; /** * Gets all reqistered AQL user functions * * @param options Additional options, can be null * @return all reqistered AQL user functions - * @throws ArangoDBException * @see API * Documentation */ - Collection getAqlFunctions(AqlFunctionGetOptions options) throws ArangoDBException; + Collection getAqlFunctions(AqlFunctionGetOptions options) ; /** * Returns a {@code ArangoGraph} instance for the given graph name. @@ -501,11 +465,10 @@ QueryTrackingPropertiesEntity setQueryTrackingProperties(QueryTrackingProperties * @param name Name of the graph * @param edgeDefinitions An array of definitions for the edge * @return information about the graph - * @throws ArangoDBException * @see API * Documentation */ - GraphEntity createGraph(String name, Collection edgeDefinitions) throws ArangoDBException; + GraphEntity createGraph(String name, Collection edgeDefinitions) ; /** * Create a new graph in the graph module. The creation of a graph requires the name of the graph and a definition @@ -515,22 +478,20 @@ QueryTrackingPropertiesEntity setQueryTrackingProperties(QueryTrackingProperties * @param edgeDefinitions An array of definitions for the edge * @param options Additional options, can be null * @return information about the graph - * @throws ArangoDBException * @see API * Documentation */ GraphEntity createGraph(String name, Collection edgeDefinitions, GraphCreateOptions options) - throws ArangoDBException; + ; /** * Lists all graphs known to the graph module * * @return graphs stored in this database - * @throws ArangoDBException * @see API * Documentation */ - Collection getGraphs() throws ArangoDBException; + Collection getGraphs() ; /** * Performs a server-side transaction and returns its return value. @@ -539,77 +500,70 @@ GraphEntity createGraph(String name, Collection edgeDefinitions, * @param type The type of the result (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) * @param options Additional options, can be null * @return the result of the transaction if it succeeded - * @throws ArangoDBException * @see API * Documentation */ - T transaction(String action, Class type, TransactionOptions options) throws ArangoDBException; + T transaction(String action, Class type, TransactionOptions options) ; /** * Begins a Stream Transaction. * * @param options Additional options, can be null * @return information about the transaction - * @throws ArangoDBException * @see API * Documentation * @since ArangoDB 3.5.0 */ - StreamTransactionEntity beginStreamTransaction(StreamTransactionOptions options) throws ArangoDBException; + StreamTransactionEntity beginStreamTransaction(StreamTransactionOptions options) ; /** * Aborts a Stream Transaction. * * @return information about the transaction - * @throws ArangoDBException * @see API * Documentation */ - StreamTransactionEntity abortStreamTransaction(String id) throws ArangoDBException; + StreamTransactionEntity abortStreamTransaction(String id) ; /** * Gets information about a Stream Transaction. * * @return information about the transaction - * @throws ArangoDBException * @see * API Documentation * @since ArangoDB 3.5.0 */ - StreamTransactionEntity getStreamTransaction(String id) throws ArangoDBException; + StreamTransactionEntity getStreamTransaction(String id) ; /** * Gets all the currently running Stream Transactions. * * @return all the currently running Stream Transactions - * @throws ArangoDBException * @see * API Documentation * @since ArangoDB 3.5.0 */ - Collection getStreamTransactions() throws ArangoDBException; + Collection getStreamTransactions() ; /** * Commits a Stream Transaction. * * @return information about the transaction - * @throws ArangoDBException * @see * API Documentation * @since ArangoDB 3.5.0 */ - StreamTransactionEntity commitStreamTransaction(String id) throws ArangoDBException; + StreamTransactionEntity commitStreamTransaction(String id) ; /** * Retrieves information about the current database * * @return information about the current database - * @throws ArangoDBException * @see API * Documentation */ - DatabaseEntity getInfo() throws ArangoDBException; + DatabaseEntity getInfo() ; /** * Reads a single document @@ -617,11 +571,10 @@ GraphEntity createGraph(String name, Collection edgeDefinitions, * @param id The id of the document * @param type The type of the document (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) * @return the document identified by the id - * @throws ArangoDBException * @see API * Documentation */ - T getDocument(String id, Class type) throws ArangoDBException; + T getDocument(String id, Class type) ; /** * Reads a single document @@ -630,21 +583,19 @@ GraphEntity createGraph(String name, Collection edgeDefinitions, * @param type The type of the document (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) * @param options Additional options, can be null * @return the document identified by the id - * @throws ArangoDBException * @see API * Documentation */ - T getDocument(String id, Class type, DocumentReadOptions options) throws ArangoDBException; + T getDocument(String id, Class type, DocumentReadOptions options) ; /** * Reload the routing table. * - * @throws ArangoDBException * @see API * Documentation */ - void reloadRouting() throws ArangoDBException; + void reloadRouting() ; /** * Returns a new {@link ArangoRoute} instance for the given path (relative to the database) that can be used to @@ -659,11 +610,10 @@ GraphEntity createGraph(String name, Collection edgeDefinitions, * Fetches all views from the database and returns an list of view descriptions. * * @return list of information about all views - * @throws ArangoDBException * @see API Documentation * @since ArangoDB 3.4.0 */ - Collection getViews() throws ArangoDBException; + Collection getViews() ; /** * Returns a {@code ArangoView} instance for the given view name. @@ -689,10 +639,9 @@ GraphEntity createGraph(String name, Collection edgeDefinitions, * @param name The name of the view * @param type The type of the view * @return information about the view - * @throws ArangoDBException * @since ArangoDB 3.4.0 */ - ViewEntity createView(String name, ViewType type) throws ArangoDBException; + ViewEntity createView(String name, ViewType type) ; /** * Creates a ArangoSearch view with the given {@code options}, then returns view information from the server. @@ -700,64 +649,58 @@ GraphEntity createGraph(String name, Collection edgeDefinitions, * @param name The name of the view * @param options Additional options, can be null * @return information about the view - * @throws ArangoDBException * @see API * Documentation * @since ArangoDB 3.4.0 */ - ViewEntity createArangoSearch(String name, ArangoSearchCreateOptions options) throws ArangoDBException; + ViewEntity createArangoSearch(String name, ArangoSearchCreateOptions options) ; /** * Creates an Analyzer * * @param analyzer SearchAnalyzer * @return the created Analyzer - * @throws ArangoDBException * @see API Documentation * @since ArangoDB 3.5.0 */ - SearchAnalyzer createSearchAnalyzer(SearchAnalyzer analyzer) throws ArangoDBException; + SearchAnalyzer createSearchAnalyzer(SearchAnalyzer analyzer) ; /** * Gets information about an Analyzer * * @param name of the Analyzer without database prefix * @return information about an Analyzer - * @throws ArangoDBException * @see API Documentation * @since ArangoDB 3.5.0 */ - SearchAnalyzer getSearchAnalyzer(String name) throws ArangoDBException; + SearchAnalyzer getSearchAnalyzer(String name) ; /** * Retrieves all analyzers definitions. * * @return collection of all analyzers definitions - * @throws ArangoDBException * @see API Documentation * @since ArangoDB 3.5.0 */ - Collection getSearchAnalyzers() throws ArangoDBException; + Collection getSearchAnalyzers() ; /** * Deletes an Analyzer * * @param name of the Analyzer without database prefix - * @throws ArangoDBException * @see API Documentation * @since ArangoDB 3.5.0 */ - void deleteSearchAnalyzer(String name) throws ArangoDBException; + void deleteSearchAnalyzer(String name) ; /** * Deletes an Analyzer * * @param name of the Analyzer without database prefix * @param options AnalyzerDeleteOptions - * @throws ArangoDBException * @see API Documentation * @since ArangoDB 3.5.0 */ - void deleteSearchAnalyzer(String name, AnalyzerDeleteOptions options) throws ArangoDBException; + void deleteSearchAnalyzer(String name, AnalyzerDeleteOptions options) ; } diff --git a/src/main/java/com/arangodb/ArangoEdgeCollection.java b/src/main/java/com/arangodb/ArangoEdgeCollection.java index 0c8bbc45d..cd0e58204 100644 --- a/src/main/java/com/arangodb/ArangoEdgeCollection.java +++ b/src/main/java/com/arangodb/ArangoEdgeCollection.java @@ -52,10 +52,9 @@ public interface ArangoEdgeCollection extends ArangoSerdeAccessor { * * @param value A representation of a single edge (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) * @return information about the edge - * @throws ArangoDBException * @see API Documentation */ - EdgeEntity insertEdge(T value) throws ArangoDBException; + EdgeEntity insertEdge(T value) ; /** * Creates a new edge in the collection @@ -63,10 +62,9 @@ public interface ArangoEdgeCollection extends ArangoSerdeAccessor { * @param value A representation of a single edge (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) * @param options Additional options, can be null * @return information about the edge - * @throws ArangoDBException * @see API Documentation */ - EdgeEntity insertEdge(T value, EdgeCreateOptions options) throws ArangoDBException; + EdgeEntity insertEdge(T value, EdgeCreateOptions options) ; /** * Fetches an existing edge @@ -74,10 +72,9 @@ public interface ArangoEdgeCollection extends ArangoSerdeAccessor { * @param key The key of the edge * @param type The type of the edge-document (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) * @return the edge identified by the key - * @throws ArangoDBException * @see API Documentation */ - T getEdge(String key, Class type) throws ArangoDBException; + T getEdge(String key, Class type) ; /** * Fetches an existing edge @@ -86,10 +83,9 @@ public interface ArangoEdgeCollection extends ArangoSerdeAccessor { * @param type The type of the edge-document (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) * @param options Additional options, can be null * @return the edge identified by the key - * @throws ArangoDBException * @see API Documentation */ - T getEdge(String key, Class type, GraphDocumentReadOptions options) throws ArangoDBException; + T getEdge(String key, Class type, GraphDocumentReadOptions options) ; /** * Replaces the edge with key with the one in the body, provided there is such a edge and no precondition is @@ -98,10 +94,9 @@ public interface ArangoEdgeCollection extends ArangoSerdeAccessor { * @param key The key of the edge * @param The type of the edge-document (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) * @return information about the edge - * @throws ArangoDBException * @see API Documentation */ - EdgeUpdateEntity replaceEdge(String key, T value) throws ArangoDBException; + EdgeUpdateEntity replaceEdge(String key, T value) ; /** * Replaces the edge with key with the one in the body, provided there is such a edge and no precondition is @@ -111,10 +106,9 @@ public interface ArangoEdgeCollection extends ArangoSerdeAccessor { * @param The type of the edge-document (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) * @param options Additional options, can be null * @return information about the edge - * @throws ArangoDBException * @see API Documentation */ - EdgeUpdateEntity replaceEdge(String key, T value, EdgeReplaceOptions options) throws ArangoDBException; + EdgeUpdateEntity replaceEdge(String key, T value, EdgeReplaceOptions options) ; /** * Partially updates the edge identified by document-key. The value must contain a document with the attributes to @@ -124,10 +118,9 @@ public interface ArangoEdgeCollection extends ArangoSerdeAccessor { * @param key The key of the edge * @param The type of the edge-document (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) * @return information about the edge - * @throws ArangoDBException * @see API Documentation */ - EdgeUpdateEntity updateEdge(String key, T value) throws ArangoDBException; + EdgeUpdateEntity updateEdge(String key, T value) ; /** * Partially updates the edge identified by document-key. The value must contain a document with the attributes to @@ -138,28 +131,25 @@ public interface ArangoEdgeCollection extends ArangoSerdeAccessor { * @param The type of the edge-document (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) * @param options Additional options, can be null * @return information about the edge - * @throws ArangoDBException * @see API Documentation */ - EdgeUpdateEntity updateEdge(String key, T value, EdgeUpdateOptions options) throws ArangoDBException; + EdgeUpdateEntity updateEdge(String key, T value, EdgeUpdateOptions options) ; /** * Removes a edge * * @param key The key of the edge - * @throws ArangoDBException * @see API Documentation */ - void deleteEdge(String key) throws ArangoDBException; + void deleteEdge(String key) ; /** * Removes a edge * * @param key The key of the edge * @param options Additional options, can be null - * @throws ArangoDBException * @see API Documentation */ - void deleteEdge(String key, EdgeDeleteOptions options) throws ArangoDBException; + void deleteEdge(String key, EdgeDeleteOptions options) ; } diff --git a/src/main/java/com/arangodb/ArangoGraph.java b/src/main/java/com/arangodb/ArangoGraph.java index a9b562a68..0288b5768 100644 --- a/src/main/java/com/arangodb/ArangoGraph.java +++ b/src/main/java/com/arangodb/ArangoGraph.java @@ -54,7 +54,7 @@ public interface ArangoGraph extends ArangoSerdeAccessor { * * @return true if the graph exists, otherwise false */ - boolean exists() throws ArangoDBException; + boolean exists() ; /** * Creates the graph in the graph module. The creation of a graph requires the name of the graph and a definition of @@ -62,11 +62,10 @@ public interface ArangoGraph extends ArangoSerdeAccessor { * * @param edgeDefinitions An array of definitions for the edge * @return information about the graph - * @throws ArangoDBException * @see API * Documentation */ - GraphEntity create(Collection edgeDefinitions) throws ArangoDBException; + GraphEntity create(Collection edgeDefinitions) ; /** * Creates the graph in the graph module. The creation of a graph requires the name of the graph and a definition of @@ -75,50 +74,45 @@ public interface ArangoGraph extends ArangoSerdeAccessor { * @param edgeDefinitions An array of definitions for the edge * @param options Additional options, can be null * @return information about the graph - * @throws ArangoDBException * @see API * Documentation */ - GraphEntity create(Collection edgeDefinitions, GraphCreateOptions options) throws ArangoDBException; + GraphEntity create(Collection edgeDefinitions, GraphCreateOptions options) ; /** * Deletes the graph from the database. * - * @throws ArangoDBException * @see API Documentation */ - void drop() throws ArangoDBException; + void drop() ; /** * Deletes the graph from the database. * * @param dropCollections Drop collections of this graph as well. Collections will only be * dropped if they are not used in other graphs. - * @throws ArangoDBException * @see API * Documentation */ - void drop(boolean dropCollections) throws ArangoDBException; + void drop(boolean dropCollections) ; /** * Retrieves general information about the graph. * * @return the definition content of this graph - * @throws ArangoDBException * @see API Documentation */ - GraphEntity getInfo() throws ArangoDBException; + GraphEntity getInfo() ; /** * Fetches all vertex collections from the graph and returns a list of collection names. * * @return all vertex collections within this graph - * @throws ArangoDBException * @see API * Documentation */ - Collection getVertexCollections() throws ArangoDBException; + Collection getVertexCollections() ; /** * Adds a vertex collection to the set of collections of the graph. If the collection does not exist, it will be @@ -126,11 +120,10 @@ public interface ArangoGraph extends ArangoSerdeAccessor { * * @param name Name of the vertex collection * @return information about the graph - * @throws ArangoDBException * @see API * Documentation */ - GraphEntity addVertexCollection(String name) throws ArangoDBException; + GraphEntity addVertexCollection(String name) ; /** * Adds a vertex collection to the set of collections of the graph. If the collection does not exist, it will be @@ -139,12 +132,11 @@ public interface ArangoGraph extends ArangoSerdeAccessor { * @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; + GraphEntity addVertexCollection(String name, VertexCollectionCreateOptions options) ; /** * Returns a {@code ArangoVertexCollection} instance for the given vertex collection name. @@ -166,22 +158,20 @@ public interface ArangoGraph extends ArangoSerdeAccessor { * Fetches all edge collections from the graph and returns a list of collection names. * * @return all edge collections within this graph - * @throws ArangoDBException * @see API * Documentation */ - Collection getEdgeDefinitions() throws ArangoDBException; + Collection getEdgeDefinitions() ; /** * Adds the given edge definition to the graph. * * @param definition The edge definition * @return information about the graph - * @throws ArangoDBException * @see API * Documentation */ - GraphEntity addEdgeDefinition(EdgeDefinition definition) throws ArangoDBException; + GraphEntity addEdgeDefinition(EdgeDefinition definition) ; /** * Change one specific edge definition. This will modify all occurrences of this definition in all graphs known to @@ -189,11 +179,10 @@ public interface ArangoGraph extends ArangoSerdeAccessor { * * @param definition The edge definition * @return information about the graph - * @throws ArangoDBException * @see API * Documentation */ - GraphEntity replaceEdgeDefinition(EdgeDefinition definition) throws ArangoDBException; + GraphEntity replaceEdgeDefinition(EdgeDefinition definition) ; /** * Remove one edge definition from the graph. This will only remove the edge collection, the vertex collections @@ -201,11 +190,10 @@ public interface ArangoGraph extends ArangoSerdeAccessor { * * @param definitionName The name of the edge collection used in the definition * @return information about the graph - * @throws ArangoDBException * @see API * Documentation */ - GraphEntity removeEdgeDefinition(String definitionName) throws ArangoDBException; + GraphEntity removeEdgeDefinition(String definitionName) ; } diff --git a/src/main/java/com/arangodb/ArangoRoute.java b/src/main/java/com/arangodb/ArangoRoute.java index b9a393add..ee343014b 100644 --- a/src/main/java/com/arangodb/ArangoRoute.java +++ b/src/main/java/com/arangodb/ArangoRoute.java @@ -68,53 +68,47 @@ public interface ArangoRoute extends ArangoSerdeAccessor { * Performs a DELETE request to the given URL and returns the server response. * * @return server response - * @throws ArangoDBException */ - Response delete() throws ArangoDBException; + Response delete() ; /** * Performs a GET request to the given URL and returns the server response. * * @return server response - * @throws ArangoDBException */ - Response get() throws ArangoDBException; + Response get() ; /** * Performs a HEAD request to the given URL and returns the server response. * * @return server response - * @throws ArangoDBException */ - Response head() throws ArangoDBException; + Response head() ; /** * Performs a PATCH request to the given URL and returns the server response. * * @return server response - * @throws ArangoDBException */ - Response patch() throws ArangoDBException; + Response patch() ; /** * Performs a POST request to the given URL and returns the server response. * * @return server response - * @throws ArangoDBException */ - Response post() throws ArangoDBException; + Response post() ; /** * Performs a PUT request to the given URL and returns the server response. * * @return server response - * @throws ArangoDBException */ - Response put() throws ArangoDBException; + Response put() ; } diff --git a/src/main/java/com/arangodb/ArangoSearch.java b/src/main/java/com/arangodb/ArangoSearch.java index 7a6600d79..e587e32a6 100644 --- a/src/main/java/com/arangodb/ArangoSearch.java +++ b/src/main/java/com/arangodb/ArangoSearch.java @@ -38,55 +38,50 @@ public interface ArangoSearch extends ArangoView { * Creates a view, then returns view information from the server. * * @return information about the view - * @throws ArangoDBException * @see API * Documentation */ - ViewEntity create() throws ArangoDBException; + ViewEntity create() ; /** * Creates a view with the given {@code options}, then returns view information from the server. * * @param options Additional options, can be null * @return information about the view - * @throws ArangoDBException * @see API * Documentation */ - ViewEntity create(ArangoSearchCreateOptions options) throws ArangoDBException; + ViewEntity create(ArangoSearchCreateOptions options) ; /** * Reads the properties of the specified view. * * @return properties of the view - * @throws ArangoDBException * @see API * Documentation */ - ArangoSearchPropertiesEntity getProperties() throws ArangoDBException; + ArangoSearchPropertiesEntity getProperties() ; /** * Partially changes properties of the view. * * @param options properties to change * @return properties of the view - * @throws ArangoDBException * @see API * Documentation */ - ArangoSearchPropertiesEntity updateProperties(ArangoSearchPropertiesOptions options) throws ArangoDBException; + ArangoSearchPropertiesEntity updateProperties(ArangoSearchPropertiesOptions options) ; /** * Changes properties of the view. * * @param options properties to change * @return properties of the view - * @throws ArangoDBException * @see API * Documentation */ - ArangoSearchPropertiesEntity replaceProperties(ArangoSearchPropertiesOptions options) throws ArangoDBException; + ArangoSearchPropertiesEntity replaceProperties(ArangoSearchPropertiesOptions options) ; } diff --git a/src/main/java/com/arangodb/ArangoVertexCollection.java b/src/main/java/com/arangodb/ArangoVertexCollection.java index 0d514a9fc..5faa507b3 100644 --- a/src/main/java/com/arangodb/ArangoVertexCollection.java +++ b/src/main/java/com/arangodb/ArangoVertexCollection.java @@ -50,21 +50,19 @@ public interface ArangoVertexCollection extends ArangoSerdeAccessor { * Removes a vertex collection from the graph and optionally deletes the collection, if it is not used in any other * graph * - * @throws ArangoDBException * @see API * Documentation */ - void drop() throws ArangoDBException; + void drop() ; /** * Creates a new vertex in the collection * * @param value A representation of a single vertex (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) * @return information about the vertex - * @throws ArangoDBException * @see API Documentation */ - VertexEntity insertVertex(T value) throws ArangoDBException; + VertexEntity insertVertex(T value) ; /** * Creates a new vertex in the collection @@ -72,10 +70,9 @@ public interface ArangoVertexCollection extends ArangoSerdeAccessor { * @param value A representation of a single vertex (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) * @param options Additional options, can be null * @return information about the vertex - * @throws ArangoDBException * @see API Documentation */ - VertexEntity insertVertex(T value, VertexCreateOptions options) throws ArangoDBException; + VertexEntity insertVertex(T value, VertexCreateOptions options) ; /** * Retrieves the vertex document with the given {@code key} from the collection. @@ -83,10 +80,9 @@ public interface ArangoVertexCollection extends ArangoSerdeAccessor { * @param key The key of the vertex * @param type The type of the vertex-document (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) * @return the vertex identified by the key - * @throws ArangoDBException * @see API Documentation */ - T getVertex(String key, Class type) throws ArangoDBException; + T getVertex(String key, Class type) ; /** * Retrieves the vertex document with the given {@code key} from the collection. @@ -95,10 +91,9 @@ public interface ArangoVertexCollection extends ArangoSerdeAccessor { * @param type The type of the vertex-document (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) * @param options Additional options, can be null * @return the vertex identified by the key - * @throws ArangoDBException * @see API Documentation */ - T getVertex(String key, Class type, GraphDocumentReadOptions options) throws ArangoDBException; + T getVertex(String key, Class type, GraphDocumentReadOptions options) ; /** * Replaces the vertex with key with the one in the body, provided there is such a vertex and no precondition is @@ -107,11 +102,10 @@ public interface ArangoVertexCollection extends ArangoSerdeAccessor { * @param key The key of the vertex * @param value A representation of a single vertex (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) * @return information about the vertex - * @throws ArangoDBException * @see API * Documentation */ - VertexUpdateEntity replaceVertex(String key, T value) throws ArangoDBException; + VertexUpdateEntity replaceVertex(String key, T value) ; /** * Replaces the vertex with key with the one in the body, provided there is such a vertex and no precondition is @@ -121,11 +115,10 @@ public interface ArangoVertexCollection extends ArangoSerdeAccessor { * @param value A representation of a single vertex (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) * @param options Additional options, can be null * @return information about the vertex - * @throws ArangoDBException * @see API * Documentation */ - VertexUpdateEntity replaceVertex(String key, T value, VertexReplaceOptions options) throws ArangoDBException; + VertexUpdateEntity replaceVertex(String key, T value, VertexReplaceOptions options) ; /** * Partially updates the vertex identified by document-key. The value must contain a document with the attributes to @@ -135,10 +128,9 @@ public interface ArangoVertexCollection extends ArangoSerdeAccessor { * @param key The key of the vertex * @param The type of the vertex-document (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) * @return information about the vertex - * @throws ArangoDBException * @see API Documentation */ - VertexUpdateEntity updateVertex(String key, T value) throws ArangoDBException; + VertexUpdateEntity updateVertex(String key, T value) ; /** * Partially updates the vertex identified by document-key. The value must contain a document with the attributes to @@ -149,28 +141,25 @@ public interface ArangoVertexCollection extends ArangoSerdeAccessor { * @param The type of the vertex-document (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) * @param options Additional options, can be null * @return information about the vertex - * @throws ArangoDBException * @see API Documentation */ - VertexUpdateEntity updateVertex(String key, T value, VertexUpdateOptions options) throws ArangoDBException; + VertexUpdateEntity updateVertex(String key, T value, VertexUpdateOptions options) ; /** * Deletes the vertex with the given {@code key} from the collection. * * @param key The key of the vertex - * @throws ArangoDBException * @see API Documentation */ - void deleteVertex(String key) throws ArangoDBException; + void deleteVertex(String key) ; /** * Deletes the vertex with the given {@code key} from the collection. * * @param key The key of the vertex * @param options Additional options, can be null - * @throws ArangoDBException * @see API Documentation */ - void deleteVertex(String key, VertexDeleteOptions options) throws ArangoDBException; + void deleteVertex(String key, VertexDeleteOptions options) ; } diff --git a/src/main/java/com/arangodb/ArangoView.java b/src/main/java/com/arangodb/ArangoView.java index b275d1131..411d462cf 100644 --- a/src/main/java/com/arangodb/ArangoView.java +++ b/src/main/java/com/arangodb/ArangoView.java @@ -50,36 +50,32 @@ public interface ArangoView extends ArangoSerdeAccessor { * Checks whether the view exists. * * @return true if the view exists, otherwise false - * @throws ArangoDBException */ - boolean exists() throws ArangoDBException; + boolean exists() ; /** * Deletes the view from the database. * - * @throws ArangoDBException * @see API Documentation */ - void drop() throws ArangoDBException; + void drop() ; /** * Renames the view. * * @param newName The new name * @return information about the view - * @throws ArangoDBException * @see API Documentation */ - ViewEntity rename(String newName) throws ArangoDBException; + ViewEntity rename(String newName) ; /** * Returns information about the view. * * @return information about the view - * @throws ArangoDBException * @see API * Documentation */ - ViewEntity getInfo() throws ArangoDBException; + ViewEntity getInfo() ; } diff --git a/src/main/java/com/arangodb/async/ArangoCollectionAsync.java b/src/main/java/com/arangodb/async/ArangoCollectionAsync.java index ea15c98fe..80903d627 100644 --- a/src/main/java/com/arangodb/async/ArangoCollectionAsync.java +++ b/src/main/java/com/arangodb/async/ArangoCollectionAsync.java @@ -174,7 +174,7 @@ CompletableFuture importDocuments( * @see API * Documentation */ - CompletableFuture getDocument(final String key, final Class type) throws ArangoDBException; + CompletableFuture getDocument(final String key, final Class type) ; /** * Reads a single document @@ -187,7 +187,7 @@ CompletableFuture importDocuments( * Documentation */ CompletableFuture getDocument(final String key, final Class type, final DocumentReadOptions options) - throws ArangoDBException; + ; /** * Reads multiple documents diff --git a/src/main/java/com/arangodb/async/ArangoDBAsync.java b/src/main/java/com/arangodb/async/ArangoDBAsync.java index 77a3bdabd..7a97a20ee 100644 --- a/src/main/java/com/arangodb/async/ArangoDBAsync.java +++ b/src/main/java/com/arangodb/async/ArangoDBAsync.java @@ -68,7 +68,7 @@ */ public interface ArangoDBAsync extends ArangoSerdeAccessor { - void shutdown() throws ArangoDBException; + void shutdown() ; /** * Updates the JWT used for requests authorization. It does not change already existing VST connections, since VST @@ -310,7 +310,7 @@ public Builder() { } @Override - public Builder loadProperties(final InputStream in) throws ArangoDBException { + public Builder loadProperties(final InputStream in) { super.loadProperties(in); return this; } diff --git a/src/main/java/com/arangodb/async/ArangoDatabaseAsync.java b/src/main/java/com/arangodb/async/ArangoDatabaseAsync.java index 4f525c838..2e5ffba1f 100644 --- a/src/main/java/com/arangodb/async/ArangoDatabaseAsync.java +++ b/src/main/java/com/arangodb/async/ArangoDatabaseAsync.java @@ -600,7 +600,7 @@ CompletableFuture createGraph( * @see API * Documentation */ - CompletableFuture getDocument(final String id, final Class type) throws ArangoDBException; + CompletableFuture getDocument(final String id, final Class type) ; /** * Reads a single document @@ -613,7 +613,7 @@ CompletableFuture createGraph( * Documentation */ CompletableFuture getDocument(final String id, final Class type, final DocumentReadOptions options) - throws ArangoDBException; + ; /** * Reload the routing table. @@ -688,7 +688,6 @@ CompletableFuture getDocument(final String id, final Class type, final * * @param analyzer SearchAnalyzer * @return the created Analyzer - * @throws ArangoDBException * @see API Documentation * @since ArangoDB 3.5.0 */ @@ -699,7 +698,6 @@ CompletableFuture getDocument(final String id, final Class type, final * * @param name of the Analyzer without database prefix * @return information about an Analyzer - * @throws ArangoDBException * @see API Documentation * @since ArangoDB 3.5.0 */ @@ -709,7 +707,6 @@ CompletableFuture getDocument(final String id, final Class type, final * Retrieves all analyzers definitions. * * @return collection of all analyzers definitions - * @throws ArangoDBException * @see API Documentation * @since ArangoDB 3.5.0 */ @@ -719,7 +716,6 @@ CompletableFuture getDocument(final String id, final Class type, final * Deletes an Analyzer * * @param name of the Analyzer without database prefix - * @throws ArangoDBException * @see API Documentation * @since ArangoDB 3.5.0 */ @@ -730,7 +726,6 @@ CompletableFuture getDocument(final String id, final Class type, final * * @param name of the Analyzer without database prefix * @param options AnalyzerDeleteOptions - * @throws ArangoDBException * @see API Documentation * @since ArangoDB 3.5.0 */ diff --git a/src/main/java/com/arangodb/async/internal/ArangoCollectionAsyncImpl.java b/src/main/java/com/arangodb/async/internal/ArangoCollectionAsyncImpl.java index 9c4b03b6c..3d20579e9 100644 --- a/src/main/java/com/arangodb/async/internal/ArangoCollectionAsyncImpl.java +++ b/src/main/java/com/arangodb/async/internal/ArangoCollectionAsyncImpl.java @@ -112,7 +112,7 @@ public CompletableFuture importDocuments( } @Override - public CompletableFuture getDocument(final String key, final Class type) throws ArangoDBException { + public CompletableFuture getDocument(final String key, final Class type) { return getDocument(key, type, new DocumentReadOptions()); } @@ -120,7 +120,7 @@ public CompletableFuture getDocument(final String key, final Class typ public CompletableFuture getDocument( final String key, final Class type, - final DocumentReadOptions options) throws ArangoDBException { + final DocumentReadOptions options) { DocumentUtil.validateDocumentKey(key); return executor.execute(getDocumentRequest(key, options), getDocumentResponseDeserializer(type)) .exceptionally(ExceptionUtil.catchGetDocumentExceptions()); diff --git a/src/main/java/com/arangodb/async/internal/ArangoDBAsyncImpl.java b/src/main/java/com/arangodb/async/internal/ArangoDBAsyncImpl.java index dc9ab39fc..44a0dd3b5 100644 --- a/src/main/java/com/arangodb/async/internal/ArangoDBAsyncImpl.java +++ b/src/main/java/com/arangodb/async/internal/ArangoDBAsyncImpl.java @@ -95,7 +95,7 @@ protected ArangoExecutorAsync executor() { } @Override - public void shutdown() throws ArangoDBException { + public void shutdown() { try { executor.disconnect(); } finally { diff --git a/src/main/java/com/arangodb/async/internal/ArangoDatabaseAsyncImpl.java b/src/main/java/com/arangodb/async/internal/ArangoDatabaseAsyncImpl.java index 24598853f..76d883a88 100644 --- a/src/main/java/com/arangodb/async/internal/ArangoDatabaseAsyncImpl.java +++ b/src/main/java/com/arangodb/async/internal/ArangoDatabaseAsyncImpl.java @@ -387,7 +387,7 @@ public CompletableFuture getInfo() { } @Override - public CompletableFuture getDocument(final String id, final Class type) throws ArangoDBException { + public CompletableFuture getDocument(final String id, final Class type) { DocumentUtil.validateDocumentId(id); final String[] split = id.split("/"); return collection(split[0]).getDocument(split[1], type); @@ -395,7 +395,7 @@ public CompletableFuture getDocument(final String id, final Class type @Override public CompletableFuture getDocument(final String id, final Class type, final DocumentReadOptions options) - throws ArangoDBException { + { DocumentUtil.validateDocumentId(id); final String[] split = id.split("/"); return collection(split[0]).getDocument(split[1], type, options); diff --git a/src/main/java/com/arangodb/internal/ArangoCollectionImpl.java b/src/main/java/com/arangodb/internal/ArangoCollectionImpl.java index 765c3b224..2bc7d50fc 100644 --- a/src/main/java/com/arangodb/internal/ArangoCollectionImpl.java +++ b/src/main/java/com/arangodb/internal/ArangoCollectionImpl.java @@ -46,7 +46,7 @@ protected ArangoCollectionImpl(final ArangoDatabaseImpl db, final String name) { } @Override - public DocumentCreateEntity insertDocument(final Object value) throws ArangoDBException { + public DocumentCreateEntity insertDocument(final Object value) { return executor.execute(insertDocumentRequest(value, new DocumentCreateOptions()), constructParametricType(DocumentCreateEntity.class, Void.class)); } @@ -54,19 +54,19 @@ public DocumentCreateEntity insertDocument(final Object value) throws Aran @Override @SuppressWarnings("unchecked") public DocumentCreateEntity insertDocument(final T value, final DocumentCreateOptions options) - throws ArangoDBException { + { return insertDocument(value, options, (Class) value.getClass()); } @Override - public DocumentCreateEntity insertDocument(final T value, final DocumentCreateOptions options, final Class type) throws ArangoDBException { + public DocumentCreateEntity insertDocument(final T value, final DocumentCreateOptions options, final Class type) { return executor.execute(insertDocumentRequest(value, options), constructParametricType(DocumentCreateEntity.class, type)); } @Override public MultiDocumentEntity> insertDocuments(final Collection values) - throws ArangoDBException { + { return executor .execute(insertDocumentsRequest(values, new DocumentCreateOptions()), insertDocumentsResponseDeserializer(Void.class)); } @@ -74,46 +74,46 @@ public MultiDocumentEntity> insertDocuments(final Col @Override @SuppressWarnings("unchecked") public MultiDocumentEntity> insertDocuments( - final Collection values, final DocumentCreateOptions options) throws ArangoDBException { + final Collection values, final DocumentCreateOptions options) { return insertDocuments(values, options, (Class) getCollectionContentClass(values)); } @Override - public MultiDocumentEntity> insertDocuments(Collection values, DocumentCreateOptions options, Class type) throws ArangoDBException { + public MultiDocumentEntity> insertDocuments(Collection values, DocumentCreateOptions options, Class type) { return executor .execute(insertDocumentsRequest(values, options), insertDocumentsResponseDeserializer(type)); } @Override - public DocumentImportEntity importDocuments(final Collection values) throws ArangoDBException { + public DocumentImportEntity importDocuments(final Collection values) { return importDocuments(values, new DocumentImportOptions()); } @Override public DocumentImportEntity importDocuments(final Collection values, final DocumentImportOptions options) - throws ArangoDBException { + { return executor.execute(importDocumentsRequest(values, options), DocumentImportEntity.class); } @Override - public DocumentImportEntity importDocuments(final String values) throws ArangoDBException { + public DocumentImportEntity importDocuments(final String values) { return importDocuments(values, new DocumentImportOptions()); } @Override public DocumentImportEntity importDocuments(final String values, final DocumentImportOptions options) - throws ArangoDBException { + { return executor.execute(importDocumentsRequest(values, options), DocumentImportEntity.class); } @Override - public T getDocument(final String key, final Class type) throws ArangoDBException { + public T getDocument(final String key, final Class type) { return getDocument(key, type, new DocumentReadOptions()); } @Override public T getDocument(final String key, final Class type, final DocumentReadOptions options) - throws ArangoDBException { + { DocumentUtil.validateDocumentKey(key); try { return executor.execute(getDocumentRequest(key, options), getDocumentResponseDeserializer(type)); @@ -137,19 +137,19 @@ public T getDocument(final String key, final Class type, final DocumentRe @Override public MultiDocumentEntity getDocuments(final Collection keys, final Class type) - throws ArangoDBException { + { return getDocuments(keys, type, new DocumentReadOptions()); } @Override public MultiDocumentEntity getDocuments( final Collection keys, final Class type, final DocumentReadOptions options) - throws ArangoDBException { + { return executor.execute(getDocumentsRequest(keys, options), getDocumentsResponseDeserializer(type, options)); } @Override - public DocumentUpdateEntity replaceDocument(final String key, final Object value) throws ArangoDBException { + public DocumentUpdateEntity replaceDocument(final String key, final Object value) { return executor.execute(replaceDocumentRequest(key, value, new DocumentReplaceOptions()), constructParametricType(DocumentUpdateEntity.class, Void.class)); } @@ -157,93 +157,93 @@ public DocumentUpdateEntity replaceDocument(final String key, final Object @Override @SuppressWarnings("unchecked") public DocumentUpdateEntity replaceDocument( - final String key, final T value, final DocumentReplaceOptions options) throws ArangoDBException { + final String key, final T value, final DocumentReplaceOptions options) { return replaceDocument(key, value, options, (Class) value.getClass()); } @Override - public DocumentUpdateEntity replaceDocument(String key, T value, DocumentReplaceOptions options, Class type) throws ArangoDBException { + public DocumentUpdateEntity replaceDocument(String key, T value, DocumentReplaceOptions options, Class type) { return executor.execute(replaceDocumentRequest(key, value, options), constructParametricType(DocumentUpdateEntity.class, type)); } @Override public MultiDocumentEntity> replaceDocuments(final Collection values) - throws ArangoDBException { + { return executor.execute(replaceDocumentsRequest(values, new DocumentReplaceOptions()), replaceDocumentsResponseDeserializer(Void.class)); } @Override @SuppressWarnings("unchecked") public MultiDocumentEntity> replaceDocuments( - final Collection values, final DocumentReplaceOptions options) throws ArangoDBException { + final Collection values, final DocumentReplaceOptions options) { return replaceDocuments(values, options, (Class) getCollectionContentClass(values)); } @Override - public MultiDocumentEntity> replaceDocuments(Collection values, DocumentReplaceOptions options, Class type) throws ArangoDBException { + public MultiDocumentEntity> replaceDocuments(Collection values, DocumentReplaceOptions options, Class type) { return executor.execute(replaceDocumentsRequest(values, options), replaceDocumentsResponseDeserializer(type)); } @Override - public DocumentUpdateEntity updateDocument(final String key, final Object value) throws ArangoDBException { + public DocumentUpdateEntity updateDocument(final String key, final Object value) { return updateDocument(key, value, new DocumentUpdateOptions(), Void.class); } @Override @SuppressWarnings("unchecked") public DocumentUpdateEntity updateDocument( - final String key, final T value, final DocumentUpdateOptions options) throws ArangoDBException { + final String key, final T value, final DocumentUpdateOptions options) { return updateDocument(key, value, options, (Class) value.getClass()); } @Override public DocumentUpdateEntity updateDocument( - final String key, final Object value, final DocumentUpdateOptions options, final Class returnType) throws ArangoDBException { + final String key, final Object value, final DocumentUpdateOptions options, final Class returnType) { return executor.execute(updateDocumentRequest(key, value, options), constructParametricType(DocumentUpdateEntity.class, returnType)); } @Override public MultiDocumentEntity> updateDocuments(final Collection values) - throws ArangoDBException { + { return updateDocuments(values, new DocumentUpdateOptions(), Void.class); } @Override @SuppressWarnings("unchecked") public MultiDocumentEntity> updateDocuments( - final Collection values, final DocumentUpdateOptions options) throws ArangoDBException { + final Collection values, final DocumentUpdateOptions options) { return updateDocuments(values, options, (Class) getCollectionContentClass(values)); } @Override public MultiDocumentEntity> updateDocuments( - final Collection values, final DocumentUpdateOptions options, final Class returnType) throws ArangoDBException { + final Collection values, final DocumentUpdateOptions options, final Class returnType) { return executor .execute(updateDocumentsRequest(values, options), updateDocumentsResponseDeserializer(returnType)); } @Override - public DocumentDeleteEntity deleteDocument(final String key) throws ArangoDBException { + public DocumentDeleteEntity deleteDocument(final String key) { return deleteDocument(key, new DocumentDeleteOptions()); } @Override - public DocumentDeleteEntity deleteDocument(String key, DocumentDeleteOptions options) throws ArangoDBException { + public DocumentDeleteEntity deleteDocument(String key, DocumentDeleteOptions options) { return deleteDocument(key, options, Void.class); } @Override public DocumentDeleteEntity deleteDocument( - final String key, final DocumentDeleteOptions options, final Class type) throws ArangoDBException { + final String key, final DocumentDeleteOptions options, final Class type) { return executor.execute(deleteDocumentRequest(key, options), constructParametricType(DocumentDeleteEntity.class, type)); } @Override public MultiDocumentEntity> deleteDocuments(final Collection values) - throws ArangoDBException { + { return deleteDocuments(values, new DocumentDeleteOptions(), Void.class); } @@ -251,14 +251,14 @@ public MultiDocumentEntity> deleteDocuments(final Col @SuppressWarnings("unchecked") public MultiDocumentEntity> deleteDocuments( final Collection values, final DocumentDeleteOptions options) - throws ArangoDBException { + { return deleteDocuments(values, options, (Class) getCollectionContentClass(values)); } @Override public MultiDocumentEntity> deleteDocuments( final Collection values, final DocumentDeleteOptions options, final Class type) - throws ArangoDBException { + { return executor.execute(deleteDocumentsRequest(values, options), deleteDocumentsResponseDeserializer(type)); } @@ -268,7 +268,7 @@ public Boolean documentExists(final String key) { } @Override - public Boolean documentExists(final String key, final DocumentExistsOptions options) throws ArangoDBException { + public Boolean documentExists(final String key, final DocumentExistsOptions options) { try { executor.execute(documentExistsRequest(key, options), Void.class); return true; @@ -288,66 +288,66 @@ public Boolean documentExists(final String key, final DocumentExistsOptions opti } @Override - public IndexEntity getIndex(final String id) throws ArangoDBException { + public IndexEntity getIndex(final String id) { return executor.execute(getIndexRequest(id), IndexEntity.class); } @Override - public String deleteIndex(final String id) throws ArangoDBException { + public String deleteIndex(final String id) { return executor.execute(deleteIndexRequest(id), deleteIndexResponseDeserializer()); } @Deprecated @Override public IndexEntity ensureHashIndex(final Iterable fields, final HashIndexOptions options) - throws ArangoDBException { + { return executor.execute(createHashIndexRequest(fields, options), IndexEntity.class); } @Deprecated @Override public IndexEntity ensureSkiplistIndex(final Iterable fields, final SkiplistIndexOptions options) - throws ArangoDBException { + { return executor.execute(createSkiplistIndexRequest(fields, options), IndexEntity.class); } @Override public IndexEntity ensurePersistentIndex(final Iterable fields, final PersistentIndexOptions options) - throws ArangoDBException { + { return executor.execute(createPersistentIndexRequest(fields, options), IndexEntity.class); } @Override public IndexEntity ensureGeoIndex(final Iterable fields, final GeoIndexOptions options) - throws ArangoDBException { + { return executor.execute(createGeoIndexRequest(fields, options), IndexEntity.class); } @Override public IndexEntity ensureFulltextIndex(final Iterable fields, final FulltextIndexOptions options) - throws ArangoDBException { + { return executor.execute(createFulltextIndexRequest(fields, options), IndexEntity.class); } @Override public IndexEntity ensureTtlIndex(final Iterable fields, final TtlIndexOptions options) - throws ArangoDBException { + { return executor.execute(createTtlIndexRequest(fields, options), IndexEntity.class); } @Override public IndexEntity ensureZKDIndex(final Iterable fields, final ZKDIndexOptions options) - throws ArangoDBException { + { return executor.execute(createZKDIndexRequest(fields, options), IndexEntity.class); } @Override - public Collection getIndexes() throws ArangoDBException { + public Collection getIndexes() { return executor.execute(getIndexesRequest(), getIndexesResponseDeserializer()); } @Override - public boolean exists() throws ArangoDBException { + public boolean exists() { try { getInfo(); return true; @@ -360,95 +360,95 @@ public boolean exists() throws ArangoDBException { } @Override - public CollectionEntity truncate() throws ArangoDBException { + public CollectionEntity truncate() { return truncate(null); } @Override - public CollectionEntity truncate(CollectionTruncateOptions options) throws ArangoDBException { + public CollectionEntity truncate(CollectionTruncateOptions options) { return executor.execute(truncateRequest(options), CollectionEntity.class); } @Override - public CollectionPropertiesEntity count() throws ArangoDBException { + public CollectionPropertiesEntity count() { return count(null); } @Override - public CollectionPropertiesEntity count(CollectionCountOptions options) throws ArangoDBException { + public CollectionPropertiesEntity count(CollectionCountOptions options) { return executor.execute(countRequest(options), CollectionPropertiesEntity.class); } @Override - public CollectionEntity create() throws ArangoDBException { + public CollectionEntity create() { return db().createCollection(name()); } @Override - public CollectionEntity create(final CollectionCreateOptions options) throws ArangoDBException { + public CollectionEntity create(final CollectionCreateOptions options) { return db().createCollection(name(), options); } @Override - public void drop() throws ArangoDBException { + public void drop() { executor.execute(dropRequest(null), Void.class); } @Override - public void drop(final boolean isSystem) throws ArangoDBException { + public void drop(final boolean isSystem) { executor.execute(dropRequest(isSystem), Void.class); } @Override - public CollectionEntity getInfo() throws ArangoDBException { + public CollectionEntity getInfo() { return executor.execute(getInfoRequest(), CollectionEntity.class); } @Override - public CollectionPropertiesEntity getProperties() throws ArangoDBException { + public CollectionPropertiesEntity getProperties() { return executor.execute(getPropertiesRequest(), CollectionPropertiesEntity.class); } @Override public CollectionPropertiesEntity changeProperties(final CollectionPropertiesOptions options) - throws ArangoDBException { + { return executor.execute(changePropertiesRequest(options), CollectionPropertiesEntity.class); } @Override - public synchronized CollectionEntity rename(final String newName) throws ArangoDBException { + public synchronized CollectionEntity rename(final String newName) { final CollectionEntity result = executor.execute(renameRequest(newName), CollectionEntity.class); name = result.getName(); return result; } @Override - public ShardEntity getResponsibleShard(final Object value) throws ArangoDBException { + public ShardEntity getResponsibleShard(final Object value) { return executor.execute(responsibleShardRequest(value), ShardEntity.class); } @Override - public CollectionRevisionEntity getRevision() throws ArangoDBException { + public CollectionRevisionEntity getRevision() { return executor.execute(getRevisionRequest(), CollectionRevisionEntity.class); } @Override - public void grantAccess(final String user, final Permissions permissions) throws ArangoDBException { + public void grantAccess(final String user, final Permissions permissions) { executor.execute(grantAccessRequest(user, permissions), Void.class); } @Override - public void revokeAccess(final String user) throws ArangoDBException { + public void revokeAccess(final String user) { executor.execute(grantAccessRequest(user, Permissions.NONE), Void.class); } @Override - public void resetAccess(final String user) throws ArangoDBException { + public void resetAccess(final String user) { executor.execute(resetAccessRequest(user), Void.class); } @Override - public Permissions getPermissions(final String user) throws ArangoDBException { + public Permissions getPermissions(final String user) { return executor.execute(getPermissionsRequest(user), getPermissionsResponseDeserialzer()); } diff --git a/src/main/java/com/arangodb/internal/ArangoCursorExecute.java b/src/main/java/com/arangodb/internal/ArangoCursorExecute.java index 8e501d66a..dbc07231a 100644 --- a/src/main/java/com/arangodb/internal/ArangoCursorExecute.java +++ b/src/main/java/com/arangodb/internal/ArangoCursorExecute.java @@ -30,8 +30,8 @@ */ public interface ArangoCursorExecute { - InternalCursorEntity next(String id, Map meta) throws ArangoDBException; + InternalCursorEntity next(String id, Map meta) ; - void close(String id, Map meta) throws ArangoDBException; + void close(String id, Map meta) ; } diff --git a/src/main/java/com/arangodb/internal/ArangoDBImpl.java b/src/main/java/com/arangodb/internal/ArangoDBImpl.java index 3a77b239f..294dced7f 100644 --- a/src/main/java/com/arangodb/internal/ArangoDBImpl.java +++ b/src/main/java/com/arangodb/internal/ArangoDBImpl.java @@ -108,7 +108,7 @@ protected ArangoExecutorSync executor() { } @Override - public void shutdown() throws ArangoDBException { + public void shutdown() { try { executor.disconnect(); } finally { @@ -143,121 +143,121 @@ public ArangoMetrics metrics() { } @Override - public Boolean createDatabase(final DbName dbName) throws ArangoDBException { + public Boolean createDatabase(final DbName dbName) { return createDatabase(new DBCreateOptions().name(dbName)); } @Override - public Boolean createDatabase(DBCreateOptions options) throws ArangoDBException { + public Boolean createDatabase(DBCreateOptions options) { return executor.execute(createDatabaseRequest(options), createDatabaseResponseDeserializer()); } @Override - public Collection getDatabases() throws ArangoDBException { + public Collection getDatabases() { return executor.execute(getDatabasesRequest(db().dbName()), getDatabaseResponseDeserializer()); } @Override - public Collection getAccessibleDatabases() throws ArangoDBException { + public Collection getAccessibleDatabases() { return db().getAccessibleDatabases(); } @Override - public Collection getAccessibleDatabasesFor(final String user) throws ArangoDBException { + public Collection getAccessibleDatabasesFor(final String user) { return executor.execute(getAccessibleDatabasesForRequest(db().dbName(), user), getAccessibleDatabasesForResponseDeserializer()); } @Override - public ArangoDBVersion getVersion() throws ArangoDBException { + public ArangoDBVersion getVersion() { return db().getVersion(); } @Override - public ArangoDBEngine getEngine() throws ArangoDBException { + public ArangoDBEngine getEngine() { return db().getEngine(); } @Override - public ServerRole getRole() throws ArangoDBException { + public ServerRole getRole() { return executor.execute(getRoleRequest(), getRoleResponseDeserializer()); } @Override - public String getServerId() throws ArangoDBException { + public String getServerId() { return executor.execute(getServerIdRequest(), getServerIdResponseDeserializer()); } @Override - public UserEntity createUser(final String user, final String passwd) throws ArangoDBException { + public UserEntity createUser(final String user, final String passwd) { return executor.execute(createUserRequest(db().dbName(), user, passwd, new UserCreateOptions()), UserEntity.class); } @Override public UserEntity createUser(final String user, final String passwd, final UserCreateOptions options) - throws ArangoDBException { + { return executor.execute(createUserRequest(db().dbName(), user, passwd, options), UserEntity.class); } @Override - public void deleteUser(final String user) throws ArangoDBException { + public void deleteUser(final String user) { executor.execute(deleteUserRequest(db().dbName(), user), Void.class); } @Override - public UserEntity getUser(final String user) throws ArangoDBException { + public UserEntity getUser(final String user) { return executor.execute(getUserRequest(db().dbName(), user), UserEntity.class); } @Override - public Collection getUsers() throws ArangoDBException { + public Collection getUsers() { return executor.execute(getUsersRequest(db().dbName()), getUsersResponseDeserializer()); } @Override - public UserEntity updateUser(final String user, final UserUpdateOptions options) throws ArangoDBException { + public UserEntity updateUser(final String user, final UserUpdateOptions options) { return executor.execute(updateUserRequest(db().dbName(), user, options), UserEntity.class); } @Override - public UserEntity replaceUser(final String user, final UserUpdateOptions options) throws ArangoDBException { + public UserEntity replaceUser(final String user, final UserUpdateOptions options) { return executor.execute(replaceUserRequest(db().dbName(), user, options), UserEntity.class); } @Override - public void grantDefaultDatabaseAccess(final String user, final Permissions permissions) throws ArangoDBException { + public void grantDefaultDatabaseAccess(final String user, final Permissions permissions) { executor.execute(updateUserDefaultDatabaseAccessRequest(user, permissions), Void.class); } @Override public void grantDefaultCollectionAccess(final String user, final Permissions permissions) - throws ArangoDBException { + { executor.execute(updateUserDefaultCollectionAccessRequest(user, permissions), Void.class); } @Override - public Response execute(final Request request) throws ArangoDBException { + public Response execute(final Request request) { return executor.execute(request, response -> response); } @Override - public Response execute(final Request request, final HostHandle hostHandle) throws ArangoDBException { + public Response execute(final Request request, final HostHandle hostHandle) { return executor.execute(request, response -> response, hostHandle); } @Override - public LogEntriesEntity getLogEntries(final LogOptions options) throws ArangoDBException { + public LogEntriesEntity getLogEntries(final LogOptions options) { return executor.execute(getLogEntriesRequest(options), LogEntriesEntity.class); } @Override - public LogLevelEntity getLogLevel() throws ArangoDBException { + public LogLevelEntity getLogLevel() { return executor.execute(getLogLevelRequest(), LogLevelEntity.class); } @Override - public LogLevelEntity setLogLevel(final LogLevelEntity entity) throws ArangoDBException { + public LogLevelEntity setLogLevel(final LogLevelEntity entity) { return executor.execute(setLogLevelRequest(entity), LogLevelEntity.class); } diff --git a/src/main/java/com/arangodb/internal/ArangoDatabaseImpl.java b/src/main/java/com/arangodb/internal/ArangoDatabaseImpl.java index 5f2cab658..5556e53f8 100644 --- a/src/main/java/com/arangodb/internal/ArangoDatabaseImpl.java +++ b/src/main/java/com/arangodb/internal/ArangoDatabaseImpl.java @@ -54,17 +54,17 @@ protected ArangoDatabaseImpl(final ArangoDBImpl arangoDB, final DbName name) { } @Override - public ArangoDBVersion getVersion() throws ArangoDBException { + public ArangoDBVersion getVersion() { return executor.execute(getVersionRequest(), ArangoDBVersion.class); } @Override - public ArangoDBEngine getEngine() throws ArangoDBException { + public ArangoDBEngine getEngine() { return executor.execute(getEngineRequest(), ArangoDBEngine.class); } @Override - public boolean exists() throws ArangoDBException { + public boolean exists() { try { getInfo(); return true; @@ -77,7 +77,7 @@ public boolean exists() throws ArangoDBException { } @Override - public Collection getAccessibleDatabases() throws ArangoDBException { + public Collection getAccessibleDatabases() { return executor.execute(getAccessibleDatabasesRequest(), getDatabaseResponseDeserializer()); } @@ -87,86 +87,86 @@ public ArangoCollection collection(final String name) { } @Override - public CollectionEntity createCollection(final String name) throws ArangoDBException { + public CollectionEntity createCollection(final String name) { return executor.execute(createCollectionRequest(name, new CollectionCreateOptions()), CollectionEntity.class); } @Override public CollectionEntity createCollection(final String name, final CollectionCreateOptions options) - throws ArangoDBException { + { return executor.execute(createCollectionRequest(name, options), CollectionEntity.class); } @Override - public Collection getCollections() throws ArangoDBException { + public Collection getCollections() { return executor .execute(getCollectionsRequest(new CollectionsReadOptions()), getCollectionsResponseDeserializer()); } @Override - public Collection getCollections(final CollectionsReadOptions options) throws ArangoDBException { + public Collection getCollections(final CollectionsReadOptions options) { return executor.execute(getCollectionsRequest(options), getCollectionsResponseDeserializer()); } @Override - public IndexEntity getIndex(final String id) throws ArangoDBException { + public IndexEntity getIndex(final String id) { DocumentUtil.validateIndexId(id); final String[] split = id.split("/"); return collection(split[0]).getIndex(split[1]); } @Override - public String deleteIndex(final String id) throws ArangoDBException { + public String deleteIndex(final String id) { DocumentUtil.validateIndexId(id); final String[] split = id.split("/"); return collection(split[0]).deleteIndex(split[1]); } @Override - public Boolean create() throws ArangoDBException { + public Boolean create() { return arango().createDatabase(dbName()); } @Override - public Boolean drop() throws ArangoDBException { + public Boolean drop() { return executor.execute(dropRequest(), createDropResponseDeserializer()); } @Override - public void grantAccess(final String user, final Permissions permissions) throws ArangoDBException { + public void grantAccess(final String user, final Permissions permissions) { executor.execute(grantAccessRequest(user, permissions), Void.class); } @Override - public void grantAccess(final String user) throws ArangoDBException { + public void grantAccess(final String user) { executor.execute(grantAccessRequest(user, Permissions.RW), Void.class); } @Override - public void revokeAccess(final String user) throws ArangoDBException { + public void revokeAccess(final String user) { executor.execute(grantAccessRequest(user, Permissions.NONE), Void.class); } @Override - public void resetAccess(final String user) throws ArangoDBException { + public void resetAccess(final String user) { executor.execute(resetAccessRequest(user), Void.class); } @Override public void grantDefaultCollectionAccess(final String user, final Permissions permissions) - throws ArangoDBException { + { executor.execute(updateUserDefaultCollectionAccessRequest(user, permissions), Void.class); } @Override - public Permissions getPermissions(final String user) throws ArangoDBException { + public Permissions getPermissions(final String user) { return executor.execute(getPermissionsRequest(user), getPermissionsResponseDeserialzer()); } @Override public ArangoCursor query( final String query, final Map bindVars, final AqlQueryOptions options, final Class type) - throws ArangoDBException { + { final Request request = queryRequest(query, bindVars, options); final HostHandle hostHandle = new HostHandle(); @@ -178,23 +178,23 @@ public ArangoCursor query( @Override public ArangoCursor query( - final String query, final Map bindVars, final Class type) throws ArangoDBException { + final String query, final Map bindVars, final Class type) { return query(query, bindVars, null, type); } @Override public ArangoCursor query(final String query, final AqlQueryOptions options, final Class type) - throws ArangoDBException { + { return query(query, null, options, type); } @Override - public ArangoCursor query(final String query, final Class type) throws ArangoDBException { + public ArangoCursor query(final String query, final Class type) { return query(query, null, null, type); } @Override - public ArangoCursor cursor(final String cursorId, final Class type) throws ArangoDBException { + public ArangoCursor cursor(final String cursorId, final Class type) { final HostHandle hostHandle = new HostHandle(); final InternalCursorEntity result = executor .execute(queryNextRequest(cursorId, null, null), InternalCursorEntity.class, hostHandle); @@ -227,78 +227,78 @@ public void close(final String id, Map meta) { @Override public AqlExecutionExplainEntity explainQuery( final String query, final Map bindVars, final AqlQueryExplainOptions options) - throws ArangoDBException { + { return executor.execute(explainQueryRequest(query, bindVars, options), AqlExecutionExplainEntity.class); } @Override - public AqlParseEntity parseQuery(final String query) throws ArangoDBException { + public AqlParseEntity parseQuery(final String query) { return executor.execute(parseQueryRequest(query), AqlParseEntity.class); } @Override - public void clearQueryCache() throws ArangoDBException { + public void clearQueryCache() { executor.execute(clearQueryCacheRequest(), Void.class); } @Override - public QueryCachePropertiesEntity getQueryCacheProperties() throws ArangoDBException { + public QueryCachePropertiesEntity getQueryCacheProperties() { return executor.execute(getQueryCachePropertiesRequest(), QueryCachePropertiesEntity.class); } @Override public QueryCachePropertiesEntity setQueryCacheProperties(final QueryCachePropertiesEntity properties) - throws ArangoDBException { + { return executor.execute(setQueryCachePropertiesRequest(properties), QueryCachePropertiesEntity.class); } @Override - public QueryTrackingPropertiesEntity getQueryTrackingProperties() throws ArangoDBException { + public QueryTrackingPropertiesEntity getQueryTrackingProperties() { return executor.execute(getQueryTrackingPropertiesRequest(), QueryTrackingPropertiesEntity.class); } @Override public QueryTrackingPropertiesEntity setQueryTrackingProperties(final QueryTrackingPropertiesEntity properties) - throws ArangoDBException { + { return executor.execute(setQueryTrackingPropertiesRequest(properties), QueryTrackingPropertiesEntity.class); } @Override - public Collection getCurrentlyRunningQueries() throws ArangoDBException { + public Collection getCurrentlyRunningQueries() { return executor.execute(getCurrentlyRunningQueriesRequest(), constructListType(QueryEntity.class)); } @Override - public Collection getSlowQueries() throws ArangoDBException { + public Collection getSlowQueries() { return executor.execute(getSlowQueriesRequest(), constructListType(QueryEntity.class)); } @Override - public void clearSlowQueries() throws ArangoDBException { + public void clearSlowQueries() { executor.execute(clearSlowQueriesRequest(), Void.class); } @Override - public void killQuery(final String id) throws ArangoDBException { + public void killQuery(final String id) { executor.execute(killQueryRequest(id), Void.class); } @Override public void createAqlFunction( - final String name, final String code, final AqlFunctionCreateOptions options) throws ArangoDBException { + final String name, final String code, final AqlFunctionCreateOptions options) { executor.execute(createAqlFunctionRequest(name, code, options), Void.class); } @Override public Integer deleteAqlFunction(final String name, final AqlFunctionDeleteOptions options) - throws ArangoDBException { + { return executor.execute(deleteAqlFunctionRequest(name, options), deleteAqlFunctionResponseDeserializer()); } @Override - public Collection getAqlFunctions(final AqlFunctionGetOptions options) throws ArangoDBException { + public Collection getAqlFunctions(final AqlFunctionGetOptions options) { return executor.execute(getAqlFunctionsRequest(options), getAqlFunctionsResponseDeserializer()); } @@ -309,7 +309,7 @@ public ArangoGraph graph(final String name) { @Override public GraphEntity createGraph(final String name, final Collection edgeDefinitions) - throws ArangoDBException { + { return executor.execute(createGraphRequest(name, edgeDefinitions, new GraphCreateOptions()), createGraphResponseDeserializer()); } @@ -317,53 +317,53 @@ public GraphEntity createGraph(final String name, final Collection edgeDefinitions, final GraphCreateOptions options) - throws ArangoDBException { + { return executor.execute(createGraphRequest(name, edgeDefinitions, options), createGraphResponseDeserializer()); } @Override - public Collection getGraphs() throws ArangoDBException { + public Collection getGraphs() { return executor.execute(getGraphsRequest(), getGraphsResponseDeserializer()); } @Override public T transaction(final String action, final Class type, final TransactionOptions options) - throws ArangoDBException { + { return executor.execute(transactionRequest(action, options), transactionResponseDeserializer(type)); } @Override - public StreamTransactionEntity beginStreamTransaction(StreamTransactionOptions options) throws ArangoDBException { + public StreamTransactionEntity beginStreamTransaction(StreamTransactionOptions options) { return executor.execute(beginStreamTransactionRequest(options), streamTransactionResponseDeserializer()); } @Override - public StreamTransactionEntity abortStreamTransaction(String id) throws ArangoDBException { + public StreamTransactionEntity abortStreamTransaction(String id) { return executor.execute(abortStreamTransactionRequest(id), streamTransactionResponseDeserializer()); } @Override - public StreamTransactionEntity getStreamTransaction(String id) throws ArangoDBException { + public StreamTransactionEntity getStreamTransaction(String id) { return executor.execute(getStreamTransactionRequest(id), streamTransactionResponseDeserializer()); } @Override - public Collection getStreamTransactions() throws ArangoDBException { + public Collection getStreamTransactions() { return executor.execute(getStreamTransactionsRequest(), transactionsResponseDeserializer()); } @Override - public StreamTransactionEntity commitStreamTransaction(String id) throws ArangoDBException { + public StreamTransactionEntity commitStreamTransaction(String id) { return executor.execute(commitStreamTransactionRequest(id), streamTransactionResponseDeserializer()); } @Override - public DatabaseEntity getInfo() throws ArangoDBException { + public DatabaseEntity getInfo() { return executor.execute(getInfoRequest(), getInfoResponseDeserializer()); } @Override - public T getDocument(final String id, final Class type) throws ArangoDBException { + public T getDocument(final String id, final Class type) { DocumentUtil.validateDocumentId(id); final String[] split = id.split("/"); return collection(split[0]).getDocument(split[1], type); @@ -371,14 +371,14 @@ public T getDocument(final String id, final Class type) throws ArangoDBEx @Override public T getDocument(final String id, final Class type, final DocumentReadOptions options) - throws ArangoDBException { + { DocumentUtil.validateDocumentId(id); final String[] split = id.split("/"); return collection(split[0]).getDocument(split[1], type, options); } @Override - public void reloadRouting() throws ArangoDBException { + public void reloadRouting() { executor.execute(reloadRoutingRequest(), Void.class); } @@ -393,7 +393,7 @@ public ArangoRoute route(final String... path) { } @Override - public Collection getViews() throws ArangoDBException { + public Collection getViews() { return executor.execute(getViewsRequest(), getViewsResponseDeserializer()); } @@ -408,38 +408,38 @@ public ArangoSearch arangoSearch(final String name) { } @Override - public ViewEntity createView(final String name, final ViewType type) throws ArangoDBException { + public ViewEntity createView(final String name, final ViewType type) { return executor.execute(createViewRequest(name, type), ViewEntity.class); } @Override public ViewEntity createArangoSearch(final String name, final ArangoSearchCreateOptions options) - throws ArangoDBException { + { return executor.execute(createArangoSearchRequest(name, options), ViewEntity.class); } @Override - public SearchAnalyzer createSearchAnalyzer(SearchAnalyzer analyzer) throws ArangoDBException { + public SearchAnalyzer createSearchAnalyzer(SearchAnalyzer analyzer) { return executor.execute(createAnalyzerRequest(analyzer), SearchAnalyzer.class); } @Override - public SearchAnalyzer getSearchAnalyzer(String name) throws ArangoDBException { + public SearchAnalyzer getSearchAnalyzer(String name) { return executor.execute(getAnalyzerRequest(name), SearchAnalyzer.class); } @Override - public Collection getSearchAnalyzers() throws ArangoDBException { + public Collection getSearchAnalyzers() { return executor.execute(getAnalyzersRequest(), getSearchAnalyzersResponseDeserializer()); } @Override - public void deleteSearchAnalyzer(String name) throws ArangoDBException { + public void deleteSearchAnalyzer(String name) { deleteSearchAnalyzer(name, null); } @Override - public void deleteSearchAnalyzer(String name, AnalyzerDeleteOptions options) throws ArangoDBException { + public void deleteSearchAnalyzer(String name, AnalyzerDeleteOptions options) { executor.execute(deleteAnalyzerRequest(name, options), Void.class); } diff --git a/src/main/java/com/arangodb/internal/ArangoEdgeCollectionImpl.java b/src/main/java/com/arangodb/internal/ArangoEdgeCollectionImpl.java index 5c84bb556..c021dad22 100644 --- a/src/main/java/com/arangodb/internal/ArangoEdgeCollectionImpl.java +++ b/src/main/java/com/arangodb/internal/ArangoEdgeCollectionImpl.java @@ -42,18 +42,18 @@ protected ArangoEdgeCollectionImpl(final ArangoGraphImpl graph, final String nam } @Override - public EdgeEntity insertEdge(final T value) throws ArangoDBException { + public EdgeEntity insertEdge(final T value) { return executor.execute(insertEdgeRequest(value, new EdgeCreateOptions()), insertEdgeResponseDeserializer(value)); } @Override - public EdgeEntity insertEdge(final T value, final EdgeCreateOptions options) throws ArangoDBException { + public EdgeEntity insertEdge(final T value, final EdgeCreateOptions options) { return executor.execute(insertEdgeRequest(value, options), insertEdgeResponseDeserializer(value)); } @Override - public T getEdge(final String key, final Class type) throws ArangoDBException { + public T getEdge(final String key, final Class type) { try { return executor.execute(getEdgeRequest(key, new GraphDocumentReadOptions()), getEdgeResponseDeserializer(type)); } catch (final ArangoDBException e) { @@ -66,7 +66,7 @@ public T getEdge(final String key, final Class type) throws ArangoDBExcep @Override public T getEdge(final String key, final Class type, final GraphDocumentReadOptions options) - throws ArangoDBException { + { try { return executor.execute(getEdgeRequest(key, options), getEdgeResponseDeserializer(type)); } catch (final ArangoDBException e) { @@ -78,36 +78,36 @@ public T getEdge(final String key, final Class type, final GraphDocumentR } @Override - public EdgeUpdateEntity replaceEdge(final String key, final T value) throws ArangoDBException { + public EdgeUpdateEntity replaceEdge(final String key, final T value) { return executor.execute(replaceEdgeRequest(key, value, new EdgeReplaceOptions()), replaceEdgeResponseDeserializer(value)); } @Override public EdgeUpdateEntity replaceEdge(final String key, final T value, final EdgeReplaceOptions options) - throws ArangoDBException { + { return executor.execute(replaceEdgeRequest(key, value, options), replaceEdgeResponseDeserializer(value)); } @Override - public EdgeUpdateEntity updateEdge(final String key, final T value) throws ArangoDBException { + public EdgeUpdateEntity updateEdge(final String key, final T value) { return executor.execute(updateEdgeRequest(key, value, new EdgeUpdateOptions()), updateEdgeResponseDeserializer(value)); } @Override public EdgeUpdateEntity updateEdge(final String key, final T value, final EdgeUpdateOptions options) - throws ArangoDBException { + { return executor.execute(updateEdgeRequest(key, value, options), updateEdgeResponseDeserializer(value)); } @Override - public void deleteEdge(final String key) throws ArangoDBException { + public void deleteEdge(final String key) { executor.execute(deleteEdgeRequest(key, new EdgeDeleteOptions()), Void.class); } @Override - public void deleteEdge(final String key, final EdgeDeleteOptions options) throws ArangoDBException { + public void deleteEdge(final String key, final EdgeDeleteOptions options) { executor.execute(deleteEdgeRequest(key, options), Void.class); } diff --git a/src/main/java/com/arangodb/internal/ArangoExecutorSync.java b/src/main/java/com/arangodb/internal/ArangoExecutorSync.java index b9f1cecee..b8cd2f2b1 100644 --- a/src/main/java/com/arangodb/internal/ArangoExecutorSync.java +++ b/src/main/java/com/arangodb/internal/ArangoExecutorSync.java @@ -48,22 +48,22 @@ public ArangoExecutorSync(final CommunicationProtocol protocol, final InternalSe this.protocol = protocol; } - public T execute(final Request request, final Type type) throws ArangoDBException { + public T execute(final Request request, final Type type) { return execute(request, type, null); } - public T execute(final Request request, final Type type, final HostHandle hostHandle) throws ArangoDBException { + public T execute(final Request request, final Type type, final HostHandle hostHandle) { return execute(request, response -> createResult(type, response), hostHandle); } - public T execute(final Request request, final ResponseDeserializer responseDeserializer) throws ArangoDBException { + public T execute(final Request request, final ResponseDeserializer responseDeserializer) { return execute(request, responseDeserializer, null); } public T execute( final Request request, final ResponseDeserializer responseDeserializer, - final HostHandle hostHandle) throws ArangoDBException { + final HostHandle hostHandle) { final Response response = protocol.execute(interceptRequest(request), hostHandle); interceptResponse(response); diff --git a/src/main/java/com/arangodb/internal/ArangoGraphImpl.java b/src/main/java/com/arangodb/internal/ArangoGraphImpl.java index c72c86fc8..246e862b5 100644 --- a/src/main/java/com/arangodb/internal/ArangoGraphImpl.java +++ b/src/main/java/com/arangodb/internal/ArangoGraphImpl.java @@ -42,7 +42,7 @@ protected ArangoGraphImpl(final ArangoDatabaseImpl db, final String name) { } @Override - public boolean exists() throws ArangoDBException { + public boolean exists() { try { getInfo(); return true; @@ -55,43 +55,43 @@ public boolean exists() throws ArangoDBException { } @Override - public GraphEntity create(final Collection edgeDefinitions) throws ArangoDBException { + public GraphEntity create(final Collection edgeDefinitions) { return db().createGraph(name(), edgeDefinitions); } @Override public GraphEntity create(final Collection edgeDefinitions, final GraphCreateOptions options) - throws ArangoDBException { + { return db().createGraph(name(), edgeDefinitions, options); } @Override - public void drop() throws ArangoDBException { + public void drop() { executor.execute(dropRequest(), Void.class); } @Override - public void drop(final boolean dropCollections) throws ArangoDBException { + public void drop(final boolean dropCollections) { executor.execute(dropRequest(dropCollections), Void.class); } @Override - public GraphEntity getInfo() throws ArangoDBException { + public GraphEntity getInfo() { return executor.execute(getInfoRequest(), getInfoResponseDeserializer()); } @Override - public Collection getVertexCollections() throws ArangoDBException { + public Collection getVertexCollections() { return executor.execute(getVertexCollectionsRequest(), getVertexCollectionsResponseDeserializer()); } @Override - public GraphEntity addVertexCollection(final String name) throws ArangoDBException { + public GraphEntity addVertexCollection(final String name) { return addVertexCollection(name, new VertexCollectionCreateOptions()); } @Override - public GraphEntity addVertexCollection(final String name, final VertexCollectionCreateOptions options) throws ArangoDBException { + public GraphEntity addVertexCollection(final String name, final VertexCollectionCreateOptions options) { return executor.execute(addVertexCollectionRequest(name, options), addVertexCollectionResponseDeserializer()); } @@ -106,22 +106,22 @@ public ArangoEdgeCollection edgeCollection(final String name) { } @Override - public Collection getEdgeDefinitions() throws ArangoDBException { + public Collection getEdgeDefinitions() { return executor.execute(getEdgeDefinitionsRequest(), getEdgeDefinitionsDeserializer()); } @Override - public GraphEntity addEdgeDefinition(final EdgeDefinition definition) throws ArangoDBException { + public GraphEntity addEdgeDefinition(final EdgeDefinition definition) { return executor.execute(addEdgeDefinitionRequest(definition), addEdgeDefinitionResponseDeserializer()); } @Override - public GraphEntity replaceEdgeDefinition(final EdgeDefinition definition) throws ArangoDBException { + public GraphEntity replaceEdgeDefinition(final EdgeDefinition definition) { return executor.execute(replaceEdgeDefinitionRequest(definition), replaceEdgeDefinitionResponseDeserializer()); } @Override - public GraphEntity removeEdgeDefinition(final String definitionName) throws ArangoDBException { + public GraphEntity removeEdgeDefinition(final String definitionName) { return executor.execute(removeEdgeDefinitionRequest(definitionName), removeEdgeDefinitionResponseDeserializer()); } diff --git a/src/main/java/com/arangodb/internal/ArangoRouteImpl.java b/src/main/java/com/arangodb/internal/ArangoRouteImpl.java index b14fba224..3c33afe0b 100644 --- a/src/main/java/com/arangodb/internal/ArangoRouteImpl.java +++ b/src/main/java/com/arangodb/internal/ArangoRouteImpl.java @@ -68,32 +68,32 @@ private Response request(final RequestType requestType) { } @Override - public Response delete() throws ArangoDBException { + public Response delete() { return request(RequestType.DELETE); } @Override - public Response get() throws ArangoDBException { + public Response get() { return request(RequestType.GET); } @Override - public Response head() throws ArangoDBException { + public Response head() { return request(RequestType.HEAD); } @Override - public Response patch() throws ArangoDBException { + public Response patch() { return request(RequestType.PATCH); } @Override - public Response post() throws ArangoDBException { + public Response post() { return request(RequestType.POST); } @Override - public Response put() throws ArangoDBException { + public Response put() { return request(RequestType.PUT); } diff --git a/src/main/java/com/arangodb/internal/ArangoSearchImpl.java b/src/main/java/com/arangodb/internal/ArangoSearchImpl.java index 286a34787..e02063e7a 100644 --- a/src/main/java/com/arangodb/internal/ArangoSearchImpl.java +++ b/src/main/java/com/arangodb/internal/ArangoSearchImpl.java @@ -38,7 +38,7 @@ protected ArangoSearchImpl(final ArangoDatabaseImpl db, final String name) { } @Override - public boolean exists() throws ArangoDBException { + public boolean exists() { try { getInfo(); return true; @@ -51,46 +51,46 @@ public boolean exists() throws ArangoDBException { } @Override - public void drop() throws ArangoDBException { + public void drop() { executor.execute(dropRequest(), Void.class); } @Override - public synchronized ViewEntity rename(final String newName) throws ArangoDBException { + public synchronized ViewEntity rename(final String newName) { final ViewEntity result = executor.execute(renameRequest(newName), ViewEntity.class); name = result.getName(); return result; } @Override - public ViewEntity getInfo() throws ArangoDBException { + public ViewEntity getInfo() { return executor.execute(getInfoRequest(), ViewEntity.class); } @Override - public ViewEntity create() throws ArangoDBException { + public ViewEntity create() { return create(new ArangoSearchCreateOptions()); } @Override - public ViewEntity create(final ArangoSearchCreateOptions options) throws ArangoDBException { + public ViewEntity create(final ArangoSearchCreateOptions options) { return db().createArangoSearch(name(), options); } @Override - public ArangoSearchPropertiesEntity getProperties() throws ArangoDBException { + public ArangoSearchPropertiesEntity getProperties() { return executor.execute(getPropertiesRequest(), ArangoSearchPropertiesEntity.class); } @Override public ArangoSearchPropertiesEntity updateProperties(final ArangoSearchPropertiesOptions options) - throws ArangoDBException { + { return executor.execute(updatePropertiesRequest(options), ArangoSearchPropertiesEntity.class); } @Override public ArangoSearchPropertiesEntity replaceProperties(final ArangoSearchPropertiesOptions options) - throws ArangoDBException { + { return executor.execute(replacePropertiesRequest(options), ArangoSearchPropertiesEntity.class); } diff --git a/src/main/java/com/arangodb/internal/ArangoVertexCollectionImpl.java b/src/main/java/com/arangodb/internal/ArangoVertexCollectionImpl.java index 399ec2321..cd578e14a 100644 --- a/src/main/java/com/arangodb/internal/ArangoVertexCollectionImpl.java +++ b/src/main/java/com/arangodb/internal/ArangoVertexCollectionImpl.java @@ -42,23 +42,23 @@ protected ArangoVertexCollectionImpl(final ArangoGraphImpl graph, final String n } @Override - public void drop() throws ArangoDBException { + public void drop() { executor.execute(dropRequest(), Void.class); } @Override - public VertexEntity insertVertex(final T value) throws ArangoDBException { + public VertexEntity insertVertex(final T value) { return executor.execute(insertVertexRequest(value, new VertexCreateOptions()), insertVertexResponseDeserializer(value)); } @Override - public VertexEntity insertVertex(final T value, final VertexCreateOptions options) throws ArangoDBException { + public VertexEntity insertVertex(final T value, final VertexCreateOptions options) { return executor.execute(insertVertexRequest(value, options), insertVertexResponseDeserializer(value)); } @Override - public T getVertex(final String key, final Class type) throws ArangoDBException { + public T getVertex(final String key, final Class type) { try { return executor.execute(getVertexRequest(key, new GraphDocumentReadOptions()), getVertexResponseDeserializer(type)); @@ -72,7 +72,7 @@ public T getVertex(final String key, final Class type) throws ArangoDBExc @Override public T getVertex(final String key, final Class type, final GraphDocumentReadOptions options) - throws ArangoDBException { + { try { return executor.execute(getVertexRequest(key, options), getVertexResponseDeserializer(type)); } catch (final ArangoDBException e) { @@ -84,36 +84,36 @@ public T getVertex(final String key, final Class type, final GraphDocumen } @Override - public VertexUpdateEntity replaceVertex(final String key, final T value) throws ArangoDBException { + public VertexUpdateEntity replaceVertex(final String key, final T value) { return executor.execute(replaceVertexRequest(key, value, new VertexReplaceOptions()), replaceVertexResponseDeserializer(value)); } @Override public VertexUpdateEntity replaceVertex(final String key, final T value, final VertexReplaceOptions options) - throws ArangoDBException { + { return executor.execute(replaceVertexRequest(key, value, options), replaceVertexResponseDeserializer(value)); } @Override - public VertexUpdateEntity updateVertex(final String key, final T value) throws ArangoDBException { + public VertexUpdateEntity updateVertex(final String key, final T value) { return executor.execute(updateVertexRequest(key, value, new VertexUpdateOptions()), updateVertexResponseDeserializer(value)); } @Override public VertexUpdateEntity updateVertex(final String key, final T value, final VertexUpdateOptions options) - throws ArangoDBException { + { return executor.execute(updateVertexRequest(key, value, options), updateVertexResponseDeserializer(value)); } @Override - public void deleteVertex(final String key) throws ArangoDBException { + public void deleteVertex(final String key) { executor.execute(deleteVertexRequest(key, new VertexDeleteOptions()), Void.class); } @Override - public void deleteVertex(final String key, final VertexDeleteOptions options) throws ArangoDBException { + public void deleteVertex(final String key, final VertexDeleteOptions options) { executor.execute(deleteVertexRequest(key, options), Void.class); } diff --git a/src/main/java/com/arangodb/internal/ArangoViewImpl.java b/src/main/java/com/arangodb/internal/ArangoViewImpl.java index 60faebd7e..926d7105c 100644 --- a/src/main/java/com/arangodb/internal/ArangoViewImpl.java +++ b/src/main/java/com/arangodb/internal/ArangoViewImpl.java @@ -35,7 +35,7 @@ protected ArangoViewImpl(final ArangoDatabaseImpl db, final String name) { } @Override - public boolean exists() throws ArangoDBException { + public boolean exists() { try { getInfo(); return true; @@ -48,19 +48,19 @@ public boolean exists() throws ArangoDBException { } @Override - public void drop() throws ArangoDBException { + public void drop() { executor.execute(dropRequest(), Void.class); } @Override - public synchronized ViewEntity rename(final String newName) throws ArangoDBException { + public synchronized ViewEntity rename(final String newName) { final ViewEntity result = executor.execute(renameRequest(newName), ViewEntity.class); name = result.getName(); return result; } @Override - public ViewEntity getInfo() throws ArangoDBException { + public ViewEntity getInfo() { return executor.execute(getInfoRequest(), ViewEntity.class); } diff --git a/src/main/java/com/arangodb/internal/InternalArangoDBBuilder.java b/src/main/java/com/arangodb/internal/InternalArangoDBBuilder.java index 9b8821057..9bb0b7e0c 100644 --- a/src/main/java/com/arangodb/internal/InternalArangoDBBuilder.java +++ b/src/main/java/com/arangodb/internal/InternalArangoDBBuilder.java @@ -93,7 +93,7 @@ public InternalArangoDBBuilder() { loadProperties(ArangoDB.class.getResourceAsStream(DEFAULT_PROPERTY_FILE)); } - public InternalArangoDBBuilder loadProperties(final InputStream in) throws ArangoDBException { + public InternalArangoDBBuilder loadProperties(final InputStream in) { final Properties properties = new Properties(); diff --git a/src/main/java/com/arangodb/internal/http/HttpCommunication.java b/src/main/java/com/arangodb/internal/http/HttpCommunication.java index 284a2b45c..614e32d42 100644 --- a/src/main/java/com/arangodb/internal/http/HttpCommunication.java +++ b/src/main/java/com/arangodb/internal/http/HttpCommunication.java @@ -72,11 +72,11 @@ public void close() throws IOException { hostHandler.close(); } - public Response execute(final Request request, final HostHandle hostHandle) throws ArangoDBException { + public Response execute(final Request request, final HostHandle hostHandle) { return execute(request, hostHandle, 0); } - private Response execute(final Request request, final HostHandle hostHandle, final int attemptCount) throws ArangoDBException { + private Response execute(final Request request, final HostHandle hostHandle, final int attemptCount) { final AccessType accessType = RequestUtils.determineAccessType(request); Host host = hostHandler.get(hostHandle, accessType); try { diff --git a/src/main/java/com/arangodb/internal/http/HttpConnection.java b/src/main/java/com/arangodb/internal/http/HttpConnection.java index 1544839dc..8486559d9 100644 --- a/src/main/java/com/arangodb/internal/http/HttpConnection.java +++ b/src/main/java/com/arangodb/internal/http/HttpConnection.java @@ -305,7 +305,7 @@ private static List toList(final Map parameters) return paramList; } - public Response execute(final Request request) throws ArangoDBException, IOException { + public Response execute(final Request request) throws IOException { final String url = buildUrl(buildBaseUrl(host), request); final HttpRequestBase httpRequest = buildHttpRequestBase(request, url); httpRequest.setHeader("User-Agent", "Mozilla/5.0 (compatible; ArangoDB-JavaDriver/1.1; +http://mt.orz.at/)"); @@ -358,7 +358,7 @@ public Response buildResponse(final CloseableHttpResponse httpResponse) return response; } - protected void checkError(final Response response) throws ArangoDBException { + protected void checkError(final Response response) { ResponseUtils.checkError(util, response); } diff --git a/src/main/java/com/arangodb/internal/http/HttpProtocol.java b/src/main/java/com/arangodb/internal/http/HttpProtocol.java index c3df748e9..64332c1e2 100644 --- a/src/main/java/com/arangodb/internal/http/HttpProtocol.java +++ b/src/main/java/com/arangodb/internal/http/HttpProtocol.java @@ -41,7 +41,7 @@ public HttpProtocol(final HttpCommunication httpCommunitaction) { } @Override - public Response execute(final Request request, final HostHandle hostHandle) throws ArangoDBException { + public Response execute(final Request request, final HostHandle hostHandle) { return httpCommunitaction.execute(request, hostHandle); } diff --git a/src/main/java/com/arangodb/internal/net/CommunicationProtocol.java b/src/main/java/com/arangodb/internal/net/CommunicationProtocol.java index 31e9a38ea..a57b59790 100644 --- a/src/main/java/com/arangodb/internal/net/CommunicationProtocol.java +++ b/src/main/java/com/arangodb/internal/net/CommunicationProtocol.java @@ -31,7 +31,7 @@ */ public interface CommunicationProtocol extends Closeable { - Response execute(final Request request, HostHandle hostHandle) throws ArangoDBException; + Response execute(final Request request, HostHandle hostHandle) ; void setJwt(String jwt); diff --git a/src/main/java/com/arangodb/internal/net/ExtendedHostResolver.java b/src/main/java/com/arangodb/internal/net/ExtendedHostResolver.java index 02181767c..85a85fd49 100644 --- a/src/main/java/com/arangodb/internal/net/ExtendedHostResolver.java +++ b/src/main/java/com/arangodb/internal/net/ExtendedHostResolver.java @@ -114,7 +114,7 @@ public HostSet resolve(boolean initial, boolean closeConnections) { return hosts; } - private Collection resolveFromServer() throws ArangoDBException { + private Collection resolveFromServer() { Collection response; diff --git a/src/main/java/com/arangodb/internal/util/DocumentUtil.java b/src/main/java/com/arangodb/internal/util/DocumentUtil.java index fb108d91c..94792e6cb 100644 --- a/src/main/java/com/arangodb/internal/util/DocumentUtil.java +++ b/src/main/java/com/arangodb/internal/util/DocumentUtil.java @@ -41,11 +41,11 @@ public static void validateIndexId(final String id) { validateName("index id", REGEX_ID, id); } - public static void validateDocumentKey(final String key) throws ArangoDBException { + public static void validateDocumentKey(final String key) { validateName("document key", REGEX_KEY, key); } - public static void validateDocumentId(final String id) throws ArangoDBException { + public static void validateDocumentId(final String id) { validateName("document id", REGEX_ID, id); } @@ -55,7 +55,7 @@ public static String createDocumentHandle(final String collection, final String } private static void validateName(final String type, final String regex, final CharSequence name) - throws ArangoDBException { + { if (!Pattern.matches(regex, name)) { throw new ArangoDBException(String.format("%s %s is not valid.", type, name)); } diff --git a/src/main/java/com/arangodb/internal/util/ResponseUtils.java b/src/main/java/com/arangodb/internal/util/ResponseUtils.java index ea70a9272..9c45995e4 100644 --- a/src/main/java/com/arangodb/internal/util/ResponseUtils.java +++ b/src/main/java/com/arangodb/internal/util/ResponseUtils.java @@ -42,7 +42,7 @@ private ResponseUtils() { super(); } - public static void checkError(final InternalSerde util, final Response response) throws ArangoDBException { + public static void checkError(final InternalSerde util, final Response response) { final int responseCode = response.getResponseCode(); if (responseCode >= ERROR_STATUS) { if (responseCode == ERROR_INTERNAL && response.getMeta().containsKey(HEADER_ENDPOINT)) { diff --git a/src/main/java/com/arangodb/internal/velocystream/VstCommunication.java b/src/main/java/com/arangodb/internal/velocystream/VstCommunication.java index 3f6c7267b..7cb214a6e 100644 --- a/src/main/java/com/arangodb/internal/velocystream/VstCommunication.java +++ b/src/main/java/com/arangodb/internal/velocystream/VstCommunication.java @@ -140,20 +140,20 @@ public void close() throws IOException { hostHandler.close(); } - public R execute(final Request request, final HostHandle hostHandle) throws ArangoDBException { + public R execute(final Request request, final HostHandle hostHandle) { return execute(request, hostHandle, 0); } - protected R execute(final Request request, final HostHandle hostHandle, final int attemptCount) throws ArangoDBException { + protected R execute(final Request request, final HostHandle hostHandle, final int attemptCount) { final C connection = connect(hostHandle, RequestUtils.determineAccessType(request)); return execute(request, connection, attemptCount); } - protected abstract R execute(final Request request, C connection) throws ArangoDBException; + protected abstract R execute(final Request request, C connection) ; - protected abstract R execute(final Request request, C connection, final int attemptCount) throws ArangoDBException; + protected abstract R execute(final Request request, C connection, final int attemptCount) ; - protected void checkError(final Response response) throws ArangoDBException { + protected void checkError(final Response response) { ResponseUtils.checkError(util, response); } diff --git a/src/main/java/com/arangodb/internal/velocystream/VstCommunicationSync.java b/src/main/java/com/arangodb/internal/velocystream/VstCommunicationSync.java index 84289e60b..03bfd0dd7 100644 --- a/src/main/java/com/arangodb/internal/velocystream/VstCommunicationSync.java +++ b/src/main/java/com/arangodb/internal/velocystream/VstCommunicationSync.java @@ -131,12 +131,12 @@ protected VstCommunicationSync(final HostHandler hostHandler, final Integer time } @Override - protected Response execute(final Request request, final VstConnectionSync connection) throws ArangoDBException { + protected Response execute(final Request request, final VstConnectionSync connection) { return execute(request, connection, 0); } @Override - protected Response execute(final Request request, final VstConnectionSync connection, final int attemptCount) throws ArangoDBException { + protected Response execute(final Request request, final VstConnectionSync connection, final int attemptCount) { try { final Message requestMessage = createMessage(request); final Message responseMessage = send(requestMessage, connection); @@ -156,7 +156,7 @@ protected Response execute(final Request request, final VstConnectionSync connec } } - private Message send(final Message message, final VstConnectionSync connection) throws ArangoDBException { + private Message send(final Message message, final VstConnectionSync connection) { if (LOGGER.isDebugEnabled()) { LOGGER.debug(String.format("Send Message (id=%s, head=%s, body=%s)", message.getId(), message.getHead(), message.getBody() != null ? message.getBody() : "{}")); diff --git a/src/main/java/com/arangodb/internal/velocystream/VstProtocol.java b/src/main/java/com/arangodb/internal/velocystream/VstProtocol.java index 25de5edba..55f0fdd68 100644 --- a/src/main/java/com/arangodb/internal/velocystream/VstProtocol.java +++ b/src/main/java/com/arangodb/internal/velocystream/VstProtocol.java @@ -42,7 +42,7 @@ public VstProtocol(final VstCommunication communica } @Override - public Response execute(final Request request, final HostHandle hostHandle) throws ArangoDBException { + public Response execute(final Request request, final HostHandle hostHandle) { return communication.execute(request, hostHandle); } diff --git a/src/main/java/com/arangodb/internal/velocystream/internal/MessageStore.java b/src/main/java/com/arangodb/internal/velocystream/internal/MessageStore.java index 657b17bfa..dd25ae976 100644 --- a/src/main/java/com/arangodb/internal/velocystream/internal/MessageStore.java +++ b/src/main/java/com/arangodb/internal/velocystream/internal/MessageStore.java @@ -63,7 +63,7 @@ public void consume(final Message message) { } } - public Message get(final long messageId) throws ArangoDBException { + public Message get(final long messageId) { final Message result = response.remove(messageId); if (result == null) { final Exception e = error.remove(messageId); diff --git a/src/main/java/com/arangodb/internal/velocystream/internal/VstConnection.java b/src/main/java/com/arangodb/internal/velocystream/internal/VstConnection.java index 142660a8b..70b9ea98b 100644 --- a/src/main/java/com/arangodb/internal/velocystream/internal/VstConnection.java +++ b/src/main/java/com/arangodb/internal/velocystream/internal/VstConnection.java @@ -267,7 +267,7 @@ private synchronized void sendProtocolHeader() throws IOException { } protected synchronized void writeIntern(final Message message, final Collection chunks) - throws ArangoDBException { + { for (final Chunk chunk : chunks) { try { if (LOGGER.isDebugEnabled()) { diff --git a/src/main/java/com/arangodb/internal/velocystream/internal/VstConnectionSync.java b/src/main/java/com/arangodb/internal/velocystream/internal/VstConnectionSync.java index 1716b4cf5..cf1490985 100644 --- a/src/main/java/com/arangodb/internal/velocystream/internal/VstConnectionSync.java +++ b/src/main/java/com/arangodb/internal/velocystream/internal/VstConnectionSync.java @@ -90,7 +90,7 @@ private VstConnectionSync(final HostDescription host, final Integer timeout, fin } @Override - public Message write(final Message message, final Collection chunks) throws ArangoDBException { + public Message write(final Message message, final Collection chunks) { final FutureTask task = new FutureTask<>(() -> messageStore.get(message.getId())); messageStore.storeMessage(message.getId(), task); super.writeIntern(message, chunks); From f3c5f1546193642e8f0ef2f373ec39364e645e2a Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Mon, 15 Aug 2022 17:37:30 +0200 Subject: [PATCH 080/254] serde API visibility refactoring --- src/main/java/com/arangodb/ArangoDB.java | 4 +--- src/main/java/com/arangodb/ArangoSerdeAccessor.java | 2 +- src/main/java/com/arangodb/async/ArangoDBAsync.java | 3 +-- .../async/internal/ArangoCollectionAsyncImpl.java | 3 +-- .../com/arangodb/async/internal/ArangoDBAsyncImpl.java | 3 +-- .../arangodb/async/internal/ArangoDatabaseAsyncImpl.java | 3 +-- .../com/arangodb/async/internal/ArangoExecutorAsync.java | 2 +- .../internal/velocystream/VstCommunicationAsync.java | 2 +- .../java/com/arangodb/entity/DocumentCreateEntity.java | 2 +- .../java/com/arangodb/entity/DocumentDeleteEntity.java | 2 +- .../java/com/arangodb/entity/DocumentUpdateEntity.java | 2 +- .../arangosearch/ArangoSearchPropertiesEntity.java | 2 +- .../com/arangodb/entity/arangosearch/CollectionLink.java | 4 ++-- .../java/com/arangodb/entity/arangosearch/FieldLink.java | 2 +- .../java/com/arangodb/internal/ArangoCollectionImpl.java | 2 +- src/main/java/com/arangodb/internal/ArangoDBImpl.java | 2 +- .../java/com/arangodb/internal/ArangoDatabaseImpl.java | 3 +-- .../java/com/arangodb/internal/ArangoExecuteable.java | 2 +- src/main/java/com/arangodb/internal/ArangoExecutor.java | 2 +- .../java/com/arangodb/internal/ArangoExecutorSync.java | 2 +- .../com/arangodb/internal/InternalArangoCollection.java | 6 +++--- .../java/com/arangodb/internal/InternalArangoDB.java | 5 ++--- .../com/arangodb/internal/InternalArangoDatabase.java | 3 +-- .../java/com/arangodb/internal/InternalArangoGraph.java | 3 +-- src/main/java/com/arangodb/internal/http/CURLLogger.java | 2 +- .../com/arangodb/internal/http/HttpCommunication.java | 2 +- .../java/com/arangodb/internal/http/HttpConnection.java | 2 +- .../arangodb/internal/http/HttpConnectionFactory.java | 2 +- .../com/arangodb/internal/net/ExtendedHostResolver.java | 5 ++--- .../java/com/arangodb/internal/net/HostResolver.java | 2 +- .../com/arangodb/internal/net/SimpleHostResolver.java | 2 +- .../serde/InternalAnnotationIntrospector.java | 2 +- .../{ => internal}/serde/InternalDeserializers.java | 2 +- .../arangodb/{ => internal}/serde/InternalModule.java | 2 +- .../{ => internal}/serde/InternalParameterizedType.java | 2 +- .../com/arangodb/{ => internal}/serde/InternalSerde.java | 5 ++++- .../arangodb/{ => internal}/serde/InternalSerdeImpl.java | 5 +++-- .../{ => internal}/serde/InternalSerializers.java | 2 +- .../arangodb/{ => internal}/serde/JacksonSerdeImpl.java | 7 ++++--- .../{ => internal}/serde/JsonMapperProvider.java | 2 +- .../arangodb/{ => internal}/serde/JsonbSerdeImpl.java | 9 +++++---- .../arangodb/{ => internal}/serde/MapperProvider.java | 7 +++++-- .../com/arangodb/{ => internal}/serde/SerdeUtils.java | 2 +- .../java/com/arangodb/{ => internal}/serde/UserData.java | 2 +- .../{ => internal}/serde/UserDataDeserializer.java | 4 ++-- .../arangodb/{ => internal}/serde/UserDataInside.java | 2 +- .../{ => internal}/serde/UserDataSerializer.java | 2 +- .../{ => internal}/serde/VPackMapperProvider.java | 2 +- .../java/com/arangodb/internal/util/ResponseUtils.java | 2 +- .../arangodb/internal/velocystream/VstCommunication.java | 2 +- .../internal/velocystream/VstCommunicationSync.java | 2 +- .../java/com/arangodb/model/AqlQueryExplainOptions.java | 2 +- src/main/java/com/arangodb/model/AqlQueryOptions.java | 2 +- src/main/java/com/arangodb/model/CollectionSchema.java | 4 ++-- .../model/arangosearch/ArangoSearchCreateOptions.java | 2 +- .../arangosearch/ArangoSearchPropertiesOptions.java | 2 +- src/main/java/com/arangodb/serde/JacksonSerde.java | 2 ++ src/main/java/com/arangodb/serde/JsonbSerde.java | 1 + src/main/java/com/arangodb/util/RawBytes.java | 4 +++- src/main/java/com/arangodb/util/RawJson.java | 4 +++- src/test/java/com/arangodb/JwtAuthTest.java | 4 ++-- src/test/java/com/arangodb/async/JwtAuthTest.java | 4 ++-- src/test/java/com/arangodb/internal/HostHandlerTest.java | 2 +- src/test/java/com/arangodb/serde/CustomSerdeTest.java | 1 + src/test/java/com/arangodb/serde/SerdeTest.java | 2 ++ 65 files changed, 96 insertions(+), 88 deletions(-) rename src/main/java/com/arangodb/{ => internal}/serde/InternalAnnotationIntrospector.java (97%) rename src/main/java/com/arangodb/{ => internal}/serde/InternalDeserializers.java (99%) rename src/main/java/com/arangodb/{ => internal}/serde/InternalModule.java (98%) rename src/main/java/com/arangodb/{ => internal}/serde/InternalParameterizedType.java (94%) rename src/main/java/com/arangodb/{ => internal}/serde/InternalSerde.java (97%) rename src/main/java/com/arangodb/{ => internal}/serde/InternalSerdeImpl.java (96%) rename src/main/java/com/arangodb/{ => internal}/serde/InternalSerializers.java (99%) rename src/main/java/com/arangodb/{ => internal}/serde/JacksonSerdeImpl.java (85%) rename src/main/java/com/arangodb/{ => internal}/serde/JsonMapperProvider.java (85%) rename src/main/java/com/arangodb/{ => internal}/serde/JsonbSerdeImpl.java (74%) rename src/main/java/com/arangodb/{ => internal}/serde/MapperProvider.java (64%) rename src/main/java/com/arangodb/{ => internal}/serde/SerdeUtils.java (98%) rename src/main/java/com/arangodb/{ => internal}/serde/UserData.java (91%) rename src/main/java/com/arangodb/{ => internal}/serde/UserDataDeserializer.java (93%) rename src/main/java/com/arangodb/{ => internal}/serde/UserDataInside.java (94%) rename src/main/java/com/arangodb/{ => internal}/serde/UserDataSerializer.java (95%) rename src/main/java/com/arangodb/{ => internal}/serde/VPackMapperProvider.java (88%) diff --git a/src/main/java/com/arangodb/ArangoDB.java b/src/main/java/com/arangodb/ArangoDB.java index 899771d58..1a2d27c5e 100644 --- a/src/main/java/com/arangodb/ArangoDB.java +++ b/src/main/java/com/arangodb/ArangoDB.java @@ -28,7 +28,7 @@ import com.arangodb.internal.http.HttpCommunication; import com.arangodb.internal.http.HttpConnectionFactory; import com.arangodb.internal.net.*; -import com.arangodb.serde.InternalSerde; +import com.arangodb.internal.serde.InternalSerde; import com.arangodb.internal.velocystream.VstCommunicationSync; import com.arangodb.internal.velocystream.VstConnectionFactorySync; import com.arangodb.model.DBCreateOptions; @@ -36,11 +36,9 @@ import com.arangodb.model.UserCreateOptions; import com.arangodb.model.UserUpdateOptions; import com.arangodb.serde.DataType; -import com.arangodb.serde.InternalSerde; import com.arangodb.serde.JacksonSerde; import com.arangodb.util.ArangoCursorInitializer; import com.arangodb.serde.ArangoSerde; -import com.arangodb.serde.InternalSerde; import com.arangodb.velocystream.Request; import com.arangodb.velocystream.Response; import org.apache.http.client.HttpRequestRetryHandler; diff --git a/src/main/java/com/arangodb/ArangoSerdeAccessor.java b/src/main/java/com/arangodb/ArangoSerdeAccessor.java index e00c86204..5918a4d43 100644 --- a/src/main/java/com/arangodb/ArangoSerdeAccessor.java +++ b/src/main/java/com/arangodb/ArangoSerdeAccessor.java @@ -20,7 +20,7 @@ package com.arangodb; -import com.arangodb.serde.InternalSerde; +import com.arangodb.internal.serde.InternalSerde; /** * @author Mark Vollmary diff --git a/src/main/java/com/arangodb/async/ArangoDBAsync.java b/src/main/java/com/arangodb/async/ArangoDBAsync.java index 7a97a20ee..7ebb35032 100644 --- a/src/main/java/com/arangodb/async/ArangoDBAsync.java +++ b/src/main/java/com/arangodb/async/ArangoDBAsync.java @@ -31,7 +31,7 @@ import com.arangodb.internal.net.ConnectionFactory; import com.arangodb.internal.net.HostHandler; import com.arangodb.internal.net.HostResolver; -import com.arangodb.serde.InternalSerde; +import com.arangodb.internal.serde.InternalSerde; import com.arangodb.internal.velocystream.VstCommunicationSync; import com.arangodb.internal.velocystream.VstConnectionFactorySync; import com.arangodb.model.DBCreateOptions; @@ -39,7 +39,6 @@ import com.arangodb.model.UserCreateOptions; import com.arangodb.model.UserUpdateOptions; import com.arangodb.serde.DataType; -import com.arangodb.serde.InternalSerde; import com.arangodb.serde.JacksonSerde; import com.arangodb.serde.ArangoSerde; import com.arangodb.velocystream.Request; diff --git a/src/main/java/com/arangodb/async/internal/ArangoCollectionAsyncImpl.java b/src/main/java/com/arangodb/async/internal/ArangoCollectionAsyncImpl.java index 3d20579e9..9712fa053 100644 --- a/src/main/java/com/arangodb/async/internal/ArangoCollectionAsyncImpl.java +++ b/src/main/java/com/arangodb/async/internal/ArangoCollectionAsyncImpl.java @@ -20,7 +20,6 @@ package com.arangodb.async.internal; -import com.arangodb.ArangoDBException; import com.arangodb.async.ArangoCollectionAsync; import com.arangodb.entity.*; import com.arangodb.internal.InternalArangoCollection; @@ -31,7 +30,7 @@ import java.util.Objects; import java.util.concurrent.CompletableFuture; -import static com.arangodb.serde.SerdeUtils.constructParametricType; +import static com.arangodb.internal.serde.SerdeUtils.constructParametricType; /** * @author Mark Vollmary diff --git a/src/main/java/com/arangodb/async/internal/ArangoDBAsyncImpl.java b/src/main/java/com/arangodb/async/internal/ArangoDBAsyncImpl.java index 44a0dd3b5..dce0333cd 100644 --- a/src/main/java/com/arangodb/async/internal/ArangoDBAsyncImpl.java +++ b/src/main/java/com/arangodb/async/internal/ArangoDBAsyncImpl.java @@ -20,7 +20,6 @@ package com.arangodb.async.internal; -import com.arangodb.ArangoDBException; import com.arangodb.ArangoMetrics; import com.arangodb.DbName; import com.arangodb.async.ArangoDBAsync; @@ -31,7 +30,7 @@ import com.arangodb.internal.net.CommunicationProtocol; import com.arangodb.internal.net.HostHandler; import com.arangodb.internal.net.HostResolver; -import com.arangodb.serde.InternalSerde; +import com.arangodb.internal.serde.InternalSerde; import com.arangodb.internal.velocystream.VstCommunication; import com.arangodb.internal.velocystream.VstCommunicationSync; import com.arangodb.internal.velocystream.VstProtocol; diff --git a/src/main/java/com/arangodb/async/internal/ArangoDatabaseAsyncImpl.java b/src/main/java/com/arangodb/async/internal/ArangoDatabaseAsyncImpl.java index 76d883a88..fdbd3dc84 100644 --- a/src/main/java/com/arangodb/async/internal/ArangoDatabaseAsyncImpl.java +++ b/src/main/java/com/arangodb/async/internal/ArangoDatabaseAsyncImpl.java @@ -34,7 +34,6 @@ import com.arangodb.model.*; import com.arangodb.model.arangosearch.AnalyzerDeleteOptions; import com.arangodb.model.arangosearch.ArangoSearchCreateOptions; -import com.arangodb.serde.SerdeUtils; import com.arangodb.velocystream.Request; import java.util.Collection; @@ -44,7 +43,7 @@ import java.util.concurrent.CompletionException; import java.util.concurrent.ExecutionException; -import static com.arangodb.serde.SerdeUtils.constructListType; +import static com.arangodb.internal.serde.SerdeUtils.constructListType; /** * @author Mark Vollmary diff --git a/src/main/java/com/arangodb/async/internal/ArangoExecutorAsync.java b/src/main/java/com/arangodb/async/internal/ArangoExecutorAsync.java index 0ae625493..0f6548674 100644 --- a/src/main/java/com/arangodb/async/internal/ArangoExecutorAsync.java +++ b/src/main/java/com/arangodb/async/internal/ArangoExecutorAsync.java @@ -25,7 +25,7 @@ import com.arangodb.internal.ArangoExecutor; import com.arangodb.internal.QueueTimeMetricsImpl; import com.arangodb.internal.net.HostHandle; -import com.arangodb.serde.InternalSerde; +import com.arangodb.internal.serde.InternalSerde; import com.arangodb.velocystream.Request; import java.io.IOException; diff --git a/src/main/java/com/arangodb/async/internal/velocystream/VstCommunicationAsync.java b/src/main/java/com/arangodb/async/internal/velocystream/VstCommunicationAsync.java index 410b8dc9a..e68efd1b6 100644 --- a/src/main/java/com/arangodb/async/internal/velocystream/VstCommunicationAsync.java +++ b/src/main/java/com/arangodb/async/internal/velocystream/VstCommunicationAsync.java @@ -30,7 +30,7 @@ import com.arangodb.internal.velocystream.internal.AuthenticationRequest; import com.arangodb.internal.velocystream.internal.JwtAuthenticationRequest; import com.arangodb.internal.velocystream.internal.Message; -import com.arangodb.serde.InternalSerde; +import com.arangodb.internal.serde.InternalSerde; import com.arangodb.velocypack.exception.VPackException; import com.arangodb.velocypack.exception.VPackParserException; import com.arangodb.velocystream.Request; diff --git a/src/main/java/com/arangodb/entity/DocumentCreateEntity.java b/src/main/java/com/arangodb/entity/DocumentCreateEntity.java index c2d07bc8c..58e58e996 100644 --- a/src/main/java/com/arangodb/entity/DocumentCreateEntity.java +++ b/src/main/java/com/arangodb/entity/DocumentCreateEntity.java @@ -20,7 +20,7 @@ package com.arangodb.entity; -import com.arangodb.serde.UserData; +import com.arangodb.internal.serde.UserData; /** * @author Mark Vollmary diff --git a/src/main/java/com/arangodb/entity/DocumentDeleteEntity.java b/src/main/java/com/arangodb/entity/DocumentDeleteEntity.java index 46fa34c56..77d12d8b6 100644 --- a/src/main/java/com/arangodb/entity/DocumentDeleteEntity.java +++ b/src/main/java/com/arangodb/entity/DocumentDeleteEntity.java @@ -20,7 +20,7 @@ package com.arangodb.entity; -import com.arangodb.serde.UserData; +import com.arangodb.internal.serde.UserData; /** * @author Mark Vollmary diff --git a/src/main/java/com/arangodb/entity/DocumentUpdateEntity.java b/src/main/java/com/arangodb/entity/DocumentUpdateEntity.java index 61b9b1f62..c64d62d38 100644 --- a/src/main/java/com/arangodb/entity/DocumentUpdateEntity.java +++ b/src/main/java/com/arangodb/entity/DocumentUpdateEntity.java @@ -20,7 +20,7 @@ package com.arangodb.entity; -import com.arangodb.serde.UserData; +import com.arangodb.internal.serde.UserData; import com.fasterxml.jackson.annotation.JsonProperty; /** diff --git a/src/main/java/com/arangodb/entity/arangosearch/ArangoSearchPropertiesEntity.java b/src/main/java/com/arangodb/entity/arangosearch/ArangoSearchPropertiesEntity.java index 4c5f3073b..d2f8015e3 100644 --- a/src/main/java/com/arangodb/entity/arangosearch/ArangoSearchPropertiesEntity.java +++ b/src/main/java/com/arangodb/entity/arangosearch/ArangoSearchPropertiesEntity.java @@ -21,7 +21,7 @@ package com.arangodb.entity.arangosearch; import com.arangodb.entity.ViewEntity; -import com.arangodb.serde.InternalDeserializers; +import com.arangodb.internal.serde.InternalDeserializers; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import java.util.Collection; diff --git a/src/main/java/com/arangodb/entity/arangosearch/CollectionLink.java b/src/main/java/com/arangodb/entity/arangosearch/CollectionLink.java index d358e24d0..e240cbbc4 100644 --- a/src/main/java/com/arangodb/entity/arangosearch/CollectionLink.java +++ b/src/main/java/com/arangodb/entity/arangosearch/CollectionLink.java @@ -20,8 +20,8 @@ package com.arangodb.entity.arangosearch; -import com.arangodb.serde.InternalDeserializers; -import com.arangodb.serde.InternalSerializers; +import com.arangodb.internal.serde.InternalDeserializers; +import com.arangodb.internal.serde.InternalSerializers; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonProperty; diff --git a/src/main/java/com/arangodb/entity/arangosearch/FieldLink.java b/src/main/java/com/arangodb/entity/arangosearch/FieldLink.java index cb3a851dc..2b2a803a4 100644 --- a/src/main/java/com/arangodb/entity/arangosearch/FieldLink.java +++ b/src/main/java/com/arangodb/entity/arangosearch/FieldLink.java @@ -1,6 +1,6 @@ package com.arangodb.entity.arangosearch; -import com.arangodb.serde.InternalSerializers; +import com.arangodb.internal.serde.InternalSerializers; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonProperty; diff --git a/src/main/java/com/arangodb/internal/ArangoCollectionImpl.java b/src/main/java/com/arangodb/internal/ArangoCollectionImpl.java index 2bc7d50fc..44cc9ed39 100644 --- a/src/main/java/com/arangodb/internal/ArangoCollectionImpl.java +++ b/src/main/java/com/arangodb/internal/ArangoCollectionImpl.java @@ -30,7 +30,7 @@ import java.util.Collection; -import static com.arangodb.serde.SerdeUtils.constructParametricType; +import static com.arangodb.internal.serde.SerdeUtils.constructParametricType; /** * @author Mark Vollmary diff --git a/src/main/java/com/arangodb/internal/ArangoDBImpl.java b/src/main/java/com/arangodb/internal/ArangoDBImpl.java index 294dced7f..391e91ac8 100644 --- a/src/main/java/com/arangodb/internal/ArangoDBImpl.java +++ b/src/main/java/com/arangodb/internal/ArangoDBImpl.java @@ -28,7 +28,7 @@ import com.arangodb.internal.net.HostHandle; import com.arangodb.internal.net.HostHandler; import com.arangodb.internal.net.HostResolver; -import com.arangodb.serde.InternalSerde; +import com.arangodb.internal.serde.InternalSerde; import com.arangodb.internal.velocystream.VstCommunicationSync; import com.arangodb.internal.velocystream.VstProtocol; import com.arangodb.model.DBCreateOptions; diff --git a/src/main/java/com/arangodb/internal/ArangoDatabaseImpl.java b/src/main/java/com/arangodb/internal/ArangoDatabaseImpl.java index 5556e53f8..fbd173ae2 100644 --- a/src/main/java/com/arangodb/internal/ArangoDatabaseImpl.java +++ b/src/main/java/com/arangodb/internal/ArangoDatabaseImpl.java @@ -30,7 +30,6 @@ import com.arangodb.model.*; import com.arangodb.model.arangosearch.AnalyzerDeleteOptions; import com.arangodb.model.arangosearch.ArangoSearchCreateOptions; -import com.arangodb.serde.SerdeUtils; import com.arangodb.util.ArangoCursorInitializer; import com.arangodb.velocystream.Request; @@ -38,7 +37,7 @@ import java.util.Collections; import java.util.Map; -import static com.arangodb.serde.SerdeUtils.constructListType; +import static com.arangodb.internal.serde.SerdeUtils.constructListType; /** * @author Mark Vollmary diff --git a/src/main/java/com/arangodb/internal/ArangoExecuteable.java b/src/main/java/com/arangodb/internal/ArangoExecuteable.java index 24b52a45d..ef70238b3 100644 --- a/src/main/java/com/arangodb/internal/ArangoExecuteable.java +++ b/src/main/java/com/arangodb/internal/ArangoExecuteable.java @@ -23,7 +23,7 @@ import com.arangodb.ArangoSerdeAccessor; import com.arangodb.DbName; import com.arangodb.internal.util.EncodeUtils; -import com.arangodb.serde.InternalSerde; +import com.arangodb.internal.serde.InternalSerde; import com.arangodb.velocystream.Request; import com.arangodb.velocystream.RequestType; diff --git a/src/main/java/com/arangodb/internal/ArangoExecutor.java b/src/main/java/com/arangodb/internal/ArangoExecutor.java index 1aad9a93d..2cf453b05 100644 --- a/src/main/java/com/arangodb/internal/ArangoExecutor.java +++ b/src/main/java/com/arangodb/internal/ArangoExecutor.java @@ -21,7 +21,7 @@ package com.arangodb.internal; import com.arangodb.QueueTimeMetrics; -import com.arangodb.serde.InternalSerde; +import com.arangodb.internal.serde.InternalSerde; import com.arangodb.velocystream.Request; import com.arangodb.velocystream.Response; diff --git a/src/main/java/com/arangodb/internal/ArangoExecutorSync.java b/src/main/java/com/arangodb/internal/ArangoExecutorSync.java index b8cd2f2b1..4e81c50cf 100644 --- a/src/main/java/com/arangodb/internal/ArangoExecutorSync.java +++ b/src/main/java/com/arangodb/internal/ArangoExecutorSync.java @@ -24,7 +24,7 @@ import com.arangodb.entity.MetaAware; import com.arangodb.internal.net.CommunicationProtocol; import com.arangodb.internal.net.HostHandle; -import com.arangodb.serde.InternalSerde; +import com.arangodb.internal.serde.InternalSerde; import com.arangodb.velocystream.Request; import com.arangodb.velocystream.Response; import org.slf4j.Logger; diff --git a/src/main/java/com/arangodb/internal/InternalArangoCollection.java b/src/main/java/com/arangodb/internal/InternalArangoCollection.java index 55b4a993f..6be1d5a27 100644 --- a/src/main/java/com/arangodb/internal/InternalArangoCollection.java +++ b/src/main/java/com/arangodb/internal/InternalArangoCollection.java @@ -27,7 +27,7 @@ import com.arangodb.internal.util.DocumentUtil; import com.arangodb.internal.util.RequestUtils; import com.arangodb.model.*; -import com.arangodb.serde.SerdeUtils; +import com.arangodb.internal.serde.SerdeUtils; import com.arangodb.velocystream.Request; import com.arangodb.velocystream.RequestType; import com.fasterxml.jackson.databind.JsonNode; @@ -35,8 +35,8 @@ import java.lang.reflect.Type; import java.util.*; -import static com.arangodb.serde.SerdeUtils.constructListType; -import static com.arangodb.serde.SerdeUtils.constructParametricType; +import static com.arangodb.internal.serde.SerdeUtils.constructListType; +import static com.arangodb.internal.serde.SerdeUtils.constructParametricType; /** * @author Mark Vollmary diff --git a/src/main/java/com/arangodb/internal/InternalArangoDB.java b/src/main/java/com/arangodb/internal/InternalArangoDB.java index c8cbba05b..763d7e612 100644 --- a/src/main/java/com/arangodb/internal/InternalArangoDB.java +++ b/src/main/java/com/arangodb/internal/InternalArangoDB.java @@ -24,8 +24,7 @@ import com.arangodb.entity.*; import com.arangodb.internal.ArangoExecutor.ResponseDeserializer; import com.arangodb.model.*; -import com.arangodb.serde.InternalSerde; -import com.arangodb.serde.SerdeUtils; +import com.arangodb.internal.serde.InternalSerde; import com.arangodb.velocystream.Request; import com.arangodb.velocystream.RequestType; @@ -33,7 +32,7 @@ import java.util.Collection; import java.util.Iterator; -import static com.arangodb.serde.SerdeUtils.constructListType; +import static com.arangodb.internal.serde.SerdeUtils.constructListType; /** * @author Mark Vollmary diff --git a/src/main/java/com/arangodb/internal/InternalArangoDatabase.java b/src/main/java/com/arangodb/internal/InternalArangoDatabase.java index a2e49e983..0a86001d9 100644 --- a/src/main/java/com/arangodb/internal/InternalArangoDatabase.java +++ b/src/main/java/com/arangodb/internal/InternalArangoDatabase.java @@ -29,14 +29,13 @@ import com.arangodb.model.arangosearch.AnalyzerDeleteOptions; import com.arangodb.model.arangosearch.ArangoSearchCreateOptions; import com.arangodb.model.arangosearch.ArangoSearchOptionsBuilder; -import com.arangodb.serde.SerdeUtils; import com.arangodb.velocystream.Request; import com.arangodb.velocystream.RequestType; import java.util.Collection; import java.util.Map; -import static com.arangodb.serde.SerdeUtils.constructListType; +import static com.arangodb.internal.serde.SerdeUtils.constructListType; /** * @author Mark Vollmary diff --git a/src/main/java/com/arangodb/internal/InternalArangoGraph.java b/src/main/java/com/arangodb/internal/InternalArangoGraph.java index 8bafa815e..f5d437d6f 100644 --- a/src/main/java/com/arangodb/internal/InternalArangoGraph.java +++ b/src/main/java/com/arangodb/internal/InternalArangoGraph.java @@ -25,13 +25,12 @@ import com.arangodb.internal.ArangoExecutor.ResponseDeserializer; import com.arangodb.model.OptionsBuilder; import com.arangodb.model.VertexCollectionCreateOptions; -import com.arangodb.serde.SerdeUtils; import com.arangodb.velocystream.Request; import com.arangodb.velocystream.RequestType; import java.util.Collection; -import static com.arangodb.serde.SerdeUtils.constructListType; +import static com.arangodb.internal.serde.SerdeUtils.constructListType; /** * @author Mark Vollmary diff --git a/src/main/java/com/arangodb/internal/http/CURLLogger.java b/src/main/java/com/arangodb/internal/http/CURLLogger.java index 062b30bba..31e4a29a9 100644 --- a/src/main/java/com/arangodb/internal/http/CURLLogger.java +++ b/src/main/java/com/arangodb/internal/http/CURLLogger.java @@ -20,7 +20,7 @@ package com.arangodb.internal.http; -import com.arangodb.serde.InternalSerde; +import com.arangodb.internal.serde.InternalSerde; import com.arangodb.velocystream.Request; import com.arangodb.velocystream.RequestType; import org.apache.http.auth.Credentials; diff --git a/src/main/java/com/arangodb/internal/http/HttpCommunication.java b/src/main/java/com/arangodb/internal/http/HttpCommunication.java index 614e32d42..b227b4b20 100644 --- a/src/main/java/com/arangodb/internal/http/HttpCommunication.java +++ b/src/main/java/com/arangodb/internal/http/HttpCommunication.java @@ -24,7 +24,7 @@ import com.arangodb.internal.net.*; import com.arangodb.internal.util.HostUtils; import com.arangodb.internal.util.RequestUtils; -import com.arangodb.serde.InternalSerde; +import com.arangodb.internal.serde.InternalSerde; import com.arangodb.velocystream.Request; import com.arangodb.velocystream.Response; import org.slf4j.Logger; diff --git a/src/main/java/com/arangodb/internal/http/HttpConnection.java b/src/main/java/com/arangodb/internal/http/HttpConnection.java index 8486559d9..05e37f53a 100644 --- a/src/main/java/com/arangodb/internal/http/HttpConnection.java +++ b/src/main/java/com/arangodb/internal/http/HttpConnection.java @@ -27,7 +27,7 @@ import com.arangodb.internal.net.HostDescription; import com.arangodb.internal.util.IOUtils; import com.arangodb.internal.util.ResponseUtils; -import com.arangodb.serde.InternalSerde; +import com.arangodb.internal.serde.InternalSerde; import com.arangodb.velocystream.Request; import com.arangodb.velocystream.Response; import org.apache.http.*; diff --git a/src/main/java/com/arangodb/internal/http/HttpConnectionFactory.java b/src/main/java/com/arangodb/internal/http/HttpConnectionFactory.java index b0294ad0c..d39d5375a 100644 --- a/src/main/java/com/arangodb/internal/http/HttpConnectionFactory.java +++ b/src/main/java/com/arangodb/internal/http/HttpConnectionFactory.java @@ -24,7 +24,7 @@ import com.arangodb.internal.net.Connection; import com.arangodb.internal.net.ConnectionFactory; import com.arangodb.internal.net.HostDescription; -import com.arangodb.serde.InternalSerde; +import com.arangodb.internal.serde.InternalSerde; import org.apache.http.client.HttpRequestRetryHandler; import javax.net.ssl.HostnameVerifier; diff --git a/src/main/java/com/arangodb/internal/net/ExtendedHostResolver.java b/src/main/java/com/arangodb/internal/net/ExtendedHostResolver.java index 85a85fd49..df0a21e4a 100644 --- a/src/main/java/com/arangodb/internal/net/ExtendedHostResolver.java +++ b/src/main/java/com/arangodb/internal/net/ExtendedHostResolver.java @@ -24,8 +24,7 @@ import com.arangodb.DbName; import com.arangodb.internal.ArangoExecutorSync; import com.arangodb.internal.util.HostUtils; -import com.arangodb.serde.SerdeUtils; -import com.arangodb.serde.InternalSerde; +import com.arangodb.internal.serde.InternalSerde; import com.arangodb.velocystream.Request; import com.arangodb.velocystream.RequestType; import org.slf4j.Logger; @@ -33,7 +32,7 @@ import java.util.*; -import static com.arangodb.serde.SerdeUtils.constructParametricType; +import static com.arangodb.internal.serde.SerdeUtils.constructParametricType; /** * @author Mark Vollmary diff --git a/src/main/java/com/arangodb/internal/net/HostResolver.java b/src/main/java/com/arangodb/internal/net/HostResolver.java index b05f6e419..744ee9e87 100644 --- a/src/main/java/com/arangodb/internal/net/HostResolver.java +++ b/src/main/java/com/arangodb/internal/net/HostResolver.java @@ -21,7 +21,7 @@ package com.arangodb.internal.net; import com.arangodb.internal.ArangoExecutorSync; -import com.arangodb.serde.InternalSerde; +import com.arangodb.internal.serde.InternalSerde; /** * @author Mark Vollmary diff --git a/src/main/java/com/arangodb/internal/net/SimpleHostResolver.java b/src/main/java/com/arangodb/internal/net/SimpleHostResolver.java index 23740938d..1d1d8f8f5 100644 --- a/src/main/java/com/arangodb/internal/net/SimpleHostResolver.java +++ b/src/main/java/com/arangodb/internal/net/SimpleHostResolver.java @@ -21,7 +21,7 @@ package com.arangodb.internal.net; import com.arangodb.internal.ArangoExecutorSync; -import com.arangodb.serde.InternalSerde; +import com.arangodb.internal.serde.InternalSerde; import java.util.List; diff --git a/src/main/java/com/arangodb/serde/InternalAnnotationIntrospector.java b/src/main/java/com/arangodb/internal/serde/InternalAnnotationIntrospector.java similarity index 97% rename from src/main/java/com/arangodb/serde/InternalAnnotationIntrospector.java rename to src/main/java/com/arangodb/internal/serde/InternalAnnotationIntrospector.java index cfaa5b417..ce05a0b63 100644 --- a/src/main/java/com/arangodb/serde/InternalAnnotationIntrospector.java +++ b/src/main/java/com/arangodb/internal/serde/InternalAnnotationIntrospector.java @@ -1,4 +1,4 @@ -package com.arangodb.serde; +package com.arangodb.internal.serde; import com.fasterxml.jackson.databind.introspect.Annotated; import com.fasterxml.jackson.databind.introspect.JacksonAnnotationIntrospector; diff --git a/src/main/java/com/arangodb/serde/InternalDeserializers.java b/src/main/java/com/arangodb/internal/serde/InternalDeserializers.java similarity index 99% rename from src/main/java/com/arangodb/serde/InternalDeserializers.java rename to src/main/java/com/arangodb/internal/serde/InternalDeserializers.java index 31f41cf46..21e95c7b7 100644 --- a/src/main/java/com/arangodb/serde/InternalDeserializers.java +++ b/src/main/java/com/arangodb/internal/serde/InternalDeserializers.java @@ -1,4 +1,4 @@ -package com.arangodb.serde; +package com.arangodb.internal.serde; import com.arangodb.entity.CollectionStatus; import com.arangodb.entity.CollectionType; diff --git a/src/main/java/com/arangodb/serde/InternalModule.java b/src/main/java/com/arangodb/internal/serde/InternalModule.java similarity index 98% rename from src/main/java/com/arangodb/serde/InternalModule.java rename to src/main/java/com/arangodb/internal/serde/InternalModule.java index 407590d7a..3fd5802aa 100644 --- a/src/main/java/com/arangodb/serde/InternalModule.java +++ b/src/main/java/com/arangodb/internal/serde/InternalModule.java @@ -1,4 +1,4 @@ -package com.arangodb.serde; +package com.arangodb.internal.serde; import com.arangodb.entity.CollectionStatus; import com.arangodb.entity.CollectionType; diff --git a/src/main/java/com/arangodb/serde/InternalParameterizedType.java b/src/main/java/com/arangodb/internal/serde/InternalParameterizedType.java similarity index 94% rename from src/main/java/com/arangodb/serde/InternalParameterizedType.java rename to src/main/java/com/arangodb/internal/serde/InternalParameterizedType.java index 40086b74f..82c0dcf4c 100644 --- a/src/main/java/com/arangodb/serde/InternalParameterizedType.java +++ b/src/main/java/com/arangodb/internal/serde/InternalParameterizedType.java @@ -1,4 +1,4 @@ -package com.arangodb.serde; +package com.arangodb.internal.serde; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; diff --git a/src/main/java/com/arangodb/serde/InternalSerde.java b/src/main/java/com/arangodb/internal/serde/InternalSerde.java similarity index 97% rename from src/main/java/com/arangodb/serde/InternalSerde.java rename to src/main/java/com/arangodb/internal/serde/InternalSerde.java index 2fcafb358..70d4fc462 100644 --- a/src/main/java/com/arangodb/serde/InternalSerde.java +++ b/src/main/java/com/arangodb/internal/serde/InternalSerde.java @@ -1,5 +1,8 @@ -package com.arangodb.serde; +package com.arangodb.internal.serde; +import com.arangodb.serde.ArangoSerde; +import com.arangodb.serde.DataType; +import com.arangodb.serde.JacksonSerde; import com.fasterxml.jackson.databind.JsonNode; import java.lang.reflect.Type; diff --git a/src/main/java/com/arangodb/serde/InternalSerdeImpl.java b/src/main/java/com/arangodb/internal/serde/InternalSerdeImpl.java similarity index 96% rename from src/main/java/com/arangodb/serde/InternalSerdeImpl.java rename to src/main/java/com/arangodb/internal/serde/InternalSerdeImpl.java index 1f206ef8c..795711cf8 100644 --- a/src/main/java/com/arangodb/serde/InternalSerdeImpl.java +++ b/src/main/java/com/arangodb/internal/serde/InternalSerdeImpl.java @@ -1,7 +1,8 @@ -package com.arangodb.serde; +package com.arangodb.internal.serde; import com.arangodb.ArangoDBException; import com.arangodb.entity.BaseDocument; +import com.arangodb.serde.*; import com.arangodb.util.RawBytes; import com.arangodb.util.RawJson; import com.fasterxml.jackson.annotation.JsonInclude; @@ -14,7 +15,7 @@ import java.util.List; import java.util.stream.Collectors; -import static com.arangodb.serde.SerdeUtils.checkSupportedJacksonVersion; +import static com.arangodb.internal.serde.SerdeUtils.checkSupportedJacksonVersion; final class InternalSerdeImpl extends JacksonSerdeImpl implements InternalSerde { diff --git a/src/main/java/com/arangodb/serde/InternalSerializers.java b/src/main/java/com/arangodb/internal/serde/InternalSerializers.java similarity index 99% rename from src/main/java/com/arangodb/serde/InternalSerializers.java rename to src/main/java/com/arangodb/internal/serde/InternalSerializers.java index 454b1a4bc..c6ab3a835 100644 --- a/src/main/java/com/arangodb/serde/InternalSerializers.java +++ b/src/main/java/com/arangodb/internal/serde/InternalSerializers.java @@ -1,4 +1,4 @@ -package com.arangodb.serde; +package com.arangodb.internal.serde; import com.arangodb.entity.CollectionType; import com.arangodb.entity.arangosearch.CollectionLink; diff --git a/src/main/java/com/arangodb/serde/JacksonSerdeImpl.java b/src/main/java/com/arangodb/internal/serde/JacksonSerdeImpl.java similarity index 85% rename from src/main/java/com/arangodb/serde/JacksonSerdeImpl.java rename to src/main/java/com/arangodb/internal/serde/JacksonSerdeImpl.java index 11f56ab1f..90f27ae6b 100644 --- a/src/main/java/com/arangodb/serde/JacksonSerdeImpl.java +++ b/src/main/java/com/arangodb/internal/serde/JacksonSerdeImpl.java @@ -1,6 +1,7 @@ -package com.arangodb.serde; +package com.arangodb.internal.serde; import com.arangodb.ArangoDBException; +import com.arangodb.serde.JacksonSerde; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; @@ -9,11 +10,11 @@ import java.lang.reflect.Type; import java.util.function.Consumer; -class JacksonSerdeImpl implements JacksonSerde { +public class JacksonSerdeImpl implements JacksonSerde { protected final ObjectMapper mapper; - JacksonSerdeImpl(final ObjectMapper mapper) { + public JacksonSerdeImpl(final ObjectMapper mapper) { this.mapper = mapper; mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); } diff --git a/src/main/java/com/arangodb/serde/JsonMapperProvider.java b/src/main/java/com/arangodb/internal/serde/JsonMapperProvider.java similarity index 85% rename from src/main/java/com/arangodb/serde/JsonMapperProvider.java rename to src/main/java/com/arangodb/internal/serde/JsonMapperProvider.java index 033deef2f..e3ba08eb5 100644 --- a/src/main/java/com/arangodb/serde/JsonMapperProvider.java +++ b/src/main/java/com/arangodb/internal/serde/JsonMapperProvider.java @@ -1,4 +1,4 @@ -package com.arangodb.serde; +package com.arangodb.internal.serde; import com.fasterxml.jackson.databind.ObjectMapper; diff --git a/src/main/java/com/arangodb/serde/JsonbSerdeImpl.java b/src/main/java/com/arangodb/internal/serde/JsonbSerdeImpl.java similarity index 74% rename from src/main/java/com/arangodb/serde/JsonbSerdeImpl.java rename to src/main/java/com/arangodb/internal/serde/JsonbSerdeImpl.java index 17993ca2b..3f3fe8fde 100644 --- a/src/main/java/com/arangodb/serde/JsonbSerdeImpl.java +++ b/src/main/java/com/arangodb/internal/serde/JsonbSerdeImpl.java @@ -1,5 +1,6 @@ -package com.arangodb.serde; +package com.arangodb.internal.serde; +import com.arangodb.serde.JsonbSerde; import jakarta.json.bind.Jsonb; import jakarta.json.bind.JsonbBuilder; import jakarta.json.bind.JsonbConfig; @@ -7,15 +8,15 @@ import java.lang.reflect.Type; import java.nio.charset.StandardCharsets; -class JsonbSerdeImpl implements JsonbSerde { +public class JsonbSerdeImpl implements JsonbSerde { private final Jsonb jsonb; - JsonbSerdeImpl() { + public JsonbSerdeImpl() { jsonb = JsonbBuilder.create(); } - JsonbSerdeImpl(final JsonbConfig config) { + public JsonbSerdeImpl(final JsonbConfig config) { jsonb = JsonbBuilder.create(config); } diff --git a/src/main/java/com/arangodb/serde/MapperProvider.java b/src/main/java/com/arangodb/internal/serde/MapperProvider.java similarity index 64% rename from src/main/java/com/arangodb/serde/MapperProvider.java rename to src/main/java/com/arangodb/internal/serde/MapperProvider.java index be5759a54..30ac3a14b 100644 --- a/src/main/java/com/arangodb/serde/MapperProvider.java +++ b/src/main/java/com/arangodb/internal/serde/MapperProvider.java @@ -1,10 +1,13 @@ -package com.arangodb.serde; +package com.arangodb.internal.serde; +import com.arangodb.internal.serde.JsonMapperProvider; +import com.arangodb.internal.serde.VPackMapperProvider; +import com.arangodb.serde.DataType; import com.fasterxml.jackson.databind.ObjectMapper; import java.util.function.Supplier; -interface MapperProvider extends Supplier { +public interface MapperProvider extends Supplier { static ObjectMapper of(final DataType dataType) { if (dataType == DataType.JSON) { return JsonMapperProvider.INSTANCE.get(); diff --git a/src/main/java/com/arangodb/serde/SerdeUtils.java b/src/main/java/com/arangodb/internal/serde/SerdeUtils.java similarity index 98% rename from src/main/java/com/arangodb/serde/SerdeUtils.java rename to src/main/java/com/arangodb/internal/serde/SerdeUtils.java index b16433285..f72322514 100644 --- a/src/main/java/com/arangodb/serde/SerdeUtils.java +++ b/src/main/java/com/arangodb/internal/serde/SerdeUtils.java @@ -1,4 +1,4 @@ -package com.arangodb.serde; +package com.arangodb.internal.serde; import com.arangodb.ArangoDBException; import com.arangodb.jackson.dataformat.velocypack.VPackMapper; diff --git a/src/main/java/com/arangodb/serde/UserData.java b/src/main/java/com/arangodb/internal/serde/UserData.java similarity index 91% rename from src/main/java/com/arangodb/serde/UserData.java rename to src/main/java/com/arangodb/internal/serde/UserData.java index 8e53d2048..da9f7dc86 100644 --- a/src/main/java/com/arangodb/serde/UserData.java +++ b/src/main/java/com/arangodb/internal/serde/UserData.java @@ -1,4 +1,4 @@ -package com.arangodb.serde; +package com.arangodb.internal.serde; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; diff --git a/src/main/java/com/arangodb/serde/UserDataDeserializer.java b/src/main/java/com/arangodb/internal/serde/UserDataDeserializer.java similarity index 93% rename from src/main/java/com/arangodb/serde/UserDataDeserializer.java rename to src/main/java/com/arangodb/internal/serde/UserDataDeserializer.java index 4f5ac9f2e..91220088b 100644 --- a/src/main/java/com/arangodb/serde/UserDataDeserializer.java +++ b/src/main/java/com/arangodb/internal/serde/UserDataDeserializer.java @@ -1,4 +1,4 @@ -package com.arangodb.serde; +package com.arangodb.internal.serde; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.databind.BeanProperty; @@ -11,7 +11,7 @@ import java.io.IOException; import java.lang.reflect.Type; -import static com.arangodb.serde.SerdeUtils.convertToType; +import static com.arangodb.internal.serde.SerdeUtils.convertToType; class UserDataDeserializer extends JsonDeserializer implements ContextualDeserializer { private final Type targetType; diff --git a/src/main/java/com/arangodb/serde/UserDataInside.java b/src/main/java/com/arangodb/internal/serde/UserDataInside.java similarity index 94% rename from src/main/java/com/arangodb/serde/UserDataInside.java rename to src/main/java/com/arangodb/internal/serde/UserDataInside.java index 6e03165f5..cdfd83b43 100644 --- a/src/main/java/com/arangodb/serde/UserDataInside.java +++ b/src/main/java/com/arangodb/internal/serde/UserDataInside.java @@ -1,4 +1,4 @@ -package com.arangodb.serde; +package com.arangodb.internal.serde; import com.fasterxml.jackson.annotation.JacksonAnnotationsInside; import com.fasterxml.jackson.annotation.JsonInclude; diff --git a/src/main/java/com/arangodb/serde/UserDataSerializer.java b/src/main/java/com/arangodb/internal/serde/UserDataSerializer.java similarity index 95% rename from src/main/java/com/arangodb/serde/UserDataSerializer.java rename to src/main/java/com/arangodb/internal/serde/UserDataSerializer.java index 9f3067db9..351c0e460 100644 --- a/src/main/java/com/arangodb/serde/UserDataSerializer.java +++ b/src/main/java/com/arangodb/internal/serde/UserDataSerializer.java @@ -1,4 +1,4 @@ -package com.arangodb.serde; +package com.arangodb.internal.serde; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.core.JsonParser; diff --git a/src/main/java/com/arangodb/serde/VPackMapperProvider.java b/src/main/java/com/arangodb/internal/serde/VPackMapperProvider.java similarity index 88% rename from src/main/java/com/arangodb/serde/VPackMapperProvider.java rename to src/main/java/com/arangodb/internal/serde/VPackMapperProvider.java index 95f4e1a7d..0762414fc 100644 --- a/src/main/java/com/arangodb/serde/VPackMapperProvider.java +++ b/src/main/java/com/arangodb/internal/serde/VPackMapperProvider.java @@ -1,4 +1,4 @@ -package com.arangodb.serde; +package com.arangodb.internal.serde; import com.arangodb.jackson.dataformat.velocypack.VPackMapper; import com.fasterxml.jackson.databind.ObjectMapper; diff --git a/src/main/java/com/arangodb/internal/util/ResponseUtils.java b/src/main/java/com/arangodb/internal/util/ResponseUtils.java index 9c45995e4..64d75efd6 100644 --- a/src/main/java/com/arangodb/internal/util/ResponseUtils.java +++ b/src/main/java/com/arangodb/internal/util/ResponseUtils.java @@ -24,7 +24,7 @@ import com.arangodb.entity.ErrorEntity; import com.arangodb.internal.ArangoErrors; import com.arangodb.internal.net.ArangoDBRedirectException; -import com.arangodb.serde.InternalSerde; +import com.arangodb.internal.serde.InternalSerde; import com.arangodb.velocystream.Response; import java.util.concurrent.TimeoutException; diff --git a/src/main/java/com/arangodb/internal/velocystream/VstCommunication.java b/src/main/java/com/arangodb/internal/velocystream/VstCommunication.java index 7cb214a6e..557fddc53 100644 --- a/src/main/java/com/arangodb/internal/velocystream/VstCommunication.java +++ b/src/main/java/com/arangodb/internal/velocystream/VstCommunication.java @@ -31,7 +31,7 @@ import com.arangodb.internal.velocystream.internal.Chunk; import com.arangodb.internal.velocystream.internal.Message; import com.arangodb.internal.velocystream.internal.VstConnection; -import com.arangodb.serde.InternalSerde; +import com.arangodb.internal.serde.InternalSerde; import com.arangodb.velocypack.VPackSlice; import com.arangodb.velocypack.exception.VPackParserException; import com.arangodb.velocystream.Request; diff --git a/src/main/java/com/arangodb/internal/velocystream/VstCommunicationSync.java b/src/main/java/com/arangodb/internal/velocystream/VstCommunicationSync.java index 03bfd0dd7..76e258f93 100644 --- a/src/main/java/com/arangodb/internal/velocystream/VstCommunicationSync.java +++ b/src/main/java/com/arangodb/internal/velocystream/VstCommunicationSync.java @@ -30,7 +30,7 @@ import com.arangodb.internal.velocystream.internal.JwtAuthenticationRequest; import com.arangodb.internal.velocystream.internal.Message; import com.arangodb.internal.velocystream.internal.VstConnectionSync; -import com.arangodb.serde.InternalSerde; +import com.arangodb.internal.serde.InternalSerde; import com.arangodb.velocypack.exception.VPackParserException; import com.arangodb.velocystream.Request; import com.arangodb.velocystream.Response; diff --git a/src/main/java/com/arangodb/model/AqlQueryExplainOptions.java b/src/main/java/com/arangodb/model/AqlQueryExplainOptions.java index 7a1b9b448..ca6513acf 100644 --- a/src/main/java/com/arangodb/model/AqlQueryExplainOptions.java +++ b/src/main/java/com/arangodb/model/AqlQueryExplainOptions.java @@ -20,7 +20,7 @@ package com.arangodb.model; -import com.arangodb.serde.UserDataInside; +import com.arangodb.internal.serde.UserDataInside; import java.util.Collection; import java.util.Map; diff --git a/src/main/java/com/arangodb/model/AqlQueryOptions.java b/src/main/java/com/arangodb/model/AqlQueryOptions.java index 9fe1e4a65..1ae4c51f4 100644 --- a/src/main/java/com/arangodb/model/AqlQueryOptions.java +++ b/src/main/java/com/arangodb/model/AqlQueryOptions.java @@ -20,7 +20,7 @@ package com.arangodb.model; -import com.arangodb.serde.UserDataInside; +import com.arangodb.internal.serde.UserDataInside; import java.util.Arrays; import java.util.Collection; diff --git a/src/main/java/com/arangodb/model/CollectionSchema.java b/src/main/java/com/arangodb/model/CollectionSchema.java index 40c5c539b..9a0164be6 100644 --- a/src/main/java/com/arangodb/model/CollectionSchema.java +++ b/src/main/java/com/arangodb/model/CollectionSchema.java @@ -22,8 +22,8 @@ package com.arangodb.model; -import com.arangodb.serde.InternalDeserializers; -import com.arangodb.serde.InternalSerializers; +import com.arangodb.internal.serde.InternalDeserializers; +import com.arangodb.internal.serde.InternalSerializers; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.fasterxml.jackson.databind.annotation.JsonSerialize; diff --git a/src/main/java/com/arangodb/model/arangosearch/ArangoSearchCreateOptions.java b/src/main/java/com/arangodb/model/arangosearch/ArangoSearchCreateOptions.java index 5d810507a..57c8a21ec 100644 --- a/src/main/java/com/arangodb/model/arangosearch/ArangoSearchCreateOptions.java +++ b/src/main/java/com/arangodb/model/arangosearch/ArangoSearchCreateOptions.java @@ -22,7 +22,7 @@ import com.arangodb.entity.ViewType; import com.arangodb.entity.arangosearch.*; -import com.arangodb.serde.InternalSerializers; +import com.arangodb.internal.serde.InternalSerializers; import com.fasterxml.jackson.databind.annotation.JsonSerialize; import java.util.Arrays; diff --git a/src/main/java/com/arangodb/model/arangosearch/ArangoSearchPropertiesOptions.java b/src/main/java/com/arangodb/model/arangosearch/ArangoSearchPropertiesOptions.java index 7be061b87..6420b13de 100644 --- a/src/main/java/com/arangodb/model/arangosearch/ArangoSearchPropertiesOptions.java +++ b/src/main/java/com/arangodb/model/arangosearch/ArangoSearchPropertiesOptions.java @@ -23,7 +23,7 @@ import com.arangodb.entity.arangosearch.CollectionLink; import com.arangodb.entity.arangosearch.ConsolidationPolicy; import com.arangodb.entity.arangosearch.PrimarySort; -import com.arangodb.serde.InternalSerializers; +import com.arangodb.internal.serde.InternalSerializers; import com.fasterxml.jackson.databind.annotation.JsonSerialize; import java.util.Arrays; diff --git a/src/main/java/com/arangodb/serde/JacksonSerde.java b/src/main/java/com/arangodb/serde/JacksonSerde.java index 122601dcf..99256a397 100644 --- a/src/main/java/com/arangodb/serde/JacksonSerde.java +++ b/src/main/java/com/arangodb/serde/JacksonSerde.java @@ -1,5 +1,7 @@ package com.arangodb.serde; +import com.arangodb.internal.serde.JacksonSerdeImpl; +import com.arangodb.internal.serde.MapperProvider; import com.fasterxml.jackson.databind.ObjectMapper; import java.util.function.Consumer; diff --git a/src/main/java/com/arangodb/serde/JsonbSerde.java b/src/main/java/com/arangodb/serde/JsonbSerde.java index c6dac0dcc..c8dc61041 100644 --- a/src/main/java/com/arangodb/serde/JsonbSerde.java +++ b/src/main/java/com/arangodb/serde/JsonbSerde.java @@ -1,5 +1,6 @@ package com.arangodb.serde; +import com.arangodb.internal.serde.JsonbSerdeImpl; import jakarta.json.bind.JsonbConfig; /** diff --git a/src/main/java/com/arangodb/util/RawBytes.java b/src/main/java/com/arangodb/util/RawBytes.java index 249713075..202812901 100644 --- a/src/main/java/com/arangodb/util/RawBytes.java +++ b/src/main/java/com/arangodb/util/RawBytes.java @@ -1,5 +1,7 @@ package com.arangodb.util; +import com.arangodb.internal.serde.InternalSerde; + import java.util.Arrays; /** @@ -14,7 +16,7 @@ * - a valid VPack * - a valid JSON UTF-8 encoded string *

- * The driver's {@link com.arangodb.serde.InternalSerde} supports serializing and deserializing to and from + * The driver's {@link InternalSerde} supports serializing and deserializing to and from * {@code RawBytes}. */ public class RawBytes { diff --git a/src/main/java/com/arangodb/util/RawJson.java b/src/main/java/com/arangodb/util/RawJson.java index 8aec5b9a3..89d6e3a4b 100644 --- a/src/main/java/com/arangodb/util/RawJson.java +++ b/src/main/java/com/arangodb/util/RawJson.java @@ -1,5 +1,7 @@ package com.arangodb.util; +import com.arangodb.internal.serde.InternalSerde; + import java.util.Objects; /** @@ -8,7 +10,7 @@ * - in serialization to append a raw JSON node * - in deserialization as target wrapper type for the raw JSON string *

- * The driver's {@link com.arangodb.serde.InternalSerde} supports serializing and deserializing to and from + * The driver's {@link InternalSerde} supports serializing and deserializing to and from * {@code RawJson}. */ public class RawJson { diff --git a/src/test/java/com/arangodb/JwtAuthTest.java b/src/test/java/com/arangodb/JwtAuthTest.java index 71bf4da0e..641d1d433 100644 --- a/src/test/java/com/arangodb/JwtAuthTest.java +++ b/src/test/java/com/arangodb/JwtAuthTest.java @@ -1,6 +1,6 @@ package com.arangodb; -import com.arangodb.serde.InternalSerde; +import com.arangodb.serde.ArangoSerde; import com.arangodb.velocystream.Request; import com.arangodb.velocystream.RequestType; import com.arangodb.velocystream.Response; @@ -82,7 +82,7 @@ private ArangoDB.Builder getBuilder(Protocol protocol) { } private static String getJwt(ArangoDB arangoDB) { - InternalSerde serde = arangoDB.getSerde(); + ArangoSerde serde = arangoDB.getSerde(); Map reqBody = new HashMap<>(); reqBody.put("username", "root"); reqBody.put("password", "test"); diff --git a/src/test/java/com/arangodb/async/JwtAuthTest.java b/src/test/java/com/arangodb/async/JwtAuthTest.java index 13ac28bc6..fd8107a6f 100644 --- a/src/test/java/com/arangodb/async/JwtAuthTest.java +++ b/src/test/java/com/arangodb/async/JwtAuthTest.java @@ -3,7 +3,7 @@ import com.arangodb.ArangoDB; import com.arangodb.ArangoDBException; import com.arangodb.DbName; -import com.arangodb.serde.InternalSerde; +import com.arangodb.serde.ArangoSerde; import com.arangodb.velocystream.Request; import com.arangodb.velocystream.RequestType; import com.arangodb.velocystream.Response; @@ -89,7 +89,7 @@ private ArangoDBAsync.Builder getBuilder() { } private static String getJwt(ArangoDB arangoDB) { - InternalSerde serde = arangoDB.getSerde(); + ArangoSerde serde = arangoDB.getSerde(); Map reqBody = new HashMap<>(); reqBody.put("username", "root"); reqBody.put("password", "test"); diff --git a/src/test/java/com/arangodb/internal/HostHandlerTest.java b/src/test/java/com/arangodb/internal/HostHandlerTest.java index 2aeecec55..73ca918b7 100644 --- a/src/test/java/com/arangodb/internal/HostHandlerTest.java +++ b/src/test/java/com/arangodb/internal/HostHandlerTest.java @@ -23,7 +23,7 @@ import com.arangodb.ArangoDBException; import com.arangodb.ArangoDBMultipleException; import com.arangodb.internal.net.*; -import com.arangodb.serde.InternalSerde; +import com.arangodb.internal.serde.InternalSerde; import org.junit.jupiter.api.Test; import java.util.List; diff --git a/src/test/java/com/arangodb/serde/CustomSerdeTest.java b/src/test/java/com/arangodb/serde/CustomSerdeTest.java index de4301b44..779b3e0e1 100644 --- a/src/test/java/com/arangodb/serde/CustomSerdeTest.java +++ b/src/test/java/com/arangodb/serde/CustomSerdeTest.java @@ -22,6 +22,7 @@ import com.arangodb.*; +import com.arangodb.internal.serde.InternalSerde; import com.arangodb.model.DocumentCreateOptions; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.core.JsonParser; diff --git a/src/test/java/com/arangodb/serde/SerdeTest.java b/src/test/java/com/arangodb/serde/SerdeTest.java index 75c374659..872945ab2 100644 --- a/src/test/java/com/arangodb/serde/SerdeTest.java +++ b/src/test/java/com/arangodb/serde/SerdeTest.java @@ -1,5 +1,7 @@ package com.arangodb.serde; +import com.arangodb.internal.serde.InternalSerde; +import com.arangodb.internal.serde.SerdeUtils; import com.arangodb.util.RawBytes; import com.arangodb.util.RawJson; import com.fasterxml.jackson.databind.JsonNode; From c5fe76ed30726f62c5d03a06f27122073e589912 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Tue, 16 Aug 2022 10:12:51 +0200 Subject: [PATCH 081/254] [DE-327] removed unnecessary generics from vertex and edges collections --- .../com/arangodb/ArangoEdgeCollection.java | 21 +++++++++---------- .../com/arangodb/ArangoVertexCollection.java | 16 +++++++------- .../async/ArangoEdgeCollectionAsync.java | 17 +++++++-------- .../async/ArangoVertexCollectionAsync.java | 17 +++++++-------- .../ArangoEdgeCollectionAsyncImpl.java | 16 +++++++------- .../ArangoVertexCollectionAsyncImpl.java | 16 +++++++------- .../internal/ArangoEdgeCollectionImpl.java | 12 +++++------ .../internal/ArangoVertexCollectionImpl.java | 12 +++++------ 8 files changed, 62 insertions(+), 65 deletions(-) diff --git a/src/main/java/com/arangodb/ArangoEdgeCollection.java b/src/main/java/com/arangodb/ArangoEdgeCollection.java index cd0e58204..829041887 100644 --- a/src/main/java/com/arangodb/ArangoEdgeCollection.java +++ b/src/main/java/com/arangodb/ArangoEdgeCollection.java @@ -30,7 +30,6 @@ * @author Mark Vollmary * @see API Documentation */ -@SuppressWarnings("UnusedReturnValue") public interface ArangoEdgeCollection extends ArangoSerdeAccessor { /** @@ -54,7 +53,7 @@ public interface ArangoEdgeCollection extends ArangoSerdeAccessor { * @return information about the edge * @see API Documentation */ - EdgeEntity insertEdge(T value) ; + EdgeEntity insertEdge(Object value) ; /** * Creates a new edge in the collection @@ -64,7 +63,7 @@ public interface ArangoEdgeCollection extends ArangoSerdeAccessor { * @return information about the edge * @see API Documentation */ - EdgeEntity insertEdge(T value, EdgeCreateOptions options) ; + EdgeEntity insertEdge(Object value, EdgeCreateOptions options) ; /** * Fetches an existing edge @@ -92,23 +91,23 @@ public interface ArangoEdgeCollection extends ArangoSerdeAccessor { * violated * * @param key The key of the edge - * @param The type of the edge-document (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) + * @param value A representation of a single edge (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) * @return information about the edge * @see API Documentation */ - EdgeUpdateEntity replaceEdge(String key, T value) ; + EdgeUpdateEntity replaceEdge(String key, Object value) ; /** * Replaces the edge with key with the one in the body, provided there is such a edge and no precondition is * violated * * @param key The key of the edge - * @param The type of the edge-document (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) + * @param value A representation of a single edge (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) * @param options Additional options, can be null * @return information about the edge * @see API Documentation */ - EdgeUpdateEntity replaceEdge(String key, T value, EdgeReplaceOptions options) ; + EdgeUpdateEntity replaceEdge(String key, Object value, EdgeReplaceOptions options) ; /** * Partially updates the edge identified by document-key. The value must contain a document with the attributes to @@ -116,11 +115,11 @@ public interface ArangoEdgeCollection extends ArangoSerdeAccessor { * do not yet exist, and overwritten in the existing document if they do exist there. * * @param key The key of the edge - * @param The type of the edge-document (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) + * @param value A representation of a single edge (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) * @return information about the edge * @see API Documentation */ - EdgeUpdateEntity updateEdge(String key, T value) ; + EdgeUpdateEntity updateEdge(String key, Object value) ; /** * Partially updates the edge identified by document-key. The value must contain a document with the attributes to @@ -128,12 +127,12 @@ public interface ArangoEdgeCollection extends ArangoSerdeAccessor { * do not yet exist, and overwritten in the existing document if they do exist there. * * @param key The key of the edge - * @param The type of the edge-document (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) + * @param value A representation of a single edge (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) * @param options Additional options, can be null * @return information about the edge * @see API Documentation */ - EdgeUpdateEntity updateEdge(String key, T value, EdgeUpdateOptions options) ; + EdgeUpdateEntity updateEdge(String key, Object value, EdgeUpdateOptions options) ; /** * Removes a edge diff --git a/src/main/java/com/arangodb/ArangoVertexCollection.java b/src/main/java/com/arangodb/ArangoVertexCollection.java index 5faa507b3..163a80a30 100644 --- a/src/main/java/com/arangodb/ArangoVertexCollection.java +++ b/src/main/java/com/arangodb/ArangoVertexCollection.java @@ -62,7 +62,7 @@ public interface ArangoVertexCollection extends ArangoSerdeAccessor { * @return information about the vertex * @see API Documentation */ - VertexEntity insertVertex(T value) ; + VertexEntity insertVertex(Object value) ; /** * Creates a new vertex in the collection @@ -72,7 +72,7 @@ public interface ArangoVertexCollection extends ArangoSerdeAccessor { * @return information about the vertex * @see API Documentation */ - VertexEntity insertVertex(T value, VertexCreateOptions options) ; + VertexEntity insertVertex(Object value, VertexCreateOptions options) ; /** * Retrieves the vertex document with the given {@code key} from the collection. @@ -105,7 +105,7 @@ public interface ArangoVertexCollection extends ArangoSerdeAccessor { * @see API * Documentation */ - VertexUpdateEntity replaceVertex(String key, T value) ; + VertexUpdateEntity replaceVertex(String key, Object value) ; /** * Replaces the vertex with key with the one in the body, provided there is such a vertex and no precondition is @@ -118,7 +118,7 @@ public interface ArangoVertexCollection extends ArangoSerdeAccessor { * @see API * Documentation */ - VertexUpdateEntity replaceVertex(String key, T value, VertexReplaceOptions options) ; + VertexUpdateEntity replaceVertex(String key, Object value, VertexReplaceOptions options) ; /** * Partially updates the vertex identified by document-key. The value must contain a document with the attributes to @@ -126,11 +126,11 @@ public interface ArangoVertexCollection extends ArangoSerdeAccessor { * do not yet exist, and overwritten in the existing document if they do exist there. * * @param key The key of the vertex - * @param The type of the vertex-document (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) + * @param value A representation of a single vertex (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) * @return information about the vertex * @see API Documentation */ - VertexUpdateEntity updateVertex(String key, T value) ; + VertexUpdateEntity updateVertex(String key, Object value) ; /** * Partially updates the vertex identified by document-key. The value must contain a document with the attributes to @@ -138,12 +138,12 @@ public interface ArangoVertexCollection extends ArangoSerdeAccessor { * do not yet exist, and overwritten in the existing document if they do exist there. * * @param key The key of the vertex - * @param The type of the vertex-document (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) + * @param value A representation of a single vertex (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) * @param options Additional options, can be null * @return information about the vertex * @see API Documentation */ - VertexUpdateEntity updateVertex(String key, T value, VertexUpdateOptions options) ; + VertexUpdateEntity updateVertex(String key, Object value, VertexUpdateOptions options) ; /** * Deletes the vertex with the given {@code key} from the collection. diff --git a/src/main/java/com/arangodb/async/ArangoEdgeCollectionAsync.java b/src/main/java/com/arangodb/async/ArangoEdgeCollectionAsync.java index 39a8a3a0d..f9ccdc768 100644 --- a/src/main/java/com/arangodb/async/ArangoEdgeCollectionAsync.java +++ b/src/main/java/com/arangodb/async/ArangoEdgeCollectionAsync.java @@ -33,7 +33,6 @@ * @author Mark Vollmary * @see API Documentation */ -@SuppressWarnings("unused") public interface ArangoEdgeCollectionAsync extends ArangoSerdeAccessor { /** @@ -57,7 +56,7 @@ public interface ArangoEdgeCollectionAsync extends ArangoSerdeAccessor { * @return information about the edge * @see API Documentation */ - CompletableFuture insertEdge(final T value); + CompletableFuture insertEdge(final Object value); /** * Creates a new edge in the collection @@ -67,7 +66,7 @@ public interface ArangoEdgeCollectionAsync extends ArangoSerdeAccessor { * @return information about the edge * @see API Documentation */ - CompletableFuture insertEdge(final T value, final EdgeCreateOptions options); + CompletableFuture insertEdge(final Object value, final EdgeCreateOptions options); /** * Fetches an existing edge @@ -98,7 +97,7 @@ public interface ArangoEdgeCollectionAsync extends ArangoSerdeAccessor { * @return information about the edge * @see API Documentation */ - CompletableFuture replaceEdge(final String key, final T value); + CompletableFuture replaceEdge(final String key, final Object value); /** * Replaces the edge with key with the one in the body, provided there is such a edge and no precondition is @@ -109,9 +108,9 @@ public interface ArangoEdgeCollectionAsync extends ArangoSerdeAccessor { * @return information about the edge * @see API Documentation */ - CompletableFuture replaceEdge( + CompletableFuture replaceEdge( final String key, - final T value, + final Object value, final EdgeReplaceOptions options); /** @@ -123,7 +122,7 @@ CompletableFuture replaceEdge( * @return information about the edge * @see API Documentation */ - CompletableFuture updateEdge(final String key, final T value); + CompletableFuture updateEdge(final String key, final Object value); /** * Partially updates the edge identified by document-key. The value must contain a document with the attributes to @@ -135,9 +134,9 @@ CompletableFuture replaceEdge( * @return information about the edge * @see API Documentation */ - CompletableFuture updateEdge( + CompletableFuture updateEdge( final String key, - final T value, + final Object value, final EdgeUpdateOptions options); /** diff --git a/src/main/java/com/arangodb/async/ArangoVertexCollectionAsync.java b/src/main/java/com/arangodb/async/ArangoVertexCollectionAsync.java index 38eb462cd..50d1dad32 100644 --- a/src/main/java/com/arangodb/async/ArangoVertexCollectionAsync.java +++ b/src/main/java/com/arangodb/async/ArangoVertexCollectionAsync.java @@ -33,7 +33,6 @@ * @author Mark Vollmary * @see API Documentation */ -@SuppressWarnings("unused") public interface ArangoVertexCollectionAsync extends ArangoSerdeAccessor { /** @@ -67,7 +66,7 @@ public interface ArangoVertexCollectionAsync extends ArangoSerdeAccessor { * @return information about the vertex * @see API Documentation */ - CompletableFuture insertVertex(final T value); + CompletableFuture insertVertex(final Object value); /** * Creates a new vertex in the collection @@ -77,7 +76,7 @@ public interface ArangoVertexCollectionAsync extends ArangoSerdeAccessor { * @return information about the vertex * @see API Documentation */ - CompletableFuture insertVertex(final T value, final VertexCreateOptions options); + CompletableFuture insertVertex(final Object value, final VertexCreateOptions options); /** * Fetches an existing vertex @@ -109,7 +108,7 @@ public interface ArangoVertexCollectionAsync extends ArangoSerdeAccessor { * @see API * Documentation */ - CompletableFuture replaceVertex(final String key, final T value); + CompletableFuture replaceVertex(final String key, final Object value); /** * Replaces the vertex with key with the one in the body, provided there is such a vertex and no precondition is @@ -121,9 +120,9 @@ public interface ArangoVertexCollectionAsync extends ArangoSerdeAccessor { * @see API * Documentation */ - CompletableFuture replaceVertex( + CompletableFuture replaceVertex( final String key, - final T value, + final Object value, final VertexReplaceOptions options); /** @@ -135,7 +134,7 @@ CompletableFuture replaceVertex( * @return information about the vertex * @see API Documentation */ - CompletableFuture updateVertex(final String key, final T value); + CompletableFuture updateVertex(final String key, final Object value); /** * Partially updates the vertex identified by document-key. The value must contain a document with the attributes to @@ -147,9 +146,9 @@ CompletableFuture replaceVertex( * @return information about the vertex * @see API Documentation */ - CompletableFuture updateVertex( + CompletableFuture updateVertex( final String key, - final T value, + final Object value, final VertexUpdateOptions options); /** diff --git a/src/main/java/com/arangodb/async/internal/ArangoEdgeCollectionAsyncImpl.java b/src/main/java/com/arangodb/async/internal/ArangoEdgeCollectionAsyncImpl.java index 84b43da97..48f2a9f99 100644 --- a/src/main/java/com/arangodb/async/internal/ArangoEdgeCollectionAsyncImpl.java +++ b/src/main/java/com/arangodb/async/internal/ArangoEdgeCollectionAsyncImpl.java @@ -40,13 +40,13 @@ public class ArangoEdgeCollectionAsyncImpl extends } @Override - public CompletableFuture insertEdge(final T value) { + public CompletableFuture insertEdge(final Object value) { return executor.execute(insertEdgeRequest(value, new EdgeCreateOptions()), insertEdgeResponseDeserializer(value)); } @Override - public CompletableFuture insertEdge(final T value, final EdgeCreateOptions options) { + public CompletableFuture insertEdge(final Object value, final EdgeCreateOptions options) { return executor.execute(insertEdgeRequest(value, options), insertEdgeResponseDeserializer(value)); } @@ -62,29 +62,29 @@ public CompletableFuture getEdge(final String key, final Class type, f } @Override - public CompletableFuture replaceEdge(final String key, final T value) { + public CompletableFuture replaceEdge(final String key, final Object value) { return executor.execute(replaceEdgeRequest(key, value, new EdgeReplaceOptions()), replaceEdgeResponseDeserializer(value)); } @Override - public CompletableFuture replaceEdge( + public CompletableFuture replaceEdge( final String key, - final T value, + final Object value, final EdgeReplaceOptions options) { return executor.execute(replaceEdgeRequest(key, value, options), replaceEdgeResponseDeserializer(value)); } @Override - public CompletableFuture updateEdge(final String key, final T value) { + public CompletableFuture updateEdge(final String key, final Object value) { return executor.execute(updateEdgeRequest(key, value, new EdgeUpdateOptions()), updateEdgeResponseDeserializer(value)); } @Override - public CompletableFuture updateEdge( + public CompletableFuture updateEdge( final String key, - final T value, + final Object value, final EdgeUpdateOptions options) { return executor.execute(updateEdgeRequest(key, value, options), updateEdgeResponseDeserializer(value)); } diff --git a/src/main/java/com/arangodb/async/internal/ArangoVertexCollectionAsyncImpl.java b/src/main/java/com/arangodb/async/internal/ArangoVertexCollectionAsyncImpl.java index 3cadf4eba..9759546d3 100644 --- a/src/main/java/com/arangodb/async/internal/ArangoVertexCollectionAsyncImpl.java +++ b/src/main/java/com/arangodb/async/internal/ArangoVertexCollectionAsyncImpl.java @@ -45,13 +45,13 @@ public CompletableFuture drop() { } @Override - public CompletableFuture insertVertex(final T value) { + public CompletableFuture insertVertex(final Object value) { return executor.execute(insertVertexRequest(value, new VertexCreateOptions()), insertVertexResponseDeserializer(value)); } @Override - public CompletableFuture insertVertex(final T value, final VertexCreateOptions options) { + public CompletableFuture insertVertex(final Object value, final VertexCreateOptions options) { return executor.execute(insertVertexRequest(value, options), insertVertexResponseDeserializer(value)); } @@ -70,29 +70,29 @@ public CompletableFuture getVertex( } @Override - public CompletableFuture replaceVertex(final String key, final T value) { + public CompletableFuture replaceVertex(final String key, final Object value) { return executor.execute(replaceVertexRequest(key, value, new VertexReplaceOptions()), replaceVertexResponseDeserializer(value)); } @Override - public CompletableFuture replaceVertex( + public CompletableFuture replaceVertex( final String key, - final T value, + final Object value, final VertexReplaceOptions options) { return executor.execute(replaceVertexRequest(key, value, options), replaceVertexResponseDeserializer(value)); } @Override - public CompletableFuture updateVertex(final String key, final T value) { + public CompletableFuture updateVertex(final String key, final Object value) { return executor.execute(updateVertexRequest(key, value, new VertexUpdateOptions()), updateVertexResponseDeserializer(value)); } @Override - public CompletableFuture updateVertex( + public CompletableFuture updateVertex( final String key, - final T value, + final Object value, final VertexUpdateOptions options) { return executor.execute(updateVertexRequest(key, value, options), updateVertexResponseDeserializer(value)); } diff --git a/src/main/java/com/arangodb/internal/ArangoEdgeCollectionImpl.java b/src/main/java/com/arangodb/internal/ArangoEdgeCollectionImpl.java index c021dad22..bde8b1804 100644 --- a/src/main/java/com/arangodb/internal/ArangoEdgeCollectionImpl.java +++ b/src/main/java/com/arangodb/internal/ArangoEdgeCollectionImpl.java @@ -42,13 +42,13 @@ protected ArangoEdgeCollectionImpl(final ArangoGraphImpl graph, final String nam } @Override - public EdgeEntity insertEdge(final T value) { + public EdgeEntity insertEdge(final Object value) { return executor.execute(insertEdgeRequest(value, new EdgeCreateOptions()), insertEdgeResponseDeserializer(value)); } @Override - public EdgeEntity insertEdge(final T value, final EdgeCreateOptions options) { + public EdgeEntity insertEdge(final Object value, final EdgeCreateOptions options) { return executor.execute(insertEdgeRequest(value, options), insertEdgeResponseDeserializer(value)); } @@ -78,25 +78,25 @@ public T getEdge(final String key, final Class type, final GraphDocumentR } @Override - public EdgeUpdateEntity replaceEdge(final String key, final T value) { + public EdgeUpdateEntity replaceEdge(final String key, final Object value) { return executor.execute(replaceEdgeRequest(key, value, new EdgeReplaceOptions()), replaceEdgeResponseDeserializer(value)); } @Override - public EdgeUpdateEntity replaceEdge(final String key, final T value, final EdgeReplaceOptions options) + public EdgeUpdateEntity replaceEdge(final String key, final Object value, final EdgeReplaceOptions options) { return executor.execute(replaceEdgeRequest(key, value, options), replaceEdgeResponseDeserializer(value)); } @Override - public EdgeUpdateEntity updateEdge(final String key, final T value) { + public EdgeUpdateEntity updateEdge(final String key, final Object value) { return executor.execute(updateEdgeRequest(key, value, new EdgeUpdateOptions()), updateEdgeResponseDeserializer(value)); } @Override - public EdgeUpdateEntity updateEdge(final String key, final T value, final EdgeUpdateOptions options) + public EdgeUpdateEntity updateEdge(final String key, final Object value, final EdgeUpdateOptions options) { return executor.execute(updateEdgeRequest(key, value, options), updateEdgeResponseDeserializer(value)); } diff --git a/src/main/java/com/arangodb/internal/ArangoVertexCollectionImpl.java b/src/main/java/com/arangodb/internal/ArangoVertexCollectionImpl.java index cd578e14a..676a4f4f5 100644 --- a/src/main/java/com/arangodb/internal/ArangoVertexCollectionImpl.java +++ b/src/main/java/com/arangodb/internal/ArangoVertexCollectionImpl.java @@ -47,13 +47,13 @@ public void drop() { } @Override - public VertexEntity insertVertex(final T value) { + public VertexEntity insertVertex(final Object value) { return executor.execute(insertVertexRequest(value, new VertexCreateOptions()), insertVertexResponseDeserializer(value)); } @Override - public VertexEntity insertVertex(final T value, final VertexCreateOptions options) { + public VertexEntity insertVertex(final Object value, final VertexCreateOptions options) { return executor.execute(insertVertexRequest(value, options), insertVertexResponseDeserializer(value)); } @@ -84,25 +84,25 @@ public T getVertex(final String key, final Class type, final GraphDocumen } @Override - public VertexUpdateEntity replaceVertex(final String key, final T value) { + public VertexUpdateEntity replaceVertex(final String key, final Object value) { return executor.execute(replaceVertexRequest(key, value, new VertexReplaceOptions()), replaceVertexResponseDeserializer(value)); } @Override - public VertexUpdateEntity replaceVertex(final String key, final T value, final VertexReplaceOptions options) + public VertexUpdateEntity replaceVertex(final String key, final Object value, final VertexReplaceOptions options) { return executor.execute(replaceVertexRequest(key, value, options), replaceVertexResponseDeserializer(value)); } @Override - public VertexUpdateEntity updateVertex(final String key, final T value) { + public VertexUpdateEntity updateVertex(final String key, final Object value) { return executor.execute(updateVertexRequest(key, value, new VertexUpdateOptions()), updateVertexResponseDeserializer(value)); } @Override - public VertexUpdateEntity updateVertex(final String key, final T value, final VertexUpdateOptions options) + public VertexUpdateEntity updateVertex(final String key, final Object value, final VertexUpdateOptions options) { return executor.execute(updateVertexRequest(key, value, options), updateVertexResponseDeserializer(value)); } From 27206d28e8b8031e5057c8820248ac038b11d9e0 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Tue, 16 Aug 2022 10:29:11 +0200 Subject: [PATCH 082/254] removed misleading @SuppressWarnings --- src/main/java/com/arangodb/ArangoCollection.java | 1 - src/main/java/com/arangodb/ArangoDB.java | 1 - src/main/java/com/arangodb/ArangoDatabase.java | 1 - src/main/java/com/arangodb/ArangoView.java | 1 - .../java/com/arangodb/async/ArangoCollectionAsync.java | 1 - src/main/java/com/arangodb/async/ArangoDBAsync.java | 3 +-- .../java/com/arangodb/async/ArangoDatabaseAsync.java | 1 - src/main/java/com/arangodb/async/ArangoGraphAsync.java | 1 - src/main/java/com/arangodb/async/ArangoRouteAsync.java | 1 - src/main/java/com/arangodb/async/ArangoViewAsync.java | 1 - src/main/java/com/arangodb/model/ViewCreateOptions.java | 6 ++---- .../model/arangosearch/ArangoSearchCreateOptions.java | 6 ++---- src/test/java/com/arangodb/ArangoCollectionTest.java | 9 ++------- src/test/java/com/arangodb/ArangoSearchTest.java | 2 -- src/test/java/com/arangodb/DocumentTest.java | 2 -- .../java/com/arangodb/async/ArangoCollectionTest.java | 2 -- src/test/java/com/arangodb/async/ArangoSearchTest.java | 1 - .../com/arangodb/async/example/document/TestEntity.java | 1 - .../example/graph/AQLActorsAndMoviesExampleTest.java | 3 --- .../java/com/arangodb/async/example/graph/Circle.java | 1 - .../com/arangodb/async/example/graph/CircleEdge.java | 1 - .../example/graph/ShortestPathInAQLExampleTest.java | 3 +-- .../AqlQueryWithSpecialReturnTypesExampleTest.java | 2 -- .../example/document/GetDocumentExampleTest.java | 1 - .../java/com/arangodb/example/document/TestEntity.java | 1 - src/test/java/com/arangodb/example/graph/Circle.java | 1 - src/test/java/com/arangodb/example/graph/CircleEdge.java | 1 - .../example/graph/ShortestPathInAQLExampleTest.java | 3 +-- 28 files changed, 9 insertions(+), 49 deletions(-) diff --git a/src/main/java/com/arangodb/ArangoCollection.java b/src/main/java/com/arangodb/ArangoCollection.java index 9c6117989..a6a34184c 100644 --- a/src/main/java/com/arangodb/ArangoCollection.java +++ b/src/main/java/com/arangodb/ArangoCollection.java @@ -34,7 +34,6 @@ * @see Collection API Documentation * @see Documents API Documentation */ -@SuppressWarnings("UnusedReturnValue") public interface ArangoCollection extends ArangoSerdeAccessor { /** diff --git a/src/main/java/com/arangodb/ArangoDB.java b/src/main/java/com/arangodb/ArangoDB.java index 1a2d27c5e..b8e69ee5b 100644 --- a/src/main/java/com/arangodb/ArangoDB.java +++ b/src/main/java/com/arangodb/ArangoDB.java @@ -67,7 +67,6 @@ * @author Mark Vollmary * @author Michele Rastelli */ -@SuppressWarnings("UnusedReturnValue") public interface ArangoDB extends ArangoSerdeAccessor { /** diff --git a/src/main/java/com/arangodb/ArangoDatabase.java b/src/main/java/com/arangodb/ArangoDatabase.java index 82db21d82..59a893188 100644 --- a/src/main/java/com/arangodb/ArangoDatabase.java +++ b/src/main/java/com/arangodb/ArangoDatabase.java @@ -37,7 +37,6 @@ * @see Databases API Documentation * @see Query API Documentation */ -@SuppressWarnings("UnusedReturnValue") public interface ArangoDatabase extends ArangoSerdeAccessor { /** diff --git a/src/main/java/com/arangodb/ArangoView.java b/src/main/java/com/arangodb/ArangoView.java index 411d462cf..22f287ad3 100644 --- a/src/main/java/com/arangodb/ArangoView.java +++ b/src/main/java/com/arangodb/ArangoView.java @@ -29,7 +29,6 @@ * @see View API Documentation * @since ArangoDB 3.4.0 */ -@SuppressWarnings("UnusedReturnValue") public interface ArangoView extends ArangoSerdeAccessor { /** diff --git a/src/main/java/com/arangodb/async/ArangoCollectionAsync.java b/src/main/java/com/arangodb/async/ArangoCollectionAsync.java index 80903d627..84b9c0ee3 100644 --- a/src/main/java/com/arangodb/async/ArangoCollectionAsync.java +++ b/src/main/java/com/arangodb/async/ArangoCollectionAsync.java @@ -35,7 +35,6 @@ * @see Collection API Documentation * @see Documents API Documentation */ -@SuppressWarnings("unused") public interface ArangoCollectionAsync extends ArangoSerdeAccessor { /** diff --git a/src/main/java/com/arangodb/async/ArangoDBAsync.java b/src/main/java/com/arangodb/async/ArangoDBAsync.java index 7ebb35032..cc7926626 100644 --- a/src/main/java/com/arangodb/async/ArangoDBAsync.java +++ b/src/main/java/com/arangodb/async/ArangoDBAsync.java @@ -299,8 +299,7 @@ public interface ArangoDBAsync extends ArangoSerdeAccessor { * * @author Mark Vollmary */ - @SuppressWarnings("unused") - class Builder extends InternalArangoDBBuilder { + class Builder extends InternalArangoDBBuilder { private static final Logger logger = LoggerFactory.getLogger(Builder.class); diff --git a/src/main/java/com/arangodb/async/ArangoDatabaseAsync.java b/src/main/java/com/arangodb/async/ArangoDatabaseAsync.java index 2e5ffba1f..4b2b63c6b 100644 --- a/src/main/java/com/arangodb/async/ArangoDatabaseAsync.java +++ b/src/main/java/com/arangodb/async/ArangoDatabaseAsync.java @@ -40,7 +40,6 @@ * @see Databases API Documentation * @see Query API Documentation */ -@SuppressWarnings("unused") public interface ArangoDatabaseAsync extends ArangoSerdeAccessor { /** diff --git a/src/main/java/com/arangodb/async/ArangoGraphAsync.java b/src/main/java/com/arangodb/async/ArangoGraphAsync.java index 0fae79e0b..f7214d8d7 100644 --- a/src/main/java/com/arangodb/async/ArangoGraphAsync.java +++ b/src/main/java/com/arangodb/async/ArangoGraphAsync.java @@ -35,7 +35,6 @@ * @author Mark Vollmary * @see API Documentation */ -@SuppressWarnings("unused") public interface ArangoGraphAsync extends ArangoSerdeAccessor { /** diff --git a/src/main/java/com/arangodb/async/ArangoRouteAsync.java b/src/main/java/com/arangodb/async/ArangoRouteAsync.java index e79d9ca13..f47a0c5d7 100644 --- a/src/main/java/com/arangodb/async/ArangoRouteAsync.java +++ b/src/main/java/com/arangodb/async/ArangoRouteAsync.java @@ -30,7 +30,6 @@ * * @author Mark Vollmary */ -@SuppressWarnings("unused") public interface ArangoRouteAsync extends ArangoSerdeAccessor { /** diff --git a/src/main/java/com/arangodb/async/ArangoViewAsync.java b/src/main/java/com/arangodb/async/ArangoViewAsync.java index c06289cee..b1de2e10a 100644 --- a/src/main/java/com/arangodb/async/ArangoViewAsync.java +++ b/src/main/java/com/arangodb/async/ArangoViewAsync.java @@ -32,7 +32,6 @@ * @see View API Documentation * @since ArangoDB 3.4.0 */ -@SuppressWarnings("unused") public interface ArangoViewAsync extends ArangoSerdeAccessor { /** diff --git a/src/main/java/com/arangodb/model/ViewCreateOptions.java b/src/main/java/com/arangodb/model/ViewCreateOptions.java index 8c11dd343..69e329963 100644 --- a/src/main/java/com/arangodb/model/ViewCreateOptions.java +++ b/src/main/java/com/arangodb/model/ViewCreateOptions.java @@ -27,10 +27,8 @@ */ public final class ViewCreateOptions { - @SuppressWarnings("unused") - private String name; - @SuppressWarnings("unused") - private ViewType type; + private String name; + private ViewType type; public ViewCreateOptions() { super(); diff --git a/src/main/java/com/arangodb/model/arangosearch/ArangoSearchCreateOptions.java b/src/main/java/com/arangodb/model/arangosearch/ArangoSearchCreateOptions.java index 57c8a21ec..871b334e8 100644 --- a/src/main/java/com/arangodb/model/arangosearch/ArangoSearchCreateOptions.java +++ b/src/main/java/com/arangodb/model/arangosearch/ArangoSearchCreateOptions.java @@ -33,10 +33,8 @@ */ public final class ArangoSearchCreateOptions { - @SuppressWarnings("unused") - private String name; - @SuppressWarnings("unused") - private final ViewType type; + private String name; + private final ViewType type; private Long consolidationIntervalMsec; private Long commitIntervalMsec; private Long cleanupIntervalStep; diff --git a/src/test/java/com/arangodb/ArangoCollectionTest.java b/src/test/java/com/arangodb/ArangoCollectionTest.java index 64cf485bc..2be47beda 100644 --- a/src/test/java/com/arangodb/ArangoCollectionTest.java +++ b/src/test/java/com/arangodb/ArangoCollectionTest.java @@ -166,7 +166,6 @@ void insertDocument(ArangoCollection collection) { @ParameterizedTest(name = "{index}") @MethodSource("cols") @Disabled - @SuppressWarnings("unchecked") void insertDocumentWithArrayWithNullValues(ArangoCollection collection) { List arr = Arrays.asList("a", null); BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); @@ -779,8 +778,7 @@ void updateDocumentKeepNullFalse(ArangoCollection collection) { } public static class TestUpdateEntity { - @SuppressWarnings("unused") - private String a, b; + private String a, b; public String getA() { return a; @@ -792,8 +790,7 @@ public String getB() { } public static class TestUpdateEntitySerializeNullFalse { - @SuppressWarnings("unused") - private String a, b; + private String a, b; @JsonInclude(JsonInclude.Include.NON_NULL) public String getA() { @@ -845,7 +842,6 @@ void updateDocumentSerializeNullFalse(ArangoCollection collection) { assertThat(readResult.getAttribute("b")).isEqualTo("foo"); } - @SuppressWarnings("unchecked") @ParameterizedTest(name = "{index}") @MethodSource("cols") void updateDocumentMergeObjectsTrue(ArangoCollection collection) { @@ -872,7 +868,6 @@ void updateDocumentMergeObjectsTrue(ArangoCollection collection) { assertThat(aMap).containsKeys("a", "b"); } - @SuppressWarnings("unchecked") @ParameterizedTest(name = "{index}") @MethodSource("cols") void updateDocumentMergeObjectsFalse(ArangoCollection collection) { diff --git a/src/test/java/com/arangodb/ArangoSearchTest.java b/src/test/java/com/arangodb/ArangoSearchTest.java index 59242b3a7..0c1cd86c8 100644 --- a/src/test/java/com/arangodb/ArangoSearchTest.java +++ b/src/test/java/com/arangodb/ArangoSearchTest.java @@ -267,7 +267,6 @@ private void createGetAndDeleteTypedAnalyzer(ArangoDatabase db, SearchAnalyzer a assertThat(gotAnalyzer).isEqualTo(analyzer); // getAnalyzers - @SuppressWarnings("OptionalGetWithoutIsPresent") SearchAnalyzer foundAnalyzer = db.getSearchAnalyzers().stream().filter(it -> it.getName().equals(fullyQualifiedName)) .findFirst().get(); assertThat(foundAnalyzer).isEqualTo(analyzer); @@ -285,7 +284,6 @@ private void createGetAndDeleteTypedAnalyzer(ArangoDatabase db, SearchAnalyzer a assertThat(e.getErrorNum()).isEqualTo(1202); } - @SuppressWarnings("unchecked") @ParameterizedTest(name = "{index}") @MethodSource("dbs") void identityAnalyzerTyped(ArangoDatabase db) { diff --git a/src/test/java/com/arangodb/DocumentTest.java b/src/test/java/com/arangodb/DocumentTest.java index a921a213d..3293316c5 100644 --- a/src/test/java/com/arangodb/DocumentTest.java +++ b/src/test/java/com/arangodb/DocumentTest.java @@ -55,7 +55,6 @@ static void init() { initCollections(COLLECTION_NAME); } - @SuppressWarnings("unchecked") @ParameterizedTest(name = "{index}") @MethodSource("cols") void insertAsJson(ArangoCollection collection) { @@ -93,7 +92,6 @@ void insertAsJson(ArangoCollection collection) { assertThat(artist.toString()).isEqualTo("PREGARDIEN/RHEINISCHE KANTOREI/DAS"); } - @SuppressWarnings("unchecked") @ParameterizedTest(name = "{index}") @MethodSource("cols") void insertAsBaseDocument(ArangoCollection collection) { diff --git a/src/test/java/com/arangodb/async/ArangoCollectionTest.java b/src/test/java/com/arangodb/async/ArangoCollectionTest.java index 1024dc609..793e03e3c 100644 --- a/src/test/java/com/arangodb/async/ArangoCollectionTest.java +++ b/src/test/java/com/arangodb/async/ArangoCollectionTest.java @@ -565,7 +565,6 @@ void updateDocumentKeepNullFalse() throws InterruptedException, ExecutionExcepti assertThat(readResult.getProperties().keySet()).doesNotContain("a"); } - @SuppressWarnings("unchecked") @Test void updateDocumentMergeObjectsTrue() throws InterruptedException, ExecutionException { final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); @@ -597,7 +596,6 @@ void updateDocumentMergeObjectsTrue() throws InterruptedException, ExecutionExce assertThat(aMap).containsKey("b"); } - @SuppressWarnings("unchecked") @Test void updateDocumentMergeObjectsFalse() throws InterruptedException, ExecutionException { final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); diff --git a/src/test/java/com/arangodb/async/ArangoSearchTest.java b/src/test/java/com/arangodb/async/ArangoSearchTest.java index 5cf5aedfe..9c5418cd5 100644 --- a/src/test/java/com/arangodb/async/ArangoSearchTest.java +++ b/src/test/java/com/arangodb/async/ArangoSearchTest.java @@ -239,7 +239,6 @@ private void createGetAndDeleteTypedAnalyzer(SearchAnalyzer analyzer) throws Exe assertThat(gotAnalyzer).isEqualTo(analyzer); // getAnalyzers - @SuppressWarnings("OptionalGetWithoutIsPresent") SearchAnalyzer foundAnalyzer = db.getSearchAnalyzers().get().stream().filter(it -> it.getName().equals(fullyQualifiedName)) .findFirst().get(); assertThat(foundAnalyzer).isEqualTo(analyzer); diff --git a/src/test/java/com/arangodb/async/example/document/TestEntity.java b/src/test/java/com/arangodb/async/example/document/TestEntity.java index d33126814..2ef89c19f 100644 --- a/src/test/java/com/arangodb/async/example/document/TestEntity.java +++ b/src/test/java/com/arangodb/async/example/document/TestEntity.java @@ -23,7 +23,6 @@ /** * @author Mark Vollmary */ -@SuppressWarnings({"WeakerAccess", "unused"}) public class TestEntity { private String foo; diff --git a/src/test/java/com/arangodb/async/example/graph/AQLActorsAndMoviesExampleTest.java b/src/test/java/com/arangodb/async/example/graph/AQLActorsAndMoviesExampleTest.java index be78c92a1..2f0de8a0b 100644 --- a/src/test/java/com/arangodb/async/example/graph/AQLActorsAndMoviesExampleTest.java +++ b/src/test/java/com/arangodb/async/example/graph/AQLActorsAndMoviesExampleTest.java @@ -48,7 +48,6 @@ * @see AQL Example Queries on an * Actors and Movies Database */ -@SuppressWarnings("JavaDoc") class AQLActorsAndMoviesExampleTest { private static final DbName TEST_DB = DbName.of("actors_movies_test_db"); @@ -481,7 +480,6 @@ void theNumberOfMoviesActedInBetween2005and2010byActor() throws InterruptedExcep new Actor("actors/TomC", 1), new Actor("actors/TomH", 2), new Actor("actors/VictorG", 1))).get(); } - @SuppressWarnings("WeakerAccess") public static class Actor { private String actor; private Integer movies; @@ -529,7 +527,6 @@ public boolean equals(final Object obj) { } - @SuppressWarnings("WeakerAccess") public static class Movie { private final String movie; private final Integer actors; diff --git a/src/test/java/com/arangodb/async/example/graph/Circle.java b/src/test/java/com/arangodb/async/example/graph/Circle.java index 4eeea5ff5..4df7cfcc1 100644 --- a/src/test/java/com/arangodb/async/example/graph/Circle.java +++ b/src/test/java/com/arangodb/async/example/graph/Circle.java @@ -27,7 +27,6 @@ /** * @author a-brandt */ -@SuppressWarnings({"WeakerAccess", "unused"}) class Circle { @Id diff --git a/src/test/java/com/arangodb/async/example/graph/CircleEdge.java b/src/test/java/com/arangodb/async/example/graph/CircleEdge.java index b3b0ca62a..aa89d8d35 100644 --- a/src/test/java/com/arangodb/async/example/graph/CircleEdge.java +++ b/src/test/java/com/arangodb/async/example/graph/CircleEdge.java @@ -25,7 +25,6 @@ /** * @author a-brandt */ -@SuppressWarnings({"WeakerAccess", "unused"}) class CircleEdge { @Id diff --git a/src/test/java/com/arangodb/async/example/graph/ShortestPathInAQLExampleTest.java b/src/test/java/com/arangodb/async/example/graph/ShortestPathInAQLExampleTest.java index 4d1edf9b4..306dfddae 100644 --- a/src/test/java/com/arangodb/async/example/graph/ShortestPathInAQLExampleTest.java +++ b/src/test/java/com/arangodb/async/example/graph/ShortestPathInAQLExampleTest.java @@ -77,8 +77,7 @@ private Collection toVertexCollection(final ArangoCursorAsync curs return result; } - @SuppressWarnings({"WeakerAccess", "unused"}) - public static class Pair { + public static class Pair { private String vertex; private String edge; diff --git a/src/test/java/com/arangodb/example/document/AqlQueryWithSpecialReturnTypesExampleTest.java b/src/test/java/com/arangodb/example/document/AqlQueryWithSpecialReturnTypesExampleTest.java index c55ab5ed0..7dde1be39 100644 --- a/src/test/java/com/arangodb/example/document/AqlQueryWithSpecialReturnTypesExampleTest.java +++ b/src/test/java/com/arangodb/example/document/AqlQueryWithSpecialReturnTypesExampleTest.java @@ -93,7 +93,6 @@ void aqlWithLimitQueryAsJsonArray() { } @Test - @SuppressWarnings("rawtypes") void aqlWithLimitQueryAsMap() { final String query = "FOR t IN " + COLLECTION_NAME + " FILTER t.age >= 20 && t.age < 30 && t.gender == @gender RETURN t"; @@ -113,7 +112,6 @@ void aqlWithLimitQueryAsMap() { } @Test - @SuppressWarnings("rawtypes") void aqlWithLimitQueryAsList() { final String query = "FOR t IN " + COLLECTION_NAME + " FILTER t.age >= 20 && t.age < 30 && t.gender == @gender RETURN [t.name, t.gender, t.age]"; diff --git a/src/test/java/com/arangodb/example/document/GetDocumentExampleTest.java b/src/test/java/com/arangodb/example/document/GetDocumentExampleTest.java index 26fee1747..ed8ce26a0 100644 --- a/src/test/java/com/arangodb/example/document/GetDocumentExampleTest.java +++ b/src/test/java/com/arangodb/example/document/GetDocumentExampleTest.java @@ -64,7 +64,6 @@ void getAsBaseDocument() { assertThat(String.valueOf(doc.getAttribute("foo"))).isEqualTo("bar"); } - @SuppressWarnings("unchecked") @Test void getAsMap() { final Map doc = collection.getDocument(key, Map.class); diff --git a/src/test/java/com/arangodb/example/document/TestEntity.java b/src/test/java/com/arangodb/example/document/TestEntity.java index a5c9aaf31..6e42a3aad 100644 --- a/src/test/java/com/arangodb/example/document/TestEntity.java +++ b/src/test/java/com/arangodb/example/document/TestEntity.java @@ -23,7 +23,6 @@ /** * @author Mark Vollmary */ -@SuppressWarnings({"WeakerAccess", "unused"}) public class TestEntity { private String foo; diff --git a/src/test/java/com/arangodb/example/graph/Circle.java b/src/test/java/com/arangodb/example/graph/Circle.java index c603983c9..8e1a00431 100644 --- a/src/test/java/com/arangodb/example/graph/Circle.java +++ b/src/test/java/com/arangodb/example/graph/Circle.java @@ -27,7 +27,6 @@ /** * @author a-brandt */ -@SuppressWarnings("unused") class Circle { @Id diff --git a/src/test/java/com/arangodb/example/graph/CircleEdge.java b/src/test/java/com/arangodb/example/graph/CircleEdge.java index 6ba211c56..e55e3bc1b 100644 --- a/src/test/java/com/arangodb/example/graph/CircleEdge.java +++ b/src/test/java/com/arangodb/example/graph/CircleEdge.java @@ -25,7 +25,6 @@ /** * @author a-brandt */ -@SuppressWarnings("unused") class CircleEdge { @Id diff --git a/src/test/java/com/arangodb/example/graph/ShortestPathInAQLExampleTest.java b/src/test/java/com/arangodb/example/graph/ShortestPathInAQLExampleTest.java index 7eb87fcb3..f49979951 100644 --- a/src/test/java/com/arangodb/example/graph/ShortestPathInAQLExampleTest.java +++ b/src/test/java/com/arangodb/example/graph/ShortestPathInAQLExampleTest.java @@ -38,8 +38,7 @@ */ class ShortestPathInAQLExampleTest extends BaseGraphTest { - @SuppressWarnings({"WeakerAccess", "unused"}) - public static class Pair { + public static class Pair { private String vertex; private String edge; From 5bad5e8e9dcf4d7f454f803b2cf7768a296547e0 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Tue, 16 Aug 2022 10:59:08 +0200 Subject: [PATCH 083/254] added method and parameter to serde annotations targets --- src/main/java/com/arangodb/entity/From.java | 3 +- src/main/java/com/arangodb/entity/Id.java | 3 +- src/main/java/com/arangodb/entity/Key.java | 3 +- src/main/java/com/arangodb/entity/Rev.java | 3 +- src/main/java/com/arangodb/entity/To.java | 3 +- .../com/arangodb/ArangoCollectionTest.java | 50 ++++++++++++++++++- 6 files changed, 53 insertions(+), 12 deletions(-) diff --git a/src/main/java/com/arangodb/entity/From.java b/src/main/java/com/arangodb/entity/From.java index 4d3b63ca0..0ded39c1e 100644 --- a/src/main/java/com/arangodb/entity/From.java +++ b/src/main/java/com/arangodb/entity/From.java @@ -15,8 +15,7 @@ /** * @author Michele Rastelli */ -// TODO: in v7 add targets ElementType.METHOD and ElementType.PARAMETER -@Target(ElementType.FIELD) +@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER}) @Retention(RetentionPolicy.RUNTIME) @JacksonAnnotationsInside @JsonProperty(DocumentFields.FROM) diff --git a/src/main/java/com/arangodb/entity/Id.java b/src/main/java/com/arangodb/entity/Id.java index 5ebd39d46..2e3cd61b9 100644 --- a/src/main/java/com/arangodb/entity/Id.java +++ b/src/main/java/com/arangodb/entity/Id.java @@ -15,8 +15,7 @@ /** * @author Michele Rastelli */ -// TODO: in v7 add targets ElementType.METHOD and ElementType.PARAMETER -@Target(ElementType.FIELD) +@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER}) @Retention(RetentionPolicy.RUNTIME) @JacksonAnnotationsInside @JsonProperty(DocumentFields.ID) diff --git a/src/main/java/com/arangodb/entity/Key.java b/src/main/java/com/arangodb/entity/Key.java index 2afc552a3..8a5fb15ce 100644 --- a/src/main/java/com/arangodb/entity/Key.java +++ b/src/main/java/com/arangodb/entity/Key.java @@ -15,8 +15,7 @@ /** * @author Michele Rastelli */ -// TODO: in v7 add targets ElementType.METHOD and ElementType.PARAMETER -@Target(ElementType.FIELD) +@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER}) @Retention(RetentionPolicy.RUNTIME) @JacksonAnnotationsInside @JsonProperty(DocumentFields.KEY) diff --git a/src/main/java/com/arangodb/entity/Rev.java b/src/main/java/com/arangodb/entity/Rev.java index 08dfa5c22..241e0ed8a 100644 --- a/src/main/java/com/arangodb/entity/Rev.java +++ b/src/main/java/com/arangodb/entity/Rev.java @@ -15,8 +15,7 @@ /** * @author Michele Rastelli */ -// TODO: in v7 add targets ElementType.METHOD and ElementType.PARAMETER -@Target(ElementType.FIELD) +@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER}) @Retention(RetentionPolicy.RUNTIME) @JacksonAnnotationsInside @JsonProperty(DocumentFields.REV) diff --git a/src/main/java/com/arangodb/entity/To.java b/src/main/java/com/arangodb/entity/To.java index deb60769c..4ebb0006c 100644 --- a/src/main/java/com/arangodb/entity/To.java +++ b/src/main/java/com/arangodb/entity/To.java @@ -15,8 +15,7 @@ /** * @author Michele Rastelli */ -// TODO: in v7 add targets ElementType.METHOD and ElementType.PARAMETER -@Target(ElementType.FIELD) +@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER}) @Retention(RetentionPolicy.RUNTIME) @JacksonAnnotationsInside @JsonProperty(DocumentFields.TO) diff --git a/src/test/java/com/arangodb/ArangoCollectionTest.java b/src/test/java/com/arangodb/ArangoCollectionTest.java index 2be47beda..26904f3af 100644 --- a/src/test/java/com/arangodb/ArangoCollectionTest.java +++ b/src/test/java/com/arangodb/ArangoCollectionTest.java @@ -35,6 +35,7 @@ import org.junit.jupiter.api.Disabled; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.EnumSource; import org.junit.jupiter.params.provider.MethodSource; import java.util.ArrayList; @@ -778,7 +779,7 @@ void updateDocumentKeepNullFalse(ArangoCollection collection) { } public static class TestUpdateEntity { - private String a, b; + private String a, b; public String getA() { return a; @@ -790,7 +791,7 @@ public String getB() { } public static class TestUpdateEntitySerializeNullFalse { - private String a, b; + private String a, b; @JsonInclude(JsonInclude.Include.NON_NULL) public String getA() { @@ -2827,4 +2828,49 @@ void getPermissions(ArangoCollection collection) { assertThat(collection.getPermissions("root")).isEqualTo(Permissions.RW); } + public static class AnnotatedEntity { + + private final String key; + private String id; + private String rev; + + public AnnotatedEntity(@Key String key) { + this.key = key; + } + + public String getKey() { + return key; + } + + public String getId() { + return id; + } + + @Id + public void setId(String id) { + this.id = id; + } + + public String getRev() { + return rev; + } + + @Rev + public void setRev(String rev) { + this.rev = rev; + } + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void annotationsInParamsAndMethods(ArangoCollection collection) { + assumeTrue(collection.getSerde().getUserSerde() instanceof JacksonSerde, "JacksonSerde only"); + AnnotatedEntity entity = new AnnotatedEntity(UUID.randomUUID().toString()); + AnnotatedEntity doc = collection.insertDocument(entity, new DocumentCreateOptions().returnNew(true)).getNew(); + assertThat(doc).isNotNull(); + assertThat(doc.getKey()).isEqualTo(entity.getKey()); + assertThat(doc.getId()).isNotNull(); + assertThat(doc.getRev()).isNotNull(); + } + } From 2c43ee8298877ff0a06058c77487df13ce7f6983 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Tue, 16 Aug 2022 11:02:43 +0200 Subject: [PATCH 084/254] re-enabled tests for documents with null values --- src/test/java/com/arangodb/ArangoCollectionTest.java | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/test/java/com/arangodb/ArangoCollectionTest.java b/src/test/java/com/arangodb/ArangoCollectionTest.java index 26904f3af..f0d603be0 100644 --- a/src/test/java/com/arangodb/ArangoCollectionTest.java +++ b/src/test/java/com/arangodb/ArangoCollectionTest.java @@ -163,10 +163,8 @@ void insertDocument(ArangoCollection collection) { assertThat(doc.getId()).isEqualTo(COLLECTION_NAME + "/" + doc.getKey()); } - // FIXME: v7 @ParameterizedTest(name = "{index}") @MethodSource("cols") - @Disabled void insertDocumentWithArrayWithNullValues(ArangoCollection collection) { List arr = Arrays.asList("a", null); BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); @@ -182,10 +180,8 @@ void insertDocumentWithArrayWithNullValues(ArangoCollection collection) { assertThat((List) insertedDoc.getNew().getAttribute("arr")).containsAll(Arrays.asList("a", null)); } - // FIXME: v7 @ParameterizedTest(name = "{index}") @MethodSource("cols") - @Disabled void insertDocumentWithNullValues(ArangoCollection collection) { BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); doc.addAttribute("null", null); From 0e18437607a963319144d81d70f9a5382dd0eb33 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Tue, 16 Aug 2022 11:03:13 +0200 Subject: [PATCH 085/254] re-enabled assertions for createCollectionWithSmartJoinAttributeWrong test --- src/test/java/com/arangodb/ArangoDatabaseTest.java | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/test/java/com/arangodb/ArangoDatabaseTest.java b/src/test/java/com/arangodb/ArangoDatabaseTest.java index 6af8f64e1..9f6642441 100644 --- a/src/test/java/com/arangodb/ArangoDatabaseTest.java +++ b/src/test/java/com/arangodb/ArangoDatabaseTest.java @@ -209,10 +209,7 @@ void createCollectionWithSmartJoinAttributeWrong(ArangoDatabase db) { db.createCollection(name, new CollectionCreateOptions().smartJoinAttribute("test123")); } catch (ArangoDBException e) { assertThat(e.getErrorNum()).isEqualTo(4006); - // TODO: - // at the moment older server versions reply with response code 500, which is a misbehavior - // when the fix has been backported to all the supported db versions uncomment the following: - // assertThat(e.getResponseCode()).isEqualTo(400)); + assertThat(e.getResponseCode()).isEqualTo(400); } } @@ -843,7 +840,7 @@ void queryWithRawBindVars(ArangoDatabase db) { bindVars.put("foo", RawJson.of("\"fooValue\"")); bindVars.put("bar", RawBytes.of(db.getSerde().serializeUserData(11))); - final JsonNode res = db.query("RETURN {foo: @foo, bar: @bar}", bindVars, null,JsonNode.class).next(); + final JsonNode res = db.query("RETURN {foo: @foo, bar: @bar}", bindVars, null, JsonNode.class).next(); assertThat(res.get("foo").textValue()).isEqualTo("fooValue"); assertThat(res.get("bar").intValue()).isEqualTo(11); From eac5ea7cc13859f125acfecfbe0f25c754ab70d1 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Tue, 16 Aug 2022 11:11:20 +0200 Subject: [PATCH 086/254] re-enabled queryWithTTL test --- .../java/com/arangodb/ArangoDatabaseTest.java | 63 +++++++++---------- 1 file changed, 28 insertions(+), 35 deletions(-) diff --git a/src/test/java/com/arangodb/ArangoDatabaseTest.java b/src/test/java/com/arangodb/ArangoDatabaseTest.java index 9f6642441..2f8aa24de 100644 --- a/src/test/java/com/arangodb/ArangoDatabaseTest.java +++ b/src/test/java/com/arangodb/ArangoDatabaseTest.java @@ -630,41 +630,34 @@ void queryIterateWithBatchSize(ArangoDatabase db) { assertThat(i.get()).isGreaterThanOrEqualTo(10); } - // FIXME -// /** -// * ignored. takes to long -// */ -// @Test -// @Ignore -// void queryWithTTL() throws InterruptedException { -// // set TTL to 1 seconds and get the second batch after 2 seconds! -// final int ttl = 1; -// final int wait = 2; -// try { -// db.createCollection(COLLECTION_NAME, null); -// for (int i = 0; i < 10; i++) { -// db.collection(COLLECTION_NAME).insertDocument(new BaseDocument(), null); -// } -// -// final ArangoCursor cursor = db -// .query("for i in db_test return i._id", null, new AqlQueryOptions().batchSize(5).ttl(ttl), -// String.class); -// -// assertThat(cursor).isNotNull(); -// -// for (int i = 0; i < 10; i++, cursor.next()) { -// assertThat(cursor.hasNext()).isEqualTo(true)); -// if (i == 1) { -// Thread.sleep(wait * 1000); -// } -// } -// fail("this should fail"); -// } catch (final ArangoDBException ex) { -// assertThat(ex.getMessage()).isEqualTo("Response: 404, Error: 1600 - cursor not found")); -// } finally { -// db.collection(COLLECTION_NAME).drop(); -// } -// } + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void queryWithTTL(ArangoDatabase db) throws InterruptedException { + // set TTL to 1 seconds and get the second batch after 2 seconds! + final int ttl = 1; + final int wait = 2; + for (int i = 0; i < 10; i++) { + db.collection(CNAME1).insertDocument(new BaseDocument(), null); + } + + final ArangoCursor cursor = db + .query("for i in " + CNAME1 + " return i._id", null, new AqlQueryOptions().batchSize(5).ttl(ttl), + String.class); + + assertThat((Iterable) cursor).isNotNull(); + + try { + for (int i = 0; i < 10; i++, cursor.next()) { + assertThat(cursor.hasNext()).isTrue(); + if (i == 1) { + Thread.sleep(wait * 1000); + } + } + fail("this should fail"); + } catch (final ArangoDBException ex) { + assertThat(ex.getMessage()).isEqualTo("Response: 404, Error: 1600 - cursor not found"); + } + } @ParameterizedTest(name = "{index}") @MethodSource("dbs") From fccacdbf01eddc02a95001336632e34c7f252217 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Tue, 16 Aug 2022 11:12:58 +0200 Subject: [PATCH 087/254] re-enabled ArangoEdgeCollectionTest test assertions --- src/test/java/com/arangodb/ArangoEdgeCollectionTest.java | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/test/java/com/arangodb/ArangoEdgeCollectionTest.java b/src/test/java/com/arangodb/ArangoEdgeCollectionTest.java index c68e4a38f..d99bf927b 100644 --- a/src/test/java/com/arangodb/ArangoEdgeCollectionTest.java +++ b/src/test/java/com/arangodb/ArangoEdgeCollectionTest.java @@ -253,8 +253,7 @@ void replaceEdgeIfMatchFail(ArangoVertexCollection vertices, ArangoEdgeCollectio Throwable thrown = catchThrowable(() -> edges.replaceEdge(createResult.getKey(), doc, options)); assertThat(thrown).isInstanceOf(ArangoDBException.class); ArangoDBException e = (ArangoDBException) thrown; - // FIXME: atm the server replies 409 for HTTP_JSON or HTTP_VPACK - // assertThat(e.getResponseCode()).isEqualTo(412)); + assertThat(e.getResponseCode()).isEqualTo(412); assertThat(e.getErrorNum()).isEqualTo(1200); } @@ -343,8 +342,7 @@ void updateEdgeIfMatchFail(ArangoVertexCollection vertices, ArangoEdgeCollection Throwable thrown = catchThrowable(() -> edges.updateEdge(createResult.getKey(), doc, options)); assertThat(thrown).isInstanceOf(ArangoDBException.class); ArangoDBException e = (ArangoDBException) thrown; - // FIXME: atm the server replies 409 for HTTP_JSON or HTTP_VPACK - // assertThat(e.getResponseCode()).isEqualTo(412)); + assertThat(e.getResponseCode()).isEqualTo(412); assertThat(e.getErrorNum()).isEqualTo(1200); } @@ -425,8 +423,7 @@ void deleteEdgeIfMatchFail(ArangoVertexCollection vertices, ArangoEdgeCollection Throwable thrown = catchThrowable(() -> edges.deleteEdge(createResult.getKey(), options)); assertThat(thrown).isInstanceOf(ArangoDBException.class); ArangoDBException e = (ArangoDBException) thrown; - // FIXME: atm the server replies 409 for HTTP_JSON or HTTP_VPACK - // assertThat(e.getResponseCode()).isEqualTo(412)); + assertThat(e.getResponseCode()).isEqualTo(412); assertThat(e.getErrorNum()).isEqualTo(1200); } From 98f493d5494cef9fe874544363b3ee78d63ce835 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Tue, 16 Aug 2022 11:13:39 +0200 Subject: [PATCH 088/254] re-enabled ArangoVertexCollectionTest test assertions --- .../java/com/arangodb/ArangoVertexCollectionTest.java | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/test/java/com/arangodb/ArangoVertexCollectionTest.java b/src/test/java/com/arangodb/ArangoVertexCollectionTest.java index 3c51d8ded..af1db2454 100644 --- a/src/test/java/com/arangodb/ArangoVertexCollectionTest.java +++ b/src/test/java/com/arangodb/ArangoVertexCollectionTest.java @@ -277,8 +277,7 @@ void replaceVertexIfMatchFail(ArangoVertexCollection vertices) { Throwable thrown = catchThrowable(() -> vertices.replaceVertex(createResult.getKey(), doc, options)); assertThat(thrown).isInstanceOf(ArangoDBException.class); ArangoDBException e = (ArangoDBException) thrown; - // FIXME: atm the server replies 409 for HTTP_JSON or HTTP_VPACK - // assertThat(e.getResponseCode()).isEqualTo(412)); + assertThat(e.getResponseCode()).isEqualTo(412); assertThat(e.getErrorNum()).isEqualTo(1200); } @@ -372,8 +371,7 @@ void updateVertexIfMatchFail(ArangoVertexCollection vertices) { Throwable thrown = catchThrowable(() -> vertices.updateVertex(createResult.getKey(), doc, options)); assertThat(thrown).isInstanceOf(ArangoDBException.class); ArangoDBException e = (ArangoDBException) thrown; - // FIXME: atm the server replies 409 for HTTP_JSON or HTTP_VPACK - // assertThat(e.getResponseCode()).isEqualTo(412)); + assertThat(e.getResponseCode()).isEqualTo(412); assertThat(e.getErrorNum()).isEqualTo(1200); } @@ -459,8 +457,7 @@ void deleteVertexIfMatchFail(ArangoVertexCollection vertices) { Throwable thrown = catchThrowable(() -> vertices.deleteVertex(createResult.getKey(), options)); assertThat(thrown).isInstanceOf(ArangoDBException.class); ArangoDBException e = (ArangoDBException) thrown; - // FIXME: atm the server replies 409 for HTTP_JSON or HTTP_VPACK - // assertThat(e.getResponseCode()).isEqualTo(412)); + assertThat(e.getResponseCode()).isEqualTo(412); assertThat(e.getErrorNum()).isEqualTo(1200); } From 9315d7433edbeb87e6fc92665b7c18f44eee7f38 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Tue, 16 Aug 2022 11:20:46 +0200 Subject: [PATCH 089/254] code cleanup --- .../java/com/arangodb/ArangoCollection.java | 138 ++--- src/main/java/com/arangodb/ArangoDB.java | 547 +++++++++--------- .../java/com/arangodb/ArangoDatabase.java | 124 ++-- .../com/arangodb/ArangoEdgeCollection.java | 24 +- src/main/java/com/arangodb/ArangoGraph.java | 28 +- src/main/java/com/arangodb/ArangoRoute.java | 12 +- src/main/java/com/arangodb/ArangoSearch.java | 10 +- .../com/arangodb/ArangoVertexCollection.java | 24 +- src/main/java/com/arangodb/ArangoView.java | 8 +- src/main/java/com/arangodb/DbName.java | 8 +- .../arangodb/async/ArangoCollectionAsync.java | 7 +- .../com/arangodb/async/ArangoDBAsync.java | 15 +- .../arangodb/async/ArangoDatabaseAsync.java | 7 +- .../com/arangodb/async/ArangoGraphAsync.java | 2 +- .../internal/ArangoCollectionAsyncImpl.java | 4 +- .../async/internal/ArangoCursorAsyncImpl.java | 2 +- .../async/internal/ArangoDBAsyncImpl.java | 2 +- .../internal/ArangoDatabaseAsyncImpl.java | 5 +- .../utils/CompletableFutureUtils.java | 13 +- .../velocystream/VstCommunicationAsync.java | 2 +- .../entity/AqlExecutionExplainEntity.java | 52 +- .../com/arangodb/entity/AqlParseEntity.java | 32 +- .../com/arangodb/entity/ArangoDBEngine.java | 8 +- .../com/arangodb/entity/CollectionStatus.java | 10 +- .../com/arangodb/entity/CollectionType.java | 8 +- .../com/arangodb/entity/EdgeDefinition.java | 2 +- .../java/com/arangodb/entity/LogLevel.java | 8 +- .../com/arangodb/entity/LogLevelEntity.java | 9 +- .../entity/QueryCachePropertiesEntity.java | 9 +- .../arangodb/entity/ReplicationFactor.java | 18 +- .../arangosearch/analyzer/AQLAnalyzer.java | 4 +- .../analyzer/AQLAnalyzerProperties.java | 8 +- .../analyzer/CollationAnalyzer.java | 4 +- .../analyzer/DelimiterAnalyzer.java | 4 +- .../analyzer/GeoJSONAnalyzer.java | 4 +- .../analyzer/GeoJSONAnalyzerProperties.java | 36 +- .../analyzer/GeoPointAnalyzer.java | 4 +- .../arangosearch/analyzer/NGramAnalyzer.java | 4 +- .../analyzer/NGramAnalyzerProperties.java | 2 +- .../arangosearch/analyzer/NormAnalyzer.java | 4 +- .../analyzer/NormAnalyzerProperties.java | 2 +- .../analyzer/PipelineAnalyzer.java | 5 +- .../analyzer/SegmentationAnalyzer.java | 4 +- .../SegmentationAnalyzerProperties.java | 8 +- .../arangosearch/analyzer/StemAnalyzer.java | 4 +- .../analyzer/StopwordsAnalyzer.java | 4 +- .../analyzer/StopwordsAnalyzerProperties.java | 16 +- .../arangosearch/analyzer/TextAnalyzer.java | 4 +- .../analyzer/TextAnalyzerProperties.java | 14 +- .../internal/ArangoCollectionImpl.java | 144 ++--- .../internal/ArangoCursorExecute.java | 5 +- .../com/arangodb/internal/ArangoDBImpl.java | 53 +- .../arangodb/internal/ArangoDatabaseImpl.java | 129 ++--- .../com/arangodb/internal/ArangoDefaults.java | 8 +- .../internal/ArangoEdgeCollectionImpl.java | 23 +- .../com/arangodb/internal/ArangoErrors.java | 7 +- .../arangodb/internal/ArangoExecuteable.java | 36 +- .../com/arangodb/internal/ArangoExecutor.java | 13 +- .../arangodb/internal/ArangoExecutorSync.java | 8 +- .../arangodb/internal/ArangoGraphImpl.java | 27 +- .../arangodb/internal/ArangoRequestParam.java | 7 +- .../internal/ArangoResponseField.java | 5 +- .../arangodb/internal/ArangoRouteImpl.java | 13 +- .../arangodb/internal/ArangoSearchImpl.java | 20 +- .../internal/ArangoVertexCollectionImpl.java | 25 +- .../com/arangodb/internal/ArangoViewImpl.java | 8 +- .../com/arangodb/internal/DocumentFields.java | 5 +- .../internal/InternalArangoCollection.java | 8 +- .../arangodb/internal/InternalArangoDB.java | 7 +- .../internal/InternalArangoDBBuilder.java | 238 ++++---- .../internal/QueueTimeMetricsImpl.java | 11 +- .../internal/cursor/ArangoCursorImpl.java | 6 +- .../internal/cursor/ArangoCursorIterator.java | 5 +- .../cursor/entity/InternalCursorEntity.java | 13 +- .../internal/http/HttpCommunication.java | 43 +- .../internal/http/HttpConnection.java | 238 ++++---- .../arangodb/internal/http/HttpProtocol.java | 3 +- .../internal/net/CommunicationProtocol.java | 3 +- .../internal/net/ConnectionPoolImpl.java | 2 +- .../internal/net/ExtendedHostResolver.java | 8 +- .../internal/net/FallbackHostHandler.java | 2 +- .../java/com/arangodb/internal/net/Host.java | 4 +- .../com/arangodb/internal/net/HostImpl.java | 8 +- .../internal/net/RoundRobinHostHandler.java | 2 +- .../internal/serde/InternalDeserializers.java | 108 ++-- .../internal/serde/InternalSerdeImpl.java | 6 +- .../internal/serde/InternalSerializers.java | 69 +-- .../internal/serde/MapperProvider.java | 2 - .../arangodb/internal/serde/SerdeUtils.java | 52 +- .../arangodb/internal/util/DocumentUtil.java | 9 +- .../arangodb/internal/util/ResponseUtils.java | 2 +- .../velocystream/VstCommunication.java | 18 +- .../velocystream/VstCommunicationSync.java | 108 ++-- .../internal/velocystream/VstProtocol.java | 3 +- .../velocystream/internal/MessageStore.java | 2 +- .../velocystream/internal/VstConnection.java | 35 +- .../internal/VstConnectionSync.java | 44 +- .../com/arangodb/model/AqlQueryOptions.java | 60 +- .../model/CollectionCreateOptions.java | 3 +- .../model/CollectionPropertiesOptions.java | 2 +- .../com/arangodb/model/CollectionSchema.java | 8 +- .../arangodb/model/DocumentImportOptions.java | 9 +- .../arangodb/model/FulltextIndexOptions.java | 2 +- .../com/arangodb/model/GeoIndexOptions.java | 2 +- .../com/arangodb/model/HashIndexOptions.java | 10 +- .../java/com/arangodb/model/LogOptions.java | 10 +- .../model/PersistentIndexOptions.java | 13 +- .../arangodb/model/SkiplistIndexOptions.java | 10 +- .../arangodb/model/TransactionOptions.java | 2 +- .../com/arangodb/model/TtlIndexOptions.java | 2 +- .../model/VertexCollectionCreateOptions.java | 2 +- .../com/arangodb/model/ViewCreateOptions.java | 4 +- .../com/arangodb/model/ZKDIndexOptions.java | 2 +- .../ArangoSearchCreateOptions.java | 4 +- .../java/com/arangodb/serde/JacksonSerde.java | 3 +- .../util/ArangoCursorInitializer.java | 2 +- src/main/java/com/arangodb/util/RawBytes.java | 8 +- src/main/java/com/arangodb/util/RawJson.java | 8 +- .../com/arangodb/velocystream/Request.java | 4 +- .../arangodb/velocystream/RequestType.java | 8 +- 120 files changed, 1450 insertions(+), 1596 deletions(-) diff --git a/src/main/java/com/arangodb/ArangoCollection.java b/src/main/java/com/arangodb/ArangoCollection.java index a6a34184c..503a3dd8d 100644 --- a/src/main/java/com/arangodb/ArangoCollection.java +++ b/src/main/java/com/arangodb/ArangoCollection.java @@ -59,7 +59,7 @@ public interface ArangoCollection extends ArangoSerdeAccessor { * @see API * Documentation */ - DocumentCreateEntity insertDocument(Object value) ; + DocumentCreateEntity insertDocument(Object value); /** * Creates a new document from the given document, unless there is already a document with the _key given. If no @@ -71,7 +71,7 @@ public interface ArangoCollection extends ArangoSerdeAccessor { * @see API * Documentation */ - DocumentCreateEntity insertDocument(T value, DocumentCreateOptions options) ; + DocumentCreateEntity insertDocument(T value, DocumentCreateOptions options); /** * Creates a new document from the given document, unless there is already a document with the _key given. If no @@ -84,7 +84,7 @@ public interface ArangoCollection extends ArangoSerdeAccessor { * @see API * Documentation */ - DocumentCreateEntity insertDocument(T value, DocumentCreateOptions options, Class type) ; + DocumentCreateEntity insertDocument(T value, DocumentCreateOptions options, Class type); /** * Creates new documents from the given documents, unless there is already a document with the _key given. If no @@ -95,7 +95,7 @@ public interface ArangoCollection extends ArangoSerdeAccessor { * @see API * Documentation */ - MultiDocumentEntity> insertDocuments(Collection values) ; + MultiDocumentEntity> insertDocuments(Collection values); /** * Creates new documents from the given documents, unless there is already a document with the _key given. If no @@ -108,7 +108,7 @@ public interface ArangoCollection extends ArangoSerdeAccessor { * Documentation */ MultiDocumentEntity> insertDocuments( - Collection values, DocumentCreateOptions options) ; + Collection values, DocumentCreateOptions options); /** * Creates new documents from the given documents, unless there is already a document with the _key given. If no @@ -122,7 +122,7 @@ MultiDocumentEntity> insertDocuments( * Documentation */ MultiDocumentEntity> insertDocuments( - Collection values, DocumentCreateOptions options, Class type) ; + Collection values, DocumentCreateOptions options, Class type); /** * Bulk imports the given values into the collection. @@ -130,7 +130,7 @@ MultiDocumentEntity> insertDocuments( * @param values a list of Objects that will be stored as documents * @return information about the import */ - DocumentImportEntity importDocuments(Collection values) ; + DocumentImportEntity importDocuments(Collection values); /** * Bulk imports the given values into the collection. @@ -139,7 +139,7 @@ MultiDocumentEntity> insertDocuments( * @param options Additional options, can be null * @return information about the import */ - DocumentImportEntity importDocuments(Collection values, DocumentImportOptions options) ; + DocumentImportEntity importDocuments(Collection values, DocumentImportOptions options); /** * Bulk imports the given values into the collection. @@ -147,7 +147,7 @@ MultiDocumentEntity> insertDocuments( * @param values JSON-encoded array of objects that will be stored as documents * @return information about the import */ - DocumentImportEntity importDocuments(String values) ; + DocumentImportEntity importDocuments(String values); /** * Bulk imports the given values into the collection. @@ -156,7 +156,7 @@ MultiDocumentEntity> insertDocuments( * @param options Additional options, can be null * @return information about the import */ - DocumentImportEntity importDocuments(String values, DocumentImportOptions options) ; + DocumentImportEntity importDocuments(String values, DocumentImportOptions options); /** * Retrieves the document with the given {@code key} from the collection. @@ -167,7 +167,7 @@ MultiDocumentEntity> insertDocuments( * @see API * Documentation */ - T getDocument(String key, Class type) ; + T getDocument(String key, Class type); /** * Retrieves the document with the given {@code key} from the collection. @@ -179,7 +179,7 @@ MultiDocumentEntity> insertDocuments( * @see API * Documentation */ - T getDocument(String key, Class type, DocumentReadOptions options) ; + T getDocument(String key, Class type, DocumentReadOptions options); /** * Retrieves multiple documents with the given {@code _key} from the collection. @@ -188,7 +188,7 @@ MultiDocumentEntity> insertDocuments( * @param type The type of the documents (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) * @return the documents and possible errors */ - MultiDocumentEntity getDocuments(Collection keys, Class type) ; + MultiDocumentEntity getDocuments(Collection keys, Class type); /** * Retrieves multiple documents with the given {@code _key} from the collection. @@ -198,9 +198,7 @@ MultiDocumentEntity> insertDocuments( * @param options Additional options, can be null * @return the documents and possible errors */ - MultiDocumentEntity getDocuments(Collection keys, Class type, DocumentReadOptions options) - ; - + MultiDocumentEntity getDocuments(Collection keys, Class type, DocumentReadOptions options); /** * Replaces the document with {@code key} with the one in the body, provided there is such a document and no * precondition is violated @@ -211,7 +209,7 @@ MultiDocumentEntity getDocuments(Collection keys, Class type, * @see API * Documentation */ - DocumentUpdateEntity replaceDocument(String key, Object value) ; + DocumentUpdateEntity replaceDocument(String key, Object value); /** * Replaces the document with {@code key} with the one in the body, provided there is such a document and no @@ -224,9 +222,7 @@ MultiDocumentEntity getDocuments(Collection keys, Class type, * @see API * Documentation */ - DocumentUpdateEntity replaceDocument(String key, T value, DocumentReplaceOptions options) - ; - + DocumentUpdateEntity replaceDocument(String key, T value, DocumentReplaceOptions options); /** * Replaces the document with {@code key} with the one in the body, provided there is such a document and no * precondition is violated @@ -239,9 +235,7 @@ DocumentUpdateEntity replaceDocument(String key, T value, DocumentReplace * @see API * Documentation */ - DocumentUpdateEntity replaceDocument(String key, T value, DocumentReplaceOptions options, Class type) - ; - + DocumentUpdateEntity replaceDocument(String key, T value, DocumentReplaceOptions options, Class type); /** * Replaces multiple documents in the specified collection with the ones in the values, the replaced documents are * specified by the _key attributes in the documents in values. @@ -251,7 +245,7 @@ DocumentUpdateEntity replaceDocument(String key, T value, DocumentReplace * @see API * Documentation */ - MultiDocumentEntity> replaceDocuments(Collection values) ; + MultiDocumentEntity> replaceDocuments(Collection values); /** * Replaces multiple documents in the specified collection with the ones in the values, the replaced documents are @@ -264,7 +258,7 @@ DocumentUpdateEntity replaceDocument(String key, T value, DocumentReplace * Documentation */ MultiDocumentEntity> replaceDocuments( - Collection values, DocumentReplaceOptions options) ; + Collection values, DocumentReplaceOptions options); /** * Replaces multiple documents in the specified collection with the ones in the values, the replaced documents are @@ -278,7 +272,7 @@ MultiDocumentEntity> replaceDocuments( * Documentation */ MultiDocumentEntity> replaceDocuments( - Collection values, DocumentReplaceOptions options, Class type) ; + Collection values, DocumentReplaceOptions options, Class type); /** * Partially updates the document identified by document-key. The value must contain a document with the attributes @@ -291,7 +285,7 @@ MultiDocumentEntity> replaceDocuments( * @see API * Documentation */ - DocumentUpdateEntity updateDocument(String key, Object value) ; + DocumentUpdateEntity updateDocument(String key, Object value); /** * Partially updates the document identified by document-key. The value must contain a document with the attributes @@ -305,9 +299,7 @@ MultiDocumentEntity> replaceDocuments( * @see API * Documentation */ - DocumentUpdateEntity updateDocument(String key, T value, DocumentUpdateOptions options) - ; - + DocumentUpdateEntity updateDocument(String key, T value, DocumentUpdateOptions options); /** * Partially updates the document identified by document-key. The value must contain a document with the attributes * to patch (the patch document). All attributes from the patch document will be added to the existing document if @@ -321,9 +313,7 @@ DocumentUpdateEntity updateDocument(String key, T value, DocumentUpdateOp * @see API * Documentation */ - DocumentUpdateEntity updateDocument(String key, Object value, DocumentUpdateOptions options, Class returnType) - ; - + DocumentUpdateEntity updateDocument(String key, Object value, DocumentUpdateOptions options, Class returnType); /** * Partially updates documents, the documents to update are specified by the _key attributes in the objects on * values. Vales must contain a list of document updates with the attributes to patch (the patch documents). All @@ -335,7 +325,7 @@ DocumentUpdateEntity updateDocument(String key, Object value, DocumentUpd * @see API * Documentation */ - MultiDocumentEntity> updateDocuments(Collection values) ; + MultiDocumentEntity> updateDocuments(Collection values); /** * Partially updates documents, the documents to update are specified by the _key attributes in the objects on @@ -350,7 +340,7 @@ DocumentUpdateEntity updateDocument(String key, Object value, DocumentUpd * Documentation */ MultiDocumentEntity> updateDocuments( - Collection values, DocumentUpdateOptions options) ; + Collection values, DocumentUpdateOptions options); /** * Partially updates documents, the documents to update are specified by the _key attributes in the objects on @@ -366,7 +356,7 @@ MultiDocumentEntity> updateDocuments( * Documentation */ MultiDocumentEntity> updateDocuments( - Collection values, DocumentUpdateOptions options, Class returnType) ; + Collection values, DocumentUpdateOptions options, Class returnType); /** * Deletes the document with the given {@code key} from the collection. @@ -376,7 +366,7 @@ MultiDocumentEntity> updateDocuments( * @see API * Documentation */ - DocumentDeleteEntity deleteDocument(String key) ; + DocumentDeleteEntity deleteDocument(String key); /** * Deletes the document with the given {@code key} from the collection. @@ -387,9 +377,7 @@ MultiDocumentEntity> updateDocuments( * @see API * Documentation */ - DocumentDeleteEntity deleteDocument(String key, DocumentDeleteOptions options) - ; - + DocumentDeleteEntity deleteDocument(String key, DocumentDeleteOptions options); /** * Deletes the document with the given {@code key} from the collection. * @@ -400,9 +388,7 @@ DocumentDeleteEntity deleteDocument(String key, DocumentDeleteOptions opti * @see API * Documentation */ - DocumentDeleteEntity deleteDocument(String key, DocumentDeleteOptions options, Class type) - ; - + DocumentDeleteEntity deleteDocument(String key, DocumentDeleteOptions options, Class type); /** * Deletes multiple documents from the collection. * @@ -412,7 +398,7 @@ DocumentDeleteEntity deleteDocument(String key, DocumentDeleteOptions opt * "https://www.arangodb.com/docs/stable/http/document-working-with-documents.html#removes-multiple-documents">API * Documentation */ - MultiDocumentEntity> deleteDocuments(Collection values) ; + MultiDocumentEntity> deleteDocuments(Collection values); /** * Deletes multiple documents from the collection. @@ -425,7 +411,7 @@ DocumentDeleteEntity deleteDocument(String key, DocumentDeleteOptions opt * Documentation */ MultiDocumentEntity> deleteDocuments( - Collection values, DocumentDeleteOptions options) ; + Collection values, DocumentDeleteOptions options); /** * Deletes multiple documents from the collection. @@ -439,7 +425,7 @@ MultiDocumentEntity> deleteDocuments( * Documentation */ MultiDocumentEntity> deleteDocuments( - Collection values, DocumentDeleteOptions options, Class type) ; + Collection values, DocumentDeleteOptions options, Class type); /** * Checks if the document exists by reading a single document head @@ -458,12 +444,12 @@ MultiDocumentEntity> deleteDocuments( * @param key The key of the document * @param options Additional options, can be null * @return true if the document was found, otherwise false - * only thrown when {@link DocumentExistsOptions#isCatchException()} == false + * only thrown when {@link DocumentExistsOptions#isCatchException()} == false * @see API * Documentation */ - Boolean documentExists(String key, DocumentExistsOptions options) ; + Boolean documentExists(String key, DocumentExistsOptions options); /** * Fetches information about the index with the given {@code id} and returns it. @@ -472,7 +458,7 @@ MultiDocumentEntity> deleteDocuments( * @return information about the index * @see API Documentation */ - IndexEntity getIndex(String id) ; + IndexEntity getIndex(String id); /** * Deletes the index with the given {@code id} from the collection. @@ -481,7 +467,7 @@ MultiDocumentEntity> deleteDocuments( * @return the id of the index * @see API Documentation */ - String deleteIndex(String id) ; + String deleteIndex(String id); /** * Creates a hash index for the collection if it does not already exist. @@ -494,7 +480,7 @@ MultiDocumentEntity> deleteDocuments( * hash index is an alias for a persistent index. */ @Deprecated - IndexEntity ensureHashIndex(Iterable fields, HashIndexOptions options) ; + IndexEntity ensureHashIndex(Iterable fields, HashIndexOptions options); /** * Creates a skip-list index for the collection, if it does not already exist. @@ -508,7 +494,7 @@ MultiDocumentEntity> deleteDocuments( * skiplist index is an alias for a persistent index. */ @Deprecated - IndexEntity ensureSkiplistIndex(Iterable fields, SkiplistIndexOptions options) ; + IndexEntity ensureSkiplistIndex(Iterable fields, SkiplistIndexOptions options); /** * Creates a persistent index for the collection, if it does not already exist. @@ -519,7 +505,7 @@ MultiDocumentEntity> deleteDocuments( * @see API * Documentation */ - IndexEntity ensurePersistentIndex(Iterable fields, PersistentIndexOptions options) ; + IndexEntity ensurePersistentIndex(Iterable fields, PersistentIndexOptions options); /** * Creates a geo-spatial index for the collection, if it does not already exist. @@ -530,7 +516,7 @@ MultiDocumentEntity> deleteDocuments( * @see API * Documentation */ - IndexEntity ensureGeoIndex(Iterable fields, GeoIndexOptions options) ; + IndexEntity ensureGeoIndex(Iterable fields, GeoIndexOptions options); /** * Creates a fulltext index for the collection, if it does not already exist. @@ -541,7 +527,7 @@ MultiDocumentEntity> deleteDocuments( * @see API * Documentation */ - IndexEntity ensureFulltextIndex(Iterable fields, FulltextIndexOptions options) ; + IndexEntity ensureFulltextIndex(Iterable fields, FulltextIndexOptions options); /** * Creates a ttl index for the collection, if it does not already exist. @@ -552,7 +538,7 @@ MultiDocumentEntity> deleteDocuments( * @see API * Documentation */ - IndexEntity ensureTtlIndex(Iterable fields, TtlIndexOptions options) ; + IndexEntity ensureTtlIndex(Iterable fields, TtlIndexOptions options); /** * Creates a ZKD multi-dimensional index for the collection, if it does not already exist. @@ -564,7 +550,7 @@ MultiDocumentEntity> deleteDocuments( * @see API Documentation * @since ArangoDB 3.9 */ - IndexEntity ensureZKDIndex(Iterable fields, ZKDIndexOptions options) ; + IndexEntity ensureZKDIndex(Iterable fields, ZKDIndexOptions options); /** * Fetches a list of all indexes on this collection. @@ -574,14 +560,14 @@ MultiDocumentEntity> deleteDocuments( * "https://www.arangodb.com/docs/stable/http/indexes-working-with.html#read-all-indexes-of-a-collection">API * Documentation */ - Collection getIndexes() ; + Collection getIndexes(); /** * Checks whether the collection exists * * @return true if the collection exists, otherwise false */ - boolean exists() ; + boolean exists(); /** * Removes all documents from the collection, but leaves the indexes intact @@ -590,7 +576,7 @@ MultiDocumentEntity> deleteDocuments( * @see API * Documentation */ - CollectionEntity truncate() ; + CollectionEntity truncate(); /** * Removes all documents from the collection, but leaves the indexes intact @@ -601,7 +587,7 @@ MultiDocumentEntity> deleteDocuments( * Documentation * @since ArangoDB 3.5.0 */ - CollectionEntity truncate(CollectionTruncateOptions options) ; + CollectionEntity truncate(CollectionTruncateOptions options); /** * Counts the documents in a collection @@ -611,7 +597,7 @@ MultiDocumentEntity> deleteDocuments( * "https://www.arangodb.com/docs/stable/http/collection-getting.html#return-number-of-documents-in-a-collection">API * Documentation */ - CollectionPropertiesEntity count() ; + CollectionPropertiesEntity count(); /** * Counts the documents in a collection @@ -623,7 +609,7 @@ MultiDocumentEntity> deleteDocuments( * Documentation * @since ArangoDB 3.5.0 */ - CollectionPropertiesEntity count(CollectionCountOptions options) ; + CollectionPropertiesEntity count(CollectionCountOptions options); /** * Creates a collection for this collection's name, then returns collection information from the server. @@ -632,7 +618,7 @@ MultiDocumentEntity> deleteDocuments( * @see API * Documentation */ - CollectionEntity create() ; + CollectionEntity create(); /** * Creates a collection with the given {@code options} for this collection's name, then returns collection @@ -643,7 +629,7 @@ MultiDocumentEntity> deleteDocuments( * @see API * Documentation */ - CollectionEntity create(CollectionCreateOptions options) ; + CollectionEntity create(CollectionCreateOptions options); /** * Deletes the collection from the database. @@ -651,7 +637,7 @@ MultiDocumentEntity> deleteDocuments( * @see API * Documentation */ - void drop() ; + void drop(); /** * Deletes the collection from the database. @@ -662,7 +648,7 @@ MultiDocumentEntity> deleteDocuments( * Documentation * @since ArangoDB 3.1.0 */ - void drop(boolean isSystem) ; + void drop(boolean isSystem); /** * Returns information about the collection @@ -672,7 +658,7 @@ MultiDocumentEntity> deleteDocuments( * "https://www.arangodb.com/docs/stable/http/collection-getting.html#return-information-about-a-collection">API * Documentation */ - CollectionEntity getInfo() ; + CollectionEntity getInfo(); /** * Reads the properties of the specified collection @@ -682,7 +668,7 @@ MultiDocumentEntity> deleteDocuments( * "https://www.arangodb.com/docs/stable/http/collection-getting.html#read-properties-of-a-collection">API * Documentation */ - CollectionPropertiesEntity getProperties() ; + CollectionPropertiesEntity getProperties(); /** * Changes the properties of the collection @@ -693,7 +679,7 @@ MultiDocumentEntity> deleteDocuments( * "https://www.arangodb.com/docs/stable/http/collection-modifying.html#change-properties-of-a-collection">API * Documentation */ - CollectionPropertiesEntity changeProperties(CollectionPropertiesOptions options) ; + CollectionPropertiesEntity changeProperties(CollectionPropertiesOptions options); /** * Renames the collection @@ -703,7 +689,7 @@ MultiDocumentEntity> deleteDocuments( * @see API * Documentation */ - CollectionEntity rename(String newName) ; + CollectionEntity rename(String newName); /** * Returns the responsible shard for the document. @@ -725,7 +711,7 @@ MultiDocumentEntity> deleteDocuments( * @see API * Documentation */ - CollectionRevisionEntity getRevision() ; + CollectionRevisionEntity getRevision(); /** * Grants or revoke access to the collection for user user. You need permission to the _system database in order to @@ -737,7 +723,7 @@ MultiDocumentEntity> deleteDocuments( * "https://www.arangodb.com/docs/stable/http/user-management.html#set-the-collection-access-level"> API * Documentation */ - void grantAccess(String user, Permissions permissions) ; + void grantAccess(String user, Permissions permissions); /** * Revokes access to the collection for user user. You need permission to the _system database in order to execute @@ -748,7 +734,7 @@ MultiDocumentEntity> deleteDocuments( * "https://www.arangodb.com/docs/stable/http/user-management.html#set-the-collection-access-level"> API * Documentation */ - void revokeAccess(String user) ; + void revokeAccess(String user); /** * Clear the collection access level, revert back to the default access level. @@ -759,7 +745,7 @@ MultiDocumentEntity> deleteDocuments( * Documentation * @since ArangoDB 3.2.0 */ - void resetAccess(String user) ; + void resetAccess(String user); /** * Get the collection access level @@ -770,6 +756,6 @@ MultiDocumentEntity> deleteDocuments( * API Documentation * @since ArangoDB 3.2.0 */ - Permissions getPermissions(String user) ; + Permissions getPermissions(String user); } diff --git a/src/main/java/com/arangodb/ArangoDB.java b/src/main/java/com/arangodb/ArangoDB.java index b8e69ee5b..04af3fd2d 100644 --- a/src/main/java/com/arangodb/ArangoDB.java +++ b/src/main/java/com/arangodb/ArangoDB.java @@ -35,10 +35,10 @@ import com.arangodb.model.LogOptions; import com.arangodb.model.UserCreateOptions; import com.arangodb.model.UserUpdateOptions; +import com.arangodb.serde.ArangoSerde; import com.arangodb.serde.DataType; import com.arangodb.serde.JacksonSerde; import com.arangodb.util.ArangoCursorInitializer; -import com.arangodb.serde.ArangoSerde; import com.arangodb.velocystream.Request; import com.arangodb.velocystream.Response; import org.apache.http.client.HttpRequestRetryHandler; @@ -69,6 +69,270 @@ */ public interface ArangoDB extends ArangoSerdeAccessor { + /** + * Releases all connections to the server and clear the connection pool. + */ + void shutdown(); + + /** + * Updates the JWT used for requests authorization. It does not change already existing VST connections, since VST + * connections are authenticated during the initialization phase. + * + * @param jwt token to use + */ + void updateJwt(String jwt); + + /** + * Returns a {@code ArangoDatabase} instance for the {@code _system} database. + * + * @return database handler + */ + ArangoDatabase db(); + + /** + * Returns a {@code ArangoDatabase} instance for the given database name. + * + * @param dbName Name of the database + * @return database handler + */ + ArangoDatabase db(DbName dbName); + + /** + * @return entry point for accessing client metrics + */ + ArangoMetrics metrics(); + + /** + * Creates a new database with the given name. + * + * @param dbName Name of the database to create + * @return true if the database was created successfully. + * @see API + * Documentation + */ + Boolean createDatabase(DbName dbName); + + /** + * Creates a new database with the given name. + * + * @param options Creation options + * @return true if the database was created successfully. + * @see API + * Documentation + * @since ArangoDB 3.6.0 + */ + Boolean createDatabase(DBCreateOptions options); + + /** + * Retrieves a list of all existing databases + * + * @return a list of all existing databases + * @see API + * Documentation + */ + Collection getDatabases(); + + /** + * Retrieves a list of all databases the current user can access + * + * @return a list of all databases the current user can access + * @see API + * Documentation + */ + Collection getAccessibleDatabases(); + + /** + * List available database to the specified user + * + * @param user The name of the user for which you want to query the databases + * @return list of database names which are available for the specified user + * @see API + * Documentation + */ + Collection getAccessibleDatabasesFor(String user); + + /** + * Returns the server name and version number. + * + * @return the server version, number + * @see API + * Documentation + */ + ArangoDBVersion getVersion(); + + /** + * Returns the server storage engine. + * + * @return the storage engine name + * @see API + * Documentation + */ + ArangoDBEngine getEngine(); + + /** + * Returns the server role. + * + * @return the server role + */ + ServerRole getRole(); + + /** + * Returns the id of a server in a cluster. + * + * @return the server id + * @see API + * Documentation + */ + String getServerId(); + + /** + * Create a new user. This user will not have access to any database. You need permission to the _system database in + * order to execute this call. + * + * @param user The name of the user + * @param passwd The user password + * @return information about the user + * @see API Documentation + */ + UserEntity createUser(String user, String passwd); + + /** + * Create a new user. This user will not have access to any database. You need permission to the _system database in + * order to execute this call. + * + * @param user The name of the user + * @param passwd The user password + * @param options Additional options, can be null + * @return information about the user + * @see API Documentation + */ + UserEntity createUser(String user, String passwd, UserCreateOptions options); + + /** + * Removes an existing user, identified by user. You need access to the _system database. + * + * @param user The name of the user + * @see API Documentation + */ + void deleteUser(String user); + + /** + * Fetches data about the specified user. You can fetch information about yourself or you need permission to the + * _system database in order to execute this call. + * + * @param user The name of the user + * @return information about the user + * @see API Documentation + */ + UserEntity getUser(String user); + + /** + * Fetches data about all users. You can only execute this call if you have access to the _system database. + * + * @return informations about all users + * @see API + * Documentation + */ + Collection getUsers(); + + /** + * Partially updates the data of an existing user. The name of an existing user must be specified in user. You can + * only change the password of your self. You need access to the _system database to change the active flag. + * + * @param user The name of the user + * @param options Properties of the user to be changed + * @return information about the user + * @see API Documentation + */ + UserEntity updateUser(String user, UserUpdateOptions options); + + /** + * Replaces the data of an existing user. The name of an existing user must be specified in user. You can only + * change the password of your self. You need access to the _system database to change the active flag. + * + * @param user The name of the user + * @param options Additional properties of the user, can be null + * @return information about the user + * @see API + * Documentation + */ + UserEntity replaceUser(String user, UserUpdateOptions options); + + /** + * Sets the default access level for databases for the user {@code user}. You need permission to the _system + * database in order to execute this call. + * + * @param user The name of the user + * @param permissions The permissions the user grant + * @since ArangoDB 3.2.0 + */ + void grantDefaultDatabaseAccess(String user, Permissions permissions); + + /** + * Sets the default access level for collections for the user {@code user}. You need permission to the _system + * database in order to execute this call. + * + * @param user The name of the user + * @param permissions The permissions the user grant + * @since ArangoDB 3.2.0 + */ + void grantDefaultCollectionAccess(String user, Permissions permissions); + + /** + * Generic Execute. Use this method to execute custom FOXX services. + * + * @param request VelocyStream request + * @return VelocyStream response + */ + Response execute(Request request); + + /** + * Generic Execute. Use this method to execute custom FOXX services. + * + * @param request VelocyStream request + * @param hostHandle Used to stick to a specific host when using {@link LoadBalancingStrategy#ROUND_ROBIN} + * @return VelocyStream response + */ + Response execute(Request request, HostHandle hostHandle); + + /** + * Returns the server logs + * + * @param options Additional options, can be null + * @return the log messages + * @see API + * Documentation + * @since ArangoDB 3.8 + */ + LogEntriesEntity getLogEntries(LogOptions options); + + /** + * Returns the server's current loglevel settings. + * + * @return the server's current loglevel settings + * @since ArangoDB 3.1.0 + */ + LogLevelEntity getLogLevel(); + + /** + * Modifies and returns the server's current loglevel settings. + * + * @param entity loglevel settings + * @return the server's current loglevel settings + * @since ArangoDB 3.1.0 + */ + LogLevelEntity setLogLevel(LogLevelEntity entity); + + /** + * Attention: Please do not use! + * + * @param cursorInitializer + * @return ArangoDB + */ + ArangoDB _setCursorInitializer(ArangoCursorInitializer cursorInitializer); + /** * Builder class to build an instance of {@link ArangoDB}. * @@ -84,25 +348,25 @@ public Builder() { super(); } - @Override - protected void loadProperties(final Properties properties) { - super.loadProperties(properties); - protocol = loadProtocol(properties, protocol); - } - private static Protocol loadProtocol(final Properties properties, final Protocol currentValue) { return Protocol.valueOf( getProperty(properties, PROPERTY_KEY_PROTOCOL, currentValue, ArangoDefaults.DEFAULT_NETWORK_PROTOCOL) .toUpperCase(Locale.ENGLISH)); } + @Override + protected void loadProperties(final Properties properties) { + super.loadProperties(properties); + protocol = loadProtocol(properties, protocol); + } + public Builder useProtocol(final Protocol protocol) { this.protocol = protocol; return this; } @Override - public Builder loadProperties(final InputStream in) { + public Builder loadProperties(final InputStream in) { super.loadProperties(in); return this; } @@ -345,7 +609,7 @@ public synchronized ArangoDB build() { hosts.add(host); } final ArangoSerde userSerde = customSerializer != null ? customSerializer : JacksonSerde.of(DataType.of(protocol)); - final InternalSerde serde = InternalSerde.of(DataType.of(protocol), userSerde); + final InternalSerde serde = InternalSerde.of(DataType.of(protocol), userSerde); int protocolMaxConnections = protocol == Protocol.VST ? ArangoDefaults.MAX_CONNECTIONS_VST_DEFAULT : @@ -377,269 +641,4 @@ public synchronized ArangoDB build() { } - /** - * Releases all connections to the server and clear the connection pool. - * - */ - void shutdown() ; - - /** - * Updates the JWT used for requests authorization. It does not change already existing VST connections, since VST - * connections are authenticated during the initialization phase. - * - * @param jwt token to use - */ - void updateJwt(String jwt); - - /** - * Returns a {@code ArangoDatabase} instance for the {@code _system} database. - * - * @return database handler - */ - ArangoDatabase db(); - - /** - * Returns a {@code ArangoDatabase} instance for the given database name. - * - * @param dbName Name of the database - * @return database handler - */ - ArangoDatabase db(DbName dbName); - - /** - * @return entry point for accessing client metrics - */ - ArangoMetrics metrics(); - - /** - * Creates a new database with the given name. - * - * @param dbName Name of the database to create - * @return true if the database was created successfully. - * @see API - * Documentation - */ - Boolean createDatabase(DbName dbName) ; - - /** - * Creates a new database with the given name. - * - * @param options Creation options - * @return true if the database was created successfully. - * @see API - * Documentation - * @since ArangoDB 3.6.0 - */ - Boolean createDatabase(DBCreateOptions options) ; - - /** - * Retrieves a list of all existing databases - * - * @return a list of all existing databases - * @see API - * Documentation - */ - Collection getDatabases() ; - - /** - * Retrieves a list of all databases the current user can access - * - * @return a list of all databases the current user can access - * @see API - * Documentation - */ - Collection getAccessibleDatabases() ; - - /** - * List available database to the specified user - * - * @param user The name of the user for which you want to query the databases - * @return list of database names which are available for the specified user - * @see API - * Documentation - */ - Collection getAccessibleDatabasesFor(String user) ; - - /** - * Returns the server name and version number. - * - * @return the server version, number - * @see API - * Documentation - */ - ArangoDBVersion getVersion() ; - - /** - * Returns the server storage engine. - * - * @return the storage engine name - * @see API - * Documentation - */ - ArangoDBEngine getEngine() ; - - /** - * Returns the server role. - * - * @return the server role - */ - ServerRole getRole() ; - - /** - * Returns the id of a server in a cluster. - * - * @return the server id - * @see API - * Documentation - */ - String getServerId() ; - - /** - * Create a new user. This user will not have access to any database. You need permission to the _system database in - * order to execute this call. - * - * @param user The name of the user - * @param passwd The user password - * @return information about the user - * @see API Documentation - */ - UserEntity createUser(String user, String passwd) ; - - /** - * Create a new user. This user will not have access to any database. You need permission to the _system database in - * order to execute this call. - * - * @param user The name of the user - * @param passwd The user password - * @param options Additional options, can be null - * @return information about the user - * @see API Documentation - */ - UserEntity createUser(String user, String passwd, UserCreateOptions options) ; - - /** - * Removes an existing user, identified by user. You need access to the _system database. - * - * @param user The name of the user - * @see API Documentation - */ - void deleteUser(String user) ; - - /** - * Fetches data about the specified user. You can fetch information about yourself or you need permission to the - * _system database in order to execute this call. - * - * @param user The name of the user - * @return information about the user - * @see API Documentation - */ - UserEntity getUser(String user) ; - - /** - * Fetches data about all users. You can only execute this call if you have access to the _system database. - * - * @return informations about all users - * @see API - * Documentation - */ - Collection getUsers() ; - - /** - * Partially updates the data of an existing user. The name of an existing user must be specified in user. You can - * only change the password of your self. You need access to the _system database to change the active flag. - * - * @param user The name of the user - * @param options Properties of the user to be changed - * @return information about the user - * @see API Documentation - */ - UserEntity updateUser(String user, UserUpdateOptions options) ; - - /** - * Replaces the data of an existing user. The name of an existing user must be specified in user. You can only - * change the password of your self. You need access to the _system database to change the active flag. - * - * @param user The name of the user - * @param options Additional properties of the user, can be null - * @return information about the user - * @see API - * Documentation - */ - UserEntity replaceUser(String user, UserUpdateOptions options) ; - - /** - * Sets the default access level for databases for the user {@code user}. You need permission to the _system - * database in order to execute this call. - * - * @param user The name of the user - * @param permissions The permissions the user grant - * @since ArangoDB 3.2.0 - */ - void grantDefaultDatabaseAccess(String user, Permissions permissions) ; - - /** - * Sets the default access level for collections for the user {@code user}. You need permission to the _system - * database in order to execute this call. - * - * @param user The name of the user - * @param permissions The permissions the user grant - * @since ArangoDB 3.2.0 - */ - void grantDefaultCollectionAccess(String user, Permissions permissions) ; - - /** - * Generic Execute. Use this method to execute custom FOXX services. - * - * @param request VelocyStream request - * @return VelocyStream response - */ - Response execute(Request request) ; - - /** - * Generic Execute. Use this method to execute custom FOXX services. - * - * @param request VelocyStream request - * @param hostHandle Used to stick to a specific host when using {@link LoadBalancingStrategy#ROUND_ROBIN} - * @return VelocyStream response - */ - Response execute(Request request, HostHandle hostHandle) ; - - /** - * Returns the server logs - * - * @param options Additional options, can be null - * @return the log messages - * @see API - * Documentation - * @since ArangoDB 3.8 - */ - LogEntriesEntity getLogEntries(LogOptions options) ; - - /** - * Returns the server's current loglevel settings. - * - * @return the server's current loglevel settings - * @since ArangoDB 3.1.0 - */ - LogLevelEntity getLogLevel() ; - - /** - * Modifies and returns the server's current loglevel settings. - * - * @param entity loglevel settings - * @return the server's current loglevel settings - * @since ArangoDB 3.1.0 - */ - LogLevelEntity setLogLevel(LogLevelEntity entity) ; - - /** - * Attention: Please do not use! - * - * @param cursorInitializer - * @return ArangoDB - */ - ArangoDB _setCursorInitializer(ArangoCursorInitializer cursorInitializer); - } diff --git a/src/main/java/com/arangodb/ArangoDatabase.java b/src/main/java/com/arangodb/ArangoDatabase.java index 59a893188..8d3805585 100644 --- a/src/main/java/com/arangodb/ArangoDatabase.java +++ b/src/main/java/com/arangodb/ArangoDatabase.java @@ -60,7 +60,7 @@ public interface ArangoDatabase extends ArangoSerdeAccessor { * @see API * Documentation */ - ArangoDBVersion getVersion() ; + ArangoDBVersion getVersion(); /** * Returns the name of the used storage engine. @@ -69,14 +69,14 @@ public interface ArangoDatabase extends ArangoSerdeAccessor { * @see API * Documentation */ - ArangoDBEngine getEngine() ; + ArangoDBEngine getEngine(); /** * Checks whether the database exists * * @return true if the database exists, otherwise false */ - boolean exists() ; + boolean exists(); /** * Retrieves a list of all databases the current user can access @@ -86,7 +86,7 @@ public interface ArangoDatabase extends ArangoSerdeAccessor { * "https://www.arangodb.com/docs/stable/http/database-database-management.html#list-of-accessible-databases">API * Documentation */ - Collection getAccessibleDatabases() ; + Collection getAccessibleDatabases(); /** * Returns a {@code ArangoCollection} instance for the given collection name. @@ -104,7 +104,7 @@ public interface ArangoDatabase extends ArangoSerdeAccessor { * @see API * Documentation */ - CollectionEntity createCollection(String name) ; + CollectionEntity createCollection(String name); /** * Creates a collection with the given {@code options} for this collection's name, then returns collection @@ -116,7 +116,7 @@ public interface ArangoDatabase extends ArangoSerdeAccessor { * @see API * Documentation */ - CollectionEntity createCollection(String name, CollectionCreateOptions options) ; + CollectionEntity createCollection(String name, CollectionCreateOptions options); /** * Fetches all collections from the database and returns an list of collection descriptions. @@ -125,7 +125,7 @@ public interface ArangoDatabase extends ArangoSerdeAccessor { * @see API * Documentation */ - Collection getCollections() ; + Collection getCollections(); /** * Fetches all collections from the database and returns an list of collection descriptions. @@ -135,7 +135,7 @@ public interface ArangoDatabase extends ArangoSerdeAccessor { * @see API * Documentation */ - Collection getCollections(CollectionsReadOptions options) ; + Collection getCollections(CollectionsReadOptions options); /** * Returns an index @@ -144,7 +144,7 @@ public interface ArangoDatabase extends ArangoSerdeAccessor { * @return information about the index * @see API Documentation */ - IndexEntity getIndex(String id) ; + IndexEntity getIndex(String id); /** * Deletes an index @@ -153,7 +153,7 @@ public interface ArangoDatabase extends ArangoSerdeAccessor { * @return the id of the index * @see API Documentation */ - String deleteIndex(String id) ; + String deleteIndex(String id); /** * Creates the database @@ -162,7 +162,7 @@ public interface ArangoDatabase extends ArangoSerdeAccessor { * @see API * Documentation */ - Boolean create() ; + Boolean create(); /** * Deletes the database from the server. @@ -171,7 +171,7 @@ public interface ArangoDatabase extends ArangoSerdeAccessor { * @see API * Documentation */ - Boolean drop() ; + Boolean drop(); /** * Grants or revoke access to the database for user {@code user}. You need permission to the _system database in @@ -182,7 +182,7 @@ public interface ArangoDatabase extends ArangoSerdeAccessor { * @see * API Documentation */ - void grantAccess(String user, Permissions permissions) ; + void grantAccess(String user, Permissions permissions); /** * Grants access to the database for user {@code user}. You need permission to the _system database in order to @@ -192,7 +192,7 @@ public interface ArangoDatabase extends ArangoSerdeAccessor { * @see * API Documentation */ - void grantAccess(String user) ; + void grantAccess(String user); /** * Revokes access to the database dbname for user {@code user}. You need permission to the _system database in order @@ -202,7 +202,7 @@ public interface ArangoDatabase extends ArangoSerdeAccessor { * @see * API Documentation */ - void revokeAccess(String user) ; + void revokeAccess(String user); /** * Clear the database access level, revert back to the default access level. @@ -212,7 +212,7 @@ public interface ArangoDatabase extends ArangoSerdeAccessor { * API Documentation * @since ArangoDB 3.2.0 */ - void resetAccess(String user) ; + void resetAccess(String user); /** * Sets the default access level for collections within this database for the user {@code user}. You need permission @@ -222,7 +222,7 @@ public interface ArangoDatabase extends ArangoSerdeAccessor { * @param permissions The permissions the user grant * @since ArangoDB 3.2.0 */ - void grantDefaultCollectionAccess(String user, Permissions permissions) ; + void grantDefaultCollectionAccess(String user, Permissions permissions); /** * Get specific database access level @@ -233,7 +233,7 @@ public interface ArangoDatabase extends ArangoSerdeAccessor { * Documentation * @since ArangoDB 3.2.0 */ - Permissions getPermissions(String user) ; + Permissions getPermissions(String user); /** * Performs a database query using the given {@code query} and {@code bindVars}, then returns a new @@ -247,9 +247,7 @@ public interface ArangoDatabase extends ArangoSerdeAccessor { * @see API * Documentation */ - ArangoCursor query(String query, Map bindVars, AqlQueryOptions options, Class type) - ; - + ArangoCursor query(String query, Map bindVars, AqlQueryOptions options, Class type); /** * Performs a database query using the given {@code query}, then returns a new {@code ArangoCursor} instance for the * result list. @@ -261,7 +259,7 @@ ArangoCursor query(String query, Map bindVars, AqlQueryOp * @see API * Documentation */ - ArangoCursor query(String query, AqlQueryOptions options, Class type) ; + ArangoCursor query(String query, AqlQueryOptions options, Class type); /** * Performs a database query using the given {@code query} and {@code bindVars}, then returns a new @@ -274,7 +272,7 @@ ArangoCursor query(String query, Map bindVars, AqlQueryOp * @see API * Documentation */ - ArangoCursor query(String query, Map bindVars, Class type) ; + ArangoCursor query(String query, Map bindVars, Class type); /** * Performs a database query using the given {@code query}, then returns a new {@code ArangoCursor} instance for the @@ -286,7 +284,7 @@ ArangoCursor query(String query, Map bindVars, AqlQueryOp * @see API * Documentation */ - ArangoCursor query(String query, Class type) ; + ArangoCursor query(String query, Class type); /** * Return an cursor from the given cursor-ID if still existing @@ -298,7 +296,7 @@ ArangoCursor query(String query, Map bindVars, AqlQueryOp * "https://www.arangodb.com/docs/stable/http/aql-query-cursor-accessing-cursors.html#read-next-batch-from-cursor">API * Documentation */ - ArangoCursor cursor(String cursorId, Class type) ; + ArangoCursor cursor(String cursorId, Class type); /** * Explain an AQL query and return information about it @@ -310,9 +308,7 @@ ArangoCursor query(String query, Map bindVars, AqlQueryOp * @see API * Documentation */ - AqlExecutionExplainEntity explainQuery(String query, Map bindVars, AqlQueryExplainOptions options) - ; - + AqlExecutionExplainEntity explainQuery(String query, Map bindVars, AqlQueryExplainOptions options); /** * Parse an AQL query and return information about it This method is for query validation only. To actually query * the database, see {@link ArangoDatabase#query(String, Map, AqlQueryOptions, Class)} @@ -322,7 +318,7 @@ AqlExecutionExplainEntity explainQuery(String query, Map bindVar * @see API * Documentation */ - AqlParseEntity parseQuery(String query) ; + AqlParseEntity parseQuery(String query); /** * Clears the AQL query cache @@ -331,7 +327,7 @@ AqlExecutionExplainEntity explainQuery(String query, Map bindVar * "https://www.arangodb.com/docs/stable/http/aql-query-cache.html#clears-any-results-in-the-aql-query-results-cache">API * Documentation */ - void clearQueryCache() ; + void clearQueryCache(); /** * Returns the global configuration for the AQL query cache @@ -341,7 +337,7 @@ AqlExecutionExplainEntity explainQuery(String query, Map bindVar * "https://www.arangodb.com/docs/stable/http/aql-query-cache.html#returns-the-global-properties-for-the-aql-query-results-cache">API * Documentation */ - QueryCachePropertiesEntity getQueryCacheProperties() ; + QueryCachePropertiesEntity getQueryCacheProperties(); /** * Changes the configuration for the AQL query cache. Note: changing the properties may invalidate all results in @@ -353,7 +349,7 @@ AqlExecutionExplainEntity explainQuery(String query, Map bindVar * "https://www.arangodb.com/docs/stable/http/aql-query-cache.html#globally-adjusts-the-aql-query-results-cache-properties">API * Documentation */ - QueryCachePropertiesEntity setQueryCacheProperties(QueryCachePropertiesEntity properties) ; + QueryCachePropertiesEntity setQueryCacheProperties(QueryCachePropertiesEntity properties); /** * Returns the configuration for the AQL query tracking @@ -363,7 +359,7 @@ AqlExecutionExplainEntity explainQuery(String query, Map bindVar * "https://www.arangodb.com/docs/stable/http/aql-query.html#returns-the-properties-for-the-aql-query-tracking">API * Documentation */ - QueryTrackingPropertiesEntity getQueryTrackingProperties() ; + QueryTrackingPropertiesEntity getQueryTrackingProperties(); /** * Changes the configuration for the AQL query tracking @@ -374,9 +370,7 @@ AqlExecutionExplainEntity explainQuery(String query, Map bindVar * "https://www.arangodb.com/docs/stable/http/aql-query.html#changes-the-properties-for-the-aql-query-tracking">API * Documentation */ - QueryTrackingPropertiesEntity setQueryTrackingProperties(QueryTrackingPropertiesEntity properties) - ; - + QueryTrackingPropertiesEntity setQueryTrackingProperties(QueryTrackingPropertiesEntity properties); /** * Returns a list of currently running AQL queries * @@ -385,7 +379,7 @@ QueryTrackingPropertiesEntity setQueryTrackingProperties(QueryTrackingProperties * "https://www.arangodb.com/docs/stable/http/aql-query.html#returns-the-currently-running-aql-queries">API * Documentation */ - Collection getCurrentlyRunningQueries() ; + Collection getCurrentlyRunningQueries(); /** * Returns a list of slow running AQL queries @@ -395,7 +389,7 @@ QueryTrackingPropertiesEntity setQueryTrackingProperties(QueryTrackingProperties * "https://www.arangodb.com/docs/stable/http/aql-query.html#returns-the-list-of-slow-aql-queries">API * Documentation */ - Collection getSlowQueries() ; + Collection getSlowQueries(); /** * Clears the list of slow AQL queries @@ -404,7 +398,7 @@ QueryTrackingPropertiesEntity setQueryTrackingProperties(QueryTrackingProperties * "https://www.arangodb.com/docs/stable/http/aql-query.html#clears-the-list-of-slow-aql-queries">API * Documentation */ - void clearSlowQueries() ; + void clearSlowQueries(); /** * Kills a running query. The query will be terminated at the next cancelation point. @@ -413,7 +407,7 @@ QueryTrackingPropertiesEntity setQueryTrackingProperties(QueryTrackingProperties * @see API * Documentation */ - void killQuery(String id) ; + void killQuery(String id); /** * Create a new AQL user function @@ -424,7 +418,7 @@ QueryTrackingPropertiesEntity setQueryTrackingProperties(QueryTrackingProperties * @see API * Documentation */ - void createAqlFunction(String name, String code, AqlFunctionCreateOptions options) ; + void createAqlFunction(String name, String code, AqlFunctionCreateOptions options); /** * Deletes the AQL user function with the given name from the database. @@ -436,7 +430,7 @@ QueryTrackingPropertiesEntity setQueryTrackingProperties(QueryTrackingProperties * "https://www.arangodb.com/docs/stable/http/aql-user-functions.html#remove-existing-aql-user-function">API * Documentation */ - Integer deleteAqlFunction(String name, AqlFunctionDeleteOptions options) ; + Integer deleteAqlFunction(String name, AqlFunctionDeleteOptions options); /** * Gets all reqistered AQL user functions @@ -447,7 +441,7 @@ QueryTrackingPropertiesEntity setQueryTrackingProperties(QueryTrackingProperties * "https://www.arangodb.com/docs/stable/http/aql-user-functions.html#return-registered-aql-user-functions">API * Documentation */ - Collection getAqlFunctions(AqlFunctionGetOptions options) ; + Collection getAqlFunctions(AqlFunctionGetOptions options); /** * Returns a {@code ArangoGraph} instance for the given graph name. @@ -467,7 +461,7 @@ QueryTrackingPropertiesEntity setQueryTrackingProperties(QueryTrackingProperties * @see API * Documentation */ - GraphEntity createGraph(String name, Collection edgeDefinitions) ; + GraphEntity createGraph(String name, Collection edgeDefinitions); /** * Create a new graph in the graph module. The creation of a graph requires the name of the graph and a definition @@ -480,9 +474,7 @@ QueryTrackingPropertiesEntity setQueryTrackingProperties(QueryTrackingProperties * @see API * Documentation */ - GraphEntity createGraph(String name, Collection edgeDefinitions, GraphCreateOptions options) - ; - + GraphEntity createGraph(String name, Collection edgeDefinitions, GraphCreateOptions options); /** * Lists all graphs known to the graph module * @@ -490,7 +482,7 @@ GraphEntity createGraph(String name, Collection edgeDefinitions, * @see API * Documentation */ - Collection getGraphs() ; + Collection getGraphs(); /** * Performs a server-side transaction and returns its return value. @@ -502,7 +494,7 @@ GraphEntity createGraph(String name, Collection edgeDefinitions, * @see API * Documentation */ - T transaction(String action, Class type, TransactionOptions options) ; + T transaction(String action, Class type, TransactionOptions options); /** * Begins a Stream Transaction. @@ -513,7 +505,7 @@ GraphEntity createGraph(String name, Collection edgeDefinitions, * Documentation * @since ArangoDB 3.5.0 */ - StreamTransactionEntity beginStreamTransaction(StreamTransactionOptions options) ; + StreamTransactionEntity beginStreamTransaction(StreamTransactionOptions options); /** * Aborts a Stream Transaction. @@ -522,7 +514,7 @@ GraphEntity createGraph(String name, Collection edgeDefinitions, * @see API * Documentation */ - StreamTransactionEntity abortStreamTransaction(String id) ; + StreamTransactionEntity abortStreamTransaction(String id); /** * Gets information about a Stream Transaction. @@ -532,7 +524,7 @@ GraphEntity createGraph(String name, Collection edgeDefinitions, * API Documentation * @since ArangoDB 3.5.0 */ - StreamTransactionEntity getStreamTransaction(String id) ; + StreamTransactionEntity getStreamTransaction(String id); /** * Gets all the currently running Stream Transactions. @@ -542,7 +534,7 @@ GraphEntity createGraph(String name, Collection edgeDefinitions, * API Documentation * @since ArangoDB 3.5.0 */ - Collection getStreamTransactions() ; + Collection getStreamTransactions(); /** * Commits a Stream Transaction. @@ -552,7 +544,7 @@ GraphEntity createGraph(String name, Collection edgeDefinitions, * API Documentation * @since ArangoDB 3.5.0 */ - StreamTransactionEntity commitStreamTransaction(String id) ; + StreamTransactionEntity commitStreamTransaction(String id); /** * Retrieves information about the current database @@ -562,7 +554,7 @@ GraphEntity createGraph(String name, Collection edgeDefinitions, * "https://www.arangodb.com/docs/stable/http/database-database-management.html#information-of-the-database">API * Documentation */ - DatabaseEntity getInfo() ; + DatabaseEntity getInfo(); /** * Reads a single document @@ -573,7 +565,7 @@ GraphEntity createGraph(String name, Collection edgeDefinitions, * @see API * Documentation */ - T getDocument(String id, Class type) ; + T getDocument(String id, Class type); /** * Reads a single document @@ -585,7 +577,7 @@ GraphEntity createGraph(String name, Collection edgeDefinitions, * @see API * Documentation */ - T getDocument(String id, Class type, DocumentReadOptions options) ; + T getDocument(String id, Class type, DocumentReadOptions options); /** * Reload the routing table. @@ -594,7 +586,7 @@ GraphEntity createGraph(String name, Collection edgeDefinitions, * "https://www.arangodb.com/docs/stable/http/administration-and-monitoring.html#reloads-the-routing-information">API * Documentation */ - void reloadRouting() ; + void reloadRouting(); /** * Returns a new {@link ArangoRoute} instance for the given path (relative to the database) that can be used to @@ -612,7 +604,7 @@ GraphEntity createGraph(String name, Collection edgeDefinitions, * @see API Documentation * @since ArangoDB 3.4.0 */ - Collection getViews() ; + Collection getViews(); /** * Returns a {@code ArangoView} instance for the given view name. @@ -640,7 +632,7 @@ GraphEntity createGraph(String name, Collection edgeDefinitions, * @return information about the view * @since ArangoDB 3.4.0 */ - ViewEntity createView(String name, ViewType type) ; + ViewEntity createView(String name, ViewType type); /** * Creates a ArangoSearch view with the given {@code options}, then returns view information from the server. @@ -652,7 +644,7 @@ GraphEntity createGraph(String name, Collection edgeDefinitions, * Documentation * @since ArangoDB 3.4.0 */ - ViewEntity createArangoSearch(String name, ArangoSearchCreateOptions options) ; + ViewEntity createArangoSearch(String name, ArangoSearchCreateOptions options); /** * Creates an Analyzer @@ -662,7 +654,7 @@ GraphEntity createGraph(String name, Collection edgeDefinitions, * @see API Documentation * @since ArangoDB 3.5.0 */ - SearchAnalyzer createSearchAnalyzer(SearchAnalyzer analyzer) ; + SearchAnalyzer createSearchAnalyzer(SearchAnalyzer analyzer); /** * Gets information about an Analyzer @@ -672,7 +664,7 @@ GraphEntity createGraph(String name, Collection edgeDefinitions, * @see API Documentation * @since ArangoDB 3.5.0 */ - SearchAnalyzer getSearchAnalyzer(String name) ; + SearchAnalyzer getSearchAnalyzer(String name); /** * Retrieves all analyzers definitions. @@ -681,7 +673,7 @@ GraphEntity createGraph(String name, Collection edgeDefinitions, * @see API Documentation * @since ArangoDB 3.5.0 */ - Collection getSearchAnalyzers() ; + Collection getSearchAnalyzers(); /** * Deletes an Analyzer @@ -690,7 +682,7 @@ GraphEntity createGraph(String name, Collection edgeDefinitions, * @see API Documentation * @since ArangoDB 3.5.0 */ - void deleteSearchAnalyzer(String name) ; + void deleteSearchAnalyzer(String name); /** * Deletes an Analyzer @@ -700,6 +692,6 @@ GraphEntity createGraph(String name, Collection edgeDefinitions, * @see API Documentation * @since ArangoDB 3.5.0 */ - void deleteSearchAnalyzer(String name, AnalyzerDeleteOptions options) ; + void deleteSearchAnalyzer(String name, AnalyzerDeleteOptions options); } diff --git a/src/main/java/com/arangodb/ArangoEdgeCollection.java b/src/main/java/com/arangodb/ArangoEdgeCollection.java index 829041887..a4930dfce 100644 --- a/src/main/java/com/arangodb/ArangoEdgeCollection.java +++ b/src/main/java/com/arangodb/ArangoEdgeCollection.java @@ -53,7 +53,7 @@ public interface ArangoEdgeCollection extends ArangoSerdeAccessor { * @return information about the edge * @see API Documentation */ - EdgeEntity insertEdge(Object value) ; + EdgeEntity insertEdge(Object value); /** * Creates a new edge in the collection @@ -63,7 +63,7 @@ public interface ArangoEdgeCollection extends ArangoSerdeAccessor { * @return information about the edge * @see API Documentation */ - EdgeEntity insertEdge(Object value, EdgeCreateOptions options) ; + EdgeEntity insertEdge(Object value, EdgeCreateOptions options); /** * Fetches an existing edge @@ -73,7 +73,7 @@ public interface ArangoEdgeCollection extends ArangoSerdeAccessor { * @return the edge identified by the key * @see API Documentation */ - T getEdge(String key, Class type) ; + T getEdge(String key, Class type); /** * Fetches an existing edge @@ -84,18 +84,18 @@ public interface ArangoEdgeCollection extends ArangoSerdeAccessor { * @return the edge identified by the key * @see API Documentation */ - T getEdge(String key, Class type, GraphDocumentReadOptions options) ; + T getEdge(String key, Class type, GraphDocumentReadOptions options); /** * Replaces the edge with key with the one in the body, provided there is such a edge and no precondition is * violated * - * @param key The key of the edge + * @param key The key of the edge * @param value A representation of a single edge (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) * @return information about the edge * @see API Documentation */ - EdgeUpdateEntity replaceEdge(String key, Object value) ; + EdgeUpdateEntity replaceEdge(String key, Object value); /** * Replaces the edge with key with the one in the body, provided there is such a edge and no precondition is @@ -107,19 +107,19 @@ public interface ArangoEdgeCollection extends ArangoSerdeAccessor { * @return information about the edge * @see API Documentation */ - EdgeUpdateEntity replaceEdge(String key, Object value, EdgeReplaceOptions options) ; + EdgeUpdateEntity replaceEdge(String key, Object value, EdgeReplaceOptions options); /** * Partially updates the edge identified by document-key. The value must contain a document with the attributes to * patch (the patch document). All attributes from the patch document will be added to the existing document if they * do not yet exist, and overwritten in the existing document if they do exist there. * - * @param key The key of the edge + * @param key The key of the edge * @param value A representation of a single edge (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) * @return information about the edge * @see API Documentation */ - EdgeUpdateEntity updateEdge(String key, Object value) ; + EdgeUpdateEntity updateEdge(String key, Object value); /** * Partially updates the edge identified by document-key. The value must contain a document with the attributes to @@ -132,7 +132,7 @@ public interface ArangoEdgeCollection extends ArangoSerdeAccessor { * @return information about the edge * @see API Documentation */ - EdgeUpdateEntity updateEdge(String key, Object value, EdgeUpdateOptions options) ; + EdgeUpdateEntity updateEdge(String key, Object value, EdgeUpdateOptions options); /** * Removes a edge @@ -140,7 +140,7 @@ public interface ArangoEdgeCollection extends ArangoSerdeAccessor { * @param key The key of the edge * @see API Documentation */ - void deleteEdge(String key) ; + void deleteEdge(String key); /** * Removes a edge @@ -149,6 +149,6 @@ public interface ArangoEdgeCollection extends ArangoSerdeAccessor { * @param options Additional options, can be null * @see API Documentation */ - void deleteEdge(String key, EdgeDeleteOptions options) ; + void deleteEdge(String key, EdgeDeleteOptions options); } diff --git a/src/main/java/com/arangodb/ArangoGraph.java b/src/main/java/com/arangodb/ArangoGraph.java index 0288b5768..445e38eb4 100644 --- a/src/main/java/com/arangodb/ArangoGraph.java +++ b/src/main/java/com/arangodb/ArangoGraph.java @@ -54,7 +54,7 @@ public interface ArangoGraph extends ArangoSerdeAccessor { * * @return true if the graph exists, otherwise false */ - boolean exists() ; + boolean exists(); /** * Creates the graph in the graph module. The creation of a graph requires the name of the graph and a definition of @@ -65,7 +65,7 @@ public interface ArangoGraph extends ArangoSerdeAccessor { * @see API * Documentation */ - GraphEntity create(Collection edgeDefinitions) ; + GraphEntity create(Collection edgeDefinitions); /** * Creates the graph in the graph module. The creation of a graph requires the name of the graph and a definition of @@ -77,14 +77,14 @@ public interface ArangoGraph extends ArangoSerdeAccessor { * @see API * Documentation */ - GraphEntity create(Collection edgeDefinitions, GraphCreateOptions options) ; + GraphEntity create(Collection edgeDefinitions, GraphCreateOptions options); /** * Deletes the graph from the database. * * @see API Documentation */ - void drop() ; + void drop(); /** * Deletes the graph from the database. @@ -95,7 +95,7 @@ public interface ArangoGraph extends ArangoSerdeAccessor { * "https://www.arangodb.com/docs/stable/http/gharial-management.html#drop-a-graph">API * Documentation */ - void drop(boolean dropCollections) ; + void drop(boolean dropCollections); /** * Retrieves general information about the graph. @@ -103,7 +103,7 @@ public interface ArangoGraph extends ArangoSerdeAccessor { * @return the definition content of this graph * @see API Documentation */ - GraphEntity getInfo() ; + GraphEntity getInfo(); /** * Fetches all vertex collections from the graph and returns a list of collection names. @@ -112,7 +112,7 @@ public interface ArangoGraph extends ArangoSerdeAccessor { * @see API * Documentation */ - Collection getVertexCollections() ; + Collection getVertexCollections(); /** * Adds a vertex collection to the set of collections of the graph. If the collection does not exist, it will be @@ -123,20 +123,20 @@ public interface ArangoGraph extends ArangoSerdeAccessor { * @see API * Documentation */ - GraphEntity addVertexCollection(String name) ; + GraphEntity addVertexCollection(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 Name of the vertex collection + * @param name Name of the vertex collection * @param options additional options * @return information about the graph * @see API * Documentation * @since ArangoDB 3.9 */ - GraphEntity addVertexCollection(String name, VertexCollectionCreateOptions options) ; + GraphEntity addVertexCollection(String name, VertexCollectionCreateOptions options); /** * Returns a {@code ArangoVertexCollection} instance for the given vertex collection name. @@ -161,7 +161,7 @@ public interface ArangoGraph extends ArangoSerdeAccessor { * @see API * Documentation */ - Collection getEdgeDefinitions() ; + Collection getEdgeDefinitions(); /** * Adds the given edge definition to the graph. @@ -171,7 +171,7 @@ public interface ArangoGraph extends ArangoSerdeAccessor { * @see API * Documentation */ - GraphEntity addEdgeDefinition(EdgeDefinition definition) ; + GraphEntity addEdgeDefinition(EdgeDefinition definition); /** * Change one specific edge definition. This will modify all occurrences of this definition in all graphs known to @@ -182,7 +182,7 @@ public interface ArangoGraph extends ArangoSerdeAccessor { * @see API * Documentation */ - GraphEntity replaceEdgeDefinition(EdgeDefinition definition) ; + GraphEntity replaceEdgeDefinition(EdgeDefinition definition); /** * Remove one edge definition from the graph. This will only remove the edge collection, the vertex collections @@ -194,6 +194,6 @@ public interface ArangoGraph extends ArangoSerdeAccessor { * "https://www.arangodb.com/docs/stable/http/gharial-management.html#remove-an-edge-definition-from-the-graph">API * Documentation */ - GraphEntity removeEdgeDefinition(String definitionName) ; + GraphEntity removeEdgeDefinition(String definitionName); } diff --git a/src/main/java/com/arangodb/ArangoRoute.java b/src/main/java/com/arangodb/ArangoRoute.java index ee343014b..f9aa6df0e 100644 --- a/src/main/java/com/arangodb/ArangoRoute.java +++ b/src/main/java/com/arangodb/ArangoRoute.java @@ -69,7 +69,7 @@ public interface ArangoRoute extends ArangoSerdeAccessor { * * @return server response */ - Response delete() ; + Response delete(); /** * Performs a GET request to the given URL and returns the server response. @@ -77,7 +77,7 @@ public interface ArangoRoute extends ArangoSerdeAccessor { * @return server response */ - Response get() ; + Response get(); /** * Performs a HEAD request to the given URL and returns the server response. @@ -85,7 +85,7 @@ public interface ArangoRoute extends ArangoSerdeAccessor { * @return server response */ - Response head() ; + Response head(); /** * Performs a PATCH request to the given URL and returns the server response. @@ -93,7 +93,7 @@ public interface ArangoRoute extends ArangoSerdeAccessor { * @return server response */ - Response patch() ; + Response patch(); /** * Performs a POST request to the given URL and returns the server response. @@ -101,7 +101,7 @@ public interface ArangoRoute extends ArangoSerdeAccessor { * @return server response */ - Response post() ; + Response post(); /** * Performs a PUT request to the given URL and returns the server response. @@ -109,6 +109,6 @@ public interface ArangoRoute extends ArangoSerdeAccessor { * @return server response */ - Response put() ; + Response put(); } diff --git a/src/main/java/com/arangodb/ArangoSearch.java b/src/main/java/com/arangodb/ArangoSearch.java index e587e32a6..e6c59b2bd 100644 --- a/src/main/java/com/arangodb/ArangoSearch.java +++ b/src/main/java/com/arangodb/ArangoSearch.java @@ -41,7 +41,7 @@ public interface ArangoSearch extends ArangoView { * @see API * Documentation */ - ViewEntity create() ; + ViewEntity create(); /** * Creates a view with the given {@code options}, then returns view information from the server. @@ -51,7 +51,7 @@ public interface ArangoSearch extends ArangoView { * @see API * Documentation */ - ViewEntity create(ArangoSearchCreateOptions options) ; + ViewEntity create(ArangoSearchCreateOptions options); /** * Reads the properties of the specified view. @@ -60,7 +60,7 @@ public interface ArangoSearch extends ArangoView { * @see API * Documentation */ - ArangoSearchPropertiesEntity getProperties() ; + ArangoSearchPropertiesEntity getProperties(); /** * Partially changes properties of the view. @@ -71,7 +71,7 @@ public interface ArangoSearch extends ArangoView { * "https://www.arangodb.com/docs/stable/http/views-arangosearch.html#partially-changes-properties-of-an-arangosearch-view">API * Documentation */ - ArangoSearchPropertiesEntity updateProperties(ArangoSearchPropertiesOptions options) ; + ArangoSearchPropertiesEntity updateProperties(ArangoSearchPropertiesOptions options); /** * Changes properties of the view. @@ -82,6 +82,6 @@ public interface ArangoSearch extends ArangoView { * "https://www.arangodb.com/docs/stable/http/views-arangosearch.html#change-properties-of-an-arangosearch-view">API * Documentation */ - ArangoSearchPropertiesEntity replaceProperties(ArangoSearchPropertiesOptions options) ; + ArangoSearchPropertiesEntity replaceProperties(ArangoSearchPropertiesOptions options); } diff --git a/src/main/java/com/arangodb/ArangoVertexCollection.java b/src/main/java/com/arangodb/ArangoVertexCollection.java index 163a80a30..7be0dd4f0 100644 --- a/src/main/java/com/arangodb/ArangoVertexCollection.java +++ b/src/main/java/com/arangodb/ArangoVertexCollection.java @@ -53,7 +53,7 @@ public interface ArangoVertexCollection extends ArangoSerdeAccessor { * @see API * Documentation */ - void drop() ; + void drop(); /** * Creates a new vertex in the collection @@ -62,7 +62,7 @@ public interface ArangoVertexCollection extends ArangoSerdeAccessor { * @return information about the vertex * @see API Documentation */ - VertexEntity insertVertex(Object value) ; + VertexEntity insertVertex(Object value); /** * Creates a new vertex in the collection @@ -72,7 +72,7 @@ public interface ArangoVertexCollection extends ArangoSerdeAccessor { * @return information about the vertex * @see API Documentation */ - VertexEntity insertVertex(Object value, VertexCreateOptions options) ; + VertexEntity insertVertex(Object value, VertexCreateOptions options); /** * Retrieves the vertex document with the given {@code key} from the collection. @@ -82,7 +82,7 @@ public interface ArangoVertexCollection extends ArangoSerdeAccessor { * @return the vertex identified by the key * @see API Documentation */ - T getVertex(String key, Class type) ; + T getVertex(String key, Class type); /** * Retrieves the vertex document with the given {@code key} from the collection. @@ -93,7 +93,7 @@ public interface ArangoVertexCollection extends ArangoSerdeAccessor { * @return the vertex identified by the key * @see API Documentation */ - T getVertex(String key, Class type, GraphDocumentReadOptions options) ; + T getVertex(String key, Class type, GraphDocumentReadOptions options); /** * Replaces the vertex with key with the one in the body, provided there is such a vertex and no precondition is @@ -105,7 +105,7 @@ public interface ArangoVertexCollection extends ArangoSerdeAccessor { * @see API * Documentation */ - VertexUpdateEntity replaceVertex(String key, Object value) ; + VertexUpdateEntity replaceVertex(String key, Object value); /** * Replaces the vertex with key with the one in the body, provided there is such a vertex and no precondition is @@ -118,19 +118,19 @@ public interface ArangoVertexCollection extends ArangoSerdeAccessor { * @see API * Documentation */ - VertexUpdateEntity replaceVertex(String key, Object value, VertexReplaceOptions options) ; + VertexUpdateEntity replaceVertex(String key, Object value, VertexReplaceOptions options); /** * Partially updates the vertex identified by document-key. The value must contain a document with the attributes to * patch (the patch document). All attributes from the patch document will be added to the existing document if they * do not yet exist, and overwritten in the existing document if they do exist there. * - * @param key The key of the vertex + * @param key The key of the vertex * @param value A representation of a single vertex (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) * @return information about the vertex * @see API Documentation */ - VertexUpdateEntity updateVertex(String key, Object value) ; + VertexUpdateEntity updateVertex(String key, Object value); /** * Partially updates the vertex identified by document-key. The value must contain a document with the attributes to @@ -143,7 +143,7 @@ public interface ArangoVertexCollection extends ArangoSerdeAccessor { * @return information about the vertex * @see API Documentation */ - VertexUpdateEntity updateVertex(String key, Object value, VertexUpdateOptions options) ; + VertexUpdateEntity updateVertex(String key, Object value, VertexUpdateOptions options); /** * Deletes the vertex with the given {@code key} from the collection. @@ -151,7 +151,7 @@ public interface ArangoVertexCollection extends ArangoSerdeAccessor { * @param key The key of the vertex * @see API Documentation */ - void deleteVertex(String key) ; + void deleteVertex(String key); /** * Deletes the vertex with the given {@code key} from the collection. @@ -160,6 +160,6 @@ public interface ArangoVertexCollection extends ArangoSerdeAccessor { * @param options Additional options, can be null * @see API Documentation */ - void deleteVertex(String key, VertexDeleteOptions options) ; + void deleteVertex(String key, VertexDeleteOptions options); } diff --git a/src/main/java/com/arangodb/ArangoView.java b/src/main/java/com/arangodb/ArangoView.java index 22f287ad3..dec2481bd 100644 --- a/src/main/java/com/arangodb/ArangoView.java +++ b/src/main/java/com/arangodb/ArangoView.java @@ -50,14 +50,14 @@ public interface ArangoView extends ArangoSerdeAccessor { * * @return true if the view exists, otherwise false */ - boolean exists() ; + boolean exists(); /** * Deletes the view from the database. * * @see API Documentation */ - void drop() ; + void drop(); /** * Renames the view. @@ -66,7 +66,7 @@ public interface ArangoView extends ArangoSerdeAccessor { * @return information about the view * @see API Documentation */ - ViewEntity rename(String newName) ; + ViewEntity rename(String newName); /** * Returns information about the view. @@ -75,6 +75,6 @@ public interface ArangoView extends ArangoSerdeAccessor { * @see API * Documentation */ - ViewEntity getInfo() ; + ViewEntity getInfo(); } diff --git a/src/main/java/com/arangodb/DbName.java b/src/main/java/com/arangodb/DbName.java index 70b3e5e42..37cffbe76 100644 --- a/src/main/java/com/arangodb/DbName.java +++ b/src/main/java/com/arangodb/DbName.java @@ -23,6 +23,10 @@ public final class DbName implements Supplier { private final String value; + private DbName(final String value) { + this.value = value; + } + /** * Creates a new {@link DbName} instance with the provided value. If the provided value is not * NFC-normalized, throws @@ -54,10 +58,6 @@ public static DbName normalize(final String value) { return new DbName(UnicodeUtils.normalize(value)); } - private DbName(final String value) { - this.value = value; - } - @Override public String get() { return value; diff --git a/src/main/java/com/arangodb/async/ArangoCollectionAsync.java b/src/main/java/com/arangodb/async/ArangoCollectionAsync.java index 84b9c0ee3..c18bd7aa1 100644 --- a/src/main/java/com/arangodb/async/ArangoCollectionAsync.java +++ b/src/main/java/com/arangodb/async/ArangoCollectionAsync.java @@ -20,7 +20,6 @@ package com.arangodb.async; -import com.arangodb.ArangoDBException; import com.arangodb.ArangoSerdeAccessor; import com.arangodb.entity.*; import com.arangodb.model.*; @@ -173,7 +172,7 @@ CompletableFuture importDocuments( * @see API * Documentation */ - CompletableFuture getDocument(final String key, final Class type) ; + CompletableFuture getDocument(final String key, final Class type); /** * Reads a single document @@ -185,9 +184,7 @@ CompletableFuture importDocuments( * @see API * Documentation */ - CompletableFuture getDocument(final String key, final Class type, final DocumentReadOptions options) - ; - + CompletableFuture getDocument(final String key, final Class type, final DocumentReadOptions options); /** * Reads multiple documents * diff --git a/src/main/java/com/arangodb/async/ArangoDBAsync.java b/src/main/java/com/arangodb/async/ArangoDBAsync.java index cc7926626..2b7a8521f 100644 --- a/src/main/java/com/arangodb/async/ArangoDBAsync.java +++ b/src/main/java/com/arangodb/async/ArangoDBAsync.java @@ -20,7 +20,10 @@ package com.arangodb.async; -import com.arangodb.*; +import com.arangodb.ArangoMetrics; +import com.arangodb.ArangoSerdeAccessor; +import com.arangodb.DbName; +import com.arangodb.Protocol; import com.arangodb.async.internal.ArangoDBAsyncImpl; import com.arangodb.async.internal.velocystream.VstCommunicationAsync; import com.arangodb.async.internal.velocystream.VstConnectionFactoryAsync; @@ -38,9 +41,9 @@ import com.arangodb.model.LogOptions; import com.arangodb.model.UserCreateOptions; import com.arangodb.model.UserUpdateOptions; +import com.arangodb.serde.ArangoSerde; import com.arangodb.serde.DataType; import com.arangodb.serde.JacksonSerde; -import com.arangodb.serde.ArangoSerde; import com.arangodb.velocystream.Request; import com.arangodb.velocystream.Response; import org.slf4j.Logger; @@ -67,7 +70,7 @@ */ public interface ArangoDBAsync extends ArangoSerdeAccessor { - void shutdown() ; + void shutdown(); /** * Updates the JWT used for requests authorization. It does not change already existing VST connections, since VST @@ -299,7 +302,7 @@ public interface ArangoDBAsync extends ArangoSerdeAccessor { * * @author Mark Vollmary */ - class Builder extends InternalArangoDBBuilder { + class Builder extends InternalArangoDBBuilder { private static final Logger logger = LoggerFactory.getLogger(Builder.class); @@ -308,7 +311,7 @@ public Builder() { } @Override - public Builder loadProperties(final InputStream in) { + public Builder loadProperties(final InputStream in) { super.loadProperties(in); return this; } @@ -506,7 +509,7 @@ public synchronized ArangoDBAsync build() { if (hosts.isEmpty()) { hosts.add(host); } - final ArangoSerde userSerde = customSerializer != null ? customSerializer : JacksonSerde.of(DataType.VPACK); + final ArangoSerde userSerde = customSerializer != null ? customSerializer : JacksonSerde.of(DataType.VPACK); final InternalSerde serde = InternalSerde.of(DataType.VPACK, userSerde); final int max = maxConnections != null ? Math.max(1, maxConnections) diff --git a/src/main/java/com/arangodb/async/ArangoDatabaseAsync.java b/src/main/java/com/arangodb/async/ArangoDatabaseAsync.java index 4b2b63c6b..62b709b64 100644 --- a/src/main/java/com/arangodb/async/ArangoDatabaseAsync.java +++ b/src/main/java/com/arangodb/async/ArangoDatabaseAsync.java @@ -20,7 +20,6 @@ package com.arangodb.async; -import com.arangodb.ArangoDBException; import com.arangodb.ArangoSerdeAccessor; import com.arangodb.DbName; import com.arangodb.entity.*; @@ -599,7 +598,7 @@ CompletableFuture createGraph( * @see API * Documentation */ - CompletableFuture getDocument(final String id, final Class type) ; + CompletableFuture getDocument(final String id, final Class type); /** * Reads a single document @@ -611,9 +610,7 @@ CompletableFuture createGraph( * @see API * Documentation */ - CompletableFuture getDocument(final String id, final Class type, final DocumentReadOptions options) - ; - + CompletableFuture getDocument(final String id, final Class type, final DocumentReadOptions options); /** * Reload the routing table. * diff --git a/src/main/java/com/arangodb/async/ArangoGraphAsync.java b/src/main/java/com/arangodb/async/ArangoGraphAsync.java index f7214d8d7..0c242261b 100644 --- a/src/main/java/com/arangodb/async/ArangoGraphAsync.java +++ b/src/main/java/com/arangodb/async/ArangoGraphAsync.java @@ -133,7 +133,7 @@ CompletableFuture createGraph( * 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 name The name of the collection * @param options additional options * @return information about the graph * @see API diff --git a/src/main/java/com/arangodb/async/internal/ArangoCollectionAsyncImpl.java b/src/main/java/com/arangodb/async/internal/ArangoCollectionAsyncImpl.java index 9712fa053..e71ac4fa0 100644 --- a/src/main/java/com/arangodb/async/internal/ArangoCollectionAsyncImpl.java +++ b/src/main/java/com/arangodb/async/internal/ArangoCollectionAsyncImpl.java @@ -111,7 +111,7 @@ public CompletableFuture importDocuments( } @Override - public CompletableFuture getDocument(final String key, final Class type) { + public CompletableFuture getDocument(final String key, final Class type) { return getDocument(key, type, new DocumentReadOptions()); } @@ -119,7 +119,7 @@ public CompletableFuture getDocument(final String key, final Class typ public CompletableFuture getDocument( final String key, final Class type, - final DocumentReadOptions options) { + final DocumentReadOptions options) { DocumentUtil.validateDocumentKey(key); return executor.execute(getDocumentRequest(key, options), getDocumentResponseDeserializer(type)) .exceptionally(ExceptionUtil.catchGetDocumentExceptions()); diff --git a/src/main/java/com/arangodb/async/internal/ArangoCursorAsyncImpl.java b/src/main/java/com/arangodb/async/internal/ArangoCursorAsyncImpl.java index 284a576b8..e8861a49e 100644 --- a/src/main/java/com/arangodb/async/internal/ArangoCursorAsyncImpl.java +++ b/src/main/java/com/arangodb/async/internal/ArangoCursorAsyncImpl.java @@ -21,10 +21,10 @@ package com.arangodb.async.internal; import com.arangodb.async.ArangoCursorAsync; -import com.arangodb.internal.cursor.entity.InternalCursorEntity; import com.arangodb.internal.ArangoCursorExecute; import com.arangodb.internal.InternalArangoDatabase; import com.arangodb.internal.cursor.ArangoCursorImpl; +import com.arangodb.internal.cursor.entity.InternalCursorEntity; import java.util.Spliterator; import java.util.Spliterators; diff --git a/src/main/java/com/arangodb/async/internal/ArangoDBAsyncImpl.java b/src/main/java/com/arangodb/async/internal/ArangoDBAsyncImpl.java index dce0333cd..04fafe5e6 100644 --- a/src/main/java/com/arangodb/async/internal/ArangoDBAsyncImpl.java +++ b/src/main/java/com/arangodb/async/internal/ArangoDBAsyncImpl.java @@ -94,7 +94,7 @@ protected ArangoExecutorAsync executor() { } @Override - public void shutdown() { + public void shutdown() { try { executor.disconnect(); } finally { diff --git a/src/main/java/com/arangodb/async/internal/ArangoDatabaseAsyncImpl.java b/src/main/java/com/arangodb/async/internal/ArangoDatabaseAsyncImpl.java index fdbd3dc84..af6a57832 100644 --- a/src/main/java/com/arangodb/async/internal/ArangoDatabaseAsyncImpl.java +++ b/src/main/java/com/arangodb/async/internal/ArangoDatabaseAsyncImpl.java @@ -386,15 +386,14 @@ public CompletableFuture getInfo() { } @Override - public CompletableFuture getDocument(final String id, final Class type) { + public CompletableFuture getDocument(final String id, final Class type) { DocumentUtil.validateDocumentId(id); final String[] split = id.split("/"); return collection(split[0]).getDocument(split[1], type); } @Override - public CompletableFuture getDocument(final String id, final Class type, final DocumentReadOptions options) - { + public CompletableFuture getDocument(final String id, final Class type, final DocumentReadOptions options) { DocumentUtil.validateDocumentId(id); final String[] split = id.split("/"); return collection(split[0]).getDocument(split[1], type, options); diff --git a/src/main/java/com/arangodb/async/internal/utils/CompletableFutureUtils.java b/src/main/java/com/arangodb/async/internal/utils/CompletableFutureUtils.java index 4648e5c0c..a8d3c0156 100644 --- a/src/main/java/com/arangodb/async/internal/utils/CompletableFutureUtils.java +++ b/src/main/java/com/arangodb/async/internal/utils/CompletableFutureUtils.java @@ -1,17 +1,9 @@ package com.arangodb.async.internal.utils; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.ScheduledFuture; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; +import java.util.concurrent.*; public class CompletableFutureUtils { - private CompletableFutureUtils() { - } - private static final ScheduledExecutorService timeoutScheduler = Executors.newSingleThreadScheduledExecutor(r -> { Thread t = Executors.defaultThreadFactory().newThread(r); t.setDaemon(true); @@ -19,6 +11,9 @@ private CompletableFutureUtils() { } ); + private CompletableFutureUtils() { + } + public static CompletableFuture orTimeout(CompletableFuture completableFuture, long timeout, TimeUnit unit) { ScheduledFuture timeoutTask = timeoutScheduler.schedule(() -> completableFuture.completeExceptionally(new TimeoutException()), timeout, unit); diff --git a/src/main/java/com/arangodb/async/internal/velocystream/VstCommunicationAsync.java b/src/main/java/com/arangodb/async/internal/velocystream/VstCommunicationAsync.java index e68efd1b6..b4690aaaf 100644 --- a/src/main/java/com/arangodb/async/internal/velocystream/VstCommunicationAsync.java +++ b/src/main/java/com/arangodb/async/internal/velocystream/VstCommunicationAsync.java @@ -25,12 +25,12 @@ import com.arangodb.internal.net.HostDescription; import com.arangodb.internal.net.HostHandle; import com.arangodb.internal.net.HostHandler; +import com.arangodb.internal.serde.InternalSerde; import com.arangodb.internal.util.HostUtils; import com.arangodb.internal.velocystream.VstCommunication; import com.arangodb.internal.velocystream.internal.AuthenticationRequest; import com.arangodb.internal.velocystream.internal.JwtAuthenticationRequest; import com.arangodb.internal.velocystream.internal.Message; -import com.arangodb.internal.serde.InternalSerde; import com.arangodb.velocypack.exception.VPackException; import com.arangodb.velocypack.exception.VPackParserException; import com.arangodb.velocystream.Request; diff --git a/src/main/java/com/arangodb/entity/AqlExecutionExplainEntity.java b/src/main/java/com/arangodb/entity/AqlExecutionExplainEntity.java index c95613764..2f586a268 100644 --- a/src/main/java/com/arangodb/entity/AqlExecutionExplainEntity.java +++ b/src/main/java/com/arangodb/entity/AqlExecutionExplainEntity.java @@ -28,6 +28,32 @@ */ public final class AqlExecutionExplainEntity { + private ExecutionPlan plan; + private Collection plans; + private Collection warnings; + private ExecutionStats stats; + private Boolean cacheable; + + public ExecutionPlan getPlan() { + return plan; + } + + public Collection getPlans() { + return plans; + } + + public Collection getWarnings() { + return warnings; + } + + public ExecutionStats getStats() { + return stats; + } + + public Boolean getCacheable() { + return cacheable; + } + public static final class ExecutionPlan { private Collection nodes; private Collection rules; @@ -267,30 +293,4 @@ public Integer getPlansCreated() { } - private ExecutionPlan plan; - private Collection plans; - private Collection warnings; - private ExecutionStats stats; - private Boolean cacheable; - - public ExecutionPlan getPlan() { - return plan; - } - - public Collection getPlans() { - return plans; - } - - public Collection getWarnings() { - return warnings; - } - - public ExecutionStats getStats() { - return stats; - } - - public Boolean getCacheable() { - return cacheable; - } - } diff --git a/src/main/java/com/arangodb/entity/AqlParseEntity.java b/src/main/java/com/arangodb/entity/AqlParseEntity.java index 9047a23e7..b50ae51e1 100644 --- a/src/main/java/com/arangodb/entity/AqlParseEntity.java +++ b/src/main/java/com/arangodb/entity/AqlParseEntity.java @@ -28,6 +28,22 @@ */ public final class AqlParseEntity { + private Collection collections; + private Collection bindVars; + private Collection ast; + + public Collection getCollections() { + return collections; + } + + public Collection getBindVars() { + return bindVars; + } + + public Collection getAst() { + return ast; + } + public static final class AstNode { private String type; private Collection subNodes; @@ -57,20 +73,4 @@ public Object getValue() { } - private Collection collections; - private Collection bindVars; - private Collection ast; - - public Collection getCollections() { - return collections; - } - - public Collection getBindVars() { - return bindVars; - } - - public Collection getAst() { - return ast; - } - } diff --git a/src/main/java/com/arangodb/entity/ArangoDBEngine.java b/src/main/java/com/arangodb/entity/ArangoDBEngine.java index 0cd2898d3..7ff44eba3 100644 --- a/src/main/java/com/arangodb/entity/ArangoDBEngine.java +++ b/src/main/java/com/arangodb/entity/ArangoDBEngine.java @@ -27,10 +27,6 @@ */ public final class ArangoDBEngine { - public enum StorageEngineName { - mmfiles, rocksdb - } - private StorageEngineName name; public ArangoDBEngine() { @@ -44,4 +40,8 @@ public StorageEngineName getName() { return name; } + public enum StorageEngineName { + mmfiles, rocksdb + } + } diff --git a/src/main/java/com/arangodb/entity/CollectionStatus.java b/src/main/java/com/arangodb/entity/CollectionStatus.java index 7cfa65c9d..b3d30f5d6 100644 --- a/src/main/java/com/arangodb/entity/CollectionStatus.java +++ b/src/main/java/com/arangodb/entity/CollectionStatus.java @@ -25,7 +25,7 @@ */ public enum CollectionStatus { - LOADED(3),DELETED(5); + LOADED(3), DELETED(5); private final int status; @@ -33,10 +33,6 @@ public enum CollectionStatus { this.status = status; } - public int getStatus() { - return status; - } - public static CollectionStatus fromStatus(final int status) { for (final CollectionStatus cStatus : CollectionStatus.values()) { if (cStatus.status == status) { @@ -46,4 +42,8 @@ public static CollectionStatus fromStatus(final int status) { return null; } + public int getStatus() { + return status; + } + } diff --git a/src/main/java/com/arangodb/entity/CollectionType.java b/src/main/java/com/arangodb/entity/CollectionType.java index af6f56797..7d771b67d 100644 --- a/src/main/java/com/arangodb/entity/CollectionType.java +++ b/src/main/java/com/arangodb/entity/CollectionType.java @@ -33,10 +33,6 @@ public enum CollectionType { this.type = type; } - public int getType() { - return type; - } - public static CollectionType fromType(final int type) { for (final CollectionType cType : CollectionType.values()) { if (cType.type == type) { @@ -45,4 +41,8 @@ public static CollectionType fromType(final int type) { } return null; } + + public int getType() { + return type; + } } diff --git a/src/main/java/com/arangodb/entity/EdgeDefinition.java b/src/main/java/com/arangodb/entity/EdgeDefinition.java index cd39c9a3b..a450726b0 100644 --- a/src/main/java/com/arangodb/entity/EdgeDefinition.java +++ b/src/main/java/com/arangodb/entity/EdgeDefinition.java @@ -30,10 +30,10 @@ */ public final class EdgeDefinition { + private final Options options = new Options(); private String collection; private Collection from; private Collection to; - private final Options options = new Options(); public String getCollection() { return collection; diff --git a/src/main/java/com/arangodb/entity/LogLevel.java b/src/main/java/com/arangodb/entity/LogLevel.java index 4e220339f..8895bfa7a 100644 --- a/src/main/java/com/arangodb/entity/LogLevel.java +++ b/src/main/java/com/arangodb/entity/LogLevel.java @@ -33,10 +33,6 @@ public enum LogLevel { this.level = level; } - public int getLevel() { - return level; - } - public static LogLevel fromLevel(final int level) { for (final LogLevel logLevel : LogLevel.values()) { if (logLevel.level == level) { @@ -46,4 +42,8 @@ public static LogLevel fromLevel(final int level) { return null; } + public int getLevel() { + return level; + } + } diff --git a/src/main/java/com/arangodb/entity/LogLevelEntity.java b/src/main/java/com/arangodb/entity/LogLevelEntity.java index a6e9ae702..ea590d988 100644 --- a/src/main/java/com/arangodb/entity/LogLevelEntity.java +++ b/src/main/java/com/arangodb/entity/LogLevelEntity.java @@ -25,10 +25,6 @@ */ public final class LogLevelEntity { - public enum LogLevel { - FATAL, ERROR, WARNING, INFO, DEBUG, TRACE, DEFAULT - } - private LogLevel all; private LogLevel agency; private LogLevel agencycomm; @@ -48,7 +44,6 @@ public enum LogLevel { private LogLevel startup; private LogLevel threads; private LogLevel v8; - public LogLevelEntity() { super(); } @@ -205,4 +200,8 @@ public void setV8(final LogLevel v8) { this.v8 = v8; } + public enum LogLevel { + FATAL, ERROR, WARNING, INFO, DEBUG, TRACE, DEFAULT + } + } diff --git a/src/main/java/com/arangodb/entity/QueryCachePropertiesEntity.java b/src/main/java/com/arangodb/entity/QueryCachePropertiesEntity.java index 67000290e..8f4655f22 100644 --- a/src/main/java/com/arangodb/entity/QueryCachePropertiesEntity.java +++ b/src/main/java/com/arangodb/entity/QueryCachePropertiesEntity.java @@ -28,13 +28,8 @@ */ public final class QueryCachePropertiesEntity { - public enum CacheMode { - off, on, demand - } - private CacheMode mode; private Long maxResults; - public QueryCachePropertiesEntity() { super(); } @@ -67,4 +62,8 @@ public void setMaxResults(final Long maxResults) { this.maxResults = maxResults; } + public enum CacheMode { + off, on, demand + } + } diff --git a/src/main/java/com/arangodb/entity/ReplicationFactor.java b/src/main/java/com/arangodb/entity/ReplicationFactor.java index f4278e972..f96ceb0dd 100644 --- a/src/main/java/com/arangodb/entity/ReplicationFactor.java +++ b/src/main/java/com/arangodb/entity/ReplicationFactor.java @@ -35,6 +35,15 @@ static SatelliteReplicationFactor ofSatellite() { @JsonValue Object getValue(); + enum SatelliteReplicationFactor implements ReplicationFactor { + INSTANCE; + + @Override + public String getValue() { + return "satellite"; + } + } + final class NumericReplicationFactor implements ReplicationFactor { private final Integer value; @@ -48,13 +57,4 @@ public Integer getValue() { return value; } } - - enum SatelliteReplicationFactor implements ReplicationFactor { - INSTANCE; - - @Override - public String getValue() { - return "satellite"; - } - } } diff --git a/src/main/java/com/arangodb/entity/arangosearch/analyzer/AQLAnalyzer.java b/src/main/java/com/arangodb/entity/arangosearch/analyzer/AQLAnalyzer.java index 4f453cdf2..428308712 100644 --- a/src/main/java/com/arangodb/entity/arangosearch/analyzer/AQLAnalyzer.java +++ b/src/main/java/com/arangodb/entity/arangosearch/analyzer/AQLAnalyzer.java @@ -33,12 +33,12 @@ * @since ArangoDB 3.8 */ public final class AQLAnalyzer extends SearchAnalyzer { + private AQLAnalyzerProperties properties; + public AQLAnalyzer() { setType(AnalyzerType.aql); } - private AQLAnalyzerProperties properties; - public AQLAnalyzerProperties getProperties() { return properties; } diff --git a/src/main/java/com/arangodb/entity/arangosearch/analyzer/AQLAnalyzerProperties.java b/src/main/java/com/arangodb/entity/arangosearch/analyzer/AQLAnalyzerProperties.java index aaa497dd6..84f9ab3b7 100644 --- a/src/main/java/com/arangodb/entity/arangosearch/analyzer/AQLAnalyzerProperties.java +++ b/src/main/java/com/arangodb/entity/arangosearch/analyzer/AQLAnalyzerProperties.java @@ -37,10 +37,6 @@ public final class AQLAnalyzerProperties { private ReturnType returnType; - public enum ReturnType { - string, number, bool - } - /** * @return AQL query to be executed */ @@ -137,4 +133,8 @@ public int hashCode() { return Objects.hash(queryString, collapsePositions, keepNull, batchSize, memoryLimit, returnType); } + public enum ReturnType { + string, number, bool + } + } diff --git a/src/main/java/com/arangodb/entity/arangosearch/analyzer/CollationAnalyzer.java b/src/main/java/com/arangodb/entity/arangosearch/analyzer/CollationAnalyzer.java index 47a588dc0..559c22def 100644 --- a/src/main/java/com/arangodb/entity/arangosearch/analyzer/CollationAnalyzer.java +++ b/src/main/java/com/arangodb/entity/arangosearch/analyzer/CollationAnalyzer.java @@ -34,12 +34,12 @@ * @since ArangoDB 3.9 */ public final class CollationAnalyzer extends SearchAnalyzer { + private CollationAnalyzerProperties properties; + public CollationAnalyzer() { setType(AnalyzerType.collation); } - private CollationAnalyzerProperties properties; - public CollationAnalyzerProperties getProperties() { return properties; } diff --git a/src/main/java/com/arangodb/entity/arangosearch/analyzer/DelimiterAnalyzer.java b/src/main/java/com/arangodb/entity/arangosearch/analyzer/DelimiterAnalyzer.java index 78306f0c1..eae42ae48 100644 --- a/src/main/java/com/arangodb/entity/arangosearch/analyzer/DelimiterAnalyzer.java +++ b/src/main/java/com/arangodb/entity/arangosearch/analyzer/DelimiterAnalyzer.java @@ -32,12 +32,12 @@ * @see API Documentation */ public final class DelimiterAnalyzer extends SearchAnalyzer { + private DelimiterAnalyzerProperties properties; + public DelimiterAnalyzer() { setType(AnalyzerType.delimiter); } - private DelimiterAnalyzerProperties properties; - public DelimiterAnalyzerProperties getProperties() { return properties; } diff --git a/src/main/java/com/arangodb/entity/arangosearch/analyzer/GeoJSONAnalyzer.java b/src/main/java/com/arangodb/entity/arangosearch/analyzer/GeoJSONAnalyzer.java index ea8fc9a70..d6e48662e 100644 --- a/src/main/java/com/arangodb/entity/arangosearch/analyzer/GeoJSONAnalyzer.java +++ b/src/main/java/com/arangodb/entity/arangosearch/analyzer/GeoJSONAnalyzer.java @@ -34,12 +34,12 @@ * @since ArangoDB 3.8 */ public final class GeoJSONAnalyzer extends SearchAnalyzer { + private GeoJSONAnalyzerProperties properties; + public GeoJSONAnalyzer() { setType(AnalyzerType.geojson); } - private GeoJSONAnalyzerProperties properties; - public GeoJSONAnalyzerProperties getProperties() { return properties; } diff --git a/src/main/java/com/arangodb/entity/arangosearch/analyzer/GeoJSONAnalyzerProperties.java b/src/main/java/com/arangodb/entity/arangosearch/analyzer/GeoJSONAnalyzerProperties.java index 3ef1cfb7f..9e43c6d3c 100644 --- a/src/main/java/com/arangodb/entity/arangosearch/analyzer/GeoJSONAnalyzerProperties.java +++ b/src/main/java/com/arangodb/entity/arangosearch/analyzer/GeoJSONAnalyzerProperties.java @@ -28,24 +28,6 @@ */ public final class GeoJSONAnalyzerProperties { - public enum GeoJSONAnalyzerType { - - /** - * (default): index all GeoJSON geometry types (Point, Polygon etc.) - */ - shape, - - /** - * compute and only index the centroid of the input geometry - */ - centroid, - - /** - * only index GeoJSON objects of type Point, ignore all other geometry types - */ - point - } - private GeoJSONAnalyzerType type; private GeoAnalyzerOptions options; @@ -81,4 +63,22 @@ public boolean equals(Object o) { public int hashCode() { return Objects.hash(type, options); } + + public enum GeoJSONAnalyzerType { + + /** + * (default): index all GeoJSON geometry types (Point, Polygon etc.) + */ + shape, + + /** + * compute and only index the centroid of the input geometry + */ + centroid, + + /** + * only index GeoJSON objects of type Point, ignore all other geometry types + */ + point + } } diff --git a/src/main/java/com/arangodb/entity/arangosearch/analyzer/GeoPointAnalyzer.java b/src/main/java/com/arangodb/entity/arangosearch/analyzer/GeoPointAnalyzer.java index af1890582..b88694c70 100644 --- a/src/main/java/com/arangodb/entity/arangosearch/analyzer/GeoPointAnalyzer.java +++ b/src/main/java/com/arangodb/entity/arangosearch/analyzer/GeoPointAnalyzer.java @@ -34,12 +34,12 @@ * @since ArangoDB 3.8 */ public final class GeoPointAnalyzer extends SearchAnalyzer { + private GeoPointAnalyzerProperties properties; + public GeoPointAnalyzer() { setType(AnalyzerType.geopoint); } - private GeoPointAnalyzerProperties properties; - public GeoPointAnalyzerProperties getProperties() { return properties; } diff --git a/src/main/java/com/arangodb/entity/arangosearch/analyzer/NGramAnalyzer.java b/src/main/java/com/arangodb/entity/arangosearch/analyzer/NGramAnalyzer.java index 83125fa0f..43cb3e23d 100644 --- a/src/main/java/com/arangodb/entity/arangosearch/analyzer/NGramAnalyzer.java +++ b/src/main/java/com/arangodb/entity/arangosearch/analyzer/NGramAnalyzer.java @@ -37,12 +37,12 @@ * @see API Documentation */ public final class NGramAnalyzer extends SearchAnalyzer { + private NGramAnalyzerProperties properties; + public NGramAnalyzer() { setType(AnalyzerType.ngram); } - private NGramAnalyzerProperties properties; - public NGramAnalyzerProperties getProperties() { return properties; } diff --git a/src/main/java/com/arangodb/entity/arangosearch/analyzer/NGramAnalyzerProperties.java b/src/main/java/com/arangodb/entity/arangosearch/analyzer/NGramAnalyzerProperties.java index 90b577225..53d51672d 100644 --- a/src/main/java/com/arangodb/entity/arangosearch/analyzer/NGramAnalyzerProperties.java +++ b/src/main/java/com/arangodb/entity/arangosearch/analyzer/NGramAnalyzerProperties.java @@ -73,7 +73,7 @@ public void setMax(long max) { /** * @return true to include the original value as well - * false to produce the n-grams based on min and max only + * false to produce the n-grams based on min and max only */ public boolean isPreserveOriginal() { return preserveOriginal; diff --git a/src/main/java/com/arangodb/entity/arangosearch/analyzer/NormAnalyzer.java b/src/main/java/com/arangodb/entity/arangosearch/analyzer/NormAnalyzer.java index 43ac0a335..1073204c2 100644 --- a/src/main/java/com/arangodb/entity/arangosearch/analyzer/NormAnalyzer.java +++ b/src/main/java/com/arangodb/entity/arangosearch/analyzer/NormAnalyzer.java @@ -32,12 +32,12 @@ * @see API Documentation */ public final class NormAnalyzer extends SearchAnalyzer { + private NormAnalyzerProperties properties; + public NormAnalyzer() { setType(AnalyzerType.norm); } - private NormAnalyzerProperties properties; - public NormAnalyzerProperties getProperties() { return properties; } diff --git a/src/main/java/com/arangodb/entity/arangosearch/analyzer/NormAnalyzerProperties.java b/src/main/java/com/arangodb/entity/arangosearch/analyzer/NormAnalyzerProperties.java index 72258ea83..17b3df2d3 100644 --- a/src/main/java/com/arangodb/entity/arangosearch/analyzer/NormAnalyzerProperties.java +++ b/src/main/java/com/arangodb/entity/arangosearch/analyzer/NormAnalyzerProperties.java @@ -52,7 +52,7 @@ public void setLocale(String locale) { /** * @return true to preserve accented characters (default) - * false to convert accented characters to their base characters + * false to convert accented characters to their base characters */ public boolean isAccent() { return accent; diff --git a/src/main/java/com/arangodb/entity/arangosearch/analyzer/PipelineAnalyzer.java b/src/main/java/com/arangodb/entity/arangosearch/analyzer/PipelineAnalyzer.java index 9319f38e6..d80efe8ef 100644 --- a/src/main/java/com/arangodb/entity/arangosearch/analyzer/PipelineAnalyzer.java +++ b/src/main/java/com/arangodb/entity/arangosearch/analyzer/PipelineAnalyzer.java @@ -32,18 +32,19 @@ * LIMITATIONS: Analyzers of types {@link GeoPointAnalyzer} and {@link GeoJSONAnalyzer} cannot be used in pipelines and * will make the creation fail. *

+ * * @author Michele Rastelli * @see API Documentation * @since ArangoDB 3.8 */ public final class PipelineAnalyzer extends SearchAnalyzer { + private PipelineAnalyzerProperties properties; + public PipelineAnalyzer() { setType(AnalyzerType.pipeline); } - private PipelineAnalyzerProperties properties; - public PipelineAnalyzerProperties getProperties() { return properties; } diff --git a/src/main/java/com/arangodb/entity/arangosearch/analyzer/SegmentationAnalyzer.java b/src/main/java/com/arangodb/entity/arangosearch/analyzer/SegmentationAnalyzer.java index 6b2f449b3..9a218a4af 100644 --- a/src/main/java/com/arangodb/entity/arangosearch/analyzer/SegmentationAnalyzer.java +++ b/src/main/java/com/arangodb/entity/arangosearch/analyzer/SegmentationAnalyzer.java @@ -36,12 +36,12 @@ * @since ArangoDB 3.9 */ public final class SegmentationAnalyzer extends SearchAnalyzer { + private SegmentationAnalyzerProperties properties; + public SegmentationAnalyzer() { setType(AnalyzerType.segmentation); } - private SegmentationAnalyzerProperties properties; - public SegmentationAnalyzerProperties getProperties() { return properties; } diff --git a/src/main/java/com/arangodb/entity/arangosearch/analyzer/SegmentationAnalyzerProperties.java b/src/main/java/com/arangodb/entity/arangosearch/analyzer/SegmentationAnalyzerProperties.java index a98b39b76..f674d6e34 100644 --- a/src/main/java/com/arangodb/entity/arangosearch/analyzer/SegmentationAnalyzerProperties.java +++ b/src/main/java/com/arangodb/entity/arangosearch/analyzer/SegmentationAnalyzerProperties.java @@ -59,10 +59,6 @@ public void setAnalyzerCase(SearchAnalyzerCase analyzerCase) { this.analyzerCase = analyzerCase; } - public enum BreakMode { - all, alpha, graphic - } - @Override public boolean equals(Object o) { if (this == o) return true; @@ -75,4 +71,8 @@ public boolean equals(Object o) { public int hashCode() { return Objects.hash(breakMode, analyzerCase); } + + public enum BreakMode { + all, alpha, graphic + } } diff --git a/src/main/java/com/arangodb/entity/arangosearch/analyzer/StemAnalyzer.java b/src/main/java/com/arangodb/entity/arangosearch/analyzer/StemAnalyzer.java index 0e4fb9cb0..bc48869c2 100644 --- a/src/main/java/com/arangodb/entity/arangosearch/analyzer/StemAnalyzer.java +++ b/src/main/java/com/arangodb/entity/arangosearch/analyzer/StemAnalyzer.java @@ -32,12 +32,12 @@ * @see API Documentation */ public final class StemAnalyzer extends SearchAnalyzer { + private StemAnalyzerProperties properties; + public StemAnalyzer() { setType(AnalyzerType.stem); } - private StemAnalyzerProperties properties; - public StemAnalyzerProperties getProperties() { return properties; } diff --git a/src/main/java/com/arangodb/entity/arangosearch/analyzer/StopwordsAnalyzer.java b/src/main/java/com/arangodb/entity/arangosearch/analyzer/StopwordsAnalyzer.java index c1041e293..34c31617c 100644 --- a/src/main/java/com/arangodb/entity/arangosearch/analyzer/StopwordsAnalyzer.java +++ b/src/main/java/com/arangodb/entity/arangosearch/analyzer/StopwordsAnalyzer.java @@ -33,12 +33,12 @@ * @since ArangoDB 3.8 */ public final class StopwordsAnalyzer extends SearchAnalyzer { + private StopwordsAnalyzerProperties properties; + public StopwordsAnalyzer() { setType(AnalyzerType.stopwords); } - private StopwordsAnalyzerProperties properties; - public StopwordsAnalyzerProperties getProperties() { return properties; } diff --git a/src/main/java/com/arangodb/entity/arangosearch/analyzer/StopwordsAnalyzerProperties.java b/src/main/java/com/arangodb/entity/arangosearch/analyzer/StopwordsAnalyzerProperties.java index b6f570267..daa3d4e04 100644 --- a/src/main/java/com/arangodb/entity/arangosearch/analyzer/StopwordsAnalyzerProperties.java +++ b/src/main/java/com/arangodb/entity/arangosearch/analyzer/StopwordsAnalyzerProperties.java @@ -33,6 +33,14 @@ */ public final class StopwordsAnalyzerProperties { + private final List stopwords; + private final boolean hex; + + public StopwordsAnalyzerProperties() { + stopwords = new ArrayList<>(); + hex = true; + } + private static String stringToHex(String str) { final StringBuilder hex = new StringBuilder(); for (final char temp : str.toCharArray()) { @@ -51,14 +59,6 @@ private static String hexToString(String hex) { return result.toString(); } - public StopwordsAnalyzerProperties() { - stopwords = new ArrayList<>(); - hex = true; - } - - private final List stopwords; - private final boolean hex; - public List getStopwords() { return stopwords; } diff --git a/src/main/java/com/arangodb/entity/arangosearch/analyzer/TextAnalyzer.java b/src/main/java/com/arangodb/entity/arangosearch/analyzer/TextAnalyzer.java index 8bde16668..13f1d2112 100644 --- a/src/main/java/com/arangodb/entity/arangosearch/analyzer/TextAnalyzer.java +++ b/src/main/java/com/arangodb/entity/arangosearch/analyzer/TextAnalyzer.java @@ -33,12 +33,12 @@ * @see API Documentation */ public final class TextAnalyzer extends SearchAnalyzer { + private TextAnalyzerProperties properties; + public TextAnalyzer() { setType(AnalyzerType.text); } - private TextAnalyzerProperties properties; - public TextAnalyzerProperties getProperties() { return properties; } diff --git a/src/main/java/com/arangodb/entity/arangosearch/analyzer/TextAnalyzerProperties.java b/src/main/java/com/arangodb/entity/arangosearch/analyzer/TextAnalyzerProperties.java index 38cbebe89..6ea4667e8 100644 --- a/src/main/java/com/arangodb/entity/arangosearch/analyzer/TextAnalyzerProperties.java +++ b/src/main/java/com/arangodb/entity/arangosearch/analyzer/TextAnalyzerProperties.java @@ -32,25 +32,19 @@ */ public final class TextAnalyzerProperties { - public TextAnalyzerProperties() { - stopwords = Collections.emptyList(); - } - private String locale; - private boolean accent; - @JsonProperty("case") private SearchAnalyzerCase analyzerCase; - private boolean stemming; - private EdgeNgram edgeNgram; - private List stopwords; - private String stopwordsPath; + public TextAnalyzerProperties() { + stopwords = Collections.emptyList(); + } + /** * @return a locale in the format `language[_COUNTRY][.encoding][@variant]` (square brackets denote optional parts), * e.g. `de.utf-8` or `en_US.utf-8`. Only UTF-8 encoding is meaningful in ArangoDB. diff --git a/src/main/java/com/arangodb/internal/ArangoCollectionImpl.java b/src/main/java/com/arangodb/internal/ArangoCollectionImpl.java index 44cc9ed39..dd2428f27 100644 --- a/src/main/java/com/arangodb/internal/ArangoCollectionImpl.java +++ b/src/main/java/com/arangodb/internal/ArangoCollectionImpl.java @@ -46,27 +46,25 @@ protected ArangoCollectionImpl(final ArangoDatabaseImpl db, final String name) { } @Override - public DocumentCreateEntity insertDocument(final Object value) { + public DocumentCreateEntity insertDocument(final Object value) { return executor.execute(insertDocumentRequest(value, new DocumentCreateOptions()), constructParametricType(DocumentCreateEntity.class, Void.class)); } @Override @SuppressWarnings("unchecked") - public DocumentCreateEntity insertDocument(final T value, final DocumentCreateOptions options) - { + public DocumentCreateEntity insertDocument(final T value, final DocumentCreateOptions options) { return insertDocument(value, options, (Class) value.getClass()); } @Override - public DocumentCreateEntity insertDocument(final T value, final DocumentCreateOptions options, final Class type) { + public DocumentCreateEntity insertDocument(final T value, final DocumentCreateOptions options, final Class type) { return executor.execute(insertDocumentRequest(value, options), constructParametricType(DocumentCreateEntity.class, type)); } @Override - public MultiDocumentEntity> insertDocuments(final Collection values) - { + public MultiDocumentEntity> insertDocuments(final Collection values) { return executor .execute(insertDocumentsRequest(values, new DocumentCreateOptions()), insertDocumentsResponseDeserializer(Void.class)); } @@ -74,46 +72,43 @@ public MultiDocumentEntity> insertDocuments(final Col @Override @SuppressWarnings("unchecked") public MultiDocumentEntity> insertDocuments( - final Collection values, final DocumentCreateOptions options) { + final Collection values, final DocumentCreateOptions options) { return insertDocuments(values, options, (Class) getCollectionContentClass(values)); } @Override - public MultiDocumentEntity> insertDocuments(Collection values, DocumentCreateOptions options, Class type) { + public MultiDocumentEntity> insertDocuments(Collection values, DocumentCreateOptions options, Class type) { return executor .execute(insertDocumentsRequest(values, options), insertDocumentsResponseDeserializer(type)); } @Override - public DocumentImportEntity importDocuments(final Collection values) { + public DocumentImportEntity importDocuments(final Collection values) { return importDocuments(values, new DocumentImportOptions()); } @Override - public DocumentImportEntity importDocuments(final Collection values, final DocumentImportOptions options) - { + public DocumentImportEntity importDocuments(final Collection values, final DocumentImportOptions options) { return executor.execute(importDocumentsRequest(values, options), DocumentImportEntity.class); } @Override - public DocumentImportEntity importDocuments(final String values) { + public DocumentImportEntity importDocuments(final String values) { return importDocuments(values, new DocumentImportOptions()); } @Override - public DocumentImportEntity importDocuments(final String values, final DocumentImportOptions options) - { + public DocumentImportEntity importDocuments(final String values, final DocumentImportOptions options) { return executor.execute(importDocumentsRequest(values, options), DocumentImportEntity.class); } @Override - public T getDocument(final String key, final Class type) { + public T getDocument(final String key, final Class type) { return getDocument(key, type, new DocumentReadOptions()); } @Override - public T getDocument(final String key, final Class type, final DocumentReadOptions options) - { + public T getDocument(final String key, final Class type, final DocumentReadOptions options) { DocumentUtil.validateDocumentKey(key); try { return executor.execute(getDocumentRequest(key, options), getDocumentResponseDeserializer(type)); @@ -136,20 +131,18 @@ public T getDocument(final String key, final Class type, final DocumentRe } @Override - public MultiDocumentEntity getDocuments(final Collection keys, final Class type) - { + public MultiDocumentEntity getDocuments(final Collection keys, final Class type) { return getDocuments(keys, type, new DocumentReadOptions()); } @Override public MultiDocumentEntity getDocuments( - final Collection keys, final Class type, final DocumentReadOptions options) - { + final Collection keys, final Class type, final DocumentReadOptions options) { return executor.execute(getDocumentsRequest(keys, options), getDocumentsResponseDeserializer(type, options)); } @Override - public DocumentUpdateEntity replaceDocument(final String key, final Object value) { + public DocumentUpdateEntity replaceDocument(final String key, final Object value) { return executor.execute(replaceDocumentRequest(key, value, new DocumentReplaceOptions()), constructParametricType(DocumentUpdateEntity.class, Void.class)); } @@ -157,108 +150,103 @@ public DocumentUpdateEntity replaceDocument(final String key, final Object @Override @SuppressWarnings("unchecked") public DocumentUpdateEntity replaceDocument( - final String key, final T value, final DocumentReplaceOptions options) { + final String key, final T value, final DocumentReplaceOptions options) { return replaceDocument(key, value, options, (Class) value.getClass()); } @Override - public DocumentUpdateEntity replaceDocument(String key, T value, DocumentReplaceOptions options, Class type) { + public DocumentUpdateEntity replaceDocument(String key, T value, DocumentReplaceOptions options, Class type) { return executor.execute(replaceDocumentRequest(key, value, options), constructParametricType(DocumentUpdateEntity.class, type)); } @Override - public MultiDocumentEntity> replaceDocuments(final Collection values) - { + public MultiDocumentEntity> replaceDocuments(final Collection values) { return executor.execute(replaceDocumentsRequest(values, new DocumentReplaceOptions()), replaceDocumentsResponseDeserializer(Void.class)); } @Override @SuppressWarnings("unchecked") public MultiDocumentEntity> replaceDocuments( - final Collection values, final DocumentReplaceOptions options) { + final Collection values, final DocumentReplaceOptions options) { return replaceDocuments(values, options, (Class) getCollectionContentClass(values)); } @Override - public MultiDocumentEntity> replaceDocuments(Collection values, DocumentReplaceOptions options, Class type) { + public MultiDocumentEntity> replaceDocuments(Collection values, DocumentReplaceOptions options, Class type) { return executor.execute(replaceDocumentsRequest(values, options), replaceDocumentsResponseDeserializer(type)); } @Override - public DocumentUpdateEntity updateDocument(final String key, final Object value) { + public DocumentUpdateEntity updateDocument(final String key, final Object value) { return updateDocument(key, value, new DocumentUpdateOptions(), Void.class); } @Override @SuppressWarnings("unchecked") public DocumentUpdateEntity updateDocument( - final String key, final T value, final DocumentUpdateOptions options) { + final String key, final T value, final DocumentUpdateOptions options) { return updateDocument(key, value, options, (Class) value.getClass()); } @Override public DocumentUpdateEntity updateDocument( - final String key, final Object value, final DocumentUpdateOptions options, final Class returnType) { + final String key, final Object value, final DocumentUpdateOptions options, final Class returnType) { return executor.execute(updateDocumentRequest(key, value, options), constructParametricType(DocumentUpdateEntity.class, returnType)); } @Override - public MultiDocumentEntity> updateDocuments(final Collection values) - { + public MultiDocumentEntity> updateDocuments(final Collection values) { return updateDocuments(values, new DocumentUpdateOptions(), Void.class); } @Override @SuppressWarnings("unchecked") public MultiDocumentEntity> updateDocuments( - final Collection values, final DocumentUpdateOptions options) { + final Collection values, final DocumentUpdateOptions options) { return updateDocuments(values, options, (Class) getCollectionContentClass(values)); } @Override public MultiDocumentEntity> updateDocuments( - final Collection values, final DocumentUpdateOptions options, final Class returnType) { + final Collection values, final DocumentUpdateOptions options, final Class returnType) { return executor .execute(updateDocumentsRequest(values, options), updateDocumentsResponseDeserializer(returnType)); } @Override - public DocumentDeleteEntity deleteDocument(final String key) { + public DocumentDeleteEntity deleteDocument(final String key) { return deleteDocument(key, new DocumentDeleteOptions()); } @Override - public DocumentDeleteEntity deleteDocument(String key, DocumentDeleteOptions options) { + public DocumentDeleteEntity deleteDocument(String key, DocumentDeleteOptions options) { return deleteDocument(key, options, Void.class); } @Override public DocumentDeleteEntity deleteDocument( - final String key, final DocumentDeleteOptions options, final Class type) { + final String key, final DocumentDeleteOptions options, final Class type) { return executor.execute(deleteDocumentRequest(key, options), constructParametricType(DocumentDeleteEntity.class, type)); } @Override - public MultiDocumentEntity> deleteDocuments(final Collection values) - { + public MultiDocumentEntity> deleteDocuments(final Collection values) { return deleteDocuments(values, new DocumentDeleteOptions(), Void.class); } @Override @SuppressWarnings("unchecked") public MultiDocumentEntity> deleteDocuments( - final Collection values, final DocumentDeleteOptions options) - { + final Collection values, final DocumentDeleteOptions options) { return deleteDocuments(values, options, (Class) getCollectionContentClass(values)); } @Override public MultiDocumentEntity> deleteDocuments( - final Collection values, final DocumentDeleteOptions options, final Class type) - { + final Collection values, final DocumentDeleteOptions options, final Class type) { return executor.execute(deleteDocumentsRequest(values, options), deleteDocumentsResponseDeserializer(type)); } @@ -268,7 +256,7 @@ public Boolean documentExists(final String key) { } @Override - public Boolean documentExists(final String key, final DocumentExistsOptions options) { + public Boolean documentExists(final String key, final DocumentExistsOptions options) { try { executor.execute(documentExistsRequest(key, options), Void.class); return true; @@ -288,66 +276,59 @@ public Boolean documentExists(final String key, final DocumentExistsOptions opti } @Override - public IndexEntity getIndex(final String id) { + public IndexEntity getIndex(final String id) { return executor.execute(getIndexRequest(id), IndexEntity.class); } @Override - public String deleteIndex(final String id) { + public String deleteIndex(final String id) { return executor.execute(deleteIndexRequest(id), deleteIndexResponseDeserializer()); } @Deprecated @Override - public IndexEntity ensureHashIndex(final Iterable fields, final HashIndexOptions options) - { + public IndexEntity ensureHashIndex(final Iterable fields, final HashIndexOptions options) { return executor.execute(createHashIndexRequest(fields, options), IndexEntity.class); } @Deprecated @Override - public IndexEntity ensureSkiplistIndex(final Iterable fields, final SkiplistIndexOptions options) - { + public IndexEntity ensureSkiplistIndex(final Iterable fields, final SkiplistIndexOptions options) { return executor.execute(createSkiplistIndexRequest(fields, options), IndexEntity.class); } @Override - public IndexEntity ensurePersistentIndex(final Iterable fields, final PersistentIndexOptions options) - { + public IndexEntity ensurePersistentIndex(final Iterable fields, final PersistentIndexOptions options) { return executor.execute(createPersistentIndexRequest(fields, options), IndexEntity.class); } @Override - public IndexEntity ensureGeoIndex(final Iterable fields, final GeoIndexOptions options) - { + public IndexEntity ensureGeoIndex(final Iterable fields, final GeoIndexOptions options) { return executor.execute(createGeoIndexRequest(fields, options), IndexEntity.class); } @Override - public IndexEntity ensureFulltextIndex(final Iterable fields, final FulltextIndexOptions options) - { + public IndexEntity ensureFulltextIndex(final Iterable fields, final FulltextIndexOptions options) { return executor.execute(createFulltextIndexRequest(fields, options), IndexEntity.class); } @Override - public IndexEntity ensureTtlIndex(final Iterable fields, final TtlIndexOptions options) - { + public IndexEntity ensureTtlIndex(final Iterable fields, final TtlIndexOptions options) { return executor.execute(createTtlIndexRequest(fields, options), IndexEntity.class); } @Override - public IndexEntity ensureZKDIndex(final Iterable fields, final ZKDIndexOptions options) - { + public IndexEntity ensureZKDIndex(final Iterable fields, final ZKDIndexOptions options) { return executor.execute(createZKDIndexRequest(fields, options), IndexEntity.class); } @Override - public Collection getIndexes() { + public Collection getIndexes() { return executor.execute(getIndexesRequest(), getIndexesResponseDeserializer()); } @Override - public boolean exists() { + public boolean exists() { try { getInfo(); return true; @@ -360,95 +341,94 @@ public boolean exists() { } @Override - public CollectionEntity truncate() { + public CollectionEntity truncate() { return truncate(null); } @Override - public CollectionEntity truncate(CollectionTruncateOptions options) { + public CollectionEntity truncate(CollectionTruncateOptions options) { return executor.execute(truncateRequest(options), CollectionEntity.class); } @Override - public CollectionPropertiesEntity count() { + public CollectionPropertiesEntity count() { return count(null); } @Override - public CollectionPropertiesEntity count(CollectionCountOptions options) { + public CollectionPropertiesEntity count(CollectionCountOptions options) { return executor.execute(countRequest(options), CollectionPropertiesEntity.class); } @Override - public CollectionEntity create() { + public CollectionEntity create() { return db().createCollection(name()); } @Override - public CollectionEntity create(final CollectionCreateOptions options) { + public CollectionEntity create(final CollectionCreateOptions options) { return db().createCollection(name(), options); } @Override - public void drop() { + public void drop() { executor.execute(dropRequest(null), Void.class); } @Override - public void drop(final boolean isSystem) { + public void drop(final boolean isSystem) { executor.execute(dropRequest(isSystem), Void.class); } @Override - public CollectionEntity getInfo() { + public CollectionEntity getInfo() { return executor.execute(getInfoRequest(), CollectionEntity.class); } @Override - public CollectionPropertiesEntity getProperties() { + public CollectionPropertiesEntity getProperties() { return executor.execute(getPropertiesRequest(), CollectionPropertiesEntity.class); } @Override - public CollectionPropertiesEntity changeProperties(final CollectionPropertiesOptions options) - { + public CollectionPropertiesEntity changeProperties(final CollectionPropertiesOptions options) { return executor.execute(changePropertiesRequest(options), CollectionPropertiesEntity.class); } @Override - public synchronized CollectionEntity rename(final String newName) { + public synchronized CollectionEntity rename(final String newName) { final CollectionEntity result = executor.execute(renameRequest(newName), CollectionEntity.class); name = result.getName(); return result; } @Override - public ShardEntity getResponsibleShard(final Object value) { + public ShardEntity getResponsibleShard(final Object value) { return executor.execute(responsibleShardRequest(value), ShardEntity.class); } @Override - public CollectionRevisionEntity getRevision() { + public CollectionRevisionEntity getRevision() { return executor.execute(getRevisionRequest(), CollectionRevisionEntity.class); } @Override - public void grantAccess(final String user, final Permissions permissions) { + public void grantAccess(final String user, final Permissions permissions) { executor.execute(grantAccessRequest(user, permissions), Void.class); } @Override - public void revokeAccess(final String user) { + public void revokeAccess(final String user) { executor.execute(grantAccessRequest(user, Permissions.NONE), Void.class); } @Override - public void resetAccess(final String user) { + public void resetAccess(final String user) { executor.execute(resetAccessRequest(user), Void.class); } @Override - public Permissions getPermissions(final String user) { + public Permissions getPermissions(final String user) { return executor.execute(getPermissionsRequest(user), getPermissionsResponseDeserialzer()); } diff --git a/src/main/java/com/arangodb/internal/ArangoCursorExecute.java b/src/main/java/com/arangodb/internal/ArangoCursorExecute.java index dbc07231a..e9a6512af 100644 --- a/src/main/java/com/arangodb/internal/ArangoCursorExecute.java +++ b/src/main/java/com/arangodb/internal/ArangoCursorExecute.java @@ -20,7 +20,6 @@ package com.arangodb.internal; -import com.arangodb.ArangoDBException; import com.arangodb.internal.cursor.entity.InternalCursorEntity; import java.util.Map; @@ -30,8 +29,8 @@ */ public interface ArangoCursorExecute { - InternalCursorEntity next(String id, Map meta) ; + InternalCursorEntity next(String id, Map meta); - void close(String id, Map meta) ; + void close(String id, Map meta); } diff --git a/src/main/java/com/arangodb/internal/ArangoDBImpl.java b/src/main/java/com/arangodb/internal/ArangoDBImpl.java index 391e91ac8..876da7493 100644 --- a/src/main/java/com/arangodb/internal/ArangoDBImpl.java +++ b/src/main/java/com/arangodb/internal/ArangoDBImpl.java @@ -52,10 +52,9 @@ public class ArangoDBImpl extends InternalArangoDB implements ArangoDB { private static final Logger LOGGER = LoggerFactory.getLogger(ArangoDBImpl.class); - - private ArangoCursorInitializer cursorInitializer; private final CommunicationProtocol cp; private final HostHandler hostHandler; + private ArangoCursorInitializer cursorInitializer; public ArangoDBImpl(final VstCommunicationSync.Builder vstBuilder, final HttpCommunication.Builder httpBuilder, final InternalSerde util, final Protocol protocol, final HostResolver hostResolver, @@ -108,7 +107,7 @@ protected ArangoExecutorSync executor() { } @Override - public void shutdown() { + public void shutdown() { try { executor.disconnect(); } finally { @@ -143,121 +142,119 @@ public ArangoMetrics metrics() { } @Override - public Boolean createDatabase(final DbName dbName) { + public Boolean createDatabase(final DbName dbName) { return createDatabase(new DBCreateOptions().name(dbName)); } @Override - public Boolean createDatabase(DBCreateOptions options) { + public Boolean createDatabase(DBCreateOptions options) { return executor.execute(createDatabaseRequest(options), createDatabaseResponseDeserializer()); } @Override - public Collection getDatabases() { + public Collection getDatabases() { return executor.execute(getDatabasesRequest(db().dbName()), getDatabaseResponseDeserializer()); } @Override - public Collection getAccessibleDatabases() { + public Collection getAccessibleDatabases() { return db().getAccessibleDatabases(); } @Override - public Collection getAccessibleDatabasesFor(final String user) { + public Collection getAccessibleDatabasesFor(final String user) { return executor.execute(getAccessibleDatabasesForRequest(db().dbName(), user), getAccessibleDatabasesForResponseDeserializer()); } @Override - public ArangoDBVersion getVersion() { + public ArangoDBVersion getVersion() { return db().getVersion(); } @Override - public ArangoDBEngine getEngine() { + public ArangoDBEngine getEngine() { return db().getEngine(); } @Override - public ServerRole getRole() { + public ServerRole getRole() { return executor.execute(getRoleRequest(), getRoleResponseDeserializer()); } @Override - public String getServerId() { + public String getServerId() { return executor.execute(getServerIdRequest(), getServerIdResponseDeserializer()); } @Override - public UserEntity createUser(final String user, final String passwd) { + public UserEntity createUser(final String user, final String passwd) { return executor.execute(createUserRequest(db().dbName(), user, passwd, new UserCreateOptions()), UserEntity.class); } @Override - public UserEntity createUser(final String user, final String passwd, final UserCreateOptions options) - { + public UserEntity createUser(final String user, final String passwd, final UserCreateOptions options) { return executor.execute(createUserRequest(db().dbName(), user, passwd, options), UserEntity.class); } @Override - public void deleteUser(final String user) { + public void deleteUser(final String user) { executor.execute(deleteUserRequest(db().dbName(), user), Void.class); } @Override - public UserEntity getUser(final String user) { + public UserEntity getUser(final String user) { return executor.execute(getUserRequest(db().dbName(), user), UserEntity.class); } @Override - public Collection getUsers() { + public Collection getUsers() { return executor.execute(getUsersRequest(db().dbName()), getUsersResponseDeserializer()); } @Override - public UserEntity updateUser(final String user, final UserUpdateOptions options) { + public UserEntity updateUser(final String user, final UserUpdateOptions options) { return executor.execute(updateUserRequest(db().dbName(), user, options), UserEntity.class); } @Override - public UserEntity replaceUser(final String user, final UserUpdateOptions options) { + public UserEntity replaceUser(final String user, final UserUpdateOptions options) { return executor.execute(replaceUserRequest(db().dbName(), user, options), UserEntity.class); } @Override - public void grantDefaultDatabaseAccess(final String user, final Permissions permissions) { + public void grantDefaultDatabaseAccess(final String user, final Permissions permissions) { executor.execute(updateUserDefaultDatabaseAccessRequest(user, permissions), Void.class); } @Override - public void grantDefaultCollectionAccess(final String user, final Permissions permissions) - { + public void grantDefaultCollectionAccess(final String user, final Permissions permissions) { executor.execute(updateUserDefaultCollectionAccessRequest(user, permissions), Void.class); } @Override - public Response execute(final Request request) { + public Response execute(final Request request) { return executor.execute(request, response -> response); } @Override - public Response execute(final Request request, final HostHandle hostHandle) { + public Response execute(final Request request, final HostHandle hostHandle) { return executor.execute(request, response -> response, hostHandle); } @Override - public LogEntriesEntity getLogEntries(final LogOptions options) { + public LogEntriesEntity getLogEntries(final LogOptions options) { return executor.execute(getLogEntriesRequest(options), LogEntriesEntity.class); } @Override - public LogLevelEntity getLogLevel() { + public LogLevelEntity getLogLevel() { return executor.execute(getLogLevelRequest(), LogLevelEntity.class); } @Override - public LogLevelEntity setLogLevel(final LogLevelEntity entity) { + public LogLevelEntity setLogLevel(final LogLevelEntity entity) { return executor.execute(setLogLevelRequest(entity), LogLevelEntity.class); } diff --git a/src/main/java/com/arangodb/internal/ArangoDatabaseImpl.java b/src/main/java/com/arangodb/internal/ArangoDatabaseImpl.java index fbd173ae2..9aad69fad 100644 --- a/src/main/java/com/arangodb/internal/ArangoDatabaseImpl.java +++ b/src/main/java/com/arangodb/internal/ArangoDatabaseImpl.java @@ -53,17 +53,17 @@ protected ArangoDatabaseImpl(final ArangoDBImpl arangoDB, final DbName name) { } @Override - public ArangoDBVersion getVersion() { + public ArangoDBVersion getVersion() { return executor.execute(getVersionRequest(), ArangoDBVersion.class); } @Override - public ArangoDBEngine getEngine() { + public ArangoDBEngine getEngine() { return executor.execute(getEngineRequest(), ArangoDBEngine.class); } @Override - public boolean exists() { + public boolean exists() { try { getInfo(); return true; @@ -76,7 +76,7 @@ public boolean exists() { } @Override - public Collection getAccessibleDatabases() { + public Collection getAccessibleDatabases() { return executor.execute(getAccessibleDatabasesRequest(), getDatabaseResponseDeserializer()); } @@ -86,86 +86,83 @@ public ArangoCollection collection(final String name) { } @Override - public CollectionEntity createCollection(final String name) { + public CollectionEntity createCollection(final String name) { return executor.execute(createCollectionRequest(name, new CollectionCreateOptions()), CollectionEntity.class); } @Override - public CollectionEntity createCollection(final String name, final CollectionCreateOptions options) - { + public CollectionEntity createCollection(final String name, final CollectionCreateOptions options) { return executor.execute(createCollectionRequest(name, options), CollectionEntity.class); } @Override - public Collection getCollections() { + public Collection getCollections() { return executor .execute(getCollectionsRequest(new CollectionsReadOptions()), getCollectionsResponseDeserializer()); } @Override - public Collection getCollections(final CollectionsReadOptions options) { + public Collection getCollections(final CollectionsReadOptions options) { return executor.execute(getCollectionsRequest(options), getCollectionsResponseDeserializer()); } @Override - public IndexEntity getIndex(final String id) { + public IndexEntity getIndex(final String id) { DocumentUtil.validateIndexId(id); final String[] split = id.split("/"); return collection(split[0]).getIndex(split[1]); } @Override - public String deleteIndex(final String id) { + public String deleteIndex(final String id) { DocumentUtil.validateIndexId(id); final String[] split = id.split("/"); return collection(split[0]).deleteIndex(split[1]); } @Override - public Boolean create() { + public Boolean create() { return arango().createDatabase(dbName()); } @Override - public Boolean drop() { + public Boolean drop() { return executor.execute(dropRequest(), createDropResponseDeserializer()); } @Override - public void grantAccess(final String user, final Permissions permissions) { + public void grantAccess(final String user, final Permissions permissions) { executor.execute(grantAccessRequest(user, permissions), Void.class); } @Override - public void grantAccess(final String user) { + public void grantAccess(final String user) { executor.execute(grantAccessRequest(user, Permissions.RW), Void.class); } @Override - public void revokeAccess(final String user) { + public void revokeAccess(final String user) { executor.execute(grantAccessRequest(user, Permissions.NONE), Void.class); } @Override - public void resetAccess(final String user) { + public void resetAccess(final String user) { executor.execute(resetAccessRequest(user), Void.class); } @Override - public void grantDefaultCollectionAccess(final String user, final Permissions permissions) - { + public void grantDefaultCollectionAccess(final String user, final Permissions permissions) { executor.execute(updateUserDefaultCollectionAccessRequest(user, permissions), Void.class); } @Override - public Permissions getPermissions(final String user) { + public Permissions getPermissions(final String user) { return executor.execute(getPermissionsRequest(user), getPermissionsResponseDeserialzer()); } @Override public ArangoCursor query( - final String query, final Map bindVars, final AqlQueryOptions options, final Class type) - { + final String query, final Map bindVars, final AqlQueryOptions options, final Class type) { final Request request = queryRequest(query, bindVars, options); final HostHandle hostHandle = new HostHandle(); @@ -177,23 +174,22 @@ public ArangoCursor query( @Override public ArangoCursor query( - final String query, final Map bindVars, final Class type) { + final String query, final Map bindVars, final Class type) { return query(query, bindVars, null, type); } @Override - public ArangoCursor query(final String query, final AqlQueryOptions options, final Class type) - { + public ArangoCursor query(final String query, final AqlQueryOptions options, final Class type) { return query(query, null, options, type); } @Override - public ArangoCursor query(final String query, final Class type) { + public ArangoCursor query(final String query, final Class type) { return query(query, null, null, type); } @Override - public ArangoCursor cursor(final String cursorId, final Class type) { + public ArangoCursor cursor(final String cursorId, final Class type) { final HostHandle hostHandle = new HostHandle(); final InternalCursorEntity result = executor .execute(queryNextRequest(cursorId, null, null), InternalCursorEntity.class, hostHandle); @@ -225,79 +221,75 @@ public void close(final String id, Map meta) { @Override public AqlExecutionExplainEntity explainQuery( - final String query, final Map bindVars, final AqlQueryExplainOptions options) - { + final String query, final Map bindVars, final AqlQueryExplainOptions options) { return executor.execute(explainQueryRequest(query, bindVars, options), AqlExecutionExplainEntity.class); } @Override - public AqlParseEntity parseQuery(final String query) { + public AqlParseEntity parseQuery(final String query) { return executor.execute(parseQueryRequest(query), AqlParseEntity.class); } @Override - public void clearQueryCache() { + public void clearQueryCache() { executor.execute(clearQueryCacheRequest(), Void.class); } @Override - public QueryCachePropertiesEntity getQueryCacheProperties() { + public QueryCachePropertiesEntity getQueryCacheProperties() { return executor.execute(getQueryCachePropertiesRequest(), QueryCachePropertiesEntity.class); } @Override - public QueryCachePropertiesEntity setQueryCacheProperties(final QueryCachePropertiesEntity properties) - { + public QueryCachePropertiesEntity setQueryCacheProperties(final QueryCachePropertiesEntity properties) { return executor.execute(setQueryCachePropertiesRequest(properties), QueryCachePropertiesEntity.class); } @Override - public QueryTrackingPropertiesEntity getQueryTrackingProperties() { + public QueryTrackingPropertiesEntity getQueryTrackingProperties() { return executor.execute(getQueryTrackingPropertiesRequest(), QueryTrackingPropertiesEntity.class); } @Override - public QueryTrackingPropertiesEntity setQueryTrackingProperties(final QueryTrackingPropertiesEntity properties) - { + public QueryTrackingPropertiesEntity setQueryTrackingProperties(final QueryTrackingPropertiesEntity properties) { return executor.execute(setQueryTrackingPropertiesRequest(properties), QueryTrackingPropertiesEntity.class); } @Override - public Collection getCurrentlyRunningQueries() { + public Collection getCurrentlyRunningQueries() { return executor.execute(getCurrentlyRunningQueriesRequest(), constructListType(QueryEntity.class)); } @Override - public Collection getSlowQueries() { + public Collection getSlowQueries() { return executor.execute(getSlowQueriesRequest(), constructListType(QueryEntity.class)); } @Override - public void clearSlowQueries() { + public void clearSlowQueries() { executor.execute(clearSlowQueriesRequest(), Void.class); } @Override - public void killQuery(final String id) { + public void killQuery(final String id) { executor.execute(killQueryRequest(id), Void.class); } @Override public void createAqlFunction( - final String name, final String code, final AqlFunctionCreateOptions options) { + final String name, final String code, final AqlFunctionCreateOptions options) { executor.execute(createAqlFunctionRequest(name, code, options), Void.class); } @Override - public Integer deleteAqlFunction(final String name, final AqlFunctionDeleteOptions options) - { + public Integer deleteAqlFunction(final String name, final AqlFunctionDeleteOptions options) { return executor.execute(deleteAqlFunctionRequest(name, options), deleteAqlFunctionResponseDeserializer()); } @Override - public Collection getAqlFunctions(final AqlFunctionGetOptions options) { + public Collection getAqlFunctions(final AqlFunctionGetOptions options) { return executor.execute(getAqlFunctionsRequest(options), getAqlFunctionsResponseDeserializer()); } @@ -307,77 +299,73 @@ public ArangoGraph graph(final String name) { } @Override - public GraphEntity createGraph(final String name, final Collection edgeDefinitions) - { + public GraphEntity createGraph(final String name, final Collection edgeDefinitions) { return executor.execute(createGraphRequest(name, edgeDefinitions, new GraphCreateOptions()), createGraphResponseDeserializer()); } @Override public GraphEntity createGraph( - final String name, final Collection edgeDefinitions, final GraphCreateOptions options) - { + final String name, final Collection edgeDefinitions, final GraphCreateOptions options) { return executor.execute(createGraphRequest(name, edgeDefinitions, options), createGraphResponseDeserializer()); } @Override - public Collection getGraphs() { + public Collection getGraphs() { return executor.execute(getGraphsRequest(), getGraphsResponseDeserializer()); } @Override - public T transaction(final String action, final Class type, final TransactionOptions options) - { + public T transaction(final String action, final Class type, final TransactionOptions options) { return executor.execute(transactionRequest(action, options), transactionResponseDeserializer(type)); } @Override - public StreamTransactionEntity beginStreamTransaction(StreamTransactionOptions options) { + public StreamTransactionEntity beginStreamTransaction(StreamTransactionOptions options) { return executor.execute(beginStreamTransactionRequest(options), streamTransactionResponseDeserializer()); } @Override - public StreamTransactionEntity abortStreamTransaction(String id) { + public StreamTransactionEntity abortStreamTransaction(String id) { return executor.execute(abortStreamTransactionRequest(id), streamTransactionResponseDeserializer()); } @Override - public StreamTransactionEntity getStreamTransaction(String id) { + public StreamTransactionEntity getStreamTransaction(String id) { return executor.execute(getStreamTransactionRequest(id), streamTransactionResponseDeserializer()); } @Override - public Collection getStreamTransactions() { + public Collection getStreamTransactions() { return executor.execute(getStreamTransactionsRequest(), transactionsResponseDeserializer()); } @Override - public StreamTransactionEntity commitStreamTransaction(String id) { + public StreamTransactionEntity commitStreamTransaction(String id) { return executor.execute(commitStreamTransactionRequest(id), streamTransactionResponseDeserializer()); } @Override - public DatabaseEntity getInfo() { + public DatabaseEntity getInfo() { return executor.execute(getInfoRequest(), getInfoResponseDeserializer()); } @Override - public T getDocument(final String id, final Class type) { + public T getDocument(final String id, final Class type) { DocumentUtil.validateDocumentId(id); final String[] split = id.split("/"); return collection(split[0]).getDocument(split[1], type); } @Override - public T getDocument(final String id, final Class type, final DocumentReadOptions options) - { + public T getDocument(final String id, final Class type, final DocumentReadOptions options) { DocumentUtil.validateDocumentId(id); final String[] split = id.split("/"); return collection(split[0]).getDocument(split[1], type, options); } @Override - public void reloadRouting() { + public void reloadRouting() { executor.execute(reloadRoutingRequest(), Void.class); } @@ -392,7 +380,7 @@ public ArangoRoute route(final String... path) { } @Override - public Collection getViews() { + public Collection getViews() { return executor.execute(getViewsRequest(), getViewsResponseDeserializer()); } @@ -407,38 +395,37 @@ public ArangoSearch arangoSearch(final String name) { } @Override - public ViewEntity createView(final String name, final ViewType type) { + public ViewEntity createView(final String name, final ViewType type) { return executor.execute(createViewRequest(name, type), ViewEntity.class); } @Override - public ViewEntity createArangoSearch(final String name, final ArangoSearchCreateOptions options) - { + public ViewEntity createArangoSearch(final String name, final ArangoSearchCreateOptions options) { return executor.execute(createArangoSearchRequest(name, options), ViewEntity.class); } @Override - public SearchAnalyzer createSearchAnalyzer(SearchAnalyzer analyzer) { + public SearchAnalyzer createSearchAnalyzer(SearchAnalyzer analyzer) { return executor.execute(createAnalyzerRequest(analyzer), SearchAnalyzer.class); } @Override - public SearchAnalyzer getSearchAnalyzer(String name) { + public SearchAnalyzer getSearchAnalyzer(String name) { return executor.execute(getAnalyzerRequest(name), SearchAnalyzer.class); } @Override - public Collection getSearchAnalyzers() { + public Collection getSearchAnalyzers() { return executor.execute(getAnalyzersRequest(), getSearchAnalyzersResponseDeserializer()); } @Override - public void deleteSearchAnalyzer(String name) { + public void deleteSearchAnalyzer(String name) { deleteSearchAnalyzer(name, null); } @Override - public void deleteSearchAnalyzer(String name, AnalyzerDeleteOptions options) { + public void deleteSearchAnalyzer(String name, AnalyzerDeleteOptions options) { executor.execute(deleteAnalyzerRequest(name, options), Void.class); } diff --git a/src/main/java/com/arangodb/internal/ArangoDefaults.java b/src/main/java/com/arangodb/internal/ArangoDefaults.java index 43a2f1ba3..c86675a52 100644 --- a/src/main/java/com/arangodb/internal/ArangoDefaults.java +++ b/src/main/java/com/arangodb/internal/ArangoDefaults.java @@ -28,13 +28,8 @@ */ public final class ArangoDefaults { - private ArangoDefaults() { - super(); - } - public static final int INTEGER_BYTES = Integer.SIZE / Byte.SIZE; public static final int LONG_BYTES = Long.SIZE / Byte.SIZE; - public static final String DEFAULT_HOST = "127.0.0.1"; public static final Integer DEFAULT_PORT = 8529; public static final Integer DEFAULT_TIMEOUT = 0; @@ -51,5 +46,8 @@ private ArangoDefaults() { public static final int DEFAULT_ACQUIRE_HOST_LIST_INTERVAL = 60 * 60 * 1000; // hour public static final LoadBalancingStrategy DEFAULT_LOAD_BALANCING_STRATEGY = LoadBalancingStrategy.NONE; public static final int DEFAULT_RESPONSE_QUEUE_TIME_SAMPLES = 10; + private ArangoDefaults() { + super(); + } } diff --git a/src/main/java/com/arangodb/internal/ArangoEdgeCollectionImpl.java b/src/main/java/com/arangodb/internal/ArangoEdgeCollectionImpl.java index bde8b1804..ebf39627b 100644 --- a/src/main/java/com/arangodb/internal/ArangoEdgeCollectionImpl.java +++ b/src/main/java/com/arangodb/internal/ArangoEdgeCollectionImpl.java @@ -42,18 +42,18 @@ protected ArangoEdgeCollectionImpl(final ArangoGraphImpl graph, final String nam } @Override - public EdgeEntity insertEdge(final Object value) { + public EdgeEntity insertEdge(final Object value) { return executor.execute(insertEdgeRequest(value, new EdgeCreateOptions()), insertEdgeResponseDeserializer(value)); } @Override - public EdgeEntity insertEdge(final Object value, final EdgeCreateOptions options) { + public EdgeEntity insertEdge(final Object value, final EdgeCreateOptions options) { return executor.execute(insertEdgeRequest(value, options), insertEdgeResponseDeserializer(value)); } @Override - public T getEdge(final String key, final Class type) { + public T getEdge(final String key, final Class type) { try { return executor.execute(getEdgeRequest(key, new GraphDocumentReadOptions()), getEdgeResponseDeserializer(type)); } catch (final ArangoDBException e) { @@ -65,8 +65,7 @@ public T getEdge(final String key, final Class type) { } @Override - public T getEdge(final String key, final Class type, final GraphDocumentReadOptions options) - { + public T getEdge(final String key, final Class type, final GraphDocumentReadOptions options) { try { return executor.execute(getEdgeRequest(key, options), getEdgeResponseDeserializer(type)); } catch (final ArangoDBException e) { @@ -78,36 +77,34 @@ public T getEdge(final String key, final Class type, final GraphDocumentR } @Override - public EdgeUpdateEntity replaceEdge(final String key, final Object value) { + public EdgeUpdateEntity replaceEdge(final String key, final Object value) { return executor.execute(replaceEdgeRequest(key, value, new EdgeReplaceOptions()), replaceEdgeResponseDeserializer(value)); } @Override - public EdgeUpdateEntity replaceEdge(final String key, final Object value, final EdgeReplaceOptions options) - { + public EdgeUpdateEntity replaceEdge(final String key, final Object value, final EdgeReplaceOptions options) { return executor.execute(replaceEdgeRequest(key, value, options), replaceEdgeResponseDeserializer(value)); } @Override - public EdgeUpdateEntity updateEdge(final String key, final Object value) { + public EdgeUpdateEntity updateEdge(final String key, final Object value) { return executor.execute(updateEdgeRequest(key, value, new EdgeUpdateOptions()), updateEdgeResponseDeserializer(value)); } @Override - public EdgeUpdateEntity updateEdge(final String key, final Object value, final EdgeUpdateOptions options) - { + public EdgeUpdateEntity updateEdge(final String key, final Object value, final EdgeUpdateOptions options) { return executor.execute(updateEdgeRequest(key, value, options), updateEdgeResponseDeserializer(value)); } @Override - public void deleteEdge(final String key) { + public void deleteEdge(final String key) { executor.execute(deleteEdgeRequest(key, new EdgeDeleteOptions()), Void.class); } @Override - public void deleteEdge(final String key, final EdgeDeleteOptions options) { + public void deleteEdge(final String key, final EdgeDeleteOptions options) { executor.execute(deleteEdgeRequest(key, options), Void.class); } diff --git a/src/main/java/com/arangodb/internal/ArangoErrors.java b/src/main/java/com/arangodb/internal/ArangoErrors.java index ba2bc5f57..442fa3aab 100644 --- a/src/main/java/com/arangodb/internal/ArangoErrors.java +++ b/src/main/java/com/arangodb/internal/ArangoErrors.java @@ -25,13 +25,12 @@ */ public final class ArangoErrors { - private ArangoErrors() { - super(); - } - public static final Integer ERROR_ARANGO_DATA_SOURCE_NOT_FOUND = 1203; public static final Integer ERROR_ARANGO_DATABASE_NOT_FOUND = 1228; public static final Integer ERROR_GRAPH_NOT_FOUND = 1924; public static final Integer QUEUE_TIME_VIOLATED = 21004; + private ArangoErrors() { + super(); + } } diff --git a/src/main/java/com/arangodb/internal/ArangoExecuteable.java b/src/main/java/com/arangodb/internal/ArangoExecuteable.java index ef70238b3..63d0d0b07 100644 --- a/src/main/java/com/arangodb/internal/ArangoExecuteable.java +++ b/src/main/java/com/arangodb/internal/ArangoExecuteable.java @@ -22,8 +22,8 @@ import com.arangodb.ArangoSerdeAccessor; import com.arangodb.DbName; -import com.arangodb.internal.util.EncodeUtils; import com.arangodb.internal.serde.InternalSerde; +import com.arangodb.internal.util.EncodeUtils; import com.arangodb.velocystream.Request; import com.arangodb.velocystream.RequestType; @@ -47,23 +47,6 @@ protected ArangoExecuteable(final E executor, final InternalSerde serde, final A this.context = context; } - protected E executor() { - return executor; - } - - @Override - public InternalSerde getSerde() { - return serde; - } - - protected Request request(final DbName dbName, final RequestType requestType, final String... path) { - final Request request = new Request(dbName, requestType, createPath(path)); - for (final Entry header : context.getHeaderParam().entrySet()) { - request.putHeaderParam(header.getKey(), header.getValue()); - } - return request; - } - protected static String createPath(final String... params) { final StringBuilder sb = new StringBuilder(); for (int i = 0; i < params.length; i++) { @@ -81,4 +64,21 @@ protected static String createPath(final String... params) { return sb.toString(); } + protected E executor() { + return executor; + } + + @Override + public InternalSerde getSerde() { + return serde; + } + + protected Request request(final DbName dbName, final RequestType requestType, final String... path) { + final Request request = new Request(dbName, requestType, createPath(path)); + for (final Entry header : context.getHeaderParam().entrySet()) { + request.putHeaderParam(header.getKey(), header.getValue()); + } + return request; + } + } diff --git a/src/main/java/com/arangodb/internal/ArangoExecutor.java b/src/main/java/com/arangodb/internal/ArangoExecutor.java index 2cf453b05..fede702f5 100644 --- a/src/main/java/com/arangodb/internal/ArangoExecutor.java +++ b/src/main/java/com/arangodb/internal/ArangoExecutor.java @@ -32,14 +32,9 @@ */ public abstract class ArangoExecutor { - protected T createResult(final Type type, final Response response) { - return serde.deserialize(response.getBody(), type); - } - private final QueueTimeMetricsImpl qtMetrics; private final InternalSerde serde; private final String timeoutS; - protected ArangoExecutor(final InternalSerde serde, final QueueTimeMetricsImpl qtMetrics, final int timeoutMs) { super(); this.qtMetrics = qtMetrics; @@ -47,8 +42,8 @@ protected ArangoExecutor(final InternalSerde serde, final QueueTimeMetricsImpl q timeoutS = timeoutMs >= 1000 ? Integer.toString(timeoutMs / 1000) : null; } - public interface ResponseDeserializer { - T deserialize(Response response); + protected T createResult(final Type type, final Response response) { + return serde.deserialize(response.getBody(), type); } protected final void interceptResponse(Response response) { @@ -66,4 +61,8 @@ protected final Request interceptRequest(Request request) { public QueueTimeMetrics getQueueTimeMetrics() { return qtMetrics; } + + public interface ResponseDeserializer { + T deserialize(Response response); + } } diff --git a/src/main/java/com/arangodb/internal/ArangoExecutorSync.java b/src/main/java/com/arangodb/internal/ArangoExecutorSync.java index 4e81c50cf..ddaf8ceff 100644 --- a/src/main/java/com/arangodb/internal/ArangoExecutorSync.java +++ b/src/main/java/com/arangodb/internal/ArangoExecutorSync.java @@ -48,22 +48,22 @@ public ArangoExecutorSync(final CommunicationProtocol protocol, final InternalSe this.protocol = protocol; } - public T execute(final Request request, final Type type) { + public T execute(final Request request, final Type type) { return execute(request, type, null); } - public T execute(final Request request, final Type type, final HostHandle hostHandle) { + public T execute(final Request request, final Type type, final HostHandle hostHandle) { return execute(request, response -> createResult(type, response), hostHandle); } - public T execute(final Request request, final ResponseDeserializer responseDeserializer) { + public T execute(final Request request, final ResponseDeserializer responseDeserializer) { return execute(request, responseDeserializer, null); } public T execute( final Request request, final ResponseDeserializer responseDeserializer, - final HostHandle hostHandle) { + final HostHandle hostHandle) { final Response response = protocol.execute(interceptRequest(request), hostHandle); interceptResponse(response); diff --git a/src/main/java/com/arangodb/internal/ArangoGraphImpl.java b/src/main/java/com/arangodb/internal/ArangoGraphImpl.java index 246e862b5..adc737f36 100644 --- a/src/main/java/com/arangodb/internal/ArangoGraphImpl.java +++ b/src/main/java/com/arangodb/internal/ArangoGraphImpl.java @@ -42,7 +42,7 @@ protected ArangoGraphImpl(final ArangoDatabaseImpl db, final String name) { } @Override - public boolean exists() { + public boolean exists() { try { getInfo(); return true; @@ -55,43 +55,42 @@ public boolean exists() { } @Override - public GraphEntity create(final Collection edgeDefinitions) { + public GraphEntity create(final Collection edgeDefinitions) { return db().createGraph(name(), edgeDefinitions); } @Override - public GraphEntity create(final Collection edgeDefinitions, final GraphCreateOptions options) - { + public GraphEntity create(final Collection edgeDefinitions, final GraphCreateOptions options) { return db().createGraph(name(), edgeDefinitions, options); } @Override - public void drop() { + public void drop() { executor.execute(dropRequest(), Void.class); } @Override - public void drop(final boolean dropCollections) { + public void drop(final boolean dropCollections) { executor.execute(dropRequest(dropCollections), Void.class); } @Override - public GraphEntity getInfo() { + public GraphEntity getInfo() { return executor.execute(getInfoRequest(), getInfoResponseDeserializer()); } @Override - public Collection getVertexCollections() { + public Collection getVertexCollections() { return executor.execute(getVertexCollectionsRequest(), getVertexCollectionsResponseDeserializer()); } @Override - public GraphEntity addVertexCollection(final String name) { + public GraphEntity addVertexCollection(final String name) { return addVertexCollection(name, new VertexCollectionCreateOptions()); } @Override - public GraphEntity addVertexCollection(final String name, final VertexCollectionCreateOptions options) { + public GraphEntity addVertexCollection(final String name, final VertexCollectionCreateOptions options) { return executor.execute(addVertexCollectionRequest(name, options), addVertexCollectionResponseDeserializer()); } @@ -106,22 +105,22 @@ public ArangoEdgeCollection edgeCollection(final String name) { } @Override - public Collection getEdgeDefinitions() { + public Collection getEdgeDefinitions() { return executor.execute(getEdgeDefinitionsRequest(), getEdgeDefinitionsDeserializer()); } @Override - public GraphEntity addEdgeDefinition(final EdgeDefinition definition) { + public GraphEntity addEdgeDefinition(final EdgeDefinition definition) { return executor.execute(addEdgeDefinitionRequest(definition), addEdgeDefinitionResponseDeserializer()); } @Override - public GraphEntity replaceEdgeDefinition(final EdgeDefinition definition) { + public GraphEntity replaceEdgeDefinition(final EdgeDefinition definition) { return executor.execute(replaceEdgeDefinitionRequest(definition), replaceEdgeDefinitionResponseDeserializer()); } @Override - public GraphEntity removeEdgeDefinition(final String definitionName) { + public GraphEntity removeEdgeDefinition(final String definitionName) { return executor.execute(removeEdgeDefinitionRequest(definitionName), removeEdgeDefinitionResponseDeserializer()); } diff --git a/src/main/java/com/arangodb/internal/ArangoRequestParam.java b/src/main/java/com/arangodb/internal/ArangoRequestParam.java index 62c9be370..cd016ccc5 100644 --- a/src/main/java/com/arangodb/internal/ArangoRequestParam.java +++ b/src/main/java/com/arangodb/internal/ArangoRequestParam.java @@ -25,15 +25,14 @@ */ public final class ArangoRequestParam { - private ArangoRequestParam() { - super(); - } - public static final String SYSTEM = "_system"; public static final String DATABASE = "database"; public static final String WAIT_FOR_SYNC = "waitForSync"; public static final String IF_NONE_MATCH = "If-None-Match"; public static final String IF_MATCH = "If-Match"; public static final String KEEP_NULL = "keepNull"; + private ArangoRequestParam() { + super(); + } } diff --git a/src/main/java/com/arangodb/internal/ArangoResponseField.java b/src/main/java/com/arangodb/internal/ArangoResponseField.java index 5ce43feda..df2a49a1e 100644 --- a/src/main/java/com/arangodb/internal/ArangoResponseField.java +++ b/src/main/java/com/arangodb/internal/ArangoResponseField.java @@ -25,11 +25,10 @@ */ public final class ArangoResponseField { + public static final String ERROR_FIELD_NAME = "error"; + public static final String RESULT_JSON_POINTER = "/result"; private ArangoResponseField() { super(); } - public static final String ERROR_FIELD_NAME = "error"; - public static final String RESULT_JSON_POINTER = "/result"; - } diff --git a/src/main/java/com/arangodb/internal/ArangoRouteImpl.java b/src/main/java/com/arangodb/internal/ArangoRouteImpl.java index 3c33afe0b..99147739d 100644 --- a/src/main/java/com/arangodb/internal/ArangoRouteImpl.java +++ b/src/main/java/com/arangodb/internal/ArangoRouteImpl.java @@ -20,7 +20,6 @@ package com.arangodb.internal; -import com.arangodb.ArangoDBException; import com.arangodb.ArangoRoute; import com.arangodb.velocystream.RequestType; import com.arangodb.velocystream.Response; @@ -68,32 +67,32 @@ private Response request(final RequestType requestType) { } @Override - public Response delete() { + public Response delete() { return request(RequestType.DELETE); } @Override - public Response get() { + public Response get() { return request(RequestType.GET); } @Override - public Response head() { + public Response head() { return request(RequestType.HEAD); } @Override - public Response patch() { + public Response patch() { return request(RequestType.PATCH); } @Override - public Response post() { + public Response post() { return request(RequestType.POST); } @Override - public Response put() { + public Response put() { return request(RequestType.PUT); } diff --git a/src/main/java/com/arangodb/internal/ArangoSearchImpl.java b/src/main/java/com/arangodb/internal/ArangoSearchImpl.java index e02063e7a..87522d6ac 100644 --- a/src/main/java/com/arangodb/internal/ArangoSearchImpl.java +++ b/src/main/java/com/arangodb/internal/ArangoSearchImpl.java @@ -38,7 +38,7 @@ protected ArangoSearchImpl(final ArangoDatabaseImpl db, final String name) { } @Override - public boolean exists() { + public boolean exists() { try { getInfo(); return true; @@ -51,46 +51,44 @@ public boolean exists() { } @Override - public void drop() { + public void drop() { executor.execute(dropRequest(), Void.class); } @Override - public synchronized ViewEntity rename(final String newName) { + public synchronized ViewEntity rename(final String newName) { final ViewEntity result = executor.execute(renameRequest(newName), ViewEntity.class); name = result.getName(); return result; } @Override - public ViewEntity getInfo() { + public ViewEntity getInfo() { return executor.execute(getInfoRequest(), ViewEntity.class); } @Override - public ViewEntity create() { + public ViewEntity create() { return create(new ArangoSearchCreateOptions()); } @Override - public ViewEntity create(final ArangoSearchCreateOptions options) { + public ViewEntity create(final ArangoSearchCreateOptions options) { return db().createArangoSearch(name(), options); } @Override - public ArangoSearchPropertiesEntity getProperties() { + public ArangoSearchPropertiesEntity getProperties() { return executor.execute(getPropertiesRequest(), ArangoSearchPropertiesEntity.class); } @Override - public ArangoSearchPropertiesEntity updateProperties(final ArangoSearchPropertiesOptions options) - { + public ArangoSearchPropertiesEntity updateProperties(final ArangoSearchPropertiesOptions options) { return executor.execute(updatePropertiesRequest(options), ArangoSearchPropertiesEntity.class); } @Override - public ArangoSearchPropertiesEntity replaceProperties(final ArangoSearchPropertiesOptions options) - { + public ArangoSearchPropertiesEntity replaceProperties(final ArangoSearchPropertiesOptions options) { return executor.execute(replacePropertiesRequest(options), ArangoSearchPropertiesEntity.class); } diff --git a/src/main/java/com/arangodb/internal/ArangoVertexCollectionImpl.java b/src/main/java/com/arangodb/internal/ArangoVertexCollectionImpl.java index 676a4f4f5..148aea746 100644 --- a/src/main/java/com/arangodb/internal/ArangoVertexCollectionImpl.java +++ b/src/main/java/com/arangodb/internal/ArangoVertexCollectionImpl.java @@ -42,23 +42,23 @@ protected ArangoVertexCollectionImpl(final ArangoGraphImpl graph, final String n } @Override - public void drop() { + public void drop() { executor.execute(dropRequest(), Void.class); } @Override - public VertexEntity insertVertex(final Object value) { + public VertexEntity insertVertex(final Object value) { return executor.execute(insertVertexRequest(value, new VertexCreateOptions()), insertVertexResponseDeserializer(value)); } @Override - public VertexEntity insertVertex(final Object value, final VertexCreateOptions options) { + public VertexEntity insertVertex(final Object value, final VertexCreateOptions options) { return executor.execute(insertVertexRequest(value, options), insertVertexResponseDeserializer(value)); } @Override - public T getVertex(final String key, final Class type) { + public T getVertex(final String key, final Class type) { try { return executor.execute(getVertexRequest(key, new GraphDocumentReadOptions()), getVertexResponseDeserializer(type)); @@ -71,8 +71,7 @@ public T getVertex(final String key, final Class type) { } @Override - public T getVertex(final String key, final Class type, final GraphDocumentReadOptions options) - { + public T getVertex(final String key, final Class type, final GraphDocumentReadOptions options) { try { return executor.execute(getVertexRequest(key, options), getVertexResponseDeserializer(type)); } catch (final ArangoDBException e) { @@ -84,36 +83,34 @@ public T getVertex(final String key, final Class type, final GraphDocumen } @Override - public VertexUpdateEntity replaceVertex(final String key, final Object value) { + public VertexUpdateEntity replaceVertex(final String key, final Object value) { return executor.execute(replaceVertexRequest(key, value, new VertexReplaceOptions()), replaceVertexResponseDeserializer(value)); } @Override - public VertexUpdateEntity replaceVertex(final String key, final Object value, final VertexReplaceOptions options) - { + public VertexUpdateEntity replaceVertex(final String key, final Object value, final VertexReplaceOptions options) { return executor.execute(replaceVertexRequest(key, value, options), replaceVertexResponseDeserializer(value)); } @Override - public VertexUpdateEntity updateVertex(final String key, final Object value) { + public VertexUpdateEntity updateVertex(final String key, final Object value) { return executor.execute(updateVertexRequest(key, value, new VertexUpdateOptions()), updateVertexResponseDeserializer(value)); } @Override - public VertexUpdateEntity updateVertex(final String key, final Object value, final VertexUpdateOptions options) - { + public VertexUpdateEntity updateVertex(final String key, final Object value, final VertexUpdateOptions options) { return executor.execute(updateVertexRequest(key, value, options), updateVertexResponseDeserializer(value)); } @Override - public void deleteVertex(final String key) { + public void deleteVertex(final String key) { executor.execute(deleteVertexRequest(key, new VertexDeleteOptions()), Void.class); } @Override - public void deleteVertex(final String key, final VertexDeleteOptions options) { + public void deleteVertex(final String key, final VertexDeleteOptions options) { executor.execute(deleteVertexRequest(key, options), Void.class); } diff --git a/src/main/java/com/arangodb/internal/ArangoViewImpl.java b/src/main/java/com/arangodb/internal/ArangoViewImpl.java index 926d7105c..a9d0d37a4 100644 --- a/src/main/java/com/arangodb/internal/ArangoViewImpl.java +++ b/src/main/java/com/arangodb/internal/ArangoViewImpl.java @@ -35,7 +35,7 @@ protected ArangoViewImpl(final ArangoDatabaseImpl db, final String name) { } @Override - public boolean exists() { + public boolean exists() { try { getInfo(); return true; @@ -48,19 +48,19 @@ public boolean exists() { } @Override - public void drop() { + public void drop() { executor.execute(dropRequest(), Void.class); } @Override - public synchronized ViewEntity rename(final String newName) { + public synchronized ViewEntity rename(final String newName) { final ViewEntity result = executor.execute(renameRequest(newName), ViewEntity.class); name = result.getName(); return result; } @Override - public ViewEntity getInfo() { + public ViewEntity getInfo() { return executor.execute(getInfoRequest(), ViewEntity.class); } diff --git a/src/main/java/com/arangodb/internal/DocumentFields.java b/src/main/java/com/arangodb/internal/DocumentFields.java index 058aa8e2f..c69d989fe 100644 --- a/src/main/java/com/arangodb/internal/DocumentFields.java +++ b/src/main/java/com/arangodb/internal/DocumentFields.java @@ -5,14 +5,13 @@ public final class DocumentFields { - private DocumentFields() { - } - public static final String ID = "_id"; public static final String KEY = "_key"; public static final String REV = "_rev"; public static final String FROM = "_from"; public static final String TO = "_to"; + private DocumentFields() { + } public static List values() { return Arrays.asList(ID, KEY, REV, FROM, TO); diff --git a/src/main/java/com/arangodb/internal/InternalArangoCollection.java b/src/main/java/com/arangodb/internal/InternalArangoCollection.java index 6be1d5a27..e1835bf70 100644 --- a/src/main/java/com/arangodb/internal/InternalArangoCollection.java +++ b/src/main/java/com/arangodb/internal/InternalArangoCollection.java @@ -24,16 +24,17 @@ import com.arangodb.DbName; import com.arangodb.entity.*; import com.arangodb.internal.ArangoExecutor.ResponseDeserializer; +import com.arangodb.internal.serde.SerdeUtils; import com.arangodb.internal.util.DocumentUtil; import com.arangodb.internal.util.RequestUtils; import com.arangodb.model.*; -import com.arangodb.internal.serde.SerdeUtils; import com.arangodb.velocystream.Request; import com.arangodb.velocystream.RequestType; import com.fasterxml.jackson.databind.JsonNode; import java.lang.reflect.Type; -import java.util.*; +import java.util.ArrayList; +import java.util.Collection; import static com.arangodb.internal.serde.SerdeUtils.constructListType; import static com.arangodb.internal.serde.SerdeUtils.constructParametricType; @@ -45,9 +46,8 @@ public abstract class InternalArangoCollection, D extends InternalArangoDatabase, E extends ArangoExecutor> extends ArangoExecuteable { - private static final String COLLECTION = "collection"; - protected static final String PATH_API_COLLECTION = "/_api/collection"; + private static final String COLLECTION = "collection"; private static final String PATH_API_DOCUMENT = "/_api/document"; private static final String PATH_API_INDEX = "/_api/index"; private static final String PATH_API_IMPORT = "/_api/import"; diff --git a/src/main/java/com/arangodb/internal/InternalArangoDB.java b/src/main/java/com/arangodb/internal/InternalArangoDB.java index 763d7e612..afb2088ab 100644 --- a/src/main/java/com/arangodb/internal/InternalArangoDB.java +++ b/src/main/java/com/arangodb/internal/InternalArangoDB.java @@ -21,10 +21,13 @@ package com.arangodb.internal; import com.arangodb.DbName; -import com.arangodb.entity.*; +import com.arangodb.entity.LogLevelEntity; +import com.arangodb.entity.Permissions; +import com.arangodb.entity.ServerRole; +import com.arangodb.entity.UserEntity; import com.arangodb.internal.ArangoExecutor.ResponseDeserializer; -import com.arangodb.model.*; import com.arangodb.internal.serde.InternalSerde; +import com.arangodb.model.*; import com.arangodb.velocystream.Request; import com.arangodb.velocystream.RequestType; diff --git a/src/main/java/com/arangodb/internal/InternalArangoDBBuilder.java b/src/main/java/com/arangodb/internal/InternalArangoDBBuilder.java index 9bb0b7e0c..9f8fae41a 100644 --- a/src/main/java/com/arangodb/internal/InternalArangoDBBuilder.java +++ b/src/main/java/com/arangodb/internal/InternalArangoDBBuilder.java @@ -93,7 +93,125 @@ public InternalArangoDBBuilder() { loadProperties(ArangoDB.class.getResourceAsStream(DEFAULT_PROPERTY_FILE)); } - public InternalArangoDBBuilder loadProperties(final InputStream in) { + private static void loadHosts(final Properties properties, final Collection hosts) { + final String hostsProp = properties.getProperty(PROPERTY_KEY_HOSTS); + if (hostsProp != null) { + final String[] hostsSplit = hostsProp.split(","); + for (final String host : hostsSplit) { + final String[] split = host.split(":"); + if (split.length != 2 || !split[1].matches("[0-9]+")) { + throw new ArangoDBException(String.format( + "Could not load property-value arangodb.hosts=%s. Expected format ip:port,ip:port,...", + hostsProp)); + } else { + hosts.add(new HostDescription(split[0], Integer.parseInt(split[1]))); + } + } + } + } + + private static String loadHost(final Properties properties, final String currentValue) { + final String host = getProperty(properties, PROPERTY_KEY_HOST, currentValue, ArangoDefaults.DEFAULT_HOST); + if (host.contains(":")) { + throw new ArangoDBException(String.format( + "Could not load property-value arangodb.host=%s. Expect only ip. Do you mean arangodb.hosts=ip:port ?", + host)); + } + return host; + } + + private static Integer loadPort(final Properties properties, final int currentValue) { + return Integer.parseInt(getProperty(properties, PROPERTY_KEY_PORT, currentValue, ArangoDefaults.DEFAULT_PORT)); + } + + private static Integer loadTimeout(final Properties properties, final Integer currentValue) { + return Integer + .parseInt(getProperty(properties, PROPERTY_KEY_TIMEOUT, currentValue, ArangoDefaults.DEFAULT_TIMEOUT)); + } + + private static String loadUser(final Properties properties, final String currentValue) { + return getProperty(properties, PROPERTY_KEY_USER, currentValue, ArangoDefaults.DEFAULT_USER); + } + + private static String loadPassword(final Properties properties, final String currentValue) { + return getProperty(properties, PROPERTY_KEY_PASSWORD, currentValue, null); + } + + private static String loadJwt(final Properties properties, final String currentValue) { + return getProperty(properties, PROPERTY_KEY_JWT, currentValue, null); + } + + private static Boolean loadUseSsl(final Properties properties, final Boolean currentValue) { + return Boolean.parseBoolean( + getProperty(properties, PROPERTY_KEY_USE_SSL, currentValue, ArangoDefaults.DEFAULT_USE_SSL)); + } + + private static String loadhttpCookieSpec(final Properties properties, final String currentValue) { + return getProperty(properties, PROPERTY_KEY_COOKIE_SPEC, currentValue, ""); + } + + private static Integer loadChunkSize(final Properties properties, final Integer currentValue) { + return Integer.parseInt(getProperty(properties, PROPERTY_KEY_V_STREAM_CHUNK_CONTENT_SIZE, currentValue, + ArangoDefaults.CHUNK_DEFAULT_CONTENT_SIZE)); + } + + private static Integer loadMaxConnections(final Properties properties, final Integer currentValue) { + return Integer.parseInt(getProperty(properties, PROPERTY_KEY_MAX_CONNECTIONS, currentValue, + ArangoDefaults.MAX_CONNECTIONS_VST_DEFAULT)); + } + + private static Long loadConnectionTtl(final Properties properties, final Long currentValue) { + final String ttl = getProperty(properties, PROPERTY_KEY_CONNECTION_TTL, currentValue, + ArangoDefaults.CONNECTION_TTL_VST_DEFAULT); + return ttl != null ? Long.parseLong(ttl) : null; + } + + private static Integer loadKeepAliveInterval(final Properties properties, final Integer currentValue) { + final String keepAliveInterval = getProperty(properties, PROPERTY_KEEP_ALIVE_INTERVAL, currentValue, + null); + return keepAliveInterval != null ? Integer.parseInt(keepAliveInterval) : null; + } + + private static Boolean loadAcquireHostList(final Properties properties, final Boolean currentValue) { + return Boolean.parseBoolean(getProperty(properties, PROPERTY_KEY_ACQUIRE_HOST_LIST, currentValue, + ArangoDefaults.DEFAULT_ACQUIRE_HOST_LIST)); + } + + private static int loadAcquireHostListInterval(final Properties properties, final Integer currentValue) { + return Integer.parseInt(getProperty(properties, PROPERTY_KEY_ACQUIRE_HOST_LIST_INTERVAL, currentValue, + ArangoDefaults.DEFAULT_ACQUIRE_HOST_LIST_INTERVAL)); + } + + private static int loadResponseQueueTimeSamples(final Properties properties, final Integer currentValue) { + return Integer.parseInt(getProperty(properties, PROPERTY_KEY_RESPONSE_QUEUE_TIME_SAMPLES, currentValue, + ArangoDefaults.DEFAULT_RESPONSE_QUEUE_TIME_SAMPLES)); + } + + private static LoadBalancingStrategy loadLoadBalancingStrategy( + final Properties properties, + final LoadBalancingStrategy currentValue) { + return LoadBalancingStrategy.valueOf(getProperty(properties, PROPERTY_KEY_LOAD_BALANCING_STRATEGY, currentValue, + ArangoDefaults.DEFAULT_LOAD_BALANCING_STRATEGY).toUpperCase(Locale.ENGLISH)); + } + + protected static String getProperty( + final Properties properties, + final String key, + final T currentValue, + final T defaultValue) { + + String overrideDefaultValue = null; + + if (currentValue != null) { + overrideDefaultValue = currentValue.toString(); + } else if (defaultValue != null) { + overrideDefaultValue = defaultValue.toString(); + } + + return properties.getProperty(key, overrideDefaultValue); + } + + public InternalArangoDBBuilder loadProperties(final InputStream in) { final Properties properties = new Properties(); @@ -205,23 +323,6 @@ protected void setSerializer(final ArangoSerde serializer) { this.customSerializer = serializer; } - private static void loadHosts(final Properties properties, final Collection hosts) { - final String hostsProp = properties.getProperty(PROPERTY_KEY_HOSTS); - if (hostsProp != null) { - final String[] hostsSplit = hostsProp.split(","); - for (final String host : hostsSplit) { - final String[] split = host.split(":"); - if (split.length != 2 || !split[1].matches("[0-9]+")) { - throw new ArangoDBException(String.format( - "Could not load property-value arangodb.hosts=%s. Expected format ip:port,ip:port,...", - hostsProp)); - } else { - hosts.add(new HostDescription(split[0], Integer.parseInt(split[1]))); - } - } - } - } - protected HostHandler createHostHandler(final HostResolver hostResolver) { final HostHandler hostHandler; @@ -260,107 +361,6 @@ protected HostResolver createHostResolver(final Collection hosts, final in } - private static String loadHost(final Properties properties, final String currentValue) { - final String host = getProperty(properties, PROPERTY_KEY_HOST, currentValue, ArangoDefaults.DEFAULT_HOST); - if (host.contains(":")) { - throw new ArangoDBException(String.format( - "Could not load property-value arangodb.host=%s. Expect only ip. Do you mean arangodb.hosts=ip:port ?", - host)); - } - return host; - } - - private static Integer loadPort(final Properties properties, final int currentValue) { - return Integer.parseInt(getProperty(properties, PROPERTY_KEY_PORT, currentValue, ArangoDefaults.DEFAULT_PORT)); - } - - private static Integer loadTimeout(final Properties properties, final Integer currentValue) { - return Integer - .parseInt(getProperty(properties, PROPERTY_KEY_TIMEOUT, currentValue, ArangoDefaults.DEFAULT_TIMEOUT)); - } - - private static String loadUser(final Properties properties, final String currentValue) { - return getProperty(properties, PROPERTY_KEY_USER, currentValue, ArangoDefaults.DEFAULT_USER); - } - - private static String loadPassword(final Properties properties, final String currentValue) { - return getProperty(properties, PROPERTY_KEY_PASSWORD, currentValue, null); - } - - private static String loadJwt(final Properties properties, final String currentValue) { - return getProperty(properties, PROPERTY_KEY_JWT, currentValue, null); - } - - private static Boolean loadUseSsl(final Properties properties, final Boolean currentValue) { - return Boolean.parseBoolean( - getProperty(properties, PROPERTY_KEY_USE_SSL, currentValue, ArangoDefaults.DEFAULT_USE_SSL)); - } - - private static String loadhttpCookieSpec(final Properties properties, final String currentValue) { - return getProperty(properties, PROPERTY_KEY_COOKIE_SPEC, currentValue, ""); - } - - private static Integer loadChunkSize(final Properties properties, final Integer currentValue) { - return Integer.parseInt(getProperty(properties, PROPERTY_KEY_V_STREAM_CHUNK_CONTENT_SIZE, currentValue, - ArangoDefaults.CHUNK_DEFAULT_CONTENT_SIZE)); - } - - private static Integer loadMaxConnections(final Properties properties, final Integer currentValue) { - return Integer.parseInt(getProperty(properties, PROPERTY_KEY_MAX_CONNECTIONS, currentValue, - ArangoDefaults.MAX_CONNECTIONS_VST_DEFAULT)); - } - - private static Long loadConnectionTtl(final Properties properties, final Long currentValue) { - final String ttl = getProperty(properties, PROPERTY_KEY_CONNECTION_TTL, currentValue, - ArangoDefaults.CONNECTION_TTL_VST_DEFAULT); - return ttl != null ? Long.parseLong(ttl) : null; - } - - private static Integer loadKeepAliveInterval(final Properties properties, final Integer currentValue) { - final String keepAliveInterval = getProperty(properties, PROPERTY_KEEP_ALIVE_INTERVAL, currentValue, - null); - return keepAliveInterval != null ? Integer.parseInt(keepAliveInterval) : null; - } - - private static Boolean loadAcquireHostList(final Properties properties, final Boolean currentValue) { - return Boolean.parseBoolean(getProperty(properties, PROPERTY_KEY_ACQUIRE_HOST_LIST, currentValue, - ArangoDefaults.DEFAULT_ACQUIRE_HOST_LIST)); - } - - private static int loadAcquireHostListInterval(final Properties properties, final Integer currentValue) { - return Integer.parseInt(getProperty(properties, PROPERTY_KEY_ACQUIRE_HOST_LIST_INTERVAL, currentValue, - ArangoDefaults.DEFAULT_ACQUIRE_HOST_LIST_INTERVAL)); - } - - private static int loadResponseQueueTimeSamples(final Properties properties, final Integer currentValue) { - return Integer.parseInt(getProperty(properties, PROPERTY_KEY_RESPONSE_QUEUE_TIME_SAMPLES, currentValue, - ArangoDefaults.DEFAULT_RESPONSE_QUEUE_TIME_SAMPLES)); - } - - private static LoadBalancingStrategy loadLoadBalancingStrategy( - final Properties properties, - final LoadBalancingStrategy currentValue) { - return LoadBalancingStrategy.valueOf(getProperty(properties, PROPERTY_KEY_LOAD_BALANCING_STRATEGY, currentValue, - ArangoDefaults.DEFAULT_LOAD_BALANCING_STRATEGY).toUpperCase(Locale.ENGLISH)); - } - - protected static String getProperty( - final Properties properties, - final String key, - final T currentValue, - final T defaultValue) { - - String overrideDefaultValue = null; - - if (currentValue != null) { - overrideDefaultValue = currentValue.toString(); - } else if (defaultValue != null) { - overrideDefaultValue = defaultValue.toString(); - } - - return properties.getProperty(key, overrideDefaultValue); - } - protected Collection createHostList( final int maxConnections, final ConnectionFactory connectionFactory) { diff --git a/src/main/java/com/arangodb/internal/QueueTimeMetricsImpl.java b/src/main/java/com/arangodb/internal/QueueTimeMetricsImpl.java index 42abe46e9..c3ac91a19 100644 --- a/src/main/java/com/arangodb/internal/QueueTimeMetricsImpl.java +++ b/src/main/java/com/arangodb/internal/QueueTimeMetricsImpl.java @@ -59,17 +59,14 @@ void clear() { private static class CircularFifoQueue { private final QueueTimeSample[] elements; - - /** - * Array index of the oldest queue element. - */ - private int start; - /** * Capacity of the queue. */ private final int size; - + /** + * Array index of the oldest queue element. + */ + private int start; /** * Amount of elements in the queue. */ diff --git a/src/main/java/com/arangodb/internal/cursor/ArangoCursorImpl.java b/src/main/java/com/arangodb/internal/cursor/ArangoCursorImpl.java index 973e7a8c2..c99be12b0 100644 --- a/src/main/java/com/arangodb/internal/cursor/ArangoCursorImpl.java +++ b/src/main/java/com/arangodb/internal/cursor/ArangoCursorImpl.java @@ -23,10 +23,10 @@ import com.arangodb.ArangoCursor; import com.arangodb.ArangoIterator; import com.arangodb.entity.CursorWarning; -import com.arangodb.internal.cursor.entity.InternalCursorEntity; -import com.arangodb.internal.cursor.entity.InternalCursorEntity.Extras; import com.arangodb.internal.ArangoCursorExecute; import com.arangodb.internal.InternalArangoDatabase; +import com.arangodb.internal.cursor.entity.InternalCursorEntity; +import com.arangodb.internal.cursor.entity.InternalCursorEntity.Extras; import java.util.ArrayList; import java.util.Collection; @@ -38,8 +38,8 @@ */ public class ArangoCursorImpl extends AbstractArangoIterable implements ArangoCursor { - private final Class type; protected final ArangoCursorIterator iterator; + private final Class type; private final String id; private final ArangoCursorExecute execute; diff --git a/src/main/java/com/arangodb/internal/cursor/ArangoCursorIterator.java b/src/main/java/com/arangodb/internal/cursor/ArangoCursorIterator.java index f34f3203a..bf451c34b 100644 --- a/src/main/java/com/arangodb/internal/cursor/ArangoCursorIterator.java +++ b/src/main/java/com/arangodb/internal/cursor/ArangoCursorIterator.java @@ -36,12 +36,11 @@ */ public class ArangoCursorIterator implements ArangoIterator { - private InternalCursorEntity result; - private Iterator arrayIterator; - private final ArangoCursor cursor; private final InternalArangoDatabase db; private final ArangoCursorExecute execute; + private InternalCursorEntity result; + private Iterator arrayIterator; protected ArangoCursorIterator(final ArangoCursor cursor, final ArangoCursorExecute execute, final InternalArangoDatabase db, final InternalCursorEntity result) { diff --git a/src/main/java/com/arangodb/internal/cursor/entity/InternalCursorEntity.java b/src/main/java/com/arangodb/internal/cursor/entity/InternalCursorEntity.java index e65aa5c48..c9c97d548 100644 --- a/src/main/java/com/arangodb/internal/cursor/entity/InternalCursorEntity.java +++ b/src/main/java/com/arangodb/internal/cursor/entity/InternalCursorEntity.java @@ -22,7 +22,6 @@ import com.arangodb.entity.CursorWarning; import com.arangodb.entity.MetaAware; -import com.fasterxml.jackson.annotation.JsonAnySetter; import com.fasterxml.jackson.databind.JsonNode; import java.util.Collection; @@ -36,9 +35,9 @@ */ public final class InternalCursorEntity implements MetaAware { + private final Extras extra = new Extras(); private String id; private Integer count; - private final Extras extra = new Extras(); private Boolean cached; private Boolean hasMore; private JsonNode result; @@ -94,6 +93,10 @@ public Map getMeta() { return meta; } + public void setMeta(Map meta) { + this.meta = cleanupMeta(meta); + } + /** * @return remove not allowed (valid storable) meta information */ @@ -104,13 +107,9 @@ public Map cleanupMeta(Map meta) { return meta; } - public void setMeta(Map meta) { - this.meta = cleanupMeta(meta); - } - public static final class Extras { - private Map stats; private final Collection warnings = Collections.emptyList(); + private Map stats; public Map getStats() { return stats; diff --git a/src/main/java/com/arangodb/internal/http/HttpCommunication.java b/src/main/java/com/arangodb/internal/http/HttpCommunication.java index b227b4b20..a8899af6e 100644 --- a/src/main/java/com/arangodb/internal/http/HttpCommunication.java +++ b/src/main/java/com/arangodb/internal/http/HttpCommunication.java @@ -22,9 +22,9 @@ import com.arangodb.ArangoDBException; import com.arangodb.internal.net.*; +import com.arangodb.internal.serde.InternalSerde; import com.arangodb.internal.util.HostUtils; import com.arangodb.internal.util.RequestUtils; -import com.arangodb.internal.serde.InternalSerde; import com.arangodb.velocystream.Request; import com.arangodb.velocystream.Response; import org.slf4j.Logger; @@ -41,25 +41,6 @@ public class HttpCommunication implements Closeable { private static final Logger LOGGER = LoggerFactory.getLogger(HttpCommunication.class); - - public static class Builder { - - private final HostHandler hostHandler; - - public Builder(final HostHandler hostHandler) { - super(); - this.hostHandler = hostHandler; - } - - public Builder(final Builder builder) { - this(builder.hostHandler); - } - - public HttpCommunication build(final InternalSerde util) { - return new HttpCommunication(hostHandler); - } - } - private final HostHandler hostHandler; private HttpCommunication(final HostHandler hostHandler) { @@ -72,11 +53,11 @@ public void close() throws IOException { hostHandler.close(); } - public Response execute(final Request request, final HostHandle hostHandle) { + public Response execute(final Request request, final HostHandle hostHandle) { return execute(request, hostHandle, 0); } - private Response execute(final Request request, final HostHandle hostHandle, final int attemptCount) { + private Response execute(final Request request, final HostHandle hostHandle, final int attemptCount) { final AccessType accessType = RequestUtils.determineAccessType(request); Host host = hostHandler.get(hostHandle, accessType); try { @@ -123,4 +104,22 @@ private Response execute(final Request request, final HostHandle hostHandle, fin } } + public static class Builder { + + private final HostHandler hostHandler; + + public Builder(final HostHandler hostHandler) { + super(); + this.hostHandler = hostHandler; + } + + public Builder(final Builder builder) { + this(builder.hostHandler); + } + + public HttpCommunication build(final InternalSerde util) { + return new HttpCommunication(hostHandler); + } + } + } diff --git a/src/main/java/com/arangodb/internal/http/HttpConnection.java b/src/main/java/com/arangodb/internal/http/HttpConnection.java index 05e37f53a..c7e57bb2c 100644 --- a/src/main/java/com/arangodb/internal/http/HttpConnection.java +++ b/src/main/java/com/arangodb/internal/http/HttpConnection.java @@ -25,9 +25,9 @@ import com.arangodb.Protocol; import com.arangodb.internal.net.Connection; import com.arangodb.internal.net.HostDescription; +import com.arangodb.internal.serde.InternalSerde; import com.arangodb.internal.util.IOUtils; import com.arangodb.internal.util.ResponseUtils; -import com.arangodb.internal.serde.InternalSerde; import com.arangodb.velocystream.Request; import com.arangodb.velocystream.Response; import org.apache.http.*; @@ -77,97 +77,15 @@ public class HttpConnection implements Connection { private static final ContentType CONTENT_TYPE_APPLICATION_JSON_UTF8 = ContentType.create("application/json", "utf-8"); private static final ContentType CONTENT_TYPE_VPACK = ContentType.create("application/x-velocypack"); - - public static class Builder { - private String user; - private String password; - private InternalSerde util; - private Boolean useSsl; - private String httpCookieSpec; - private Protocol contentType; - private HostDescription host; - private Long ttl; - private SSLContext sslContext; - private HostnameVerifier hostnameVerifier; - private Integer timeout; - private HttpRequestRetryHandler httpRequestRetryHandler; - - public Builder user(final String user) { - this.user = user; - return this; - } - - public Builder password(final String password) { - this.password = password; - return this; - } - - public Builder serializationUtil(final InternalSerde util) { - this.util = util; - return this; - } - - public Builder useSsl(final Boolean useSsl) { - this.useSsl = useSsl; - return this; - } - - public Builder httpCookieSpec(String httpCookieSpec) { - this.httpCookieSpec = httpCookieSpec; - return this; - } - - public Builder contentType(final Protocol contentType) { - this.contentType = contentType; - return this; - } - - public Builder host(final HostDescription host) { - this.host = host; - return this; - } - - public Builder ttl(final Long ttl) { - this.ttl = ttl; - return this; - } - - public Builder sslContext(final SSLContext sslContext) { - this.sslContext = sslContext; - return this; - } - - public Builder hostnameVerifier(final HostnameVerifier hostnameVerifier) { - this.hostnameVerifier = hostnameVerifier; - return this; - } - - public Builder timeout(final Integer timeout) { - this.timeout = timeout; - return this; - } - - public Builder httpRequestRetryHandler(final HttpRequestRetryHandler httpRequestRetryHandler) { - this.httpRequestRetryHandler = httpRequestRetryHandler; - return this; - } - - public HttpConnection build() { - return new HttpConnection(host, timeout, user, password, useSsl, sslContext, hostnameVerifier, util, - contentType, ttl, httpCookieSpec, httpRequestRetryHandler); - } - } - private final PoolingHttpClientConnectionManager cm; private final CloseableHttpClient client; private final String user; private final String password; - private volatile String jwt = null; private final InternalSerde util; private final Boolean useSsl; private final Protocol contentType; private final HostDescription host; - + private volatile String jwt = null; private HttpConnection(final HostDescription host, final Integer timeout, final String user, final String password, final Boolean useSsl, final SSLContext sslContext, final HostnameVerifier hostnameVerifier, final InternalSerde util, final Protocol contentType, final Long ttl, final String httpCookieSpec, final HttpRequestRetryHandler httpRequestRetryHandler) { @@ -212,6 +130,41 @@ private HttpConnection(final HostDescription host, final Integer timeout, final client = builder.build(); } + private static String buildUrl(final String baseUrl, final Request request) { + StringBuilder sb = new StringBuilder().append(baseUrl); + DbName dbName = request.getDbName(); + if (dbName != null && !dbName.get().isEmpty()) { + sb.append("/_db/").append(dbName.getEncoded()); + } + sb.append(request.getRequest()); + if (!request.getQueryParam().isEmpty()) { + if (request.getRequest().contains("?")) { + sb.append("&"); + } else { + sb.append("?"); + } + final String paramString = URLEncodedUtils.format(toList(request.getQueryParam()), "utf-8"); + sb.append(paramString); + } + return sb.toString(); + } + + private static List toList(final Map parameters) { + final ArrayList paramList = new ArrayList<>(parameters.size()); + for (final Entry param : parameters.entrySet()) { + if (param.getValue() != null) { + paramList.add(new BasicNameValuePair(param.getKey(), param.getValue())); + } + } + return paramList; + } + + private static void addHeader(final Request request, final HttpRequestBase httpRequest) { + for (final Entry header : request.getHeaderParam().entrySet()) { + httpRequest.addHeader(header.getKey(), header.getValue()); + } + } + private long getKeepAliveDuration(final HttpResponse response) { final HeaderElementIterator it = new BasicHeaderElementIterator(response.headerIterator(HTTP.CONN_KEEP_ALIVE)); while (it.hasNext()) { @@ -234,25 +187,6 @@ public void close() throws IOException { client.close(); } - private static String buildUrl(final String baseUrl, final Request request) { - StringBuilder sb = new StringBuilder().append(baseUrl); - DbName dbName = request.getDbName(); - if (dbName != null && !dbName.get().isEmpty()) { - sb.append("/_db/").append(dbName.getEncoded()); - } - sb.append(request.getRequest()); - if (!request.getQueryParam().isEmpty()) { - if (request.getRequest().contains("?")) { - sb.append("&"); - } else { - sb.append("?"); - } - final String paramString = URLEncodedUtils.format(toList(request.getQueryParam()), "utf-8"); - sb.append(paramString); - } - return sb.toString(); - } - private HttpRequestBase buildHttpRequestBase(final Request request, final String url) { final HttpRequestBase httpRequest; switch (request.getRequestType()) { @@ -295,16 +229,6 @@ private String buildBaseUrl(final HostDescription host) { return (Boolean.TRUE == useSsl ? "https://" : "http://") + host.getHost() + ":" + host.getPort(); } - private static List toList(final Map parameters) { - final ArrayList paramList = new ArrayList<>(parameters.size()); - for (final Entry param : parameters.entrySet()) { - if (param.getValue() != null) { - paramList.add(new BasicNameValuePair(param.getKey(), param.getValue())); - } - } - return paramList; - } - public Response execute(final Request request) throws IOException { final String url = buildUrl(buildBaseUrl(host), request); final HttpRequestBase httpRequest = buildHttpRequestBase(request, url); @@ -333,12 +257,6 @@ public Response execute(final Request request) throws IOException { return response; } - private static void addHeader(final Request request, final HttpRequestBase httpRequest) { - for (final Entry header : request.getHeaderParam().entrySet()) { - httpRequest.addHeader(header.getKey(), header.getValue()); - } - } - public Response buildResponse(final CloseableHttpResponse httpResponse) throws UnsupportedOperationException, IOException { final Response response = new Response(); @@ -358,7 +276,7 @@ public Response buildResponse(final CloseableHttpResponse httpResponse) return response; } - protected void checkError(final Response response) { + protected void checkError(final Response response) { ResponseUtils.checkError(util, response); } @@ -367,4 +285,84 @@ public void setJwt(String jwt) { this.jwt = jwt; } + public static class Builder { + private String user; + private String password; + private InternalSerde util; + private Boolean useSsl; + private String httpCookieSpec; + private Protocol contentType; + private HostDescription host; + private Long ttl; + private SSLContext sslContext; + private HostnameVerifier hostnameVerifier; + private Integer timeout; + private HttpRequestRetryHandler httpRequestRetryHandler; + + public Builder user(final String user) { + this.user = user; + return this; + } + + public Builder password(final String password) { + this.password = password; + return this; + } + + public Builder serializationUtil(final InternalSerde util) { + this.util = util; + return this; + } + + public Builder useSsl(final Boolean useSsl) { + this.useSsl = useSsl; + return this; + } + + public Builder httpCookieSpec(String httpCookieSpec) { + this.httpCookieSpec = httpCookieSpec; + return this; + } + + public Builder contentType(final Protocol contentType) { + this.contentType = contentType; + return this; + } + + public Builder host(final HostDescription host) { + this.host = host; + return this; + } + + public Builder ttl(final Long ttl) { + this.ttl = ttl; + return this; + } + + public Builder sslContext(final SSLContext sslContext) { + this.sslContext = sslContext; + return this; + } + + public Builder hostnameVerifier(final HostnameVerifier hostnameVerifier) { + this.hostnameVerifier = hostnameVerifier; + return this; + } + + public Builder timeout(final Integer timeout) { + this.timeout = timeout; + return this; + } + + public Builder httpRequestRetryHandler(final HttpRequestRetryHandler httpRequestRetryHandler) { + this.httpRequestRetryHandler = httpRequestRetryHandler; + return this; + } + + public HttpConnection build() { + return new HttpConnection(host, timeout, user, password, useSsl, sslContext, hostnameVerifier, util, + contentType, ttl, httpCookieSpec, httpRequestRetryHandler); + } + } + } diff --git a/src/main/java/com/arangodb/internal/http/HttpProtocol.java b/src/main/java/com/arangodb/internal/http/HttpProtocol.java index 64332c1e2..245bea678 100644 --- a/src/main/java/com/arangodb/internal/http/HttpProtocol.java +++ b/src/main/java/com/arangodb/internal/http/HttpProtocol.java @@ -20,7 +20,6 @@ package com.arangodb.internal.http; -import com.arangodb.ArangoDBException; import com.arangodb.internal.net.CommunicationProtocol; import com.arangodb.internal.net.HostHandle; import com.arangodb.velocystream.Request; @@ -41,7 +40,7 @@ public HttpProtocol(final HttpCommunication httpCommunitaction) { } @Override - public Response execute(final Request request, final HostHandle hostHandle) { + public Response execute(final Request request, final HostHandle hostHandle) { return httpCommunitaction.execute(request, hostHandle); } diff --git a/src/main/java/com/arangodb/internal/net/CommunicationProtocol.java b/src/main/java/com/arangodb/internal/net/CommunicationProtocol.java index a57b59790..2404879f9 100644 --- a/src/main/java/com/arangodb/internal/net/CommunicationProtocol.java +++ b/src/main/java/com/arangodb/internal/net/CommunicationProtocol.java @@ -20,7 +20,6 @@ package com.arangodb.internal.net; -import com.arangodb.ArangoDBException; import com.arangodb.velocystream.Request; import com.arangodb.velocystream.Response; @@ -31,7 +30,7 @@ */ public interface CommunicationProtocol extends Closeable { - Response execute(final Request request, HostHandle hostHandle) ; + Response execute(final Request request, HostHandle hostHandle); void setJwt(String jwt); diff --git a/src/main/java/com/arangodb/internal/net/ConnectionPoolImpl.java b/src/main/java/com/arangodb/internal/net/ConnectionPoolImpl.java index cf275e6db..652dbf353 100644 --- a/src/main/java/com/arangodb/internal/net/ConnectionPoolImpl.java +++ b/src/main/java/com/arangodb/internal/net/ConnectionPoolImpl.java @@ -39,8 +39,8 @@ public class ConnectionPoolImpl implements ConnectionPool { private final HostDescription host; private final int maxConnections; private final List connections; - private int current; private final ConnectionFactory factory; + private int current; private volatile String jwt = null; public ConnectionPoolImpl(final HostDescription host, final Integer maxConnections, diff --git a/src/main/java/com/arangodb/internal/net/ExtendedHostResolver.java b/src/main/java/com/arangodb/internal/net/ExtendedHostResolver.java index df0a21e4a..df3864406 100644 --- a/src/main/java/com/arangodb/internal/net/ExtendedHostResolver.java +++ b/src/main/java/com/arangodb/internal/net/ExtendedHostResolver.java @@ -23,8 +23,8 @@ import com.arangodb.ArangoDBException; import com.arangodb.DbName; import com.arangodb.internal.ArangoExecutorSync; -import com.arangodb.internal.util.HostUtils; import com.arangodb.internal.serde.InternalSerde; +import com.arangodb.internal.util.HostUtils; import com.arangodb.velocystream.Request; import com.arangodb.velocystream.RequestType; import org.slf4j.Logger; @@ -45,10 +45,8 @@ public class ExtendedHostResolver implements HostResolver { private final Integer maxConnections; private final ConnectionFactory connectionFactory; - - private long lastUpdate; private final Integer acquireHostListInterval; - + private long lastUpdate; private ArangoExecutorSync executor; private InternalSerde arangoSerialization; @@ -113,7 +111,7 @@ public HostSet resolve(boolean initial, boolean closeConnections) { return hosts; } - private Collection resolveFromServer() { + private Collection resolveFromServer() { Collection response; diff --git a/src/main/java/com/arangodb/internal/net/FallbackHostHandler.java b/src/main/java/com/arangodb/internal/net/FallbackHostHandler.java index 241a1b270..05ee6ebac 100644 --- a/src/main/java/com/arangodb/internal/net/FallbackHostHandler.java +++ b/src/main/java/com/arangodb/internal/net/FallbackHostHandler.java @@ -32,10 +32,10 @@ public class FallbackHostHandler implements HostHandler { private final HostResolver resolver; + private final List lastFailExceptions; private Host current; private Host lastSuccess; private int iterations; - private final List lastFailExceptions; private boolean firstOpened; private HostSet hosts; diff --git a/src/main/java/com/arangodb/internal/net/Host.java b/src/main/java/com/arangodb/internal/net/Host.java index 57f4d6e80..28b2571d7 100644 --- a/src/main/java/com/arangodb/internal/net/Host.java +++ b/src/main/java/com/arangodb/internal/net/Host.java @@ -35,10 +35,10 @@ public interface Host { void close() throws IOException; - void setMarkforDeletion(boolean markforDeletion); - boolean isMarkforDeletion(); + void setMarkforDeletion(boolean markforDeletion); + void setJwt(String jwt); } diff --git a/src/main/java/com/arangodb/internal/net/HostImpl.java b/src/main/java/com/arangodb/internal/net/HostImpl.java index d50b84ae1..419645db4 100644 --- a/src/main/java/com/arangodb/internal/net/HostImpl.java +++ b/src/main/java/com/arangodb/internal/net/HostImpl.java @@ -73,15 +73,15 @@ public boolean isMarkforDeletion() { return markforDeletion; } + public void setMarkforDeletion(boolean markforDeletion) { + this.markforDeletion = markforDeletion; + } + @Override public void setJwt(String jwt) { connectionPool.setJwt(jwt); } - public void setMarkforDeletion(boolean markforDeletion) { - this.markforDeletion = markforDeletion; - } - @Override public int hashCode() { final int prime = 31; diff --git a/src/main/java/com/arangodb/internal/net/RoundRobinHostHandler.java b/src/main/java/com/arangodb/internal/net/RoundRobinHostHandler.java index e7cc650ea..c4b925471 100644 --- a/src/main/java/com/arangodb/internal/net/RoundRobinHostHandler.java +++ b/src/main/java/com/arangodb/internal/net/RoundRobinHostHandler.java @@ -32,9 +32,9 @@ public class RoundRobinHostHandler implements HostHandler { private final HostResolver resolver; + private final List lastFailExceptions; private long current; private int fails; - private final List lastFailExceptions; private Host currentHost; private HostSet hosts; diff --git a/src/main/java/com/arangodb/internal/serde/InternalDeserializers.java b/src/main/java/com/arangodb/internal/serde/InternalDeserializers.java index 21e95c7b7..b5e2ee5e7 100644 --- a/src/main/java/com/arangodb/internal/serde/InternalDeserializers.java +++ b/src/main/java/com/arangodb/internal/serde/InternalDeserializers.java @@ -25,58 +25,6 @@ public final class InternalDeserializers { - private static T readTreeAsValue(JsonParser p, DeserializationContext ctxt, JsonNode n, Class targetType) throws IOException { - try (TreeTraversingParser t = new TreeTraversingParser(n, p.getCodec())) { - t.nextToken(); - return ctxt.readValue(t, targetType); - } - } - - public static class CollectionLinksDeserializer extends JsonDeserializer> { - - @Override - public Collection deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { - Collection out = new ArrayList<>(); - ObjectNode tree = p.readValueAsTree(); - Iterator> it = tree.fields(); - while (it.hasNext()) { - Map.Entry e = it.next(); - ObjectNode v = (ObjectNode) e.getValue(); - v.put("name", e.getKey()); - out.add(readTreeAsValue(p, ctxt, v, CollectionLink.class)); - } - return out; - } - } - - public static class FieldLinksDeserializer extends JsonDeserializer { - - @Override - public FieldLink[] deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { - Collection out = new ArrayList<>(); - ObjectNode tree = p.readValueAsTree(); - Iterator> it = tree.fields(); - while (it.hasNext()) { - Map.Entry e = it.next(); - ObjectNode v = (ObjectNode) e.getValue(); - v.put("name", e.getKey()); - out.add(readTreeAsValue(p, ctxt, v, FieldLink.class)); - } - return out.toArray(new FieldLink[0]); - } - } - - public static class CollectionSchemaRuleDeserializer extends JsonDeserializer { - @Override - public String deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { - return SerdeUtils.INSTANCE.writeJson(p.readValueAsTree()); - } - } - - - private InternalDeserializers() { - } - static final JsonDeserializer RAW_JSON_DESERIALIZER = new JsonDeserializer() { @Override public RawJson deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { @@ -84,7 +32,6 @@ public RawJson deserialize(JsonParser p, DeserializationContext ctxt) throws IOE return RawJson.of(SerdeUtils.INSTANCE.writeJson(p.readValueAsTree())); } }; - static final JsonDeserializer RAW_BYTES_DESERIALIZER = new JsonDeserializer() { @Override public RawBytes deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { @@ -96,21 +43,18 @@ public RawBytes deserialize(JsonParser p, DeserializationContext ctxt) throws IO return RawBytes.of(os.toByteArray()); } }; - static final JsonDeserializer COLLECTION_STATUS = new JsonDeserializer() { @Override public CollectionStatus deserialize(final JsonParser p, final DeserializationContext ctxt) throws IOException { return CollectionStatus.fromStatus(p.getIntValue()); } }; - static final JsonDeserializer COLLECTION_TYPE = new JsonDeserializer() { @Override public CollectionType deserialize(final JsonParser p, final DeserializationContext ctxt) throws IOException { return CollectionType.fromType(p.getIntValue()); } }; - static final JsonDeserializer REPLICATION_FACTOR = new JsonDeserializer() { @Override public ReplicationFactor deserialize(final JsonParser p, final DeserializationContext ctxt) throws IOException { @@ -122,7 +66,6 @@ public ReplicationFactor deserialize(final JsonParser p, final DeserializationCo } else throw new IllegalArgumentException(); } }; - @SuppressWarnings("unchecked") static final JsonDeserializer RESPONSE = new JsonDeserializer() { @Override @@ -139,5 +82,56 @@ public Response deserialize(final JsonParser p, final DeserializationContext ctx } }; + private InternalDeserializers() { + } + + private static T readTreeAsValue(JsonParser p, DeserializationContext ctxt, JsonNode n, Class targetType) throws IOException { + try (TreeTraversingParser t = new TreeTraversingParser(n, p.getCodec())) { + t.nextToken(); + return ctxt.readValue(t, targetType); + } + } + + public static class CollectionLinksDeserializer extends JsonDeserializer> { + + @Override + public Collection deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { + Collection out = new ArrayList<>(); + ObjectNode tree = p.readValueAsTree(); + Iterator> it = tree.fields(); + while (it.hasNext()) { + Map.Entry e = it.next(); + ObjectNode v = (ObjectNode) e.getValue(); + v.put("name", e.getKey()); + out.add(readTreeAsValue(p, ctxt, v, CollectionLink.class)); + } + return out; + } + } + + public static class FieldLinksDeserializer extends JsonDeserializer { + + @Override + public FieldLink[] deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { + Collection out = new ArrayList<>(); + ObjectNode tree = p.readValueAsTree(); + Iterator> it = tree.fields(); + while (it.hasNext()) { + Map.Entry e = it.next(); + ObjectNode v = (ObjectNode) e.getValue(); + v.put("name", e.getKey()); + out.add(readTreeAsValue(p, ctxt, v, FieldLink.class)); + } + return out.toArray(new FieldLink[0]); + } + } + + public static class CollectionSchemaRuleDeserializer extends JsonDeserializer { + @Override + public String deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { + return SerdeUtils.INSTANCE.writeJson(p.readValueAsTree()); + } + } + } diff --git a/src/main/java/com/arangodb/internal/serde/InternalSerdeImpl.java b/src/main/java/com/arangodb/internal/serde/InternalSerdeImpl.java index 795711cf8..a0e193247 100644 --- a/src/main/java/com/arangodb/internal/serde/InternalSerdeImpl.java +++ b/src/main/java/com/arangodb/internal/serde/InternalSerdeImpl.java @@ -2,7 +2,7 @@ import com.arangodb.ArangoDBException; import com.arangodb.entity.BaseDocument; -import com.arangodb.serde.*; +import com.arangodb.serde.ArangoSerde; import com.arangodb.util.RawBytes; import com.arangodb.util.RawJson; import com.fasterxml.jackson.annotation.JsonInclude; @@ -19,12 +19,12 @@ final class InternalSerdeImpl extends JacksonSerdeImpl implements InternalSerde { - private final ArangoSerde userSerde; - static { checkSupportedJacksonVersion(); } + private final ArangoSerde userSerde; + InternalSerdeImpl(final ObjectMapper mapper, final ArangoSerde userSerde) { super(mapper); this.userSerde = userSerde; diff --git a/src/main/java/com/arangodb/internal/serde/InternalSerializers.java b/src/main/java/com/arangodb/internal/serde/InternalSerializers.java index c6ab3a835..f889602fb 100644 --- a/src/main/java/com/arangodb/internal/serde/InternalSerializers.java +++ b/src/main/java/com/arangodb/internal/serde/InternalSerializers.java @@ -20,45 +20,12 @@ public final class InternalSerializers { - public static class CollectionSchemaRuleSerializer extends JsonSerializer { - @Override - public void serialize(String value, JsonGenerator gen, SerializerProvider serializers) throws IOException { - gen.writeTree(SerdeUtils.INSTANCE.parseJson(value)); - } - } - - public static class FieldLinksSerializer extends JsonSerializer> { - @Override - public void serialize(Collection value, JsonGenerator gen, SerializerProvider serializers) throws IOException { - Map mapLikeValue = new HashMap<>(); - for (FieldLink fl : value) { - mapLikeValue.put(fl.getName(), fl); - } - gen.writeObject(mapLikeValue); - } - } - - public static class CollectionLinksSerializer extends JsonSerializer> { - @Override - public void serialize(Collection value, JsonGenerator gen, SerializerProvider serializers) throws IOException { - Map mapLikeValue = new HashMap<>(); - for (CollectionLink cl : value) { - mapLikeValue.put(cl.getName(), cl); - } - gen.writeObject(mapLikeValue); - } - } - - private InternalSerializers() { - } - static final JsonSerializer RAW_JSON_SERIALIZER = new JsonSerializer() { @Override public void serialize(RawJson value, JsonGenerator gen, SerializerProvider serializers) throws IOException { gen.writeTree(SerdeUtils.INSTANCE.parseJson(value.getValue())); } }; - static final JsonSerializer RAW_BYTES_SERIALIZER = new JsonSerializer() { @Override public void serialize(RawBytes value, JsonGenerator gen, SerializerProvider serializers) throws IOException { @@ -69,7 +36,6 @@ public void serialize(RawBytes value, JsonGenerator gen, SerializerProvider seri } } }; - static final JsonSerializer AUTHENTICATION_REQUEST = new JsonSerializer() { @Override public void serialize(AuthenticationRequest value, JsonGenerator gen, SerializerProvider serializers) throws IOException { @@ -82,7 +48,6 @@ public void serialize(AuthenticationRequest value, JsonGenerator gen, Serializer gen.writeEndArray(); } }; - static final JsonSerializer JWT_AUTHENTICATION_REQUEST = new JsonSerializer() { @Override public void serialize(JwtAuthenticationRequest value, JsonGenerator gen, SerializerProvider serializers) throws IOException { @@ -94,7 +59,6 @@ public void serialize(JwtAuthenticationRequest value, JsonGenerator gen, Seriali gen.writeEndArray(); } }; - static final JsonSerializer REQUEST = new JsonSerializer() { @Override public void serialize(Request value, JsonGenerator gen, SerializerProvider serializers) throws IOException { @@ -117,7 +81,6 @@ public void serialize(Request value, JsonGenerator gen, SerializerProvider seria gen.writeEndArray(); } }; - static final JsonSerializer COLLECTION_TYPE = new JsonSerializer() { @Override public void serialize(CollectionType value, JsonGenerator gen, SerializerProvider serializers) throws IOException { @@ -125,4 +88,36 @@ public void serialize(CollectionType value, JsonGenerator gen, SerializerProvide } }; + private InternalSerializers() { + } + + public static class CollectionSchemaRuleSerializer extends JsonSerializer { + @Override + public void serialize(String value, JsonGenerator gen, SerializerProvider serializers) throws IOException { + gen.writeTree(SerdeUtils.INSTANCE.parseJson(value)); + } + } + + public static class FieldLinksSerializer extends JsonSerializer> { + @Override + public void serialize(Collection value, JsonGenerator gen, SerializerProvider serializers) throws IOException { + Map mapLikeValue = new HashMap<>(); + for (FieldLink fl : value) { + mapLikeValue.put(fl.getName(), fl); + } + gen.writeObject(mapLikeValue); + } + } + + public static class CollectionLinksSerializer extends JsonSerializer> { + @Override + public void serialize(Collection value, JsonGenerator gen, SerializerProvider serializers) throws IOException { + Map mapLikeValue = new HashMap<>(); + for (CollectionLink cl : value) { + mapLikeValue.put(cl.getName(), cl); + } + gen.writeObject(mapLikeValue); + } + } + } diff --git a/src/main/java/com/arangodb/internal/serde/MapperProvider.java b/src/main/java/com/arangodb/internal/serde/MapperProvider.java index 30ac3a14b..2f0152b19 100644 --- a/src/main/java/com/arangodb/internal/serde/MapperProvider.java +++ b/src/main/java/com/arangodb/internal/serde/MapperProvider.java @@ -1,7 +1,5 @@ package com.arangodb.internal.serde; -import com.arangodb.internal.serde.JsonMapperProvider; -import com.arangodb.internal.serde.VPackMapperProvider; import com.arangodb.serde.DataType; import com.fasterxml.jackson.databind.ObjectMapper; diff --git a/src/main/java/com/arangodb/internal/serde/SerdeUtils.java b/src/main/java/com/arangodb/internal/serde/SerdeUtils.java index f72322514..0a4d83374 100644 --- a/src/main/java/com/arangodb/internal/serde/SerdeUtils.java +++ b/src/main/java/com/arangodb/internal/serde/SerdeUtils.java @@ -20,32 +20,6 @@ public enum SerdeUtils { private final ObjectMapper jsonMapper = new ObjectMapper(); - /** - * Parse a JSON string. - * - * @param json JSON string to parse - * @return root of the parsed tree - */ - public JsonNode parseJson(final String json) { - try { - return jsonMapper.readTree(json); - } catch (JsonProcessingException e) { - throw new ArangoDBException(e); - } - } - - /** - * @param data JsonNode - * @return JSON string - */ - public String writeJson(final JsonNode data) { - try { - return jsonMapper.writeValueAsString(data); - } catch (JsonProcessingException e) { - throw new ArangoDBException(e); - } - } - public static Type constructListType(Class clazz) { return TypeFactory.defaultInstance().constructCollectionType(List.class, clazz); } @@ -81,4 +55,30 @@ static void checkSupportedJacksonVersion() { }); } + /** + * Parse a JSON string. + * + * @param json JSON string to parse + * @return root of the parsed tree + */ + public JsonNode parseJson(final String json) { + try { + return jsonMapper.readTree(json); + } catch (JsonProcessingException e) { + throw new ArangoDBException(e); + } + } + + /** + * @param data JsonNode + * @return JSON string + */ + public String writeJson(final JsonNode data) { + try { + return jsonMapper.writeValueAsString(data); + } catch (JsonProcessingException e) { + throw new ArangoDBException(e); + } + } + } diff --git a/src/main/java/com/arangodb/internal/util/DocumentUtil.java b/src/main/java/com/arangodb/internal/util/DocumentUtil.java index 94792e6cb..239ad7371 100644 --- a/src/main/java/com/arangodb/internal/util/DocumentUtil.java +++ b/src/main/java/com/arangodb/internal/util/DocumentUtil.java @@ -29,9 +29,9 @@ */ public final class DocumentUtil { - private static final String SLASH = "/"; public static final String REGEX_KEY = "[^/]+"; public static final String REGEX_ID = "[^/]+/[^/]+"; + private static final String SLASH = "/"; private DocumentUtil() { super(); @@ -41,11 +41,11 @@ public static void validateIndexId(final String id) { validateName("index id", REGEX_ID, id); } - public static void validateDocumentKey(final String key) { + public static void validateDocumentKey(final String key) { validateName("document key", REGEX_KEY, key); } - public static void validateDocumentId(final String id) { + public static void validateDocumentId(final String id) { validateName("document id", REGEX_ID, id); } @@ -54,8 +54,7 @@ public static String createDocumentHandle(final String collection, final String return collection + SLASH + key; } - private static void validateName(final String type, final String regex, final CharSequence name) - { + private static void validateName(final String type, final String regex, final CharSequence name) { if (!Pattern.matches(regex, name)) { throw new ArangoDBException(String.format("%s %s is not valid.", type, name)); } diff --git a/src/main/java/com/arangodb/internal/util/ResponseUtils.java b/src/main/java/com/arangodb/internal/util/ResponseUtils.java index 64d75efd6..d09cd181b 100644 --- a/src/main/java/com/arangodb/internal/util/ResponseUtils.java +++ b/src/main/java/com/arangodb/internal/util/ResponseUtils.java @@ -42,7 +42,7 @@ private ResponseUtils() { super(); } - public static void checkError(final InternalSerde util, final Response response) { + public static void checkError(final InternalSerde util, final Response response) { final int responseCode = response.getResponseCode(); if (responseCode >= ERROR_STATUS) { if (responseCode == ERROR_INTERNAL && response.getMeta().containsKey(HEADER_ENDPOINT)) { diff --git a/src/main/java/com/arangodb/internal/velocystream/VstCommunication.java b/src/main/java/com/arangodb/internal/velocystream/VstCommunication.java index 557fddc53..192aa1e71 100644 --- a/src/main/java/com/arangodb/internal/velocystream/VstCommunication.java +++ b/src/main/java/com/arangodb/internal/velocystream/VstCommunication.java @@ -26,12 +26,12 @@ import com.arangodb.internal.net.Host; import com.arangodb.internal.net.HostHandle; import com.arangodb.internal.net.HostHandler; +import com.arangodb.internal.serde.InternalSerde; import com.arangodb.internal.util.RequestUtils; import com.arangodb.internal.util.ResponseUtils; import com.arangodb.internal.velocystream.internal.Chunk; import com.arangodb.internal.velocystream.internal.Message; import com.arangodb.internal.velocystream.internal.VstConnection; -import com.arangodb.internal.serde.InternalSerde; import com.arangodb.velocypack.VPackSlice; import com.arangodb.velocypack.exception.VPackParserException; import com.arangodb.velocystream.Request; @@ -53,17 +53,15 @@ public abstract class VstCommunication implements Cl protected static final String ENCRYPTION_PLAIN = "plain"; protected static final String ENCRYPTION_JWT = "jwt"; - private static final Logger LOGGER = LoggerFactory.getLogger(VstCommunication.class); - protected static final AtomicLong mId = new AtomicLong(0L); + private static final Logger LOGGER = LoggerFactory.getLogger(VstCommunication.class); protected final InternalSerde util; protected final String user; protected final String password; - protected volatile String jwt; - protected final Integer chunksize; protected final HostHandler hostHandler; + protected volatile String jwt; protected VstCommunication(final Integer timeout, final String user, final String password, final String jwt, final Boolean useSsl, final SSLContext sslContext, final InternalSerde util, @@ -140,20 +138,20 @@ public void close() throws IOException { hostHandler.close(); } - public R execute(final Request request, final HostHandle hostHandle) { + public R execute(final Request request, final HostHandle hostHandle) { return execute(request, hostHandle, 0); } - protected R execute(final Request request, final HostHandle hostHandle, final int attemptCount) { + protected R execute(final Request request, final HostHandle hostHandle, final int attemptCount) { final C connection = connect(hostHandle, RequestUtils.determineAccessType(request)); return execute(request, connection, attemptCount); } - protected abstract R execute(final Request request, C connection) ; + protected abstract R execute(final Request request, C connection); - protected abstract R execute(final Request request, C connection, final int attemptCount) ; + protected abstract R execute(final Request request, C connection, final int attemptCount); - protected void checkError(final Response response) { + protected void checkError(final Response response) { ResponseUtils.checkError(util, response); } diff --git a/src/main/java/com/arangodb/internal/velocystream/VstCommunicationSync.java b/src/main/java/com/arangodb/internal/velocystream/VstCommunicationSync.java index 76e258f93..b475f39a2 100644 --- a/src/main/java/com/arangodb/internal/velocystream/VstCommunicationSync.java +++ b/src/main/java/com/arangodb/internal/velocystream/VstCommunicationSync.java @@ -25,12 +25,12 @@ import com.arangodb.internal.net.HostDescription; import com.arangodb.internal.net.HostHandle; import com.arangodb.internal.net.HostHandler; +import com.arangodb.internal.serde.InternalSerde; import com.arangodb.internal.util.HostUtils; import com.arangodb.internal.velocystream.internal.AuthenticationRequest; import com.arangodb.internal.velocystream.internal.JwtAuthenticationRequest; import com.arangodb.internal.velocystream.internal.Message; import com.arangodb.internal.velocystream.internal.VstConnectionSync; -import com.arangodb.internal.serde.InternalSerde; import com.arangodb.velocypack.exception.VPackParserException; import com.arangodb.velocystream.Request; import com.arangodb.velocystream.Response; @@ -46,6 +46,59 @@ public class VstCommunicationSync extends VstCommunication= 3) { + throw e; + } + final String location = e.getLocation(); + final HostDescription redirectHost = HostUtils.createFromLocation(location); + hostHandler.failIfNotMatch(redirectHost, e); + return execute(request, new HostHandle().setHost(redirectHost), attemptCount + 1); + } + } + + private Message send(final Message message, final VstConnectionSync connection) { + if (LOGGER.isDebugEnabled()) { + LOGGER.debug(String.format("Send Message (id=%s, head=%s, body=%s)", message.getId(), message.getHead(), + message.getBody() != null ? message.getBody() : "{}")); + } + return connection.write(message, buildChunks(message)); + } + + @Override + protected void authenticate(final VstConnectionSync connection) { + Request authRequest; + if (jwt != null) { + authRequest = new JwtAuthenticationRequest(jwt, ENCRYPTION_JWT); + } else { + authRequest = new AuthenticationRequest(user, password != null ? password : "", ENCRYPTION_PLAIN); + } + final Response response = execute(authRequest, connection); + checkError(response); + } + public static class Builder { private final HostHandler hostHandler; @@ -123,57 +176,4 @@ public VstCommunication build(final InternalSerde u } - protected VstCommunicationSync(final HostHandler hostHandler, final Integer timeout, final String user, - final String password, final String jwt, final Boolean useSsl, - final SSLContext sslContext, final InternalSerde util, - final Integer chunksize, final Integer maxConnections, final Long ttl) { - super(timeout, user, password, jwt, useSsl, sslContext, util, chunksize, hostHandler); - } - - @Override - protected Response execute(final Request request, final VstConnectionSync connection) { - return execute(request, connection, 0); - } - - @Override - protected Response execute(final Request request, final VstConnectionSync connection, final int attemptCount) { - try { - final Message requestMessage = createMessage(request); - final Message responseMessage = send(requestMessage, connection); - final Response response = createResponse(responseMessage); - checkError(response); - return response; - } catch (final VPackParserException e) { - throw new ArangoDBException(e); - } catch (final ArangoDBRedirectException e) { - if (attemptCount >= 3) { - throw e; - } - final String location = e.getLocation(); - final HostDescription redirectHost = HostUtils.createFromLocation(location); - hostHandler.failIfNotMatch(redirectHost, e); - return execute(request, new HostHandle().setHost(redirectHost), attemptCount + 1); - } - } - - private Message send(final Message message, final VstConnectionSync connection) { - if (LOGGER.isDebugEnabled()) { - LOGGER.debug(String.format("Send Message (id=%s, head=%s, body=%s)", message.getId(), message.getHead(), - message.getBody() != null ? message.getBody() : "{}")); - } - return connection.write(message, buildChunks(message)); - } - - @Override - protected void authenticate(final VstConnectionSync connection) { - Request authRequest; - if (jwt != null) { - authRequest = new JwtAuthenticationRequest(jwt, ENCRYPTION_JWT); - } else { - authRequest = new AuthenticationRequest(user, password != null ? password : "", ENCRYPTION_PLAIN); - } - final Response response = execute(authRequest, connection); - checkError(response); - } - } diff --git a/src/main/java/com/arangodb/internal/velocystream/VstProtocol.java b/src/main/java/com/arangodb/internal/velocystream/VstProtocol.java index 55f0fdd68..054af4258 100644 --- a/src/main/java/com/arangodb/internal/velocystream/VstProtocol.java +++ b/src/main/java/com/arangodb/internal/velocystream/VstProtocol.java @@ -20,7 +20,6 @@ package com.arangodb.internal.velocystream; -import com.arangodb.ArangoDBException; import com.arangodb.internal.net.CommunicationProtocol; import com.arangodb.internal.net.HostHandle; import com.arangodb.internal.velocystream.internal.VstConnectionSync; @@ -42,7 +41,7 @@ public VstProtocol(final VstCommunication communica } @Override - public Response execute(final Request request, final HostHandle hostHandle) { + public Response execute(final Request request, final HostHandle hostHandle) { return communication.execute(request, hostHandle); } diff --git a/src/main/java/com/arangodb/internal/velocystream/internal/MessageStore.java b/src/main/java/com/arangodb/internal/velocystream/internal/MessageStore.java index dd25ae976..f8cb1e5a1 100644 --- a/src/main/java/com/arangodb/internal/velocystream/internal/MessageStore.java +++ b/src/main/java/com/arangodb/internal/velocystream/internal/MessageStore.java @@ -63,7 +63,7 @@ public void consume(final Message message) { } } - public Message get(final long messageId) { + public Message get(final long messageId) { final Message result = response.remove(messageId); if (result == null) { final Exception e = error.remove(messageId); diff --git a/src/main/java/com/arangodb/internal/velocystream/internal/VstConnection.java b/src/main/java/com/arangodb/internal/velocystream/internal/VstConnection.java index 70b9ea98b..f920d85fc 100644 --- a/src/main/java/com/arangodb/internal/velocystream/internal/VstConnection.java +++ b/src/main/java/com/arangodb/internal/velocystream/internal/VstConnection.java @@ -46,12 +46,7 @@ import java.util.Collections; import java.util.Date; import java.util.Map; -import java.util.concurrent.Callable; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.TimeUnit; +import java.util.concurrent.*; import java.util.concurrent.atomic.AtomicLong; /** @@ -60,33 +55,16 @@ public abstract class VstConnection implements Connection { private static final Logger LOGGER = LoggerFactory.getLogger(VstConnection.class); private static final byte[] PROTOCOL_HEADER = "VST/1.0\r\n\r\n".getBytes(); - - private ExecutorService executor; - - private ScheduledExecutorService keepAliveScheduler; - private final AtomicLong keepAliveId = new AtomicLong(); - protected final MessageStore messageStore; - protected final Integer timeout; + private final AtomicLong keepAliveId = new AtomicLong(); private final Long ttl; - private final Integer keepAliveInterval; - private int keepAliveFailCounter = 0; - private final Boolean useSsl; private final SSLContext sslContext; - - private Socket socket; - private OutputStream outputStream; - private InputStream inputStream; - private final HostDescription host; - private final Map sendTimestamps = new ConcurrentHashMap<>(); - private final String connectionName; - private final byte[] keepAliveRequest = new VPackBuilder() .add(ValueType.ARRAY) .add(1) @@ -101,6 +79,12 @@ public abstract class VstConnection implements Connection { .close() .slice() .toByteArray(); + private ExecutorService executor; + private ScheduledExecutorService keepAliveScheduler; + private int keepAliveFailCounter = 0; + private Socket socket; + private OutputStream outputStream; + private InputStream inputStream; protected VstConnection(final HostDescription host, final Integer timeout, @@ -266,8 +250,7 @@ private synchronized void sendProtocolHeader() throws IOException { outputStream.flush(); } - protected synchronized void writeIntern(final Message message, final Collection chunks) - { + protected synchronized void writeIntern(final Message message, final Collection chunks) { for (final Chunk chunk : chunks) { try { if (LOGGER.isDebugEnabled()) { diff --git a/src/main/java/com/arangodb/internal/velocystream/internal/VstConnectionSync.java b/src/main/java/com/arangodb/internal/velocystream/internal/VstConnectionSync.java index cf1490985..95d659b20 100644 --- a/src/main/java/com/arangodb/internal/velocystream/internal/VstConnectionSync.java +++ b/src/main/java/com/arangodb/internal/velocystream/internal/VstConnectionSync.java @@ -33,6 +33,28 @@ */ public class VstConnectionSync extends VstConnection { + private VstConnectionSync(final HostDescription host, final Integer timeout, final Long ttl, final Integer keepAliveInterval, + final Boolean useSsl, final SSLContext sslContext, final MessageStore messageStore) { + super(host, timeout, ttl, keepAliveInterval, useSsl, sslContext, messageStore); + } + + @Override + public Message write(final Message message, final Collection chunks) { + final FutureTask task = new FutureTask<>(() -> messageStore.get(message.getId())); + messageStore.storeMessage(message.getId(), task); + super.writeIntern(message, chunks); + try { + return timeout == null || timeout == 0L ? task.get() : task.get(timeout, TimeUnit.MILLISECONDS); + } catch (final Exception e) { + throw new ArangoDBException(e); + } + } + + @Override + protected void doKeepAlive() { + sendKeepAlive(); + } + public static class Builder { private HostDescription host; @@ -84,26 +106,4 @@ public VstConnectionSync build() { } } - private VstConnectionSync(final HostDescription host, final Integer timeout, final Long ttl, final Integer keepAliveInterval, - final Boolean useSsl, final SSLContext sslContext, final MessageStore messageStore) { - super(host, timeout, ttl, keepAliveInterval, useSsl, sslContext, messageStore); - } - - @Override - public Message write(final Message message, final Collection chunks) { - final FutureTask task = new FutureTask<>(() -> messageStore.get(message.getId())); - messageStore.storeMessage(message.getId(), task); - super.writeIntern(message, chunks); - try { - return timeout == null || timeout == 0L ? task.get() : task.get(timeout, TimeUnit.MILLISECONDS); - } catch (final Exception e) { - throw new ArangoDBException(e); - } - } - - @Override - protected void doKeepAlive() { - sendKeepAlive(); - } - } diff --git a/src/main/java/com/arangodb/model/AqlQueryOptions.java b/src/main/java/com/arangodb/model/AqlQueryOptions.java index 1ae4c51f4..458219c0a 100644 --- a/src/main/java/com/arangodb/model/AqlQueryOptions.java +++ b/src/main/java/com/arangodb/model/AqlQueryOptions.java @@ -405,6 +405,36 @@ public Options getOptions() { return options; } + /** + * @param allowDirtyRead Set to {@code true} allows reading from followers in an active-failover setup. + * @return options + * @see API + * Documentation + * @since ArangoDB 3.4.0 + */ + public AqlQueryOptions allowDirtyRead(final Boolean allowDirtyRead) { + this.allowDirtyRead = allowDirtyRead; + return this; + } + + public Boolean getAllowDirtyRead() { + return allowDirtyRead; + } + + public String getStreamTransactionId() { + return streamTransactionId; + } + + /** + * @param streamTransactionId If set, the operation will be executed within the transaction. + * @return options + * @since ArangoDB 3.5.0 + */ + public AqlQueryOptions streamTransactionId(final String streamTransactionId) { + this.streamTransactionId = streamTransactionId; + return this; + } + public static final class Options { private Boolean failOnWarning; @@ -496,34 +526,4 @@ public Collection getRules() { } } - /** - * @param allowDirtyRead Set to {@code true} allows reading from followers in an active-failover setup. - * @return options - * @see API - * Documentation - * @since ArangoDB 3.4.0 - */ - public AqlQueryOptions allowDirtyRead(final Boolean allowDirtyRead) { - this.allowDirtyRead = allowDirtyRead; - return this; - } - - public Boolean getAllowDirtyRead() { - return allowDirtyRead; - } - - public String getStreamTransactionId() { - return streamTransactionId; - } - - /** - * @param streamTransactionId If set, the operation will be executed within the transaction. - * @return options - * @since ArangoDB 3.5.0 - */ - public AqlQueryOptions streamTransactionId(final String streamTransactionId) { - this.streamTransactionId = streamTransactionId; - return this; - } - } diff --git a/src/main/java/com/arangodb/model/CollectionCreateOptions.java b/src/main/java/com/arangodb/model/CollectionCreateOptions.java index fa7ebc9db..dceeb77ce 100644 --- a/src/main/java/com/arangodb/model/CollectionCreateOptions.java +++ b/src/main/java/com/arangodb/model/CollectionCreateOptions.java @@ -259,8 +259,7 @@ public CollectionSchema getSchema() { } /** - * @param schema - * object that specifies the collection level schema for documents + * @param schema object that specifies the collection level schema for documents * @return options * @since ArangoDB 3.7 */ diff --git a/src/main/java/com/arangodb/model/CollectionPropertiesOptions.java b/src/main/java/com/arangodb/model/CollectionPropertiesOptions.java index c10909e65..3d64239b9 100644 --- a/src/main/java/com/arangodb/model/CollectionPropertiesOptions.java +++ b/src/main/java/com/arangodb/model/CollectionPropertiesOptions.java @@ -53,8 +53,8 @@ public CollectionSchema getSchema() { /** * @param schema object that specifies the collection level schema for documents - * @since ArangoDB 3.7 * @return options + * @since ArangoDB 3.7 */ public CollectionPropertiesOptions schema(final CollectionSchema schema) { this.schema = schema; diff --git a/src/main/java/com/arangodb/model/CollectionSchema.java b/src/main/java/com/arangodb/model/CollectionSchema.java index 9a0164be6..92d685d25 100644 --- a/src/main/java/com/arangodb/model/CollectionSchema.java +++ b/src/main/java/com/arangodb/model/CollectionSchema.java @@ -108,6 +108,10 @@ public enum Level { private final String value; + Level(String value) { + this.value = value; + } + public static Level of(String label) { for (Level e : values()) { if (e.value.equals(label)) { @@ -117,10 +121,6 @@ public static Level of(String label) { return null; } - Level(String value) { - this.value = value; - } - public String getValue() { return value; } diff --git a/src/main/java/com/arangodb/model/DocumentImportOptions.java b/src/main/java/com/arangodb/model/DocumentImportOptions.java index 4cd40b71b..c6dbfb6fc 100644 --- a/src/main/java/com/arangodb/model/DocumentImportOptions.java +++ b/src/main/java/com/arangodb/model/DocumentImportOptions.java @@ -25,10 +25,6 @@ */ public final class DocumentImportOptions { - public enum OnDuplicate { - error, update, replace, ignore - } - private String fromPrefix; private String toPrefix; private Boolean overwrite; @@ -36,7 +32,6 @@ public enum OnDuplicate { private OnDuplicate onDuplicate; private Boolean complete; private Boolean details; - public DocumentImportOptions() { super(); } @@ -150,4 +145,8 @@ public DocumentImportOptions details(final Boolean details) { return this; } + public enum OnDuplicate { + error, update, replace, ignore + } + } diff --git a/src/main/java/com/arangodb/model/FulltextIndexOptions.java b/src/main/java/com/arangodb/model/FulltextIndexOptions.java index 89bb478e3..d309bd3aa 100644 --- a/src/main/java/com/arangodb/model/FulltextIndexOptions.java +++ b/src/main/java/com/arangodb/model/FulltextIndexOptions.java @@ -29,8 +29,8 @@ */ public final class FulltextIndexOptions extends IndexOptions { - private Iterable fields; private final IndexType type = IndexType.fulltext; + private Iterable fields; private Integer minLength; public FulltextIndexOptions() { diff --git a/src/main/java/com/arangodb/model/GeoIndexOptions.java b/src/main/java/com/arangodb/model/GeoIndexOptions.java index 3b2fb9446..7e06bf81c 100644 --- a/src/main/java/com/arangodb/model/GeoIndexOptions.java +++ b/src/main/java/com/arangodb/model/GeoIndexOptions.java @@ -28,8 +28,8 @@ */ public final class GeoIndexOptions extends IndexOptions { - private Iterable fields; private final IndexType type = IndexType.geo; + private Iterable fields; private Boolean geoJson; public GeoIndexOptions() { diff --git a/src/main/java/com/arangodb/model/HashIndexOptions.java b/src/main/java/com/arangodb/model/HashIndexOptions.java index 1192f601c..9e22c633a 100644 --- a/src/main/java/com/arangodb/model/HashIndexOptions.java +++ b/src/main/java/com/arangodb/model/HashIndexOptions.java @@ -31,8 +31,8 @@ @Deprecated public final class HashIndexOptions extends IndexOptions { - private Iterable fields; private final IndexType type = IndexType.hash; + private Iterable fields; private Boolean unique; private Boolean sparse; private Boolean deduplicate; @@ -95,8 +95,7 @@ public Boolean getDeduplicate() { } /** - * @param deduplicate - * if false, the deduplication of array values is turned off. + * @param deduplicate if false, the deduplication of array values is turned off. * @return options */ public HashIndexOptions deduplicate(final Boolean deduplicate) { @@ -105,9 +104,8 @@ public HashIndexOptions deduplicate(final Boolean deduplicate) { } /** - * @param estimates - * This attribute controls whether index selectivity estimates are maintained for the index. Default: {@code - * true} + * @param estimates This attribute controls whether index selectivity estimates are maintained for the index. Default: {@code + * true} * @since ArangoDB 3.8 */ public HashIndexOptions estimates(final Boolean estimates) { diff --git a/src/main/java/com/arangodb/model/LogOptions.java b/src/main/java/com/arangodb/model/LogOptions.java index 944305f3e..861dbefb3 100644 --- a/src/main/java/com/arangodb/model/LogOptions.java +++ b/src/main/java/com/arangodb/model/LogOptions.java @@ -37,11 +37,6 @@ public final class LogOptions { public static final String PROPERTY_OFFSET = "offset"; public static final String PROPERTY_SEARCH = "search"; public static final String PROPERTY_SORT = "sort"; - - public enum SortOrder { - asc, desc - } - private LogLevel upto; private LogLevel level; private Long start; @@ -49,7 +44,6 @@ public enum SortOrder { private Integer offset; private String search; private SortOrder sort; - public LogOptions() { super(); } @@ -148,4 +142,8 @@ public LogOptions sort(final SortOrder sort) { return this; } + public enum SortOrder { + asc, desc + } + } diff --git a/src/main/java/com/arangodb/model/PersistentIndexOptions.java b/src/main/java/com/arangodb/model/PersistentIndexOptions.java index 598054551..ce9917ba6 100644 --- a/src/main/java/com/arangodb/model/PersistentIndexOptions.java +++ b/src/main/java/com/arangodb/model/PersistentIndexOptions.java @@ -29,8 +29,8 @@ */ public final class PersistentIndexOptions extends IndexOptions { - private Iterable fields; private final IndexType type = IndexType.persistent; + private Iterable fields; private Boolean unique; private Boolean sparse; private Boolean deduplicate; @@ -80,8 +80,7 @@ public Boolean getSparse() { } /** - * @param sparse - * if true, then create a sparse index + * @param sparse if true, then create a sparse index * @return options */ public PersistentIndexOptions sparse(final Boolean sparse) { @@ -94,8 +93,7 @@ public Boolean getDeduplicate() { } /** - * @param deduplicate - * if false, the deduplication of array values is turned off. Default: {@code true} + * @param deduplicate if false, the deduplication of array values is turned off. Default: {@code true} * @return options */ public PersistentIndexOptions deduplicate(final Boolean deduplicate) { @@ -104,9 +102,8 @@ public PersistentIndexOptions deduplicate(final Boolean deduplicate) { } /** - * @param estimates - * This attribute controls whether index selectivity estimates are maintained for the index. Default: {@code - * true} + * @param estimates This attribute controls whether index selectivity estimates are maintained for the index. Default: {@code + * true} * @since ArangoDB 3.8 */ public PersistentIndexOptions estimates(final Boolean estimates) { diff --git a/src/main/java/com/arangodb/model/SkiplistIndexOptions.java b/src/main/java/com/arangodb/model/SkiplistIndexOptions.java index 1ab9babb5..86fca8f0b 100644 --- a/src/main/java/com/arangodb/model/SkiplistIndexOptions.java +++ b/src/main/java/com/arangodb/model/SkiplistIndexOptions.java @@ -31,8 +31,8 @@ @Deprecated public final class SkiplistIndexOptions extends IndexOptions { - private Iterable fields; private final IndexType type = IndexType.skiplist; + private Iterable fields; private Boolean unique; private Boolean sparse; private Boolean deduplicate; @@ -95,8 +95,7 @@ public Boolean getDeduplicate() { } /** - * @param deduplicate - * if false, the deduplication of array values is turned off. + * @param deduplicate if false, the deduplication of array values is turned off. * @return options */ public SkiplistIndexOptions deduplicate(final Boolean deduplicate) { @@ -105,9 +104,8 @@ public SkiplistIndexOptions deduplicate(final Boolean deduplicate) { } /** - * @param estimates - * This attribute controls whether index selectivity estimates are maintained for the index. Default: {@code - * true} + * @param estimates This attribute controls whether index selectivity estimates are maintained for the index. Default: {@code + * true} * @since ArangoDB 3.8 */ public SkiplistIndexOptions estimates(final Boolean estimates) { diff --git a/src/main/java/com/arangodb/model/TransactionOptions.java b/src/main/java/com/arangodb/model/TransactionOptions.java index 19b5b2599..726f75edf 100644 --- a/src/main/java/com/arangodb/model/TransactionOptions.java +++ b/src/main/java/com/arangodb/model/TransactionOptions.java @@ -28,9 +28,9 @@ */ public final class TransactionOptions { + private final TransactionCollectionOptions collections; private String action; private Object params; - private final TransactionCollectionOptions collections; private Integer lockTimeout; private Boolean waitForSync; private Long maxTransactionSize; diff --git a/src/main/java/com/arangodb/model/TtlIndexOptions.java b/src/main/java/com/arangodb/model/TtlIndexOptions.java index c599a614e..023c12fa3 100644 --- a/src/main/java/com/arangodb/model/TtlIndexOptions.java +++ b/src/main/java/com/arangodb/model/TtlIndexOptions.java @@ -28,8 +28,8 @@ */ public final class TtlIndexOptions extends IndexOptions { - private Iterable fields; private final IndexType type = IndexType.ttl; + private Iterable fields; private Integer expireAfter; public TtlIndexOptions() { diff --git a/src/main/java/com/arangodb/model/VertexCollectionCreateOptions.java b/src/main/java/com/arangodb/model/VertexCollectionCreateOptions.java index 86fa34067..a832f3f88 100644 --- a/src/main/java/com/arangodb/model/VertexCollectionCreateOptions.java +++ b/src/main/java/com/arangodb/model/VertexCollectionCreateOptions.java @@ -28,8 +28,8 @@ */ public final class VertexCollectionCreateOptions { - private String collection; private final Options options = new Options(); + private String collection; public VertexCollectionCreateOptions() { super(); diff --git a/src/main/java/com/arangodb/model/ViewCreateOptions.java b/src/main/java/com/arangodb/model/ViewCreateOptions.java index 69e329963..e0a58273d 100644 --- a/src/main/java/com/arangodb/model/ViewCreateOptions.java +++ b/src/main/java/com/arangodb/model/ViewCreateOptions.java @@ -27,8 +27,8 @@ */ public final class ViewCreateOptions { - private String name; - private ViewType type; + private String name; + private ViewType type; public ViewCreateOptions() { super(); diff --git a/src/main/java/com/arangodb/model/ZKDIndexOptions.java b/src/main/java/com/arangodb/model/ZKDIndexOptions.java index aad739d86..e4742e8ed 100644 --- a/src/main/java/com/arangodb/model/ZKDIndexOptions.java +++ b/src/main/java/com/arangodb/model/ZKDIndexOptions.java @@ -30,8 +30,8 @@ */ public final class ZKDIndexOptions extends IndexOptions { - private Iterable fields; final IndexType type = IndexType.zkd; + private Iterable fields; private Boolean unique; private FieldValueTypes fieldValueTypes; diff --git a/src/main/java/com/arangodb/model/arangosearch/ArangoSearchCreateOptions.java b/src/main/java/com/arangodb/model/arangosearch/ArangoSearchCreateOptions.java index 871b334e8..a6fa3b8b8 100644 --- a/src/main/java/com/arangodb/model/arangosearch/ArangoSearchCreateOptions.java +++ b/src/main/java/com/arangodb/model/arangosearch/ArangoSearchCreateOptions.java @@ -33,8 +33,8 @@ */ public final class ArangoSearchCreateOptions { - private String name; - private final ViewType type; + private final ViewType type; + private String name; private Long consolidationIntervalMsec; private Long commitIntervalMsec; private Long cleanupIntervalStep; diff --git a/src/main/java/com/arangodb/serde/JacksonSerde.java b/src/main/java/com/arangodb/serde/JacksonSerde.java index 99256a397..dfaa24cfd 100644 --- a/src/main/java/com/arangodb/serde/JacksonSerde.java +++ b/src/main/java/com/arangodb/serde/JacksonSerde.java @@ -24,7 +24,7 @@ static JacksonSerde of(final DataType dataType) { /** * Creates a new JacksonSerde using the provided ObjectMapper. * - * @param mapper Jackson ObjectMapper to use + * @param mapper Jackson ObjectMapper to use * @return the created JacksonSerde */ static JacksonSerde create(final ObjectMapper mapper) { @@ -33,6 +33,7 @@ static JacksonSerde create(final ObjectMapper mapper) { /** * Allows configuring the underlying Jackson ObjectMapper + * * @param configureFunction function to configure the Jackson ObjectMapper */ void configure(final Consumer configureFunction); diff --git a/src/main/java/com/arangodb/util/ArangoCursorInitializer.java b/src/main/java/com/arangodb/util/ArangoCursorInitializer.java index 6344bf2d3..b00721917 100644 --- a/src/main/java/com/arangodb/util/ArangoCursorInitializer.java +++ b/src/main/java/com/arangodb/util/ArangoCursorInitializer.java @@ -21,9 +21,9 @@ package com.arangodb.util; import com.arangodb.ArangoCursor; -import com.arangodb.internal.cursor.entity.InternalCursorEntity; import com.arangodb.internal.ArangoCursorExecute; import com.arangodb.internal.InternalArangoDatabase; +import com.arangodb.internal.cursor.entity.InternalCursorEntity; /** * @author Mark Vollmary diff --git a/src/main/java/com/arangodb/util/RawBytes.java b/src/main/java/com/arangodb/util/RawBytes.java index 202812901..82c9adaae 100644 --- a/src/main/java/com/arangodb/util/RawBytes.java +++ b/src/main/java/com/arangodb/util/RawBytes.java @@ -22,14 +22,14 @@ public class RawBytes { private final byte[] value; - public static RawBytes of(final byte[] value) { - return new RawBytes(value); - } - protected RawBytes(final byte[] value) { this.value = value; } + public static RawBytes of(final byte[] value) { + return new RawBytes(value); + } + public byte[] getValue() { return value; } diff --git a/src/main/java/com/arangodb/util/RawJson.java b/src/main/java/com/arangodb/util/RawJson.java index 89d6e3a4b..45bad862d 100644 --- a/src/main/java/com/arangodb/util/RawJson.java +++ b/src/main/java/com/arangodb/util/RawJson.java @@ -16,14 +16,14 @@ public class RawJson { private final String value; - public static RawJson of(final String value) { - return new RawJson(value); - } - protected RawJson(final String value) { this.value = value; } + public static RawJson of(final String value) { + return new RawJson(value); + } + public String getValue() { return value; } diff --git a/src/main/java/com/arangodb/velocystream/Request.java b/src/main/java/com/arangodb/velocystream/Request.java index 678808e59..666b00e21 100644 --- a/src/main/java/com/arangodb/velocystream/Request.java +++ b/src/main/java/com/arangodb/velocystream/Request.java @@ -30,13 +30,13 @@ */ public class Request { - private int version = 1; - private int type = 1; private final DbName dbName; private final RequestType requestType; private final String request; private final Map queryParam; private final Map headerParam; + private int version = 1; + private int type = 1; private byte[] body; public Request(final DbName dbName, final RequestType requestType, final String path) { diff --git a/src/main/java/com/arangodb/velocystream/RequestType.java b/src/main/java/com/arangodb/velocystream/RequestType.java index f9f18192f..43b04dd9d 100644 --- a/src/main/java/com/arangodb/velocystream/RequestType.java +++ b/src/main/java/com/arangodb/velocystream/RequestType.java @@ -43,10 +43,6 @@ public enum RequestType { this.type = type; } - public int getType() { - return type; - } - public static RequestType fromType(final int type) { for (final RequestType rType : RequestType.values()) { if (rType.type == type) { @@ -55,4 +51,8 @@ public static RequestType fromType(final int type) { } return null; } + + public int getType() { + return type; + } } From 50c0d5fa7de431c6c89cf382007c9ccc7e9ec225 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Tue, 16 Aug 2022 11:57:32 +0200 Subject: [PATCH 090/254] code analysis fixes --- src/main/java/com/arangodb/ArangoCollection.java | 1 - src/main/java/com/arangodb/entity/ShardingStrategy.java | 2 +- .../arangodb/entity/arangosearch/analyzer/IdentityAnalyzer.java | 2 ++ src/main/java/com/arangodb/model/AqlFunctionGetOptions.java | 2 +- src/main/java/com/arangodb/model/IndexOptions.java | 2 +- 5 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/arangodb/ArangoCollection.java b/src/main/java/com/arangodb/ArangoCollection.java index 503a3dd8d..77497971c 100644 --- a/src/main/java/com/arangodb/ArangoCollection.java +++ b/src/main/java/com/arangodb/ArangoCollection.java @@ -444,7 +444,6 @@ MultiDocumentEntity> deleteDocuments( * @param key The key of the document * @param options Additional options, can be null * @return true if the document was found, otherwise false - * only thrown when {@link DocumentExistsOptions#isCatchException()} == false * @see API * Documentation diff --git a/src/main/java/com/arangodb/entity/ShardingStrategy.java b/src/main/java/com/arangodb/entity/ShardingStrategy.java index a75e3b74d..d00108c51 100644 --- a/src/main/java/com/arangodb/entity/ShardingStrategy.java +++ b/src/main/java/com/arangodb/entity/ShardingStrategy.java @@ -22,7 +22,7 @@ /** * @author Axel Becker - * https://www.arangodb.com/docs/stable/http/collection-creating.html + * API documentation */ public enum ShardingStrategy { diff --git a/src/main/java/com/arangodb/entity/arangosearch/analyzer/IdentityAnalyzer.java b/src/main/java/com/arangodb/entity/arangosearch/analyzer/IdentityAnalyzer.java index e658ea327..14fbfefd5 100644 --- a/src/main/java/com/arangodb/entity/arangosearch/analyzer/IdentityAnalyzer.java +++ b/src/main/java/com/arangodb/entity/arangosearch/analyzer/IdentityAnalyzer.java @@ -36,6 +36,8 @@ public IdentityAnalyzer() { @Override public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; return super.equals(o); } diff --git a/src/main/java/com/arangodb/model/AqlFunctionGetOptions.java b/src/main/java/com/arangodb/model/AqlFunctionGetOptions.java index e5c5dcd95..a043bb60e 100644 --- a/src/main/java/com/arangodb/model/AqlFunctionGetOptions.java +++ b/src/main/java/com/arangodb/model/AqlFunctionGetOptions.java @@ -39,7 +39,7 @@ public String getNamespace() { } /** - * @param namespace Returns all registered AQL user functions from namespace namespace + * @param namespace Returns all registered AQL user functions from namespace * @return options */ public AqlFunctionGetOptions namespace(final String namespace) { diff --git a/src/main/java/com/arangodb/model/IndexOptions.java b/src/main/java/com/arangodb/model/IndexOptions.java index afd7240c1..9f47117ab 100644 --- a/src/main/java/com/arangodb/model/IndexOptions.java +++ b/src/main/java/com/arangodb/model/IndexOptions.java @@ -25,7 +25,7 @@ *

* This final class is used for all index similarities */ -public abstract class IndexOptions { +public abstract class IndexOptions> { private Boolean inBackground; private String name; From d0958e3301168d7035ebd08d4844b070877d93ad Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Tue, 16 Aug 2022 12:03:49 +0200 Subject: [PATCH 091/254] jacoco --- pom.xml | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/pom.xml b/pom.xml index 92b2b5e1d..e72abb327 100644 --- a/pom.xml +++ b/pom.xml @@ -259,6 +259,25 @@ + + org.jacoco + jacoco-maven-plugin + 0.8.8 + + + + prepare-agent + + + + report + prepare-package + + report + + + + From f16f6facf5b9b7b1bc9d4f9d320a670fb39a4b52 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Tue, 16 Aug 2022 12:32:10 +0200 Subject: [PATCH 092/254] spotbugs --- pom.xml | 23 +++++++++++++++++++++++ spotbugs/spotbugs-exclude.xml | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 55 insertions(+) create mode 100644 spotbugs/spotbugs-exclude.xml diff --git a/pom.xml b/pom.xml index e72abb327..d86ea7d31 100644 --- a/pom.xml +++ b/pom.xml @@ -278,6 +278,29 @@ + + com.github.spotbugs + spotbugs-maven-plugin + 4.7.1.1 + + spotbugs/spotbugs-exclude.xml + + + + compile + + check + + + + + + com.github.spotbugs + spotbugs + 4.7.1 + + + diff --git a/spotbugs/spotbugs-exclude.xml b/spotbugs/spotbugs-exclude.xml new file mode 100644 index 000000000..bef77eff5 --- /dev/null +++ b/spotbugs/spotbugs-exclude.xml @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + From ebc6f7a7208f69bb8ecfdf5c841eb159cd942bc0 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Tue, 16 Aug 2022 12:58:15 +0200 Subject: [PATCH 093/254] spotbugs fixes --- spotbugs/spotbugs-exclude.xml | 4 ++++ src/main/java/com/arangodb/ArangoDB.java | 2 +- src/main/java/com/arangodb/async/ArangoDBAsync.java | 2 +- .../com/arangodb/internal/InternalArangoCollection.java | 4 ++-- .../java/com/arangodb/internal/InternalArangoDBBuilder.java | 6 +++++- .../java/com/arangodb/internal/InternalArangoDatabase.java | 6 +++--- .../com/arangodb/internal/InternalArangoEdgeCollection.java | 2 +- .../arangodb/internal/InternalArangoVertexCollection.java | 2 +- .../java/com/arangodb/internal/cursor/ArangoCursorImpl.java | 2 +- .../java/com/arangodb/internal/http/HttpConnection.java | 4 ++-- .../internal/velocystream/internal/VstConnection.java | 4 ++-- 11 files changed, 23 insertions(+), 15 deletions(-) diff --git a/spotbugs/spotbugs-exclude.xml b/spotbugs/spotbugs-exclude.xml index bef77eff5..3062bfbe9 100644 --- a/spotbugs/spotbugs-exclude.xml +++ b/spotbugs/spotbugs-exclude.xml @@ -29,4 +29,8 @@ + + + + diff --git a/src/main/java/com/arangodb/ArangoDB.java b/src/main/java/com/arangodb/ArangoDB.java index 04af3fd2d..aa6204efa 100644 --- a/src/main/java/com/arangodb/ArangoDB.java +++ b/src/main/java/com/arangodb/ArangoDB.java @@ -604,7 +604,7 @@ public Builder serializer(final ArangoSerde serialization) { * * @return {@link ArangoDB} */ - public synchronized ArangoDB build() { + public ArangoDB build() { if (hosts.isEmpty()) { hosts.add(host); } diff --git a/src/main/java/com/arangodb/async/ArangoDBAsync.java b/src/main/java/com/arangodb/async/ArangoDBAsync.java index 2b7a8521f..06b125a09 100644 --- a/src/main/java/com/arangodb/async/ArangoDBAsync.java +++ b/src/main/java/com/arangodb/async/ArangoDBAsync.java @@ -505,7 +505,7 @@ public Builder serializer(final ArangoSerde serialization) { * * @return {@link ArangoDBAsync} */ - public synchronized ArangoDBAsync build() { + public ArangoDBAsync build() { if (hosts.isEmpty()) { hosts.add(host); } diff --git a/src/main/java/com/arangodb/internal/InternalArangoCollection.java b/src/main/java/com/arangodb/internal/InternalArangoCollection.java index e1835bf70..872e88db0 100644 --- a/src/main/java/com/arangodb/internal/InternalArangoCollection.java +++ b/src/main/java/com/arangodb/internal/InternalArangoCollection.java @@ -161,7 +161,7 @@ protected Request getDocumentRequest(final String key, final DocumentReadOptions request.putHeaderParam(ArangoRequestParam.IF_NONE_MATCH, params.getIfNoneMatch()); request.putHeaderParam(ArangoRequestParam.IF_MATCH, params.getIfMatch()); request.putHeaderParam(TRANSACTION_ID, params.getStreamTransactionId()); - if (params.getAllowDirtyRead() == Boolean.TRUE) { + if (Boolean.TRUE.equals(params.getAllowDirtyRead())) { RequestUtils.allowDirtyRead(request); } return request; @@ -178,7 +178,7 @@ protected Request getDocumentsRequest(final Collection keys, final Docum .putHeaderParam(ArangoRequestParam.IF_NONE_MATCH, params.getIfNoneMatch()) .putHeaderParam(ArangoRequestParam.IF_MATCH, params.getIfMatch()).setBody(getSerde().serialize(keys)) .putHeaderParam(TRANSACTION_ID, params.getStreamTransactionId()); - if (params.getAllowDirtyRead() == Boolean.TRUE) { + if (Boolean.TRUE.equals(params.getAllowDirtyRead())) { RequestUtils.allowDirtyRead(request); } return request; diff --git a/src/main/java/com/arangodb/internal/InternalArangoDBBuilder.java b/src/main/java/com/arangodb/internal/InternalArangoDBBuilder.java index 9f8fae41a..2e9402386 100644 --- a/src/main/java/com/arangodb/internal/InternalArangoDBBuilder.java +++ b/src/main/java/com/arangodb/internal/InternalArangoDBBuilder.java @@ -90,7 +90,11 @@ public InternalArangoDBBuilder() { host = new HostDescription(ArangoDefaults.DEFAULT_HOST, ArangoDefaults.DEFAULT_PORT); hosts = new ArrayList<>(); user = ArangoDefaults.DEFAULT_USER; - loadProperties(ArangoDB.class.getResourceAsStream(DEFAULT_PROPERTY_FILE)); + try (InputStream is = ArangoDB.class.getResourceAsStream(DEFAULT_PROPERTY_FILE)) { + loadProperties(is); + } catch (IOException e) { + throw new ArangoDBException(e); + } } private static void loadHosts(final Properties properties, final Collection hosts) { diff --git a/src/main/java/com/arangodb/internal/InternalArangoDatabase.java b/src/main/java/com/arangodb/internal/InternalArangoDatabase.java index 0a86001d9..df2ddc951 100644 --- a/src/main/java/com/arangodb/internal/InternalArangoDatabase.java +++ b/src/main/java/com/arangodb/internal/InternalArangoDatabase.java @@ -147,7 +147,7 @@ protected Request queryRequest(final String query, final Map bin final AqlQueryOptions opt = options != null ? options : new AqlQueryOptions(); final Request request = request(dbName, RequestType.POST, PATH_API_CURSOR) .setBody(getSerde().serialize(OptionsBuilder.build(opt, query, bindVars))); - if (opt.getAllowDirtyRead() == Boolean.TRUE) { + if (Boolean.TRUE.equals(opt.getAllowDirtyRead())) { RequestUtils.allowDirtyRead(request); } request.putHeaderParam(TRANSACTION_ID, opt.getStreamTransactionId()); @@ -164,7 +164,7 @@ protected Request queryNextRequest(final String id, final AqlQueryOptions option final AqlQueryOptions opt = options != null ? options : new AqlQueryOptions(); - if (opt.getAllowDirtyRead() == Boolean.TRUE) { + if (Boolean.TRUE.equals(opt.getAllowDirtyRead())) { RequestUtils.allowDirtyRead(request); } request.putHeaderParam(TRANSACTION_ID, opt.getStreamTransactionId()); @@ -181,7 +181,7 @@ protected Request queryCloseRequest(final String id, final AqlQueryOptions optio final AqlQueryOptions opt = options != null ? options : new AqlQueryOptions(); - if (opt.getAllowDirtyRead() == Boolean.TRUE) { + if (Boolean.TRUE.equals(opt.getAllowDirtyRead())) { RequestUtils.allowDirtyRead(request); } request.putHeaderParam(TRANSACTION_ID, opt.getStreamTransactionId()); diff --git a/src/main/java/com/arangodb/internal/InternalArangoEdgeCollection.java b/src/main/java/com/arangodb/internal/InternalArangoEdgeCollection.java index 701ed3a74..2d1b60942 100644 --- a/src/main/java/com/arangodb/internal/InternalArangoEdgeCollection.java +++ b/src/main/java/com/arangodb/internal/InternalArangoEdgeCollection.java @@ -77,7 +77,7 @@ protected Request getEdgeRequest(final String key, final GraphDocumentReadOption request.putHeaderParam(TRANSACTION_ID, params.getStreamTransactionId()); request.putHeaderParam(ArangoRequestParam.IF_NONE_MATCH, params.getIfNoneMatch()); request.putHeaderParam(ArangoRequestParam.IF_MATCH, params.getIfMatch()); - if (params.getAllowDirtyRead() == Boolean.TRUE) { + if (Boolean.TRUE.equals(params.getAllowDirtyRead())) { RequestUtils.allowDirtyRead(request); } return request; diff --git a/src/main/java/com/arangodb/internal/InternalArangoVertexCollection.java b/src/main/java/com/arangodb/internal/InternalArangoVertexCollection.java index dd7f1140e..25c7b0f32 100644 --- a/src/main/java/com/arangodb/internal/InternalArangoVertexCollection.java +++ b/src/main/java/com/arangodb/internal/InternalArangoVertexCollection.java @@ -81,7 +81,7 @@ protected Request getVertexRequest(final String key, final GraphDocumentReadOpti request.putHeaderParam(TRANSACTION_ID, params.getStreamTransactionId()); request.putHeaderParam(ArangoRequestParam.IF_NONE_MATCH, params.getIfNoneMatch()); request.putHeaderParam(ArangoRequestParam.IF_MATCH, params.getIfMatch()); - if (params.getAllowDirtyRead() == Boolean.TRUE) { + if (Boolean.TRUE.equals(params.getAllowDirtyRead())) { RequestUtils.allowDirtyRead(request); } return request; diff --git a/src/main/java/com/arangodb/internal/cursor/ArangoCursorImpl.java b/src/main/java/com/arangodb/internal/cursor/ArangoCursorImpl.java index c99be12b0..dfbb635a1 100644 --- a/src/main/java/com/arangodb/internal/cursor/ArangoCursorImpl.java +++ b/src/main/java/com/arangodb/internal/cursor/ArangoCursorImpl.java @@ -90,7 +90,7 @@ public Collection getWarnings() { @Override public boolean isCached() { final Boolean cached = iterator.getResult().getCached(); - return Boolean.TRUE == cached; + return Boolean.TRUE.equals(cached); } @Override diff --git a/src/main/java/com/arangodb/internal/http/HttpConnection.java b/src/main/java/com/arangodb/internal/http/HttpConnection.java index c7e57bb2c..3a9ebbf18 100644 --- a/src/main/java/com/arangodb/internal/http/HttpConnection.java +++ b/src/main/java/com/arangodb/internal/http/HttpConnection.java @@ -98,7 +98,7 @@ private HttpConnection(final HostDescription host, final Integer timeout, final this.contentType = contentType; final RegistryBuilder registryBuilder = RegistryBuilder .create(); - if (Boolean.TRUE == useSsl) { + if (Boolean.TRUE.equals(useSsl)) { registryBuilder.register("https", new SSLConnectionSocketFactory( sslContext != null ? sslContext : SSLContexts.createSystemDefault(), hostnameVerifier != null ? hostnameVerifier : SSLConnectionSocketFactory.getDefaultHostnameVerifier() @@ -226,7 +226,7 @@ private HttpRequestBase requestWithBody(final HttpEntityEnclosingRequestBase htt } private String buildBaseUrl(final HostDescription host) { - return (Boolean.TRUE == useSsl ? "https://" : "http://") + host.getHost() + ":" + host.getPort(); + return (Boolean.TRUE.equals(useSsl) ? "https://" : "http://") + host.getHost() + ":" + host.getPort(); } public Response execute(final Request request) throws IOException { diff --git a/src/main/java/com/arangodb/internal/velocystream/internal/VstConnection.java b/src/main/java/com/arangodb/internal/velocystream/internal/VstConnection.java index f920d85fc..e9e52d694 100644 --- a/src/main/java/com/arangodb/internal/velocystream/internal/VstConnection.java +++ b/src/main/java/com/arangodb/internal/velocystream/internal/VstConnection.java @@ -149,7 +149,7 @@ public synchronized void open() throws IOException { if (LOGGER.isDebugEnabled()) { LOGGER.debug(String.format("[%s]: Open connection to %s", connectionName, host)); } - if (Boolean.TRUE == useSsl) { + if (Boolean.TRUE.equals(useSsl)) { if (sslContext != null) { socket = sslContext.getSocketFactory().createSocket(); } else { @@ -168,7 +168,7 @@ public synchronized void open() throws IOException { outputStream = new BufferedOutputStream(socket.getOutputStream()); inputStream = socket.getInputStream(); - if (Boolean.TRUE == useSsl) { + if (Boolean.TRUE.equals(useSsl)) { if (LOGGER.isDebugEnabled()) { LOGGER.debug(String.format("[%s]: Start Handshake on %s", connectionName, socket)); } From 831605fa9410e6bbb46fe260d5b69bb7c6e069d6 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Tue, 16 Aug 2022 13:04:34 +0200 Subject: [PATCH 094/254] codeql --- .github/workflows/codeql.yml | 75 ++++++++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) create mode 100644 .github/workflows/codeql.yml diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml new file mode 100644 index 000000000..0f6cdd774 --- /dev/null +++ b/.github/workflows/codeql.yml @@ -0,0 +1,75 @@ +# For most projects, this workflow file will not need changing; you simply need +# to commit it to your repository. +# +# You may wish to alter this file to override the set of languages analyzed, +# or to provide custom queries or build logic. +# +# ******** NOTE ******** +# We have attempted to detect the languages in your repository. Please check +# the `language` matrix defined below to confirm you have the correct set of +# supported CodeQL languages. +# +name: "CodeQL" + +on: + push: + branches: + - master + - v7 + pull_request: + types: [ opened, synchronize, reopened ] + branches: + - master + schedule: + - cron: '0 0 * * *' + +jobs: + analyze: + name: Analyze + runs-on: ubuntu-latest + permissions: + actions: read + contents: read + security-events: write + + strategy: + fail-fast: false + matrix: + language: [ 'java' ] + # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ] + # Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support + + steps: + - name: Checkout repository + uses: actions/checkout@v3 + + # Initializes the CodeQL tools for scanning. + - name: Initialize CodeQL + uses: github/codeql-action/init@v2 + with: + languages: ${{ matrix.language }} + # If you wish to specify custom queries, you can do so here or in a config file. + # By default, queries listed here will override any specified in a config file. + # Prefix the list here with "+" to use these queries and those in the config file. + + # Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs + # queries: security-extended,security-and-quality + + + # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). + # If this step fails, then you should remove it and run the build manually (see below) + - name: Autobuild + uses: github/codeql-action/autobuild@v2 + + # ℹ️ Command-line programs to run using the OS shell. + # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun + + # If the Autobuild fails above, remove it and uncomment the following three lines. + # modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance. + + # - run: | + # echo "Run, Build Application using script" + # ./location_of_script_within_repo/buildscript.sh + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v2 From 7ea91e033066185aaf239ce30e4e5545c6874c8b Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Tue, 16 Aug 2022 13:13:20 +0200 Subject: [PATCH 095/254] dev readme upd --- dev-README.md | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/dev-README.md b/dev-README.md index fb6f0c109..b8405a6a0 100644 --- a/dev-README.md +++ b/dev-README.md @@ -1,5 +1,25 @@ # dev-README +## GH Actions +Check results [here](https://github.com/arangodb/arangodb-java-driver/actions). + +## SonarCloud +Check results [here](https://sonarcloud.io/project/overview?id=arangodb_arangodb-java-driver). + +## check dependencies updates +```shell +mvn versions:display-dependency-updates +mvn versions:display-plugin-updates +``` + +## JaCoCo +```shell +mvn verify +``` +Report: +- [integration-tests](target/site/jacoco/index.html) + + ## native image reflection configuration To generate reflection configuration run `helper.NativeImageHelper` and copy the generated json to `src/main/resources/META-INF/native-image/com.arangodb/arangodb-java-driver/reflect-config.json`. From 7dcf791bec2dc5768781fac52ee8fa85d882843c Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Wed, 17 Aug 2022 08:44:10 +0200 Subject: [PATCH 096/254] [DE-330] added DocumentCreateOptions#keepNull --- .../internal/InternalArangoCollection.java | 4 ++- .../arangodb/model/DocumentCreateOptions.java | 26 ++++++++++++-- .../com/arangodb/ArangoCollectionTest.java | 36 +++++++++++++++++++ 3 files changed, 62 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/arangodb/internal/InternalArangoCollection.java b/src/main/java/com/arangodb/internal/InternalArangoCollection.java index 872e88db0..df71fc06c 100644 --- a/src/main/java/com/arangodb/internal/InternalArangoCollection.java +++ b/src/main/java/com/arangodb/internal/InternalArangoCollection.java @@ -52,8 +52,8 @@ public abstract class InternalArangoCollection, D private static final String PATH_API_INDEX = "/_api/index"; private static final String PATH_API_IMPORT = "/_api/import"; private static final String PATH_API_USER = "/_api/user"; - private static final String MERGE_OBJECTS = "mergeObjects"; + private static final String KEEP_NULL = "keepNull"; private static final String IGNORE_REVS = "ignoreRevs"; private static final String RETURN_NEW = "returnNew"; private static final String NEW = "new"; @@ -91,6 +91,7 @@ protected Request insertDocumentRequest(final T value, final DocumentCreateO request.putQueryParam(SILENT, params.getSilent()); request.putQueryParam(OVERWRITE_MODE, params.getOverwriteMode() != null ? params.getOverwriteMode().getValue() : null); request.putQueryParam(MERGE_OBJECTS, params.getMergeObjects()); + request.putQueryParam(KEEP_NULL, params.getKeepNull()); request.putHeaderParam(TRANSACTION_ID, params.getStreamTransactionId()); request.setBody(getSerde().serializeUserData(value)); return request; @@ -104,6 +105,7 @@ protected Request insertDocumentsRequest(final Collection values, final D request.putQueryParam(SILENT, params.getSilent()); request.putQueryParam(OVERWRITE_MODE, params.getOverwriteMode() != null ? params.getOverwriteMode().getValue() : null); request.putQueryParam(MERGE_OBJECTS, params.getMergeObjects()); + request.putQueryParam(KEEP_NULL, params.getKeepNull()); request.putHeaderParam(TRANSACTION_ID, params.getStreamTransactionId()); request.setBody(getSerde().serializeCollectionUserData(values)); return request; diff --git a/src/main/java/com/arangodb/model/DocumentCreateOptions.java b/src/main/java/com/arangodb/model/DocumentCreateOptions.java index b0722c541..a510ff32f 100644 --- a/src/main/java/com/arangodb/model/DocumentCreateOptions.java +++ b/src/main/java/com/arangodb/model/DocumentCreateOptions.java @@ -35,7 +35,7 @@ public final class DocumentCreateOptions { private Boolean silent; private String streamTransactionId; private Boolean mergeObjects; - + private Boolean keepNull; public DocumentCreateOptions() { super(); @@ -132,8 +132,10 @@ public Boolean getMergeObjects() { /** * Only considered if {@link this#overwriteMode} is set to {@link OverwriteMode#update} * - * @param mergeObjects Controls whether objects (not arrays) will be merged if present in both the existing and the patch - * document. If set to false, the value in the patch document will overwrite the existing document's + * @param mergeObjects Controls whether objects (not arrays) will be merged if present in both the existing and + * the patch + * document. If set to false, the value in the patch document will overwrite the existing + * document's * value. If set to true, objects will be merged. The default is true. * @return options * @since ArangoDB 3.7 @@ -143,4 +145,22 @@ public DocumentCreateOptions mergeObjects(Boolean mergeObjects) { return this; } + public Boolean getKeepNull() { + return keepNull; + } + + /** + * @param keepNull If the intention is to delete existing attributes with the update-insert command, the URL + * query parameter keepNull can be used with a value of false. This will modify the behavior of + * the patch command to remove any attributes from the existing document that are contained in + * the patch document with an attribute value of null. This option controls the update-insert + * behavior only. + * @return options + * @since ArangoDB 3.7 + */ + public DocumentCreateOptions keepNull(Boolean keepNull) { + this.keepNull = keepNull; + return this; + } + } diff --git a/src/test/java/com/arangodb/ArangoCollectionTest.java b/src/test/java/com/arangodb/ArangoCollectionTest.java index f0d603be0..ca0c813c3 100644 --- a/src/test/java/com/arangodb/ArangoCollectionTest.java +++ b/src/test/java/com/arangodb/ArangoCollectionTest.java @@ -343,6 +343,42 @@ void insertDocumentOverwriteModeUpdateMergeObjectsFalse(ArangoCollection collect assertThat(updated.getNew().getAttribute("foo")).isEqualTo(fieldB); } + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void insertDocumentOverwriteModeUpdateKeepNullTrue(ArangoCollection collection) { + assumeTrue(isAtLeastVersion(3, 7)); + + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); + doc.addAttribute("foo", "bar"); + collection.insertDocument(doc); + + doc.updateAttribute("foo", null); + final BaseDocument updated = collection.insertDocument(doc, new DocumentCreateOptions() + .overwriteMode(OverwriteMode.update) + .keepNull(true) + .returnNew(true)).getNew(); + + assertThat(updated.getProperties()).containsEntry("foo", null); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void insertDocumentOverwriteModeUpdateKeepNullFalse(ArangoCollection collection) { + assumeTrue(isAtLeastVersion(3, 7)); + + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); + doc.addAttribute("foo", "bar"); + collection.insertDocument(doc); + + doc.updateAttribute("foo", null); + final BaseDocument updated = collection.insertDocument(doc, new DocumentCreateOptions() + .overwriteMode(OverwriteMode.update) + .keepNull(false) + .returnNew(true)).getNew(); + + assertThat(updated.getProperties()).doesNotContainKey("foo"); + } + @ParameterizedTest(name = "{index}") @MethodSource("cols") void insertDocumentWaitForSync(ArangoCollection collection) { From faff9e3919a622a1de0426e925822d95fd68db82 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Wed, 17 Aug 2022 08:51:54 +0200 Subject: [PATCH 097/254] code cleanup --- .../java/com/arangodb/ArangoCollection.java | 130 ++++++++++++------ src/main/java/com/arangodb/ArangoDB.java | 21 ++- .../java/com/arangodb/ArangoDatabase.java | 82 +++++++---- .../com/arangodb/ArangoEdgeCollection.java | 24 ++-- src/main/java/com/arangodb/ArangoGraph.java | 6 +- src/main/java/com/arangodb/ArangoSearch.java | 3 +- .../com/arangodb/ArangoVertexCollection.java | 42 ++++-- src/main/java/com/arangodb/ArangoView.java | 9 +- .../arangodb/async/ArangoCollectionAsync.java | 124 +++++++++++------ .../com/arangodb/async/ArangoDBAsync.java | 9 +- .../arangodb/async/ArangoDatabaseAsync.java | 79 +++++++---- .../async/ArangoEdgeCollectionAsync.java | 12 +- .../com/arangodb/async/ArangoGraphAsync.java | 12 +- .../com/arangodb/async/ArangoSearchAsync.java | 3 +- .../async/ArangoVertexCollectionAsync.java | 30 ++-- .../com/arangodb/async/ArangoViewAsync.java | 9 +- .../internal/ArangoCollectionAsyncImpl.java | 22 ++- .../internal/ArangoDatabaseAsyncImpl.java | 15 +- .../ArangoEdgeCollectionAsyncImpl.java | 6 +- .../async/internal/ArangoGraphAsyncImpl.java | 3 +- .../ArangoVertexCollectionAsyncImpl.java | 3 +- .../utils/CompletableFutureUtils.java | 3 +- .../velocystream/VstCommunicationAsync.java | 9 +- .../velocystream/VstConnectionAsync.java | 3 +- .../VstConnectionFactoryAsync.java | 3 +- .../com/arangodb/entity/ArangoDBEngine.java | 3 +- .../com/arangodb/entity/LogEntriesEntity.java | 3 +- .../com/arangodb/entity/LogLevelEntity.java | 1 + .../entity/QueryCachePropertiesEntity.java | 1 + .../entity/QueryTrackingPropertiesEntity.java | 24 ++-- .../arangodb/entity/TransactionEntity.java | 3 +- .../entity/arangosearch/AnalyzerFeature.java | 6 +- .../entity/arangosearch/CollectionLink.java | 9 +- .../arangosearch/ConsolidationPolicy.java | 3 +- .../entity/arangosearch/FieldLink.java | 9 +- .../entity/arangosearch/StoredValue.java | 3 +- .../analyzer/AQLAnalyzerProperties.java | 7 +- .../analyzer/CollationAnalyzerProperties.java | 3 +- .../analyzer/DelimiterAnalyzer.java | 3 +- .../analyzer/NormAnalyzerProperties.java | 3 +- .../analyzer/PipelineAnalyzer.java | 3 +- .../analyzer/StemAnalyzerProperties.java | 3 +- .../analyzer/TextAnalyzerProperties.java | 9 +- .../internal/ArangoCollectionImpl.java | 20 ++- .../com/arangodb/internal/ArangoDBImpl.java | 3 +- .../arangodb/internal/ArangoDatabaseImpl.java | 3 +- .../com/arangodb/internal/ArangoDefaults.java | 1 + .../internal/ArangoEdgeCollectionImpl.java | 3 +- .../com/arangodb/internal/ArangoErrors.java | 1 + .../com/arangodb/internal/ArangoExecutor.java | 1 + .../arangodb/internal/ArangoRequestParam.java | 1 + .../internal/ArangoResponseField.java | 1 + .../com/arangodb/internal/DocumentFields.java | 1 + .../internal/InternalArangoCollection.java | 21 ++- .../arangodb/internal/InternalArangoDB.java | 9 +- .../internal/InternalArangoDBBuilder.java | 9 +- .../internal/InternalArangoDatabase.java | 36 +++-- .../InternalArangoEdgeCollection.java | 3 +- .../internal/InternalArangoGraph.java | 3 +- .../internal/InternalArangoRoute.java | 3 +- .../internal/InternalArangoSearch.java | 3 +- .../InternalArangoVertexCollection.java | 6 +- .../arangodb/internal/InternalArangoView.java | 3 +- .../internal/http/HttpConnection.java | 16 ++- .../internal/net/ExtendedHostResolver.java | 3 +- .../internal/serde/InternalSerializers.java | 6 +- .../velocystream/VstCommunicationSync.java | 3 +- .../VstConnectionFactorySync.java | 3 +- .../velocystream/internal/VstConnection.java | 12 +- .../internal/VstConnectionSync.java | 3 +- .../model/AqlFunctionCreateOptions.java | 6 +- .../model/AqlQueryExplainOptions.java | 6 +- .../com/arangodb/model/AqlQueryOptions.java | 105 +++++++++----- .../model/CollectionCreateOptions.java | 66 ++++++--- .../model/CollectionPropertiesOptions.java | 6 +- .../com/arangodb/model/CollectionSchema.java | 3 +- .../arangodb/model/DocumentDeleteOptions.java | 3 +- .../arangodb/model/DocumentExistsOptions.java | 3 +- .../arangodb/model/DocumentImportOptions.java | 28 ++-- .../model/DocumentReplaceOptions.java | 9 +- .../arangodb/model/DocumentUpdateOptions.java | 15 +- .../arangodb/model/FulltextIndexOptions.java | 3 +- .../com/arangodb/model/GeoIndexOptions.java | 3 +- .../arangodb/model/GraphCreateOptions.java | 24 ++-- .../com/arangodb/model/HashIndexOptions.java | 3 +- .../java/com/arangodb/model/LogOptions.java | 7 +- .../com/arangodb/model/OptionsBuilder.java | 3 +- .../model/PersistentIndexOptions.java | 3 +- .../arangodb/model/SkiplistIndexOptions.java | 3 +- .../model/StreamTransactionOptions.java | 6 +- .../arangodb/model/TransactionOptions.java | 18 ++- .../com/arangodb/model/TtlIndexOptions.java | 3 +- .../ArangoSearchCreateOptions.java | 57 +++++--- .../ArangoSearchPropertiesOptions.java | 27 ++-- .../java/com/arangodb/serde/ArangoSerde.java | 3 +- 95 files changed, 908 insertions(+), 440 deletions(-) diff --git a/src/main/java/com/arangodb/ArangoCollection.java b/src/main/java/com/arangodb/ArangoCollection.java index 77497971c..d0c7d31f5 100644 --- a/src/main/java/com/arangodb/ArangoCollection.java +++ b/src/main/java/com/arangodb/ArangoCollection.java @@ -54,7 +54,8 @@ public interface ArangoCollection extends ArangoSerdeAccessor { * Creates a new document from the given document, unless there is already a document with the _key given. If no * _key is given, a new unique _key is generated automatically. * - * @param value A representation of a single document (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) + * @param value A representation of a single document (POJO, {@link com.arangodb.util.RawJson} or + * {@link com.arangodb.util.RawBytes}) * @return information about the document * @see API * Documentation @@ -65,7 +66,8 @@ public interface ArangoCollection extends ArangoSerdeAccessor { * Creates a new document from the given document, unless there is already a document with the _key given. If no * _key is given, a new unique _key is generated automatically. * - * @param value A representation of a single document (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) + * @param value A representation of a single document (POJO, {@link com.arangodb.util.RawJson} or + * {@link com.arangodb.util.RawBytes}) * @param options Additional options * @return information about the document * @see API @@ -77,7 +79,8 @@ public interface ArangoCollection extends ArangoSerdeAccessor { * Creates a new document from the given document, unless there is already a document with the _key given. If no * _key is given, a new unique _key is generated automatically. * - * @param value A representation of a single document (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) + * @param value A representation of a single document (POJO, {@link com.arangodb.util.RawJson} or + * {@link com.arangodb.util.RawBytes}) * @param options Additional options * @param type Deserialization target type for the returned documents. * @return information about the document @@ -101,7 +104,8 @@ public interface ArangoCollection extends ArangoSerdeAccessor { * Creates new documents from the given documents, unless there is already a document with the _key given. If no * _key is given, a new unique _key is generated automatically. * - * @param values A List of documents (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) + * @param values A List of documents (POJO, {@link com.arangodb.util.RawJson} or + * {@link com.arangodb.util.RawBytes}) * @param options Additional options * @return information about the documents * @see API @@ -114,7 +118,8 @@ MultiDocumentEntity> insertDocuments( * Creates new documents from the given documents, unless there is already a document with the _key given. If no * _key is given, a new unique _key is generated automatically. * - * @param values A List of documents (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) + * @param values A List of documents (POJO, {@link com.arangodb.util.RawJson} or + * {@link com.arangodb.util.RawBytes}) * @param options Additional options * @param type Deserialization target type for the returned documents. * @return information about the documents @@ -162,7 +167,8 @@ MultiDocumentEntity> insertDocuments( * Retrieves the document with the given {@code key} from the collection. * * @param key The key of the document - * @param type The type of the document (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) + * @param type The type of the document (POJO, {@link com.arangodb.util.RawJson} or + * {@link com.arangodb.util.RawBytes}) * @return the document identified by the key * @see API * Documentation @@ -173,7 +179,8 @@ MultiDocumentEntity> insertDocuments( * Retrieves the document with the given {@code key} from the collection. * * @param key The key of the document - * @param type The type of the document (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) + * @param type The type of the document (POJO, {@link com.arangodb.util.RawJson} or + * {@link com.arangodb.util.RawBytes}) * @param options Additional options, can be null * @return the document identified by the key * @see API @@ -185,7 +192,8 @@ MultiDocumentEntity> insertDocuments( * Retrieves multiple documents with the given {@code _key} from the collection. * * @param keys The keys of the documents - * @param type The type of the documents (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) + * @param type The type of the documents (POJO, {@link com.arangodb.util.RawJson} or + * {@link com.arangodb.util.RawBytes}) * @return the documents and possible errors */ MultiDocumentEntity getDocuments(Collection keys, Class type); @@ -194,19 +202,23 @@ MultiDocumentEntity> insertDocuments( * Retrieves multiple documents with the given {@code _key} from the collection. * * @param keys The keys of the documents - * @param type The type of the documents (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) + * @param type The type of the documents (POJO, {@link com.arangodb.util.RawJson} or + * {@link com.arangodb.util.RawBytes}) * @param options Additional options, can be null * @return the documents and possible errors */ MultiDocumentEntity getDocuments(Collection keys, Class type, DocumentReadOptions options); + /** * Replaces the document with {@code key} with the one in the body, provided there is such a document and no * precondition is violated * * @param key The key of the document - * @param value A representation of a single document (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) + * @param value A representation of a single document (POJO, {@link com.arangodb.util.RawJson} or + * {@link com.arangodb.util.RawBytes}) * @return information about the document - * @see API + * @see + * API * Documentation */ DocumentUpdateEntity replaceDocument(String key, Object value); @@ -216,33 +228,40 @@ MultiDocumentEntity> insertDocuments( * precondition is violated * * @param key The key of the document - * @param value A representation of a single document (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) + * @param value A representation of a single document (POJO, {@link com.arangodb.util.RawJson} or + * {@link com.arangodb.util.RawBytes}) * @param options Additional options * @return information about the document - * @see API + * @see + * API * Documentation */ DocumentUpdateEntity replaceDocument(String key, T value, DocumentReplaceOptions options); + /** * Replaces the document with {@code key} with the one in the body, provided there is such a document and no * precondition is violated * * @param key The key of the document - * @param value A representation of a single document (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) + * @param value A representation of a single document (POJO, {@link com.arangodb.util.RawJson} or + * {@link com.arangodb.util.RawBytes}) * @param options Additional options * @param type Deserialization target type for the returned documents. * @return information about the document - * @see API + * @see + * API * Documentation */ DocumentUpdateEntity replaceDocument(String key, T value, DocumentReplaceOptions options, Class type); + /** * Replaces multiple documents in the specified collection with the ones in the values, the replaced documents are * specified by the _key attributes in the documents in values. * * @param values A List of documents (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) * @return information about the documents - * @see API + * @see + * API * Documentation */ MultiDocumentEntity> replaceDocuments(Collection values); @@ -251,10 +270,12 @@ MultiDocumentEntity> insertDocuments( * Replaces multiple documents in the specified collection with the ones in the values, the replaced documents are * specified by the _key attributes in the documents in values. * - * @param values A List of documents (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) + * @param values A List of documents (POJO, {@link com.arangodb.util.RawJson} or + * {@link com.arangodb.util.RawBytes}) * @param options Additional options * @return information about the documents - * @see API + * @see + * API * Documentation */ MultiDocumentEntity> replaceDocuments( @@ -264,11 +285,13 @@ MultiDocumentEntity> replaceDocuments( * Replaces multiple documents in the specified collection with the ones in the values, the replaced documents are * specified by the _key attributes in the documents in values. * - * @param values A List of documents (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) + * @param values A List of documents (POJO, {@link com.arangodb.util.RawJson} or + * {@link com.arangodb.util.RawBytes}) * @param options Additional options * @param type Deserialization target type for the returned documents. * @return information about the documents - * @see API + * @see + * API * Documentation */ MultiDocumentEntity> replaceDocuments( @@ -280,7 +303,8 @@ MultiDocumentEntity> replaceDocuments( * they do not yet exist, and overwritten in the existing document if they do exist there. * * @param key The key of the document - * @param value A representation of a single document (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) + * @param value A representation of a single document (POJO, {@link com.arangodb.util.RawJson} or + * {@link com.arangodb.util.RawBytes}) * @return information about the document * @see API * Documentation @@ -293,27 +317,32 @@ MultiDocumentEntity> replaceDocuments( * they do not yet exist, and overwritten in the existing document if they do exist there. * * @param key The key of the document - * @param value A representation of a single document (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) + * @param value A representation of a single document (POJO, {@link com.arangodb.util.RawJson} or + * {@link com.arangodb.util.RawBytes}) * @param options Additional options * @return information about the document * @see API * Documentation */ DocumentUpdateEntity updateDocument(String key, T value, DocumentUpdateOptions options); + /** * Partially updates the document identified by document-key. The value must contain a document with the attributes * to patch (the patch document). All attributes from the patch document will be added to the existing document if * they do not yet exist, and overwritten in the existing document if they do exist there. * * @param key The key of the document - * @param value A representation of a single document (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) + * @param value A representation of a single document (POJO, {@link com.arangodb.util.RawJson} or + * {@link com.arangodb.util.RawBytes}) * @param options Additional options * @param returnType Type of the returned newDocument and/or oldDocument * @return information about the document * @see API * Documentation */ - DocumentUpdateEntity updateDocument(String key, Object value, DocumentUpdateOptions options, Class returnType); + DocumentUpdateEntity updateDocument(String key, Object value, DocumentUpdateOptions options, + Class returnType); + /** * Partially updates documents, the documents to update are specified by the _key attributes in the objects on * values. Vales must contain a list of document updates with the attributes to patch (the patch documents). All @@ -322,7 +351,8 @@ MultiDocumentEntity> replaceDocuments( * * @param values A list of documents (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) * @return information about the documents - * @see API + * @see + * API * Documentation */ MultiDocumentEntity> updateDocuments(Collection values); @@ -333,10 +363,12 @@ MultiDocumentEntity> replaceDocuments( * attributes from the patch documents will be added to the existing documents if they do not yet exist, and * overwritten in the existing documents if they do exist there. * - * @param values A list of documents (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) + * @param values A list of documents (POJO, {@link com.arangodb.util.RawJson} or + * {@link com.arangodb.util.RawBytes}) * @param options Additional options * @return information about the documents - * @see API + * @see + * API * Documentation */ MultiDocumentEntity> updateDocuments( @@ -348,11 +380,13 @@ MultiDocumentEntity> updateDocuments( * attributes from the patch documents will be added to the existing documents if they do not yet exist, and * overwritten in the existing documents if they do exist there. * - * @param values A list of documents (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) + * @param values A list of documents (POJO, {@link com.arangodb.util.RawJson} or + * {@link com.arangodb.util.RawBytes}) * @param options Additional options * @param returnType Type of the returned newDocument and/or oldDocument * @return information about the documents - * @see API + * @see + * API * Documentation */ MultiDocumentEntity> updateDocuments( @@ -363,7 +397,8 @@ MultiDocumentEntity> updateDocuments( * * @param key The key of the document * @return information about the document - * @see API + * @see + * API * Documentation */ DocumentDeleteEntity deleteDocument(String key); @@ -374,10 +409,12 @@ MultiDocumentEntity> updateDocuments( * @param key The key of the document * @param options Additional options * @return information about the document - * @see API + * @see + * API * Documentation */ DocumentDeleteEntity deleteDocument(String key, DocumentDeleteOptions options); + /** * Deletes the document with the given {@code key} from the collection. * @@ -385,10 +422,12 @@ MultiDocumentEntity> updateDocuments( * @param type Deserialization target type for the returned documents. * @param options Additional options * @return information about the document - * @see API + * @see + * API * Documentation */ DocumentDeleteEntity deleteDocument(String key, DocumentDeleteOptions options, Class type); + /** * Deletes multiple documents from the collection. * @@ -455,7 +494,8 @@ MultiDocumentEntity> deleteDocuments( * * @param id The index-handle * @return information about the index - * @see API Documentation + * @see + * API Documentation */ IndexEntity getIndex(String id); @@ -464,7 +504,8 @@ MultiDocumentEntity> deleteDocuments( * * @param id The index-handle * @return the id of the index - * @see API Documentation + * @see + * API Documentation */ String deleteIndex(String id); @@ -474,7 +515,8 @@ MultiDocumentEntity> deleteDocuments( * @param fields A list of attribute paths * @param options Additional options, can be null * @return information about the index - * @see API Documentation + * @see + * API Documentation * @deprecated use {@link #ensurePersistentIndex(Iterable, PersistentIndexOptions)} instead. Since ArangoDB 3.7 a * hash index is an alias for a persistent index. */ @@ -593,7 +635,8 @@ MultiDocumentEntity> deleteDocuments( * * @return information about the collection, including the number of documents * @see API + * "https://www.arangodb.com/docs/stable/http/collection-getting + * .html#return-number-of-documents-in-a-collection">API * Documentation */ CollectionPropertiesEntity count(); @@ -604,7 +647,8 @@ MultiDocumentEntity> deleteDocuments( * @param options * @return information about the collection, including the number of documents * @see API + * "https://www.arangodb.com/docs/stable/http/collection-getting + * .html#return-number-of-documents-in-a-collection">API * Documentation * @since ArangoDB 3.5.0 */ @@ -641,7 +685,8 @@ MultiDocumentEntity> deleteDocuments( /** * Deletes the collection from the database. * - * @param isSystem Whether or not the collection to drop is a system collection. This parameter must be set to true in + * @param isSystem Whether or not the collection to drop is a system collection. This parameter must be set to + * true in * order to drop a system collection. * @see API * Documentation @@ -697,7 +742,8 @@ MultiDocumentEntity> deleteDocuments( * @param value A projection of the document containing at least the shard key (_key or a custom attribute) for * which the responsible shard should be determined * @return information about the responsible shard - * @see + * @see + * * API Documentation * @since ArangoDB 3.5.0 */ @@ -707,7 +753,8 @@ MultiDocumentEntity> deleteDocuments( * Retrieve the collections revision * * @return information about the collection, including the collections revision - * @see API + * @see + * API * Documentation */ CollectionRevisionEntity getRevision(); @@ -751,7 +798,8 @@ MultiDocumentEntity> deleteDocuments( * * @param user The name of the user * @return permissions of the user - * @see + * @see + * * API Documentation * @since ArangoDB 3.2.0 */ diff --git a/src/main/java/com/arangodb/ArangoDB.java b/src/main/java/com/arangodb/ArangoDB.java index aa6204efa..45413cb42 100644 --- a/src/main/java/com/arangodb/ArangoDB.java +++ b/src/main/java/com/arangodb/ArangoDB.java @@ -166,7 +166,8 @@ public interface ArangoDB extends ArangoSerdeAccessor { * Returns the server storage engine. * * @return the storage engine name - * @see API + * @see + * API * Documentation */ ArangoDBEngine getEngine(); @@ -182,7 +183,8 @@ public interface ArangoDB extends ArangoSerdeAccessor { * Returns the id of a server in a cluster. * * @return the server id - * @see API + * @see + * API * Documentation */ String getServerId(); @@ -302,7 +304,8 @@ public interface ArangoDB extends ArangoSerdeAccessor { * * @param options Additional options, can be null * @return the log messages - * @see API + * @see + * API * Documentation * @since ArangoDB 3.8 */ @@ -350,7 +353,8 @@ public Builder() { private static Protocol loadProtocol(final Properties properties, final Protocol currentValue) { return Protocol.valueOf( - getProperty(properties, PROPERTY_KEY_PROTOCOL, currentValue, ArangoDefaults.DEFAULT_NETWORK_PROTOCOL) + getProperty(properties, PROPERTY_KEY_PROTOCOL, currentValue, + ArangoDefaults.DEFAULT_NETWORK_PROTOCOL) .toUpperCase(Locale.ENGLISH)); } @@ -521,7 +525,8 @@ public Builder connectionTtl(final Long connectionTtl) { } /** - * Set the keep-alive interval for VST connections. If set, every VST connection will perform a no-op request every + * Set the keep-alive interval for VST connections. If set, every VST connection will perform a no-op request + * every * {@code keepAliveInterval} seconds, to avoid to be closed due to inactivity by the server (or by the external * environment, eg. firewall, intermediate routers, operating system). * @@ -566,7 +571,8 @@ public Builder acquireHostListInterval(final Integer acquireHostListInterval) { * In case of Active-Failover deployment set to {@link LoadBalancingStrategy#NONE} or not set at all, since that * would be the default. * - * @param loadBalancingStrategy the load balancing strategy to be used (default: {@link LoadBalancingStrategy#NONE} + * @param loadBalancingStrategy the load balancing strategy to be used (default: + * {@link LoadBalancingStrategy#NONE} * @return {@link ArangoDB.Builder} */ public Builder loadBalancingStrategy(final LoadBalancingStrategy loadBalancingStrategy) { @@ -608,7 +614,8 @@ public ArangoDB build() { if (hosts.isEmpty()) { hosts.add(host); } - final ArangoSerde userSerde = customSerializer != null ? customSerializer : JacksonSerde.of(DataType.of(protocol)); + final ArangoSerde userSerde = customSerializer != null ? customSerializer : + JacksonSerde.of(DataType.of(protocol)); final InternalSerde serde = InternalSerde.of(DataType.of(protocol), userSerde); int protocolMaxConnections = protocol == Protocol.VST ? diff --git a/src/main/java/com/arangodb/ArangoDatabase.java b/src/main/java/com/arangodb/ArangoDatabase.java index 8d3805585..af8b02808 100644 --- a/src/main/java/com/arangodb/ArangoDatabase.java +++ b/src/main/java/com/arangodb/ArangoDatabase.java @@ -66,7 +66,8 @@ public interface ArangoDatabase extends ArangoSerdeAccessor { * Returns the name of the used storage engine. * * @return the storage engine name - * @see API + * @see + * API * Documentation */ ArangoDBEngine getEngine(); @@ -142,7 +143,8 @@ public interface ArangoDatabase extends ArangoSerdeAccessor { * * @param id The index-handle * @return information about the index - * @see API Documentation + * @see + * API Documentation */ IndexEntity getIndex(String id); @@ -151,7 +153,8 @@ public interface ArangoDatabase extends ArangoSerdeAccessor { * * @param id The index-handle * @return the id of the index - * @see API Documentation + * @see + * API Documentation */ String deleteIndex(String id); @@ -242,21 +245,26 @@ public interface ArangoDatabase extends ArangoSerdeAccessor { * @param query An AQL query string * @param bindVars key/value pairs defining the variables to bind the query to * @param options Additional options that will be passed to the query API, can be null - * @param type The type of the result (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) + * @param type The type of the result (POJO, {@link com.arangodb.util.RawJson} or + * {@link com.arangodb.util.RawBytes}) * @return cursor of the results - * @see API + * @see + * API * Documentation */ ArangoCursor query(String query, Map bindVars, AqlQueryOptions options, Class type); + /** * Performs a database query using the given {@code query}, then returns a new {@code ArangoCursor} instance for the * result list. * * @param query An AQL query string * @param options Additional options that will be passed to the query API, can be null - * @param type The type of the result (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) + * @param type The type of the result (POJO, {@link com.arangodb.util.RawJson} or + * {@link com.arangodb.util.RawBytes}) * @return cursor of the results - * @see API + * @see + * API * Documentation */ ArangoCursor query(String query, AqlQueryOptions options, Class type); @@ -267,9 +275,11 @@ public interface ArangoDatabase extends ArangoSerdeAccessor { * * @param query An AQL query string * @param bindVars key/value pairs defining the variables to bind the query to - * @param type The type of the result (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) + * @param type The type of the result (POJO, {@link com.arangodb.util.RawJson} or + * {@link com.arangodb.util.RawBytes}) * @return cursor of the results - * @see API + * @see + * API * Documentation */ ArangoCursor query(String query, Map bindVars, Class type); @@ -279,9 +289,11 @@ public interface ArangoDatabase extends ArangoSerdeAccessor { * result list. * * @param query An AQL query string - * @param type The type of the result (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) + * @param type The type of the result (POJO, {@link com.arangodb.util.RawJson} or + * {@link com.arangodb.util.RawBytes}) * @return cursor of the results - * @see API + * @see + * API * Documentation */ ArangoCursor query(String query, Class type); @@ -290,10 +302,12 @@ public interface ArangoDatabase extends ArangoSerdeAccessor { * Return an cursor from the given cursor-ID if still existing * * @param cursorId The ID of the cursor - * @param type The type of the result (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) + * @param type The type of the result (POJO, {@link com.arangodb.util.RawJson} or + * {@link com.arangodb.util.RawBytes}) * @return cursor of the results * @see API + * "https://www.arangodb.com/docs/stable/http/aql-query-cursor-accessing-cursors + * .html#read-next-batch-from-cursor">API * Documentation */ ArangoCursor cursor(String cursorId, Class type); @@ -309,6 +323,7 @@ public interface ArangoDatabase extends ArangoSerdeAccessor { * Documentation */ AqlExecutionExplainEntity explainQuery(String query, Map bindVars, AqlQueryExplainOptions options); + /** * Parse an AQL query and return information about it This method is for query validation only. To actually query * the database, see {@link ArangoDatabase#query(String, Map, AqlQueryOptions, Class)} @@ -324,7 +339,8 @@ public interface ArangoDatabase extends ArangoSerdeAccessor { * Clears the AQL query cache * * @see API + * "https://www.arangodb.com/docs/stable/http/aql-query-cache + * .html#clears-any-results-in-the-aql-query-results-cache">API * Documentation */ void clearQueryCache(); @@ -334,7 +350,8 @@ public interface ArangoDatabase extends ArangoSerdeAccessor { * * @return configuration for the AQL query cache * @see API + * "https://www.arangodb.com/docs/stable/http/aql-query-cache + * .html#returns-the-global-properties-for-the-aql-query-results-cache">API * Documentation */ QueryCachePropertiesEntity getQueryCacheProperties(); @@ -346,7 +363,8 @@ public interface ArangoDatabase extends ArangoSerdeAccessor { * @param properties properties to be set * @return current set of properties * @see API + * "https://www.arangodb.com/docs/stable/http/aql-query-cache + * .html#globally-adjusts-the-aql-query-results-cache-properties">API * Documentation */ QueryCachePropertiesEntity setQueryCacheProperties(QueryCachePropertiesEntity properties); @@ -371,6 +389,7 @@ public interface ArangoDatabase extends ArangoSerdeAccessor { * Documentation */ QueryTrackingPropertiesEntity setQueryTrackingProperties(QueryTrackingPropertiesEntity properties); + /** * Returns a list of currently running AQL queries * @@ -475,6 +494,7 @@ public interface ArangoDatabase extends ArangoSerdeAccessor { * Documentation */ GraphEntity createGraph(String name, Collection edgeDefinitions, GraphCreateOptions options); + /** * Lists all graphs known to the graph module * @@ -488,7 +508,8 @@ public interface ArangoDatabase extends ArangoSerdeAccessor { * Performs a server-side transaction and returns its return value. * * @param action A String evaluating to a JavaScript function to be executed on the server. - * @param type The type of the result (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) + * @param type The type of the result (POJO, {@link com.arangodb.util.RawJson} or + * {@link com.arangodb.util.RawBytes}) * @param options Additional options, can be null * @return the result of the transaction if it succeeded * @see API @@ -501,7 +522,8 @@ public interface ArangoDatabase extends ArangoSerdeAccessor { * * @param options Additional options, can be null * @return information about the transaction - * @see API + * @see + * API * Documentation * @since ArangoDB 3.5.0 */ @@ -511,7 +533,8 @@ public interface ArangoDatabase extends ArangoSerdeAccessor { * Aborts a Stream Transaction. * * @return information about the transaction - * @see API + * @see + * API * Documentation */ StreamTransactionEntity abortStreamTransaction(String id); @@ -520,7 +543,8 @@ public interface ArangoDatabase extends ArangoSerdeAccessor { * Gets information about a Stream Transaction. * * @return information about the transaction - * @see + * @see + * * API Documentation * @since ArangoDB 3.5.0 */ @@ -530,7 +554,8 @@ public interface ArangoDatabase extends ArangoSerdeAccessor { * Gets all the currently running Stream Transactions. * * @return all the currently running Stream Transactions - * @see + * @see + * * API Documentation * @since ArangoDB 3.5.0 */ @@ -540,7 +565,8 @@ public interface ArangoDatabase extends ArangoSerdeAccessor { * Commits a Stream Transaction. * * @return information about the transaction - * @see + * @see + * * API Documentation * @since ArangoDB 3.5.0 */ @@ -560,7 +586,8 @@ public interface ArangoDatabase extends ArangoSerdeAccessor { * Reads a single document * * @param id The id of the document - * @param type The type of the document (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) + * @param type The type of the document (POJO, {@link com.arangodb.util.RawJson} or + * {@link com.arangodb.util.RawBytes}) * @return the document identified by the id * @see API * Documentation @@ -571,7 +598,8 @@ public interface ArangoDatabase extends ArangoSerdeAccessor { * Reads a single document * * @param id The id of the document - * @param type The type of the document (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) + * @param type The type of the document (POJO, {@link com.arangodb.util.RawJson} or + * {@link com.arangodb.util.RawBytes}) * @param options Additional options, can be null * @return the document identified by the id * @see API @@ -583,7 +611,8 @@ public interface ArangoDatabase extends ArangoSerdeAccessor { * Reload the routing table. * * @see API + * "https://www.arangodb.com/docs/stable/http/administration-and-monitoring + * .html#reloads-the-routing-information">API * Documentation */ void reloadRouting(); @@ -601,7 +630,8 @@ public interface ArangoDatabase extends ArangoSerdeAccessor { * Fetches all views from the database and returns an list of view descriptions. * * @return list of information about all views - * @see API Documentation + * @see + * API Documentation * @since ArangoDB 3.4.0 */ Collection getViews(); diff --git a/src/main/java/com/arangodb/ArangoEdgeCollection.java b/src/main/java/com/arangodb/ArangoEdgeCollection.java index a4930dfce..333cdeb34 100644 --- a/src/main/java/com/arangodb/ArangoEdgeCollection.java +++ b/src/main/java/com/arangodb/ArangoEdgeCollection.java @@ -49,7 +49,8 @@ public interface ArangoEdgeCollection extends ArangoSerdeAccessor { /** * Creates a new edge in the collection * - * @param value A representation of a single edge (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) + * @param value A representation of a single edge (POJO, {@link com.arangodb.util.RawJson} or + * {@link com.arangodb.util.RawBytes}) * @return information about the edge * @see API Documentation */ @@ -58,7 +59,8 @@ public interface ArangoEdgeCollection extends ArangoSerdeAccessor { /** * Creates a new edge in the collection * - * @param value A representation of a single edge (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) + * @param value A representation of a single edge (POJO, {@link com.arangodb.util.RawJson} or + * {@link com.arangodb.util.RawBytes}) * @param options Additional options, can be null * @return information about the edge * @see API Documentation @@ -69,7 +71,8 @@ public interface ArangoEdgeCollection extends ArangoSerdeAccessor { * Fetches an existing edge * * @param key The key of the edge - * @param type The type of the edge-document (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) + * @param type The type of the edge-document (POJO, {@link com.arangodb.util.RawJson} or + * {@link com.arangodb.util.RawBytes}) * @return the edge identified by the key * @see API Documentation */ @@ -79,7 +82,8 @@ public interface ArangoEdgeCollection extends ArangoSerdeAccessor { * Fetches an existing edge * * @param key The key of the edge - * @param type The type of the edge-document (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) + * @param type The type of the edge-document (POJO, {@link com.arangodb.util.RawJson} or + * {@link com.arangodb.util.RawBytes}) * @param options Additional options, can be null * @return the edge identified by the key * @see API Documentation @@ -91,7 +95,8 @@ public interface ArangoEdgeCollection extends ArangoSerdeAccessor { * violated * * @param key The key of the edge - * @param value A representation of a single edge (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) + * @param value A representation of a single edge (POJO, {@link com.arangodb.util.RawJson} or + * {@link com.arangodb.util.RawBytes}) * @return information about the edge * @see API Documentation */ @@ -102,7 +107,8 @@ public interface ArangoEdgeCollection extends ArangoSerdeAccessor { * violated * * @param key The key of the edge - * @param value A representation of a single edge (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) + * @param value A representation of a single edge (POJO, {@link com.arangodb.util.RawJson} or + * {@link com.arangodb.util.RawBytes}) * @param options Additional options, can be null * @return information about the edge * @see API Documentation @@ -115,7 +121,8 @@ public interface ArangoEdgeCollection extends ArangoSerdeAccessor { * do not yet exist, and overwritten in the existing document if they do exist there. * * @param key The key of the edge - * @param value A representation of a single edge (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) + * @param value A representation of a single edge (POJO, {@link com.arangodb.util.RawJson} or + * {@link com.arangodb.util.RawBytes}) * @return information about the edge * @see API Documentation */ @@ -127,7 +134,8 @@ public interface ArangoEdgeCollection extends ArangoSerdeAccessor { * do not yet exist, and overwritten in the existing document if they do exist there. * * @param key The key of the edge - * @param value A representation of a single edge (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) + * @param value A representation of a single edge (POJO, {@link com.arangodb.util.RawJson} or + * {@link com.arangodb.util.RawBytes}) * @param options Additional options, can be null * @return information about the edge * @see API Documentation diff --git a/src/main/java/com/arangodb/ArangoGraph.java b/src/main/java/com/arangodb/ArangoGraph.java index 445e38eb4..b37d0aded 100644 --- a/src/main/java/com/arangodb/ArangoGraph.java +++ b/src/main/java/com/arangodb/ArangoGraph.java @@ -82,7 +82,8 @@ public interface ArangoGraph extends ArangoSerdeAccessor { /** * Deletes the graph from the database. * - * @see API Documentation + * @see + * API Documentation */ void drop(); @@ -101,7 +102,8 @@ public interface ArangoGraph extends ArangoSerdeAccessor { * Retrieves general information about the graph. * * @return the definition content of this graph - * @see API Documentation + * @see + * API Documentation */ GraphEntity getInfo(); diff --git a/src/main/java/com/arangodb/ArangoSearch.java b/src/main/java/com/arangodb/ArangoSearch.java index e6c59b2bd..3ccb89e60 100644 --- a/src/main/java/com/arangodb/ArangoSearch.java +++ b/src/main/java/com/arangodb/ArangoSearch.java @@ -68,7 +68,8 @@ public interface ArangoSearch extends ArangoView { * @param options properties to change * @return properties of the view * @see API + * "https://www.arangodb.com/docs/stable/http/views-arangosearch + * .html#partially-changes-properties-of-an-arangosearch-view">API * Documentation */ ArangoSearchPropertiesEntity updateProperties(ArangoSearchPropertiesOptions options); diff --git a/src/main/java/com/arangodb/ArangoVertexCollection.java b/src/main/java/com/arangodb/ArangoVertexCollection.java index 7be0dd4f0..7a3954195 100644 --- a/src/main/java/com/arangodb/ArangoVertexCollection.java +++ b/src/main/java/com/arangodb/ArangoVertexCollection.java @@ -58,19 +58,23 @@ public interface ArangoVertexCollection extends ArangoSerdeAccessor { /** * Creates a new vertex in the collection * - * @param value A representation of a single vertex (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) + * @param value A representation of a single vertex (POJO, {@link com.arangodb.util.RawJson} or + * {@link com.arangodb.util.RawBytes}) * @return information about the vertex - * @see API Documentation + * @see + * API Documentation */ VertexEntity insertVertex(Object value); /** * Creates a new vertex in the collection * - * @param value A representation of a single vertex (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) + * @param value A representation of a single vertex (POJO, {@link com.arangodb.util.RawJson} or + * {@link com.arangodb.util.RawBytes}) * @param options Additional options, can be null * @return information about the vertex - * @see API Documentation + * @see + * API Documentation */ VertexEntity insertVertex(Object value, VertexCreateOptions options); @@ -78,7 +82,8 @@ public interface ArangoVertexCollection extends ArangoSerdeAccessor { * Retrieves the vertex document with the given {@code key} from the collection. * * @param key The key of the vertex - * @param type The type of the vertex-document (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) + * @param type The type of the vertex-document (POJO, {@link com.arangodb.util.RawJson} or + * {@link com.arangodb.util.RawBytes}) * @return the vertex identified by the key * @see API Documentation */ @@ -88,7 +93,8 @@ public interface ArangoVertexCollection extends ArangoSerdeAccessor { * Retrieves the vertex document with the given {@code key} from the collection. * * @param key The key of the vertex - * @param type The type of the vertex-document (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) + * @param type The type of the vertex-document (POJO, {@link com.arangodb.util.RawJson} or + * {@link com.arangodb.util.RawBytes}) * @param options Additional options, can be null * @return the vertex identified by the key * @see API Documentation @@ -100,7 +106,8 @@ public interface ArangoVertexCollection extends ArangoSerdeAccessor { * violated * * @param key The key of the vertex - * @param value A representation of a single vertex (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) + * @param value A representation of a single vertex (POJO, {@link com.arangodb.util.RawJson} or + * {@link com.arangodb.util.RawBytes}) * @return information about the vertex * @see API * Documentation @@ -112,7 +119,8 @@ public interface ArangoVertexCollection extends ArangoSerdeAccessor { * violated * * @param key The key of the vertex - * @param value A representation of a single vertex (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) + * @param value A representation of a single vertex (POJO, {@link com.arangodb.util.RawJson} or + * {@link com.arangodb.util.RawBytes}) * @param options Additional options, can be null * @return information about the vertex * @see API @@ -126,9 +134,11 @@ public interface ArangoVertexCollection extends ArangoSerdeAccessor { * do not yet exist, and overwritten in the existing document if they do exist there. * * @param key The key of the vertex - * @param value A representation of a single vertex (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) + * @param value A representation of a single vertex (POJO, {@link com.arangodb.util.RawJson} or + * {@link com.arangodb.util.RawBytes}) * @return information about the vertex - * @see API Documentation + * @see + * API Documentation */ VertexUpdateEntity updateVertex(String key, Object value); @@ -138,10 +148,12 @@ public interface ArangoVertexCollection extends ArangoSerdeAccessor { * do not yet exist, and overwritten in the existing document if they do exist there. * * @param key The key of the vertex - * @param value A representation of a single vertex (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) + * @param value A representation of a single vertex (POJO, {@link com.arangodb.util.RawJson} or + * {@link com.arangodb.util.RawBytes}) * @param options Additional options, can be null * @return information about the vertex - * @see API Documentation + * @see + * API Documentation */ VertexUpdateEntity updateVertex(String key, Object value, VertexUpdateOptions options); @@ -149,7 +161,8 @@ public interface ArangoVertexCollection extends ArangoSerdeAccessor { * Deletes the vertex with the given {@code key} from the collection. * * @param key The key of the vertex - * @see API Documentation + * @see + * API Documentation */ void deleteVertex(String key); @@ -158,7 +171,8 @@ public interface ArangoVertexCollection extends ArangoSerdeAccessor { * * @param key The key of the vertex * @param options Additional options, can be null - * @see API Documentation + * @see + * API Documentation */ void deleteVertex(String key, VertexDeleteOptions options); diff --git a/src/main/java/com/arangodb/ArangoView.java b/src/main/java/com/arangodb/ArangoView.java index dec2481bd..6520ab469 100644 --- a/src/main/java/com/arangodb/ArangoView.java +++ b/src/main/java/com/arangodb/ArangoView.java @@ -55,7 +55,8 @@ public interface ArangoView extends ArangoSerdeAccessor { /** * Deletes the view from the database. * - * @see API Documentation + * @see + * API Documentation */ void drop(); @@ -64,7 +65,8 @@ public interface ArangoView extends ArangoSerdeAccessor { * * @param newName The new name * @return information about the view - * @see API Documentation + * @see + * API Documentation */ ViewEntity rename(String newName); @@ -72,7 +74,8 @@ public interface ArangoView extends ArangoSerdeAccessor { * Returns information about the view. * * @return information about the view - * @see API + * @see + * API * Documentation */ ViewEntity getInfo(); diff --git a/src/main/java/com/arangodb/async/ArangoCollectionAsync.java b/src/main/java/com/arangodb/async/ArangoCollectionAsync.java index c18bd7aa1..d155ba0ed 100644 --- a/src/main/java/com/arangodb/async/ArangoCollectionAsync.java +++ b/src/main/java/com/arangodb/async/ArangoCollectionAsync.java @@ -54,7 +54,8 @@ public interface ArangoCollectionAsync extends ArangoSerdeAccessor { * Creates a new document from the given document, unless there is already a document with the _key given. If no * _key is given, a new unique _key is generated automatically. * - * @param value A representation of a single document (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) + * @param value A representation of a single document (POJO, {@link com.arangodb.util.RawJson} or + * {@link com.arangodb.util.RawBytes}) * @return information about the document * @see API * Documentation @@ -65,7 +66,8 @@ public interface ArangoCollectionAsync extends ArangoSerdeAccessor { * Creates a new document from the given document, unless there is already a document with the _key given. If no * _key is given, a new unique _key is generated automatically. * - * @param value A representation of a single document (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) + * @param value A representation of a single document (POJO, {@link com.arangodb.util.RawJson} or + * {@link com.arangodb.util.RawBytes}) * @param options Additional options * @return information about the document * @see API @@ -77,14 +79,16 @@ public interface ArangoCollectionAsync extends ArangoSerdeAccessor { * Creates a new document from the given document, unless there is already a document with the _key given. If no * _key is given, a new unique _key is generated automatically. * - * @param value A representation of a single document (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) + * @param value A representation of a single document (POJO, {@link com.arangodb.util.RawJson} or + * {@link com.arangodb.util.RawBytes}) * @param options Additional options * @param type Deserialization target type for the returned documents. * @return information about the document * @see API * Documentation */ - CompletableFuture> insertDocument(final T value, final DocumentCreateOptions options, Class type); + CompletableFuture> insertDocument(final T value, final DocumentCreateOptions options, + Class type); /** * Creates new documents from the given documents, unless there is already a document with the _key given. If no @@ -101,7 +105,8 @@ public interface ArangoCollectionAsync extends ArangoSerdeAccessor { * Creates new documents from the given documents, unless there is already a document with the _key given. If no * _key is given, a new unique _key is generated automatically. * - * @param values A List of documents (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) + * @param values A List of documents (POJO, {@link com.arangodb.util.RawJson} or + * {@link com.arangodb.util.RawBytes}) * @param options Additional options * @return information about the documents * @see API @@ -115,7 +120,8 @@ CompletableFuture>> insertDocume * Creates new documents from the given documents, unless there is already a document with the _key given. If no * _key is given, a new unique _key is generated automatically. * - * @param values A List of documents (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) + * @param values A List of documents (POJO, {@link com.arangodb.util.RawJson} or + * {@link com.arangodb.util.RawBytes}) * @param options Additional options * @param type Deserialization target type for the returned documents. * @return information about the documents @@ -167,7 +173,8 @@ CompletableFuture importDocuments( * Reads a single document * * @param key The key of the document - * @param type The type of the document (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) + * @param type The type of the document (POJO, {@link com.arangodb.util.RawJson} or + * {@link com.arangodb.util.RawBytes}) * @return the document identified by the key * @see API * Documentation @@ -178,18 +185,21 @@ CompletableFuture importDocuments( * Reads a single document * * @param key The key of the document - * @param type The type of the document (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) + * @param type The type of the document (POJO, {@link com.arangodb.util.RawJson} or + * {@link com.arangodb.util.RawBytes}) * @param options Additional options, can be null * @return the document identified by the key * @see API * Documentation */ CompletableFuture getDocument(final String key, final Class type, final DocumentReadOptions options); + /** * Reads multiple documents * * @param keys The keys of the documents - * @param type The type of the documents (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) + * @param type The type of the documents (POJO, {@link com.arangodb.util.RawJson} or + * {@link com.arangodb.util.RawBytes}) * @return the documents and possible errors */ CompletableFuture> getDocuments(final Collection keys, final Class type); @@ -198,7 +208,8 @@ CompletableFuture importDocuments( * Reads multiple documents * * @param keys The keys of the documents - * @param type The type of the documents (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) + * @param type The type of the documents (POJO, {@link com.arangodb.util.RawJson} or + * {@link com.arangodb.util.RawBytes}) * @param options Additional options, can be null * @return the documents and possible errors */ @@ -212,9 +223,11 @@ CompletableFuture> getDocuments( * violated * * @param key The key of the document - * @param value A representation of a single document (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) + * @param value A representation of a single document (POJO, {@link com.arangodb.util.RawJson} or + * {@link com.arangodb.util.RawBytes}) * @return information about the document - * @see API + * @see + * API * Documentation */ CompletableFuture> replaceDocument(final String key, final Object value); @@ -224,10 +237,12 @@ CompletableFuture> getDocuments( * violated * * @param key The key of the document - * @param value A representation of a single document (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) + * @param value A representation of a single document (POJO, {@link com.arangodb.util.RawJson} or + * {@link com.arangodb.util.RawBytes}) * @param options Additional options * @return information about the document - * @see API + * @see + * API * Documentation */ CompletableFuture> replaceDocument( @@ -240,11 +255,13 @@ CompletableFuture> replaceDocument( * violated * * @param key The key of the document - * @param value A representation of a single document (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) + * @param value A representation of a single document (POJO, {@link com.arangodb.util.RawJson} or + * {@link com.arangodb.util.RawBytes}) * @param options Additional options * @param type Deserialization target type for the returned documents. * @return information about the document - * @see API + * @see + * API * Documentation */ CompletableFuture> replaceDocument( @@ -259,7 +276,8 @@ CompletableFuture> replaceDocument( * * @param values A List of documents (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) * @return information about the documents - * @see API + * @see + * API * Documentation */ CompletableFuture>> replaceDocuments(final Collection values); @@ -268,10 +286,12 @@ CompletableFuture> replaceDocument( * Replaces multiple documents in the specified collection with the ones in the values, the replaced documents are * specified by the _key attributes in the documents in values. * - * @param values A List of documents (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) + * @param values A List of documents (POJO, {@link com.arangodb.util.RawJson} or + * {@link com.arangodb.util.RawBytes}) * @param options Additional options * @return information about the documents - * @see API + * @see + * API * Documentation */ CompletableFuture>> replaceDocuments( @@ -282,11 +302,13 @@ CompletableFuture>> replaceDocum * Replaces multiple documents in the specified collection with the ones in the values, the replaced documents are * specified by the _key attributes in the documents in values. * - * @param values A List of documents (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) + * @param values A List of documents (POJO, {@link com.arangodb.util.RawJson} or + * {@link com.arangodb.util.RawBytes}) * @param options Additional options * @param type Deserialization target type for the returned documents. * @return information about the documents - * @see API + * @see + * API * Documentation */ CompletableFuture>> replaceDocuments( @@ -300,7 +322,8 @@ CompletableFuture>> replaceDocum * they do not yet exist, and overwritten in the existing document if they do exist there. * * @param key The key of the document - * @param value A representation of a single document (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) + * @param value A representation of a single document (POJO, {@link com.arangodb.util.RawJson} or + * {@link com.arangodb.util.RawBytes}) * @return information about the document * @see API * Documentation @@ -313,7 +336,8 @@ CompletableFuture>> replaceDocum * they do not yet exist, and overwritten in the existing document if they do exist there. * * @param key The key of the document - * @param value A representation of a single document (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) + * @param value A representation of a single document (POJO, {@link com.arangodb.util.RawJson} or + * {@link com.arangodb.util.RawBytes}) * @param options Additional options * @return information about the document * @see API @@ -330,7 +354,8 @@ CompletableFuture> updateDocument( * they do not yet exist, and overwritten in the existing document if they do exist there. * * @param key The key of the document - * @param value A representation of a single document (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) + * @param value A representation of a single document (POJO, {@link com.arangodb.util.RawJson} or + * {@link com.arangodb.util.RawBytes}) * @param options Additional options * @param returnType Type of the returned newDocument and/or oldDocument * @return information about the document @@ -351,7 +376,8 @@ CompletableFuture> updateDocument( * * @param values A list of documents (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) * @return information about the documents - * @see API + * @see + * API * Documentation */ CompletableFuture>> updateDocuments(final Collection values); @@ -362,10 +388,12 @@ CompletableFuture> updateDocument( * attributes from the patch documents will be added to the existing documents if they do not yet exist, and * overwritten in the existing documents if they do exist there. * - * @param values A list of documents (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) + * @param values A list of documents (POJO, {@link com.arangodb.util.RawJson} or + * {@link com.arangodb.util.RawBytes}) * @param options Additional options * @return information about the documents - * @see API + * @see + * API * Documentation */ CompletableFuture>> updateDocuments( @@ -378,11 +406,13 @@ CompletableFuture>> updateDocume * attributes from the patch documents will be added to the existing documents if they do not yet exist, and * overwritten in the existing documents if they do exist there. * - * @param values A list of documents (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) + * @param values A list of documents (POJO, {@link com.arangodb.util.RawJson} or + * {@link com.arangodb.util.RawBytes}) * @param options Additional options * @param returnType Type of the returned newDocument and/or oldDocument * @return information about the documents - * @see API + * @see + * API * Documentation */ CompletableFuture>> updateDocuments( @@ -395,7 +425,8 @@ CompletableFuture>> updateDocume * * @param key The key of the document * @return information about the document - * @see API + * @see + * API * Documentation */ CompletableFuture> deleteDocument(final String key); @@ -406,7 +437,8 @@ CompletableFuture>> updateDocume * @param key The key of the document * @param options Additional options * @return information about the document - * @see API + * @see + * API * Documentation */ CompletableFuture> deleteDocument( @@ -420,7 +452,8 @@ CompletableFuture> deleteDocument( * @param type Deserialization target type for the returned documents. * @param options Additional options * @return information about the document - * @see API + * @see + * API * Documentation */ CompletableFuture> deleteDocument( @@ -497,7 +530,8 @@ CompletableFuture>> deleteDocume * * @param id The index-handle * @return information about the index - * @see API Documentation + * @see + * API Documentation */ CompletableFuture getIndex(final String id); @@ -506,7 +540,8 @@ CompletableFuture>> deleteDocume * * @param id The index-handle * @return the id of the index - * @see API Documentation + * @see + * API Documentation */ CompletableFuture deleteIndex(final String id); @@ -516,7 +551,8 @@ CompletableFuture>> deleteDocume * @param fields A list of attribute paths * @param options Additional options, can be null * @return information about the index - * @see API Documentation + * @see + * API Documentation * @deprecated use {@link #ensurePersistentIndex(Iterable, PersistentIndexOptions)} instead. Since ArangoDB 3.7 a * hash index is an alias for a persistent index. */ @@ -639,7 +675,8 @@ CompletableFuture ensureFulltextIndex( * * @return information about the collection, including the number of documents * @see API + * "https://www.arangodb.com/docs/stable/http/collection-getting + * .html#return-number-of-documents-in-a-collection">API * Documentation */ CompletableFuture count(); @@ -649,7 +686,8 @@ CompletableFuture ensureFulltextIndex( * * @return information about the collection, including the number of documents * @see API + * "https://www.arangodb.com/docs/stable/http/collection-getting + * .html#return-number-of-documents-in-a-collection">API * Documentation */ CompletableFuture count(CollectionCountOptions options); @@ -685,7 +723,8 @@ CompletableFuture ensureFulltextIndex( /** * Drops the collection * - * @param isSystem Whether or not the collection to drop is a system collection. This parameter must be set to true in + * @param isSystem Whether or not the collection to drop is a system collection. This parameter must be set to + * true in * order to drop a system collection. * @return void * @see API @@ -741,7 +780,8 @@ CompletableFuture ensureFulltextIndex( * @param value A projection of the document containing at least the shard key (_key or a custom attribute) for * which the responsible shard should be determined * @return information about the responsible shard - * @see + * @see + * * API Documentation * @since ArangoDB 3.5.0 */ @@ -751,7 +791,8 @@ CompletableFuture ensureFulltextIndex( * Retrieve the collections revision * * @return information about the collection, including the collections revision - * @see API + * @see + * API * Documentation */ CompletableFuture getRevision(); @@ -798,7 +839,8 @@ CompletableFuture ensureFulltextIndex( * * @param user The name of the user * @return permissions of the user - * @see + * @see + * * API Documentation * @since ArangoDB 3.2.0 */ diff --git a/src/main/java/com/arangodb/async/ArangoDBAsync.java b/src/main/java/com/arangodb/async/ArangoDBAsync.java index 06b125a09..20007f246 100644 --- a/src/main/java/com/arangodb/async/ArangoDBAsync.java +++ b/src/main/java/com/arangodb/async/ArangoDBAsync.java @@ -276,7 +276,8 @@ public interface ArangoDBAsync extends ArangoSerdeAccessor { * * @param options Additional options, can be null * @return the log messages - * @see API + * @see + * API * Documentation * @since ArangoDB 3.8 */ @@ -433,7 +434,8 @@ public Builder connectionTtl(final Long connectionTtl) { } /** - * Set the keep-alive interval for VST connections. If set, every VST connection will perform a no-op request every + * Set the keep-alive interval for VST connections. If set, every VST connection will perform a no-op request + * every * {@code keepAliveInterval} seconds, to avoid to be closed due to inactivity by the server (or by the external * environment, eg. firewall, intermediate routers, operating system). * @@ -478,7 +480,8 @@ public Builder responseQueueTimeSamples(final Integer responseQueueTimeSamples) * In case of Active-Failover deployment set to {@link LoadBalancingStrategy#NONE} or not set at all, since that * would be the default. * - * @param loadBalancingStrategy the load balancing strategy to be used (default: {@link LoadBalancingStrategy#NONE} + * @param loadBalancingStrategy the load balancing strategy to be used (default: + * {@link LoadBalancingStrategy#NONE} * @return {@link ArangoDBAsync.Builder} */ public Builder loadBalancingStrategy(final LoadBalancingStrategy loadBalancingStrategy) { diff --git a/src/main/java/com/arangodb/async/ArangoDatabaseAsync.java b/src/main/java/com/arangodb/async/ArangoDatabaseAsync.java index 62b709b64..6dc963151 100644 --- a/src/main/java/com/arangodb/async/ArangoDatabaseAsync.java +++ b/src/main/java/com/arangodb/async/ArangoDatabaseAsync.java @@ -68,7 +68,8 @@ public interface ArangoDatabaseAsync extends ArangoSerdeAccessor { * Returns the name of the used storage engine. * * @return the storage engine name - * @see API + * @see + * API * Documentation */ CompletableFuture getEngine(); @@ -143,7 +144,8 @@ public interface ArangoDatabaseAsync extends ArangoSerdeAccessor { * * @param id The index-handle * @return information about the index - * @see API Documentation + * @see + * API Documentation */ CompletableFuture getIndex(final String id); @@ -152,7 +154,8 @@ public interface ArangoDatabaseAsync extends ArangoSerdeAccessor { * * @param id The index handle * @return the id of the index - * @see API Documentation + * @see + * API Documentation */ CompletableFuture deleteIndex(final String id); @@ -247,9 +250,11 @@ public interface ArangoDatabaseAsync extends ArangoSerdeAccessor { * @param query contains the query string to be executed * @param bindVars key/value pairs representing the bind parameters * @param options Additional options, can be null - * @param type The type of the result (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) + * @param type The type of the result (POJO, {@link com.arangodb.util.RawJson} or + * {@link com.arangodb.util.RawBytes}) * @return cursor of the results - * @see API + * @see + * API * Documentation */ CompletableFuture> query( @@ -264,9 +269,11 @@ CompletableFuture> query( * * @param query contains the query string to be executed * @param options Additional options, can be null - * @param type The type of the result (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) + * @param type The type of the result (POJO, {@link com.arangodb.util.RawJson} or + * {@link com.arangodb.util.RawBytes}) * @return cursor of the results - * @see API + * @see + * API * Documentation */ CompletableFuture> query( @@ -280,9 +287,11 @@ CompletableFuture> query( * * @param query contains the query string to be executed * @param bindVars key/value pairs representing the bind parameters - * @param type The type of the result (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) + * @param type The type of the result (POJO, {@link com.arangodb.util.RawJson} or + * {@link com.arangodb.util.RawBytes}) * @return cursor of the results - * @see API + * @see + * API * Documentation */ CompletableFuture> query( @@ -295,9 +304,11 @@ CompletableFuture> query( * result list. * * @param query contains the query string to be executed - * @param type The type of the result (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) + * @param type The type of the result (POJO, {@link com.arangodb.util.RawJson} or + * {@link com.arangodb.util.RawBytes}) * @return cursor of the results - * @see API + * @see + * API * Documentation */ CompletableFuture> query(final String query, final Class type); @@ -306,10 +317,12 @@ CompletableFuture> query( * Return an cursor from the given cursor-ID if still existing * * @param cursorId The ID of the cursor - * @param type The type of the result (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) + * @param type The type of the result (POJO, {@link com.arangodb.util.RawJson} or + * {@link com.arangodb.util.RawBytes}) * @return cursor of the results * @see API + * "https://www.arangodb.com/docs/stable/http/aql-query-cursor-accessing-cursors + * .html#read-next-batch-from-cursor">API * Documentation */ CompletableFuture> cursor(final String cursorId, final Class type); @@ -345,7 +358,8 @@ CompletableFuture explainQuery( * * @return void * @see API + * "https://www.arangodb.com/docs/stable/http/aql-query-cache + * .html#clears-any-results-in-the-aql-query-results-cache">API * Documentation */ CompletableFuture clearQueryCache(); @@ -355,7 +369,8 @@ CompletableFuture explainQuery( * * @return configuration for the AQL query cache * @see API + * "https://www.arangodb.com/docs/stable/http/aql-query-cache + * .html#returns-the-global-properties-for-the-aql-query-results-cache">API * Documentation */ CompletableFuture getQueryCacheProperties(); @@ -367,7 +382,8 @@ CompletableFuture explainQuery( * @param properties properties to be set * @return current set of properties * @see API + * "https://www.arangodb.com/docs/stable/http/aql-query-cache + * .html#globally-adjusts-the-aql-query-results-cache-properties">API * Documentation */ CompletableFuture setQueryCacheProperties(final QueryCachePropertiesEntity properties); @@ -521,7 +537,8 @@ CompletableFuture createGraph( * Execute a server-side transaction * * @param action the actual transaction operations to be executed, in the form of stringified JavaScript code - * @param type The type of the result (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) + * @param type The type of the result (POJO, {@link com.arangodb.util.RawJson} or + * {@link com.arangodb.util.RawBytes}) * @param options Additional options, can be null * @return the result of the transaction if it succeeded * @see API @@ -534,7 +551,8 @@ CompletableFuture createGraph( * * @param options Additional options, can be null * @return information about the transaction - * @see API + * @see + * API * Documentation * @since ArangoDB 3.5.0 */ @@ -544,7 +562,8 @@ CompletableFuture createGraph( * Aborts a Stream Transaction. * * @return information about the transaction - * @see API + * @see + * API * Documentation */ CompletableFuture abortStreamTransaction(String id); @@ -553,7 +572,8 @@ CompletableFuture createGraph( * Gets information about a Stream Transaction. * * @return information about the transaction - * @see + * @see + * * API Documentation * @since ArangoDB 3.5.0 */ @@ -563,7 +583,8 @@ CompletableFuture createGraph( * Gets all the currently running Stream Transactions. * * @return all the currently running Stream Transactions - * @see + * @see + * * API Documentation * @since ArangoDB 3.5.0 */ @@ -573,7 +594,8 @@ CompletableFuture createGraph( * Commits a Stream Transaction. * * @return information about the transaction - * @see + * @see + * * API Documentation * @since ArangoDB 3.5.0 */ @@ -593,7 +615,8 @@ CompletableFuture createGraph( * Reads a single document * * @param id The id of the document - * @param type The type of the document (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) + * @param type The type of the document (POJO, {@link com.arangodb.util.RawJson} or + * {@link com.arangodb.util.RawBytes}) * @return the document identified by the id * @see API * Documentation @@ -604,19 +627,22 @@ CompletableFuture createGraph( * Reads a single document * * @param id The id of the document - * @param type The type of the document (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) + * @param type The type of the document (POJO, {@link com.arangodb.util.RawJson} or + * {@link com.arangodb.util.RawBytes}) * @param options Additional options, can be null * @return the document identified by the id * @see API * Documentation */ CompletableFuture getDocument(final String id, final Class type, final DocumentReadOptions options); + /** * Reload the routing table. * * @return void * @see API + * "https://www.arangodb.com/docs/stable/http/administration-and-monitoring + * .html#reloads-the-routing-information">API * Documentation */ CompletableFuture reloadRouting(); @@ -634,7 +660,8 @@ CompletableFuture createGraph( * Fetches all views from the database and returns an list of view descriptions. * * @return list of information about all views - * @see API Documentation + * @see + * API Documentation * @since ArangoDB 3.4.0 */ CompletableFuture> getViews(); diff --git a/src/main/java/com/arangodb/async/ArangoEdgeCollectionAsync.java b/src/main/java/com/arangodb/async/ArangoEdgeCollectionAsync.java index f9ccdc768..d2465cd8f 100644 --- a/src/main/java/com/arangodb/async/ArangoEdgeCollectionAsync.java +++ b/src/main/java/com/arangodb/async/ArangoEdgeCollectionAsync.java @@ -52,7 +52,8 @@ public interface ArangoEdgeCollectionAsync extends ArangoSerdeAccessor { /** * Creates a new edge in the collection * - * @param value A representation of a single edge (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) + * @param value A representation of a single edge (POJO, {@link com.arangodb.util.RawJson} or + * {@link com.arangodb.util.RawBytes}) * @return information about the edge * @see API Documentation */ @@ -61,7 +62,8 @@ public interface ArangoEdgeCollectionAsync extends ArangoSerdeAccessor { /** * Creates a new edge in the collection * - * @param value A representation of a single edge (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) + * @param value A representation of a single edge (POJO, {@link com.arangodb.util.RawJson} or + * {@link com.arangodb.util.RawBytes}) * @param options Additional options, can be null * @return information about the edge * @see API Documentation @@ -72,7 +74,8 @@ public interface ArangoEdgeCollectionAsync extends ArangoSerdeAccessor { * Fetches an existing edge * * @param key The key of the edge - * @param type The type of the edge-document (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) + * @param type The type of the edge-document (POJO, {@link com.arangodb.util.RawJson} or + * {@link com.arangodb.util.RawBytes}) * @return the edge identified by the key * @see API Documentation */ @@ -82,7 +85,8 @@ public interface ArangoEdgeCollectionAsync extends ArangoSerdeAccessor { * Fetches an existing edge * * @param key The key of the edge - * @param type The type of the edge-document (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) + * @param type The type of the edge-document (POJO, {@link com.arangodb.util.RawJson} or + * {@link com.arangodb.util.RawBytes}) * @param options Additional options, can be null * @return the edge identified by the key * @see API Documentation diff --git a/src/main/java/com/arangodb/async/ArangoGraphAsync.java b/src/main/java/com/arangodb/async/ArangoGraphAsync.java index 0c242261b..289741d79 100644 --- a/src/main/java/com/arangodb/async/ArangoGraphAsync.java +++ b/src/main/java/com/arangodb/async/ArangoGraphAsync.java @@ -87,17 +87,20 @@ CompletableFuture createGraph( * Delete an existing graph * * @return void - * @see API Documentation + * @see + * API Documentation */ CompletableFuture drop(); /** * Delete an existing graph including * - * @param dropCollections Drop collections of this graph as well. Collections will only be dropped if they are not used in other + * @param dropCollections Drop collections of this graph as well. Collections will only be dropped if they are + * not used in other * graphs. * @return void - * @see API Documentation + * @see + * API Documentation */ CompletableFuture drop(boolean dropCollections); @@ -105,7 +108,8 @@ CompletableFuture createGraph( * Get a graph from the graph module * * @return the definition content of this graph - * @see API Documentation + * @see + * API Documentation */ CompletableFuture getInfo(); diff --git a/src/main/java/com/arangodb/async/ArangoSearchAsync.java b/src/main/java/com/arangodb/async/ArangoSearchAsync.java index d738012c1..1c4d2babc 100644 --- a/src/main/java/com/arangodb/async/ArangoSearchAsync.java +++ b/src/main/java/com/arangodb/async/ArangoSearchAsync.java @@ -70,7 +70,8 @@ public interface ArangoSearchAsync extends ArangoViewAsync { * @param options properties to change * @return properties of the view @ * @see API + * "https://www.arangodb.com/docs/stable/http/views-arangosearch + * .html#partially-changes-properties-of-an-arangosearch-view">API * Documentation */ CompletableFuture updateProperties(ArangoSearchPropertiesOptions options); diff --git a/src/main/java/com/arangodb/async/ArangoVertexCollectionAsync.java b/src/main/java/com/arangodb/async/ArangoVertexCollectionAsync.java index 50d1dad32..38e22d660 100644 --- a/src/main/java/com/arangodb/async/ArangoVertexCollectionAsync.java +++ b/src/main/java/com/arangodb/async/ArangoVertexCollectionAsync.java @@ -62,19 +62,23 @@ public interface ArangoVertexCollectionAsync extends ArangoSerdeAccessor { /** * Creates a new vertex in the collection * - * @param value A representation of a single vertex (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) + * @param value A representation of a single vertex (POJO, {@link com.arangodb.util.RawJson} or + * {@link com.arangodb.util.RawBytes}) * @return information about the vertex - * @see API Documentation + * @see + * API Documentation */ CompletableFuture insertVertex(final Object value); /** * Creates a new vertex in the collection * - * @param value A representation of a single vertex (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) + * @param value A representation of a single vertex (POJO, {@link com.arangodb.util.RawJson} or + * {@link com.arangodb.util.RawBytes}) * @param options Additional options, can be null * @return information about the vertex - * @see API Documentation + * @see + * API Documentation */ CompletableFuture insertVertex(final Object value, final VertexCreateOptions options); @@ -82,7 +86,8 @@ public interface ArangoVertexCollectionAsync extends ArangoSerdeAccessor { * Fetches an existing vertex * * @param key The key of the vertex - * @param type The type of the vertex-document (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) + * @param type The type of the vertex-document (POJO, {@link com.arangodb.util.RawJson} or + * {@link com.arangodb.util.RawBytes}) * @return the vertex identified by the key * @see API Documentation */ @@ -92,7 +97,8 @@ public interface ArangoVertexCollectionAsync extends ArangoSerdeAccessor { * Fetches an existing vertex * * @param key The key of the vertex - * @param type The type of the vertex-document (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) + * @param type The type of the vertex-document (POJO, {@link com.arangodb.util.RawJson} or + * {@link com.arangodb.util.RawBytes}) * @param options Additional options, can be null * @return the vertex identified by the key * @see API Documentation @@ -132,7 +138,8 @@ CompletableFuture replaceVertex( * * @param key The key of the vertex * @return information about the vertex - * @see API Documentation + * @see + * API Documentation */ CompletableFuture updateVertex(final String key, final Object value); @@ -144,7 +151,8 @@ CompletableFuture replaceVertex( * @param key The key of the vertex * @param options Additional options, can be null * @return information about the vertex - * @see API Documentation + * @see + * API Documentation */ CompletableFuture updateVertex( final String key, @@ -155,7 +163,8 @@ CompletableFuture updateVertex( * Removes a vertex * * @param key The key of the vertex - * @see API Documentation + * @see + * API Documentation */ CompletableFuture deleteVertex(final String key); @@ -164,7 +173,8 @@ CompletableFuture updateVertex( * * @param key The key of the vertex * @param options Additional options, can be null - * @see API Documentation + * @see + * API Documentation */ CompletableFuture deleteVertex(final String key, final VertexDeleteOptions options); diff --git a/src/main/java/com/arangodb/async/ArangoViewAsync.java b/src/main/java/com/arangodb/async/ArangoViewAsync.java index b1de2e10a..433c536ef 100644 --- a/src/main/java/com/arangodb/async/ArangoViewAsync.java +++ b/src/main/java/com/arangodb/async/ArangoViewAsync.java @@ -58,7 +58,8 @@ public interface ArangoViewAsync extends ArangoSerdeAccessor { /** * Deletes the view from the database. * - * @see API Documentation + * @see + * API Documentation */ CompletableFuture drop(); @@ -67,7 +68,8 @@ public interface ArangoViewAsync extends ArangoSerdeAccessor { * * @param newName The new name * @return information about the view - * @see API Documentation + * @see + * API Documentation */ CompletableFuture rename(String newName); @@ -75,7 +77,8 @@ public interface ArangoViewAsync extends ArangoSerdeAccessor { * Returns information about the view. * * @return information about the view - * @see API + * @see + * API * Documentation */ CompletableFuture getInfo(); diff --git a/src/main/java/com/arangodb/async/internal/ArangoCollectionAsyncImpl.java b/src/main/java/com/arangodb/async/internal/ArangoCollectionAsyncImpl.java index e71ac4fa0..ba93556ba 100644 --- a/src/main/java/com/arangodb/async/internal/ArangoCollectionAsyncImpl.java +++ b/src/main/java/com/arangodb/async/internal/ArangoCollectionAsyncImpl.java @@ -59,7 +59,8 @@ public CompletableFuture> insertDocument( } @Override - public CompletableFuture> insertDocument(T value, DocumentCreateOptions options, Class type) { + public CompletableFuture> insertDocument(T value, DocumentCreateOptions options, + Class type) { return executor.execute(insertDocumentRequest(value, options), constructParametricType(DocumentCreateEntity.class, type)); } @@ -68,7 +69,8 @@ public CompletableFuture> insertDocument(T value, Do public CompletableFuture>> insertDocuments( final Collection values) { return executor - .execute(insertDocumentsRequest(values, new DocumentCreateOptions()), insertDocumentsResponseDeserializer(Void.class)); + .execute(insertDocumentsRequest(values, new DocumentCreateOptions()), + insertDocumentsResponseDeserializer(Void.class)); } @Override @@ -80,7 +82,8 @@ public CompletableFuture>> inser } @Override - public CompletableFuture>> insertDocuments(Collection values, DocumentCreateOptions options, Class type) { + public CompletableFuture>> insertDocuments(Collection values, + DocumentCreateOptions options, Class type) { return executor .execute(insertDocumentsRequest(values, options), insertDocumentsResponseDeserializer(type)); } @@ -157,7 +160,9 @@ public CompletableFuture> replaceDocument( } @Override - public CompletableFuture> replaceDocument(String key, T value, DocumentReplaceOptions options, Class type) { + public CompletableFuture> replaceDocument(String key, T value, + DocumentReplaceOptions options, + Class type) { return executor.execute(replaceDocumentRequest(key, value, options), constructParametricType(DocumentUpdateEntity.class, type)); } @@ -165,7 +170,8 @@ public CompletableFuture> replaceDocument(String key @Override public CompletableFuture>> replaceDocuments( final Collection values) { - return executor.execute(replaceDocumentsRequest(values, new DocumentReplaceOptions()), replaceDocumentsResponseDeserializer(Void.class)); + return executor.execute(replaceDocumentsRequest(values, new DocumentReplaceOptions()), + replaceDocumentsResponseDeserializer(Void.class)); } @Override @@ -177,7 +183,8 @@ public CompletableFuture>> repla } @Override - public CompletableFuture>> replaceDocuments(Collection values, DocumentReplaceOptions options, Class type) { + public CompletableFuture>> replaceDocuments(Collection values, + DocumentReplaceOptions options, Class type) { return executor.execute(replaceDocumentsRequest(values, options), replaceDocumentsResponseDeserializer(type)); } @@ -255,7 +262,8 @@ public CompletableFuture>> delete @Override @SuppressWarnings("unchecked") - public CompletableFuture>> deleteDocuments(Collection values, DocumentDeleteOptions options) { + public CompletableFuture>> deleteDocuments(Collection values, + DocumentDeleteOptions options) { return deleteDocuments(values, options, (Class) getCollectionContentClass(values)); } diff --git a/src/main/java/com/arangodb/async/internal/ArangoDatabaseAsyncImpl.java b/src/main/java/com/arangodb/async/internal/ArangoDatabaseAsyncImpl.java index af6a57832..f163f0543 100644 --- a/src/main/java/com/arangodb/async/internal/ArangoDatabaseAsyncImpl.java +++ b/src/main/java/com/arangodb/async/internal/ArangoDatabaseAsyncImpl.java @@ -180,7 +180,8 @@ public CompletableFuture> query( final Class type) { final Request request = queryRequest(query, bindVars, options); final HostHandle hostHandle = new HostHandle(); - final CompletableFuture execution = executor.execute(request, InternalCursorEntity.class, hostHandle); + final CompletableFuture execution = executor.execute(request, + InternalCursorEntity.class, hostHandle); return execution.thenApply(result -> createCursor(result, type, options, hostHandle)); } @@ -208,7 +209,8 @@ public CompletableFuture> query(final String query, fin @Override public CompletableFuture> cursor(final String cursorId, final Class type) { final HostHandle hostHandle = new HostHandle(); - final CompletableFuture execution = executor.execute(queryNextRequest(cursorId, null, null), InternalCursorEntity.class, hostHandle); + final CompletableFuture execution = executor.execute(queryNextRequest(cursorId, null, + null), InternalCursorEntity.class, hostHandle); return execution.thenApply(result -> createCursor(result, type, null, hostHandle)); } @@ -220,7 +222,8 @@ private ArangoCursorAsync createCursor( return new ArangoCursorAsyncImpl<>(this, new ArangoCursorExecute() { @Override public InternalCursorEntity next(final String id, Map meta) { - final CompletableFuture result = executor.execute(queryNextRequest(id, options, meta), + final CompletableFuture result = executor.execute(queryNextRequest(id, options, + meta), InternalCursorEntity.class, hostHandle); try { return result.get(); @@ -393,7 +396,8 @@ public CompletableFuture getDocument(final String id, final Class type } @Override - public CompletableFuture getDocument(final String id, final Class type, final DocumentReadOptions options) { + public CompletableFuture getDocument(final String id, final Class type, + final DocumentReadOptions options) { DocumentUtil.validateDocumentId(id); final String[] split = id.split("/"); return collection(split[0]).getDocument(split[1], type, options); @@ -430,7 +434,8 @@ public CompletableFuture createView(final String name, final ViewTyp } @Override - public CompletableFuture createArangoSearch(final String name, final ArangoSearchCreateOptions options) { + public CompletableFuture createArangoSearch(final String name, + final ArangoSearchCreateOptions options) { return executor.execute(createArangoSearchRequest(name, options), ViewEntity.class); } diff --git a/src/main/java/com/arangodb/async/internal/ArangoEdgeCollectionAsyncImpl.java b/src/main/java/com/arangodb/async/internal/ArangoEdgeCollectionAsyncImpl.java index 48f2a9f99..9edaf9a91 100644 --- a/src/main/java/com/arangodb/async/internal/ArangoEdgeCollectionAsyncImpl.java +++ b/src/main/java/com/arangodb/async/internal/ArangoEdgeCollectionAsyncImpl.java @@ -32,7 +32,8 @@ * @author Mark Vollmary */ public class ArangoEdgeCollectionAsyncImpl extends - InternalArangoEdgeCollection + InternalArangoEdgeCollection implements ArangoEdgeCollectionAsync { ArangoEdgeCollectionAsyncImpl(final ArangoGraphAsyncImpl graph, final String name) { @@ -56,7 +57,8 @@ public CompletableFuture getEdge(final String key, final Class type) { } @Override - public CompletableFuture getEdge(final String key, final Class type, final GraphDocumentReadOptions options) { + public CompletableFuture getEdge(final String key, final Class type, + final GraphDocumentReadOptions options) { return executor.execute(getEdgeRequest(key, options), getEdgeResponseDeserializer(type)) .exceptionally(ExceptionUtil.catchGetDocumentExceptions()); } diff --git a/src/main/java/com/arangodb/async/internal/ArangoGraphAsyncImpl.java b/src/main/java/com/arangodb/async/internal/ArangoGraphAsyncImpl.java index 23777f933..c16a32aaf 100644 --- a/src/main/java/com/arangodb/async/internal/ArangoGraphAsyncImpl.java +++ b/src/main/java/com/arangodb/async/internal/ArangoGraphAsyncImpl.java @@ -87,7 +87,8 @@ public CompletableFuture addVertexCollection(final String name) { } @Override - public CompletableFuture addVertexCollection(final String name, final VertexCollectionCreateOptions options) { + public CompletableFuture addVertexCollection(final String name, + final VertexCollectionCreateOptions options) { return executor.execute(addVertexCollectionRequest(name, options), addVertexCollectionResponseDeserializer()); } diff --git a/src/main/java/com/arangodb/async/internal/ArangoVertexCollectionAsyncImpl.java b/src/main/java/com/arangodb/async/internal/ArangoVertexCollectionAsyncImpl.java index 9759546d3..018b5ee57 100644 --- a/src/main/java/com/arangodb/async/internal/ArangoVertexCollectionAsyncImpl.java +++ b/src/main/java/com/arangodb/async/internal/ArangoVertexCollectionAsyncImpl.java @@ -32,7 +32,8 @@ * @author Mark Vollmary */ public class ArangoVertexCollectionAsyncImpl extends - InternalArangoVertexCollection + InternalArangoVertexCollection implements ArangoVertexCollectionAsync { ArangoVertexCollectionAsyncImpl(final ArangoGraphAsyncImpl graph, final String name) { diff --git a/src/main/java/com/arangodb/async/internal/utils/CompletableFutureUtils.java b/src/main/java/com/arangodb/async/internal/utils/CompletableFutureUtils.java index a8d3c0156..026453645 100644 --- a/src/main/java/com/arangodb/async/internal/utils/CompletableFutureUtils.java +++ b/src/main/java/com/arangodb/async/internal/utils/CompletableFutureUtils.java @@ -14,7 +14,8 @@ public class CompletableFutureUtils { private CompletableFutureUtils() { } - public static CompletableFuture orTimeout(CompletableFuture completableFuture, long timeout, TimeUnit unit) { + public static CompletableFuture orTimeout(CompletableFuture completableFuture, long timeout, + TimeUnit unit) { ScheduledFuture timeoutTask = timeoutScheduler.schedule(() -> completableFuture.completeExceptionally(new TimeoutException()), timeout, unit); completableFuture.whenComplete((v, e) -> timeoutTask.cancel(false)); diff --git a/src/main/java/com/arangodb/async/internal/velocystream/VstCommunicationAsync.java b/src/main/java/com/arangodb/async/internal/velocystream/VstCommunicationAsync.java index b4690aaaf..23fdc76ce 100644 --- a/src/main/java/com/arangodb/async/internal/velocystream/VstCommunicationAsync.java +++ b/src/main/java/com/arangodb/async/internal/velocystream/VstCommunicationAsync.java @@ -50,7 +50,8 @@ public class VstCommunicationAsync extends VstCommunication execute(final Request request, final VstCo } @Override - protected CompletableFuture execute(final Request request, final VstConnectionAsync connection, final int attemptCount) { + protected CompletableFuture execute(final Request request, final VstConnectionAsync connection, + final int attemptCount) { final CompletableFuture rfuture = new CompletableFuture<>(); try { final Message message = createMessage(request); @@ -210,7 +212,8 @@ public Builder connectionTtl(final Long connectionTtl) { } public VstCommunicationAsync build(final InternalSerde util) { - return new VstCommunicationAsync(hostHandler, timeout, user, password, jwt, useSsl, sslContext, util, chunksize, + return new VstCommunicationAsync(hostHandler, timeout, user, password, jwt, useSsl, sslContext, util, + chunksize, maxConnections, connectionTtl); } } diff --git a/src/main/java/com/arangodb/async/internal/velocystream/VstConnectionAsync.java b/src/main/java/com/arangodb/async/internal/velocystream/VstConnectionAsync.java index 8f5b73ab9..8805fd674 100644 --- a/src/main/java/com/arangodb/async/internal/velocystream/VstConnectionAsync.java +++ b/src/main/java/com/arangodb/async/internal/velocystream/VstConnectionAsync.java @@ -38,7 +38,8 @@ */ public class VstConnectionAsync extends VstConnection> { - private VstConnectionAsync(final HostDescription host, final Integer timeout, final Long ttl, final Integer keepAliveInterval, + private VstConnectionAsync(final HostDescription host, final Integer timeout, final Long ttl, + final Integer keepAliveInterval, final Boolean useSsl, final SSLContext sslContext, final MessageStore messageStore) { super(host, timeout, ttl, keepAliveInterval, useSsl, sslContext, messageStore); } diff --git a/src/main/java/com/arangodb/async/internal/velocystream/VstConnectionFactoryAsync.java b/src/main/java/com/arangodb/async/internal/velocystream/VstConnectionFactoryAsync.java index bd2380feb..eaabb7b08 100644 --- a/src/main/java/com/arangodb/async/internal/velocystream/VstConnectionFactoryAsync.java +++ b/src/main/java/com/arangodb/async/internal/velocystream/VstConnectionFactoryAsync.java @@ -35,7 +35,8 @@ public class VstConnectionFactoryAsync implements ConnectionFactory { private final VstConnectionAsync.Builder builder; public VstConnectionFactoryAsync(final HostDescription host, final Integer timeout, final Long connectionTtl, - final Integer keepAliveInterval, final Boolean useSsl, final SSLContext sslContext) { + final Integer keepAliveInterval, final Boolean useSsl, + final SSLContext sslContext) { super(); builder = new VstConnectionAsync.Builder().timeout(timeout).ttl(connectionTtl) .keepAliveInterval(keepAliveInterval).useSsl(useSsl) diff --git a/src/main/java/com/arangodb/entity/ArangoDBEngine.java b/src/main/java/com/arangodb/entity/ArangoDBEngine.java index 7ff44eba3..9c35da0c7 100644 --- a/src/main/java/com/arangodb/entity/ArangoDBEngine.java +++ b/src/main/java/com/arangodb/entity/ArangoDBEngine.java @@ -22,7 +22,8 @@ /** * @author Michele Rastelli - * @see API + * @see + * API * Documentation */ public final class ArangoDBEngine { diff --git a/src/main/java/com/arangodb/entity/LogEntriesEntity.java b/src/main/java/com/arangodb/entity/LogEntriesEntity.java index e43d44713..f7bf4ee51 100644 --- a/src/main/java/com/arangodb/entity/LogEntriesEntity.java +++ b/src/main/java/com/arangodb/entity/LogEntriesEntity.java @@ -24,7 +24,8 @@ /** * @author Michele Rastelli - * @see API + * @see + * API * Documentation * @since ArangoDB 3.8 */ diff --git a/src/main/java/com/arangodb/entity/LogLevelEntity.java b/src/main/java/com/arangodb/entity/LogLevelEntity.java index ea590d988..890998a68 100644 --- a/src/main/java/com/arangodb/entity/LogLevelEntity.java +++ b/src/main/java/com/arangodb/entity/LogLevelEntity.java @@ -44,6 +44,7 @@ public final class LogLevelEntity { private LogLevel startup; private LogLevel threads; private LogLevel v8; + public LogLevelEntity() { super(); } diff --git a/src/main/java/com/arangodb/entity/QueryCachePropertiesEntity.java b/src/main/java/com/arangodb/entity/QueryCachePropertiesEntity.java index 8f4655f22..d0e8b73c8 100644 --- a/src/main/java/com/arangodb/entity/QueryCachePropertiesEntity.java +++ b/src/main/java/com/arangodb/entity/QueryCachePropertiesEntity.java @@ -30,6 +30,7 @@ public final class QueryCachePropertiesEntity { private CacheMode mode; private Long maxResults; + public QueryCachePropertiesEntity() { super(); } diff --git a/src/main/java/com/arangodb/entity/QueryTrackingPropertiesEntity.java b/src/main/java/com/arangodb/entity/QueryTrackingPropertiesEntity.java index f8054ec32..e25e95015 100644 --- a/src/main/java/com/arangodb/entity/QueryTrackingPropertiesEntity.java +++ b/src/main/java/com/arangodb/entity/QueryTrackingPropertiesEntity.java @@ -44,7 +44,8 @@ public Boolean getEnabled() { } /** - * @param enabled If set to true, then queries will be tracked. If set to false, neither queries nor slow queries will + * @param enabled If set to true, then queries will be tracked. If set to false, neither queries nor slow queries + * will * be tracked */ public void setEnabled(final Boolean enabled) { @@ -61,8 +62,10 @@ public Boolean getTrackSlowQueries() { } /** - * @param trackSlowQueries If set to true, then slow queries will be tracked in the list of slow queries if their runtime exceeds - * the value set in slowQueryThreshold. In order for slow queries to be tracked, the enabled property + * @param trackSlowQueries If set to true, then slow queries will be tracked in the list of slow queries if their + * runtime exceeds + * the value set in slowQueryThreshold. In order for slow queries to be tracked, the + * enabled property * must also be set to true. */ public void setTrackSlowQueries(final Boolean trackSlowQueries) { @@ -78,7 +81,8 @@ public Long getMaxSlowQueries() { } /** - * @param maxSlowQueries The maximum number of slow queries to keep in the list of slow queries. If the list of slow queries is + * @param maxSlowQueries The maximum number of slow queries to keep in the list of slow queries. If the list of + * slow queries is * full, the oldest entry in it will be discarded when additional slow queries occur. */ public void setMaxSlowQueries(final Long maxSlowQueries) { @@ -95,8 +99,10 @@ public Long getSlowQueryThreshold() { } /** - * @param slowQueryThreshold The threshold value for treating a query as slow. A query with a runtime greater or equal to this - * threshold value will be put into the list of slow queries when slow query tracking is enabled. The + * @param slowQueryThreshold The threshold value for treating a query as slow. A query with a runtime greater or + * equal to this + * threshold value will be put into the list of slow queries when slow query tracking + * is enabled. The * value for slowQueryThreshold is specified in seconds. */ public void setSlowQueryThreshold(final Long slowQueryThreshold) { @@ -113,8 +119,10 @@ public Long getMaxQueryStringLength() { } /** - * @param maxQueryStringLength The maximum query string length to keep in the list of queries. Query strings can have arbitrary - * lengths, and this property can be used to save memory in case very long query strings are used. The + * @param maxQueryStringLength The maximum query string length to keep in the list of queries. Query strings can + * have arbitrary + * lengths, and this property can be used to save memory in case very long query + * strings are used. The * value is specified in bytes. */ public void setMaxQueryStringLength(final Long maxQueryStringLength) { diff --git a/src/main/java/com/arangodb/entity/TransactionEntity.java b/src/main/java/com/arangodb/entity/TransactionEntity.java index f9925927d..786a803b4 100644 --- a/src/main/java/com/arangodb/entity/TransactionEntity.java +++ b/src/main/java/com/arangodb/entity/TransactionEntity.java @@ -23,7 +23,8 @@ /** * @author Michele Rastelli * @see + * "https://www.arangodb.com/docs/stable/http/transaction-stream-transaction + * .html#list-currently-ongoing-transactions * @since ArangoDB 3.5.0 */ public final class TransactionEntity { diff --git a/src/main/java/com/arangodb/entity/arangosearch/AnalyzerFeature.java b/src/main/java/com/arangodb/entity/arangosearch/AnalyzerFeature.java index 8fdf06509..8482c8b46 100644 --- a/src/main/java/com/arangodb/entity/arangosearch/AnalyzerFeature.java +++ b/src/main/java/com/arangodb/entity/arangosearch/AnalyzerFeature.java @@ -22,7 +22,8 @@ /** * @author Michele Rastelli - * @see API Documentation + * @see + * API Documentation */ public enum AnalyzerFeature { @@ -37,7 +38,8 @@ public enum AnalyzerFeature { norm, /** - * sequentially increasing term position, required for PHRASE(). If present then the frequency feature is also required + * sequentially increasing term position, required for PHRASE(). If present then the frequency feature is also + * required */ position diff --git a/src/main/java/com/arangodb/entity/arangosearch/CollectionLink.java b/src/main/java/com/arangodb/entity/arangosearch/CollectionLink.java index e240cbbc4..a64a85679 100644 --- a/src/main/java/com/arangodb/entity/arangosearch/CollectionLink.java +++ b/src/main/java/com/arangodb/entity/arangosearch/CollectionLink.java @@ -69,7 +69,8 @@ public CollectionLink analyzers(final String... analyzers) { } /** - * @param includeAllFields The flag determines whether or not to index all fields on a particular level of depth (default: + * @param includeAllFields The flag determines whether or not to index all fields on a particular level of depth + * (default: * false). * @return link */ @@ -79,7 +80,8 @@ public CollectionLink includeAllFields(final Boolean includeAllFields) { } /** - * @param trackListPositions The flag determines whether or not values in a lists should be treated separate (default: false). + * @param trackListPositions The flag determines whether or not values in a lists should be treated separate + * (default: false). * @return link */ public CollectionLink trackListPositions(final Boolean trackListPositions) { @@ -88,7 +90,8 @@ public CollectionLink trackListPositions(final Boolean trackListPositions) { } /** - * @param storeValues How should the view track the attribute values, this setting allows for additional value retrieval + * @param storeValues How should the view track the attribute values, this setting allows for additional value + * retrieval * optimizations (default "none"). * @return link */ diff --git a/src/main/java/com/arangodb/entity/arangosearch/ConsolidationPolicy.java b/src/main/java/com/arangodb/entity/arangosearch/ConsolidationPolicy.java index 63bf7483c..d06f1b1a4 100644 --- a/src/main/java/com/arangodb/entity/arangosearch/ConsolidationPolicy.java +++ b/src/main/java/com/arangodb/entity/arangosearch/ConsolidationPolicy.java @@ -42,7 +42,8 @@ public ConsolidationPolicy type(final ConsolidationType type) { } /** - * @param threshold Select a given segment for "consolidation" if and only if the formula based on type (as defined above) + * @param threshold Select a given segment for "consolidation" if and only if the formula based on type (as + * defined above) * evaluates to true, valid value range [0.0, 1.0] (default: 0.85) * @return policy */ diff --git a/src/main/java/com/arangodb/entity/arangosearch/FieldLink.java b/src/main/java/com/arangodb/entity/arangosearch/FieldLink.java index 2b2a803a4..00a7a93d9 100644 --- a/src/main/java/com/arangodb/entity/arangosearch/FieldLink.java +++ b/src/main/java/com/arangodb/entity/arangosearch/FieldLink.java @@ -44,7 +44,8 @@ public FieldLink analyzers(final String... analyzers) { } /** - * @param includeAllFields The flag determines whether or not to index all fields on a particular level of depth (default: + * @param includeAllFields The flag determines whether or not to index all fields on a particular level of depth + * (default: * false). * @return link */ @@ -54,7 +55,8 @@ public FieldLink includeAllFields(final Boolean includeAllFields) { } /** - * @param trackListPositions The flag determines whether or not values in a lists should be treated separate (default: false). + * @param trackListPositions The flag determines whether or not values in a lists should be treated separate + * (default: false). * @return link */ public FieldLink trackListPositions(final Boolean trackListPositions) { @@ -63,7 +65,8 @@ public FieldLink trackListPositions(final Boolean trackListPositions) { } /** - * @param storeValues How should the view track the attribute values, this setting allows for additional value retrieval + * @param storeValues How should the view track the attribute values, this setting allows for additional value + * retrieval * optimizations (default "none"). * @return link */ diff --git a/src/main/java/com/arangodb/entity/arangosearch/StoredValue.java b/src/main/java/com/arangodb/entity/arangosearch/StoredValue.java index d44df7a6d..c25a31e70 100644 --- a/src/main/java/com/arangodb/entity/arangosearch/StoredValue.java +++ b/src/main/java/com/arangodb/entity/arangosearch/StoredValue.java @@ -37,7 +37,8 @@ public final class StoredValue { private final ArangoSearchCompression compression; @JsonCreator - public StoredValue(@JsonProperty("fields") List fields, @JsonProperty("compression") ArangoSearchCompression compression) { + public StoredValue(@JsonProperty("fields") List fields, + @JsonProperty("compression") ArangoSearchCompression compression) { this.fields = fields; this.compression = compression; } diff --git a/src/main/java/com/arangodb/entity/arangosearch/analyzer/AQLAnalyzerProperties.java b/src/main/java/com/arangodb/entity/arangosearch/analyzer/AQLAnalyzerProperties.java index 84f9ab3b7..acb3c2a29 100644 --- a/src/main/java/com/arangodb/entity/arangosearch/analyzer/AQLAnalyzerProperties.java +++ b/src/main/java/com/arangodb/entity/arangosearch/analyzer/AQLAnalyzerProperties.java @@ -72,7 +72,8 @@ public void setCollapsePositions(Boolean collapsePositions) { * true (default): treat null like an empty string * *

  • - * false: discard nulls from View index. Can be used for index filtering (i.e. make your query return null for unwanted data). Note that empty results are always discarded. + * false: discard nulls from View index. Can be used for index filtering (i.e. make your query return null for + * unwanted data). Note that empty results are always discarded. *
  • * */ @@ -125,7 +126,9 @@ public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; AQLAnalyzerProperties that = (AQLAnalyzerProperties) o; - return Objects.equals(queryString, that.queryString) && Objects.equals(collapsePositions, that.collapsePositions) && Objects.equals(keepNull, that.keepNull) && Objects.equals(batchSize, that.batchSize) && Objects.equals(memoryLimit, that.memoryLimit) && returnType == that.returnType; + return Objects.equals(queryString, that.queryString) && Objects.equals(collapsePositions, + that.collapsePositions) && Objects.equals(keepNull, that.keepNull) && Objects.equals(batchSize, + that.batchSize) && Objects.equals(memoryLimit, that.memoryLimit) && returnType == that.returnType; } @Override diff --git a/src/main/java/com/arangodb/entity/arangosearch/analyzer/CollationAnalyzerProperties.java b/src/main/java/com/arangodb/entity/arangosearch/analyzer/CollationAnalyzerProperties.java index bbfb0581b..0e21c4029 100644 --- a/src/main/java/com/arangodb/entity/arangosearch/analyzer/CollationAnalyzerProperties.java +++ b/src/main/java/com/arangodb/entity/arangosearch/analyzer/CollationAnalyzerProperties.java @@ -35,7 +35,8 @@ public final class CollationAnalyzerProperties { * @return a locale in the format `language[_COUNTRY][.encoding][@variant]` (square brackets denote optional parts), * e.g. `de.utf-8` or `en_US.utf-8`. Only UTF-8 encoding is meaningful in ArangoDB. * The locale is forwarded to ICU without checks. An invalid locale does not prevent the creation of the Analyzer. - * @see Supported Languages + * @see + * Supported Languages */ public String getLocale() { return locale; diff --git a/src/main/java/com/arangodb/entity/arangosearch/analyzer/DelimiterAnalyzer.java b/src/main/java/com/arangodb/entity/arangosearch/analyzer/DelimiterAnalyzer.java index eae42ae48..ccfcee9de 100644 --- a/src/main/java/com/arangodb/entity/arangosearch/analyzer/DelimiterAnalyzer.java +++ b/src/main/java/com/arangodb/entity/arangosearch/analyzer/DelimiterAnalyzer.java @@ -26,7 +26,8 @@ import java.util.Objects; /** - * An Analyzer capable of breaking up delimited text into tokens as per RFC 4180 (without starting new records on newlines). + * An Analyzer capable of breaking up delimited text into tokens as per RFC 4180 (without starting new records on + * newlines). * * @author Michele Rastelli * @see API Documentation diff --git a/src/main/java/com/arangodb/entity/arangosearch/analyzer/NormAnalyzerProperties.java b/src/main/java/com/arangodb/entity/arangosearch/analyzer/NormAnalyzerProperties.java index 17b3df2d3..5fcfa23ca 100644 --- a/src/main/java/com/arangodb/entity/arangosearch/analyzer/NormAnalyzerProperties.java +++ b/src/main/java/com/arangodb/entity/arangosearch/analyzer/NormAnalyzerProperties.java @@ -40,7 +40,8 @@ public final class NormAnalyzerProperties { /** * @return a locale in the format `language[_COUNTRY][.encoding][@variant]` (square brackets denote optional parts), * e.g. `de.utf-8` or `en_US.utf-8`. Only UTF-8 encoding is meaningful in ArangoDB. - * @see Supported Languages + * @see + * Supported Languages */ public String getLocale() { return locale; diff --git a/src/main/java/com/arangodb/entity/arangosearch/analyzer/PipelineAnalyzer.java b/src/main/java/com/arangodb/entity/arangosearch/analyzer/PipelineAnalyzer.java index d80efe8ef..d61b6cda8 100644 --- a/src/main/java/com/arangodb/entity/arangosearch/analyzer/PipelineAnalyzer.java +++ b/src/main/java/com/arangodb/entity/arangosearch/analyzer/PipelineAnalyzer.java @@ -29,7 +29,8 @@ * An Analyzer capable of chaining effects of multiple Analyzers into one. The pipeline is a list of Analyzers, where * the output of an Analyzer is passed to the next for further processing. *

    - * LIMITATIONS: Analyzers of types {@link GeoPointAnalyzer} and {@link GeoJSONAnalyzer} cannot be used in pipelines and + * LIMITATIONS: Analyzers of types {@link GeoPointAnalyzer} and {@link GeoJSONAnalyzer} cannot be used in + * pipelines and * will make the creation fail. *

    * diff --git a/src/main/java/com/arangodb/entity/arangosearch/analyzer/StemAnalyzerProperties.java b/src/main/java/com/arangodb/entity/arangosearch/analyzer/StemAnalyzerProperties.java index 600ffa5a1..9057c3c21 100644 --- a/src/main/java/com/arangodb/entity/arangosearch/analyzer/StemAnalyzerProperties.java +++ b/src/main/java/com/arangodb/entity/arangosearch/analyzer/StemAnalyzerProperties.java @@ -33,7 +33,8 @@ public final class StemAnalyzerProperties { /** * @return a locale in the format `language[_COUNTRY][.encoding][@variant]` (square brackets denote optional parts), * e.g. `de.utf-8` or `en_US.utf-8`. Only UTF-8 encoding is meaningful in ArangoDB. - * @see Supported Languages + * @see + * Supported Languages */ public String getLocale() { return locale; diff --git a/src/main/java/com/arangodb/entity/arangosearch/analyzer/TextAnalyzerProperties.java b/src/main/java/com/arangodb/entity/arangosearch/analyzer/TextAnalyzerProperties.java index 6ea4667e8..acba41525 100644 --- a/src/main/java/com/arangodb/entity/arangosearch/analyzer/TextAnalyzerProperties.java +++ b/src/main/java/com/arangodb/entity/arangosearch/analyzer/TextAnalyzerProperties.java @@ -48,7 +48,8 @@ public TextAnalyzerProperties() { /** * @return a locale in the format `language[_COUNTRY][.encoding][@variant]` (square brackets denote optional parts), * e.g. `de.utf-8` or `en_US.utf-8`. Only UTF-8 encoding is meaningful in ArangoDB. - * @see Supported Languages + * @see + * Supported Languages */ public String getLocale() { return locale; @@ -124,13 +125,15 @@ public void setStopwords(List stopwords) { } /** - * @return path with a language sub-directory (e.g. en for a locale en_US.utf-8) containing files with words to omit. + * @return path with a language sub-directory (e.g. en for a locale en_US.utf-8) containing files with words to + * omit. * Each word has to be on a separate line. Everything after the first whitespace character on a line will be ignored * and can be used for comments. The files can be named arbitrarily and have any file extension (or none). *

    * Default: if no path is provided then the value of the environment variable IRESEARCH_TEXT_STOPWORD_PATH is used * to determine the path, or if it is undefined then the current working directory is assumed. If the stopwords - * attribute is provided then no stop-words are loaded from files, unless an explicit stopwordsPath is also provided. + * attribute is provided then no stop-words are loaded from files, unless an explicit stopwordsPath is also + * provided. *

    * Note that if the stopwordsPath can not be accessed, is missing language sub-directories or has no files for a * language required by an Analyzer, then the creation of a new Analyzer is refused. If such an issue is discovered diff --git a/src/main/java/com/arangodb/internal/ArangoCollectionImpl.java b/src/main/java/com/arangodb/internal/ArangoCollectionImpl.java index dd2428f27..9c211d35d 100644 --- a/src/main/java/com/arangodb/internal/ArangoCollectionImpl.java +++ b/src/main/java/com/arangodb/internal/ArangoCollectionImpl.java @@ -58,7 +58,8 @@ public DocumentCreateEntity insertDocument(final T value, final DocumentC } @Override - public DocumentCreateEntity insertDocument(final T value, final DocumentCreateOptions options, final Class type) { + public DocumentCreateEntity insertDocument(final T value, final DocumentCreateOptions options, + final Class type) { return executor.execute(insertDocumentRequest(value, options), constructParametricType(DocumentCreateEntity.class, type)); } @@ -66,7 +67,8 @@ public DocumentCreateEntity insertDocument(final T value, final DocumentC @Override public MultiDocumentEntity> insertDocuments(final Collection values) { return executor - .execute(insertDocumentsRequest(values, new DocumentCreateOptions()), insertDocumentsResponseDeserializer(Void.class)); + .execute(insertDocumentsRequest(values, new DocumentCreateOptions()), + insertDocumentsResponseDeserializer(Void.class)); } @Override @@ -77,7 +79,9 @@ public MultiDocumentEntity> insertDocuments( } @Override - public MultiDocumentEntity> insertDocuments(Collection values, DocumentCreateOptions options, Class type) { + public MultiDocumentEntity> insertDocuments(Collection values, + DocumentCreateOptions options, + Class type) { return executor .execute(insertDocumentsRequest(values, options), insertDocumentsResponseDeserializer(type)); } @@ -155,14 +159,16 @@ public DocumentUpdateEntity replaceDocument( } @Override - public DocumentUpdateEntity replaceDocument(String key, T value, DocumentReplaceOptions options, Class type) { + public DocumentUpdateEntity replaceDocument(String key, T value, DocumentReplaceOptions options, + Class type) { return executor.execute(replaceDocumentRequest(key, value, options), constructParametricType(DocumentUpdateEntity.class, type)); } @Override public MultiDocumentEntity> replaceDocuments(final Collection values) { - return executor.execute(replaceDocumentsRequest(values, new DocumentReplaceOptions()), replaceDocumentsResponseDeserializer(Void.class)); + return executor.execute(replaceDocumentsRequest(values, new DocumentReplaceOptions()), + replaceDocumentsResponseDeserializer(Void.class)); } @Override @@ -173,7 +179,9 @@ public MultiDocumentEntity> replaceDocuments( } @Override - public MultiDocumentEntity> replaceDocuments(Collection values, DocumentReplaceOptions options, Class type) { + public MultiDocumentEntity> replaceDocuments(Collection values, + DocumentReplaceOptions options, + Class type) { return executor.execute(replaceDocumentsRequest(values, options), replaceDocumentsResponseDeserializer(type)); } diff --git a/src/main/java/com/arangodb/internal/ArangoDBImpl.java b/src/main/java/com/arangodb/internal/ArangoDBImpl.java index 876da7493..f9a938cea 100644 --- a/src/main/java/com/arangodb/internal/ArangoDBImpl.java +++ b/src/main/java/com/arangodb/internal/ArangoDBImpl.java @@ -58,7 +58,8 @@ public class ArangoDBImpl extends InternalArangoDB implement public ArangoDBImpl(final VstCommunicationSync.Builder vstBuilder, final HttpCommunication.Builder httpBuilder, final InternalSerde util, final Protocol protocol, final HostResolver hostResolver, - final HostHandler hostHandler, final ArangoContext context, int responseQueueTimeSamples, final int timeoutMs) { + final HostHandler hostHandler, final ArangoContext context, int responseQueueTimeSamples, + final int timeoutMs) { super(new ArangoExecutorSync( createProtocol(vstBuilder, httpBuilder, util, protocol), diff --git a/src/main/java/com/arangodb/internal/ArangoDatabaseImpl.java b/src/main/java/com/arangodb/internal/ArangoDatabaseImpl.java index 9aad69fad..274dcc4bf 100644 --- a/src/main/java/com/arangodb/internal/ArangoDatabaseImpl.java +++ b/src/main/java/com/arangodb/internal/ArangoDatabaseImpl.java @@ -162,7 +162,8 @@ public Permissions getPermissions(final String user) { @Override public ArangoCursor query( - final String query, final Map bindVars, final AqlQueryOptions options, final Class type) { + final String query, final Map bindVars, final AqlQueryOptions options, + final Class type) { final Request request = queryRequest(query, bindVars, options); final HostHandle hostHandle = new HostHandle(); diff --git a/src/main/java/com/arangodb/internal/ArangoDefaults.java b/src/main/java/com/arangodb/internal/ArangoDefaults.java index c86675a52..f9351b827 100644 --- a/src/main/java/com/arangodb/internal/ArangoDefaults.java +++ b/src/main/java/com/arangodb/internal/ArangoDefaults.java @@ -46,6 +46,7 @@ public final class ArangoDefaults { public static final int DEFAULT_ACQUIRE_HOST_LIST_INTERVAL = 60 * 60 * 1000; // hour public static final LoadBalancingStrategy DEFAULT_LOAD_BALANCING_STRATEGY = LoadBalancingStrategy.NONE; public static final int DEFAULT_RESPONSE_QUEUE_TIME_SAMPLES = 10; + private ArangoDefaults() { super(); } diff --git a/src/main/java/com/arangodb/internal/ArangoEdgeCollectionImpl.java b/src/main/java/com/arangodb/internal/ArangoEdgeCollectionImpl.java index ebf39627b..4793c45e9 100644 --- a/src/main/java/com/arangodb/internal/ArangoEdgeCollectionImpl.java +++ b/src/main/java/com/arangodb/internal/ArangoEdgeCollectionImpl.java @@ -55,7 +55,8 @@ public EdgeEntity insertEdge(final Object value, final EdgeCreateOptions options @Override public T getEdge(final String key, final Class type) { try { - return executor.execute(getEdgeRequest(key, new GraphDocumentReadOptions()), getEdgeResponseDeserializer(type)); + return executor.execute(getEdgeRequest(key, new GraphDocumentReadOptions()), + getEdgeResponseDeserializer(type)); } catch (final ArangoDBException e) { if (LOGGER.isDebugEnabled()) { LOGGER.debug(e.getMessage(), e); diff --git a/src/main/java/com/arangodb/internal/ArangoErrors.java b/src/main/java/com/arangodb/internal/ArangoErrors.java index 442fa3aab..70a07f1bf 100644 --- a/src/main/java/com/arangodb/internal/ArangoErrors.java +++ b/src/main/java/com/arangodb/internal/ArangoErrors.java @@ -29,6 +29,7 @@ public final class ArangoErrors { public static final Integer ERROR_ARANGO_DATABASE_NOT_FOUND = 1228; public static final Integer ERROR_GRAPH_NOT_FOUND = 1924; public static final Integer QUEUE_TIME_VIOLATED = 21004; + private ArangoErrors() { super(); } diff --git a/src/main/java/com/arangodb/internal/ArangoExecutor.java b/src/main/java/com/arangodb/internal/ArangoExecutor.java index fede702f5..711308012 100644 --- a/src/main/java/com/arangodb/internal/ArangoExecutor.java +++ b/src/main/java/com/arangodb/internal/ArangoExecutor.java @@ -35,6 +35,7 @@ public abstract class ArangoExecutor { private final QueueTimeMetricsImpl qtMetrics; private final InternalSerde serde; private final String timeoutS; + protected ArangoExecutor(final InternalSerde serde, final QueueTimeMetricsImpl qtMetrics, final int timeoutMs) { super(); this.qtMetrics = qtMetrics; diff --git a/src/main/java/com/arangodb/internal/ArangoRequestParam.java b/src/main/java/com/arangodb/internal/ArangoRequestParam.java index cd016ccc5..7db9e599b 100644 --- a/src/main/java/com/arangodb/internal/ArangoRequestParam.java +++ b/src/main/java/com/arangodb/internal/ArangoRequestParam.java @@ -31,6 +31,7 @@ public final class ArangoRequestParam { public static final String IF_NONE_MATCH = "If-None-Match"; public static final String IF_MATCH = "If-Match"; public static final String KEEP_NULL = "keepNull"; + private ArangoRequestParam() { super(); } diff --git a/src/main/java/com/arangodb/internal/ArangoResponseField.java b/src/main/java/com/arangodb/internal/ArangoResponseField.java index df2a49a1e..0388977dc 100644 --- a/src/main/java/com/arangodb/internal/ArangoResponseField.java +++ b/src/main/java/com/arangodb/internal/ArangoResponseField.java @@ -27,6 +27,7 @@ public final class ArangoResponseField { public static final String ERROR_FIELD_NAME = "error"; public static final String RESULT_JSON_POINTER = "/result"; + private ArangoResponseField() { super(); } diff --git a/src/main/java/com/arangodb/internal/DocumentFields.java b/src/main/java/com/arangodb/internal/DocumentFields.java index c69d989fe..f2b20e375 100644 --- a/src/main/java/com/arangodb/internal/DocumentFields.java +++ b/src/main/java/com/arangodb/internal/DocumentFields.java @@ -10,6 +10,7 @@ public final class DocumentFields { public static final String REV = "_rev"; public static final String FROM = "_from"; public static final String TO = "_to"; + private DocumentFields() { } diff --git a/src/main/java/com/arangodb/internal/InternalArangoCollection.java b/src/main/java/com/arangodb/internal/InternalArangoCollection.java index df71fc06c..58061cc0e 100644 --- a/src/main/java/com/arangodb/internal/InternalArangoCollection.java +++ b/src/main/java/com/arangodb/internal/InternalArangoCollection.java @@ -43,7 +43,8 @@ * @author Mark Vollmary * @author Michele Rastelli */ -public abstract class InternalArangoCollection, D extends InternalArangoDatabase, E extends ArangoExecutor> +public abstract class InternalArangoCollection, D extends InternalArangoDatabase, + E extends ArangoExecutor> extends ArangoExecuteable { protected static final String PATH_API_COLLECTION = "/_api/collection"; @@ -89,7 +90,8 @@ protected Request insertDocumentRequest(final T value, final DocumentCreateO request.putQueryParam(RETURN_NEW, params.getReturnNew()); request.putQueryParam(RETURN_OLD, params.getReturnOld()); request.putQueryParam(SILENT, params.getSilent()); - request.putQueryParam(OVERWRITE_MODE, params.getOverwriteMode() != null ? params.getOverwriteMode().getValue() : null); + request.putQueryParam(OVERWRITE_MODE, params.getOverwriteMode() != null ? + params.getOverwriteMode().getValue() : null); request.putQueryParam(MERGE_OBJECTS, params.getMergeObjects()); request.putQueryParam(KEEP_NULL, params.getKeepNull()); request.putHeaderParam(TRANSACTION_ID, params.getStreamTransactionId()); @@ -103,7 +105,8 @@ protected Request insertDocumentsRequest(final Collection values, final D request.putQueryParam(RETURN_NEW, params.getReturnNew()); request.putQueryParam(RETURN_OLD, params.getReturnOld()); request.putQueryParam(SILENT, params.getSilent()); - request.putQueryParam(OVERWRITE_MODE, params.getOverwriteMode() != null ? params.getOverwriteMode().getValue() : null); + request.putQueryParam(OVERWRITE_MODE, params.getOverwriteMode() != null ? + params.getOverwriteMode().getValue() : null); request.putQueryParam(MERGE_OBJECTS, params.getMergeObjects()); request.putQueryParam(KEEP_NULL, params.getKeepNull()); request.putHeaderParam(TRANSACTION_ID, params.getStreamTransactionId()); @@ -430,7 +433,8 @@ protected Request createSkiplistIndexRequest(final Iterable fields, fina final Request request = request(db.dbName(), RequestType.POST, PATH_API_INDEX); request.putQueryParam(COLLECTION, name); request.setBody( - getSerde().serialize(OptionsBuilder.build(options != null ? options : new SkiplistIndexOptions(), fields))); + getSerde().serialize(OptionsBuilder.build(options != null ? options : new SkiplistIndexOptions(), + fields))); return request; } @@ -455,7 +459,8 @@ protected Request createFulltextIndexRequest(final Iterable fields, fina final Request request = request(db.dbName(), RequestType.POST, PATH_API_INDEX); request.putQueryParam(COLLECTION, name); request.setBody( - getSerde().serialize(OptionsBuilder.build(options != null ? options : new FulltextIndexOptions(), fields))); + getSerde().serialize(OptionsBuilder.build(options != null ? options : new FulltextIndexOptions(), + fields))); return request; } @@ -537,7 +542,8 @@ protected Request getRevisionRequest() { protected Request grantAccessRequest(final String user, final Permissions permissions) { return request(DbName.SYSTEM, RequestType.PUT, PATH_API_USER, user, ArangoRequestParam.DATABASE, - db.dbName().get(), name).setBody(getSerde().serialize(OptionsBuilder.build(new UserAccessOptions(), permissions))); + db.dbName().get(), name).setBody(getSerde().serialize(OptionsBuilder.build(new UserAccessOptions(), + permissions))); } protected Request resetAccessRequest(final String user) { @@ -551,7 +557,8 @@ protected Request getPermissionsRequest(final String user) { } protected ResponseDeserializer getPermissionsResponseDeserialzer() { - return response -> getSerde().deserialize(response.getBody(), ArangoResponseField.RESULT_JSON_POINTER, Permissions.class); + return response -> getSerde().deserialize(response.getBody(), ArangoResponseField.RESULT_JSON_POINTER, + Permissions.class); } protected Class getCollectionContentClass(Collection c) { diff --git a/src/main/java/com/arangodb/internal/InternalArangoDB.java b/src/main/java/com/arangodb/internal/InternalArangoDB.java index afb2088ab..22b2b8e6d 100644 --- a/src/main/java/com/arangodb/internal/InternalArangoDB.java +++ b/src/main/java/com/arangodb/internal/InternalArangoDB.java @@ -79,7 +79,8 @@ protected Request createDatabaseRequest(final DBCreateOptions options) { } protected ResponseDeserializer createDatabaseResponseDeserializer() { - return response -> getSerde().deserialize(response.getBody(), ArangoResponseField.RESULT_JSON_POINTER, Boolean.class); + return response -> getSerde().deserialize(response.getBody(), ArangoResponseField.RESULT_JSON_POINTER, + Boolean.class); } protected Request getDatabasesRequest(final DbName dbName) { @@ -97,7 +98,8 @@ protected Request getAccessibleDatabasesForRequest(final DbName dbName, final St protected ResponseDeserializer> getAccessibleDatabasesForResponseDeserializer() { return response -> { - Iterator names = getSerde().parse(response.getBody(), ArangoResponseField.RESULT_JSON_POINTER).fieldNames(); + Iterator names = + getSerde().parse(response.getBody(), ArangoResponseField.RESULT_JSON_POINTER).fieldNames(); final Collection dbs = new ArrayList<>(); while (names.hasNext()) { dbs.add(names.next()); @@ -114,7 +116,8 @@ protected Request createUserRequest( final Request request; request = request(dbName, RequestType.POST, PATH_API_USER); request.setBody( - getSerde().serialize(OptionsBuilder.build(options != null ? options : new UserCreateOptions(), user, passwd))); + getSerde().serialize(OptionsBuilder.build(options != null ? options : new UserCreateOptions(), user, + passwd))); return request; } diff --git a/src/main/java/com/arangodb/internal/InternalArangoDBBuilder.java b/src/main/java/com/arangodb/internal/InternalArangoDBBuilder.java index 2e9402386..63ba8e603 100644 --- a/src/main/java/com/arangodb/internal/InternalArangoDBBuilder.java +++ b/src/main/java/com/arangodb/internal/InternalArangoDBBuilder.java @@ -118,7 +118,8 @@ private static String loadHost(final Properties properties, final String current final String host = getProperty(properties, PROPERTY_KEY_HOST, currentValue, ArangoDefaults.DEFAULT_HOST); if (host.contains(":")) { throw new ArangoDBException(String.format( - "Could not load property-value arangodb.host=%s. Expect only ip. Do you mean arangodb.hosts=ip:port ?", + "Could not load property-value arangodb.host=%s. Expect only ip. Do you mean arangodb" + + ".hosts=ip:port ?", host)); } return host; @@ -353,11 +354,13 @@ protected HostHandler createHostHandler(final HostResolver hostResolver) { return new DirtyReadHostHandler(hostHandler, new RoundRobinHostHandler(hostResolver)); } - protected HostResolver createHostResolver(final Collection hosts, final int maxConnections, final ConnectionFactory connectionFactory) { + protected HostResolver createHostResolver(final Collection hosts, final int maxConnections, + final ConnectionFactory connectionFactory) { if (acquireHostList != null && acquireHostList) { LOG.debug("acquireHostList -> Use ExtendedHostResolver"); - return new ExtendedHostResolver(new ArrayList<>(hosts), maxConnections, connectionFactory, acquireHostListInterval); + return new ExtendedHostResolver(new ArrayList<>(hosts), maxConnections, connectionFactory, + acquireHostListInterval); } else { LOG.debug("Use SimpleHostResolver"); return new SimpleHostResolver(new ArrayList<>(hosts)); diff --git a/src/main/java/com/arangodb/internal/InternalArangoDatabase.java b/src/main/java/com/arangodb/internal/InternalArangoDatabase.java index df2ddc951..760264c77 100644 --- a/src/main/java/com/arangodb/internal/InternalArangoDatabase.java +++ b/src/main/java/com/arangodb/internal/InternalArangoDatabase.java @@ -97,7 +97,8 @@ protected Request getEngineRequest() { protected Request createCollectionRequest(final String name, final CollectionCreateOptions options) { - byte[] body = getSerde().serialize(OptionsBuilder.build(options != null ? options : new CollectionCreateOptions(), name)); + byte[] body = getSerde().serialize(OptionsBuilder.build(options != null ? options : + new CollectionCreateOptions(), name)); return request(dbName, RequestType.POST, InternalArangoCollection.PATH_API_COLLECTION).setBody(body); } @@ -120,19 +121,23 @@ protected Request dropRequest() { } protected ResponseDeserializer createDropResponseDeserializer() { - return response -> getSerde().deserialize(response.getBody(), ArangoResponseField.RESULT_JSON_POINTER, Boolean.class); + return response -> getSerde().deserialize(response.getBody(), ArangoResponseField.RESULT_JSON_POINTER, + Boolean.class); } protected Request grantAccessRequest(final String user, final Permissions permissions) { - return request(DbName.SYSTEM, RequestType.PUT, PATH_API_USER, user, ArangoRequestParam.DATABASE, dbName.get()).setBody(getSerde().serialize(OptionsBuilder.build(new UserAccessOptions(), permissions))); + return request(DbName.SYSTEM, RequestType.PUT, PATH_API_USER, user, ArangoRequestParam.DATABASE, + dbName.get()).setBody(getSerde().serialize(OptionsBuilder.build(new UserAccessOptions(), permissions))); } protected Request resetAccessRequest(final String user) { - return request(DbName.SYSTEM, RequestType.DELETE, PATH_API_USER, user, ArangoRequestParam.DATABASE, dbName.get()); + return request(DbName.SYSTEM, RequestType.DELETE, PATH_API_USER, user, ArangoRequestParam.DATABASE, + dbName.get()); } protected Request updateUserDefaultCollectionAccessRequest(final String user, final Permissions permissions) { - return request(DbName.SYSTEM, RequestType.PUT, PATH_API_USER, user, ArangoRequestParam.DATABASE, dbName.get(), "*").setBody(getSerde().serialize(OptionsBuilder.build(new UserAccessOptions(), permissions))); + return request(DbName.SYSTEM, RequestType.PUT, PATH_API_USER, user, ArangoRequestParam.DATABASE, dbName.get() + , "*").setBody(getSerde().serialize(OptionsBuilder.build(new UserAccessOptions(), permissions))); } protected Request getPermissionsRequest(final String user) { @@ -140,10 +145,12 @@ protected Request getPermissionsRequest(final String user) { } protected ResponseDeserializer getPermissionsResponseDeserialzer() { - return response -> getSerde().deserialize(response.getBody(), ArangoResponseField.RESULT_JSON_POINTER, Permissions.class); + return response -> getSerde().deserialize(response.getBody(), ArangoResponseField.RESULT_JSON_POINTER, + Permissions.class); } - protected Request queryRequest(final String query, final Map bindVars, final AqlQueryOptions options) { + protected Request queryRequest(final String query, final Map bindVars, + final AqlQueryOptions options) { final AqlQueryOptions opt = options != null ? options : new AqlQueryOptions(); final Request request = request(dbName, RequestType.POST, PATH_API_CURSOR) .setBody(getSerde().serialize(OptionsBuilder.build(opt, query, bindVars))); @@ -188,7 +195,8 @@ protected Request queryCloseRequest(final String id, final AqlQueryOptions optio return request; } - protected Request explainQueryRequest(final String query, final Map bindVars, final AqlQueryExplainOptions options) { + protected Request explainQueryRequest(final String query, final Map bindVars, + final AqlQueryExplainOptions options) { final AqlQueryExplainOptions opt = options != null ? options : new AqlQueryExplainOptions(); return request(dbName, RequestType.POST, PATH_API_EXPLAIN) .setBody(getSerde().serialize(OptionsBuilder.build(opt, query, bindVars))); @@ -234,7 +242,8 @@ protected Request killQueryRequest(final String id) { return request(dbName, RequestType.DELETE, PATH_API_QUERY, id); } - protected Request createAqlFunctionRequest(final String name, final String code, final AqlFunctionCreateOptions options) { + protected Request createAqlFunctionRequest(final String name, final String code, + final AqlFunctionCreateOptions options) { return request(dbName, RequestType.POST, PATH_API_AQLFUNCTION).setBody(getSerde().serialize(OptionsBuilder.build(options != null ? options : new AqlFunctionCreateOptions(), name, code))); } @@ -261,7 +270,8 @@ protected ResponseDeserializer> getAqlFunctionsRes constructListType(AqlFunctionEntity.class)); } - protected Request createGraphRequest(final String name, final Collection edgeDefinitions, final GraphCreateOptions options) { + protected Request createGraphRequest(final String name, final Collection edgeDefinitions, + final GraphCreateOptions options) { return request(dbName, RequestType.POST, InternalArangoGraph.PATH_API_GHARIAL).setBody(getSerde().serialize(OptionsBuilder.build(options != null ? options : new GraphCreateOptions(), name, edgeDefinitions))); } @@ -315,7 +325,8 @@ protected Request commitStreamTransactionRequest(String id) { } protected ResponseDeserializer streamTransactionResponseDeserializer() { - return response -> getSerde().deserialize(response.getBody(), ArangoResponseField.RESULT_JSON_POINTER, StreamTransactionEntity.class); + return response -> getSerde().deserialize(response.getBody(), ArangoResponseField.RESULT_JSON_POINTER, + StreamTransactionEntity.class); } protected Request getInfoRequest() { @@ -323,7 +334,8 @@ protected Request getInfoRequest() { } protected ResponseDeserializer getInfoResponseDeserializer() { - return response -> getSerde().deserialize(response.getBody(), ArangoResponseField.RESULT_JSON_POINTER, DatabaseEntity.class); + return response -> getSerde().deserialize(response.getBody(), ArangoResponseField.RESULT_JSON_POINTER, + DatabaseEntity.class); } protected Request reloadRoutingRequest() { diff --git a/src/main/java/com/arangodb/internal/InternalArangoEdgeCollection.java b/src/main/java/com/arangodb/internal/InternalArangoEdgeCollection.java index 2d1b60942..198f2dec0 100644 --- a/src/main/java/com/arangodb/internal/InternalArangoEdgeCollection.java +++ b/src/main/java/com/arangodb/internal/InternalArangoEdgeCollection.java @@ -32,7 +32,8 @@ /** * @author Mark Vollmary */ -public abstract class InternalArangoEdgeCollection, D extends InternalArangoDatabase, G extends InternalArangoGraph, E extends ArangoExecutor> +public abstract class InternalArangoEdgeCollection, D extends InternalArangoDatabase, G extends InternalArangoGraph, E extends ArangoExecutor> extends ArangoExecuteable { private static final String PATH_API_GHARIAL = "/_api/gharial"; diff --git a/src/main/java/com/arangodb/internal/InternalArangoGraph.java b/src/main/java/com/arangodb/internal/InternalArangoGraph.java index f5d437d6f..5d09a22ba 100644 --- a/src/main/java/com/arangodb/internal/InternalArangoGraph.java +++ b/src/main/java/com/arangodb/internal/InternalArangoGraph.java @@ -35,7 +35,8 @@ /** * @author Mark Vollmary */ -public abstract class InternalArangoGraph, D extends InternalArangoDatabase, E extends ArangoExecutor> +public abstract class InternalArangoGraph, D extends InternalArangoDatabase, + E extends ArangoExecutor> extends ArangoExecuteable { protected static final String PATH_API_GHARIAL = "/_api/gharial"; diff --git a/src/main/java/com/arangodb/internal/InternalArangoRoute.java b/src/main/java/com/arangodb/internal/InternalArangoRoute.java index 7e0f11949..23ba43f01 100644 --- a/src/main/java/com/arangodb/internal/InternalArangoRoute.java +++ b/src/main/java/com/arangodb/internal/InternalArangoRoute.java @@ -30,7 +30,8 @@ /** * @author Mark Vollmary */ -public abstract class InternalArangoRoute, D extends InternalArangoDatabase, E extends ArangoExecutor> +public abstract class InternalArangoRoute, D extends InternalArangoDatabase, + E extends ArangoExecutor> extends ArangoExecuteable { protected final D db; diff --git a/src/main/java/com/arangodb/internal/InternalArangoSearch.java b/src/main/java/com/arangodb/internal/InternalArangoSearch.java index cb836c9de..6934584f3 100644 --- a/src/main/java/com/arangodb/internal/InternalArangoSearch.java +++ b/src/main/java/com/arangodb/internal/InternalArangoSearch.java @@ -27,7 +27,8 @@ /** * @author Mark Vollmary */ -public class InternalArangoSearch, D extends InternalArangoDatabase, E extends ArangoExecutor> +public class InternalArangoSearch, D extends InternalArangoDatabase, + E extends ArangoExecutor> extends InternalArangoView { protected InternalArangoSearch(final D db, final String name) { diff --git a/src/main/java/com/arangodb/internal/InternalArangoVertexCollection.java b/src/main/java/com/arangodb/internal/InternalArangoVertexCollection.java index 25c7b0f32..142601448 100644 --- a/src/main/java/com/arangodb/internal/InternalArangoVertexCollection.java +++ b/src/main/java/com/arangodb/internal/InternalArangoVertexCollection.java @@ -32,7 +32,8 @@ /** * @author Mark Vollmary */ -public abstract class InternalArangoVertexCollection, D extends InternalArangoDatabase, G extends InternalArangoGraph, E extends ArangoExecutor> +public abstract class InternalArangoVertexCollection, + D extends InternalArangoDatabase, G extends InternalArangoGraph, E extends ArangoExecutor> extends ArangoExecuteable { private static final String PATH_API_GHARIAL = "/_api/gharial"; @@ -124,7 +125,8 @@ protected ResponseDeserializer updateVertexResponseDeser } protected Request deleteVertexRequest(final String key, final VertexDeleteOptions options) { - final Request request = request(graph.db().dbName(), RequestType.DELETE, PATH_API_GHARIAL, graph.name(), "vertex", + final Request request = request(graph.db().dbName(), RequestType.DELETE, PATH_API_GHARIAL, graph.name(), + "vertex", DocumentUtil.createDocumentHandle(name, key)); final VertexDeleteOptions params = (options != null ? options : new VertexDeleteOptions()); request.putHeaderParam(TRANSACTION_ID, params.getStreamTransactionId()); diff --git a/src/main/java/com/arangodb/internal/InternalArangoView.java b/src/main/java/com/arangodb/internal/InternalArangoView.java index fde7cfa64..e0b3ba089 100644 --- a/src/main/java/com/arangodb/internal/InternalArangoView.java +++ b/src/main/java/com/arangodb/internal/InternalArangoView.java @@ -29,7 +29,8 @@ * @author Mark Vollmary * @author Michele Rastelli */ -public abstract class InternalArangoView, D extends InternalArangoDatabase, E extends ArangoExecutor> +public abstract class InternalArangoView, D extends InternalArangoDatabase, + E extends ArangoExecutor> extends ArangoExecuteable { protected static final String PATH_API_VIEW = "/_api/view"; diff --git a/src/main/java/com/arangodb/internal/http/HttpConnection.java b/src/main/java/com/arangodb/internal/http/HttpConnection.java index 3a9ebbf18..69dbb4dd4 100644 --- a/src/main/java/com/arangodb/internal/http/HttpConnection.java +++ b/src/main/java/com/arangodb/internal/http/HttpConnection.java @@ -86,9 +86,12 @@ public class HttpConnection implements Connection { private final Protocol contentType; private final HostDescription host; private volatile String jwt = null; + private HttpConnection(final HostDescription host, final Integer timeout, final String user, final String password, - final Boolean useSsl, final SSLContext sslContext, final HostnameVerifier hostnameVerifier, final InternalSerde util, final Protocol contentType, - final Long ttl, final String httpCookieSpec, final HttpRequestRetryHandler httpRequestRetryHandler) { + final Boolean useSsl, final SSLContext sslContext, final HostnameVerifier hostnameVerifier + , final InternalSerde util, final Protocol contentType, + final Long ttl, final String httpCookieSpec, + final HttpRequestRetryHandler httpRequestRetryHandler) { super(); this.host = host; this.user = user; @@ -101,7 +104,8 @@ private HttpConnection(final HostDescription host, final Integer timeout, final if (Boolean.TRUE.equals(useSsl)) { registryBuilder.register("https", new SSLConnectionSocketFactory( sslContext != null ? sslContext : SSLContexts.createSystemDefault(), - hostnameVerifier != null ? hostnameVerifier : SSLConnectionSocketFactory.getDefaultHostnameVerifier() + hostnameVerifier != null ? hostnameVerifier : + SSLConnectionSocketFactory.getDefaultHostnameVerifier() )); } else { registryBuilder.register("http", new PlainConnectionSocketFactory()); @@ -120,10 +124,12 @@ private HttpConnection(final HostDescription host, final Integer timeout, final requestConfig.setCookieSpec(httpCookieSpec); } - final ConnectionKeepAliveStrategy keepAliveStrategy = (response, context) -> HttpConnection.this.getKeepAliveDuration(response); + final ConnectionKeepAliveStrategy keepAliveStrategy = + (response, context) -> HttpConnection.this.getKeepAliveDuration(response); final HttpClientBuilder builder = HttpClientBuilder.create().setDefaultRequestConfig(requestConfig.build()) .setConnectionManager(cm).setKeepAliveStrategy(keepAliveStrategy) - .setRetryHandler(httpRequestRetryHandler != null ? httpRequestRetryHandler : new DefaultHttpRequestRetryHandler()); + .setRetryHandler(httpRequestRetryHandler != null ? httpRequestRetryHandler : + new DefaultHttpRequestRetryHandler()); if (ttl != null) { builder.setConnectionTimeToLive(ttl, TimeUnit.MILLISECONDS); } diff --git a/src/main/java/com/arangodb/internal/net/ExtendedHostResolver.java b/src/main/java/com/arangodb/internal/net/ExtendedHostResolver.java index df3864406..1dc0d11dd 100644 --- a/src/main/java/com/arangodb/internal/net/ExtendedHostResolver.java +++ b/src/main/java/com/arangodb/internal/net/ExtendedHostResolver.java @@ -120,7 +120,8 @@ private Collection resolveFromServer() { response = executor.execute( new Request(DbName.SYSTEM, RequestType.GET, "/_api/cluster/endpoints"), response1 -> { - final List> tmp = arangoSerialization.deserialize(response1.getBody(), "/endpoints", + final List> tmp = arangoSerialization.deserialize(response1.getBody(), + "/endpoints", constructParametricType(List.class, constructParametricType(Map.class, String.class, String.class))); Collection endpoints = new ArrayList<>(); diff --git a/src/main/java/com/arangodb/internal/serde/InternalSerializers.java b/src/main/java/com/arangodb/internal/serde/InternalSerializers.java index f889602fb..8fb0da26a 100644 --- a/src/main/java/com/arangodb/internal/serde/InternalSerializers.java +++ b/src/main/java/com/arangodb/internal/serde/InternalSerializers.java @@ -36,7 +36,8 @@ public void serialize(RawBytes value, JsonGenerator gen, SerializerProvider seri } } }; - static final JsonSerializer AUTHENTICATION_REQUEST = new JsonSerializer() { + static final JsonSerializer AUTHENTICATION_REQUEST = + new JsonSerializer() { @Override public void serialize(AuthenticationRequest value, JsonGenerator gen, SerializerProvider serializers) throws IOException { gen.writeStartArray(); @@ -48,7 +49,8 @@ public void serialize(AuthenticationRequest value, JsonGenerator gen, Serializer gen.writeEndArray(); } }; - static final JsonSerializer JWT_AUTHENTICATION_REQUEST = new JsonSerializer() { + static final JsonSerializer JWT_AUTHENTICATION_REQUEST = + new JsonSerializer() { @Override public void serialize(JwtAuthenticationRequest value, JsonGenerator gen, SerializerProvider serializers) throws IOException { gen.writeStartArray(); diff --git a/src/main/java/com/arangodb/internal/velocystream/VstCommunicationSync.java b/src/main/java/com/arangodb/internal/velocystream/VstCommunicationSync.java index b475f39a2..7a26d0344 100644 --- a/src/main/java/com/arangodb/internal/velocystream/VstCommunicationSync.java +++ b/src/main/java/com/arangodb/internal/velocystream/VstCommunicationSync.java @@ -170,7 +170,8 @@ public Builder connectionTtl(final Long connectionTtl) { } public VstCommunication build(final InternalSerde util) { - return new VstCommunicationSync(hostHandler, timeout, user, password, jwt, useSsl, sslContext, util, chunksize, + return new VstCommunicationSync(hostHandler, timeout, user, password, jwt, useSsl, sslContext, util, + chunksize, maxConnections, connectionTtl); } diff --git a/src/main/java/com/arangodb/internal/velocystream/VstConnectionFactorySync.java b/src/main/java/com/arangodb/internal/velocystream/VstConnectionFactorySync.java index df88bcc25..79f511efe 100644 --- a/src/main/java/com/arangodb/internal/velocystream/VstConnectionFactorySync.java +++ b/src/main/java/com/arangodb/internal/velocystream/VstConnectionFactorySync.java @@ -36,7 +36,8 @@ public class VstConnectionFactorySync implements ConnectionFactory { private final VstConnectionSync.Builder builder; public VstConnectionFactorySync(final HostDescription host, final Integer timeout, final Long connectionTtl, - final Integer keepAliveInterval, final Boolean useSsl, final SSLContext sslContext) { + final Integer keepAliveInterval, final Boolean useSsl, + final SSLContext sslContext) { super(); builder = new VstConnectionSync.Builder().timeout(timeout).ttl(connectionTtl) .keepAliveInterval(keepAliveInterval).useSsl(useSsl) diff --git a/src/main/java/com/arangodb/internal/velocystream/internal/VstConnection.java b/src/main/java/com/arangodb/internal/velocystream/internal/VstConnection.java index e9e52d694..9bb834f09 100644 --- a/src/main/java/com/arangodb/internal/velocystream/internal/VstConnection.java +++ b/src/main/java/com/arangodb/internal/velocystream/internal/VstConnection.java @@ -110,7 +110,8 @@ protected T sendKeepAlive() { long id = keepAliveId.decrementAndGet(); Message message = new Message(id, keepAliveRequest, null); if (LOGGER.isDebugEnabled()) { - LOGGER.debug(String.format("[%s]: Send keepalive probe (id=%s, head=%s, body=%s)", connectionName, message.getId(), message.getHead(), + LOGGER.debug(String.format("[%s]: Send keepalive probe (id=%s, head=%s, body=%s)", connectionName, + message.getId(), message.getHead(), message.getBody() != null ? message.getBody() : "{}")); } return write(message, Collections.singleton(new Chunk( @@ -158,7 +159,8 @@ public synchronized void open() throws IOException { } else { socket = SocketFactory.getDefault().createSocket(); } - socket.connect(new InetSocketAddress(host.getHost(), host.getPort()), timeout != null ? timeout : ArangoDefaults.DEFAULT_TIMEOUT); + socket.connect(new InetSocketAddress(host.getHost(), host.getPort()), timeout != null ? timeout : + ArangoDefaults.DEFAULT_TIMEOUT); socket.setKeepAlive(true); socket.setTcpNoDelay(true); if (LOGGER.isDebugEnabled()) { @@ -254,7 +256,8 @@ protected synchronized void writeIntern(final Message message, final Collection< for (final Chunk chunk : chunks) { try { if (LOGGER.isDebugEnabled()) { - LOGGER.debug(String.format("[%s]: Send chunk %s:%s from message %s", connectionName, chunk.getChunk(), + LOGGER.debug(String.format("[%s]: Send chunk %s:%s from message %s", connectionName, + chunk.getChunk(), chunk.isFirstChunk() ? 1 : 0, chunk.getMessageId())); sendTimestamps.put(chunk.getMessageId(), System.currentTimeMillis()); } @@ -312,7 +315,8 @@ protected Chunk readChunk() throws IOException { final Chunk chunk = new Chunk(messageId, chunkX, messageLength, 0, contentLength); if (LOGGER.isDebugEnabled()) { - LOGGER.debug(String.format("[%s]: Received chunk %s:%s from message %s", connectionName, chunk.getChunk(), chunk.isFirstChunk() ? 1 : 0, chunk.getMessageId())); + LOGGER.debug(String.format("[%s]: Received chunk %s:%s from message %s", connectionName, chunk.getChunk() + , chunk.isFirstChunk() ? 1 : 0, chunk.getMessageId())); LOGGER.debug("[" + connectionName + "]: Responsetime for Message " + chunk.getMessageId() + " is " + (System.currentTimeMillis() - sendTimestamps.get(chunk.getMessageId()))); } diff --git a/src/main/java/com/arangodb/internal/velocystream/internal/VstConnectionSync.java b/src/main/java/com/arangodb/internal/velocystream/internal/VstConnectionSync.java index 95d659b20..ecac6bd33 100644 --- a/src/main/java/com/arangodb/internal/velocystream/internal/VstConnectionSync.java +++ b/src/main/java/com/arangodb/internal/velocystream/internal/VstConnectionSync.java @@ -33,7 +33,8 @@ */ public class VstConnectionSync extends VstConnection { - private VstConnectionSync(final HostDescription host, final Integer timeout, final Long ttl, final Integer keepAliveInterval, + private VstConnectionSync(final HostDescription host, final Integer timeout, final Long ttl, + final Integer keepAliveInterval, final Boolean useSsl, final SSLContext sslContext, final MessageStore messageStore) { super(host, timeout, ttl, keepAliveInterval, useSsl, sslContext, messageStore); } diff --git a/src/main/java/com/arangodb/model/AqlFunctionCreateOptions.java b/src/main/java/com/arangodb/model/AqlFunctionCreateOptions.java index ebd50373e..78f025d1f 100644 --- a/src/main/java/com/arangodb/model/AqlFunctionCreateOptions.java +++ b/src/main/java/com/arangodb/model/AqlFunctionCreateOptions.java @@ -62,8 +62,10 @@ public String getCode() { } /** - * @param isDeterministic an optional boolean value to indicate that the function results are fully deterministic (function - * return value solely depends on the input value and return value is the same for repeated calls with + * @param isDeterministic an optional boolean value to indicate that the function results are fully deterministic + * (function + * return value solely depends on the input value and return value is the same for + * repeated calls with * same input) * @return options */ diff --git a/src/main/java/com/arangodb/model/AqlQueryExplainOptions.java b/src/main/java/com/arangodb/model/AqlQueryExplainOptions.java index ca6513acf..b99aebd92 100644 --- a/src/main/java/com/arangodb/model/AqlQueryExplainOptions.java +++ b/src/main/java/com/arangodb/model/AqlQueryExplainOptions.java @@ -72,7 +72,8 @@ public Integer getMaxNumberOfPlans() { } /** - * @param maxNumberOfPlans an optional maximum number of plans that the optimizer is allowed to generate. Setting this attribute + * @param maxNumberOfPlans an optional maximum number of plans that the optimizer is allowed to generate. Setting + * this attribute * to a low value allows to put a cap on the amount of work the optimizer does. * @return options */ @@ -86,7 +87,8 @@ public Boolean getAllPlans() { } /** - * @param allPlans if set to true, all possible execution plans will be returned. The default is false, meaning only the + * @param allPlans if set to true, all possible execution plans will be returned. The default is false, meaning + * only the * optimal plan will be returned. * @return options */ diff --git a/src/main/java/com/arangodb/model/AqlQueryOptions.java b/src/main/java/com/arangodb/model/AqlQueryOptions.java index 458219c0a..83c78c3dc 100644 --- a/src/main/java/com/arangodb/model/AqlQueryOptions.java +++ b/src/main/java/com/arangodb/model/AqlQueryOptions.java @@ -85,8 +85,10 @@ public Integer getBatchSize() { } /** - * @param batchSize maximum number of result documents to be transferred from the server to the client in one roundtrip. - * If this attribute is not set, a server-controlled default value will be used. A batchSize value of 0 + * @param batchSize maximum number of result documents to be transferred from the server to the client in one + * roundtrip. + * If this attribute is not set, a server-controlled default value will be used. A batchSize + * value of 0 * is disallowed. * @return options */ @@ -100,8 +102,10 @@ public Long getMemoryLimit() { } /** - * @param memoryLimit the maximum number of memory (measured in bytes) that the query is allowed to use. If set, then the - * query will fail with error "resource limit exceeded" in case it allocates too much memory. A value of + * @param memoryLimit the maximum number of memory (measured in bytes) that the query is allowed to use. If set, + * then the + * query will fail with error "resource limit exceeded" in case it allocates too much memory. + * A value of * 0 indicates that there is no memory limit. * @return options * @since ArangoDB 3.1.0 @@ -136,7 +140,8 @@ public Boolean getFillBlockCache() { * usually the desired behavior. The option can be set to false for queries that * are known to either read a lot of data that would thrash the block cache, or for queries * that read data known to be outside of the hot set. By setting the option - * to false, data read by the query will not make it into the RocksDB block cache if + * to false, data read by the query will not make it into the RocksDB block + * cache if * it is not already in there, thus leaving more room for the actual hot set. * @return options * @since ArangoDB 3.8.1 @@ -178,10 +183,14 @@ public Boolean getFailOnWarning() { } /** - * @param failOnWarning When set to true, the query will throw an exception and abort instead of producing a warning. This - * option should be used during development to catch potential issues early. When the attribute is set to - * false, warnings will not be propagated to exceptions and will be returned with the query result. There - * is also a server configuration option --query.fail-on-warning for setting the default value for + * @param failOnWarning When set to true, the query will throw an exception and abort instead of producing a + * warning. This + * option should be used during development to catch potential issues early. When the + * attribute is set to + * false, warnings will not be propagated to exceptions and will be returned with the query + * result. There + * is also a server configuration option --query.fail-on-warning for setting the default + * value for * failOnWarning so it does not need to be set on a per-query level. * @return options */ @@ -209,7 +218,8 @@ public Boolean getProfile() { } /** - * @param profile If set to true, then the additional query profiling information will be returned in the sub-attribute + * @param profile If set to true, then the additional query profiling information will be returned in the + * sub-attribute * profile of the extra return attribute if the query result is not served from the query cache. * @return options */ @@ -237,8 +247,10 @@ public Long getMaxWarningCount() { } /** - * @param maxWarningCount Limits the maximum number of warnings a query will return. The number of warnings a query will return - * is limited to 10 by default, but that number can be increased or decreased by setting this attribute. + * @param maxWarningCount Limits the maximum number of warnings a query will return. The number of warnings a + * query will return + * is limited to 10 by default, but that number can be increased or decreased by setting + * this attribute. * @return options * @since ArangoDB 3.2.0 */ @@ -252,7 +264,8 @@ public Long getIntermediateCommitCount() { } /** - * @param intermediateCommitCount Maximum number of operations after which an intermediate commit is performed automatically. Honored by + * @param intermediateCommitCount Maximum number of operations after which an intermediate commit is performed + * automatically. Honored by * the RocksDB storage engine only. * @return options * @since ArangoDB 3.2.0 @@ -267,7 +280,8 @@ public Long getIntermediateCommitSize() { } /** - * @param intermediateCommitSize Maximum total size of operations after which an intermediate commit is performed automatically. + * @param intermediateCommitSize Maximum total size of operations after which an intermediate commit is performed + * automatically. * Honored by the RocksDB storage engine only. * @return options * @since ArangoDB 3.2.0 @@ -282,8 +296,10 @@ public Double getSatelliteSyncWait() { } /** - * @param satelliteSyncWait This enterprise parameter allows to configure how long a DBServer will have time to bring the - * satellite collections involved in the query into sync. The default value is 60.0 (seconds). When the + * @param satelliteSyncWait This enterprise parameter allows to configure how long a DBServer will have time to + * bring the + * satellite collections involved in the query into sync. The default value is 60.0 + * (seconds). When the * max time has been reached the query will be stopped. * @return options * @since ArangoDB 3.2.0 @@ -298,11 +314,16 @@ public Boolean getSkipInaccessibleCollections() { } /** - * @param skipInaccessibleCollections AQL queries (especially graph traversals) will treat collection to which a user has no access rights - * as if these collections were empty. Instead of returning a forbidden access error, your queries will - * execute normally. This is intended to help with certain use-cases: A graph contains several - * collections and different users execute AQL queries on that graph. You can now naturally limit the - * accessible results by changing the access rights of users on collections. This feature is only + * @param skipInaccessibleCollections AQL queries (especially graph traversals) will treat collection to which a + * user has no access rights + * as if these collections were empty. Instead of returning a forbidden access + * error, your queries will + * execute normally. This is intended to help with certain use-cases: A graph + * contains several + * collections and different users execute AQL queries on that graph. You can + * now naturally limit the + * accessible results by changing the access rights of users on collections. + * This feature is only * available in the Enterprise Edition. * @return options * @since ArangoDB 3.2.0 @@ -317,14 +338,22 @@ public Boolean getFullCount() { } /** - * @param fullCount if set to true and the query contains a LIMIT clause, then the result will have an extra attribute - * with the sub-attributes stats and fullCount, { ... , "extra": { "stats": { "fullCount": 123 } } }. The - * fullCount attribute will contain the number of documents in the result before the last LIMIT in the - * query was applied. It can be used to count the number of documents that match certain filter criteria, - * but only return a subset of them, in one go. It is thus similar to MySQL's SQL_CALC_FOUND_ROWS hint. - * Note that setting the option will disable a few LIMIT optimizations and may lead to more documents - * being processed, and thus make queries run longer. Note that the fullCount attribute will only be - * present in the result if the query has a LIMIT clause and the LIMIT clause is actually used in the + * @param fullCount if set to true and the query contains a LIMIT clause, then the result will have an extra + * attribute + * with the sub-attributes stats and fullCount, { ... , "extra": { "stats": { "fullCount": 123 } + * } }. The + * fullCount attribute will contain the number of documents in the result before the last LIMIT + * in the + * query was applied. It can be used to count the number of documents that match certain filter + * criteria, + * but only return a subset of them, in one go. It is thus similar to MySQL's + * SQL_CALC_FOUND_ROWS hint. + * Note that setting the option will disable a few LIMIT optimizations and may lead to more + * documents + * being processed, and thus make queries run longer. Note that the fullCount attribute will + * only be + * present in the result if the query has a LIMIT clause and the LIMIT clause is actually used + * in the * query. * @return options */ @@ -351,8 +380,10 @@ public Collection getRules() { } /** - * @param rules A list of to-be-included or to-be-excluded optimizer rules can be put into this attribute, telling the - * optimizer to include or exclude specific rules. To disable a rule, prefix its name with a -, to enable + * @param rules A list of to-be-included or to-be-excluded optimizer rules can be put into this attribute, + * telling the + * optimizer to include or exclude specific rules. To disable a rule, prefix its name with a -, to + * enable * a rule, prefix it with a +. There is also a pseudo-rule all, which will match all optimizer rules * @return options */ @@ -366,13 +397,17 @@ public Boolean getStream() { } /** - * @param stream Specify true and the query will be executed in a streaming fashion. The query result is not stored on - * the server, but calculated on the fly. Beware: long-running queries will need to hold the collection - * locks for as long as the query cursor exists. When set to false a query will be executed right away in + * @param stream Specify true and the query will be executed in a streaming fashion. The query result is not + * stored on + * the server, but calculated on the fly. Beware: long-running queries will need to hold the + * collection + * locks for as long as the query cursor exists. When set to false a query will be executed right + * away in * its entirety. In that case query results are either returned right away (if the resultset is small * enough), or stored on the arangod instance and accessible via the cursor API (with respect to the * ttl). It is advisable to only use this option on short-running queries or without exclusive locks - * (write-locks on MMFiles). Please note that the query options cache, count and fullCount will not work + * (write-locks on MMFiles). Please note that the query options cache, count and fullCount will not + * work * on streaming queries. Additionally query statistics, warnings and profiling data will only be * available after the query is finished. The default value is false * @return options diff --git a/src/main/java/com/arangodb/model/CollectionCreateOptions.java b/src/main/java/com/arangodb/model/CollectionCreateOptions.java index dceeb77ce..4d4fccd3c 100644 --- a/src/main/java/com/arangodb/model/CollectionCreateOptions.java +++ b/src/main/java/com/arangodb/model/CollectionCreateOptions.java @@ -73,12 +73,18 @@ public ReplicationFactor getReplicationFactor() { } /** - * @param replicationFactor (The default is 1): in a cluster, this attribute determines how many copies of each shard are kept on - * different DBServers. The value 1 means that only one copy (no synchronous replication) is kept. A - * value of k means that k-1 replicas are kept. Any two copies reside on different DBServers. Replication - * between them is synchronous, that is, every write operation to the "leader" copy will be replicated to - * all "follower" replicas, before the write operation is reported successful. If a server fails, this is - * detected automatically and one of the servers holding copies take over, usually without an error being + * @param replicationFactor (The default is 1): in a cluster, this attribute determines how many copies of each + * shard are kept on + * different DBServers. The value 1 means that only one copy (no synchronous + * replication) is kept. A + * value of k means that k-1 replicas are kept. Any two copies reside on different + * DBServers. Replication + * between them is synchronous, that is, every write operation to the "leader" copy will + * be replicated to + * all "follower" replicas, before the write operation is reported successful. If a + * server fails, this is + * detected automatically and one of the servers holding copies take over, usually + * without an error being * reported. * @return options */ @@ -119,13 +125,17 @@ public KeyOptions getKeyOptions() { } /** - * @param allowUserKeys if set to true, then it is allowed to supply own key values in the _key attribute of a document. If - * set to false, then the key generator will solely be responsible for generating keys and supplying own + * @param allowUserKeys if set to true, then it is allowed to supply own key values in the _key attribute of a + * document. If + * set to false, then the key generator will solely be responsible for generating keys and + * supplying own * key values in the _key attribute of documents is considered an error. - * @param type specifies the type of the key generator. The currently available generators are traditional and + * @param type specifies the type of the key generator. The currently available generators are + * traditional and * autoincrement. * @param increment increment value for autoincrement key generator. Not used for other key generator types. - * @param offset Initial offset value for autoincrement key generator. Not used for other key generator types. + * @param offset Initial offset value for autoincrement key generator. Not used for other key generator + * types. * @return options */ public CollectionCreateOptions keyOptions( @@ -142,7 +152,8 @@ public Boolean getWaitForSync() { } /** - * @param waitForSync If true then the data is synchronized to disk before returning from a document create, update, replace + * @param waitForSync If true then the data is synchronized to disk before returning from a document create, + * update, replace * or removal operation. (default: false) * @return options */ @@ -156,9 +167,12 @@ public Collection getShardKeys() { } /** - * @param shardKeys (The default is [ "_key" ]): in a cluster, this attribute determines which document attributes are - * used to determine the target shard for documents. Documents are sent to shards based on the values of - * their shard key attributes. The values of all shard key attributes in a document are hashed, and the + * @param shardKeys (The default is [ "_key" ]): in a cluster, this attribute determines which document + * attributes are + * used to determine the target shard for documents. Documents are sent to shards based on the + * values of + * their shard key attributes. The values of all shard key attributes in a document are hashed, + * and the * hash value is used to determine the target shard. Note: Values of shard key attributes cannot be * changed once set. This option is meaningless in a single server setup. * @return options @@ -195,7 +209,8 @@ public String getShardingStrategy() { } /** - * @param numberOfShards (The default is 1): in a cluster, this value determines the number of shards to create for the + * @param numberOfShards (The default is 1): in a cluster, this value determines the number of shards to create + * for the * collection. In a single server setup, this option is meaningless. * @return options */ @@ -213,9 +228,12 @@ public Boolean getIsSystem() { } /** - * @param isSystem If true, create a system collection. In this case collection-name should start with an underscore. End - * users should normally create non-system collections only. API implementors may be required to create - * system collections in very special occasions, but normally a regular collection will do. (The default + * @param isSystem If true, create a system collection. In this case collection-name should start with an + * underscore. End + * users should normally create non-system collections only. API implementors may be required to + * create + * system collections in very special occasions, but normally a regular collection will do. (The + * default * is false) * @return options */ @@ -242,10 +260,14 @@ public String getDistributeShardsLike() { } /** - * @param distributeShardsLike (The default is ""): in an enterprise cluster, this attribute binds the specifics of sharding for the - * newly created collection to follow that of a specified existing collection. Note: Using this parameter - * has consequences for the prototype collection. It can no longer be dropped, before sharding imitating - * collections are dropped. Equally, backups and restores of imitating collections alone will generate + * @param distributeShardsLike (The default is ""): in an enterprise cluster, this attribute binds the specifics + * of sharding for the + * newly created collection to follow that of a specified existing collection. Note: + * Using this parameter + * has consequences for the prototype collection. It can no longer be dropped, before + * sharding imitating + * collections are dropped. Equally, backups and restores of imitating collections + * alone will generate * warnings, which can be overridden, about missing sharding prototype. * @return options */ diff --git a/src/main/java/com/arangodb/model/CollectionPropertiesOptions.java b/src/main/java/com/arangodb/model/CollectionPropertiesOptions.java index 3d64239b9..046842652 100644 --- a/src/main/java/com/arangodb/model/CollectionPropertiesOptions.java +++ b/src/main/java/com/arangodb/model/CollectionPropertiesOptions.java @@ -22,7 +22,8 @@ /** * @author Mark Vollmary - * @see API + * @see + * API * Documentation */ public final class CollectionPropertiesOptions { @@ -39,7 +40,8 @@ public Boolean getWaitForSync() { } /** - * @param waitForSync If true then creating or changing a document will wait until the data has been synchronized to disk. + * @param waitForSync If true then creating or changing a document will wait until the data has been synchronized + * to disk. * @return options */ public CollectionPropertiesOptions waitForSync(final Boolean waitForSync) { diff --git a/src/main/java/com/arangodb/model/CollectionSchema.java b/src/main/java/com/arangodb/model/CollectionSchema.java index 92d685d25..60d7cbf0d 100644 --- a/src/main/java/com/arangodb/model/CollectionSchema.java +++ b/src/main/java/com/arangodb/model/CollectionSchema.java @@ -30,7 +30,8 @@ /** * @author Michele Rastelli - * @see API Documentation + * @see + * API Documentation * @since ArangoDB 3.7 */ public final class CollectionSchema { diff --git a/src/main/java/com/arangodb/model/DocumentDeleteOptions.java b/src/main/java/com/arangodb/model/DocumentDeleteOptions.java index ba59aaf5e..d2de3aa43 100644 --- a/src/main/java/com/arangodb/model/DocumentDeleteOptions.java +++ b/src/main/java/com/arangodb/model/DocumentDeleteOptions.java @@ -69,7 +69,8 @@ public Boolean getReturnOld() { } /** - * @param returnOld Return additionally the complete previous revision of the changed document under the attribute old in + * @param returnOld Return additionally the complete previous revision of the changed document under the + * attribute old in * the result. * @return options */ diff --git a/src/main/java/com/arangodb/model/DocumentExistsOptions.java b/src/main/java/com/arangodb/model/DocumentExistsOptions.java index 06c3a44d5..a14dfaf16 100644 --- a/src/main/java/com/arangodb/model/DocumentExistsOptions.java +++ b/src/main/java/com/arangodb/model/DocumentExistsOptions.java @@ -23,7 +23,8 @@ /** * @author Mark Vollmary * @author Michele Rastelli - * @see API + * @see + * API * Documentation */ public final class DocumentExistsOptions { diff --git a/src/main/java/com/arangodb/model/DocumentImportOptions.java b/src/main/java/com/arangodb/model/DocumentImportOptions.java index c6dbfb6fc..154a629d5 100644 --- a/src/main/java/com/arangodb/model/DocumentImportOptions.java +++ b/src/main/java/com/arangodb/model/DocumentImportOptions.java @@ -32,6 +32,7 @@ public final class DocumentImportOptions { private OnDuplicate onDuplicate; private Boolean complete; private Boolean details; + public DocumentImportOptions() { super(); } @@ -69,7 +70,8 @@ public Boolean getOverwrite() { } /** - * @param overwrite If this parameter has a value of true, then all data in the collection will be removed prior to the + * @param overwrite If this parameter has a value of true, then all data in the collection will be removed prior + * to the * import. Note that any existing index definitions will be preserved. * @return options */ @@ -96,18 +98,25 @@ public OnDuplicate getOnDuplicate() { } /** - * @param onDuplicate Controls what action is carried out in case of a unique key constraint violation. Possible values are: + * @param onDuplicate Controls what action is carried out in case of a unique key constraint violation. Possible + * values are: *

      - *
    • error: this will not import the current document because of the unique key constraint violation. + *
    • error: this will not import the current document because of the unique key constraint + * violation. * This is the default setting.
    • - *
    • update: this will update an existing document in the database with the data specified in the + *
    • update: this will update an existing document in the database with the data specified + * in the * request. Attributes of the existing document that are not present in the request will be * preserved.
    • - *
    • replace: this will replace an existing document in the database with the data specified in the + *
    • replace: this will replace an existing document in the database with the data specified + * in the * request.
    • - *
    • ignore: this will not update an existing document and simply ignore the error caused by the unique - * key constraint violation. Note that update, replace and ignore will only work when the import document - * in the request contains the _key attribute. update and replace may also fail because of secondary + *
    • ignore: this will not update an existing document and simply ignore the error caused by + * the unique + * key constraint violation. Note that update, replace and ignore will only work when the + * import document + * in the request contains the _key attribute. update and replace may also fail because of + * secondary * unique key constraint violations.
    • *
    * @return options @@ -136,7 +145,8 @@ public Boolean getDetails() { } /** - * @param details If set to true, the result will include an attribute details with details about documents that could + * @param details If set to true, the result will include an attribute details with details about documents that + * could * not be imported. * @return options */ diff --git a/src/main/java/com/arangodb/model/DocumentReplaceOptions.java b/src/main/java/com/arangodb/model/DocumentReplaceOptions.java index d32fb56c5..f08f18470 100644 --- a/src/main/java/com/arangodb/model/DocumentReplaceOptions.java +++ b/src/main/java/com/arangodb/model/DocumentReplaceOptions.java @@ -58,8 +58,10 @@ public Boolean getIgnoreRevs() { } /** - * @param ignoreRevs By default, or if this is set to true, the _rev attributes in the given document is ignored. If this - * is set to false, then the _rev attribute given in the body document is taken as a precondition. The + * @param ignoreRevs By default, or if this is set to true, the _rev attributes in the given document is ignored. + * If this + * is set to false, then the _rev attribute given in the body document is taken as a + * precondition. The * document is only replaced if the current revision is the one specified. * @return options */ @@ -99,7 +101,8 @@ public Boolean getReturnOld() { } /** - * @param returnOld Return additionally the complete previous revision of the changed document under the attribute old in + * @param returnOld Return additionally the complete previous revision of the changed document under the + * attribute old in * the result. * @return options */ diff --git a/src/main/java/com/arangodb/model/DocumentUpdateOptions.java b/src/main/java/com/arangodb/model/DocumentUpdateOptions.java index c1d74b837..ae39ae8f5 100644 --- a/src/main/java/com/arangodb/model/DocumentUpdateOptions.java +++ b/src/main/java/com/arangodb/model/DocumentUpdateOptions.java @@ -63,8 +63,10 @@ public Boolean getMergeObjects() { } /** - * @param mergeObjects Controls whether objects (not arrays) will be merged if present in both the existing and the patch - * document. If set to false, the value in the patch document will overwrite the existing document's + * @param mergeObjects Controls whether objects (not arrays) will be merged if present in both the existing and + * the patch + * document. If set to false, the value in the patch document will overwrite the existing + * document's * value. If set to true, objects will be merged. The default is true. * @return options */ @@ -91,8 +93,10 @@ public Boolean getIgnoreRevs() { } /** - * @param ignoreRevs By default, or if this is set to true, the _rev attributes in the given document is ignored. If this - * is set to false, then the _rev attribute given in the body document is taken as a precondition. The + * @param ignoreRevs By default, or if this is set to true, the _rev attributes in the given document is ignored. + * If this + * is set to false, then the _rev attribute given in the body document is taken as a + * precondition. The * document is only updated if the current revision is the one specified. * @return options */ @@ -132,7 +136,8 @@ public Boolean getReturnOld() { } /** - * @param returnOld Return additionally the complete previous revision of the changed document under the attribute old in + * @param returnOld Return additionally the complete previous revision of the changed document under the + * attribute old in * the result. * @return options */ diff --git a/src/main/java/com/arangodb/model/FulltextIndexOptions.java b/src/main/java/com/arangodb/model/FulltextIndexOptions.java index d309bd3aa..fd69c56af 100644 --- a/src/main/java/com/arangodb/model/FulltextIndexOptions.java +++ b/src/main/java/com/arangodb/model/FulltextIndexOptions.java @@ -64,7 +64,8 @@ public Integer getMinLength() { } /** - * @param minLength Minimum character length of words to index. Will default to a server-defined value if unspecified. It + * @param minLength Minimum character length of words to index. Will default to a server-defined value if + * unspecified. It * is thus recommended to set this value explicitly when creating the index. * @return options */ diff --git a/src/main/java/com/arangodb/model/GeoIndexOptions.java b/src/main/java/com/arangodb/model/GeoIndexOptions.java index 7e06bf81c..db3f43f95 100644 --- a/src/main/java/com/arangodb/model/GeoIndexOptions.java +++ b/src/main/java/com/arangodb/model/GeoIndexOptions.java @@ -24,7 +24,8 @@ /** * @author Mark Vollmary - * @see API Documentation + * @see + * API Documentation */ public final class GeoIndexOptions extends IndexOptions { diff --git a/src/main/java/com/arangodb/model/GraphCreateOptions.java b/src/main/java/com/arangodb/model/GraphCreateOptions.java index 83cb05363..340b506cb 100644 --- a/src/main/java/com/arangodb/model/GraphCreateOptions.java +++ b/src/main/java/com/arangodb/model/GraphCreateOptions.java @@ -114,12 +114,18 @@ public ReplicationFactor getReplicationFactor() { } /** - * @param replicationFactor (The default is 1): in a cluster, this attribute determines how many copies of each shard are kept on - * different DBServers. The value 1 means that only one copy (no synchronous replication) is kept. A - * value of k means that k-1 replicas are kept. Any two copies reside on different DBServers. Replication - * between them is synchronous, that is, every write operation to the "leader" copy will be replicated to - * all "follower" replicas, before the write operation is reported successful. If a server fails, this is - * detected automatically and one of the servers holding copies take over, usually without an error being + * @param replicationFactor (The default is 1): in a cluster, this attribute determines how many copies of each + * shard are kept on + * different DBServers. The value 1 means that only one copy (no synchronous + * replication) is kept. A + * value of k means that k-1 replicas are kept. Any two copies reside on different + * DBServers. Replication + * between them is synchronous, that is, every write operation to the "leader" copy will + * be replicated to + * all "follower" replicas, before the write operation is reported successful. If a + * server fails, this is + * detected automatically and one of the servers holding copies take over, usually + * without an error being * reported. * @return options */ @@ -160,7 +166,8 @@ public Integer getNumberOfShards() { } /** - * @param numberOfShards The number of shards that is used for every collection within this graph. Cannot be modified later. + * @param numberOfShards The number of shards that is used for every collection within this graph. Cannot be + * modified later. * @return options */ public GraphCreateOptions numberOfShards(final Integer numberOfShards) { @@ -173,7 +180,8 @@ public String getSmartGraphAttribute() { } /** - * @param smartGraphAttribute The attribute name that is used to smartly shard the vertices of a graph. Every vertex in this Graph + * @param smartGraphAttribute The attribute name that is used to smartly shard the vertices of a graph. Every + * vertex in this Graph * has to have this attribute. Cannot be modified later. * @return options */ diff --git a/src/main/java/com/arangodb/model/HashIndexOptions.java b/src/main/java/com/arangodb/model/HashIndexOptions.java index 9e22c633a..633910c16 100644 --- a/src/main/java/com/arangodb/model/HashIndexOptions.java +++ b/src/main/java/com/arangodb/model/HashIndexOptions.java @@ -104,7 +104,8 @@ public HashIndexOptions deduplicate(final Boolean deduplicate) { } /** - * @param estimates This attribute controls whether index selectivity estimates are maintained for the index. Default: {@code + * @param estimates This attribute controls whether index selectivity estimates are maintained for the index. + * Default: {@code * true} * @since ArangoDB 3.8 */ diff --git a/src/main/java/com/arangodb/model/LogOptions.java b/src/main/java/com/arangodb/model/LogOptions.java index 861dbefb3..bc5a25f17 100644 --- a/src/main/java/com/arangodb/model/LogOptions.java +++ b/src/main/java/com/arangodb/model/LogOptions.java @@ -44,6 +44,7 @@ public final class LogOptions { private Integer offset; private String search; private SortOrder sort; + public LogOptions() { super(); } @@ -66,7 +67,8 @@ public LogLevel getLevel() { } /** - * @param level Returns all log entries of log level level. Note that the query parameters upto and level are mutually + * @param level Returns all log entries of log level level. Note that the query parameters upto and level are + * mutually * exclusive * @return options */ @@ -80,7 +82,8 @@ public Long getStart() { } /** - * @param start Returns all log entries such that their log entry identifier (lid value) is greater or equal to start + * @param start Returns all log entries such that their log entry identifier (lid value) is greater or equal to + * start * @return options */ public LogOptions start(final Long start) { diff --git a/src/main/java/com/arangodb/model/OptionsBuilder.java b/src/main/java/com/arangodb/model/OptionsBuilder.java index f62a45d19..17e9bf263 100644 --- a/src/main/java/com/arangodb/model/OptionsBuilder.java +++ b/src/main/java/com/arangodb/model/OptionsBuilder.java @@ -83,7 +83,8 @@ public static CollectionCreateOptions build(final CollectionCreateOptions option return options.name(name); } - public static AqlQueryOptions build(final AqlQueryOptions options, final String query, final Map bindVars) { + public static AqlQueryOptions build(final AqlQueryOptions options, final String query, + final Map bindVars) { return options.query(query).bindVars(bindVars); } diff --git a/src/main/java/com/arangodb/model/PersistentIndexOptions.java b/src/main/java/com/arangodb/model/PersistentIndexOptions.java index ce9917ba6..077a0f6ff 100644 --- a/src/main/java/com/arangodb/model/PersistentIndexOptions.java +++ b/src/main/java/com/arangodb/model/PersistentIndexOptions.java @@ -102,7 +102,8 @@ public PersistentIndexOptions deduplicate(final Boolean deduplicate) { } /** - * @param estimates This attribute controls whether index selectivity estimates are maintained for the index. Default: {@code + * @param estimates This attribute controls whether index selectivity estimates are maintained for the index. + * Default: {@code * true} * @since ArangoDB 3.8 */ diff --git a/src/main/java/com/arangodb/model/SkiplistIndexOptions.java b/src/main/java/com/arangodb/model/SkiplistIndexOptions.java index 86fca8f0b..e608632e9 100644 --- a/src/main/java/com/arangodb/model/SkiplistIndexOptions.java +++ b/src/main/java/com/arangodb/model/SkiplistIndexOptions.java @@ -104,7 +104,8 @@ public SkiplistIndexOptions deduplicate(final Boolean deduplicate) { } /** - * @param estimates This attribute controls whether index selectivity estimates are maintained for the index. Default: {@code + * @param estimates This attribute controls whether index selectivity estimates are maintained for the index. + * Default: {@code * true} * @since ArangoDB 3.8 */ diff --git a/src/main/java/com/arangodb/model/StreamTransactionOptions.java b/src/main/java/com/arangodb/model/StreamTransactionOptions.java index 9bcf5000e..c47bad388 100644 --- a/src/main/java/com/arangodb/model/StreamTransactionOptions.java +++ b/src/main/java/com/arangodb/model/StreamTransactionOptions.java @@ -65,7 +65,8 @@ public Boolean getWaitForSync() { } /** - * @param waitForSync an optional boolean flag that, if set, will force the transaction to write all data to disk before + * @param waitForSync an optional boolean flag that, if set, will force the transaction to write all data to disk + * before * returning * @return options */ @@ -93,7 +94,8 @@ public StreamTransactionOptions writeCollections(final String... write) { } /** - * @param exclusive contains the array of collection-names to be used in the transaction (mandatory) for exclusive write + * @param exclusive contains the array of collection-names to be used in the transaction (mandatory) for + * exclusive write * @return options */ public StreamTransactionOptions exclusiveCollections(final String... exclusive) { diff --git a/src/main/java/com/arangodb/model/TransactionOptions.java b/src/main/java/com/arangodb/model/TransactionOptions.java index 726f75edf..1306c11f3 100644 --- a/src/main/java/com/arangodb/model/TransactionOptions.java +++ b/src/main/java/com/arangodb/model/TransactionOptions.java @@ -92,7 +92,8 @@ public Boolean getWaitForSync() { } /** - * @param waitForSync an optional boolean flag that, if set, will force the transaction to write all data to disk before + * @param waitForSync an optional boolean flag that, if set, will force the transaction to write all data to disk + * before * returning * @return options */ @@ -120,7 +121,8 @@ public TransactionOptions writeCollections(final String... write) { } /** - * @param exclusive contains the array of collection-names to be used in the transaction (mandatory) for exclusive write + * @param exclusive contains the array of collection-names to be used in the transaction (mandatory) for + * exclusive write * @return options * @since ArangoDB 3.4.0 */ @@ -130,10 +132,14 @@ public TransactionOptions exclusiveCollections(final String... exclusive) { } /** - * @param allowImplicit Collections that will be written to in the transaction must be declared with the write attribute or it - * will fail, whereas non-declared collections from which is solely read will be added lazily. The - * optional attribute allowImplicit can be set to false to let transactions fail in case of undeclared - * collections for reading. Collections for reading should be fully declared if possible, to avoid + * @param allowImplicit Collections that will be written to in the transaction must be declared with the write + * attribute or it + * will fail, whereas non-declared collections from which is solely read will be added + * lazily. The + * optional attribute allowImplicit can be set to false to let transactions fail in case of + * undeclared + * collections for reading. Collections for reading should be fully declared if possible, to + * avoid * deadlocks. * @return options */ diff --git a/src/main/java/com/arangodb/model/TtlIndexOptions.java b/src/main/java/com/arangodb/model/TtlIndexOptions.java index 023c12fa3..bca69e759 100644 --- a/src/main/java/com/arangodb/model/TtlIndexOptions.java +++ b/src/main/java/com/arangodb/model/TtlIndexOptions.java @@ -59,7 +59,8 @@ public IndexType getType() { } /** - * @param expireAfter The time (in seconds) after a document’s creation after which the documents count as “expired”. + * @param expireAfter The time (in seconds) after a document’s creation after which the documents count as + * “expired”. * @return options */ public TtlIndexOptions expireAfter(final Integer expireAfter) { diff --git a/src/main/java/com/arangodb/model/arangosearch/ArangoSearchCreateOptions.java b/src/main/java/com/arangodb/model/arangosearch/ArangoSearchCreateOptions.java index a6fa3b8b8..7b9ba4238 100644 --- a/src/main/java/com/arangodb/model/arangosearch/ArangoSearchCreateOptions.java +++ b/src/main/java/com/arangodb/model/arangosearch/ArangoSearchCreateOptions.java @@ -55,11 +55,16 @@ ArangoSearchCreateOptions name(final String name) { } /** - * @param consolidationIntervalMsec Wait at least this many milliseconds between committing index data changes and making them visible to - * queries (default: 60000, to disable use: 0). For the case where there are a lot of inserts/updates, a - * lower value, until commit, will cause the index not to account for them and memory usage would - * continue to grow. For the case where there are a few inserts/updates, a higher value will impact - * performance and waste disk space for each commit call without any added benefits. + * @param consolidationIntervalMsec Wait at least this many milliseconds between committing index data changes + * and making them visible to + * queries (default: 60000, to disable use: 0). For the case where there are a + * lot of inserts/updates, a + * lower value, until commit, will cause the index not to account for them and + * memory usage would + * continue to grow. For the case where there are a few inserts/updates, a + * higher value will impact + * performance and waste disk space for each commit call without any added + * benefits. * @return options */ public ArangoSearchCreateOptions consolidationIntervalMsec(final Long consolidationIntervalMsec) { @@ -68,16 +73,26 @@ public ArangoSearchCreateOptions consolidationIntervalMsec(final Long consolidat } /** - * @param commitIntervalMsec Wait at least this many milliseconds between committing view data store changes and making documents visible to - * queries (default: 1000, to disable use: 0). For the case where there are a lot of inserts/updates, a lower value, - * until commit, will cause the index not to account for them and memory usage would continue to grow. For the case - * where there are a few inserts/updates, a higher value will impact performance and waste disk space for each - * commit call without any added benefits. Background: For data retrieval ArangoSearch views follow the concept of - * “eventually-consistent”, i.e. eventually all the data in ArangoDB will be matched by corresponding query - * expressions. The concept of ArangoSearch view “commit” operation is introduced to control the upper-bound on the - * time until document addition/removals are actually reflected by corresponding query expressions. Once a “commit” - * operation is complete all documents added/removed prior to the start of the “commit” operation will be reflected - * by queries invoked in subsequent ArangoDB transactions, in-progress ArangoDB transactions will still continue to + * @param commitIntervalMsec Wait at least this many milliseconds between committing view data store changes and + * making documents visible to + * queries (default: 1000, to disable use: 0). For the case where there are a lot of + * inserts/updates, a lower value, + * until commit, will cause the index not to account for them and memory usage would + * continue to grow. For the case + * where there are a few inserts/updates, a higher value will impact performance and + * waste disk space for each + * commit call without any added benefits. Background: For data retrieval ArangoSearch + * views follow the concept of + * “eventually-consistent”, i.e. eventually all the data in ArangoDB will be matched by + * corresponding query + * expressions. The concept of ArangoSearch view “commit” operation is introduced to + * control the upper-bound on the + * time until document addition/removals are actually reflected by corresponding query + * expressions. Once a “commit” + * operation is complete all documents added/removed prior to the start of the “commit” + * operation will be reflected + * by queries invoked in subsequent ArangoDB transactions, in-progress ArangoDB + * transactions will still continue to * return a repeatable-read state. * @return options */ @@ -87,10 +102,14 @@ public ArangoSearchCreateOptions commitIntervalMsec(final Long commitIntervalMse } /** - * @param cleanupIntervalStep Wait at least this many commits between removing unused files in data directory (default: 10, to - * disable use: 0). For the case where the consolidation policies merge segments often (i.e. a lot of - * commit+consolidate), a lower value will cause a lot of disk space to be wasted. For the case where the - * consolidation policies rarely merge segments (i.e. few inserts/deletes), a higher value will impact + * @param cleanupIntervalStep Wait at least this many commits between removing unused files in data directory + * (default: 10, to + * disable use: 0). For the case where the consolidation policies merge segments often + * (i.e. a lot of + * commit+consolidate), a lower value will cause a lot of disk space to be wasted. For + * the case where the + * consolidation policies rarely merge segments (i.e. few inserts/deletes), a higher + * value will impact * performance without any added benefits. * @return options */ diff --git a/src/main/java/com/arangodb/model/arangosearch/ArangoSearchPropertiesOptions.java b/src/main/java/com/arangodb/model/arangosearch/ArangoSearchPropertiesOptions.java index 6420b13de..912540c7f 100644 --- a/src/main/java/com/arangodb/model/arangosearch/ArangoSearchPropertiesOptions.java +++ b/src/main/java/com/arangodb/model/arangosearch/ArangoSearchPropertiesOptions.java @@ -41,11 +41,16 @@ public final class ArangoSearchPropertiesOptions { private Collection primarySorts; /** - * @param consolidationIntervalMsec Wait at least this many milliseconds between committing index data changes and making them visible to - * queries (default: 60000, to disable use: 0). For the case where there are a lot of inserts/updates, a - * lower value, until commit, will cause the index not to account for them and memory usage would - * continue to grow. For the case where there are a few inserts/updates, a higher value will impact - * performance and waste disk space for each commit call without any added benefits. + * @param consolidationIntervalMsec Wait at least this many milliseconds between committing index data changes + * and making them visible to + * queries (default: 60000, to disable use: 0). For the case where there are a + * lot of inserts/updates, a + * lower value, until commit, will cause the index not to account for them and + * memory usage would + * continue to grow. For the case where there are a few inserts/updates, a + * higher value will impact + * performance and waste disk space for each commit call without any added + * benefits. * @return options */ public ArangoSearchPropertiesOptions consolidationIntervalMsec(final Long consolidationIntervalMsec) { @@ -54,10 +59,14 @@ public ArangoSearchPropertiesOptions consolidationIntervalMsec(final Long consol } /** - * @param cleanupIntervalStep Wait at least this many commits between removing unused files in data directory (default: 10, to - * disable use: 0). For the case where the consolidation policies merge segments often (i.e. a lot of - * commit+consolidate), a lower value will cause a lot of disk space to be wasted. For the case where the - * consolidation policies rarely merge segments (i.e. few inserts/deletes), a higher value will impact + * @param cleanupIntervalStep Wait at least this many commits between removing unused files in data directory + * (default: 10, to + * disable use: 0). For the case where the consolidation policies merge segments often + * (i.e. a lot of + * commit+consolidate), a lower value will cause a lot of disk space to be wasted. For + * the case where the + * consolidation policies rarely merge segments (i.e. few inserts/deletes), a higher + * value will impact * performance without any added benefits. * @return options */ diff --git a/src/main/java/com/arangodb/serde/ArangoSerde.java b/src/main/java/com/arangodb/serde/ArangoSerde.java index f09e1d2f6..548662a11 100644 --- a/src/main/java/com/arangodb/serde/ArangoSerde.java +++ b/src/main/java/com/arangodb/serde/ArangoSerde.java @@ -13,7 +13,8 @@ * - low-level libraries without support to data binding *

    * To create a custom serde based on Jackson, existing {@link JacksonSerde} can be reused and instantiated providing a - * custom configured ObjectMapper ({@link JacksonSerde#create(com.fasterxml.jackson.databind.ObjectMapper)}) or configured + * custom configured ObjectMapper ({@link JacksonSerde#create(com.fasterxml.jackson.databind.ObjectMapper)}) or + * configured * after creation through {@link JacksonSerde#configure(Consumer)}. */ public interface ArangoSerde { From 1d50ce75cf68dade8461e83c7b34fe46fc402eb4 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Wed, 17 Aug 2022 10:22:07 +0200 Subject: [PATCH 098/254] sonarcloud --- .github/workflows/maven.yml | 52 +++++++++++++++++++++++++++++++++++++ pom.xml | 2 ++ 2 files changed, 54 insertions(+) diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index c667a2e16..3fbb91e02 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -173,3 +173,55 @@ jobs: run: mvn -version - name: Test run: mvn --no-transfer-progress test -Dadb.jackson.version=${{matrix.jackson-version}} + + sonar: + timeout-minutes: 10 + runs-on: ubuntu-latest + + strategy: + fail-fast: false + matrix: + docker-img: + - docker.io/arangodb/enterprise:3.9.1 + topology: + - cluster + db-ext-names: + - false + java-version: + - 11 + + steps: + - uses: actions/checkout@v2 + - name: Set up JDK + uses: actions/setup-java@v2 + with: + java-version: ${{matrix.java-version}} + distribution: 'adopt' + cache: maven + - name: Start Database + run: ./docker/start_db.sh + env: + ARANGO_LICENSE_KEY: ${{ secrets.ARANGO_LICENSE_KEY }} + STARTER_MODE: ${{matrix.topology}} + DOCKER_IMAGE: ${{matrix.docker-img}} + DATABASE_EXTENDED_NAMES: ${{matrix.db-ext-names}} + - name: Info + run: mvn -version + - name: Cache SonarCloud packages + uses: actions/cache@v1 + with: + path: ~/.sonar/cache + key: ${{ runner.os }}-sonar + restore-keys: ${{ runner.os }}-sonar + - name: Cache Maven packages + uses: actions/cache@v1 + with: + path: ~/.m2 + key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }} + restore-keys: ${{ runner.os }}-m2 + - name: Build and analyze + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Needed to get PR information, if any + SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} + run: mvn --no-transfer-progress -B verify org.sonarsource.scanner.maven:sonar-maven-plugin:sonar -Dsonar.projectKey=arangodb_arangodb-java-reactive-driver + diff --git a/pom.xml b/pom.xml index d86ea7d31..5d5a3529d 100644 --- a/pom.xml +++ b/pom.xml @@ -24,6 +24,8 @@ UTF-8 2.13.3 + arangodb-1 + https://sonarcloud.io From 112b565addb94287c99ba867cdd2780cbeeb14c0 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Wed, 17 Aug 2022 10:31:32 +0200 Subject: [PATCH 099/254] sonarcloud --- .github/workflows/maven.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index 3fbb91e02..814bcb98a 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -223,5 +223,5 @@ jobs: env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Needed to get PR information, if any SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} - run: mvn --no-transfer-progress -B verify org.sonarsource.scanner.maven:sonar-maven-plugin:sonar -Dsonar.projectKey=arangodb_arangodb-java-reactive-driver + run: mvn -B --no-transfer-progress -Dgpg.skip=true verify org.sonarsource.scanner.maven:sonar-maven-plugin:sonar -Dsonar.projectKey=arangodb_arangodb-java-driver From dbee9a7b50cf84e5f247ed636bd824622665405a Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Wed, 17 Aug 2022 13:35:46 +0200 Subject: [PATCH 100/254] [DE-331] multi document operations from raw data (#450) * RawData * addded API methods to handle multi documents from raw data * test fixes * sync implementation * async implementation --- .../java/com/arangodb/ArangoCollection.java | 180 ++++++++++++----- .../java/com/arangodb/ArangoDatabase.java | 24 +-- .../com/arangodb/ArangoEdgeCollection.java | 24 +-- .../com/arangodb/ArangoVertexCollection.java | 24 +-- .../arangodb/async/ArangoCollectionAsync.java | 184 +++++++++++++----- .../arangodb/async/ArangoDatabaseAsync.java | 24 +-- .../async/ArangoEdgeCollectionAsync.java | 12 +- .../async/ArangoVertexCollectionAsync.java | 12 +- .../internal/ArangoCollectionAsyncImpl.java | 67 ++++++- .../internal/ArangoCollectionImpl.java | 65 ++++++- .../internal/InternalArangoCollection.java | 123 ++++++------ src/main/java/com/arangodb/util/RawBytes.java | 2 +- src/main/java/com/arangodb/util/RawData.java | 17 ++ src/main/java/com/arangodb/util/RawJson.java | 2 +- .../com/arangodb/ArangoCollectionTest.java | 150 ++++++++++++-- .../arangodb/async/ArangoCollectionTest.java | 155 +++++++++++++-- 16 files changed, 801 insertions(+), 264 deletions(-) create mode 100644 src/main/java/com/arangodb/util/RawData.java diff --git a/src/main/java/com/arangodb/ArangoCollection.java b/src/main/java/com/arangodb/ArangoCollection.java index d0c7d31f5..86c42cbb1 100644 --- a/src/main/java/com/arangodb/ArangoCollection.java +++ b/src/main/java/com/arangodb/ArangoCollection.java @@ -22,6 +22,7 @@ import com.arangodb.entity.*; import com.arangodb.model.*; +import com.arangodb.util.RawData; import java.util.Collection; @@ -54,8 +55,7 @@ public interface ArangoCollection extends ArangoSerdeAccessor { * Creates a new document from the given document, unless there is already a document with the _key given. If no * _key is given, a new unique _key is generated automatically. * - * @param value A representation of a single document (POJO, {@link com.arangodb.util.RawJson} or - * {@link com.arangodb.util.RawBytes}) + * @param value A representation of a single document (POJO or {@link com.arangodb.util.RawData} * @return information about the document * @see API * Documentation @@ -66,8 +66,7 @@ public interface ArangoCollection extends ArangoSerdeAccessor { * Creates a new document from the given document, unless there is already a document with the _key given. If no * _key is given, a new unique _key is generated automatically. * - * @param value A representation of a single document (POJO, {@link com.arangodb.util.RawJson} or - * {@link com.arangodb.util.RawBytes}) + * @param value A representation of a single document (POJO or {@link com.arangodb.util.RawData}) * @param options Additional options * @return information about the document * @see API @@ -79,8 +78,7 @@ public interface ArangoCollection extends ArangoSerdeAccessor { * Creates a new document from the given document, unless there is already a document with the _key given. If no * _key is given, a new unique _key is generated automatically. * - * @param value A representation of a single document (POJO, {@link com.arangodb.util.RawJson} or - * {@link com.arangodb.util.RawBytes}) + * @param value A representation of a single document (POJO or {@link com.arangodb.util.RawData}) * @param options Additional options * @param type Deserialization target type for the returned documents. * @return information about the document @@ -93,7 +91,31 @@ public interface ArangoCollection extends ArangoSerdeAccessor { * Creates new documents from the given documents, unless there is already a document with the _key given. If no * _key is given, a new unique _key is generated automatically. * - * @param values A List of documents (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) + * @param values Raw data representing a collection of documents + * @return information about the documents + * @see API + * Documentation + */ + MultiDocumentEntity> insertDocuments(RawData values); + + /** + * Creates new documents from the given documents, unless there is already a document with the _key given. If no + * _key is given, a new unique _key is generated automatically. + * + * @param values Raw data representing a collection of documents + * @param options Additional options + * @return information about the documents + * @see API + * Documentation + */ + MultiDocumentEntity> insertDocuments( + RawData values, DocumentCreateOptions options); + + /** + * Creates new documents from the given documents, unless there is already a document with the _key given. If no + * _key is given, a new unique _key is generated automatically. + * + * @param values A List of documents * @return information about the documents * @see API * Documentation @@ -104,8 +126,7 @@ public interface ArangoCollection extends ArangoSerdeAccessor { * Creates new documents from the given documents, unless there is already a document with the _key given. If no * _key is given, a new unique _key is generated automatically. * - * @param values A List of documents (POJO, {@link com.arangodb.util.RawJson} or - * {@link com.arangodb.util.RawBytes}) + * @param values A List of documents (POJO or {@link com.arangodb.util.RawData}) * @param options Additional options * @return information about the documents * @see API @@ -118,8 +139,7 @@ MultiDocumentEntity> insertDocuments( * Creates new documents from the given documents, unless there is already a document with the _key given. If no * _key is given, a new unique _key is generated automatically. * - * @param values A List of documents (POJO, {@link com.arangodb.util.RawJson} or - * {@link com.arangodb.util.RawBytes}) + * @param values A List of documents (POJO or {@link com.arangodb.util.RawData}) * @param options Additional options * @param type Deserialization target type for the returned documents. * @return information about the documents @@ -132,7 +152,7 @@ MultiDocumentEntity> insertDocuments( /** * Bulk imports the given values into the collection. * - * @param values a list of Objects that will be stored as documents + * @param values A List of documents (POJO or {@link com.arangodb.util.RawData}) * @return information about the import */ DocumentImportEntity importDocuments(Collection values); @@ -140,7 +160,7 @@ MultiDocumentEntity> insertDocuments( /** * Bulk imports the given values into the collection. * - * @param values a list of Objects that will be stored as documents + * @param values A List of documents (POJO or {@link com.arangodb.util.RawData}) * @param options Additional options, can be null * @return information about the import */ @@ -149,26 +169,25 @@ MultiDocumentEntity> insertDocuments( /** * Bulk imports the given values into the collection. * - * @param values JSON-encoded array of objects that will be stored as documents + * @param values Raw data representing a collection of documents * @return information about the import */ - DocumentImportEntity importDocuments(String values); + DocumentImportEntity importDocuments(RawData values); /** * Bulk imports the given values into the collection. * - * @param values JSON-encoded array of objects that will be stored as documents + * @param values Raw data representing a collection of documents * @param options Additional options, can be null * @return information about the import */ - DocumentImportEntity importDocuments(String values, DocumentImportOptions options); + DocumentImportEntity importDocuments(RawData values, DocumentImportOptions options); /** * Retrieves the document with the given {@code key} from the collection. * * @param key The key of the document - * @param type The type of the document (POJO, {@link com.arangodb.util.RawJson} or - * {@link com.arangodb.util.RawBytes}) + * @param type The type of the document (POJO or {@link com.arangodb.util.RawData}) * @return the document identified by the key * @see API * Documentation @@ -179,8 +198,7 @@ MultiDocumentEntity> insertDocuments( * Retrieves the document with the given {@code key} from the collection. * * @param key The key of the document - * @param type The type of the document (POJO, {@link com.arangodb.util.RawJson} or - * {@link com.arangodb.util.RawBytes}) + * @param type The type of the document (POJO or {@link com.arangodb.util.RawData}) * @param options Additional options, can be null * @return the document identified by the key * @see API @@ -192,8 +210,7 @@ MultiDocumentEntity> insertDocuments( * Retrieves multiple documents with the given {@code _key} from the collection. * * @param keys The keys of the documents - * @param type The type of the documents (POJO, {@link com.arangodb.util.RawJson} or - * {@link com.arangodb.util.RawBytes}) + * @param type The type of the documents (POJO or {@link com.arangodb.util.RawData}) * @return the documents and possible errors */ MultiDocumentEntity getDocuments(Collection keys, Class type); @@ -202,8 +219,7 @@ MultiDocumentEntity> insertDocuments( * Retrieves multiple documents with the given {@code _key} from the collection. * * @param keys The keys of the documents - * @param type The type of the documents (POJO, {@link com.arangodb.util.RawJson} or - * {@link com.arangodb.util.RawBytes}) + * @param type The type of the documents (POJO or {@link com.arangodb.util.RawData}) * @param options Additional options, can be null * @return the documents and possible errors */ @@ -214,8 +230,7 @@ MultiDocumentEntity> insertDocuments( * precondition is violated * * @param key The key of the document - * @param value A representation of a single document (POJO, {@link com.arangodb.util.RawJson} or - * {@link com.arangodb.util.RawBytes}) + * @param value A representation of a single document (POJO or {@link com.arangodb.util.RawData}) * @return information about the document * @see * API @@ -228,8 +243,7 @@ MultiDocumentEntity> insertDocuments( * precondition is violated * * @param key The key of the document - * @param value A representation of a single document (POJO, {@link com.arangodb.util.RawJson} or - * {@link com.arangodb.util.RawBytes}) + * @param value A representation of a single document (POJO or {@link com.arangodb.util.RawData}) * @param options Additional options * @return information about the document * @see @@ -243,8 +257,7 @@ MultiDocumentEntity> insertDocuments( * precondition is violated * * @param key The key of the document - * @param value A representation of a single document (POJO, {@link com.arangodb.util.RawJson} or - * {@link com.arangodb.util.RawBytes}) + * @param value A representation of a single document (POJO or {@link com.arangodb.util.RawData}) * @param options Additional options * @param type Deserialization target type for the returned documents. * @return information about the document @@ -258,7 +271,33 @@ MultiDocumentEntity> insertDocuments( * Replaces multiple documents in the specified collection with the ones in the values, the replaced documents are * specified by the _key attributes in the documents in values. * - * @param values A List of documents (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) + * @param values Raw data representing a collection of documents + * @return information about the documents + * @see + * API + * Documentation + */ + MultiDocumentEntity> replaceDocuments(RawData values); + + /** + * Replaces multiple documents in the specified collection with the ones in the values, the replaced documents are + * specified by the _key attributes in the documents in values. + * + * @param values Raw data representing a collection of documents + * @param options Additional options + * @return information about the documents + * @see + * API + * Documentation + */ + MultiDocumentEntity> replaceDocuments( + RawData values, DocumentReplaceOptions options); + + /** + * Replaces multiple documents in the specified collection with the ones in the values, the replaced documents are + * specified by the _key attributes in the documents in values. + * + * @param values A List of documents (POJO or {@link com.arangodb.util.RawData}) * @return information about the documents * @see * API @@ -270,8 +309,7 @@ MultiDocumentEntity> insertDocuments( * Replaces multiple documents in the specified collection with the ones in the values, the replaced documents are * specified by the _key attributes in the documents in values. * - * @param values A List of documents (POJO, {@link com.arangodb.util.RawJson} or - * {@link com.arangodb.util.RawBytes}) + * @param values A List of documents (POJO or {@link com.arangodb.util.RawData}) * @param options Additional options * @return information about the documents * @see @@ -285,8 +323,7 @@ MultiDocumentEntity> replaceDocuments( * Replaces multiple documents in the specified collection with the ones in the values, the replaced documents are * specified by the _key attributes in the documents in values. * - * @param values A List of documents (POJO, {@link com.arangodb.util.RawJson} or - * {@link com.arangodb.util.RawBytes}) + * @param values A List of documents (POJO or {@link com.arangodb.util.RawData}) * @param options Additional options * @param type Deserialization target type for the returned documents. * @return information about the documents @@ -303,8 +340,7 @@ MultiDocumentEntity> replaceDocuments( * they do not yet exist, and overwritten in the existing document if they do exist there. * * @param key The key of the document - * @param value A representation of a single document (POJO, {@link com.arangodb.util.RawJson} or - * {@link com.arangodb.util.RawBytes}) + * @param value A representation of a single document (POJO or {@link com.arangodb.util.RawData}) * @return information about the document * @see API * Documentation @@ -317,8 +353,7 @@ MultiDocumentEntity> replaceDocuments( * they do not yet exist, and overwritten in the existing document if they do exist there. * * @param key The key of the document - * @param value A representation of a single document (POJO, {@link com.arangodb.util.RawJson} or - * {@link com.arangodb.util.RawBytes}) + * @param value A representation of a single document (POJO or {@link com.arangodb.util.RawData}) * @param options Additional options * @return information about the document * @see API @@ -332,8 +367,7 @@ MultiDocumentEntity> replaceDocuments( * they do not yet exist, and overwritten in the existing document if they do exist there. * * @param key The key of the document - * @param value A representation of a single document (POJO, {@link com.arangodb.util.RawJson} or - * {@link com.arangodb.util.RawBytes}) + * @param value A representation of a single document (POJO or {@link com.arangodb.util.RawData}) * @param options Additional options * @param returnType Type of the returned newDocument and/or oldDocument * @return information about the document @@ -349,7 +383,37 @@ DocumentUpdateEntity updateDocument(String key, Object value, DocumentUpd * attributes from the patch documents will be added to the existing documents if they do not yet exist, and * overwritten in the existing documents if they do exist there. * - * @param values A list of documents (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) + * @param values Raw data representing a collection of documents + * @return information about the documents + * @see + * API + * Documentation + */ + MultiDocumentEntity> updateDocuments(RawData values); + + /** + * Partially updates documents, the documents to update are specified by the _key attributes in the objects on + * values. Vales must contain a list of document updates with the attributes to patch (the patch documents). All + * attributes from the patch documents will be added to the existing documents if they do not yet exist, and + * overwritten in the existing documents if they do exist there. + * + * @param values Raw data representing a collection of documents + * @param options Additional options + * @return information about the documents + * @see + * API + * Documentation + */ + MultiDocumentEntity> updateDocuments( + RawData values, DocumentUpdateOptions options); + + /** + * Partially updates documents, the documents to update are specified by the _key attributes in the objects on + * values. Vales must contain a list of document updates with the attributes to patch (the patch documents). All + * attributes from the patch documents will be added to the existing documents if they do not yet exist, and + * overwritten in the existing documents if they do exist there. + * + * @param values A list of documents (POJO or {@link com.arangodb.util.RawData}) * @return information about the documents * @see * API @@ -363,8 +427,7 @@ DocumentUpdateEntity updateDocument(String key, Object value, DocumentUpd * attributes from the patch documents will be added to the existing documents if they do not yet exist, and * overwritten in the existing documents if they do exist there. * - * @param values A list of documents (POJO, {@link com.arangodb.util.RawJson} or - * {@link com.arangodb.util.RawBytes}) + * @param values A list of documents (POJO or {@link com.arangodb.util.RawData}) * @param options Additional options * @return information about the documents * @see @@ -380,8 +443,7 @@ MultiDocumentEntity> updateDocuments( * attributes from the patch documents will be added to the existing documents if they do not yet exist, and * overwritten in the existing documents if they do exist there. * - * @param values A list of documents (POJO, {@link com.arangodb.util.RawJson} or - * {@link com.arangodb.util.RawBytes}) + * @param values A list of documents (POJO or {@link com.arangodb.util.RawData}) * @param options Additional options * @param returnType Type of the returned newDocument and/or oldDocument * @return information about the documents @@ -428,6 +490,30 @@ MultiDocumentEntity> updateDocuments( */ DocumentDeleteEntity deleteDocument(String key, DocumentDeleteOptions options, Class type); + /** + * Deletes multiple documents from the collection. + * + * @param values Raw data representing the keys of the documents or the documents themselves + * @return information about the documents + * @see API + * Documentation + */ + MultiDocumentEntity> deleteDocuments(RawData values); + + /** + * Deletes multiple documents from the collection. + * + * @param values Raw data representing the keys of the documents or the documents themselves + * @param options Additional options + * @return information about the documents + * @see API + * Documentation + */ + MultiDocumentEntity> deleteDocuments( + RawData values, DocumentDeleteOptions options); + /** * Deletes multiple documents from the collection. * diff --git a/src/main/java/com/arangodb/ArangoDatabase.java b/src/main/java/com/arangodb/ArangoDatabase.java index af8b02808..16cd93cbf 100644 --- a/src/main/java/com/arangodb/ArangoDatabase.java +++ b/src/main/java/com/arangodb/ArangoDatabase.java @@ -245,8 +245,7 @@ public interface ArangoDatabase extends ArangoSerdeAccessor { * @param query An AQL query string * @param bindVars key/value pairs defining the variables to bind the query to * @param options Additional options that will be passed to the query API, can be null - * @param type The type of the result (POJO, {@link com.arangodb.util.RawJson} or - * {@link com.arangodb.util.RawBytes}) + * @param type The type of the result (POJO or {@link com.arangodb.util.RawData}) * @return cursor of the results * @see * API @@ -260,8 +259,7 @@ public interface ArangoDatabase extends ArangoSerdeAccessor { * * @param query An AQL query string * @param options Additional options that will be passed to the query API, can be null - * @param type The type of the result (POJO, {@link com.arangodb.util.RawJson} or - * {@link com.arangodb.util.RawBytes}) + * @param type The type of the result (POJO or {@link com.arangodb.util.RawData}) * @return cursor of the results * @see * API @@ -275,8 +273,7 @@ public interface ArangoDatabase extends ArangoSerdeAccessor { * * @param query An AQL query string * @param bindVars key/value pairs defining the variables to bind the query to - * @param type The type of the result (POJO, {@link com.arangodb.util.RawJson} or - * {@link com.arangodb.util.RawBytes}) + * @param type The type of the result (POJO or {@link com.arangodb.util.RawData}) * @return cursor of the results * @see * API @@ -289,8 +286,7 @@ public interface ArangoDatabase extends ArangoSerdeAccessor { * result list. * * @param query An AQL query string - * @param type The type of the result (POJO, {@link com.arangodb.util.RawJson} or - * {@link com.arangodb.util.RawBytes}) + * @param type The type of the result (POJO or {@link com.arangodb.util.RawData}) * @return cursor of the results * @see * API @@ -302,8 +298,7 @@ public interface ArangoDatabase extends ArangoSerdeAccessor { * Return an cursor from the given cursor-ID if still existing * * @param cursorId The ID of the cursor - * @param type The type of the result (POJO, {@link com.arangodb.util.RawJson} or - * {@link com.arangodb.util.RawBytes}) + * @param type The type of the result (POJO or {@link com.arangodb.util.RawData}) * @return cursor of the results * @see API @@ -586,8 +580,7 @@ public interface ArangoDatabase extends ArangoSerdeAccessor { * Reads a single document * * @param id The id of the document - * @param type The type of the document (POJO, {@link com.arangodb.util.RawJson} or - * {@link com.arangodb.util.RawBytes}) + * @param type The type of the document (POJO or {@link com.arangodb.util.RawData}) * @return the document identified by the id * @see API * Documentation @@ -598,8 +591,7 @@ public interface ArangoDatabase extends ArangoSerdeAccessor { * Reads a single document * * @param id The id of the document - * @param type The type of the document (POJO, {@link com.arangodb.util.RawJson} or - * {@link com.arangodb.util.RawBytes}) + * @param type The type of the document (POJO or {@link com.arangodb.util.RawData}) * @param options Additional options, can be null * @return the document identified by the id * @see API diff --git a/src/main/java/com/arangodb/ArangoEdgeCollection.java b/src/main/java/com/arangodb/ArangoEdgeCollection.java index 333cdeb34..7558d9f65 100644 --- a/src/main/java/com/arangodb/ArangoEdgeCollection.java +++ b/src/main/java/com/arangodb/ArangoEdgeCollection.java @@ -49,8 +49,7 @@ public interface ArangoEdgeCollection extends ArangoSerdeAccessor { /** * Creates a new edge in the collection * - * @param value A representation of a single edge (POJO, {@link com.arangodb.util.RawJson} or - * {@link com.arangodb.util.RawBytes}) + * @param value A representation of a single edge (POJO or {@link com.arangodb.util.RawData}) * @return information about the edge * @see API Documentation */ @@ -59,8 +58,7 @@ public interface ArangoEdgeCollection extends ArangoSerdeAccessor { /** * Creates a new edge in the collection * - * @param value A representation of a single edge (POJO, {@link com.arangodb.util.RawJson} or - * {@link com.arangodb.util.RawBytes}) + * @param value A representation of a single edge (POJO or {@link com.arangodb.util.RawData}) * @param options Additional options, can be null * @return information about the edge * @see API Documentation @@ -71,8 +69,7 @@ public interface ArangoEdgeCollection extends ArangoSerdeAccessor { * Fetches an existing edge * * @param key The key of the edge - * @param type The type of the edge-document (POJO, {@link com.arangodb.util.RawJson} or - * {@link com.arangodb.util.RawBytes}) + * @param type The type of the edge-document (POJO or {@link com.arangodb.util.RawData}) * @return the edge identified by the key * @see API Documentation */ @@ -82,8 +79,7 @@ public interface ArangoEdgeCollection extends ArangoSerdeAccessor { * Fetches an existing edge * * @param key The key of the edge - * @param type The type of the edge-document (POJO, {@link com.arangodb.util.RawJson} or - * {@link com.arangodb.util.RawBytes}) + * @param type The type of the edge-document (POJO or {@link com.arangodb.util.RawData}) * @param options Additional options, can be null * @return the edge identified by the key * @see API Documentation @@ -95,8 +91,7 @@ public interface ArangoEdgeCollection extends ArangoSerdeAccessor { * violated * * @param key The key of the edge - * @param value A representation of a single edge (POJO, {@link com.arangodb.util.RawJson} or - * {@link com.arangodb.util.RawBytes}) + * @param value A representation of a single edge (POJO or {@link com.arangodb.util.RawData}) * @return information about the edge * @see API Documentation */ @@ -107,8 +102,7 @@ public interface ArangoEdgeCollection extends ArangoSerdeAccessor { * violated * * @param key The key of the edge - * @param value A representation of a single edge (POJO, {@link com.arangodb.util.RawJson} or - * {@link com.arangodb.util.RawBytes}) + * @param value A representation of a single edge (POJO or {@link com.arangodb.util.RawData}) * @param options Additional options, can be null * @return information about the edge * @see API Documentation @@ -121,8 +115,7 @@ public interface ArangoEdgeCollection extends ArangoSerdeAccessor { * do not yet exist, and overwritten in the existing document if they do exist there. * * @param key The key of the edge - * @param value A representation of a single edge (POJO, {@link com.arangodb.util.RawJson} or - * {@link com.arangodb.util.RawBytes}) + * @param value A representation of a single edge (POJO or {@link com.arangodb.util.RawData}) * @return information about the edge * @see API Documentation */ @@ -134,8 +127,7 @@ public interface ArangoEdgeCollection extends ArangoSerdeAccessor { * do not yet exist, and overwritten in the existing document if they do exist there. * * @param key The key of the edge - * @param value A representation of a single edge (POJO, {@link com.arangodb.util.RawJson} or - * {@link com.arangodb.util.RawBytes}) + * @param value A representation of a single edge (POJO or {@link com.arangodb.util.RawData}) * @param options Additional options, can be null * @return information about the edge * @see API Documentation diff --git a/src/main/java/com/arangodb/ArangoVertexCollection.java b/src/main/java/com/arangodb/ArangoVertexCollection.java index 7a3954195..03d755327 100644 --- a/src/main/java/com/arangodb/ArangoVertexCollection.java +++ b/src/main/java/com/arangodb/ArangoVertexCollection.java @@ -58,8 +58,7 @@ public interface ArangoVertexCollection extends ArangoSerdeAccessor { /** * Creates a new vertex in the collection * - * @param value A representation of a single vertex (POJO, {@link com.arangodb.util.RawJson} or - * {@link com.arangodb.util.RawBytes}) + * @param value A representation of a single vertex (POJO or {@link com.arangodb.util.RawData}) * @return information about the vertex * @see * API Documentation @@ -69,8 +68,7 @@ public interface ArangoVertexCollection extends ArangoSerdeAccessor { /** * Creates a new vertex in the collection * - * @param value A representation of a single vertex (POJO, {@link com.arangodb.util.RawJson} or - * {@link com.arangodb.util.RawBytes}) + * @param value A representation of a single vertex (POJO or {@link com.arangodb.util.RawData}) * @param options Additional options, can be null * @return information about the vertex * @see @@ -82,8 +80,7 @@ public interface ArangoVertexCollection extends ArangoSerdeAccessor { * Retrieves the vertex document with the given {@code key} from the collection. * * @param key The key of the vertex - * @param type The type of the vertex-document (POJO, {@link com.arangodb.util.RawJson} or - * {@link com.arangodb.util.RawBytes}) + * @param type The type of the vertex-document (POJO or {@link com.arangodb.util.RawData}) * @return the vertex identified by the key * @see API Documentation */ @@ -93,8 +90,7 @@ public interface ArangoVertexCollection extends ArangoSerdeAccessor { * Retrieves the vertex document with the given {@code key} from the collection. * * @param key The key of the vertex - * @param type The type of the vertex-document (POJO, {@link com.arangodb.util.RawJson} or - * {@link com.arangodb.util.RawBytes}) + * @param type The type of the vertex-document (POJO or {@link com.arangodb.util.RawData}) * @param options Additional options, can be null * @return the vertex identified by the key * @see API Documentation @@ -106,8 +102,7 @@ public interface ArangoVertexCollection extends ArangoSerdeAccessor { * violated * * @param key The key of the vertex - * @param value A representation of a single vertex (POJO, {@link com.arangodb.util.RawJson} or - * {@link com.arangodb.util.RawBytes}) + * @param value A representation of a single vertex (POJO or {@link com.arangodb.util.RawData}) * @return information about the vertex * @see API * Documentation @@ -119,8 +114,7 @@ public interface ArangoVertexCollection extends ArangoSerdeAccessor { * violated * * @param key The key of the vertex - * @param value A representation of a single vertex (POJO, {@link com.arangodb.util.RawJson} or - * {@link com.arangodb.util.RawBytes}) + * @param value A representation of a single vertex (POJO or {@link com.arangodb.util.RawData}) * @param options Additional options, can be null * @return information about the vertex * @see API @@ -134,8 +128,7 @@ public interface ArangoVertexCollection extends ArangoSerdeAccessor { * do not yet exist, and overwritten in the existing document if they do exist there. * * @param key The key of the vertex - * @param value A representation of a single vertex (POJO, {@link com.arangodb.util.RawJson} or - * {@link com.arangodb.util.RawBytes}) + * @param value A representation of a single vertex (POJO or {@link com.arangodb.util.RawData}) * @return information about the vertex * @see * API Documentation @@ -148,8 +141,7 @@ public interface ArangoVertexCollection extends ArangoSerdeAccessor { * do not yet exist, and overwritten in the existing document if they do exist there. * * @param key The key of the vertex - * @param value A representation of a single vertex (POJO, {@link com.arangodb.util.RawJson} or - * {@link com.arangodb.util.RawBytes}) + * @param value A representation of a single vertex (POJO or {@link com.arangodb.util.RawData}) * @param options Additional options, can be null * @return information about the vertex * @see diff --git a/src/main/java/com/arangodb/async/ArangoCollectionAsync.java b/src/main/java/com/arangodb/async/ArangoCollectionAsync.java index d155ba0ed..b2d21d01b 100644 --- a/src/main/java/com/arangodb/async/ArangoCollectionAsync.java +++ b/src/main/java/com/arangodb/async/ArangoCollectionAsync.java @@ -23,6 +23,7 @@ import com.arangodb.ArangoSerdeAccessor; import com.arangodb.entity.*; import com.arangodb.model.*; +import com.arangodb.util.RawData; import java.util.Collection; import java.util.concurrent.CompletableFuture; @@ -54,8 +55,7 @@ public interface ArangoCollectionAsync extends ArangoSerdeAccessor { * Creates a new document from the given document, unless there is already a document with the _key given. If no * _key is given, a new unique _key is generated automatically. * - * @param value A representation of a single document (POJO, {@link com.arangodb.util.RawJson} or - * {@link com.arangodb.util.RawBytes}) + * @param value A representation of a single document (POJO or {@link com.arangodb.util.RawData}) * @return information about the document * @see API * Documentation @@ -66,8 +66,7 @@ public interface ArangoCollectionAsync extends ArangoSerdeAccessor { * Creates a new document from the given document, unless there is already a document with the _key given. If no * _key is given, a new unique _key is generated automatically. * - * @param value A representation of a single document (POJO, {@link com.arangodb.util.RawJson} or - * {@link com.arangodb.util.RawBytes}) + * @param value A representation of a single document (POJO or {@link com.arangodb.util.RawData}) * @param options Additional options * @return information about the document * @see API @@ -79,8 +78,7 @@ public interface ArangoCollectionAsync extends ArangoSerdeAccessor { * Creates a new document from the given document, unless there is already a document with the _key given. If no * _key is given, a new unique _key is generated automatically. * - * @param value A representation of a single document (POJO, {@link com.arangodb.util.RawJson} or - * {@link com.arangodb.util.RawBytes}) + * @param value A representation of a single document (POJO or {@link com.arangodb.util.RawData}) * @param options Additional options * @param type Deserialization target type for the returned documents. * @return information about the document @@ -94,7 +92,32 @@ CompletableFuture> insertDocument(final T value, fin * Creates new documents from the given documents, unless there is already a document with the _key given. If no * _key is given, a new unique _key is generated automatically. * - * @param values A List of documents (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) + * @param values Raw data representing a collection of documents + * @return information about the documents + * @see API + * Documentation + */ + CompletableFuture>> insertDocuments(final RawData values); + + /** + * Creates new documents from the given documents, unless there is already a document with the _key given. If no + * _key is given, a new unique _key is generated automatically. + * + * @param values Raw data representing a collection of documents + * @param options Additional options + * @return information about the documents + * @see API + * Documentation + */ + CompletableFuture>> insertDocuments( + final RawData values, + final DocumentCreateOptions options); + + /** + * Creates new documents from the given documents, unless there is already a document with the _key given. If no + * _key is given, a new unique _key is generated automatically. + * + * @param values A List of documents (POJO or {@link com.arangodb.util.RawData}) * @return information about the documents * @see API * Documentation @@ -105,8 +128,7 @@ CompletableFuture> insertDocument(final T value, fin * Creates new documents from the given documents, unless there is already a document with the _key given. If no * _key is given, a new unique _key is generated automatically. * - * @param values A List of documents (POJO, {@link com.arangodb.util.RawJson} or - * {@link com.arangodb.util.RawBytes}) + * @param values A List of documents (POJO or {@link com.arangodb.util.RawData}) * @param options Additional options * @return information about the documents * @see API @@ -120,8 +142,7 @@ CompletableFuture>> insertDocume * Creates new documents from the given documents, unless there is already a document with the _key given. If no * _key is given, a new unique _key is generated automatically. * - * @param values A List of documents (POJO, {@link com.arangodb.util.RawJson} or - * {@link com.arangodb.util.RawBytes}) + * @param values A List of documents (POJO or {@link com.arangodb.util.RawData}) * @param options Additional options * @param type Deserialization target type for the returned documents. * @return information about the documents @@ -136,7 +157,7 @@ CompletableFuture>> insertDocume /** * Imports documents * - * @param values a list of Objects that will be stored as documents + * @param values A List of documents (POJO or {@link com.arangodb.util.RawData}) * @return information about the import */ CompletableFuture importDocuments(final Collection values); @@ -144,7 +165,7 @@ CompletableFuture>> insertDocume /** * Imports documents * - * @param values a list of Objects that will be stored as documents + * @param values A List of documents (POJO or {@link com.arangodb.util.RawData}) * @param options Additional options, can be null * @return information about the import */ @@ -155,26 +176,25 @@ CompletableFuture importDocuments( /** * Imports documents * - * @param values JSON-encoded array of objects that will be stored as documents + * @param values Raw data representing a collection of documents * @return information about the import */ - CompletableFuture importDocuments(final String values); + CompletableFuture importDocuments(final RawData values); /** * Imports documents * - * @param values JSON-encoded array of objects that will be stored as documents + * @param values Raw data representing a collection of documents * @param options Additional options, can be null * @return information about the import */ - CompletableFuture importDocuments(final String values, final DocumentImportOptions options); + CompletableFuture importDocuments(final RawData values, final DocumentImportOptions options); /** * Reads a single document * * @param key The key of the document - * @param type The type of the document (POJO, {@link com.arangodb.util.RawJson} or - * {@link com.arangodb.util.RawBytes}) + * @param type The type of the document (POJO or {@link com.arangodb.util.RawData}) * @return the document identified by the key * @see API * Documentation @@ -185,8 +205,7 @@ CompletableFuture importDocuments( * Reads a single document * * @param key The key of the document - * @param type The type of the document (POJO, {@link com.arangodb.util.RawJson} or - * {@link com.arangodb.util.RawBytes}) + * @param type The type of the document (POJO or {@link com.arangodb.util.RawData}) * @param options Additional options, can be null * @return the document identified by the key * @see API @@ -198,8 +217,7 @@ CompletableFuture importDocuments( * Reads multiple documents * * @param keys The keys of the documents - * @param type The type of the documents (POJO, {@link com.arangodb.util.RawJson} or - * {@link com.arangodb.util.RawBytes}) + * @param type The type of the documents (POJO or {@link com.arangodb.util.RawData}) * @return the documents and possible errors */ CompletableFuture> getDocuments(final Collection keys, final Class type); @@ -208,8 +226,7 @@ CompletableFuture importDocuments( * Reads multiple documents * * @param keys The keys of the documents - * @param type The type of the documents (POJO, {@link com.arangodb.util.RawJson} or - * {@link com.arangodb.util.RawBytes}) + * @param type The type of the documents (POJO or {@link com.arangodb.util.RawData}) * @param options Additional options, can be null * @return the documents and possible errors */ @@ -223,8 +240,7 @@ CompletableFuture> getDocuments( * violated * * @param key The key of the document - * @param value A representation of a single document (POJO, {@link com.arangodb.util.RawJson} or - * {@link com.arangodb.util.RawBytes}) + * @param value A representation of a single document (POJO or {@link com.arangodb.util.RawData}) * @return information about the document * @see * API @@ -237,8 +253,7 @@ CompletableFuture> getDocuments( * violated * * @param key The key of the document - * @param value A representation of a single document (POJO, {@link com.arangodb.util.RawJson} or - * {@link com.arangodb.util.RawBytes}) + * @param value A representation of a single document (POJO or {@link com.arangodb.util.RawData}) * @param options Additional options * @return information about the document * @see @@ -255,8 +270,7 @@ CompletableFuture> replaceDocument( * violated * * @param key The key of the document - * @param value A representation of a single document (POJO, {@link com.arangodb.util.RawJson} or - * {@link com.arangodb.util.RawBytes}) + * @param value A representation of a single document (POJO or {@link com.arangodb.util.RawData}) * @param options Additional options * @param type Deserialization target type for the returned documents. * @return information about the document @@ -274,7 +288,34 @@ CompletableFuture> replaceDocument( * Replaces multiple documents in the specified collection with the ones in the values, the replaced documents are * specified by the _key attributes in the documents in values. * - * @param values A List of documents (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) + * @param values Raw data representing a collection of documents + * @return information about the documents + * @see + * API + * Documentation + */ + CompletableFuture>> replaceDocuments(final RawData values); + + /** + * Replaces multiple documents in the specified collection with the ones in the values, the replaced documents are + * specified by the _key attributes in the documents in values. + * + * @param values Raw data representing a collection of documents + * @param options Additional options + * @return information about the documents + * @see + * API + * Documentation + */ + CompletableFuture>> replaceDocuments( + final RawData values, + final DocumentReplaceOptions options); + + /** + * Replaces multiple documents in the specified collection with the ones in the values, the replaced documents are + * specified by the _key attributes in the documents in values. + * + * @param values A List of documents (POJO or {@link com.arangodb.util.RawData}) * @return information about the documents * @see * API @@ -286,8 +327,7 @@ CompletableFuture> replaceDocument( * Replaces multiple documents in the specified collection with the ones in the values, the replaced documents are * specified by the _key attributes in the documents in values. * - * @param values A List of documents (POJO, {@link com.arangodb.util.RawJson} or - * {@link com.arangodb.util.RawBytes}) + * @param values A List of documents (POJO or {@link com.arangodb.util.RawData}) * @param options Additional options * @return information about the documents * @see @@ -302,8 +342,7 @@ CompletableFuture>> replaceDocum * Replaces multiple documents in the specified collection with the ones in the values, the replaced documents are * specified by the _key attributes in the documents in values. * - * @param values A List of documents (POJO, {@link com.arangodb.util.RawJson} or - * {@link com.arangodb.util.RawBytes}) + * @param values A List of documents (POJO or {@link com.arangodb.util.RawData}) * @param options Additional options * @param type Deserialization target type for the returned documents. * @return information about the documents @@ -322,8 +361,7 @@ CompletableFuture>> replaceDocum * they do not yet exist, and overwritten in the existing document if they do exist there. * * @param key The key of the document - * @param value A representation of a single document (POJO, {@link com.arangodb.util.RawJson} or - * {@link com.arangodb.util.RawBytes}) + * @param value A representation of a single document (POJO or {@link com.arangodb.util.RawData}) * @return information about the document * @see API * Documentation @@ -336,8 +374,7 @@ CompletableFuture>> replaceDocum * they do not yet exist, and overwritten in the existing document if they do exist there. * * @param key The key of the document - * @param value A representation of a single document (POJO, {@link com.arangodb.util.RawJson} or - * {@link com.arangodb.util.RawBytes}) + * @param value A representation of a single document (POJO or {@link com.arangodb.util.RawData}) * @param options Additional options * @return information about the document * @see API @@ -354,8 +391,7 @@ CompletableFuture> updateDocument( * they do not yet exist, and overwritten in the existing document if they do exist there. * * @param key The key of the document - * @param value A representation of a single document (POJO, {@link com.arangodb.util.RawJson} or - * {@link com.arangodb.util.RawBytes}) + * @param value A representation of a single document (POJO or {@link com.arangodb.util.RawData}) * @param options Additional options * @param returnType Type of the returned newDocument and/or oldDocument * @return information about the document @@ -374,7 +410,38 @@ CompletableFuture> updateDocument( * attributes from the patch documents will be added to the existing documents if they do not yet exist, and * overwritten in the existing documents if they do exist there. * - * @param values A list of documents (POJO, {@link com.arangodb.util.RawJson} or {@link com.arangodb.util.RawBytes}) + * @param values Raw data representing a collection of documents + * @return information about the documents + * @see + * API + * Documentation + */ + CompletableFuture>> updateDocuments(final RawData values); + + /** + * Partially updates documents, the documents to update are specified by the _key attributes in the objects on + * values. Vales must contain a list of document updates with the attributes to patch (the patch documents). All + * attributes from the patch documents will be added to the existing documents if they do not yet exist, and + * overwritten in the existing documents if they do exist there. + * + * @param values Raw data representing a collection of documents + * @param options Additional options + * @return information about the documents + * @see + * API + * Documentation + */ + CompletableFuture>> updateDocuments( + final RawData values, + final DocumentUpdateOptions options); + + /** + * Partially updates documents, the documents to update are specified by the _key attributes in the objects on + * values. Vales must contain a list of document updates with the attributes to patch (the patch documents). All + * attributes from the patch documents will be added to the existing documents if they do not yet exist, and + * overwritten in the existing documents if they do exist there. + * + * @param values A list of documents (POJO or {@link com.arangodb.util.RawData}) * @return information about the documents * @see * API @@ -388,8 +455,7 @@ CompletableFuture> updateDocument( * attributes from the patch documents will be added to the existing documents if they do not yet exist, and * overwritten in the existing documents if they do exist there. * - * @param values A list of documents (POJO, {@link com.arangodb.util.RawJson} or - * {@link com.arangodb.util.RawBytes}) + * @param values A list of documents (POJO or {@link com.arangodb.util.RawData}) * @param options Additional options * @return information about the documents * @see @@ -406,8 +472,7 @@ CompletableFuture>> updateDocume * attributes from the patch documents will be added to the existing documents if they do not yet exist, and * overwritten in the existing documents if they do exist there. * - * @param values A list of documents (POJO, {@link com.arangodb.util.RawJson} or - * {@link com.arangodb.util.RawBytes}) + * @param values A list of documents (POJO or {@link com.arangodb.util.RawData}) * @param options Additional options * @param returnType Type of the returned newDocument and/or oldDocument * @return information about the documents @@ -461,6 +526,31 @@ CompletableFuture> deleteDocument( final DocumentDeleteOptions options, final Class type); + /** + * Removes multiple document + * + * @param values Raw data representing the keys of the documents or the documents themselves + * @return information about the documents + * @see API + * Documentation + */ + CompletableFuture>> deleteDocuments(final RawData values); + + /** + * Removes multiple document + * + * @param values Raw data representing the keys of the documents or the documents themselves + * @param options Additional options + * @return information about the documents + * @see API + * Documentation + */ + CompletableFuture>> deleteDocuments( + final RawData values, + final DocumentDeleteOptions options); + /** * Removes multiple document * diff --git a/src/main/java/com/arangodb/async/ArangoDatabaseAsync.java b/src/main/java/com/arangodb/async/ArangoDatabaseAsync.java index 6dc963151..73db9152e 100644 --- a/src/main/java/com/arangodb/async/ArangoDatabaseAsync.java +++ b/src/main/java/com/arangodb/async/ArangoDatabaseAsync.java @@ -250,8 +250,7 @@ public interface ArangoDatabaseAsync extends ArangoSerdeAccessor { * @param query contains the query string to be executed * @param bindVars key/value pairs representing the bind parameters * @param options Additional options, can be null - * @param type The type of the result (POJO, {@link com.arangodb.util.RawJson} or - * {@link com.arangodb.util.RawBytes}) + * @param type The type of the result (POJO or {@link com.arangodb.util.RawData}) * @return cursor of the results * @see * API @@ -269,8 +268,7 @@ CompletableFuture> query( * * @param query contains the query string to be executed * @param options Additional options, can be null - * @param type The type of the result (POJO, {@link com.arangodb.util.RawJson} or - * {@link com.arangodb.util.RawBytes}) + * @param type The type of the result (POJO or {@link com.arangodb.util.RawData}) * @return cursor of the results * @see * API @@ -287,8 +285,7 @@ CompletableFuture> query( * * @param query contains the query string to be executed * @param bindVars key/value pairs representing the bind parameters - * @param type The type of the result (POJO, {@link com.arangodb.util.RawJson} or - * {@link com.arangodb.util.RawBytes}) + * @param type The type of the result (POJO or {@link com.arangodb.util.RawData}) * @return cursor of the results * @see * API @@ -304,8 +301,7 @@ CompletableFuture> query( * result list. * * @param query contains the query string to be executed - * @param type The type of the result (POJO, {@link com.arangodb.util.RawJson} or - * {@link com.arangodb.util.RawBytes}) + * @param type The type of the result (POJO or {@link com.arangodb.util.RawData}) * @return cursor of the results * @see * API @@ -317,8 +313,7 @@ CompletableFuture> query( * Return an cursor from the given cursor-ID if still existing * * @param cursorId The ID of the cursor - * @param type The type of the result (POJO, {@link com.arangodb.util.RawJson} or - * {@link com.arangodb.util.RawBytes}) + * @param type The type of the result (POJO or {@link com.arangodb.util.RawData}) * @return cursor of the results * @see createGraph( * Execute a server-side transaction * * @param action the actual transaction operations to be executed, in the form of stringified JavaScript code - * @param type The type of the result (POJO, {@link com.arangodb.util.RawJson} or - * {@link com.arangodb.util.RawBytes}) + * @param type The type of the result (POJO or {@link com.arangodb.util.RawData}) * @param options Additional options, can be null * @return the result of the transaction if it succeeded * @see API @@ -615,8 +609,7 @@ CompletableFuture createGraph( * Reads a single document * * @param id The id of the document - * @param type The type of the document (POJO, {@link com.arangodb.util.RawJson} or - * {@link com.arangodb.util.RawBytes}) + * @param type The type of the document (POJO or {@link com.arangodb.util.RawData}) * @return the document identified by the id * @see API * Documentation @@ -627,8 +620,7 @@ CompletableFuture createGraph( * Reads a single document * * @param id The id of the document - * @param type The type of the document (POJO, {@link com.arangodb.util.RawJson} or - * {@link com.arangodb.util.RawBytes}) + * @param type The type of the document (POJO or {@link com.arangodb.util.RawData}) * @param options Additional options, can be null * @return the document identified by the id * @see API diff --git a/src/main/java/com/arangodb/async/ArangoEdgeCollectionAsync.java b/src/main/java/com/arangodb/async/ArangoEdgeCollectionAsync.java index d2465cd8f..eab16f39c 100644 --- a/src/main/java/com/arangodb/async/ArangoEdgeCollectionAsync.java +++ b/src/main/java/com/arangodb/async/ArangoEdgeCollectionAsync.java @@ -52,8 +52,7 @@ public interface ArangoEdgeCollectionAsync extends ArangoSerdeAccessor { /** * Creates a new edge in the collection * - * @param value A representation of a single edge (POJO, {@link com.arangodb.util.RawJson} or - * {@link com.arangodb.util.RawBytes}) + * @param value A representation of a single edge (POJO or {@link com.arangodb.util.RawData} * @return information about the edge * @see API Documentation */ @@ -62,8 +61,7 @@ public interface ArangoEdgeCollectionAsync extends ArangoSerdeAccessor { /** * Creates a new edge in the collection * - * @param value A representation of a single edge (POJO, {@link com.arangodb.util.RawJson} or - * {@link com.arangodb.util.RawBytes}) + * @param value A representation of a single edge (POJO or {@link com.arangodb.util.RawData} * @param options Additional options, can be null * @return information about the edge * @see API Documentation @@ -74,8 +72,7 @@ public interface ArangoEdgeCollectionAsync extends ArangoSerdeAccessor { * Fetches an existing edge * * @param key The key of the edge - * @param type The type of the edge-document (POJO, {@link com.arangodb.util.RawJson} or - * {@link com.arangodb.util.RawBytes}) + * @param type The type of the edge-document (POJO or {@link com.arangodb.util.RawData} * @return the edge identified by the key * @see API Documentation */ @@ -85,8 +82,7 @@ public interface ArangoEdgeCollectionAsync extends ArangoSerdeAccessor { * Fetches an existing edge * * @param key The key of the edge - * @param type The type of the edge-document (POJO, {@link com.arangodb.util.RawJson} or - * {@link com.arangodb.util.RawBytes}) + * @param type The type of the edge-document (POJO or {@link com.arangodb.util.RawData} * @param options Additional options, can be null * @return the edge identified by the key * @see API Documentation diff --git a/src/main/java/com/arangodb/async/ArangoVertexCollectionAsync.java b/src/main/java/com/arangodb/async/ArangoVertexCollectionAsync.java index 38e22d660..c26be8f55 100644 --- a/src/main/java/com/arangodb/async/ArangoVertexCollectionAsync.java +++ b/src/main/java/com/arangodb/async/ArangoVertexCollectionAsync.java @@ -62,8 +62,7 @@ public interface ArangoVertexCollectionAsync extends ArangoSerdeAccessor { /** * Creates a new vertex in the collection * - * @param value A representation of a single vertex (POJO, {@link com.arangodb.util.RawJson} or - * {@link com.arangodb.util.RawBytes}) + * @param value A representation of a single vertex (POJO or {@link com.arangodb.util.RawData}) * @return information about the vertex * @see * API Documentation @@ -73,8 +72,7 @@ public interface ArangoVertexCollectionAsync extends ArangoSerdeAccessor { /** * Creates a new vertex in the collection * - * @param value A representation of a single vertex (POJO, {@link com.arangodb.util.RawJson} or - * {@link com.arangodb.util.RawBytes}) + * @param value A representation of a single vertex (POJO or {@link com.arangodb.util.RawData}) * @param options Additional options, can be null * @return information about the vertex * @see @@ -86,8 +84,7 @@ public interface ArangoVertexCollectionAsync extends ArangoSerdeAccessor { * Fetches an existing vertex * * @param key The key of the vertex - * @param type The type of the vertex-document (POJO, {@link com.arangodb.util.RawJson} or - * {@link com.arangodb.util.RawBytes}) + * @param type The type of the vertex-document (POJO or {@link com.arangodb.util.RawData}) * @return the vertex identified by the key * @see API Documentation */ @@ -97,8 +94,7 @@ public interface ArangoVertexCollectionAsync extends ArangoSerdeAccessor { * Fetches an existing vertex * * @param key The key of the vertex - * @param type The type of the vertex-document (POJO, {@link com.arangodb.util.RawJson} or - * {@link com.arangodb.util.RawBytes}) + * @param type The type of the vertex-document (POJO or {@link com.arangodb.util.RawData}) * @param options Additional options, can be null * @return the vertex identified by the key * @see API Documentation diff --git a/src/main/java/com/arangodb/async/internal/ArangoCollectionAsyncImpl.java b/src/main/java/com/arangodb/async/internal/ArangoCollectionAsyncImpl.java index ba93556ba..b06bc0ebf 100644 --- a/src/main/java/com/arangodb/async/internal/ArangoCollectionAsyncImpl.java +++ b/src/main/java/com/arangodb/async/internal/ArangoCollectionAsyncImpl.java @@ -25,6 +25,7 @@ import com.arangodb.internal.InternalArangoCollection; import com.arangodb.internal.util.DocumentUtil; import com.arangodb.model.*; +import com.arangodb.util.RawData; import java.util.Collection; import java.util.Objects; @@ -65,6 +66,22 @@ public CompletableFuture> insertDocument(T value, Do constructParametricType(DocumentCreateEntity.class, type)); } + @Override + public CompletableFuture>> insertDocuments(RawData values) { + return executor + .execute(insertDocumentsRequest(values, new DocumentCreateOptions()), + insertDocumentsResponseDeserializer(Void.class)); + } + + @Override + @SuppressWarnings("unchecked") + public CompletableFuture>> insertDocuments(RawData values, + DocumentCreateOptions options) { + return executor + .execute(insertDocumentsRequest(values, options), + insertDocumentsResponseDeserializer((Class) values.getClass())); + } + @Override public CompletableFuture>> insertDocuments( final Collection values) { @@ -101,15 +118,13 @@ public CompletableFuture importDocuments( } @Override - public CompletableFuture importDocuments(final String values) { + public CompletableFuture importDocuments(RawData values) { return executor.execute(importDocumentsRequest(values, new DocumentImportOptions()), DocumentImportEntity.class); } @Override - public CompletableFuture importDocuments( - final String values, - final DocumentImportOptions options) { + public CompletableFuture importDocuments(RawData values, DocumentImportOptions options) { return executor.execute(importDocumentsRequest(values, options), DocumentImportEntity.class); } @@ -167,6 +182,20 @@ public CompletableFuture> replaceDocument(String key constructParametricType(DocumentUpdateEntity.class, type)); } + @Override + public CompletableFuture>> replaceDocuments(RawData values) { + return executor.execute(replaceDocumentsRequest(values, new DocumentReplaceOptions()), + replaceDocumentsResponseDeserializer(Void.class)); + } + + @Override + @SuppressWarnings("unchecked") + public CompletableFuture>> replaceDocuments(RawData values, + DocumentReplaceOptions options) { + return executor.execute(replaceDocumentsRequest(values, options), + replaceDocumentsResponseDeserializer((Class) values.getClass())); + } + @Override public CompletableFuture>> replaceDocuments( final Collection values) { @@ -212,6 +241,22 @@ public CompletableFuture> updateDocument( constructParametricType(DocumentUpdateEntity.class, returnType)); } + @Override + public CompletableFuture>> updateDocuments(RawData values) { + return executor + .execute(updateDocumentsRequest(values, new DocumentUpdateOptions()), + updateDocumentsResponseDeserializer(Void.class)); + } + + @Override + @SuppressWarnings("unchecked") + public CompletableFuture>> updateDocuments(RawData values, + DocumentUpdateOptions options) { + return executor + .execute(updateDocumentsRequest(values, options), + updateDocumentsResponseDeserializer((Class) values.getClass())); + } + @Override public CompletableFuture>> updateDocuments( final Collection values) { @@ -254,6 +299,20 @@ public CompletableFuture> deleteDocument( constructParametricType(DocumentDeleteEntity.class, type)); } + @Override + public CompletableFuture>> deleteDocuments(RawData values) { + return executor.execute(deleteDocumentsRequest(values, new DocumentDeleteOptions()), + deleteDocumentsResponseDeserializer(Void.class)); + } + + @Override + @SuppressWarnings("unchecked") + public CompletableFuture>> deleteDocuments(RawData values, + DocumentDeleteOptions options) { + return executor.execute(deleteDocumentsRequest(values, options), + deleteDocumentsResponseDeserializer((Class) values.getClass())); + } + @Override public CompletableFuture>> deleteDocuments( final Collection values) { diff --git a/src/main/java/com/arangodb/internal/ArangoCollectionImpl.java b/src/main/java/com/arangodb/internal/ArangoCollectionImpl.java index 9c211d35d..8fd3102e7 100644 --- a/src/main/java/com/arangodb/internal/ArangoCollectionImpl.java +++ b/src/main/java/com/arangodb/internal/ArangoCollectionImpl.java @@ -25,6 +25,7 @@ import com.arangodb.entity.*; import com.arangodb.internal.util.DocumentUtil; import com.arangodb.model.*; +import com.arangodb.util.RawData; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -64,6 +65,22 @@ public DocumentCreateEntity insertDocument(final T value, final DocumentC constructParametricType(DocumentCreateEntity.class, type)); } + @Override + public MultiDocumentEntity> insertDocuments(RawData values) { + return executor + .execute(insertDocumentsRequest(values, new DocumentCreateOptions()), + insertDocumentsResponseDeserializer(Void.class)); + } + + @Override + @SuppressWarnings("unchecked") + public MultiDocumentEntity> insertDocuments(RawData values, + DocumentCreateOptions options) { + return executor + .execute(insertDocumentsRequest(values, options), + insertDocumentsResponseDeserializer((Class) values.getClass())); + } + @Override public MultiDocumentEntity> insertDocuments(final Collection values) { return executor @@ -97,12 +114,12 @@ public DocumentImportEntity importDocuments(final Collection values, final Do } @Override - public DocumentImportEntity importDocuments(final String values) { + public DocumentImportEntity importDocuments(RawData values) { return importDocuments(values, new DocumentImportOptions()); } @Override - public DocumentImportEntity importDocuments(final String values, final DocumentImportOptions options) { + public DocumentImportEntity importDocuments(RawData values, DocumentImportOptions options) { return executor.execute(importDocumentsRequest(values, options), DocumentImportEntity.class); } @@ -165,6 +182,20 @@ public DocumentUpdateEntity replaceDocument(String key, T value, Document constructParametricType(DocumentUpdateEntity.class, type)); } + @Override + public MultiDocumentEntity> replaceDocuments(RawData values) { + return executor.execute(replaceDocumentsRequest(values, new DocumentReplaceOptions()), + replaceDocumentsResponseDeserializer(Void.class)); + } + + @Override + @SuppressWarnings("unchecked") + public MultiDocumentEntity> replaceDocuments(RawData values, + DocumentReplaceOptions options) { + return executor.execute(replaceDocumentsRequest(values, options), + replaceDocumentsResponseDeserializer((Class) values.getClass())); + } + @Override public MultiDocumentEntity> replaceDocuments(final Collection values) { return executor.execute(replaceDocumentsRequest(values, new DocumentReplaceOptions()), @@ -204,6 +235,22 @@ public DocumentUpdateEntity updateDocument( constructParametricType(DocumentUpdateEntity.class, returnType)); } + @Override + public MultiDocumentEntity> updateDocuments(RawData values) { + return executor + .execute(updateDocumentsRequest(values, new DocumentUpdateOptions()), + updateDocumentsResponseDeserializer(Void.class)); + } + + @Override + @SuppressWarnings("unchecked") + public MultiDocumentEntity> updateDocuments(RawData values, + DocumentUpdateOptions options) { + return executor + .execute(updateDocumentsRequest(values, options), + updateDocumentsResponseDeserializer((Class) values.getClass())); + } + @Override public MultiDocumentEntity> updateDocuments(final Collection values) { return updateDocuments(values, new DocumentUpdateOptions(), Void.class); @@ -240,6 +287,20 @@ public DocumentDeleteEntity deleteDocument( constructParametricType(DocumentDeleteEntity.class, type)); } + @Override + public MultiDocumentEntity> deleteDocuments(RawData values) { + return executor.execute(deleteDocumentsRequest(values, new DocumentDeleteOptions()), + deleteDocumentsResponseDeserializer(Void.class)); + } + + @Override + @SuppressWarnings("unchecked") + public MultiDocumentEntity> deleteDocuments(RawData values, + DocumentDeleteOptions options) { + return executor.execute(deleteDocumentsRequest(values, options), + deleteDocumentsResponseDeserializer((Class) values.getClass())); + } + @Override public MultiDocumentEntity> deleteDocuments(final Collection values) { return deleteDocuments(values, new DocumentDeleteOptions(), Void.class); diff --git a/src/main/java/com/arangodb/internal/InternalArangoCollection.java b/src/main/java/com/arangodb/internal/InternalArangoCollection.java index 58061cc0e..4d6831533 100644 --- a/src/main/java/com/arangodb/internal/InternalArangoCollection.java +++ b/src/main/java/com/arangodb/internal/InternalArangoCollection.java @@ -24,10 +24,10 @@ import com.arangodb.DbName; import com.arangodb.entity.*; import com.arangodb.internal.ArangoExecutor.ResponseDeserializer; -import com.arangodb.internal.serde.SerdeUtils; import com.arangodb.internal.util.DocumentUtil; import com.arangodb.internal.util.RequestUtils; import com.arangodb.model.*; +import com.arangodb.util.RawData; import com.arangodb.velocystream.Request; import com.arangodb.velocystream.RequestType; import com.fasterxml.jackson.databind.JsonNode; @@ -84,22 +84,25 @@ public String name() { } protected Request insertDocumentRequest(final T value, final DocumentCreateOptions options) { - final Request request = request(db.dbName(), RequestType.POST, PATH_API_DOCUMENT, name); - final DocumentCreateOptions params = (options != null ? options : new DocumentCreateOptions()); - request.putQueryParam(ArangoRequestParam.WAIT_FOR_SYNC, params.getWaitForSync()); - request.putQueryParam(RETURN_NEW, params.getReturnNew()); - request.putQueryParam(RETURN_OLD, params.getReturnOld()); - request.putQueryParam(SILENT, params.getSilent()); - request.putQueryParam(OVERWRITE_MODE, params.getOverwriteMode() != null ? - params.getOverwriteMode().getValue() : null); - request.putQueryParam(MERGE_OBJECTS, params.getMergeObjects()); - request.putQueryParam(KEEP_NULL, params.getKeepNull()); - request.putHeaderParam(TRANSACTION_ID, params.getStreamTransactionId()); + final Request request = createInsertDocumentRequest(options); request.setBody(getSerde().serializeUserData(value)); return request; } - protected Request insertDocumentsRequest(final Collection values, final DocumentCreateOptions params) { + protected Request insertDocumentsRequest(final RawData values, final DocumentCreateOptions options) { + Request request = createInsertDocumentRequest(options); + request.setBody(getSerde().serialize(values)); + return request; + } + + protected Request insertDocumentsRequest(final Collection values, final DocumentCreateOptions options) { + Request request = createInsertDocumentRequest(options); + request.setBody(getSerde().serializeCollectionUserData(values)); + return request; + } + + private Request createInsertDocumentRequest(final DocumentCreateOptions options) { + final DocumentCreateOptions params = (options != null ? options : new DocumentCreateOptions()); final Request request = request(db.dbName(), RequestType.POST, PATH_API_DOCUMENT, name); request.putQueryParam(ArangoRequestParam.WAIT_FOR_SYNC, params.getWaitForSync()); request.putQueryParam(RETURN_NEW, params.getReturnNew()); @@ -110,7 +113,6 @@ protected Request insertDocumentsRequest(final Collection values, final D request.putQueryParam(MERGE_OBJECTS, params.getMergeObjects()); request.putQueryParam(KEEP_NULL, params.getKeepNull()); request.putHeaderParam(TRANSACTION_ID, params.getStreamTransactionId()); - request.setBody(getSerde().serializeCollectionUserData(values)); return request; } @@ -141,8 +143,8 @@ protected ResponseDeserializer>> }; } - protected Request importDocumentsRequest(final String values, final DocumentImportOptions options) { - return importDocumentsRequest(options).putQueryParam("type", ImportType.auto).setBody(getSerde().serialize(SerdeUtils.INSTANCE.parseJson(values))); + protected Request importDocumentsRequest(final RawData values, final DocumentImportOptions options) { + return importDocumentsRequest(options).putQueryParam("type", ImportType.auto).setBody(getSerde().serialize(values)); } protected Request importDocumentsRequest(final Collection values, final DocumentImportOptions options) { @@ -218,22 +220,26 @@ protected ResponseDeserializer> getDocumentsResponseD protected Request replaceDocumentRequest( final String key, final T value, final DocumentReplaceOptions options) { - final Request request = request(db.dbName(), RequestType.PUT, PATH_API_DOCUMENT, - DocumentUtil.createDocumentHandle(name, key)); - final DocumentReplaceOptions params = (options != null ? options : new DocumentReplaceOptions()); - request.putHeaderParam(ArangoRequestParam.IF_MATCH, params.getIfMatch()); - request.putHeaderParam(TRANSACTION_ID, params.getStreamTransactionId()); - request.putQueryParam(ArangoRequestParam.WAIT_FOR_SYNC, params.getWaitForSync()); - request.putQueryParam(IGNORE_REVS, params.getIgnoreRevs()); - request.putQueryParam(RETURN_NEW, params.getReturnNew()); - request.putQueryParam(RETURN_OLD, params.getReturnOld()); - request.putQueryParam(SILENT, params.getSilent()); + final Request request = createReplaceDocumentRequest(options, DocumentUtil.createDocumentHandle(name, key)); request.setBody(getSerde().serializeUserData(value)); return request; } - protected Request replaceDocumentsRequest(final Collection values, final DocumentReplaceOptions params) { - final Request request = request(db.dbName(), RequestType.PUT, PATH_API_DOCUMENT, name); + protected Request replaceDocumentsRequest(final Collection values, final DocumentReplaceOptions options) { + final Request request = createReplaceDocumentRequest(options, name); + request.setBody(getSerde().serializeCollectionUserData(values)); + return request; + } + + protected Request replaceDocumentsRequest(final RawData values, final DocumentReplaceOptions options) { + final Request request = createReplaceDocumentRequest(options, name); + request.setBody(getSerde().serialize(values)); + return request; + } + + private Request createReplaceDocumentRequest(final DocumentReplaceOptions options, String path) { + final DocumentReplaceOptions params = (options != null ? options : new DocumentReplaceOptions()); + final Request request = request(db.dbName(), RequestType.PUT, PATH_API_DOCUMENT, path); request.putHeaderParam(ArangoRequestParam.IF_MATCH, params.getIfMatch()); request.putHeaderParam(TRANSACTION_ID, params.getStreamTransactionId()); request.putQueryParam(ArangoRequestParam.WAIT_FOR_SYNC, params.getWaitForSync()); @@ -241,7 +247,6 @@ protected Request replaceDocumentsRequest(final Collection values, final request.putQueryParam(RETURN_NEW, params.getReturnNew()); request.putQueryParam(RETURN_OLD, params.getReturnOld()); request.putQueryParam(SILENT, params.getSilent()); - request.setBody(getSerde().serializeCollectionUserData(values)); return request; } @@ -274,35 +279,35 @@ protected ResponseDeserializer>> } protected Request updateDocumentRequest(final String key, final T value, final DocumentUpdateOptions options) { - final Request request = request(db.dbName(), RequestType.PATCH, PATH_API_DOCUMENT, - DocumentUtil.createDocumentHandle(name, key)); - final DocumentUpdateOptions params = (options != null ? options : new DocumentUpdateOptions()); - request.putHeaderParam(ArangoRequestParam.IF_MATCH, params.getIfMatch()); - request.putHeaderParam(TRANSACTION_ID, params.getStreamTransactionId()); - request.putQueryParam(ArangoRequestParam.KEEP_NULL, params.getKeepNull()); - request.putQueryParam(ArangoRequestParam.WAIT_FOR_SYNC, params.getWaitForSync()); - request.putQueryParam(MERGE_OBJECTS, params.getMergeObjects()); - request.putQueryParam(IGNORE_REVS, params.getIgnoreRevs()); - request.putQueryParam(RETURN_NEW, params.getReturnNew()); - request.putQueryParam(RETURN_OLD, params.getReturnOld()); - request.putQueryParam(SILENT, params.getSilent()); + final Request request = createUpdateDocumentRequest(options, DocumentUtil.createDocumentHandle(name, key)); request.setBody(getSerde().serializeUserData(value)); return request; } - protected Request updateDocumentsRequest(final Collection values, final DocumentUpdateOptions params) { - final Request request = request(db.dbName(), RequestType.PATCH, PATH_API_DOCUMENT, name); - final Boolean keepNull = params.getKeepNull(); + protected Request updateDocumentsRequest(final Collection values, final DocumentUpdateOptions options) { + final Request request = createUpdateDocumentRequest(options, name); + request.setBody(getSerde().serializeCollectionUserData(values)); + return request; + } + + protected Request updateDocumentsRequest(final RawData values, final DocumentUpdateOptions options) { + final Request request = createUpdateDocumentRequest(options, name); + request.setBody(getSerde().serialize(values)); + return request; + } + + private Request createUpdateDocumentRequest(final DocumentUpdateOptions options, String path) { + final DocumentUpdateOptions params = (options != null ? options : new DocumentUpdateOptions()); + final Request request = request(db.dbName(), RequestType.PATCH, PATH_API_DOCUMENT, path); request.putHeaderParam(ArangoRequestParam.IF_MATCH, params.getIfMatch()); request.putHeaderParam(TRANSACTION_ID, params.getStreamTransactionId()); - request.putQueryParam(ArangoRequestParam.KEEP_NULL, keepNull); + request.putQueryParam(ArangoRequestParam.KEEP_NULL, params.getKeepNull()); request.putQueryParam(ArangoRequestParam.WAIT_FOR_SYNC, params.getWaitForSync()); request.putQueryParam(MERGE_OBJECTS, params.getMergeObjects()); request.putQueryParam(IGNORE_REVS, params.getIgnoreRevs()); request.putQueryParam(RETURN_NEW, params.getReturnNew()); request.putQueryParam(RETURN_OLD, params.getReturnOld()); request.putQueryParam(SILENT, params.getSilent()); - request.setBody(getSerde().serializeCollectionUserData(values)); return request; } @@ -335,25 +340,29 @@ protected ResponseDeserializer>> } protected Request deleteDocumentRequest(final String key, final DocumentDeleteOptions options) { - final Request request = request(db.dbName(), RequestType.DELETE, PATH_API_DOCUMENT, - DocumentUtil.createDocumentHandle(name, key)); - final DocumentDeleteOptions params = (options != null ? options : new DocumentDeleteOptions()); - request.putHeaderParam(ArangoRequestParam.IF_MATCH, params.getIfMatch()); - request.putHeaderParam(TRANSACTION_ID, params.getStreamTransactionId()); - request.putQueryParam(ArangoRequestParam.WAIT_FOR_SYNC, params.getWaitForSync()); - request.putQueryParam(RETURN_OLD, params.getReturnOld()); - request.putQueryParam(SILENT, params.getSilent()); + return createDeleteDocumentRequest(options, DocumentUtil.createDocumentHandle(name, key)); + } + + protected Request deleteDocumentsRequest(final Collection docs, final DocumentDeleteOptions options) { + final Request request = createDeleteDocumentRequest(options, name); + request.setBody(getSerde().serializeCollectionUserData(docs)); return request; } - protected Request deleteDocumentsRequest(final Collection keys, final DocumentDeleteOptions options) { - final Request request = request(db.dbName(), RequestType.DELETE, PATH_API_DOCUMENT, name); + protected Request deleteDocumentsRequest(final RawData docs, final DocumentDeleteOptions options) { + final Request request = createDeleteDocumentRequest(options, name); + request.setBody(getSerde().serialize(docs)); + return request; + } + + private Request createDeleteDocumentRequest(final DocumentDeleteOptions options, String path){ final DocumentDeleteOptions params = (options != null ? options : new DocumentDeleteOptions()); + final Request request = request(db.dbName(), RequestType.DELETE, PATH_API_DOCUMENT, path); + request.putHeaderParam(ArangoRequestParam.IF_MATCH, params.getIfMatch()); request.putHeaderParam(TRANSACTION_ID, params.getStreamTransactionId()); request.putQueryParam(ArangoRequestParam.WAIT_FOR_SYNC, params.getWaitForSync()); request.putQueryParam(RETURN_OLD, params.getReturnOld()); request.putQueryParam(SILENT, params.getSilent()); - request.setBody(getSerde().serialize(keys)); return request; } diff --git a/src/main/java/com/arangodb/util/RawBytes.java b/src/main/java/com/arangodb/util/RawBytes.java index 82c9adaae..8e9aded1b 100644 --- a/src/main/java/com/arangodb/util/RawBytes.java +++ b/src/main/java/com/arangodb/util/RawBytes.java @@ -19,7 +19,7 @@ * The driver's {@link InternalSerde} supports serializing and deserializing to and from * {@code RawBytes}. */ -public class RawBytes { +public class RawBytes implements RawData { private final byte[] value; protected RawBytes(final byte[] value) { diff --git a/src/main/java/com/arangodb/util/RawData.java b/src/main/java/com/arangodb/util/RawData.java new file mode 100644 index 000000000..610ec7827 --- /dev/null +++ b/src/main/java/com/arangodb/util/RawData.java @@ -0,0 +1,17 @@ +package com.arangodb.util; + +/** + * Wrapper for raw data, current implementations are: + * - {@link RawBytes} + * - {@link RawJson} + */ +public interface RawData { + static RawJson of(final String value) { + return RawJson.of(value); + } + + static RawBytes of(final byte[] value) { + return RawBytes.of(value); + } + +} diff --git a/src/main/java/com/arangodb/util/RawJson.java b/src/main/java/com/arangodb/util/RawJson.java index 45bad862d..3642af973 100644 --- a/src/main/java/com/arangodb/util/RawJson.java +++ b/src/main/java/com/arangodb/util/RawJson.java @@ -13,7 +13,7 @@ * The driver's {@link InternalSerde} supports serializing and deserializing to and from * {@code RawJson}. */ -public class RawJson { +public class RawJson implements RawData { private final String value; protected RawJson(final String value) { diff --git a/src/test/java/com/arangodb/ArangoCollectionTest.java b/src/test/java/com/arangodb/ArangoCollectionTest.java index ca0c813c3..0c3df4279 100644 --- a/src/test/java/com/arangodb/ArangoCollectionTest.java +++ b/src/test/java/com/arangodb/ArangoCollectionTest.java @@ -21,15 +21,18 @@ package com.arangodb; import com.arangodb.entity.*; +import com.arangodb.internal.serde.SerdeUtils; import com.arangodb.model.*; import com.arangodb.model.DocumentImportOptions.OnDuplicate; import com.arangodb.serde.JacksonSerde; import com.arangodb.util.MapBuilder; import com.arangodb.util.RawBytes; +import com.arangodb.util.RawData; import com.arangodb.util.RawJson; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonTypeInfo; import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Disabled; @@ -1904,6 +1907,42 @@ void insertDocumentsJson(ArangoCollection collection) { assertThat(docs.getErrors()).isEmpty(); } + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void insertDocumentsRawData(ArangoCollection collection) { + final RawData values = RawData.of("[{},{},{}]"); + final MultiDocumentEntity docs = collection.insertDocuments(values); + assertThat(docs).isNotNull(); + assertThat(docs.getDocuments()).isNotNull(); + assertThat(docs.getDocuments()).hasSize(3); + assertThat(docs.getErrors()).isNotNull(); + assertThat(docs.getErrors()).isEmpty(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void insertDocumentsRawDataReturnNew(ArangoCollection collection) { + final RawData values = RawData.of("[{\"aaa\":33},{\"aaa\":33},{\"aaa\":33}]"); + final MultiDocumentEntity> docs = + collection.insertDocuments(values, new DocumentCreateOptions().returnNew(true)); + assertThat(docs).isNotNull(); + assertThat(docs.getDocuments()).isNotNull(); + assertThat(docs.getDocuments()).hasSize(3); + assertThat(docs.getErrors()).isNotNull(); + assertThat(docs.getErrors()).isEmpty(); + + for (final DocumentCreateEntity doc : docs.getDocuments()) { + RawData d = doc.getNew(); + assertThat(d) + .isNotNull() + .isInstanceOf(RawJson.class); + + JsonNode jn = SerdeUtils.INSTANCE.parseJson(((RawJson) d).getValue()); + assertThat(jn.has("aaa")).isTrue(); + assertThat(jn.get("aaa").intValue()).isEqualTo(33); + } + } + @ParameterizedTest(name = "{index}") @MethodSource("cols") void insertDocumentsOne(ArangoCollection collection) { @@ -2175,7 +2214,7 @@ void importDocumentsFromToPrefix(ArangoCollection edgeCollection) { void importDocumentsJson(ArangoCollection collection) throws JsonProcessingException { final String values = mapper.writeValueAsString(Arrays.asList(Collections.singletonMap("_key", rnd()), Collections.singletonMap("_key", rnd()))); - final DocumentImportEntity docs = collection.importDocuments(values); + final DocumentImportEntity docs = collection.importDocuments(RawData.of(values)); assertThat(docs).isNotNull(); assertThat(docs.getCreated()).isEqualTo(2); assertThat(docs.getEmpty()).isZero(); @@ -2193,7 +2232,7 @@ void importDocumentsJsonDuplicateDefaultError(ArangoCollection collection) throw final String values = mapper.writeValueAsString(Arrays.asList(Collections.singletonMap("_key", k1), Collections.singletonMap("_key", k2), Collections.singletonMap("_key", k2))); - final DocumentImportEntity docs = collection.importDocuments(values); + final DocumentImportEntity docs = collection.importDocuments(RawData.of(values)); assertThat(docs).isNotNull(); assertThat(docs.getCreated()).isEqualTo(2); assertThat(docs.getEmpty()).isZero(); @@ -2211,7 +2250,7 @@ void importDocumentsJsonDuplicateError(ArangoCollection collection) throws JsonP final String values = mapper.writeValueAsString(Arrays.asList(Collections.singletonMap("_key", k1), Collections.singletonMap("_key", k2), Collections.singletonMap("_key", k2))); - final DocumentImportEntity docs = collection.importDocuments(values, new DocumentImportOptions().onDuplicate(OnDuplicate.error)); + final DocumentImportEntity docs = collection.importDocuments(RawData.of(values), new DocumentImportOptions().onDuplicate(OnDuplicate.error)); assertThat(docs).isNotNull(); assertThat(docs.getCreated()).isEqualTo(2); assertThat(docs.getEmpty()).isZero(); @@ -2228,7 +2267,7 @@ void importDocumentsJsonDuplicateIgnore(ArangoCollection collection) throws Json String k2 = rnd(); final String values = mapper.writeValueAsString(Arrays.asList(Collections.singletonMap("_key", k1), Collections.singletonMap("_key", k2), Collections.singletonMap("_key", k2))); - final DocumentImportEntity docs = collection.importDocuments(values, new DocumentImportOptions().onDuplicate(OnDuplicate.ignore)); + final DocumentImportEntity docs = collection.importDocuments(RawData.of(values), new DocumentImportOptions().onDuplicate(OnDuplicate.ignore)); assertThat(docs).isNotNull(); assertThat(docs.getCreated()).isEqualTo(2); assertThat(docs.getEmpty()).isZero(); @@ -2246,7 +2285,7 @@ void importDocumentsJsonDuplicateReplace(ArangoCollection collection) throws Jso final String values = mapper.writeValueAsString(Arrays.asList(Collections.singletonMap("_key", k1), Collections.singletonMap("_key", k2), Collections.singletonMap("_key", k2))); - final DocumentImportEntity docs = collection.importDocuments(values, new DocumentImportOptions().onDuplicate(OnDuplicate.replace)); + final DocumentImportEntity docs = collection.importDocuments(RawData.of(values), new DocumentImportOptions().onDuplicate(OnDuplicate.replace)); assertThat(docs).isNotNull(); assertThat(docs.getCreated()).isEqualTo(2); assertThat(docs.getEmpty()).isZero(); @@ -2264,7 +2303,7 @@ void importDocumentsJsonDuplicateUpdate(ArangoCollection collection) throws Json final String values = mapper.writeValueAsString(Arrays.asList(Collections.singletonMap("_key", k1), Collections.singletonMap("_key", k2), Collections.singletonMap("_key", k2))); - final DocumentImportEntity docs = collection.importDocuments(values, new DocumentImportOptions().onDuplicate(OnDuplicate.update)); + final DocumentImportEntity docs = collection.importDocuments(RawData.of(values), new DocumentImportOptions().onDuplicate(OnDuplicate.update)); assertThat(docs).isNotNull(); assertThat(docs.getCreated()).isEqualTo(2); assertThat(docs.getEmpty()).isZero(); @@ -2278,7 +2317,7 @@ void importDocumentsJsonDuplicateUpdate(ArangoCollection collection) throws Json @MethodSource("cols") void importDocumentsJsonCompleteFail(ArangoCollection collection) { final String values = "[{\"_key\":\"1\"},{\"_key\":\"2\"},{\"_key\":\"2\"}]"; - Throwable thrown = catchThrowable(() -> collection.importDocuments(values, new DocumentImportOptions().complete(true))); + Throwable thrown = catchThrowable(() -> collection.importDocuments(RawData.of(values), new DocumentImportOptions().complete(true))); assertThat(thrown).isInstanceOf(ArangoDBException.class); ArangoDBException e = (ArangoDBException) thrown; assertThat(e.getErrorNum()).isEqualTo(1210); @@ -2292,7 +2331,7 @@ void importDocumentsJsonDetails(ArangoCollection collection) throws JsonProcessi final String values = mapper.writeValueAsString(Arrays.asList(Collections.singletonMap("_key", k1), Collections.singletonMap("_key", k2), Collections.singletonMap("_key", k2))); - final DocumentImportEntity docs = collection.importDocuments(values, new DocumentImportOptions().details(true)); + final DocumentImportEntity docs = collection.importDocuments(RawData.of(values), new DocumentImportOptions().details(true)); assertThat(docs).isNotNull(); assertThat(docs.getCreated()).isEqualTo(2); assertThat(docs.getEmpty()).isZero(); @@ -2310,7 +2349,7 @@ void importDocumentsJsonOverwriteFalse(ArangoCollection collection) throws JsonP Long initialCount = collection.count().getCount(); final String values = mapper.writeValueAsString(Arrays.asList(Collections.singletonMap("_key", rnd()), Collections.singletonMap("_key", rnd()))); - collection.importDocuments(values, new DocumentImportOptions().overwrite(false)); + collection.importDocuments(RawData.of(values), new DocumentImportOptions().overwrite(false)); assertThat(collection.count().getCount()).isEqualTo(initialCount + 2L); } @@ -2320,7 +2359,7 @@ void importDocumentsJsonOverwriteTrue(ArangoCollection collection) throws JsonPr collection.insertDocument(new BaseDocument()); final String values = mapper.writeValueAsString(Arrays.asList(Collections.singletonMap("_key", rnd()), Collections.singletonMap("_key", rnd()))); - collection.importDocuments(values, new DocumentImportOptions().overwrite(true)); + collection.importDocuments(RawData.of(values), new DocumentImportOptions().overwrite(true)); assertThat(collection.count().getCount()).isEqualTo(2L); } @@ -2334,7 +2373,7 @@ void importDocumentsJsonFromToPrefix(ArangoCollection edgeCollection) throws Jso final String values = mapper.writeValueAsString(Arrays.asList(new MapBuilder().put("_key", k1).put("_from", "from").put("_to", "to").get(), new MapBuilder().put("_key", k2).put("_from", "from").put("_to", "to").get())); - final DocumentImportEntity importResult = edgeCollection.importDocuments(values, new DocumentImportOptions().fromPrefix("foo").toPrefix("bar")); + final DocumentImportEntity importResult = edgeCollection.importDocuments(RawData.of(values), new DocumentImportOptions().fromPrefix("foo").toPrefix("bar")); assertThat(importResult).isNotNull(); assertThat(importResult.getCreated()).isEqualTo(2); for (String key : keys) { @@ -2372,6 +2411,25 @@ void deleteDocumentsByKey(ArangoCollection collection) { assertThat(deleteResult.getErrors()).isEmpty(); } + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void deleteDocumentsRawDataByKeyReturnOld(ArangoCollection collection) { + final RawData values = RawData.of("[{\"_key\":\"1\"},{\"_key\":\"2\"}]"); + collection.insertDocuments(values); + final RawData keys = RawData.of("[\"1\",\"2\"]"); + MultiDocumentEntity> deleteResult = collection.deleteDocuments(keys, + new DocumentDeleteOptions().returnOld(true)); + assertThat(deleteResult).isNotNull(); + assertThat(deleteResult.getDocuments()).hasSize(2); + for (final DocumentDeleteEntity i : deleteResult.getDocuments()) { + assertThat(i.getKey()).isIn("1", "2"); + assertThat(i.getOld()).isNotNull().isInstanceOf(RawJson.class); + JsonNode jn = SerdeUtils.INSTANCE.parseJson(((RawJson) i.getOld()).getValue()); + assertThat(jn.get("_key").asText()).isEqualTo(i.getKey()); + } + assertThat(deleteResult.getErrors()).isEmpty(); + } + @ParameterizedTest(name = "{index}") @MethodSource("cols") void deleteDocumentsByDocuments(ArangoCollection collection) { @@ -2578,6 +2636,41 @@ void updateDocumentsJson(ArangoCollection collection) { assertThat(updateResult.getErrors()).isEmpty(); } + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void updateDocumentsRawData(ArangoCollection collection) { + final RawData values = RawData.of("[{\"_key\":\"1\"}, {\"_key\":\"2\"}]"); + collection.insertDocuments(values); + + final RawData updatedValues = RawData.of("[{\"_key\":\"1\", \"foo\":\"bar\"}, {\"_key\":\"2\", \"foo\":\"bar\"}]"); + final MultiDocumentEntity updateResult = collection.updateDocuments(updatedValues); + assertThat(updateResult.getDocuments()).hasSize(2); + assertThat(updateResult.getErrors()).isEmpty(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void updateDocumentsRawDataReturnNew(ArangoCollection collection) { + final RawData values = RawData.of("[{\"_key\":\"1\"}, {\"_key\":\"2\"}]"); + collection.insertDocuments(values); + + final RawData updatedValues = RawData.of("[{\"_key\":\"1\", \"foo\":\"bar\"}, {\"_key\":\"2\", \"foo\":\"bar\"}]"); + MultiDocumentEntity> updateResult = + collection.updateDocuments(updatedValues, new DocumentUpdateOptions().returnNew(true)); + assertThat(updateResult.getDocuments()).hasSize(2); + assertThat(updateResult.getErrors()).isEmpty(); + for (DocumentUpdateEntity doc : updateResult.getDocuments()) { + RawData d = doc.getNew(); + assertThat(d) + .isNotNull() + .isInstanceOf(RawJson.class); + + JsonNode jn = SerdeUtils.INSTANCE.parseJson(((RawJson) d).getValue()); + assertThat(jn.has("foo")).isTrue(); + assertThat(jn.get("foo").textValue()).isEqualTo("bar"); + } + } + @ParameterizedTest(name = "{index}") @MethodSource("cols") void replaceDocuments(ArangoCollection collection) { @@ -2660,6 +2753,41 @@ void replaceDocumentsJson(ArangoCollection collection) { assertThat(updateResult.getErrors()).isEmpty(); } + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void replaceDocumentsRawData(ArangoCollection collection) { + final RawData values = RawData.of("[{\"_key\":\"1\"}, {\"_key\":\"2\"}]"); + collection.insertDocuments(values); + + final RawData updatedValues = RawData.of("[{\"_key\":\"1\", \"foo\":\"bar\"}, {\"_key\":\"2\", \"foo\":\"bar\"}]"); + final MultiDocumentEntity updateResult = collection.replaceDocuments(updatedValues); + assertThat(updateResult.getDocuments()).hasSize(2); + assertThat(updateResult.getErrors()).isEmpty(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void replaceDocumentsRawDataReturnNew(ArangoCollection collection) { + final RawData values = RawData.of("[{\"_key\":\"1\"}, {\"_key\":\"2\"}]"); + collection.insertDocuments(values); + + final RawData updatedValues = RawData.of("[{\"_key\":\"1\", \"foo\":\"bar\"}, {\"_key\":\"2\", \"foo\":\"bar\"}]"); + MultiDocumentEntity> updateResult = + collection.replaceDocuments(updatedValues, new DocumentReplaceOptions().returnNew(true)); + assertThat(updateResult.getDocuments()).hasSize(2); + assertThat(updateResult.getErrors()).isEmpty(); + for (DocumentUpdateEntity doc : updateResult.getDocuments()) { + RawData d = doc.getNew(); + assertThat(d) + .isNotNull() + .isInstanceOf(RawJson.class); + + JsonNode jn = SerdeUtils.INSTANCE.parseJson(((RawJson) d).getValue()); + assertThat(jn.has("foo")).isTrue(); + assertThat(jn.get("foo").textValue()).isEqualTo("bar"); + } + } + @ParameterizedTest(name = "{index}") @MethodSource("cols") void getInfo(ArangoCollection collection) { diff --git a/src/test/java/com/arangodb/async/ArangoCollectionTest.java b/src/test/java/com/arangodb/async/ArangoCollectionTest.java index 793e03e3c..b41d7613c 100644 --- a/src/test/java/com/arangodb/async/ArangoCollectionTest.java +++ b/src/test/java/com/arangodb/async/ArangoCollectionTest.java @@ -20,19 +20,19 @@ package com.arangodb.async; -import com.arangodb.ArangoCollection; import com.arangodb.ArangoDBException; import com.arangodb.entity.*; +import com.arangodb.internal.serde.SerdeUtils; import com.arangodb.model.*; import com.arangodb.model.DocumentImportOptions.OnDuplicate; import com.arangodb.serde.JacksonSerde; +import com.arangodb.util.RawData; import com.arangodb.util.RawJson; import com.fasterxml.jackson.annotation.JsonTypeInfo; +import com.fasterxml.jackson.databind.JsonNode; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.MethodSource; import java.util.*; import java.util.concurrent.CompletableFuture; @@ -1506,6 +1506,40 @@ void insertDocumentsFail() throws InterruptedException, ExecutionException { .get(); } + @Test + void insertDocumentsRawData() throws ExecutionException, InterruptedException { + final RawData values = RawData.of("[{},{},{}]"); + final MultiDocumentEntity docs = db.collection(COLLECTION_NAME).insertDocuments(values).get(); + assertThat(docs).isNotNull(); + assertThat(docs.getDocuments()).isNotNull(); + assertThat(docs.getDocuments()).hasSize(3); + assertThat(docs.getErrors()).isNotNull(); + assertThat(docs.getErrors()).isEmpty(); + } + + @Test + void insertDocumentsRawDataReturnNew() throws ExecutionException, InterruptedException { + final RawData values = RawData.of("[{\"aaa\":33},{\"aaa\":33},{\"aaa\":33}]"); + final MultiDocumentEntity> docs = + db.collection(COLLECTION_NAME).insertDocuments(values, new DocumentCreateOptions().returnNew(true)).get(); + assertThat(docs).isNotNull(); + assertThat(docs.getDocuments()).isNotNull(); + assertThat(docs.getDocuments()).hasSize(3); + assertThat(docs.getErrors()).isNotNull(); + assertThat(docs.getErrors()).isEmpty(); + + for (final DocumentCreateEntity doc : docs.getDocuments()) { + RawData d = doc.getNew(); + assertThat(d) + .isNotNull() + .isInstanceOf(RawJson.class); + + JsonNode jn = SerdeUtils.INSTANCE.parseJson(((RawJson) d).getValue()); + assertThat(jn.has("aaa")).isTrue(); + assertThat(jn.get("aaa").intValue()).isEqualTo(33); + } + } + @Test void importDocuments() throws InterruptedException, ExecutionException { final Collection values = new ArrayList<>(); @@ -1712,7 +1746,7 @@ void importDocumentsFromToPrefix() throws InterruptedException, ExecutionExcepti @Test void importDocumentsJson() throws InterruptedException, ExecutionException { final String values = "[{\"_key\":\"1\"},{\"_key\":\"2\"}]"; - db.collection(COLLECTION_NAME).importDocuments(values) + db.collection(COLLECTION_NAME).importDocuments(RawData.of(values)) .whenComplete((docs, ex) -> { assertThat(docs).isNotNull(); assertThat(docs.getCreated()).isEqualTo(2); @@ -1728,7 +1762,7 @@ void importDocumentsJson() throws InterruptedException, ExecutionException { @Test void importDocumentsJsonDuplicateDefaultError() throws InterruptedException, ExecutionException { final String values = "[{\"_key\":\"1\"},{\"_key\":\"2\"},{\"_key\":\"2\"}]"; - db.collection(COLLECTION_NAME).importDocuments(values) + db.collection(COLLECTION_NAME).importDocuments(RawData.of(values)) .whenComplete((docs, ex) -> { assertThat(docs).isNotNull(); assertThat(docs.getCreated()).isEqualTo(2); @@ -1744,7 +1778,7 @@ void importDocumentsJsonDuplicateDefaultError() throws InterruptedException, Exe @Test void importDocumentsJsonDuplicateError() throws InterruptedException, ExecutionException { final String values = "[{\"_key\":\"1\"},{\"_key\":\"2\"},{\"_key\":\"2\"}]"; - db.collection(COLLECTION_NAME).importDocuments(values, new DocumentImportOptions().onDuplicate(OnDuplicate.error)) + db.collection(COLLECTION_NAME).importDocuments(RawData.of(values), new DocumentImportOptions().onDuplicate(OnDuplicate.error)) .whenComplete((docs, ex) -> { assertThat(docs).isNotNull(); assertThat(docs.getCreated()).isEqualTo(2); @@ -1760,7 +1794,7 @@ void importDocumentsJsonDuplicateError() throws InterruptedException, ExecutionE @Test void importDocumentsJsonDuplicateIgnore() throws InterruptedException, ExecutionException { final String values = "[{\"_key\":\"1\"},{\"_key\":\"2\"},{\"_key\":\"2\"}]"; - db.collection(COLLECTION_NAME).importDocuments(values, new DocumentImportOptions().onDuplicate(OnDuplicate.ignore)) + db.collection(COLLECTION_NAME).importDocuments(RawData.of(values), new DocumentImportOptions().onDuplicate(OnDuplicate.ignore)) .whenComplete((docs, ex) -> { assertThat(docs).isNotNull(); assertThat(docs.getCreated()).isEqualTo(2); @@ -1776,7 +1810,7 @@ void importDocumentsJsonDuplicateIgnore() throws InterruptedException, Execution @Test void importDocumentsJsonDuplicateReplace() throws InterruptedException, ExecutionException { final String values = "[{\"_key\":\"1\"},{\"_key\":\"2\"},{\"_key\":\"2\"}]"; - db.collection(COLLECTION_NAME).importDocuments(values, new DocumentImportOptions().onDuplicate(OnDuplicate.replace)) + db.collection(COLLECTION_NAME).importDocuments(RawData.of(values), new DocumentImportOptions().onDuplicate(OnDuplicate.replace)) .whenComplete((docs, ex) -> { assertThat(docs).isNotNull(); assertThat(docs.getCreated()).isEqualTo(2); @@ -1792,7 +1826,7 @@ void importDocumentsJsonDuplicateReplace() throws InterruptedException, Executio @Test void importDocumentsJsonDuplicateUpdate() throws InterruptedException, ExecutionException { final String values = "[{\"_key\":\"1\"},{\"_key\":\"2\"},{\"_key\":\"2\"}]"; - db.collection(COLLECTION_NAME).importDocuments(values, new DocumentImportOptions().onDuplicate(OnDuplicate.update)) + db.collection(COLLECTION_NAME).importDocuments(RawData.of(values), new DocumentImportOptions().onDuplicate(OnDuplicate.update)) .whenComplete((docs, ex) -> { assertThat(docs).isNotNull(); assertThat(docs.getCreated()).isEqualTo(2); @@ -1809,7 +1843,7 @@ void importDocumentsJsonDuplicateUpdate() throws InterruptedException, Execution void importDocumentsJsonCompleteFail() throws InterruptedException { final String values = "[{\"_key\":\"1\"},{\"_key\":\"2\"},{\"_key\":\"2\"}]"; try { - db.collection(COLLECTION_NAME).importDocuments(values, new DocumentImportOptions().complete(true)).get(); + db.collection(COLLECTION_NAME).importDocuments(RawData.of(values), new DocumentImportOptions().complete(true)).get(); fail(); } catch (ExecutionException e) { assertThat(e.getCause()).isInstanceOf(ArangoDBException.class); @@ -1820,7 +1854,7 @@ void importDocumentsJsonCompleteFail() throws InterruptedException { @Test void importDocumentsJsonDetails() throws InterruptedException, ExecutionException { final String values = "[{\"_key\":\"1\"},{\"_key\":\"2\"},{\"_key\":\"2\"}]"; - db.collection(COLLECTION_NAME).importDocuments(values, new DocumentImportOptions().details(true)) + db.collection(COLLECTION_NAME).importDocuments(RawData.of(values), new DocumentImportOptions().details(true)) .whenComplete((docs, ex) -> { assertThat(docs).isNotNull(); assertThat(docs.getCreated()).isEqualTo(2); @@ -1841,7 +1875,7 @@ void importDocumentsJsonOverwriteFalse() throws InterruptedException, ExecutionE assertThat(collection.count().get().getCount()).isEqualTo(1L); final String values = "[{\"_key\":\"1\"},{\"_key\":\"2\"}]"; - collection.importDocuments(values, new DocumentImportOptions().overwrite(false)).get(); + collection.importDocuments(RawData.of(values), new DocumentImportOptions().overwrite(false)).get(); assertThat(collection.count().get().getCount()).isEqualTo(3L); } @@ -1852,7 +1886,7 @@ void importDocumentsJsonOverwriteTrue() throws InterruptedException, ExecutionEx assertThat(collection.count().get().getCount()).isEqualTo(1L); final String values = "[{\"_key\":\"1\"},{\"_key\":\"2\"}]"; - collection.importDocuments(values, new DocumentImportOptions().overwrite(true)).get(); + collection.importDocuments(RawData.of(values), new DocumentImportOptions().overwrite(true)).get(); assertThat(collection.count().get().getCount()).isEqualTo(2L); } @@ -1865,7 +1899,7 @@ void importDocumentsJsonFromToPrefix() throws InterruptedException, ExecutionExc final String values = "[{\"_key\":\"1\",\"_from\":\"from\",\"_to\":\"to\"},{\"_key\":\"2\",\"_from\":\"from\",\"_to\":\"to\"}]"; final DocumentImportEntity importResult = collection - .importDocuments(values, new DocumentImportOptions().fromPrefix("foo").toPrefix("bar")).get(); + .importDocuments(RawData.of(values), new DocumentImportOptions().fromPrefix("foo").toPrefix("bar")).get(); assertThat(importResult).isNotNull(); assertThat(importResult.getCreated()).isEqualTo(2); for (String key : keys) { @@ -2031,6 +2065,26 @@ void deleteDocumentsByDocumentsNotExisting() throws InterruptedException, Execut .get(); } + @Test + void deleteDocumentsRawDataByKeyReturnOld() throws ExecutionException, InterruptedException { + ArangoCollectionAsync collection = db.collection(COLLECTION_NAME); + final RawData values = RawData.of("[{\"_key\":\"1\"},{\"_key\":\"2\"}]"); + collection.insertDocuments(values).get(); + final RawData keys = RawData.of("[\"1\",\"2\"]"); + MultiDocumentEntity> deleteResult = collection.deleteDocuments(keys, + new DocumentDeleteOptions().returnOld(true)).get(); + assertThat(deleteResult).isNotNull(); + assertThat(deleteResult.getDocuments()).hasSize(2); + for (final DocumentDeleteEntity i : deleteResult.getDocuments()) { + assertThat(i.getKey()).isIn("1", "2"); + assertThat(i.getOld()).isNotNull().isInstanceOf(RawJson.class); + JsonNode jn = SerdeUtils.INSTANCE.parseJson(((RawJson) i.getOld()).getValue()); + assertThat(jn.get("_key").asText()).isEqualTo(i.getKey()); + } + assertThat(deleteResult.getErrors()).isEmpty(); + } + + @Test void updateDocuments() throws InterruptedException, ExecutionException { final Collection values = new ArrayList<>(); @@ -2142,6 +2196,41 @@ void updateDocumentsWithoutKey() throws InterruptedException, ExecutionException .get(); } + @Test + void updateDocumentsRawData() throws ExecutionException, InterruptedException { + ArangoCollectionAsync collection = db.collection(COLLECTION_NAME); + final RawData values = RawData.of("[{\"_key\":\"1\"}, {\"_key\":\"2\"}]"); + collection.insertDocuments(values).get(); + + final RawData updatedValues = RawData.of("[{\"_key\":\"1\", \"foo\":\"bar\"}, {\"_key\":\"2\", \"foo\":\"bar\"}]"); + final MultiDocumentEntity updateResult = collection.updateDocuments(updatedValues).get(); + assertThat(updateResult.getDocuments()).hasSize(2); + assertThat(updateResult.getErrors()).isEmpty(); + } + + @Test + void updateDocumentsRawDataReturnNew() throws ExecutionException, InterruptedException { + ArangoCollectionAsync collection = db.collection(COLLECTION_NAME); + final RawData values = RawData.of("[{\"_key\":\"1\"}, {\"_key\":\"2\"}]"); + collection.insertDocuments(values).get(); + + final RawData updatedValues = RawData.of("[{\"_key\":\"1\", \"foo\":\"bar\"}, {\"_key\":\"2\", \"foo\":\"bar\"}]"); + MultiDocumentEntity> updateResult = + collection.updateDocuments(updatedValues, new DocumentUpdateOptions().returnNew(true)).get(); + assertThat(updateResult.getDocuments()).hasSize(2); + assertThat(updateResult.getErrors()).isEmpty(); + for (DocumentUpdateEntity doc : updateResult.getDocuments()) { + RawData d = doc.getNew(); + assertThat(d) + .isNotNull() + .isInstanceOf(RawJson.class); + + JsonNode jn = SerdeUtils.INSTANCE.parseJson(((RawJson) d).getValue()); + assertThat(jn.has("foo")).isTrue(); + assertThat(jn.get("foo").textValue()).isEqualTo("bar"); + } + } + @Test void replaceDocuments() throws InterruptedException, ExecutionException { final Collection values = new ArrayList<>(); @@ -2216,6 +2305,44 @@ void replaceDocumentsWithoutKey() throws InterruptedException, ExecutionExceptio .get(); } + @Test + void replaceDocumentsRawData() throws ExecutionException, InterruptedException { + ArangoCollectionAsync collection = db.collection(COLLECTION_NAME); + + final RawData values = RawData.of("[{\"_key\":\"1\"}, {\"_key\":\"2\"}]"); + collection.insertDocuments(values).get(); + + final RawData updatedValues = RawData.of("[{\"_key\":\"1\", \"foo\":\"bar\"}, {\"_key\":\"2\", \"foo\":\"bar\"}]"); + final MultiDocumentEntity updateResult = collection.replaceDocuments(updatedValues).get(); + assertThat(updateResult.getDocuments()).hasSize(2); + assertThat(updateResult.getErrors()).isEmpty(); + } + + @Test + void replaceDocumentsRawDataReturnNew() throws ExecutionException, InterruptedException { + ArangoCollectionAsync collection = db.collection(COLLECTION_NAME); + + final RawData values = RawData.of("[{\"_key\":\"1\"}, {\"_key\":\"2\"}]"); + collection.insertDocuments(values).get(); + + final RawData updatedValues = RawData.of("[{\"_key\":\"1\", \"foo\":\"bar\"}, {\"_key\":\"2\", \"foo\":\"bar\"}]"); + MultiDocumentEntity> updateResult = + collection.replaceDocuments(updatedValues, new DocumentReplaceOptions().returnNew(true)).get(); + assertThat(updateResult.getDocuments()).hasSize(2); + assertThat(updateResult.getErrors()).isEmpty(); + for (DocumentUpdateEntity doc : updateResult.getDocuments()) { + RawData d = doc.getNew(); + assertThat(d) + .isNotNull() + .isInstanceOf(RawJson.class); + + JsonNode jn = SerdeUtils.INSTANCE.parseJson(((RawJson) d).getValue()); + assertThat(jn.has("foo")).isTrue(); + assertThat(jn.get("foo").textValue()).isEqualTo("bar"); + } + } + + @Test void getInfo() throws InterruptedException, ExecutionException { db.collection(COLLECTION_NAME).getInfo() From 1c9fb1991b7b25972765ebf439de79a9f56c8878 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Wed, 17 Aug 2022 15:06:32 +0200 Subject: [PATCH 101/254] code cleanup --- .../java/com/arangodb/ArangoCollection.java | 12 +- src/main/java/com/arangodb/ArangoDB.java | 2 +- .../arangodb/async/ArangoCollectionAsync.java | 12 +- .../com/arangodb/async/ArangoDBAsync.java | 2 +- .../entity/QueryTrackingPropertiesEntity.java | 4 +- .../internal/InternalArangoCollection.java | 2 +- .../internal/serde/InternalSerializers.java | 43 +- .../model/AqlFunctionCreateOptions.java | 2 +- .../model/AqlQueryExplainOptions.java | 2 +- .../com/arangodb/model/AqlQueryOptions.java | 2 +- .../model/CollectionPropertiesOptions.java | 2 +- .../model/DocumentReplaceOptions.java | 2 +- .../arangodb/model/DocumentUpdateOptions.java | 2 +- .../model/StreamTransactionOptions.java | 2 +- .../arangodb/model/TransactionOptions.java | 2 +- .../com/arangodb/ArangoCollectionTest.java | 514 ++++++++++------- .../java/com/arangodb/ArangoCursorTest.java | 6 +- src/test/java/com/arangodb/ArangoDBTest.java | 31 +- .../java/com/arangodb/ArangoDatabaseTest.java | 48 +- .../java/com/arangodb/ArangoGraphTest.java | 12 +- .../java/com/arangodb/ArangoRouteTest.java | 6 +- .../java/com/arangodb/ArangoSearchTest.java | 6 +- .../arangodb/ArangoVertexCollectionTest.java | 3 +- src/test/java/com/arangodb/JwtAuthTest.java | 30 +- .../arangodb/StreamTransactionGraphTest.java | 27 +- .../com/arangodb/StreamTransactionTest.java | 3 +- .../arangodb/async/ArangoCollectionTest.java | 216 +++---- .../java/com/arangodb/async/ArangoDBTest.java | 4 +- .../arangodb/async/ArangoDatabaseTest.java | 3 +- .../async/ArangoEdgeCollectionTest.java | 2 - .../com/arangodb/async/ArangoGraphTest.java | 3 +- .../com/arangodb/async/ArangoRouteTest.java | 2 - .../com/arangodb/async/ArangoSearchTest.java | 14 +- .../async/ArangoVertexCollectionTest.java | 2 - .../java/com/arangodb/async/BaseTest.java | 14 +- .../com/arangodb/async/CommunicationTest.java | 1 - .../com/arangodb/async/ConcurrencyTests.java | 1 - .../java/com/arangodb/async/JwtAuthTest.java | 32 +- .../async/StreamTransactionGraphTest.java | 52 +- .../arangodb/async/StreamTransactionTest.java | 9 +- ...ueryWithSpecialReturnTypesExampleTest.java | 12 +- .../document/GetDocumentExampleTest.java | 2 - .../document/ImportDocumentExampleTest.java | 1 - .../graph/AQLActorsAndMoviesExampleTest.java | 76 ++- .../GraphTraversalsInAQLExampleTest.java | 13 +- .../graph/ShortestPathInAQLExampleTest.java | 15 +- .../async/example/ssl/SslExampleTest.java | 1 - .../arangodb/async/serde/CustomSerdeTest.java | 1 - .../com/arangodb/example/ExampleBase.java | 10 +- .../com/arangodb/example/FirstProject.java | 4 +- ...ueryWithSpecialReturnTypesExampleTest.java | 8 +- .../document/GetDocumentExampleTest.java | 3 +- .../graph/AQLActorsAndMoviesExampleTest.java | 532 +++++++++--------- .../arangodb/example/graph/BaseGraphTest.java | 4 +- .../GraphTraversalsInAQLExampleTest.java | 12 +- .../graph/ShortestPathInAQLExampleTest.java | 58 +- .../arangodb/example/ssl/SslExampleTest.java | 4 +- .../arangodb/internal/HostHandlerTest.java | 6 +- .../annotations/ArangoAnnotationsTest.java | 2 +- .../com/arangodb/serde/CustomSerdeTest.java | 59 +- .../arangodb/serde/CustomTypeHintTest.java | 90 +-- .../java/com/arangodb/serde/SerdeTest.java | 1 - .../java/com/arangodb/util/TestUtils.java | 9 +- .../com/arangodb/util/UnicodeUtilsTest.java | 4 +- 64 files changed, 1132 insertions(+), 929 deletions(-) diff --git a/src/main/java/com/arangodb/ArangoCollection.java b/src/main/java/com/arangodb/ArangoCollection.java index 86c42cbb1..cbf14b5d5 100644 --- a/src/main/java/com/arangodb/ArangoCollection.java +++ b/src/main/java/com/arangodb/ArangoCollection.java @@ -102,7 +102,7 @@ public interface ArangoCollection extends ArangoSerdeAccessor { * Creates new documents from the given documents, unless there is already a document with the _key given. If no * _key is given, a new unique _key is generated automatically. * - * @param values Raw data representing a collection of documents + * @param values Raw data representing a collection of documents * @param options Additional options * @return information about the documents * @see API @@ -152,7 +152,7 @@ MultiDocumentEntity> insertDocuments( /** * Bulk imports the given values into the collection. * - * @param values A List of documents (POJO or {@link com.arangodb.util.RawData}) + * @param values A List of documents (POJO or {@link com.arangodb.util.RawData}) * @return information about the import */ DocumentImportEntity importDocuments(Collection values); @@ -177,7 +177,7 @@ MultiDocumentEntity> insertDocuments( /** * Bulk imports the given values into the collection. * - * @param values Raw data representing a collection of documents + * @param values Raw data representing a collection of documents * @param options Additional options, can be null * @return information about the import */ @@ -283,7 +283,7 @@ MultiDocumentEntity> insertDocuments( * Replaces multiple documents in the specified collection with the ones in the values, the replaced documents are * specified by the _key attributes in the documents in values. * - * @param values Raw data representing a collection of documents + * @param values Raw data representing a collection of documents * @param options Additional options * @return information about the documents * @see @@ -397,7 +397,7 @@ DocumentUpdateEntity updateDocument(String key, Object value, DocumentUpd * attributes from the patch documents will be added to the existing documents if they do not yet exist, and * overwritten in the existing documents if they do exist there. * - * @param values Raw data representing a collection of documents + * @param values Raw data representing a collection of documents * @param options Additional options * @return information about the documents * @see @@ -504,7 +504,7 @@ MultiDocumentEntity> updateDocuments( /** * Deletes multiple documents from the collection. * - * @param values Raw data representing the keys of the documents or the documents themselves + * @param values Raw data representing the keys of the documents or the documents themselves * @param options Additional options * @return information about the documents * @see CompletableFuture> insertDocument(final T value, fin * Creates new documents from the given documents, unless there is already a document with the _key given. If no * _key is given, a new unique _key is generated automatically. * - * @param values Raw data representing a collection of documents + * @param values Raw data representing a collection of documents * @param options Additional options * @return information about the documents * @see API @@ -157,7 +157,7 @@ CompletableFuture>> insertDocume /** * Imports documents * - * @param values A List of documents (POJO or {@link com.arangodb.util.RawData}) + * @param values A List of documents (POJO or {@link com.arangodb.util.RawData}) * @return information about the import */ CompletableFuture importDocuments(final Collection values); @@ -184,7 +184,7 @@ CompletableFuture importDocuments( /** * Imports documents * - * @param values Raw data representing a collection of documents + * @param values Raw data representing a collection of documents * @param options Additional options, can be null * @return information about the import */ @@ -300,7 +300,7 @@ CompletableFuture> replaceDocument( * Replaces multiple documents in the specified collection with the ones in the values, the replaced documents are * specified by the _key attributes in the documents in values. * - * @param values Raw data representing a collection of documents + * @param values Raw data representing a collection of documents * @param options Additional options * @return information about the documents * @see @@ -424,7 +424,7 @@ CompletableFuture> updateDocument( * attributes from the patch documents will be added to the existing documents if they do not yet exist, and * overwritten in the existing documents if they do exist there. * - * @param values Raw data representing a collection of documents + * @param values Raw data representing a collection of documents * @param options Additional options * @return information about the documents * @see @@ -540,7 +540,7 @@ CompletableFuture> deleteDocument( /** * Removes multiple document * - * @param values Raw data representing the keys of the documents or the documents themselves + * @param values Raw data representing the keys of the documents or the documents themselves * @param options Additional options * @return information about the documents * @see AUTHENTICATION_REQUEST = new JsonSerializer() { - @Override - public void serialize(AuthenticationRequest value, JsonGenerator gen, SerializerProvider serializers) throws IOException { - gen.writeStartArray(); - gen.writeNumber(value.getVersion()); - gen.writeNumber(value.getType()); - gen.writeString(value.getEncryption()); - gen.writeString(value.getUser()); - gen.writeString(value.getPassword()); - gen.writeEndArray(); - } - }; + @Override + public void serialize(AuthenticationRequest value, JsonGenerator gen, SerializerProvider serializers) throws IOException { + gen.writeStartArray(); + gen.writeNumber(value.getVersion()); + gen.writeNumber(value.getType()); + gen.writeString(value.getEncryption()); + gen.writeString(value.getUser()); + gen.writeString(value.getPassword()); + gen.writeEndArray(); + } + }; static final JsonSerializer JWT_AUTHENTICATION_REQUEST = new JsonSerializer() { - @Override - public void serialize(JwtAuthenticationRequest value, JsonGenerator gen, SerializerProvider serializers) throws IOException { - gen.writeStartArray(); - gen.writeNumber(value.getVersion()); - gen.writeNumber(value.getType()); - gen.writeString(value.getEncryption()); - gen.writeString(value.getToken()); - gen.writeEndArray(); - } - }; + @Override + public void serialize(JwtAuthenticationRequest value, JsonGenerator gen, + SerializerProvider serializers) throws IOException { + gen.writeStartArray(); + gen.writeNumber(value.getVersion()); + gen.writeNumber(value.getType()); + gen.writeString(value.getEncryption()); + gen.writeString(value.getToken()); + gen.writeEndArray(); + } + }; static final JsonSerializer REQUEST = new JsonSerializer() { @Override public void serialize(Request value, JsonGenerator gen, SerializerProvider serializers) throws IOException { diff --git a/src/main/java/com/arangodb/model/AqlFunctionCreateOptions.java b/src/main/java/com/arangodb/model/AqlFunctionCreateOptions.java index 78f025d1f..23e6e5f4c 100644 --- a/src/main/java/com/arangodb/model/AqlFunctionCreateOptions.java +++ b/src/main/java/com/arangodb/model/AqlFunctionCreateOptions.java @@ -63,7 +63,7 @@ public String getCode() { /** * @param isDeterministic an optional boolean value to indicate that the function results are fully deterministic - * (function + * (function * return value solely depends on the input value and return value is the same for * repeated calls with * same input) diff --git a/src/main/java/com/arangodb/model/AqlQueryExplainOptions.java b/src/main/java/com/arangodb/model/AqlQueryExplainOptions.java index b99aebd92..a0f58805d 100644 --- a/src/main/java/com/arangodb/model/AqlQueryExplainOptions.java +++ b/src/main/java/com/arangodb/model/AqlQueryExplainOptions.java @@ -73,7 +73,7 @@ public Integer getMaxNumberOfPlans() { /** * @param maxNumberOfPlans an optional maximum number of plans that the optimizer is allowed to generate. Setting - * this attribute + * this attribute * to a low value allows to put a cap on the amount of work the optimizer does. * @return options */ diff --git a/src/main/java/com/arangodb/model/AqlQueryOptions.java b/src/main/java/com/arangodb/model/AqlQueryOptions.java index 83c78c3dc..27921a4f8 100644 --- a/src/main/java/com/arangodb/model/AqlQueryOptions.java +++ b/src/main/java/com/arangodb/model/AqlQueryOptions.java @@ -281,7 +281,7 @@ public Long getIntermediateCommitSize() { /** * @param intermediateCommitSize Maximum total size of operations after which an intermediate commit is performed - * automatically. + * automatically. * Honored by the RocksDB storage engine only. * @return options * @since ArangoDB 3.2.0 diff --git a/src/main/java/com/arangodb/model/CollectionPropertiesOptions.java b/src/main/java/com/arangodb/model/CollectionPropertiesOptions.java index 046842652..b764c49c4 100644 --- a/src/main/java/com/arangodb/model/CollectionPropertiesOptions.java +++ b/src/main/java/com/arangodb/model/CollectionPropertiesOptions.java @@ -41,7 +41,7 @@ public Boolean getWaitForSync() { /** * @param waitForSync If true then creating or changing a document will wait until the data has been synchronized - * to disk. + * to disk. * @return options */ public CollectionPropertiesOptions waitForSync(final Boolean waitForSync) { diff --git a/src/main/java/com/arangodb/model/DocumentReplaceOptions.java b/src/main/java/com/arangodb/model/DocumentReplaceOptions.java index f08f18470..8dae60508 100644 --- a/src/main/java/com/arangodb/model/DocumentReplaceOptions.java +++ b/src/main/java/com/arangodb/model/DocumentReplaceOptions.java @@ -59,7 +59,7 @@ public Boolean getIgnoreRevs() { /** * @param ignoreRevs By default, or if this is set to true, the _rev attributes in the given document is ignored. - * If this + * If this * is set to false, then the _rev attribute given in the body document is taken as a * precondition. The * document is only replaced if the current revision is the one specified. diff --git a/src/main/java/com/arangodb/model/DocumentUpdateOptions.java b/src/main/java/com/arangodb/model/DocumentUpdateOptions.java index ae39ae8f5..e405582c1 100644 --- a/src/main/java/com/arangodb/model/DocumentUpdateOptions.java +++ b/src/main/java/com/arangodb/model/DocumentUpdateOptions.java @@ -94,7 +94,7 @@ public Boolean getIgnoreRevs() { /** * @param ignoreRevs By default, or if this is set to true, the _rev attributes in the given document is ignored. - * If this + * If this * is set to false, then the _rev attribute given in the body document is taken as a * precondition. The * document is only updated if the current revision is the one specified. diff --git a/src/main/java/com/arangodb/model/StreamTransactionOptions.java b/src/main/java/com/arangodb/model/StreamTransactionOptions.java index c47bad388..722e0f3be 100644 --- a/src/main/java/com/arangodb/model/StreamTransactionOptions.java +++ b/src/main/java/com/arangodb/model/StreamTransactionOptions.java @@ -66,7 +66,7 @@ public Boolean getWaitForSync() { /** * @param waitForSync an optional boolean flag that, if set, will force the transaction to write all data to disk - * before + * before * returning * @return options */ diff --git a/src/main/java/com/arangodb/model/TransactionOptions.java b/src/main/java/com/arangodb/model/TransactionOptions.java index 1306c11f3..95d0b5378 100644 --- a/src/main/java/com/arangodb/model/TransactionOptions.java +++ b/src/main/java/com/arangodb/model/TransactionOptions.java @@ -93,7 +93,7 @@ public Boolean getWaitForSync() { /** * @param waitForSync an optional boolean flag that, if set, will force the transaction to write all data to disk - * before + * before * returning * @return options */ diff --git a/src/test/java/com/arangodb/ArangoCollectionTest.java b/src/test/java/com/arangodb/ArangoCollectionTest.java index 0c3df4279..b5e44a8f8 100644 --- a/src/test/java/com/arangodb/ArangoCollectionTest.java +++ b/src/test/java/com/arangodb/ArangoCollectionTest.java @@ -35,20 +35,11 @@ import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.Disabled; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; -import org.junit.jupiter.params.provider.EnumSource; import org.junit.jupiter.params.provider.MethodSource; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.UUID; +import java.util.*; import java.util.stream.Collectors; import java.util.stream.IntStream; import java.util.stream.Stream; @@ -82,78 +73,6 @@ static void init() { initEdgeCollections(EDGE_COLLECTION_NAME); } - @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, property = "type") - public interface Animal { - String getKey(); - - String getName(); - } - - public static class Dog implements Animal { - - @Key - private String key; - private String name; - - public Dog() { - } - - public Dog(String key, String name) { - this.key = key; - this.name = name; - } - - @Override - public String getKey() { - return key; - } - - public void setKey(String key) { - this.key = key; - } - - @Override - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - } - - public static class Cat implements Animal { - @Key - private String key; - private String name; - - public Cat() { - } - - public Cat(String key, String name) { - this.key = key; - this.name = name; - } - - @Override - public String getKey() { - return key; - } - - public void setKey(String key) { - this.key = key; - } - - @Override - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - } - @ParameterizedTest(name = "{index}") @MethodSource("cols") void insertDocument(ArangoCollection collection) { @@ -173,7 +92,8 @@ void insertDocumentWithArrayWithNullValues(ArangoCollection collection) { BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); doc.addAttribute("arr", arr); - final DocumentCreateEntity insertedDoc = collection.insertDocument(doc, new DocumentCreateOptions().returnNew(true)); + final DocumentCreateEntity insertedDoc = collection.insertDocument(doc, + new DocumentCreateOptions().returnNew(true)); assertThat(insertedDoc).isNotNull(); assertThat(insertedDoc.getId()).isNotNull(); assertThat(insertedDoc.getKey()).isNotNull(); @@ -189,7 +109,8 @@ void insertDocumentWithNullValues(ArangoCollection collection) { BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); doc.addAttribute("null", null); - final DocumentCreateEntity insertedDoc = collection.insertDocument(doc, new DocumentCreateOptions().returnNew(true)); + final DocumentCreateEntity insertedDoc = collection.insertDocument(doc, + new DocumentCreateOptions().returnNew(true)); assertThat(insertedDoc).isNotNull(); assertThat(insertedDoc.getId()).isNotNull(); assertThat(insertedDoc.getKey()).isNotNull(); @@ -223,7 +144,8 @@ void insertDocumentReturnNew(ArangoCollection collection) { @MethodSource("cols") void insertDocumentWithTypeOverwriteModeReplace(ArangoCollection collection) { assumeTrue(isAtLeastVersion(3, 7)); - assumeTrue(collection.getSerde().getUserSerde() instanceof JacksonSerde, "polymorphic deserialization support required"); + assumeTrue(collection.getSerde().getUserSerde() instanceof JacksonSerde, "polymorphic deserialization support" + + " required"); String key = UUID.randomUUID().toString(); Dog dog = new Dog(key, "Teddy"); @@ -265,7 +187,8 @@ void insertDocumentOverwriteModeIgnore(ArangoCollection collection) { final BaseDocument doc2 = new BaseDocument(key); doc2.addAttribute("bar", "b"); - final DocumentCreateEntity insertIgnore = collection.insertDocument(doc2, new DocumentCreateOptions().overwriteMode(OverwriteMode.ignore)); + final DocumentCreateEntity insertIgnore = collection.insertDocument(doc2, + new DocumentCreateOptions().overwriteMode(OverwriteMode.ignore)); assertThat(insertIgnore).isNotNull(); assertThat(insertIgnore.getRev()).isEqualTo(meta.getRev()); @@ -282,7 +205,8 @@ void insertDocumentOverwriteModeConflict(ArangoCollection collection) { collection.insertDocument(doc); final BaseDocument doc2 = new BaseDocument(key); - Throwable thrown = catchThrowable(() -> collection.insertDocument(doc2, new DocumentCreateOptions().overwriteMode(OverwriteMode.conflict))); + Throwable thrown = catchThrowable(() -> collection.insertDocument(doc2, + new DocumentCreateOptions().overwriteMode(OverwriteMode.conflict))); assertThat(thrown).isInstanceOf(ArangoDBException.class); ArangoDBException e = (ArangoDBException) thrown; assertThat(e.getResponseCode()).isEqualTo(409); @@ -301,7 +225,8 @@ void insertDocumentOverwriteModeReplace(ArangoCollection collection) { final BaseDocument doc2 = new BaseDocument(key); doc2.addAttribute("bar", "b"); - final DocumentCreateEntity repsert = collection.insertDocument(doc2, new DocumentCreateOptions().overwriteMode(OverwriteMode.replace).returnNew(true)); + final DocumentCreateEntity repsert = collection.insertDocument(doc2, +new DocumentCreateOptions().overwriteMode(OverwriteMode.replace).returnNew(true)); assertThat(repsert).isNotNull(); assertThat(repsert.getRev()).isNotEqualTo(meta.getRev()); @@ -319,7 +244,8 @@ void insertDocumentOverwriteModeUpdate(ArangoCollection collection) { final DocumentCreateEntity meta = collection.insertDocument(doc); doc.addAttribute("bar", "b"); - final DocumentCreateEntity updated = collection.insertDocument(doc, new DocumentCreateOptions().overwriteMode(OverwriteMode.update).returnNew(true)); + final DocumentCreateEntity updated = collection.insertDocument(doc, + new DocumentCreateOptions().overwriteMode(OverwriteMode.update).returnNew(true)); assertThat(updated).isNotNull(); assertThat(updated.getRev()).isNotEqualTo(meta.getRev()); @@ -339,7 +265,8 @@ void insertDocumentOverwriteModeUpdateMergeObjectsFalse(ArangoCollection collect Map fieldB = Collections.singletonMap("b", "b"); doc.addAttribute("foo", fieldB); - final DocumentCreateEntity updated = collection.insertDocument(doc, new DocumentCreateOptions().overwriteMode(OverwriteMode.update).mergeObjects(false).returnNew(true)); + final DocumentCreateEntity updated = collection.insertDocument(doc, + new DocumentCreateOptions().overwriteMode(OverwriteMode.update).mergeObjects(false).returnNew(true)); assertThat(updated).isNotNull(); assertThat(updated.getRev()).isNotEqualTo(meta.getRev()); @@ -415,13 +342,15 @@ void insertDocumentAsBytes(ArangoCollection collection) { doc.put("a", "test"); byte[] bytes = collection.getSerde().serializeUserData(doc); RawBytes rawJson = RawBytes.of(bytes); - final DocumentCreateEntity createEntity = collection.insertDocument(rawJson, new DocumentCreateOptions().returnNew(true)); + final DocumentCreateEntity createEntity = collection.insertDocument(rawJson, +new DocumentCreateOptions().returnNew(true)); assertThat(createEntity).isNotNull(); assertThat(createEntity.getId()).isEqualTo(collection.name() + "/" + key); assertThat(createEntity.getKey()).isEqualTo(key); assertThat(createEntity.getRev()).isNotNull(); assertThat(createEntity.getNew()).isNotNull().isInstanceOf(RawBytes.class); - Map newDoc = collection.getSerde().deserializeUserData(createEntity.getNew().getValue(), Map.class); + Map newDoc = collection.getSerde().deserializeUserData(createEntity.getNew().getValue(), + Map.class); assertThat(newDoc).containsAllEntriesOf(doc); } @@ -429,7 +358,8 @@ void insertDocumentAsBytes(ArangoCollection collection) { @MethodSource("cols") void insertDocumentSilent(ArangoCollection collection) { assumeTrue(isSingleServer()); - final DocumentCreateEntity meta = collection.insertDocument(new BaseDocument(), new DocumentCreateOptions().silent(true)); + final DocumentCreateEntity meta = collection.insertDocument(new BaseDocument(), + new DocumentCreateOptions().silent(true)); assertThat(meta).isNotNull(); assertThat(meta.getId()).isNull(); assertThat(meta.getKey()).isNull(); @@ -443,7 +373,8 @@ void insertDocumentSilentDontTouchInstance(ArangoCollection collection) { final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); final String key = "testkey-" + UUID.randomUUID(); doc.setKey(key); - final DocumentCreateEntity meta = collection.insertDocument(doc, new DocumentCreateOptions().silent(true)); + final DocumentCreateEntity meta = collection.insertDocument(doc, + new DocumentCreateOptions().silent(true)); assertThat(meta).isNotNull(); assertThat(meta.getKey()).isNull(); assertThat(doc.getKey()).isEqualTo(key); @@ -453,7 +384,9 @@ void insertDocumentSilentDontTouchInstance(ArangoCollection collection) { @MethodSource("cols") void insertDocumentsSilent(ArangoCollection collection) { assumeTrue(isSingleServer()); - final MultiDocumentEntity> info = collection.insertDocuments(Arrays.asList(new BaseDocument(), new BaseDocument()), new DocumentCreateOptions().silent(true)); + final MultiDocumentEntity> info = + collection.insertDocuments(Arrays.asList(new BaseDocument(), new BaseDocument()), +new DocumentCreateOptions().silent(true)); assertThat(info).isNotNull(); assertThat(info.getDocuments()).isEmpty(); assertThat(info.getDocumentsAndErrors()).isEmpty(); @@ -543,7 +476,6 @@ void getDocumentNotFoundOptionsNull(ArangoCollection collection) { assertThat(document).isNull(); } - @ParameterizedTest(name = "{index}") @MethodSource("cols") void getDocumentWrongKey(ArangoCollection collection) { @@ -557,7 +489,8 @@ void getDocumentDirtyRead(ArangoCollection collection) throws InterruptedExcepti final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); collection.insertDocument(doc, new DocumentCreateOptions()); Thread.sleep(2000); - final RawJson document = collection.getDocument(doc.getKey(), RawJson.class, new DocumentReadOptions().allowDirtyRead(true)); + final RawJson document = collection.getDocument(doc.getKey(), RawJson.class, + new DocumentReadOptions().allowDirtyRead(true)); assertThat(document).isNotNull(); } @@ -569,11 +502,13 @@ void getDocuments(ArangoCollection collection) { values.add(new BaseDocument("2")); values.add(new BaseDocument("3")); collection.insertDocuments(values); - final MultiDocumentEntity documents = collection.getDocuments(Arrays.asList("1", "2", "3"), BaseDocument.class); + final MultiDocumentEntity documents = collection.getDocuments(Arrays.asList("1", "2", "3"), +BaseDocument.class); assertThat(documents).isNotNull(); assertThat(documents.getDocuments()).hasSize(3); for (final BaseDocument document : documents.getDocuments()) { - assertThat(document.getId()).isIn(COLLECTION_NAME + "/" + "1", COLLECTION_NAME + "/" + "2", COLLECTION_NAME + "/" + "3"); + assertThat(document.getId()).isIn(COLLECTION_NAME + "/" + "1", COLLECTION_NAME + "/" + "2", + COLLECTION_NAME + "/" + "3"); } } @@ -585,12 +520,16 @@ void getDocumentsWithCustomShardingKey(ArangoCollection c) { collection.create(new CollectionCreateOptions().shardKeys("customField").numberOfShards(10)); - List values = IntStream.range(0, 10).mapToObj(String::valueOf).map(key -> new BaseDocument()).peek(it -> it.addAttribute("customField", rnd())).collect(Collectors.toList()); + List values = + IntStream.range(0, 10).mapToObj(String::valueOf).map(key -> new BaseDocument()).peek(it -> it.addAttribute( + "customField", rnd())).collect(Collectors.toList()); MultiDocumentEntity> inserted = collection.insertDocuments(values); - List insertedKeys = inserted.getDocuments().stream().map(DocumentEntity::getKey).collect(Collectors.toList()); + List insertedKeys = + inserted.getDocuments().stream().map(DocumentEntity::getKey).collect(Collectors.toList()); - final Collection documents = collection.getDocuments(insertedKeys, BaseDocument.class).getDocuments(); + final Collection documents = +collection.getDocuments(insertedKeys, BaseDocument.class).getDocuments(); assertThat(documents).hasSize(10); } @@ -603,18 +542,21 @@ void getDocumentsDirtyRead(ArangoCollection collection) { values.add(new BaseDocument("2")); values.add(new BaseDocument("3")); collection.insertDocuments(values); - final MultiDocumentEntity documents = collection.getDocuments(Arrays.asList("1", "2", "3"), BaseDocument.class, new DocumentReadOptions().allowDirtyRead(true)); + final MultiDocumentEntity documents = collection.getDocuments(Arrays.asList("1", "2", "3"), + BaseDocument.class, new DocumentReadOptions().allowDirtyRead(true)); assertThat(documents).isNotNull(); assertThat(documents.getDocuments()).hasSize(3); for (final BaseDocument document : documents.getDocuments()) { - assertThat(document.getId()).isIn(COLLECTION_NAME + "/" + "1", COLLECTION_NAME + "/" + "2", COLLECTION_NAME + "/" + "3"); + assertThat(document.getId()).isIn(COLLECTION_NAME + "/" + "1", COLLECTION_NAME + "/" + "2", + COLLECTION_NAME + "/" + "3"); } } @ParameterizedTest(name = "{index}") @MethodSource("cols") void getDocumentsNotFound(ArangoCollection collection) { - final MultiDocumentEntity readResult = collection.getDocuments(Collections.singleton("no"), BaseDocument.class); + final MultiDocumentEntity readResult = collection.getDocuments(Collections.singleton("no"), + BaseDocument.class); assertThat(readResult).isNotNull(); assertThat(readResult.getDocuments()).isEmpty(); assertThat(readResult.getErrors()).hasSize(1); @@ -623,7 +565,8 @@ void getDocumentsNotFound(ArangoCollection collection) { @ParameterizedTest(name = "{index}") @MethodSource("cols") void getDocumentsWrongKey(ArangoCollection collection) { - final MultiDocumentEntity readResult = collection.getDocuments(Collections.singleton("no/no"), BaseDocument.class); + final MultiDocumentEntity readResult = collection.getDocuments(Collections.singleton("no/no"), + BaseDocument.class); assertThat(readResult).isNotNull(); assertThat(readResult.getDocuments()).isEmpty(); assertThat(readResult.getErrors()).hasSize(1); @@ -639,7 +582,8 @@ void updateDocument(ArangoCollection collection) { doc.updateAttribute("a", "test1"); doc.addAttribute("b", "test"); doc.updateAttribute("c", null); - final DocumentUpdateEntity updateResult = collection.updateDocument(createResult.getKey(), doc, null); + final DocumentUpdateEntity updateResult = collection.updateDocument(createResult.getKey(), doc, +null); assertThat(updateResult).isNotNull(); assertThat(updateResult.getId()).isEqualTo(createResult.getId()); assertThat(updateResult.getNew()).isNull(); @@ -665,7 +609,8 @@ void updateDocumentWithDifferentReturnType(ArangoCollection collection) { doc.addAttribute("a", "test"); collection.insertDocument(doc); - final DocumentUpdateEntity updateResult = collection.updateDocument(key, Collections.singletonMap("b", "test"), new DocumentUpdateOptions().returnNew(true), BaseDocument.class); + final DocumentUpdateEntity updateResult = collection.updateDocument(key, +Collections.singletonMap("b", "test"), new DocumentUpdateOptions().returnNew(true), BaseDocument.class); assertThat(updateResult).isNotNull(); assertThat(updateResult.getKey()).isEqualTo(key); BaseDocument updated = updateResult.getNew(); @@ -679,7 +624,8 @@ void updateDocumentWithDifferentReturnType(ArangoCollection collection) { void updateDocumentUpdateRev(ArangoCollection collection) { final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); final DocumentCreateEntity createResult = collection.insertDocument(doc, null); - final DocumentUpdateEntity updateResult = collection.updateDocument(createResult.getKey(), doc, null); + final DocumentUpdateEntity updateResult = collection.updateDocument(createResult.getKey(), doc, + null); assertThat(doc.getRevision()).isNull(); assertThat(createResult.getRev()).isNotNull(); assertThat(updateResult.getRev()) @@ -698,7 +644,8 @@ void updateDocumentIfMatch(ArangoCollection collection) { doc.addAttribute("b", "test"); doc.updateAttribute("c", null); final DocumentUpdateOptions options = new DocumentUpdateOptions().ifMatch(createResult.getRev()); - final DocumentUpdateEntity updateResult = collection.updateDocument(createResult.getKey(), doc, options); + final DocumentUpdateEntity updateResult = collection.updateDocument(createResult.getKey(), doc, + options); assertThat(updateResult).isNotNull(); assertThat(updateResult.getId()).isEqualTo(createResult.getId()); assertThat(updateResult.getRev()).isNotEqualTo(updateResult.getOldRev()); @@ -739,7 +686,8 @@ void updateDocumentReturnNew(ArangoCollection collection) { doc.updateAttribute("a", "test1"); doc.addAttribute("b", "test"); final DocumentUpdateOptions options = new DocumentUpdateOptions().returnNew(true); - final DocumentUpdateEntity updateResult = collection.updateDocument(createResult.getKey(), doc, options); + final DocumentUpdateEntity updateResult = collection.updateDocument(createResult.getKey(), doc, + options); assertThat(updateResult).isNotNull(); assertThat(updateResult.getId()).isEqualTo(createResult.getId()); assertThat(updateResult.getOldRev()).isEqualTo(createResult.getRev()); @@ -761,7 +709,8 @@ void updateDocumentReturnOld(ArangoCollection collection) { doc.updateAttribute("a", "test1"); doc.addAttribute("b", "test"); final DocumentUpdateOptions options = new DocumentUpdateOptions().returnOld(true); - final DocumentUpdateEntity updateResult = collection.updateDocument(createResult.getKey(), doc, options); + final DocumentUpdateEntity updateResult = collection.updateDocument(createResult.getKey(), doc, + options); assertThat(updateResult).isNotNull(); assertThat(updateResult.getId()).isEqualTo(createResult.getId()); assertThat(updateResult.getOldRev()).isEqualTo(createResult.getRev()); @@ -781,7 +730,8 @@ void updateDocumentKeepNullTrue(ArangoCollection collection) { final DocumentCreateEntity createResult = collection.insertDocument(doc, null); doc.updateAttribute("a", null); final DocumentUpdateOptions options = new DocumentUpdateOptions().keepNull(true); - final DocumentUpdateEntity updateResult = collection.updateDocument(createResult.getKey(), doc, options); + final DocumentUpdateEntity updateResult = collection.updateDocument(createResult.getKey(), doc, + options); assertThat(updateResult).isNotNull(); assertThat(updateResult.getId()).isEqualTo(createResult.getId()); assertThat(updateResult.getRev()).isNotEqualTo(updateResult.getOldRev()); @@ -800,7 +750,8 @@ void updateDocumentKeepNullFalse(ArangoCollection collection) { final DocumentCreateEntity createResult = collection.insertDocument(doc, null); doc.updateAttribute("a", null); final DocumentUpdateOptions options = new DocumentUpdateOptions().keepNull(false); - final DocumentUpdateEntity updateResult = collection.updateDocument(createResult.getKey(), doc, options); + final DocumentUpdateEntity updateResult = collection.updateDocument(createResult.getKey(), doc, + options); assertThat(updateResult).isNotNull(); assertThat(updateResult.getId()).isEqualTo(createResult.getId()); assertThat(updateResult.getRev()).isNotEqualTo(updateResult.getOldRev()); @@ -813,32 +764,6 @@ void updateDocumentKeepNullFalse(ArangoCollection collection) { assertThat(readResult.getProperties().keySet()).doesNotContain("a"); } - public static class TestUpdateEntity { - private String a, b; - - public String getA() { - return a; - } - - public String getB() { - return b; - } - } - - public static class TestUpdateEntitySerializeNullFalse { - private String a, b; - - @JsonInclude(JsonInclude.Include.NON_NULL) - public String getA() { - return a; - } - - @JsonInclude(JsonInclude.Include.NON_NULL) - public String getB() { - return b; - } - } - @ParameterizedTest(name = "{index}") @MethodSource("cols") void updateDocumentSerializeNullTrue(ArangoCollection collection) { @@ -890,7 +815,8 @@ void updateDocumentMergeObjectsTrue(ArangoCollection collection) { a.put("b", "test"); doc.updateAttribute("a", a); final DocumentUpdateOptions options = new DocumentUpdateOptions().mergeObjects(true); - final DocumentUpdateEntity updateResult = collection.updateDocument(createResult.getKey(), doc, options); + final DocumentUpdateEntity updateResult = collection.updateDocument(createResult.getKey(), doc, +options); assertThat(updateResult).isNotNull(); assertThat(updateResult.getId()).isEqualTo(createResult.getId()); assertThat(updateResult.getRev()).isNotEqualTo(updateResult.getOldRev()); @@ -916,7 +842,8 @@ void updateDocumentMergeObjectsFalse(ArangoCollection collection) { a.put("b", "test"); doc.updateAttribute("a", a); final DocumentUpdateOptions options = new DocumentUpdateOptions().mergeObjects(false); - final DocumentUpdateEntity updateResult = collection.updateDocument(createResult.getKey(), doc, options); + final DocumentUpdateEntity updateResult = collection.updateDocument(createResult.getKey(), doc, + options); assertThat(updateResult).isNotNull(); assertThat(updateResult.getId()).isEqualTo(createResult.getId()); assertThat(updateResult.getRev()).isNotEqualTo(updateResult.getOldRev()); @@ -950,7 +877,8 @@ void updateDocumentIgnoreRevsFalse(ArangoCollection collection) { void updateDocumentSilent(ArangoCollection collection) { assumeTrue(isSingleServer()); final DocumentCreateEntity createResult = collection.insertDocument(new BaseDocument()); - final DocumentUpdateEntity meta = collection.updateDocument(createResult.getKey(), new BaseDocument(), new DocumentUpdateOptions().silent(true)); + final DocumentUpdateEntity meta = collection.updateDocument(createResult.getKey(), + new BaseDocument(), new DocumentUpdateOptions().silent(true)); assertThat(meta).isNotNull(); assertThat(meta.getId()).isNull(); assertThat(meta.getKey()).isNull(); @@ -962,7 +890,9 @@ void updateDocumentSilent(ArangoCollection collection) { void updateDocumentsSilent(ArangoCollection collection) { assumeTrue(isSingleServer()); final DocumentCreateEntity createResult = collection.insertDocument(new BaseDocument()); - final MultiDocumentEntity> info = collection.updateDocuments(Collections.singletonList(new BaseDocument(createResult.getKey())), new DocumentUpdateOptions().silent(true)); + final MultiDocumentEntity> info = +collection.updateDocuments(Collections.singletonList(new BaseDocument(createResult.getKey())), + new DocumentUpdateOptions().silent(true)); assertThat(info).isNotNull(); assertThat(info.getDocuments()).isEmpty(); assertThat(info.getDocumentsAndErrors()).isEmpty(); @@ -994,7 +924,8 @@ void updateDocumentPreconditionFailed(ArangoCollection collection) { collection.updateDocument(doc.getKey(), doc, null); doc.updateAttribute("foo", "c"); - Throwable thrown = catchThrowable(() -> collection.updateDocument(doc.getKey(), doc, new DocumentUpdateOptions().ifMatch(createResult.getRev()))); + Throwable thrown = catchThrowable(() -> collection.updateDocument(doc.getKey(), doc, + new DocumentUpdateOptions().ifMatch(createResult.getRev()))); assertThat(thrown).isInstanceOf(ArangoDBException.class); ArangoDBException e = (ArangoDBException) thrown; assertThat(e.getResponseCode()).isEqualTo(412); @@ -1011,7 +942,8 @@ void replaceDocument(ArangoCollection collection) { final DocumentCreateEntity createResult = collection.insertDocument(doc, null); doc.removeAttribute("a"); doc.addAttribute("b", "test"); - final DocumentUpdateEntity replaceResult = collection.replaceDocument(createResult.getKey(), doc, null); + final DocumentUpdateEntity replaceResult = collection.replaceDocument(createResult.getKey(), +doc, null); assertThat(replaceResult).isNotNull(); assertThat(replaceResult.getId()).isEqualTo(createResult.getId()); assertThat(replaceResult.getNew()).isNull(); @@ -1032,7 +964,8 @@ void replaceDocument(ArangoCollection collection) { void replaceDocumentUpdateRev(ArangoCollection collection) { final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); final DocumentCreateEntity createResult = collection.insertDocument(doc, null); - final DocumentUpdateEntity replaceResult = collection.replaceDocument(createResult.getKey(), doc, null); + final DocumentUpdateEntity replaceResult = collection.replaceDocument(createResult.getKey(), + doc, null); assertThat(doc.getRevision()).isNull(); assertThat(createResult.getRev()).isNotNull(); assertThat(replaceResult.getRev()) @@ -1049,7 +982,8 @@ void replaceDocumentIfMatch(ArangoCollection collection) { doc.removeAttribute("a"); doc.addAttribute("b", "test"); final DocumentReplaceOptions options = new DocumentReplaceOptions().ifMatch(createResult.getRev()); - final DocumentUpdateEntity replaceResult = collection.replaceDocument(createResult.getKey(), doc, options); + final DocumentUpdateEntity replaceResult = collection.replaceDocument(createResult.getKey(), + doc, options); assertThat(replaceResult).isNotNull(); assertThat(replaceResult.getId()).isEqualTo(createResult.getId()); assertThat(replaceResult.getRev()).isNotEqualTo(replaceResult.getOldRev()); @@ -1102,7 +1036,8 @@ void replaceDocumentReturnNew(ArangoCollection collection) { doc.removeAttribute("a"); doc.addAttribute("b", "test"); final DocumentReplaceOptions options = new DocumentReplaceOptions().returnNew(true); - final DocumentUpdateEntity replaceResult = collection.replaceDocument(createResult.getKey(), doc, options); + final DocumentUpdateEntity replaceResult = collection.replaceDocument(createResult.getKey(), +doc, options); assertThat(replaceResult).isNotNull(); assertThat(replaceResult.getId()).isEqualTo(createResult.getId()); assertThat(replaceResult.getOldRev()).isEqualTo(createResult.getRev()); @@ -1123,7 +1058,8 @@ void replaceDocumentReturnOld(ArangoCollection collection) { doc.removeAttribute("a"); doc.addAttribute("b", "test"); final DocumentReplaceOptions options = new DocumentReplaceOptions().returnOld(true); - final DocumentUpdateEntity replaceResult = collection.replaceDocument(createResult.getKey(), doc, options); + final DocumentUpdateEntity replaceResult = collection.replaceDocument(createResult.getKey(), + doc, options); assertThat(replaceResult).isNotNull(); assertThat(replaceResult.getId()).isEqualTo(createResult.getId()); assertThat(replaceResult.getOldRev()).isEqualTo(createResult.getRev()); @@ -1140,7 +1076,8 @@ void replaceDocumentReturnOld(ArangoCollection collection) { void replaceDocumentSilent(ArangoCollection collection) { assumeTrue(isSingleServer()); final DocumentCreateEntity createResult = collection.insertDocument(new BaseDocument()); - final DocumentUpdateEntity meta = collection.replaceDocument(createResult.getKey(), new BaseDocument(), new DocumentReplaceOptions().silent(true)); + final DocumentUpdateEntity meta = collection.replaceDocument(createResult.getKey(), +new BaseDocument(), new DocumentReplaceOptions().silent(true)); assertThat(meta).isNotNull(); assertThat(meta.getId()).isNull(); assertThat(meta.getKey()).isNull(); @@ -1153,7 +1090,8 @@ void replaceDocumentSilentDontTouchInstance(ArangoCollection collection) { assumeTrue(isSingleServer()); final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); final DocumentCreateEntity createResult = collection.insertDocument(doc); - final DocumentUpdateEntity meta = collection.replaceDocument(createResult.getKey(), doc, new DocumentReplaceOptions().silent(true)); + final DocumentUpdateEntity meta = collection.replaceDocument(createResult.getKey(), doc, + new DocumentReplaceOptions().silent(true)); assertThat(meta.getRev()).isNull(); assertThat(doc.getRevision()).isNull(); assertThat(createResult.getRev()).isNotNull(); @@ -1164,7 +1102,9 @@ void replaceDocumentSilentDontTouchInstance(ArangoCollection collection) { void replaceDocumentsSilent(ArangoCollection collection) { assumeTrue(isSingleServer()); final DocumentCreateEntity createResult = collection.insertDocument(new BaseDocument()); - final MultiDocumentEntity> info = collection.replaceDocuments(Collections.singletonList(new BaseDocument(createResult.getKey())), new DocumentReplaceOptions().silent(true)); + final MultiDocumentEntity> info = + collection.replaceDocuments(Collections.singletonList(new BaseDocument(createResult.getKey())), + new DocumentReplaceOptions().silent(true)); assertThat(info).isNotNull(); assertThat(info.getDocuments()).isEmpty(); assertThat(info.getDocumentsAndErrors()).isEmpty(); @@ -1188,7 +1128,8 @@ void deleteDocumentReturnOld(ArangoCollection collection) { doc.addAttribute("a", "test"); final DocumentCreateEntity createResult = collection.insertDocument(doc, null); final DocumentDeleteOptions options = new DocumentDeleteOptions().returnOld(true); - final DocumentDeleteEntity deleteResult = collection.deleteDocument(createResult.getKey(), options, BaseDocument.class); + final DocumentDeleteEntity deleteResult = collection.deleteDocument(createResult.getKey(), + options, BaseDocument.class); assertThat(deleteResult.getOld()).isNotNull(); assertThat(deleteResult.getOld()).isInstanceOf(BaseDocument.class); assertThat(deleteResult.getOld().getAttribute("a")).isNotNull(); @@ -1221,7 +1162,8 @@ void deleteDocumentIfMatchFail(ArangoCollection collection) { void deleteDocumentSilent(ArangoCollection collection) { assumeTrue(isSingleServer()); final DocumentCreateEntity createResult = collection.insertDocument(new BaseDocument()); - final DocumentDeleteEntity meta = collection.deleteDocument(createResult.getKey(), new DocumentDeleteOptions().silent(true), BaseDocument.class); + final DocumentDeleteEntity meta = collection.deleteDocument(createResult.getKey(), + new DocumentDeleteOptions().silent(true), BaseDocument.class); assertThat(meta).isNotNull(); assertThat(meta.getId()).isNull(); assertThat(meta.getKey()).isNull(); @@ -1563,7 +1505,8 @@ void createZKDIndexWithOptions(ArangoCollection collection) { collection.truncate(); String name = "ZKDIndex-" + rnd(); - final ZKDIndexOptions options = new ZKDIndexOptions().name(name).fieldValueTypes(ZKDIndexOptions.FieldValueTypes.DOUBLE); + final ZKDIndexOptions options = + new ZKDIndexOptions().name(name).fieldValueTypes(ZKDIndexOptions.FieldValueTypes.DOUBLE); String f1 = "field-" + rnd(); String f2 = "field-" + rnd(); @@ -1749,7 +1692,8 @@ void getIndexes(ArangoCollection collection) { String f1 = "field-" + rnd(); final Collection fields = Collections.singletonList(f1); collection.ensureHashIndex(fields, null); - long matchingIndexes = collection.getIndexes().stream().filter(i -> i.getType() == IndexType.hash).filter(i -> i.getFields().contains(f1)).count(); + long matchingIndexes = + collection.getIndexes().stream().filter(i -> i.getType() == IndexType.hash).filter(i -> i.getFields().contains(f1)).count(); assertThat(matchingIndexes).isEqualTo(1L); } @@ -1806,7 +1750,6 @@ void documentExists(ArangoCollection collection) { assertThat(exists).isTrue(); } - @ParameterizedTest(name = "{index}") @MethodSource("cols") void documentExistsIfMatch(ArangoCollection collection) { @@ -1854,7 +1797,8 @@ void documentExistsIfNoneMatchFail(ArangoCollection collection) { @ParameterizedTest(name = "{index}") @MethodSource("cols") void insertDocuments(ArangoCollection collection) { - final Collection values = Arrays.asList(new BaseDocument(), new BaseDocument(), new BaseDocument()); + final Collection values = Arrays.asList(new BaseDocument(), new BaseDocument(), + new BaseDocument()); final MultiDocumentEntity docs = collection.insertDocuments(values); assertThat(docs).isNotNull(); @@ -1880,7 +1824,9 @@ void insertDocumentsOverwriteModeUpdate(ArangoCollection collection) { doc1.addAttribute("bar", "b"); doc2.addAttribute("bar", "b"); - final MultiDocumentEntity> repsert = collection.insertDocuments(Arrays.asList(doc1, doc2), new DocumentCreateOptions().overwriteMode(OverwriteMode.update).returnNew(true)); + final MultiDocumentEntity> repsert = + collection.insertDocuments(Arrays.asList(doc1, doc2), + new DocumentCreateOptions().overwriteMode(OverwriteMode.update).returnNew(true)); assertThat(repsert).isNotNull(); assertThat(repsert.getDocuments()).hasSize(2); assertThat(repsert.getErrors()).isEmpty(); @@ -1976,7 +1922,8 @@ void insertDocumentsReturnNew(ArangoCollection collection) { values.add(new BaseDocument()); values.add(new BaseDocument()); final DocumentCreateOptions options = new DocumentCreateOptions().returnNew(true); - final MultiDocumentEntity> docs = collection.insertDocuments(values, options); + final MultiDocumentEntity> docs = collection.insertDocuments(values, + options); assertThat(docs).isNotNull(); assertThat(docs.getDocuments()).isNotNull(); assertThat(docs.getDocuments()).hasSize(3); @@ -1995,7 +1942,8 @@ void insertDocumentsReturnNew(ArangoCollection collection) { void insertDocumentsFail(ArangoCollection collection) { String k1 = rnd(); String k2 = rnd(); - final Collection values = Arrays.asList(new BaseDocument(k1), new BaseDocument(k2), new BaseDocument(k2)); + final Collection values = Arrays.asList(new BaseDocument(k1), new BaseDocument(k2), + new BaseDocument(k2)); final MultiDocumentEntity docs = collection.insertDocuments(values); assertThat(docs).isNotNull(); @@ -2009,7 +1957,8 @@ void insertDocumentsFail(ArangoCollection collection) { @ParameterizedTest(name = "{index}") @MethodSource("cols") void importDocuments(ArangoCollection collection) { - final Collection values = Arrays.asList(new BaseDocument(), new BaseDocument(), new BaseDocument()); + final Collection values = Arrays.asList(new BaseDocument(), new BaseDocument(), + new BaseDocument()); final DocumentImportEntity docs = collection.importDocuments(values); assertThat(docs).isNotNull(); @@ -2046,7 +1995,8 @@ void importDocumentsDuplicateDefaultError(ArangoCollection collection) { String k1 = rnd(); String k2 = rnd(); - final Collection values = Arrays.asList(new BaseDocument(k1), new BaseDocument(k2), new BaseDocument(k2)); + final Collection values = Arrays.asList(new BaseDocument(k1), new BaseDocument(k2), +new BaseDocument(k2)); final DocumentImportEntity docs = collection.importDocuments(values); assertThat(docs).isNotNull(); @@ -2064,9 +2014,11 @@ void importDocumentsDuplicateError(ArangoCollection collection) { String k1 = rnd(); String k2 = rnd(); - final Collection values = Arrays.asList(new BaseDocument(k1), new BaseDocument(k2), new BaseDocument(k2)); + final Collection values = Arrays.asList(new BaseDocument(k1), new BaseDocument(k2), + new BaseDocument(k2)); - final DocumentImportEntity docs = collection.importDocuments(values, new DocumentImportOptions().onDuplicate(OnDuplicate.error)); + final DocumentImportEntity docs = collection.importDocuments(values, + new DocumentImportOptions().onDuplicate(OnDuplicate.error)); assertThat(docs).isNotNull(); assertThat(docs.getCreated()).isEqualTo(2); assertThat(docs.getEmpty()).isZero(); @@ -2082,9 +2034,11 @@ void importDocumentsDuplicateIgnore(ArangoCollection collection) { String k1 = rnd(); String k2 = rnd(); - final Collection values = Arrays.asList(new BaseDocument(k1), new BaseDocument(k2), new BaseDocument(k2)); + final Collection values = Arrays.asList(new BaseDocument(k1), new BaseDocument(k2), + new BaseDocument(k2)); - final DocumentImportEntity docs = collection.importDocuments(values, new DocumentImportOptions().onDuplicate(OnDuplicate.ignore)); + final DocumentImportEntity docs = collection.importDocuments(values, + new DocumentImportOptions().onDuplicate(OnDuplicate.ignore)); assertThat(docs).isNotNull(); assertThat(docs.getCreated()).isEqualTo(2); assertThat(docs.getEmpty()).isZero(); @@ -2100,9 +2054,11 @@ void importDocumentsDuplicateReplace(ArangoCollection collection) { String k1 = rnd(); String k2 = rnd(); - final Collection values = Arrays.asList(new BaseDocument(k1), new BaseDocument(k2), new BaseDocument(k2)); + final Collection values = Arrays.asList(new BaseDocument(k1), new BaseDocument(k2), + new BaseDocument(k2)); - final DocumentImportEntity docs = collection.importDocuments(values, new DocumentImportOptions().onDuplicate(OnDuplicate.replace)); + final DocumentImportEntity docs = collection.importDocuments(values, +new DocumentImportOptions().onDuplicate(OnDuplicate.replace)); assertThat(docs).isNotNull(); assertThat(docs.getCreated()).isEqualTo(2); assertThat(docs.getEmpty()).isZero(); @@ -2118,9 +2074,11 @@ void importDocumentsDuplicateUpdate(ArangoCollection collection) { String k1 = rnd(); String k2 = rnd(); - final Collection values = Arrays.asList(new BaseDocument(k1), new BaseDocument(k2), new BaseDocument(k2)); + final Collection values = Arrays.asList(new BaseDocument(k1), new BaseDocument(k2), + new BaseDocument(k2)); - final DocumentImportEntity docs = collection.importDocuments(values, new DocumentImportOptions().onDuplicate(OnDuplicate.update)); + final DocumentImportEntity docs = collection.importDocuments(values, + new DocumentImportOptions().onDuplicate(OnDuplicate.update)); assertThat(docs).isNotNull(); assertThat(docs.getCreated()).isEqualTo(2); assertThat(docs.getEmpty()).isZero(); @@ -2136,9 +2094,11 @@ void importDocumentsCompleteFail(ArangoCollection collection) { String k1 = rnd(); String k2 = rnd(); - final Collection values = Arrays.asList(new BaseDocument(k1), new BaseDocument(k2), new BaseDocument(k2)); + final Collection values = Arrays.asList(new BaseDocument(k1), new BaseDocument(k2), + new BaseDocument(k2)); - Throwable thrown = catchThrowable(() -> collection.importDocuments(values, new DocumentImportOptions().complete(true))); + Throwable thrown = catchThrowable(() -> collection.importDocuments(values, + new DocumentImportOptions().complete(true))); assertThat(thrown).isInstanceOf(ArangoDBException.class); ArangoDBException e = (ArangoDBException) thrown; assertThat(e.getErrorNum()).isEqualTo(1210); @@ -2150,7 +2110,8 @@ void importDocumentsDetails(ArangoCollection collection) { String k1 = rnd(); String k2 = rnd(); - final Collection values = Arrays.asList(new BaseDocument(k1), new BaseDocument(k2), new BaseDocument(k2)); + final Collection values = Arrays.asList(new BaseDocument(k1), new BaseDocument(k2), + new BaseDocument(k2)); final DocumentImportEntity docs = collection.importDocuments(values, new DocumentImportOptions().details(true)); assertThat(docs).isNotNull(); @@ -2198,7 +2159,8 @@ void importDocumentsFromToPrefix(ArangoCollection edgeCollection) { } assertThat(values).hasSize(keys.length); - final DocumentImportEntity importResult = edgeCollection.importDocuments(values, new DocumentImportOptions().fromPrefix("foo").toPrefix("bar")); + final DocumentImportEntity importResult = edgeCollection.importDocuments(values, + new DocumentImportOptions().fromPrefix("foo").toPrefix("bar")); assertThat(importResult).isNotNull(); assertThat(importResult.getCreated()).isEqualTo(values.size()); for (String key : keys) { @@ -2212,7 +2174,8 @@ void importDocumentsFromToPrefix(ArangoCollection edgeCollection) { @ParameterizedTest(name = "{index}") @MethodSource("cols") void importDocumentsJson(ArangoCollection collection) throws JsonProcessingException { - final String values = mapper.writeValueAsString(Arrays.asList(Collections.singletonMap("_key", rnd()), Collections.singletonMap("_key", rnd()))); + final String values = mapper.writeValueAsString(Arrays.asList(Collections.singletonMap("_key", rnd()), + Collections.singletonMap("_key", rnd()))); final DocumentImportEntity docs = collection.importDocuments(RawData.of(values)); assertThat(docs).isNotNull(); @@ -2230,7 +2193,8 @@ void importDocumentsJsonDuplicateDefaultError(ArangoCollection collection) throw String k1 = rnd(); String k2 = rnd(); - final String values = mapper.writeValueAsString(Arrays.asList(Collections.singletonMap("_key", k1), Collections.singletonMap("_key", k2), Collections.singletonMap("_key", k2))); + final String values = mapper.writeValueAsString(Arrays.asList(Collections.singletonMap("_key", k1), + Collections.singletonMap("_key", k2), Collections.singletonMap("_key", k2))); final DocumentImportEntity docs = collection.importDocuments(RawData.of(values)); assertThat(docs).isNotNull(); @@ -2248,9 +2212,11 @@ void importDocumentsJsonDuplicateError(ArangoCollection collection) throws JsonP String k1 = rnd(); String k2 = rnd(); - final String values = mapper.writeValueAsString(Arrays.asList(Collections.singletonMap("_key", k1), Collections.singletonMap("_key", k2), Collections.singletonMap("_key", k2))); + final String values = mapper.writeValueAsString(Arrays.asList(Collections.singletonMap("_key", k1), + Collections.singletonMap("_key", k2), Collections.singletonMap("_key", k2))); - final DocumentImportEntity docs = collection.importDocuments(RawData.of(values), new DocumentImportOptions().onDuplicate(OnDuplicate.error)); + final DocumentImportEntity docs = collection.importDocuments(RawData.of(values), + new DocumentImportOptions().onDuplicate(OnDuplicate.error)); assertThat(docs).isNotNull(); assertThat(docs.getCreated()).isEqualTo(2); assertThat(docs.getEmpty()).isZero(); @@ -2266,8 +2232,10 @@ void importDocumentsJsonDuplicateIgnore(ArangoCollection collection) throws Json String k1 = rnd(); String k2 = rnd(); - final String values = mapper.writeValueAsString(Arrays.asList(Collections.singletonMap("_key", k1), Collections.singletonMap("_key", k2), Collections.singletonMap("_key", k2))); - final DocumentImportEntity docs = collection.importDocuments(RawData.of(values), new DocumentImportOptions().onDuplicate(OnDuplicate.ignore)); + final String values = mapper.writeValueAsString(Arrays.asList(Collections.singletonMap("_key", k1), + Collections.singletonMap("_key", k2), Collections.singletonMap("_key", k2))); + final DocumentImportEntity docs = collection.importDocuments(RawData.of(values), + new DocumentImportOptions().onDuplicate(OnDuplicate.ignore)); assertThat(docs).isNotNull(); assertThat(docs.getCreated()).isEqualTo(2); assertThat(docs.getEmpty()).isZero(); @@ -2283,9 +2251,11 @@ void importDocumentsJsonDuplicateReplace(ArangoCollection collection) throws Jso String k1 = rnd(); String k2 = rnd(); - final String values = mapper.writeValueAsString(Arrays.asList(Collections.singletonMap("_key", k1), Collections.singletonMap("_key", k2), Collections.singletonMap("_key", k2))); + final String values = mapper.writeValueAsString(Arrays.asList(Collections.singletonMap("_key", k1), + Collections.singletonMap("_key", k2), Collections.singletonMap("_key", k2))); - final DocumentImportEntity docs = collection.importDocuments(RawData.of(values), new DocumentImportOptions().onDuplicate(OnDuplicate.replace)); + final DocumentImportEntity docs = collection.importDocuments(RawData.of(values), + new DocumentImportOptions().onDuplicate(OnDuplicate.replace)); assertThat(docs).isNotNull(); assertThat(docs.getCreated()).isEqualTo(2); assertThat(docs.getEmpty()).isZero(); @@ -2301,9 +2271,11 @@ void importDocumentsJsonDuplicateUpdate(ArangoCollection collection) throws Json String k1 = rnd(); String k2 = rnd(); - final String values = mapper.writeValueAsString(Arrays.asList(Collections.singletonMap("_key", k1), Collections.singletonMap("_key", k2), Collections.singletonMap("_key", k2))); + final String values = mapper.writeValueAsString(Arrays.asList(Collections.singletonMap("_key", k1), +Collections.singletonMap("_key", k2), Collections.singletonMap("_key", k2))); - final DocumentImportEntity docs = collection.importDocuments(RawData.of(values), new DocumentImportOptions().onDuplicate(OnDuplicate.update)); + final DocumentImportEntity docs = collection.importDocuments(RawData.of(values), + new DocumentImportOptions().onDuplicate(OnDuplicate.update)); assertThat(docs).isNotNull(); assertThat(docs.getCreated()).isEqualTo(2); assertThat(docs.getEmpty()).isZero(); @@ -2317,7 +2289,8 @@ void importDocumentsJsonDuplicateUpdate(ArangoCollection collection) throws Json @MethodSource("cols") void importDocumentsJsonCompleteFail(ArangoCollection collection) { final String values = "[{\"_key\":\"1\"},{\"_key\":\"2\"},{\"_key\":\"2\"}]"; - Throwable thrown = catchThrowable(() -> collection.importDocuments(RawData.of(values), new DocumentImportOptions().complete(true))); + Throwable thrown = catchThrowable(() -> collection.importDocuments(RawData.of(values), + new DocumentImportOptions().complete(true))); assertThat(thrown).isInstanceOf(ArangoDBException.class); ArangoDBException e = (ArangoDBException) thrown; assertThat(e.getErrorNum()).isEqualTo(1210); @@ -2329,9 +2302,11 @@ void importDocumentsJsonDetails(ArangoCollection collection) throws JsonProcessi String k1 = rnd(); String k2 = rnd(); - final String values = mapper.writeValueAsString(Arrays.asList(Collections.singletonMap("_key", k1), Collections.singletonMap("_key", k2), Collections.singletonMap("_key", k2))); + final String values = mapper.writeValueAsString(Arrays.asList(Collections.singletonMap("_key", k1), + Collections.singletonMap("_key", k2), Collections.singletonMap("_key", k2))); - final DocumentImportEntity docs = collection.importDocuments(RawData.of(values), new DocumentImportOptions().details(true)); + final DocumentImportEntity docs = collection.importDocuments(RawData.of(values), +new DocumentImportOptions().details(true)); assertThat(docs).isNotNull(); assertThat(docs.getCreated()).isEqualTo(2); assertThat(docs.getEmpty()).isZero(); @@ -2348,7 +2323,8 @@ void importDocumentsJsonOverwriteFalse(ArangoCollection collection) throws JsonP collection.insertDocument(new BaseDocument()); Long initialCount = collection.count().getCount(); - final String values = mapper.writeValueAsString(Arrays.asList(Collections.singletonMap("_key", rnd()), Collections.singletonMap("_key", rnd()))); + final String values = mapper.writeValueAsString(Arrays.asList(Collections.singletonMap("_key", rnd()), + Collections.singletonMap("_key", rnd()))); collection.importDocuments(RawData.of(values), new DocumentImportOptions().overwrite(false)); assertThat(collection.count().getCount()).isEqualTo(initialCount + 2L); } @@ -2358,7 +2334,8 @@ void importDocumentsJsonOverwriteFalse(ArangoCollection collection) throws JsonP void importDocumentsJsonOverwriteTrue(ArangoCollection collection) throws JsonProcessingException { collection.insertDocument(new BaseDocument()); - final String values = mapper.writeValueAsString(Arrays.asList(Collections.singletonMap("_key", rnd()), Collections.singletonMap("_key", rnd()))); + final String values = mapper.writeValueAsString(Arrays.asList(Collections.singletonMap("_key", rnd()), + Collections.singletonMap("_key", rnd()))); collection.importDocuments(RawData.of(values), new DocumentImportOptions().overwrite(true)); assertThat(collection.count().getCount()).isEqualTo(2L); } @@ -2371,9 +2348,11 @@ void importDocumentsJsonFromToPrefix(ArangoCollection edgeCollection) throws Jso final String[] keys = {k1, k2}; - final String values = mapper.writeValueAsString(Arrays.asList(new MapBuilder().put("_key", k1).put("_from", "from").put("_to", "to").get(), new MapBuilder().put("_key", k2).put("_from", "from").put("_to", "to").get())); + final String values = mapper.writeValueAsString(Arrays.asList(new MapBuilder().put("_key", k1).put("_from", + "from").put("_to", "to").get(), new MapBuilder().put("_key", k2).put("_from", "from").put("_to", "to").get())); - final DocumentImportEntity importResult = edgeCollection.importDocuments(RawData.of(values), new DocumentImportOptions().fromPrefix("foo").toPrefix("bar")); + final DocumentImportEntity importResult = edgeCollection.importDocuments(RawData.of(values), +new DocumentImportOptions().fromPrefix("foo").toPrefix("bar")); assertThat(importResult).isNotNull(); assertThat(importResult.getCreated()).isEqualTo(2); for (String key : keys) { @@ -2554,8 +2533,10 @@ void updateDocuments(ArangoCollection collection) { @ParameterizedTest(name = "{index}") @MethodSource("cols") void updateDocumentsWithDifferentReturnType(ArangoCollection collection) { - List keys = IntStream.range(0, 3).mapToObj(it -> "key-" + UUID.randomUUID()).collect(Collectors.toList()); - List docs = keys.stream().map(BaseDocument::new).peek(it -> it.addAttribute("a", "test")).collect(Collectors.toList()); + List keys = + IntStream.range(0, 3).mapToObj(it -> "key-" + UUID.randomUUID()).collect(Collectors.toList()); + List docs = + keys.stream().map(BaseDocument::new).peek(it -> it.addAttribute("a", "test")).collect(Collectors.toList()); collection.insertDocuments(docs); @@ -2567,7 +2548,8 @@ void updateDocumentsWithDifferentReturnType(ArangoCollection collection) { return map; }).collect(Collectors.toList()); - final MultiDocumentEntity> updateResult = collection.updateDocuments(modifiedDocs, new DocumentUpdateOptions().returnNew(true), BaseDocument.class); + final MultiDocumentEntity> updateResult = + collection.updateDocuments(modifiedDocs, new DocumentUpdateOptions().returnNew(true), BaseDocument.class); assertThat(updateResult.getDocuments()).hasSize(3); assertThat(updateResult.getErrors()).isEmpty(); assertThat(updateResult.getDocuments().stream()).map(DocumentUpdateEntity::getNew).allMatch(it -> it.getAttribute("a").equals("test")).allMatch(it -> it.getAttribute("b").equals("test")); @@ -2642,7 +2624,8 @@ void updateDocumentsRawData(ArangoCollection collection) { final RawData values = RawData.of("[{\"_key\":\"1\"}, {\"_key\":\"2\"}]"); collection.insertDocuments(values); - final RawData updatedValues = RawData.of("[{\"_key\":\"1\", \"foo\":\"bar\"}, {\"_key\":\"2\", \"foo\":\"bar\"}]"); + final RawData updatedValues = RawData.of("[{\"_key\":\"1\", \"foo\":\"bar\"}, {\"_key\":\"2\", " + + "\"foo\":\"bar\"}]"); final MultiDocumentEntity updateResult = collection.updateDocuments(updatedValues); assertThat(updateResult.getDocuments()).hasSize(2); assertThat(updateResult.getErrors()).isEmpty(); @@ -2654,7 +2637,8 @@ void updateDocumentsRawDataReturnNew(ArangoCollection collection) { final RawData values = RawData.of("[{\"_key\":\"1\"}, {\"_key\":\"2\"}]"); collection.insertDocuments(values); - final RawData updatedValues = RawData.of("[{\"_key\":\"1\", \"foo\":\"bar\"}, {\"_key\":\"2\", \"foo\":\"bar\"}]"); + final RawData updatedValues = RawData.of("[{\"_key\":\"1\", \"foo\":\"bar\"}, {\"_key\":\"2\", " + + "\"foo\":\"bar\"}]"); MultiDocumentEntity> updateResult = collection.updateDocuments(updatedValues, new DocumentUpdateOptions().returnNew(true)); assertThat(updateResult.getDocuments()).hasSize(2); @@ -2759,7 +2743,8 @@ void replaceDocumentsRawData(ArangoCollection collection) { final RawData values = RawData.of("[{\"_key\":\"1\"}, {\"_key\":\"2\"}]"); collection.insertDocuments(values); - final RawData updatedValues = RawData.of("[{\"_key\":\"1\", \"foo\":\"bar\"}, {\"_key\":\"2\", \"foo\":\"bar\"}]"); + final RawData updatedValues = RawData.of("[{\"_key\":\"1\", \"foo\":\"bar\"}, {\"_key\":\"2\", " + + "\"foo\":\"bar\"}]"); final MultiDocumentEntity updateResult = collection.replaceDocuments(updatedValues); assertThat(updateResult.getDocuments()).hasSize(2); assertThat(updateResult.getErrors()).isEmpty(); @@ -2771,7 +2756,8 @@ void replaceDocumentsRawDataReturnNew(ArangoCollection collection) { final RawData values = RawData.of("[{\"_key\":\"1\"}, {\"_key\":\"2\"}]"); collection.insertDocuments(values); - final RawData updatedValues = RawData.of("[{\"_key\":\"1\", \"foo\":\"bar\"}, {\"_key\":\"2\", \"foo\":\"bar\"}]"); + final RawData updatedValues = RawData.of("[{\"_key\":\"1\", \"foo\":\"bar\"}, {\"_key\":\"2\", " + + "\"foo\":\"bar\"}]"); MultiDocumentEntity> updateResult = collection.replaceDocuments(updatedValues, new DocumentReplaceOptions().returnNew(true)); assertThat(updateResult.getDocuments()).hasSize(2); @@ -2812,10 +2798,12 @@ void changeProperties(ArangoCollection collection) { assertThat(properties.getSchema()).isNull(); } - String schemaRule = ("{ " + " \"properties\": {" + " \"number\": {" + " \"type\": \"number\"" + " }" + " }" + " }").replaceAll("\\s", ""); + String schemaRule = ("{ " + " \"properties\": {" + " \"number\": {" + " " + +" \"type\": \"number\"" + " }" + " }" + " }").replaceAll("\\s", ""); String schemaMessage = "The document has problems!"; - CollectionPropertiesOptions updatedOptions = new CollectionPropertiesOptions().waitForSync(!properties.getWaitForSync()).schema(new CollectionSchema().setLevel(CollectionSchema.Level.NEW).setMessage(schemaMessage).setRule(schemaRule)); + CollectionPropertiesOptions updatedOptions = +new CollectionPropertiesOptions().waitForSync(!properties.getWaitForSync()).schema(new CollectionSchema().setLevel(CollectionSchema.Level.NEW).setMessage(schemaMessage).setRule(schemaRule)); final CollectionPropertiesEntity changedProperties = collection.changeProperties(updatedOptions); assertThat(changedProperties.getWaitForSync()).isNotNull(); @@ -2988,6 +2976,116 @@ void getPermissions(ArangoCollection collection) { assertThat(collection.getPermissions("root")).isEqualTo(Permissions.RW); } + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void annotationsInParamsAndMethods(ArangoCollection collection) { + assumeTrue(collection.getSerde().getUserSerde() instanceof JacksonSerde, "JacksonSerde only"); + AnnotatedEntity entity = new AnnotatedEntity(UUID.randomUUID().toString()); + AnnotatedEntity doc = collection.insertDocument(entity, new DocumentCreateOptions().returnNew(true)).getNew(); + assertThat(doc).isNotNull(); + assertThat(doc.getKey()).isEqualTo(entity.getKey()); + assertThat(doc.getId()).isNotNull(); + assertThat(doc.getRev()).isNotNull(); + } + + @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, property = "type") + public interface Animal { + String getKey(); + + String getName(); + } + + public static class Dog implements Animal { + + @Key + private String key; + private String name; + + public Dog() { + } + + public Dog(String key, String name) { + this.key = key; + this.name = name; + } + + @Override + public String getKey() { + return key; + } + + public void setKey(String key) { + this.key = key; + } + + @Override + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + } + + public static class Cat implements Animal { + @Key + private String key; + private String name; + + public Cat() { + } + + public Cat(String key, String name) { + this.key = key; + this.name = name; + } + + @Override + public String getKey() { + return key; + } + + public void setKey(String key) { + this.key = key; + } + + @Override + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + } + + public static class TestUpdateEntity { + private String a, b; + + public String getA() { + return a; + } + + public String getB() { + return b; + } + } + + public static class TestUpdateEntitySerializeNullFalse { + private String a, b; + + @JsonInclude(JsonInclude.Include.NON_NULL) + public String getA() { + return a; + } + + @JsonInclude(JsonInclude.Include.NON_NULL) + public String getB() { + return b; + } + } + public static class AnnotatedEntity { private final String key; @@ -3021,16 +3119,4 @@ public void setRev(String rev) { } } - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void annotationsInParamsAndMethods(ArangoCollection collection) { - assumeTrue(collection.getSerde().getUserSerde() instanceof JacksonSerde, "JacksonSerde only"); - AnnotatedEntity entity = new AnnotatedEntity(UUID.randomUUID().toString()); - AnnotatedEntity doc = collection.insertDocument(entity, new DocumentCreateOptions().returnNew(true)).getNew(); - assertThat(doc).isNotNull(); - assertThat(doc.getKey()).isEqualTo(entity.getKey()); - assertThat(doc.getId()).isNotNull(); - assertThat(doc.getRev()).isNotNull(); - } - } diff --git a/src/test/java/com/arangodb/ArangoCursorTest.java b/src/test/java/com/arangodb/ArangoCursorTest.java index a1988b132..cfbd98775 100644 --- a/src/test/java/com/arangodb/ArangoCursorTest.java +++ b/src/test/java/com/arangodb/ArangoCursorTest.java @@ -26,7 +26,8 @@ import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.MethodSource; -import java.util.*; +import java.util.Optional; +import java.util.Set; import java.util.concurrent.atomic.AtomicLong; import java.util.stream.Collectors; @@ -56,7 +57,8 @@ void firstStream(ArangoDatabase db) { @ParameterizedTest(name = "{index}") @MethodSource("dbs") void next(ArangoDatabase db) { - final ArangoCursor cursor = db.query("FOR i IN 0..99 RETURN i", new AqlQueryOptions().batchSize(5), JsonNode.class); + final ArangoCursor cursor = db.query("FOR i IN 0..99 RETURN i", new AqlQueryOptions().batchSize(5), + JsonNode.class); while (cursor.hasNext()) { cursor.next(); } diff --git a/src/test/java/com/arangodb/ArangoDBTest.java b/src/test/java/com/arangodb/ArangoDBTest.java index c51a12272..fad65f710 100644 --- a/src/test/java/com/arangodb/ArangoDBTest.java +++ b/src/test/java/com/arangodb/ArangoDBTest.java @@ -34,14 +34,7 @@ import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.MethodSource; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.UUID; +import java.util.*; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; import java.util.concurrent.Executors; @@ -104,7 +97,8 @@ void getVersion(ArangoDB arangoDB) { @ParameterizedTest(name = "{index}") @MethodSource("arangos") void createAndDeleteDatabase(ArangoDB arangoDB) { - final DbName dbName = DbName.of("testDB-" + TestUtils.generateRandomDbName(20, supportsExtendedNames(arangoDB))); + final DbName dbName = DbName.of("testDB-" + TestUtils.generateRandomDbName(20, + supportsExtendedNames(arangoDB))); final Boolean resultCreate; resultCreate = arangoDB.createDatabase(dbName); assertThat(resultCreate).isTrue(); @@ -133,7 +127,8 @@ void createWithNotNormalizedName(ArangoDB arangoDB) { void createDatabaseWithOptions(ArangoDB arangoDB) { assumeTrue(isCluster()); assumeTrue(isAtLeastVersion(3, 6)); - final DbName dbName = DbName.of("testDB-" + TestUtils.generateRandomDbName(20, supportsExtendedNames(arangoDB))); + final DbName dbName = DbName.of("testDB-" + TestUtils.generateRandomDbName(20, + supportsExtendedNames(arangoDB))); final Boolean resultCreate = arangoDB.createDatabase(new DBCreateOptions() .name(dbName) .options(new DatabaseOptions() @@ -160,7 +155,8 @@ void createDatabaseWithOptionsSatellite(ArangoDB arangoDB) { assumeTrue(isEnterprise()); assumeTrue(isAtLeastVersion(3, 6)); - final DbName dbName = DbName.of("testDB-" + TestUtils.generateRandomDbName(20, supportsExtendedNames(arangoDB))); + final DbName dbName = DbName.of("testDB-" + TestUtils.generateRandomDbName(20, + supportsExtendedNames(arangoDB))); final Boolean resultCreate = arangoDB.createDatabase(new DBCreateOptions() .name(dbName) .options(new DatabaseOptions() @@ -183,7 +179,8 @@ void createDatabaseWithOptionsSatellite(ArangoDB arangoDB) { @ParameterizedTest(name = "{index}") @MethodSource("arangos") void createDatabaseWithUsers(ArangoDB arangoDB) throws InterruptedException { - final DbName dbName = DbName.of("testDB-" + TestUtils.generateRandomDbName(20, supportsExtendedNames(arangoDB))); + final DbName dbName = DbName.of("testDB-" + TestUtils.generateRandomDbName(20, + supportsExtendedNames(arangoDB))); final Map extra = Collections.singletonMap("key", "value"); final Boolean resultCreate = arangoDB.createDatabase(new DBCreateOptions() .name(dbName) @@ -212,7 +209,7 @@ void createDatabaseWithUsers(ArangoDB arangoDB) throws InterruptedException { Thread.sleep(1_000); ArangoDB arangoDBTestUser = new ArangoDB.Builder() - + .user("testUser") .password("testPasswd") .build(); @@ -391,7 +388,7 @@ void authenticationFailUser() { @ParameterizedTest(name = "{index}") @MethodSource("arangos") - void execute(ArangoDB arangoDB) { + void execute(ArangoDB arangoDB) { final Response response = arangoDB.execute(new Request(DbName.SYSTEM, RequestType.GET, "/_api/version")); assertThat(arangoDB.getSerde().parse(response.getBody(), "/version").isTextual()).isTrue(); } @@ -563,7 +560,8 @@ void fallbackHost() { @MethodSource("arangos") void loadproperties() { Throwable thrown = catchThrowable(() -> - new ArangoDB.Builder().loadProperties(ArangoDBTest.class.getResourceAsStream("/arangodb-bad.properties")) + new ArangoDB.Builder().loadProperties(ArangoDBTest.class.getResourceAsStream("/arangodb-bad" + + ".properties")) ); assertThat(thrown).isInstanceOf(ArangoDBException.class); } @@ -572,7 +570,8 @@ void loadproperties() { @MethodSource("arangos") void loadproperties2() { Throwable thrown = catchThrowable(() -> - new ArangoDB.Builder().loadProperties(ArangoDBTest.class.getResourceAsStream("/arangodb-bad2.properties")) + new ArangoDB.Builder().loadProperties(ArangoDBTest.class.getResourceAsStream("/arangodb-bad2" + + ".properties")) ); assertThat(thrown).isInstanceOf(ArangoDBException.class); } diff --git a/src/test/java/com/arangodb/ArangoDatabaseTest.java b/src/test/java/com/arangodb/ArangoDatabaseTest.java index 2f8aa24de..5898d7f5d 100644 --- a/src/test/java/com/arangodb/ArangoDatabaseTest.java +++ b/src/test/java/com/arangodb/ArangoDatabaseTest.java @@ -536,7 +536,8 @@ void query(ArangoDatabase db) { @ParameterizedTest(name = "{index}") @MethodSource("dbs") void queryWithNullBindVar(ArangoDatabase db) { - final ArangoCursor cursor = db.query("return @foo", Collections.singletonMap("foo", null), null, Object.class); + final ArangoCursor cursor = db.query("return @foo", Collections.singletonMap("foo", null), null, + Object.class); assertThat(cursor.hasNext()).isTrue(); assertThat(cursor.next()).isNull(); } @@ -714,7 +715,8 @@ void queryWithCache(ArangoDatabase db) { @ParameterizedTest(name = "{index}") @MethodSource("dbs") void queryWithMemoryLimit(ArangoDatabase db) { - Throwable thrown = catchThrowable(() -> db.query("RETURN 1..100000", null, new AqlQueryOptions().memoryLimit(32 * 1024L), String.class)); + Throwable thrown = catchThrowable(() -> db.query("RETURN 1..100000", null, + new AqlQueryOptions().memoryLimit(32 * 1024L), String.class)); assertThat(thrown).isInstanceOf(ArangoDBException.class); assertThat(((ArangoDBException) thrown).getErrorNum()).isEqualTo(32); } @@ -722,7 +724,8 @@ void queryWithMemoryLimit(ArangoDatabase db) { @ParameterizedTest(name = "{index}") @MethodSource("dbs") void queryWithFailOnWarningTrue(ArangoDatabase db) { - Throwable thrown = catchThrowable(() -> db.query("RETURN 1 / 0", null, new AqlQueryOptions().failOnWarning(true), String.class)); + Throwable thrown = catchThrowable(() -> db.query("RETURN 1 / 0", null, + new AqlQueryOptions().failOnWarning(true), String.class)); assertThat(thrown).isInstanceOf(ArangoDBException.class); } @@ -738,7 +741,8 @@ void queryWithFailOnWarningFalse(ArangoDatabase db) { @MethodSource("dbs") void queryWithTimeout(ArangoDatabase db) { assumeTrue(isAtLeastVersion(3, 6)); - Throwable thrown = catchThrowable(() -> db.query("RETURN SLEEP(1)", null, new AqlQueryOptions().maxRuntime(0.1), String.class).next()); + Throwable thrown = catchThrowable(() -> db.query("RETURN SLEEP(1)", null, + new AqlQueryOptions().maxRuntime(0.1), String.class).next()); assertThat(thrown).isInstanceOf(ArangoDBException.class); assertThat(((ArangoDBException) thrown).getResponseCode()).isEqualTo(410); } @@ -1123,7 +1127,8 @@ void createGraphReplicationFaktor(ArangoDatabase db) { final String edgeCollection = "edge-" + rnd(); final String fromCollection = "from-" + rnd(); final String toCollection = "to-" + rnd(); - final Collection edgeDefinitions = Collections.singletonList(new EdgeDefinition().collection(edgeCollection).from(fromCollection).to(toCollection)); + final Collection edgeDefinitions = + Collections.singletonList(new EdgeDefinition().collection(edgeCollection).from(fromCollection).to(toCollection)); final GraphEntity result = db.createGraph(name, edgeDefinitions, new GraphCreateOptions().replicationFactor(2)); assertThat(result).isNotNull(); for (final String collection : Arrays.asList(edgeCollection, fromCollection, toCollection)) { @@ -1140,7 +1145,8 @@ void createGraphNumberOfShards(ArangoDatabase db) { final String edgeCollection = "edge-" + rnd(); final String fromCollection = "from-" + rnd(); final String toCollection = "to-" + rnd(); - final Collection edgeDefinitions = Collections.singletonList(new EdgeDefinition().collection(edgeCollection).from(fromCollection).to(toCollection)); + final Collection edgeDefinitions = + Collections.singletonList(new EdgeDefinition().collection(edgeCollection).from(fromCollection).to(toCollection)); final GraphEntity result = db .createGraph(name, edgeDefinitions, new GraphCreateOptions().numberOfShards(2)); assertThat(result).isNotNull(); @@ -1192,7 +1198,8 @@ void transactionJsonObject(ArangoDatabase db) { ObjectNode params = JsonNodeFactory.instance.objectNode().put("foo", "hello").put("bar", "world"); final TransactionOptions options = new TransactionOptions().params(params); final RawJson result = db - .transaction("function (params) { return params['foo'] + ' ' + params['bar'];}", RawJson.class, options); + .transaction("function (params) { return params['foo'] + ' ' + params['bar'];}", RawJson.class, + options); assertThat(result.getValue()).isEqualTo("\"hello world\""); } @@ -1212,7 +1219,8 @@ void transactionMap(ArangoDatabase db) { final Map params = new MapBuilder().put("foo", "hello").put("bar", "world").get(); final TransactionOptions options = new TransactionOptions().params(params); final RawJson result = db - .transaction("function (params) { return params['foo'] + ' ' + params['bar'];}", RawJson.class, options); + .transaction("function (params) { return params['foo'] + ' ' + params['bar'];}", RawJson.class, + options); assertThat(result.getValue()).isEqualTo("\"hello world\""); } @@ -1287,18 +1295,6 @@ void transactionAllowImplicit(ArangoDatabase db) { .isEqualTo(400); } - public static class TransactionTestEntity { - private String value; - - public String getValue() { - return value; - } - - public void setValue(String value) { - this.value = value; - } - } - @ParameterizedTest(name = "{index}") @MethodSource("dbs") void transactionPojoReturn(ArangoDatabase db) { @@ -1363,4 +1359,16 @@ void getDocumentWrongId(ArangoDatabase db) { void reloadRouting(ArangoDatabase db) { db.reloadRouting(); } + + public static class TransactionTestEntity { + private String value; + + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } + } } diff --git a/src/test/java/com/arangodb/ArangoGraphTest.java b/src/test/java/com/arangodb/ArangoGraphTest.java index 9314d5dd1..d254ff985 100644 --- a/src/test/java/com/arangodb/ArangoGraphTest.java +++ b/src/test/java/com/arangodb/ArangoGraphTest.java @@ -58,8 +58,10 @@ class ArangoGraphTest extends BaseJunit5 { private static final Integer REPLICATION_FACTOR = 2; private static final Integer NUMBER_OF_SHARDS = 2; - private static final EdgeDefinition ed1 = new EdgeDefinition().collection(EDGE_COL_1).from(VERTEX_COL_1).to(VERTEX_COL_2); - private static final EdgeDefinition ed2 = new EdgeDefinition().collection(EDGE_COL_2).from(VERTEX_COL_2).to(VERTEX_COL_1, VERTEX_COL_3); + private static final EdgeDefinition ed1 = + new EdgeDefinition().collection(EDGE_COL_1).from(VERTEX_COL_1).to(VERTEX_COL_2); + private static final EdgeDefinition ed2 = + new EdgeDefinition().collection(EDGE_COL_2).from(VERTEX_COL_2).to(VERTEX_COL_1, VERTEX_COL_3); private static Stream graphs() { return dbsStream() @@ -93,7 +95,8 @@ void createWithReplicationAndWriteConcern(ArangoDatabase db) { assumeTrue(isCluster()); final Collection edgeDefinitions = new ArrayList<>(); - final GraphEntity graph = db.createGraph(GRAPH_NAME + "_1", edgeDefinitions, new GraphCreateOptions().isSmart(true).replicationFactor(2).writeConcern(2)); + final GraphEntity graph = db.createGraph(GRAPH_NAME + "_1", edgeDefinitions, + new GraphCreateOptions().isSmart(true).replicationFactor(2).writeConcern(2)); assertThat(graph).isNotNull(); assertThat(graph.getName()).isEqualTo(GRAPH_NAME + "_1"); assertThat(graph.getWriteConcern()).isEqualTo(2); @@ -296,7 +299,8 @@ void smartGraph(ArangoDatabase db) { edgeDefinitions.add(new EdgeDefinition().collection("smartGraph-edge-" + rnd()).from("smartGraph-vertex-" + rnd()).to("smartGraph-vertex-" + rnd())); String graphId = GRAPH_NAME + rnd(); - final GraphEntity g = db.createGraph(graphId, edgeDefinitions, new GraphCreateOptions().isSmart(true).smartGraphAttribute("test").numberOfShards(2)); + final GraphEntity g = db.createGraph(graphId, edgeDefinitions, + new GraphCreateOptions().isSmart(true).smartGraphAttribute("test").numberOfShards(2)); assertThat(g).isNotNull(); assertThat(g.getIsSmart()).isTrue(); diff --git a/src/test/java/com/arangodb/ArangoRouteTest.java b/src/test/java/com/arangodb/ArangoRouteTest.java index 3334d9461..592674f7e 100644 --- a/src/test/java/com/arangodb/ArangoRouteTest.java +++ b/src/test/java/com/arangodb/ArangoRouteTest.java @@ -58,7 +58,8 @@ void withHeader(ArangoDatabase db) { final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); String rev = db.collection(COLLECTION_NAME).insertDocument(doc).getRev(); Throwable thrown = catchThrowable(() -> - db.route("/_api/document", COLLECTION_NAME, doc.getKey()).withHeader(ArangoRequestParam.IF_NONE_MATCH, rev).get()); + db.route("/_api/document", COLLECTION_NAME, doc.getKey()).withHeader(ArangoRequestParam.IF_NONE_MATCH + , rev).get()); assertThat(thrown).isInstanceOf(ArangoDBException.class); ArangoDBException e = (ArangoDBException) thrown; assertThat(e.getResponseCode()).isEqualTo(304); @@ -70,7 +71,8 @@ void withParentHeader(ArangoDatabase db) { final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); String rev = db.collection(COLLECTION_NAME).insertDocument(doc).getRev(); Throwable thrown = catchThrowable(() -> - db.route("/_api/document").withHeader(ArangoRequestParam.IF_NONE_MATCH, rev).route(COLLECTION_NAME, doc.getKey()).get()); + db.route("/_api/document").withHeader(ArangoRequestParam.IF_NONE_MATCH, rev).route(COLLECTION_NAME, + doc.getKey()).get()); assertThat(thrown).isInstanceOf(ArangoDBException.class); ArangoDBException e = (ArangoDBException) thrown; assertThat(e.getResponseCode()).isEqualTo(304); diff --git a/src/test/java/com/arangodb/ArangoSearchTest.java b/src/test/java/com/arangodb/ArangoSearchTest.java index 0c1cd86c8..3ca5780cb 100644 --- a/src/test/java/com/arangodb/ArangoSearchTest.java +++ b/src/test/java/com/arangodb/ArangoSearchTest.java @@ -267,7 +267,8 @@ private void createGetAndDeleteTypedAnalyzer(ArangoDatabase db, SearchAnalyzer a assertThat(gotAnalyzer).isEqualTo(analyzer); // getAnalyzers - SearchAnalyzer foundAnalyzer = db.getSearchAnalyzers().stream().filter(it -> it.getName().equals(fullyQualifiedName)) + SearchAnalyzer foundAnalyzer = + db.getSearchAnalyzers().stream().filter(it -> it.getName().equals(fullyQualifiedName)) .findFirst().get(); assertThat(foundAnalyzer).isEqualTo(analyzer); @@ -593,7 +594,8 @@ void stopwordsAnalyzer(ArangoDatabase db) { createGetAndDeleteTypedAnalyzer(db, analyzer); db.createSearchAnalyzer(analyzer); - Collection res = db.query("RETURN FLATTEN(TOKENS(SPLIT('the fox and the dog and a theater', ' '), @aName))", + Collection res = db.query("RETURN FLATTEN(TOKENS(SPLIT('the fox and the dog and a theater', ' '), " + + "@aName))", Collections.singletonMap("aName", name), Collection.class).next(); assertThat(res).containsExactly("fox", "dog", "a", "theater"); db.deleteSearchAnalyzer(name); diff --git a/src/test/java/com/arangodb/ArangoVertexCollectionTest.java b/src/test/java/com/arangodb/ArangoVertexCollectionTest.java index af1db2454..8937f5231 100644 --- a/src/test/java/com/arangodb/ArangoVertexCollectionTest.java +++ b/src/test/java/com/arangodb/ArangoVertexCollectionTest.java @@ -94,7 +94,8 @@ void insertVertex(ArangoVertexCollection vertices) { void insertVertexViolatingUniqueConstraint(ArangoVertexCollection vertices) { ArangoCollection collection = vertices.graph().db().collection(vertices.name()); collection - .ensureSkiplistIndex(Collections.singletonList("field"), new SkiplistIndexOptions().unique(true).sparse(true)); + .ensureSkiplistIndex(Collections.singletonList("field"), + new SkiplistIndexOptions().unique(true).sparse(true)); VertexEntity inserted = vertices.insertVertex(RawJson.of("{\"field\": 99}")); diff --git a/src/test/java/com/arangodb/JwtAuthTest.java b/src/test/java/com/arangodb/JwtAuthTest.java index 641d1d433..6aeb103e9 100644 --- a/src/test/java/com/arangodb/JwtAuthTest.java +++ b/src/test/java/com/arangodb/JwtAuthTest.java @@ -29,6 +29,20 @@ static void init() { arangoDB.shutdown(); } + private static String getJwt(ArangoDB arangoDB) { + ArangoSerde serde = arangoDB.getSerde(); + Map reqBody = new HashMap<>(); + reqBody.put("username", "root"); + reqBody.put("password", "test"); + + Request req = new Request(DbName.SYSTEM, RequestType.POST, "/_open/auth"); + req.setBody(serde.serialize(reqBody)); + + Response resp = arangoDB.execute(req); + Map respBody = serde.deserialize(resp.getBody(), Map.class); + return respBody.get("jwt"); + } + @ParameterizedTest @EnumSource(Protocol.class) void notAuthenticated(Protocol protocol) { @@ -75,23 +89,9 @@ void updateJwt(Protocol protocol) { private ArangoDB.Builder getBuilder(Protocol protocol) { return new ArangoDB.Builder() .useProtocol(protocol) - + .jwt(null) // unset credentials from properties file .user(null) // unset credentials from properties file .password(null); // unset credentials from properties file } - - private static String getJwt(ArangoDB arangoDB) { - ArangoSerde serde = arangoDB.getSerde(); - Map reqBody = new HashMap<>(); - reqBody.put("username", "root"); - reqBody.put("password", "test"); - - Request req = new Request(DbName.SYSTEM, RequestType.POST, "/_open/auth"); - req.setBody(serde.serialize(reqBody)); - - Response resp = arangoDB.execute(req); - Map respBody = serde.deserialize(resp.getBody(), Map.class); - return respBody.get("jwt"); - } } diff --git a/src/test/java/com/arangodb/StreamTransactionGraphTest.java b/src/test/java/com/arangodb/StreamTransactionGraphTest.java index 58264d620..e4d73fa33 100644 --- a/src/test/java/com/arangodb/StreamTransactionGraphTest.java +++ b/src/test/java/com/arangodb/StreamTransactionGraphTest.java @@ -68,8 +68,10 @@ static void init() { private BaseEdgeDocument createEdgeValue(String streamTransactionId, ArangoGraph graph) { ArangoVertexCollection vertexCollection1 = graph.vertexCollection(VERTEX_COLLECTION_1); ArangoVertexCollection vertexCollection2 = graph.vertexCollection(VERTEX_COLLECTION_2); - VertexEntity v1 = vertexCollection1.insertVertex(new BaseDocument(), new VertexCreateOptions().streamTransactionId(streamTransactionId)); - VertexEntity v2 = vertexCollection2.insertVertex(new BaseDocument(), new VertexCreateOptions().streamTransactionId(streamTransactionId)); + VertexEntity v1 = vertexCollection1.insertVertex(new BaseDocument(), + new VertexCreateOptions().streamTransactionId(streamTransactionId)); + VertexEntity v2 = vertexCollection2.insertVertex(new BaseDocument(), + new VertexCreateOptions().streamTransactionId(streamTransactionId)); BaseEdgeDocument value = new BaseEdgeDocument(); value.setFrom(v1.getId()); value.setTo(v2.getId()); @@ -114,7 +116,8 @@ void createVertex(ArangoVertexCollection vertexCollection1) { .writeCollections(VERTEX_COLLECTION_1, VERTEX_COLLECTION_2, EDGE_COLLECTION)); // insert a vertex from within the tx - VertexEntity createdVertex = vertexCollection1.insertVertex(new BaseDocument(), new VertexCreateOptions().streamTransactionId(tx.getId())); + VertexEntity createdVertex = vertexCollection1.insertVertex(new BaseDocument(), + new VertexCreateOptions().streamTransactionId(tx.getId())); // assert that the vertex is not found from outside the tx assertThat(vertexCollection1.getVertex(createdVertex.getKey(), BaseDocument.class, null)).isNull(); @@ -158,7 +161,8 @@ void replaceVertex(ArangoVertexCollection vertexCollection1) { // assert that the vertex has been replaced from within the tx assertThat(vertexCollection1.getVertex(createdVertex.getKey(), BaseDocument.class, - new GraphDocumentReadOptions().streamTransactionId(tx.getId())).getProperties()).containsEntry("test", "bar"); + new GraphDocumentReadOptions().streamTransactionId(tx.getId())).getProperties()).containsEntry("test" + , "bar"); db.commitStreamTransaction(tx.getId()); @@ -187,7 +191,8 @@ void updateVertex(ArangoVertexCollection vertexCollection1) { // update vertex from within the tx doc.updateAttribute("test", "bar"); - vertexCollection1.updateVertex(createdDoc.getKey(), doc, new VertexUpdateOptions().streamTransactionId(tx.getId())); + vertexCollection1.updateVertex(createdDoc.getKey(), doc, + new VertexUpdateOptions().streamTransactionId(tx.getId())); // assert that the vertex has not been updated from outside the tx assertThat(vertexCollection1.getVertex(createdDoc.getKey(), BaseDocument.class, null) @@ -195,7 +200,8 @@ void updateVertex(ArangoVertexCollection vertexCollection1) { // assert that the vertex has been updated from within the tx assertThat(vertexCollection1.getVertex(createdDoc.getKey(), BaseDocument.class, - new GraphDocumentReadOptions().streamTransactionId(tx.getId())).getProperties()).containsEntry("test", "bar"); + new GraphDocumentReadOptions().streamTransactionId(tx.getId())).getProperties()).containsEntry("test" + , "bar"); db.commitStreamTransaction(tx.getId()); @@ -274,7 +280,8 @@ void createEdge(ArangoEdgeCollection edgeCollection) { .writeCollections(VERTEX_COLLECTION_1, VERTEX_COLLECTION_2, EDGE_COLLECTION)); // insert an edge from within the tx - EdgeEntity createdEdge = edgeCollection.insertEdge(createEdgeValue(tx.getId(), edgeCollection.graph()), new EdgeCreateOptions().streamTransactionId(tx.getId())); + EdgeEntity createdEdge = edgeCollection.insertEdge(createEdgeValue(tx.getId(), edgeCollection.graph()), + new EdgeCreateOptions().streamTransactionId(tx.getId())); // assert that the edge is not found from outside the tx assertThat(edgeCollection.getEdge(createdEdge.getKey(), BaseEdgeDocument.class, null)).isNull(); @@ -318,7 +325,8 @@ void replaceEdge(ArangoEdgeCollection edgeCollection) { // assert that the edge has been replaced from within the tx assertThat(edgeCollection.getEdge(createdEdge.getKey(), BaseEdgeDocument.class, - new GraphDocumentReadOptions().streamTransactionId(tx.getId())).getProperties()).containsEntry("test", "bar"); + new GraphDocumentReadOptions().streamTransactionId(tx.getId())).getProperties()).containsEntry("test" + , "bar"); db.commitStreamTransaction(tx.getId()); @@ -355,7 +363,8 @@ void updateEdge(ArangoEdgeCollection edgeCollection) { // assert that the edge has been updated from within the tx assertThat(edgeCollection.getEdge(createdDoc.getKey(), BaseEdgeDocument.class, - new GraphDocumentReadOptions().streamTransactionId(tx.getId())).getProperties()).containsEntry("test", "bar"); + new GraphDocumentReadOptions().streamTransactionId(tx.getId())).getProperties()).containsEntry("test" + , "bar"); db.commitStreamTransaction(tx.getId()); diff --git a/src/test/java/com/arangodb/StreamTransactionTest.java b/src/test/java/com/arangodb/StreamTransactionTest.java index bc52a0673..e4f1ef24c 100644 --- a/src/test/java/com/arangodb/StreamTransactionTest.java +++ b/src/test/java/com/arangodb/StreamTransactionTest.java @@ -395,7 +395,8 @@ void replaceDocument(ArangoDatabase db) { // assert that the document has been replaced from within the tx assertThat(collection.getDocument(createdDoc.getKey(), BaseDocument.class, - new DocumentReadOptions().streamTransactionId(tx.getId())).getProperties()).containsEntry("test", "bar"); + new DocumentReadOptions().streamTransactionId(tx.getId())).getProperties()).containsEntry("test", + "bar"); db.commitStreamTransaction(tx.getId()); diff --git a/src/test/java/com/arangodb/async/ArangoCollectionTest.java b/src/test/java/com/arangodb/async/ArangoCollectionTest.java index b41d7613c..69090d7c8 100644 --- a/src/test/java/com/arangodb/async/ArangoCollectionTest.java +++ b/src/test/java/com/arangodb/async/ArangoCollectionTest.java @@ -53,78 +53,6 @@ class ArangoCollectionTest extends BaseTest { private static final String COLLECTION_NAME = "db_collection_test"; - @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, property = "type") - public interface Animal { - String getKey(); - - String getName(); - } - - public static class Dog implements Animal { - - @Key - private String key; - private String name; - - public Dog() { - } - - public Dog(String key, String name) { - this.key = key; - this.name = name; - } - - @Override - public String getKey() { - return key; - } - - public void setKey(String key) { - this.key = key; - } - - @Override - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - } - - public static class Cat implements Animal { - @Key - private String key; - private String name; - - public Cat() { - } - - public Cat(String key, String name) { - this.key = key; - this.name = name; - } - - @Override - public String getKey() { - return key; - } - - public void setKey(String key) { - this.key = key; - } - - @Override - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - } - ArangoCollectionTest() throws ExecutionException, InterruptedException { ArangoCollectionAsync collection = db.collection(COLLECTION_NAME); if (!collection.exists().get()) { @@ -180,11 +108,11 @@ void insertDocumentReturnNew() throws InterruptedException, ExecutionException { .get(); } - @Test - void insertDocumentWithTypeOverwriteModeReplace() throws InterruptedException, ExecutionException { + void insertDocumentWithTypeOverwriteModeReplace() throws InterruptedException, ExecutionException { assumeTrue(isAtLeastVersion(3, 7)); - assumeTrue(db.getSerde().getUserSerde() instanceof JacksonSerde, "polymorphic deserialization support required"); + assumeTrue(db.getSerde().getUserSerde() instanceof JacksonSerde, "polymorphic deserialization support " + + "required"); ArangoCollectionAsync collection = db.collection(COLLECTION_NAME); String key = UUID.randomUUID().toString(); Dog dog = new Dog(key, "Teddy"); @@ -214,7 +142,6 @@ void insertDocumentWithTypeOverwriteModeReplace() throws InterruptedException, assertThat(doc.getNew().getName()).isEqualTo("Luna"); } - @Test void insertDocumentWaitForSync() throws InterruptedException, ExecutionException { final DocumentCreateOptions options = new DocumentCreateOptions().waitForSync(true); @@ -326,7 +253,8 @@ void getDocumentNotFound() throws InterruptedException, ExecutionException { @Test void getDocumentWrongKey() { - Throwable thrown = catchThrowable(() -> db.collection(COLLECTION_NAME).getDocument("no/no", BaseDocument.class)); + Throwable thrown = catchThrowable(() -> db.collection(COLLECTION_NAME).getDocument("no/no", + BaseDocument.class)); assertThat(thrown).isInstanceOf(ArangoDBException.class); } @@ -342,7 +270,8 @@ void getDocuments() throws InterruptedException, ExecutionException { assertThat(documents).isNotNull(); assertThat(documents.getDocuments()).hasSize(3); for (final BaseDocument document : documents.getDocuments()) { - assertThat(document.getId()).isIn(COLLECTION_NAME + "/" + "1", COLLECTION_NAME + "/" + "2", COLLECTION_NAME + "/" + "3"); + assertThat(document.getId()).isIn(COLLECTION_NAME + "/" + "1", COLLECTION_NAME + "/" + "2", + COLLECTION_NAME + "/" + "3"); } } @@ -407,7 +336,8 @@ void updateDocumentWithDifferentReturnType() throws ExecutionException, Interrup collection.insertDocument(doc).get(); final DocumentUpdateEntity updateResult = collection - .updateDocument(key, Collections.singletonMap("b", "test"), new DocumentUpdateOptions().returnNew(true), BaseDocument.class).get(); + .updateDocument(key, Collections.singletonMap("b", "test"), + new DocumentUpdateOptions().returnNew(true), BaseDocument.class).get(); assertThat(updateResult).isNotNull(); assertThat(updateResult.getKey()).isEqualTo(key); BaseDocument updated = updateResult.getNew(); @@ -1584,7 +1514,8 @@ void importDocumentsDuplicateError() throws InterruptedException, ExecutionExcep values.add(new BaseDocument("1")); values.add(new BaseDocument("2")); values.add(new BaseDocument("2")); - db.collection(COLLECTION_NAME).importDocuments(values, new DocumentImportOptions().onDuplicate(OnDuplicate.error)) + db.collection(COLLECTION_NAME).importDocuments(values, +new DocumentImportOptions().onDuplicate(OnDuplicate.error)) .whenComplete((docs, ex) -> { assertThat(docs).isNotNull(); assertThat(docs.getCreated()).isEqualTo(2); @@ -1603,7 +1534,8 @@ void importDocumentsDuplicateIgnore() throws InterruptedException, ExecutionExce values.add(new BaseDocument("1")); values.add(new BaseDocument("2")); values.add(new BaseDocument("2")); - db.collection(COLLECTION_NAME).importDocuments(values, new DocumentImportOptions().onDuplicate(OnDuplicate.ignore)) + db.collection(COLLECTION_NAME).importDocuments(values, + new DocumentImportOptions().onDuplicate(OnDuplicate.ignore)) .whenComplete((docs, ex) -> { assertThat(docs).isNotNull(); assertThat(docs.getCreated()).isEqualTo(2); @@ -1622,7 +1554,8 @@ void importDocumentsDuplicateReplace() throws InterruptedException, ExecutionExc values.add(new BaseDocument("1")); values.add(new BaseDocument("2")); values.add(new BaseDocument("2")); - db.collection(COLLECTION_NAME).importDocuments(values, new DocumentImportOptions().onDuplicate(OnDuplicate.replace)) + db.collection(COLLECTION_NAME).importDocuments(values, +new DocumentImportOptions().onDuplicate(OnDuplicate.replace)) .whenComplete((docs, ex) -> { assertThat(docs).isNotNull(); assertThat(docs.getCreated()).isEqualTo(2); @@ -1641,7 +1574,8 @@ void importDocumentsDuplicateUpdate() throws InterruptedException, ExecutionExce values.add(new BaseDocument("1")); values.add(new BaseDocument("2")); values.add(new BaseDocument("2")); - db.collection(COLLECTION_NAME).importDocuments(values, new DocumentImportOptions().onDuplicate(OnDuplicate.update)) + db.collection(COLLECTION_NAME).importDocuments(values, + new DocumentImportOptions().onDuplicate(OnDuplicate.update)) .whenComplete((docs, ex) -> { assertThat(docs).isNotNull(); assertThat(docs.getCreated()).isEqualTo(2); @@ -1778,7 +1712,8 @@ void importDocumentsJsonDuplicateDefaultError() throws InterruptedException, Exe @Test void importDocumentsJsonDuplicateError() throws InterruptedException, ExecutionException { final String values = "[{\"_key\":\"1\"},{\"_key\":\"2\"},{\"_key\":\"2\"}]"; - db.collection(COLLECTION_NAME).importDocuments(RawData.of(values), new DocumentImportOptions().onDuplicate(OnDuplicate.error)) + db.collection(COLLECTION_NAME).importDocuments(RawData.of(values), + new DocumentImportOptions().onDuplicate(OnDuplicate.error)) .whenComplete((docs, ex) -> { assertThat(docs).isNotNull(); assertThat(docs.getCreated()).isEqualTo(2); @@ -1794,7 +1729,8 @@ void importDocumentsJsonDuplicateError() throws InterruptedException, ExecutionE @Test void importDocumentsJsonDuplicateIgnore() throws InterruptedException, ExecutionException { final String values = "[{\"_key\":\"1\"},{\"_key\":\"2\"},{\"_key\":\"2\"}]"; - db.collection(COLLECTION_NAME).importDocuments(RawData.of(values), new DocumentImportOptions().onDuplicate(OnDuplicate.ignore)) + db.collection(COLLECTION_NAME).importDocuments(RawData.of(values), + new DocumentImportOptions().onDuplicate(OnDuplicate.ignore)) .whenComplete((docs, ex) -> { assertThat(docs).isNotNull(); assertThat(docs.getCreated()).isEqualTo(2); @@ -1810,7 +1746,8 @@ void importDocumentsJsonDuplicateIgnore() throws InterruptedException, Execution @Test void importDocumentsJsonDuplicateReplace() throws InterruptedException, ExecutionException { final String values = "[{\"_key\":\"1\"},{\"_key\":\"2\"},{\"_key\":\"2\"}]"; - db.collection(COLLECTION_NAME).importDocuments(RawData.of(values), new DocumentImportOptions().onDuplicate(OnDuplicate.replace)) + db.collection(COLLECTION_NAME).importDocuments(RawData.of(values), + new DocumentImportOptions().onDuplicate(OnDuplicate.replace)) .whenComplete((docs, ex) -> { assertThat(docs).isNotNull(); assertThat(docs.getCreated()).isEqualTo(2); @@ -1826,7 +1763,8 @@ void importDocumentsJsonDuplicateReplace() throws InterruptedException, Executio @Test void importDocumentsJsonDuplicateUpdate() throws InterruptedException, ExecutionException { final String values = "[{\"_key\":\"1\"},{\"_key\":\"2\"},{\"_key\":\"2\"}]"; - db.collection(COLLECTION_NAME).importDocuments(RawData.of(values), new DocumentImportOptions().onDuplicate(OnDuplicate.update)) + db.collection(COLLECTION_NAME).importDocuments(RawData.of(values), + new DocumentImportOptions().onDuplicate(OnDuplicate.update)) .whenComplete((docs, ex) -> { assertThat(docs).isNotNull(); assertThat(docs.getCreated()).isEqualTo(2); @@ -1843,7 +1781,8 @@ void importDocumentsJsonDuplicateUpdate() throws InterruptedException, Execution void importDocumentsJsonCompleteFail() throws InterruptedException { final String values = "[{\"_key\":\"1\"},{\"_key\":\"2\"},{\"_key\":\"2\"}]"; try { - db.collection(COLLECTION_NAME).importDocuments(RawData.of(values), new DocumentImportOptions().complete(true)).get(); + db.collection(COLLECTION_NAME).importDocuments(RawData.of(values), + new DocumentImportOptions().complete(true)).get(); fail(); } catch (ExecutionException e) { assertThat(e.getCause()).isInstanceOf(ArangoDBException.class); @@ -1896,10 +1835,12 @@ void importDocumentsJsonFromToPrefix() throws InterruptedException, ExecutionExc final ArangoCollectionAsync collection = db.collection(COLLECTION_NAME + "_edge"); try { final String[] keys = {"1", "2"}; - final String values = "[{\"_key\":\"1\",\"_from\":\"from\",\"_to\":\"to\"},{\"_key\":\"2\",\"_from\":\"from\",\"_to\":\"to\"}]"; + final String values = "[{\"_key\":\"1\",\"_from\":\"from\",\"_to\":\"to\"},{\"_key\":\"2\"," + + "\"_from\":\"from\",\"_to\":\"to\"}]"; final DocumentImportEntity importResult = collection - .importDocuments(RawData.of(values), new DocumentImportOptions().fromPrefix("foo").toPrefix("bar")).get(); + .importDocuments(RawData.of(values), + new DocumentImportOptions().fromPrefix("foo").toPrefix("bar")).get(); assertThat(importResult).isNotNull(); assertThat(importResult.getCreated()).isEqualTo(2); for (String key : keys) { @@ -2084,7 +2025,6 @@ void deleteDocumentsRawDataByKeyReturnOld() throws ExecutionException, Interrupt assertThat(deleteResult.getErrors()).isEmpty(); } - @Test void updateDocuments() throws InterruptedException, ExecutionException { final Collection values = new ArrayList<>(); @@ -2115,7 +2055,8 @@ void updateDocuments() throws InterruptedException, ExecutionException { @Test void updateDocumentsWithDifferentReturnType() throws ExecutionException, InterruptedException { ArangoCollectionAsync collection = db.collection(COLLECTION_NAME); - List keys = IntStream.range(0, 3).mapToObj(it -> "key-" + UUID.randomUUID()).collect(Collectors.toList()); + List keys = + IntStream.range(0, 3).mapToObj(it -> "key-" + UUID.randomUUID()).collect(Collectors.toList()); List docs = keys.stream() .map(BaseDocument::new) .peek(it -> it.addAttribute("a", "test")) @@ -2202,7 +2143,8 @@ void updateDocumentsRawData() throws ExecutionException, InterruptedException { final RawData values = RawData.of("[{\"_key\":\"1\"}, {\"_key\":\"2\"}]"); collection.insertDocuments(values).get(); - final RawData updatedValues = RawData.of("[{\"_key\":\"1\", \"foo\":\"bar\"}, {\"_key\":\"2\", \"foo\":\"bar\"}]"); + final RawData updatedValues = RawData.of("[{\"_key\":\"1\", \"foo\":\"bar\"}, {\"_key\":\"2\", " + + "\"foo\":\"bar\"}]"); final MultiDocumentEntity updateResult = collection.updateDocuments(updatedValues).get(); assertThat(updateResult.getDocuments()).hasSize(2); assertThat(updateResult.getErrors()).isEmpty(); @@ -2214,7 +2156,8 @@ void updateDocumentsRawDataReturnNew() throws ExecutionException, InterruptedExc final RawData values = RawData.of("[{\"_key\":\"1\"}, {\"_key\":\"2\"}]"); collection.insertDocuments(values).get(); - final RawData updatedValues = RawData.of("[{\"_key\":\"1\", \"foo\":\"bar\"}, {\"_key\":\"2\", \"foo\":\"bar\"}]"); + final RawData updatedValues = RawData.of("[{\"_key\":\"1\", \"foo\":\"bar\"}, {\"_key\":\"2\", " + +"\"foo\":\"bar\"}]"); MultiDocumentEntity> updateResult = collection.updateDocuments(updatedValues, new DocumentUpdateOptions().returnNew(true)).get(); assertThat(updateResult.getDocuments()).hasSize(2); @@ -2312,7 +2255,8 @@ void replaceDocumentsRawData() throws ExecutionException, InterruptedException { final RawData values = RawData.of("[{\"_key\":\"1\"}, {\"_key\":\"2\"}]"); collection.insertDocuments(values).get(); - final RawData updatedValues = RawData.of("[{\"_key\":\"1\", \"foo\":\"bar\"}, {\"_key\":\"2\", \"foo\":\"bar\"}]"); + final RawData updatedValues = RawData.of("[{\"_key\":\"1\", \"foo\":\"bar\"}, {\"_key\":\"2\", " + +"\"foo\":\"bar\"}]"); final MultiDocumentEntity updateResult = collection.replaceDocuments(updatedValues).get(); assertThat(updateResult.getDocuments()).hasSize(2); assertThat(updateResult.getErrors()).isEmpty(); @@ -2325,7 +2269,8 @@ void replaceDocumentsRawDataReturnNew() throws ExecutionException, InterruptedEx final RawData values = RawData.of("[{\"_key\":\"1\"}, {\"_key\":\"2\"}]"); collection.insertDocuments(values).get(); - final RawData updatedValues = RawData.of("[{\"_key\":\"1\", \"foo\":\"bar\"}, {\"_key\":\"2\", \"foo\":\"bar\"}]"); + final RawData updatedValues = RawData.of("[{\"_key\":\"1\", \"foo\":\"bar\"}, {\"_key\":\"2\", " + + "\"foo\":\"bar\"}]"); MultiDocumentEntity> updateResult = collection.replaceDocuments(updatedValues, new DocumentReplaceOptions().returnNew(true)).get(); assertThat(updateResult.getDocuments()).hasSize(2); @@ -2342,7 +2287,6 @@ void replaceDocumentsRawDataReturnNew() throws ExecutionException, InterruptedEx } } - @Test void getInfo() throws InterruptedException, ExecutionException { db.collection(COLLECTION_NAME).getInfo() @@ -2452,7 +2396,8 @@ void grantAccessNONE() throws InterruptedException, ExecutionException { @Test void grantAccessUserNotFound() { - Throwable thrown = catchThrowable(() -> db.collection(COLLECTION_NAME).grantAccess("user1", Permissions.RW).get()); + Throwable thrown = + catchThrowable(() -> db.collection(COLLECTION_NAME).grantAccess("user1", Permissions.RW).get()); assertThat(thrown).isInstanceOf(ExecutionException.class); } @@ -2468,7 +2413,8 @@ void revokeAccess() throws InterruptedException, ExecutionException { @Test void revokeAccessUserNotFound() { - Throwable thrown = catchThrowable(() -> db.collection(COLLECTION_NAME).grantAccess("user1", Permissions.NONE).get()); + Throwable thrown = + catchThrowable(() -> db.collection(COLLECTION_NAME).grantAccess("user1", Permissions.NONE).get()); assertThat(thrown).isInstanceOf(ExecutionException.class); } @@ -2492,4 +2438,76 @@ void resetAccessUserNotFound() { void getPermissions() throws InterruptedException, ExecutionException { assertThat(db.collection(COLLECTION_NAME).getPermissions("root").get()).isEqualTo(Permissions.RW); } + + @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, property = "type") + public interface Animal { + String getKey(); + + String getName(); + } + + public static class Dog implements Animal { + + @Key + private String key; + private String name; + + public Dog() { + } + + public Dog(String key, String name) { + this.key = key; + this.name = name; + } + + @Override + public String getKey() { + return key; + } + + public void setKey(String key) { + this.key = key; + } + + @Override + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + } + + public static class Cat implements Animal { + @Key + private String key; + private String name; + + public Cat() { + } + + public Cat(String key, String name) { + this.key = key; + this.name = name; + } + + @Override + public String getKey() { + return key; + } + + public void setKey(String key) { + this.key = key; + } + + @Override + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + } } diff --git a/src/test/java/com/arangodb/async/ArangoDBTest.java b/src/test/java/com/arangodb/async/ArangoDBTest.java index 2169914d4..3a1dd2f46 100644 --- a/src/test/java/com/arangodb/async/ArangoDBTest.java +++ b/src/test/java/com/arangodb/async/ArangoDBTest.java @@ -434,7 +434,7 @@ void authenticationFailUser() throws InterruptedException { } @Test - void execute() throws InterruptedException, ExecutionException { + void execute() throws InterruptedException, ExecutionException { arangoDB .execute(new Request(DbName.SYSTEM, RequestType.GET, "/_api/version")) .whenComplete((response, ex) -> { @@ -445,7 +445,7 @@ void execute() throws InterruptedException, ExecutionException { } @Test - void execute_acquireHostList_enabled() throws InterruptedException, ExecutionException { + void execute_acquireHostList_enabled() throws InterruptedException, ExecutionException { final ArangoDBAsync arangoDB = new ArangoDBAsync.Builder().acquireHostList(true).build(); arangoDB .execute(new Request(DbName.SYSTEM, RequestType.GET, "/_api/version")) diff --git a/src/test/java/com/arangodb/async/ArangoDatabaseTest.java b/src/test/java/com/arangodb/async/ArangoDatabaseTest.java index 54bade719..07e0ea0d9 100644 --- a/src/test/java/com/arangodb/async/ArangoDatabaseTest.java +++ b/src/test/java/com/arangodb/async/ArangoDatabaseTest.java @@ -911,7 +911,8 @@ void transactionAllowImplicit() throws InterruptedException, ExecutionException db.createCollection("someCollection", null).get(); db.createCollection("someOtherCollection", null).get(); final String action = "function (params) {" + "var db = require('internal').db;" - + "return {'a':db.someCollection.all().toArray()[0], 'b':db.someOtherCollection.all().toArray()[0]};" + + "return {'a':db.someCollection.all().toArray()[0], 'b':db.someOtherCollection.all().toArray()" + + "[0]};" + "}"; final TransactionOptions options = new TransactionOptions().readCollections("someCollection"); db.transaction(action, Void.class, options).get(); diff --git a/src/test/java/com/arangodb/async/ArangoEdgeCollectionTest.java b/src/test/java/com/arangodb/async/ArangoEdgeCollectionTest.java index e089cd415..e1b106875 100644 --- a/src/test/java/com/arangodb/async/ArangoEdgeCollectionTest.java +++ b/src/test/java/com/arangodb/async/ArangoEdgeCollectionTest.java @@ -27,12 +27,10 @@ import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; - import java.util.ArrayList; import java.util.Collection; import java.util.concurrent.ExecutionException; - import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.fail; diff --git a/src/test/java/com/arangodb/async/ArangoGraphTest.java b/src/test/java/com/arangodb/async/ArangoGraphTest.java index 1e7407aa4..beed0bf10 100644 --- a/src/test/java/com/arangodb/async/ArangoGraphTest.java +++ b/src/test/java/com/arangodb/async/ArangoGraphTest.java @@ -95,7 +95,8 @@ void createWithReplicationAndWriteConcern() throws ExecutionException, Interrupt assumeTrue(isAtLeastVersion(3, 5)); assumeTrue(isCluster()); final Collection edgeDefinitions = new ArrayList<>(); - final GraphEntity graph = db.createGraph(GRAPH_NAME + "_1", edgeDefinitions, new GraphCreateOptions().isSmart(true).replicationFactor(2).writeConcern(2)).get(); + final GraphEntity graph = db.createGraph(GRAPH_NAME + "_1", edgeDefinitions, + new GraphCreateOptions().isSmart(true).replicationFactor(2).writeConcern(2)).get(); assertThat(graph).isNotNull(); assertThat(graph.getName()).isEqualTo(GRAPH_NAME + "_1"); assertThat(graph.getWriteConcern()).isEqualTo(2); diff --git a/src/test/java/com/arangodb/async/ArangoRouteTest.java b/src/test/java/com/arangodb/async/ArangoRouteTest.java index 5a3dbbf4b..772e593f5 100644 --- a/src/test/java/com/arangodb/async/ArangoRouteTest.java +++ b/src/test/java/com/arangodb/async/ArangoRouteTest.java @@ -25,11 +25,9 @@ import com.arangodb.internal.ArangoRequestParam; import org.junit.jupiter.api.Test; - import java.util.UUID; import java.util.concurrent.ExecutionException; - import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.fail; diff --git a/src/test/java/com/arangodb/async/ArangoSearchTest.java b/src/test/java/com/arangodb/async/ArangoSearchTest.java index 9c5418cd5..41a88e0e1 100644 --- a/src/test/java/com/arangodb/async/ArangoSearchTest.java +++ b/src/test/java/com/arangodb/async/ArangoSearchTest.java @@ -31,7 +31,10 @@ import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; -import java.util.*; +import java.util.Collection; +import java.util.HashSet; +import java.util.Set; +import java.util.UUID; import java.util.concurrent.ExecutionException; import static org.assertj.core.api.Assertions.assertThat; @@ -215,7 +218,8 @@ void replaceProperties() throws InterruptedException, ExecutionException { view.create(new ArangoSearchCreateOptions()).get(); final ArangoSearchPropertiesOptions options = new ArangoSearchPropertiesOptions(); options.link( - CollectionLink.on("view_replace_prop_test_collection").fields(FieldLink.on("value").analyzers("identity"))); + CollectionLink.on("view_replace_prop_test_collection").fields(FieldLink.on("value").analyzers( + "identity"))); final ArangoSearchPropertiesEntity properties = view.replaceProperties(options).get(); assertThat(properties).isNotNull(); assertThat(properties.getLinks()).hasSize(1); @@ -225,7 +229,8 @@ void replaceProperties() throws InterruptedException, ExecutionException { assertThat(link.getFields().iterator().next().getName()).isEqualTo("value"); } - private void createGetAndDeleteTypedAnalyzer(SearchAnalyzer analyzer) throws ExecutionException, InterruptedException { + private void createGetAndDeleteTypedAnalyzer(SearchAnalyzer analyzer) throws ExecutionException, + InterruptedException { String fullyQualifiedName = db.dbName().get() + "::" + analyzer.getName(); analyzer.setName(fullyQualifiedName); @@ -239,7 +244,8 @@ private void createGetAndDeleteTypedAnalyzer(SearchAnalyzer analyzer) throws Exe assertThat(gotAnalyzer).isEqualTo(analyzer); // getAnalyzers - SearchAnalyzer foundAnalyzer = db.getSearchAnalyzers().get().stream().filter(it -> it.getName().equals(fullyQualifiedName)) + SearchAnalyzer foundAnalyzer = + db.getSearchAnalyzers().get().stream().filter(it -> it.getName().equals(fullyQualifiedName)) .findFirst().get(); assertThat(foundAnalyzer).isEqualTo(analyzer); diff --git a/src/test/java/com/arangodb/async/ArangoVertexCollectionTest.java b/src/test/java/com/arangodb/async/ArangoVertexCollectionTest.java index 164201137..4da5b6735 100644 --- a/src/test/java/com/arangodb/async/ArangoVertexCollectionTest.java +++ b/src/test/java/com/arangodb/async/ArangoVertexCollectionTest.java @@ -29,12 +29,10 @@ import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; - import java.util.Collection; import java.util.UUID; import java.util.concurrent.ExecutionException; - import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.fail; diff --git a/src/test/java/com/arangodb/async/BaseTest.java b/src/test/java/com/arangodb/async/BaseTest.java index d0c318744..654e773b0 100644 --- a/src/test/java/com/arangodb/async/BaseTest.java +++ b/src/test/java/com/arangodb/async/BaseTest.java @@ -20,8 +20,8 @@ package com.arangodb.async; -import com.arangodb.entity.ArangoDBEngine; import com.arangodb.DbName; +import com.arangodb.entity.ArangoDBEngine; import com.arangodb.entity.License; import com.arangodb.entity.ServerRole; import org.junit.jupiter.api.AfterAll; @@ -65,9 +65,11 @@ static String rnd() { return UUID.randomUUID().toString(); } - protected static boolean isAtLeastVersion(final ArangoDBAsync arangoDB, final int major, final int minor, final int patch) + 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); + return com.arangodb.util.TestUtils.isAtLeastVersion(arangoDB.getVersion().get().getVersion(), major, minor, + patch); } protected static boolean isAtLeastVersion(final ArangoDBAsync arangoDB, final int major, final int minor) @@ -75,11 +77,13 @@ protected static boolean isAtLeastVersion(final ArangoDBAsync arangoDB, final in return isAtLeastVersion(arangoDB, major, minor, 0); } - protected boolean isAtLeastVersion(final int major, final int minor, final int patch) throws InterruptedException, ExecutionException { + protected boolean isAtLeastVersion(final int major, final int minor, final int patch) throws InterruptedException + , ExecutionException { return isAtLeastVersion(arangoDB, major, minor, patch); } - protected boolean isAtLeastVersion(final int major, final int minor) throws InterruptedException, ExecutionException { + protected boolean isAtLeastVersion(final int major, final int minor) throws InterruptedException, + ExecutionException { return isAtLeastVersion(major, minor, 0); } diff --git a/src/test/java/com/arangodb/async/CommunicationTest.java b/src/test/java/com/arangodb/async/CommunicationTest.java index ecbfd3a42..0b2b6c962 100644 --- a/src/test/java/com/arangodb/async/CommunicationTest.java +++ b/src/test/java/com/arangodb/async/CommunicationTest.java @@ -23,7 +23,6 @@ import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; - import java.util.concurrent.CompletableFuture; import static org.assertj.core.api.Assertions.assertThat; diff --git a/src/test/java/com/arangodb/async/ConcurrencyTests.java b/src/test/java/com/arangodb/async/ConcurrencyTests.java index 3219a5f50..e01a76156 100644 --- a/src/test/java/com/arangodb/async/ConcurrencyTests.java +++ b/src/test/java/com/arangodb/async/ConcurrencyTests.java @@ -1,7 +1,6 @@ package com.arangodb.async; - import org.junit.jupiter.api.Test; import java.util.List; diff --git a/src/test/java/com/arangodb/async/JwtAuthTest.java b/src/test/java/com/arangodb/async/JwtAuthTest.java index fd8107a6f..c4bbc9b60 100644 --- a/src/test/java/com/arangodb/async/JwtAuthTest.java +++ b/src/test/java/com/arangodb/async/JwtAuthTest.java @@ -11,12 +11,10 @@ import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; - import java.util.HashMap; import java.util.Map; import java.util.concurrent.ExecutionException; - import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.fail; @@ -32,6 +30,20 @@ static void init() { arangoDB.shutdown(); } + private static String getJwt(ArangoDB arangoDB) { + ArangoSerde serde = arangoDB.getSerde(); + Map reqBody = new HashMap<>(); + reqBody.put("username", "root"); + reqBody.put("password", "test"); + + Request req = new Request(DbName.SYSTEM, RequestType.POST, "/_open/auth"); + req.setBody(serde.serialize(reqBody)); + + Response resp = arangoDB.execute(req); + Map respBody = serde.deserialize(resp.getBody(), Map.class); + return respBody.get("jwt"); + } + @AfterEach void after() { if (arangoDB != null) @@ -82,23 +94,9 @@ void updateJwt() throws ExecutionException, InterruptedException { private ArangoDBAsync.Builder getBuilder() { return new ArangoDBAsync.Builder() - + .jwt(null) // unset credentials from properties file .user(null) // unset credentials from properties file .password(null); // unset credentials from properties file } - - private static String getJwt(ArangoDB arangoDB) { - ArangoSerde serde = arangoDB.getSerde(); - Map reqBody = new HashMap<>(); - reqBody.put("username", "root"); - reqBody.put("password", "test"); - - Request req = new Request(DbName.SYSTEM, RequestType.POST, "/_open/auth"); - req.setBody(serde.serialize(reqBody)); - - Response resp = arangoDB.execute(req); - Map respBody = serde.deserialize(resp.getBody(), Map.class); - return respBody.get("jwt"); - } } diff --git a/src/test/java/com/arangodb/async/StreamTransactionGraphTest.java b/src/test/java/com/arangodb/async/StreamTransactionGraphTest.java index 0083e4802..60ee6ea11 100644 --- a/src/test/java/com/arangodb/async/StreamTransactionGraphTest.java +++ b/src/test/java/com/arangodb/async/StreamTransactionGraphTest.java @@ -21,23 +21,8 @@ package com.arangodb.async; -import com.arangodb.entity.ArangoDBEngine; -import com.arangodb.entity.BaseDocument; -import com.arangodb.entity.BaseEdgeDocument; -import com.arangodb.entity.EdgeDefinition; -import com.arangodb.entity.EdgeEntity; -import com.arangodb.entity.StreamTransactionEntity; -import com.arangodb.entity.VertexEntity; -import com.arangodb.model.EdgeCreateOptions; -import com.arangodb.model.EdgeDeleteOptions; -import com.arangodb.model.EdgeReplaceOptions; -import com.arangodb.model.EdgeUpdateOptions; -import com.arangodb.model.GraphDocumentReadOptions; -import com.arangodb.model.StreamTransactionOptions; -import com.arangodb.model.VertexCreateOptions; -import com.arangodb.model.VertexDeleteOptions; -import com.arangodb.model.VertexReplaceOptions; -import com.arangodb.model.VertexUpdateOptions; +import com.arangodb.entity.*; +import com.arangodb.model.*; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Test; @@ -90,9 +75,12 @@ void teardown() throws ExecutionException, InterruptedException { db.collection(VERTEX_COLLECTION_2).drop().get(); } - private BaseEdgeDocument createEdgeValue(String streamTransactionId) throws ExecutionException, InterruptedException { - final VertexEntity v1 = vertexCollection1.insertVertex(new BaseDocument(), new VertexCreateOptions().streamTransactionId(streamTransactionId)).get(); - final VertexEntity v2 = vertexCollection2.insertVertex(new BaseDocument(), new VertexCreateOptions().streamTransactionId(streamTransactionId)).get(); + private BaseEdgeDocument createEdgeValue(String streamTransactionId) throws ExecutionException, + InterruptedException { + final VertexEntity v1 = vertexCollection1.insertVertex(new BaseDocument(), + new VertexCreateOptions().streamTransactionId(streamTransactionId)).get(); + final VertexEntity v2 = vertexCollection2.insertVertex(new BaseDocument(), + new VertexCreateOptions().streamTransactionId(streamTransactionId)).get(); final BaseEdgeDocument value = new BaseEdgeDocument(); value.setFrom(v1.getId()); value.setTo(v2.getId()); @@ -133,7 +121,8 @@ void createVertex() throws ExecutionException, InterruptedException { .writeCollections(VERTEX_COLLECTION_1, VERTEX_COLLECTION_2, EDGE_COLLECTION)).get(); // insert a vertex from within the tx - VertexEntity createdVertex = vertexCollection1.insertVertex(new BaseDocument(), new VertexCreateOptions().streamTransactionId(tx.getId())).get(); + VertexEntity createdVertex = vertexCollection1.insertVertex(new BaseDocument(), + new VertexCreateOptions().streamTransactionId(tx.getId())).get(); // assert that the vertex is not found from outside the tx assertThat(vertexCollection1.getVertex(createdVertex.getKey(), BaseDocument.class, null).get()).isNull(); @@ -175,7 +164,8 @@ void replaceVertex() throws ExecutionException, InterruptedException { // assert that the vertex has been replaced from within the tx assertThat(vertexCollection1.getVertex(createdVertex.getKey(), BaseDocument.class, - new GraphDocumentReadOptions().streamTransactionId(tx.getId())).get().getProperties()).containsEntry("test", "bar"); + new GraphDocumentReadOptions().streamTransactionId(tx.getId())).get().getProperties()).containsEntry( + "test", "bar"); db.commitStreamTransaction(tx.getId()).get(); @@ -202,7 +192,8 @@ void updateVertex() throws ExecutionException, InterruptedException { // update vertex from within the tx doc.updateAttribute("test", "bar"); - vertexCollection1.updateVertex(createdDoc.getKey(), doc, new VertexUpdateOptions().streamTransactionId(tx.getId())).get(); + vertexCollection1.updateVertex(createdDoc.getKey(), doc, + new VertexUpdateOptions().streamTransactionId(tx.getId())).get(); // assert that the vertex has not been updated from outside the tx assertThat(vertexCollection1.getVertex(createdDoc.getKey(), BaseDocument.class, null).get() @@ -210,7 +201,8 @@ void updateVertex() throws ExecutionException, InterruptedException { // assert that the vertex has been updated from within the tx assertThat(vertexCollection1.getVertex(createdDoc.getKey(), BaseDocument.class, - new GraphDocumentReadOptions().streamTransactionId(tx.getId())).get().getProperties()).containsEntry("test", "bar"); + new GraphDocumentReadOptions().streamTransactionId(tx.getId())).get().getProperties()).containsEntry( + "test", "bar"); db.commitStreamTransaction(tx.getId()).get(); @@ -233,7 +225,8 @@ void deleteVertex() throws ExecutionException, InterruptedException { .writeCollections(VERTEX_COLLECTION_1, VERTEX_COLLECTION_2, EDGE_COLLECTION)).get(); // delete vertex from within the tx - vertexCollection1.deleteVertex(createdDoc.getKey(), new VertexDeleteOptions().streamTransactionId(tx.getId())).get(); + vertexCollection1.deleteVertex(createdDoc.getKey(), + new VertexDeleteOptions().streamTransactionId(tx.getId())).get(); // assert that the vertex has not been deleted from outside the tx assertThat(vertexCollection1.getVertex(createdDoc.getKey(), BaseDocument.class, null).get()).isNotNull(); @@ -283,7 +276,8 @@ void createEdge() throws ExecutionException, InterruptedException { .writeCollections(VERTEX_COLLECTION_1, VERTEX_COLLECTION_2, EDGE_COLLECTION)).get(); // insert an edge from within the tx - EdgeEntity createdEdge = edgeCollection.insertEdge(createEdgeValue(tx.getId()), new EdgeCreateOptions().streamTransactionId(tx.getId())).get(); + EdgeEntity createdEdge = edgeCollection.insertEdge(createEdgeValue(tx.getId()), + new EdgeCreateOptions().streamTransactionId(tx.getId())).get(); // assert that the edge is not found from outside the tx assertThat(edgeCollection.getEdge(createdEdge.getKey(), BaseEdgeDocument.class, null).get()).isNull(); @@ -325,7 +319,8 @@ void replaceEdge() throws ExecutionException, InterruptedException { // assert that the edge has been replaced from within the tx assertThat(edgeCollection.getEdge(createdEdge.getKey(), BaseEdgeDocument.class, - new GraphDocumentReadOptions().streamTransactionId(tx.getId())).get().getProperties()).containsEntry("test", "bar"); + new GraphDocumentReadOptions().streamTransactionId(tx.getId())).get().getProperties()).containsEntry( + "test", "bar"); db.commitStreamTransaction(tx.getId()).get(); @@ -361,7 +356,8 @@ void updateEdge() throws ExecutionException, InterruptedException { // assert that the edge has been updated from within the tx assertThat(edgeCollection.getEdge(createdDoc.getKey(), BaseEdgeDocument.class, - new GraphDocumentReadOptions().streamTransactionId(tx.getId())).get().getProperties()).containsEntry("test", "bar"); + new GraphDocumentReadOptions().streamTransactionId(tx.getId())).get().getProperties()).containsEntry( + "test", "bar"); db.commitStreamTransaction(tx.getId()).get(); diff --git a/src/test/java/com/arangodb/async/StreamTransactionTest.java b/src/test/java/com/arangodb/async/StreamTransactionTest.java index 5f6690095..658bab18b 100644 --- a/src/test/java/com/arangodb/async/StreamTransactionTest.java +++ b/src/test/java/com/arangodb/async/StreamTransactionTest.java @@ -110,7 +110,8 @@ void abortStreamTransactionTwice() throws ExecutionException, InterruptedExcepti } @Test - void abortStreamTransactionWhenTransactionIdDoesNotExistsShouldThrow() throws ExecutionException, InterruptedException { + void abortStreamTransactionWhenTransactionIdDoesNotExistsShouldThrow() throws ExecutionException, + InterruptedException { assumeTrue(isSingleServer()); assumeTrue(isAtLeastVersion(3, 5)); assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); @@ -171,7 +172,8 @@ void getStreamTransaction() throws ExecutionException, InterruptedException { } @Test - void getStreamTransactionWhenTransactionIdDoesNotExistsShouldThrow() throws ExecutionException, InterruptedException { + void getStreamTransactionWhenTransactionIdDoesNotExistsShouldThrow() throws ExecutionException, + InterruptedException { assumeTrue(isSingleServer()); assumeTrue(isAtLeastVersion(3, 5)); assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); @@ -224,7 +226,8 @@ void commitStreamTransactionTwice() throws ExecutionException, InterruptedExcept } @Test - void commitStreamTransactionWhenTransactionIdDoesNotExistsShouldThrow() throws ExecutionException, InterruptedException { + void commitStreamTransactionWhenTransactionIdDoesNotExistsShouldThrow() throws ExecutionException, + InterruptedException { assumeTrue(isSingleServer()); assumeTrue(isAtLeastVersion(3, 5)); assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); diff --git a/src/test/java/com/arangodb/async/example/document/AqlQueryWithSpecialReturnTypesExampleTest.java b/src/test/java/com/arangodb/async/example/document/AqlQueryWithSpecialReturnTypesExampleTest.java index 7358ae8ed..9ab6624df 100644 --- a/src/test/java/com/arangodb/async/example/document/AqlQueryWithSpecialReturnTypesExampleTest.java +++ b/src/test/java/com/arangodb/async/example/document/AqlQueryWithSpecialReturnTypesExampleTest.java @@ -63,7 +63,8 @@ void aqlWithLimitQueryAsJsonObject() throws InterruptedException, ExecutionExcep final Map bindVars = Collections.singletonMap("gender", Gender.FEMALE); db.query(query, bindVars, null, ObjectNode.class) .whenComplete((cursor, ex) -> cursor.forEachRemaining(node -> { - assertThat(node.get("name").asText()).isIn("TestUser11", "TestUser13", "TestUser15", "TestUser17", "TestUser19"); + assertThat(node.get("name").asText()).isIn("TestUser11", "TestUser13", "TestUser15", "TestUser17" + , "TestUser19"); assertThat(node.get("gender").asText()).isEqualTo(Gender.FEMALE.name()); assertThat(node.get("age").asInt()).isIn(21, 23, 25, 27, 29); })) @@ -77,7 +78,8 @@ void aqlWithLimitQueryAsArrayNode() throws InterruptedException, ExecutionExcept final Map bindVars = Collections.singletonMap("gender", Gender.FEMALE); db.query(query, bindVars, null, ArrayNode.class) .whenComplete((cursor, ex) -> cursor.forEachRemaining(arrNode -> { - assertThat(arrNode.get(0).asText()).isIn("TestUser11", "TestUser13", "TestUser15", "TestUser17", "TestUser19"); + assertThat(arrNode.get(0).asText()).isIn("TestUser11", "TestUser13", "TestUser15", "TestUser17", + "TestUser19"); assertThat(arrNode.get(1).asText()).isEqualTo(Gender.FEMALE.name()); assertThat(arrNode.get(2).asInt()).isIn(21, 23, 25, 27, 29); })) @@ -92,7 +94,8 @@ void aqlWithLimitQueryAsMap() throws InterruptedException, ExecutionException { db.query(query, bindVars, null, Map.class) .whenComplete((cursor, ex) -> cursor.forEachRemaining(map -> { assertThat(map.get("name")).isNotNull(); - assertThat(String.valueOf(map.get("name"))).isIn("TestUser11", "TestUser13", "TestUser15", "TestUser17", "TestUser19"); + assertThat(String.valueOf(map.get("name"))).isIn("TestUser11", "TestUser13", "TestUser15", + "TestUser17", "TestUser19"); assertThat(map.get("gender")).isNotNull(); assertThat(String.valueOf(map.get("gender"))).isEqualTo(Gender.FEMALE.name()); assertThat(map.get("age")).isNotNull(); @@ -109,7 +112,8 @@ void aqlWithLimitQueryAsList() throws InterruptedException, ExecutionException { db.query(query, bindVars, null, List.class) .whenComplete((cursor, ex) -> cursor.forEachRemaining(list -> { assertThat(list.get(0)).isNotNull(); - assertThat(String.valueOf(list.get(0))).isIn("TestUser11", "TestUser13", "TestUser15", "TestUser17", "TestUser19"); + assertThat(String.valueOf(list.get(0))).isIn("TestUser11", "TestUser13", "TestUser15", + "TestUser17", "TestUser19"); assertThat(list.get(1)).isNotNull(); assertThat(Gender.valueOf(String.valueOf(list.get(1)))).isEqualTo(Gender.FEMALE); assertThat(list.get(2)).isNotNull(); diff --git a/src/test/java/com/arangodb/async/example/document/GetDocumentExampleTest.java b/src/test/java/com/arangodb/async/example/document/GetDocumentExampleTest.java index 2b74c8ad2..11ef3c63f 100644 --- a/src/test/java/com/arangodb/async/example/document/GetDocumentExampleTest.java +++ b/src/test/java/com/arangodb/async/example/document/GetDocumentExampleTest.java @@ -22,13 +22,11 @@ import com.arangodb.async.example.ExampleBase; import com.arangodb.entity.BaseDocument; -import com.arangodb.entity.DocumentCreateEntity; import com.arangodb.util.RawJson; import com.fasterxml.jackson.databind.JsonNode; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; - import java.util.UUID; import java.util.concurrent.ExecutionException; diff --git a/src/test/java/com/arangodb/async/example/document/ImportDocumentExampleTest.java b/src/test/java/com/arangodb/async/example/document/ImportDocumentExampleTest.java index d2df0678c..dacf1bd87 100644 --- a/src/test/java/com/arangodb/async/example/document/ImportDocumentExampleTest.java +++ b/src/test/java/com/arangodb/async/example/document/ImportDocumentExampleTest.java @@ -25,7 +25,6 @@ import com.arangodb.model.DocumentImportOptions; import org.junit.jupiter.api.Test; - import java.util.List; import java.util.UUID; import java.util.concurrent.CompletableFuture; diff --git a/src/test/java/com/arangodb/async/example/graph/AQLActorsAndMoviesExampleTest.java b/src/test/java/com/arangodb/async/example/graph/AQLActorsAndMoviesExampleTest.java index 2f0de8a0b..f619b5c40 100644 --- a/src/test/java/com/arangodb/async/example/graph/AQLActorsAndMoviesExampleTest.java +++ b/src/test/java/com/arangodb/async/example/graph/AQLActorsAndMoviesExampleTest.java @@ -45,7 +45,8 @@ /** * @author Mark Vollmary - * @see AQL Example Queries on an + * @see + * AQL Example Queries on an * Actors and Movies Database */ class AQLActorsAndMoviesExampleTest { @@ -156,7 +157,8 @@ private static void createData() throws InterruptedException, ExecutionException saveActsIn(actsIn, al, theDevilsAdvocate, new String[]{"John Milton"}, 1997); final String AFewGoodMen = saveMovie(movies, "AFewGoodMen", "A Few Good Men", 1992, - "In the heart of the nation's capital, in a courthouse of the U.S. government, one man will stop at nothing to keep his honor, and one will stop at nothing to find the truth.") + "In the heart of the nation's capital, in a courthouse of the U.S. government, one man will stop at " + + "nothing to keep his honor, and one will stop at nothing to find the truth.") .getId(); final String tomC = saveActor(actors, "TomC", "Tom Cruise", 1962).getId(); final String jackN = saveActor(actors, "JackN", "Jack Nicholson", 1937).getId(); @@ -215,7 +217,8 @@ private static void createData() throws InterruptedException, ExecutionException saveActsIn(actsIn, jonathanL, jerryMaguire, new String[]{"Ray Boyd"}, 2000); final String standByMe = saveMovie(movies, "StandByMe", "Stand By Me", 1986, - "For some, it's the last real taste of innocence, and the first real taste of life. But for everyone, it's the time that memories are made of.") + "For some, it's the last real taste of innocence, and the first real taste of life. But for everyone," + + " it's the time that memories are made of.") .getId(); final String riverP = saveActor(actors, "RiverP", "River Phoenix", 1970).getId(); final String coreyF = saveActor(actors, "CoreyF", "Corey Feldman", 1971).getId(); @@ -275,7 +278,8 @@ private static void createData() throws InterruptedException, ExecutionException saveActsIn(actsIn, steveZ, youveGotMail, new String[]{"George Pappas"}, 1998); final String sleeplessInSeattle = saveMovie(movies, "SleeplessInSeattle", "Sleepless in Seattle", 1993, - "What if someone you never met, someone you never saw, someone you never knew was the only someone for you?") + "What if someone you never met, someone you never saw, someone you never knew was the only someone " + + "for you?") .getId(); final String ritaW = saveActor(actors, "RitaW", "Rita Wilson", 1956).getId(); final String billPull = saveActor(actors, "BillPull", "Bill Pullman", 1953).getId(); @@ -311,28 +315,34 @@ private static void createData() throws InterruptedException, ExecutionException * @throws ExecutionException * @throws InterruptedException * @see AQL + * "https://www.arangodb.com/docs/stable/cookbook/graph-example-actors-and-movies + * .html#all-actors-who-acted-in-movie1-or-movie2">AQL * Example Queries on an Actors and Movies Database */ @Test void allActorsActsInMovie1or2() throws InterruptedException, ExecutionException { final CompletableFuture> f = db.query( - "WITH actors, movies FOR x IN ANY 'movies/TheMatrix' actsIn OPTIONS {bfs: true, uniqueVertices: 'global'} RETURN x._id", + "WITH actors, movies FOR x IN ANY 'movies/TheMatrix' actsIn OPTIONS {bfs: true, uniqueVertices: " + + "'global'} RETURN x._id", null, null, String.class); - f.whenComplete((cursor, ex) -> assertThat(cursor.asListRemaining()).contains("actors/Keanu", "actors/Hugo", "actors/Emil", "actors/Carrie", "actors/Laurence")).get(); + f.whenComplete((cursor, ex) -> assertThat(cursor.asListRemaining()).contains("actors/Keanu", "actors/Hugo", + "actors/Emil", "actors/Carrie", "actors/Laurence")).get(); } /** * @throws ExecutionException * @throws InterruptedException * @see AQL + * "https://www.arangodb.com/docs/stable/cookbook/graph-example-actors-and-movies + * .html#all-actors-who-acted-in-movie1-or-movie2">AQL * Example Queries on an Actors and Movies Database */ @Test void allActorsActsInMovie1or2UnionDistinct() throws InterruptedException, ExecutionException { final CompletableFuture> f = db.query( - "WITH actors, movies FOR x IN UNION_DISTINCT ((FOR y IN ANY 'movies/TheMatrix' actsIn OPTIONS {bfs: true, uniqueVertices: 'global'} RETURN y._id), (FOR y IN ANY 'movies/TheDevilsAdvocate' actsIn OPTIONS {bfs: true, uniqueVertices: 'global'} RETURN y._id)) RETURN x", + "WITH actors, movies FOR x IN UNION_DISTINCT ((FOR y IN ANY 'movies/TheMatrix' actsIn OPTIONS {bfs: " + + "true, uniqueVertices: 'global'} RETURN y._id), (FOR y IN ANY 'movies/TheDevilsAdvocate' " + + "actsIn OPTIONS {bfs: true, uniqueVertices: 'global'} RETURN y._id)) RETURN x", null, null, String.class); f.whenComplete((cursor, ex) -> assertThat(cursor.asListRemaining()).contains( "actors/Emil", "actors/Hugo", "actors/Carrie", @@ -343,13 +353,16 @@ void allActorsActsInMovie1or2UnionDistinct() throws InterruptedException, Execut * @throws ExecutionException * @throws InterruptedException * @see AQL + * "https://www.arangodb.com/docs/stable/cookbook/graph-example-actors-and-movies + * .html#all-actors-who-acted-in-both-movie1-and-movie2-">AQL * Example Queries on an Actors and Movies Database */ @Test void allActorsActsInMovie1and2() throws InterruptedException, ExecutionException { final CompletableFuture> f = db.query( - "WITH actors, movies FOR x IN INTERSECTION ((FOR y IN ANY 'movies/TheMatrix' actsIn OPTIONS {bfs: true, uniqueVertices: 'global'} RETURN y._id), (FOR y IN ANY 'movies/TheDevilsAdvocate' actsIn OPTIONS {bfs: true, uniqueVertices: 'global'} RETURN y._id)) RETURN x", + "WITH actors, movies FOR x IN INTERSECTION ((FOR y IN ANY 'movies/TheMatrix' actsIn OPTIONS {bfs: " + + "true, uniqueVertices: 'global'} RETURN y._id), (FOR y IN ANY 'movies/TheDevilsAdvocate' " + + "actsIn OPTIONS {bfs: true, uniqueVertices: 'global'} RETURN y._id)) RETURN x", null, null, String.class); f.whenComplete((cursor, ex) -> assertThat(cursor.asListRemaining()).contains("actors/Keanu")).get(); } @@ -358,28 +371,34 @@ void allActorsActsInMovie1and2() throws InterruptedException, ExecutionException * @throws ExecutionException * @throws InterruptedException * @see AQL + * "https://www.arangodb.com/docs/stable/cookbook/graph-example-actors-and-movies + * .html#all-common-movies-between-actor1-and-actor2-">AQL * Example Queries on an Actors and Movies Database */ @Test void allMoviesBetweenActor1andActor2() throws InterruptedException, ExecutionException { final CompletableFuture> f = db.query( - "WITH actors, movies FOR x IN INTERSECTION ((FOR y IN ANY 'actors/Hugo' actsIn OPTIONS {bfs: true, uniqueVertices: 'global'} RETURN y._id), (FOR y IN ANY 'actors/Keanu' actsIn OPTIONS {bfs: true, uniqueVertices: 'global'} RETURN y._id)) RETURN x", + "WITH actors, movies FOR x IN INTERSECTION ((FOR y IN ANY 'actors/Hugo' actsIn OPTIONS {bfs: true, " + + "uniqueVertices: 'global'} RETURN y._id), (FOR y IN ANY 'actors/Keanu' actsIn OPTIONS {bfs: " + + "true, uniqueVertices: 'global'} RETURN y._id)) RETURN x", null, null, String.class); - f.whenComplete((cursor, ex) -> assertThat(cursor.asListRemaining()).contains("movies/TheMatrixRevolutions", "movies/TheMatrixReloaded", "movies/TheMatrix")).get(); + f.whenComplete((cursor, ex) -> assertThat(cursor.asListRemaining()).contains("movies/TheMatrixRevolutions", + "movies/TheMatrixReloaded", "movies/TheMatrix")).get(); } /** * @throws ExecutionException * @throws InterruptedException * @see AQL + * "https://www.arangodb.com/docs/stable/cookbook/graph-example-actors-and-movies + * .html#all-actors-who-acted-in-3-or-more-movies-">AQL * Example Queries on an Actors and Movies Database */ @Test void allActorsWhoActedIn3orMoreMovies() throws InterruptedException, ExecutionException { final CompletableFuture> f = db.query( - "FOR x IN actsIn COLLECT actor = x._from WITH COUNT INTO counter FILTER counter >= 3 RETURN {actor: actor, movies: counter}", + "FOR x IN actsIn COLLECT actor = x._from WITH COUNT INTO counter FILTER counter >= 3 RETURN {actor: " + + "actor, movies: counter}", null, null, Actor.class); f.whenComplete((cursor, ex) -> assertThat(cursor.asListRemaining()).contains( new Actor("actors/Carrie", 3), new Actor("actors/CubaG", 4), new Actor("actors/Hugo", 3), @@ -391,7 +410,8 @@ void allActorsWhoActedIn3orMoreMovies() throws InterruptedException, ExecutionEx * @throws ExecutionException * @throws InterruptedException * @see AQL + * "https://www.arangodb.com/docs/stable/cookbook/graph-example-actors-and-movies + * .html#all-movies-where-exactly-6-actors-acted-in-">AQL * Example Queries on an Actors and Movies Database */ @Test @@ -399,14 +419,16 @@ void allMoviesWhereExactly6ActorsActedIn() throws InterruptedException, Executio final CompletableFuture> f = db.query( "FOR x IN actsIn COLLECT movie = x._to WITH COUNT INTO counter FILTER counter == 6 RETURN movie", null, null, String.class); - f.whenComplete((cursor, ex) -> assertThat(cursor.asListRemaining()).contains("movies/SleeplessInSeattle", "movies/TopGun", "movies/YouveGotMail")).get(); + f.whenComplete((cursor, ex) -> assertThat(cursor.asListRemaining()).contains("movies/SleeplessInSeattle", + "movies/TopGun", "movies/YouveGotMail")).get(); } /** * @throws ExecutionException * @throws InterruptedException * @see AQL + * "https://www.arangodb.com/docs/stable/cookbook/graph-example-actors-and-movies + * .html#the-number-of-actors-by-movie-">AQL * Example Queries on an Actors and Movies Database */ @Test @@ -429,13 +451,15 @@ void theNumberOfActorsByMovie() throws InterruptedException, ExecutionException * @throws ExecutionException * @throws InterruptedException * @see AQL + * "https://www.arangodb.com/docs/stable/cookbook/graph-example-actors-and-movies + * .html#the-number-of-movies-by-actor-">AQL * Example Queries on an Actors and Movies Database */ @Test void theNumberOfMoviesByActor() throws InterruptedException, ExecutionException { final CompletableFuture> f = db.query( - "FOR x IN actsIn COLLECT actor = x._from WITH COUNT INTO counter RETURN {actor: actor, movies: counter}", + "FOR x IN actsIn COLLECT actor = x._from WITH COUNT INTO counter RETURN {actor: actor, movies: " + + "counter}", null, null, Actor.class); f.whenComplete((cursor, ex) -> assertThat(cursor.asListRemaining()).contains( new Actor("actors/Al", 1), new Actor("actors/AnnabellaS", 1), new Actor("actors/AnthonyE", 1), @@ -463,13 +487,15 @@ void theNumberOfMoviesByActor() throws InterruptedException, ExecutionException * @throws ExecutionException * @throws InterruptedException * @see AQL + * "https://www.arangodb.com/docs/stable/cookbook/graph-example-actors-and-movies + * .html#the-number-of-movies-acted-in-between-2005-and-2010-by-actor-">AQL * Example Queries on an Actors and Movies Database */ @Test void theNumberOfMoviesActedInBetween2005and2010byActor() throws InterruptedException, ExecutionException { final CompletableFuture> f = db.query( - "FOR x IN actsIn FILTER x.year >= 1990 && x.year <= 1995 COLLECT actor = x._from WITH COUNT INTO counter RETURN {actor: actor, movies: counter}", + "FOR x IN actsIn FILTER x.year >= 1990 && x.year <= 1995 COLLECT actor = x._from WITH COUNT INTO " + + "counter RETURN {actor: actor, movies: counter}", null, null, Actor.class); f.whenComplete((cursor, ex) -> assertThat(cursor.asListRemaining()).contains( new Actor("actors/BillPull", 1), new Actor("actors/ChristopherG", 1), @@ -481,8 +507,8 @@ void theNumberOfMoviesActedInBetween2005and2010byActor() throws InterruptedExcep } public static class Actor { - private String actor; - private Integer movies; + private final String actor; + private final Integer movies; @JsonCreator diff --git a/src/test/java/com/arangodb/async/example/graph/GraphTraversalsInAQLExampleTest.java b/src/test/java/com/arangodb/async/example/graph/GraphTraversalsInAQLExampleTest.java index f6b46cbd2..b3628f572 100644 --- a/src/test/java/com/arangodb/async/example/graph/GraphTraversalsInAQLExampleTest.java +++ b/src/test/java/com/arangodb/async/example/graph/GraphTraversalsInAQLExampleTest.java @@ -23,7 +23,6 @@ import com.arangodb.async.ArangoCursorAsync; import org.junit.jupiter.api.Test; - import java.util.Collection; import java.util.concurrent.ExecutionException; @@ -68,26 +67,30 @@ void queryDepthTwo() throws InterruptedException, ExecutionException { @Test void queryWithFilter() throws InterruptedException, ExecutionException { - String queryString = "FOR v, e, p IN 1..3 OUTBOUND 'circles/A' GRAPH 'traversalGraph' FILTER p.vertices[1]._key != 'G' RETURN v._key"; + String queryString = "FOR v, e, p IN 1..3 OUTBOUND 'circles/A' GRAPH 'traversalGraph' FILTER p.vertices[1]" + + "._key != 'G' RETURN v._key"; ArangoCursorAsync cursor = db.query(queryString, null, null, String.class).get(); Collection result = cursor.asListRemaining(); assertThat(result).hasSize(5); assertThat(result).contains("B", "C", "D", "E", "F"); - queryString = "FOR v, e, p IN 1..3 OUTBOUND 'circles/A' GRAPH 'traversalGraph' FILTER p.edges[0].label != 'right_foo' RETURN v._key"; + queryString = "FOR v, e, p IN 1..3 OUTBOUND 'circles/A' GRAPH 'traversalGraph' FILTER p.edges[0].label != " + + "'right_foo' RETURN v._key"; cursor = db.query(queryString, null, null, String.class).get(); result = cursor.asListRemaining(); assertThat(result).hasSize(5); assertThat(result).contains("B", "C", "D", "E", "F"); - queryString = "FOR v,e,p IN 1..3 OUTBOUND 'circles/A' GRAPH 'traversalGraph' FILTER p.vertices[1]._key != 'G' FILTER p.edges[1].label != 'left_blub' return v._key"; + queryString = "FOR v,e,p IN 1..3 OUTBOUND 'circles/A' GRAPH 'traversalGraph' FILTER p.vertices[1]._key != 'G'" + + " FILTER p.edges[1].label != 'left_blub' return v._key"; cursor = db.query(queryString, null, null, String.class).get(); result = cursor.asListRemaining(); assertThat(result).hasSize(3); assertThat(result).contains("B", "C", "D"); - queryString = "FOR v,e,p IN 1..3 OUTBOUND 'circles/A' GRAPH 'traversalGraph' FILTER p.vertices[1]._key != 'G' AND p.edges[1].label != 'left_blub' return v._key"; + queryString = "FOR v,e,p IN 1..3 OUTBOUND 'circles/A' GRAPH 'traversalGraph' FILTER p.vertices[1]._key != 'G'" + + " AND p.edges[1].label != 'left_blub' return v._key"; cursor = db.query(queryString, null, null, String.class).get(); result = cursor.asListRemaining(); assertThat(result).hasSize(3); diff --git a/src/test/java/com/arangodb/async/example/graph/ShortestPathInAQLExampleTest.java b/src/test/java/com/arangodb/async/example/graph/ShortestPathInAQLExampleTest.java index 306dfddae..515f8e13f 100644 --- a/src/test/java/com/arangodb/async/example/graph/ShortestPathInAQLExampleTest.java +++ b/src/test/java/com/arangodb/async/example/graph/ShortestPathInAQLExampleTest.java @@ -23,7 +23,6 @@ import com.arangodb.async.ArangoCursorAsync; import org.junit.jupiter.api.Test; - import java.util.ArrayList; import java.util.Collection; import java.util.List; @@ -42,13 +41,15 @@ class ShortestPathInAQLExampleTest extends BaseGraphTest { @Test void queryShortestPathFromAToD() throws InterruptedException, ExecutionException { - String queryString = "FOR v, e IN OUTBOUND SHORTEST_PATH 'circles/A' TO 'circles/D' GRAPH 'traversalGraph' RETURN {'vertex': v._key, 'edge': e._key}"; + String queryString = "FOR v, e IN OUTBOUND SHORTEST_PATH 'circles/A' TO 'circles/D' GRAPH 'traversalGraph' " + + "RETURN {'vertex': v._key, 'edge': e._key}"; ArangoCursorAsync cursor = db.query(queryString, null, null, Pair.class).get(); final Collection collection = toVertexCollection(cursor); assertThat(collection).hasSize(4); assertThat(collection).contains("A", "B", "C", "D"); - queryString = "WITH circles FOR v, e IN OUTBOUND SHORTEST_PATH 'circles/A' TO 'circles/D' edges RETURN {'vertex': v._key, 'edge': e._key}"; + queryString = "WITH circles FOR v, e IN OUTBOUND SHORTEST_PATH 'circles/A' TO 'circles/D' edges RETURN " + + "{'vertex': v._key, 'edge': e._key}"; db.query(queryString, null, null, Pair.class).get(); assertThat(collection).hasSize(4); assertThat(collection).contains("A", "B", "C", "D"); @@ -56,13 +57,15 @@ void queryShortestPathFromAToD() throws InterruptedException, ExecutionException @Test void queryShortestPathByFilter() throws InterruptedException, ExecutionException { - String queryString = "FOR a IN circles FILTER a._key == 'A' FOR d IN circles FILTER d._key == 'D' FOR v, e IN OUTBOUND SHORTEST_PATH a TO d GRAPH 'traversalGraph' RETURN {'vertex':v._key, 'edge':e._key}"; + String queryString = "FOR a IN circles FILTER a._key == 'A' FOR d IN circles FILTER d._key == 'D' FOR v, e IN" + + " OUTBOUND SHORTEST_PATH a TO d GRAPH 'traversalGraph' RETURN {'vertex':v._key, 'edge':e._key}"; ArangoCursorAsync cursor = db.query(queryString, null, null, Pair.class).get(); final Collection collection = toVertexCollection(cursor); assertThat(collection).hasSize(4); assertThat(collection).contains("A", "B", "C", "D"); - queryString = "FOR a IN circles FILTER a._key == 'A' FOR d IN circles FILTER d._key == 'D' FOR v, e IN OUTBOUND SHORTEST_PATH a TO d edges RETURN {'vertex': v._key, 'edge': e._key}"; + queryString = "FOR a IN circles FILTER a._key == 'A' FOR d IN circles FILTER d._key == 'D' FOR v, e IN " + + "OUTBOUND SHORTEST_PATH a TO d edges RETURN {'vertex': v._key, 'edge': e._key}"; db.query(queryString, null, null, Pair.class).get(); assertThat(collection).hasSize(4); assertThat(collection).contains("A", "B", "C", "D"); @@ -77,7 +80,7 @@ private Collection toVertexCollection(final ArangoCursorAsync curs return result; } - public static class Pair { + public static class Pair { private String vertex; private String edge; diff --git a/src/test/java/com/arangodb/async/example/ssl/SslExampleTest.java b/src/test/java/com/arangodb/async/example/ssl/SslExampleTest.java index 4c55a0ceb..bba0fe6ec 100644 --- a/src/test/java/com/arangodb/async/example/ssl/SslExampleTest.java +++ b/src/test/java/com/arangodb/async/example/ssl/SslExampleTest.java @@ -25,7 +25,6 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.api.condition.EnabledIfSystemProperty; - import javax.net.ssl.KeyManagerFactory; import javax.net.ssl.SSLContext; import javax.net.ssl.TrustManagerFactory; diff --git a/src/test/java/com/arangodb/async/serde/CustomSerdeTest.java b/src/test/java/com/arangodb/async/serde/CustomSerdeTest.java index 231f6a1e7..e601c5185 100644 --- a/src/test/java/com/arangodb/async/serde/CustomSerdeTest.java +++ b/src/test/java/com/arangodb/async/serde/CustomSerdeTest.java @@ -32,7 +32,6 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; - import java.math.BigInteger; import java.util.Collections; import java.util.HashMap; diff --git a/src/test/java/com/arangodb/example/ExampleBase.java b/src/test/java/com/arangodb/example/ExampleBase.java index 6267026d5..967c57a6a 100644 --- a/src/test/java/com/arangodb/example/ExampleBase.java +++ b/src/test/java/com/arangodb/example/ExampleBase.java @@ -20,7 +20,10 @@ package com.arangodb.example; -import com.arangodb.*; +import com.arangodb.ArangoCollection; +import com.arangodb.ArangoDB; +import com.arangodb.ArangoDatabase; +import com.arangodb.DbName; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; @@ -29,12 +32,11 @@ */ public class ExampleBase { - private static final String DB_NAME = "json_example_db"; protected static final String COLLECTION_NAME = "json_example_collection"; - - private static ArangoDB arangoDB; + private static final String DB_NAME = "json_example_db"; protected static ArangoDatabase db; protected static ArangoCollection collection; + private static ArangoDB arangoDB; @BeforeAll static void setUp() { diff --git a/src/test/java/com/arangodb/example/FirstProject.java b/src/test/java/com/arangodb/example/FirstProject.java index 9cda94573..31adecc12 100644 --- a/src/test/java/com/arangodb/example/FirstProject.java +++ b/src/test/java/com/arangodb/example/FirstProject.java @@ -108,7 +108,7 @@ public static void main(final String[] args) { final Map bindVars = Collections.singletonMap("name", "Homer"); final ArangoCursor cursor = arangoDB.db(dbName).query(query, bindVars, null, BaseDocument.class); - for (; cursor.hasNext(); ) { + while (cursor.hasNext()) { System.out.println("Key: " + cursor.next().getKey()); } } catch (final ArangoDBException e) { @@ -122,7 +122,7 @@ public static void main(final String[] args) { final Map bindVars = Collections.singletonMap("name", "Homer"); final ArangoCursor cursor = arangoDB.db(dbName).query(query, bindVars, null, BaseDocument.class); - for (; cursor.hasNext(); ) { + while (cursor.hasNext()) { System.out.println("Removed document " + cursor.next().getKey()); } } catch (final ArangoDBException e) { diff --git a/src/test/java/com/arangodb/example/document/AqlQueryWithSpecialReturnTypesExampleTest.java b/src/test/java/com/arangodb/example/document/AqlQueryWithSpecialReturnTypesExampleTest.java index 7dde1be39..9c9279c28 100644 --- a/src/test/java/com/arangodb/example/document/AqlQueryWithSpecialReturnTypesExampleTest.java +++ b/src/test/java/com/arangodb/example/document/AqlQueryWithSpecialReturnTypesExampleTest.java @@ -46,10 +46,6 @@ static void before() { createExamples(); } - enum Gender { - MALE, FEMALE - } - private static void createExamples() { for (int i = 0; i < 100; i++) { final BaseDocument value = new BaseDocument(UUID.randomUUID().toString()); @@ -129,4 +125,8 @@ void aqlWithLimitQueryAsList() { assertThat(Long.valueOf(String.valueOf(list.get(2)))).isIn(21L, 23L, 25L, 27L, 29L); } } + + enum Gender { + MALE, FEMALE + } } diff --git a/src/test/java/com/arangodb/example/document/GetDocumentExampleTest.java b/src/test/java/com/arangodb/example/document/GetDocumentExampleTest.java index ed8ce26a0..dc7318139 100644 --- a/src/test/java/com/arangodb/example/document/GetDocumentExampleTest.java +++ b/src/test/java/com/arangodb/example/document/GetDocumentExampleTest.java @@ -21,7 +21,6 @@ package com.arangodb.example.document; import com.arangodb.entity.BaseDocument; -import com.arangodb.entity.DocumentCreateEntity; import com.arangodb.example.ExampleBase; import com.arangodb.util.RawBytes; import com.arangodb.util.RawJson; @@ -85,7 +84,7 @@ void getAsJson() { final RawJson doc = collection.getDocument(key, RawJson.class); assertThat(doc.getValue()).isNotNull() .contains("foo") - .contains("bar"); + .contains("bar"); } @Test diff --git a/src/test/java/com/arangodb/example/graph/AQLActorsAndMoviesExampleTest.java b/src/test/java/com/arangodb/example/graph/AQLActorsAndMoviesExampleTest.java index da93131f1..b7208f6a1 100644 --- a/src/test/java/com/arangodb/example/graph/AQLActorsAndMoviesExampleTest.java +++ b/src/test/java/com/arangodb/example/graph/AQLActorsAndMoviesExampleTest.java @@ -39,7 +39,8 @@ /** * @author Mark Vollmary - * @see AQL Example Queries on an + * @see + * AQL Example Queries on an * Actors and Movies Database */ class AQLActorsAndMoviesExampleTest { @@ -64,255 +65,6 @@ static void tearDown() { arangoDB.shutdown(); } - /** - * @see AQL - * Example Queries on an Actors and Movies Database - */ - @Test - void allActorsActsInMovie1or2() { - final ArangoCursor cursor = db.query( - "WITH actors, movies FOR x IN ANY 'movies/TheMatrix' actsIn OPTIONS {bfs: true, uniqueVertices: 'global'} RETURN x._id", - null, null, String.class); - assertThat(cursor.asListRemaining()) - .contains("actors/Keanu", "actors/Hugo", "actors/Emil", "actors/Carrie", "actors/Laurence"); - } - - /** - * @see AQL - * Example Queries on an Actors and Movies Database - */ - @Test - void allActorsActsInMovie1or2UnionDistinct() { - final ArangoCursor cursor = db.query( - "WITH actors, movies FOR x IN UNION_DISTINCT ((FOR y IN ANY 'movies/TheMatrix' actsIn OPTIONS {bfs: true, uniqueVertices: 'global'} RETURN y._id), (FOR y IN ANY 'movies/TheDevilsAdvocate' actsIn OPTIONS {bfs: true, uniqueVertices: 'global'} RETURN y._id)) RETURN x", - null, null, String.class); - assertThat(cursor.asListRemaining()).contains("actors/Emil", "actors/Hugo", "actors/Carrie", "actors/Laurence", - "actors/Keanu", "actors/Al", "actors/Charlize"); - } - - /** - * @see AQL - * Example Queries on an Actors and Movies Database - */ - @Test - void allActorsActsInMovie1and2() { - final ArangoCursor cursor = db.query( - "WITH actors, movies FOR x IN INTERSECTION ((FOR y IN ANY 'movies/TheMatrix' actsIn OPTIONS {bfs: true, uniqueVertices: 'global'} RETURN y._id), (FOR y IN ANY 'movies/TheDevilsAdvocate' actsIn OPTIONS {bfs: true, uniqueVertices: 'global'} RETURN y._id)) RETURN x", - null, null, String.class); - assertThat(cursor.asListRemaining()).contains("actors/Keanu"); - } - - /** - * @see AQL - * Example Queries on an Actors and Movies Database - */ - @Test - void allMoviesBetweenActor1andActor2() { - final ArangoCursor cursor = db.query( - "WITH actors, movies FOR x IN INTERSECTION ((FOR y IN ANY 'actors/Hugo' actsIn OPTIONS {bfs: true, uniqueVertices: 'global'} RETURN y._id), (FOR y IN ANY 'actors/Keanu' actsIn OPTIONS {bfs: true, uniqueVertices: 'global'} RETURN y._id)) RETURN x", - null, null, String.class); - assertThat(cursor.asListRemaining()) - .contains("movies/TheMatrixRevolutions", "movies/TheMatrixReloaded", "movies/TheMatrix"); - } - - /** - * @see AQL - * Example Queries on an Actors and Movies Database - */ - @Test - void allActorsWhoActedIn3orMoreMovies() { - final ArangoCursor cursor = db.query( - "FOR x IN actsIn COLLECT actor = x._from WITH COUNT INTO counter FILTER counter >= 3 RETURN {actor: actor, movies: counter}", - null, null, Actor.class); - assertThat(cursor.asListRemaining()) - .contains(new Actor("actors/Carrie", 3), new Actor("actors/CubaG", 4), new Actor("actors/Hugo", 3), - new Actor("actors/Keanu", 4), new Actor("actors/Laurence", 3), new Actor("actors/MegR", 5), - new Actor("actors/TomC", 3), new Actor("actors/TomH", 3)); - } - - /** - * @see AQL - * Example Queries on an Actors and Movies Database - */ - @Test - void allMoviesWhereExactly6ActorsActedIn() { - final ArangoCursor cursor = db.query( - "FOR x IN actsIn COLLECT movie = x._to WITH COUNT INTO counter FILTER counter == 6 RETURN movie", null, - null, String.class); - assertThat(cursor.asListRemaining()) - .contains("movies/SleeplessInSeattle", "movies/TopGun", "movies/YouveGotMail"); - } - - /** - * @see AQL - * Example Queries on an Actors and Movies Database - */ - @Test - void theNumberOfActorsByMovie() { - final ArangoCursor cursor = db.query( - "FOR x IN actsIn COLLECT movie = x._to WITH COUNT INTO counter RETURN {movie: movie, actors: counter}", - null, null, Movie.class); - assertThat(cursor.asListRemaining()) - .contains(new Movie("movies/AFewGoodMen", 11), new Movie("movies/AsGoodAsItGets", 4), - new Movie("movies/JerryMaguire", 9), new Movie("movies/JoeVersustheVolcano", 3), - new Movie("movies/SleeplessInSeattle", 6), new Movie("movies/SnowFallingonCedars", 4), - new Movie("movies/StandByMe", 7), new Movie("movies/TheDevilsAdvocate", 3), - new Movie("movies/TheMatrix", 5), new Movie("movies/TheMatrixReloaded", 4), - new Movie("movies/TheMatrixRevolutions", 4), new Movie("movies/TopGun", 6), - new Movie("movies/WhatDreamsMayCome", 5), new Movie("movies/WhenHarryMetSally", 4), - new Movie("movies/YouveGotMail", 6)); - } - - /** - * @see AQL - * Example Queries on an Actors and Movies Database - */ - @Test - void theNumberOfMoviesByActor() { - final ArangoCursor cursor = db.query( - "FOR x IN actsIn COLLECT actor = x._from WITH COUNT INTO counter RETURN {actor: actor, movies: counter}", - null, null, Actor.class); - assertThat(cursor.asListRemaining()) - .contains(new Actor("actors/Al", 1), new Actor("actors/AnnabellaS", 1), new Actor("actors/AnthonyE", 1), - new Actor("actors/BillPull", 1), new Actor("actors/BillyC", 1), new Actor("actors/BonnieH", 1), - new Actor("actors/BrunoK", 1), new Actor("actors/Carrie", 3), new Actor("actors/CarrieF", 1), - new Actor("actors/Charlize", 1), new Actor("actors/ChristopherG", 1), new Actor("actors/CoreyF", 1), - new Actor("actors/CubaG", 4), new Actor("actors/DaveC", 1), new Actor("actors/DemiM", 1), - new Actor("actors/Emil", 1), new Actor("actors/EthanH", 1), new Actor("actors/GregK", 2), - new Actor("actors/HelenH", 1), new Actor("actors/Hugo", 3), new Actor("actors/JackN", 2), - new Actor("actors/JamesC", 1), new Actor("actors/JamesM", 1), new Actor("actors/JayM", 1), - new Actor("actors/JerryO", 2), new Actor("actors/JohnC", 1), new Actor("actors/JonathanL", 1), - new Actor("actors/JTW", 1), new Actor("actors/Keanu", 4), new Actor("actors/KellyM", 1), - new Actor("actors/KellyP", 1), new Actor("actors/KevinB", 1), new Actor("actors/KevinP", 1), - new Actor("actors/KieferS", 2), new Actor("actors/Laurence", 3), new Actor("actors/MarshallB", 1), - new Actor("actors/MaxS", 2), new Actor("actors/MegR", 5), new Actor("actors/Nathan", 1), - new Actor("actors/NoahW", 1), new Actor("actors/ParkerP", 1), new Actor("actors/ReginaK", 1), - new Actor("actors/ReneeZ", 1), new Actor("actors/RickY", 1), new Actor("actors/RitaW", 1), - new Actor("actors/RiverP", 1), new Actor("actors/Robin", 1), new Actor("actors/RosieO", 1), - new Actor("actors/SteveZ", 1), new Actor("actors/TomC", 3), new Actor("actors/TomH", 3), - new Actor("actors/TomS", 1), new Actor("actors/ValK", 1), new Actor("actors/VictorG", 1), - new Actor("actors/WernerH", 1), new Actor("actors/WilW", 1)); - } - - /** - * @see AQL - * Example Queries on an Actors and Movies Database - */ - @Test - void theNumberOfMoviesActedInBetween2005and2010byActor() { - final ArangoCursor cursor = db.query( - "FOR x IN actsIn FILTER x.year >= 1990 && x.year <= 1995 COLLECT actor = x._from WITH COUNT INTO counter RETURN {actor: actor, movies: counter}", - null, null, Actor.class); - assertThat(cursor.asListRemaining()) - .contains(new Actor("actors/BillPull", 1), new Actor("actors/ChristopherG", 1), new Actor("actors/CubaG", 1), - new Actor("actors/DemiM", 1), new Actor("actors/JackN", 1), new Actor("actors/JamesM", 1), - new Actor("actors/JTW", 1), new Actor("actors/KevinB", 1), new Actor("actors/KieferS", 1), - new Actor("actors/MegR", 2), new Actor("actors/Nathan", 1), new Actor("actors/NoahW", 1), - new Actor("actors/RitaW", 1), new Actor("actors/RosieO", 1), new Actor("actors/TomC", 1), - new Actor("actors/TomH", 2), new Actor("actors/VictorG", 1)); - } - - public static class Actor { - private final String actor; - private final Integer movies; - - @JsonCreator - Actor(@JsonProperty("actor") final String actor, @JsonProperty("movies") final Integer movies) { - super(); - this.actor = actor; - this.movies = movies; - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((actor == null) ? 0 : actor.hashCode()); - result = prime * result + ((movies == null) ? 0 : movies.hashCode()); - return result; - } - - @Override - public boolean equals(final Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (getClass() != obj.getClass()) { - return false; - } - final Actor other = (Actor) obj; - if (actor == null) { - if (other.actor != null) { - return false; - } - } else if (!actor.equals(other.actor)) { - return false; - } - if (movies == null) { - return other.movies == null; - } else return movies.equals(other.movies); - } - - } - - public static class Movie { - private final String movie; - private final Integer actors; - - @JsonCreator - public Movie(@JsonProperty("movie") final String movie, @JsonProperty("actors") final Integer actors) { - super(); - this.movie = movie; - this.actors = actors; - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((actors == null) ? 0 : actors.hashCode()); - result = prime * result + ((movie == null) ? 0 : movie.hashCode()); - return result; - } - - @Override - public boolean equals(final Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (getClass() != obj.getClass()) { - return false; - } - final Movie other = (Movie) obj; - if (actors == null) { - if (other.actors != null) { - return false; - } - } else if (!actors.equals(other.actors)) { - return false; - } - if (movie == null) { - return other.movie == null; - } else return movie.equals(other.movie); - } - - } - private static DocumentCreateEntity saveMovie( final ArangoCollection movies, final String key, @@ -398,7 +150,8 @@ private static void createData() { saveActsIn(actsIn, al, theDevilsAdvocate, new String[]{"John Milton"}, 1997); final String AFewGoodMen = saveMovie(movies, "AFewGoodMen", "A Few Good Men", 1992, - "In the heart of the nation's capital, in a courthouse of the U.S. government, one man will stop at nothing to keep his honor, and one will stop at nothing to find the truth.") + "In the heart of the nation's capital, in a courthouse of the U.S. government, one man will stop at " + + "nothing to keep his honor, and one will stop at nothing to find the truth.") .getId(); final String tomC = saveActor(actors, "TomC", "Tom Cruise", 1962).getId(); final String jackN = saveActor(actors, "JackN", "Jack Nicholson", 1937).getId(); @@ -457,7 +210,8 @@ private static void createData() { saveActsIn(actsIn, jonathanL, jerryMaguire, new String[]{"Ray Boyd"}, 2000); final String standByMe = saveMovie(movies, "StandByMe", "Stand By Me", 1986, - "For some, it's the last real taste of innocence, and the first real taste of life. But for everyone, it's the time that memories are made of.") + "For some, it's the last real taste of innocence, and the first real taste of life. But for everyone," + + " it's the time that memories are made of.") .getId(); final String riverP = saveActor(actors, "RiverP", "River Phoenix", 1970).getId(); final String coreyF = saveActor(actors, "CoreyF", "Corey Feldman", 1971).getId(); @@ -517,7 +271,8 @@ private static void createData() { saveActsIn(actsIn, steveZ, youveGotMail, new String[]{"George Pappas"}, 1998); final String sleeplessInSeattle = saveMovie(movies, "SleeplessInSeattle", "Sleepless in Seattle", 1993, - "What if someone you never met, someone you never saw, someone you never knew was the only someone for you?") + "What if someone you never met, someone you never saw, someone you never knew was the only someone " + + "for you?") .getId(); final String ritaW = saveActor(actors, "RitaW", "Rita Wilson", 1956).getId(); final String billPull = saveActor(actors, "BillPull", "Bill Pullman", 1953).getId(); @@ -549,4 +304,275 @@ private static void createData() { saveActsIn(actsIn, brunoK, whenHarryMetSally, new String[]{"Jess"}, 1998); } + /** + * @see AQL + * Example Queries on an Actors and Movies Database + */ + @Test + void allActorsActsInMovie1or2() { + final ArangoCursor cursor = db.query( + "WITH actors, movies FOR x IN ANY 'movies/TheMatrix' actsIn OPTIONS {bfs: true, uniqueVertices: " + + "'global'} RETURN x._id", + null, null, String.class); + assertThat(cursor.asListRemaining()) + .contains("actors/Keanu", "actors/Hugo", "actors/Emil", "actors/Carrie", "actors/Laurence"); + } + + /** + * @see AQL + * Example Queries on an Actors and Movies Database + */ + @Test + void allActorsActsInMovie1or2UnionDistinct() { + final ArangoCursor cursor = db.query( + "WITH actors, movies FOR x IN UNION_DISTINCT ((FOR y IN ANY 'movies/TheMatrix' actsIn OPTIONS {bfs: " + + "true, uniqueVertices: 'global'} RETURN y._id), (FOR y IN ANY 'movies/TheDevilsAdvocate' " + + "actsIn OPTIONS {bfs: true, uniqueVertices: 'global'} RETURN y._id)) RETURN x", + null, null, String.class); + assertThat(cursor.asListRemaining()).contains("actors/Emil", "actors/Hugo", "actors/Carrie", "actors/Laurence", + "actors/Keanu", "actors/Al", "actors/Charlize"); + } + + /** + * @see AQL + * Example Queries on an Actors and Movies Database + */ + @Test + void allActorsActsInMovie1and2() { + final ArangoCursor cursor = db.query( + "WITH actors, movies FOR x IN INTERSECTION ((FOR y IN ANY 'movies/TheMatrix' actsIn OPTIONS {bfs: " + + "true, uniqueVertices: 'global'} RETURN y._id), (FOR y IN ANY 'movies/TheDevilsAdvocate' " + + "actsIn OPTIONS {bfs: true, uniqueVertices: 'global'} RETURN y._id)) RETURN x", + null, null, String.class); + assertThat(cursor.asListRemaining()).contains("actors/Keanu"); + } + + /** + * @see AQL + * Example Queries on an Actors and Movies Database + */ + @Test + void allMoviesBetweenActor1andActor2() { + final ArangoCursor cursor = db.query( + "WITH actors, movies FOR x IN INTERSECTION ((FOR y IN ANY 'actors/Hugo' actsIn OPTIONS {bfs: true, " + + "uniqueVertices: 'global'} RETURN y._id), (FOR y IN ANY 'actors/Keanu' actsIn OPTIONS {bfs: " + + "true, uniqueVertices: 'global'} RETURN y._id)) RETURN x", + null, null, String.class); + assertThat(cursor.asListRemaining()) + .contains("movies/TheMatrixRevolutions", "movies/TheMatrixReloaded", "movies/TheMatrix"); + } + + /** + * @see AQL + * Example Queries on an Actors and Movies Database + */ + @Test + void allActorsWhoActedIn3orMoreMovies() { + final ArangoCursor cursor = db.query( + "FOR x IN actsIn COLLECT actor = x._from WITH COUNT INTO counter FILTER counter >= 3 RETURN {actor: " + + "actor, movies: counter}", + null, null, Actor.class); + assertThat(cursor.asListRemaining()) + .contains(new Actor("actors/Carrie", 3), new Actor("actors/CubaG", 4), new Actor("actors/Hugo", 3), + new Actor("actors/Keanu", 4), new Actor("actors/Laurence", 3), new Actor("actors/MegR", 5), + new Actor("actors/TomC", 3), new Actor("actors/TomH", 3)); + } + + /** + * @see AQL + * Example Queries on an Actors and Movies Database + */ + @Test + void allMoviesWhereExactly6ActorsActedIn() { + final ArangoCursor cursor = db.query( + "FOR x IN actsIn COLLECT movie = x._to WITH COUNT INTO counter FILTER counter == 6 RETURN movie", null, + null, String.class); + assertThat(cursor.asListRemaining()) + .contains("movies/SleeplessInSeattle", "movies/TopGun", "movies/YouveGotMail"); + } + + /** + * @see AQL + * Example Queries on an Actors and Movies Database + */ + @Test + void theNumberOfActorsByMovie() { + final ArangoCursor cursor = db.query( + "FOR x IN actsIn COLLECT movie = x._to WITH COUNT INTO counter RETURN {movie: movie, actors: counter}", + null, null, Movie.class); + assertThat(cursor.asListRemaining()) + .contains(new Movie("movies/AFewGoodMen", 11), new Movie("movies/AsGoodAsItGets", 4), + new Movie("movies/JerryMaguire", 9), new Movie("movies/JoeVersustheVolcano", 3), + new Movie("movies/SleeplessInSeattle", 6), new Movie("movies/SnowFallingonCedars", 4), + new Movie("movies/StandByMe", 7), new Movie("movies/TheDevilsAdvocate", 3), + new Movie("movies/TheMatrix", 5), new Movie("movies/TheMatrixReloaded", 4), + new Movie("movies/TheMatrixRevolutions", 4), new Movie("movies/TopGun", 6), + new Movie("movies/WhatDreamsMayCome", 5), new Movie("movies/WhenHarryMetSally", 4), + new Movie("movies/YouveGotMail", 6)); + } + + /** + * @see AQL + * Example Queries on an Actors and Movies Database + */ + @Test + void theNumberOfMoviesByActor() { + final ArangoCursor cursor = db.query( + "FOR x IN actsIn COLLECT actor = x._from WITH COUNT INTO counter RETURN {actor: actor, movies: " + + "counter}", + null, null, Actor.class); + assertThat(cursor.asListRemaining()) + .contains(new Actor("actors/Al", 1), new Actor("actors/AnnabellaS", 1), new Actor("actors/AnthonyE", 1), + new Actor("actors/BillPull", 1), new Actor("actors/BillyC", 1), new Actor("actors/BonnieH", 1), + new Actor("actors/BrunoK", 1), new Actor("actors/Carrie", 3), new Actor("actors/CarrieF", 1), + new Actor("actors/Charlize", 1), new Actor("actors/ChristopherG", 1), new Actor("actors" + + "/CoreyF", 1), + new Actor("actors/CubaG", 4), new Actor("actors/DaveC", 1), new Actor("actors/DemiM", 1), + new Actor("actors/Emil", 1), new Actor("actors/EthanH", 1), new Actor("actors/GregK", 2), + new Actor("actors/HelenH", 1), new Actor("actors/Hugo", 3), new Actor("actors/JackN", 2), + new Actor("actors/JamesC", 1), new Actor("actors/JamesM", 1), new Actor("actors/JayM", 1), + new Actor("actors/JerryO", 2), new Actor("actors/JohnC", 1), new Actor("actors/JonathanL", 1), + new Actor("actors/JTW", 1), new Actor("actors/Keanu", 4), new Actor("actors/KellyM", 1), + new Actor("actors/KellyP", 1), new Actor("actors/KevinB", 1), new Actor("actors/KevinP", 1), + new Actor("actors/KieferS", 2), new Actor("actors/Laurence", 3), new Actor("actors/MarshallB" + , 1), + new Actor("actors/MaxS", 2), new Actor("actors/MegR", 5), new Actor("actors/Nathan", 1), + new Actor("actors/NoahW", 1), new Actor("actors/ParkerP", 1), new Actor("actors/ReginaK", 1), + new Actor("actors/ReneeZ", 1), new Actor("actors/RickY", 1), new Actor("actors/RitaW", 1), + new Actor("actors/RiverP", 1), new Actor("actors/Robin", 1), new Actor("actors/RosieO", 1), + new Actor("actors/SteveZ", 1), new Actor("actors/TomC", 3), new Actor("actors/TomH", 3), + new Actor("actors/TomS", 1), new Actor("actors/ValK", 1), new Actor("actors/VictorG", 1), + new Actor("actors/WernerH", 1), new Actor("actors/WilW", 1)); + } + + /** + * @see AQL + * Example Queries on an Actors and Movies Database + */ + @Test + void theNumberOfMoviesActedInBetween2005and2010byActor() { + final ArangoCursor cursor = db.query( + "FOR x IN actsIn FILTER x.year >= 1990 && x.year <= 1995 COLLECT actor = x._from WITH COUNT INTO " + + "counter RETURN {actor: actor, movies: counter}", + null, null, Actor.class); + assertThat(cursor.asListRemaining()) + .contains(new Actor("actors/BillPull", 1), new Actor("actors/ChristopherG", 1), new Actor("actors" + + "/CubaG", 1), + new Actor("actors/DemiM", 1), new Actor("actors/JackN", 1), new Actor("actors/JamesM", 1), + new Actor("actors/JTW", 1), new Actor("actors/KevinB", 1), new Actor("actors/KieferS", 1), + new Actor("actors/MegR", 2), new Actor("actors/Nathan", 1), new Actor("actors/NoahW", 1), + new Actor("actors/RitaW", 1), new Actor("actors/RosieO", 1), new Actor("actors/TomC", 1), + new Actor("actors/TomH", 2), new Actor("actors/VictorG", 1)); + } + + public static class Actor { + private final String actor; + private final Integer movies; + + @JsonCreator + Actor(@JsonProperty("actor") final String actor, @JsonProperty("movies") final Integer movies) { + super(); + this.actor = actor; + this.movies = movies; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((actor == null) ? 0 : actor.hashCode()); + result = prime * result + ((movies == null) ? 0 : movies.hashCode()); + return result; + } + + @Override + public boolean equals(final Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + final Actor other = (Actor) obj; + if (actor == null) { + if (other.actor != null) { + return false; + } + } else if (!actor.equals(other.actor)) { + return false; + } + if (movies == null) { + return other.movies == null; + } else return movies.equals(other.movies); + } + + } + + public static class Movie { + private final String movie; + private final Integer actors; + + @JsonCreator + public Movie(@JsonProperty("movie") final String movie, @JsonProperty("actors") final Integer actors) { + super(); + this.movie = movie; + this.actors = actors; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((actors == null) ? 0 : actors.hashCode()); + result = prime * result + ((movie == null) ? 0 : movie.hashCode()); + return result; + } + + @Override + public boolean equals(final Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + final Movie other = (Movie) obj; + if (actors == null) { + if (other.actors != null) { + return false; + } + } else if (!actors.equals(other.actors)) { + return false; + } + if (movie == null) { + return other.movie == null; + } else return movie.equals(other.movie); + } + + } + } diff --git a/src/test/java/com/arangodb/example/graph/BaseGraphTest.java b/src/test/java/com/arangodb/example/graph/BaseGraphTest.java index 2a7baa2f1..d60239fa3 100644 --- a/src/test/java/com/arangodb/example/graph/BaseGraphTest.java +++ b/src/test/java/com/arangodb/example/graph/BaseGraphTest.java @@ -38,11 +38,11 @@ abstract class BaseGraphTest { private static final DbName TEST_DB = DbName.of("java_driver_graph_test_db"); - private static ArangoDB arangoDB; - static ArangoDatabase db; private static final String GRAPH_NAME = "traversalGraph"; private static final String EDGE_COLLECTION_NAME = "edges"; private static final String VERTEX_COLLECTION_NAME = "circles"; + static ArangoDatabase db; + private static ArangoDB arangoDB; @BeforeAll static void init() { diff --git a/src/test/java/com/arangodb/example/graph/GraphTraversalsInAQLExampleTest.java b/src/test/java/com/arangodb/example/graph/GraphTraversalsInAQLExampleTest.java index 35330c490..94e48a307 100644 --- a/src/test/java/com/arangodb/example/graph/GraphTraversalsInAQLExampleTest.java +++ b/src/test/java/com/arangodb/example/graph/GraphTraversalsInAQLExampleTest.java @@ -65,23 +65,27 @@ void queryDepthTwo() throws ArangoDBException { @Test void queryWithFilter() throws ArangoDBException { - String queryString = "FOR v, e, p IN 1..3 OUTBOUND 'circles/A' GRAPH 'traversalGraph' FILTER p.vertices[1]._key != 'G' RETURN v._key"; + String queryString = "FOR v, e, p IN 1..3 OUTBOUND 'circles/A' GRAPH 'traversalGraph' FILTER p.vertices[1]" + + "._key != 'G' RETURN v._key"; ArangoCursor cursor = db.query(queryString, null, null, String.class); Collection result = cursor.asListRemaining(); assertThat(result).containsExactlyInAnyOrder("B", "C", "D", "E", "F"); - queryString = "FOR v, e, p IN 1..3 OUTBOUND 'circles/A' GRAPH 'traversalGraph' FILTER p.edges[0].label != 'right_foo' RETURN v._key"; + queryString = "FOR v, e, p IN 1..3 OUTBOUND 'circles/A' GRAPH 'traversalGraph' FILTER p.edges[0].label != " + + "'right_foo' RETURN v._key"; cursor = db.query(queryString, null, null, String.class); result = cursor.asListRemaining(); assertThat(result).containsExactlyInAnyOrder("B", "C", "D", "E", "F"); - queryString = "FOR v,e,p IN 1..3 OUTBOUND 'circles/A' GRAPH 'traversalGraph' FILTER p.vertices[1]._key != 'G' FILTER p.edges[1].label != 'left_blub' return v._key"; + queryString = "FOR v,e,p IN 1..3 OUTBOUND 'circles/A' GRAPH 'traversalGraph' FILTER p.vertices[1]._key != 'G'" + + " FILTER p.edges[1].label != 'left_blub' return v._key"; cursor = db.query(queryString, null, null, String.class); result = cursor.asListRemaining(); assertThat(result).containsExactlyInAnyOrder("B", "C", "D"); - queryString = "FOR v,e,p IN 1..3 OUTBOUND 'circles/A' GRAPH 'traversalGraph' FILTER p.vertices[1]._key != 'G' AND p.edges[1].label != 'left_blub' return v._key"; + queryString = "FOR v,e,p IN 1..3 OUTBOUND 'circles/A' GRAPH 'traversalGraph' FILTER p.vertices[1]._key != 'G'" + + " AND p.edges[1].label != 'left_blub' return v._key"; cursor = db.query(queryString, null, null, String.class); result = cursor.asListRemaining(); assertThat(result).containsExactlyInAnyOrder("B", "C", "D"); diff --git a/src/test/java/com/arangodb/example/graph/ShortestPathInAQLExampleTest.java b/src/test/java/com/arangodb/example/graph/ShortestPathInAQLExampleTest.java index f49979951..aecf7321a 100644 --- a/src/test/java/com/arangodb/example/graph/ShortestPathInAQLExampleTest.java +++ b/src/test/java/com/arangodb/example/graph/ShortestPathInAQLExampleTest.java @@ -38,38 +38,17 @@ */ class ShortestPathInAQLExampleTest extends BaseGraphTest { - public static class Pair { - - private String vertex; - private String edge; - - String getVertex() { - return vertex; - } - - void setVertex(final String vertex) { - this.vertex = vertex; - } - - String getEdge() { - return edge; - } - - void setEdge(final String edge) { - this.edge = edge; - } - - } - @Test void queryShortestPathFromAToD() throws ArangoDBException { - String queryString = "FOR v, e IN OUTBOUND SHORTEST_PATH 'circles/A' TO 'circles/D' GRAPH 'traversalGraph' RETURN {'vertex': v._key, 'edge': e._key}"; + String queryString = "FOR v, e IN OUTBOUND SHORTEST_PATH 'circles/A' TO 'circles/D' GRAPH 'traversalGraph' " + + "RETURN {'vertex': v._key, 'edge': e._key}"; ArangoCursor cursor = db.query(queryString, null, null, Pair.class); final Collection collection = toVertexCollection(cursor); assertThat(collection.size()).isEqualTo(4); assertThat(collection).containsExactlyInAnyOrder("A", "B", "C", "D"); - queryString = "WITH circles FOR v, e IN OUTBOUND SHORTEST_PATH 'circles/A' TO 'circles/D' edges RETURN {'vertex': v._key, 'edge': e._key}"; + queryString = "WITH circles FOR v, e IN OUTBOUND SHORTEST_PATH 'circles/A' TO 'circles/D' edges RETURN " + + "{'vertex': v._key, 'edge': e._key}"; db.query(queryString, null, null, Pair.class); assertThat(collection.size()).isEqualTo(4); assertThat(collection).containsExactlyInAnyOrder("A", "B", "C", "D"); @@ -77,13 +56,15 @@ void queryShortestPathFromAToD() throws ArangoDBException { @Test void queryShortestPathByFilter() throws ArangoDBException { - String queryString = "FOR a IN circles FILTER a._key == 'A' FOR d IN circles FILTER d._key == 'D' FOR v, e IN OUTBOUND SHORTEST_PATH a TO d GRAPH 'traversalGraph' RETURN {'vertex':v._key, 'edge':e._key}"; + String queryString = "FOR a IN circles FILTER a._key == 'A' FOR d IN circles FILTER d._key == 'D' FOR v, e IN" + + " OUTBOUND SHORTEST_PATH a TO d GRAPH 'traversalGraph' RETURN {'vertex':v._key, 'edge':e._key}"; ArangoCursor cursor = db.query(queryString, null, null, Pair.class); final Collection collection = toVertexCollection(cursor); assertThat(collection.size()).isEqualTo(4); assertThat(collection).containsExactlyInAnyOrder("A", "B", "C", "D"); - queryString = "FOR a IN circles FILTER a._key == 'A' FOR d IN circles FILTER d._key == 'D' FOR v, e IN OUTBOUND SHORTEST_PATH a TO d edges RETURN {'vertex': v._key, 'edge': e._key}"; + queryString = "FOR a IN circles FILTER a._key == 'A' FOR d IN circles FILTER d._key == 'D' FOR v, e IN " + + "OUTBOUND SHORTEST_PATH a TO d edges RETURN {'vertex': v._key, 'edge': e._key}"; db.query(queryString, null, null, Pair.class); assertThat(collection.size()).isEqualTo(4); assertThat(collection).containsExactlyInAnyOrder("A", "B", "C", "D"); @@ -98,4 +79,27 @@ private Collection toVertexCollection(final ArangoCursor cursor) { return result; } + public static class Pair { + + private String vertex; + private String edge; + + String getVertex() { + return vertex; + } + + void setVertex(final String vertex) { + this.vertex = vertex; + } + + String getEdge() { + return edge; + } + + void setEdge(final String edge) { + this.edge = edge; + } + + } + } diff --git a/src/test/java/com/arangodb/example/ssl/SslExampleTest.java b/src/test/java/com/arangodb/example/ssl/SslExampleTest.java index b2b2ed2bb..1fd34647d 100644 --- a/src/test/java/com/arangodb/example/ssl/SslExampleTest.java +++ b/src/test/java/com/arangodb/example/ssl/SslExampleTest.java @@ -56,7 +56,7 @@ class SslExampleTest { @Test void connect() throws Exception { final ArangoDB arangoDB = new ArangoDB.Builder() - + .host("localhost", 8529) .password("test") .useSsl(true) @@ -71,7 +71,7 @@ void connect() throws Exception { @Test void noopHostnameVerifier() throws Exception { final ArangoDB arangoDB = new ArangoDB.Builder() - + .host("127.0.0.1", 8529) .password("test") .useSsl(true) diff --git a/src/test/java/com/arangodb/internal/HostHandlerTest.java b/src/test/java/com/arangodb/internal/HostHandlerTest.java index 73ca918b7..ceff3a79e 100644 --- a/src/test/java/com/arangodb/internal/HostHandlerTest.java +++ b/src/test/java/com/arangodb/internal/HostHandlerTest.java @@ -59,9 +59,6 @@ public void close() { }; private static final Host HOST_0 = new HostImpl(mockCP, new HostDescription("127.0.0.1", 8529)); - private static final Host HOST_1 = new HostImpl(mockCP, new HostDescription("127.0.0.2", 8529)); - private static final Host HOST_2 = new HostImpl(mockCP, new HostDescription("127.0.0.3", 8529)); - private static final HostResolver SINGLE_HOST = new HostResolver() { @Override @@ -78,7 +75,8 @@ public void init(ArangoExecutorSync executor, InternalSerde arangoSerialization) } }; - + private static final Host HOST_1 = new HostImpl(mockCP, new HostDescription("127.0.0.2", 8529)); + private static final Host HOST_2 = new HostImpl(mockCP, new HostDescription("127.0.0.3", 8529)); private static final HostResolver MULTIPLE_HOSTS = new HostResolver() { @Override diff --git a/src/test/java/com/arangodb/mapping/annotations/ArangoAnnotationsTest.java b/src/test/java/com/arangodb/mapping/annotations/ArangoAnnotationsTest.java index 1e1389b9c..9f6165b4a 100644 --- a/src/test/java/com/arangodb/mapping/annotations/ArangoAnnotationsTest.java +++ b/src/test/java/com/arangodb/mapping/annotations/ArangoAnnotationsTest.java @@ -38,7 +38,7 @@ class ArangoAnnotationsTest { @ParameterizedTest @EnumSource(DataType.class) void documentFieldAnnotations(DataType dataType) { - ArangoSerde mapper = JacksonSerde.of(dataType); + ArangoSerde mapper = JacksonSerde.of(dataType); AnnotatedEntity e = new AnnotatedEntity(); e.setId("Id"); diff --git a/src/test/java/com/arangodb/serde/CustomSerdeTest.java b/src/test/java/com/arangodb/serde/CustomSerdeTest.java index 779b3e0e1..6f67c0dda 100644 --- a/src/test/java/com/arangodb/serde/CustomSerdeTest.java +++ b/src/test/java/com/arangodb/serde/CustomSerdeTest.java @@ -58,34 +58,6 @@ class CustomSerdeTest { private static ArangoDatabase db; private static ArangoCollection collection; - static class PersonSerializer extends JsonSerializer { - @Override - public void serialize(Person value, JsonGenerator gen, SerializerProvider serializers) throws IOException { - gen.writeStartObject(); - gen.writeFieldName("name"); - gen.writeString(PERSON_SERIALIZER_ADDED_PREFIX + value.name); - gen.writeEndObject(); - } - } - - static class PersonDeserializer extends JsonDeserializer { - @Override - public Person deserialize(JsonParser parser, DeserializationContext ctx) throws IOException { - Person person = new Person(); - JsonNode rootNode = parser.getCodec().readTree(parser); - JsonNode nameNode = rootNode.get("name"); - if (nameNode != null && nameNode.isTextual()) { - person.name = PERSON_DESERIALIZER_ADDED_PREFIX + nameNode.asText(); - } - return person; - } - } - - @JsonSerialize(using = PersonSerializer.class) - static class Person { - String name; - } - @BeforeAll static void init() { JacksonSerde serde = JacksonSerde.of(DataType.VPACK); @@ -230,8 +202,37 @@ void getDocument() { @Test void parseNullString() { - final String json = arangoDB.getSerde().deserializeUserData(arangoDB.getSerde().serializeUserData(null), String.class); + final String json = arangoDB.getSerde().deserializeUserData(arangoDB.getSerde().serializeUserData(null), + String.class); assertThat(json).isNull(); } + static class PersonSerializer extends JsonSerializer { + @Override + public void serialize(Person value, JsonGenerator gen, SerializerProvider serializers) throws IOException { + gen.writeStartObject(); + gen.writeFieldName("name"); + gen.writeString(PERSON_SERIALIZER_ADDED_PREFIX + value.name); + gen.writeEndObject(); + } + } + + static class PersonDeserializer extends JsonDeserializer { + @Override + public Person deserialize(JsonParser parser, DeserializationContext ctx) throws IOException { + Person person = new Person(); + JsonNode rootNode = parser.getCodec().readTree(parser); + JsonNode nameNode = rootNode.get("name"); + if (nameNode != null && nameNode.isTextual()) { + person.name = PERSON_DESERIALIZER_ADDED_PREFIX + nameNode.asText(); + } + return person; + } + } + + @JsonSerialize(using = PersonSerializer.class) + static class Person { + String name; + } + } diff --git a/src/test/java/com/arangodb/serde/CustomTypeHintTest.java b/src/test/java/com/arangodb/serde/CustomTypeHintTest.java index d2144e0ee..cf3569bd6 100644 --- a/src/test/java/com/arangodb/serde/CustomTypeHintTest.java +++ b/src/test/java/com/arangodb/serde/CustomTypeHintTest.java @@ -21,7 +21,10 @@ package com.arangodb.serde; -import com.arangodb.*; +import com.arangodb.ArangoCollection; +import com.arangodb.ArangoDB; +import com.arangodb.ArangoDatabase; +import com.arangodb.DbName; import com.arangodb.entity.Key; import com.arangodb.model.DocumentCreateOptions; import com.fasterxml.jackson.annotation.JsonTypeInfo; @@ -37,50 +40,7 @@ */ class CustomTypeHintTest { - @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, property = "type") - public interface Animal { - String getName(); - } - - public static class Gorilla implements Animal { - private String name; - - @Override - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - } - - public static class Zoo { - - @Key - private String key; - - private Animal animal; - - public String getKey() { - return key; - } - - public void setKey(String key) { - this.key = key; - } - - public Animal getAnimal() { - return animal; - } - - public void setAnimal(Animal animal) { - this.animal = animal; - } - } - private static final String COLLECTION_NAME = "collection"; - private ArangoDatabase db; private ArangoCollection collection; @@ -137,4 +97,46 @@ void insertDocument() { assertThat((readDoc.getAnimal().getName())).isEqualTo("kingKong"); } + + @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, property = "type") + public interface Animal { + String getName(); + } + + public static class Gorilla implements Animal { + private String name; + + @Override + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + } + + public static class Zoo { + + @Key + private String key; + + private Animal animal; + + public String getKey() { + return key; + } + + public void setKey(String key) { + this.key = key; + } + + public Animal getAnimal() { + return animal; + } + + public void setAnimal(Animal animal) { + this.animal = animal; + } + } } diff --git a/src/test/java/com/arangodb/serde/SerdeTest.java b/src/test/java/com/arangodb/serde/SerdeTest.java index 872945ab2..d3bbe9e7d 100644 --- a/src/test/java/com/arangodb/serde/SerdeTest.java +++ b/src/test/java/com/arangodb/serde/SerdeTest.java @@ -10,7 +10,6 @@ import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.EnumSource; - import java.sql.Date; import static org.assertj.core.api.Assertions.assertThat; diff --git a/src/test/java/com/arangodb/util/TestUtils.java b/src/test/java/com/arangodb/util/TestUtils.java index 836466429..a8faab73a 100644 --- a/src/test/java/com/arangodb/util/TestUtils.java +++ b/src/test/java/com/arangodb/util/TestUtils.java @@ -43,7 +43,8 @@ private TestUtils() { * <{@param otherMajor}, {@param otherMinor}, {@param otherPatch}> * comparing the corresponding version components in lexicographical order. */ - public static boolean isAtLeastVersion(final String version, final int otherMajor, final int otherMinor, final int otherPatch) { + public static boolean isAtLeastVersion(final String version, final int otherMajor, final int otherMinor, + final int otherPatch) { return compareVersion(version, otherMajor, otherMinor, otherPatch) >= 0; } @@ -52,11 +53,13 @@ public static boolean isAtLeastVersion(final String version, final int otherMajo * <{@param otherMajor}, {@param otherMinor}, {@param otherPatch}> * comparing the corresponding version components in lexicographical order. */ - public static boolean isLessThanVersion(final String version, final int otherMajor, final int otherMinor, final int otherPatch) { + public static boolean isLessThanVersion(final String version, final int otherMajor, final int otherMinor, + final int otherPatch) { return compareVersion(version, otherMajor, otherMinor, otherPatch) < 0; } - private static int compareVersion(final String version, final int otherMajor, final int otherMinor, final int otherPatch) { + private static int compareVersion(final String version, final int otherMajor, final int otherMinor, + final int otherPatch) { String[] parts = version.split("-")[0].split("\\."); int major = Integer.parseInt(parts[0]); diff --git a/src/test/java/com/arangodb/util/UnicodeUtilsTest.java b/src/test/java/com/arangodb/util/UnicodeUtilsTest.java index c4b21b6de..b295223bd 100644 --- a/src/test/java/com/arangodb/util/UnicodeUtilsTest.java +++ b/src/test/java/com/arangodb/util/UnicodeUtilsTest.java @@ -16,11 +16,11 @@ class UnicodeUtilsTest { + private static final String encodeFn = "(function encode(x){return encodeURIComponent(x);})"; + private static final String normalizeFn = "(function normalize(x){return x.normalize('NFC');})"; private static Context context; private static Value jsEncoder; private static Value jsNormalizer; - private static final String encodeFn = "(function encode(x){return encodeURIComponent(x);})"; - private static final String normalizeFn = "(function normalize(x){return x.normalize('NFC');})"; @BeforeAll static void beforeClass() { From 8eba3cea215f33194fb915e76d65f93bd56a1d37 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Wed, 17 Aug 2022 15:07:20 +0200 Subject: [PATCH 102/254] optional mvn deps --- pom.xml | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/pom.xml b/pom.xml index 5d5a3529d..79085d348 100644 --- a/pom.xml +++ b/pom.xml @@ -312,30 +312,34 @@ slf4j-api - org.apache.httpcomponents - httpclient + jakarta.json.bind + jakarta.json.bind-api + 2.0.0 com.fasterxml.jackson.core jackson-databind + provided com.fasterxml.jackson.core jackson-core + provided com.fasterxml.jackson.core jackson-annotations + provided - com.arangodb - jackson-dataformat-velocypack + org.apache.httpcomponents + httpclient true - jakarta.json.bind - jakarta.json.bind-api - 2.0.0 + com.arangodb + jackson-dataformat-velocypack + true ch.qos.logback From fd6223a2940cdec6bb01982b74f8af5e27256ff2 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Thu, 18 Aug 2022 09:10:12 +0200 Subject: [PATCH 103/254] [DE-333] removed all occurrences of satellite() in pkg com.arangodb.model --- .../java/com/arangodb/model/CollectionCreateOptions.java | 5 ----- src/main/java/com/arangodb/model/DatabaseOptions.java | 5 ----- src/main/java/com/arangodb/model/GraphCreateOptions.java | 5 ----- src/test/java/com/arangodb/ArangoDBTest.java | 2 +- src/test/java/com/arangodb/ArangoDatabaseTest.java | 4 ++-- src/test/java/com/arangodb/async/ArangoDBTest.java | 2 +- 6 files changed, 4 insertions(+), 19 deletions(-) diff --git a/src/main/java/com/arangodb/model/CollectionCreateOptions.java b/src/main/java/com/arangodb/model/CollectionCreateOptions.java index 4d4fccd3c..92b20a35e 100644 --- a/src/main/java/com/arangodb/model/CollectionCreateOptions.java +++ b/src/main/java/com/arangodb/model/CollectionCreateOptions.java @@ -98,11 +98,6 @@ public CollectionCreateOptions replicationFactor(int replicationFactor) { return this; } - public CollectionCreateOptions satellite() { - this.replicationFactor = ReplicationFactor.ofSatellite(); - return this; - } - public Integer getWriteConcern() { return writeConcern; } diff --git a/src/main/java/com/arangodb/model/DatabaseOptions.java b/src/main/java/com/arangodb/model/DatabaseOptions.java index 68cfd83d0..62bbaa7cd 100644 --- a/src/main/java/com/arangodb/model/DatabaseOptions.java +++ b/src/main/java/com/arangodb/model/DatabaseOptions.java @@ -63,11 +63,6 @@ public DatabaseOptions replicationFactor(int replicationFactor) { return this; } - public DatabaseOptions satellite() { - this.replicationFactor = ReplicationFactor.ofSatellite(); - return this; - } - /** * Default write concern for new collections created in this database. It determines how many copies of each shard * are required to be in sync on the different DBServers. If there are less then these many copies in the cluster a diff --git a/src/main/java/com/arangodb/model/GraphCreateOptions.java b/src/main/java/com/arangodb/model/GraphCreateOptions.java index 340b506cb..1b7e3b322 100644 --- a/src/main/java/com/arangodb/model/GraphCreateOptions.java +++ b/src/main/java/com/arangodb/model/GraphCreateOptions.java @@ -139,11 +139,6 @@ public GraphCreateOptions replicationFactor(int replicationFactor) { return this; } - public GraphCreateOptions satellite() { - getOptions().setReplicationFactor(ReplicationFactor.ofSatellite()); - return this; - } - public Integer getWriteConcern() { return getOptions().getWriteConcern(); } diff --git a/src/test/java/com/arangodb/ArangoDBTest.java b/src/test/java/com/arangodb/ArangoDBTest.java index fad65f710..4570a2322 100644 --- a/src/test/java/com/arangodb/ArangoDBTest.java +++ b/src/test/java/com/arangodb/ArangoDBTest.java @@ -161,7 +161,7 @@ void createDatabaseWithOptionsSatellite(ArangoDB arangoDB) { .name(dbName) .options(new DatabaseOptions() .writeConcern(2) - .satellite() + .replicationFactor(ReplicationFactor.ofSatellite()) .sharding("") ) ); diff --git a/src/test/java/com/arangodb/ArangoDatabaseTest.java b/src/test/java/com/arangodb/ArangoDatabaseTest.java index 5898d7f5d..026ed4d21 100644 --- a/src/test/java/com/arangodb/ArangoDatabaseTest.java +++ b/src/test/java/com/arangodb/ArangoDatabaseTest.java @@ -143,7 +143,7 @@ void createSatelliteCollection(ArangoDatabase db) { String name = "collection-" + rnd(); final CollectionEntity result = db - .createCollection(name, new CollectionCreateOptions().satellite()); + .createCollection(name, new CollectionCreateOptions().replicationFactor(ReplicationFactor.ofSatellite())); assertThat(result).isNotNull(); assertThat(result.getId()).isNotNull(); @@ -1109,7 +1109,7 @@ void createGraphSatellite(ArangoDatabase db) { assumeTrue(isEnterprise()); String name = "graph-" + rnd(); - final GraphEntity result = db.createGraph(name, null, new GraphCreateOptions().satellite()); + final GraphEntity result = db.createGraph(name, null, new GraphCreateOptions().replicationFactor(ReplicationFactor.ofSatellite())); assertThat(result.getReplicationFactor()).isEqualTo(ReplicationFactor.ofSatellite()); GraphEntity info = db.graph(name).getInfo(); diff --git a/src/test/java/com/arangodb/async/ArangoDBTest.java b/src/test/java/com/arangodb/async/ArangoDBTest.java index 3a1dd2f46..d5a48438e 100644 --- a/src/test/java/com/arangodb/async/ArangoDBTest.java +++ b/src/test/java/com/arangodb/async/ArangoDBTest.java @@ -186,7 +186,7 @@ void createDatabaseWithOptionsSatellite() throws ExecutionException, Interrupted .name(dbName) .options(new DatabaseOptions() .writeConcern(2) - .satellite() + .replicationFactor(ReplicationFactor.ofSatellite()) .sharding("") ) ).get(); From 5fbd10b6fa4115ecdf2463671d1db2f822a31af8 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Tue, 16 Aug 2022 13:20:15 +0200 Subject: [PATCH 104/254] added thread safety annotations (#445) (cherry picked from commit b6445b66d751dcc1eaf06259c038992d27dde88c) --- pom.xml | 6 ++++++ src/main/java/com/arangodb/ArangoCollection.java | 2 ++ src/main/java/com/arangodb/ArangoDB.java | 2 ++ src/main/java/com/arangodb/ArangoDatabase.java | 2 ++ src/main/java/com/arangodb/ArangoEdgeCollection.java | 3 +++ src/main/java/com/arangodb/ArangoGraph.java | 2 ++ src/main/java/com/arangodb/ArangoMetrics.java | 3 +++ src/main/java/com/arangodb/ArangoSearch.java | 3 +++ src/main/java/com/arangodb/ArangoSerdeAccessor.java | 3 +++ src/main/java/com/arangodb/ArangoVertexCollection.java | 3 +++ src/main/java/com/arangodb/ArangoView.java | 3 +++ src/main/java/com/arangodb/QueueTimeMetrics.java | 3 +++ src/main/java/com/arangodb/async/ArangoCollectionAsync.java | 2 ++ src/main/java/com/arangodb/async/ArangoDBAsync.java | 2 ++ src/main/java/com/arangodb/async/ArangoDatabaseAsync.java | 2 ++ .../java/com/arangodb/async/ArangoEdgeCollectionAsync.java | 2 ++ src/main/java/com/arangodb/async/ArangoGraphAsync.java | 2 ++ src/main/java/com/arangodb/async/ArangoSearchAsync.java | 2 ++ .../com/arangodb/async/ArangoVertexCollectionAsync.java | 2 ++ src/main/java/com/arangodb/async/ArangoViewAsync.java | 2 ++ 20 files changed, 51 insertions(+) diff --git a/pom.xml b/pom.xml index 79085d348..e8988cd00 100644 --- a/pom.xml +++ b/pom.xml @@ -341,6 +341,12 @@ jackson-dataformat-velocypack true + + com.google.code.findbugs + jsr305 + 3.0.2 + provided + ch.qos.logback logback-classic diff --git a/src/main/java/com/arangodb/ArangoCollection.java b/src/main/java/com/arangodb/ArangoCollection.java index cbf14b5d5..bfe741ca5 100644 --- a/src/main/java/com/arangodb/ArangoCollection.java +++ b/src/main/java/com/arangodb/ArangoCollection.java @@ -24,6 +24,7 @@ import com.arangodb.model.*; import com.arangodb.util.RawData; +import javax.annotation.concurrent.ThreadSafe; import java.util.Collection; /** @@ -35,6 +36,7 @@ * @see Collection API Documentation * @see Documents API Documentation */ +@ThreadSafe public interface ArangoCollection extends ArangoSerdeAccessor { /** diff --git a/src/main/java/com/arangodb/ArangoDB.java b/src/main/java/com/arangodb/ArangoDB.java index de79fb542..1729a0182 100644 --- a/src/main/java/com/arangodb/ArangoDB.java +++ b/src/main/java/com/arangodb/ArangoDB.java @@ -45,6 +45,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import javax.annotation.concurrent.ThreadSafe; import javax.net.ssl.HostnameVerifier; import javax.net.ssl.SSLContext; import java.io.InputStream; @@ -67,6 +68,7 @@ * @author Mark Vollmary * @author Michele Rastelli */ +@ThreadSafe public interface ArangoDB extends ArangoSerdeAccessor { /** diff --git a/src/main/java/com/arangodb/ArangoDatabase.java b/src/main/java/com/arangodb/ArangoDatabase.java index 16cd93cbf..bb506b6f8 100644 --- a/src/main/java/com/arangodb/ArangoDatabase.java +++ b/src/main/java/com/arangodb/ArangoDatabase.java @@ -26,6 +26,7 @@ import com.arangodb.model.arangosearch.AnalyzerDeleteOptions; import com.arangodb.model.arangosearch.ArangoSearchCreateOptions; +import javax.annotation.concurrent.ThreadSafe; import java.util.Collection; import java.util.Map; @@ -37,6 +38,7 @@ * @see Databases API Documentation * @see Query API Documentation */ +@ThreadSafe public interface ArangoDatabase extends ArangoSerdeAccessor { /** diff --git a/src/main/java/com/arangodb/ArangoEdgeCollection.java b/src/main/java/com/arangodb/ArangoEdgeCollection.java index 7558d9f65..c0d64d369 100644 --- a/src/main/java/com/arangodb/ArangoEdgeCollection.java +++ b/src/main/java/com/arangodb/ArangoEdgeCollection.java @@ -24,12 +24,15 @@ import com.arangodb.entity.EdgeUpdateEntity; import com.arangodb.model.*; +import javax.annotation.concurrent.ThreadSafe; + /** * Interface for operations on ArangoDB edge collection level. * * @author Mark Vollmary * @see API Documentation */ +@ThreadSafe public interface ArangoEdgeCollection extends ArangoSerdeAccessor { /** diff --git a/src/main/java/com/arangodb/ArangoGraph.java b/src/main/java/com/arangodb/ArangoGraph.java index b37d0aded..49038891a 100644 --- a/src/main/java/com/arangodb/ArangoGraph.java +++ b/src/main/java/com/arangodb/ArangoGraph.java @@ -25,6 +25,7 @@ import com.arangodb.model.GraphCreateOptions; import com.arangodb.model.VertexCollectionCreateOptions; +import javax.annotation.concurrent.ThreadSafe; import java.util.Collection; /** @@ -33,6 +34,7 @@ * @author Mark Vollmary * @see API Documentation */ +@ThreadSafe public interface ArangoGraph extends ArangoSerdeAccessor { /** diff --git a/src/main/java/com/arangodb/ArangoMetrics.java b/src/main/java/com/arangodb/ArangoMetrics.java index 21d659b53..38253fac4 100644 --- a/src/main/java/com/arangodb/ArangoMetrics.java +++ b/src/main/java/com/arangodb/ArangoMetrics.java @@ -20,12 +20,15 @@ package com.arangodb; +import javax.annotation.concurrent.ThreadSafe; + /** * Interface for accessing metrics. * * @author Michele Rastelli * @since ArangoDB 3.9 */ +@ThreadSafe public interface ArangoMetrics { /** * @return queue time metrics diff --git a/src/main/java/com/arangodb/ArangoSearch.java b/src/main/java/com/arangodb/ArangoSearch.java index 3ccb89e60..21ebe800d 100644 --- a/src/main/java/com/arangodb/ArangoSearch.java +++ b/src/main/java/com/arangodb/ArangoSearch.java @@ -25,6 +25,8 @@ import com.arangodb.model.arangosearch.ArangoSearchCreateOptions; import com.arangodb.model.arangosearch.ArangoSearchPropertiesOptions; +import javax.annotation.concurrent.ThreadSafe; + /** * Interface for operations on ArangoDB view level for ArangoSearch views. * @@ -32,6 +34,7 @@ * @see View API Documentation * @since ArangoDB 3.4.0 */ +@ThreadSafe public interface ArangoSearch extends ArangoView { /** diff --git a/src/main/java/com/arangodb/ArangoSerdeAccessor.java b/src/main/java/com/arangodb/ArangoSerdeAccessor.java index 5918a4d43..7ff4892c0 100644 --- a/src/main/java/com/arangodb/ArangoSerdeAccessor.java +++ b/src/main/java/com/arangodb/ArangoSerdeAccessor.java @@ -22,9 +22,12 @@ import com.arangodb.internal.serde.InternalSerde; +import javax.annotation.concurrent.ThreadSafe; + /** * @author Mark Vollmary */ +@ThreadSafe public interface ArangoSerdeAccessor { /** diff --git a/src/main/java/com/arangodb/ArangoVertexCollection.java b/src/main/java/com/arangodb/ArangoVertexCollection.java index 03d755327..fa43961f8 100644 --- a/src/main/java/com/arangodb/ArangoVertexCollection.java +++ b/src/main/java/com/arangodb/ArangoVertexCollection.java @@ -24,12 +24,15 @@ import com.arangodb.entity.VertexUpdateEntity; import com.arangodb.model.*; +import javax.annotation.concurrent.ThreadSafe; + /** * Interface for operations on ArangoDB vertex collection level. * * @author Mark Vollmary * @see API Documentation */ +@ThreadSafe public interface ArangoVertexCollection extends ArangoSerdeAccessor { /** diff --git a/src/main/java/com/arangodb/ArangoView.java b/src/main/java/com/arangodb/ArangoView.java index 6520ab469..38f848c09 100644 --- a/src/main/java/com/arangodb/ArangoView.java +++ b/src/main/java/com/arangodb/ArangoView.java @@ -22,6 +22,8 @@ import com.arangodb.entity.ViewEntity; +import javax.annotation.concurrent.ThreadSafe; + /** * Interface for operations on ArangoDB view level. * @@ -29,6 +31,7 @@ * @see View API Documentation * @since ArangoDB 3.4.0 */ +@ThreadSafe public interface ArangoView extends ArangoSerdeAccessor { /** diff --git a/src/main/java/com/arangodb/QueueTimeMetrics.java b/src/main/java/com/arangodb/QueueTimeMetrics.java index 333d14997..c04a7110b 100644 --- a/src/main/java/com/arangodb/QueueTimeMetrics.java +++ b/src/main/java/com/arangodb/QueueTimeMetrics.java @@ -22,6 +22,8 @@ import com.arangodb.model.QueueTimeSample; +import javax.annotation.concurrent.ThreadSafe; + /** * Interface for accessing queue time latency metrics, reported by the "X-Arango-Queue-Time-Seconds" response header. * This header contains the most recent request (de)queuing time (in seconds) as tracked by the server’s scheduler. @@ -30,6 +32,7 @@ * @see API Documentation * @since ArangoDB 3.9 */ +@ThreadSafe public interface QueueTimeMetrics { /** diff --git a/src/main/java/com/arangodb/async/ArangoCollectionAsync.java b/src/main/java/com/arangodb/async/ArangoCollectionAsync.java index 83bfe3a88..4ddcd2d6b 100644 --- a/src/main/java/com/arangodb/async/ArangoCollectionAsync.java +++ b/src/main/java/com/arangodb/async/ArangoCollectionAsync.java @@ -25,6 +25,7 @@ import com.arangodb.model.*; import com.arangodb.util.RawData; +import javax.annotation.concurrent.ThreadSafe; import java.util.Collection; import java.util.concurrent.CompletableFuture; @@ -35,6 +36,7 @@ * @see Collection API Documentation * @see Documents API Documentation */ +@ThreadSafe public interface ArangoCollectionAsync extends ArangoSerdeAccessor { /** diff --git a/src/main/java/com/arangodb/async/ArangoDBAsync.java b/src/main/java/com/arangodb/async/ArangoDBAsync.java index 79a873159..56088cbf7 100644 --- a/src/main/java/com/arangodb/async/ArangoDBAsync.java +++ b/src/main/java/com/arangodb/async/ArangoDBAsync.java @@ -49,6 +49,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import javax.annotation.concurrent.ThreadSafe; import javax.net.ssl.SSLContext; import java.io.InputStream; import java.util.Collection; @@ -68,6 +69,7 @@ * * @author Mark Vollmary */ +@ThreadSafe public interface ArangoDBAsync extends ArangoSerdeAccessor { void shutdown(); diff --git a/src/main/java/com/arangodb/async/ArangoDatabaseAsync.java b/src/main/java/com/arangodb/async/ArangoDatabaseAsync.java index 73db9152e..a2cf44135 100644 --- a/src/main/java/com/arangodb/async/ArangoDatabaseAsync.java +++ b/src/main/java/com/arangodb/async/ArangoDatabaseAsync.java @@ -28,6 +28,7 @@ import com.arangodb.model.arangosearch.AnalyzerDeleteOptions; import com.arangodb.model.arangosearch.ArangoSearchCreateOptions; +import javax.annotation.concurrent.ThreadSafe; import java.util.Collection; import java.util.Map; import java.util.concurrent.CompletableFuture; @@ -39,6 +40,7 @@ * @see Databases API Documentation * @see Query API Documentation */ +@ThreadSafe public interface ArangoDatabaseAsync extends ArangoSerdeAccessor { /** diff --git a/src/main/java/com/arangodb/async/ArangoEdgeCollectionAsync.java b/src/main/java/com/arangodb/async/ArangoEdgeCollectionAsync.java index eab16f39c..22d9b791b 100644 --- a/src/main/java/com/arangodb/async/ArangoEdgeCollectionAsync.java +++ b/src/main/java/com/arangodb/async/ArangoEdgeCollectionAsync.java @@ -25,6 +25,7 @@ import com.arangodb.entity.EdgeUpdateEntity; import com.arangodb.model.*; +import javax.annotation.concurrent.ThreadSafe; import java.util.concurrent.CompletableFuture; /** @@ -33,6 +34,7 @@ * @author Mark Vollmary * @see API Documentation */ +@ThreadSafe public interface ArangoEdgeCollectionAsync extends ArangoSerdeAccessor { /** diff --git a/src/main/java/com/arangodb/async/ArangoGraphAsync.java b/src/main/java/com/arangodb/async/ArangoGraphAsync.java index 289741d79..ebf014c38 100644 --- a/src/main/java/com/arangodb/async/ArangoGraphAsync.java +++ b/src/main/java/com/arangodb/async/ArangoGraphAsync.java @@ -26,6 +26,7 @@ import com.arangodb.model.GraphCreateOptions; import com.arangodb.model.VertexCollectionCreateOptions; +import javax.annotation.concurrent.ThreadSafe; import java.util.Collection; import java.util.concurrent.CompletableFuture; @@ -35,6 +36,7 @@ * @author Mark Vollmary * @see API Documentation */ +@ThreadSafe public interface ArangoGraphAsync extends ArangoSerdeAccessor { /** diff --git a/src/main/java/com/arangodb/async/ArangoSearchAsync.java b/src/main/java/com/arangodb/async/ArangoSearchAsync.java index 1c4d2babc..88ae53ba8 100644 --- a/src/main/java/com/arangodb/async/ArangoSearchAsync.java +++ b/src/main/java/com/arangodb/async/ArangoSearchAsync.java @@ -25,6 +25,7 @@ import com.arangodb.model.arangosearch.ArangoSearchCreateOptions; import com.arangodb.model.arangosearch.ArangoSearchPropertiesOptions; +import javax.annotation.concurrent.ThreadSafe; import java.util.concurrent.CompletableFuture; /** @@ -34,6 +35,7 @@ * @see View API Documentation * @since ArangoDB 3.4.0 */ +@ThreadSafe public interface ArangoSearchAsync extends ArangoViewAsync { /** diff --git a/src/main/java/com/arangodb/async/ArangoVertexCollectionAsync.java b/src/main/java/com/arangodb/async/ArangoVertexCollectionAsync.java index c26be8f55..986aa011e 100644 --- a/src/main/java/com/arangodb/async/ArangoVertexCollectionAsync.java +++ b/src/main/java/com/arangodb/async/ArangoVertexCollectionAsync.java @@ -25,6 +25,7 @@ import com.arangodb.entity.VertexUpdateEntity; import com.arangodb.model.*; +import javax.annotation.concurrent.ThreadSafe; import java.util.concurrent.CompletableFuture; /** @@ -33,6 +34,7 @@ * @author Mark Vollmary * @see API Documentation */ +@ThreadSafe public interface ArangoVertexCollectionAsync extends ArangoSerdeAccessor { /** diff --git a/src/main/java/com/arangodb/async/ArangoViewAsync.java b/src/main/java/com/arangodb/async/ArangoViewAsync.java index 433c536ef..68fa883dc 100644 --- a/src/main/java/com/arangodb/async/ArangoViewAsync.java +++ b/src/main/java/com/arangodb/async/ArangoViewAsync.java @@ -23,6 +23,7 @@ import com.arangodb.ArangoSerdeAccessor; import com.arangodb.entity.ViewEntity; +import javax.annotation.concurrent.ThreadSafe; import java.util.concurrent.CompletableFuture; /** @@ -32,6 +33,7 @@ * @see View API Documentation * @since ArangoDB 3.4.0 */ +@ThreadSafe public interface ArangoViewAsync extends ArangoSerdeAccessor { /** From 5e0ca56eee6a6ea6cc4a90ba2c8ec28c9d7c4bf2 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Thu, 18 Aug 2022 09:35:20 +0200 Subject: [PATCH 105/254] CI fixes (cherry picked from commit be7693eb9e49fb9e0552f13ef02ad845d127280b) --- .github/workflows/maven.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index 814bcb98a..4bf13aebd 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -5,6 +5,7 @@ on: branches: - master - v7 + - v6 pull_request: types: [ opened, synchronize, reopened ] branches: From f8427966ad4a59fbf1cd168ac76371a0f4ae33e2 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Fri, 19 Aug 2022 08:59:50 +0200 Subject: [PATCH 106/254] CI: disabled shallow clone in sonar analysis job --- .github/workflows/maven.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index 4bf13aebd..695c470ca 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -193,6 +193,8 @@ jobs: steps: - uses: actions/checkout@v2 + with: + fetch-depth: 0 - name: Set up JDK uses: actions/setup-java@v2 with: From af8c56ad6ece1c66511ca067e9029038adc3e078 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Fri, 19 Aug 2022 09:06:36 +0200 Subject: [PATCH 107/254] CI updates --- .github/workflows/codeql.yml | 1 - .github/workflows/maven.yml | 1 - 2 files changed, 2 deletions(-) diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 0f6cdd774..862522072 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -15,7 +15,6 @@ on: push: branches: - master - - v7 pull_request: types: [ opened, synchronize, reopened ] branches: diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index 695c470ca..57a339d01 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -4,7 +4,6 @@ on: push: branches: - master - - v7 - v6 pull_request: types: [ opened, synchronize, reopened ] From e75c767315c1cc1178f2f474713813cd485d3825 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Fri, 19 Aug 2022 10:25:09 +0200 Subject: [PATCH 108/254] Revert "optional mvn deps" This reverts commit 8eba3cea --- pom.xml | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/pom.xml b/pom.xml index e8988cd00..db102d8d0 100644 --- a/pom.xml +++ b/pom.xml @@ -312,35 +312,31 @@ slf4j-api - jakarta.json.bind - jakarta.json.bind-api - 2.0.0 + org.apache.httpcomponents + httpclient com.fasterxml.jackson.core jackson-databind - provided com.fasterxml.jackson.core jackson-core - provided com.fasterxml.jackson.core jackson-annotations - provided - - - org.apache.httpcomponents - httpclient - true com.arangodb jackson-dataformat-velocypack true + + jakarta.json.bind + jakarta.json.bind-api + 2.0.0 + com.google.code.findbugs jsr305 From 2ca213e03890b73b0013dcaf5880105f5122221d Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Fri, 19 Aug 2022 10:42:21 +0200 Subject: [PATCH 109/254] native image fixes --- .../arangodb-java-driver/reflect-config.json | 528 +++++++++++++----- src/test/java/helper/NativeImageHelper.java | 11 +- .../META-INF/native-image/reflect-config.json | 68 ++- 3 files changed, 464 insertions(+), 143 deletions(-) diff --git a/src/main/resources/META-INF/native-image/com.arangodb/arangodb-java-driver/reflect-config.json b/src/main/resources/META-INF/native-image/com.arangodb/arangodb-java-driver/reflect-config.json index 09cda49c3..3ef3eb162 100644 --- a/src/main/resources/META-INF/native-image/com.arangodb/arangodb-java-driver/reflect-config.json +++ b/src/main/resources/META-INF/native-image/com.arangodb/arangodb-java-driver/reflect-config.json @@ -1,276 +1,300 @@ [ { - "name": "com.arangodb.serde.InternalSerializers$CollectionSchemaRuleSerializer", + "name": "com.arangodb.internal.serde.InternalSerializers$FieldLinksSerializer", "allDeclaredFields": true, "allDeclaredMethods": true, "allDeclaredConstructors": true }, { - "name": "com.arangodb.serde.InternalSerializers$FieldLinksSerializer", + "name": "com.arangodb.internal.serde.InternalSerializers$CollectionLinksSerializer", "allDeclaredFields": true, "allDeclaredMethods": true, "allDeclaredConstructors": true }, { - "name": "com.arangodb.serde.InternalSerializers$CollectionLinksSerializer", + "name": "com.arangodb.internal.serde.InternalSerializers$CollectionSchemaRuleSerializer", "allDeclaredFields": true, "allDeclaredMethods": true, "allDeclaredConstructors": true }, { - "name": "com.arangodb.serde.InternalDeserializers$CollectionLinksDeserializer", + "name": "com.arangodb.internal.serde.InternalDeserializers$CollectionLinksDeserializer", "allDeclaredFields": true, "allDeclaredMethods": true, "allDeclaredConstructors": true }, { - "name": "com.arangodb.serde.InternalDeserializers$FieldLinksDeserializer", + "name": "com.arangodb.internal.serde.InternalDeserializers$CollectionSchemaRuleDeserializer", "allDeclaredFields": true, "allDeclaredMethods": true, "allDeclaredConstructors": true }, { - "name": "com.arangodb.serde.InternalDeserializers$CollectionSchemaRuleDeserializer", + "name": "com.arangodb.internal.serde.InternalDeserializers$FieldLinksDeserializer", "allDeclaredFields": true, "allDeclaredMethods": true, "allDeclaredConstructors": true }, { - "name": "com.arangodb.entity.DocumentCreateEntity", + "name": "com.arangodb.entity.ViewEntity", "allDeclaredFields": true, "allDeclaredMethods": true, "allDeclaredConstructors": true }, { - "name": "com.arangodb.entity.ReplicationFactor$SatelliteReplicationFactor", + "name": "com.arangodb.entity.BaseDocument", "allDeclaredFields": true, "allDeclaredMethods": true, "allDeclaredConstructors": true }, { - "name": "com.arangodb.entity.arangosearch.analyzer.GeoPointAnalyzerProperties", + "name": "java.lang.Enum", "allDeclaredFields": true, "allDeclaredMethods": true, "allDeclaredConstructors": true }, { - "name": "com.arangodb.entity.arangosearch.analyzer.GeoJSONAnalyzerProperties", + "name": "java.lang.annotation.Annotation", "allDeclaredFields": true, "allDeclaredMethods": true, "allDeclaredConstructors": true }, { - "name": "com.arangodb.entity.Rev", + "name": "java.lang.Comparable", "allDeclaredFields": true, "allDeclaredMethods": true, "allDeclaredConstructors": true }, { - "name": "com.arangodb.entity.MetaAware", + "name": "com.arangodb.entity.CollectionEntity", "allDeclaredFields": true, "allDeclaredMethods": true, "allDeclaredConstructors": true }, { - "name": "com.arangodb.entity.IndexEntity", + "name": "java.lang.Object", "allDeclaredFields": true, "allDeclaredMethods": true, "allDeclaredConstructors": true }, { - "name": "com.arangodb.entity.VertexEntity", + "name": "com.arangodb.entity.ReplicationFactor", "allDeclaredFields": true, "allDeclaredMethods": true, "allDeclaredConstructors": true }, { - "name": "com.arangodb.entity.AqlExecutionExplainEntity", + "name": "com.arangodb.entity.DocumentEntity", "allDeclaredFields": true, "allDeclaredMethods": true, "allDeclaredConstructors": true }, { - "name": "com.arangodb.entity.AqlParseEntity", + "name": "com.arangodb.entity.arangosearch.analyzer.SearchAnalyzer", "allDeclaredFields": true, "allDeclaredMethods": true, "allDeclaredConstructors": true }, { - "name": "com.arangodb.entity.EdgeDefinition", + "name": "java.io.Serializable", "allDeclaredFields": true, "allDeclaredMethods": true, "allDeclaredConstructors": true }, { - "name": "com.arangodb.entity.CollectionEntity", + "name": "com.arangodb.entity.arangosearch.ArangoSearchPropertiesEntity", "allDeclaredFields": true, "allDeclaredMethods": true, "allDeclaredConstructors": true }, { - "name": "com.arangodb.entity.MultiDocumentEntity", + "name": "com.arangodb.entity.BaseEdgeDocument", "allDeclaredFields": true, "allDeclaredMethods": true, "allDeclaredConstructors": true }, { - "name": "com.arangodb.entity.arangosearch.analyzer.StopwordsAnalyzerProperties", + "name": "com.arangodb.entity.ServerRole", "allDeclaredFields": true, "allDeclaredMethods": true, "allDeclaredConstructors": true }, { - "name": "com.arangodb.entity.AqlExecutionExplainEntity$ExecutionVariable", + "name": "com.arangodb.entity.ReplicationFactor$SatelliteReplicationFactor", "allDeclaredFields": true, "allDeclaredMethods": true, "allDeclaredConstructors": true }, { - "name": "com.arangodb.entity.arangosearch.analyzer.StopwordsAnalyzer", + "name": "com.arangodb.entity.arangosearch.analyzer.SegmentationAnalyzerProperties$BreakMode", "allDeclaredFields": true, "allDeclaredMethods": true, "allDeclaredConstructors": true }, { - "name": "com.arangodb.entity.CollectionPropertiesEntity", + "name": "com.arangodb.entity.arangosearch.AnalyzerFeature", "allDeclaredFields": true, "allDeclaredMethods": true, "allDeclaredConstructors": true }, { - "name": "com.arangodb.entity.EdgeUpdateEntity", + "name": "com.arangodb.entity.ArangoDBEngine$StorageEngineName", "allDeclaredFields": true, "allDeclaredMethods": true, "allDeclaredConstructors": true }, { - "name": "com.arangodb.entity.QueryCachePropertiesEntity", + "name": "com.arangodb.entity.StreamTransactionStatus", "allDeclaredFields": true, "allDeclaredMethods": true, "allDeclaredConstructors": true }, { - "name": "com.arangodb.entity.DocumentUpdateEntity", + "name": "com.arangodb.entity.QueryExecutionState", "allDeclaredFields": true, "allDeclaredMethods": true, "allDeclaredConstructors": true }, { - "name": "com.arangodb.entity.CursorStats", + "name": "com.arangodb.entity.LogLevel", "allDeclaredFields": true, "allDeclaredMethods": true, "allDeclaredConstructors": true }, { - "name": "com.arangodb.entity.arangosearch.analyzer.AQLAnalyzer", + "name": "com.arangodb.entity.QueryCachePropertiesEntity$CacheMode", "allDeclaredFields": true, "allDeclaredMethods": true, "allDeclaredConstructors": true }, { - "name": "com.arangodb.entity.GraphEntity", + "name": "com.arangodb.entity.LogLevelEntity$LogLevel", "allDeclaredFields": true, "allDeclaredMethods": true, "allDeclaredConstructors": true }, { - "name": "com.arangodb.entity.arangosearch.analyzer.GeoJSONAnalyzer", + "name": "com.arangodb.entity.arangosearch.StoreValuesType", "allDeclaredFields": true, "allDeclaredMethods": true, "allDeclaredConstructors": true }, { - "name": "com.arangodb.entity.AqlFunctionEntity", + "name": "com.arangodb.entity.LoadBalancingStrategy", "allDeclaredFields": true, "allDeclaredMethods": true, "allDeclaredConstructors": true }, { - "name": "com.arangodb.entity.arangosearch.PrimarySort", + "name": "com.arangodb.entity.IndexType", "allDeclaredFields": true, "allDeclaredMethods": true, "allDeclaredConstructors": true }, { - "name": "com.arangodb.entity.DatabaseEntity", + "name": "com.arangodb.entity.arangosearch.ArangoSearchCompression", "allDeclaredFields": true, "allDeclaredMethods": true, "allDeclaredConstructors": true }, { - "name": "com.arangodb.entity.EdgeEntity", + "name": "com.arangodb.entity.License", "allDeclaredFields": true, "allDeclaredMethods": true, "allDeclaredConstructors": true }, { - "name": "com.arangodb.entity.ViewEntity", + "name": "com.arangodb.entity.CollectionStatus", "allDeclaredFields": true, "allDeclaredMethods": true, "allDeclaredConstructors": true }, { - "name": "com.arangodb.entity.arangosearch.analyzer.EdgeNgram", + "name": "com.arangodb.entity.arangosearch.analyzer.SearchAnalyzerCase", "allDeclaredFields": true, "allDeclaredMethods": true, "allDeclaredConstructors": true }, { - "name": "com.arangodb.entity.AqlExecutionExplainEntity$ExecutionNode", + "name": "com.arangodb.entity.arangosearch.analyzer.AQLAnalyzerProperties$ReturnType", "allDeclaredFields": true, "allDeclaredMethods": true, "allDeclaredConstructors": true }, { - "name": "com.arangodb.entity.BaseDocument", + "name": "com.arangodb.entity.arangosearch.analyzer.StreamType", "allDeclaredFields": true, "allDeclaredMethods": true, "allDeclaredConstructors": true }, { - "name": "com.arangodb.entity.TransactionEntity", + "name": "com.arangodb.entity.CollectionType", "allDeclaredFields": true, "allDeclaredMethods": true, "allDeclaredConstructors": true }, { - "name": "com.arangodb.entity.ArangoDBEngine", + "name": "com.arangodb.entity.KeyType", "allDeclaredFields": true, "allDeclaredMethods": true, "allDeclaredConstructors": true }, { - "name": "com.arangodb.entity.UserEntity", + "name": "com.arangodb.entity.ViewType", "allDeclaredFields": true, "allDeclaredMethods": true, "allDeclaredConstructors": true }, { - "name": "com.arangodb.entity.ErrorEntity", + "name": "com.arangodb.entity.ServerMode", "allDeclaredFields": true, "allDeclaredMethods": true, "allDeclaredConstructors": true }, { - "name": "com.arangodb.entity.arangosearch.analyzer.DelimiterAnalyzerProperties", + "name": "com.arangodb.entity.arangosearch.AnalyzerType", "allDeclaredFields": true, "allDeclaredMethods": true, "allDeclaredConstructors": true }, { - "name": "com.arangodb.entity.AqlExecutionExplainEntity$ExecutionStats", + "name": "com.arangodb.entity.arangosearch.analyzer.GeoJSONAnalyzerProperties$GeoJSONAnalyzerType", "allDeclaredFields": true, "allDeclaredMethods": true, "allDeclaredConstructors": true }, { - "name": "com.arangodb.entity.arangosearch.analyzer.NormAnalyzer", + "name": "com.arangodb.entity.ShardingStrategy", "allDeclaredFields": true, "allDeclaredMethods": true, "allDeclaredConstructors": true }, { - "name": "com.arangodb.entity.arangosearch.FieldLink", + "name": "com.arangodb.entity.arangosearch.ConsolidationType", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.Permissions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.Key", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.Rev", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.Id", "allDeclaredFields": true, "allDeclaredMethods": true, "allDeclaredConstructors": true @@ -282,7 +306,163 @@ "allDeclaredConstructors": true }, { - "name": "com.arangodb.entity.arangosearch.analyzer.GeoAnalyzerOptions", + "name": "com.arangodb.entity.From", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.CollectionRevisionEntity", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.CollectionPropertiesEntity", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.analyzer.GeoJSONAnalyzerProperties", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.analyzer.GeoPointAnalyzerProperties", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.MetaAware", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.IndexEntity", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.AqlExecutionExplainEntity", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.AqlParseEntity", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.EdgeDefinition", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.MultiDocumentEntity", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.analyzer.StopwordsAnalyzerProperties", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.AqlExecutionExplainEntity$ExecutionVariable", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.QueryCachePropertiesEntity", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.GraphEntity", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.AqlFunctionEntity", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.DatabaseEntity", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.PrimarySort", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.analyzer.EdgeNgram", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.AqlExecutionExplainEntity$ExecutionNode", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.TransactionEntity", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.ArangoDBEngine", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.UserEntity", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.ErrorEntity", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.AqlExecutionExplainEntity$ExecutionStats", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.analyzer.DelimiterAnalyzerProperties", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.FieldLink", "allDeclaredFields": true, "allDeclaredMethods": true, "allDeclaredConstructors": true @@ -294,7 +474,7 @@ "allDeclaredConstructors": true }, { - "name": "com.arangodb.entity.arangosearch.analyzer.NGramAnalyzer", + "name": "com.arangodb.entity.arangosearch.analyzer.GeoAnalyzerOptions", "allDeclaredFields": true, "allDeclaredMethods": true, "allDeclaredConstructors": true @@ -324,253 +504,259 @@ "allDeclaredConstructors": true }, { - "name": "com.arangodb.entity.Key", + "name": "com.arangodb.entity.arangosearch.analyzer.TextAnalyzerProperties", "allDeclaredFields": true, "allDeclaredMethods": true, "allDeclaredConstructors": true }, { - "name": "com.arangodb.entity.arangosearch.analyzer.TextAnalyzerProperties", + "name": "com.arangodb.entity.EdgeDefinition$Options", "allDeclaredFields": true, "allDeclaredMethods": true, "allDeclaredConstructors": true }, { - "name": "com.arangodb.entity.arangosearch.analyzer.SegmentationAnalyzer", + "name": "com.arangodb.entity.ArangoDBVersion", "allDeclaredFields": true, "allDeclaredMethods": true, "allDeclaredConstructors": true }, { - "name": "com.arangodb.entity.DocumentDeleteEntity", + "name": "com.arangodb.entity.arangosearch.analyzer.SegmentationAnalyzerProperties", "allDeclaredFields": true, "allDeclaredMethods": true, "allDeclaredConstructors": true }, { - "name": "com.arangodb.entity.EdgeDefinition$Options", + "name": "com.arangodb.entity.arangosearch.analyzer.AQLAnalyzerProperties", "allDeclaredFields": true, "allDeclaredMethods": true, "allDeclaredConstructors": true }, { - "name": "com.arangodb.entity.ArangoDBVersion", + "name": "com.arangodb.entity.arangosearch.ConsolidationPolicy", "allDeclaredFields": true, "allDeclaredMethods": true, "allDeclaredConstructors": true }, { - "name": "com.arangodb.entity.arangosearch.analyzer.AQLAnalyzerProperties", + "name": "com.arangodb.entity.arangosearch.analyzer.NormAnalyzerProperties", "allDeclaredFields": true, "allDeclaredMethods": true, "allDeclaredConstructors": true }, { - "name": "com.arangodb.entity.arangosearch.analyzer.SegmentationAnalyzerProperties", + "name": "com.arangodb.entity.KeyOptions", "allDeclaredFields": true, "allDeclaredMethods": true, "allDeclaredConstructors": true }, { - "name": "com.arangodb.entity.BaseEdgeDocument", + "name": "com.arangodb.entity.AqlExecutionExplainEntity$ExecutionPlan", "allDeclaredFields": true, "allDeclaredMethods": true, "allDeclaredConstructors": true }, { - "name": "com.arangodb.entity.arangosearch.ConsolidationPolicy", + "name": "com.arangodb.entity.LogLevelEntity", "allDeclaredFields": true, "allDeclaredMethods": true, "allDeclaredConstructors": true }, { - "name": "com.arangodb.entity.VertexUpdateEntity", + "name": "com.arangodb.entity.arangosearch.analyzer.NGramAnalyzerProperties", "allDeclaredFields": true, "allDeclaredMethods": true, "allDeclaredConstructors": true }, { - "name": "com.arangodb.entity.arangosearch.analyzer.NormAnalyzerProperties", + "name": "com.arangodb.entity.CursorWarning", "allDeclaredFields": true, "allDeclaredMethods": true, "allDeclaredConstructors": true }, { - "name": "com.arangodb.entity.KeyOptions", + "name": "com.arangodb.entity.arangosearch.analyzer.StemAnalyzerProperties", "allDeclaredFields": true, "allDeclaredMethods": true, "allDeclaredConstructors": true }, { - "name": "com.arangodb.entity.AqlExecutionExplainEntity$ExecutionPlan", + "name": "com.arangodb.entity.StreamTransactionEntity", "allDeclaredFields": true, "allDeclaredMethods": true, "allDeclaredConstructors": true }, { - "name": "com.arangodb.entity.LogLevelEntity", + "name": "com.arangodb.entity.LogEntriesEntity", "allDeclaredFields": true, "allDeclaredMethods": true, "allDeclaredConstructors": true }, { - "name": "com.arangodb.entity.ReplicationFactor", + "name": "com.arangodb.entity.QueryEntity", "allDeclaredFields": true, "allDeclaredMethods": true, "allDeclaredConstructors": true }, { - "name": "com.arangodb.entity.Id", + "name": "com.arangodb.entity.arangosearch.CollectionLink", "allDeclaredFields": true, "allDeclaredMethods": true, "allDeclaredConstructors": true }, { - "name": "com.arangodb.entity.arangosearch.analyzer.DelimiterAnalyzer", + "name": "com.arangodb.entity.arangosearch.StoredValue", "allDeclaredFields": true, "allDeclaredMethods": true, "allDeclaredConstructors": true }, { - "name": "com.arangodb.entity.DocumentEntity", + "name": "com.arangodb.entity.DocumentImportEntity", "allDeclaredFields": true, "allDeclaredMethods": true, "allDeclaredConstructors": true }, { - "name": "com.arangodb.entity.arangosearch.analyzer.NGramAnalyzerProperties", + "name": "com.arangodb.entity.arangosearch.analyzer.CollationAnalyzerProperties", "allDeclaredFields": true, "allDeclaredMethods": true, "allDeclaredConstructors": true }, { - "name": "com.arangodb.entity.CursorWarning", + "name": "com.arangodb.entity.QueryTrackingPropertiesEntity", "allDeclaredFields": true, "allDeclaredMethods": true, "allDeclaredConstructors": true }, { - "name": "com.arangodb.entity.arangosearch.analyzer.StemAnalyzerProperties", + "name": "com.arangodb.entity.LogEntriesEntity$Message", "allDeclaredFields": true, "allDeclaredMethods": true, "allDeclaredConstructors": true }, { - "name": "com.arangodb.entity.arangosearch.analyzer.IdentityAnalyzer", + "name": "com.arangodb.entity.AqlExecutionExplainEntity$ExecutionExpression", "allDeclaredFields": true, "allDeclaredMethods": true, "allDeclaredConstructors": true }, { - "name": "com.arangodb.entity.StreamTransactionEntity", + "name": "com.arangodb.entity.EdgeUpdateEntity", "allDeclaredFields": true, "allDeclaredMethods": true, "allDeclaredConstructors": true }, { - "name": "com.arangodb.entity.LogEntriesEntity", + "name": "com.arangodb.entity.DocumentCreateEntity", "allDeclaredFields": true, "allDeclaredMethods": true, "allDeclaredConstructors": true }, { - "name": "com.arangodb.entity.arangosearch.analyzer.GeoPointAnalyzer", + "name": "com.arangodb.entity.VertexUpdateEntity", "allDeclaredFields": true, "allDeclaredMethods": true, "allDeclaredConstructors": true }, { - "name": "com.arangodb.entity.QueryEntity", + "name": "com.arangodb.entity.DocumentDeleteEntity", "allDeclaredFields": true, "allDeclaredMethods": true, "allDeclaredConstructors": true }, { - "name": "com.arangodb.entity.arangosearch.CollectionLink", + "name": "com.arangodb.entity.VertexEntity", "allDeclaredFields": true, "allDeclaredMethods": true, "allDeclaredConstructors": true }, { - "name": "com.arangodb.entity.arangosearch.StoredValue", + "name": "com.arangodb.entity.DocumentUpdateEntity", "allDeclaredFields": true, "allDeclaredMethods": true, "allDeclaredConstructors": true }, { - "name": "com.arangodb.entity.DocumentImportEntity", + "name": "com.arangodb.entity.EdgeEntity", "allDeclaredFields": true, "allDeclaredMethods": true, "allDeclaredConstructors": true }, { - "name": "com.arangodb.entity.arangosearch.analyzer.PipelineAnalyzer", + "name": "com.arangodb.entity.arangosearch.analyzer.SegmentationAnalyzer", "allDeclaredFields": true, "allDeclaredMethods": true, "allDeclaredConstructors": true }, { - "name": "com.arangodb.entity.arangosearch.analyzer.CollationAnalyzerProperties", + "name": "com.arangodb.entity.arangosearch.analyzer.IdentityAnalyzer", "allDeclaredFields": true, "allDeclaredMethods": true, "allDeclaredConstructors": true }, { - "name": "com.arangodb.entity.arangosearch.analyzer.StemAnalyzer", + "name": "com.arangodb.entity.arangosearch.analyzer.GeoPointAnalyzer", "allDeclaredFields": true, "allDeclaredMethods": true, "allDeclaredConstructors": true }, { - "name": "com.arangodb.entity.QueryTrackingPropertiesEntity", + "name": "com.arangodb.entity.arangosearch.analyzer.AQLAnalyzer", "allDeclaredFields": true, "allDeclaredMethods": true, "allDeclaredConstructors": true }, { - "name": "com.arangodb.entity.CollectionRevisionEntity", + "name": "com.arangodb.entity.arangosearch.analyzer.GeoJSONAnalyzer", "allDeclaredFields": true, "allDeclaredMethods": true, "allDeclaredConstructors": true }, { - "name": "com.arangodb.entity.LogEntriesEntity$Message", + "name": "com.arangodb.entity.arangosearch.analyzer.PipelineAnalyzer", "allDeclaredFields": true, "allDeclaredMethods": true, "allDeclaredConstructors": true }, { - "name": "com.arangodb.entity.arangosearch.ArangoSearchPropertiesEntity", + "name": "com.arangodb.entity.arangosearch.analyzer.StemAnalyzer", "allDeclaredFields": true, "allDeclaredMethods": true, "allDeclaredConstructors": true }, { - "name": "com.arangodb.entity.arangosearch.analyzer.CollationAnalyzer", + "name": "com.arangodb.entity.arangosearch.analyzer.NormAnalyzer", "allDeclaredFields": true, "allDeclaredMethods": true, "allDeclaredConstructors": true }, { - "name": "com.arangodb.entity.arangosearch.analyzer.TextAnalyzer", + "name": "com.arangodb.entity.arangosearch.analyzer.DelimiterAnalyzer", "allDeclaredFields": true, "allDeclaredMethods": true, "allDeclaredConstructors": true }, { - "name": "com.arangodb.entity.arangosearch.analyzer.SearchAnalyzer", + "name": "com.arangodb.entity.arangosearch.analyzer.CollationAnalyzer", "allDeclaredFields": true, "allDeclaredMethods": true, "allDeclaredConstructors": true }, { - "name": "com.arangodb.entity.From", + "name": "com.arangodb.entity.arangosearch.analyzer.TextAnalyzer", "allDeclaredFields": true, "allDeclaredMethods": true, "allDeclaredConstructors": true }, { - "name": "com.arangodb.entity.AqlExecutionExplainEntity$ExecutionExpression", + "name": "com.arangodb.entity.arangosearch.analyzer.NGramAnalyzer", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.analyzer.StopwordsAnalyzer", "allDeclaredFields": true, "allDeclaredMethods": true, "allDeclaredConstructors": true @@ -582,19 +768,19 @@ "allDeclaredConstructors": true }, { - "name": "com.arangodb.entity.arangosearch.analyzer.SegmentationAnalyzerProperties$BreakMode", + "name": "com.arangodb.entity.ReplicationFactor$SatelliteReplicationFactor", "allDeclaredFields": true, "allDeclaredMethods": true, "allDeclaredConstructors": true }, { - "name": "com.arangodb.entity.arangosearch.AnalyzerFeature", + "name": "com.arangodb.entity.arangosearch.analyzer.SegmentationAnalyzerProperties$BreakMode", "allDeclaredFields": true, "allDeclaredMethods": true, "allDeclaredConstructors": true }, { - "name": "com.arangodb.entity.ReplicationFactor$SatelliteReplicationFactor", + "name": "com.arangodb.entity.arangosearch.AnalyzerFeature", "allDeclaredFields": true, "allDeclaredMethods": true, "allDeclaredConstructors": true @@ -678,13 +864,13 @@ "allDeclaredConstructors": true }, { - "name": "com.arangodb.entity.arangosearch.analyzer.StreamType", + "name": "com.arangodb.entity.arangosearch.analyzer.AQLAnalyzerProperties$ReturnType", "allDeclaredFields": true, "allDeclaredMethods": true, "allDeclaredConstructors": true }, { - "name": "com.arangodb.entity.arangosearch.analyzer.AQLAnalyzerProperties$ReturnType", + "name": "com.arangodb.entity.arangosearch.analyzer.StreamType", "allDeclaredFields": true, "allDeclaredMethods": true, "allDeclaredConstructors": true @@ -744,13 +930,67 @@ "allDeclaredConstructors": true }, { - "name": "com.arangodb.model.GeoIndexOptions", + "name": "java.lang.Enum", "allDeclaredFields": true, "allDeclaredMethods": true, "allDeclaredConstructors": true }, { - "name": "com.arangodb.model.TtlIndexOptions", + "name": "java.lang.Comparable", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "java.lang.Object", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.IndexOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "java.io.Serializable", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.DocumentImportOptions$OnDuplicate", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.OverwriteMode", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.ImportType", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.LogOptions$SortOrder", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.CollectionSchema$Level", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.ZKDIndexOptions$FieldValueTypes", "allDeclaredFields": true, "allDeclaredMethods": true, "allDeclaredConstructors": true @@ -797,12 +1037,6 @@ "allDeclaredMethods": true, "allDeclaredConstructors": true }, - { - "name": "com.arangodb.model.FulltextIndexOptions", - "allDeclaredFields": true, - "allDeclaredMethods": true, - "allDeclaredConstructors": true - }, { "name": "com.arangodb.model.UserUpdateOptions", "allDeclaredFields": true, @@ -875,12 +1109,6 @@ "allDeclaredMethods": true, "allDeclaredConstructors": true }, - { - "name": "com.arangodb.model.HashIndexOptions", - "allDeclaredFields": true, - "allDeclaredMethods": true, - "allDeclaredConstructors": true - }, { "name": "com.arangodb.model.arangosearch.ArangoSearchPropertiesOptions", "allDeclaredFields": true, @@ -941,24 +1169,6 @@ "allDeclaredMethods": true, "allDeclaredConstructors": true }, - { - "name": "com.arangodb.model.PersistentIndexOptions", - "allDeclaredFields": true, - "allDeclaredMethods": true, - "allDeclaredConstructors": true - }, - { - "name": "com.arangodb.model.SkiplistIndexOptions", - "allDeclaredFields": true, - "allDeclaredMethods": true, - "allDeclaredConstructors": true - }, - { - "name": "com.arangodb.model.ZKDIndexOptions", - "allDeclaredFields": true, - "allDeclaredMethods": true, - "allDeclaredConstructors": true - }, { "name": "com.arangodb.model.CollectionSchema", "allDeclaredFields": true, @@ -996,13 +1206,13 @@ "allDeclaredConstructors": true }, { - "name": "com.arangodb.model.DocumentUpdateOptions", + "name": "com.arangodb.model.GraphDocumentReadOptions", "allDeclaredFields": true, "allDeclaredMethods": true, "allDeclaredConstructors": true }, { - "name": "com.arangodb.model.GraphDocumentReadOptions", + "name": "com.arangodb.model.DocumentUpdateOptions", "allDeclaredFields": true, "allDeclaredMethods": true, "allDeclaredConstructors": true @@ -1073,12 +1283,6 @@ "allDeclaredMethods": true, "allDeclaredConstructors": true }, - { - "name": "com.arangodb.model.IndexOptions", - "allDeclaredFields": true, - "allDeclaredMethods": true, - "allDeclaredConstructors": true - }, { "name": "com.arangodb.model.CollectionRenameOptions", "allDeclaredFields": true, @@ -1121,6 +1325,48 @@ "allDeclaredMethods": true, "allDeclaredConstructors": true }, + { + "name": "com.arangodb.model.SkiplistIndexOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.GeoIndexOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.TtlIndexOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.FulltextIndexOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.HashIndexOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.ZKDIndexOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.PersistentIndexOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, { "name": "com.arangodb.model.DocumentImportOptions$OnDuplicate", "allDeclaredFields": true, @@ -1157,6 +1403,18 @@ "allDeclaredMethods": true, "allDeclaredConstructors": true }, + { + "name": "java.lang.Object", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.MetaAware", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, { "name": "com.arangodb.internal.cursor.entity.InternalCursorEntity", "allDeclaredFields": true, diff --git a/src/test/java/helper/NativeImageHelper.java b/src/test/java/helper/NativeImageHelper.java index 5ec356589..638410dab 100644 --- a/src/test/java/helper/NativeImageHelper.java +++ b/src/test/java/helper/NativeImageHelper.java @@ -12,7 +12,10 @@ import org.reflections.util.ConfigurationBuilder; import org.reflections.util.FilterBuilder; +import java.net.URL; import java.util.Arrays; +import java.util.Collection; +import java.util.HashSet; import java.util.List; import java.util.stream.Stream; @@ -41,10 +44,14 @@ private static void generateReflectConfig() throws JsonProcessingException { ArrayNode rootNode = mapper.createArrayNode(); String serdePackage = "com.arangodb.serde"; + String internalSerdePackage = "com.arangodb.internal.serde"; + Collection serdeUrls = new HashSet<>(); + serdeUrls.addAll(ClasspathHelper.forPackage(serdePackage)); + serdeUrls.addAll(ClasspathHelper.forPackage(internalSerdePackage)); Reflections r = new Reflections(new ConfigurationBuilder() .setScanners(new SubTypesScanner(false)) - .setUrls(ClasspathHelper.forPackage(serdePackage)) - .filterInputsBy(new FilterBuilder().includePackage(serdePackage))); + .setUrls(serdeUrls) + .filterInputsBy(new FilterBuilder().includePackage(serdePackage).includePackage(internalSerdePackage))); Stream serializers = r.getSubTypesOf(JsonSerializer.class).stream() .filter(it -> !it.isAnonymousClass()) .map(Class::getName); diff --git a/src/test/resources/META-INF/native-image/reflect-config.json b/src/test/resources/META-INF/native-image/reflect-config.json index a71ddaf2c..de22561a7 100644 --- a/src/test/resources/META-INF/native-image/reflect-config.json +++ b/src/test/resources/META-INF/native-image/reflect-config.json @@ -84,15 +84,19 @@ }, { "name": "com.arangodb.ArangoCollectionTest$TestUpdateEntity", - "allDeclaredFields": true, - "allDeclaredMethods": true, - "allDeclaredConstructors": true + "allDeclaredFields":true, + "allDeclaredMethods":true, + "allPublicMethods":true, + "allDeclaredConstructors":true, + "allDeclaredClasses":true }, { "name": "com.arangodb.ArangoCollectionTest$TestUpdateEntitySerializeNullFalse", - "allDeclaredFields": true, - "allDeclaredMethods": true, - "allDeclaredConstructors": true + "allDeclaredFields":true, + "allDeclaredMethods":true, + "allPublicMethods":true, + "allDeclaredConstructors":true, + "allDeclaredClasses":true }, { "name": "com.arangodb.ArangoDatabaseTest$TransactionTestEntity", @@ -295,5 +299,57 @@ "parameterTypes": [] } ] + }, + { + "name":"com.arangodb.async.ArangoCollectionTest$Animal", + "allDeclaredMethods":true, + "allPublicMethods":true, + "allDeclaredClasses":true + }, + { + "name":"com.arangodb.async.ArangoCollectionTest$Cat", + "allDeclaredFields":true, + "allDeclaredMethods":true, + "allPublicMethods":true, + "allDeclaredConstructors":true, + "allDeclaredClasses":true + }, + { + "name":"com.arangodb.async.ArangoCollectionTest$Dog", + "allDeclaredFields":true, + "allDeclaredMethods":true, + "allPublicMethods":true, + "allDeclaredConstructors":true, + "allDeclaredClasses":true + }, + { + "name":"com.arangodb.ArangoCollectionTest$Animal", + "allDeclaredMethods":true, + "allPublicMethods":true, + "allDeclaredClasses":true + }, + { + "name":"com.arangodb.ArangoCollectionTest$AnnotatedEntity", + "allDeclaredFields":true, + "allDeclaredMethods":true, + "allPublicMethods":true, + "allDeclaredConstructors":true, + "allDeclaredClasses":true + }, + { + "name":"com.arangodb.ArangoCollectionTest$Cat", + "allDeclaredFields":true, + "allDeclaredMethods":true, + "allPublicMethods":true, + "allDeclaredConstructors":true, + "allDeclaredClasses":true + }, + { + "name":"com.arangodb.ArangoCollectionTest$Dog", + "allDeclaredFields":true, + "allDeclaredMethods":true, + "allPublicMethods":true, + "allDeclaredConstructors":true, + "allDeclaredClasses":true } ] From 687fc41d460e8e427188d93f8ba66f4ea7c3b267 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Wed, 7 Sep 2022 17:23:40 +0200 Subject: [PATCH 110/254] deprecated fulltext index (DE-375) (#454) (cherry picked from commit 5084a49e01c35d17bfe6d40af78e43c3d81681a5) --- .../java/com/arangodb/ArangoCollection.java | 2 ++ .../arangodb/async/ArangoCollectionAsync.java | 2 ++ .../internal/ArangoCollectionAsyncImpl.java | 1 + .../java/com/arangodb/entity/IndexType.java | 27 ++++++++++++++++++- .../internal/ArangoCollectionImpl.java | 1 + .../internal/InternalArangoCollection.java | 1 + .../arangodb/model/FulltextIndexOptions.java | 2 ++ .../com/arangodb/model/OptionsBuilder.java | 1 + 8 files changed, 36 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/arangodb/ArangoCollection.java b/src/main/java/com/arangodb/ArangoCollection.java index bfe741ca5..ca6171a34 100644 --- a/src/main/java/com/arangodb/ArangoCollection.java +++ b/src/main/java/com/arangodb/ArangoCollection.java @@ -655,7 +655,9 @@ MultiDocumentEntity> deleteDocuments( * @return information about the index * @see API * Documentation + * @deprecated since ArangoDB 3.10, use ArangoSearch view instead. */ + @Deprecated IndexEntity ensureFulltextIndex(Iterable fields, FulltextIndexOptions options); /** diff --git a/src/main/java/com/arangodb/async/ArangoCollectionAsync.java b/src/main/java/com/arangodb/async/ArangoCollectionAsync.java index 4ddcd2d6b..c62490484 100644 --- a/src/main/java/com/arangodb/async/ArangoCollectionAsync.java +++ b/src/main/java/com/arangodb/async/ArangoCollectionAsync.java @@ -699,7 +699,9 @@ CompletableFuture ensurePersistentIndex( * @return information about the index * @see API * Documentation + * @deprecated since ArangoDB 3.10, use ArangoSearch view instead. */ + @Deprecated CompletableFuture ensureFulltextIndex( final Iterable fields, final FulltextIndexOptions options); diff --git a/src/main/java/com/arangodb/async/internal/ArangoCollectionAsyncImpl.java b/src/main/java/com/arangodb/async/internal/ArangoCollectionAsyncImpl.java index b06bc0ebf..78ae21f9a 100644 --- a/src/main/java/com/arangodb/async/internal/ArangoCollectionAsyncImpl.java +++ b/src/main/java/com/arangodb/async/internal/ArangoCollectionAsyncImpl.java @@ -384,6 +384,7 @@ public CompletableFuture ensureGeoIndex(final Iterable fiel return executor.execute(createGeoIndexRequest(fields, options), IndexEntity.class); } + @Deprecated @Override public CompletableFuture ensureFulltextIndex( final Iterable fields, diff --git a/src/main/java/com/arangodb/entity/IndexType.java b/src/main/java/com/arangodb/entity/IndexType.java index 062f35ff1..26a048cb0 100644 --- a/src/main/java/com/arangodb/entity/IndexType.java +++ b/src/main/java/com/arangodb/entity/IndexType.java @@ -25,5 +25,30 @@ * @author Heiko Kernbach */ public enum IndexType { - primary, hash, skiplist, persistent, geo, geo1, geo2, fulltext, edge, ttl, zkd + + primary, + + hash, + + skiplist, + + persistent, + + geo, + + geo1, + + geo2, + + /** + * @deprecated since ArangoDB 3.10, use ArangoSearch view instead. + */ + @Deprecated + fulltext, + + edge, + + ttl, + + zkd } diff --git a/src/main/java/com/arangodb/internal/ArangoCollectionImpl.java b/src/main/java/com/arangodb/internal/ArangoCollectionImpl.java index 8fd3102e7..61e4d679d 100644 --- a/src/main/java/com/arangodb/internal/ArangoCollectionImpl.java +++ b/src/main/java/com/arangodb/internal/ArangoCollectionImpl.java @@ -376,6 +376,7 @@ public IndexEntity ensureGeoIndex(final Iterable fields, final GeoIndexO return executor.execute(createGeoIndexRequest(fields, options), IndexEntity.class); } + @Deprecated @Override public IndexEntity ensureFulltextIndex(final Iterable fields, final FulltextIndexOptions options) { return executor.execute(createFulltextIndexRequest(fields, options), IndexEntity.class); diff --git a/src/main/java/com/arangodb/internal/InternalArangoCollection.java b/src/main/java/com/arangodb/internal/InternalArangoCollection.java index 0a95c5c59..f0c924583 100644 --- a/src/main/java/com/arangodb/internal/InternalArangoCollection.java +++ b/src/main/java/com/arangodb/internal/InternalArangoCollection.java @@ -464,6 +464,7 @@ protected Request createGeoIndexRequest(final Iterable fields, final Geo return request; } + @Deprecated protected Request createFulltextIndexRequest(final Iterable fields, final FulltextIndexOptions options) { final Request request = request(db.dbName(), RequestType.POST, PATH_API_INDEX); request.putQueryParam(COLLECTION, name); diff --git a/src/main/java/com/arangodb/model/FulltextIndexOptions.java b/src/main/java/com/arangodb/model/FulltextIndexOptions.java index fd69c56af..84fadca34 100644 --- a/src/main/java/com/arangodb/model/FulltextIndexOptions.java +++ b/src/main/java/com/arangodb/model/FulltextIndexOptions.java @@ -26,7 +26,9 @@ * @author Mark Vollmary * @see API * Documentation + * @deprecated since ArangoDB 3.10, use ArangoSearch view instead. */ +@Deprecated public final class FulltextIndexOptions extends IndexOptions { private final IndexType type = IndexType.fulltext; diff --git a/src/main/java/com/arangodb/model/OptionsBuilder.java b/src/main/java/com/arangodb/model/OptionsBuilder.java index 17e9bf263..3b4f6c86d 100644 --- a/src/main/java/com/arangodb/model/OptionsBuilder.java +++ b/src/main/java/com/arangodb/model/OptionsBuilder.java @@ -67,6 +67,7 @@ public static GeoIndexOptions build(final GeoIndexOptions options, final Iterabl return options.fields(fields); } + @Deprecated public static FulltextIndexOptions build(final FulltextIndexOptions options, final Iterable fields) { return options.fields(fields); } From 786db3a829a71dc69352a461eb143a653e3a4507 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Tue, 20 Sep 2022 11:33:17 +0200 Subject: [PATCH 111/254] update test docker images --- .github/workflows/codeql.yml | 2 ++ .github/workflows/maven.yml | 19 ++++++++++--------- .github/workflows/native.yml | 2 +- 3 files changed, 13 insertions(+), 10 deletions(-) diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 862522072..a50a410d9 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -15,6 +15,8 @@ on: push: branches: - master + - v7 + - v6 pull_request: types: [ opened, synchronize, reopened ] branches: diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index 57a339d01..323ece6ed 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -4,6 +4,7 @@ on: push: branches: - master + - v7 - v6 pull_request: types: [ opened, synchronize, reopened ] @@ -20,12 +21,12 @@ jobs: fail-fast: false matrix: docker-img: - - docker.io/arangodb/arangodb:3.7.17 - - docker.io/arangodb/arangodb:3.8.6 - - docker.io/arangodb/arangodb:3.9.1 - - docker.io/arangodb/enterprise:3.7.17 - - docker.io/arangodb/enterprise:3.8.6 - - docker.io/arangodb/enterprise:3.9.1 + - docker.io/arangodb/arangodb:3.8.7 + - docker.io/arangodb/arangodb:3.9.3 + - docker.io/arangodb/arangodb-preview:3.10-nightly + - docker.io/arangodb/enterprise:3.8.7 + - docker.io/arangodb/enterprise:3.9.3 + - docker.io/arangodb/enterprise-preview:3.10-nightly topology: - single - cluster @@ -37,12 +38,12 @@ jobs: user-language: - en include: - - docker-img: docker.io/arangodb/arangodb:3.9.1 + - docker-img: docker.io/arangodb/arangodb:3.9.3 topology: single db-ext-names: true java-version: 11 user-language: tr - - docker-img: docker.io/arangodb/enterprise:3.9.1 + - docker-img: docker.io/arangodb/enterprise:3.9.3 topology: cluster db-ext-names: true java-version: 17 @@ -92,7 +93,7 @@ jobs: fail-fast: false matrix: docker-img: - - docker.io/arangodb/enterprise:3.9.1 + - docker.io/arangodb/enterprise:3.9.3 topology: - single - cluster diff --git a/.github/workflows/native.yml b/.github/workflows/native.yml index 08882d850..61ee29718 100644 --- a/.github/workflows/native.yml +++ b/.github/workflows/native.yml @@ -14,7 +14,7 @@ jobs: fail-fast: false matrix: docker-img: - - docker.io/arangodb/enterprise:3.9.1 + - docker.io/arangodb/enterprise:3.9.3 topology: - cluster db-ext-names: From afaa14a59f40b8267fa717b6e76fd1e7c3c27e9f Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Thu, 8 Sep 2022 09:25:00 +0200 Subject: [PATCH 112/254] [DE-374] index cache (cherry picked from commit 65b491529576fb964ee8aee4fede41c11405e7a6) --- .../java/com/arangodb/entity/IndexEntity.java | 6 +++++ .../model/PersistentIndexOptions.java | 14 ++++++++++ .../com/arangodb/ArangoCollectionTest.java | 27 +++++++++++++++++++ 3 files changed, 47 insertions(+) diff --git a/src/main/java/com/arangodb/entity/IndexEntity.java b/src/main/java/com/arangodb/entity/IndexEntity.java index a379ed161..3d98a8aa9 100644 --- a/src/main/java/com/arangodb/entity/IndexEntity.java +++ b/src/main/java/com/arangodb/entity/IndexEntity.java @@ -43,6 +43,8 @@ public final class IndexEntity { private Boolean inBackground; private Boolean estimates; + private Boolean cacheEnabled; + public IndexEntity() { super(); } @@ -107,4 +109,8 @@ public Boolean getEstimates() { return estimates; } + public Boolean getCacheEnabled() { + return cacheEnabled; + } + } diff --git a/src/main/java/com/arangodb/model/PersistentIndexOptions.java b/src/main/java/com/arangodb/model/PersistentIndexOptions.java index 077a0f6ff..c305987c7 100644 --- a/src/main/java/com/arangodb/model/PersistentIndexOptions.java +++ b/src/main/java/com/arangodb/model/PersistentIndexOptions.java @@ -35,6 +35,7 @@ public final class PersistentIndexOptions extends IndexOptions fields = Arrays.asList(f1, f2); + + final IndexEntity indexResult = collection.ensurePersistentIndex(fields, new PersistentIndexOptions().cacheEnabled(true)); + assertThat(indexResult).isNotNull(); + assertThat(indexResult.getConstraint()).isNull(); + assertThat(indexResult.getFields()).contains(f1); + assertThat(indexResult.getFields()).contains(f2); + assertThat(indexResult.getId()).startsWith(COLLECTION_NAME); + assertThat(indexResult.getIsNewlyCreated()).isTrue(); + assertThat(indexResult.getMinLength()).isNull(); + assertThat(indexResult.getSparse()).isFalse(); + assertThat(indexResult.getType()).isEqualTo(IndexType.persistent); + assertThat(indexResult.getUnique()).isFalse(); + assertThat(indexResult.getDeduplicate()).isTrue(); + assertThat(indexResult.getCacheEnabled()).isTrue(); } @ParameterizedTest(name = "{index}") From e8cf62556267088660af9d6124b4e4993ca6e0cb Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Tue, 20 Sep 2022 13:21:39 +0200 Subject: [PATCH 113/254] fixed tests for 3.10 --- src/test/java/com/arangodb/ArangoCollectionTest.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/test/java/com/arangodb/ArangoCollectionTest.java b/src/test/java/com/arangodb/ArangoCollectionTest.java index d211e606a..9aca583f2 100644 --- a/src/test/java/com/arangodb/ArangoCollectionTest.java +++ b/src/test/java/com/arangodb/ArangoCollectionTest.java @@ -624,6 +624,7 @@ void updateDocumentWithDifferentReturnType(ArangoCollection collection) { void updateDocumentUpdateRev(ArangoCollection collection) { final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); final DocumentCreateEntity createResult = collection.insertDocument(doc, null); + doc.addAttribute("foo", "bar"); final DocumentUpdateEntity updateResult = collection.updateDocument(createResult.getKey(), doc, null); assertThat(doc.getRevision()).isNull(); From d69af102e3425addb7616827427797602b256a5c Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Thu, 8 Sep 2022 11:59:33 +0200 Subject: [PATCH 114/254] [DE-378] computed values (cherry picked from commit b86f1c56ae437e7379110cffbab8c3a19b6dd5a7) --- .../com/arangodb/entity/CollectionEntity.java | 12 ++ .../model/CollectionCreateOptions.java | 20 +++- .../model/CollectionPropertiesOptions.java | 18 +++ .../com/arangodb/model/ComputedValue.java | 104 ++++++++++++++++++ .../java/com/arangodb/ArangoDatabaseTest.java | 36 ++++++ 5 files changed, 186 insertions(+), 4 deletions(-) create mode 100644 src/main/java/com/arangodb/model/ComputedValue.java diff --git a/src/main/java/com/arangodb/entity/CollectionEntity.java b/src/main/java/com/arangodb/entity/CollectionEntity.java index 6f9fff3aa..bff127761 100644 --- a/src/main/java/com/arangodb/entity/CollectionEntity.java +++ b/src/main/java/com/arangodb/entity/CollectionEntity.java @@ -21,6 +21,9 @@ package com.arangodb.entity; import com.arangodb.model.CollectionSchema; +import com.arangodb.model.ComputedValue; + +import java.util.List; /** * @author Mark Vollmary @@ -35,6 +38,7 @@ public class CollectionEntity { private CollectionStatus status; private CollectionType type; private CollectionSchema schema; + private List computedValues; public CollectionEntity() { super(); @@ -72,4 +76,12 @@ public CollectionSchema getSchema() { return schema; } + /** + * @return A list of computed values. + * @since ArangoDB 3.10 + */ + public List getComputedValues() { + return computedValues; + } + } diff --git a/src/main/java/com/arangodb/model/CollectionCreateOptions.java b/src/main/java/com/arangodb/model/CollectionCreateOptions.java index 92b20a35e..d443c11b7 100644 --- a/src/main/java/com/arangodb/model/CollectionCreateOptions.java +++ b/src/main/java/com/arangodb/model/CollectionCreateOptions.java @@ -20,10 +20,11 @@ package com.arangodb.model; -import com.arangodb.entity.CollectionType; -import com.arangodb.entity.KeyOptions; -import com.arangodb.entity.KeyType; -import com.arangodb.entity.ReplicationFactor; +import com.arangodb.entity.*; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; import java.util.Arrays; import java.util.Collection; @@ -40,6 +41,7 @@ public final class CollectionCreateOptions { private Integer writeConcern; private KeyOptions keyOptions; private Boolean waitForSync; + private List computedValues = new ArrayList<>(); private Collection shardKeys; private Integer numberOfShards; private Boolean isSystem; @@ -285,4 +287,14 @@ public CollectionCreateOptions schema(final CollectionSchema schema) { return this; } + /** + * @param computedValues An optional list of computed values. + * @return options + * @since ArangoDB 3.10 + */ + public CollectionCreateOptions computedValues(final ComputedValue... computedValues) { + Collections.addAll(this.computedValues, computedValues); + return this; + } + } diff --git a/src/main/java/com/arangodb/model/CollectionPropertiesOptions.java b/src/main/java/com/arangodb/model/CollectionPropertiesOptions.java index b764c49c4..95fb5842b 100644 --- a/src/main/java/com/arangodb/model/CollectionPropertiesOptions.java +++ b/src/main/java/com/arangodb/model/CollectionPropertiesOptions.java @@ -20,6 +20,10 @@ package com.arangodb.model; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + /** * @author Mark Vollmary * @see @@ -30,6 +34,7 @@ public final class CollectionPropertiesOptions { private Boolean waitForSync; private CollectionSchema schema; + private List computedValues; public CollectionPropertiesOptions() { super(); @@ -63,4 +68,17 @@ public CollectionPropertiesOptions schema(final CollectionSchema schema) { return this; } + /** + * @param computedValues An optional list of computed values. + * @return options + * @since ArangoDB 3.10 + */ + public CollectionPropertiesOptions computedValues(final ComputedValue... computedValues) { + if(this.computedValues == null) { + this.computedValues = new ArrayList<>(); + } + Collections.addAll(this.computedValues, computedValues); + return this; + } + } diff --git a/src/main/java/com/arangodb/model/ComputedValue.java b/src/main/java/com/arangodb/model/ComputedValue.java new file mode 100644 index 000000000..f0a3bd5b2 --- /dev/null +++ b/src/main/java/com/arangodb/model/ComputedValue.java @@ -0,0 +1,104 @@ +package com.arangodb.model; + +import java.util.Collections; +import java.util.HashSet; +import java.util.Objects; +import java.util.Set; + +/** + * @since ArangoDB 3.10 + */ +public class ComputedValue { + private String name; + private String expression; + private Boolean overwrite; + private Set computeOn; + private Boolean keepNull; + private Boolean failOnWarning; + + public enum ComputeOn { + insert, update, replace + } + + public ComputedValue() { + super(); + } + + /** + * @param name (required) The name of the target attribute. Can only be a top-level attribute, but you may return + * a nested object. Cannot be _key, _id, _rev, _from, _to, or a shard key attribute. + * @return this + */ + public ComputedValue name(final String name) { + this.name = name; + return this; + } + + /** + * @param expression (required) An AQL RETURN operation with an expression that computes the desired value. See + * Computed Value Expressions + * for details. + * @return this + */ + public ComputedValue expression(final String expression) { + this.expression = expression; + return this; + } + + /** + * @param overwrite (required) Whether the computed value shall take precedence over a user-provided or existing + * attribute. + * @return this + */ + public ComputedValue overwrite(final Boolean overwrite) { + this.overwrite = overwrite; + return this; + } + + /** + * @param computeOn (optional) An array of operations to define on which write operations the value shall be + * computed. The default is ["insert", "update", "replace"]. + * @return this + */ + public ComputedValue computeOn(final ComputeOn... computeOn) { + if (this.computeOn == null) { + this.computeOn = new HashSet<>(); + } + Collections.addAll(this.computeOn, computeOn); + return this; + } + + /** + * @param keepNull (optional) Whether the target attribute shall be set if the expression evaluates to null. You + * can set the option to false to not set (or unset) the target attribute if the expression + * returns null. The default is true. + * @return this + */ + public ComputedValue keepNull(final Boolean keepNull) { + this.keepNull = keepNull; + return this; + } + + /** + * @param failOnWarning (optional) Whether to let the write operation fail if the expression produces a warning. + * The default is false. + * @return this + */ + public ComputedValue failOnWarning(final Boolean failOnWarning) { + this.failOnWarning = failOnWarning; + return this; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + ComputedValue that = (ComputedValue) o; + return Objects.equals(name, that.name) && Objects.equals(expression, that.expression) && Objects.equals(overwrite, that.overwrite) && Objects.equals(computeOn, that.computeOn) && Objects.equals(keepNull, that.keepNull) && Objects.equals(failOnWarning, that.failOnWarning); + } + + @Override + public int hashCode() { + return Objects.hash(name, expression, overwrite, computeOn, keepNull, failOnWarning); + } +} diff --git a/src/test/java/com/arangodb/ArangoDatabaseTest.java b/src/test/java/com/arangodb/ArangoDatabaseTest.java index 026ed4d21..174144d9d 100644 --- a/src/test/java/com/arangodb/ArangoDatabaseTest.java +++ b/src/test/java/com/arangodb/ArangoDatabaseTest.java @@ -345,6 +345,42 @@ void createCollectionWithJsonSchema(ArangoDatabase db) { assertThat(e.getErrorNum()).isEqualTo(1620); } + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void createCollectionWithComputedFields(ArangoDatabase db) { + assumeTrue(isAtLeastVersion(3, 10)); + String cName = "collection-" + rnd(); + ComputedValue cv = new ComputedValue() + .name("foo") + .expression("RETURN 11") + .overwrite(false) + .computeOn(ComputedValue.ComputeOn.insert) + .keepNull(false) + .failOnWarning(true); + + final CollectionEntity result = db.createCollection(cName, new CollectionCreateOptions().computedValues(cv)); + + assertThat(result).isNotNull(); + assertThat(result.getComputedValues()) + .hasSize(1) + .contains(cv); + + ComputedValue cv2 = new ComputedValue() + .name("bar") + .expression("RETURN 22") + .overwrite(true) + .computeOn(ComputedValue.ComputeOn.update, ComputedValue.ComputeOn.replace) + .keepNull(true) + .failOnWarning(false); + + db.collection(cName).changeProperties(new CollectionPropertiesOptions().computedValues(cv2)); + + CollectionPropertiesEntity props = db.collection(cName).getProperties(); + assertThat(props.getComputedValues()) + .hasSize(1) + .contains(cv2); + } + @ParameterizedTest(name = "{index}") @MethodSource("dbs") void deleteCollection(ArangoDatabase db) { From 8a9534dc552c62c9f9bb09fc90863e5608941a69 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Thu, 8 Sep 2022 12:10:17 +0200 Subject: [PATCH 115/254] fixed tests for 3.10 --- .../model/CollectionCreateOptions.java | 3 +++ .../model/CollectionPropertiesOptions.java | 3 +++ .../com/arangodb/model/ComputedValue.java | 24 +++++++++++++++++++ .../java/com/arangodb/ArangoDatabaseTest.java | 2 +- .../arangodb/ArangoVertexCollectionTest.java | 1 + .../arangodb/async/ArangoDatabaseTest.java | 2 +- 6 files changed, 33 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/arangodb/model/CollectionCreateOptions.java b/src/main/java/com/arangodb/model/CollectionCreateOptions.java index d443c11b7..856bc03ae 100644 --- a/src/main/java/com/arangodb/model/CollectionCreateOptions.java +++ b/src/main/java/com/arangodb/model/CollectionCreateOptions.java @@ -297,4 +297,7 @@ public CollectionCreateOptions computedValues(final ComputedValue... computedVal return this; } + public List getComputedValues() { + return computedValues; + } } diff --git a/src/main/java/com/arangodb/model/CollectionPropertiesOptions.java b/src/main/java/com/arangodb/model/CollectionPropertiesOptions.java index 95fb5842b..d83109e24 100644 --- a/src/main/java/com/arangodb/model/CollectionPropertiesOptions.java +++ b/src/main/java/com/arangodb/model/CollectionPropertiesOptions.java @@ -81,4 +81,7 @@ public CollectionPropertiesOptions computedValues(final ComputedValue... compute return this; } + public List getComputedValues() { + return computedValues; + } } diff --git a/src/main/java/com/arangodb/model/ComputedValue.java b/src/main/java/com/arangodb/model/ComputedValue.java index f0a3bd5b2..ebb68002f 100644 --- a/src/main/java/com/arangodb/model/ComputedValue.java +++ b/src/main/java/com/arangodb/model/ComputedValue.java @@ -89,6 +89,30 @@ public ComputedValue failOnWarning(final Boolean failOnWarning) { return this; } + public String getName() { + return name; + } + + public String getExpression() { + return expression; + } + + public Boolean getOverwrite() { + return overwrite; + } + + public Set getComputeOn() { + return computeOn; + } + + public Boolean getKeepNull() { + return keepNull; + } + + public Boolean getFailOnWarning() { + return failOnWarning; + } + @Override public boolean equals(Object o) { if (this == o) return true; diff --git a/src/test/java/com/arangodb/ArangoDatabaseTest.java b/src/test/java/com/arangodb/ArangoDatabaseTest.java index 174144d9d..139c6bfb9 100644 --- a/src/test/java/com/arangodb/ArangoDatabaseTest.java +++ b/src/test/java/com/arangodb/ArangoDatabaseTest.java @@ -627,7 +627,7 @@ void queryWithLimitAndFullCount(ArangoDatabase db) { assertThat((Iterator) cursor).hasNext(); } assertThat(cursor.getStats()).isNotNull(); - assertThat((Integer) cursor.getStats().get("fullCount")) + assertThat(((Number) cursor.getStats().get("fullCount")).intValue()) .isGreaterThanOrEqualTo(10); } diff --git a/src/test/java/com/arangodb/ArangoVertexCollectionTest.java b/src/test/java/com/arangodb/ArangoVertexCollectionTest.java index 8937f5231..7861f9217 100644 --- a/src/test/java/com/arangodb/ArangoVertexCollectionTest.java +++ b/src/test/java/com/arangodb/ArangoVertexCollectionTest.java @@ -317,6 +317,7 @@ void updateVertexUpdateRev(ArangoVertexCollection vertices) { final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); final VertexEntity createResult = vertices .insertVertex(doc, null); + doc.addAttribute("foo", "bar"); final VertexUpdateEntity updateResult = vertices .updateVertex(createResult.getKey(), doc, null); assertThat(doc.getRevision()).isNull(); diff --git a/src/test/java/com/arangodb/async/ArangoDatabaseTest.java b/src/test/java/com/arangodb/async/ArangoDatabaseTest.java index 07e0ea0d9..a12bf84ec 100644 --- a/src/test/java/com/arangodb/async/ArangoDatabaseTest.java +++ b/src/test/java/com/arangodb/async/ArangoDatabaseTest.java @@ -493,7 +493,7 @@ void queryWithLimitAndFullCount() throws InterruptedException, ExecutionExceptio assertThat(cursor.hasNext()).isEqualTo(true); } assertThat(cursor.getStats()).isNotNull(); - assertThat((Integer) cursor.getStats().get("fullCount")) + assertThat(((Number) cursor.getStats().get("fullCount")).intValue()) .isGreaterThanOrEqualTo(10); }) .get(); From af43f69a8fa2de3495de739181c1d0f0df15114d Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Thu, 8 Sep 2022 12:43:11 +0200 Subject: [PATCH 116/254] [DE-370] get query optimizer rules (cherry picked from commit b9e5af5a3e7b820871a231f68a9467c321352b2c) --- src/main/java/com/arangodb/ArangoDB.java | 7 +++ .../com/arangodb/async/ArangoDBAsync.java | 6 +++ .../async/internal/ArangoDBAsyncImpl.java | 8 +++ .../arangodb/entity/QueryOptimizerRule.java | 50 +++++++++++++++++++ .../com/arangodb/internal/ArangoDBImpl.java | 6 +++ .../arangodb/internal/InternalArangoDB.java | 5 ++ src/test/java/com/arangodb/ArangoDBTest.java | 19 +++++++ .../java/com/arangodb/async/ArangoDBTest.java | 19 +++++++ 8 files changed, 120 insertions(+) create mode 100644 src/main/java/com/arangodb/entity/QueryOptimizerRule.java diff --git a/src/main/java/com/arangodb/ArangoDB.java b/src/main/java/com/arangodb/ArangoDB.java index 1729a0182..7fba6cac8 100644 --- a/src/main/java/com/arangodb/ArangoDB.java +++ b/src/main/java/com/arangodb/ArangoDB.java @@ -330,6 +330,13 @@ public interface ArangoDB extends ArangoSerdeAccessor { */ LogLevelEntity setLogLevel(LogLevelEntity entity); + /** + * @return the list of available rules and their respective flags + * @throws ArangoDBException + * @since ArangoDB 3.10 + */ + Collection getQueryOptimizerRules(); + /** * Attention: Please do not use! * diff --git a/src/main/java/com/arangodb/async/ArangoDBAsync.java b/src/main/java/com/arangodb/async/ArangoDBAsync.java index 56088cbf7..1ade8d537 100644 --- a/src/main/java/com/arangodb/async/ArangoDBAsync.java +++ b/src/main/java/com/arangodb/async/ArangoDBAsync.java @@ -300,6 +300,12 @@ public interface ArangoDBAsync extends ArangoSerdeAccessor { */ CompletableFuture setLogLevel(final LogLevelEntity entity); + /** + * @return the list of available rules and their respective flags + * @since ArangoDB 3.10 + */ + CompletableFuture> getQueryOptimizerRules(); + /** * Builder class to build an instance of {@link ArangoDBAsync}. * diff --git a/src/main/java/com/arangodb/async/internal/ArangoDBAsyncImpl.java b/src/main/java/com/arangodb/async/internal/ArangoDBAsyncImpl.java index 04fafe5e6..364d760fc 100644 --- a/src/main/java/com/arangodb/async/internal/ArangoDBAsyncImpl.java +++ b/src/main/java/com/arangodb/async/internal/ArangoDBAsyncImpl.java @@ -39,6 +39,7 @@ import com.arangodb.model.LogOptions; import com.arangodb.model.UserCreateOptions; import com.arangodb.model.UserUpdateOptions; +import com.arangodb.velocypack.Type; import com.arangodb.velocystream.Request; import com.arangodb.velocystream.Response; import org.slf4j.Logger; @@ -233,4 +234,11 @@ public CompletableFuture getLogLevel() { public CompletableFuture setLogLevel(final LogLevelEntity entity) { return executor.execute(setLogLevelRequest(entity), LogLevelEntity.class); } + + @Override + public CompletableFuture> getQueryOptimizerRules() { + return executor.execute(getQueryOptimizerRulesRequest(), new Type>() { + }.getType()); + } + } diff --git a/src/main/java/com/arangodb/entity/QueryOptimizerRule.java b/src/main/java/com/arangodb/entity/QueryOptimizerRule.java new file mode 100644 index 000000000..df4869f2f --- /dev/null +++ b/src/main/java/com/arangodb/entity/QueryOptimizerRule.java @@ -0,0 +1,50 @@ +package com.arangodb.entity; + +/** + * @since ArangoDB 3.10 + */ +public class QueryOptimizerRule { + private String name; + private Flags flags; + + public String getName() { + return name; + } + + public Flags getFlags() { + return flags; + } + + public static class Flags { + private Boolean hidden; + private Boolean clusterOnly; + private Boolean canBeDisabled; + private Boolean canCreateAdditionalPlans; + private Boolean disabledByDefault; + private Boolean enterpriseOnly; + + public Boolean getHidden() { + return hidden; + } + + public Boolean getClusterOnly() { + return clusterOnly; + } + + public Boolean getCanBeDisabled() { + return canBeDisabled; + } + + public Boolean getCanCreateAdditionalPlans() { + return canCreateAdditionalPlans; + } + + public Boolean getDisabledByDefault() { + return disabledByDefault; + } + + public Boolean getEnterpriseOnly() { + return enterpriseOnly; + } + } +} diff --git a/src/main/java/com/arangodb/internal/ArangoDBImpl.java b/src/main/java/com/arangodb/internal/ArangoDBImpl.java index f9a938cea..b2f407b23 100644 --- a/src/main/java/com/arangodb/internal/ArangoDBImpl.java +++ b/src/main/java/com/arangodb/internal/ArangoDBImpl.java @@ -29,6 +29,7 @@ import com.arangodb.internal.net.HostHandler; import com.arangodb.internal.net.HostResolver; import com.arangodb.internal.serde.InternalSerde; +import com.arangodb.internal.serde.SerdeUtils; import com.arangodb.internal.velocystream.VstCommunicationSync; import com.arangodb.internal.velocystream.VstProtocol; import com.arangodb.model.DBCreateOptions; @@ -259,6 +260,11 @@ public LogLevelEntity setLogLevel(final LogLevelEntity entity) { return executor.execute(setLogLevelRequest(entity), LogLevelEntity.class); } + @Override + public Collection getQueryOptimizerRules() throws ArangoDBException { + return executor.execute(getQueryOptimizerRulesRequest(), SerdeUtils.constructListType(QueryOptimizerRule.class)); + } + @Override public ArangoDBImpl _setCursorInitializer(final ArangoCursorInitializer cursorInitializer) { this.cursorInitializer = cursorInitializer; diff --git a/src/main/java/com/arangodb/internal/InternalArangoDB.java b/src/main/java/com/arangodb/internal/InternalArangoDB.java index 22b2b8e6d..13efd696d 100644 --- a/src/main/java/com/arangodb/internal/InternalArangoDB.java +++ b/src/main/java/com/arangodb/internal/InternalArangoDB.java @@ -50,6 +50,7 @@ public abstract class InternalArangoDB extends ArangoE private static final String PATH_API_SERVER_ID = "/_admin/server/id"; private static final String PATH_ENDPOINTS = "/_api/cluster/endpoints"; private static final String PATH_API_USER = "/_api/user"; + private static final String PATH_API_QUERY_RULES = "/_api/query/rules"; protected InternalArangoDB(final E executor, final InternalSerde util, final ArangoContext context) { super(executor, util, context); @@ -183,4 +184,8 @@ protected Request setLogLevelRequest(final LogLevelEntity entity) { .setBody(getSerde().serialize(entity)); } + protected Request getQueryOptimizerRulesRequest() { + return request(DbName.SYSTEM, RequestType.GET, PATH_API_QUERY_RULES); + } + } diff --git a/src/test/java/com/arangodb/ArangoDBTest.java b/src/test/java/com/arangodb/ArangoDBTest.java index 4570a2322..fdf18a5c1 100644 --- a/src/test/java/com/arangodb/ArangoDBTest.java +++ b/src/test/java/com/arangodb/ArangoDBTest.java @@ -538,6 +538,25 @@ void setAllLogLevel(ArangoDB arangoDB) { } } + @ParameterizedTest(name = "{index}") + @MethodSource("arangos") + void getQueryOptimizerRules(ArangoDB arangoDB) { + assumeTrue(isAtLeastVersion(3, 10)); + final Collection rules = arangoDB.getQueryOptimizerRules(); + assertThat(rules).isNotEmpty(); + for (QueryOptimizerRule rule : rules) { + assertThat(rule).isNotNull(); + assertThat(rule.getName()).isNotNull(); + QueryOptimizerRule.Flags flags = rule.getFlags(); + assertThat(flags.getHidden()).isNotNull(); + assertThat(flags.getClusterOnly()).isNotNull(); + assertThat(flags.getCanBeDisabled()).isNotNull(); + assertThat(flags.getCanCreateAdditionalPlans()).isNotNull(); + assertThat(flags.getDisabledByDefault()).isNotNull(); + assertThat(flags.getEnterpriseOnly()).isNotNull(); + } + } + @ParameterizedTest(name = "{index}") @MethodSource("arangos") void arangoDBException(ArangoDB arangoDB) { diff --git a/src/test/java/com/arangodb/async/ArangoDBTest.java b/src/test/java/com/arangodb/async/ArangoDBTest.java index d5a48438e..e7c5bbd1b 100644 --- a/src/test/java/com/arangodb/async/ArangoDBTest.java +++ b/src/test/java/com/arangodb/async/ArangoDBTest.java @@ -526,4 +526,23 @@ void queueTime() throws InterruptedException, ExecutionException { } } + @Test + void getQueryOptimizerRules() throws ExecutionException, InterruptedException { + assumeTrue(isAtLeastVersion(3, 10)); + final Collection rules = arangoDB.getQueryOptimizerRules().get(); + assertThat(rules).isNotEmpty(); + for (QueryOptimizerRule rule : rules) { + assertThat(rule).isNotNull(); + assertThat(rule.getName()).isNotNull(); + QueryOptimizerRule.Flags flags = rule.getFlags(); + assertThat(flags.getHidden()).isNotNull(); + assertThat(flags.getClusterOnly()).isNotNull(); + assertThat(flags.getCanBeDisabled()).isNotNull(); + assertThat(flags.getCanCreateAdditionalPlans()).isNotNull(); + assertThat(flags.getDisabledByDefault()).isNotNull(); + assertThat(flags.getEnterpriseOnly()).isNotNull(); + } + } + + } From 389590e9826908959fa1aaeb26b8e68c57846c49 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Thu, 8 Sep 2022 13:05:43 +0200 Subject: [PATCH 117/254] [DE-376] geo index legacy polygons (cherry picked from commit 901550d243bb64fa847b2c07c1fa14febb67ed43) --- .../java/com/arangodb/entity/IndexEntity.java | 6 ++- .../com/arangodb/model/GeoIndexOptions.java | 18 +++++++++ .../com/arangodb/ArangoCollectionTest.java | 37 +++++++++++++++++++ 3 files changed, 60 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/arangodb/entity/IndexEntity.java b/src/main/java/com/arangodb/entity/IndexEntity.java index 3d98a8aa9..92055c080 100644 --- a/src/main/java/com/arangodb/entity/IndexEntity.java +++ b/src/main/java/com/arangodb/entity/IndexEntity.java @@ -42,8 +42,8 @@ public final class IndexEntity { private Integer expireAfter; private Boolean inBackground; private Boolean estimates; - private Boolean cacheEnabled; + private Boolean legacyPolygons; public IndexEntity() { super(); @@ -113,4 +113,8 @@ public Boolean getCacheEnabled() { return cacheEnabled; } + public Boolean getLegacyPolygons() { + return legacyPolygons; + } + } diff --git a/src/main/java/com/arangodb/model/GeoIndexOptions.java b/src/main/java/com/arangodb/model/GeoIndexOptions.java index db3f43f95..d71c10555 100644 --- a/src/main/java/com/arangodb/model/GeoIndexOptions.java +++ b/src/main/java/com/arangodb/model/GeoIndexOptions.java @@ -32,6 +32,7 @@ public final class GeoIndexOptions extends IndexOptions { private final IndexType type = IndexType.geo; private Iterable fields; private Boolean geoJson; + private Boolean legacyPolygons; public GeoIndexOptions() { super(); @@ -73,4 +74,21 @@ public GeoIndexOptions geoJson(final Boolean geoJson) { return this; } + public Boolean getLegacyPolygons() { + return legacyPolygons; + } + + /** + * @param legacyPolygons If `true` will use the old rules (pre-3.10) for the parsing GeoJSON polygons. This + * allows you to let old indexes produce the same, potentially wrong results as before an + * upgrade. A geo index with `legacyPolygons` set to `false` will use the new, correct and + * consistent method for parsing of GeoJSON polygons. + * See Legacy Polygons. + * @return options + * @since ArangoDB 3.10 + */ + public GeoIndexOptions legacyPolygons(final Boolean legacyPolygons) { + this.legacyPolygons = legacyPolygons; + return this; + } } diff --git a/src/test/java/com/arangodb/ArangoCollectionTest.java b/src/test/java/com/arangodb/ArangoCollectionTest.java index 9aca583f2..27310e689 100644 --- a/src/test/java/com/arangodb/ArangoCollectionTest.java +++ b/src/test/java/com/arangodb/ArangoCollectionTest.java @@ -1302,6 +1302,9 @@ void createGeoIndex(ArangoCollection collection) { } else { assertThat(indexResult.getType()).isEqualTo(IndexType.geo1); } + if (isAtLeastVersion(3, 10)) { + assertThat(indexResult.getLegacyPolygons()).isFalse(); + } } @ParameterizedTest(name = "{index}") @@ -1329,6 +1332,40 @@ void createGeoIndexWithOptions(ArangoCollection collection) { assertThat(indexResult.getType()).isEqualTo(IndexType.geo1); } assertThat(indexResult.getName()).isEqualTo(name); + if (isAtLeastVersion(3, 10)) { + assertThat(indexResult.getLegacyPolygons()).isFalse(); + } + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void createGeoIndexLegacyPolygons(ArangoCollection collection) { + assumeTrue(isAtLeastVersion(3, 10)); + + String name = "geoIndex-" + rnd(); + final GeoIndexOptions options = new GeoIndexOptions(); + options.name(name); + options.legacyPolygons(true); + + String f1 = "field-" + rnd(); + final Collection fields = Collections.singletonList(f1); + final IndexEntity indexResult = collection.ensureGeoIndex(fields, options); + assertThat(indexResult).isNotNull(); + assertThat(indexResult.getFields()).contains(f1); + assertThat(indexResult.getId()).startsWith(COLLECTION_NAME); + assertThat(indexResult.getIsNewlyCreated()).isTrue(); + assertThat(indexResult.getMinLength()).isNull(); + assertThat(indexResult.getSparse()).isTrue(); + assertThat(indexResult.getUnique()).isFalse(); + if (isAtLeastVersion(3, 4)) { + assertThat(indexResult.getType()).isEqualTo(IndexType.geo); + } else { + assertThat(indexResult.getType()).isEqualTo(IndexType.geo1); + } + assertThat(indexResult.getName()).isEqualTo(name); + if (isAtLeastVersion(3, 10)) { + assertThat(indexResult.getLegacyPolygons()).isTrue(); + } } @ParameterizedTest(name = "{index}") From b501a5c0a4022d325d144671e57031776ca8bc83 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Fri, 9 Sep 2022 09:46:47 +0200 Subject: [PATCH 118/254] [DE-377] test support for enterprise graphs (cherry picked from commit b9266858aa7eae0e5c7cba615d40a29da2dc96dc) --- .../java/com/arangodb/ArangoGraphTest.java | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/src/test/java/com/arangodb/ArangoGraphTest.java b/src/test/java/com/arangodb/ArangoGraphTest.java index d254ff985..cc944f8e0 100644 --- a/src/test/java/com/arangodb/ArangoGraphTest.java +++ b/src/test/java/com/arangodb/ArangoGraphTest.java @@ -385,6 +385,28 @@ void hybridDisjointSmartGraph(ArangoDatabase db) { assertThat(db.collection(v2Name).getProperties().getReplicationFactor().getValue()).isEqualTo(2); } + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void enterpriseGraph(ArangoDatabase db) { + assumeTrue(isEnterprise()); + assumeTrue(isCluster()); + + final Collection edgeDefinitions = new ArrayList<>(); + edgeDefinitions.add(new EdgeDefinition().collection("enterpriseGraph-edge-" + rnd()).from("enterpriseGraph-vertex-" + rnd()).to("enterpriseGraph-vertex-" + rnd())); + + String graphId = GRAPH_NAME + rnd(); + final GraphEntity g = db.createGraph(graphId, edgeDefinitions, new GraphCreateOptions().isSmart(true).numberOfShards(2)); + + assertThat(g).isNotNull(); + assertThat(g.getSmartGraphAttribute()).isNull(); + assertThat(g.getNumberOfShards()).isEqualTo(2); + if (isAtLeastVersion(3, 10)) { + assertThat(g.getIsSmart()).isTrue(); + } else { + assertThat(g.getIsSmart()).isFalse(); + } + } + @ParameterizedTest(name = "{index}") @MethodSource("dbs") void drop(ArangoDatabase db) { From 9073b3151c115398a2d32cd7efc56084f88d8c30 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Fri, 9 Sep 2022 10:32:26 +0200 Subject: [PATCH 119/254] [DE-373] index stored values (cherry picked from commit 0d1f01ae99f50ec0fabdc058ca850ae901b97459) --- .../java/com/arangodb/entity/IndexEntity.java | 5 ++++ .../model/PersistentIndexOptions.java | 25 +++++++++++++++++ .../com/arangodb/ArangoCollectionTest.java | 27 +++++++++++++++++++ 3 files changed, 57 insertions(+) diff --git a/src/main/java/com/arangodb/entity/IndexEntity.java b/src/main/java/com/arangodb/entity/IndexEntity.java index 92055c080..06bf9c65f 100644 --- a/src/main/java/com/arangodb/entity/IndexEntity.java +++ b/src/main/java/com/arangodb/entity/IndexEntity.java @@ -43,6 +43,7 @@ public final class IndexEntity { private Boolean inBackground; private Boolean estimates; private Boolean cacheEnabled; + private Collection storedValues; private Boolean legacyPolygons; public IndexEntity() { @@ -113,6 +114,10 @@ public Boolean getCacheEnabled() { return cacheEnabled; } + public Collection getStoredValues() { + return storedValues; + } + public Boolean getLegacyPolygons() { return legacyPolygons; } diff --git a/src/main/java/com/arangodb/model/PersistentIndexOptions.java b/src/main/java/com/arangodb/model/PersistentIndexOptions.java index c305987c7..1ad5be93c 100644 --- a/src/main/java/com/arangodb/model/PersistentIndexOptions.java +++ b/src/main/java/com/arangodb/model/PersistentIndexOptions.java @@ -22,6 +22,10 @@ import com.arangodb.entity.IndexType; +import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; + /** * @author Mark Vollmary * @see API @@ -36,6 +40,7 @@ public final class PersistentIndexOptions extends IndexOptions storedValues; public PersistentIndexOptions() { super(); @@ -119,6 +124,7 @@ public Boolean getEstimates() { /** * @param cacheEnabled enables in-memory caching of index entries + * @return options * @since ArangoDB 3.10 */ public PersistentIndexOptions cacheEnabled(final Boolean cacheEnabled) { @@ -130,4 +136,23 @@ public Boolean getCacheEnabled() { return cacheEnabled; } + public Collection getStoredValues() { + return storedValues; + } + + /** + * @param storedValues (optional) array of paths to additional attributes to store in the index. These additional + * attributes cannot be used for index lookups or for sorting, but they can be used for + * projections. This allows an index to fully cover more queries and avoid extra document + * lookups. The maximum number of attributes in `storedValues` is 32. + * @return options + */ + public PersistentIndexOptions storedValues(final String... storedValues) { + if (this.storedValues == null) { + this.storedValues = new HashSet<>(); + } + Collections.addAll(this.storedValues, storedValues); + return this; + } + } diff --git a/src/test/java/com/arangodb/ArangoCollectionTest.java b/src/test/java/com/arangodb/ArangoCollectionTest.java index 27310e689..bed275d1a 100644 --- a/src/test/java/com/arangodb/ArangoCollectionTest.java +++ b/src/test/java/com/arangodb/ArangoCollectionTest.java @@ -1514,6 +1514,33 @@ void createPersistentIndexCacheEnabled(ArangoCollection collection) { assertThat(indexResult.getCacheEnabled()).isTrue(); } + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void createPersistentIndexStoredValues(ArangoCollection collection) { + assumeTrue(isAtLeastVersion(3, 10)); + + String f1 = "field-" + rnd(); + String f2 = "field-" + rnd(); + final Collection fields = Arrays.asList(f1, f2); + + final IndexEntity indexResult = collection.ensurePersistentIndex(fields, new PersistentIndexOptions().storedValues("v1", "v2")); + assertThat(indexResult).isNotNull(); + assertThat(indexResult.getConstraint()).isNull(); + assertThat(indexResult.getFields()).contains(f1); + assertThat(indexResult.getFields()).contains(f2); + assertThat(indexResult.getId()).startsWith(COLLECTION_NAME); + assertThat(indexResult.getIsNewlyCreated()).isTrue(); + assertThat(indexResult.getMinLength()).isNull(); + assertThat(indexResult.getSparse()).isFalse(); + assertThat(indexResult.getType()).isEqualTo(IndexType.persistent); + assertThat(indexResult.getUnique()).isFalse(); + assertThat(indexResult.getDeduplicate()).isTrue(); + assertThat(indexResult.getCacheEnabled()).isFalse(); + assertThat(indexResult.getStoredValues()) + .hasSize(2) + .contains("v1", "v2"); + } + @ParameterizedTest(name = "{index}") @MethodSource("cols") void createPersistentIndexWithOptions(ArangoCollection collection) { From bc1c43157c86dd67829ecaa6a994a68ac3fcfb9b Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Fri, 9 Sep 2022 15:39:07 +0200 Subject: [PATCH 120/254] [DE-371] cluster dirty reads (#455) * getDocumentsDirtyRead * queryAllowDirtyRead * tests fixes * transactionDirtyRead (cherry picked from commit 62b2d60372e3a1b552864664a99ec932d58f2436) --- src/main/java/com/arangodb/ArangoCursor.java | 6 ++++ .../arangodb/entity/MultiDocumentEntity.java | 12 +++++++ .../internal/InternalArangoCollection.java | 2 ++ .../internal/InternalArangoDatabase.java | 7 +++- .../internal/cursor/ArangoCursorImpl.java | 7 ++++ .../cursor/entity/InternalCursorEntity.java | 1 + .../model/StreamTransactionOptions.java | 20 ++++++++++++ .../com/arangodb/ArangoCollectionTest.java | 3 ++ .../java/com/arangodb/ArangoDatabaseTest.java | 3 ++ .../com/arangodb/StreamTransactionTest.java | 32 +++++++++++++++++++ 10 files changed, 92 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/arangodb/ArangoCursor.java b/src/main/java/com/arangodb/ArangoCursor.java index bbccfc068..45f3bf1e2 100644 --- a/src/main/java/com/arangodb/ArangoCursor.java +++ b/src/main/java/com/arangodb/ArangoCursor.java @@ -70,4 +70,10 @@ public interface ArangoCursor extends ArangoIterable, ArangoIterator, C */ List asListRemaining(); + /** + * @return true if the result is a potential dirty read + * @since ArangoDB 3.10 + */ + boolean isPotentialDirtyRead(); + } diff --git a/src/main/java/com/arangodb/entity/MultiDocumentEntity.java b/src/main/java/com/arangodb/entity/MultiDocumentEntity.java index edf154696..6a4c5f3e0 100644 --- a/src/main/java/com/arangodb/entity/MultiDocumentEntity.java +++ b/src/main/java/com/arangodb/entity/MultiDocumentEntity.java @@ -30,6 +30,7 @@ public final class MultiDocumentEntity { private Collection documents; private Collection errors; private Collection documentsAndErrors; + private boolean isPotentialDirtyRead = false; public MultiDocumentEntity() { super(); @@ -68,4 +69,15 @@ public void setDocumentsAndErrors(final Collection documentsAndErrors) { this.documentsAndErrors = documentsAndErrors; } + /** + * @return true if the result is a potential dirty read + * @since ArangoDB 3.10 + */ + public Boolean isPotentialDirtyRead() { + return isPotentialDirtyRead; + } + + public void setPotentialDirtyRead(final Boolean isPotentialDirtyRead) { + this.isPotentialDirtyRead = isPotentialDirtyRead; + } } diff --git a/src/main/java/com/arangodb/internal/InternalArangoCollection.java b/src/main/java/com/arangodb/internal/InternalArangoCollection.java index f0c924583..4028c3202 100644 --- a/src/main/java/com/arangodb/internal/InternalArangoCollection.java +++ b/src/main/java/com/arangodb/internal/InternalArangoCollection.java @@ -195,6 +195,8 @@ protected ResponseDeserializer> getDocumentsResponseD final Class type, final DocumentReadOptions options) { return response -> { final MultiDocumentEntity multiDocument = new MultiDocumentEntity<>(); + boolean potentialDirtyRead = Boolean.parseBoolean(response.getMeta().get("X-Arango-Potential-Dirty-Read")); + multiDocument.setPotentialDirtyRead(potentialDirtyRead); final Collection docs = new ArrayList<>(); final Collection errors = new ArrayList<>(); final Collection documentsAndErrors = new ArrayList<>(); diff --git a/src/main/java/com/arangodb/internal/InternalArangoDatabase.java b/src/main/java/com/arangodb/internal/InternalArangoDatabase.java index 760264c77..4f473607c 100644 --- a/src/main/java/com/arangodb/internal/InternalArangoDatabase.java +++ b/src/main/java/com/arangodb/internal/InternalArangoDatabase.java @@ -300,7 +300,12 @@ protected ResponseDeserializer transactionResponseDeserializer(final Clas } protected Request beginStreamTransactionRequest(final StreamTransactionOptions options) { - return request(dbName, RequestType.POST, PATH_API_BEGIN_STREAM_TRANSACTION).setBody(getSerde().serialize(options != null ? options : new StreamTransactionOptions())); + StreamTransactionOptions opts = options != null ? options : new StreamTransactionOptions(); + Request r = request(dbName, RequestType.POST, PATH_API_BEGIN_STREAM_TRANSACTION).setBody(getSerde().serialize(opts)); + if(Boolean.TRUE.equals(opts.getAllowDirtyRead())) { + RequestUtils.allowDirtyRead(r); + } + return r; } protected Request abortStreamTransactionRequest(String id) { diff --git a/src/main/java/com/arangodb/internal/cursor/ArangoCursorImpl.java b/src/main/java/com/arangodb/internal/cursor/ArangoCursorImpl.java index dfbb635a1..8f3ac6f0a 100644 --- a/src/main/java/com/arangodb/internal/cursor/ArangoCursorImpl.java +++ b/src/main/java/com/arangodb/internal/cursor/ArangoCursorImpl.java @@ -42,6 +42,7 @@ public class ArangoCursorImpl extends AbstractArangoIterable implements Ar private final Class type; private final String id; private final ArangoCursorExecute execute; + private final boolean isPontentialDirtyRead; public ArangoCursorImpl(final InternalArangoDatabase db, final ArangoCursorExecute execute, final Class type, final InternalCursorEntity result) { @@ -50,6 +51,7 @@ public ArangoCursorImpl(final InternalArangoDatabase db, final ArangoCurso this.type = type; iterator = createIterator(this, db, execute, result); id = result.getId(); + this.isPontentialDirtyRead = Boolean.parseBoolean(result.getMeta().get("X-Arango-Potential-Dirty-Read")); } protected ArangoCursorIterator createIterator( @@ -119,6 +121,11 @@ public List asListRemaining() { return remaining; } + @Override + public boolean isPotentialDirtyRead() { + return isPontentialDirtyRead; + } + @Override public void remove() { throw new UnsupportedOperationException(); diff --git a/src/main/java/com/arangodb/internal/cursor/entity/InternalCursorEntity.java b/src/main/java/com/arangodb/internal/cursor/entity/InternalCursorEntity.java index c9c97d548..1ab557b49 100644 --- a/src/main/java/com/arangodb/internal/cursor/entity/InternalCursorEntity.java +++ b/src/main/java/com/arangodb/internal/cursor/entity/InternalCursorEntity.java @@ -90,6 +90,7 @@ public JsonNode getResult() { } public Map getMeta() { + if (meta == null) return Collections.emptyMap(); return meta; } diff --git a/src/main/java/com/arangodb/model/StreamTransactionOptions.java b/src/main/java/com/arangodb/model/StreamTransactionOptions.java index 722e0f3be..deb2e1cf9 100644 --- a/src/main/java/com/arangodb/model/StreamTransactionOptions.java +++ b/src/main/java/com/arangodb/model/StreamTransactionOptions.java @@ -20,6 +20,8 @@ package com.arangodb.model; +import com.arangodb.velocypack.annotations.Expose; + /** * @author Mark Vollmary * @author Michele Rastelli @@ -33,6 +35,8 @@ public final class StreamTransactionOptions { private Boolean waitForSync; private Long maxTransactionSize; private Boolean allowImplicit; + @Expose(serialize = false) + private Boolean allowDirtyRead; public StreamTransactionOptions() { super(); @@ -129,4 +133,20 @@ public StreamTransactionOptions maxTransactionSize(final Long maxTransactionSize return this; } + public Boolean getAllowDirtyRead() { + return allowDirtyRead; + } + + /** + * @param allowDirtyRead Set to {@code true} allows reading from followers in an active-failover setup. + * @return options + * @see API + * Documentation + * @since ArangoDB 3.4.0 + */ + public StreamTransactionOptions allowDirtyRead(final Boolean allowDirtyRead) { + this.allowDirtyRead = allowDirtyRead; + return this; + } + } diff --git a/src/test/java/com/arangodb/ArangoCollectionTest.java b/src/test/java/com/arangodb/ArangoCollectionTest.java index bed275d1a..66c34ba34 100644 --- a/src/test/java/com/arangodb/ArangoCollectionTest.java +++ b/src/test/java/com/arangodb/ArangoCollectionTest.java @@ -545,6 +545,9 @@ void getDocumentsDirtyRead(ArangoCollection collection) { final MultiDocumentEntity documents = collection.getDocuments(Arrays.asList("1", "2", "3"), BaseDocument.class, new DocumentReadOptions().allowDirtyRead(true)); assertThat(documents).isNotNull(); + if (isAtLeastVersion(3, 10)) { + assertThat(documents.isPotentialDirtyRead()).isTrue(); + } assertThat(documents.getDocuments()).hasSize(3); for (final BaseDocument document : documents.getDocuments()) { assertThat(document.getId()).isIn(COLLECTION_NAME + "/" + "1", COLLECTION_NAME + "/" + "2", diff --git a/src/test/java/com/arangodb/ArangoDatabaseTest.java b/src/test/java/com/arangodb/ArangoDatabaseTest.java index 139c6bfb9..bfd9924cd 100644 --- a/src/test/java/com/arangodb/ArangoDatabaseTest.java +++ b/src/test/java/com/arangodb/ArangoDatabaseTest.java @@ -941,6 +941,9 @@ void queryAllowDirtyRead(ArangoDatabase db) throws IOException { final ArangoCursor cursor = db.query("FOR i IN @@col FILTER i.test == @test RETURN i", new MapBuilder().put("@col", CNAME1).put("test", null).get(), new AqlQueryOptions().allowDirtyRead(true), BaseDocument.class); + if (isAtLeastVersion(3, 10)) { + assertThat(cursor.isPotentialDirtyRead()).isTrue(); + } cursor.close(); } diff --git a/src/test/java/com/arangodb/StreamTransactionTest.java b/src/test/java/com/arangodb/StreamTransactionTest.java index e4f1ef24c..3b47d9222 100644 --- a/src/test/java/com/arangodb/StreamTransactionTest.java +++ b/src/test/java/com/arangodb/StreamTransactionTest.java @@ -26,6 +26,7 @@ import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.MethodSource; +import java.io.IOException; import java.util.*; import java.util.stream.Collectors; import java.util.stream.IntStream; @@ -785,4 +786,35 @@ void transactionAllowImplicitFalse(ArangoDatabase db) { db.abortStreamTransaction(tx.getId()); } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void transactionDirtyRead(ArangoDatabase db) throws IOException { + assumeTrue(isCluster()); + assumeTrue(isAtLeastVersion(3, 10)); + + ArangoCollection collection = db.collection(COLLECTION_NAME); + DocumentCreateEntity doc = collection.insertDocument(new BaseDocument()); + + StreamTransactionEntity tx = db + .beginStreamTransaction(new StreamTransactionOptions() + .readCollections(COLLECTION_NAME) + .allowDirtyRead(true)); + + MultiDocumentEntity readDocs = collection.getDocuments(Collections.singletonList(doc.getKey()), + BaseDocument.class, + new DocumentReadOptions().streamTransactionId(tx.getId())); + + assertThat(readDocs.isPotentialDirtyRead()).isTrue(); + assertThat(readDocs.getDocuments()).hasSize(1); + + final ArangoCursor cursor = db.query("FOR i IN @@col RETURN i", + Collections.singletonMap("@col", COLLECTION_NAME), + new AqlQueryOptions().streamTransactionId(tx.getId()), BaseDocument.class); + assertThat(cursor.isPotentialDirtyRead()).isTrue(); + cursor.close(); + + db.abortStreamTransaction(tx.getId()); + } + } From c0e2bb66f2360e4d4a36639065c7c95bfbabde44 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Wed, 14 Sep 2022 12:51:19 +0200 Subject: [PATCH 121/254] [DE-382] inverted index (#457) * updated fulltext index deprecation note * added AnalyzerFeature.offset * InvertedIndexOptions * create InvertedIndex sync * get InvertedIndex sync * test fixes * async API (cherry picked from commit 72809067455663b6678dff05010d5369dc6777ee) --- .../java/com/arangodb/ArangoCollection.java | 42 +++- .../arangodb/async/ArangoCollectionAsync.java | 39 ++- .../internal/ArangoCollectionAsyncImpl.java | 15 ++ .../async/internal/ArangoDBAsyncImpl.java | 5 +- .../java/com/arangodb/entity/IndexType.java | 9 +- .../arangodb/entity/InvertedIndexEntity.java | 154 ++++++++++++ .../arangodb/entity/InvertedIndexField.java | 98 ++++++++ .../entity/InvertedIndexPrimarySort.java | 92 +++++++ .../entity/arangosearch/AnalyzerFeature.java | 10 +- .../arangosearch/ConsolidationPolicy.java | 14 ++ .../entity/arangosearch/StoredValue.java | 13 + .../internal/ArangoCollectionImpl.java | 15 ++ .../internal/InternalArangoCollection.java | 35 ++- .../internal/serde/InternalDeserializers.java | 17 ++ .../internal/serde/InternalModule.java | 2 + .../arangodb/model/FulltextIndexOptions.java | 2 +- .../arangodb/model/InvertedIndexOptions.java | 226 ++++++++++++++++++ .../model/StreamTransactionOptions.java | 4 +- .../java/com/arangodb/ArangoSearchTest.java | 20 ++ .../java/com/arangodb/InvertedIndexTest.java | 188 +++++++++++++++ .../com/arangodb/async/InvertedIndexTest.java | 199 +++++++++++++++ src/test/resources/logback-test.xml | 2 +- 22 files changed, 1186 insertions(+), 15 deletions(-) create mode 100644 src/main/java/com/arangodb/entity/InvertedIndexEntity.java create mode 100644 src/main/java/com/arangodb/entity/InvertedIndexField.java create mode 100644 src/main/java/com/arangodb/entity/InvertedIndexPrimarySort.java create mode 100644 src/main/java/com/arangodb/model/InvertedIndexOptions.java create mode 100644 src/test/java/com/arangodb/InvertedIndexTest.java create mode 100644 src/test/java/com/arangodb/async/InvertedIndexTest.java diff --git a/src/main/java/com/arangodb/ArangoCollection.java b/src/main/java/com/arangodb/ArangoCollection.java index ca6171a34..3d05f293c 100644 --- a/src/main/java/com/arangodb/ArangoCollection.java +++ b/src/main/java/com/arangodb/ArangoCollection.java @@ -579,6 +579,9 @@ MultiDocumentEntity> deleteDocuments( /** * Fetches information about the index with the given {@code id} and returns it. + *
    + * Note: inverted indexes are not returned by this method. Use + * {@link ArangoCollection#getInvertedIndex(String)} instead. * * @param id The index-handle * @return information about the index @@ -587,6 +590,17 @@ MultiDocumentEntity> deleteDocuments( */ IndexEntity getIndex(String id); + /** + * Fetches information about the inverted index with the given {@code id} and returns it. + * + * @param id The index-handle + * @return information about the index + * @throws ArangoDBException + * @see API Documentation + * @since ArangoDB 3.10 + */ + InvertedIndexEntity getInvertedIndex(String id) throws ArangoDBException; + /** * Deletes the index with the given {@code id} from the collection. * @@ -655,7 +669,7 @@ MultiDocumentEntity> deleteDocuments( * @return information about the index * @see API * Documentation - * @deprecated since ArangoDB 3.10, use ArangoSearch view instead. + * @deprecated since ArangoDB 3.10, use ArangoSearch or Inverted indexes instead. */ @Deprecated IndexEntity ensureFulltextIndex(Iterable fields, FulltextIndexOptions options); @@ -683,8 +697,22 @@ MultiDocumentEntity> deleteDocuments( */ IndexEntity ensureZKDIndex(Iterable fields, ZKDIndexOptions options); + /** + * Creates an inverted index for the collection, if it does not already exist. + * + * @param options index creation options + * @return information about the index + * @throws ArangoDBException + * @see API Documentation + * @since ArangoDB 3.10 + */ + InvertedIndexEntity ensureInvertedIndex(InvertedIndexOptions options) throws ArangoDBException; + /** * Fetches a list of all indexes on this collection. + *
    + * Note: inverted indexes are not returned by this method. Use + * {@link ArangoCollection#getInvertedIndexes()} instead. * * @return information about the indexes * @see MultiDocumentEntity> deleteDocuments( */ Collection getIndexes(); + /** + * Fetches a list of all inverted indexes on this collection. + * + * @return information about the indexes + * @throws ArangoDBException + * @see API + * Documentation + * @since ArangoDB 3.10 + */ + Collection getInvertedIndexes() throws ArangoDBException; + /** * Checks whether the collection exists * diff --git a/src/main/java/com/arangodb/async/ArangoCollectionAsync.java b/src/main/java/com/arangodb/async/ArangoCollectionAsync.java index c62490484..ad04dc5bf 100644 --- a/src/main/java/com/arangodb/async/ArangoCollectionAsync.java +++ b/src/main/java/com/arangodb/async/ArangoCollectionAsync.java @@ -619,6 +619,9 @@ CompletableFuture>> deleteDocume /** * Returns an index + *
    + * Note: inverted indexes are not returned by this method. Use + * {@link ArangoCollectionAsync#getInvertedIndex(String)} instead. * * @param id The index-handle * @return information about the index @@ -627,6 +630,16 @@ CompletableFuture>> deleteDocume */ CompletableFuture getIndex(final String id); + /** + * Returns an inverted index + * + * @param id The index-handle + * @return information about the index + * @see API Documentation + * @since ArangoDB 3.10 + */ + CompletableFuture getInvertedIndex(String id); + /** * Deletes an index * @@ -699,7 +712,7 @@ CompletableFuture ensurePersistentIndex( * @return information about the index * @see API * Documentation - * @deprecated since ArangoDB 3.10, use ArangoSearch view instead. + * @deprecated since ArangoDB 3.10, use ArangoSearch or Inverted indexes instead. */ @Deprecated CompletableFuture ensureFulltextIndex( @@ -729,8 +742,21 @@ CompletableFuture ensureFulltextIndex( */ CompletableFuture ensureZKDIndex(final Iterable fields, final ZKDIndexOptions options); + /** + * Creates an inverted index for the collection, if it does not already exist. + * + * @param options index creation options + * @return information about the index + * @see API Documentation + * @since ArangoDB 3.10 + */ + CompletableFuture ensureInvertedIndex(InvertedIndexOptions options); + /** * Returns all indexes of the collection + *
    + * Note: inverted indexes are not returned by this method. Use + * {@link ArangoCollectionAsync#getInvertedIndexes()} instead. * * @return information about the indexes * @see ensureFulltextIndex( */ CompletableFuture> getIndexes(); + /** + * Fetches a list of all inverted indexes on this collection. + * + * @return information about the indexes + * @see API + * Documentation + * @since ArangoDB 3.10 + */ + CompletableFuture> getInvertedIndexes(); + /** * Checks whether the collection exists * diff --git a/src/main/java/com/arangodb/async/internal/ArangoCollectionAsyncImpl.java b/src/main/java/com/arangodb/async/internal/ArangoCollectionAsyncImpl.java index 78ae21f9a..a850af8db 100644 --- a/src/main/java/com/arangodb/async/internal/ArangoCollectionAsyncImpl.java +++ b/src/main/java/com/arangodb/async/internal/ArangoCollectionAsyncImpl.java @@ -351,6 +351,11 @@ public CompletableFuture getIndex(final String id) { return executor.execute(getIndexRequest(id), IndexEntity.class); } + @Override + public CompletableFuture getInvertedIndex(String id) { + return executor.execute(getIndexRequest(id), InvertedIndexEntity.class); + } + @Override public CompletableFuture deleteIndex(final String id) { return executor.execute(deleteIndexRequest(id), deleteIndexResponseDeserializer()); @@ -404,11 +409,21 @@ public CompletableFuture ensureZKDIndex( return executor.execute(createZKDIndexRequest(fields, options), IndexEntity.class); } + @Override + public CompletableFuture ensureInvertedIndex(InvertedIndexOptions options) { + return executor.execute(createInvertedIndexRequest(options), InvertedIndexEntity.class); + } + @Override public CompletableFuture> getIndexes() { return executor.execute(getIndexesRequest(), getIndexesResponseDeserializer()); } + @Override + public CompletableFuture> getInvertedIndexes() { + return executor.execute(getIndexesRequest(), getInvertedIndexesResponseDeserializer()); + } + @Override public CompletableFuture exists() { return getInfo().thenApply(Objects::nonNull).exceptionally(Objects::isNull); diff --git a/src/main/java/com/arangodb/async/internal/ArangoDBAsyncImpl.java b/src/main/java/com/arangodb/async/internal/ArangoDBAsyncImpl.java index 364d760fc..fb7f1d8a8 100644 --- a/src/main/java/com/arangodb/async/internal/ArangoDBAsyncImpl.java +++ b/src/main/java/com/arangodb/async/internal/ArangoDBAsyncImpl.java @@ -31,6 +31,7 @@ import com.arangodb.internal.net.HostHandler; import com.arangodb.internal.net.HostResolver; import com.arangodb.internal.serde.InternalSerde; +import com.arangodb.internal.serde.SerdeUtils; import com.arangodb.internal.velocystream.VstCommunication; import com.arangodb.internal.velocystream.VstCommunicationSync; import com.arangodb.internal.velocystream.VstProtocol; @@ -39,7 +40,6 @@ import com.arangodb.model.LogOptions; import com.arangodb.model.UserCreateOptions; import com.arangodb.model.UserUpdateOptions; -import com.arangodb.velocypack.Type; import com.arangodb.velocystream.Request; import com.arangodb.velocystream.Response; import org.slf4j.Logger; @@ -237,8 +237,7 @@ public CompletableFuture setLogLevel(final LogLevelEntity entity @Override public CompletableFuture> getQueryOptimizerRules() { - return executor.execute(getQueryOptimizerRulesRequest(), new Type>() { - }.getType()); + return executor.execute(getQueryOptimizerRulesRequest(), SerdeUtils.constructListType(QueryOptimizerRule.class)); } } diff --git a/src/main/java/com/arangodb/entity/IndexType.java b/src/main/java/com/arangodb/entity/IndexType.java index 26a048cb0..3fbd025c3 100644 --- a/src/main/java/com/arangodb/entity/IndexType.java +++ b/src/main/java/com/arangodb/entity/IndexType.java @@ -41,7 +41,7 @@ public enum IndexType { geo2, /** - * @deprecated since ArangoDB 3.10, use ArangoSearch view instead. + * @deprecated since ArangoDB 3.10, use ArangoSearch or Inverted indexes instead. */ @Deprecated fulltext, @@ -50,5 +50,10 @@ public enum IndexType { ttl, - zkd + zkd, + + /** + * @since ArangoDB 3.10 + */ + inverted } diff --git a/src/main/java/com/arangodb/entity/InvertedIndexEntity.java b/src/main/java/com/arangodb/entity/InvertedIndexEntity.java new file mode 100644 index 000000000..d656c525a --- /dev/null +++ b/src/main/java/com/arangodb/entity/InvertedIndexEntity.java @@ -0,0 +1,154 @@ +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed 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. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.entity; + +import com.arangodb.entity.arangosearch.AnalyzerFeature; +import com.arangodb.entity.arangosearch.ConsolidationPolicy; +import com.arangodb.entity.arangosearch.StoredValue; + +import java.util.Collection; +import java.util.Set; + +/** + * TODO: add documentation + * + * @author Michele Rastelli + * @see API Documentation + * @since ArangoDB 3.10 + */ +public class InvertedIndexEntity { + + private String id; + private Boolean isNewlyCreated; + private Boolean unique; + private Boolean sparse; + private Long version; + private Integer code; + private IndexType type; + private String name; + private Collection fields; + private Boolean searchField; + private Collection storedValues; + private InvertedIndexPrimarySort primarySort; + private String analyzer; + private Set features; + private Boolean includeAllFields; + private Boolean trackListPositions; + private Long cleanupIntervalStep; + private Long commitIntervalMsec; + private Long consolidationIntervalMsec; + private ConsolidationPolicy consolidationPolicy; + private Long writebufferIdle; + private Long writebufferActive; + private Long writebufferSizeMax; + + public String getId() { + return id; + } + + public Boolean getIsNewlyCreated() { + return isNewlyCreated; + } + + public Boolean getUnique() { + return unique; + } + + public Boolean getSparse() { + return sparse; + } + + public Long getVersion() { + return version; + } + + public Integer getCode() { + return code; + } + + public IndexType getType() { + return type; + } + + public String getName() { + return name; + } + + public Collection getFields() { + return fields; + } + + public Boolean getSearchField() { + return searchField; + } + + public Collection getStoredValues() { + return storedValues; + } + + public InvertedIndexPrimarySort getPrimarySort() { + return primarySort; + } + + public String getAnalyzer() { + return analyzer; + } + + public Set getFeatures() { + return features; + } + + public Boolean getIncludeAllFields() { + return includeAllFields; + } + + public Boolean getTrackListPositions() { + return trackListPositions; + } + + public Long getCleanupIntervalStep() { + return cleanupIntervalStep; + } + + public Long getCommitIntervalMsec() { + return commitIntervalMsec; + } + + public Long getConsolidationIntervalMsec() { + return consolidationIntervalMsec; + } + + public ConsolidationPolicy getConsolidationPolicy() { + return consolidationPolicy; + } + + public Long getWritebufferIdle() { + return writebufferIdle; + } + + public Long getWritebufferActive() { + return writebufferActive; + } + + public Long getWritebufferSizeMax() { + return writebufferSizeMax; + } +} diff --git a/src/main/java/com/arangodb/entity/InvertedIndexField.java b/src/main/java/com/arangodb/entity/InvertedIndexField.java new file mode 100644 index 000000000..48512d239 --- /dev/null +++ b/src/main/java/com/arangodb/entity/InvertedIndexField.java @@ -0,0 +1,98 @@ +package com.arangodb.entity; + +import com.arangodb.entity.arangosearch.AnalyzerFeature; + +import java.util.*; + +/** + * TODO: add documentation + * + * @author Michele Rastelli + * @see API Documentation + * @since ArangoDB 3.10 + */ +public class InvertedIndexField { + private String name; + private String analyzer; + private Boolean includeAllFields; + private Boolean searchField; + private Boolean trackListPositions; + private final Set features = new HashSet<>(); + private final Collection nested = new ArrayList<>(); + + public String getName() { + return name; + } + + public InvertedIndexField name(String name) { + this.name = name; + return this; + } + + public String getAnalyzer() { + return analyzer; + } + + public InvertedIndexField analyzer(String analyzer) { + this.analyzer = analyzer; + return this; + } + + public Boolean getIncludeAllFields() { + return includeAllFields; + } + + public InvertedIndexField includeAllFields(Boolean includeAllFields) { + this.includeAllFields = includeAllFields; + return this; + } + + public Boolean getSearchField() { + return searchField; + } + + public InvertedIndexField searchField(Boolean searchField) { + this.searchField = searchField; + return this; + } + + public Boolean getTrackListPositions() { + return trackListPositions; + } + + public InvertedIndexField trackListPositions(Boolean trackListPositions) { + this.trackListPositions = trackListPositions; + return this; + } + + public Set getFeatures() { + return features; + } + + public InvertedIndexField features(AnalyzerFeature... features) { + Collections.addAll(this.features, features); + return this; + } + + public Collection getNested() { + return nested; + } + + public InvertedIndexField nested(InvertedIndexField... nested) { + Collections.addAll(this.nested, nested); + return this; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + InvertedIndexField that = (InvertedIndexField) o; + return Objects.equals(name, that.name) && Objects.equals(analyzer, that.analyzer) && Objects.equals(includeAllFields, that.includeAllFields) && Objects.equals(searchField, that.searchField) && Objects.equals(trackListPositions, that.trackListPositions) && Objects.equals(features, that.features) && Objects.equals(nested, that.nested); + } + + @Override + public int hashCode() { + return Objects.hash(name, analyzer, includeAllFields, searchField, trackListPositions, features, nested); + } +} diff --git a/src/main/java/com/arangodb/entity/InvertedIndexPrimarySort.java b/src/main/java/com/arangodb/entity/InvertedIndexPrimarySort.java new file mode 100644 index 000000000..bfb812fe5 --- /dev/null +++ b/src/main/java/com/arangodb/entity/InvertedIndexPrimarySort.java @@ -0,0 +1,92 @@ +package com.arangodb.entity; + +import com.arangodb.entity.arangosearch.ArangoSearchCompression; +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Objects; + +/** + * TODO: add documentation + * + * @author Michele Rastelli + * @see API Documentation + * @since ArangoDB 3.10 + */ +public class InvertedIndexPrimarySort { + private final List fields = new ArrayList<>(); + private ArangoSearchCompression compression; + + public List getFields() { + return fields; + } + + public InvertedIndexPrimarySort fields(Field... fields) { + Collections.addAll(this.fields, fields); + return this; + } + + public ArangoSearchCompression getCompression() { + return compression; + } + + public InvertedIndexPrimarySort compression(ArangoSearchCompression compression) { + this.compression = compression; + return this; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + InvertedIndexPrimarySort that = (InvertedIndexPrimarySort) o; + return Objects.equals(fields, that.fields) && compression == that.compression; + } + + @Override + public int hashCode() { + return Objects.hash(fields, compression); + } + + public static class Field { + private final String field; + private final Direction direction; + + @JsonCreator + public Field(@JsonProperty("field") String field, @JsonProperty("direction") Direction direction) { + this.field = field; + this.direction = direction; + } + + public String getField() { + return field; + } + + public Direction getDirection() { + return direction; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + Field field1 = (Field) o; + return Objects.equals(field, field1.field) && direction == field1.direction; + } + + @Override + public int hashCode() { + return Objects.hash(field, direction); + } + + public enum Direction { + asc, + desc + } + + } + +} diff --git a/src/main/java/com/arangodb/entity/arangosearch/AnalyzerFeature.java b/src/main/java/com/arangodb/entity/arangosearch/AnalyzerFeature.java index 8482c8b46..c06d8945f 100644 --- a/src/main/java/com/arangodb/entity/arangosearch/AnalyzerFeature.java +++ b/src/main/java/com/arangodb/entity/arangosearch/AnalyzerFeature.java @@ -39,8 +39,14 @@ public enum AnalyzerFeature { /** * sequentially increasing term position, required for PHRASE(). If present then the frequency feature is also - * required + * required. */ - position + position, + + /** + * enable search highlighting capabilities (Enterprise Edition only). If present, then the `position` and `frequency` features are also required. + * @since ArangoDB 3.10 + */ + offset } diff --git a/src/main/java/com/arangodb/entity/arangosearch/ConsolidationPolicy.java b/src/main/java/com/arangodb/entity/arangosearch/ConsolidationPolicy.java index d06f1b1a4..d3b117b84 100644 --- a/src/main/java/com/arangodb/entity/arangosearch/ConsolidationPolicy.java +++ b/src/main/java/com/arangodb/entity/arangosearch/ConsolidationPolicy.java @@ -20,6 +20,8 @@ package com.arangodb.entity.arangosearch; +import java.util.Objects; + /** * @author Mark Vollmary */ @@ -74,4 +76,16 @@ public Long getSegmentThreshold() { return segmentThreshold; } + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + ConsolidationPolicy that = (ConsolidationPolicy) o; + return type == that.type && Objects.equals(threshold, that.threshold) && Objects.equals(segmentThreshold, that.segmentThreshold); + } + + @Override + public int hashCode() { + return Objects.hash(type, threshold, segmentThreshold); + } } diff --git a/src/main/java/com/arangodb/entity/arangosearch/StoredValue.java b/src/main/java/com/arangodb/entity/arangosearch/StoredValue.java index c25a31e70..98373653c 100644 --- a/src/main/java/com/arangodb/entity/arangosearch/StoredValue.java +++ b/src/main/java/com/arangodb/entity/arangosearch/StoredValue.java @@ -25,6 +25,7 @@ import com.fasterxml.jackson.annotation.JsonProperty; import java.util.List; +import java.util.Objects; /** * @author Michele Rastelli @@ -63,4 +64,16 @@ public ArangoSearchCompression getCompression() { return compression; } + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + StoredValue that = (StoredValue) o; + return Objects.equals(fields, that.fields) && compression == that.compression; + } + + @Override + public int hashCode() { + return Objects.hash(fields, compression); + } } diff --git a/src/main/java/com/arangodb/internal/ArangoCollectionImpl.java b/src/main/java/com/arangodb/internal/ArangoCollectionImpl.java index 61e4d679d..aa26cd931 100644 --- a/src/main/java/com/arangodb/internal/ArangoCollectionImpl.java +++ b/src/main/java/com/arangodb/internal/ArangoCollectionImpl.java @@ -349,6 +349,11 @@ public IndexEntity getIndex(final String id) { return executor.execute(getIndexRequest(id), IndexEntity.class); } + @Override + public InvertedIndexEntity getInvertedIndex(String id) throws ArangoDBException { + return executor.execute(getIndexRequest(id), InvertedIndexEntity.class); + } + @Override public String deleteIndex(final String id) { return executor.execute(deleteIndexRequest(id), deleteIndexResponseDeserializer()); @@ -371,6 +376,11 @@ public IndexEntity ensurePersistentIndex(final Iterable fields, final Pe return executor.execute(createPersistentIndexRequest(fields, options), IndexEntity.class); } + @Override + public InvertedIndexEntity ensureInvertedIndex(final InvertedIndexOptions options) throws ArangoDBException { + return executor.execute(createInvertedIndexRequest(options), InvertedIndexEntity.class); + } + @Override public IndexEntity ensureGeoIndex(final Iterable fields, final GeoIndexOptions options) { return executor.execute(createGeoIndexRequest(fields, options), IndexEntity.class); @@ -397,6 +407,11 @@ public Collection getIndexes() { return executor.execute(getIndexesRequest(), getIndexesResponseDeserializer()); } + @Override + public Collection getInvertedIndexes() throws ArangoDBException { + return executor.execute(getIndexesRequest(), getInvertedIndexesResponseDeserializer()); + } + @Override public boolean exists() { try { diff --git a/src/main/java/com/arangodb/internal/InternalArangoCollection.java b/src/main/java/com/arangodb/internal/InternalArangoCollection.java index 4028c3202..ea5d283ce 100644 --- a/src/main/java/com/arangodb/internal/InternalArangoCollection.java +++ b/src/main/java/com/arangodb/internal/InternalArangoCollection.java @@ -35,6 +35,7 @@ import java.lang.reflect.Type; import java.util.ArrayList; import java.util.Collection; +import java.util.Iterator; import static com.arangodb.internal.serde.SerdeUtils.constructListType; import static com.arangodb.internal.serde.SerdeUtils.constructParametricType; @@ -458,6 +459,13 @@ protected Request createPersistentIndexRequest( return request; } + protected Request createInvertedIndexRequest(final InvertedIndexOptions options) { + final Request request = request(db.dbName(), RequestType.POST, PATH_API_INDEX); + request.putQueryParam(COLLECTION, name); + request.setBody(getSerde().serialize(options)); + return request; + } + protected Request createGeoIndexRequest(final Iterable fields, final GeoIndexOptions options) { final Request request = request(db.dbName(), RequestType.POST, PATH_API_INDEX); request.putQueryParam(COLLECTION, name); @@ -500,8 +508,31 @@ protected Request getIndexesRequest() { } protected ResponseDeserializer> getIndexesResponseDeserializer() { - return response -> getSerde().deserialize(response.getBody(), "/indexes", - constructListType(IndexEntity.class)); + return response -> { + Collection indexes = new ArrayList<>(); + final Iterator it = getSerde().parse(response.getBody(), "/indexes").iterator(); + while (it.hasNext()) { + JsonNode idx = it.next(); + if (!"inverted".equals(idx.get("type").textValue())) { + indexes.add(getSerde().deserialize(idx, IndexEntity.class)); + } + } + return indexes; + }; + } + + protected ResponseDeserializer> getInvertedIndexesResponseDeserializer() { + return response -> { + Collection indexes = new ArrayList<>(); + final Iterator it = getSerde().parse(response.getBody(), "/indexes").iterator(); + while (it.hasNext()) { + JsonNode idx = it.next(); + if ("inverted".equals(idx.get("type").textValue())) { + indexes.add(getSerde().deserialize(idx, InvertedIndexEntity.class)); + } + } + return indexes; + }; } protected Request truncateRequest(final CollectionTruncateOptions options) { diff --git a/src/main/java/com/arangodb/internal/serde/InternalDeserializers.java b/src/main/java/com/arangodb/internal/serde/InternalDeserializers.java index b5e2ee5e7..6abb792ce 100644 --- a/src/main/java/com/arangodb/internal/serde/InternalDeserializers.java +++ b/src/main/java/com/arangodb/internal/serde/InternalDeserializers.java @@ -2,6 +2,7 @@ import com.arangodb.entity.CollectionStatus; import com.arangodb.entity.CollectionType; +import com.arangodb.entity.InvertedIndexPrimarySort; import com.arangodb.entity.ReplicationFactor; import com.arangodb.entity.arangosearch.CollectionLink; import com.arangodb.entity.arangosearch.FieldLink; @@ -32,6 +33,7 @@ public RawJson deserialize(JsonParser p, DeserializationContext ctxt) throws IOE return RawJson.of(SerdeUtils.INSTANCE.writeJson(p.readValueAsTree())); } }; + static final JsonDeserializer RAW_BYTES_DESERIALIZER = new JsonDeserializer() { @Override public RawBytes deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { @@ -43,18 +45,21 @@ public RawBytes deserialize(JsonParser p, DeserializationContext ctxt) throws IO return RawBytes.of(os.toByteArray()); } }; + static final JsonDeserializer COLLECTION_STATUS = new JsonDeserializer() { @Override public CollectionStatus deserialize(final JsonParser p, final DeserializationContext ctxt) throws IOException { return CollectionStatus.fromStatus(p.getIntValue()); } }; + static final JsonDeserializer COLLECTION_TYPE = new JsonDeserializer() { @Override public CollectionType deserialize(final JsonParser p, final DeserializationContext ctxt) throws IOException { return CollectionType.fromType(p.getIntValue()); } }; + static final JsonDeserializer REPLICATION_FACTOR = new JsonDeserializer() { @Override public ReplicationFactor deserialize(final JsonParser p, final DeserializationContext ctxt) throws IOException { @@ -66,6 +71,7 @@ public ReplicationFactor deserialize(final JsonParser p, final DeserializationCo } else throw new IllegalArgumentException(); } }; + @SuppressWarnings("unchecked") static final JsonDeserializer RESPONSE = new JsonDeserializer() { @Override @@ -82,6 +88,17 @@ public Response deserialize(final JsonParser p, final DeserializationContext ctx } }; + static final JsonDeserializer INVERTED_INDEX_PRIMARY_SORT_FIELD = new JsonDeserializer() { + @Override + public InvertedIndexPrimarySort.Field deserialize(final JsonParser p, final DeserializationContext ctxt) throws IOException { + ObjectNode tree = p.readValueAsTree(); + String field = tree.get("field").textValue(); + InvertedIndexPrimarySort.Field.Direction direction = tree.get("asc").booleanValue() ? + InvertedIndexPrimarySort.Field.Direction.asc : InvertedIndexPrimarySort.Field.Direction.desc; + return new InvertedIndexPrimarySort.Field(field, direction); + } + }; + private InternalDeserializers() { } diff --git a/src/main/java/com/arangodb/internal/serde/InternalModule.java b/src/main/java/com/arangodb/internal/serde/InternalModule.java index 3fd5802aa..2e35e5b64 100644 --- a/src/main/java/com/arangodb/internal/serde/InternalModule.java +++ b/src/main/java/com/arangodb/internal/serde/InternalModule.java @@ -2,6 +2,7 @@ import com.arangodb.entity.CollectionStatus; import com.arangodb.entity.CollectionType; +import com.arangodb.entity.InvertedIndexPrimarySort; import com.arangodb.entity.ReplicationFactor; import com.arangodb.internal.velocystream.internal.AuthenticationRequest; import com.arangodb.internal.velocystream.internal.JwtAuthenticationRequest; @@ -35,6 +36,7 @@ enum InternalModule implements Supplier { module.addDeserializer(CollectionType.class, InternalDeserializers.COLLECTION_TYPE); module.addDeserializer(ReplicationFactor.class, InternalDeserializers.REPLICATION_FACTOR); module.addDeserializer(Response.class, InternalDeserializers.RESPONSE); + module.addDeserializer(InvertedIndexPrimarySort.Field.class, InternalDeserializers.INVERTED_INDEX_PRIMARY_SORT_FIELD); } @Override diff --git a/src/main/java/com/arangodb/model/FulltextIndexOptions.java b/src/main/java/com/arangodb/model/FulltextIndexOptions.java index 84fadca34..84735b5b0 100644 --- a/src/main/java/com/arangodb/model/FulltextIndexOptions.java +++ b/src/main/java/com/arangodb/model/FulltextIndexOptions.java @@ -26,7 +26,7 @@ * @author Mark Vollmary * @see API * Documentation - * @deprecated since ArangoDB 3.10, use ArangoSearch view instead. + * @deprecated since ArangoDB 3.10, use ArangoSearch or Inverted indexes instead. */ @Deprecated public final class FulltextIndexOptions extends IndexOptions { diff --git a/src/main/java/com/arangodb/model/InvertedIndexOptions.java b/src/main/java/com/arangodb/model/InvertedIndexOptions.java new file mode 100644 index 000000000..f8335424f --- /dev/null +++ b/src/main/java/com/arangodb/model/InvertedIndexOptions.java @@ -0,0 +1,226 @@ +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed 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. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.model; + +import com.arangodb.entity.IndexType; +import com.arangodb.entity.InvertedIndexField; +import com.arangodb.entity.InvertedIndexPrimarySort; +import com.arangodb.entity.arangosearch.*; + +import java.util.*; + +/** + * TODO: add documentation + * + * @author Michele Rastelli + * @see API Documentation + * @since ArangoDB 3.10 + */ +public class InvertedIndexOptions extends IndexOptions { + + protected final IndexType type = IndexType.inverted; + private Integer parallelism; + private InvertedIndexPrimarySort primarySort; + private final Collection storedValues = new ArrayList<>(); + private String analyzer; + private final Set features = new HashSet<>(); + private Boolean includeAllFields; + private Boolean trackListPositions; + private Boolean searchField; + private final Collection fields = new ArrayList<>(); + private Long consolidationIntervalMsec; + private Long commitIntervalMsec; + private Long cleanupIntervalStep; + private ConsolidationPolicy consolidationPolicy; + private Long writebufferIdle; + private Long writebufferActive; + private Long writebufferSizeMax; + + public InvertedIndexOptions() { + super(); + } + + @Override + protected InvertedIndexOptions getThis() { + return this; + } + + public IndexType getType() { + return type; + } + + public Integer getParallelism() { + return parallelism; + } + + public InvertedIndexOptions parallelism(Integer parallelism) { + this.parallelism = parallelism; + return this; + } + + public InvertedIndexPrimarySort getPrimarySort() { + return primarySort; + } + + public InvertedIndexOptions primarySort(InvertedIndexPrimarySort primarySort) { + this.primarySort = primarySort; + return this; + } + + public Collection getStoredValues() { + return storedValues; + } + + public InvertedIndexOptions storedValues(StoredValue... storedValues) { + Collections.addAll(this.storedValues, storedValues); + return this; + } + + public String getAnalyzer() { + return analyzer; + } + + public InvertedIndexOptions analyzer(String analyzer) { + this.analyzer = analyzer; + return this; + } + + public Set getFeatures() { + return features; + } + + public InvertedIndexOptions features(AnalyzerFeature... features) { + Collections.addAll(this.features, features); + return this; + } + + public Boolean getIncludeAllFields() { + return includeAllFields; + } + + public InvertedIndexOptions includeAllFields(Boolean includeAllFields) { + this.includeAllFields = includeAllFields; + return this; + } + + public Boolean getTrackListPositions() { + return trackListPositions; + } + + public InvertedIndexOptions trackListPositions(Boolean trackListPositions) { + this.trackListPositions = trackListPositions; + return this; + } + + public Boolean getSearchField() { + return searchField; + } + + public InvertedIndexOptions searchField(Boolean searchField) { + this.searchField = searchField; + return this; + } + + public Collection getFields() { + return fields; + } + + public InvertedIndexOptions fields(InvertedIndexField... fields) { + Collections.addAll(this.fields, fields); + return this; + } + + public Long getConsolidationIntervalMsec() { + return consolidationIntervalMsec; + } + + public InvertedIndexOptions consolidationIntervalMsec(Long consolidationIntervalMsec) { + this.consolidationIntervalMsec = consolidationIntervalMsec; + return this; + } + + public Long getCommitIntervalMsec() { + return commitIntervalMsec; + } + + public InvertedIndexOptions commitIntervalMsec(Long commitIntervalMsec) { + this.commitIntervalMsec = commitIntervalMsec; + return this; + } + + public Long getCleanupIntervalStep() { + return cleanupIntervalStep; + } + + public InvertedIndexOptions cleanupIntervalStep(Long cleanupIntervalStep) { + this.cleanupIntervalStep = cleanupIntervalStep; + return this; + } + + public ConsolidationPolicy getConsolidationPolicy() { + return consolidationPolicy; + } + + public InvertedIndexOptions consolidationPolicy(ConsolidationPolicy consolidationPolicy) { + this.consolidationPolicy = consolidationPolicy; + return this; + } + + public Long getWritebufferIdle() { + return writebufferIdle; + } + + public InvertedIndexOptions writebufferIdle(Long writebufferIdle) { + this.writebufferIdle = writebufferIdle; + return this; + } + + public Long getWritebufferActive() { + return writebufferActive; + } + + public InvertedIndexOptions writebufferActive(Long writebufferActive) { + this.writebufferActive = writebufferActive; + return this; + } + + public Long getWritebufferSizeMax() { + return writebufferSizeMax; + } + + public InvertedIndexOptions writebufferSizeMax(Long writebufferSizeMax) { + this.writebufferSizeMax = writebufferSizeMax; + return this; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + InvertedIndexOptions that = (InvertedIndexOptions) o; + return type == that.type && Objects.equals(parallelism, that.parallelism) && Objects.equals(primarySort, that.primarySort) && Objects.equals(storedValues, that.storedValues) && Objects.equals(analyzer, that.analyzer) && Objects.equals(features, that.features) && Objects.equals(includeAllFields, that.includeAllFields) && Objects.equals(trackListPositions, that.trackListPositions) && Objects.equals(searchField, that.searchField) && Objects.equals(fields, that.fields) && Objects.equals(consolidationIntervalMsec, that.consolidationIntervalMsec) && Objects.equals(commitIntervalMsec, that.commitIntervalMsec) && Objects.equals(cleanupIntervalStep, that.cleanupIntervalStep) && Objects.equals(consolidationPolicy, that.consolidationPolicy) && Objects.equals(writebufferIdle, that.writebufferIdle) && Objects.equals(writebufferActive, that.writebufferActive) && Objects.equals(writebufferSizeMax, that.writebufferSizeMax); + } + + @Override + public int hashCode() { + return Objects.hash(type, parallelism, primarySort, storedValues, analyzer, features, includeAllFields, trackListPositions, searchField, fields, consolidationIntervalMsec, commitIntervalMsec, cleanupIntervalStep, consolidationPolicy, writebufferIdle, writebufferActive, writebufferSizeMax); + } +} diff --git a/src/main/java/com/arangodb/model/StreamTransactionOptions.java b/src/main/java/com/arangodb/model/StreamTransactionOptions.java index deb2e1cf9..a723f4034 100644 --- a/src/main/java/com/arangodb/model/StreamTransactionOptions.java +++ b/src/main/java/com/arangodb/model/StreamTransactionOptions.java @@ -20,7 +20,7 @@ package com.arangodb.model; -import com.arangodb.velocypack.annotations.Expose; +import com.fasterxml.jackson.annotation.JsonIgnore; /** * @author Mark Vollmary @@ -35,7 +35,7 @@ public final class StreamTransactionOptions { private Boolean waitForSync; private Long maxTransactionSize; private Boolean allowImplicit; - @Expose(serialize = false) + @JsonIgnore private Boolean allowDirtyRead; public StreamTransactionOptions() { diff --git a/src/test/java/com/arangodb/ArangoSearchTest.java b/src/test/java/com/arangodb/ArangoSearchTest.java index 3ca5780cb..5fee8b7ed 100644 --- a/src/test/java/com/arangodb/ArangoSearchTest.java +++ b/src/test/java/com/arangodb/ArangoSearchTest.java @@ -728,4 +728,24 @@ void collationAnalyzer(ArangoDatabase db) { } + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void offsetFeature(ArangoDatabase db) { + assumeTrue(isAtLeastVersion(3, 5)); + + String name = "test-" + UUID.randomUUID(); + + Set features = new HashSet<>(); + features.add(AnalyzerFeature.frequency); + features.add(AnalyzerFeature.norm); + features.add(AnalyzerFeature.position); + features.add(AnalyzerFeature.offset); + + IdentityAnalyzer analyzer = new IdentityAnalyzer(); + analyzer.setFeatures(features); + analyzer.setName(name); + + createGetAndDeleteTypedAnalyzer(db, analyzer); + } + } diff --git a/src/test/java/com/arangodb/InvertedIndexTest.java b/src/test/java/com/arangodb/InvertedIndexTest.java new file mode 100644 index 000000000..3a42b941e --- /dev/null +++ b/src/test/java/com/arangodb/InvertedIndexTest.java @@ -0,0 +1,188 @@ +package com.arangodb; + +import com.arangodb.entity.*; +import com.arangodb.entity.arangosearch.*; +import com.arangodb.entity.arangosearch.analyzer.DelimiterAnalyzer; +import com.arangodb.entity.arangosearch.analyzer.DelimiterAnalyzerProperties; +import com.arangodb.model.InvertedIndexOptions; +import com.arangodb.model.PersistentIndexOptions; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +import java.util.*; +import java.util.stream.Stream; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assumptions.assumeTrue; + +public class InvertedIndexTest extends BaseJunit5 { + + private static final String COLLECTION_NAME = "InvertedIndexTest_collection"; + + private static Stream cols() { + return dbsStream().map(db -> db.collection(COLLECTION_NAME)).map(Arguments::of); + } + + @BeforeAll + static void init() { + initCollections(COLLECTION_NAME); + } + + private void createAnalyzer(String analyzerName, ArangoDatabase db) { + Set features = new HashSet<>(); + features.add(AnalyzerFeature.frequency); + features.add(AnalyzerFeature.norm); + features.add(AnalyzerFeature.position); + + DelimiterAnalyzer da = new DelimiterAnalyzer(); + da.setName(analyzerName); + da.setFeatures(features); + DelimiterAnalyzerProperties props = new DelimiterAnalyzerProperties(); + props.setDelimiter("-"); + da.setProperties(props); + + db.createSearchAnalyzer(da); + } + + private InvertedIndexOptions createOptions(String analyzerName) { + InvertedIndexField field = new InvertedIndexField() + .name("foo") + .analyzer(AnalyzerType.identity.toString()) + .includeAllFields(true) + .searchField(false) + .trackListPositions(false) + .features( + AnalyzerFeature.position, + AnalyzerFeature.frequency, + AnalyzerFeature.norm, + AnalyzerFeature.offset + ); + + if (isEnterprise()) { + field.nested( + new InvertedIndexField() + .name("bar") + .analyzer(analyzerName) + .searchField(true) + .features(AnalyzerFeature.position) + .nested( + new InvertedIndexField() + .name("baz") + .analyzer(AnalyzerType.identity.toString()) + .searchField(false) + .features(AnalyzerFeature.frequency) + ) + ); + } + + return new InvertedIndexOptions() + .name("invertedIndex-" + UUID.randomUUID()) + .inBackground(true) + .parallelism(5) + .primarySort(new InvertedIndexPrimarySort() + .fields( + new InvertedIndexPrimarySort.Field("f1", InvertedIndexPrimarySort.Field.Direction.asc), + new InvertedIndexPrimarySort.Field("f2", InvertedIndexPrimarySort.Field.Direction.desc) + ) + .compression(ArangoSearchCompression.lz4) + ) + .storedValues(new StoredValue(Arrays.asList("f3", "f4"), ArangoSearchCompression.none)) + .analyzer(analyzerName) + .features(AnalyzerFeature.position, AnalyzerFeature.frequency) + .includeAllFields(false) + .trackListPositions(true) + .searchField(true) + .fields(field) + .consolidationIntervalMsec(11L) + .commitIntervalMsec(22L) + .cleanupIntervalStep(33L) + .consolidationPolicy(ConsolidationPolicy.of(ConsolidationType.BYTES_ACCUM).threshold(1.)) + .writebufferIdle(44L) + .writebufferActive(55L) + .writebufferSizeMax(66L); + } + + private void assertCorrectIndexEntity(InvertedIndexEntity indexResult, InvertedIndexOptions options) { + assertThat(indexResult).isNotNull(); + assertThat(indexResult.getId()).isNotNull().isNotEmpty(); + // FIXME: in single server this is null + // assertThat(indexResult.getIsNewlyCreated()).isTrue(); + assertThat(indexResult.getUnique()).isFalse(); + assertThat(indexResult.getSparse()).isTrue(); + assertThat(indexResult.getVersion()).isNotNull(); + assertThat(indexResult.getCode()).isNotNull(); + assertThat(indexResult.getType()).isEqualTo(IndexType.inverted); + assertThat(indexResult.getName()).isEqualTo(options.getName()); + assertThat(indexResult.getFields()).containsExactlyElementsOf(options.getFields()); + assertThat(indexResult.getSearchField()).isEqualTo(options.getSearchField()); + assertThat(indexResult.getStoredValues()).containsExactlyElementsOf(options.getStoredValues()); + assertThat(indexResult.getPrimarySort()).isEqualTo(options.getPrimarySort()); + assertThat(indexResult.getAnalyzer()).isEqualTo(options.getAnalyzer()); + assertThat(indexResult.getFeatures()).hasSameElementsAs(options.getFeatures()); + assertThat(indexResult.getIncludeAllFields()).isEqualTo(options.getIncludeAllFields()); + assertThat(indexResult.getTrackListPositions()).isEqualTo(options.getTrackListPositions()); + assertThat(indexResult.getCleanupIntervalStep()).isEqualTo(options.getCleanupIntervalStep()); + assertThat(indexResult.getCommitIntervalMsec()).isEqualTo(options.getCommitIntervalMsec()); + assertThat(indexResult.getConsolidationIntervalMsec()).isEqualTo(options.getConsolidationIntervalMsec()); + assertThat(indexResult.getConsolidationPolicy()).isEqualTo(options.getConsolidationPolicy()); + assertThat(indexResult.getWritebufferIdle()).isEqualTo(options.getWritebufferIdle()); + assertThat(indexResult.getWritebufferActive()).isEqualTo(options.getWritebufferActive()); + assertThat(indexResult.getWritebufferSizeMax()).isEqualTo(options.getWritebufferSizeMax()); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void createAndGetInvertedIndex(ArangoCollection collection) { + assumeTrue(isAtLeastVersion(3, 10)); + String analyzerName = "delimiter-" + UUID.randomUUID(); + createAnalyzer(analyzerName, collection.db()); + InvertedIndexOptions options = createOptions(analyzerName); + InvertedIndexEntity created = collection.ensureInvertedIndex(options); + assertCorrectIndexEntity(created, options); + InvertedIndexEntity loadedIndex = collection.getInvertedIndex(created.getName()); + assertCorrectIndexEntity(loadedIndex, options); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void getInvertedIndexesShouldNotReturnOtherIndexTypes(ArangoCollection collection) { + assumeTrue(isAtLeastVersion(3, 10)); + + // create persistent index + collection.ensurePersistentIndex(Collections.singletonList("foo"), new PersistentIndexOptions().name("persistentIndex")); + + // create inverted index + String analyzerName = "delimiter-" + UUID.randomUUID(); + createAnalyzer(analyzerName, collection.db()); + InvertedIndexOptions options = createOptions(analyzerName); + InvertedIndexEntity created = collection.ensureInvertedIndex(options); + + Collection loadedIndexes = collection.getInvertedIndexes(); + assertThat(loadedIndexes).map(InvertedIndexEntity::getName) + .doesNotContain("persistentIndex") + .contains(created.getName()); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void getIndexesShouldNotReturnInvertedIndexes(ArangoCollection collection) { + assumeTrue(isAtLeastVersion(3, 10)); + + // create persistent index + collection.ensurePersistentIndex(Collections.singletonList("foo"), new PersistentIndexOptions().name("persistentIndex")); + + // create inverted index + String analyzerName = "delimiter-" + UUID.randomUUID(); + createAnalyzer(analyzerName, collection.db()); + InvertedIndexOptions options = createOptions(analyzerName); + InvertedIndexEntity created = collection.ensureInvertedIndex(options); + + Collection loadedIndexes = collection.getIndexes(); + assertThat(loadedIndexes).map(IndexEntity::getName) + .doesNotContain(created.getName()) + .contains("persistentIndex"); + } + +} diff --git a/src/test/java/com/arangodb/async/InvertedIndexTest.java b/src/test/java/com/arangodb/async/InvertedIndexTest.java new file mode 100644 index 000000000..1b9eebe14 --- /dev/null +++ b/src/test/java/com/arangodb/async/InvertedIndexTest.java @@ -0,0 +1,199 @@ +package com.arangodb.async; + +import com.arangodb.entity.*; +import com.arangodb.entity.arangosearch.*; +import com.arangodb.entity.arangosearch.analyzer.DelimiterAnalyzer; +import com.arangodb.entity.arangosearch.analyzer.DelimiterAnalyzerProperties; +import com.arangodb.model.InvertedIndexOptions; +import com.arangodb.model.PersistentIndexOptions; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; + +import java.util.*; +import java.util.concurrent.ExecutionException; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assumptions.assumeTrue; + +public class InvertedIndexTest extends BaseTest { + + private static final String COLLECTION_NAME = "InvertedIndexTestAsync_collection"; + + InvertedIndexTest() throws ExecutionException, InterruptedException { + ArangoCollectionAsync collection = db.collection(COLLECTION_NAME); + if (!collection.exists().get()) { + collection.create().get(); + } + } + + @BeforeAll + static void setup() throws InterruptedException, ExecutionException { + db.createCollection(COLLECTION_NAME, null).get(); + } + + @AfterEach + void teardown() throws InterruptedException, ExecutionException { + db.collection(COLLECTION_NAME).drop().get(); + } + + + private void createAnalyzer(String analyzerName, ArangoDatabaseAsync db) throws ExecutionException, InterruptedException { + Set features = new HashSet<>(); + features.add(AnalyzerFeature.frequency); + features.add(AnalyzerFeature.norm); + features.add(AnalyzerFeature.position); + + DelimiterAnalyzer da = new DelimiterAnalyzer(); + da.setName(analyzerName); + da.setFeatures(features); + DelimiterAnalyzerProperties props = new DelimiterAnalyzerProperties(); + props.setDelimiter("-"); + da.setProperties(props); + + db.createSearchAnalyzer(da).get(); + } + + private InvertedIndexOptions createOptions(String analyzerName) throws ExecutionException, InterruptedException { + InvertedIndexField field = new InvertedIndexField() + .name("foo") + .analyzer(AnalyzerType.identity.toString()) + .includeAllFields(true) + .searchField(false) + .trackListPositions(false) + .features( + AnalyzerFeature.position, + AnalyzerFeature.frequency, + AnalyzerFeature.norm, + AnalyzerFeature.offset + ); + + if (isEnterprise()) { + field.nested( + new InvertedIndexField() + .name("bar") + .analyzer(analyzerName) + .searchField(true) + .features(AnalyzerFeature.position) + .nested( + new InvertedIndexField() + .name("baz") + .analyzer(AnalyzerType.identity.toString()) + .searchField(false) + .features(AnalyzerFeature.frequency) + ) + ); + } + + return new InvertedIndexOptions() + .name("invertedIndex-" + UUID.randomUUID()) + .inBackground(true) + .parallelism(5) + .primarySort(new InvertedIndexPrimarySort() + .fields( + new InvertedIndexPrimarySort.Field("f1", InvertedIndexPrimarySort.Field.Direction.asc), + new InvertedIndexPrimarySort.Field("f2", InvertedIndexPrimarySort.Field.Direction.desc) + ) + .compression(ArangoSearchCompression.lz4) + ) + .storedValues(new StoredValue(Arrays.asList("f3", "f4"), ArangoSearchCompression.none)) + .analyzer(analyzerName) + .features(AnalyzerFeature.position, AnalyzerFeature.frequency) + .includeAllFields(false) + .trackListPositions(true) + .searchField(true) + .fields(field) + .consolidationIntervalMsec(11L) + .commitIntervalMsec(22L) + .cleanupIntervalStep(33L) + .consolidationPolicy(ConsolidationPolicy.of(ConsolidationType.BYTES_ACCUM).threshold(1.)) + .writebufferIdle(44L) + .writebufferActive(55L) + .writebufferSizeMax(66L); + } + + private void assertCorrectIndexEntity(InvertedIndexEntity indexResult, InvertedIndexOptions options) { + assertThat(indexResult).isNotNull(); + assertThat(indexResult.getId()).isNotNull().isNotEmpty(); + // FIXME: in single server this is null + // assertThat(indexResult.getIsNewlyCreated()).isTrue(); + assertThat(indexResult.getUnique()).isFalse(); + assertThat(indexResult.getSparse()).isTrue(); + assertThat(indexResult.getVersion()).isNotNull(); + assertThat(indexResult.getCode()).isNotNull(); + assertThat(indexResult.getType()).isEqualTo(IndexType.inverted); + assertThat(indexResult.getName()).isEqualTo(options.getName()); + assertThat(indexResult.getFields()).containsExactlyElementsOf(options.getFields()); + assertThat(indexResult.getSearchField()).isEqualTo(options.getSearchField()); + assertThat(indexResult.getStoredValues()).containsExactlyElementsOf(options.getStoredValues()); + assertThat(indexResult.getPrimarySort()).isEqualTo(options.getPrimarySort()); + assertThat(indexResult.getAnalyzer()).isEqualTo(options.getAnalyzer()); + assertThat(indexResult.getFeatures()).hasSameElementsAs(options.getFeatures()); + assertThat(indexResult.getIncludeAllFields()).isEqualTo(options.getIncludeAllFields()); + assertThat(indexResult.getTrackListPositions()).isEqualTo(options.getTrackListPositions()); + assertThat(indexResult.getCleanupIntervalStep()).isEqualTo(options.getCleanupIntervalStep()); + assertThat(indexResult.getCommitIntervalMsec()).isEqualTo(options.getCommitIntervalMsec()); + assertThat(indexResult.getConsolidationIntervalMsec()).isEqualTo(options.getConsolidationIntervalMsec()); + assertThat(indexResult.getConsolidationPolicy()).isEqualTo(options.getConsolidationPolicy()); + assertThat(indexResult.getWritebufferIdle()).isEqualTo(options.getWritebufferIdle()); + assertThat(indexResult.getWritebufferActive()).isEqualTo(options.getWritebufferActive()); + assertThat(indexResult.getWritebufferSizeMax()).isEqualTo(options.getWritebufferSizeMax()); + } + + @Test + void createAndGetInvertedIndex() throws ExecutionException, InterruptedException { + assumeTrue(isAtLeastVersion(3, 10)); + + ArangoCollectionAsync collection = db.collection(COLLECTION_NAME); + String analyzerName = "delimiter-" + UUID.randomUUID(); + createAnalyzer(analyzerName, collection.db()); + InvertedIndexOptions options = createOptions(analyzerName); + InvertedIndexEntity created = collection.ensureInvertedIndex(options).get(); + assertCorrectIndexEntity(created, options); + InvertedIndexEntity loadedIndex = collection.getInvertedIndex(created.getName()).get(); + assertCorrectIndexEntity(loadedIndex, options); + } + + @Test + void getInvertedIndexesShouldNotReturnOtherIndexTypes() throws ExecutionException, InterruptedException { + assumeTrue(isAtLeastVersion(3, 10)); + + ArangoCollectionAsync collection = db.collection(COLLECTION_NAME); + + // create persistent index + collection.ensurePersistentIndex(Collections.singletonList("foo"), new PersistentIndexOptions().name("persistentIndex")); + + // create inverted index + String analyzerName = "delimiter-" + UUID.randomUUID(); + createAnalyzer(analyzerName, collection.db()); + InvertedIndexOptions options = createOptions(analyzerName); + InvertedIndexEntity created = collection.ensureInvertedIndex(options).get(); + + Collection loadedIndexes = collection.getInvertedIndexes().get(); + assertThat(loadedIndexes).map(InvertedIndexEntity::getName) + .doesNotContain("persistentIndex") + .contains(created.getName()); + } + + @Test + void getIndexesShouldNotReturnInvertedIndexes() throws ExecutionException, InterruptedException { + assumeTrue(isAtLeastVersion(3, 10)); + + ArangoCollectionAsync collection = db.collection(COLLECTION_NAME); + + // create persistent index + collection.ensurePersistentIndex(Collections.singletonList("foo"), new PersistentIndexOptions().name("persistentIndex")); + + // create inverted index + String analyzerName = "delimiter-" + UUID.randomUUID(); + createAnalyzer(analyzerName, collection.db()); + InvertedIndexOptions options = createOptions(analyzerName); + InvertedIndexEntity created = collection.ensureInvertedIndex(options).get(); + + Collection loadedIndexes = collection.getIndexes().get(); + assertThat(loadedIndexes).map(IndexEntity::getName) + .doesNotContain(created.getName()) + .contains("persistentIndex"); + } + +} diff --git a/src/test/resources/logback-test.xml b/src/test/resources/logback-test.xml index f67855e9c..579f1b9db 100644 --- a/src/test/resources/logback-test.xml +++ b/src/test/resources/logback-test.xml @@ -8,7 +8,7 @@ - + From ace1ef29274e32eb53ce6457a798490f68e44726 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Tue, 20 Sep 2022 20:43:45 +0200 Subject: [PATCH 122/254] test fixes --- src/test/java/com/arangodb/ArangoSearchTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/java/com/arangodb/ArangoSearchTest.java b/src/test/java/com/arangodb/ArangoSearchTest.java index 5fee8b7ed..84fd54b81 100644 --- a/src/test/java/com/arangodb/ArangoSearchTest.java +++ b/src/test/java/com/arangodb/ArangoSearchTest.java @@ -731,7 +731,7 @@ void collationAnalyzer(ArangoDatabase db) { @ParameterizedTest(name = "{index}") @MethodSource("dbs") void offsetFeature(ArangoDatabase db) { - assumeTrue(isAtLeastVersion(3, 5)); + assumeTrue(isAtLeastVersion(3, 10)); String name = "test-" + UUID.randomUUID(); From 87566e29099c1dc763711e3d1d8ce2605c208817 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Wed, 14 Sep 2022 14:28:06 +0200 Subject: [PATCH 123/254] [DE-380] fixed ConsolidationPolicy API (cherry picked from commit e4c8b5c87917e7a54529a0a18e7fd897ae222957) --- .../arangosearch/ConsolidationPolicy.java | 83 +++++++++++++++---- .../arangosearch/ConsolidationType.java | 5 ++ .../java/com/arangodb/InvertedIndexTest.java | 7 +- src/test/resources/logback-test.xml | 2 +- 4 files changed, 78 insertions(+), 19 deletions(-) diff --git a/src/main/java/com/arangodb/entity/arangosearch/ConsolidationPolicy.java b/src/main/java/com/arangodb/entity/arangosearch/ConsolidationPolicy.java index d3b117b84..fb81b6b40 100644 --- a/src/main/java/com/arangodb/entity/arangosearch/ConsolidationPolicy.java +++ b/src/main/java/com/arangodb/entity/arangosearch/ConsolidationPolicy.java @@ -29,7 +29,11 @@ public final class ConsolidationPolicy { private ConsolidationType type; private Double threshold; - private Long segmentThreshold; + private Long segmentsMin; + private Long segmentsMax; + private Long segmentsBytesMax; + private Long segmentsBytesFloor; + public ConsolidationPolicy() { } @@ -44,36 +48,81 @@ public ConsolidationPolicy type(final ConsolidationType type) { } /** - * @param threshold Select a given segment for "consolidation" if and only if the formula based on type (as - * defined above) - * evaluates to true, valid value range [0.0, 1.0] (default: 0.85) + * @param threshold Select a given segment for "consolidation" if and only if the formula based on type (as defined + * above) evaluates to true, valid value range [0.0, 1.0] (default: 0.85) + * @param threshold Defines threshold value of [0.0, 1.0] possible range. Consolidation is performed on segments + * which accumulated size in bytes is less than all segments’ byte size multiplied by the + * threshold; i.e. the following formula is applied for each segment: {threshold} > (segment_bytes + * + sum_of_merge_candidate_segment_bytes) / all_segment_bytes. (default: 0.1) * @return policy + * @return this */ public ConsolidationPolicy threshold(final Double threshold) { this.threshold = threshold; return this; } + public ConsolidationType getType() { + return type; + } + + public Double getThreshold() { + return threshold; + } + + public Long getSegmentsMin() { + return segmentsMin; + } + /** - * @param segmentThreshold Apply the "consolidation" operation if and only if (default: 300): {segmentThreshold} < - * number_of_segments - * @return policy + * @param segmentsMin The minimum number of segments that will be evaluated as candidates for consolidation. + * (default: 1) + * @return this */ - public ConsolidationPolicy segmentThreshold(final Long segmentThreshold) { - this.segmentThreshold = segmentThreshold; + public ConsolidationPolicy segmentsMin(final Long segmentsMin) { + this.segmentsMin = segmentsMin; return this; } - public ConsolidationType getType() { - return type; + public Long getSegmentsMax() { + return segmentsMax; } - public Double getThreshold() { - return threshold; + /** + * @param segmentsMax The maximum number of segments that will be evaluated as candidates for consolidation. + * (default: 10) + * @return this + */ + public ConsolidationPolicy segmentsMax(final Long segmentsMax) { + this.segmentsMax = segmentsMax; + return this; + } + + public Long getSegmentsBytesMax() { + return segmentsBytesMax; } - public Long getSegmentThreshold() { - return segmentThreshold; + /** + * @param segmentsBytesMax Maximum allowed size of all consolidated segments in bytes. (default: 5368709120) + * @return this + */ + public ConsolidationPolicy segmentsBytesMax(final Long segmentsBytesMax) { + this.segmentsBytesMax = segmentsBytesMax; + return this; + } + + public Long getSegmentsBytesFloor() { + return segmentsBytesFloor; + } + + /** + * @param segmentsBytesFloor Defines the value (in bytes) to treat all smaller segments as equal for consolidation + * selection. (default: 2097152) + * @return this + */ + public ConsolidationPolicy segmentsBytesFloor(final Long segmentsBytesFloor) { + this.segmentsBytesFloor = segmentsBytesFloor; + return this; } @Override @@ -81,11 +130,11 @@ public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; ConsolidationPolicy that = (ConsolidationPolicy) o; - return type == that.type && Objects.equals(threshold, that.threshold) && Objects.equals(segmentThreshold, that.segmentThreshold); + return type == that.type && Objects.equals(threshold, that.threshold) && Objects.equals(segmentsMin, that.segmentsMin) && Objects.equals(segmentsMax, that.segmentsMax) && Objects.equals(segmentsBytesMax, that.segmentsBytesMax) && Objects.equals(segmentsBytesFloor, that.segmentsBytesFloor); } @Override public int hashCode() { - return Objects.hash(type, threshold, segmentThreshold); + return Objects.hash(type, threshold, segmentsMin, segmentsMax, segmentsBytesMax, segmentsBytesFloor); } } diff --git a/src/main/java/com/arangodb/entity/arangosearch/ConsolidationType.java b/src/main/java/com/arangodb/entity/arangosearch/ConsolidationType.java index 9ab2da72a..1eb3b1ebc 100644 --- a/src/main/java/com/arangodb/entity/arangosearch/ConsolidationType.java +++ b/src/main/java/com/arangodb/entity/arangosearch/ConsolidationType.java @@ -4,6 +4,11 @@ public enum ConsolidationType { + /** + * @deprecated The “bytes_accum” policy type is deprecated and remains in ArangoSearch for backwards compatibility + * with the older versions. Please make sure to always use the “tier” policy instead. + */ + @Deprecated @JsonProperty("bytes_accum") BYTES_ACCUM, diff --git a/src/test/java/com/arangodb/InvertedIndexTest.java b/src/test/java/com/arangodb/InvertedIndexTest.java index 3a42b941e..0314c6499 100644 --- a/src/test/java/com/arangodb/InvertedIndexTest.java +++ b/src/test/java/com/arangodb/InvertedIndexTest.java @@ -98,7 +98,12 @@ private InvertedIndexOptions createOptions(String analyzerName) { .consolidationIntervalMsec(11L) .commitIntervalMsec(22L) .cleanupIntervalStep(33L) - .consolidationPolicy(ConsolidationPolicy.of(ConsolidationType.BYTES_ACCUM).threshold(1.)) + .consolidationPolicy(ConsolidationPolicy.of(ConsolidationType.TIER) + .segmentsMin(3L) + .segmentsMax(44L) + .segmentsBytesMax(55555L) + .segmentsBytesFloor(666L) + ) .writebufferIdle(44L) .writebufferActive(55L) .writebufferSizeMax(66L); diff --git a/src/test/resources/logback-test.xml b/src/test/resources/logback-test.xml index 579f1b9db..f67855e9c 100644 --- a/src/test/resources/logback-test.xml +++ b/src/test/resources/logback-test.xml @@ -8,7 +8,7 @@ - + From 10ec28ed9ea286e379a9f75e2599a49a22673f2c Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Thu, 15 Sep 2022 10:55:33 +0200 Subject: [PATCH 124/254] [DE-385] 3.10 analyzers (#458) * ClassificationAnalyzer * added test ML model to docker containers * NearestNeighborsAnalyzer * MinHashAnalyzer * test fixes (cherry picked from commit 1900820ee9d492c94fc7db2a511bece3dc1a964d) --- docker/foo.bin | Bin 0 -> 5537 bytes docker/start_db.sh | 7 ++ .../arangodb/entity/InvertedIndexField.java | 3 +- .../entity/arangosearch/AnalyzerType.java | 17 +++- .../analyzer/ClassificationAnalyzer.java | 64 ++++++++++++++ .../ClassificationAnalyzerProperties.java | 78 ++++++++++++++++++ .../analyzer/MinHashAnalyzer.java | 64 ++++++++++++++ .../analyzer/MinHashAnalyzerProperties.java | 63 ++++++++++++++ .../analyzer/NearestNeighborsAnalyzer.java | 66 +++++++++++++++ .../NearestNeighborsAnalyzerProperties.java | 69 ++++++++++++++++ .../arangosearch/analyzer/SearchAnalyzer.java | 5 +- .../java/com/arangodb/ArangoSearchTest.java | 77 +++++++++++++++++ 12 files changed, 510 insertions(+), 3 deletions(-) create mode 100644 docker/foo.bin create mode 100644 src/main/java/com/arangodb/entity/arangosearch/analyzer/ClassificationAnalyzer.java create mode 100644 src/main/java/com/arangodb/entity/arangosearch/analyzer/ClassificationAnalyzerProperties.java create mode 100644 src/main/java/com/arangodb/entity/arangosearch/analyzer/MinHashAnalyzer.java create mode 100644 src/main/java/com/arangodb/entity/arangosearch/analyzer/MinHashAnalyzerProperties.java create mode 100644 src/main/java/com/arangodb/entity/arangosearch/analyzer/NearestNeighborsAnalyzer.java create mode 100644 src/main/java/com/arangodb/entity/arangosearch/analyzer/NearestNeighborsAnalyzerProperties.java diff --git a/docker/foo.bin b/docker/foo.bin new file mode 100644 index 0000000000000000000000000000000000000000..97c4296cd3c37f0b8abffa39f6b2975acb2e2546 GIT binary patch literal 5537 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 literal 0 HcmV?d00001 diff --git a/docker/start_db.sh b/docker/start_db.sh index a322aa97c..f5a946dbf 100755 --- a/docker/start_db.sh +++ b/docker/start_db.sh @@ -101,6 +101,13 @@ for a in ${COORDINATORS[*]} ; do curl -u root:test --insecure --fail "$SCHEME://$a/_api/version" done +echo "" +echo "" +echo "Copying test ML models into containers..." +for c in $(docker ps -a -f name=adb-.* -q) ; do + docker cp "$LOCATION"/foo.bin "$c":/tmp +done + echo "" echo "" echo "Done, your deployment is reachable at: " diff --git a/src/main/java/com/arangodb/entity/InvertedIndexField.java b/src/main/java/com/arangodb/entity/InvertedIndexField.java index 48512d239..bff8cc828 100644 --- a/src/main/java/com/arangodb/entity/InvertedIndexField.java +++ b/src/main/java/com/arangodb/entity/InvertedIndexField.java @@ -18,7 +18,7 @@ public class InvertedIndexField { private Boolean searchField; private Boolean trackListPositions; private final Set features = new HashSet<>(); - private final Collection nested = new ArrayList<>(); + private Collection nested; public String getName() { return name; @@ -79,6 +79,7 @@ public Collection getNested() { } public InvertedIndexField nested(InvertedIndexField... nested) { + if(this.nested == null) this.nested = new ArrayList<>(); Collections.addAll(this.nested, nested); return this; } diff --git a/src/main/java/com/arangodb/entity/arangosearch/AnalyzerType.java b/src/main/java/com/arangodb/entity/arangosearch/AnalyzerType.java index 7a5ea5918..acf38797d 100644 --- a/src/main/java/com/arangodb/entity/arangosearch/AnalyzerType.java +++ b/src/main/java/com/arangodb/entity/arangosearch/AnalyzerType.java @@ -24,5 +24,20 @@ * @author Michele Rastelli */ public enum AnalyzerType { - identity, delimiter, stem, norm, ngram, text, pipeline, stopwords, aql, geojson, geopoint, segmentation, collation + identity, + delimiter, + stem, + norm, + ngram, + text, + pipeline, + stopwords, + aql, + geojson, + geopoint, + segmentation, + collation, + classification, + nearest_neighbors, + minhash } diff --git a/src/main/java/com/arangodb/entity/arangosearch/analyzer/ClassificationAnalyzer.java b/src/main/java/com/arangodb/entity/arangosearch/analyzer/ClassificationAnalyzer.java new file mode 100644 index 000000000..55eb3a47a --- /dev/null +++ b/src/main/java/com/arangodb/entity/arangosearch/analyzer/ClassificationAnalyzer.java @@ -0,0 +1,64 @@ +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed 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. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.entity.arangosearch.analyzer; + + +import com.arangodb.entity.arangosearch.AnalyzerType; + +import java.util.Objects; + +/** + * An Analyzer capable of classifying tokens in the input text. It applies a user-provided supervised fastText word + * embedding model to classify the input text. It is able to classify individual tokens as well as entire inputs. + * + * @author Michele Rastelli + * @see API Documentation + * @since ArangoDB 3.10 + */ +public class ClassificationAnalyzer extends SearchAnalyzer { + public ClassificationAnalyzer() { + setType(AnalyzerType.classification); + } + + private ClassificationAnalyzerProperties properties; + + public ClassificationAnalyzerProperties getProperties() { + return properties; + } + + public void setProperties(ClassificationAnalyzerProperties properties) { + this.properties = properties; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + if (!super.equals(o)) return false; + ClassificationAnalyzer that = (ClassificationAnalyzer) o; + return Objects.equals(properties, that.properties); + } + + @Override + public int hashCode() { + return Objects.hash(super.hashCode(), properties); + } +} diff --git a/src/main/java/com/arangodb/entity/arangosearch/analyzer/ClassificationAnalyzerProperties.java b/src/main/java/com/arangodb/entity/arangosearch/analyzer/ClassificationAnalyzerProperties.java new file mode 100644 index 000000000..06e3d339a --- /dev/null +++ b/src/main/java/com/arangodb/entity/arangosearch/analyzer/ClassificationAnalyzerProperties.java @@ -0,0 +1,78 @@ +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed 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. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.entity.arangosearch.analyzer; + + +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.Objects; + +/** + * @author Michele Rastelli + * @since ArangoDB 3.10 + */ +public class ClassificationAnalyzerProperties { + + @JsonProperty("model_location") + private String modelLocation; + + @JsonProperty("top_k") + private Integer topK; + + private Double threshold; + + public String getModelLocation() { + return modelLocation; + } + + public void setModelLocation(String modelLocation) { + this.modelLocation = modelLocation; + } + + public Integer getTopK() { + return topK; + } + + public void setTopK(Integer topK) { + this.topK = topK; + } + + public Double getThreshold() { + return threshold; + } + + public void setThreshold(Double threshold) { + this.threshold = threshold; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + ClassificationAnalyzerProperties that = (ClassificationAnalyzerProperties) o; + return Objects.equals(modelLocation, that.modelLocation) && Objects.equals(topK, that.topK) && Objects.equals(threshold, that.threshold); + } + + @Override + public int hashCode() { + return Objects.hash(modelLocation, topK, threshold); + } +} diff --git a/src/main/java/com/arangodb/entity/arangosearch/analyzer/MinHashAnalyzer.java b/src/main/java/com/arangodb/entity/arangosearch/analyzer/MinHashAnalyzer.java new file mode 100644 index 000000000..116103e52 --- /dev/null +++ b/src/main/java/com/arangodb/entity/arangosearch/analyzer/MinHashAnalyzer.java @@ -0,0 +1,64 @@ +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed 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. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.entity.arangosearch.analyzer; + + +import com.arangodb.entity.arangosearch.AnalyzerType; + +import java.util.Objects; + +/** + * An Analyzer that computes so called MinHash signatures using a locality-sensitive hash function. It applies an + * Analyzer of your choice before the hashing, for example, to break up text into words. + * + * @author Michele Rastelli + * @see API Documentation + * @since ArangoDB 3.10 + */ +public class MinHashAnalyzer extends SearchAnalyzer { + public MinHashAnalyzer() { + setType(AnalyzerType.minhash); + } + + private MinHashAnalyzerProperties properties; + + public MinHashAnalyzerProperties getProperties() { + return properties; + } + + public void setProperties(MinHashAnalyzerProperties properties) { + this.properties = properties; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + if (!super.equals(o)) return false; + MinHashAnalyzer that = (MinHashAnalyzer) o; + return Objects.equals(properties, that.properties); + } + + @Override + public int hashCode() { + return Objects.hash(super.hashCode(), properties); + } +} diff --git a/src/main/java/com/arangodb/entity/arangosearch/analyzer/MinHashAnalyzerProperties.java b/src/main/java/com/arangodb/entity/arangosearch/analyzer/MinHashAnalyzerProperties.java new file mode 100644 index 000000000..a451c0525 --- /dev/null +++ b/src/main/java/com/arangodb/entity/arangosearch/analyzer/MinHashAnalyzerProperties.java @@ -0,0 +1,63 @@ +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed 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. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.entity.arangosearch.analyzer; + + +import java.util.Objects; + +/** + * @author Michele Rastelli + * @since ArangoDB 3.10 + */ +public class MinHashAnalyzerProperties { + + private SearchAnalyzer analyzer; + private Integer numHashes; + + public SearchAnalyzer getAnalyzer() { + return analyzer; + } + + public void setAnalyzer(SearchAnalyzer analyzer) { + this.analyzer = analyzer; + } + + public Integer getNumHashes() { + return numHashes; + } + + public void setNumHashes(Integer numHashes) { + this.numHashes = numHashes; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + MinHashAnalyzerProperties that = (MinHashAnalyzerProperties) o; + return Objects.equals(analyzer, that.analyzer) && Objects.equals(numHashes, that.numHashes); + } + + @Override + public int hashCode() { + return Objects.hash(analyzer, numHashes); + } +} diff --git a/src/main/java/com/arangodb/entity/arangosearch/analyzer/NearestNeighborsAnalyzer.java b/src/main/java/com/arangodb/entity/arangosearch/analyzer/NearestNeighborsAnalyzer.java new file mode 100644 index 000000000..c8641db4f --- /dev/null +++ b/src/main/java/com/arangodb/entity/arangosearch/analyzer/NearestNeighborsAnalyzer.java @@ -0,0 +1,66 @@ +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed 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. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.entity.arangosearch.analyzer; + + +import com.arangodb.entity.arangosearch.AnalyzerType; + +import java.util.Objects; + +/** + * An Analyzer capable of finding nearest neighbors of tokens in the input. It applies a user-provided supervised + * fastText word embedding model to retrieve nearest neighbor tokens in the text. It is able to find neighbors of + * individual tokens as well as entire input strings. For entire input strings, the Analyzer will return nearest + * neighbors for each token within the input string. + * + * @author Michele Rastelli + * @see API Documentation + * @since ArangoDB 3.10 + */ +public class NearestNeighborsAnalyzer extends SearchAnalyzer { + public NearestNeighborsAnalyzer() { + setType(AnalyzerType.nearest_neighbors); + } + + private NearestNeighborsAnalyzerProperties properties; + + public NearestNeighborsAnalyzerProperties getProperties() { + return properties; + } + + public void setProperties(NearestNeighborsAnalyzerProperties properties) { + this.properties = properties; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + if (!super.equals(o)) return false; + NearestNeighborsAnalyzer that = (NearestNeighborsAnalyzer) o; + return Objects.equals(properties, that.properties); + } + + @Override + public int hashCode() { + return Objects.hash(super.hashCode(), properties); + } +} diff --git a/src/main/java/com/arangodb/entity/arangosearch/analyzer/NearestNeighborsAnalyzerProperties.java b/src/main/java/com/arangodb/entity/arangosearch/analyzer/NearestNeighborsAnalyzerProperties.java new file mode 100644 index 000000000..a2f850936 --- /dev/null +++ b/src/main/java/com/arangodb/entity/arangosearch/analyzer/NearestNeighborsAnalyzerProperties.java @@ -0,0 +1,69 @@ +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed 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. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.entity.arangosearch.analyzer; + + +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.Objects; + +/** + * @author Michele Rastelli + * @since ArangoDB 3.10 + */ +public class NearestNeighborsAnalyzerProperties { + + @JsonProperty("model_location") + private String modelLocation; + + @JsonProperty("top_k") + private Integer topK; + + + public String getModelLocation() { + return modelLocation; + } + + public void setModelLocation(String modelLocation) { + this.modelLocation = modelLocation; + } + + public Integer getTopK() { + return topK; + } + + public void setTopK(Integer topK) { + this.topK = topK; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + NearestNeighborsAnalyzerProperties that = (NearestNeighborsAnalyzerProperties) o; + return Objects.equals(modelLocation, that.modelLocation) && Objects.equals(topK, that.topK); + } + + @Override + public int hashCode() { + return Objects.hash(modelLocation, topK); + } +} diff --git a/src/main/java/com/arangodb/entity/arangosearch/analyzer/SearchAnalyzer.java b/src/main/java/com/arangodb/entity/arangosearch/analyzer/SearchAnalyzer.java index 8963a365f..6d10f8c69 100644 --- a/src/main/java/com/arangodb/entity/arangosearch/analyzer/SearchAnalyzer.java +++ b/src/main/java/com/arangodb/entity/arangosearch/analyzer/SearchAnalyzer.java @@ -49,7 +49,10 @@ @JsonSubTypes.Type(name = "geojson", value = GeoJSONAnalyzer.class), @JsonSubTypes.Type(name = "geopoint", value = GeoPointAnalyzer.class), @JsonSubTypes.Type(name = "segmentation", value = SegmentationAnalyzer.class), - @JsonSubTypes.Type(name = "collation", value = CollationAnalyzer.class) + @JsonSubTypes.Type(name = "collation", value = CollationAnalyzer.class), + @JsonSubTypes.Type(name = "classification", value = ClassificationAnalyzer.class), + @JsonSubTypes.Type(name = "nearest_neighbors", value = NearestNeighborsAnalyzer.class), + @JsonSubTypes.Type(name = "minhash", value = MinHashAnalyzer.class) }) public abstract class SearchAnalyzer { private String name; diff --git a/src/test/java/com/arangodb/ArangoSearchTest.java b/src/test/java/com/arangodb/ArangoSearchTest.java index 84fd54b81..a4494eb50 100644 --- a/src/test/java/com/arangodb/ArangoSearchTest.java +++ b/src/test/java/com/arangodb/ArangoSearchTest.java @@ -728,6 +728,83 @@ void collationAnalyzer(ArangoDatabase db) { } + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void classificationAnalyzer(ArangoDatabase db) { + assumeTrue(isAtLeastVersion(3, 10)); + assumeTrue(isEnterprise()); + + ClassificationAnalyzerProperties properties = new ClassificationAnalyzerProperties(); + properties.setModelLocation("/tmp/foo.bin"); + properties.setTopK(2); + properties.setThreshold(.5); + + Set features = new HashSet<>(); + features.add(AnalyzerFeature.frequency); + features.add(AnalyzerFeature.norm); + features.add(AnalyzerFeature.position); + + ClassificationAnalyzer analyzer = new ClassificationAnalyzer(); + analyzer.setName("test-" + UUID.randomUUID()); + analyzer.setProperties(properties); + analyzer.setFeatures(features); + + createGetAndDeleteTypedAnalyzer(db, analyzer); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void nearestNeighborsAnalyzer(ArangoDatabase db) { + assumeTrue(isAtLeastVersion(3, 10)); + assumeTrue(isEnterprise()); + + NearestNeighborsAnalyzerProperties properties = new NearestNeighborsAnalyzerProperties(); + properties.setModelLocation("/tmp/foo.bin"); + properties.setTopK(2); + + Set features = new HashSet<>(); + features.add(AnalyzerFeature.frequency); + features.add(AnalyzerFeature.norm); + features.add(AnalyzerFeature.position); + + NearestNeighborsAnalyzer analyzer = new NearestNeighborsAnalyzer(); + analyzer.setName("test-" + UUID.randomUUID()); + analyzer.setProperties(properties); + analyzer.setFeatures(features); + + createGetAndDeleteTypedAnalyzer(db, analyzer); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void MinHashAnalyzer(ArangoDatabase db) { + assumeTrue(isAtLeastVersion(3, 10)); + assumeTrue(isEnterprise()); + + SegmentationAnalyzerProperties segProperties = new SegmentationAnalyzerProperties(); + segProperties.setBreakMode(SegmentationAnalyzerProperties.BreakMode.alpha); + segProperties.setAnalyzerCase(SearchAnalyzerCase.lower); + + SegmentationAnalyzer segAnalyzer = new SegmentationAnalyzer(); + segAnalyzer.setProperties(segProperties); + + MinHashAnalyzerProperties properties = new MinHashAnalyzerProperties(); + properties.setAnalyzer(segAnalyzer); + properties.setNumHashes(2); + + Set features = new HashSet<>(); + features.add(AnalyzerFeature.frequency); + features.add(AnalyzerFeature.norm); + features.add(AnalyzerFeature.position); + + MinHashAnalyzer analyzer = new MinHashAnalyzer(); + analyzer.setName("test-" + UUID.randomUUID()); + analyzer.setProperties(properties); + analyzer.setFeatures(features); + + createGetAndDeleteTypedAnalyzer(db, analyzer); + } + @ParameterizedTest(name = "{index}") @MethodSource("dbs") void offsetFeature(ArangoDatabase db) { From 37c07c2c6d3a558b31cd5bb516a567f4bdfccfcf Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Thu, 15 Sep 2022 19:00:50 +0200 Subject: [PATCH 125/254] [DE-392] nested search support (#460) * docker images upd * arangosearch nested links (cherry picked from commit 0f80bc04b261bcced08e60cddc41e0ec609d3093) --- .../entity/arangosearch/CollectionLink.java | 17 ++++++ .../entity/arangosearch/FieldLink.java | 19 +++++++ .../java/com/arangodb/ArangoSearchTest.java | 53 ++++++++++++------- 3 files changed, 70 insertions(+), 19 deletions(-) diff --git a/src/main/java/com/arangodb/entity/arangosearch/CollectionLink.java b/src/main/java/com/arangodb/entity/arangosearch/CollectionLink.java index a64a85679..66cf9c73f 100644 --- a/src/main/java/com/arangodb/entity/arangosearch/CollectionLink.java +++ b/src/main/java/com/arangodb/entity/arangosearch/CollectionLink.java @@ -42,6 +42,7 @@ public final class CollectionLink { private Boolean trackListPositions; private StoreValuesType storeValues; private Collection fields; + private Collection nested; private CollectionLink(final String name) { super(); @@ -110,6 +111,17 @@ public CollectionLink fields(final FieldLink... fields) { return this; } + /** + * @param nested A list of nested fields + * @return link + * @since ArangoDB 3.10 + */ + @JsonDeserialize(using = InternalDeserializers.FieldLinksDeserializer.class) + public CollectionLink nested(final FieldLink... nested) { + this.nested = Arrays.asList(nested); + return this; + } + @JsonIgnore public String getName() { return name; @@ -136,4 +148,9 @@ public Collection getFields() { return fields; } + @JsonSerialize(using = InternalSerializers.FieldLinksSerializer.class) + public Collection getNested() { + return nested; + } + } \ No newline at end of file diff --git a/src/main/java/com/arangodb/entity/arangosearch/FieldLink.java b/src/main/java/com/arangodb/entity/arangosearch/FieldLink.java index 00a7a93d9..f33d858a3 100644 --- a/src/main/java/com/arangodb/entity/arangosearch/FieldLink.java +++ b/src/main/java/com/arangodb/entity/arangosearch/FieldLink.java @@ -1,9 +1,11 @@ package com.arangodb.entity.arangosearch; +import com.arangodb.internal.serde.InternalDeserializers; import com.arangodb.internal.serde.InternalSerializers; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.fasterxml.jackson.databind.annotation.JsonSerialize; import java.util.Arrays; @@ -17,6 +19,7 @@ public final class FieldLink { private Boolean trackListPositions; private StoreValuesType storeValues; private Collection fields; + private Collection nested; private FieldLink(final String name) { super(); @@ -79,11 +82,23 @@ public FieldLink storeValues(final StoreValuesType storeValues) { * @param fields A list of linked fields * @return link */ + @JsonDeserialize(using = InternalDeserializers.FieldLinksDeserializer.class) public FieldLink fields(final FieldLink... fields) { this.fields = Arrays.asList(fields); return this; } + /** + * @param nested A list of nested fields + * @return link + * @since ArangoDB 3.10 + */ + @JsonDeserialize(using = InternalDeserializers.FieldLinksDeserializer.class) + public FieldLink nested(final FieldLink... nested) { + this.nested = Arrays.asList(nested); + return this; + } + @JsonIgnore public String getName() { return name; @@ -110,4 +125,8 @@ public Collection getFields() { return fields; } + @JsonSerialize(using = InternalSerializers.FieldLinksSerializer.class) + public Collection getNested() { + return nested; + } } \ No newline at end of file diff --git a/src/test/java/com/arangodb/ArangoSearchTest.java b/src/test/java/com/arangodb/ArangoSearchTest.java index a4494eb50..bdeca9cea 100644 --- a/src/test/java/com/arangodb/ArangoSearchTest.java +++ b/src/test/java/com/arangodb/ArangoSearchTest.java @@ -493,19 +493,20 @@ void enhancedTextAnalyzerTyped(ArangoDatabase db) { void arangoSearchOptions(ArangoDatabase db) { assumeTrue(isAtLeastVersion(3, 4)); String viewName = "view-" + rnd(); - ArangoSearchCreateOptions options = new ArangoSearchCreateOptions() - .link( - CollectionLink.on(COLL_1) - .analyzers("identity") - .fields( - FieldLink.on("id") - .analyzers("identity") - ) - .includeAllFields(true) - .storeValues(StoreValuesType.ID) - .trackListPositions(false) - - ); + FieldLink field = FieldLink.on("f1"); + if (isEnterprise()) { + field.nested(FieldLink.on("f2")); + } + CollectionLink link = CollectionLink.on(COLL_1) + .analyzers("identity") + .fields(field) + .includeAllFields(true) + .storeValues(StoreValuesType.ID) + .trackListPositions(false); + if (isEnterprise()) { + link.nested(FieldLink.on("f3")); + } + ArangoSearchCreateOptions options = new ArangoSearchCreateOptions().link(link); final ArangoSearch view = db.arangoSearch(viewName); view.create(options); @@ -515,13 +516,27 @@ void arangoSearchOptions(ArangoDatabase db) { assertThat(properties.getId()).isNotNull(); assertThat(properties.getName()).isEqualTo(viewName); assertThat(properties.getType()).isEqualTo(ViewType.ARANGO_SEARCH); + assertThat(properties.getLinks()).isNotEmpty(); + + CollectionLink createdLink = properties.getLinks().iterator().next(); + assertThat(createdLink.getName()).isEqualTo(COLL_1); + assertThat(createdLink.getAnalyzers()).contains("identity"); + assertThat(createdLink.getIncludeAllFields()).isTrue(); + assertThat(createdLink.getStoreValues()).isEqualTo(StoreValuesType.ID); + assertThat(createdLink.getTrackListPositions()).isFalse(); + if (isEnterprise() && isAtLeastVersion(3, 10)) { + assertThat(createdLink.getNested()).isNotEmpty(); + FieldLink nested = createdLink.getNested().iterator().next(); + assertThat(nested.getName()).isEqualTo("f3"); + } - CollectionLink link = properties.getLinks().iterator().next(); - assertThat(link.getAnalyzers()).contains("identity"); - assertThat(link.getName()).isEqualTo(COLL_1); - assertThat(link.getIncludeAllFields()).isTrue(); - assertThat(link.getStoreValues()).isEqualTo(StoreValuesType.ID); - assertThat(link.getTrackListPositions()).isFalse(); + FieldLink fieldLink = createdLink.getFields().iterator().next(); + assertThat(fieldLink.getName()).isEqualTo("f1"); + if (isEnterprise() && isAtLeastVersion(3, 10)) { + assertThat(fieldLink.getNested()).isNotEmpty(); + FieldLink nested = fieldLink.getNested().iterator().next(); + assertThat(nested.getName()).isEqualTo("f2"); + } } @ParameterizedTest(name = "{index}") From 7b710f6df47406d40341330e57cb2cadb497b3fc Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Fri, 16 Sep 2022 20:34:37 +0200 Subject: [PATCH 126/254] [DE-384] search-alias views (#461) * [DE-157] added support to inBackground parameter in ArangoSearch links * ViewType.SEARCH_ALIAS * SearchAlias sync * SearchAlias async * SearchAlias sync tests * disabled ArangoSearchTest for 3.10 cluster * SearchAlias async tests (cherry picked from commit 2d175b0496b147cf07c54ada2bf963eaa62409d6) --- .../java/com/arangodb/ArangoDatabase.java | 25 ++- src/main/java/com/arangodb/ArangoSearch.java | 2 +- src/main/java/com/arangodb/SearchAlias.java | 92 +++++++++ .../arangodb/async/ArangoDatabaseAsync.java | 24 ++- .../com/arangodb/async/ArangoSearchAsync.java | 2 +- .../com/arangodb/async/SearchAliasAsync.java | 89 +++++++++ .../internal/ArangoDatabaseAsyncImpl.java | 11 ++ .../async/internal/SearchAliasAsyncImpl.java | 87 +++++++++ .../java/com/arangodb/entity/ViewType.java | 4 +- .../entity/arangosearch/CollectionLink.java | 16 ++ .../entity/arangosearch/FieldLink.java | 17 ++ .../entity/arangosearch/SearchAliasIndex.java | 27 +++ .../SearchAliasPropertiesEntity.java | 43 +++++ .../arangodb/internal/ArangoDatabaseImpl.java | 11 ++ .../internal/InternalArangoDatabase.java | 9 +- .../internal/InternalSearchAlias.java | 50 +++++ .../arangodb/internal/SearchAliasImpl.java | 97 ++++++++++ .../SearchAliasCreateOptions.java | 71 +++++++ .../SearchAliasOptionsBuilder.java | 35 ++++ .../SearchAliasPropertiesOptions.java | 49 +++++ .../java/com/arangodb/ArangoSearchTest.java | 175 +++++++++++++++-- .../java/com/arangodb/ArangoViewTest.java | 27 +++ .../com/arangodb/async/ArangoSearchTest.java | 179 ++++++++++++++++-- .../java/com/arangodb/async/BaseTest.java | 9 + 24 files changed, 1119 insertions(+), 32 deletions(-) create mode 100644 src/main/java/com/arangodb/SearchAlias.java create mode 100644 src/main/java/com/arangodb/async/SearchAliasAsync.java create mode 100644 src/main/java/com/arangodb/async/internal/SearchAliasAsyncImpl.java create mode 100644 src/main/java/com/arangodb/entity/arangosearch/SearchAliasIndex.java create mode 100644 src/main/java/com/arangodb/entity/arangosearch/SearchAliasPropertiesEntity.java create mode 100644 src/main/java/com/arangodb/internal/InternalSearchAlias.java create mode 100644 src/main/java/com/arangodb/internal/SearchAliasImpl.java create mode 100644 src/main/java/com/arangodb/model/arangosearch/SearchAliasCreateOptions.java create mode 100644 src/main/java/com/arangodb/model/arangosearch/SearchAliasOptionsBuilder.java create mode 100644 src/main/java/com/arangodb/model/arangosearch/SearchAliasPropertiesOptions.java diff --git a/src/main/java/com/arangodb/ArangoDatabase.java b/src/main/java/com/arangodb/ArangoDatabase.java index bb506b6f8..47d9e76a3 100644 --- a/src/main/java/com/arangodb/ArangoDatabase.java +++ b/src/main/java/com/arangodb/ArangoDatabase.java @@ -25,6 +25,7 @@ import com.arangodb.model.*; import com.arangodb.model.arangosearch.AnalyzerDeleteOptions; import com.arangodb.model.arangosearch.ArangoSearchCreateOptions; +import com.arangodb.model.arangosearch.SearchAliasCreateOptions; import javax.annotation.concurrent.ThreadSafe; import java.util.Collection; @@ -640,7 +641,7 @@ public interface ArangoDatabase extends ArangoSerdeAccessor { ArangoView view(String name); /** - * Returns a {@code ArangoSearch} instance for the given ArangoSearch view name. + * Returns a {@link ArangoSearch} instance for the given view name. * * @param name Name of the view * @return ArangoSearch view handler @@ -648,6 +649,15 @@ public interface ArangoDatabase extends ArangoSerdeAccessor { */ ArangoSearch arangoSearch(String name); + /** + * Returns a {@link SearchAlias} instance for the given view name. + * + * @param name Name of the view + * @return SearchAlias view handler + * @since ArangoDB 3.10 + */ + SearchAlias searchAlias(String name); + /** * Creates a view of the given {@code type}, then returns view information from the server. * @@ -670,6 +680,19 @@ public interface ArangoDatabase extends ArangoSerdeAccessor { */ ViewEntity createArangoSearch(String name, ArangoSearchCreateOptions options); + /** + * Creates a SearchAlias view with the given {@code options}, then returns view information from the server. + * + * @param name The name of the view + * @param options Additional options, can be null + * @return information about the view + * @throws ArangoDBException + * @see API + * Documentation + * @since ArangoDB 3.10 + */ + ViewEntity createSearchAlias(String name, SearchAliasCreateOptions options) throws ArangoDBException; + /** * Creates an Analyzer * diff --git a/src/main/java/com/arangodb/ArangoSearch.java b/src/main/java/com/arangodb/ArangoSearch.java index 21ebe800d..8bdaf6c66 100644 --- a/src/main/java/com/arangodb/ArangoSearch.java +++ b/src/main/java/com/arangodb/ArangoSearch.java @@ -31,7 +31,7 @@ * Interface for operations on ArangoDB view level for ArangoSearch views. * * @author Mark Vollmary - * @see View API Documentation + * @see View API Documentation * @since ArangoDB 3.4.0 */ @ThreadSafe diff --git a/src/main/java/com/arangodb/SearchAlias.java b/src/main/java/com/arangodb/SearchAlias.java new file mode 100644 index 000000000..7f732fe87 --- /dev/null +++ b/src/main/java/com/arangodb/SearchAlias.java @@ -0,0 +1,92 @@ +/* + * DISCLAIMER + * + * Copyright 2018 ArangoDB GmbH, Cologne, Germany + * + * Licensed 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. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb; + +import com.arangodb.entity.ViewEntity; +import com.arangodb.entity.arangosearch.SearchAliasPropertiesEntity; +import com.arangodb.model.arangosearch.SearchAliasCreateOptions; +import com.arangodb.model.arangosearch.SearchAliasPropertiesOptions; + +/** + * Interface for operations on ArangoDB view level for SearchAlias views. + * + * @author Michele Rastelli + * @see View API Documentation + * @since ArangoDB 3.10 + */ +public interface SearchAlias extends ArangoView { + + /** + * Creates a view, then returns view information from the server. + * + * @return information about the view + * @throws ArangoDBException + * @see API + * Documentation + */ + ViewEntity create() throws ArangoDBException; + + /** + * Creates a view with the given {@code options}, then returns view information from the server. + * + * @param options Additional options, can be null + * @return information about the view + * @throws ArangoDBException + * @see API + * Documentation + */ + ViewEntity create(SearchAliasCreateOptions options) throws ArangoDBException; + + /** + * Reads the properties of the specified view. + * + * @return properties of the view + * @throws ArangoDBException + * @see API + * Documentation + */ + SearchAliasPropertiesEntity getProperties() throws ArangoDBException; + + /** + * Partially changes properties of the view. + * + * @param options properties to change + * @return properties of the view + * @throws ArangoDBException + * @see API + * Documentation + */ + SearchAliasPropertiesEntity updateProperties(SearchAliasPropertiesOptions options) throws ArangoDBException; + + /** + * Changes properties of the view. + * + * @param options properties to change + * @return properties of the view + * @throws ArangoDBException + * @see API + * Documentation + */ + SearchAliasPropertiesEntity replaceProperties(SearchAliasPropertiesOptions options) throws ArangoDBException; + +} diff --git a/src/main/java/com/arangodb/async/ArangoDatabaseAsync.java b/src/main/java/com/arangodb/async/ArangoDatabaseAsync.java index a2cf44135..bbd46f8b6 100644 --- a/src/main/java/com/arangodb/async/ArangoDatabaseAsync.java +++ b/src/main/java/com/arangodb/async/ArangoDatabaseAsync.java @@ -27,6 +27,7 @@ import com.arangodb.model.*; import com.arangodb.model.arangosearch.AnalyzerDeleteOptions; import com.arangodb.model.arangosearch.ArangoSearchCreateOptions; +import com.arangodb.model.arangosearch.SearchAliasCreateOptions; import javax.annotation.concurrent.ThreadSafe; import java.util.Collection; @@ -670,7 +671,7 @@ CompletableFuture createGraph( ArangoViewAsync view(String name); /** - * Returns a {@code ArangoSearchAsync} instance for the given ArangoSearch view name. + * Returns a {@link ArangoSearchAsync} instance for the given ArangoSearch view name. * * @param name Name of the view * @return ArangoSearch view handler @@ -678,6 +679,15 @@ CompletableFuture createGraph( */ ArangoSearchAsync arangoSearch(String name); + /** + * Returns a {@link SearchAliasAsync} instance for the given view name. + * + * @param name Name of the view + * @return SearchAlias view handler + * @since ArangoDB 3.10 + */ + SearchAliasAsync searchAlias(String name); + /** * Creates a view of the given {@code type}, then returns view information from the server. * @@ -700,6 +710,18 @@ CompletableFuture createGraph( */ CompletableFuture createArangoSearch(String name, ArangoSearchCreateOptions options); + /** + * Creates a SearchAlias view with the given {@code options}, then returns view information from the server. + * + * @param name The name of the view + * @param options Additional options, can be null + * @return information about the view + * @see API + * Documentation + * @since ArangoDB 3.10 + */ + CompletableFuture createSearchAlias(String name, SearchAliasCreateOptions options); + /** * Creates an Analyzer * diff --git a/src/main/java/com/arangodb/async/ArangoSearchAsync.java b/src/main/java/com/arangodb/async/ArangoSearchAsync.java index 88ae53ba8..77f112a0d 100644 --- a/src/main/java/com/arangodb/async/ArangoSearchAsync.java +++ b/src/main/java/com/arangodb/async/ArangoSearchAsync.java @@ -32,7 +32,7 @@ * Interface for operations on ArangoDB view level for ArangoSearch views. * * @author Mark Vollmary - * @see View API Documentation + * @see View API Documentation * @since ArangoDB 3.4.0 */ @ThreadSafe diff --git a/src/main/java/com/arangodb/async/SearchAliasAsync.java b/src/main/java/com/arangodb/async/SearchAliasAsync.java new file mode 100644 index 000000000..cfb6d8a84 --- /dev/null +++ b/src/main/java/com/arangodb/async/SearchAliasAsync.java @@ -0,0 +1,89 @@ +/* + * DISCLAIMER + * + * Copyright 2018 ArangoDB GmbH, Cologne, Germany + * + * Licensed 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. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.async; + +import com.arangodb.entity.ViewEntity; +import com.arangodb.entity.arangosearch.SearchAliasPropertiesEntity; +import com.arangodb.model.arangosearch.SearchAliasCreateOptions; +import com.arangodb.model.arangosearch.SearchAliasPropertiesOptions; + +import java.util.concurrent.CompletableFuture; + +/** + * Interface for operations on ArangoDB view level for SearchAlias views. + * + * @author Michele Rastelli + * @see View API Documentation + * @since ArangoDB 3.10 + */ +public interface SearchAliasAsync extends ArangoViewAsync { + + /** + * Creates a view, then returns view information from the server. + * + * @return information about the view + * @see API + * Documentation + */ + CompletableFuture create(); + + /** + * Creates a view with the given {@code options}, then returns view information from the server. + * + * @param options Additional options, can be null + * @return information about the view + * @see API + * Documentation + */ + CompletableFuture create(SearchAliasCreateOptions options); + + /** + * Reads the properties of the specified view. + * + * @return properties of the view + * @see API + * Documentation + */ + CompletableFuture getProperties(); + + /** + * Partially changes properties of the view. + * + * @param options properties to change + * @return properties of the view + * @see API + * Documentation + */ + CompletableFuture updateProperties(SearchAliasPropertiesOptions options); + + /** + * Changes properties of the view. + * + * @param options properties to change + * @return properties of the view + * @see API + * Documentation + */ + CompletableFuture replaceProperties(SearchAliasPropertiesOptions options); + +} diff --git a/src/main/java/com/arangodb/async/internal/ArangoDatabaseAsyncImpl.java b/src/main/java/com/arangodb/async/internal/ArangoDatabaseAsyncImpl.java index f163f0543..f173bf678 100644 --- a/src/main/java/com/arangodb/async/internal/ArangoDatabaseAsyncImpl.java +++ b/src/main/java/com/arangodb/async/internal/ArangoDatabaseAsyncImpl.java @@ -34,6 +34,7 @@ import com.arangodb.model.*; import com.arangodb.model.arangosearch.AnalyzerDeleteOptions; import com.arangodb.model.arangosearch.ArangoSearchCreateOptions; +import com.arangodb.model.arangosearch.SearchAliasCreateOptions; import com.arangodb.velocystream.Request; import java.util.Collection; @@ -428,6 +429,11 @@ public ArangoSearchAsync arangoSearch(final String name) { return new ArangoSearchAsyncImpl(this, name); } + @Override + public SearchAliasAsync searchAlias(String name) { + return new SearchAliasAsyncImpl(this, name); + } + @Override public CompletableFuture createView(final String name, final ViewType type) { return executor.execute(createViewRequest(name, type), ViewEntity.class); @@ -439,6 +445,11 @@ public CompletableFuture createArangoSearch(final String name, return executor.execute(createArangoSearchRequest(name, options), ViewEntity.class); } + @Override + public CompletableFuture createSearchAlias(String name, SearchAliasCreateOptions options) { + return executor.execute(createSearchAliasRequest(name, options), ViewEntity.class); + } + @Override public CompletableFuture createSearchAnalyzer(SearchAnalyzer analyzer) { return executor.execute(createAnalyzerRequest(analyzer), SearchAnalyzer.class); diff --git a/src/main/java/com/arangodb/async/internal/SearchAliasAsyncImpl.java b/src/main/java/com/arangodb/async/internal/SearchAliasAsyncImpl.java new file mode 100644 index 000000000..d5e4cbd4f --- /dev/null +++ b/src/main/java/com/arangodb/async/internal/SearchAliasAsyncImpl.java @@ -0,0 +1,87 @@ +/* + * DISCLAIMER + * + * Copyright 2018 ArangoDB GmbH, Cologne, Germany + * + * Licensed 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. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.async.internal; + +import com.arangodb.async.SearchAliasAsync; +import com.arangodb.entity.ViewEntity; +import com.arangodb.entity.arangosearch.SearchAliasPropertiesEntity; +import com.arangodb.internal.InternalSearchAlias; +import com.arangodb.model.arangosearch.SearchAliasCreateOptions; +import com.arangodb.model.arangosearch.SearchAliasPropertiesOptions; + +import java.util.Objects; +import java.util.concurrent.CompletableFuture; + +public class SearchAliasAsyncImpl + extends InternalSearchAlias + implements SearchAliasAsync { + + SearchAliasAsyncImpl(final ArangoDatabaseAsyncImpl db, final String name) { + super(db, name); + } + + @Override + public CompletableFuture exists() { + return getInfo().thenApply(Objects::nonNull).exceptionally(Objects::isNull); + } + + @Override + public CompletableFuture drop() { + return executor.execute(dropRequest(), Void.class); + } + + @Override + public synchronized CompletableFuture rename(final String newName) { + return executor.execute(renameRequest(newName), ViewEntity.class); + } + + @Override + public CompletableFuture getInfo() { + return executor.execute(getInfoRequest(), ViewEntity.class); + } + + @Override + public CompletableFuture create() { + return create(new SearchAliasCreateOptions()); + } + + @Override + public CompletableFuture create(final SearchAliasCreateOptions options) { + return db().createSearchAlias(name(), options); + } + + @Override + public CompletableFuture getProperties() { + return executor.execute(getPropertiesRequest(), SearchAliasPropertiesEntity.class); + } + + @Override + public CompletableFuture updateProperties(final SearchAliasPropertiesOptions options) { + return executor.execute(updatePropertiesRequest(options), SearchAliasPropertiesEntity.class); + } + + @Override + public CompletableFuture replaceProperties( + final SearchAliasPropertiesOptions options) { + return executor.execute(replacePropertiesRequest(options), SearchAliasPropertiesEntity.class); + } + +} diff --git a/src/main/java/com/arangodb/entity/ViewType.java b/src/main/java/com/arangodb/entity/ViewType.java index 4844fe560..063553cd5 100644 --- a/src/main/java/com/arangodb/entity/ViewType.java +++ b/src/main/java/com/arangodb/entity/ViewType.java @@ -28,6 +28,8 @@ public enum ViewType { @JsonProperty("arangosearch") - ARANGO_SEARCH + ARANGO_SEARCH, + @JsonProperty("search-alias") + SEARCH_ALIAS } diff --git a/src/main/java/com/arangodb/entity/arangosearch/CollectionLink.java b/src/main/java/com/arangodb/entity/arangosearch/CollectionLink.java index 66cf9c73f..63b6a1a38 100644 --- a/src/main/java/com/arangodb/entity/arangosearch/CollectionLink.java +++ b/src/main/java/com/arangodb/entity/arangosearch/CollectionLink.java @@ -43,6 +43,7 @@ public final class CollectionLink { private StoreValuesType storeValues; private Collection fields; private Collection nested; + private Boolean inBackground; private CollectionLink(final String name) { super(); @@ -122,6 +123,18 @@ public CollectionLink nested(final FieldLink... nested) { return this; } + /** + * @param inBackground If set to true, then no exclusive lock is used on the source collection during View index + * creation, so that it remains basically available. inBackground is an option that can be set + * when adding links. It does not get persisted as it is not a View property, but only a + * one-off option. (default: false) + * @return link + */ + public CollectionLink inBackground(final Boolean inBackground) { + this.inBackground = inBackground; + return this; + } + @JsonIgnore public String getName() { return name; @@ -153,4 +166,7 @@ public Collection getNested() { return nested; } + public Boolean getInBackground() { + return inBackground; + } } \ No newline at end of file diff --git a/src/main/java/com/arangodb/entity/arangosearch/FieldLink.java b/src/main/java/com/arangodb/entity/arangosearch/FieldLink.java index f33d858a3..ab71321b3 100644 --- a/src/main/java/com/arangodb/entity/arangosearch/FieldLink.java +++ b/src/main/java/com/arangodb/entity/arangosearch/FieldLink.java @@ -20,6 +20,7 @@ public final class FieldLink { private StoreValuesType storeValues; private Collection fields; private Collection nested; + private Boolean inBackground; private FieldLink(final String name) { super(); @@ -99,6 +100,18 @@ public FieldLink nested(final FieldLink... nested) { return this; } + /** + * @param inBackground If set to true, then no exclusive lock is used on the source collection during View index + * creation, so that it remains basically available. inBackground is an option that can be set + * when adding links. It does not get persisted as it is not a View property, but only a + * one-off option. (default: false) + * @return link + */ + public FieldLink inBackground(final Boolean inBackground) { + this.inBackground = inBackground; + return this; + } + @JsonIgnore public String getName() { return name; @@ -129,4 +142,8 @@ public Collection getFields() { public Collection getNested() { return nested; } + + public Boolean getInBackground() { + return inBackground; + } } \ No newline at end of file diff --git a/src/main/java/com/arangodb/entity/arangosearch/SearchAliasIndex.java b/src/main/java/com/arangodb/entity/arangosearch/SearchAliasIndex.java new file mode 100644 index 000000000..40f19930d --- /dev/null +++ b/src/main/java/com/arangodb/entity/arangosearch/SearchAliasIndex.java @@ -0,0 +1,27 @@ +package com.arangodb.entity.arangosearch; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * @author Michele Rastelli + * @since ArabgoDB 3.10 + */ +public class SearchAliasIndex { + private final String collection; + private final String index; + + @JsonCreator + public SearchAliasIndex(@JsonProperty("collection") String collection, @JsonProperty("index") String index) { + this.collection = collection; + this.index = index; + } + + public String getCollection() { + return collection; + } + + public String getIndex() { + return index; + } +} diff --git a/src/main/java/com/arangodb/entity/arangosearch/SearchAliasPropertiesEntity.java b/src/main/java/com/arangodb/entity/arangosearch/SearchAliasPropertiesEntity.java new file mode 100644 index 000000000..4049bd78d --- /dev/null +++ b/src/main/java/com/arangodb/entity/arangosearch/SearchAliasPropertiesEntity.java @@ -0,0 +1,43 @@ +/* + * DISCLAIMER + * + * Copyright 2018 ArangoDB GmbH, Cologne, Germany + * + * Licensed 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. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.entity.arangosearch; + +import com.arangodb.entity.ViewEntity; + +import java.util.ArrayList; +import java.util.Collection; + +/** + * @author Michele Rastelli + * @see API Documentation + */ +public class SearchAliasPropertiesEntity extends ViewEntity { + + private final Collection indexes = new ArrayList<>(); + + /** + * @return A list of inverted indexes to add to the View. + */ + public Collection getIndexes() { + return indexes; + } + +} diff --git a/src/main/java/com/arangodb/internal/ArangoDatabaseImpl.java b/src/main/java/com/arangodb/internal/ArangoDatabaseImpl.java index 274dcc4bf..9d81dd261 100644 --- a/src/main/java/com/arangodb/internal/ArangoDatabaseImpl.java +++ b/src/main/java/com/arangodb/internal/ArangoDatabaseImpl.java @@ -30,6 +30,7 @@ import com.arangodb.model.*; import com.arangodb.model.arangosearch.AnalyzerDeleteOptions; import com.arangodb.model.arangosearch.ArangoSearchCreateOptions; +import com.arangodb.model.arangosearch.SearchAliasCreateOptions; import com.arangodb.util.ArangoCursorInitializer; import com.arangodb.velocystream.Request; @@ -395,6 +396,11 @@ public ArangoSearch arangoSearch(final String name) { return new ArangoSearchImpl(this, name); } + @Override + public SearchAlias searchAlias(String name) { + return new SearchAliasImpl(this, name); + } + @Override public ViewEntity createView(final String name, final ViewType type) { return executor.execute(createViewRequest(name, type), ViewEntity.class); @@ -405,6 +411,11 @@ public ViewEntity createArangoSearch(final String name, final ArangoSearchCreate return executor.execute(createArangoSearchRequest(name, options), ViewEntity.class); } + @Override + public ViewEntity createSearchAlias(String name, SearchAliasCreateOptions options) throws ArangoDBException { + return executor.execute(createSearchAliasRequest(name, options), ViewEntity.class); + } + @Override public SearchAnalyzer createSearchAnalyzer(SearchAnalyzer analyzer) { return executor.execute(createAnalyzerRequest(analyzer), SearchAnalyzer.class); diff --git a/src/main/java/com/arangodb/internal/InternalArangoDatabase.java b/src/main/java/com/arangodb/internal/InternalArangoDatabase.java index 4f473607c..c1da4db4d 100644 --- a/src/main/java/com/arangodb/internal/InternalArangoDatabase.java +++ b/src/main/java/com/arangodb/internal/InternalArangoDatabase.java @@ -26,9 +26,7 @@ import com.arangodb.internal.ArangoExecutor.ResponseDeserializer; import com.arangodb.internal.util.RequestUtils; import com.arangodb.model.*; -import com.arangodb.model.arangosearch.AnalyzerDeleteOptions; -import com.arangodb.model.arangosearch.ArangoSearchCreateOptions; -import com.arangodb.model.arangosearch.ArangoSearchOptionsBuilder; +import com.arangodb.model.arangosearch.*; import com.arangodb.velocystream.Request; import com.arangodb.velocystream.RequestType; @@ -364,6 +362,11 @@ protected Request createArangoSearchRequest(final String name, final ArangoSearc return request(dbName, RequestType.POST, InternalArangoView.PATH_API_VIEW).setBody(getSerde().serialize(ArangoSearchOptionsBuilder.build(options != null ? options : new ArangoSearchCreateOptions(), name))); } + protected Request createSearchAliasRequest(final String name, final SearchAliasCreateOptions options) { + return request(dbName, RequestType.POST, InternalArangoView.PATH_API_VIEW).setBody(getSerde().serialize( + SearchAliasOptionsBuilder.build(options != null ? options : new SearchAliasCreateOptions(), name))); + } + protected Request getAnalyzerRequest(final String name) { return request(dbName, RequestType.GET, InternalArangoView.PATH_API_ANALYZER, name); } diff --git a/src/main/java/com/arangodb/internal/InternalSearchAlias.java b/src/main/java/com/arangodb/internal/InternalSearchAlias.java new file mode 100644 index 000000000..46e6a11bb --- /dev/null +++ b/src/main/java/com/arangodb/internal/InternalSearchAlias.java @@ -0,0 +1,50 @@ +/* + * DISCLAIMER + * + * Copyright 2018 ArangoDB GmbH, Cologne, Germany + * + * Licensed 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. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.internal; + +import com.arangodb.model.arangosearch.SearchAliasPropertiesOptions; +import com.arangodb.velocystream.Request; +import com.arangodb.velocystream.RequestType; + +public class InternalSearchAlias, D extends InternalArangoDatabase, E extends ArangoExecutor> + extends InternalArangoView { + + protected InternalSearchAlias(final D db, final String name) { + super(db, name); + } + + protected Request getPropertiesRequest() { + return request(db.dbName(), RequestType.GET, PATH_API_VIEW, name, "properties"); + } + + protected Request replacePropertiesRequest(final SearchAliasPropertiesOptions options) { + final Request request = request(db.dbName(), RequestType.PUT, PATH_API_VIEW, name, "properties"); + request.setBody(getSerde().serialize(options != null ? options : new SearchAliasPropertiesOptions())); + return request; + } + + protected Request updatePropertiesRequest(final SearchAliasPropertiesOptions options) { + final Request request = request(db.dbName(), RequestType.PATCH, PATH_API_VIEW, name, "properties"); + request.setBody(getSerde().serialize(options != null ? options : new SearchAliasPropertiesOptions())); + return request; + } + +} diff --git a/src/main/java/com/arangodb/internal/SearchAliasImpl.java b/src/main/java/com/arangodb/internal/SearchAliasImpl.java new file mode 100644 index 000000000..589e4e208 --- /dev/null +++ b/src/main/java/com/arangodb/internal/SearchAliasImpl.java @@ -0,0 +1,97 @@ +/* + * DISCLAIMER + * + * Copyright 2018 ArangoDB GmbH, Cologne, Germany + * + * Licensed 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. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.internal; + +import com.arangodb.ArangoDBException; +import com.arangodb.SearchAlias; +import com.arangodb.entity.ViewEntity; +import com.arangodb.entity.arangosearch.SearchAliasPropertiesEntity; +import com.arangodb.model.arangosearch.SearchAliasCreateOptions; +import com.arangodb.model.arangosearch.SearchAliasPropertiesOptions; + +/** + * @author Michele Rastelli + */ +public class SearchAliasImpl extends InternalSearchAlias + implements SearchAlias { + + protected SearchAliasImpl(final ArangoDatabaseImpl db, final String name) { + super(db, name); + } + + @Override + public boolean exists() throws ArangoDBException { + try { + getInfo(); + return true; + } catch (final ArangoDBException e) { + if (ArangoErrors.ERROR_ARANGO_DATA_SOURCE_NOT_FOUND.equals(e.getErrorNum())) { + return false; + } + throw e; + } + } + + @Override + public void drop() throws ArangoDBException { + executor.execute(dropRequest(), Void.class); + } + + @Override + public synchronized ViewEntity rename(final String newName) throws ArangoDBException { + final ViewEntity result = executor.execute(renameRequest(newName), ViewEntity.class); + name = result.getName(); + return result; + } + + @Override + public ViewEntity getInfo() throws ArangoDBException { + return executor.execute(getInfoRequest(), ViewEntity.class); + } + + @Override + public ViewEntity create() throws ArangoDBException { + return create(new SearchAliasCreateOptions()); + } + + @Override + public ViewEntity create(final SearchAliasCreateOptions options) throws ArangoDBException { + return db().createSearchAlias(name(), options); + } + + @Override + public SearchAliasPropertiesEntity getProperties() throws ArangoDBException { + return executor.execute(getPropertiesRequest(), SearchAliasPropertiesEntity.class); + } + + @Override + public SearchAliasPropertiesEntity updateProperties(final SearchAliasPropertiesOptions options) + throws ArangoDBException { + return executor.execute(updatePropertiesRequest(options), SearchAliasPropertiesEntity.class); + } + + @Override + public SearchAliasPropertiesEntity replaceProperties(final SearchAliasPropertiesOptions options) + throws ArangoDBException { + return executor.execute(replacePropertiesRequest(options), SearchAliasPropertiesEntity.class); + } + +} diff --git a/src/main/java/com/arangodb/model/arangosearch/SearchAliasCreateOptions.java b/src/main/java/com/arangodb/model/arangosearch/SearchAliasCreateOptions.java new file mode 100644 index 000000000..8e4f589cf --- /dev/null +++ b/src/main/java/com/arangodb/model/arangosearch/SearchAliasCreateOptions.java @@ -0,0 +1,71 @@ +/* + * DISCLAIMER + * + * Copyright 2018 ArangoDB GmbH, Cologne, Germany + * + * Licensed 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. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.model.arangosearch; + +import com.arangodb.entity.ViewType; +import com.arangodb.entity.arangosearch.*; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; + +/** + * @author Michele Rastelli + * @since ArangoDB 3.10 + */ +public class SearchAliasCreateOptions { + + private String name; + private final ViewType type; + + private final Collection indexes = new ArrayList<>(); + + public SearchAliasCreateOptions() { + super(); + type = ViewType.SEARCH_ALIAS; + } + + protected SearchAliasCreateOptions name(final String name) { + this.name = name; + return this; + } + + /** + * @param indexes A list of inverted indexes to add to the View. + * @return options + */ + public SearchAliasCreateOptions indexes(final SearchAliasIndex... indexes) { + Collections.addAll(this.indexes, indexes); + return this; + } + + public String getName() { + return name; + } + + public ViewType getType() { + return type; + } + + public Collection getIndexes() { + return indexes; + } +} diff --git a/src/main/java/com/arangodb/model/arangosearch/SearchAliasOptionsBuilder.java b/src/main/java/com/arangodb/model/arangosearch/SearchAliasOptionsBuilder.java new file mode 100644 index 000000000..155e916be --- /dev/null +++ b/src/main/java/com/arangodb/model/arangosearch/SearchAliasOptionsBuilder.java @@ -0,0 +1,35 @@ +/* + * DISCLAIMER + * + * Copyright 2018 ArangoDB GmbH, Cologne, Germany + * + * Licensed 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. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.model.arangosearch; + +/** + * @author Michele Rastelli + */ +public abstract class SearchAliasOptionsBuilder { + + private SearchAliasOptionsBuilder() { + super(); + } + + public static SearchAliasCreateOptions build(final SearchAliasCreateOptions options, final String name) { + return options.name(name); + } +} diff --git a/src/main/java/com/arangodb/model/arangosearch/SearchAliasPropertiesOptions.java b/src/main/java/com/arangodb/model/arangosearch/SearchAliasPropertiesOptions.java new file mode 100644 index 000000000..fff218def --- /dev/null +++ b/src/main/java/com/arangodb/model/arangosearch/SearchAliasPropertiesOptions.java @@ -0,0 +1,49 @@ +/* + * DISCLAIMER + * + * Copyright 2018 ArangoDB GmbH, Cologne, Germany + * + * Licensed 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. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.model.arangosearch; + +import com.arangodb.entity.arangosearch.*; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; + +/** + * @author Michele Rastelli + * @since ArangoDB 3.10 + */ +public class SearchAliasPropertiesOptions { + + private final Collection indexes = new ArrayList<>(); + + /** + * @param indexes A list of inverted indexes to add to the View. + * @return options + */ + public SearchAliasPropertiesOptions indexes(SearchAliasIndex... indexes) { + Collections.addAll(this.indexes, indexes); + return this; + } + + public Collection getIndexes() { + return indexes; + } +} diff --git a/src/test/java/com/arangodb/ArangoSearchTest.java b/src/test/java/com/arangodb/ArangoSearchTest.java index bdeca9cea..32cabf6de 100644 --- a/src/test/java/com/arangodb/ArangoSearchTest.java +++ b/src/test/java/com/arangodb/ArangoSearchTest.java @@ -20,14 +20,15 @@ package com.arangodb; +import com.arangodb.entity.InvertedIndexField; import com.arangodb.entity.ViewEntity; import com.arangodb.entity.ViewType; import com.arangodb.entity.arangosearch.*; import com.arangodb.entity.arangosearch.analyzer.*; -import com.arangodb.model.arangosearch.AnalyzerDeleteOptions; -import com.arangodb.model.arangosearch.ArangoSearchCreateOptions; -import com.arangodb.model.arangosearch.ArangoSearchPropertiesOptions; +import com.arangodb.model.InvertedIndexOptions; +import com.arangodb.model.arangosearch.*; import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.MethodSource; @@ -51,6 +52,11 @@ static void init() { initCollections(COLL_1, COLL_2); } + @BeforeEach + void setUp() { + assumeTrue(isLessThanVersion(3, 10) || isSingleServer()); + } + @ParameterizedTest(name = "{index}") @MethodSource("dbs") void exists(ArangoDatabase db) { @@ -60,6 +66,15 @@ void exists(ArangoDatabase db) { assertThat(db.arangoSearch(viewName).exists()).isTrue(); } + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void createAndExistsSearchAlias(ArangoDatabase db) { + assumeTrue(isAtLeastVersion(3, 10)); + String viewName = "view-" + rnd(); + db.createSearchAlias(viewName, new SearchAliasCreateOptions()); + assertThat(db.arangoSearch(viewName).exists()).isTrue(); + } + @ParameterizedTest(name = "{index}") @MethodSource("dbs") void getInfo(ArangoDatabase db) { @@ -99,7 +114,7 @@ void rename(ArangoDatabase db) { @ParameterizedTest(name = "{index}") @MethodSource("dbs") - void create(ArangoDatabase db) { + void createArangoSearchView(ArangoDatabase db) { assumeTrue(isAtLeastVersion(3, 4)); String viewName = "view-" + rnd(); final ViewEntity info = db.arangoSearch(viewName).create(); @@ -112,7 +127,20 @@ void create(ArangoDatabase db) { @ParameterizedTest(name = "{index}") @MethodSource("dbs") - void createWithOptions(ArangoDatabase db) { + void createSearchAliasView(ArangoDatabase db) { + assumeTrue(isAtLeastVersion(3, 10)); + String viewName = "view-" + rnd(); + final ViewEntity info = db.searchAlias(viewName).create(); + assertThat(info).isNotNull(); + assertThat(info.getId()).isNotNull(); + assertThat(info.getName()).isEqualTo(viewName); + assertThat(info.getType()).isEqualTo(ViewType.SEARCH_ALIAS); + assertThat(db.searchAlias(viewName).exists()).isTrue(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void createArangoSearchViewWithOptions(ArangoDatabase db) { assumeTrue(isAtLeastVersion(3, 4)); String viewName = "view-" + rnd(); final ArangoSearchCreateOptions options = new ArangoSearchCreateOptions(); @@ -126,7 +154,7 @@ void createWithOptions(ArangoDatabase db) { @ParameterizedTest(name = "{index}") @MethodSource("dbs") - void createWithPrimarySort(ArangoDatabase db) { + void createArangoSearchViewWithPrimarySort(ArangoDatabase db) { assumeTrue(isAtLeastVersion(3, 5)); String viewName = "view-" + rnd(); final ArangoSearchCreateOptions options = new ArangoSearchCreateOptions(); @@ -162,7 +190,7 @@ void createWithPrimarySort(ArangoDatabase db) { @ParameterizedTest(name = "{index}") @MethodSource("dbs") - void createWithCommitIntervalMsec(ArangoDatabase db) { + void createArangoSearchViewWithCommitIntervalMsec(ArangoDatabase db) { assumeTrue(isAtLeastVersion(3, 5)); String viewName = "view-" + rnd(); final ArangoSearchCreateOptions options = new ArangoSearchCreateOptions(); @@ -183,7 +211,50 @@ void createWithCommitIntervalMsec(ArangoDatabase db) { @ParameterizedTest(name = "{index}") @MethodSource("dbs") - void getProperties(ArangoDatabase db) { + void createSearchAliasViewWithOptions(ArangoDatabase db) { + assumeTrue(isAtLeastVersion(3, 10)); + String viewName = "view-" + rnd(); + final SearchAliasCreateOptions options = new SearchAliasCreateOptions(); + final ViewEntity info = db.searchAlias(viewName).create(options); + assertThat(info).isNotNull(); + assertThat(info.getId()).isNotNull(); + assertThat(info.getName()).isEqualTo(viewName); + assertThat(info.getType()).isEqualTo(ViewType.SEARCH_ALIAS); + assertThat(db.searchAlias(viewName).exists()).isTrue(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void createSearchAliasViewWithIndexesAndGetProperties(ArangoDatabase db) { + assumeTrue(isAtLeastVersion(3, 10)); + ArangoCollection col = db.collection(COLL_1); + String idxName = "idx-" + rnd(); + col.ensureInvertedIndex(new InvertedIndexOptions() + .name(idxName) + .fields(new InvertedIndexField().name("a" + rnd()))); + String viewName = "view-" + rnd(); + final SearchAliasCreateOptions options = new SearchAliasCreateOptions() + .indexes(new SearchAliasIndex(COLL_1, idxName)); + final ViewEntity info = db.searchAlias(viewName).create(options); + assertThat(info).isNotNull(); + assertThat(info.getId()).isNotNull(); + assertThat(info.getName()).isEqualTo(viewName); + assertThat(info.getType()).isEqualTo(ViewType.SEARCH_ALIAS); + + final SearchAliasPropertiesEntity properties = db.searchAlias(viewName).getProperties(); + assertThat(properties).isNotNull(); + assertThat(properties.getId()).isNotNull(); + assertThat(properties.getName()).isEqualTo(viewName); + assertThat(properties.getType()).isEqualTo(ViewType.SEARCH_ALIAS); + assertThat(properties.getIndexes()) + .isNotNull() + .isNotEmpty() + .anyMatch(i -> i.getCollection().equals(COLL_1) && i.getIndex().equals(idxName)); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void getArangoSearchViewProperties(ArangoDatabase db) { assumeTrue(isAtLeastVersion(3, 4)); String viewName = "view-" + rnd(); final ArangoSearch view = db.arangoSearch(viewName); @@ -203,7 +274,7 @@ void getProperties(ArangoDatabase db) { @ParameterizedTest(name = "{index}") @MethodSource("dbs") - void updateProperties(ArangoDatabase db) { + void updateArangoSearchViewProperties(ArangoDatabase db) { assumeTrue(isAtLeastVersion(3, 4)); String viewName = "view-" + rnd(); final ArangoSearch view = db.arangoSearch(viewName); @@ -236,7 +307,47 @@ void updateProperties(ArangoDatabase db) { @ParameterizedTest(name = "{index}") @MethodSource("dbs") - void replaceProperties(ArangoDatabase db) { + void updateSearchAliasViewWithIndexesAndGetProperties(ArangoDatabase db) { + assumeTrue(isAtLeastVersion(3, 10)); + ArangoCollection col = db.collection(COLL_1); + String idxName = "idx-" + rnd(); + col.ensureInvertedIndex(new InvertedIndexOptions() + .name(idxName) + .fields(new InvertedIndexField().name("a" + rnd()))); + ArangoCollection col2 = db.collection(COLL_2); + String idxName2 = "idx-" + rnd(); + col2.ensureInvertedIndex(new InvertedIndexOptions() + .name(idxName2) + .fields(new InvertedIndexField().name("a" + rnd()))); + + String viewName = "view-" + rnd(); + final SearchAliasCreateOptions options = new SearchAliasCreateOptions() + .indexes(new SearchAliasIndex(COLL_1, idxName)); + final ViewEntity info = db.searchAlias(viewName).create(options); + db.searchAlias(viewName).updateProperties(new SearchAliasPropertiesOptions() + .indexes(new SearchAliasIndex(COLL_2, idxName2))); + + assertThat(info).isNotNull(); + assertThat(info.getId()).isNotNull(); + assertThat(info.getName()).isEqualTo(viewName); + assertThat(info.getType()).isEqualTo(ViewType.SEARCH_ALIAS); + + final SearchAliasPropertiesEntity properties = db.searchAlias(viewName).getProperties(); + assertThat(properties).isNotNull(); + assertThat(properties.getId()).isNotNull(); + assertThat(properties.getName()).isEqualTo(viewName); + assertThat(properties.getType()).isEqualTo(ViewType.SEARCH_ALIAS); + assertThat(properties.getIndexes()) + .isNotNull() + .isNotEmpty() + .hasSize(2) + .anyMatch(i -> i.getCollection().equals(COLL_1) && i.getIndex().equals(idxName)) + .anyMatch(i -> i.getCollection().equals(COLL_2) && i.getIndex().equals(idxName2)); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void replaceArangoSearchViewProperties(ArangoDatabase db) { assumeTrue(isAtLeastVersion(3, 4)); String viewName = "view-" + rnd(); final ArangoSearch view = db.arangoSearch(viewName); @@ -253,6 +364,45 @@ void replaceProperties(ArangoDatabase db) { assertThat(link.getFields().iterator().next().getName()).isEqualTo("value"); } + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void replaceSearchAliasViewWithIndexesAndGetProperties(ArangoDatabase db) { + assumeTrue(isAtLeastVersion(3, 10)); + ArangoCollection col = db.collection(COLL_1); + String idxName = "idx-" + rnd(); + col.ensureInvertedIndex(new InvertedIndexOptions() + .name(idxName) + .fields(new InvertedIndexField().name("a" + rnd()))); + ArangoCollection col2 = db.collection(COLL_2); + String idxName2 = "idx-" + rnd(); + col2.ensureInvertedIndex(new InvertedIndexOptions() + .name(idxName2) + .fields(new InvertedIndexField().name("a" + rnd()))); + + String viewName = "view-" + rnd(); + final SearchAliasCreateOptions options = new SearchAliasCreateOptions() + .indexes(new SearchAliasIndex(COLL_1, idxName)); + final ViewEntity info = db.searchAlias(viewName).create(options); + db.searchAlias(viewName).replaceProperties(new SearchAliasPropertiesOptions() + .indexes(new SearchAliasIndex(COLL_2, idxName2))); + + assertThat(info).isNotNull(); + assertThat(info.getId()).isNotNull(); + assertThat(info.getName()).isEqualTo(viewName); + assertThat(info.getType()).isEqualTo(ViewType.SEARCH_ALIAS); + + final SearchAliasPropertiesEntity properties = db.searchAlias(viewName).getProperties(); + assertThat(properties).isNotNull(); + assertThat(properties.getId()).isNotNull(); + assertThat(properties.getName()).isEqualTo(viewName); + assertThat(properties.getType()).isEqualTo(ViewType.SEARCH_ALIAS); + assertThat(properties.getIndexes()) + .isNotNull() + .isNotEmpty() + .hasSize(1) + .anyMatch(i -> i.getCollection().equals(COLL_2) && i.getIndex().equals(idxName2)); + } + private void createGetAndDeleteTypedAnalyzer(ArangoDatabase db, SearchAnalyzer analyzer) { String fullyQualifiedName = db.dbName().get() + "::" + analyzer.getName(); @@ -493,7 +643,7 @@ void enhancedTextAnalyzerTyped(ArangoDatabase db) { void arangoSearchOptions(ArangoDatabase db) { assumeTrue(isAtLeastVersion(3, 4)); String viewName = "view-" + rnd(); - FieldLink field = FieldLink.on("f1"); + FieldLink field = FieldLink.on("f1").inBackground(true); if (isEnterprise()) { field.nested(FieldLink.on("f2")); } @@ -502,7 +652,8 @@ void arangoSearchOptions(ArangoDatabase db) { .fields(field) .includeAllFields(true) .storeValues(StoreValuesType.ID) - .trackListPositions(false); + .trackListPositions(false) + .inBackground(true); if (isEnterprise()) { link.nested(FieldLink.on("f3")); } diff --git a/src/test/java/com/arangodb/ArangoViewTest.java b/src/test/java/com/arangodb/ArangoViewTest.java index 5d63b02ac..09121b7ff 100644 --- a/src/test/java/com/arangodb/ArangoViewTest.java +++ b/src/test/java/com/arangodb/ArangoViewTest.java @@ -26,6 +26,8 @@ import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.MethodSource; +import java.util.Collection; + import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assumptions.assumeTrue; @@ -61,6 +63,31 @@ void getInfo(ArangoDatabase db) { assertThat(info.getType()).isEqualTo(ViewType.ARANGO_SEARCH); } + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void getInfoSearchAlias(ArangoDatabase db) { + assumeTrue(isAtLeastVersion(3, 10)); + String name = "view-" + rnd(); + db.createView(name, ViewType.SEARCH_ALIAS); + final ViewEntity info = db.view(name).getInfo(); + assertThat(info).isNotNull(); + assertThat(info.getId()).isNotNull(); + assertThat(info.getName()).isEqualTo(name); + assertThat(info.getType()).isEqualTo(ViewType.SEARCH_ALIAS); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void getViews(ArangoDatabase db) { + assumeTrue(isAtLeastVersion(3, 10)); + String name1 = "view-" + rnd(); + String name2 = "view-" + rnd(); + db.createView(name1, ViewType.ARANGO_SEARCH); + db.createView(name2, ViewType.SEARCH_ALIAS); + Collection views = db.getViews(); + assertThat(views).extracting(ViewEntity::getName).contains(name1, name2); + } + @ParameterizedTest(name = "{index}") @MethodSource("dbs") void drop(ArangoDatabase db) { diff --git a/src/test/java/com/arangodb/async/ArangoSearchTest.java b/src/test/java/com/arangodb/async/ArangoSearchTest.java index 41a88e0e1..ff2cebe83 100644 --- a/src/test/java/com/arangodb/async/ArangoSearchTest.java +++ b/src/test/java/com/arangodb/async/ArangoSearchTest.java @@ -20,16 +20,21 @@ package com.arangodb.async; +import com.arangodb.ArangoCollection; import com.arangodb.ArangoDBException; +import com.arangodb.ArangoDatabase; +import com.arangodb.entity.InvertedIndexField; import com.arangodb.entity.ViewEntity; import com.arangodb.entity.ViewType; import com.arangodb.entity.arangosearch.*; import com.arangodb.entity.arangosearch.analyzer.*; -import com.arangodb.model.arangosearch.AnalyzerDeleteOptions; -import com.arangodb.model.arangosearch.ArangoSearchCreateOptions; -import com.arangodb.model.arangosearch.ArangoSearchPropertiesOptions; +import com.arangodb.model.InvertedIndexOptions; +import com.arangodb.model.arangosearch.*; import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; import java.util.Collection; import java.util.HashSet; @@ -48,12 +53,21 @@ class ArangoSearchTest extends BaseTest { private static final String VIEW_NAME = "view_test"; + private static final String COLL_1 = "view_update_prop_test_collection"; + private static final String COLL_2 = "view_replace_prop_test_collection"; @BeforeAll static void setup() throws InterruptedException, ExecutionException { if (!isAtLeastVersion(arangoDB, 3, 4)) return; db.createArangoSearch(VIEW_NAME, new ArangoSearchCreateOptions()).get(); + db.createCollection(COLL_1).get(); + db.createCollection(COLL_2).get(); + } + + @BeforeEach + void setUp() throws ExecutionException, InterruptedException { + assumeTrue(isLessThanVersion(3, 10) || isSingleServer()); } @Test @@ -62,6 +76,14 @@ void exists() throws InterruptedException, ExecutionException { assertThat(db.arangoSearch(VIEW_NAME).exists().get()).isTrue(); } + @Test + void createAndExistsSearchAlias() throws ExecutionException, InterruptedException { + assumeTrue(isAtLeastVersion(3, 10)); + String viewName = "view-" + rnd(); + db.createSearchAlias(viewName, new SearchAliasCreateOptions()).get(); + assertThat(db.arangoSearch(viewName).exists().get()).isTrue(); + } + @Test void getInfo() throws InterruptedException, ExecutionException { assumeTrue(isAtLeastVersion(3, 4)); @@ -95,7 +117,7 @@ void rename() throws InterruptedException, ExecutionException { } @Test - void create() throws InterruptedException, ExecutionException { + void createArangoSearchView() throws InterruptedException, ExecutionException { assumeTrue(isAtLeastVersion(3, 4)); final String name = VIEW_NAME + "_createtest"; final ViewEntity info = db.arangoSearch(name).create().get(); @@ -107,7 +129,19 @@ void create() throws InterruptedException, ExecutionException { } @Test - void createWithOptions() throws InterruptedException, ExecutionException { + void createSearchAliasView() throws ExecutionException, InterruptedException { + assumeTrue(isAtLeastVersion(3, 10)); + String viewName = "view-" + rnd(); + final ViewEntity info = db.searchAlias(viewName).create().get(); + assertThat(info).isNotNull(); + assertThat(info.getId()).isNotNull(); + assertThat(info.getName()).isEqualTo(viewName); + assertThat(info.getType()).isEqualTo(ViewType.SEARCH_ALIAS); + assertThat(db.searchAlias(viewName).exists().get()).isTrue(); + } + + @Test + void createArangoSearchViewWithOptions() throws InterruptedException, ExecutionException { assumeTrue(isAtLeastVersion(3, 4)); final String name = VIEW_NAME + "_createtest_withotpions"; final ViewEntity info = db.arangoSearch(name).create(new ArangoSearchCreateOptions()).get(); @@ -119,7 +153,7 @@ void createWithOptions() throws InterruptedException, ExecutionException { } @Test - void createWithPrimarySort() throws ExecutionException, InterruptedException { + void createArangoSearchViewWithPrimarySort() throws ExecutionException, InterruptedException { assumeTrue(isAtLeastVersion(3, 5)); final String name = "createWithPrimarySort"; final ArangoSearchCreateOptions options = new ArangoSearchCreateOptions(); @@ -138,7 +172,7 @@ void createWithPrimarySort() throws ExecutionException, InterruptedException { } @Test - void createWithCommitIntervalMsec() throws ExecutionException, InterruptedException { + void createArangoSearchViewWithCommitIntervalMsec() throws ExecutionException, InterruptedException { assumeTrue(isAtLeastVersion(3, 5)); final String name = "createWithCommitIntervalMsec"; final ArangoSearchCreateOptions options = new ArangoSearchCreateOptions(); @@ -158,7 +192,49 @@ void createWithCommitIntervalMsec() throws ExecutionException, InterruptedExcept } @Test - void getProperties() throws InterruptedException, ExecutionException { + void createSearchAliasViewWithOptions() throws ExecutionException, InterruptedException { + assumeTrue(isAtLeastVersion(3, 10)); + String viewName = "view-" + rnd(); + final SearchAliasCreateOptions options = new SearchAliasCreateOptions(); + final ViewEntity info = db.searchAlias(viewName).create(options).get(); + assertThat(info).isNotNull(); + assertThat(info.getId()).isNotNull(); + assertThat(info.getName()).isEqualTo(viewName); + assertThat(info.getType()).isEqualTo(ViewType.SEARCH_ALIAS); + assertThat(db.searchAlias(viewName).exists().get()).isTrue(); + } + + @Test + void createSearchAliasViewWithIndexesAndGetProperties() throws ExecutionException, InterruptedException { + assumeTrue(isAtLeastVersion(3, 10)); + ArangoCollectionAsync col = db.collection(COLL_1); + String idxName = "idx-" + rnd(); + col.ensureInvertedIndex(new InvertedIndexOptions() + .name(idxName) + .fields(new InvertedIndexField().name("a" + rnd()))) + .get(); + String viewName = "view-" + rnd(); + final SearchAliasCreateOptions options = new SearchAliasCreateOptions() + .indexes(new SearchAliasIndex(COLL_1, idxName)); + final ViewEntity info = db.searchAlias(viewName).create(options).get(); + assertThat(info).isNotNull(); + assertThat(info.getId()).isNotNull(); + assertThat(info.getName()).isEqualTo(viewName); + assertThat(info.getType()).isEqualTo(ViewType.SEARCH_ALIAS); + + final SearchAliasPropertiesEntity properties = db.searchAlias(viewName).getProperties().get(); + assertThat(properties).isNotNull(); + assertThat(properties.getId()).isNotNull(); + assertThat(properties.getName()).isEqualTo(viewName); + assertThat(properties.getType()).isEqualTo(ViewType.SEARCH_ALIAS); + assertThat(properties.getIndexes()) + .isNotNull() + .isNotEmpty() + .anyMatch(i -> i.getCollection().equals(COLL_1) && i.getIndex().equals(idxName)); + } + + @Test + void getArangoSearchViewProperties() throws InterruptedException, ExecutionException { assumeTrue(isAtLeastVersion(3, 4)); final String name = VIEW_NAME + "_getpropertiestest"; final ArangoSearchAsync view = db.arangoSearch(name); @@ -177,9 +253,8 @@ void getProperties() throws InterruptedException, ExecutionException { } @Test - void updateProperties() throws InterruptedException, ExecutionException { + void updateArangoSearchViewProperties() throws InterruptedException, ExecutionException { assumeTrue(isAtLeastVersion(3, 4)); - db.createCollection("view_update_prop_test_collection").get(); final String name = VIEW_NAME + "_updatepropertiestest"; final ArangoSearchAsync view = db.arangoSearch(name); view.create(new ArangoSearchCreateOptions()).get(); @@ -210,9 +285,49 @@ void updateProperties() throws InterruptedException, ExecutionException { } @Test - void replaceProperties() throws InterruptedException, ExecutionException { + void updateSearchAliasViewWithIndexesAndGetProperties() throws ExecutionException, InterruptedException { + assumeTrue(isAtLeastVersion(3, 10)); + ArangoCollectionAsync col = db.collection(COLL_1); + String idxName = "idx-" + rnd(); + col.ensureInvertedIndex(new InvertedIndexOptions() + .name(idxName) + .fields(new InvertedIndexField().name("a" + rnd()))) + .get(); + ArangoCollectionAsync col2 = db.collection(COLL_2); + String idxName2 = "idx-" + rnd(); + col2.ensureInvertedIndex(new InvertedIndexOptions() + .name(idxName2) + .fields(new InvertedIndexField().name("a" + rnd()))) + .get(); + + String viewName = "view-" + rnd(); + final SearchAliasCreateOptions options = new SearchAliasCreateOptions() + .indexes(new SearchAliasIndex(COLL_1, idxName)); + final ViewEntity info = db.searchAlias(viewName).create(options).get(); + db.searchAlias(viewName).updateProperties(new SearchAliasPropertiesOptions() + .indexes(new SearchAliasIndex(COLL_2, idxName2))); + + assertThat(info).isNotNull(); + assertThat(info.getId()).isNotNull(); + assertThat(info.getName()).isEqualTo(viewName); + assertThat(info.getType()).isEqualTo(ViewType.SEARCH_ALIAS); + + final SearchAliasPropertiesEntity properties = db.searchAlias(viewName).getProperties().get(); + assertThat(properties).isNotNull(); + assertThat(properties.getId()).isNotNull(); + assertThat(properties.getName()).isEqualTo(viewName); + assertThat(properties.getType()).isEqualTo(ViewType.SEARCH_ALIAS); + assertThat(properties.getIndexes()) + .isNotNull() + .isNotEmpty() + .hasSize(2) + .anyMatch(i -> i.getCollection().equals(COLL_1) && i.getIndex().equals(idxName)) + .anyMatch(i -> i.getCollection().equals(COLL_2) && i.getIndex().equals(idxName2)); + } + + @Test + void replaceArangoSearchViewProperties() throws InterruptedException, ExecutionException { assumeTrue(isAtLeastVersion(3, 4)); - db.createCollection("view_replace_prop_test_collection").get(); final String name = VIEW_NAME + "_replacepropertiestest"; final ArangoSearchAsync view = db.arangoSearch(name); view.create(new ArangoSearchCreateOptions()).get(); @@ -229,6 +344,46 @@ void replaceProperties() throws InterruptedException, ExecutionException { assertThat(link.getFields().iterator().next().getName()).isEqualTo("value"); } + @Test + void replaceSearchAliasViewWithIndexesAndGetProperties() throws ExecutionException, InterruptedException { + assumeTrue(isAtLeastVersion(3, 10)); + ArangoCollectionAsync col = db.collection(COLL_1); + String idxName = "idx-" + rnd(); + col.ensureInvertedIndex(new InvertedIndexOptions() + .name(idxName) + .fields(new InvertedIndexField().name("a" + rnd()))) + .get(); + ArangoCollectionAsync col2 = db.collection(COLL_2); + String idxName2 = "idx-" + rnd(); + col2.ensureInvertedIndex(new InvertedIndexOptions() + .name(idxName2) + .fields(new InvertedIndexField().name("a" + rnd()))) + .get(); + + String viewName = "view-" + rnd(); + final SearchAliasCreateOptions options = new SearchAliasCreateOptions() + .indexes(new SearchAliasIndex(COLL_1, idxName)); + final ViewEntity info = db.searchAlias(viewName).create(options).get(); + db.searchAlias(viewName).replaceProperties(new SearchAliasPropertiesOptions() + .indexes(new SearchAliasIndex(COLL_2, idxName2))); + + assertThat(info).isNotNull(); + assertThat(info.getId()).isNotNull(); + assertThat(info.getName()).isEqualTo(viewName); + assertThat(info.getType()).isEqualTo(ViewType.SEARCH_ALIAS); + + final SearchAliasPropertiesEntity properties = db.searchAlias(viewName).getProperties().get(); + assertThat(properties).isNotNull(); + assertThat(properties.getId()).isNotNull(); + assertThat(properties.getName()).isEqualTo(viewName); + assertThat(properties.getType()).isEqualTo(ViewType.SEARCH_ALIAS); + assertThat(properties.getIndexes()) + .isNotNull() + .isNotEmpty() + .hasSize(1) + .anyMatch(i -> i.getCollection().equals(COLL_2) && i.getIndex().equals(idxName2)); + } + private void createGetAndDeleteTypedAnalyzer(SearchAnalyzer analyzer) throws ExecutionException, InterruptedException { diff --git a/src/test/java/com/arangodb/async/BaseTest.java b/src/test/java/com/arangodb/async/BaseTest.java index 654e773b0..520fe6aa0 100644 --- a/src/test/java/com/arangodb/async/BaseTest.java +++ b/src/test/java/com/arangodb/async/BaseTest.java @@ -24,6 +24,7 @@ import com.arangodb.entity.ArangoDBEngine; import com.arangodb.entity.License; import com.arangodb.entity.ServerRole; +import com.arangodb.util.TestUtils; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; @@ -87,6 +88,14 @@ protected boolean isAtLeastVersion(final int major, final int minor) throws Inte return isAtLeastVersion(major, minor, 0); } + boolean isLessThanVersion(final int major, final int minor) throws ExecutionException, InterruptedException { + return isLessThanVersion(major, minor, 0); + } + + boolean isLessThanVersion(final int major, final int minor, final int patch) throws ExecutionException, InterruptedException { + return TestUtils.isLessThanVersion(db.getVersion().get().getVersion(), major, minor, patch); + } + boolean isStorageEngine(ArangoDBEngine.StorageEngineName name) throws ExecutionException, InterruptedException { return name.equals(db.getEngine().get().getName()); } From 1976e168a6d0a2fd73f1dab0a4b948e99adc1a6c Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Fri, 16 Sep 2022 21:10:33 +0200 Subject: [PATCH 127/254] tests fixes (cherry picked from commit 15e791ece87cad5a372a4f029b043681722d8f40) --- src/test/java/com/arangodb/async/ArangoSearchTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/java/com/arangodb/async/ArangoSearchTest.java b/src/test/java/com/arangodb/async/ArangoSearchTest.java index ff2cebe83..c0113b291 100644 --- a/src/test/java/com/arangodb/async/ArangoSearchTest.java +++ b/src/test/java/com/arangodb/async/ArangoSearchTest.java @@ -305,7 +305,7 @@ void updateSearchAliasViewWithIndexesAndGetProperties() throws ExecutionExceptio .indexes(new SearchAliasIndex(COLL_1, idxName)); final ViewEntity info = db.searchAlias(viewName).create(options).get(); db.searchAlias(viewName).updateProperties(new SearchAliasPropertiesOptions() - .indexes(new SearchAliasIndex(COLL_2, idxName2))); + .indexes(new SearchAliasIndex(COLL_2, idxName2))).get(); assertThat(info).isNotNull(); assertThat(info.getId()).isNotNull(); @@ -365,7 +365,7 @@ void replaceSearchAliasViewWithIndexesAndGetProperties() throws ExecutionExcepti .indexes(new SearchAliasIndex(COLL_1, idxName)); final ViewEntity info = db.searchAlias(viewName).create(options).get(); db.searchAlias(viewName).replaceProperties(new SearchAliasPropertiesOptions() - .indexes(new SearchAliasIndex(COLL_2, idxName2))); + .indexes(new SearchAliasIndex(COLL_2, idxName2))).get(); assertThat(info).isNotNull(); assertThat(info.getId()).isNotNull(); From a7fb568b2a6a58b9c83c1f7fa1387f4d9083f404 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Mon, 19 Sep 2022 10:12:26 +0200 Subject: [PATCH 128/254] [DE-384] added SearchAliasIndex operation type (cherry picked from commit fe0f79838c6fc6375038886c82bfb090ffcdfee0) --- .../entity/arangosearch/SearchAliasIndex.java | 28 ++++++++++++++++++- .../java/com/arangodb/ArangoSearchTest.java | 18 +++++++++--- 2 files changed, 41 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/arangodb/entity/arangosearch/SearchAliasIndex.java b/src/main/java/com/arangodb/entity/arangosearch/SearchAliasIndex.java index 40f19930d..28ded55e7 100644 --- a/src/main/java/com/arangodb/entity/arangosearch/SearchAliasIndex.java +++ b/src/main/java/com/arangodb/entity/arangosearch/SearchAliasIndex.java @@ -10,11 +10,29 @@ public class SearchAliasIndex { private final String collection; private final String index; + private final OperationType operation; + /** + * @param collection The name of a collection. + * @param index The name of an inverted index of the collection. + */ + public SearchAliasIndex(String collection, String index) { + this(collection, index, null); + } + + /** + * @param collection The name of a collection. + * @param index The name of an inverted index of the collection. + * @param operation Whether to add or remove the index to the stored indexes property of the View. (default "add") + */ @JsonCreator - public SearchAliasIndex(@JsonProperty("collection") String collection, @JsonProperty("index") String index) { + public SearchAliasIndex( + @JsonProperty("collection") String collection, + @JsonProperty("index") String index, + @JsonProperty("operation") OperationType operation) { this.collection = collection; this.index = index; + this.operation = operation; } public String getCollection() { @@ -24,4 +42,12 @@ public String getCollection() { public String getIndex() { return index; } + + public OperationType getOperation() { + return operation; + } + + public enum OperationType { + add, del + } } diff --git a/src/test/java/com/arangodb/ArangoSearchTest.java b/src/test/java/com/arangodb/ArangoSearchTest.java index 32cabf6de..fb108e599 100644 --- a/src/test/java/com/arangodb/ArangoSearchTest.java +++ b/src/test/java/com/arangodb/ArangoSearchTest.java @@ -228,13 +228,23 @@ void createSearchAliasViewWithOptions(ArangoDatabase db) { void createSearchAliasViewWithIndexesAndGetProperties(ArangoDatabase db) { assumeTrue(isAtLeastVersion(3, 10)); ArangoCollection col = db.collection(COLL_1); - String idxName = "idx-" + rnd(); + String idxName1 = "idx-" + rnd(); col.ensureInvertedIndex(new InvertedIndexOptions() - .name(idxName) + .name(idxName1) .fields(new InvertedIndexField().name("a" + rnd()))); + + String idxName2 = "idx-" + rnd(); + col.ensureInvertedIndex(new InvertedIndexOptions() + .name(idxName2) + .fields(new InvertedIndexField().name("a" + rnd()))); + String viewName = "view-" + rnd(); final SearchAliasCreateOptions options = new SearchAliasCreateOptions() - .indexes(new SearchAliasIndex(COLL_1, idxName)); + .indexes( + new SearchAliasIndex(COLL_1, idxName1, SearchAliasIndex.OperationType.add), + new SearchAliasIndex(COLL_1, idxName2, SearchAliasIndex.OperationType.add), + new SearchAliasIndex(COLL_1, idxName2, SearchAliasIndex.OperationType.del) + ); final ViewEntity info = db.searchAlias(viewName).create(options); assertThat(info).isNotNull(); assertThat(info.getId()).isNotNull(); @@ -249,7 +259,7 @@ void createSearchAliasViewWithIndexesAndGetProperties(ArangoDatabase db) { assertThat(properties.getIndexes()) .isNotNull() .isNotEmpty() - .anyMatch(i -> i.getCollection().equals(COLL_1) && i.getIndex().equals(idxName)); + .anyMatch(i -> i.getCollection().equals(COLL_1) && i.getIndex().equals(idxName1)); } @ParameterizedTest(name = "{index}") From 05f903e0fd39924588c97094940c5ecbf3fef4fb Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Mon, 19 Sep 2022 10:28:25 +0200 Subject: [PATCH 129/254] enabled SmartGraphs tests for 3.10 single server (cherry picked from commit f7f5089847809221a9b36e5c845400d8c3436f03) --- src/test/java/com/arangodb/ArangoGraphTest.java | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/test/java/com/arangodb/ArangoGraphTest.java b/src/test/java/com/arangodb/ArangoGraphTest.java index cc944f8e0..25efae22b 100644 --- a/src/test/java/com/arangodb/ArangoGraphTest.java +++ b/src/test/java/com/arangodb/ArangoGraphTest.java @@ -92,7 +92,7 @@ void exists(ArangoGraph graph) { @MethodSource("dbs") void createWithReplicationAndWriteConcern(ArangoDatabase db) { assumeTrue(isAtLeastVersion(3, 5)); - assumeTrue(isCluster()); + assumeTrue(isCluster() || isAtLeastVersion(3, 10)); final Collection edgeDefinitions = new ArrayList<>(); final GraphEntity graph = db.createGraph(GRAPH_NAME + "_1", edgeDefinitions, @@ -162,7 +162,7 @@ void addVertexCollection(ArangoGraph graph) { @ParameterizedTest(name = "{index}") @MethodSource("dbs") void addSatelliteVertexCollection(ArangoDatabase db) { - assumeTrue(isCluster()); + assumeTrue(isCluster() || isAtLeastVersion(3, 10)); assumeTrue(isEnterprise()); assumeTrue(isAtLeastVersion(3, 9)); @@ -223,7 +223,7 @@ void addEdgeDefinition(ArangoGraph graph) { @ParameterizedTest(name = "{index}") @MethodSource("dbs") void addSatelliteEdgeDefinition(ArangoDatabase db) { - assumeTrue(isCluster()); + assumeTrue(isCluster() || isAtLeastVersion(3, 10)); assumeTrue(isEnterprise()); assumeTrue(isAtLeastVersion(3, 9)); @@ -293,7 +293,7 @@ void removeEdgeDefinition(ArangoGraph graph) { @MethodSource("dbs") void smartGraph(ArangoDatabase db) { assumeTrue(isEnterprise()); - assumeTrue(isCluster()); + assumeTrue(isCluster() || isAtLeastVersion(3, 10)); final Collection edgeDefinitions = new ArrayList<>(); edgeDefinitions.add(new EdgeDefinition().collection("smartGraph-edge-" + rnd()).from("smartGraph-vertex-" + rnd()).to("smartGraph-vertex-" + rnd())); @@ -312,7 +312,7 @@ void smartGraph(ArangoDatabase db) { @MethodSource("dbs") void hybridSmartGraph(ArangoDatabase db) { assumeTrue(isEnterprise()); - assumeTrue(isCluster()); + assumeTrue(isCluster() || isAtLeastVersion(3, 10)); assumeTrue((isAtLeastVersion(3, 9))); final Collection edgeDefinitions = new ArrayList<>(); @@ -340,7 +340,7 @@ void hybridSmartGraph(ArangoDatabase db) { @MethodSource("dbs") void disjointSmartGraph(ArangoDatabase db) { assumeTrue(isEnterprise()); - assumeTrue(isCluster()); + assumeTrue(isCluster() || isAtLeastVersion(3, 10)); assumeTrue((isAtLeastVersion(3, 7))); final Collection edgeDefinitions = new ArrayList<>(); @@ -361,7 +361,7 @@ void disjointSmartGraph(ArangoDatabase db) { @MethodSource("dbs") void hybridDisjointSmartGraph(ArangoDatabase db) { assumeTrue(isEnterprise()); - assumeTrue(isCluster()); + assumeTrue(isCluster() || isAtLeastVersion(3, 10)); assumeTrue((isAtLeastVersion(3, 9))); final Collection edgeDefinitions = new ArrayList<>(); @@ -389,7 +389,7 @@ void hybridDisjointSmartGraph(ArangoDatabase db) { @MethodSource("dbs") void enterpriseGraph(ArangoDatabase db) { assumeTrue(isEnterprise()); - assumeTrue(isCluster()); + assumeTrue(isCluster() || isAtLeastVersion(3, 10)); final Collection edgeDefinitions = new ArrayList<>(); edgeDefinitions.add(new EdgeDefinition().collection("enterpriseGraph-edge-" + rnd()).from("enterpriseGraph-vertex-" + rnd()).to("enterpriseGraph-vertex-" + rnd())); From 4d714bd3c6dea929ca05efb33f9bde37b007051d Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Mon, 19 Sep 2022 11:06:59 +0200 Subject: [PATCH 130/254] [DE-379] inverted indexes documentation (cherry picked from commit 64d07c10b5eab0a7e3c10a396cfbbf26479f7f48) --- .../arangodb/entity/InvertedIndexEntity.java | 2 - .../arangodb/entity/InvertedIndexField.java | 56 ++++++- .../entity/InvertedIndexPrimarySort.java | 14 +- .../entity/arangosearch/StoredValue.java | 12 +- .../arangodb/model/InvertedIndexOptions.java | 140 +++++++++++++++++- 5 files changed, 207 insertions(+), 17 deletions(-) diff --git a/src/main/java/com/arangodb/entity/InvertedIndexEntity.java b/src/main/java/com/arangodb/entity/InvertedIndexEntity.java index d656c525a..4c1d85c25 100644 --- a/src/main/java/com/arangodb/entity/InvertedIndexEntity.java +++ b/src/main/java/com/arangodb/entity/InvertedIndexEntity.java @@ -28,8 +28,6 @@ import java.util.Set; /** - * TODO: add documentation - * * @author Michele Rastelli * @see API Documentation * @since ArangoDB 3.10 diff --git a/src/main/java/com/arangodb/entity/InvertedIndexField.java b/src/main/java/com/arangodb/entity/InvertedIndexField.java index bff8cc828..6e330c7ac 100644 --- a/src/main/java/com/arangodb/entity/InvertedIndexField.java +++ b/src/main/java/com/arangodb/entity/InvertedIndexField.java @@ -5,8 +5,6 @@ import java.util.*; /** - * TODO: add documentation - * * @author Michele Rastelli * @see API Documentation * @since ArangoDB 3.10 @@ -24,6 +22,10 @@ public String getName() { return name; } + /** + * @param name An attribute path. The . character denotes sub-attributes. + * @return this + */ public InvertedIndexField name(String name) { this.name = name; return this; @@ -33,6 +35,11 @@ public String getAnalyzer() { return analyzer; } + /** + * @param analyzer The name of an Analyzer to use for this field. Default: the value defined by the top-level + * analyzer option, or if not set, the default identity Analyzer. + * @return this + */ public InvertedIndexField analyzer(String analyzer) { this.analyzer = analyzer; return this; @@ -42,6 +49,15 @@ public Boolean getIncludeAllFields() { return includeAllFields; } + /** + * @param includeAllFields This option only applies if you use the inverted index in a search-alias Views. If set to + * true, then all sub-attributes of this field are indexed, excluding any sub-attributes + * that are configured separately by other elements in the fields array (and their + * sub-attributes). The analyzer and features properties apply to the sub-attributes. If set + * to false, then sub-attributes are ignored. The default value is defined by the top-level + * includeAllFields option, or false if not set. + * @return this + */ public InvertedIndexField includeAllFields(Boolean includeAllFields) { this.includeAllFields = includeAllFields; return this; @@ -51,6 +67,18 @@ public Boolean getSearchField() { return searchField; } + /** + * @param searchField This option only applies if you use the inverted index in a search-alias Views. You can set + * the option to true to get the same behavior as with arangosearch Views regarding the indexing + * of array values for this field. If enabled, both, array and primitive values (strings, + * numbers, etc.) are accepted. Every element of an array is indexed according to the + * trackListPositions option. If set to false, it depends on the attribute path. If it explicitly + * expand an array ([*]), then the elements are indexed separately. Otherwise, the array is + * indexed as a whole, but only geopoint and aql Analyzers accept array inputs. You cannot use an + * array expansion if searchField is enabled. Default: the value defined by the top-level + * searchField option, or false if not set. + * @return this + */ public InvertedIndexField searchField(Boolean searchField) { this.searchField = searchField; return this; @@ -60,6 +88,16 @@ public Boolean getTrackListPositions() { return trackListPositions; } + /** + * @param trackListPositions This option only applies if you use the inverted index in a search-alias Views. If set + * to true, then track the value position in arrays for array values. For example, when + * querying a document like { attr: [ "valueX", "valueY", "valueZ" ] }, you need to + * specify the array element, e.g. doc.attr[1] == "valueY". If set to false, all values in + * an array are treated as equal alternatives. You don’t specify an array element in + * queries, e.g. doc.attr == "valueY", and all elements are searched for a match. Default: + * the value defined by the top-level trackListPositions option, or false if not set. + * @return this + */ public InvertedIndexField trackListPositions(Boolean trackListPositions) { this.trackListPositions = trackListPositions; return this; @@ -69,6 +107,11 @@ public Set getFeatures() { return features; } + /** + * @param features A list of Analyzer features to use for this field. They define what features are enabled for the + * analyzer. + * @return this + */ public InvertedIndexField features(AnalyzerFeature... features) { Collections.addAll(this.features, features); return this; @@ -78,8 +121,15 @@ public Collection getNested() { return nested; } + /** + * @param nested Index the specified sub-objects that are stored in an array. Other than with the fields property, + * the values get indexed in a way that lets you query for co-occurring values. For example, you can + * search the sub-objects and all the conditions need to be met by a single sub-object instead of + * across all of them. This property is available in the Enterprise Edition only. + * @return this + */ public InvertedIndexField nested(InvertedIndexField... nested) { - if(this.nested == null) this.nested = new ArrayList<>(); + if (this.nested == null) this.nested = new ArrayList<>(); Collections.addAll(this.nested, nested); return this; } diff --git a/src/main/java/com/arangodb/entity/InvertedIndexPrimarySort.java b/src/main/java/com/arangodb/entity/InvertedIndexPrimarySort.java index bfb812fe5..c42e94e40 100644 --- a/src/main/java/com/arangodb/entity/InvertedIndexPrimarySort.java +++ b/src/main/java/com/arangodb/entity/InvertedIndexPrimarySort.java @@ -10,8 +10,6 @@ import java.util.Objects; /** - * TODO: add documentation - * * @author Michele Rastelli * @see API Documentation * @since ArangoDB 3.10 @@ -24,6 +22,10 @@ public List getFields() { return fields; } + /** + * @param fields An array of the fields to sort the index by and the direction to sort each field in. + * @return this + */ public InvertedIndexPrimarySort fields(Field... fields) { Collections.addAll(this.fields, fields); return this; @@ -33,6 +35,10 @@ public ArangoSearchCompression getCompression() { return compression; } + /** + * @param compression Defines how to compress the primary sort data. + * @return this + */ public InvertedIndexPrimarySort compression(ArangoSearchCompression compression) { this.compression = compression; return this; @@ -55,6 +61,10 @@ public static class Field { private final String field; private final Direction direction; + /** + * @param field An attribute path. The . character denotes sub-attributes. + * @param direction The sorting direction. + */ @JsonCreator public Field(@JsonProperty("field") String field, @JsonProperty("direction") Direction direction) { this.field = field; diff --git a/src/main/java/com/arangodb/entity/arangosearch/StoredValue.java b/src/main/java/com/arangodb/entity/arangosearch/StoredValue.java index 98373653c..66448a4d4 100644 --- a/src/main/java/com/arangodb/entity/arangosearch/StoredValue.java +++ b/src/main/java/com/arangodb/entity/arangosearch/StoredValue.java @@ -37,6 +37,10 @@ public final class StoredValue { private final List fields; private final ArangoSearchCompression compression; + /** + * @param fields A list of attribute paths. The . character denotes sub-attributes. + * @param compression Defines how to compress the attribute values. + */ @JsonCreator public StoredValue(@JsonProperty("fields") List fields, @JsonProperty("compression") ArangoSearchCompression compression) { @@ -48,18 +52,10 @@ public StoredValue(List fields) { this(fields, null); } - /** - * @return an array of strings with one or more document attribute paths. The specified attributes are placed into a - * single column of the index. A column with all fields that are involved in common search queries is ideal for - * performance. The column should not include too many unneeded fields however. - */ public List getFields() { return fields; } - /** - * @return defines the compression type used for the internal column-store - */ public ArangoSearchCompression getCompression() { return compression; } diff --git a/src/main/java/com/arangodb/model/InvertedIndexOptions.java b/src/main/java/com/arangodb/model/InvertedIndexOptions.java index f8335424f..9a4ddb601 100644 --- a/src/main/java/com/arangodb/model/InvertedIndexOptions.java +++ b/src/main/java/com/arangodb/model/InvertedIndexOptions.java @@ -28,8 +28,6 @@ import java.util.*; /** - * TODO: add documentation - * * @author Michele Rastelli * @see API Documentation * @since ArangoDB 3.10 @@ -71,6 +69,10 @@ public Integer getParallelism() { return parallelism; } + /** + * @param parallelism The number of threads to use for indexing the fields. Default: 2 + * @return this + */ public InvertedIndexOptions parallelism(Integer parallelism) { this.parallelism = parallelism; return this; @@ -80,6 +82,13 @@ public InvertedIndexPrimarySort getPrimarySort() { return primarySort; } + /** + * @param primarySort You can define a primary sort order to enable an AQL optimization. If a query iterates over + * all documents of a collection, wants to sort them by attribute values, and the (left-most) + * fields to sort by, as well as their sorting direction, match with the primarySort definition, + * then the SORT operation is optimized away. + * @return this + */ public InvertedIndexOptions primarySort(InvertedIndexPrimarySort primarySort) { this.primarySort = primarySort; return this; @@ -89,6 +98,13 @@ public Collection getStoredValues() { return storedValues; } + /** + * @param storedValues The optional storedValues attribute can contain an array of paths to additional attributes to + * store in the index. These additional attributes cannot be used for index lookups or for + * sorting, but they can be used for projections. This allows an index to fully cover more + * queries and avoid extra document lookups. + * @return this + */ public InvertedIndexOptions storedValues(StoredValue... storedValues) { Collections.addAll(this.storedValues, storedValues); return this; @@ -98,6 +114,11 @@ public String getAnalyzer() { return analyzer; } + /** + * @param analyzer The name of an Analyzer to use by default. This Analyzer is applied to the values of the indexed + * fields for which you don’t define Analyzers explicitly. + * @return this + */ public InvertedIndexOptions analyzer(String analyzer) { this.analyzer = analyzer; return this; @@ -107,6 +128,11 @@ public Set getFeatures() { return features; } + /** + * @param features A list of Analyzer features to use by default. They define what features are enabled for the + * default analyzer. + * @return this + */ public InvertedIndexOptions features(AnalyzerFeature... features) { Collections.addAll(this.features, features); return this; @@ -116,6 +142,15 @@ public Boolean getIncludeAllFields() { return includeAllFields; } + /** + * @param includeAllFields This option only applies if you use the inverted index in a search-alias Views. If set to + * true, then all sub-attributes of this field are indexed, excluding any sub-attributes + * that are configured separately by other elements in the fields array (and their + * sub-attributes). The analyzer and features properties apply to the sub-attributes. If set + * to false, then sub-attributes are ignored. The default value is defined by the top-level + * includeAllFields option, or false if not set. + * @return this + */ public InvertedIndexOptions includeAllFields(Boolean includeAllFields) { this.includeAllFields = includeAllFields; return this; @@ -125,6 +160,16 @@ public Boolean getTrackListPositions() { return trackListPositions; } + /** + * @param trackListPositions This option only applies if you use the inverted index in a search-alias Views. If set + * to true, then track the value position in arrays for array values. For example, when + * querying a document like { attr: [ "valueX", "valueY", "valueZ" ] }, you need to + * specify the array element, e.g. doc.attr[1] == "valueY". If set to false, all values in + * an array are treated as equal alternatives. You don’t specify an array element in + * queries, e.g. doc.attr == "valueY", and all elements are searched for a match. Default: + * the value defined by the top-level trackListPositions option, or false if not set. + * @return this + */ public InvertedIndexOptions trackListPositions(Boolean trackListPositions) { this.trackListPositions = trackListPositions; return this; @@ -134,6 +179,17 @@ public Boolean getSearchField() { return searchField; } + /** + * @param searchField This option only applies if you use the inverted index in a search-alias Views. You can set + * the option to true to get the same behavior as with arangosearch Views regarding the indexing + * of array values as the default. If enabled, both, array and primitive values (strings, + * numbers, etc.) are accepted. Every element of an array is indexed according to the + * trackListPositions option. If set to false, it depends on the attribute path. If it explicitly + * expand an array ([*]), then the elements are indexed separately. Otherwise, the array is + * indexed as a whole, but only geopoint and aql Analyzers accept array inputs. You cannot use an + * array expansion if searchField is enabled. + * @return this + */ public InvertedIndexOptions searchField(Boolean searchField) { this.searchField = searchField; return this; @@ -143,6 +199,11 @@ public Collection getFields() { return fields; } + /** + * @param fields An array of attribute paths as strings to index the fields with the default options, or objects to + * specify options for the fields. + * @return this + */ public InvertedIndexOptions fields(InvertedIndexField... fields) { Collections.addAll(this.fields, fields); return this; @@ -152,6 +213,21 @@ public Long getConsolidationIntervalMsec() { return consolidationIntervalMsec; } + /** + * @param consolidationIntervalMsec Wait at least this many milliseconds between applying ‘consolidationPolicy’ to + * consolidate View data store and possibly release space on the filesystem + * (default: 1000, to disable use: 0). For the case where there are a lot of data + * modification operations, a higher value could potentially have the data store + * consume more space and file handles. For the case where there are a few data + * modification operations, a lower value will impact performance due to no segment + * candidates available for consolidation. Background: For data modification + * ArangoSearch Views follow the concept of a “versioned data store”. Thus old + * versions of data may be removed once there are no longer any users of the old + * data. The frequency of the cleanup and compaction operations are governed by + * ‘consolidationIntervalMsec’ and the candidates for compaction are selected via + * ‘consolidationPolicy’. + * @return this + */ public InvertedIndexOptions consolidationIntervalMsec(Long consolidationIntervalMsec) { this.consolidationIntervalMsec = consolidationIntervalMsec; return this; @@ -161,6 +237,23 @@ public Long getCommitIntervalMsec() { return commitIntervalMsec; } + /** + * @param commitIntervalMsec Wait at least this many milliseconds between committing View data store changes and + * making documents visible to queries (default: 1000, to disable use: 0). For the case + * where there are a lot of inserts/updates, a lower value, until commit, will cause the + * index not to account for them and memory usage would continue to grow. For the case + * where there are a few inserts/updates, a higher value will impact performance and waste + * disk space for each commit call without any added benefits. Background: For data + * retrieval ArangoSearch Views follow the concept of “eventually-consistent”, i.e. + * eventually all the data in ArangoDB will be matched by corresponding query expressions. + * The concept of ArangoSearch View “commit” operation is introduced to control the + * upper-bound on the time until document addition/removals are actually reflected by + * corresponding query expressions. Once a “commit” operation is complete all documents + * added/removed prior to the start of the “commit” operation will be reflected by queries + * invoked in subsequent ArangoDB transactions, in-progress ArangoDB transactions will + * still continue to return a repeatable-read state. + * @return this + */ public InvertedIndexOptions commitIntervalMsec(Long commitIntervalMsec) { this.commitIntervalMsec = commitIntervalMsec; return this; @@ -170,6 +263,19 @@ public Long getCleanupIntervalStep() { return cleanupIntervalStep; } + /** + * @param cleanupIntervalStep Wait at least this many commits between removing unused files in the ArangoSearch data + * directory (default: 2, to disable use: 0). For the case where the consolidation + * policies merge segments often (i.e. a lot of commit+consolidate), a lower value will + * cause a lot of disk space to be wasted. For the case where the consolidation policies + * rarely merge segments (i.e. few inserts/deletes), a higher value will impact + * performance without any added benefits. Background: With every “commit” or + * “consolidate” operation a new state of the View internal data-structures is created on + * disk. Old states/snapshots are released once there are no longer any users remaining. + * However, the files for the released states/snapshots are left on disk, and only + * removed by “cleanup” operation. + * @return this + */ public InvertedIndexOptions cleanupIntervalStep(Long cleanupIntervalStep) { this.cleanupIntervalStep = cleanupIntervalStep; return this; @@ -179,6 +285,18 @@ public ConsolidationPolicy getConsolidationPolicy() { return consolidationPolicy; } + /** + * @param consolidationPolicy The consolidation policy to apply for selecting which segments should be merged + * (default: {}). Background: With each ArangoDB transaction that inserts documents one + * or more ArangoSearch internal segments gets created. Similarly for removed documents + * the segments that contain such documents will have these documents marked as + * ‘deleted’. Over time this approach causes a lot of small and sparse segments to be + * created. A “consolidation” operation selects one or more segments and copies all of + * their valid documents into a single new segment, thereby allowing the search algorithm + * to perform more optimally and for extra file handles to be released once old segments + * are no longer used. + * @return this + */ public InvertedIndexOptions consolidationPolicy(ConsolidationPolicy consolidationPolicy) { this.consolidationPolicy = consolidationPolicy; return this; @@ -188,6 +306,10 @@ public Long getWritebufferIdle() { return writebufferIdle; } + /** + * @param writebufferIdle Maximum number of writers (segments) cached in the pool (default: 64, use 0 to disable) + * @return this + */ public InvertedIndexOptions writebufferIdle(Long writebufferIdle) { this.writebufferIdle = writebufferIdle; return this; @@ -197,6 +319,12 @@ public Long getWritebufferActive() { return writebufferActive; } + /** + * @param writebufferActive Maximum number of concurrent active writers (segments) that perform a transaction. Other + * writers (segments) wait till current active writers (segments) finish (default: 0, use 0 + * to disable) + * @return this + */ public InvertedIndexOptions writebufferActive(Long writebufferActive) { this.writebufferActive = writebufferActive; return this; @@ -206,6 +334,14 @@ public Long getWritebufferSizeMax() { return writebufferSizeMax; } + /** + * @param writebufferSizeMax Maximum memory byte size per writer (segment) before a writer (segment) flush is + * triggered. 0 value turns off this limit for any writer (buffer) and data will be + * flushed periodically based on the value defined for the flush thread (ArangoDB server + * startup option). 0 value should be used carefully due to high potential memory + * consumption (default: 33554432, use 0 to disable) + * @return this + */ public InvertedIndexOptions writebufferSizeMax(Long writebufferSizeMax) { this.writebufferSizeMax = writebufferSizeMax; return this; From 89b4861a974ba734f96b1d60004616b928ed21c4 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Mon, 19 Sep 2022 12:06:22 +0200 Subject: [PATCH 131/254] tests fixes (cherry picked from commit 11d55b6887b1e54a49b9ac755bcf4c0eb386810a) --- src/test/java/com/arangodb/ArangoDBTest.java | 2 +- src/test/java/com/arangodb/ArangoGraphTest.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/java/com/arangodb/ArangoDBTest.java b/src/test/java/com/arangodb/ArangoDBTest.java index fdf18a5c1..23f1699b0 100644 --- a/src/test/java/com/arangodb/ArangoDBTest.java +++ b/src/test/java/com/arangodb/ArangoDBTest.java @@ -206,7 +206,7 @@ void createDatabaseWithUsers(ArangoDB arangoDB) throws InterruptedException { assertThat(retrievedUser.getExtra()).isEqualTo(extra); // needed for active-failover tests only - Thread.sleep(1_000); + Thread.sleep(2_000); ArangoDB arangoDBTestUser = new ArangoDB.Builder() diff --git a/src/test/java/com/arangodb/ArangoGraphTest.java b/src/test/java/com/arangodb/ArangoGraphTest.java index 25efae22b..73e56711c 100644 --- a/src/test/java/com/arangodb/ArangoGraphTest.java +++ b/src/test/java/com/arangodb/ArangoGraphTest.java @@ -92,7 +92,7 @@ void exists(ArangoGraph graph) { @MethodSource("dbs") void createWithReplicationAndWriteConcern(ArangoDatabase db) { assumeTrue(isAtLeastVersion(3, 5)); - assumeTrue(isCluster() || isAtLeastVersion(3, 10)); + assumeTrue(isCluster()); final Collection edgeDefinitions = new ArrayList<>(); final GraphEntity graph = db.createGraph(GRAPH_NAME + "_1", edgeDefinitions, From f0b623b7478ab32f1fc05982b9bb08c36b67d15e Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Wed, 21 Sep 2022 20:00:39 +0200 Subject: [PATCH 132/254] fixed native image support --- .../arangodb-java-driver/reflect-config.json | 158 +++++++++++++++++- .../META-INF/native-image/reflect-config.json | 4 + 2 files changed, 158 insertions(+), 4 deletions(-) diff --git a/src/main/resources/META-INF/native-image/com.arangodb/arangodb-java-driver/reflect-config.json b/src/main/resources/META-INF/native-image/com.arangodb/arangodb-java-driver/reflect-config.json index 3ef3eb162..db01aa4b2 100644 --- a/src/main/resources/META-INF/native-image/com.arangodb/arangodb-java-driver/reflect-config.json +++ b/src/main/resources/META-INF/native-image/com.arangodb/arangodb-java-driver/reflect-config.json @@ -101,6 +101,12 @@ "allDeclaredMethods": true, "allDeclaredConstructors": true }, + { + "name": "com.arangodb.entity.arangosearch.SearchAliasPropertiesEntity", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, { "name": "com.arangodb.entity.arangosearch.ArangoSearchPropertiesEntity", "allDeclaredFields": true, @@ -143,6 +149,12 @@ "allDeclaredMethods": true, "allDeclaredConstructors": true }, + { + "name": "com.arangodb.entity.arangosearch.SearchAliasIndex$OperationType", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, { "name": "com.arangodb.entity.StreamTransactionStatus", "allDeclaredFields": true, @@ -185,6 +197,12 @@ "allDeclaredMethods": true, "allDeclaredConstructors": true }, + { + "name": "com.arangodb.entity.InvertedIndexPrimarySort$Field$Direction", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, { "name": "com.arangodb.entity.IndexType", "allDeclaredFields": true, @@ -323,6 +341,18 @@ "allDeclaredMethods": true, "allDeclaredConstructors": true }, + { + "name": "com.arangodb.entity.QueryOptimizerRule", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.InvertedIndexPrimarySort$Field", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, { "name": "com.arangodb.entity.arangosearch.analyzer.GeoJSONAnalyzerProperties", "allDeclaredFields": true, @@ -335,6 +365,18 @@ "allDeclaredMethods": true, "allDeclaredConstructors": true }, + { + "name": "com.arangodb.entity.arangosearch.analyzer.ClassificationAnalyzerProperties", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.SearchAliasIndex", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, { "name": "com.arangodb.entity.MetaAware", "allDeclaredFields": true, @@ -450,13 +492,13 @@ "allDeclaredConstructors": true }, { - "name": "com.arangodb.entity.AqlExecutionExplainEntity$ExecutionStats", + "name": "com.arangodb.entity.arangosearch.analyzer.DelimiterAnalyzerProperties", "allDeclaredFields": true, "allDeclaredMethods": true, "allDeclaredConstructors": true }, { - "name": "com.arangodb.entity.arangosearch.analyzer.DelimiterAnalyzerProperties", + "name": "com.arangodb.entity.AqlExecutionExplainEntity$ExecutionStats", "allDeclaredFields": true, "allDeclaredMethods": true, "allDeclaredConstructors": true @@ -485,12 +527,24 @@ "allDeclaredMethods": true, "allDeclaredConstructors": true }, + { + "name": "com.arangodb.entity.QueryOptimizerRule$Flags", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, { "name": "com.arangodb.entity.AqlExecutionExplainEntity$ExecutionCollection", "allDeclaredFields": true, "allDeclaredMethods": true, "allDeclaredConstructors": true }, + { + "name": "com.arangodb.entity.arangosearch.analyzer.NearestNeighborsAnalyzerProperties", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, { "name": "com.arangodb.entity.arangosearch.analyzer.PipelineAnalyzerProperties", "allDeclaredFields": true, @@ -533,6 +587,12 @@ "allDeclaredMethods": true, "allDeclaredConstructors": true }, + { + "name": "com.arangodb.entity.arangosearch.analyzer.MinHashAnalyzerProperties", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, { "name": "com.arangodb.entity.arangosearch.ConsolidationPolicy", "allDeclaredFields": true, @@ -623,6 +683,12 @@ "allDeclaredMethods": true, "allDeclaredConstructors": true }, + { + "name": "com.arangodb.entity.InvertedIndexPrimarySort", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, { "name": "com.arangodb.entity.QueryTrackingPropertiesEntity", "allDeclaredFields": true, @@ -635,6 +701,18 @@ "allDeclaredMethods": true, "allDeclaredConstructors": true }, + { + "name": "com.arangodb.entity.InvertedIndexEntity", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.InvertedIndexField", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, { "name": "com.arangodb.entity.AqlExecutionExplainEntity$ExecutionExpression", "allDeclaredFields": true, @@ -719,6 +797,24 @@ "allDeclaredMethods": true, "allDeclaredConstructors": true }, + { + "name": "com.arangodb.entity.arangosearch.analyzer.NearestNeighborsAnalyzer", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.analyzer.MinHashAnalyzer", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.analyzer.ClassificationAnalyzer", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, { "name": "com.arangodb.entity.arangosearch.analyzer.StemAnalyzer", "allDeclaredFields": true, @@ -791,6 +887,12 @@ "allDeclaredMethods": true, "allDeclaredConstructors": true }, + { + "name": "com.arangodb.entity.arangosearch.SearchAliasIndex$OperationType", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, { "name": "com.arangodb.entity.StreamTransactionStatus", "allDeclaredFields": true, @@ -833,6 +935,12 @@ "allDeclaredMethods": true, "allDeclaredConstructors": true }, + { + "name": "com.arangodb.entity.InvertedIndexPrimarySort$Field$Direction", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, { "name": "com.arangodb.entity.IndexType", "allDeclaredFields": true, @@ -983,6 +1091,12 @@ "allDeclaredMethods": true, "allDeclaredConstructors": true }, + { + "name": "com.arangodb.model.ComputedValue$ComputeOn", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, { "name": "com.arangodb.model.CollectionSchema$Level", "allDeclaredFields": true, @@ -1038,13 +1152,13 @@ "allDeclaredConstructors": true }, { - "name": "com.arangodb.model.UserUpdateOptions", + "name": "com.arangodb.model.StreamTransactionOptions", "allDeclaredFields": true, "allDeclaredMethods": true, "allDeclaredConstructors": true }, { - "name": "com.arangodb.model.StreamTransactionOptions", + "name": "com.arangodb.model.UserUpdateOptions", "allDeclaredFields": true, "allDeclaredMethods": true, "allDeclaredConstructors": true @@ -1067,6 +1181,12 @@ "allDeclaredMethods": true, "allDeclaredConstructors": true }, + { + "name": "com.arangodb.model.arangosearch.SearchAliasPropertiesOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, { "name": "com.arangodb.model.CollectionCreateOptions", "allDeclaredFields": true, @@ -1109,6 +1229,12 @@ "allDeclaredMethods": true, "allDeclaredConstructors": true }, + { + "name": "com.arangodb.model.ComputedValue", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, { "name": "com.arangodb.model.arangosearch.ArangoSearchPropertiesOptions", "allDeclaredFields": true, @@ -1283,12 +1409,24 @@ "allDeclaredMethods": true, "allDeclaredConstructors": true }, + { + "name": "com.arangodb.model.arangosearch.SearchAliasOptionsBuilder", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, { "name": "com.arangodb.model.CollectionRenameOptions", "allDeclaredFields": true, "allDeclaredMethods": true, "allDeclaredConstructors": true }, + { + "name": "com.arangodb.model.arangosearch.SearchAliasCreateOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, { "name": "com.arangodb.model.DocumentExistsOptions", "allDeclaredFields": true, @@ -1361,6 +1499,12 @@ "allDeclaredMethods": true, "allDeclaredConstructors": true }, + { + "name": "com.arangodb.model.InvertedIndexOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, { "name": "com.arangodb.model.PersistentIndexOptions", "allDeclaredFields": true, @@ -1391,6 +1535,12 @@ "allDeclaredMethods": true, "allDeclaredConstructors": true }, + { + "name": "com.arangodb.model.ComputedValue$ComputeOn", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, { "name": "com.arangodb.model.CollectionSchema$Level", "allDeclaredFields": true, diff --git a/src/test/resources/META-INF/native-image/reflect-config.json b/src/test/resources/META-INF/native-image/reflect-config.json index de22561a7..e8a1f86bc 100644 --- a/src/test/resources/META-INF/native-image/reflect-config.json +++ b/src/test/resources/META-INF/native-image/reflect-config.json @@ -1,4 +1,8 @@ [ + { + "name":"org.junit.jupiter.engine.extension.TimeoutInvocationFactory$SingleThreadExecutorResource", + "methods":[{"name":"","parameterTypes":[] }] + }, { "name": "org.junit.jupiter.engine.extension.TimeoutInvocationFactory$SingleThreadExecutorResource", "methods": [ From a7edf28b85b75922cbe977338435ff6a5767da1e Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Wed, 21 Sep 2022 20:11:50 +0200 Subject: [PATCH 133/254] removed throws ArangoDBException declarations from API method signatures --- .../java/com/arangodb/ArangoCollection.java | 9 +++------ src/main/java/com/arangodb/ArangoDB.java | 1 - .../java/com/arangodb/ArangoDatabase.java | 3 +-- src/main/java/com/arangodb/SearchAlias.java | 15 +++++--------- .../internal/ArangoCollectionImpl.java | 6 +++--- .../com/arangodb/internal/ArangoDBImpl.java | 2 +- .../arangodb/internal/ArangoDatabaseImpl.java | 2 +- .../arangodb/internal/SearchAliasImpl.java | 20 +++++++++---------- 8 files changed, 23 insertions(+), 35 deletions(-) diff --git a/src/main/java/com/arangodb/ArangoCollection.java b/src/main/java/com/arangodb/ArangoCollection.java index 3d05f293c..79e3daf2c 100644 --- a/src/main/java/com/arangodb/ArangoCollection.java +++ b/src/main/java/com/arangodb/ArangoCollection.java @@ -595,11 +595,10 @@ MultiDocumentEntity> deleteDocuments( * * @param id The index-handle * @return information about the index - * @throws ArangoDBException * @see API Documentation * @since ArangoDB 3.10 */ - InvertedIndexEntity getInvertedIndex(String id) throws ArangoDBException; + InvertedIndexEntity getInvertedIndex(String id); /** * Deletes the index with the given {@code id} from the collection. @@ -702,11 +701,10 @@ MultiDocumentEntity> deleteDocuments( * * @param options index creation options * @return information about the index - * @throws ArangoDBException * @see API Documentation * @since ArangoDB 3.10 */ - InvertedIndexEntity ensureInvertedIndex(InvertedIndexOptions options) throws ArangoDBException; + InvertedIndexEntity ensureInvertedIndex(InvertedIndexOptions options); /** * Fetches a list of all indexes on this collection. @@ -725,13 +723,12 @@ MultiDocumentEntity> deleteDocuments( * Fetches a list of all inverted indexes on this collection. * * @return information about the indexes - * @throws ArangoDBException * @see API * Documentation * @since ArangoDB 3.10 */ - Collection getInvertedIndexes() throws ArangoDBException; + Collection getInvertedIndexes(); /** * Checks whether the collection exists diff --git a/src/main/java/com/arangodb/ArangoDB.java b/src/main/java/com/arangodb/ArangoDB.java index 7fba6cac8..21f55b465 100644 --- a/src/main/java/com/arangodb/ArangoDB.java +++ b/src/main/java/com/arangodb/ArangoDB.java @@ -332,7 +332,6 @@ public interface ArangoDB extends ArangoSerdeAccessor { /** * @return the list of available rules and their respective flags - * @throws ArangoDBException * @since ArangoDB 3.10 */ Collection getQueryOptimizerRules(); diff --git a/src/main/java/com/arangodb/ArangoDatabase.java b/src/main/java/com/arangodb/ArangoDatabase.java index 47d9e76a3..8224f27c0 100644 --- a/src/main/java/com/arangodb/ArangoDatabase.java +++ b/src/main/java/com/arangodb/ArangoDatabase.java @@ -686,12 +686,11 @@ public interface ArangoDatabase extends ArangoSerdeAccessor { * @param name The name of the view * @param options Additional options, can be null * @return information about the view - * @throws ArangoDBException * @see API * Documentation * @since ArangoDB 3.10 */ - ViewEntity createSearchAlias(String name, SearchAliasCreateOptions options) throws ArangoDBException; + ViewEntity createSearchAlias(String name, SearchAliasCreateOptions options); /** * Creates an Analyzer diff --git a/src/main/java/com/arangodb/SearchAlias.java b/src/main/java/com/arangodb/SearchAlias.java index 7f732fe87..f8cd4353e 100644 --- a/src/main/java/com/arangodb/SearchAlias.java +++ b/src/main/java/com/arangodb/SearchAlias.java @@ -38,55 +38,50 @@ public interface SearchAlias extends ArangoView { * Creates a view, then returns view information from the server. * * @return information about the view - * @throws ArangoDBException * @see API * Documentation */ - ViewEntity create() throws ArangoDBException; + ViewEntity create(); /** * Creates a view with the given {@code options}, then returns view information from the server. * * @param options Additional options, can be null * @return information about the view - * @throws ArangoDBException * @see API * Documentation */ - ViewEntity create(SearchAliasCreateOptions options) throws ArangoDBException; + ViewEntity create(SearchAliasCreateOptions options); /** * Reads the properties of the specified view. * * @return properties of the view - * @throws ArangoDBException * @see API * Documentation */ - SearchAliasPropertiesEntity getProperties() throws ArangoDBException; + SearchAliasPropertiesEntity getProperties(); /** * Partially changes properties of the view. * * @param options properties to change * @return properties of the view - * @throws ArangoDBException * @see API * Documentation */ - SearchAliasPropertiesEntity updateProperties(SearchAliasPropertiesOptions options) throws ArangoDBException; + SearchAliasPropertiesEntity updateProperties(SearchAliasPropertiesOptions options); /** * Changes properties of the view. * * @param options properties to change * @return properties of the view - * @throws ArangoDBException * @see API * Documentation */ - SearchAliasPropertiesEntity replaceProperties(SearchAliasPropertiesOptions options) throws ArangoDBException; + SearchAliasPropertiesEntity replaceProperties(SearchAliasPropertiesOptions options); } diff --git a/src/main/java/com/arangodb/internal/ArangoCollectionImpl.java b/src/main/java/com/arangodb/internal/ArangoCollectionImpl.java index aa26cd931..8c1c6aa0a 100644 --- a/src/main/java/com/arangodb/internal/ArangoCollectionImpl.java +++ b/src/main/java/com/arangodb/internal/ArangoCollectionImpl.java @@ -350,7 +350,7 @@ public IndexEntity getIndex(final String id) { } @Override - public InvertedIndexEntity getInvertedIndex(String id) throws ArangoDBException { + public InvertedIndexEntity getInvertedIndex(String id) { return executor.execute(getIndexRequest(id), InvertedIndexEntity.class); } @@ -377,7 +377,7 @@ public IndexEntity ensurePersistentIndex(final Iterable fields, final Pe } @Override - public InvertedIndexEntity ensureInvertedIndex(final InvertedIndexOptions options) throws ArangoDBException { + public InvertedIndexEntity ensureInvertedIndex(final InvertedIndexOptions options) { return executor.execute(createInvertedIndexRequest(options), InvertedIndexEntity.class); } @@ -408,7 +408,7 @@ public Collection getIndexes() { } @Override - public Collection getInvertedIndexes() throws ArangoDBException { + public Collection getInvertedIndexes() { return executor.execute(getIndexesRequest(), getInvertedIndexesResponseDeserializer()); } diff --git a/src/main/java/com/arangodb/internal/ArangoDBImpl.java b/src/main/java/com/arangodb/internal/ArangoDBImpl.java index b2f407b23..de0a92c7b 100644 --- a/src/main/java/com/arangodb/internal/ArangoDBImpl.java +++ b/src/main/java/com/arangodb/internal/ArangoDBImpl.java @@ -261,7 +261,7 @@ public LogLevelEntity setLogLevel(final LogLevelEntity entity) { } @Override - public Collection getQueryOptimizerRules() throws ArangoDBException { + public Collection getQueryOptimizerRules() { return executor.execute(getQueryOptimizerRulesRequest(), SerdeUtils.constructListType(QueryOptimizerRule.class)); } diff --git a/src/main/java/com/arangodb/internal/ArangoDatabaseImpl.java b/src/main/java/com/arangodb/internal/ArangoDatabaseImpl.java index 9d81dd261..91bdfa1c7 100644 --- a/src/main/java/com/arangodb/internal/ArangoDatabaseImpl.java +++ b/src/main/java/com/arangodb/internal/ArangoDatabaseImpl.java @@ -412,7 +412,7 @@ public ViewEntity createArangoSearch(final String name, final ArangoSearchCreate } @Override - public ViewEntity createSearchAlias(String name, SearchAliasCreateOptions options) throws ArangoDBException { + public ViewEntity createSearchAlias(String name, SearchAliasCreateOptions options) { return executor.execute(createSearchAliasRequest(name, options), ViewEntity.class); } diff --git a/src/main/java/com/arangodb/internal/SearchAliasImpl.java b/src/main/java/com/arangodb/internal/SearchAliasImpl.java index 589e4e208..adb278bf0 100644 --- a/src/main/java/com/arangodb/internal/SearchAliasImpl.java +++ b/src/main/java/com/arangodb/internal/SearchAliasImpl.java @@ -38,7 +38,7 @@ protected SearchAliasImpl(final ArangoDatabaseImpl db, final String name) { } @Override - public boolean exists() throws ArangoDBException { + public boolean exists() { try { getInfo(); return true; @@ -51,46 +51,44 @@ public boolean exists() throws ArangoDBException { } @Override - public void drop() throws ArangoDBException { + public void drop() { executor.execute(dropRequest(), Void.class); } @Override - public synchronized ViewEntity rename(final String newName) throws ArangoDBException { + public synchronized ViewEntity rename(final String newName) { final ViewEntity result = executor.execute(renameRequest(newName), ViewEntity.class); name = result.getName(); return result; } @Override - public ViewEntity getInfo() throws ArangoDBException { + public ViewEntity getInfo() { return executor.execute(getInfoRequest(), ViewEntity.class); } @Override - public ViewEntity create() throws ArangoDBException { + public ViewEntity create() { return create(new SearchAliasCreateOptions()); } @Override - public ViewEntity create(final SearchAliasCreateOptions options) throws ArangoDBException { + public ViewEntity create(final SearchAliasCreateOptions options) { return db().createSearchAlias(name(), options); } @Override - public SearchAliasPropertiesEntity getProperties() throws ArangoDBException { + public SearchAliasPropertiesEntity getProperties() { return executor.execute(getPropertiesRequest(), SearchAliasPropertiesEntity.class); } @Override - public SearchAliasPropertiesEntity updateProperties(final SearchAliasPropertiesOptions options) - throws ArangoDBException { + public SearchAliasPropertiesEntity updateProperties(final SearchAliasPropertiesOptions options) { return executor.execute(updatePropertiesRequest(options), SearchAliasPropertiesEntity.class); } @Override - public SearchAliasPropertiesEntity replaceProperties(final SearchAliasPropertiesOptions options) - throws ArangoDBException { + public SearchAliasPropertiesEntity replaceProperties(final SearchAliasPropertiesOptions options) { return executor.execute(replacePropertiesRequest(options), SearchAliasPropertiesEntity.class); } From ce76557eab427c63aba1a139c4a6e7f20dad846e Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Thu, 22 Sep 2022 12:04:08 +0200 Subject: [PATCH 134/254] [DE-395] made managed classes final --- .../arangodb/entity/InvertedIndexEntity.java | 2 +- .../arangodb/entity/InvertedIndexField.java | 2 +- .../entity/InvertedIndexPrimarySort.java | 2 +- .../arangodb/entity/QueryOptimizerRule.java | 2 +- .../entity/arangosearch/SearchAliasIndex.java | 2 +- .../SearchAliasPropertiesEntity.java | 2 +- .../analyzer/ClassificationAnalyzer.java | 2 +- .../ClassificationAnalyzerProperties.java | 2 +- .../analyzer/MinHashAnalyzer.java | 2 +- .../analyzer/MinHashAnalyzerProperties.java | 2 +- .../analyzer/NearestNeighborsAnalyzer.java | 2 +- .../NearestNeighborsAnalyzerProperties.java | 2 +- .../internal/serde/InternalSerdeImpl.java | 20 +++++++++---------- .../com/arangodb/model/ComputedValue.java | 2 +- .../arangodb/model/InvertedIndexOptions.java | 2 +- .../SearchAliasCreateOptions.java | 2 +- .../SearchAliasPropertiesOptions.java | 2 +- src/main/java/com/arangodb/util/RawBytes.java | 4 ++-- src/main/java/com/arangodb/util/RawJson.java | 4 ++-- 19 files changed, 30 insertions(+), 30 deletions(-) diff --git a/src/main/java/com/arangodb/entity/InvertedIndexEntity.java b/src/main/java/com/arangodb/entity/InvertedIndexEntity.java index 4c1d85c25..c6e184615 100644 --- a/src/main/java/com/arangodb/entity/InvertedIndexEntity.java +++ b/src/main/java/com/arangodb/entity/InvertedIndexEntity.java @@ -32,7 +32,7 @@ * @see API Documentation * @since ArangoDB 3.10 */ -public class InvertedIndexEntity { +public final class InvertedIndexEntity { private String id; private Boolean isNewlyCreated; diff --git a/src/main/java/com/arangodb/entity/InvertedIndexField.java b/src/main/java/com/arangodb/entity/InvertedIndexField.java index 6e330c7ac..29f59c7c5 100644 --- a/src/main/java/com/arangodb/entity/InvertedIndexField.java +++ b/src/main/java/com/arangodb/entity/InvertedIndexField.java @@ -9,7 +9,7 @@ * @see API Documentation * @since ArangoDB 3.10 */ -public class InvertedIndexField { +public final class InvertedIndexField { private String name; private String analyzer; private Boolean includeAllFields; diff --git a/src/main/java/com/arangodb/entity/InvertedIndexPrimarySort.java b/src/main/java/com/arangodb/entity/InvertedIndexPrimarySort.java index c42e94e40..c4a3677d8 100644 --- a/src/main/java/com/arangodb/entity/InvertedIndexPrimarySort.java +++ b/src/main/java/com/arangodb/entity/InvertedIndexPrimarySort.java @@ -14,7 +14,7 @@ * @see API Documentation * @since ArangoDB 3.10 */ -public class InvertedIndexPrimarySort { +public final class InvertedIndexPrimarySort { private final List fields = new ArrayList<>(); private ArangoSearchCompression compression; diff --git a/src/main/java/com/arangodb/entity/QueryOptimizerRule.java b/src/main/java/com/arangodb/entity/QueryOptimizerRule.java index df4869f2f..e6b543a6d 100644 --- a/src/main/java/com/arangodb/entity/QueryOptimizerRule.java +++ b/src/main/java/com/arangodb/entity/QueryOptimizerRule.java @@ -3,7 +3,7 @@ /** * @since ArangoDB 3.10 */ -public class QueryOptimizerRule { +public final class QueryOptimizerRule { private String name; private Flags flags; diff --git a/src/main/java/com/arangodb/entity/arangosearch/SearchAliasIndex.java b/src/main/java/com/arangodb/entity/arangosearch/SearchAliasIndex.java index 28ded55e7..1d18076f0 100644 --- a/src/main/java/com/arangodb/entity/arangosearch/SearchAliasIndex.java +++ b/src/main/java/com/arangodb/entity/arangosearch/SearchAliasIndex.java @@ -7,7 +7,7 @@ * @author Michele Rastelli * @since ArabgoDB 3.10 */ -public class SearchAliasIndex { +public final class SearchAliasIndex { private final String collection; private final String index; private final OperationType operation; diff --git a/src/main/java/com/arangodb/entity/arangosearch/SearchAliasPropertiesEntity.java b/src/main/java/com/arangodb/entity/arangosearch/SearchAliasPropertiesEntity.java index 4049bd78d..37d2a1587 100644 --- a/src/main/java/com/arangodb/entity/arangosearch/SearchAliasPropertiesEntity.java +++ b/src/main/java/com/arangodb/entity/arangosearch/SearchAliasPropertiesEntity.java @@ -29,7 +29,7 @@ * @author Michele Rastelli * @see API Documentation */ -public class SearchAliasPropertiesEntity extends ViewEntity { +public final class SearchAliasPropertiesEntity extends ViewEntity { private final Collection indexes = new ArrayList<>(); diff --git a/src/main/java/com/arangodb/entity/arangosearch/analyzer/ClassificationAnalyzer.java b/src/main/java/com/arangodb/entity/arangosearch/analyzer/ClassificationAnalyzer.java index 55eb3a47a..62290126b 100644 --- a/src/main/java/com/arangodb/entity/arangosearch/analyzer/ClassificationAnalyzer.java +++ b/src/main/java/com/arangodb/entity/arangosearch/analyzer/ClassificationAnalyzer.java @@ -33,7 +33,7 @@ * @see API Documentation * @since ArangoDB 3.10 */ -public class ClassificationAnalyzer extends SearchAnalyzer { +public final class ClassificationAnalyzer extends SearchAnalyzer { public ClassificationAnalyzer() { setType(AnalyzerType.classification); } diff --git a/src/main/java/com/arangodb/entity/arangosearch/analyzer/ClassificationAnalyzerProperties.java b/src/main/java/com/arangodb/entity/arangosearch/analyzer/ClassificationAnalyzerProperties.java index 06e3d339a..00ee39c88 100644 --- a/src/main/java/com/arangodb/entity/arangosearch/analyzer/ClassificationAnalyzerProperties.java +++ b/src/main/java/com/arangodb/entity/arangosearch/analyzer/ClassificationAnalyzerProperties.java @@ -29,7 +29,7 @@ * @author Michele Rastelli * @since ArangoDB 3.10 */ -public class ClassificationAnalyzerProperties { +public final class ClassificationAnalyzerProperties { @JsonProperty("model_location") private String modelLocation; diff --git a/src/main/java/com/arangodb/entity/arangosearch/analyzer/MinHashAnalyzer.java b/src/main/java/com/arangodb/entity/arangosearch/analyzer/MinHashAnalyzer.java index 116103e52..8afbde752 100644 --- a/src/main/java/com/arangodb/entity/arangosearch/analyzer/MinHashAnalyzer.java +++ b/src/main/java/com/arangodb/entity/arangosearch/analyzer/MinHashAnalyzer.java @@ -33,7 +33,7 @@ * @see API Documentation * @since ArangoDB 3.10 */ -public class MinHashAnalyzer extends SearchAnalyzer { +public final class MinHashAnalyzer extends SearchAnalyzer { public MinHashAnalyzer() { setType(AnalyzerType.minhash); } diff --git a/src/main/java/com/arangodb/entity/arangosearch/analyzer/MinHashAnalyzerProperties.java b/src/main/java/com/arangodb/entity/arangosearch/analyzer/MinHashAnalyzerProperties.java index a451c0525..1c37c1c0f 100644 --- a/src/main/java/com/arangodb/entity/arangosearch/analyzer/MinHashAnalyzerProperties.java +++ b/src/main/java/com/arangodb/entity/arangosearch/analyzer/MinHashAnalyzerProperties.java @@ -27,7 +27,7 @@ * @author Michele Rastelli * @since ArangoDB 3.10 */ -public class MinHashAnalyzerProperties { +public final class MinHashAnalyzerProperties { private SearchAnalyzer analyzer; private Integer numHashes; diff --git a/src/main/java/com/arangodb/entity/arangosearch/analyzer/NearestNeighborsAnalyzer.java b/src/main/java/com/arangodb/entity/arangosearch/analyzer/NearestNeighborsAnalyzer.java index c8641db4f..5bf97df0f 100644 --- a/src/main/java/com/arangodb/entity/arangosearch/analyzer/NearestNeighborsAnalyzer.java +++ b/src/main/java/com/arangodb/entity/arangosearch/analyzer/NearestNeighborsAnalyzer.java @@ -35,7 +35,7 @@ * @see API Documentation * @since ArangoDB 3.10 */ -public class NearestNeighborsAnalyzer extends SearchAnalyzer { +public final class NearestNeighborsAnalyzer extends SearchAnalyzer { public NearestNeighborsAnalyzer() { setType(AnalyzerType.nearest_neighbors); } diff --git a/src/main/java/com/arangodb/entity/arangosearch/analyzer/NearestNeighborsAnalyzerProperties.java b/src/main/java/com/arangodb/entity/arangosearch/analyzer/NearestNeighborsAnalyzerProperties.java index a2f850936..25f31ce7a 100644 --- a/src/main/java/com/arangodb/entity/arangosearch/analyzer/NearestNeighborsAnalyzerProperties.java +++ b/src/main/java/com/arangodb/entity/arangosearch/analyzer/NearestNeighborsAnalyzerProperties.java @@ -29,7 +29,7 @@ * @author Michele Rastelli * @since ArangoDB 3.10 */ -public class NearestNeighborsAnalyzerProperties { +public final class NearestNeighborsAnalyzerProperties { @JsonProperty("model_location") private String modelLocation; diff --git a/src/main/java/com/arangodb/internal/serde/InternalSerdeImpl.java b/src/main/java/com/arangodb/internal/serde/InternalSerdeImpl.java index a0e193247..cf6c70e6a 100644 --- a/src/main/java/com/arangodb/internal/serde/InternalSerdeImpl.java +++ b/src/main/java/com/arangodb/internal/serde/InternalSerdeImpl.java @@ -2,6 +2,7 @@ import com.arangodb.ArangoDBException; import com.arangodb.entity.BaseDocument; +import com.arangodb.entity.BaseEdgeDocument; import com.arangodb.serde.ArangoSerde; import com.arangodb.util.RawBytes; import com.arangodb.util.RawJson; @@ -79,11 +80,7 @@ public byte[] serializeUserData(Object value) { return serialize(null); } Class clazz = value.getClass(); - if (RawJson.class.isAssignableFrom(clazz) || - RawBytes.class.isAssignableFrom(clazz) || - JsonNode.class.isAssignableFrom(clazz) || - BaseDocument.class.isAssignableFrom(clazz) - ) { + if (isManagedClass(clazz)) { return serialize(value); } else { return userSerde.serialize(value); @@ -101,11 +98,7 @@ public byte[] serializeCollectionUserData(Collection value) { @Override public T deserializeUserData(byte[] content, Class clazz) { - if (RawJson.class.isAssignableFrom(clazz) || - RawBytes.class.isAssignableFrom(clazz) || - JsonNode.class.isAssignableFrom(clazz) || - BaseDocument.class.isAssignableFrom(clazz) - ) { + if (isManagedClass(clazz)) { return deserialize(content, clazz); } else { return userSerde.deserialize(content, clazz); @@ -149,4 +142,11 @@ public T deserialize(final byte[] content, final Type type) { return super.deserialize(content, type); } + private boolean isManagedClass(Class clazz) { + return JsonNode.class.isAssignableFrom(clazz) || + RawJson.class.equals(clazz) || + RawBytes.class.equals(clazz) || + BaseDocument.class.equals(clazz) || + BaseEdgeDocument.class.equals(clazz); + } } diff --git a/src/main/java/com/arangodb/model/ComputedValue.java b/src/main/java/com/arangodb/model/ComputedValue.java index ebb68002f..54d6a2b9f 100644 --- a/src/main/java/com/arangodb/model/ComputedValue.java +++ b/src/main/java/com/arangodb/model/ComputedValue.java @@ -8,7 +8,7 @@ /** * @since ArangoDB 3.10 */ -public class ComputedValue { +public final class ComputedValue { private String name; private String expression; private Boolean overwrite; diff --git a/src/main/java/com/arangodb/model/InvertedIndexOptions.java b/src/main/java/com/arangodb/model/InvertedIndexOptions.java index 9a4ddb601..b5b30caea 100644 --- a/src/main/java/com/arangodb/model/InvertedIndexOptions.java +++ b/src/main/java/com/arangodb/model/InvertedIndexOptions.java @@ -32,7 +32,7 @@ * @see API Documentation * @since ArangoDB 3.10 */ -public class InvertedIndexOptions extends IndexOptions { +public final class InvertedIndexOptions extends IndexOptions { protected final IndexType type = IndexType.inverted; private Integer parallelism; diff --git a/src/main/java/com/arangodb/model/arangosearch/SearchAliasCreateOptions.java b/src/main/java/com/arangodb/model/arangosearch/SearchAliasCreateOptions.java index 8e4f589cf..ac094f935 100644 --- a/src/main/java/com/arangodb/model/arangosearch/SearchAliasCreateOptions.java +++ b/src/main/java/com/arangodb/model/arangosearch/SearchAliasCreateOptions.java @@ -31,7 +31,7 @@ * @author Michele Rastelli * @since ArangoDB 3.10 */ -public class SearchAliasCreateOptions { +public final class SearchAliasCreateOptions { private String name; private final ViewType type; diff --git a/src/main/java/com/arangodb/model/arangosearch/SearchAliasPropertiesOptions.java b/src/main/java/com/arangodb/model/arangosearch/SearchAliasPropertiesOptions.java index fff218def..7530b2cb3 100644 --- a/src/main/java/com/arangodb/model/arangosearch/SearchAliasPropertiesOptions.java +++ b/src/main/java/com/arangodb/model/arangosearch/SearchAliasPropertiesOptions.java @@ -30,7 +30,7 @@ * @author Michele Rastelli * @since ArangoDB 3.10 */ -public class SearchAliasPropertiesOptions { +public final class SearchAliasPropertiesOptions { private final Collection indexes = new ArrayList<>(); diff --git a/src/main/java/com/arangodb/util/RawBytes.java b/src/main/java/com/arangodb/util/RawBytes.java index 8e9aded1b..4fa2b21dd 100644 --- a/src/main/java/com/arangodb/util/RawBytes.java +++ b/src/main/java/com/arangodb/util/RawBytes.java @@ -19,10 +19,10 @@ * The driver's {@link InternalSerde} supports serializing and deserializing to and from * {@code RawBytes}. */ -public class RawBytes implements RawData { +public final class RawBytes implements RawData { private final byte[] value; - protected RawBytes(final byte[] value) { + private RawBytes(final byte[] value) { this.value = value; } diff --git a/src/main/java/com/arangodb/util/RawJson.java b/src/main/java/com/arangodb/util/RawJson.java index 3642af973..a221a0017 100644 --- a/src/main/java/com/arangodb/util/RawJson.java +++ b/src/main/java/com/arangodb/util/RawJson.java @@ -13,10 +13,10 @@ * The driver's {@link InternalSerde} supports serializing and deserializing to and from * {@code RawJson}. */ -public class RawJson implements RawData { +public final class RawJson implements RawData { private final String value; - protected RawJson(final String value) { + private RawJson(final String value) { this.value = value; } From 6fda2537787a8ccd6ac06638fc5558df41aeb88d Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Thu, 22 Sep 2022 12:47:06 +0200 Subject: [PATCH 135/254] 3.10 test fixes --- src/test/java/com/arangodb/InvertedIndexTest.java | 2 +- src/test/java/com/arangodb/async/InvertedIndexTest.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/java/com/arangodb/InvertedIndexTest.java b/src/test/java/com/arangodb/InvertedIndexTest.java index 0314c6499..1850660a9 100644 --- a/src/test/java/com/arangodb/InvertedIndexTest.java +++ b/src/test/java/com/arangodb/InvertedIndexTest.java @@ -66,7 +66,7 @@ private InvertedIndexOptions createOptions(String analyzerName) { .name("bar") .analyzer(analyzerName) .searchField(true) - .features(AnalyzerFeature.position) + .features(AnalyzerFeature.position, AnalyzerFeature.frequency) .nested( new InvertedIndexField() .name("baz") diff --git a/src/test/java/com/arangodb/async/InvertedIndexTest.java b/src/test/java/com/arangodb/async/InvertedIndexTest.java index 1b9eebe14..8ee509526 100644 --- a/src/test/java/com/arangodb/async/InvertedIndexTest.java +++ b/src/test/java/com/arangodb/async/InvertedIndexTest.java @@ -74,7 +74,7 @@ private InvertedIndexOptions createOptions(String analyzerName) throws Execution .name("bar") .analyzer(analyzerName) .searchField(true) - .features(AnalyzerFeature.position) + .features(AnalyzerFeature.position, AnalyzerFeature.frequency) .nested( new InvertedIndexField() .name("baz") From 7b97346756660bd770ccc8ef95950e4f2356112a Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Thu, 22 Sep 2022 13:59:03 +0200 Subject: [PATCH 136/254] enabled ArangoSearchTest for 3.10 cluster (cherry picked from commit 7681147738f8ae52a58256787fe70e0a1152b3b8) --- src/test/java/com/arangodb/ArangoSearchTest.java | 6 ------ src/test/java/com/arangodb/async/ArangoSearchTest.java | 10 ---------- 2 files changed, 16 deletions(-) diff --git a/src/test/java/com/arangodb/ArangoSearchTest.java b/src/test/java/com/arangodb/ArangoSearchTest.java index fb108e599..280a60f48 100644 --- a/src/test/java/com/arangodb/ArangoSearchTest.java +++ b/src/test/java/com/arangodb/ArangoSearchTest.java @@ -28,7 +28,6 @@ import com.arangodb.model.InvertedIndexOptions; import com.arangodb.model.arangosearch.*; import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.MethodSource; @@ -52,11 +51,6 @@ static void init() { initCollections(COLL_1, COLL_2); } - @BeforeEach - void setUp() { - assumeTrue(isLessThanVersion(3, 10) || isSingleServer()); - } - @ParameterizedTest(name = "{index}") @MethodSource("dbs") void exists(ArangoDatabase db) { diff --git a/src/test/java/com/arangodb/async/ArangoSearchTest.java b/src/test/java/com/arangodb/async/ArangoSearchTest.java index c0113b291..84dc1ba01 100644 --- a/src/test/java/com/arangodb/async/ArangoSearchTest.java +++ b/src/test/java/com/arangodb/async/ArangoSearchTest.java @@ -20,9 +20,7 @@ package com.arangodb.async; -import com.arangodb.ArangoCollection; import com.arangodb.ArangoDBException; -import com.arangodb.ArangoDatabase; import com.arangodb.entity.InvertedIndexField; import com.arangodb.entity.ViewEntity; import com.arangodb.entity.ViewType; @@ -31,10 +29,7 @@ import com.arangodb.model.InvertedIndexOptions; import com.arangodb.model.arangosearch.*; import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.MethodSource; import java.util.Collection; import java.util.HashSet; @@ -65,11 +60,6 @@ static void setup() throws InterruptedException, ExecutionException { db.createCollection(COLL_2).get(); } - @BeforeEach - void setUp() throws ExecutionException, InterruptedException { - assumeTrue(isLessThanVersion(3, 10) || isSingleServer()); - } - @Test void exists() throws InterruptedException, ExecutionException { assumeTrue(isAtLeastVersion(3, 4)); From 9934262f385f5d8977b0268981089da0e4c6a9b4 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Fri, 23 Sep 2022 14:40:55 +0200 Subject: [PATCH 137/254] removed unecessary protected methods --- src/main/java/com/arangodb/model/InvertedIndexOptions.java | 4 ++-- .../arangodb/model/arangosearch/SearchAliasCreateOptions.java | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/arangodb/model/InvertedIndexOptions.java b/src/main/java/com/arangodb/model/InvertedIndexOptions.java index b5b30caea..d03422bf7 100644 --- a/src/main/java/com/arangodb/model/InvertedIndexOptions.java +++ b/src/main/java/com/arangodb/model/InvertedIndexOptions.java @@ -34,7 +34,7 @@ */ public final class InvertedIndexOptions extends IndexOptions { - protected final IndexType type = IndexType.inverted; + private final IndexType type = IndexType.inverted; private Integer parallelism; private InvertedIndexPrimarySort primarySort; private final Collection storedValues = new ArrayList<>(); @@ -57,7 +57,7 @@ public InvertedIndexOptions() { } @Override - protected InvertedIndexOptions getThis() { + InvertedIndexOptions getThis() { return this; } diff --git a/src/main/java/com/arangodb/model/arangosearch/SearchAliasCreateOptions.java b/src/main/java/com/arangodb/model/arangosearch/SearchAliasCreateOptions.java index ac094f935..6456fe6ee 100644 --- a/src/main/java/com/arangodb/model/arangosearch/SearchAliasCreateOptions.java +++ b/src/main/java/com/arangodb/model/arangosearch/SearchAliasCreateOptions.java @@ -43,7 +43,7 @@ public SearchAliasCreateOptions() { type = ViewType.SEARCH_ALIAS; } - protected SearchAliasCreateOptions name(final String name) { + SearchAliasCreateOptions name(final String name) { this.name = name; return this; } From 212152b95f84a265bab9c4b5237704451a7be208 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Fri, 23 Sep 2022 15:28:15 +0200 Subject: [PATCH 138/254] moved JsonbSerde into test code --- src/{main => test}/java/com/arangodb/serde/JsonbSerde.java | 1 - .../java/com/arangodb}/serde/JsonbSerdeImpl.java | 3 +-- 2 files changed, 1 insertion(+), 3 deletions(-) rename src/{main => test}/java/com/arangodb/serde/JsonbSerde.java (92%) rename src/{main/java/com/arangodb/internal => test/java/com/arangodb}/serde/JsonbSerdeImpl.java (90%) diff --git a/src/main/java/com/arangodb/serde/JsonbSerde.java b/src/test/java/com/arangodb/serde/JsonbSerde.java similarity index 92% rename from src/main/java/com/arangodb/serde/JsonbSerde.java rename to src/test/java/com/arangodb/serde/JsonbSerde.java index c8dc61041..c6dac0dcc 100644 --- a/src/main/java/com/arangodb/serde/JsonbSerde.java +++ b/src/test/java/com/arangodb/serde/JsonbSerde.java @@ -1,6 +1,5 @@ package com.arangodb.serde; -import com.arangodb.internal.serde.JsonbSerdeImpl; import jakarta.json.bind.JsonbConfig; /** diff --git a/src/main/java/com/arangodb/internal/serde/JsonbSerdeImpl.java b/src/test/java/com/arangodb/serde/JsonbSerdeImpl.java similarity index 90% rename from src/main/java/com/arangodb/internal/serde/JsonbSerdeImpl.java rename to src/test/java/com/arangodb/serde/JsonbSerdeImpl.java index 3f3fe8fde..a19dacbbf 100644 --- a/src/main/java/com/arangodb/internal/serde/JsonbSerdeImpl.java +++ b/src/test/java/com/arangodb/serde/JsonbSerdeImpl.java @@ -1,6 +1,5 @@ -package com.arangodb.internal.serde; +package com.arangodb.serde; -import com.arangodb.serde.JsonbSerde; import jakarta.json.bind.Jsonb; import jakarta.json.bind.JsonbBuilder; import jakarta.json.bind.JsonbConfig; From 45080e3e457642bf75b902d6be8ec965de26c373 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Tue, 27 Sep 2022 12:56:00 +0200 Subject: [PATCH 139/254] updated changelog --- ChangeLog.md | 81 +++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 80 insertions(+), 1 deletion(-) diff --git a/ChangeLog.md b/ChangeLog.md index c7bcfb8e4..95fa065ac 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -6,7 +6,86 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) a ## [Unreleased] -- changed default protocol from VST to HTTP/1.1 +## [7.0.0] + +### Changed + +- changed default communication protocol from VST to HTTP/1.1 +- changed default content-type encoding format from VPACK to JSON +- transitive dependency on `org.apache.httpcomponents:httpclient:4.5.x` is not optional anymore, but it can be excluded + if using VST only +- VPACK support is now provided by the optional dependency `com.arangodb:jackson-dataformat-velocypack` as dataformat + backend for Jackson +- changed serialization module, which is now based on Jackson API +- data objects passed as arguments to API methods are now treated as immutable and the related metadata fields are not + updated anymore (updated metadata can be found anyway in the object returned by the API method) +- changed some API signatures which were using unnecessary generics +- changed `com.arangodb.ArangoCursor#getStats()` to return untyped map +- modeled replication factor with a new interface (`com.arangodb.entity.ReplicationFactor`) with + implementations: `NumericReplicationFactor` and `SatelliteReplicationFactor` +- all data definition classes are now `final` +- `BaseDocument` and `BaseEdgeDocument` are now `final` +- `BaseDocument#getProperties()` and `BaseEdgeDocument#getProperties()` return now an unmodifiable map + +### Removed + +- removed user-data custom serializer API based on `com.arangodb.util.ArangoSerialization` (in favor + of `com.arangodb.serde.ArangoSerde`) +- removed user-data custom serializer implementation `com.arangodb.mapping.ArangoJack` (in favor + of `com.arangodb.serde.JacksonSerde`) +- removed support for interpreting raw strings as JSON (use `com.arangodb.util.RawJson` instead) +- removed support of data type `com.arangodb.velocypack.VPackSlice` +- removed `catchException` parameter option from Collections, Vertexes and Edges API +- removed `throws ArangoDBException` declarations from API method signatures +- removed client APIs already deprecated in Java Driver version 6.19.0 +- removed deprecated server APIs: + - MMFiles related APIs + - `ArangoDatabase.executeTraversal()` + - `ArangoDB.getLogs()` + - `minReplicationFactor` in collections and graphs + - `overwrite` flag in `DocumentCreateOptions` +- removed `com.arangodb.entity.CursorEntity` from public API +- removed interface `com.arangodb.entity.Entity` + +### Added + +- added transitive dependency on Jackson Core, Databind and Annotations +- added wrapper class for raw JSON content (`com.arangodb.util.RawJson`) +- added wrapper class for content already encoded as byte array (`com.arangodb.util.RawBytes`) +- added support for Jackson types (`JsonNode`, `ArrayNode`, `ObjectNode`, ...) +- added support for Jackson annotations in data types +- added new user-data custom serializer API based on `com.arangodb.serde.ArangoSerde` +- added new user-data custom serializer implementation based on Jackson (`com.arangodb.serde.JacksonSerde`) +- added JSON-B compatibility to meta binding annotations (`@Id`, `@Key`, `@Rev`, `@From`, `@To`) +- added methods and parameters targets to meta binding annotations +- added overloaded methods for CRUD operations allowing specifying the return type +- added API to support CRUD operations from raw data (`RawBytes` and `RawJson`) containing multiple documents +- added `BaseDocument#removeAttribute(String)` and `BaseEdgeDocument#removeAttribute(String)` + +### Fixed + +- removed `--allow-incomplete-classpath` from native image configuration (#397) +- ability to control whether `null` values are included in the serialization (#389) +- added support to `com.arangodb.model.DocumentCreateOptions#keepNull` (#374) +- allow specifying the return type on insertDocuments (#373) + +## [6.19.0] + +- added support for `search-alias` views (ArangoDB 3.10 #461) +- added support for nested search (ArangoDB 3.10, #460) +- added support for `classification`, `nearest_neighbors` and `minhash` search analyzers (ArangoDB 3.10, #458) +- added support for inverted indexes (ArangoDB 3.10, #457) +- added support for cluster dirty reads (ArangoDB 3.10, #455) +- added support for index stored values (ArangoDB 3.10) +- added support for geo index legacy polygons (ArangoDB 3.10) +- added support for getting query optimizer rules (ArangoDB 3.10) +- added support for enhanced cursor stats (ArangoDB 3.10) +- added support for computed values (ArangoDB 3.10) +- added support for index cache (ArangoDB 3.10) +- deprecated fulltext indexes (ArangoDB 3.10, #454) +- fixed `ConsolidationPolicy` API +- deprecated MMFiles collection attributes (#442) +- documented thead safe classes (#445) ## [6.18.0] - 2022-06-07 From 407dad70e49bb0b706244405c1107807a30b8407 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Tue, 27 Sep 2022 21:01:33 +0200 Subject: [PATCH 140/254] made BaseDocument final --- .../arangodb/entity/AbstractBaseDocument.java | 150 ++++++++++++++++++ .../com/arangodb/entity/BaseDocument.java | 113 +------------ .../com/arangodb/entity/BaseEdgeDocument.java | 16 +- 3 files changed, 159 insertions(+), 120 deletions(-) create mode 100644 src/main/java/com/arangodb/entity/AbstractBaseDocument.java diff --git a/src/main/java/com/arangodb/entity/AbstractBaseDocument.java b/src/main/java/com/arangodb/entity/AbstractBaseDocument.java new file mode 100644 index 000000000..be77acaaf --- /dev/null +++ b/src/main/java/com/arangodb/entity/AbstractBaseDocument.java @@ -0,0 +1,150 @@ +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed 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. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.entity; + +import com.fasterxml.jackson.annotation.JsonAnyGetter; +import com.fasterxml.jackson.annotation.JsonAnySetter; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonInclude; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; + +/** + * @author Mark Vollmary + * @author Michele Rastelli + */ +abstract class AbstractBaseDocument { + + private static final String[] META_PROPS = new String[]{"_id", "_key", "_rev"}; + private final Map properties; + + AbstractBaseDocument() { + properties = new HashMap<>(); + } + + AbstractBaseDocument(final String key) { + this(); + setKey(key); + } + + AbstractBaseDocument(final Map properties) { + this(); + setProperties(properties); + } + + @JsonIgnore + public String getId() { + return (String) getAttribute("_id"); + } + + public void setId(final String id) { + addAttribute("_id", id); + } + + @JsonIgnore + public String getKey() { + return (String) getAttribute("_key"); + } + + public void setKey(final String key) { + addAttribute("_key", key); + } + + @JsonIgnore + public String getRevision() { + return (String) getAttribute("_rev"); + } + + public void setRevision(final String rev) { + addAttribute("_rev", rev); + } + + @JsonInclude + @JsonAnyGetter + public Map getProperties() { + return Collections.unmodifiableMap(properties); + } + + public void setProperties(final Map props) { + for (String f : getMetaProps()) { + requireString(f, props.get(f)); + } + this.properties.putAll(props); + } + + public Object getAttribute(final String key) { + return properties.get(key); + } + + @JsonInclude + @JsonAnySetter + public void addAttribute(final String key, final Object value) { + for (String f : getMetaProps()) { + if (f.equals(key)) { + requireString(key, value); + } + } + properties.put(key, value); + } + + public void updateAttribute(final String key, final Object value) { + if (properties.containsKey(key)) { + addAttribute(key, value); + } + } + + public void removeAttribute(final String key) { + properties.remove(key); + } + + protected String[] getMetaProps() { + return META_PROPS; + } + + private void requireString(final String k, final Object v) { + if (v != null && !(v instanceof String)) { + throw new IllegalArgumentException(k + " must be a String"); + } + } + + @Override + public String toString() { + return "{" + + "properties=" + properties + + '}'; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + AbstractBaseDocument that = (AbstractBaseDocument) o; + return Objects.equals(properties, that.properties); + } + + @Override + public int hashCode() { + return Objects.hash(properties); + } +} diff --git a/src/main/java/com/arangodb/entity/BaseDocument.java b/src/main/java/com/arangodb/entity/BaseDocument.java index d4be3df7c..3b5c805c1 100644 --- a/src/main/java/com/arangodb/entity/BaseDocument.java +++ b/src/main/java/com/arangodb/entity/BaseDocument.java @@ -20,130 +20,29 @@ package com.arangodb.entity; -import com.fasterxml.jackson.annotation.JsonAnyGetter; -import com.fasterxml.jackson.annotation.JsonAnySetter; -import com.fasterxml.jackson.annotation.JsonIgnore; -import com.fasterxml.jackson.annotation.JsonInclude; - -import java.util.Collections; -import java.util.HashMap; import java.util.Map; -import java.util.Objects; /** * @author Mark Vollmary + * @author Michele Rastelli */ -public class BaseDocument { - - private static final String[] META_PROPS = new String[]{"_id", "_key", "_rev"}; - private final Map properties; +public final class BaseDocument extends AbstractBaseDocument { public BaseDocument() { - properties = new HashMap<>(); + super(); } public BaseDocument(final String key) { - this(); - setKey(key); + super(key); } public BaseDocument(final Map properties) { - this(); - setProperties(properties); - } - - @JsonIgnore - public String getId() { - return (String) getAttribute("_id"); - } - - public void setId(final String id) { - addAttribute("_id", id); - } - - @JsonIgnore - public String getKey() { - return (String) getAttribute("_key"); - } - - public void setKey(final String key) { - addAttribute("_key", key); - } - - @JsonIgnore - public String getRevision() { - return (String) getAttribute("_rev"); - } - - public void setRevision(final String rev) { - addAttribute("_rev", rev); - } - - @JsonInclude - @JsonAnyGetter - public Map getProperties() { - return Collections.unmodifiableMap(properties); - } - - public void setProperties(final Map props) { - for (String f : getMetaProps()) { - requireString(f, props.get(f)); - } - this.properties.putAll(props); - } - - public Object getAttribute(final String key) { - return properties.get(key); - } - - @JsonInclude - @JsonAnySetter - public void addAttribute(final String key, final Object value) { - for (String f : getMetaProps()) { - if (f.equals(key)) { - requireString(key, value); - } - } - properties.put(key, value); - } - - public void updateAttribute(final String key, final Object value) { - if (properties.containsKey(key)) { - addAttribute(key, value); - } - } - - public void removeAttribute(final String key) { - properties.remove(key); - } - - protected String[] getMetaProps() { - return META_PROPS; - } - - private void requireString(final String k, final Object v) { - if (v != null && !(v instanceof String)) { - throw new IllegalArgumentException(k + " must be a String"); - } + super(properties); } @Override public String toString() { - return "BaseDocument{" + - "properties=" + properties + - '}'; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - BaseDocument that = (BaseDocument) o; - return properties.equals(that.properties); + return "BaseDocument" + super.toString(); } - @Override - public int hashCode() { - return Objects.hash(properties); - } } diff --git a/src/main/java/com/arangodb/entity/BaseEdgeDocument.java b/src/main/java/com/arangodb/entity/BaseEdgeDocument.java index 21dad292c..1dd6f4098 100644 --- a/src/main/java/com/arangodb/entity/BaseEdgeDocument.java +++ b/src/main/java/com/arangodb/entity/BaseEdgeDocument.java @@ -26,8 +26,9 @@ /** * @author Mark Vollmary + * @author Michele Rastelli */ -public final class BaseEdgeDocument extends BaseDocument { +public final class BaseEdgeDocument extends AbstractBaseDocument { private static final String[] META_PROPS = new String[]{"_id", "_key", "_rev", "_from", "_to"}; @@ -76,18 +77,7 @@ protected String[] getMetaProps() { @Override public String toString() { - return "BaseEdgeDocument{properties=" + getProperties() + '}'; + return "BaseEdgeDocument" + super.toString(); } - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - return super.equals(o); - } - - @Override - public int hashCode() { - return super.hashCode(); - } } From 090d7cc331ef256ae6b7a209ffad990df29714cd Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Tue, 27 Sep 2022 21:21:54 +0200 Subject: [PATCH 141/254] made BaseDocument and BaseEdgeDocument serializable --- .../arangodb/entity/AbstractBaseDocument.java | 5 +++- .../com/arangodb/entity/BaseDocument.java | 5 +++- .../com/arangodb/entity/BaseEdgeDocument.java | 5 +++- .../java/com/arangodb/BaseDocumentTest.java | 29 +++++++++++++++++++ 4 files changed, 41 insertions(+), 3 deletions(-) create mode 100644 src/test/java/com/arangodb/BaseDocumentTest.java diff --git a/src/main/java/com/arangodb/entity/AbstractBaseDocument.java b/src/main/java/com/arangodb/entity/AbstractBaseDocument.java index be77acaaf..889c34542 100644 --- a/src/main/java/com/arangodb/entity/AbstractBaseDocument.java +++ b/src/main/java/com/arangodb/entity/AbstractBaseDocument.java @@ -25,6 +25,7 @@ import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonInclude; +import java.io.Serializable; import java.util.Collections; import java.util.HashMap; import java.util.Map; @@ -34,7 +35,9 @@ * @author Mark Vollmary * @author Michele Rastelli */ -abstract class AbstractBaseDocument { +abstract class AbstractBaseDocument implements Serializable { + + private static final long serialVersionUID = 846874908582L; private static final String[] META_PROPS = new String[]{"_id", "_key", "_rev"}; private final Map properties; diff --git a/src/main/java/com/arangodb/entity/BaseDocument.java b/src/main/java/com/arangodb/entity/BaseDocument.java index 3b5c805c1..62207db9e 100644 --- a/src/main/java/com/arangodb/entity/BaseDocument.java +++ b/src/main/java/com/arangodb/entity/BaseDocument.java @@ -20,13 +20,16 @@ package com.arangodb.entity; +import java.io.Serializable; import java.util.Map; /** * @author Mark Vollmary * @author Michele Rastelli */ -public final class BaseDocument extends AbstractBaseDocument { +public final class BaseDocument extends AbstractBaseDocument implements Serializable { + + private static final long serialVersionUID = 733033350470L; public BaseDocument() { super(); diff --git a/src/main/java/com/arangodb/entity/BaseEdgeDocument.java b/src/main/java/com/arangodb/entity/BaseEdgeDocument.java index 1dd6f4098..fcf082256 100644 --- a/src/main/java/com/arangodb/entity/BaseEdgeDocument.java +++ b/src/main/java/com/arangodb/entity/BaseEdgeDocument.java @@ -22,13 +22,16 @@ import com.fasterxml.jackson.annotation.JsonIgnore; +import java.io.Serializable; import java.util.Map; /** * @author Mark Vollmary * @author Michele Rastelli */ -public final class BaseEdgeDocument extends AbstractBaseDocument { +public final class BaseEdgeDocument extends AbstractBaseDocument implements Serializable { + + private static final long serialVersionUID = 356629614444L; private static final String[] META_PROPS = new String[]{"_id", "_key", "_rev", "_from", "_to"}; diff --git a/src/test/java/com/arangodb/BaseDocumentTest.java b/src/test/java/com/arangodb/BaseDocumentTest.java new file mode 100644 index 000000000..52314ba85 --- /dev/null +++ b/src/test/java/com/arangodb/BaseDocumentTest.java @@ -0,0 +1,29 @@ +package com.arangodb; + +import com.arangodb.entity.BaseDocument; +import org.junit.jupiter.api.Test; + +import java.io.*; + +import static org.assertj.core.api.Assertions.assertThat; + +public class BaseDocumentTest { + @Test + public void serializeBaseDocument() throws IOException, ClassNotFoundException { + BaseDocument bd = new BaseDocument("poaids"); + bd.setId("apdso/02193"); + bd.setRevision("poip"); + bd.addAttribute("aaa", "bbb"); + + ByteArrayOutputStream os = new ByteArrayOutputStream(); + ObjectOutputStream objectOutputStream = new ObjectOutputStream(os); + objectOutputStream.writeObject(bd); + + InputStream is = new ByteArrayInputStream(os.toByteArray()); + ObjectInputStream objectInputStream = new ObjectInputStream(is); + BaseDocument bd2 = (BaseDocument) objectInputStream.readObject(); + objectInputStream.close(); + + assertThat(bd).isEqualTo(bd2); + } +} From 9d184979b044fc80fd5ab142ea131f33cfc33e3f Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Tue, 27 Sep 2022 21:28:58 +0200 Subject: [PATCH 142/254] updated changelog --- ChangeLog.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ChangeLog.md b/ChangeLog.md index 95fa065ac..28f48f247 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -33,13 +33,13 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) a of `com.arangodb.serde.ArangoSerde`) - removed user-data custom serializer implementation `com.arangodb.mapping.ArangoJack` (in favor of `com.arangodb.serde.JacksonSerde`) -- removed support for interpreting raw strings as JSON (use `com.arangodb.util.RawJson` instead) +- removed support for interpreting raw strings as JSON (in favor of `com.arangodb.util.RawJson`) - removed support of data type `com.arangodb.velocypack.VPackSlice` - removed `catchException` parameter option from Collections, Vertexes and Edges API - removed `throws ArangoDBException` declarations from API method signatures -- removed client APIs already deprecated in Java Driver version 6.19.0 +- removed client APIs already deprecated in Java Driver version `6.19.0` - removed deprecated server APIs: - - MMFiles related APIs + - `MMFiles` related APIs - `ArangoDatabase.executeTraversal()` - `ArangoDB.getLogs()` - `minReplicationFactor` in collections and graphs From ea62484cdaf72f60dd0c40cebfd452176a3a6e38 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Thu, 29 Sep 2022 20:09:06 +0200 Subject: [PATCH 143/254] [DE-399] added support for ConsolidationPolicy#minScore() (cherry picked from commit cc6a7ac19a49979943a48509efb6040395185f14) --- .../arangosearch/ConsolidationPolicy.java | 18 ++++++++++++++++-- .../java/com/arangodb/InvertedIndexTest.java | 1 + 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/arangodb/entity/arangosearch/ConsolidationPolicy.java b/src/main/java/com/arangodb/entity/arangosearch/ConsolidationPolicy.java index fb81b6b40..fb0fe6244 100644 --- a/src/main/java/com/arangodb/entity/arangosearch/ConsolidationPolicy.java +++ b/src/main/java/com/arangodb/entity/arangosearch/ConsolidationPolicy.java @@ -33,6 +33,7 @@ public final class ConsolidationPolicy { private Long segmentsMax; private Long segmentsBytesMax; private Long segmentsBytesFloor; + private Long minScore; public ConsolidationPolicy() { @@ -125,16 +126,29 @@ public ConsolidationPolicy segmentsBytesFloor(final Long segmentsBytesFloor) { return this; } + public Long getMinScore() { + return minScore; + } + + /** + * @param minScore Filter out consolidation candidates with a score less than this. (default: 0) + * @return this + */ + public ConsolidationPolicy minScore(final Long minScore) { + this.minScore = minScore; + return this; + } + @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; ConsolidationPolicy that = (ConsolidationPolicy) o; - return type == that.type && Objects.equals(threshold, that.threshold) && Objects.equals(segmentsMin, that.segmentsMin) && Objects.equals(segmentsMax, that.segmentsMax) && Objects.equals(segmentsBytesMax, that.segmentsBytesMax) && Objects.equals(segmentsBytesFloor, that.segmentsBytesFloor); + return type == that.type && Objects.equals(threshold, that.threshold) && Objects.equals(segmentsMin, that.segmentsMin) && Objects.equals(segmentsMax, that.segmentsMax) && Objects.equals(segmentsBytesMax, that.segmentsBytesMax) && Objects.equals(segmentsBytesFloor, that.segmentsBytesFloor) && Objects.equals(minScore, that.minScore); } @Override public int hashCode() { - return Objects.hash(type, threshold, segmentsMin, segmentsMax, segmentsBytesMax, segmentsBytesFloor); + return Objects.hash(type, threshold, segmentsMin, segmentsMax, segmentsBytesMax, segmentsBytesFloor, minScore); } } diff --git a/src/test/java/com/arangodb/InvertedIndexTest.java b/src/test/java/com/arangodb/InvertedIndexTest.java index 1850660a9..e96bc70ef 100644 --- a/src/test/java/com/arangodb/InvertedIndexTest.java +++ b/src/test/java/com/arangodb/InvertedIndexTest.java @@ -103,6 +103,7 @@ private InvertedIndexOptions createOptions(String analyzerName) { .segmentsMax(44L) .segmentsBytesMax(55555L) .segmentsBytesFloor(666L) + .minScore(77L) ) .writebufferIdle(44L) .writebufferActive(55L) From e5b18cd791011013e01b3d29db38d52dc5db0541 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Wed, 28 Sep 2022 22:32:20 +0200 Subject: [PATCH 144/254] detailed changes --- ChangeLog.md | 16 ++---- docs/v7_detailed_changes.md | 112 ++++++++++++++++++++++++++++++++++++ 2 files changed, 118 insertions(+), 10 deletions(-) create mode 100644 docs/v7_detailed_changes.md diff --git a/ChangeLog.md b/ChangeLog.md index 28f48f247..e45f5540a 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -26,17 +26,16 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) a - all data definition classes are now `final` - `BaseDocument` and `BaseEdgeDocument` are now `final` - `BaseDocument#getProperties()` and `BaseEdgeDocument#getProperties()` return now an unmodifiable map +- changed API method signatures removing throw declarations like: `throws ArangoDBException` (unchecked exception) ### Removed -- removed user-data custom serializer API based on `com.arangodb.util.ArangoSerialization` (in favor +- removed user data custom serializer API based on `com.arangodb.util.ArangoSerialization` (in favor of `com.arangodb.serde.ArangoSerde`) -- removed user-data custom serializer implementation `com.arangodb.mapping.ArangoJack` (in favor +- removed user data custom serializer implementation `com.arangodb.mapping.ArangoJack` (in favor of `com.arangodb.serde.JacksonSerde`) - removed support for interpreting raw strings as JSON (in favor of `com.arangodb.util.RawJson`) -- removed support of data type `com.arangodb.velocypack.VPackSlice` -- removed `catchException` parameter option from Collections, Vertexes and Edges API -- removed `throws ArangoDBException` declarations from API method signatures +- removed support of data type `com.arangodb.velocypack.VPackSlice` (in favor of Jackson types: `JsonNode`, `ArrayNode`, `ObjectNode`, ...) - removed client APIs already deprecated in Java Driver version `6.19.0` - removed deprecated server APIs: - `MMFiles` related APIs @@ -44,8 +43,6 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) a - `ArangoDB.getLogs()` - `minReplicationFactor` in collections and graphs - `overwrite` flag in `DocumentCreateOptions` -- removed `com.arangodb.entity.CursorEntity` from public API -- removed interface `com.arangodb.entity.Entity` ### Added @@ -54,9 +51,8 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) a - added wrapper class for content already encoded as byte array (`com.arangodb.util.RawBytes`) - added support for Jackson types (`JsonNode`, `ArrayNode`, `ObjectNode`, ...) - added support for Jackson annotations in data types -- added new user-data custom serializer API based on `com.arangodb.serde.ArangoSerde` -- added new user-data custom serializer implementation based on Jackson (`com.arangodb.serde.JacksonSerde`) -- added JSON-B compatibility to meta binding annotations (`@Id`, `@Key`, `@Rev`, `@From`, `@To`) +- added new user data custom serializer API based on `com.arangodb.serde.ArangoSerde` +- added new user data custom serializer implementation based on Jackson (`com.arangodb.serde.JacksonSerde`) - added methods and parameters targets to meta binding annotations - added overloaded methods for CRUD operations allowing specifying the return type - added API to support CRUD operations from raw data (`RawBytes` and `RawJson`) containing multiple documents diff --git a/docs/v7_detailed_changes.md b/docs/v7_detailed_changes.md new file mode 100644 index 000000000..65769cd83 --- /dev/null +++ b/docs/v7_detailed_changes.md @@ -0,0 +1,112 @@ +# Version 7.0: detailed changes + + +## Default protocol + +The default communication protocol is now `HTTP_JSON` (`HTTP/1.1` with `JSON` content type). + + +## Transitive dependencies + +A transitive dependency on `org.apache.httpcomponents:httpclient:4.5.x` has been added and the dependency +on `com.arangodb:velocypack` has been removed. +The dependency on `org.apache.httpcomponents:httpclient` can be excluded when using `VST` communication protocol only. +When using `VST` or `HTTP_VPACK`, the optional dependency on `com.arangodb:jackson-dataformat-velocypack` must be +provided. +When using `HTTP_JSON` (default), no dependencies on `VPACK` libraries are required. +Transitive dependencies on Jackson Core, Databind and Annotations have been added, using by default version `2.13`. +The versions of such libraries can be overridden, the driver is compatible with Jackson versions: `2.10`, `2.11`, `2.12` +, `2.13`. + + +## User Data Types + +Before version `7.0` the driver always parsed raw strings as JSON, but unfortunately this does not allow distinguishing +the case when the intent is to use the raw string as such, without parsing it. Since version `7.0`, strings are not +interpreted as JSON anymore. To represent user data as raw JSON, the wrapper class `com.arangodb.util.RawJson` has been +added. + +To represent user data already encoded as byte array, the wrapper class `com.arangodb.util.RawBytes` has been added. +The byte array can either represent a `JSON` string (UTF-8 encoded) or a `VPACK` value, but the encoding must be the +same used for the driver protocol configuration (`JSON` for `HTTP_JSON`, `VPACK` otherwise). + +`BaseDocument` and `BaseEdgeDocument` are now `final`, they have a new method `removeAttribute(String)` +and `getProperties()` returns now an unmodifiable map. + +Before version `7.0` when performing write operations, the metadata of the input data objects was updated with the +metadata received in the response. Since version `7.0`, the input data objects passed as arguments to API methods are +treated as immutable and the related metadata fields are not updated anymore. The updated metadata can still be found in +the object returned by the API method. + + +## Serialization + +The serialization module has been changed and is now based on the Jackson API. + +Up to version 6, the (de)serialization was always performed to/from `VPACK`. In case the JSON representation was required, +the raw `VPACK` was then converted to `JSON`. Since version 7, the serialization module is a dataformat agnostic API, based +on the Jackson API. By default, it reads and writes `JSON` format. `VPACK` support is provided by the optional +dependency `com.arangodb:jackson-dataformat-velocypack`, which is a dataformat backend implementation for Jackson. + +The (de)serialization of user data can be customized by registering an implementation +of `com.arangodb.serde.ArangoSerde` via `com.arangodb.ArangoDB.Builder#serializer()`. +The default user data serializer is `com.arangodb.serde.JacksonSerde`, which is based on Jackson API and is available +for both `JSON` and `VPACK`. It (de)serializes user data using Jackson Databind and can handle Jackson Annotations. +It can be customized through `com.arangodb.serde.JacksonSerde#configure(Consumer)`, +i.e. registering Kotlin or Scala modules. Furthermore, meta binding annotations (`@Id`, `@Key`, `@Rev`, `@From`, `@To`) +are supported for mapping documents and edges metadata fields (`_id`, `_key`, `_rev`, `_from`, `_to`). + +`com.arangodb.serde.ArangoSerde` interface is not constrained to Jackson. It is instead an abstract API that can be +implemented using any custom serialization library, e.g. an example of `JSON-B` implementation can be found in +the [tests](../src/test/java/com/arangodb/serde/JsonbSerdeImpl.java). + +Independently of the user data serializer, the following data types are (de)serialized with specific handlers (not +customizable): +- `JsonNode` and its children (`ArrayNode`, `ObjectNode`, ...) +- `RawJson` +- `RawBytes` +- `BaseDocument` +- `BaseEdgeDocument` + + +## Removed APIs + +The following client APIs have been removed: +- client APIs already deprecated in Java Driver version `6.19.0` +- client API to interact with deprecated server APIs: + - `MMFiles` related APIs + - `ArangoDatabase.executeTraversal()` + - `ArangoDB.getLogs()` + - `minReplicationFactor` in collections and graphs + - `overwrite` flag in `DocumentCreateOptions` + +The deprecation notes in the related javadoc contain information about the reason of the deprecation and suggest +migration alternatives to use. + +To migrate your existing project to Java Driver version `7.0`, it is recommended updating to version `6.19` first and +make sure that your code does not use any deprecated API. This can be done by checking the presence of deprecation +warnings in the Java compiler output. + +The user data custom serializer implementation `com.arangodb.mapping.ArangoJack` has been removed in favor of `com.arangodb.serde.JacksonSerde`. + +Support for interpreting raw strings as JSON has been removed (in favor of `com.arangodb.util.RawJson`). + +Support of data type `com.arangodb.velocypack.VPackSlice` has been removed (in favor of Jackson types: `JsonNode`, `ArrayNode`, `ObjectNode`, ...). + + +## API methods changes + +Before version `7.0` some CRUD API methods inferred the return type from the type of the data object passed as input. Now the return type can be explicitly set for each CRUD API method. + +CRUD operations operating with multiple documents have now an overloaded variant which accepts raw data (`RawBytes` +and `RawJson`) containing multiple documents. + +`com.arangodb.ArangoCursor#getStats()` returns now an untyped map. + + +## API entities + +All entities and options classes are now `final`. + +The replication factor is now modeled with a new interface (`com.arangodb.entity.ReplicationFactor`) with +implementations: `NumericReplicationFactor` and `SatelliteReplicationFactor`. From 3de86c4bd9a089fbf64e39cac47c55303c610910 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Wed, 5 Oct 2022 11:03:59 +0200 Subject: [PATCH 145/254] removed ArangoCursorInitializer --- src/main/java/com/arangodb/ArangoDB.java | 12 ------ .../com/arangodb/internal/ArangoDBImpl.java | 10 +---- .../arangodb/internal/ArangoDatabaseImpl.java | 12 +----- .../util/ArangoCursorInitializer.java | 39 ------------------- 4 files changed, 2 insertions(+), 71 deletions(-) delete mode 100644 src/main/java/com/arangodb/util/ArangoCursorInitializer.java diff --git a/src/main/java/com/arangodb/ArangoDB.java b/src/main/java/com/arangodb/ArangoDB.java index 21f55b465..3983b7b55 100644 --- a/src/main/java/com/arangodb/ArangoDB.java +++ b/src/main/java/com/arangodb/ArangoDB.java @@ -38,12 +38,9 @@ import com.arangodb.serde.ArangoSerde; import com.arangodb.serde.DataType; import com.arangodb.serde.JacksonSerde; -import com.arangodb.util.ArangoCursorInitializer; import com.arangodb.velocystream.Request; import com.arangodb.velocystream.Response; import org.apache.http.client.HttpRequestRetryHandler; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import javax.annotation.concurrent.ThreadSafe; import javax.net.ssl.HostnameVerifier; @@ -336,21 +333,12 @@ public interface ArangoDB extends ArangoSerdeAccessor { */ Collection getQueryOptimizerRules(); - /** - * Attention: Please do not use! - * - * @param cursorInitializer - * @return ArangoDB - */ - ArangoDB _setCursorInitializer(ArangoCursorInitializer cursorInitializer); - /** * Builder class to build an instance of {@link ArangoDB}. * * @author Mark Vollmary */ class Builder extends InternalArangoDBBuilder { - private static final Logger logger = LoggerFactory.getLogger(Builder.class); private static final String PROPERTY_KEY_PROTOCOL = "arangodb.protocol"; protected Protocol protocol; diff --git a/src/main/java/com/arangodb/internal/ArangoDBImpl.java b/src/main/java/com/arangodb/internal/ArangoDBImpl.java index de0a92c7b..e37cd9596 100644 --- a/src/main/java/com/arangodb/internal/ArangoDBImpl.java +++ b/src/main/java/com/arangodb/internal/ArangoDBImpl.java @@ -36,7 +36,6 @@ import com.arangodb.model.LogOptions; import com.arangodb.model.UserCreateOptions; import com.arangodb.model.UserUpdateOptions; -import com.arangodb.util.ArangoCursorInitializer; import com.arangodb.velocystream.Request; import com.arangodb.velocystream.Response; import org.slf4j.Logger; @@ -55,7 +54,6 @@ public class ArangoDBImpl extends InternalArangoDB implement private static final Logger LOGGER = LoggerFactory.getLogger(ArangoDBImpl.class); private final CommunicationProtocol cp; private final HostHandler hostHandler; - private ArangoCursorInitializer cursorInitializer; public ArangoDBImpl(final VstCommunicationSync.Builder vstBuilder, final HttpCommunication.Builder httpBuilder, final InternalSerde util, final Protocol protocol, final HostResolver hostResolver, @@ -135,7 +133,7 @@ public ArangoDatabase db() { @Override public ArangoDatabase db(final DbName dbName) { - return new ArangoDatabaseImpl(this, dbName).setCursorInitializer(cursorInitializer); + return new ArangoDatabaseImpl(this, dbName); } @Override @@ -265,10 +263,4 @@ public Collection getQueryOptimizerRules() { return executor.execute(getQueryOptimizerRulesRequest(), SerdeUtils.constructListType(QueryOptimizerRule.class)); } - @Override - public ArangoDBImpl _setCursorInitializer(final ArangoCursorInitializer cursorInitializer) { - this.cursorInitializer = cursorInitializer; - return this; - } - } diff --git a/src/main/java/com/arangodb/internal/ArangoDatabaseImpl.java b/src/main/java/com/arangodb/internal/ArangoDatabaseImpl.java index 91bdfa1c7..f54788c50 100644 --- a/src/main/java/com/arangodb/internal/ArangoDatabaseImpl.java +++ b/src/main/java/com/arangodb/internal/ArangoDatabaseImpl.java @@ -31,7 +31,6 @@ import com.arangodb.model.arangosearch.AnalyzerDeleteOptions; import com.arangodb.model.arangosearch.ArangoSearchCreateOptions; import com.arangodb.model.arangosearch.SearchAliasCreateOptions; -import com.arangodb.util.ArangoCursorInitializer; import com.arangodb.velocystream.Request; import java.util.Collection; @@ -47,8 +46,6 @@ public class ArangoDatabaseImpl extends InternalArangoDatabase implements ArangoDatabase { - private ArangoCursorInitializer cursorInitializer; - protected ArangoDatabaseImpl(final ArangoDBImpl arangoDB, final DbName name) { super(arangoDB, name); } @@ -216,9 +213,7 @@ public void close(final String id, Map meta) { } }; - return cursorInitializer != null ? - cursorInitializer.createInstance(this, execute, type, result) : - new ArangoCursorImpl<>(this, execute, type, result); + return new ArangoCursorImpl<>(this, execute, type, result); } @Override @@ -371,11 +366,6 @@ public void reloadRouting() { executor.execute(reloadRoutingRequest(), Void.class); } - protected ArangoDatabaseImpl setCursorInitializer(final ArangoCursorInitializer cursorInitializer) { - this.cursorInitializer = cursorInitializer; - return this; - } - @Override public ArangoRoute route(final String... path) { return new ArangoRouteImpl(this, String.join("/", path), Collections.emptyMap()); diff --git a/src/main/java/com/arangodb/util/ArangoCursorInitializer.java b/src/main/java/com/arangodb/util/ArangoCursorInitializer.java deleted file mode 100644 index b00721917..000000000 --- a/src/main/java/com/arangodb/util/ArangoCursorInitializer.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2017 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.util; - -import com.arangodb.ArangoCursor; -import com.arangodb.internal.ArangoCursorExecute; -import com.arangodb.internal.InternalArangoDatabase; -import com.arangodb.internal.cursor.entity.InternalCursorEntity; - -/** - * @author Mark Vollmary - */ -public interface ArangoCursorInitializer { - - ArangoCursor createInstance( - final InternalArangoDatabase db, - final ArangoCursorExecute execute, - final Class type, - final InternalCursorEntity result); - -} From 9cd9a06f98b0fcdb9adb1ddc8e9013bd1cc01048 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Tue, 18 Oct 2022 14:14:25 +0200 Subject: [PATCH 146/254] [DE-400] vertx webclient (#463) * vertx webclient * fixed CURLLogger * ttl and timeout * credentials refactoring * BenchmarkTest * ssl config * hostname verifier refactoring * removed apache httpclient * removed httpCookieSpec * case-insensitive headers --- ChangeLog.md | 1 + pom.xml | 49 +-- src/main/java/com/arangodb/ArangoDB.java | 33 +- .../com/arangodb/internal/ArangoExecutor.java | 4 +- .../arangodb/internal/ArangoRequestParam.java | 4 +- .../internal/InternalArangoCollection.java | 2 +- .../internal/InternalArangoDBBuilder.java | 22 +- .../internal/InternalArangoDatabase.java | 10 +- .../internal/cursor/ArangoCursorImpl.java | 2 +- .../cursor/entity/InternalCursorEntity.java | 15 +- .../arangodb/internal/http/CURLLogger.java | 16 +- .../internal/http/HttpConnection.java | 375 +++++++++--------- .../internal/http/HttpConnectionFactory.java | 11 +- .../internal/http/HttpDeleteWithBody.java | 43 -- .../internal/serde/InternalDeserializers.java | 2 +- .../com/arangodb/internal/util/IOUtils.java | 76 ---- .../arangodb/internal/util/RequestUtils.java | 4 +- .../arangodb/internal/util/ResponseUtils.java | 6 +- .../com/arangodb/velocystream/Request.java | 23 +- .../com/arangodb/velocystream/Response.java | 24 +- .../arangodb/example/ssl/SslExampleTest.java | 3 +- src/test/java/perf/Benchmark.java | 123 ++++++ src/test/java/perf/SyncBenchmarkTest.java | 60 +++ 23 files changed, 463 insertions(+), 445 deletions(-) delete mode 100644 src/main/java/com/arangodb/internal/http/HttpDeleteWithBody.java delete mode 100644 src/main/java/com/arangodb/internal/util/IOUtils.java create mode 100644 src/test/java/perf/Benchmark.java create mode 100644 src/test/java/perf/SyncBenchmarkTest.java diff --git a/ChangeLog.md b/ChangeLog.md index e45f5540a..0b27cc0df 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -27,6 +27,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) a - `BaseDocument` and `BaseEdgeDocument` are now `final` - `BaseDocument#getProperties()` and `BaseEdgeDocument#getProperties()` return now an unmodifiable map - changed API method signatures removing throw declarations like: `throws ArangoDBException` (unchecked exception) +- removed passwords from debug level requests logs ### Removed diff --git a/pom.xml b/pom.xml index db102d8d0..b8d177cb9 100644 --- a/pom.xml +++ b/pom.xml @@ -310,10 +310,7 @@ org.slf4j slf4j-api - - - org.apache.httpcomponents - httpclient + 1.7.36 com.fasterxml.jackson.core @@ -327,9 +324,14 @@ com.fasterxml.jackson.core jackson-annotations + + io.vertx + vertx-web-client + com.arangodb jackson-dataformat-velocypack + 3.0.1 true @@ -346,6 +348,7 @@ ch.qos.logback logback-classic + 1.2.11 test @@ -399,39 +402,11 @@ pom - com.arangodb - jackson-dataformat-velocypack - 3.0.1 - - - org.apache.httpcomponents - httpclient - 4.5.13 - - - org.apache.httpcomponents - httpcore - 4.4.15 - - - commons-codec - commons-codec - 1.15 - - - commons-logging - commons-logging - 1.2 - - - org.slf4j - slf4j-api - 1.7.36 - - - ch.qos.logback - logback-classic - 1.2.11 + io.vertx + vertx-stack-depchain + 4.3.4 + pom + import org.junit diff --git a/src/main/java/com/arangodb/ArangoDB.java b/src/main/java/com/arangodb/ArangoDB.java index 3983b7b55..fc9eb6d3f 100644 --- a/src/main/java/com/arangodb/ArangoDB.java +++ b/src/main/java/com/arangodb/ArangoDB.java @@ -40,10 +40,8 @@ import com.arangodb.serde.JacksonSerde; import com.arangodb.velocystream.Request; import com.arangodb.velocystream.Response; -import org.apache.http.client.HttpRequestRetryHandler; import javax.annotation.concurrent.ThreadSafe; -import javax.net.ssl.HostnameVerifier; import javax.net.ssl.SSLContext; import java.io.InputStream; import java.util.Collection; @@ -351,7 +349,7 @@ private static Protocol loadProtocol(final Properties properties, final Protocol return Protocol.valueOf( getProperty(properties, PROPERTY_KEY_PROTOCOL, currentValue, ArangoDefaults.DEFAULT_NETWORK_PROTOCOL) - .toUpperCase(Locale.ENGLISH)); + .toUpperCase(Locale.ROOT)); } @Override @@ -450,30 +448,13 @@ public Builder sslContext(final SSLContext sslContext) { } /** - * Sets the {@link javax.net.ssl.HostnameVerifier} to be used when using ssl with http protocol. + * Set whether hostname verification is enabled * - * @param hostnameVerifier HostnameVerifier to be used + * @param verifyHost {@code true} if enabled * @return {@link ArangoDB.Builder} */ - public Builder hostnameVerifier(final HostnameVerifier hostnameVerifier) { - setHostnameVerifier(hostnameVerifier); - return this; - } - - /** - * Sets the {@link HttpRequestRetryHandler} to be used when using http protocol. - * - * @param httpRequestRetryHandler HttpRequestRetryHandler to be used - * @return {@link ArangoDB.Builder} - *

    - *

    - * NOTE: - * Some ArangoDB HTTP endpoints do not honor RFC-2616 HTTP 1.1 specification in respect to - * 9.1 Safe and Idempotent Methods. - * Please refer to HTTP API Documentation for details. - */ - public Builder httpRequestRetryHandler(final HttpRequestRetryHandler httpRequestRetryHandler) { - setHttpRequestRetryHandler(httpRequestRetryHandler); + public Builder verifyHost(final Boolean verifyHost) { + setVerifyHost(verifyHost); return this; } @@ -621,8 +602,8 @@ public ArangoDB build() { final ConnectionFactory connectionFactory = (protocol == null || Protocol.VST == protocol) ? new VstConnectionFactorySync(host, timeout, connectionTtl, keepAliveInterval, useSsl, sslContext) - : new HttpConnectionFactory(timeout, user, password, useSsl, sslContext, hostnameVerifier, serde, - protocol, connectionTtl, httpCookieSpec, httpRequestRetryHandler); + : new HttpConnectionFactory(timeout, user, password, useSsl, sslContext, verifyHost, serde, + protocol, connectionTtl); final Collection hostList = createHostList(max, connectionFactory); final HostResolver hostResolver = createHostResolver(hostList, max, connectionFactory); diff --git a/src/main/java/com/arangodb/internal/ArangoExecutor.java b/src/main/java/com/arangodb/internal/ArangoExecutor.java index 711308012..37917dad8 100644 --- a/src/main/java/com/arangodb/internal/ArangoExecutor.java +++ b/src/main/java/com/arangodb/internal/ArangoExecutor.java @@ -48,14 +48,14 @@ protected T createResult(final Type type, final Response response) { } protected final void interceptResponse(Response response) { - String queueTime = response.getMeta().get("X-Arango-Queue-Time-Seconds"); + String queueTime = response.getMeta("X-Arango-Queue-Time-Seconds"); if (queueTime != null) { qtMetrics.add(Double.parseDouble(queueTime)); } } protected final Request interceptRequest(Request request) { - request.putHeaderParam("X-Arango-Queue-Time-Seconds", timeoutS); + request.putHeaderParam("x-arango-queue-time-seconds", timeoutS); return request; } diff --git a/src/main/java/com/arangodb/internal/ArangoRequestParam.java b/src/main/java/com/arangodb/internal/ArangoRequestParam.java index 7db9e599b..16c497994 100644 --- a/src/main/java/com/arangodb/internal/ArangoRequestParam.java +++ b/src/main/java/com/arangodb/internal/ArangoRequestParam.java @@ -28,8 +28,8 @@ public final class ArangoRequestParam { public static final String SYSTEM = "_system"; public static final String DATABASE = "database"; public static final String WAIT_FOR_SYNC = "waitForSync"; - public static final String IF_NONE_MATCH = "If-None-Match"; - public static final String IF_MATCH = "If-Match"; + public static final String IF_NONE_MATCH = "if-none-match"; + public static final String IF_MATCH = "if-match"; public static final String KEEP_NULL = "keepNull"; private ArangoRequestParam() { diff --git a/src/main/java/com/arangodb/internal/InternalArangoCollection.java b/src/main/java/com/arangodb/internal/InternalArangoCollection.java index ea5d283ce..fdc1f24c1 100644 --- a/src/main/java/com/arangodb/internal/InternalArangoCollection.java +++ b/src/main/java/com/arangodb/internal/InternalArangoCollection.java @@ -196,7 +196,7 @@ protected ResponseDeserializer> getDocumentsResponseD final Class type, final DocumentReadOptions options) { return response -> { final MultiDocumentEntity multiDocument = new MultiDocumentEntity<>(); - boolean potentialDirtyRead = Boolean.parseBoolean(response.getMeta().get("X-Arango-Potential-Dirty-Read")); + boolean potentialDirtyRead = Boolean.parseBoolean(response.getMeta("X-Arango-Potential-Dirty-Read")); multiDocument.setPotentialDirtyRead(potentialDirtyRead); final Collection docs = new ArrayList<>(); final Collection errors = new ArrayList<>(); diff --git a/src/main/java/com/arangodb/internal/InternalArangoDBBuilder.java b/src/main/java/com/arangodb/internal/InternalArangoDBBuilder.java index 63ba8e603..38e6b6441 100644 --- a/src/main/java/com/arangodb/internal/InternalArangoDBBuilder.java +++ b/src/main/java/com/arangodb/internal/InternalArangoDBBuilder.java @@ -26,11 +26,9 @@ import com.arangodb.internal.net.*; import com.arangodb.internal.util.HostUtils; import com.arangodb.serde.ArangoSerde; -import org.apache.http.client.HttpRequestRetryHandler; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import javax.net.ssl.HostnameVerifier; import javax.net.ssl.SSLContext; import java.io.IOException; import java.io.InputStream; @@ -52,7 +50,6 @@ public abstract class InternalArangoDBBuilder { private static final String PROPERTY_KEY_PASSWORD = "arangodb.password"; private static final String PROPERTY_KEY_JWT = "arangodb.jwt"; private static final String PROPERTY_KEY_USE_SSL = "arangodb.usessl"; - private static final String PROPERTY_KEY_COOKIE_SPEC = "arangodb.httpCookieSpec"; private static final String PROPERTY_KEY_V_STREAM_CHUNK_CONTENT_SIZE = "arangodb.chunksize"; private static final String PROPERTY_KEY_MAX_CONNECTIONS = "arangodb.connections.max"; private static final String PROPERTY_KEY_CONNECTION_TTL = "arangodb.connections.ttl"; @@ -70,10 +67,8 @@ public abstract class InternalArangoDBBuilder { protected String password; protected String jwt; protected Boolean useSsl; - protected String httpCookieSpec; - protected HttpRequestRetryHandler httpRequestRetryHandler; protected SSLContext sslContext; - protected HostnameVerifier hostnameVerifier; + protected Boolean verifyHost; protected Integer chunksize; protected Integer maxConnections; protected Long connectionTtl; @@ -151,10 +146,6 @@ private static Boolean loadUseSsl(final Properties properties, final Boolean cur getProperty(properties, PROPERTY_KEY_USE_SSL, currentValue, ArangoDefaults.DEFAULT_USE_SSL)); } - private static String loadhttpCookieSpec(final Properties properties, final String currentValue) { - return getProperty(properties, PROPERTY_KEY_COOKIE_SPEC, currentValue, ""); - } - private static Integer loadChunkSize(final Properties properties, final Integer currentValue) { return Integer.parseInt(getProperty(properties, PROPERTY_KEY_V_STREAM_CHUNK_CONTENT_SIZE, currentValue, ArangoDefaults.CHUNK_DEFAULT_CONTENT_SIZE)); @@ -196,7 +187,7 @@ private static LoadBalancingStrategy loadLoadBalancingStrategy( final Properties properties, final LoadBalancingStrategy currentValue) { return LoadBalancingStrategy.valueOf(getProperty(properties, PROPERTY_KEY_LOAD_BALANCING_STRATEGY, currentValue, - ArangoDefaults.DEFAULT_LOAD_BALANCING_STRATEGY).toUpperCase(Locale.ENGLISH)); + ArangoDefaults.DEFAULT_LOAD_BALANCING_STRATEGY).toUpperCase(Locale.ROOT)); } protected static String getProperty( @@ -245,7 +236,6 @@ protected void loadProperties(final Properties properties) { password = loadPassword(properties, password); jwt = loadJwt(properties, jwt); useSsl = loadUseSsl(properties, useSsl); - httpCookieSpec = loadhttpCookieSpec(properties, httpCookieSpec); chunksize = loadChunkSize(properties, chunksize); maxConnections = loadMaxConnections(properties, maxConnections); connectionTtl = loadConnectionTtl(properties, connectionTtl); @@ -284,12 +274,8 @@ protected void setSslContext(final SSLContext sslContext) { this.sslContext = sslContext; } - protected void setHostnameVerifier(final HostnameVerifier hostnameVerifier) { - this.hostnameVerifier = hostnameVerifier; - } - - protected void setHttpRequestRetryHandler(final HttpRequestRetryHandler httpRequestRetryHandler) { - this.httpRequestRetryHandler = httpRequestRetryHandler; + protected void setVerifyHost(final Boolean verifyHost) { + this.verifyHost = verifyHost; } protected void setChunksize(final Integer chunksize) { diff --git a/src/main/java/com/arangodb/internal/InternalArangoDatabase.java b/src/main/java/com/arangodb/internal/InternalArangoDatabase.java index c1da4db4d..edfe70b70 100644 --- a/src/main/java/com/arangodb/internal/InternalArangoDatabase.java +++ b/src/main/java/com/arangodb/internal/InternalArangoDatabase.java @@ -162,10 +162,7 @@ protected Request queryRequest(final String query, final Map bin protected Request queryNextRequest(final String id, final AqlQueryOptions options, Map meta) { final Request request = request(dbName, RequestType.POST, PATH_API_CURSOR, id); - - if (meta != null) { - request.getHeaderParam().putAll(meta); - } + request.putHeaderParams(meta); final AqlQueryOptions opt = options != null ? options : new AqlQueryOptions(); @@ -179,10 +176,7 @@ protected Request queryNextRequest(final String id, final AqlQueryOptions option protected Request queryCloseRequest(final String id, final AqlQueryOptions options, Map meta) { final Request request = request(dbName, RequestType.DELETE, PATH_API_CURSOR, id); - - if (meta != null) { - request.getHeaderParam().putAll(meta); - } + request.putHeaderParams(meta); final AqlQueryOptions opt = options != null ? options : new AqlQueryOptions(); diff --git a/src/main/java/com/arangodb/internal/cursor/ArangoCursorImpl.java b/src/main/java/com/arangodb/internal/cursor/ArangoCursorImpl.java index 8f3ac6f0a..cff3dd4b5 100644 --- a/src/main/java/com/arangodb/internal/cursor/ArangoCursorImpl.java +++ b/src/main/java/com/arangodb/internal/cursor/ArangoCursorImpl.java @@ -51,7 +51,7 @@ public ArangoCursorImpl(final InternalArangoDatabase db, final ArangoCurso this.type = type; iterator = createIterator(this, db, execute, result); id = result.getId(); - this.isPontentialDirtyRead = Boolean.parseBoolean(result.getMeta().get("X-Arango-Potential-Dirty-Read")); + this.isPontentialDirtyRead = Boolean.parseBoolean(result.getMeta().get("x-arango-potential-dirty-read")); } protected ArangoCursorIterator createIterator( diff --git a/src/main/java/com/arangodb/internal/cursor/entity/InternalCursorEntity.java b/src/main/java/com/arangodb/internal/cursor/entity/InternalCursorEntity.java index 1ab557b49..abaa5ad41 100644 --- a/src/main/java/com/arangodb/internal/cursor/entity/InternalCursorEntity.java +++ b/src/main/java/com/arangodb/internal/cursor/entity/InternalCursorEntity.java @@ -26,7 +26,10 @@ import java.util.Collection; import java.util.Collections; +import java.util.HashMap; import java.util.Map; +import java.util.function.Function; +import java.util.stream.Collectors; /** * @author Mark Vollmary @@ -89,22 +92,24 @@ public JsonNode getResult() { return result; } + @Override public Map getMeta() { if (meta == null) return Collections.emptyMap(); - return meta; + return Collections.unmodifiableMap(meta); } + @Override public void setMeta(Map meta) { - this.meta = cleanupMeta(meta); + this.meta = cleanupMeta(new HashMap<>(meta)); } /** * @return remove not allowed (valid storable) meta information */ public Map cleanupMeta(Map meta) { - meta.remove("Content-Length"); - meta.remove("Transfer-Encoding"); - meta.remove("X-Arango-Queue-Time-Seconds"); + meta.remove("content-length"); + meta.remove("transfer-encoding"); + meta.remove("x-arango-queue-time-seconds"); return meta; } diff --git a/src/main/java/com/arangodb/internal/http/CURLLogger.java b/src/main/java/com/arangodb/internal/http/CURLLogger.java index 31e4a29a9..b2e72418b 100644 --- a/src/main/java/com/arangodb/internal/http/CURLLogger.java +++ b/src/main/java/com/arangodb/internal/http/CURLLogger.java @@ -23,7 +23,6 @@ import com.arangodb.internal.serde.InternalSerde; import com.arangodb.velocystream.Request; import com.arangodb.velocystream.RequestType; -import org.apache.http.auth.Credentials; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -40,10 +39,9 @@ private CURLLogger() { } public static void log( - final String url, + final String baseUrl, + final String path, final Request request, - final Credentials credentials, - final String jwt, final InternalSerde util) { final RequestType requestType = request.getRequestType(); final boolean includeBody = (requestType == RequestType.POST || requestType == RequestType.PUT @@ -54,23 +52,17 @@ public static void log( buffer.append("cat <<-___EOB___ | "); } buffer.append("curl -X ").append(requestType); + // FIXME: add --http2 in case protocol is HTTP/2 buffer.append(" --dump -"); if (request.getHeaderParam().size() > 0) { for (final Entry header : request.getHeaderParam().entrySet()) { buffer.append(" -H '").append(header.getKey()).append(":").append(header.getValue()).append("'"); } } - if (credentials != null) { - buffer.append(" -u ").append(credentials.getUserPrincipal().getName()).append(":") - .append(credentials.getPassword()); - } - if (jwt != null) { - buffer.append(" -H ").append("'Authorization: Bearer ").append(jwt).append("'"); - } if (includeBody) { buffer.append(" -d @-"); } - buffer.append(" '").append(url).append("'"); + buffer.append(" '").append(baseUrl).append(path).append("'"); if (includeBody) { buffer.append("\n"); buffer.append(util.toJsonString(request.getBody())); diff --git a/src/main/java/com/arangodb/internal/http/HttpConnection.java b/src/main/java/com/arangodb/internal/http/HttpConnection.java index 69dbb4dd4..0303fc740 100644 --- a/src/main/java/com/arangodb/internal/http/HttpConnection.java +++ b/src/main/java/com/arangodb/internal/http/HttpConnection.java @@ -26,258 +26,257 @@ import com.arangodb.internal.net.Connection; import com.arangodb.internal.net.HostDescription; import com.arangodb.internal.serde.InternalSerde; -import com.arangodb.internal.util.IOUtils; import com.arangodb.internal.util.ResponseUtils; import com.arangodb.velocystream.Request; +import com.arangodb.velocystream.RequestType; import com.arangodb.velocystream.Response; -import org.apache.http.*; -import org.apache.http.auth.AuthenticationException; -import org.apache.http.auth.Credentials; -import org.apache.http.auth.UsernamePasswordCredentials; -import org.apache.http.client.HttpRequestRetryHandler; -import org.apache.http.client.config.RequestConfig; -import org.apache.http.client.methods.*; -import org.apache.http.client.utils.URLEncodedUtils; -import org.apache.http.config.RegistryBuilder; -import org.apache.http.conn.ConnectionKeepAliveStrategy; -import org.apache.http.conn.socket.ConnectionSocketFactory; -import org.apache.http.conn.socket.PlainConnectionSocketFactory; -import org.apache.http.conn.ssl.SSLConnectionSocketFactory; -import org.apache.http.entity.ByteArrayEntity; -import org.apache.http.entity.ContentType; -import org.apache.http.impl.auth.BasicScheme; -import org.apache.http.impl.client.CloseableHttpClient; -import org.apache.http.impl.client.DefaultHttpRequestRetryHandler; -import org.apache.http.impl.client.HttpClientBuilder; -import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; -import org.apache.http.message.BasicHeaderElementIterator; -import org.apache.http.message.BasicNameValuePair; -import org.apache.http.protocol.HTTP; -import org.apache.http.ssl.SSLContexts; +import io.netty.handler.ssl.ApplicationProtocolConfig; +import io.netty.handler.ssl.ClientAuth; +import io.netty.handler.ssl.IdentityCipherSuiteFilter; +import io.netty.handler.ssl.JdkSslContext; +import io.vertx.core.Vertx; +import io.vertx.core.VertxOptions; +import io.vertx.core.buffer.Buffer; +import io.vertx.core.http.HttpHeaders; +import io.vertx.core.http.HttpMethod; +import io.vertx.core.http.HttpVersion; +import io.vertx.core.net.JdkSSLEngineOptions; +import io.vertx.core.spi.tls.SslContextFactory; +import io.vertx.ext.auth.authentication.TokenCredentials; +import io.vertx.ext.auth.authentication.UsernamePasswordCredentials; +import io.vertx.ext.web.client.HttpRequest; +import io.vertx.ext.web.client.HttpResponse; +import io.vertx.ext.web.client.WebClient; +import io.vertx.ext.web.client.WebClientOptions; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import javax.net.ssl.HostnameVerifier; import javax.net.ssl.SSLContext; import java.io.IOException; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; +import java.security.NoSuchAlgorithmException; +import java.util.Iterator; import java.util.Map.Entry; +import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; -import static org.apache.http.HttpHeaders.AUTHORIZATION; /** * @author Mark Vollmary */ public class HttpConnection implements Connection { - private static final Logger LOGGER = LoggerFactory.getLogger(HttpCommunication.class); - private static final ContentType CONTENT_TYPE_APPLICATION_JSON_UTF8 = ContentType.create("application/json", - "utf-8"); - private static final ContentType CONTENT_TYPE_VPACK = ContentType.create("application/x-velocypack"); - private final PoolingHttpClientConnectionManager cm; - private final CloseableHttpClient client; - private final String user; - private final String password; + private static final String CONTENT_TYPE_APPLICATION_JSON_UTF8 = "application/json; charset=utf-8"; + private static final String CONTENT_TYPE_VPACK = "application/x-velocypack"; + private static final AtomicInteger THREAD_COUNT = new AtomicInteger(); private final InternalSerde util; - private final Boolean useSsl; + private final String baseUrl; private final Protocol contentType; - private final HostDescription host; - private volatile String jwt = null; + private volatile String auth; + private final WebClient client; + private final Integer timeout; + private final Vertx vertx; private HttpConnection(final HostDescription host, final Integer timeout, final String user, final String password, - final Boolean useSsl, final SSLContext sslContext, final HostnameVerifier hostnameVerifier - , final InternalSerde util, final Protocol contentType, - final Long ttl, final String httpCookieSpec, - final HttpRequestRetryHandler httpRequestRetryHandler) { + final Boolean useSsl, final SSLContext sslContext, final Boolean verifyHost, + final InternalSerde util, final Protocol contentType, final Long ttl) { super(); - this.host = host; - this.user = user; - this.password = password; - this.useSsl = useSsl; this.util = util; this.contentType = contentType; - final RegistryBuilder registryBuilder = RegistryBuilder - .create(); + this.timeout = timeout; + baseUrl = buildBaseUrl(host, useSsl); + auth = new UsernamePasswordCredentials(user, password != null ? password : "").toHttpAuthorization(); + vertx = Vertx.vertx(new VertxOptions().setPreferNativeTransport(true).setEventLoopPoolSize(1)); + vertx.runOnContext(e -> Thread.currentThread().setName("adb-eventloop-" + THREAD_COUNT.getAndIncrement())); + + int _ttl = ttl == null ? 0 : Math.toIntExact(ttl / 1000); + + WebClientOptions webClientOptions = new WebClientOptions() + .setConnectTimeout(timeout) + .setIdleTimeoutUnit(TimeUnit.MILLISECONDS) + .setIdleTimeout(timeout) + .setKeepAliveTimeout(_ttl) + .setHttp2KeepAliveTimeout(_ttl) + .setUserAgentEnabled(false) + .setFollowRedirects(false) + .setLogActivity(true) + .setKeepAlive(true) + .setTcpKeepAlive(true) + .setPipelining(true) + .setReuseAddress(true) + .setReusePort(true) + .setHttp2ClearTextUpgrade(false) + //TODO: allow configuring HTTP_2 or HTTP_1_1 +// .setProtocolVersion(HttpVersion.HTTP_1_1) + .setProtocolVersion(HttpVersion.HTTP_2) + .setUseAlpn(true) + .setDefaultHost(host.getHost()) + .setDefaultPort(host.getPort()); + + if (Boolean.TRUE.equals(useSsl)) { - registryBuilder.register("https", new SSLConnectionSocketFactory( - sslContext != null ? sslContext : SSLContexts.createSystemDefault(), - hostnameVerifier != null ? hostnameVerifier : - SSLConnectionSocketFactory.getDefaultHostnameVerifier() - )); - } else { - registryBuilder.register("http", new PlainConnectionSocketFactory()); - } - cm = new PoolingHttpClientConnectionManager(registryBuilder.build()); - cm.setDefaultMaxPerRoute(1); - cm.setMaxTotal(1); - final RequestConfig.Builder requestConfig = RequestConfig.custom(); - if (timeout != null && timeout >= 0) { - requestConfig.setConnectTimeout(timeout); - requestConfig.setConnectionRequestTimeout(timeout); - requestConfig.setSocketTimeout(timeout); - } + SSLContext ctx; + if (sslContext != null) { + ctx = sslContext; + } else { + try { + ctx = SSLContext.getDefault(); + } catch (NoSuchAlgorithmException e) { + throw new ArangoDBException(e); + } + } - if (httpCookieSpec != null && httpCookieSpec.length() > 1) { - requestConfig.setCookieSpec(httpCookieSpec); + webClientOptions + .setSsl(true) + .setVerifyHost(verifyHost != null ? verifyHost : true) + .setJdkSslEngineOptions(new JdkSSLEngineOptions() { + @Override + public JdkSSLEngineOptions copy() { + return this; + } + + @Override + public SslContextFactory sslContextFactory() { + return () -> new JdkSslContext( + ctx, + true, + null, + IdentityCipherSuiteFilter.INSTANCE, + ApplicationProtocolConfig.DISABLED, + ClientAuth.NONE, + null, + false + ); + } + }); } - final ConnectionKeepAliveStrategy keepAliveStrategy = - (response, context) -> HttpConnection.this.getKeepAliveDuration(response); - final HttpClientBuilder builder = HttpClientBuilder.create().setDefaultRequestConfig(requestConfig.build()) - .setConnectionManager(cm).setKeepAliveStrategy(keepAliveStrategy) - .setRetryHandler(httpRequestRetryHandler != null ? httpRequestRetryHandler : - new DefaultHttpRequestRetryHandler()); - if (ttl != null) { - builder.setConnectionTimeToLive(ttl, TimeUnit.MILLISECONDS); - } - client = builder.build(); + client = WebClient.create(vertx, webClientOptions); } - private static String buildUrl(final String baseUrl, final Request request) { - StringBuilder sb = new StringBuilder().append(baseUrl); + private static String buildUrl(final Request request) { + StringBuilder sb = new StringBuilder(); DbName dbName = request.getDbName(); if (dbName != null && !dbName.get().isEmpty()) { sb.append("/_db/").append(dbName.getEncoded()); } sb.append(request.getRequest()); if (!request.getQueryParam().isEmpty()) { - if (request.getRequest().contains("?")) { - sb.append("&"); - } else { - sb.append("?"); - } - final String paramString = URLEncodedUtils.format(toList(request.getQueryParam()), "utf-8"); - sb.append(paramString); - } - return sb.toString(); - } + sb.append("?"); - private static List toList(final Map parameters) { - final ArrayList paramList = new ArrayList<>(parameters.size()); - for (final Entry param : parameters.entrySet()) { - if (param.getValue() != null) { - paramList.add(new BasicNameValuePair(param.getKey(), param.getValue())); + try { + for (Iterator> iterator = request.getQueryParam().entrySet().iterator(); iterator.hasNext(); ) { + Entry param = iterator.next(); + if (param.getValue() != null) { + sb.append(URLEncoder.encode(param.getKey(), StandardCharsets.UTF_8.toString())); + sb.append("="); + sb.append(URLEncoder.encode(param.getValue(), StandardCharsets.UTF_8.toString())); + if (iterator.hasNext()) { + sb.append("&"); + } + } + } + } catch (UnsupportedEncodingException e) { + throw new RuntimeException(e); } - } - return paramList; - } - private static void addHeader(final Request request, final HttpRequestBase httpRequest) { - for (final Entry header : request.getHeaderParam().entrySet()) { - httpRequest.addHeader(header.getKey(), header.getValue()); } + return sb.toString(); } - private long getKeepAliveDuration(final HttpResponse response) { - final HeaderElementIterator it = new BasicHeaderElementIterator(response.headerIterator(HTTP.CONN_KEEP_ALIVE)); - while (it.hasNext()) { - final HeaderElement he = it.nextElement(); - final String param = he.getName(); - final String value = he.getValue(); - if (value != null && "timeout".equalsIgnoreCase(param)) { - try { - return Long.parseLong(value) * 1000L; - } catch (final NumberFormatException ignore) { - } - } + private static void addHeader(final Request request, final HttpRequest httpRequest) { + for (final Entry header : request.getHeaderParam().entrySet()) { + httpRequest.putHeader(header.getKey(), header.getValue()); } - return 30L * 1000L; } @Override public void close() throws IOException { - cm.shutdown(); client.close(); + vertx.close(); } - private HttpRequestBase buildHttpRequestBase(final Request request, final String url) { - final HttpRequestBase httpRequest; - switch (request.getRequestType()) { + private HttpMethod requestTypeToHttpMethod(RequestType requestType) { + switch (requestType) { case POST: - httpRequest = requestWithBody(new HttpPost(url), request); - break; + return HttpMethod.POST; case PUT: - httpRequest = requestWithBody(new HttpPut(url), request); - break; + return HttpMethod.PUT; case PATCH: - httpRequest = requestWithBody(new HttpPatch(url), request); - break; + return HttpMethod.PATCH; case DELETE: - httpRequest = requestWithBody(new HttpDeleteWithBody(url), request); - break; + return HttpMethod.DELETE; case HEAD: - httpRequest = new HttpHead(url); - break; + return HttpMethod.HEAD; case GET: default: - httpRequest = new HttpGet(url); - break; - } - return httpRequest; - } - - private HttpRequestBase requestWithBody(final HttpEntityEnclosingRequestBase httpRequest, final Request request) { - final byte[] body = request.getBody(); - if (body != null) { - if (contentType == Protocol.HTTP_VPACK) { - httpRequest.setEntity(new ByteArrayEntity(body, CONTENT_TYPE_VPACK)); - } else { - httpRequest.setEntity(new ByteArrayEntity(body, CONTENT_TYPE_APPLICATION_JSON_UTF8)); - } + return HttpMethod.GET; } - return httpRequest; } - private String buildBaseUrl(final HostDescription host) { + private String buildBaseUrl(HostDescription host, boolean useSsl) { return (Boolean.TRUE.equals(useSsl) ? "https://" : "http://") + host.getHost() + ":" + host.getPort(); } public Response execute(final Request request) throws IOException { - final String url = buildUrl(buildBaseUrl(host), request); - final HttpRequestBase httpRequest = buildHttpRequestBase(request, url); - httpRequest.setHeader("User-Agent", "Mozilla/5.0 (compatible; ArangoDB-JavaDriver/1.1; +http://mt.orz.at/)"); + String path = buildUrl(request); + HttpRequest httpRequest = client + .request(requestTypeToHttpMethod(request.getRequestType()), path) + .timeout(timeout); if (contentType == Protocol.HTTP_VPACK) { - httpRequest.setHeader("Accept", "application/x-velocypack"); + httpRequest.putHeader("Accept", "application/x-velocypack"); } addHeader(request, httpRequest); - Credentials credentials = null; - if (jwt != null) { - httpRequest.addHeader(AUTHORIZATION, "Bearer " + jwt); - } else if (user != null) { - credentials = new UsernamePasswordCredentials(user, password != null ? password : ""); - try { - httpRequest.addHeader(new BasicScheme().authenticate(credentials, httpRequest, null)); - } catch (final AuthenticationException e) { - throw new ArangoDBException(e); + httpRequest.putHeader(HttpHeaders.AUTHORIZATION.toString(), auth); + + if (LOGGER.isDebugEnabled()) { + CURLLogger.log(baseUrl, path, request, util); + } + + byte[] reqBody = request.getBody(); + Buffer buffer; + if (reqBody != null) { + buffer = Buffer.buffer(reqBody); + if (contentType == Protocol.HTTP_VPACK) { + httpRequest.putHeader(HttpHeaders.CONTENT_TYPE.toString(), CONTENT_TYPE_VPACK); + } else { + httpRequest.putHeader(HttpHeaders.CONTENT_TYPE.toString(), CONTENT_TYPE_APPLICATION_JSON_UTF8); } + } else { + buffer = Buffer.buffer(); } - if (LOGGER.isDebugEnabled()) { - CURLLogger.log(url, request, credentials, jwt, util); + HttpResponse bufferResponse; + try { + // FIXME: make async API + bufferResponse = httpRequest.sendBuffer(buffer).toCompletionStage().toCompletableFuture().get(); + } catch (InterruptedException | ExecutionException e) { + Throwable cause = e.getCause(); + if (cause instanceof IOException) { + throw (IOException) cause; + } else { + throw new ArangoDBException(e); + } } - Response response; - response = buildResponse(client.execute(httpRequest)); + Response response = buildResponse(bufferResponse); checkError(response); return response; } - public Response buildResponse(final CloseableHttpResponse httpResponse) - throws UnsupportedOperationException, IOException { + public Response buildResponse(final HttpResponse httpResponse) throws UnsupportedOperationException { final Response response = new Response(); - response.setResponseCode(httpResponse.getStatusLine().getStatusCode()); - final HttpEntity entity = httpResponse.getEntity(); - if (entity != null && entity.getContent() != null) { - final byte[] content = IOUtils.toByteArray(entity.getContent()); - if (content.length > 0) { - response.setBody(content); + response.setResponseCode(httpResponse.statusCode()); + Buffer body = httpResponse.body(); + if (body != null) { + byte[] bytes = body.getBytes(); + if (bytes.length > 0) { + response.setBody(bytes); } } - final Header[] headers = httpResponse.getAllHeaders(); - final Map meta = response.getMeta(); - for (final Header header : headers) { - meta.put(header.getName(), header.getValue()); + for (Entry header : httpResponse.headers()) { + response.putMeta(header.getKey(), header.getValue()); } return response; } @@ -288,7 +287,9 @@ protected void checkError(final Response response) { @Override public void setJwt(String jwt) { - this.jwt = jwt; + if (jwt != null) { + auth = new TokenCredentials(jwt).toHttpAuthorization(); + } } public static class Builder { @@ -296,14 +297,12 @@ public static class Builder { private String password; private InternalSerde util; private Boolean useSsl; - private String httpCookieSpec; private Protocol contentType; private HostDescription host; private Long ttl; private SSLContext sslContext; - private HostnameVerifier hostnameVerifier; + private Boolean verifyHost; private Integer timeout; - private HttpRequestRetryHandler httpRequestRetryHandler; public Builder user(final String user) { this.user = user; @@ -325,11 +324,6 @@ public Builder useSsl(final Boolean useSsl) { return this; } - public Builder httpCookieSpec(String httpCookieSpec) { - this.httpCookieSpec = httpCookieSpec; - return this; - } - public Builder contentType(final Protocol contentType) { this.contentType = contentType; return this; @@ -350,8 +344,8 @@ public Builder sslContext(final SSLContext sslContext) { return this; } - public Builder hostnameVerifier(final HostnameVerifier hostnameVerifier) { - this.hostnameVerifier = hostnameVerifier; + public Builder verifyHost(final Boolean verifyHost) { + this.verifyHost = verifyHost; return this; } @@ -360,14 +354,9 @@ public Builder timeout(final Integer timeout) { return this; } - public Builder httpRequestRetryHandler(final HttpRequestRetryHandler httpRequestRetryHandler) { - this.httpRequestRetryHandler = httpRequestRetryHandler; - return this; - } - public HttpConnection build() { - return new HttpConnection(host, timeout, user, password, useSsl, sslContext, hostnameVerifier, util, - contentType, ttl, httpCookieSpec, httpRequestRetryHandler); + return new HttpConnection(host, timeout, user, password, useSsl, sslContext, verifyHost, util, + contentType, ttl); } } diff --git a/src/main/java/com/arangodb/internal/http/HttpConnectionFactory.java b/src/main/java/com/arangodb/internal/http/HttpConnectionFactory.java index d39d5375a..5e0abc74b 100644 --- a/src/main/java/com/arangodb/internal/http/HttpConnectionFactory.java +++ b/src/main/java/com/arangodb/internal/http/HttpConnectionFactory.java @@ -25,9 +25,7 @@ import com.arangodb.internal.net.ConnectionFactory; import com.arangodb.internal.net.HostDescription; import com.arangodb.internal.serde.InternalSerde; -import org.apache.http.client.HttpRequestRetryHandler; -import javax.net.ssl.HostnameVerifier; import javax.net.ssl.SSLContext; /** @@ -38,13 +36,12 @@ public class HttpConnectionFactory implements ConnectionFactory { private final HttpConnection.Builder builder; public HttpConnectionFactory(final Integer timeout, final String user, final String password, final Boolean useSsl, - final SSLContext sslContext, final HostnameVerifier hostnameVerifier, - final InternalSerde util, final Protocol protocol, final Long connectionTtl, - final String httpCookieSpec, final HttpRequestRetryHandler httpRequestRetryHandler) { + final SSLContext sslContext, final Boolean verifyHost, + final InternalSerde util, final Protocol protocol, final Long connectionTtl) { super(); builder = new HttpConnection.Builder().timeout(timeout).user(user).password(password).useSsl(useSsl) - .sslContext(sslContext).hostnameVerifier(hostnameVerifier).serializationUtil(util).contentType(protocol) - .ttl(connectionTtl).httpCookieSpec(httpCookieSpec).httpRequestRetryHandler(httpRequestRetryHandler); + .sslContext(sslContext).verifyHost(verifyHost).serializationUtil(util).contentType(protocol) + .ttl(connectionTtl); } diff --git a/src/main/java/com/arangodb/internal/http/HttpDeleteWithBody.java b/src/main/java/com/arangodb/internal/http/HttpDeleteWithBody.java deleted file mode 100644 index 080e01974..000000000 --- a/src/main/java/com/arangodb/internal/http/HttpDeleteWithBody.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.internal.http; - -import org.apache.http.client.methods.HttpEntityEnclosingRequestBase; - -import java.net.URI; - -/** - * @author Mark Vollmary - */ -public class HttpDeleteWithBody extends HttpEntityEnclosingRequestBase { - public final static String METHOD_NAME = "DELETE"; - - public HttpDeleteWithBody(final String uri) { - super(); - setURI(URI.create(uri)); - } - - @Override - public String getMethod() { - return METHOD_NAME; - } - -} diff --git a/src/main/java/com/arangodb/internal/serde/InternalDeserializers.java b/src/main/java/com/arangodb/internal/serde/InternalDeserializers.java index 6abb792ce..d99449a64 100644 --- a/src/main/java/com/arangodb/internal/serde/InternalDeserializers.java +++ b/src/main/java/com/arangodb/internal/serde/InternalDeserializers.java @@ -82,7 +82,7 @@ public Response deserialize(final JsonParser p, final DeserializationContext ctx response.setType(it.next().intValue()); response.setResponseCode(it.next().intValue()); if (it.hasNext()) { - response.setMeta(readTreeAsValue(p, ctxt, it.next(), Map.class)); + response.putMetas(readTreeAsValue(p, ctxt, it.next(), Map.class)); } return response; } diff --git a/src/main/java/com/arangodb/internal/util/IOUtils.java b/src/main/java/com/arangodb/internal/util/IOUtils.java deleted file mode 100644 index c2985c4f6..000000000 --- a/src/main/java/com/arangodb/internal/util/IOUtils.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.internal.util; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.*; - -/** - * @author Mark Vollmary - */ -public final class IOUtils { - - private static final Logger LOGGER = LoggerFactory.getLogger(IOUtils.class); - - private IOUtils() { - } - - public static String toString(final InputStream input) throws IOException { - return toString(input, "utf-8"); - } - - public static String toString(final InputStream input, final String encode) throws IOException { - try { - final StringBuilder buffer = new StringBuilder(8012); - final InputStreamReader in = new InputStreamReader(new BufferedInputStream(input), encode); - final char[] cbuf = new char[8012]; - int len; - while ((len = in.read(cbuf)) != -1) { - buffer.append(cbuf, 0, len); - } - return buffer.toString(); - } catch (final UnsupportedEncodingException e) { - throw new RuntimeException(e); - } finally { - if (input != null) { - try { - input.close(); - } catch (final IOException e) { - // TODO - } - } - } - } - - public static byte[] toByteArray(final InputStream input) throws IOException { - final ByteArrayOutputStream buffer = new ByteArrayOutputStream(); - int nRead; - final byte[] data = new byte[8012]; - while ((nRead = input.read(data, 0, data.length)) != -1) { - buffer.write(data, 0, nRead); - } - buffer.flush(); - return buffer.toByteArray(); - } - -} diff --git a/src/main/java/com/arangodb/internal/util/RequestUtils.java b/src/main/java/com/arangodb/internal/util/RequestUtils.java index 2b5f56b47..1539b8a76 100644 --- a/src/main/java/com/arangodb/internal/util/RequestUtils.java +++ b/src/main/java/com/arangodb/internal/util/RequestUtils.java @@ -29,7 +29,7 @@ */ public final class RequestUtils { - public static final String HEADER_ALLOW_DIRTY_READ = "X-Arango-Allow-Dirty-Read"; + public static final String HEADER_ALLOW_DIRTY_READ = "x-arango-allow-dirty-read"; private RequestUtils() { super(); @@ -40,7 +40,7 @@ public static Request allowDirtyRead(final Request request) { } public static AccessType determineAccessType(final Request request) { - if (request.getHeaderParam().containsKey(HEADER_ALLOW_DIRTY_READ)) { + if (request.containsHeaderParam(HEADER_ALLOW_DIRTY_READ)) { return AccessType.DIRTY_READ; } if (request.getRequestType() == RequestType.GET) { diff --git a/src/main/java/com/arangodb/internal/util/ResponseUtils.java b/src/main/java/com/arangodb/internal/util/ResponseUtils.java index d09cd181b..fcab67e88 100644 --- a/src/main/java/com/arangodb/internal/util/ResponseUtils.java +++ b/src/main/java/com/arangodb/internal/util/ResponseUtils.java @@ -36,7 +36,7 @@ public final class ResponseUtils { private static final int ERROR_STATUS = 300; private static final int ERROR_INTERNAL = 503; - private static final String HEADER_ENDPOINT = "X-Arango-Endpoint"; + private static final String HEADER_ENDPOINT = "x-arango-endpoint"; private ResponseUtils() { super(); @@ -45,9 +45,9 @@ private ResponseUtils() { public static void checkError(final InternalSerde util, final Response response) { final int responseCode = response.getResponseCode(); if (responseCode >= ERROR_STATUS) { - if (responseCode == ERROR_INTERNAL && response.getMeta().containsKey(HEADER_ENDPOINT)) { + if (responseCode == ERROR_INTERNAL && response.containsMeta(HEADER_ENDPOINT)) { throw new ArangoDBRedirectException(String.format("Response Code: %s", responseCode), - response.getMeta().get(HEADER_ENDPOINT)); + response.getMeta(HEADER_ENDPOINT)); } else if (response.getBody() != null) { final ErrorEntity errorEntity = util.deserialize(response.getBody(), ErrorEntity.class); ArangoDBException e = new ArangoDBException(errorEntity); diff --git a/src/main/java/com/arangodb/velocystream/Request.java b/src/main/java/com/arangodb/velocystream/Request.java index 666b00e21..4802c6c00 100644 --- a/src/main/java/com/arangodb/velocystream/Request.java +++ b/src/main/java/com/arangodb/velocystream/Request.java @@ -22,7 +22,9 @@ import com.arangodb.DbName; +import java.util.Collections; import java.util.HashMap; +import java.util.Locale; import java.util.Map; /** @@ -91,12 +93,29 @@ public Request putQueryParam(final String key, final Object value) { } public Map getHeaderParam() { - return headerParam; + return Collections.unmodifiableMap(headerParam); + } + + public String getHeaderParam(final String key) { + return headerParam.get(key.toLowerCase(Locale.ROOT)); + } + + public boolean containsHeaderParam(final String key) { + return headerParam.containsKey(key.toLowerCase(Locale.ROOT)); } public Request putHeaderParam(final String key, final String value) { if (value != null) { - headerParam.put(key, value); + headerParam.put(key.toLowerCase(Locale.ROOT), value); + } + return this; + } + + public Request putHeaderParams(final Map params) { + if (params != null) { + for (Map.Entry it : params.entrySet()) { + putHeaderParam(it.getKey(), it.getValue()); + } } return this; } diff --git a/src/main/java/com/arangodb/velocystream/Response.java b/src/main/java/com/arangodb/velocystream/Response.java index 1f7b164bd..9b5cf6fd8 100644 --- a/src/main/java/com/arangodb/velocystream/Response.java +++ b/src/main/java/com/arangodb/velocystream/Response.java @@ -20,7 +20,9 @@ package com.arangodb.velocystream; +import java.util.Collections; import java.util.HashMap; +import java.util.Locale; import java.util.Map; /** @@ -31,7 +33,7 @@ public class Response { private int version = 1; private int type = 2; private int responseCode; - private Map meta; + private final Map meta; private byte[] body = null; public Response() { @@ -64,11 +66,25 @@ public void setResponseCode(final int responseCode) { } public Map getMeta() { - return meta; + return Collections.unmodifiableMap(meta); } - public void setMeta(final Map meta) { - this.meta = meta; + public String getMeta(final String key) { + return meta.get(key.toLowerCase(Locale.ROOT)); + } + + public boolean containsMeta(final String key) { + return meta.containsKey(key.toLowerCase(Locale.ROOT)); + } + + public void putMeta(final String key, final String value) { + this.meta.put(key.toLowerCase(Locale.ROOT), value); + } + + public void putMetas(final Map meta) { + for (Map.Entry it : meta.entrySet()) { + putMeta(it.getKey(), it.getValue()); + } } public byte[] getBody() { diff --git a/src/test/java/com/arangodb/example/ssl/SslExampleTest.java b/src/test/java/com/arangodb/example/ssl/SslExampleTest.java index 1fd34647d..764f1ae52 100644 --- a/src/test/java/com/arangodb/example/ssl/SslExampleTest.java +++ b/src/test/java/com/arangodb/example/ssl/SslExampleTest.java @@ -23,7 +23,6 @@ import com.arangodb.ArangoDB; import com.arangodb.Protocol; import com.arangodb.entity.ArangoDBVersion; -import org.apache.http.conn.ssl.NoopHostnameVerifier; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.condition.EnabledIfSystemProperty; @@ -76,7 +75,7 @@ void noopHostnameVerifier() throws Exception { .password("test") .useSsl(true) .sslContext(createSslContext()) - .hostnameVerifier(NoopHostnameVerifier.INSTANCE) + .verifyHost(false) .useProtocol(Protocol.HTTP_JSON) .build(); final ArangoDBVersion version = arangoDB.getVersion(); diff --git a/src/test/java/perf/Benchmark.java b/src/test/java/perf/Benchmark.java new file mode 100644 index 000000000..8fade9e17 --- /dev/null +++ b/src/test/java/perf/Benchmark.java @@ -0,0 +1,123 @@ +package perf; + +import java.util.Date; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.atomic.AtomicInteger; + +public abstract class Benchmark { + + private static final int SYNC_THREADS = 128; + private final CountDownLatch completed = new CountDownLatch(1); + private volatile Long startTime = null; + private volatile Long endTime = null; + private volatile int targetCount = Integer.MAX_VALUE; + private final AtomicInteger counter = new AtomicInteger(); + private final ExecutorService es = Executors.newFixedThreadPool(SYNC_THREADS); + private final int warmupDurationSeconds; + private final int numberOfRequests; + + public Benchmark(int warmupDurationSeconds, int numberOfRequests) { + this.warmupDurationSeconds = warmupDurationSeconds; + this.numberOfRequests = numberOfRequests; + } + + public void run() { + // warmup + startBenchmark(); + + // start monitor / warmup + startMonitor(); + + // start benchmark + startMeasuring(); + } + + private void startMonitor() { + for (int i = 0; i < warmupDurationSeconds; i++) { + counter.set(0); + long start = new Date().getTime(); + try { + Thread.sleep(1_000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + + long current = new Date().getTime(); + long elapsed = current - start; + double reqsPerSec = 1_000.0 * counter.get() / elapsed; + System.out.println("reqs/s: \t" + reqsPerSec); + } + } + + private void startBenchmark() { + start(); + new Thread(() -> { + try { + completed.await(); + // wait graceful shutdown + Thread.sleep(1_000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + // force shutdown + es.shutdown(); + shutdown(); + }).start(); + } + + private void startMeasuring() { + counter.set(0); + targetCount = numberOfRequests; + startTime = System.currentTimeMillis(); + } + + public long waitComplete() { + try { + completed.await(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + return endTime - startTime; + } + + /** + * @return req/s + */ + public long getThroughput() { + return targetCount * 1000L / (endTime - startTime); + } + + /** + * notify the success of #count requests + * + * @return whether more requests should be performed + */ + private boolean success() { + if (endTime != null) return false; + if (counter.addAndGet(1) >= targetCount) { + endTime = System.currentTimeMillis(); + completed.countDown(); + return false; + } + return true; + } + + private void start() { + for (int i = 0; i < SYNC_THREADS; i++) { + es.execute(() -> { + boolean more = true; + while (more) { + sendRequest(); + more = success(); + } + }); + } + } + + protected abstract void sendRequest(); + + protected abstract void shutdown(); + +} diff --git a/src/test/java/perf/SyncBenchmarkTest.java b/src/test/java/perf/SyncBenchmarkTest.java new file mode 100644 index 000000000..fb8fea25f --- /dev/null +++ b/src/test/java/perf/SyncBenchmarkTest.java @@ -0,0 +1,60 @@ +package perf; + +import com.arangodb.ArangoDB; +import com.arangodb.DbName; +import com.arangodb.Protocol; +import com.arangodb.velocystream.Request; +import com.arangodb.velocystream.RequestType; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.EnumSource; + +@Disabled +public class SyncBenchmarkTest { + private final int warmupDurationSeconds = 15; + private final int numberOfRequests = 1_000_000; + + @ParameterizedTest + @EnumSource(Protocol.class) + void getVersion(Protocol protocol) { + ArangoDB adb = new ArangoDB.Builder().useProtocol(protocol).build(); + Benchmark benchmark = new Benchmark(warmupDurationSeconds, numberOfRequests) { + @Override + protected void sendRequest() { + adb.getVersion(); + } + + @Override + protected void shutdown() { + adb.shutdown(); + } + }; + benchmark.run(); + System.out.println("elapsed time [ms]: \t" + benchmark.waitComplete()); + System.out.println("throughput [req/s]: \t" + benchmark.getThroughput()); + } + + @ParameterizedTest + @EnumSource(Protocol.class) + void getVersionWithDetails(Protocol protocol) { + ArangoDB adb = new ArangoDB.Builder().useProtocol(protocol).build(); + Benchmark benchmark = new Benchmark(warmupDurationSeconds, numberOfRequests) { + private final Request request = new Request(DbName.SYSTEM, RequestType.GET, + "/_api/version").putQueryParam("details", true); + + @Override + protected void sendRequest() { + adb.execute(request); + } + + @Override + protected void shutdown() { + adb.shutdown(); + } + }; + benchmark.run(); + System.out.println("elapsed time [ms]: \t" + benchmark.waitComplete()); + System.out.println("throughput [req/s]: \t" + benchmark.getThroughput()); + } + +} From a8fa889e9827414205aef74798d48023cc507625 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Tue, 18 Oct 2022 16:37:02 +0200 Subject: [PATCH 147/254] removed ArangoContext --- src/main/java/com/arangodb/ArangoDB.java | 2 - .../com/arangodb/async/ArangoDBAsync.java | 2 - .../async/internal/ArangoDBAsyncImpl.java | 3 +- .../com/arangodb/internal/ArangoContext.java | 49 ------------------- .../com/arangodb/internal/ArangoDBImpl.java | 5 +- .../arangodb/internal/ArangoExecuteable.java | 12 +---- .../internal/InternalArangoCollection.java | 2 +- .../arangodb/internal/InternalArangoDB.java | 7 +-- .../internal/InternalArangoDatabase.java | 2 +- .../InternalArangoEdgeCollection.java | 2 +- .../internal/InternalArangoGraph.java | 2 +- .../internal/InternalArangoRoute.java | 2 +- .../InternalArangoVertexCollection.java | 2 +- .../arangodb/internal/InternalArangoView.java | 2 +- 14 files changed, 14 insertions(+), 80 deletions(-) delete mode 100644 src/main/java/com/arangodb/internal/ArangoContext.java diff --git a/src/main/java/com/arangodb/ArangoDB.java b/src/main/java/com/arangodb/ArangoDB.java index fc9eb6d3f..84f8c86e9 100644 --- a/src/main/java/com/arangodb/ArangoDB.java +++ b/src/main/java/com/arangodb/ArangoDB.java @@ -21,7 +21,6 @@ package com.arangodb; import com.arangodb.entity.*; -import com.arangodb.internal.ArangoContext; import com.arangodb.internal.ArangoDBImpl; import com.arangodb.internal.ArangoDefaults; import com.arangodb.internal.InternalArangoDBBuilder; @@ -619,7 +618,6 @@ public ArangoDB build() { protocol, hostResolver, hostHandler, - new ArangoContext(), responseQueueTimeSamples, timeout); } diff --git a/src/main/java/com/arangodb/async/ArangoDBAsync.java b/src/main/java/com/arangodb/async/ArangoDBAsync.java index 1ade8d537..67ec5352f 100644 --- a/src/main/java/com/arangodb/async/ArangoDBAsync.java +++ b/src/main/java/com/arangodb/async/ArangoDBAsync.java @@ -28,7 +28,6 @@ import com.arangodb.async.internal.velocystream.VstCommunicationAsync; import com.arangodb.async.internal.velocystream.VstConnectionFactoryAsync; import com.arangodb.entity.*; -import com.arangodb.internal.ArangoContext; import com.arangodb.internal.ArangoDefaults; import com.arangodb.internal.InternalArangoDBBuilder; import com.arangodb.internal.net.ConnectionFactory; @@ -543,7 +542,6 @@ public ArangoDBAsync build() { syncHostResolver, asyncHostHandler, syncHostHandler, - new ArangoContext(), responseQueueTimeSamples, timeout); } diff --git a/src/main/java/com/arangodb/async/internal/ArangoDBAsyncImpl.java b/src/main/java/com/arangodb/async/internal/ArangoDBAsyncImpl.java index fb7f1d8a8..d045b1bf7 100644 --- a/src/main/java/com/arangodb/async/internal/ArangoDBAsyncImpl.java +++ b/src/main/java/com/arangodb/async/internal/ArangoDBAsyncImpl.java @@ -68,13 +68,12 @@ public ArangoDBAsyncImpl( final HostResolver syncHostResolver, final HostHandler asyncHostHandler, final HostHandler syncHostHandler, - final ArangoContext context, final int responseQueueTimeSamples, final int timeoutMs ) { super(new ArangoExecutorAsync(asyncCommBuilder.build(util), util, - new QueueTimeMetricsImpl(responseQueueTimeSamples), timeoutMs), util, context); + new QueueTimeMetricsImpl(responseQueueTimeSamples), timeoutMs), util); final VstCommunication cacheCom = syncCommBuilder.build(util); diff --git a/src/main/java/com/arangodb/internal/ArangoContext.java b/src/main/java/com/arangodb/internal/ArangoContext.java deleted file mode 100644 index 67c80c238..000000000 --- a/src/main/java/com/arangodb/internal/ArangoContext.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2018 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.internal; - -import java.util.HashMap; -import java.util.Map; - -/** - * @author Mark Vollmary - */ -public class ArangoContext { - - private final Map headerParam; - - public ArangoContext() { - super(); - headerParam = new HashMap<>(); - } - - public Map getHeaderParam() { - return headerParam; - } - - public ArangoContext putHeaderParam(final String key, final Object value) { - if (value != null) { - headerParam.put(key, value.toString()); - } - return this; - } - -} diff --git a/src/main/java/com/arangodb/internal/ArangoDBImpl.java b/src/main/java/com/arangodb/internal/ArangoDBImpl.java index e37cd9596..a981c024f 100644 --- a/src/main/java/com/arangodb/internal/ArangoDBImpl.java +++ b/src/main/java/com/arangodb/internal/ArangoDBImpl.java @@ -57,14 +57,13 @@ public class ArangoDBImpl extends InternalArangoDB implement public ArangoDBImpl(final VstCommunicationSync.Builder vstBuilder, final HttpCommunication.Builder httpBuilder, final InternalSerde util, final Protocol protocol, final HostResolver hostResolver, - final HostHandler hostHandler, final ArangoContext context, int responseQueueTimeSamples, + final HostHandler hostHandler, int responseQueueTimeSamples, final int timeoutMs) { super(new ArangoExecutorSync( createProtocol(vstBuilder, httpBuilder, util, protocol), util, new QueueTimeMetricsImpl(responseQueueTimeSamples), timeoutMs), - util, - context); + util); cp = createProtocol( new VstCommunicationSync.Builder(vstBuilder).maxConnections(1), diff --git a/src/main/java/com/arangodb/internal/ArangoExecuteable.java b/src/main/java/com/arangodb/internal/ArangoExecuteable.java index 63d0d0b07..e039a9878 100644 --- a/src/main/java/com/arangodb/internal/ArangoExecuteable.java +++ b/src/main/java/com/arangodb/internal/ArangoExecuteable.java @@ -27,8 +27,6 @@ import com.arangodb.velocystream.Request; import com.arangodb.velocystream.RequestType; -import java.util.Map.Entry; - /** * @author Mark Vollmary */ @@ -38,13 +36,11 @@ public abstract class ArangoExecuteable implements Ara protected final E executor; protected final InternalSerde serde; - protected final ArangoContext context; - protected ArangoExecuteable(final E executor, final InternalSerde serde, final ArangoContext context) { + protected ArangoExecuteable(final E executor, final InternalSerde serde) { super(); this.executor = executor; this.serde = serde; - this.context = context; } protected static String createPath(final String... params) { @@ -74,11 +70,7 @@ public InternalSerde getSerde() { } protected Request request(final DbName dbName, final RequestType requestType, final String... path) { - final Request request = new Request(dbName, requestType, createPath(path)); - for (final Entry header : context.getHeaderParam().entrySet()) { - request.putHeaderParam(header.getKey(), header.getValue()); - } - return request; + return new Request(dbName, requestType, createPath(path)); } } diff --git a/src/main/java/com/arangodb/internal/InternalArangoCollection.java b/src/main/java/com/arangodb/internal/InternalArangoCollection.java index fdc1f24c1..6b311dac6 100644 --- a/src/main/java/com/arangodb/internal/InternalArangoCollection.java +++ b/src/main/java/com/arangodb/internal/InternalArangoCollection.java @@ -71,7 +71,7 @@ public abstract class InternalArangoCollection, D protected volatile String name; protected InternalArangoCollection(final D db, final String name) { - super(db.executor, db.serde, db.context); + super(db.executor, db.serde); this.db = db; this.name = name; } diff --git a/src/main/java/com/arangodb/internal/InternalArangoDB.java b/src/main/java/com/arangodb/internal/InternalArangoDB.java index 13efd696d..8c10fba1b 100644 --- a/src/main/java/com/arangodb/internal/InternalArangoDB.java +++ b/src/main/java/com/arangodb/internal/InternalArangoDB.java @@ -42,18 +42,15 @@ * @author Heiko Kernbach */ public abstract class InternalArangoDB extends ArangoExecuteable { - - private static final String PATH_API_ADMIN_LOG = "/_admin/log"; private static final String PATH_API_ADMIN_LOG_ENTRIES = "/_admin/log/entries"; private static final String PATH_API_ADMIN_LOG_LEVEL = "/_admin/log/level"; private static final String PATH_API_ROLE = "/_admin/server/role"; private static final String PATH_API_SERVER_ID = "/_admin/server/id"; - private static final String PATH_ENDPOINTS = "/_api/cluster/endpoints"; private static final String PATH_API_USER = "/_api/user"; private static final String PATH_API_QUERY_RULES = "/_api/query/rules"; - protected InternalArangoDB(final E executor, final InternalSerde util, final ArangoContext context) { - super(executor, util, context); + protected InternalArangoDB(final E executor, final InternalSerde util) { + super(executor, util); } protected Request getRoleRequest() { diff --git a/src/main/java/com/arangodb/internal/InternalArangoDatabase.java b/src/main/java/com/arangodb/internal/InternalArangoDatabase.java index edfe70b70..cb9860194 100644 --- a/src/main/java/com/arangodb/internal/InternalArangoDatabase.java +++ b/src/main/java/com/arangodb/internal/InternalArangoDatabase.java @@ -64,7 +64,7 @@ public abstract class InternalArangoDatabase private final String name; protected InternalArangoEdgeCollection(final G graph, final String name) { - super(graph.executor, graph.serde, graph.context); + super(graph.executor, graph.serde); this.graph = graph; this.name = name; } diff --git a/src/main/java/com/arangodb/internal/InternalArangoGraph.java b/src/main/java/com/arangodb/internal/InternalArangoGraph.java index 5d09a22ba..9196e58f0 100644 --- a/src/main/java/com/arangodb/internal/InternalArangoGraph.java +++ b/src/main/java/com/arangodb/internal/InternalArangoGraph.java @@ -48,7 +48,7 @@ public abstract class InternalArangoGraph, D exten private final String name; protected InternalArangoGraph(final D db, final String name) { - super(db.executor, db.serde, db.context); + super(db.executor, db.serde); this.db = db; this.name = name; } diff --git a/src/main/java/com/arangodb/internal/InternalArangoRoute.java b/src/main/java/com/arangodb/internal/InternalArangoRoute.java index 23ba43f01..966aac05c 100644 --- a/src/main/java/com/arangodb/internal/InternalArangoRoute.java +++ b/src/main/java/com/arangodb/internal/InternalArangoRoute.java @@ -42,7 +42,7 @@ public abstract class InternalArangoRoute, D exten protected Object body; protected InternalArangoRoute(final D db, final String path, final Map headerParam) { - super(db.executor, db.serde, db.context); + super(db.executor, db.serde); this.db = db; this.path = path; this.queryParam = new HashMap<>(); diff --git a/src/main/java/com/arangodb/internal/InternalArangoVertexCollection.java b/src/main/java/com/arangodb/internal/InternalArangoVertexCollection.java index 142601448..93b2e0646 100644 --- a/src/main/java/com/arangodb/internal/InternalArangoVertexCollection.java +++ b/src/main/java/com/arangodb/internal/InternalArangoVertexCollection.java @@ -44,7 +44,7 @@ public abstract class InternalArangoVertexCollection, D extend protected volatile String name; protected InternalArangoView(final D db, final String name) { - super(db.executor, db.serde, db.context); + super(db.executor, db.serde); this.db = db; this.name = name; } From 9b7a2bb23201e81221bd015e13c5e56c04552dcd Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Wed, 19 Oct 2022 08:40:10 +0200 Subject: [PATCH 148/254] [DE-408] HTTP2 config --- src/main/java/com/arangodb/ArangoDB.java | 5 +- .../{serde/DataType.java => ContentType.java} | 16 +++---- src/main/java/com/arangodb/Protocol.java | 22 +++++++-- .../com/arangodb/async/ArangoDBAsync.java | 6 +-- .../com/arangodb/internal/ArangoDefaults.java | 3 +- .../internal/InternalArangoDBBuilder.java | 7 +++ .../internal/http/HttpConnection.java | 28 ++++++----- .../internal/http/HttpConnectionFactory.java | 2 +- .../internal/serde/InternalSerde.java | 12 ++--- .../internal/serde/MapperProvider.java | 10 ++-- .../java/com/arangodb/serde/ArangoSerde.java | 8 ++-- .../java/com/arangodb/serde/JacksonSerde.java | 7 +-- src/test/java/com/arangodb/ArangoSslTest.java | 15 ++++-- src/test/java/com/arangodb/BaseJunit5.java | 4 +- .../arangodb/async/serde/CustomSerdeTest.java | 4 +- .../arangodb/example/ssl/SslExampleTest.java | 48 ++++++++++++++----- .../annotations/ArangoAnnotationsTest.java | 8 ++-- .../com/arangodb/serde/CustomSerdeTest.java | 2 +- .../java/com/arangodb/serde/SerdeTest.java | 17 +++---- 19 files changed, 142 insertions(+), 82 deletions(-) rename src/main/java/com/arangodb/{serde/DataType.java => ContentType.java} (79%) diff --git a/src/main/java/com/arangodb/ArangoDB.java b/src/main/java/com/arangodb/ArangoDB.java index 84f8c86e9..cb4186127 100644 --- a/src/main/java/com/arangodb/ArangoDB.java +++ b/src/main/java/com/arangodb/ArangoDB.java @@ -35,7 +35,6 @@ import com.arangodb.model.UserCreateOptions; import com.arangodb.model.UserUpdateOptions; import com.arangodb.serde.ArangoSerde; -import com.arangodb.serde.DataType; import com.arangodb.serde.JacksonSerde; import com.arangodb.velocystream.Request; import com.arangodb.velocystream.Response; @@ -591,8 +590,8 @@ public ArangoDB build() { hosts.add(host); } final ArangoSerde userSerde = customSerializer != null ? customSerializer : - JacksonSerde.of(DataType.of(protocol)); - final InternalSerde serde = InternalSerde.of(DataType.of(protocol), userSerde); + JacksonSerde.of(ContentType.of(protocol)); + final InternalSerde serde = InternalSerde.of(ContentType.of(protocol), userSerde); int protocolMaxConnections = protocol == Protocol.VST ? ArangoDefaults.MAX_CONNECTIONS_VST_DEFAULT : diff --git a/src/main/java/com/arangodb/serde/DataType.java b/src/main/java/com/arangodb/ContentType.java similarity index 79% rename from src/main/java/com/arangodb/serde/DataType.java rename to src/main/java/com/arangodb/ContentType.java index 59fc96bcf..ed9077ac3 100644 --- a/src/main/java/com/arangodb/serde/DataType.java +++ b/src/main/java/com/arangodb/ContentType.java @@ -17,20 +17,20 @@ * * Copyright holder is ArangoDB GmbH, Cologne, Germany */ -package com.arangodb.serde; +package com.arangodb; -import com.arangodb.Protocol; - -public enum DataType { +public enum ContentType { JSON, VPACK; - public static DataType of(Protocol protocol) { + public static ContentType of(Protocol protocol) { switch (protocol) { case HTTP_JSON: - return DataType.JSON; - case HTTP_VPACK: + case HTTP2_JSON: + return ContentType.JSON; case VST: - return DataType.VPACK; + case HTTP_VPACK: + case HTTP2_VPACK: + return ContentType.VPACK; default: throw new IllegalArgumentException("Unexpected value: " + protocol); } diff --git a/src/main/java/com/arangodb/Protocol.java b/src/main/java/com/arangodb/Protocol.java index 486ab62f7..1ca4bb4ea 100644 --- a/src/main/java/com/arangodb/Protocol.java +++ b/src/main/java/com/arangodb/Protocol.java @@ -24,20 +24,36 @@ * @author Mark Vollmary */ public enum Protocol { + /** * VelocyStream * * @see VelocyStream specification */ VST, + /** - * HTTP with JSON body + * HTTP 1.1 with JSON body */ HTTP_JSON, + + /** + * HTTP 1.1 with VelocyPack body + * + * @see VelocyPack specification + */ + HTTP_VPACK, + + /** + * HTTP 2 with JSON body + */ + HTTP2_JSON, + /** - * HTTP with VelocyPack body + * HTTP 2 with VelocyPack body * * @see VelocyPack specification */ - HTTP_VPACK + HTTP2_VPACK, + } diff --git a/src/main/java/com/arangodb/async/ArangoDBAsync.java b/src/main/java/com/arangodb/async/ArangoDBAsync.java index 67ec5352f..327cd7cfa 100644 --- a/src/main/java/com/arangodb/async/ArangoDBAsync.java +++ b/src/main/java/com/arangodb/async/ArangoDBAsync.java @@ -41,7 +41,7 @@ import com.arangodb.model.UserCreateOptions; import com.arangodb.model.UserUpdateOptions; import com.arangodb.serde.ArangoSerde; -import com.arangodb.serde.DataType; +import com.arangodb.ContentType; import com.arangodb.serde.JacksonSerde; import com.arangodb.velocystream.Request; import com.arangodb.velocystream.Response; @@ -519,8 +519,8 @@ public ArangoDBAsync build() { if (hosts.isEmpty()) { hosts.add(host); } - final ArangoSerde userSerde = customSerializer != null ? customSerializer : JacksonSerde.of(DataType.VPACK); - final InternalSerde serde = InternalSerde.of(DataType.VPACK, userSerde); + final ArangoSerde userSerde = customSerializer != null ? customSerializer : JacksonSerde.of(ContentType.VPACK); + final InternalSerde serde = InternalSerde.of(ContentType.VPACK, userSerde); final int max = maxConnections != null ? Math.max(1, maxConnections) : ArangoDefaults.MAX_CONNECTIONS_VST_DEFAULT; diff --git a/src/main/java/com/arangodb/internal/ArangoDefaults.java b/src/main/java/com/arangodb/internal/ArangoDefaults.java index f9351b827..ebd39f521 100644 --- a/src/main/java/com/arangodb/internal/ArangoDefaults.java +++ b/src/main/java/com/arangodb/internal/ArangoDefaults.java @@ -35,13 +35,14 @@ public final class ArangoDefaults { public static final Integer DEFAULT_TIMEOUT = 0; public static final String DEFAULT_USER = "root"; public static final Boolean DEFAULT_USE_SSL = false; + public static final Boolean DEFAULT_VERIFY_HOST = true; public static final int CHUNK_MIN_HEADER_SIZE = INTEGER_BYTES + INTEGER_BYTES + LONG_BYTES; public static final int CHUNK_MAX_HEADER_SIZE = CHUNK_MIN_HEADER_SIZE + LONG_BYTES; public static final int CHUNK_DEFAULT_CONTENT_SIZE = 30000; public static final int MAX_CONNECTIONS_VST_DEFAULT = 1; public static final Integer CONNECTION_TTL_VST_DEFAULT = null; public static final int MAX_CONNECTIONS_HTTP_DEFAULT = 20; - public static final Protocol DEFAULT_NETWORK_PROTOCOL = Protocol.HTTP_JSON; + public static final Protocol DEFAULT_NETWORK_PROTOCOL = Protocol.HTTP2_JSON; public static final boolean DEFAULT_ACQUIRE_HOST_LIST = false; public static final int DEFAULT_ACQUIRE_HOST_LIST_INTERVAL = 60 * 60 * 1000; // hour public static final LoadBalancingStrategy DEFAULT_LOAD_BALANCING_STRATEGY = LoadBalancingStrategy.NONE; diff --git a/src/main/java/com/arangodb/internal/InternalArangoDBBuilder.java b/src/main/java/com/arangodb/internal/InternalArangoDBBuilder.java index 38e6b6441..dc119bd79 100644 --- a/src/main/java/com/arangodb/internal/InternalArangoDBBuilder.java +++ b/src/main/java/com/arangodb/internal/InternalArangoDBBuilder.java @@ -50,6 +50,7 @@ public abstract class InternalArangoDBBuilder { private static final String PROPERTY_KEY_PASSWORD = "arangodb.password"; private static final String PROPERTY_KEY_JWT = "arangodb.jwt"; private static final String PROPERTY_KEY_USE_SSL = "arangodb.usessl"; + private static final String PROPERTY_KEY_VERIFY_HOST = "arangodb.verifyHost"; private static final String PROPERTY_KEY_V_STREAM_CHUNK_CONTENT_SIZE = "arangodb.chunksize"; private static final String PROPERTY_KEY_MAX_CONNECTIONS = "arangodb.connections.max"; private static final String PROPERTY_KEY_CONNECTION_TTL = "arangodb.connections.ttl"; @@ -146,6 +147,11 @@ private static Boolean loadUseSsl(final Properties properties, final Boolean cur getProperty(properties, PROPERTY_KEY_USE_SSL, currentValue, ArangoDefaults.DEFAULT_USE_SSL)); } + private static Boolean loadVerifyHost(final Properties properties, final Boolean currentValue) { + return Boolean.parseBoolean(getProperty(properties, PROPERTY_KEY_VERIFY_HOST, currentValue, + ArangoDefaults.DEFAULT_VERIFY_HOST)); + } + private static Integer loadChunkSize(final Properties properties, final Integer currentValue) { return Integer.parseInt(getProperty(properties, PROPERTY_KEY_V_STREAM_CHUNK_CONTENT_SIZE, currentValue, ArangoDefaults.CHUNK_DEFAULT_CONTENT_SIZE)); @@ -236,6 +242,7 @@ protected void loadProperties(final Properties properties) { password = loadPassword(properties, password); jwt = loadJwt(properties, jwt); useSsl = loadUseSsl(properties, useSsl); + verifyHost = loadVerifyHost(properties, verifyHost); chunksize = loadChunkSize(properties, chunksize); maxConnections = loadMaxConnections(properties, maxConnections); connectionTtl = loadConnectionTtl(properties, connectionTtl); diff --git a/src/main/java/com/arangodb/internal/http/HttpConnection.java b/src/main/java/com/arangodb/internal/http/HttpConnection.java index 0303fc740..c79ae72d7 100644 --- a/src/main/java/com/arangodb/internal/http/HttpConnection.java +++ b/src/main/java/com/arangodb/internal/http/HttpConnection.java @@ -27,6 +27,7 @@ import com.arangodb.internal.net.HostDescription; import com.arangodb.internal.serde.InternalSerde; import com.arangodb.internal.util.ResponseUtils; +import com.arangodb.ContentType; import com.arangodb.velocystream.Request; import com.arangodb.velocystream.RequestType; import com.arangodb.velocystream.Response; @@ -74,7 +75,7 @@ public class HttpConnection implements Connection { private static final AtomicInteger THREAD_COUNT = new AtomicInteger(); private final InternalSerde util; private final String baseUrl; - private final Protocol contentType; + private final ContentType contentType; private volatile String auth; private final WebClient client; private final Integer timeout; @@ -82,10 +83,10 @@ public class HttpConnection implements Connection { private HttpConnection(final HostDescription host, final Integer timeout, final String user, final String password, final Boolean useSsl, final SSLContext sslContext, final Boolean verifyHost, - final InternalSerde util, final Protocol contentType, final Long ttl) { + final InternalSerde util, final Protocol protocol, final Long ttl) { super(); this.util = util; - this.contentType = contentType; + this.contentType = ContentType.of(protocol); this.timeout = timeout; baseUrl = buildBaseUrl(host, useSsl); auth = new UsernamePasswordCredentials(user, password != null ? password : "").toHttpAuthorization(); @@ -94,6 +95,9 @@ private HttpConnection(final HostDescription host, final Integer timeout, final int _ttl = ttl == null ? 0 : Math.toIntExact(ttl / 1000); + HttpVersion httpVersion = protocol == Protocol.HTTP_JSON || protocol == Protocol.HTTP_VPACK ? + HttpVersion.HTTP_1_1 : HttpVersion.HTTP_2; + WebClientOptions webClientOptions = new WebClientOptions() .setConnectTimeout(timeout) .setIdleTimeoutUnit(TimeUnit.MILLISECONDS) @@ -109,10 +113,7 @@ private HttpConnection(final HostDescription host, final Integer timeout, final .setReuseAddress(true) .setReusePort(true) .setHttp2ClearTextUpgrade(false) - //TODO: allow configuring HTTP_2 or HTTP_1_1 -// .setProtocolVersion(HttpVersion.HTTP_1_1) - .setProtocolVersion(HttpVersion.HTTP_2) - .setUseAlpn(true) + .setProtocolVersion(httpVersion) .setDefaultHost(host.getHost()) .setDefaultPort(host.getPort()); @@ -131,6 +132,7 @@ private HttpConnection(final HostDescription host, final Integer timeout, final webClientOptions .setSsl(true) + .setUseAlpn(true) .setVerifyHost(verifyHost != null ? verifyHost : true) .setJdkSslEngineOptions(new JdkSSLEngineOptions() { @Override @@ -226,7 +228,7 @@ public Response execute(final Request request) throws IOException { HttpRequest httpRequest = client .request(requestTypeToHttpMethod(request.getRequestType()), path) .timeout(timeout); - if (contentType == Protocol.HTTP_VPACK) { + if (contentType == ContentType.VPACK) { httpRequest.putHeader("Accept", "application/x-velocypack"); } addHeader(request, httpRequest); @@ -240,7 +242,7 @@ public Response execute(final Request request) throws IOException { Buffer buffer; if (reqBody != null) { buffer = Buffer.buffer(reqBody); - if (contentType == Protocol.HTTP_VPACK) { + if (contentType == ContentType.VPACK) { httpRequest.putHeader(HttpHeaders.CONTENT_TYPE.toString(), CONTENT_TYPE_VPACK); } else { httpRequest.putHeader(HttpHeaders.CONTENT_TYPE.toString(), CONTENT_TYPE_APPLICATION_JSON_UTF8); @@ -297,7 +299,7 @@ public static class Builder { private String password; private InternalSerde util; private Boolean useSsl; - private Protocol contentType; + private Protocol protocol; private HostDescription host; private Long ttl; private SSLContext sslContext; @@ -324,8 +326,8 @@ public Builder useSsl(final Boolean useSsl) { return this; } - public Builder contentType(final Protocol contentType) { - this.contentType = contentType; + public Builder protocol(final Protocol protocol) { + this.protocol = protocol; return this; } @@ -356,7 +358,7 @@ public Builder timeout(final Integer timeout) { public HttpConnection build() { return new HttpConnection(host, timeout, user, password, useSsl, sslContext, verifyHost, util, - contentType, ttl); + protocol, ttl); } } diff --git a/src/main/java/com/arangodb/internal/http/HttpConnectionFactory.java b/src/main/java/com/arangodb/internal/http/HttpConnectionFactory.java index 5e0abc74b..59783cdf9 100644 --- a/src/main/java/com/arangodb/internal/http/HttpConnectionFactory.java +++ b/src/main/java/com/arangodb/internal/http/HttpConnectionFactory.java @@ -40,7 +40,7 @@ public HttpConnectionFactory(final Integer timeout, final String user, final Str final InternalSerde util, final Protocol protocol, final Long connectionTtl) { super(); builder = new HttpConnection.Builder().timeout(timeout).user(user).password(password).useSsl(useSsl) - .sslContext(sslContext).verifyHost(verifyHost).serializationUtil(util).contentType(protocol) + .sslContext(sslContext).verifyHost(verifyHost).serializationUtil(util).protocol(protocol) .ttl(connectionTtl); } diff --git a/src/main/java/com/arangodb/internal/serde/InternalSerde.java b/src/main/java/com/arangodb/internal/serde/InternalSerde.java index 70d4fc462..4a6087981 100644 --- a/src/main/java/com/arangodb/internal/serde/InternalSerde.java +++ b/src/main/java/com/arangodb/internal/serde/InternalSerde.java @@ -1,7 +1,7 @@ package com.arangodb.internal.serde; import com.arangodb.serde.ArangoSerde; -import com.arangodb.serde.DataType; +import com.arangodb.ContentType; import com.arangodb.serde.JacksonSerde; import com.fasterxml.jackson.databind.JsonNode; @@ -13,11 +13,11 @@ public interface InternalSerde extends JacksonSerde { /** * Creates a new InternalSerde with default settings for the specified data type. * - * @param dataType serialization target data type + * @param contentType serialization target data type * @return the created InternalSerde */ - static InternalSerde of(final DataType dataType, ArangoSerde userSerde) { - return new InternalSerdeImpl(MapperProvider.of(dataType), userSerde); + static InternalSerde of(final ContentType contentType, ArangoSerde userSerde) { + return new InternalSerdeImpl(MapperProvider.of(contentType), userSerde); } /** @@ -77,7 +77,7 @@ default T deserialize(JsonNode node, Class clazz) { /** * Deserializes the content at json pointer and binds it to the target data type. - * For data type {@link DataType#JSON}, the byte array is the JSON string encoded using the UTF-8 charset. + * For data type {@link ContentType#JSON}, the byte array is the JSON string encoded using the UTF-8 charset. * * @param content byte array to deserialize * @param jsonPointer location of data to be deserialized @@ -90,7 +90,7 @@ default T deserialize(byte[] content, String jsonPointer, Class clazz) { /** * Deserializes the content at json pointer and binds it to the target data type. - * For data type {@link DataType#JSON}, the byte array is the JSON string encoded using the UTF-8 charset. + * For data type {@link ContentType#JSON}, the byte array is the JSON string encoded using the UTF-8 charset. * * @param content byte array to deserialize * @param jsonPointer location of data to be deserialized diff --git a/src/main/java/com/arangodb/internal/serde/MapperProvider.java b/src/main/java/com/arangodb/internal/serde/MapperProvider.java index 2f0152b19..a4431a6cd 100644 --- a/src/main/java/com/arangodb/internal/serde/MapperProvider.java +++ b/src/main/java/com/arangodb/internal/serde/MapperProvider.java @@ -1,18 +1,18 @@ package com.arangodb.internal.serde; -import com.arangodb.serde.DataType; +import com.arangodb.ContentType; import com.fasterxml.jackson.databind.ObjectMapper; import java.util.function.Supplier; public interface MapperProvider extends Supplier { - static ObjectMapper of(final DataType dataType) { - if (dataType == DataType.JSON) { + static ObjectMapper of(final ContentType contentType) { + if (contentType == ContentType.JSON) { return JsonMapperProvider.INSTANCE.get(); - } else if (dataType == DataType.VPACK) { + } else if (contentType == ContentType.VPACK) { return VPackMapperProvider.INSTANCE.get(); } else { - throw new IllegalArgumentException("Unexpected value: " + dataType); + throw new IllegalArgumentException("Unexpected value: " + contentType); } } } diff --git a/src/main/java/com/arangodb/serde/ArangoSerde.java b/src/main/java/com/arangodb/serde/ArangoSerde.java index 548662a11..b8071be04 100644 --- a/src/main/java/com/arangodb/serde/ArangoSerde.java +++ b/src/main/java/com/arangodb/serde/ArangoSerde.java @@ -1,5 +1,7 @@ package com.arangodb.serde; +import com.arangodb.ContentType; + import java.lang.reflect.Type; import java.util.function.Consumer; @@ -20,7 +22,7 @@ public interface ArangoSerde { /** - * Serializes the object into the target data type. For data type {@link DataType#JSON}, the serialized JSON string + * Serializes the object into the target data type. For data type {@link ContentType#JSON}, the serialized JSON string * must be encoded into a byte array using the UTF-8 charset. * * @param value object to serialize @@ -30,7 +32,7 @@ public interface ArangoSerde { /** * Deserializes the content and binds it to the target data type. - * For data type {@link DataType#JSON}, the byte array is the JSON string encoded using the UTF-8 charset. + * For data type {@link ContentType#JSON}, the byte array is the JSON string encoded using the UTF-8 charset. * * @param content byte array to deserialize * @param clazz class of target data type @@ -42,7 +44,7 @@ default T deserialize(byte[] content, Class clazz) { /** * Deserializes the content and binds it to the target data type. - * For data type {@link DataType#JSON}, the byte array is the JSON string encoded using the UTF-8 charset. + * For data type {@link ContentType#JSON}, the byte array is the JSON string encoded using the UTF-8 charset. * * @param content byte array to deserialize * @param type target data type diff --git a/src/main/java/com/arangodb/serde/JacksonSerde.java b/src/main/java/com/arangodb/serde/JacksonSerde.java index dfaa24cfd..2a642c2ac 100644 --- a/src/main/java/com/arangodb/serde/JacksonSerde.java +++ b/src/main/java/com/arangodb/serde/JacksonSerde.java @@ -1,5 +1,6 @@ package com.arangodb.serde; +import com.arangodb.ContentType; import com.arangodb.internal.serde.JacksonSerdeImpl; import com.arangodb.internal.serde.MapperProvider; import com.fasterxml.jackson.databind.ObjectMapper; @@ -14,11 +15,11 @@ public interface JacksonSerde extends ArangoSerde { /** * Creates a new JacksonSerde with default settings for the specified data type. * - * @param dataType serialization target data type + * @param contentType serialization target data type * @return the created JacksonSerde */ - static JacksonSerde of(final DataType dataType) { - return create(MapperProvider.of(dataType)); + static JacksonSerde of(final ContentType contentType) { + return create(MapperProvider.of(contentType)); } /** diff --git a/src/test/java/com/arangodb/ArangoSslTest.java b/src/test/java/com/arangodb/ArangoSslTest.java index b2693dae9..52c9de434 100644 --- a/src/test/java/com/arangodb/ArangoSslTest.java +++ b/src/test/java/com/arangodb/ArangoSslTest.java @@ -21,8 +21,9 @@ package com.arangodb; import com.arangodb.entity.ArangoDBVersion; -import org.junit.jupiter.api.Test; import org.junit.jupiter.api.condition.EnabledIfSystemProperty; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.EnumSource; import javax.net.ssl.KeyManagerFactory; import javax.net.ssl.SSLContext; @@ -54,8 +55,9 @@ class ArangoSslTest { private static final String SSL_TRUSTSTORE = "/example.truststore"; private static final String SSL_TRUSTSTORE_PASSWORD = "12345678"; - @Test - void connect() throws Exception { + @ParameterizedTest + @EnumSource(Protocol.class) + void connect(Protocol protocol) throws Exception { final KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType()); ks.load(this.getClass().getResourceAsStream(SSL_TRUSTSTORE), SSL_TRUSTSTORE_PASSWORD.toCharArray()); @@ -69,15 +71,18 @@ void connect() throws Exception { sc.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null); final ArangoDB arangoDB = new ArangoDB.Builder() + .useProtocol(protocol) .loadProperties(ArangoSslTest.class.getResourceAsStream("/arangodb-ssl.properties")).useSsl(true) .sslContext(sc).build(); final ArangoDBVersion version = arangoDB.getVersion(); assertThat(version).isNotNull(); } - @Test - void connectWithoutValidSslContext() { + @ParameterizedTest + @EnumSource(Protocol.class) + void connectWithoutValidSslContext(Protocol protocol) { final ArangoDB arangoDB = new ArangoDB.Builder() + .useProtocol(protocol) .loadProperties(ArangoSslTest.class.getResourceAsStream("/arangodb-ssl.properties")).useSsl(true) .build(); Throwable thrown = catchThrowable(arangoDB::getVersion); diff --git a/src/test/java/com/arangodb/BaseJunit5.java b/src/test/java/com/arangodb/BaseJunit5.java index 506bba0ef..3e3b35ca1 100644 --- a/src/test/java/com/arangodb/BaseJunit5.java +++ b/src/test/java/com/arangodb/BaseJunit5.java @@ -22,7 +22,9 @@ class BaseJunit5 { new ArangoDB.Builder().useProtocol(Protocol.VST).build(), new ArangoDB.Builder().useProtocol(Protocol.HTTP_VPACK).build(), new ArangoDB.Builder().useProtocol(Protocol.HTTP_JSON).build(), - new ArangoDB.Builder().useProtocol(Protocol.HTTP_JSON).serializer(JsonbSerde.create()).build() + new ArangoDB.Builder().useProtocol(Protocol.HTTP2_VPACK).build(), + new ArangoDB.Builder().useProtocol(Protocol.HTTP2_JSON).build(), + new ArangoDB.Builder().useProtocol(Protocol.HTTP2_JSON).serializer(JsonbSerde.create()).build() ); protected static Stream dbsStream() { diff --git a/src/test/java/com/arangodb/async/serde/CustomSerdeTest.java b/src/test/java/com/arangodb/async/serde/CustomSerdeTest.java index e601c5185..270a15872 100644 --- a/src/test/java/com/arangodb/async/serde/CustomSerdeTest.java +++ b/src/test/java/com/arangodb/async/serde/CustomSerdeTest.java @@ -26,7 +26,7 @@ import com.arangodb.async.ArangoDBAsync; import com.arangodb.async.ArangoDatabaseAsync; import com.arangodb.model.DocumentCreateOptions; -import com.arangodb.serde.DataType; +import com.arangodb.ContentType; import com.arangodb.serde.JacksonSerde; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; @@ -56,7 +56,7 @@ class CustomSerdeTest { @BeforeEach void init() throws ExecutionException, InterruptedException { - JacksonSerde serde = JacksonSerde.of(DataType.VPACK); + JacksonSerde serde = JacksonSerde.of(ContentType.VPACK); serde.configure((mapper) -> { mapper.configure(WRITE_SINGLE_ELEM_ARRAYS_UNWRAPPED, true); mapper.configure(USE_BIG_INTEGER_FOR_INTS, true); diff --git a/src/test/java/com/arangodb/example/ssl/SslExampleTest.java b/src/test/java/com/arangodb/example/ssl/SslExampleTest.java index 764f1ae52..5dd54f204 100644 --- a/src/test/java/com/arangodb/example/ssl/SslExampleTest.java +++ b/src/test/java/com/arangodb/example/ssl/SslExampleTest.java @@ -21,17 +21,21 @@ package com.arangodb.example.ssl; import com.arangodb.ArangoDB; +import com.arangodb.ArangoDBException; +import com.arangodb.ArangoDBMultipleException; import com.arangodb.Protocol; import com.arangodb.entity.ArangoDBVersion; -import org.junit.jupiter.api.Test; import org.junit.jupiter.api.condition.EnabledIfSystemProperty; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.EnumSource; -import javax.net.ssl.KeyManagerFactory; -import javax.net.ssl.SSLContext; -import javax.net.ssl.TrustManagerFactory; +import javax.net.ssl.*; import java.security.KeyStore; +import java.util.List; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.catchThrowable; +import static org.junit.jupiter.api.Assumptions.assumeTrue; /** * @author Mark Vollmary @@ -52,37 +56,57 @@ class SslExampleTest { private static final String SSL_TRUSTSTORE = "/example.truststore"; private static final String SSL_TRUSTSTORE_PASSWORD = "12345678"; - @Test - void connect() throws Exception { + @ParameterizedTest + @EnumSource(Protocol.class) + void connect(Protocol protocol) throws Exception { final ArangoDB arangoDB = new ArangoDB.Builder() - .host("localhost", 8529) .password("test") .useSsl(true) .sslContext(createSslContext()) - .useProtocol(Protocol.HTTP_JSON) + .useProtocol(protocol) .build(); final ArangoDBVersion version = arangoDB.getVersion(); assertThat(version).isNotNull(); System.out.println(version.getVersion()); } - @Test - void noopHostnameVerifier() throws Exception { + @ParameterizedTest + @EnumSource(Protocol.class) + void noopHostnameVerifier(Protocol protocol) throws Exception { final ArangoDB arangoDB = new ArangoDB.Builder() - .host("127.0.0.1", 8529) .password("test") .useSsl(true) .sslContext(createSslContext()) .verifyHost(false) - .useProtocol(Protocol.HTTP_JSON) + .useProtocol(protocol) .build(); final ArangoDBVersion version = arangoDB.getVersion(); assertThat(version).isNotNull(); System.out.println(version.getVersion()); } + @ParameterizedTest + @EnumSource(Protocol.class) + void hostnameVerifierFailure(Protocol protocol) throws Exception { + assumeTrue(protocol != Protocol.VST, "VST does not support hostname verification"); + final ArangoDB arangoDB = new ArangoDB.Builder() + .host("127.0.0.1", 8529) + .password("test") + .useSsl(true) + .sslContext(createSslContext()) + .verifyHost(true) + .useProtocol(protocol) + .build(); + Throwable thrown = catchThrowable(arangoDB::getVersion); + assertThat(thrown).isInstanceOf(ArangoDBException.class); + ArangoDBException ex = (ArangoDBException) thrown; + assertThat(ex.getCause()).isInstanceOf(ArangoDBMultipleException.class); + List exceptions = ((ArangoDBMultipleException) ex.getCause()).getExceptions(); + exceptions.forEach(e -> assertThat(e).isInstanceOf(SSLHandshakeException.class)); + } + private SSLContext createSslContext() throws Exception { final KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType()); ks.load(this.getClass().getResourceAsStream(SSL_TRUSTSTORE), SSL_TRUSTSTORE_PASSWORD.toCharArray()); diff --git a/src/test/java/com/arangodb/mapping/annotations/ArangoAnnotationsTest.java b/src/test/java/com/arangodb/mapping/annotations/ArangoAnnotationsTest.java index 9f6165b4a..a2ca82f22 100644 --- a/src/test/java/com/arangodb/mapping/annotations/ArangoAnnotationsTest.java +++ b/src/test/java/com/arangodb/mapping/annotations/ArangoAnnotationsTest.java @@ -21,7 +21,7 @@ package com.arangodb.mapping.annotations; import com.arangodb.serde.ArangoSerde; -import com.arangodb.serde.DataType; +import com.arangodb.ContentType; import com.arangodb.serde.JacksonSerde; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.EnumSource; @@ -36,9 +36,9 @@ class ArangoAnnotationsTest { @ParameterizedTest - @EnumSource(DataType.class) - void documentFieldAnnotations(DataType dataType) { - ArangoSerde mapper = JacksonSerde.of(dataType); + @EnumSource(ContentType.class) + void documentFieldAnnotations(ContentType contentType) { + ArangoSerde mapper = JacksonSerde.of(contentType); AnnotatedEntity e = new AnnotatedEntity(); e.setId("Id"); diff --git a/src/test/java/com/arangodb/serde/CustomSerdeTest.java b/src/test/java/com/arangodb/serde/CustomSerdeTest.java index 6f67c0dda..c80665c1f 100644 --- a/src/test/java/com/arangodb/serde/CustomSerdeTest.java +++ b/src/test/java/com/arangodb/serde/CustomSerdeTest.java @@ -60,7 +60,7 @@ class CustomSerdeTest { @BeforeAll static void init() { - JacksonSerde serde = JacksonSerde.of(DataType.VPACK); + JacksonSerde serde = JacksonSerde.of(ContentType.VPACK); serde.configure((mapper) -> { mapper.configure(WRITE_SINGLE_ELEM_ARRAYS_UNWRAPPED, true); mapper.configure(USE_BIG_INTEGER_FOR_INTS, true); diff --git a/src/test/java/com/arangodb/serde/SerdeTest.java b/src/test/java/com/arangodb/serde/SerdeTest.java index d3bbe9e7d..73517f8b7 100644 --- a/src/test/java/com/arangodb/serde/SerdeTest.java +++ b/src/test/java/com/arangodb/serde/SerdeTest.java @@ -1,5 +1,6 @@ package com.arangodb.serde; +import com.arangodb.ContentType; import com.arangodb.internal.serde.InternalSerde; import com.arangodb.internal.serde.SerdeUtils; import com.arangodb.util.RawBytes; @@ -18,8 +19,8 @@ class SerdeTest { @ParameterizedTest - @EnumSource(DataType.class) - void rawJsonSerde(DataType type) { + @EnumSource(ContentType.class) + void rawJsonSerde(ContentType type) { InternalSerde s = InternalSerde.of(type, null); ObjectNode node = JsonNodeFactory.instance.objectNode().put("foo", "bar"); RawJson raw = RawJson.of(SerdeUtils.INSTANCE.writeJson(node)); @@ -29,8 +30,8 @@ void rawJsonSerde(DataType type) { } @ParameterizedTest - @EnumSource(DataType.class) - void rawBytesSerde(DataType type) { + @EnumSource(ContentType.class) + void rawBytesSerde(ContentType type) { InternalSerde s = InternalSerde.of(type, null); ObjectNode node = JsonNodeFactory.instance.objectNode().put("foo", "bar"); RawBytes raw = RawBytes.of(s.serialize(node)); @@ -40,8 +41,8 @@ void rawBytesSerde(DataType type) { } @ParameterizedTest - @EnumSource(DataType.class) - void utilDateSerde(DataType type) { + @EnumSource(ContentType.class) + void utilDateSerde(ContentType type) { InternalSerde s = InternalSerde.of(type, null); long ts = 1000000000000L; java.util.Date date = new java.util.Date(ts); @@ -54,8 +55,8 @@ void utilDateSerde(DataType type) { } @ParameterizedTest - @EnumSource(DataType.class) - void sqlDateSerde(DataType type) { + @EnumSource(ContentType.class) + void sqlDateSerde(ContentType type) { InternalSerde s = InternalSerde.of(type, null); long ts = 1000000000000L; java.sql.Date date = new Date(ts); From 0d5f175df05be2b3aae2513da13a03baf76dca43 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Wed, 19 Oct 2022 09:34:55 +0200 Subject: [PATCH 149/254] code cleanup --- .../entity/arangosearch/analyzer/IdentityAnalyzer.java | 5 ----- .../com/arangodb/internal/InternalArangoCollection.java | 9 ++------- .../internal/cursor/entity/InternalCursorEntity.java | 2 -- .../java/com/arangodb/internal/http/HttpConnection.java | 2 +- .../com/arangodb/internal/net/ConnectionPoolImpl.java | 2 +- .../arangodb/internal/velocystream/VstCommunication.java | 2 +- .../java/com/arangodb/model/CollectionCreateOptions.java | 2 +- 7 files changed, 6 insertions(+), 18 deletions(-) diff --git a/src/main/java/com/arangodb/entity/arangosearch/analyzer/IdentityAnalyzer.java b/src/main/java/com/arangodb/entity/arangosearch/analyzer/IdentityAnalyzer.java index 14fbfefd5..dbb412397 100644 --- a/src/main/java/com/arangodb/entity/arangosearch/analyzer/IdentityAnalyzer.java +++ b/src/main/java/com/arangodb/entity/arangosearch/analyzer/IdentityAnalyzer.java @@ -40,9 +40,4 @@ public boolean equals(Object o) { if (o == null || getClass() != o.getClass()) return false; return super.equals(o); } - - @Override - public int hashCode() { - return super.hashCode(); - } } diff --git a/src/main/java/com/arangodb/internal/InternalArangoCollection.java b/src/main/java/com/arangodb/internal/InternalArangoCollection.java index 6b311dac6..5e77606b0 100644 --- a/src/main/java/com/arangodb/internal/InternalArangoCollection.java +++ b/src/main/java/com/arangodb/internal/InternalArangoCollection.java @@ -37,7 +37,6 @@ import java.util.Collection; import java.util.Iterator; -import static com.arangodb.internal.serde.SerdeUtils.constructListType; import static com.arangodb.internal.serde.SerdeUtils.constructParametricType; /** @@ -510,9 +509,7 @@ protected Request getIndexesRequest() { protected ResponseDeserializer> getIndexesResponseDeserializer() { return response -> { Collection indexes = new ArrayList<>(); - final Iterator it = getSerde().parse(response.getBody(), "/indexes").iterator(); - while (it.hasNext()) { - JsonNode idx = it.next(); + for (JsonNode idx : getSerde().parse(response.getBody(), "/indexes")) { if (!"inverted".equals(idx.get("type").textValue())) { indexes.add(getSerde().deserialize(idx, IndexEntity.class)); } @@ -524,9 +521,7 @@ protected ResponseDeserializer> getIndexesResponseDeseri protected ResponseDeserializer> getInvertedIndexesResponseDeserializer() { return response -> { Collection indexes = new ArrayList<>(); - final Iterator it = getSerde().parse(response.getBody(), "/indexes").iterator(); - while (it.hasNext()) { - JsonNode idx = it.next(); + for (JsonNode idx : getSerde().parse(response.getBody(), "/indexes")) { if ("inverted".equals(idx.get("type").textValue())) { indexes.add(getSerde().deserialize(idx, InvertedIndexEntity.class)); } diff --git a/src/main/java/com/arangodb/internal/cursor/entity/InternalCursorEntity.java b/src/main/java/com/arangodb/internal/cursor/entity/InternalCursorEntity.java index abaa5ad41..1145d5646 100644 --- a/src/main/java/com/arangodb/internal/cursor/entity/InternalCursorEntity.java +++ b/src/main/java/com/arangodb/internal/cursor/entity/InternalCursorEntity.java @@ -28,8 +28,6 @@ import java.util.Collections; import java.util.HashMap; import java.util.Map; -import java.util.function.Function; -import java.util.stream.Collectors; /** * @author Mark Vollmary diff --git a/src/main/java/com/arangodb/internal/http/HttpConnection.java b/src/main/java/com/arangodb/internal/http/HttpConnection.java index c79ae72d7..bb6cf59c3 100644 --- a/src/main/java/com/arangodb/internal/http/HttpConnection.java +++ b/src/main/java/com/arangodb/internal/http/HttpConnection.java @@ -196,7 +196,7 @@ private static void addHeader(final Request request, final HttpRequest httpRe } @Override - public void close() throws IOException { + public void close() { client.close(); vertx.close(); } diff --git a/src/main/java/com/arangodb/internal/net/ConnectionPoolImpl.java b/src/main/java/com/arangodb/internal/net/ConnectionPoolImpl.java index 652dbf353..597445d4b 100644 --- a/src/main/java/com/arangodb/internal/net/ConnectionPoolImpl.java +++ b/src/main/java/com/arangodb/internal/net/ConnectionPoolImpl.java @@ -75,7 +75,7 @@ public synchronized Connection connection() { } if (connection instanceof VstConnectionSync) { - LOGGER.debug("Return Connection " + ((VstConnection) connection).getConnectionName()); + LOGGER.debug("Return Connection " + ((VstConnection) connection).getConnectionName()); } return connection; diff --git a/src/main/java/com/arangodb/internal/velocystream/VstCommunication.java b/src/main/java/com/arangodb/internal/velocystream/VstCommunication.java index 192aa1e71..67c2f2961 100644 --- a/src/main/java/com/arangodb/internal/velocystream/VstCommunication.java +++ b/src/main/java/com/arangodb/internal/velocystream/VstCommunication.java @@ -49,7 +49,7 @@ /** * @author Mark Vollmary */ -public abstract class VstCommunication implements Closeable { +public abstract class VstCommunication> implements Closeable { protected static final String ENCRYPTION_PLAIN = "plain"; protected static final String ENCRYPTION_JWT = "jwt"; diff --git a/src/main/java/com/arangodb/model/CollectionCreateOptions.java b/src/main/java/com/arangodb/model/CollectionCreateOptions.java index 856bc03ae..89ed62e93 100644 --- a/src/main/java/com/arangodb/model/CollectionCreateOptions.java +++ b/src/main/java/com/arangodb/model/CollectionCreateOptions.java @@ -41,7 +41,7 @@ public final class CollectionCreateOptions { private Integer writeConcern; private KeyOptions keyOptions; private Boolean waitForSync; - private List computedValues = new ArrayList<>(); + private final List computedValues = new ArrayList<>(); private Collection shardKeys; private Integer numberOfShards; private Boolean isSystem; From f0ee278fdfd2f091212a21dd029155ed71a5dc70 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Wed, 19 Oct 2022 10:43:55 +0200 Subject: [PATCH 150/254] javadoc fixes --- .../arangodb/entity/arangosearch/ConsolidationPolicy.java | 8 +------- .../java/com/arangodb/model/DocumentCreateOptions.java | 2 +- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/src/main/java/com/arangodb/entity/arangosearch/ConsolidationPolicy.java b/src/main/java/com/arangodb/entity/arangosearch/ConsolidationPolicy.java index fb0fe6244..9148ff7c7 100644 --- a/src/main/java/com/arangodb/entity/arangosearch/ConsolidationPolicy.java +++ b/src/main/java/com/arangodb/entity/arangosearch/ConsolidationPolicy.java @@ -49,13 +49,7 @@ public ConsolidationPolicy type(final ConsolidationType type) { } /** - * @param threshold Select a given segment for "consolidation" if and only if the formula based on type (as defined - * above) evaluates to true, valid value range [0.0, 1.0] (default: 0.85) - * @param threshold Defines threshold value of [0.0, 1.0] possible range. Consolidation is performed on segments - * which accumulated size in bytes is less than all segments’ byte size multiplied by the - * threshold; i.e. the following formula is applied for each segment: {threshold} > (segment_bytes - * + sum_of_merge_candidate_segment_bytes) / all_segment_bytes. (default: 0.1) - * @return policy + * @param threshold value in the range [0.0, 1.0] * @return this */ public ConsolidationPolicy threshold(final Double threshold) { diff --git a/src/main/java/com/arangodb/model/DocumentCreateOptions.java b/src/main/java/com/arangodb/model/DocumentCreateOptions.java index a510ff32f..f90845950 100644 --- a/src/main/java/com/arangodb/model/DocumentCreateOptions.java +++ b/src/main/java/com/arangodb/model/DocumentCreateOptions.java @@ -130,7 +130,7 @@ public Boolean getMergeObjects() { } /** - * Only considered if {@link this#overwriteMode} is set to {@link OverwriteMode#update} + * Only considered if {@link DocumentCreateOptions#overwriteMode(OverwriteMode)} is set to {@link OverwriteMode#update} * * @param mergeObjects Controls whether objects (not arrays) will be merged if present in both the existing and * the patch From 33e3963dc062c2914d3ede3c9e726c273c568186 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Wed, 19 Oct 2022 11:11:19 +0200 Subject: [PATCH 151/254] [DE-409] fixed resiliency tests --- pom.xml | 7 +++++++ .../java/com/arangodb/internal/http/HttpConnection.java | 6 ++++-- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index b8d177cb9..84d2bd845 100644 --- a/pom.xml +++ b/pom.xml @@ -408,6 +408,13 @@ pom import + + io.netty + netty-bom + 4.1.82.Final + pom + import + org.junit junit-bom diff --git a/src/main/java/com/arangodb/internal/http/HttpConnection.java b/src/main/java/com/arangodb/internal/http/HttpConnection.java index bb6cf59c3..c3c502921 100644 --- a/src/main/java/com/arangodb/internal/http/HttpConnection.java +++ b/src/main/java/com/arangodb/internal/http/HttpConnection.java @@ -254,12 +254,14 @@ public Response execute(final Request request) throws IOException { try { // FIXME: make async API bufferResponse = httpRequest.sendBuffer(buffer).toCompletionStage().toCompletableFuture().get(); - } catch (InterruptedException | ExecutionException e) { + } catch (InterruptedException e) { + throw new ArangoDBException(e); + } catch (ExecutionException e) { Throwable cause = e.getCause(); if (cause instanceof IOException) { throw (IOException) cause; } else { - throw new ArangoDBException(e); + throw new ArangoDBException(e.getCause()); } } Response response = buildResponse(bufferResponse); From c3759796fac256a53b64903137de418fad0ee08d Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Thu, 20 Oct 2022 15:39:08 +0200 Subject: [PATCH 152/254] benchmark logs --- src/test/java/perf/SyncBenchmarkTest.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/test/java/perf/SyncBenchmarkTest.java b/src/test/java/perf/SyncBenchmarkTest.java index fb8fea25f..8a5fa5a51 100644 --- a/src/test/java/perf/SyncBenchmarkTest.java +++ b/src/test/java/perf/SyncBenchmarkTest.java @@ -17,6 +17,10 @@ public class SyncBenchmarkTest { @ParameterizedTest @EnumSource(Protocol.class) void getVersion(Protocol protocol) { + System.out.println("-----------------------------------------"); + System.out.println("--- getVersion(): " + protocol); + System.out.println("-----------------------------------------"); + ArangoDB adb = new ArangoDB.Builder().useProtocol(protocol).build(); Benchmark benchmark = new Benchmark(warmupDurationSeconds, numberOfRequests) { @Override @@ -37,6 +41,10 @@ protected void shutdown() { @ParameterizedTest @EnumSource(Protocol.class) void getVersionWithDetails(Protocol protocol) { + System.out.println("-----------------------------------------"); + System.out.println("--- getVersion w/ details: " + protocol); + System.out.println("-----------------------------------------"); + ArangoDB adb = new ArangoDB.Builder().useProtocol(protocol).build(); Benchmark benchmark = new Benchmark(warmupDurationSeconds, numberOfRequests) { private final Request request = new Request(DbName.SYSTEM, RequestType.GET, From 990dcfae77416f33a86a9ba9f3717206e7008704 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Fri, 21 Oct 2022 10:01:40 +0200 Subject: [PATCH 153/254] execute http request in vertx context --- .../java/com/arangodb/ArangoDBException.java | 8 +++ .../internal/http/HttpConnection.java | 57 ++++++++++++------- 2 files changed, 43 insertions(+), 22 deletions(-) diff --git a/src/main/java/com/arangodb/ArangoDBException.java b/src/main/java/com/arangodb/ArangoDBException.java index 6ea9ce8c8..015c0b585 100644 --- a/src/main/java/com/arangodb/ArangoDBException.java +++ b/src/main/java/com/arangodb/ArangoDBException.java @@ -62,6 +62,14 @@ public ArangoDBException(final String message, final Throwable cause) { this.responseCode = null; } + public static ArangoDBException wrap(Throwable t) { + if (t instanceof ArangoDBException) { + return (ArangoDBException) t; + } else { + return new ArangoDBException(t); + } + } + /** * @return ArangoDB error message */ diff --git a/src/main/java/com/arangodb/internal/http/HttpConnection.java b/src/main/java/com/arangodb/internal/http/HttpConnection.java index c3c502921..df0b463e0 100644 --- a/src/main/java/com/arangodb/internal/http/HttpConnection.java +++ b/src/main/java/com/arangodb/internal/http/HttpConnection.java @@ -60,6 +60,7 @@ import java.security.NoSuchAlgorithmException; import java.util.Iterator; import java.util.Map.Entry; +import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; @@ -67,6 +68,7 @@ /** * @author Mark Vollmary + * @author Michele Rastelli */ public class HttpConnection implements Connection { private static final Logger LOGGER = LoggerFactory.getLogger(HttpCommunication.class); @@ -76,7 +78,7 @@ public class HttpConnection implements Connection { private final InternalSerde util; private final String baseUrl; private final ContentType contentType; - private volatile String auth; + private String auth; private final WebClient client; private final Integer timeout; private final Vertx vertx; @@ -89,9 +91,12 @@ private HttpConnection(final HostDescription host, final Integer timeout, final this.contentType = ContentType.of(protocol); this.timeout = timeout; baseUrl = buildBaseUrl(host, useSsl); - auth = new UsernamePasswordCredentials(user, password != null ? password : "").toHttpAuthorization(); vertx = Vertx.vertx(new VertxOptions().setPreferNativeTransport(true).setEventLoopPoolSize(1)); - vertx.runOnContext(e -> Thread.currentThread().setName("adb-eventloop-" + THREAD_COUNT.getAndIncrement())); + vertx.runOnContext(e -> { + Thread.currentThread().setName("adb-eventloop-" + THREAD_COUNT.getAndIncrement()); + auth = new UsernamePasswordCredentials(user, password != null ? password : "").toHttpAuthorization(); + LOGGER.debug("Created Vert.x context"); + }); int _ttl = ttl == null ? 0 : Math.toIntExact(ttl / 1000); @@ -224,6 +229,26 @@ private String buildBaseUrl(HostDescription host, boolean useSsl) { } public Response execute(final Request request) throws IOException { + CompletableFuture rfuture = new CompletableFuture<>(); + vertx.runOnContext(e -> doExecute(request, rfuture)); + Response resp; + try { + resp = rfuture.get(); + } catch (InterruptedException e) { + throw ArangoDBException.wrap(e); + } catch (ExecutionException e) { + Throwable cause = e.getCause(); + if (cause instanceof IOException) { + throw (IOException) cause; + } else { + throw ArangoDBException.wrap(e.getCause()); + } + } + checkError(resp); + return resp; + } + + public void doExecute(final Request request, final CompletableFuture rfuture) { String path = buildUrl(request); HttpRequest httpRequest = client .request(requestTypeToHttpMethod(request.getRequestType()), path) @@ -250,26 +275,14 @@ public Response execute(final Request request) throws IOException { } else { buffer = Buffer.buffer(); } - HttpResponse bufferResponse; - try { - // FIXME: make async API - bufferResponse = httpRequest.sendBuffer(buffer).toCompletionStage().toCompletableFuture().get(); - } catch (InterruptedException e) { - throw new ArangoDBException(e); - } catch (ExecutionException e) { - Throwable cause = e.getCause(); - if (cause instanceof IOException) { - throw (IOException) cause; - } else { - throw new ArangoDBException(e.getCause()); - } - } - Response response = buildResponse(bufferResponse); - checkError(response); - return response; + + httpRequest.sendBuffer(buffer) + .map(this::buildResponse) + .onSuccess(rfuture::complete) + .onFailure(rfuture::completeExceptionally); } - public Response buildResponse(final HttpResponse httpResponse) throws UnsupportedOperationException { + private Response buildResponse(final HttpResponse httpResponse) { final Response response = new Response(); response.setResponseCode(httpResponse.statusCode()); Buffer body = httpResponse.body(); @@ -292,7 +305,7 @@ protected void checkError(final Response response) { @Override public void setJwt(String jwt) { if (jwt != null) { - auth = new TokenCredentials(jwt).toHttpAuthorization(); + vertx.runOnContext((e) -> auth = new TokenCredentials(jwt).toHttpAuthorization()); } } From a99ff3743f3354e34995460c133c74a923e1d392 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Fri, 21 Oct 2022 10:15:12 +0200 Subject: [PATCH 154/254] explicitly disabled Jackson default typing --- src/main/java/com/arangodb/internal/serde/InternalSerdeImpl.java | 1 + src/main/java/com/arangodb/internal/serde/JacksonSerdeImpl.java | 1 + 2 files changed, 2 insertions(+) diff --git a/src/main/java/com/arangodb/internal/serde/InternalSerdeImpl.java b/src/main/java/com/arangodb/internal/serde/InternalSerdeImpl.java index cf6c70e6a..9ade5dbbf 100644 --- a/src/main/java/com/arangodb/internal/serde/InternalSerdeImpl.java +++ b/src/main/java/com/arangodb/internal/serde/InternalSerdeImpl.java @@ -31,6 +31,7 @@ final class InternalSerdeImpl extends JacksonSerdeImpl implements InternalSerde this.userSerde = userSerde; mapper.registerModule(InternalModule.INSTANCE.get()); mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); + mapper.deactivateDefaultTyping(); mapper.setAnnotationIntrospector(new InternalAnnotationIntrospector( new UserDataSerializer(this), new UserDataDeserializer(this) diff --git a/src/main/java/com/arangodb/internal/serde/JacksonSerdeImpl.java b/src/main/java/com/arangodb/internal/serde/JacksonSerdeImpl.java index 90f27ae6b..cf24b9f01 100644 --- a/src/main/java/com/arangodb/internal/serde/JacksonSerdeImpl.java +++ b/src/main/java/com/arangodb/internal/serde/JacksonSerdeImpl.java @@ -16,6 +16,7 @@ public class JacksonSerdeImpl implements JacksonSerde { public JacksonSerdeImpl(final ObjectMapper mapper) { this.mapper = mapper; + mapper.deactivateDefaultTyping(); mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); } From 1150c44079c9ad7686a5290ec3a871e9ebe99f48 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Fri, 21 Oct 2022 20:27:17 +0200 Subject: [PATCH 155/254] fixed query params encoding --- .../internal/http/HttpConnection.java | 23 ++++++++----------- .../com/arangodb/velocystream/Request.java | 4 ---- 2 files changed, 9 insertions(+), 18 deletions(-) diff --git a/src/main/java/com/arangodb/internal/http/HttpConnection.java b/src/main/java/com/arangodb/internal/http/HttpConnection.java index df0b463e0..847adad16 100644 --- a/src/main/java/com/arangodb/internal/http/HttpConnection.java +++ b/src/main/java/com/arangodb/internal/http/HttpConnection.java @@ -26,6 +26,7 @@ import com.arangodb.internal.net.Connection; import com.arangodb.internal.net.HostDescription; import com.arangodb.internal.serde.InternalSerde; +import com.arangodb.internal.util.EncodeUtils; import com.arangodb.internal.util.ResponseUtils; import com.arangodb.ContentType; import com.arangodb.velocystream.Request; @@ -173,23 +174,17 @@ private static String buildUrl(final Request request) { sb.append(request.getRequest()); if (!request.getQueryParam().isEmpty()) { sb.append("?"); - - try { - for (Iterator> iterator = request.getQueryParam().entrySet().iterator(); iterator.hasNext(); ) { - Entry param = iterator.next(); - if (param.getValue() != null) { - sb.append(URLEncoder.encode(param.getKey(), StandardCharsets.UTF_8.toString())); - sb.append("="); - sb.append(URLEncoder.encode(param.getValue(), StandardCharsets.UTF_8.toString())); - if (iterator.hasNext()) { - sb.append("&"); - } + for (Iterator> iterator = request.getQueryParam().entrySet().iterator(); iterator.hasNext(); ) { + Entry param = iterator.next(); + if (param.getValue() != null) { + sb.append(EncodeUtils.encodeURIComponent(param.getKey())); + sb.append("="); + sb.append(EncodeUtils.encodeURIComponent(param.getValue())); + if (iterator.hasNext()) { + sb.append("&"); } } - } catch (UnsupportedEncodingException e) { - throw new RuntimeException(e); } - } return sb.toString(); } diff --git a/src/main/java/com/arangodb/velocystream/Request.java b/src/main/java/com/arangodb/velocystream/Request.java index 4802c6c00..348082605 100644 --- a/src/main/java/com/arangodb/velocystream/Request.java +++ b/src/main/java/com/arangodb/velocystream/Request.java @@ -96,10 +96,6 @@ public Map getHeaderParam() { return Collections.unmodifiableMap(headerParam); } - public String getHeaderParam(final String key) { - return headerParam.get(key.toLowerCase(Locale.ROOT)); - } - public boolean containsHeaderParam(final String key) { return headerParam.containsKey(key.toLowerCase(Locale.ROOT)); } From 46d1204c1b9e79483fc2ae90487c02c813a64af2 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Mon, 24 Oct 2022 11:36:01 +0200 Subject: [PATCH 156/254] [DE-421] http debug logs --- src/main/java/com/arangodb/ArangoDB.java | 2 +- .../com/arangodb/internal/ArangoDBImpl.java | 23 +----- .../arangodb/internal/http/CURLLogger.java | 74 ------------------- .../internal/http/HttpCommunication.java | 33 ++++++--- .../internal/http/HttpConnection.java | 15 +--- .../com/arangodb/velocystream/Request.java | 11 +++ .../com/arangodb/velocystream/Response.java | 7 ++ src/test/resources/logback-test.xml | 1 + 8 files changed, 47 insertions(+), 119 deletions(-) delete mode 100644 src/main/java/com/arangodb/internal/http/CURLLogger.java diff --git a/src/main/java/com/arangodb/ArangoDB.java b/src/main/java/com/arangodb/ArangoDB.java index cb4186127..8fe9fe51b 100644 --- a/src/main/java/com/arangodb/ArangoDB.java +++ b/src/main/java/com/arangodb/ArangoDB.java @@ -612,7 +612,7 @@ public ArangoDB build() { new VstCommunicationSync.Builder(hostHandler).timeout(timeout).user(user).password(password) .jwt(jwt).useSsl(useSsl).sslContext(sslContext).chunksize(chunksize) .maxConnections(maxConnections).connectionTtl(connectionTtl), - new HttpCommunication.Builder(hostHandler), + new HttpCommunication.Builder().hostHandler(hostHandler), serde, protocol, hostResolver, diff --git a/src/main/java/com/arangodb/internal/ArangoDBImpl.java b/src/main/java/com/arangodb/internal/ArangoDBImpl.java index a981c024f..6c11ded4c 100644 --- a/src/main/java/com/arangodb/internal/ArangoDBImpl.java +++ b/src/main/java/com/arangodb/internal/ArangoDBImpl.java @@ -41,7 +41,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.io.IOException; import java.util.Collection; /** @@ -52,7 +51,6 @@ public class ArangoDBImpl extends InternalArangoDB implements ArangoDB { private static final Logger LOGGER = LoggerFactory.getLogger(ArangoDBImpl.class); - private final CommunicationProtocol cp; private final HostHandler hostHandler; public ArangoDBImpl(final VstCommunicationSync.Builder vstBuilder, final HttpCommunication.Builder httpBuilder, @@ -65,17 +63,9 @@ public ArangoDBImpl(final VstCommunicationSync.Builder vstBuilder, final HttpCom util, new QueueTimeMetricsImpl(responseQueueTimeSamples), timeoutMs), util); - cp = createProtocol( - new VstCommunicationSync.Builder(vstBuilder).maxConnections(1), - new HttpCommunication.Builder(httpBuilder), - util, - protocol); this.hostHandler = hostHandler; - hostResolver.init(this.executor(), getSerde()); - LOGGER.debug("ArangoDB Client is ready to use"); - } private static CommunicationProtocol createProtocol( @@ -97,7 +87,7 @@ private static CommunicationProtocol createVST( private static CommunicationProtocol createHTTP( final HttpCommunication.Builder builder, final InternalSerde util) { - return new HttpProtocol(builder.build(util)); + return new HttpProtocol(builder.serde(util).build()); } @Override @@ -107,21 +97,12 @@ protected ArangoExecutorSync executor() { @Override public void shutdown() { - try { - executor.disconnect(); - } finally { - try { - cp.close(); - } catch (final IOException e) { - LOGGER.error("Got exception during shutdown:", e); - } - } + executor.disconnect(); } @Override public void updateJwt(String jwt) { hostHandler.setJwt(jwt); - cp.setJwt(jwt); executor.setJwt(jwt); } diff --git a/src/main/java/com/arangodb/internal/http/CURLLogger.java b/src/main/java/com/arangodb/internal/http/CURLLogger.java deleted file mode 100644 index b2e72418b..000000000 --- a/src/main/java/com/arangodb/internal/http/CURLLogger.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.internal.http; - -import com.arangodb.internal.serde.InternalSerde; -import com.arangodb.velocystream.Request; -import com.arangodb.velocystream.RequestType; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.Map.Entry; - -/** - * @author Mark Vollmary - */ -public final class CURLLogger { - - private static final Logger LOGGER = LoggerFactory.getLogger(CURLLogger.class); - - private CURLLogger() { - } - - public static void log( - final String baseUrl, - final String path, - final Request request, - final InternalSerde util) { - final RequestType requestType = request.getRequestType(); - final boolean includeBody = (requestType == RequestType.POST || requestType == RequestType.PUT - || requestType == RequestType.PATCH || requestType == RequestType.DELETE) && request.getBody() != null; - final StringBuilder buffer = new StringBuilder(); - if (includeBody) { - buffer.append("\n"); - buffer.append("cat <<-___EOB___ | "); - } - buffer.append("curl -X ").append(requestType); - // FIXME: add --http2 in case protocol is HTTP/2 - buffer.append(" --dump -"); - if (request.getHeaderParam().size() > 0) { - for (final Entry header : request.getHeaderParam().entrySet()) { - buffer.append(" -H '").append(header.getKey()).append(":").append(header.getValue()).append("'"); - } - } - if (includeBody) { - buffer.append(" -d @-"); - } - buffer.append(" '").append(baseUrl).append(path).append("'"); - if (includeBody) { - buffer.append("\n"); - buffer.append(util.toJsonString(request.getBody())); - buffer.append("\n"); - buffer.append("___EOB___"); - } - LOGGER.debug("[CURL] {}", buffer); - } -} diff --git a/src/main/java/com/arangodb/internal/http/HttpCommunication.java b/src/main/java/com/arangodb/internal/http/HttpCommunication.java index a8899af6e..48ff99215 100644 --- a/src/main/java/com/arangodb/internal/http/HttpCommunication.java +++ b/src/main/java/com/arangodb/internal/http/HttpCommunication.java @@ -34,6 +34,7 @@ import java.io.IOException; import java.net.SocketTimeoutException; import java.util.concurrent.TimeoutException; +import java.util.concurrent.atomic.AtomicInteger; /** * @author Mark Vollmary @@ -42,10 +43,14 @@ public class HttpCommunication implements Closeable { private static final Logger LOGGER = LoggerFactory.getLogger(HttpCommunication.class); private final HostHandler hostHandler; + private final InternalSerde serde; + private final AtomicInteger reqCount; - private HttpCommunication(final HostHandler hostHandler) { + private HttpCommunication(final HostHandler hostHandler, final InternalSerde serde) { super(); this.hostHandler = hostHandler; + this.serde = serde; + reqCount = new AtomicInteger(); } @Override @@ -62,9 +67,18 @@ private Response execute(final Request request, final HostHandle hostHandle, fin Host host = hostHandler.get(hostHandle, accessType); try { while (true) { + int reqId = reqCount.getAndIncrement(); try { final HttpConnection connection = (HttpConnection) host.connection(); + if (LOGGER.isDebugEnabled()) { + String body = request.getBody() == null ? "" : serde.toJsonString(request.getBody()); + LOGGER.debug("Send Request [id={}]: {} {}", reqId, request, body); + } final Response response = connection.execute(request); + if (LOGGER.isDebugEnabled()) { + String body = response.getBody() == null ? "" : serde.toJsonString(response.getBody()); + LOGGER.debug("Received Response [id={}]: {} {}", reqId, response, body); + } hostHandler.success(); hostHandler.confirm(); return response; @@ -105,20 +119,21 @@ private Response execute(final Request request, final HostHandle hostHandle, fin } public static class Builder { + private HostHandler hostHandler; + private InternalSerde serde; - private final HostHandler hostHandler; - - public Builder(final HostHandler hostHandler) { - super(); + public Builder hostHandler(HostHandler hostHandler) { this.hostHandler = hostHandler; + return this; } - public Builder(final Builder builder) { - this(builder.hostHandler); + public Builder serde(InternalSerde serde) { + this.serde = serde; + return this; } - public HttpCommunication build(final InternalSerde util) { - return new HttpCommunication(hostHandler); + public HttpCommunication build() { + return new HttpCommunication(hostHandler, serde); } } diff --git a/src/main/java/com/arangodb/internal/http/HttpConnection.java b/src/main/java/com/arangodb/internal/http/HttpConnection.java index 847adad16..c0ad5a1de 100644 --- a/src/main/java/com/arangodb/internal/http/HttpConnection.java +++ b/src/main/java/com/arangodb/internal/http/HttpConnection.java @@ -21,6 +21,7 @@ package com.arangodb.internal.http; import com.arangodb.ArangoDBException; +import com.arangodb.ContentType; import com.arangodb.DbName; import com.arangodb.Protocol; import com.arangodb.internal.net.Connection; @@ -28,7 +29,6 @@ import com.arangodb.internal.serde.InternalSerde; import com.arangodb.internal.util.EncodeUtils; import com.arangodb.internal.util.ResponseUtils; -import com.arangodb.ContentType; import com.arangodb.velocystream.Request; import com.arangodb.velocystream.RequestType; import com.arangodb.velocystream.Response; @@ -55,9 +55,6 @@ import javax.net.ssl.SSLContext; import java.io.IOException; -import java.io.UnsupportedEncodingException; -import java.net.URLEncoder; -import java.nio.charset.StandardCharsets; import java.security.NoSuchAlgorithmException; import java.util.Iterator; import java.util.Map.Entry; @@ -77,7 +74,6 @@ public class HttpConnection implements Connection { private static final String CONTENT_TYPE_VPACK = "application/x-velocypack"; private static final AtomicInteger THREAD_COUNT = new AtomicInteger(); private final InternalSerde util; - private final String baseUrl; private final ContentType contentType; private String auth; private final WebClient client; @@ -91,7 +87,6 @@ private HttpConnection(final HostDescription host, final Integer timeout, final this.util = util; this.contentType = ContentType.of(protocol); this.timeout = timeout; - baseUrl = buildBaseUrl(host, useSsl); vertx = Vertx.vertx(new VertxOptions().setPreferNativeTransport(true).setEventLoopPoolSize(1)); vertx.runOnContext(e -> { Thread.currentThread().setName("adb-eventloop-" + THREAD_COUNT.getAndIncrement()); @@ -219,10 +214,6 @@ private HttpMethod requestTypeToHttpMethod(RequestType requestType) { } } - private String buildBaseUrl(HostDescription host, boolean useSsl) { - return (Boolean.TRUE.equals(useSsl) ? "https://" : "http://") + host.getHost() + ":" + host.getPort(); - } - public Response execute(final Request request) throws IOException { CompletableFuture rfuture = new CompletableFuture<>(); vertx.runOnContext(e -> doExecute(request, rfuture)); @@ -254,10 +245,6 @@ public void doExecute(final Request request, final CompletableFuture r addHeader(request, httpRequest); httpRequest.putHeader(HttpHeaders.AUTHORIZATION.toString(), auth); - if (LOGGER.isDebugEnabled()) { - CURLLogger.log(baseUrl, path, request, util); - } - byte[] reqBody = request.getBody(); Buffer buffer; if (reqBody != null) { diff --git a/src/main/java/com/arangodb/velocystream/Request.java b/src/main/java/com/arangodb/velocystream/Request.java index 348082605..5fd5fd8a9 100644 --- a/src/main/java/com/arangodb/velocystream/Request.java +++ b/src/main/java/com/arangodb/velocystream/Request.java @@ -125,4 +125,15 @@ public Request setBody(final byte[] body) { return this; } + @Override + public String toString() { + return "{" + + "requestType=" + requestType + + ", database='" + dbName + '\'' + + ", url='" + request + '\'' + + ", parameters=" + queryParam + + ", headers=" + headerParam + + '}'; + } + } diff --git a/src/main/java/com/arangodb/velocystream/Response.java b/src/main/java/com/arangodb/velocystream/Response.java index 9b5cf6fd8..b20667131 100644 --- a/src/main/java/com/arangodb/velocystream/Response.java +++ b/src/main/java/com/arangodb/velocystream/Response.java @@ -95,4 +95,11 @@ public void setBody(final byte[] body) { this.body = body; } + @Override + public String toString() { + return "{" + + "statusCode=" + responseCode + + ", headers=" + meta + + '}'; + } } diff --git a/src/test/resources/logback-test.xml b/src/test/resources/logback-test.xml index f67855e9c..b1d65b196 100644 --- a/src/test/resources/logback-test.xml +++ b/src/test/resources/logback-test.xml @@ -12,6 +12,7 @@ + From 45002557c88e76ccc532f68599843f87d5a5a949 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Mon, 24 Oct 2022 12:31:54 +0200 Subject: [PATCH 157/254] updated test docker images --- .github/workflows/maven.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index 323ece6ed..2db0f0546 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -23,10 +23,10 @@ jobs: docker-img: - docker.io/arangodb/arangodb:3.8.7 - docker.io/arangodb/arangodb:3.9.3 - - docker.io/arangodb/arangodb-preview:3.10-nightly + - docker.io/arangodb/arangodb:3.10.0 - docker.io/arangodb/enterprise:3.8.7 - docker.io/arangodb/enterprise:3.9.3 - - docker.io/arangodb/enterprise-preview:3.10-nightly + - docker.io/arangodb/enterprise:3.10.0 topology: - single - cluster From 38a6dce8d675389685497bd611151e8b7d77d9b2 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Mon, 24 Oct 2022 14:21:10 +0200 Subject: [PATCH 158/254] [DE-414] removed default host 127.0.0.1 --- src/main/java/com/arangodb/ArangoDB.java | 5 +---- .../com/arangodb/async/ArangoDBAsync.java | 7 ++---- .../VstConnectionFactoryAsync.java | 2 +- .../com/arangodb/internal/ArangoDefaults.java | 2 -- .../internal/InternalArangoDBBuilder.java | 22 ------------------- .../VstConnectionFactorySync.java | 2 +- src/test/java/com/arangodb/ArangoDBTest.java | 10 --------- src/test/resources/arangodb-bad2.properties | 1 - 8 files changed, 5 insertions(+), 46 deletions(-) delete mode 100644 src/test/resources/arangodb-bad2.properties diff --git a/src/main/java/com/arangodb/ArangoDB.java b/src/main/java/com/arangodb/ArangoDB.java index 8fe9fe51b..74ea7fca0 100644 --- a/src/main/java/com/arangodb/ArangoDB.java +++ b/src/main/java/com/arangodb/ArangoDB.java @@ -586,9 +586,6 @@ public Builder serializer(final ArangoSerde serialization) { * @return {@link ArangoDB} */ public ArangoDB build() { - if (hosts.isEmpty()) { - hosts.add(host); - } final ArangoSerde userSerde = customSerializer != null ? customSerializer : JacksonSerde.of(ContentType.of(protocol)); final InternalSerde serde = InternalSerde.of(ContentType.of(protocol), userSerde); @@ -599,7 +596,7 @@ public ArangoDB build() { final int max = maxConnections != null ? Math.max(1, maxConnections) : protocolMaxConnections; final ConnectionFactory connectionFactory = (protocol == null || Protocol.VST == protocol) - ? new VstConnectionFactorySync(host, timeout, connectionTtl, keepAliveInterval, useSsl, sslContext) + ? new VstConnectionFactorySync(timeout, connectionTtl, keepAliveInterval, useSsl, sslContext) : new HttpConnectionFactory(timeout, user, password, useSsl, sslContext, verifyHost, serde, protocol, connectionTtl); diff --git a/src/main/java/com/arangodb/async/ArangoDBAsync.java b/src/main/java/com/arangodb/async/ArangoDBAsync.java index 327cd7cfa..c5ad894d7 100644 --- a/src/main/java/com/arangodb/async/ArangoDBAsync.java +++ b/src/main/java/com/arangodb/async/ArangoDBAsync.java @@ -516,17 +516,14 @@ public Builder serializer(final ArangoSerde serialization) { * @return {@link ArangoDBAsync} */ public ArangoDBAsync build() { - if (hosts.isEmpty()) { - hosts.add(host); - } final ArangoSerde userSerde = customSerializer != null ? customSerializer : JacksonSerde.of(ContentType.VPACK); final InternalSerde serde = InternalSerde.of(ContentType.VPACK, userSerde); final int max = maxConnections != null ? Math.max(1, maxConnections) : ArangoDefaults.MAX_CONNECTIONS_VST_DEFAULT; - final ConnectionFactory syncConnectionFactory = new VstConnectionFactorySync(host, timeout, connectionTtl, + final ConnectionFactory syncConnectionFactory = new VstConnectionFactorySync(timeout, connectionTtl, keepAliveInterval, useSsl, sslContext); - final ConnectionFactory asyncConnectionFactory = new VstConnectionFactoryAsync(host, timeout, connectionTtl, + final ConnectionFactory asyncConnectionFactory = new VstConnectionFactoryAsync(timeout, connectionTtl, keepAliveInterval, useSsl, sslContext); final HostResolver syncHostResolver = createHostResolver(createHostList(max, syncConnectionFactory), max, syncConnectionFactory); diff --git a/src/main/java/com/arangodb/async/internal/velocystream/VstConnectionFactoryAsync.java b/src/main/java/com/arangodb/async/internal/velocystream/VstConnectionFactoryAsync.java index eaabb7b08..443a90865 100644 --- a/src/main/java/com/arangodb/async/internal/velocystream/VstConnectionFactoryAsync.java +++ b/src/main/java/com/arangodb/async/internal/velocystream/VstConnectionFactoryAsync.java @@ -34,7 +34,7 @@ public class VstConnectionFactoryAsync implements ConnectionFactory { private final VstConnectionAsync.Builder builder; - public VstConnectionFactoryAsync(final HostDescription host, final Integer timeout, final Long connectionTtl, + public VstConnectionFactoryAsync(final Integer timeout, final Long connectionTtl, final Integer keepAliveInterval, final Boolean useSsl, final SSLContext sslContext) { super(); diff --git a/src/main/java/com/arangodb/internal/ArangoDefaults.java b/src/main/java/com/arangodb/internal/ArangoDefaults.java index ebd39f521..370158c59 100644 --- a/src/main/java/com/arangodb/internal/ArangoDefaults.java +++ b/src/main/java/com/arangodb/internal/ArangoDefaults.java @@ -30,8 +30,6 @@ public final class ArangoDefaults { public static final int INTEGER_BYTES = Integer.SIZE / Byte.SIZE; public static final int LONG_BYTES = Long.SIZE / Byte.SIZE; - public static final String DEFAULT_HOST = "127.0.0.1"; - public static final Integer DEFAULT_PORT = 8529; public static final Integer DEFAULT_TIMEOUT = 0; public static final String DEFAULT_USER = "root"; public static final Boolean DEFAULT_USE_SSL = false; diff --git a/src/main/java/com/arangodb/internal/InternalArangoDBBuilder.java b/src/main/java/com/arangodb/internal/InternalArangoDBBuilder.java index dc119bd79..7efa13c3a 100644 --- a/src/main/java/com/arangodb/internal/InternalArangoDBBuilder.java +++ b/src/main/java/com/arangodb/internal/InternalArangoDBBuilder.java @@ -43,8 +43,6 @@ public abstract class InternalArangoDBBuilder { private static final Logger LOG = LoggerFactory.getLogger(InternalArangoDBBuilder.class); private static final String PROPERTY_KEY_HOSTS = "arangodb.hosts"; - private static final String PROPERTY_KEY_HOST = "arangodb.host"; - private static final String PROPERTY_KEY_PORT = "arangodb.port"; private static final String PROPERTY_KEY_TIMEOUT = "arangodb.timeout"; private static final String PROPERTY_KEY_USER = "arangodb.user"; private static final String PROPERTY_KEY_PASSWORD = "arangodb.password"; @@ -62,7 +60,6 @@ public abstract class InternalArangoDBBuilder { private static final String DEFAULT_PROPERTY_FILE = "/arangodb.properties"; protected final List hosts; - protected HostDescription host; protected Integer timeout; protected String user; protected String password; @@ -83,7 +80,6 @@ public abstract class InternalArangoDBBuilder { public InternalArangoDBBuilder() { super(); - host = new HostDescription(ArangoDefaults.DEFAULT_HOST, ArangoDefaults.DEFAULT_PORT); hosts = new ArrayList<>(); user = ArangoDefaults.DEFAULT_USER; try (InputStream is = ArangoDB.class.getResourceAsStream(DEFAULT_PROPERTY_FILE)) { @@ -110,21 +106,6 @@ private static void loadHosts(final Properties properties, final Collection - new ArangoDB.Builder().loadProperties(ArangoDBTest.class.getResourceAsStream("/arangodb-bad2" + - ".properties")) - ); - assertThat(thrown).isInstanceOf(ArangoDBException.class); - } - @ParameterizedTest(name = "{index}") @MethodSource("arangos") void accessMultipleDatabases(ArangoDB arangoDB) { diff --git a/src/test/resources/arangodb-bad2.properties b/src/test/resources/arangodb-bad2.properties deleted file mode 100644 index 1c19ad869..000000000 --- a/src/test/resources/arangodb-bad2.properties +++ /dev/null @@ -1 +0,0 @@ -arangodb.host=127.0.0.1:8529 From 7c9ebcfeb2b0b23d09f41139c5a506c6e2771235 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Mon, 24 Oct 2022 20:07:19 +0200 Subject: [PATCH 159/254] moved Request and Response classes under com.arangodb package --- src/main/java/com/arangodb/ArangoDB.java | 6 +- src/main/java/com/arangodb/ArangoRoute.java | 2 - .../arangodb/{velocystream => }/Request.java | 4 +- .../{velocystream => }/RequestType.java | 116 +++++----- .../arangodb/{velocystream => }/Response.java | 210 +++++++++--------- .../com/arangodb/async/ArangoDBAsync.java | 4 +- .../com/arangodb/async/ArangoRouteAsync.java | 2 +- .../async/internal/ArangoDBAsyncImpl.java | 4 +- .../internal/ArangoDatabaseAsyncImpl.java | 2 +- .../async/internal/ArangoExecutorAsync.java | 2 +- .../async/internal/ArangoRouteAsyncImpl.java | 4 +- .../velocystream/VstCommunicationAsync.java | 4 +- .../com/arangodb/internal/ArangoDBImpl.java | 4 +- .../arangodb/internal/ArangoDatabaseImpl.java | 2 +- .../arangodb/internal/ArangoExecuteable.java | 4 +- .../com/arangodb/internal/ArangoExecutor.java | 4 +- .../arangodb/internal/ArangoExecutorSync.java | 4 +- .../arangodb/internal/ArangoRouteImpl.java | 4 +- .../internal/InternalArangoCollection.java | 5 +- .../arangodb/internal/InternalArangoDB.java | 4 +- .../internal/InternalArangoDatabase.java | 4 +- .../InternalArangoEdgeCollection.java | 4 +- .../internal/InternalArangoGraph.java | 4 +- .../internal/InternalArangoRoute.java | 4 +- .../internal/InternalArangoSearch.java | 4 +- .../InternalArangoVertexCollection.java | 4 +- .../arangodb/internal/InternalArangoView.java | 4 +- .../internal/InternalSearchAlias.java | 4 +- .../internal/http/HttpCommunication.java | 4 +- .../internal/http/HttpConnection.java | 6 +- .../arangodb/internal/http/HttpProtocol.java | 4 +- .../internal/net/CommunicationProtocol.java | 4 +- .../internal/net/ExtendedHostResolver.java | 4 +- .../internal/serde/InternalDeserializers.java | 2 +- .../internal/serde/InternalModule.java | 4 +- .../internal/serde/InternalSerializers.java | 2 +- .../arangodb/internal/util/RequestUtils.java | 4 +- .../arangodb/internal/util/ResponseUtils.java | 2 +- .../velocystream/VstCommunication.java | 4 +- .../velocystream/VstCommunicationSync.java | 4 +- .../internal/velocystream/VstProtocol.java | 4 +- .../internal/AuthenticationRequest.java | 2 +- .../internal/JwtAuthenticationRequest.java | 2 +- src/test/java/com/arangodb/ArangoDBTest.java | 3 - .../java/com/arangodb/ArangoRouteTest.java | 1 - src/test/java/com/arangodb/JwtAuthTest.java | 3 - .../java/com/arangodb/async/ArangoDBTest.java | 4 +- .../java/com/arangodb/async/JwtAuthTest.java | 6 +- src/test/java/perf/SyncBenchmarkTest.java | 4 +- 49 files changed, 241 insertions(+), 255 deletions(-) rename src/main/java/com/arangodb/{velocystream => }/Request.java (98%) rename src/main/java/com/arangodb/{velocystream => }/RequestType.java (93%) rename src/main/java/com/arangodb/{velocystream => }/Response.java (94%) diff --git a/src/main/java/com/arangodb/ArangoDB.java b/src/main/java/com/arangodb/ArangoDB.java index 74ea7fca0..e17937755 100644 --- a/src/main/java/com/arangodb/ArangoDB.java +++ b/src/main/java/com/arangodb/ArangoDB.java @@ -36,8 +36,6 @@ import com.arangodb.model.UserUpdateOptions; import com.arangodb.serde.ArangoSerde; import com.arangodb.serde.JacksonSerde; -import com.arangodb.velocystream.Request; -import com.arangodb.velocystream.Response; import javax.annotation.concurrent.ThreadSafe; import javax.net.ssl.SSLContext; @@ -280,7 +278,7 @@ public interface ArangoDB extends ArangoSerdeAccessor { /** * Generic Execute. Use this method to execute custom FOXX services. * - * @param request VelocyStream request + * @param request request * @return VelocyStream response */ Response execute(Request request); @@ -288,7 +286,7 @@ public interface ArangoDB extends ArangoSerdeAccessor { /** * Generic Execute. Use this method to execute custom FOXX services. * - * @param request VelocyStream request + * @param request request * @param hostHandle Used to stick to a specific host when using {@link LoadBalancingStrategy#ROUND_ROBIN} * @return VelocyStream response */ diff --git a/src/main/java/com/arangodb/ArangoRoute.java b/src/main/java/com/arangodb/ArangoRoute.java index f9aa6df0e..4e4bab95b 100644 --- a/src/main/java/com/arangodb/ArangoRoute.java +++ b/src/main/java/com/arangodb/ArangoRoute.java @@ -20,8 +20,6 @@ package com.arangodb; -import com.arangodb.velocystream.Response; - /** * Interface for a specific path to be used to perform arbitrary requests. * diff --git a/src/main/java/com/arangodb/velocystream/Request.java b/src/main/java/com/arangodb/Request.java similarity index 98% rename from src/main/java/com/arangodb/velocystream/Request.java rename to src/main/java/com/arangodb/Request.java index 5fd5fd8a9..f4b626eb1 100644 --- a/src/main/java/com/arangodb/velocystream/Request.java +++ b/src/main/java/com/arangodb/Request.java @@ -18,9 +18,7 @@ * Copyright holder is ArangoDB GmbH, Cologne, Germany */ -package com.arangodb.velocystream; - -import com.arangodb.DbName; +package com.arangodb; import java.util.Collections; import java.util.HashMap; diff --git a/src/main/java/com/arangodb/velocystream/RequestType.java b/src/main/java/com/arangodb/RequestType.java similarity index 93% rename from src/main/java/com/arangodb/velocystream/RequestType.java rename to src/main/java/com/arangodb/RequestType.java index 43b04dd9d..009f08c35 100644 --- a/src/main/java/com/arangodb/velocystream/RequestType.java +++ b/src/main/java/com/arangodb/RequestType.java @@ -1,58 +1,58 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.velocystream; - -/** - * @author Mark Vollmary - */ -public enum RequestType { - - DELETE(0), - GET(1), - POST(2), - PUT(3), - HEAD(4), - PATCH(5), - OPTIONS(6), - VSTREAM_CRED(7), - VSTREAM_REGISTER(8), - VSTREAM_STATUS(9), - ILLEGAL(10); - - private final int type; - - RequestType(final int type) { - this.type = type; - } - - public static RequestType fromType(final int type) { - for (final RequestType rType : RequestType.values()) { - if (rType.type == type) { - return rType; - } - } - return null; - } - - public int getType() { - return type; - } -} +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed 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. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb; + +/** + * @author Mark Vollmary + */ +public enum RequestType { + + DELETE(0), + GET(1), + POST(2), + PUT(3), + HEAD(4), + PATCH(5), + OPTIONS(6), + VSTREAM_CRED(7), + VSTREAM_REGISTER(8), + VSTREAM_STATUS(9), + ILLEGAL(10); + + private final int type; + + RequestType(final int type) { + this.type = type; + } + + public static RequestType fromType(final int type) { + for (final RequestType rType : RequestType.values()) { + if (rType.type == type) { + return rType; + } + } + return null; + } + + public int getType() { + return type; + } +} diff --git a/src/main/java/com/arangodb/velocystream/Response.java b/src/main/java/com/arangodb/Response.java similarity index 94% rename from src/main/java/com/arangodb/velocystream/Response.java rename to src/main/java/com/arangodb/Response.java index b20667131..a7fffa552 100644 --- a/src/main/java/com/arangodb/velocystream/Response.java +++ b/src/main/java/com/arangodb/Response.java @@ -1,105 +1,105 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.velocystream; - -import java.util.Collections; -import java.util.HashMap; -import java.util.Locale; -import java.util.Map; - -/** - * @author Mark Vollmary - */ -public class Response { - - private int version = 1; - private int type = 2; - private int responseCode; - private final Map meta; - private byte[] body = null; - - public Response() { - super(); - meta = new HashMap<>(); - } - - public int getVersion() { - return version; - } - - public void setVersion(final int version) { - this.version = version; - } - - public int getType() { - return type; - } - - public void setType(final int type) { - this.type = type; - } - - public int getResponseCode() { - return responseCode; - } - - public void setResponseCode(final int responseCode) { - this.responseCode = responseCode; - } - - public Map getMeta() { - return Collections.unmodifiableMap(meta); - } - - public String getMeta(final String key) { - return meta.get(key.toLowerCase(Locale.ROOT)); - } - - public boolean containsMeta(final String key) { - return meta.containsKey(key.toLowerCase(Locale.ROOT)); - } - - public void putMeta(final String key, final String value) { - this.meta.put(key.toLowerCase(Locale.ROOT), value); - } - - public void putMetas(final Map meta) { - for (Map.Entry it : meta.entrySet()) { - putMeta(it.getKey(), it.getValue()); - } - } - - public byte[] getBody() { - return body; - } - - public void setBody(final byte[] body) { - this.body = body; - } - - @Override - public String toString() { - return "{" + - "statusCode=" + responseCode + - ", headers=" + meta + - '}'; - } -} +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed 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. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Locale; +import java.util.Map; + +/** + * @author Mark Vollmary + */ +public class Response { + + private int version = 1; + private int type = 2; + private int responseCode; + private final Map meta; + private byte[] body = null; + + public Response() { + super(); + meta = new HashMap<>(); + } + + public int getVersion() { + return version; + } + + public void setVersion(final int version) { + this.version = version; + } + + public int getType() { + return type; + } + + public void setType(final int type) { + this.type = type; + } + + public int getResponseCode() { + return responseCode; + } + + public void setResponseCode(final int responseCode) { + this.responseCode = responseCode; + } + + public Map getMeta() { + return Collections.unmodifiableMap(meta); + } + + public String getMeta(final String key) { + return meta.get(key.toLowerCase(Locale.ROOT)); + } + + public boolean containsMeta(final String key) { + return meta.containsKey(key.toLowerCase(Locale.ROOT)); + } + + public void putMeta(final String key, final String value) { + this.meta.put(key.toLowerCase(Locale.ROOT), value); + } + + public void putMetas(final Map meta) { + for (Map.Entry it : meta.entrySet()) { + putMeta(it.getKey(), it.getValue()); + } + } + + public byte[] getBody() { + return body; + } + + public void setBody(final byte[] body) { + this.body = body; + } + + @Override + public String toString() { + return "{" + + "statusCode=" + responseCode + + ", headers=" + meta + + '}'; + } +} diff --git a/src/main/java/com/arangodb/async/ArangoDBAsync.java b/src/main/java/com/arangodb/async/ArangoDBAsync.java index c5ad894d7..0c3c8ec61 100644 --- a/src/main/java/com/arangodb/async/ArangoDBAsync.java +++ b/src/main/java/com/arangodb/async/ArangoDBAsync.java @@ -43,8 +43,8 @@ import com.arangodb.serde.ArangoSerde; import com.arangodb.ContentType; import com.arangodb.serde.JacksonSerde; -import com.arangodb.velocystream.Request; -import com.arangodb.velocystream.Response; +import com.arangodb.Request; +import com.arangodb.Response; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/src/main/java/com/arangodb/async/ArangoRouteAsync.java b/src/main/java/com/arangodb/async/ArangoRouteAsync.java index f47a0c5d7..ed66aff87 100644 --- a/src/main/java/com/arangodb/async/ArangoRouteAsync.java +++ b/src/main/java/com/arangodb/async/ArangoRouteAsync.java @@ -21,7 +21,7 @@ package com.arangodb.async; import com.arangodb.ArangoSerdeAccessor; -import com.arangodb.velocystream.Response; +import com.arangodb.Response; import java.util.concurrent.CompletableFuture; diff --git a/src/main/java/com/arangodb/async/internal/ArangoDBAsyncImpl.java b/src/main/java/com/arangodb/async/internal/ArangoDBAsyncImpl.java index d045b1bf7..5e52ffdf5 100644 --- a/src/main/java/com/arangodb/async/internal/ArangoDBAsyncImpl.java +++ b/src/main/java/com/arangodb/async/internal/ArangoDBAsyncImpl.java @@ -40,8 +40,8 @@ import com.arangodb.model.LogOptions; import com.arangodb.model.UserCreateOptions; import com.arangodb.model.UserUpdateOptions; -import com.arangodb.velocystream.Request; -import com.arangodb.velocystream.Response; +import com.arangodb.Request; +import com.arangodb.Response; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/src/main/java/com/arangodb/async/internal/ArangoDatabaseAsyncImpl.java b/src/main/java/com/arangodb/async/internal/ArangoDatabaseAsyncImpl.java index f173bf678..4d723b1be 100644 --- a/src/main/java/com/arangodb/async/internal/ArangoDatabaseAsyncImpl.java +++ b/src/main/java/com/arangodb/async/internal/ArangoDatabaseAsyncImpl.java @@ -35,7 +35,7 @@ import com.arangodb.model.arangosearch.AnalyzerDeleteOptions; import com.arangodb.model.arangosearch.ArangoSearchCreateOptions; import com.arangodb.model.arangosearch.SearchAliasCreateOptions; -import com.arangodb.velocystream.Request; +import com.arangodb.Request; import java.util.Collection; import java.util.Collections; diff --git a/src/main/java/com/arangodb/async/internal/ArangoExecutorAsync.java b/src/main/java/com/arangodb/async/internal/ArangoExecutorAsync.java index 0f6548674..1510cbf2a 100644 --- a/src/main/java/com/arangodb/async/internal/ArangoExecutorAsync.java +++ b/src/main/java/com/arangodb/async/internal/ArangoExecutorAsync.java @@ -26,7 +26,7 @@ import com.arangodb.internal.QueueTimeMetricsImpl; import com.arangodb.internal.net.HostHandle; import com.arangodb.internal.serde.InternalSerde; -import com.arangodb.velocystream.Request; +import com.arangodb.Request; import java.io.IOException; import java.lang.reflect.Type; diff --git a/src/main/java/com/arangodb/async/internal/ArangoRouteAsyncImpl.java b/src/main/java/com/arangodb/async/internal/ArangoRouteAsyncImpl.java index d4af273e9..e00688dcc 100644 --- a/src/main/java/com/arangodb/async/internal/ArangoRouteAsyncImpl.java +++ b/src/main/java/com/arangodb/async/internal/ArangoRouteAsyncImpl.java @@ -22,8 +22,8 @@ import com.arangodb.async.ArangoRouteAsync; import com.arangodb.internal.InternalArangoRoute; -import com.arangodb.velocystream.RequestType; -import com.arangodb.velocystream.Response; +import com.arangodb.RequestType; +import com.arangodb.Response; import java.util.Map; import java.util.concurrent.CompletableFuture; diff --git a/src/main/java/com/arangodb/async/internal/velocystream/VstCommunicationAsync.java b/src/main/java/com/arangodb/async/internal/velocystream/VstCommunicationAsync.java index 23fdc76ce..9f33bd3c9 100644 --- a/src/main/java/com/arangodb/async/internal/velocystream/VstCommunicationAsync.java +++ b/src/main/java/com/arangodb/async/internal/velocystream/VstCommunicationAsync.java @@ -33,8 +33,8 @@ import com.arangodb.internal.velocystream.internal.Message; import com.arangodb.velocypack.exception.VPackException; import com.arangodb.velocypack.exception.VPackParserException; -import com.arangodb.velocystream.Request; -import com.arangodb.velocystream.Response; +import com.arangodb.Request; +import com.arangodb.Response; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/src/main/java/com/arangodb/internal/ArangoDBImpl.java b/src/main/java/com/arangodb/internal/ArangoDBImpl.java index 6c11ded4c..04d631369 100644 --- a/src/main/java/com/arangodb/internal/ArangoDBImpl.java +++ b/src/main/java/com/arangodb/internal/ArangoDBImpl.java @@ -36,8 +36,8 @@ import com.arangodb.model.LogOptions; import com.arangodb.model.UserCreateOptions; import com.arangodb.model.UserUpdateOptions; -import com.arangodb.velocystream.Request; -import com.arangodb.velocystream.Response; +import com.arangodb.Request; +import com.arangodb.Response; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/src/main/java/com/arangodb/internal/ArangoDatabaseImpl.java b/src/main/java/com/arangodb/internal/ArangoDatabaseImpl.java index f54788c50..c3ed750d9 100644 --- a/src/main/java/com/arangodb/internal/ArangoDatabaseImpl.java +++ b/src/main/java/com/arangodb/internal/ArangoDatabaseImpl.java @@ -31,7 +31,7 @@ import com.arangodb.model.arangosearch.AnalyzerDeleteOptions; import com.arangodb.model.arangosearch.ArangoSearchCreateOptions; import com.arangodb.model.arangosearch.SearchAliasCreateOptions; -import com.arangodb.velocystream.Request; +import com.arangodb.Request; import java.util.Collection; import java.util.Collections; diff --git a/src/main/java/com/arangodb/internal/ArangoExecuteable.java b/src/main/java/com/arangodb/internal/ArangoExecuteable.java index e039a9878..c1bb79eed 100644 --- a/src/main/java/com/arangodb/internal/ArangoExecuteable.java +++ b/src/main/java/com/arangodb/internal/ArangoExecuteable.java @@ -24,8 +24,8 @@ import com.arangodb.DbName; import com.arangodb.internal.serde.InternalSerde; import com.arangodb.internal.util.EncodeUtils; -import com.arangodb.velocystream.Request; -import com.arangodb.velocystream.RequestType; +import com.arangodb.Request; +import com.arangodb.RequestType; /** * @author Mark Vollmary diff --git a/src/main/java/com/arangodb/internal/ArangoExecutor.java b/src/main/java/com/arangodb/internal/ArangoExecutor.java index 37917dad8..359a0f952 100644 --- a/src/main/java/com/arangodb/internal/ArangoExecutor.java +++ b/src/main/java/com/arangodb/internal/ArangoExecutor.java @@ -22,8 +22,8 @@ import com.arangodb.QueueTimeMetrics; import com.arangodb.internal.serde.InternalSerde; -import com.arangodb.velocystream.Request; -import com.arangodb.velocystream.Response; +import com.arangodb.Request; +import com.arangodb.Response; import java.lang.reflect.Type; diff --git a/src/main/java/com/arangodb/internal/ArangoExecutorSync.java b/src/main/java/com/arangodb/internal/ArangoExecutorSync.java index ddaf8ceff..8588c26b0 100644 --- a/src/main/java/com/arangodb/internal/ArangoExecutorSync.java +++ b/src/main/java/com/arangodb/internal/ArangoExecutorSync.java @@ -25,8 +25,8 @@ import com.arangodb.internal.net.CommunicationProtocol; import com.arangodb.internal.net.HostHandle; import com.arangodb.internal.serde.InternalSerde; -import com.arangodb.velocystream.Request; -import com.arangodb.velocystream.Response; +import com.arangodb.Request; +import com.arangodb.Response; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/src/main/java/com/arangodb/internal/ArangoRouteImpl.java b/src/main/java/com/arangodb/internal/ArangoRouteImpl.java index 99147739d..b73753ddc 100644 --- a/src/main/java/com/arangodb/internal/ArangoRouteImpl.java +++ b/src/main/java/com/arangodb/internal/ArangoRouteImpl.java @@ -21,8 +21,8 @@ package com.arangodb.internal; import com.arangodb.ArangoRoute; -import com.arangodb.velocystream.RequestType; -import com.arangodb.velocystream.Response; +import com.arangodb.RequestType; +import com.arangodb.Response; import java.util.Map; diff --git a/src/main/java/com/arangodb/internal/InternalArangoCollection.java b/src/main/java/com/arangodb/internal/InternalArangoCollection.java index 5e77606b0..7d31e31d5 100644 --- a/src/main/java/com/arangodb/internal/InternalArangoCollection.java +++ b/src/main/java/com/arangodb/internal/InternalArangoCollection.java @@ -28,14 +28,13 @@ import com.arangodb.internal.util.RequestUtils; import com.arangodb.model.*; import com.arangodb.util.RawData; -import com.arangodb.velocystream.Request; -import com.arangodb.velocystream.RequestType; +import com.arangodb.Request; +import com.arangodb.RequestType; import com.fasterxml.jackson.databind.JsonNode; import java.lang.reflect.Type; import java.util.ArrayList; import java.util.Collection; -import java.util.Iterator; import static com.arangodb.internal.serde.SerdeUtils.constructParametricType; diff --git a/src/main/java/com/arangodb/internal/InternalArangoDB.java b/src/main/java/com/arangodb/internal/InternalArangoDB.java index 8c10fba1b..25376bade 100644 --- a/src/main/java/com/arangodb/internal/InternalArangoDB.java +++ b/src/main/java/com/arangodb/internal/InternalArangoDB.java @@ -28,8 +28,8 @@ import com.arangodb.internal.ArangoExecutor.ResponseDeserializer; import com.arangodb.internal.serde.InternalSerde; import com.arangodb.model.*; -import com.arangodb.velocystream.Request; -import com.arangodb.velocystream.RequestType; +import com.arangodb.Request; +import com.arangodb.RequestType; import java.util.ArrayList; import java.util.Collection; diff --git a/src/main/java/com/arangodb/internal/InternalArangoDatabase.java b/src/main/java/com/arangodb/internal/InternalArangoDatabase.java index cb9860194..8841570ef 100644 --- a/src/main/java/com/arangodb/internal/InternalArangoDatabase.java +++ b/src/main/java/com/arangodb/internal/InternalArangoDatabase.java @@ -27,8 +27,8 @@ import com.arangodb.internal.util.RequestUtils; import com.arangodb.model.*; import com.arangodb.model.arangosearch.*; -import com.arangodb.velocystream.Request; -import com.arangodb.velocystream.RequestType; +import com.arangodb.Request; +import com.arangodb.RequestType; import java.util.Collection; import java.util.Map; diff --git a/src/main/java/com/arangodb/internal/InternalArangoEdgeCollection.java b/src/main/java/com/arangodb/internal/InternalArangoEdgeCollection.java index 978388d4b..897623e35 100644 --- a/src/main/java/com/arangodb/internal/InternalArangoEdgeCollection.java +++ b/src/main/java/com/arangodb/internal/InternalArangoEdgeCollection.java @@ -26,8 +26,8 @@ import com.arangodb.internal.util.DocumentUtil; import com.arangodb.internal.util.RequestUtils; import com.arangodb.model.*; -import com.arangodb.velocystream.Request; -import com.arangodb.velocystream.RequestType; +import com.arangodb.Request; +import com.arangodb.RequestType; /** * @author Mark Vollmary diff --git a/src/main/java/com/arangodb/internal/InternalArangoGraph.java b/src/main/java/com/arangodb/internal/InternalArangoGraph.java index 9196e58f0..8c874c041 100644 --- a/src/main/java/com/arangodb/internal/InternalArangoGraph.java +++ b/src/main/java/com/arangodb/internal/InternalArangoGraph.java @@ -25,8 +25,8 @@ import com.arangodb.internal.ArangoExecutor.ResponseDeserializer; import com.arangodb.model.OptionsBuilder; import com.arangodb.model.VertexCollectionCreateOptions; -import com.arangodb.velocystream.Request; -import com.arangodb.velocystream.RequestType; +import com.arangodb.Request; +import com.arangodb.RequestType; import java.util.Collection; diff --git a/src/main/java/com/arangodb/internal/InternalArangoRoute.java b/src/main/java/com/arangodb/internal/InternalArangoRoute.java index 966aac05c..78e782d68 100644 --- a/src/main/java/com/arangodb/internal/InternalArangoRoute.java +++ b/src/main/java/com/arangodb/internal/InternalArangoRoute.java @@ -20,8 +20,8 @@ package com.arangodb.internal; -import com.arangodb.velocystream.Request; -import com.arangodb.velocystream.RequestType; +import com.arangodb.Request; +import com.arangodb.RequestType; import java.util.HashMap; import java.util.Map; diff --git a/src/main/java/com/arangodb/internal/InternalArangoSearch.java b/src/main/java/com/arangodb/internal/InternalArangoSearch.java index 6934584f3..22b536312 100644 --- a/src/main/java/com/arangodb/internal/InternalArangoSearch.java +++ b/src/main/java/com/arangodb/internal/InternalArangoSearch.java @@ -21,8 +21,8 @@ package com.arangodb.internal; import com.arangodb.model.arangosearch.ArangoSearchPropertiesOptions; -import com.arangodb.velocystream.Request; -import com.arangodb.velocystream.RequestType; +import com.arangodb.Request; +import com.arangodb.RequestType; /** * @author Mark Vollmary diff --git a/src/main/java/com/arangodb/internal/InternalArangoVertexCollection.java b/src/main/java/com/arangodb/internal/InternalArangoVertexCollection.java index 93b2e0646..c3407cb95 100644 --- a/src/main/java/com/arangodb/internal/InternalArangoVertexCollection.java +++ b/src/main/java/com/arangodb/internal/InternalArangoVertexCollection.java @@ -26,8 +26,8 @@ import com.arangodb.internal.util.DocumentUtil; import com.arangodb.internal.util.RequestUtils; import com.arangodb.model.*; -import com.arangodb.velocystream.Request; -import com.arangodb.velocystream.RequestType; +import com.arangodb.Request; +import com.arangodb.RequestType; /** * @author Mark Vollmary diff --git a/src/main/java/com/arangodb/internal/InternalArangoView.java b/src/main/java/com/arangodb/internal/InternalArangoView.java index 2647a37af..150a297d9 100644 --- a/src/main/java/com/arangodb/internal/InternalArangoView.java +++ b/src/main/java/com/arangodb/internal/InternalArangoView.java @@ -22,8 +22,8 @@ import com.arangodb.model.OptionsBuilder; import com.arangodb.model.ViewRenameOptions; -import com.arangodb.velocystream.Request; -import com.arangodb.velocystream.RequestType; +import com.arangodb.Request; +import com.arangodb.RequestType; /** * @author Mark Vollmary diff --git a/src/main/java/com/arangodb/internal/InternalSearchAlias.java b/src/main/java/com/arangodb/internal/InternalSearchAlias.java index 46e6a11bb..3341c1a6a 100644 --- a/src/main/java/com/arangodb/internal/InternalSearchAlias.java +++ b/src/main/java/com/arangodb/internal/InternalSearchAlias.java @@ -21,8 +21,8 @@ package com.arangodb.internal; import com.arangodb.model.arangosearch.SearchAliasPropertiesOptions; -import com.arangodb.velocystream.Request; -import com.arangodb.velocystream.RequestType; +import com.arangodb.Request; +import com.arangodb.RequestType; public class InternalSearchAlias, D extends InternalArangoDatabase, E extends ArangoExecutor> extends InternalArangoView { diff --git a/src/main/java/com/arangodb/internal/http/HttpCommunication.java b/src/main/java/com/arangodb/internal/http/HttpCommunication.java index 48ff99215..c021d978b 100644 --- a/src/main/java/com/arangodb/internal/http/HttpCommunication.java +++ b/src/main/java/com/arangodb/internal/http/HttpCommunication.java @@ -25,8 +25,8 @@ import com.arangodb.internal.serde.InternalSerde; import com.arangodb.internal.util.HostUtils; import com.arangodb.internal.util.RequestUtils; -import com.arangodb.velocystream.Request; -import com.arangodb.velocystream.Response; +import com.arangodb.Request; +import com.arangodb.Response; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/src/main/java/com/arangodb/internal/http/HttpConnection.java b/src/main/java/com/arangodb/internal/http/HttpConnection.java index c0ad5a1de..e7be90706 100644 --- a/src/main/java/com/arangodb/internal/http/HttpConnection.java +++ b/src/main/java/com/arangodb/internal/http/HttpConnection.java @@ -29,9 +29,9 @@ import com.arangodb.internal.serde.InternalSerde; import com.arangodb.internal.util.EncodeUtils; import com.arangodb.internal.util.ResponseUtils; -import com.arangodb.velocystream.Request; -import com.arangodb.velocystream.RequestType; -import com.arangodb.velocystream.Response; +import com.arangodb.Request; +import com.arangodb.RequestType; +import com.arangodb.Response; import io.netty.handler.ssl.ApplicationProtocolConfig; import io.netty.handler.ssl.ClientAuth; import io.netty.handler.ssl.IdentityCipherSuiteFilter; diff --git a/src/main/java/com/arangodb/internal/http/HttpProtocol.java b/src/main/java/com/arangodb/internal/http/HttpProtocol.java index 245bea678..3bdc01d74 100644 --- a/src/main/java/com/arangodb/internal/http/HttpProtocol.java +++ b/src/main/java/com/arangodb/internal/http/HttpProtocol.java @@ -22,8 +22,8 @@ import com.arangodb.internal.net.CommunicationProtocol; import com.arangodb.internal.net.HostHandle; -import com.arangodb.velocystream.Request; -import com.arangodb.velocystream.Response; +import com.arangodb.Request; +import com.arangodb.Response; import java.io.IOException; diff --git a/src/main/java/com/arangodb/internal/net/CommunicationProtocol.java b/src/main/java/com/arangodb/internal/net/CommunicationProtocol.java index 2404879f9..5f1d8f16b 100644 --- a/src/main/java/com/arangodb/internal/net/CommunicationProtocol.java +++ b/src/main/java/com/arangodb/internal/net/CommunicationProtocol.java @@ -20,8 +20,8 @@ package com.arangodb.internal.net; -import com.arangodb.velocystream.Request; -import com.arangodb.velocystream.Response; +import com.arangodb.Request; +import com.arangodb.Response; import java.io.Closeable; diff --git a/src/main/java/com/arangodb/internal/net/ExtendedHostResolver.java b/src/main/java/com/arangodb/internal/net/ExtendedHostResolver.java index 1dc0d11dd..9ca115c38 100644 --- a/src/main/java/com/arangodb/internal/net/ExtendedHostResolver.java +++ b/src/main/java/com/arangodb/internal/net/ExtendedHostResolver.java @@ -25,8 +25,8 @@ import com.arangodb.internal.ArangoExecutorSync; import com.arangodb.internal.serde.InternalSerde; import com.arangodb.internal.util.HostUtils; -import com.arangodb.velocystream.Request; -import com.arangodb.velocystream.RequestType; +import com.arangodb.Request; +import com.arangodb.RequestType; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/src/main/java/com/arangodb/internal/serde/InternalDeserializers.java b/src/main/java/com/arangodb/internal/serde/InternalDeserializers.java index d99449a64..2cd22326a 100644 --- a/src/main/java/com/arangodb/internal/serde/InternalDeserializers.java +++ b/src/main/java/com/arangodb/internal/serde/InternalDeserializers.java @@ -8,7 +8,7 @@ import com.arangodb.entity.arangosearch.FieldLink; import com.arangodb.util.RawBytes; import com.arangodb.util.RawJson; -import com.arangodb.velocystream.Response; +import com.arangodb.Response; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.TreeNode; diff --git a/src/main/java/com/arangodb/internal/serde/InternalModule.java b/src/main/java/com/arangodb/internal/serde/InternalModule.java index 2e35e5b64..5f7d465ac 100644 --- a/src/main/java/com/arangodb/internal/serde/InternalModule.java +++ b/src/main/java/com/arangodb/internal/serde/InternalModule.java @@ -8,8 +8,8 @@ import com.arangodb.internal.velocystream.internal.JwtAuthenticationRequest; import com.arangodb.util.RawBytes; import com.arangodb.util.RawJson; -import com.arangodb.velocystream.Request; -import com.arangodb.velocystream.Response; +import com.arangodb.Request; +import com.arangodb.Response; import com.fasterxml.jackson.databind.Module; import com.fasterxml.jackson.databind.module.SimpleModule; diff --git a/src/main/java/com/arangodb/internal/serde/InternalSerializers.java b/src/main/java/com/arangodb/internal/serde/InternalSerializers.java index ab9f4c217..d721e5eae 100644 --- a/src/main/java/com/arangodb/internal/serde/InternalSerializers.java +++ b/src/main/java/com/arangodb/internal/serde/InternalSerializers.java @@ -7,7 +7,7 @@ import com.arangodb.internal.velocystream.internal.JwtAuthenticationRequest; import com.arangodb.util.RawBytes; import com.arangodb.util.RawJson; -import com.arangodb.velocystream.Request; +import com.arangodb.Request; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.databind.JsonSerializer; diff --git a/src/main/java/com/arangodb/internal/util/RequestUtils.java b/src/main/java/com/arangodb/internal/util/RequestUtils.java index 1539b8a76..710fd8d0f 100644 --- a/src/main/java/com/arangodb/internal/util/RequestUtils.java +++ b/src/main/java/com/arangodb/internal/util/RequestUtils.java @@ -21,8 +21,8 @@ package com.arangodb.internal.util; import com.arangodb.internal.net.AccessType; -import com.arangodb.velocystream.Request; -import com.arangodb.velocystream.RequestType; +import com.arangodb.Request; +import com.arangodb.RequestType; /** * @author Mark Vollmary diff --git a/src/main/java/com/arangodb/internal/util/ResponseUtils.java b/src/main/java/com/arangodb/internal/util/ResponseUtils.java index fcab67e88..8ff292b4f 100644 --- a/src/main/java/com/arangodb/internal/util/ResponseUtils.java +++ b/src/main/java/com/arangodb/internal/util/ResponseUtils.java @@ -25,7 +25,7 @@ import com.arangodb.internal.ArangoErrors; import com.arangodb.internal.net.ArangoDBRedirectException; import com.arangodb.internal.serde.InternalSerde; -import com.arangodb.velocystream.Response; +import com.arangodb.Response; import java.util.concurrent.TimeoutException; diff --git a/src/main/java/com/arangodb/internal/velocystream/VstCommunication.java b/src/main/java/com/arangodb/internal/velocystream/VstCommunication.java index 67c2f2961..7b3a1d917 100644 --- a/src/main/java/com/arangodb/internal/velocystream/VstCommunication.java +++ b/src/main/java/com/arangodb/internal/velocystream/VstCommunication.java @@ -34,8 +34,8 @@ import com.arangodb.internal.velocystream.internal.VstConnection; import com.arangodb.velocypack.VPackSlice; import com.arangodb.velocypack.exception.VPackParserException; -import com.arangodb.velocystream.Request; -import com.arangodb.velocystream.Response; +import com.arangodb.Request; +import com.arangodb.Response; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/src/main/java/com/arangodb/internal/velocystream/VstCommunicationSync.java b/src/main/java/com/arangodb/internal/velocystream/VstCommunicationSync.java index 7a26d0344..d1acdbc60 100644 --- a/src/main/java/com/arangodb/internal/velocystream/VstCommunicationSync.java +++ b/src/main/java/com/arangodb/internal/velocystream/VstCommunicationSync.java @@ -32,8 +32,8 @@ import com.arangodb.internal.velocystream.internal.Message; import com.arangodb.internal.velocystream.internal.VstConnectionSync; import com.arangodb.velocypack.exception.VPackParserException; -import com.arangodb.velocystream.Request; -import com.arangodb.velocystream.Response; +import com.arangodb.Request; +import com.arangodb.Response; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/src/main/java/com/arangodb/internal/velocystream/VstProtocol.java b/src/main/java/com/arangodb/internal/velocystream/VstProtocol.java index 054af4258..729c3028b 100644 --- a/src/main/java/com/arangodb/internal/velocystream/VstProtocol.java +++ b/src/main/java/com/arangodb/internal/velocystream/VstProtocol.java @@ -23,8 +23,8 @@ import com.arangodb.internal.net.CommunicationProtocol; import com.arangodb.internal.net.HostHandle; import com.arangodb.internal.velocystream.internal.VstConnectionSync; -import com.arangodb.velocystream.Request; -import com.arangodb.velocystream.Response; +import com.arangodb.Request; +import com.arangodb.Response; import java.io.IOException; diff --git a/src/main/java/com/arangodb/internal/velocystream/internal/AuthenticationRequest.java b/src/main/java/com/arangodb/internal/velocystream/internal/AuthenticationRequest.java index 9d47bc548..8e8310791 100644 --- a/src/main/java/com/arangodb/internal/velocystream/internal/AuthenticationRequest.java +++ b/src/main/java/com/arangodb/internal/velocystream/internal/AuthenticationRequest.java @@ -21,7 +21,7 @@ package com.arangodb.internal.velocystream.internal; import com.arangodb.DbName; -import com.arangodb.velocystream.Request; +import com.arangodb.Request; /** * @author Mark Vollmary diff --git a/src/main/java/com/arangodb/internal/velocystream/internal/JwtAuthenticationRequest.java b/src/main/java/com/arangodb/internal/velocystream/internal/JwtAuthenticationRequest.java index c2ccf53b3..f2667b125 100644 --- a/src/main/java/com/arangodb/internal/velocystream/internal/JwtAuthenticationRequest.java +++ b/src/main/java/com/arangodb/internal/velocystream/internal/JwtAuthenticationRequest.java @@ -1,7 +1,7 @@ package com.arangodb.internal.velocystream.internal; import com.arangodb.DbName; -import com.arangodb.velocystream.Request; +import com.arangodb.Request; public class JwtAuthenticationRequest extends Request { diff --git a/src/test/java/com/arangodb/ArangoDBTest.java b/src/test/java/com/arangodb/ArangoDBTest.java index 9f9d1bf5f..8e3336a02 100644 --- a/src/test/java/com/arangodb/ArangoDBTest.java +++ b/src/test/java/com/arangodb/ArangoDBTest.java @@ -24,9 +24,6 @@ import com.arangodb.model.*; import com.arangodb.model.LogOptions.SortOrder; import com.arangodb.util.TestUtils; -import com.arangodb.velocystream.Request; -import com.arangodb.velocystream.RequestType; -import com.arangodb.velocystream.Response; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Disabled; diff --git a/src/test/java/com/arangodb/ArangoRouteTest.java b/src/test/java/com/arangodb/ArangoRouteTest.java index 592674f7e..768175fc6 100644 --- a/src/test/java/com/arangodb/ArangoRouteTest.java +++ b/src/test/java/com/arangodb/ArangoRouteTest.java @@ -22,7 +22,6 @@ import com.arangodb.entity.BaseDocument; import com.arangodb.internal.ArangoRequestParam; -import com.arangodb.velocystream.Response; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.MethodSource; diff --git a/src/test/java/com/arangodb/JwtAuthTest.java b/src/test/java/com/arangodb/JwtAuthTest.java index 6aeb103e9..a5b87e803 100644 --- a/src/test/java/com/arangodb/JwtAuthTest.java +++ b/src/test/java/com/arangodb/JwtAuthTest.java @@ -1,9 +1,6 @@ package com.arangodb; import com.arangodb.serde.ArangoSerde; -import com.arangodb.velocystream.Request; -import com.arangodb.velocystream.RequestType; -import com.arangodb.velocystream.Response; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.EnumSource; diff --git a/src/test/java/com/arangodb/async/ArangoDBTest.java b/src/test/java/com/arangodb/async/ArangoDBTest.java index e7c5bbd1b..51980226b 100644 --- a/src/test/java/com/arangodb/async/ArangoDBTest.java +++ b/src/test/java/com/arangodb/async/ArangoDBTest.java @@ -24,8 +24,8 @@ import com.arangodb.entity.*; import com.arangodb.model.*; import com.arangodb.util.TestUtils; -import com.arangodb.velocystream.Request; -import com.arangodb.velocystream.RequestType; +import com.arangodb.Request; +import com.arangodb.RequestType; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Timeout; diff --git a/src/test/java/com/arangodb/async/JwtAuthTest.java b/src/test/java/com/arangodb/async/JwtAuthTest.java index c4bbc9b60..562b9684f 100644 --- a/src/test/java/com/arangodb/async/JwtAuthTest.java +++ b/src/test/java/com/arangodb/async/JwtAuthTest.java @@ -4,9 +4,9 @@ import com.arangodb.ArangoDBException; import com.arangodb.DbName; import com.arangodb.serde.ArangoSerde; -import com.arangodb.velocystream.Request; -import com.arangodb.velocystream.RequestType; -import com.arangodb.velocystream.Response; +import com.arangodb.Request; +import com.arangodb.RequestType; +import com.arangodb.Response; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; diff --git a/src/test/java/perf/SyncBenchmarkTest.java b/src/test/java/perf/SyncBenchmarkTest.java index 8a5fa5a51..fceb46685 100644 --- a/src/test/java/perf/SyncBenchmarkTest.java +++ b/src/test/java/perf/SyncBenchmarkTest.java @@ -3,8 +3,8 @@ import com.arangodb.ArangoDB; import com.arangodb.DbName; import com.arangodb.Protocol; -import com.arangodb.velocystream.Request; -import com.arangodb.velocystream.RequestType; +import com.arangodb.Request; +import com.arangodb.RequestType; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.EnumSource; From 0bb27f2e953de3a0c8a2204a5f6ad60c4df57d04 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Tue, 25 Oct 2022 10:18:17 +0200 Subject: [PATCH 160/254] added request id to ArangoDBException --- .../java/com/arangodb/ArangoDBException.java | 19 ++++++++++++++++ .../internal/http/HttpCommunication.java | 22 +++++++++---------- 2 files changed, 30 insertions(+), 11 deletions(-) diff --git a/src/main/java/com/arangodb/ArangoDBException.java b/src/main/java/com/arangodb/ArangoDBException.java index 015c0b585..ab6d63610 100644 --- a/src/main/java/com/arangodb/ArangoDBException.java +++ b/src/main/java/com/arangodb/ArangoDBException.java @@ -30,36 +30,49 @@ public class ArangoDBException extends RuntimeException { private static final long serialVersionUID = 6165638002614173801L; private final ErrorEntity entity; private final Integer responseCode; + private final Long requestId; public ArangoDBException(final ErrorEntity errorEntity) { super(String.format("Response: %s, Error: %s - %s", errorEntity.getCode(), errorEntity.getErrorNum(), errorEntity.getErrorMessage())); this.entity = errorEntity; this.responseCode = null; + this.requestId = null; } public ArangoDBException(final String message) { super(message); this.entity = null; this.responseCode = null; + this.requestId = null; } public ArangoDBException(final String message, final Integer responseCode) { super(message); this.entity = null; this.responseCode = responseCode; + this.requestId = null; } public ArangoDBException(final Throwable cause) { super(cause); this.entity = null; this.responseCode = null; + this.requestId = null; } public ArangoDBException(final String message, final Throwable cause) { super(message, cause); this.entity = null; this.responseCode = null; + this.requestId = null; + } + + public ArangoDBException(Throwable cause, long requestId) { + super(cause); + this.entity = null; + this.responseCode = null; + this.requestId = requestId; } public static ArangoDBException wrap(Throwable t) { @@ -99,4 +112,10 @@ public Integer getErrorNum() { return entity != null ? entity.getErrorNum() : null; } + /** + * @return request id + */ + public Long getRequestId() { + return requestId; + } } diff --git a/src/main/java/com/arangodb/internal/http/HttpCommunication.java b/src/main/java/com/arangodb/internal/http/HttpCommunication.java index c021d978b..82229676c 100644 --- a/src/main/java/com/arangodb/internal/http/HttpCommunication.java +++ b/src/main/java/com/arangodb/internal/http/HttpCommunication.java @@ -21,12 +21,12 @@ package com.arangodb.internal.http; import com.arangodb.ArangoDBException; +import com.arangodb.Request; +import com.arangodb.Response; import com.arangodb.internal.net.*; import com.arangodb.internal.serde.InternalSerde; import com.arangodb.internal.util.HostUtils; import com.arangodb.internal.util.RequestUtils; -import com.arangodb.Request; -import com.arangodb.Response; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -34,7 +34,7 @@ import java.io.IOException; import java.net.SocketTimeoutException; import java.util.concurrent.TimeoutException; -import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicLong; /** * @author Mark Vollmary @@ -44,13 +44,13 @@ public class HttpCommunication implements Closeable { private static final Logger LOGGER = LoggerFactory.getLogger(HttpCommunication.class); private final HostHandler hostHandler; private final InternalSerde serde; - private final AtomicInteger reqCount; + private final AtomicLong reqCount; private HttpCommunication(final HostHandler hostHandler, final InternalSerde serde) { super(); this.hostHandler = hostHandler; this.serde = serde; - reqCount = new AtomicInteger(); + reqCount = new AtomicLong(); } @Override @@ -67,7 +67,7 @@ private Response execute(final Request request, final HostHandle hostHandle, fin Host host = hostHandler.get(hostHandle, accessType); try { while (true) { - int reqId = reqCount.getAndIncrement(); + long reqId = reqCount.getAndIncrement(); try { final HttpConnection connection = (HttpConnection) host.connection(); if (LOGGER.isDebugEnabled()) { @@ -88,7 +88,7 @@ private Response execute(final Request request, final HostHandle hostHandle, fin // since the requests could not be idempotent. TimeoutException te = new TimeoutException(e.getMessage()); te.initCause(e); - throw new ArangoDBException(te); + throw new ArangoDBException(te, reqId); } catch (final IOException e) { hostHandler.fail(e); if (hostHandle != null && hostHandle.getHost() != null) { @@ -97,12 +97,12 @@ private Response execute(final Request request, final HostHandle hostHandle, fin final Host failedHost = host; host = hostHandler.get(hostHandle, accessType); if (host != null) { - LOGGER.warn(String.format("Could not connect to %s", failedHost.getDescription()), e); - LOGGER.warn(String.format("Could not connect to %s. Try connecting to %s", - failedHost.getDescription(), host.getDescription())); + LOGGER.warn("Could not connect to {} while executing request [id={}]", + failedHost.getDescription(), reqId, e); + LOGGER.debug("Try connecting to {}", host.getDescription()); } else { LOGGER.error(e.getMessage(), e); - throw new ArangoDBException(e); + throw new ArangoDBException(e, reqId); } } } From 8383c10fd4939d5a439be3befc9fad79a9445156 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Tue, 25 Oct 2022 14:43:39 +0200 Subject: [PATCH 161/254] [DE-418] native tests --- .github/workflows/maven.yml | 10 ++--- .github/workflows/native.yml | 2 +- pom.xml | 4 +- .../http-reflect-config.json | 29 -------------- .../native-image.properties | 9 ++++- .../arangodb-java-driver/reflect-config.json | 38 +++++++++++-------- .../arangodb-java-driver/resource-config.json | 10 +++++ .../serialization-config.json | 14 +++++++ src/main/resources/vertx/vertx-version.txt | 1 + .../native-image/native-image.properties | 6 ++- .../native-image/serialization-config.json | 5 +++ 11 files changed, 71 insertions(+), 57 deletions(-) delete mode 100644 src/main/resources/META-INF/native-image/com.arangodb/arangodb-java-driver/http-reflect-config.json create mode 100644 src/main/resources/META-INF/native-image/com.arangodb/arangodb-java-driver/resource-config.json create mode 100644 src/main/resources/META-INF/native-image/com.arangodb/arangodb-java-driver/serialization-config.json create mode 100644 src/main/resources/vertx/vertx-version.txt create mode 100644 src/test/resources/META-INF/native-image/serialization-config.json diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index 2db0f0546..fd679e851 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -38,12 +38,12 @@ jobs: user-language: - en include: - - docker-img: docker.io/arangodb/arangodb:3.9.3 + - docker-img: docker.io/arangodb/arangodb:3.10.0 topology: single db-ext-names: true java-version: 11 user-language: tr - - docker-img: docker.io/arangodb/enterprise:3.9.3 + - docker-img: docker.io/arangodb/enterprise:3.10.0 topology: cluster db-ext-names: true java-version: 17 @@ -93,7 +93,7 @@ jobs: fail-fast: false matrix: docker-img: - - docker.io/arangodb/enterprise:3.9.3 + - docker.io/arangodb/enterprise:3.10.0 topology: - single - cluster @@ -145,7 +145,7 @@ jobs: - 2.11.4 - 2.10.5 docker-img: - - docker.io/arangodb/arangodb:3.9.1 + - docker.io/arangodb/arangodb:3.10.0 topology: - single db-ext-names: @@ -183,7 +183,7 @@ jobs: fail-fast: false matrix: docker-img: - - docker.io/arangodb/enterprise:3.9.1 + - docker.io/arangodb/enterprise:3.10.0 topology: - cluster db-ext-names: diff --git a/.github/workflows/native.yml b/.github/workflows/native.yml index 61ee29718..8631862d9 100644 --- a/.github/workflows/native.yml +++ b/.github/workflows/native.yml @@ -14,7 +14,7 @@ jobs: fail-fast: false matrix: docker-img: - - docker.io/arangodb/enterprise:3.9.3 + - docker.io/arangodb/enterprise:3.10.0 topology: - cluster db-ext-names: diff --git a/pom.xml b/pom.xml index 84d2bd845..d2bb61fca 100644 --- a/pom.xml +++ b/pom.xml @@ -92,7 +92,7 @@ org.graalvm.buildtools native-maven-plugin - 0.9.13 + 0.9.16 true @@ -418,7 +418,7 @@ org.junit junit-bom - 5.9.0 + 5.9.1 pom import diff --git a/src/main/resources/META-INF/native-image/com.arangodb/arangodb-java-driver/http-reflect-config.json b/src/main/resources/META-INF/native-image/com.arangodb/arangodb-java-driver/http-reflect-config.json deleted file mode 100644 index 869cd250d..000000000 --- a/src/main/resources/META-INF/native-image/com.arangodb/arangodb-java-driver/http-reflect-config.json +++ /dev/null @@ -1,29 +0,0 @@ -[ - { - "name": "org.apache.commons.logging.impl.LogFactoryImpl", - "allDeclaredConstructors": true, - "allPublicConstructors": true, - "allDeclaredMethods": true, - "allPublicMethods": true, - "allDeclaredClasses": true, - "allPublicClasses": true - }, - { - "name": "org.apache.commons.logging.LogFactory", - "allDeclaredConstructors": true, - "allPublicConstructors": true, - "allDeclaredMethods": true, - "allPublicMethods": true, - "allDeclaredClasses": true, - "allPublicClasses": true - }, - { - "name": "org.apache.commons.logging.impl.SimpleLog", - "allDeclaredConstructors": true, - "allPublicConstructors": true, - "allDeclaredMethods": true, - "allPublicMethods": true, - "allDeclaredClasses": true, - "allPublicClasses": true - } -] \ No newline at end of file diff --git a/src/main/resources/META-INF/native-image/com.arangodb/arangodb-java-driver/native-image.properties b/src/main/resources/META-INF/native-image/com.arangodb/arangodb-java-driver/native-image.properties index c4b6a9e8f..264093215 100644 --- a/src/main/resources/META-INF/native-image/com.arangodb/arangodb-java-driver/native-image.properties +++ b/src/main/resources/META-INF/native-image/com.arangodb/arangodb-java-driver/native-image.properties @@ -1,2 +1,7 @@ -Args= -H:ReflectionConfigurationResources=${.}/reflect-config.json,${.}/http-reflect-config.json \ - --initialize-at-run-time=org.apache.http.impl.auth.NTLMEngineImpl,org.apache.http.conn.ssl.SSLConnectionSocketFactory +Args=\ +-H:ResourceConfigurationFiles=target/classes/META-INF/native-image/com.arangodb/arangodb-java-driver/resource-config.json \ +-H:ReflectionConfigurationResources=${.}/reflect-config.json \ +-H:SerializationConfigurationResources=${.}/serialization-config.json \ +--initialize-at-run-time=\ + io.netty.handler.ssl.BouncyCastleAlpnSslUtils,\ + io.netty.handler.codec.compression.ZstdOptions diff --git a/src/main/resources/META-INF/native-image/com.arangodb/arangodb-java-driver/reflect-config.json b/src/main/resources/META-INF/native-image/com.arangodb/arangodb-java-driver/reflect-config.json index db01aa4b2..c2874757c 100644 --- a/src/main/resources/META-INF/native-image/com.arangodb/arangodb-java-driver/reflect-config.json +++ b/src/main/resources/META-INF/native-image/com.arangodb/arangodb-java-driver/reflect-config.json @@ -41,12 +41,6 @@ "allDeclaredMethods": true, "allDeclaredConstructors": true }, - { - "name": "com.arangodb.entity.BaseDocument", - "allDeclaredFields": true, - "allDeclaredMethods": true, - "allDeclaredConstructors": true - }, { "name": "java.lang.Enum", "allDeclaredFields": true, @@ -84,37 +78,37 @@ "allDeclaredConstructors": true }, { - "name": "com.arangodb.entity.DocumentEntity", + "name": "com.arangodb.entity.AbstractBaseDocument", "allDeclaredFields": true, "allDeclaredMethods": true, "allDeclaredConstructors": true }, { - "name": "com.arangodb.entity.arangosearch.analyzer.SearchAnalyzer", + "name": "com.arangodb.entity.DocumentEntity", "allDeclaredFields": true, "allDeclaredMethods": true, "allDeclaredConstructors": true }, { - "name": "java.io.Serializable", + "name": "com.arangodb.entity.arangosearch.analyzer.SearchAnalyzer", "allDeclaredFields": true, "allDeclaredMethods": true, "allDeclaredConstructors": true }, { - "name": "com.arangodb.entity.arangosearch.SearchAliasPropertiesEntity", + "name": "java.io.Serializable", "allDeclaredFields": true, "allDeclaredMethods": true, "allDeclaredConstructors": true }, { - "name": "com.arangodb.entity.arangosearch.ArangoSearchPropertiesEntity", + "name": "com.arangodb.entity.arangosearch.SearchAliasPropertiesEntity", "allDeclaredFields": true, "allDeclaredMethods": true, "allDeclaredConstructors": true }, { - "name": "com.arangodb.entity.BaseEdgeDocument", + "name": "com.arangodb.entity.arangosearch.ArangoSearchPropertiesEntity", "allDeclaredFields": true, "allDeclaredMethods": true, "allDeclaredConstructors": true @@ -492,13 +486,13 @@ "allDeclaredConstructors": true }, { - "name": "com.arangodb.entity.arangosearch.analyzer.DelimiterAnalyzerProperties", + "name": "com.arangodb.entity.AqlExecutionExplainEntity$ExecutionStats", "allDeclaredFields": true, "allDeclaredMethods": true, "allDeclaredConstructors": true }, { - "name": "com.arangodb.entity.AqlExecutionExplainEntity$ExecutionStats", + "name": "com.arangodb.entity.arangosearch.analyzer.DelimiterAnalyzerProperties", "allDeclaredFields": true, "allDeclaredMethods": true, "allDeclaredConstructors": true @@ -719,6 +713,18 @@ "allDeclaredMethods": true, "allDeclaredConstructors": true }, + { + "name": "com.arangodb.entity.BaseEdgeDocument", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.BaseDocument", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, { "name": "com.arangodb.entity.EdgeUpdateEntity", "allDeclaredFields": true, @@ -1152,13 +1158,13 @@ "allDeclaredConstructors": true }, { - "name": "com.arangodb.model.StreamTransactionOptions", + "name": "com.arangodb.model.UserUpdateOptions", "allDeclaredFields": true, "allDeclaredMethods": true, "allDeclaredConstructors": true }, { - "name": "com.arangodb.model.UserUpdateOptions", + "name": "com.arangodb.model.StreamTransactionOptions", "allDeclaredFields": true, "allDeclaredMethods": true, "allDeclaredConstructors": true diff --git a/src/main/resources/META-INF/native-image/com.arangodb/arangodb-java-driver/resource-config.json b/src/main/resources/META-INF/native-image/com.arangodb/arangodb-java-driver/resource-config.json new file mode 100644 index 000000000..3bb430bb1 --- /dev/null +++ b/src/main/resources/META-INF/native-image/com.arangodb/arangodb-java-driver/resource-config.json @@ -0,0 +1,10 @@ +{ + "resources": { + "includes": [ + { + "pattern": "META-INF/vertx/vertx-version.txt" + } + ] + }, + "bundles": [] +} diff --git a/src/main/resources/META-INF/native-image/com.arangodb/arangodb-java-driver/serialization-config.json b/src/main/resources/META-INF/native-image/com.arangodb/arangodb-java-driver/serialization-config.json new file mode 100644 index 000000000..44081b42d --- /dev/null +++ b/src/main/resources/META-INF/native-image/com.arangodb/arangodb-java-driver/serialization-config.json @@ -0,0 +1,14 @@ +[ + { + "name": "com.arangodb.entity.AbstractBaseDocument" + }, + { + "name": "com.arangodb.entity.BaseDocument" + }, + { + "name": "com.arangodb.entity.BaseEdgeDocument" + }, + { + "name": "java.util.HashMap" + } +] diff --git a/src/main/resources/vertx/vertx-version.txt b/src/main/resources/vertx/vertx-version.txt new file mode 100644 index 000000000..a6695ff98 --- /dev/null +++ b/src/main/resources/vertx/vertx-version.txt @@ -0,0 +1 @@ +4.3.4 \ No newline at end of file diff --git a/src/test/resources/META-INF/native-image/native-image.properties b/src/test/resources/META-INF/native-image/native-image.properties index a18c4a2fe..36012e7f3 100644 --- a/src/test/resources/META-INF/native-image/native-image.properties +++ b/src/test/resources/META-INF/native-image/native-image.properties @@ -1,3 +1,5 @@ Args=\ - -H:ResourceConfigurationFiles=test-classes/META-INF/native-image/resource-config.json \ - -H:ReflectionConfigurationResources=${.}/reflect-config.json + -H:ResourceConfigurationFiles=target/test-classes/META-INF/native-image/resource-config.json \ + -H:ReflectionConfigurationResources=${.}/reflect-config.json \ + -H:SerializationConfigurationResources=${.}/serialization-config.json \ + --initialize-at-build-time=ch.qos.logback,org.slf4j diff --git a/src/test/resources/META-INF/native-image/serialization-config.json b/src/test/resources/META-INF/native-image/serialization-config.json new file mode 100644 index 000000000..7eba81efa --- /dev/null +++ b/src/test/resources/META-INF/native-image/serialization-config.json @@ -0,0 +1,5 @@ +[ + { + "name": "java.lang.String" + } +] From 3a2f660dddc51d6da5a3a9271ee5f32aa90ed95f Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Tue, 25 Oct 2022 20:33:00 +0200 Subject: [PATCH 162/254] ssl CI tests --- .github/workflows/maven.yml | 35 +++++++++++++++++++ pom.xml | 1 + src/test/java/com/arangodb/ArangoSslTest.java | 2 ++ .../async/example/ssl/SslExampleTest.java | 2 ++ .../arangodb/example/ssl/SslExampleTest.java | 2 ++ 5 files changed, 42 insertions(+) diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index fd679e851..e0117f0ec 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -69,6 +69,41 @@ jobs: - name: Test run: mvn --no-transfer-progress test -DargLine="-Duser.language=${{matrix.user-language}}" + test-ssl: + timeout-minutes: 10 + runs-on: ubuntu-latest + + strategy: + fail-fast: false + matrix: + docker-img: + - docker.io/arangodb/arangodb:3.10.0 + topology: + - single + java-version: + - 17 + + steps: + - uses: actions/checkout@v2 + - name: Set up JDK + uses: actions/setup-java@v2 + with: + java-version: ${{matrix.java-version}} + distribution: 'adopt' + cache: maven + - name: Start Database + run: ./docker/start_db.sh + env: + ARANGO_LICENSE_KEY: ${{ secrets.ARANGO_LICENSE_KEY }} + STARTER_MODE: ${{matrix.topology}} + DOCKER_IMAGE: ${{matrix.docker-img}} + DATABASE_EXTENDED_NAMES: ${{matrix.db-ext-names}} + SSL: true + - name: Info + run: mvn -version + - name: Test + run: mvn --no-transfer-progress -Dgroups=ssl -DSslTest=true test + # test encodeURIComponent() and normalize('NFC') comparing to Javascript behavior test-graalvm: runs-on: ubuntu-latest diff --git a/pom.xml b/pom.xml index d2bb61fca..0caf317db 100644 --- a/pom.xml +++ b/pom.xml @@ -164,6 +164,7 @@ true 1.8 1.8 + 8 diff --git a/src/test/java/com/arangodb/ArangoSslTest.java b/src/test/java/com/arangodb/ArangoSslTest.java index 52c9de434..875aeca33 100644 --- a/src/test/java/com/arangodb/ArangoSslTest.java +++ b/src/test/java/com/arangodb/ArangoSslTest.java @@ -21,6 +21,7 @@ package com.arangodb; import com.arangodb.entity.ArangoDBVersion; +import org.junit.jupiter.api.Tag; import org.junit.jupiter.api.condition.EnabledIfSystemProperty; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.EnumSource; @@ -40,6 +41,7 @@ * @author Mark Vollmary * @author Michele Rastelli */ +@Tag("ssl") @EnabledIfSystemProperty(named = "SslTest", matches = "true") class ArangoSslTest { diff --git a/src/test/java/com/arangodb/async/example/ssl/SslExampleTest.java b/src/test/java/com/arangodb/async/example/ssl/SslExampleTest.java index bba0fe6ec..3e39e7dff 100644 --- a/src/test/java/com/arangodb/async/example/ssl/SslExampleTest.java +++ b/src/test/java/com/arangodb/async/example/ssl/SslExampleTest.java @@ -22,6 +22,7 @@ import com.arangodb.async.ArangoDBAsync; import com.arangodb.entity.ArangoDBVersion; +import org.junit.jupiter.api.Tag; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.condition.EnabledIfSystemProperty; @@ -36,6 +37,7 @@ /** * @author Mark Vollmary */ +@Tag("ssl") @EnabledIfSystemProperty(named = "SslTest", matches = "true") class SslExampleTest { diff --git a/src/test/java/com/arangodb/example/ssl/SslExampleTest.java b/src/test/java/com/arangodb/example/ssl/SslExampleTest.java index 5dd54f204..b3f97ff16 100644 --- a/src/test/java/com/arangodb/example/ssl/SslExampleTest.java +++ b/src/test/java/com/arangodb/example/ssl/SslExampleTest.java @@ -25,6 +25,7 @@ import com.arangodb.ArangoDBMultipleException; import com.arangodb.Protocol; import com.arangodb.entity.ArangoDBVersion; +import org.junit.jupiter.api.Tag; import org.junit.jupiter.api.condition.EnabledIfSystemProperty; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.EnumSource; @@ -41,6 +42,7 @@ * @author Mark Vollmary * @author Michele Rastelli */ +@Tag("ssl") @EnabledIfSystemProperty(named = "SslTest", matches = "true") class SslExampleTest { From 5de5b9dd542fc82a4dab75b1f3e06b27b059ca98 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Wed, 26 Oct 2022 14:20:48 +0200 Subject: [PATCH 163/254] native ssl CI tests --- .github/workflows/maven.yml | 1 - .github/workflows/native.yml | 34 +++++++++++++++++++ pom.xml | 4 +++ src/test/java/com/arangodb/ArangoSslTest.java | 6 ++-- .../async/example/ssl/SslExampleTest.java | 3 +- .../native-image/native-image.properties | 5 ++- src/test/resources/arangodb-ssl.properties | 2 -- 7 files changed, 48 insertions(+), 7 deletions(-) delete mode 100644 src/test/resources/arangodb-ssl.properties diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index e0117f0ec..96a57d376 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -97,7 +97,6 @@ jobs: ARANGO_LICENSE_KEY: ${{ secrets.ARANGO_LICENSE_KEY }} STARTER_MODE: ${{matrix.topology}} DOCKER_IMAGE: ${{matrix.docker-img}} - DATABASE_EXTENDED_NAMES: ${{matrix.db-ext-names}} SSL: true - name: Info run: mvn -version diff --git a/.github/workflows/native.yml b/.github/workflows/native.yml index 8631862d9..3112392fb 100644 --- a/.github/workflows/native.yml +++ b/.github/workflows/native.yml @@ -41,3 +41,37 @@ jobs: run: mvn -version - name: Test Native run: mvn -Pnative --no-transfer-progress test + + test-native-ssl: + timeout-minutes: 20 + runs-on: ubuntu-latest + + strategy: + fail-fast: false + matrix: + docker-img: + - docker.io/arangodb/enterprise:3.10.0 + topology: + - single + java-version: + - 17 + + steps: + - uses: actions/checkout@v2 + - uses: graalvm/setup-graalvm@v1 + with: + version: 'latest' + java-version: ${{matrix.java-version}} + github-token: ${{ secrets.GITHUB_TOKEN }} + components: 'native-image,js' + - name: Start Database + run: ./docker/start_db.sh + env: + ARANGO_LICENSE_KEY: ${{ secrets.ARANGO_LICENSE_KEY }} + STARTER_MODE: ${{matrix.topology}} + DOCKER_IMAGE: ${{matrix.docker-img}} + SSL: true + - name: Info + run: mvn -version + - name: Test Native + run: mvn -Pnative --no-transfer-progress -Dgroups=ssl -DSslTest=true test diff --git a/pom.xml b/pom.xml index 0caf317db..56b1f12ff 100644 --- a/pom.xml +++ b/pom.xml @@ -26,6 +26,7 @@ 2.13.3 arangodb-1 https://sonarcloud.io + false @@ -110,6 +111,9 @@ --no-fallback + + ${SslTest} + diff --git a/src/test/java/com/arangodb/ArangoSslTest.java b/src/test/java/com/arangodb/ArangoSslTest.java index 875aeca33..9155e0419 100644 --- a/src/test/java/com/arangodb/ArangoSslTest.java +++ b/src/test/java/com/arangodb/ArangoSslTest.java @@ -74,7 +74,8 @@ void connect(Protocol protocol) throws Exception { final ArangoDB arangoDB = new ArangoDB.Builder() .useProtocol(protocol) - .loadProperties(ArangoSslTest.class.getResourceAsStream("/arangodb-ssl.properties")).useSsl(true) + .host("localhost", 8529) + .useSsl(true) .sslContext(sc).build(); final ArangoDBVersion version = arangoDB.getVersion(); assertThat(version).isNotNull(); @@ -85,7 +86,8 @@ void connect(Protocol protocol) throws Exception { void connectWithoutValidSslContext(Protocol protocol) { final ArangoDB arangoDB = new ArangoDB.Builder() .useProtocol(protocol) - .loadProperties(ArangoSslTest.class.getResourceAsStream("/arangodb-ssl.properties")).useSsl(true) + .host("localhost", 8529) + .useSsl(true) .build(); Throwable thrown = catchThrowable(arangoDB::getVersion); assertThat(thrown).isInstanceOf(ArangoDBException.class); diff --git a/src/test/java/com/arangodb/async/example/ssl/SslExampleTest.java b/src/test/java/com/arangodb/async/example/ssl/SslExampleTest.java index 3e39e7dff..33df7cf88 100644 --- a/src/test/java/com/arangodb/async/example/ssl/SslExampleTest.java +++ b/src/test/java/com/arangodb/async/example/ssl/SslExampleTest.java @@ -68,7 +68,8 @@ void connect() throws Exception { sc.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null); final ArangoDBAsync arangoDB = new ArangoDBAsync.Builder() - .loadProperties(SslExampleTest.class.getResourceAsStream("/arangodb-ssl.properties")).useSsl(true) + .host("localhost", 8529) + .useSsl(true) .sslContext(sc).build(); final ArangoDBVersion version = arangoDB.getVersion().get(); assertThat(version).isNotNull(); diff --git a/src/test/resources/META-INF/native-image/native-image.properties b/src/test/resources/META-INF/native-image/native-image.properties index 36012e7f3..0c3f4b841 100644 --- a/src/test/resources/META-INF/native-image/native-image.properties +++ b/src/test/resources/META-INF/native-image/native-image.properties @@ -2,4 +2,7 @@ Args=\ -H:ResourceConfigurationFiles=target/test-classes/META-INF/native-image/resource-config.json \ -H:ReflectionConfigurationResources=${.}/reflect-config.json \ -H:SerializationConfigurationResources=${.}/serialization-config.json \ - --initialize-at-build-time=ch.qos.logback,org.slf4j + --initialize-at-build-time=\ + ch.qos.logback,\ + org.slf4j,\ + org.junit.platform.engine.TestTag diff --git a/src/test/resources/arangodb-ssl.properties b/src/test/resources/arangodb-ssl.properties deleted file mode 100644 index cc3e07b70..000000000 --- a/src/test/resources/arangodb-ssl.properties +++ /dev/null @@ -1,2 +0,0 @@ -arangodb.hosts=localhost:8529 -arangodb.useSsl=true From 51dc2d43a886563e11ee651237d0a6e55535666b Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Thu, 27 Oct 2022 08:40:21 +0200 Subject: [PATCH 164/254] fixed java 8 compilation --- pom.xml | 1 - 1 file changed, 1 deletion(-) diff --git a/pom.xml b/pom.xml index 56b1f12ff..3cb091dab 100644 --- a/pom.xml +++ b/pom.xml @@ -168,7 +168,6 @@ true 1.8 1.8 - 8 From 520342a0d42dde31ea6a1c86e4fdb10ab85f1de5 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Thu, 27 Oct 2022 09:16:01 +0200 Subject: [PATCH 165/254] exceptions serialization test --- .../serialization-config.json | 12 ++++ .../java/com/arangodb/BaseDocumentTest.java | 29 ---------- .../java/com/arangodb/SerializableTest.java | 57 +++++++++++++++++++ .../native-image/serialization-config.json | 18 ++++++ 4 files changed, 87 insertions(+), 29 deletions(-) delete mode 100644 src/test/java/com/arangodb/BaseDocumentTest.java create mode 100644 src/test/java/com/arangodb/SerializableTest.java diff --git a/src/main/resources/META-INF/native-image/com.arangodb/arangodb-java-driver/serialization-config.json b/src/main/resources/META-INF/native-image/com.arangodb/arangodb-java-driver/serialization-config.json index 44081b42d..24dd5cb27 100644 --- a/src/main/resources/META-INF/native-image/com.arangodb/arangodb-java-driver/serialization-config.json +++ b/src/main/resources/META-INF/native-image/com.arangodb/arangodb-java-driver/serialization-config.json @@ -10,5 +10,17 @@ }, { "name": "java.util.HashMap" + }, + { + "name": "com.arangodb.entity.ErrorEntity" + }, + { + "name": "com.arangodb.ArangoDBException" + }, + { + "name": "com.arangodb.ArangoDBMultipleException" + }, + { + "name": "com.arangodb.internal.net.ArangoDBRedirectException" } ] diff --git a/src/test/java/com/arangodb/BaseDocumentTest.java b/src/test/java/com/arangodb/BaseDocumentTest.java deleted file mode 100644 index 52314ba85..000000000 --- a/src/test/java/com/arangodb/BaseDocumentTest.java +++ /dev/null @@ -1,29 +0,0 @@ -package com.arangodb; - -import com.arangodb.entity.BaseDocument; -import org.junit.jupiter.api.Test; - -import java.io.*; - -import static org.assertj.core.api.Assertions.assertThat; - -public class BaseDocumentTest { - @Test - public void serializeBaseDocument() throws IOException, ClassNotFoundException { - BaseDocument bd = new BaseDocument("poaids"); - bd.setId("apdso/02193"); - bd.setRevision("poip"); - bd.addAttribute("aaa", "bbb"); - - ByteArrayOutputStream os = new ByteArrayOutputStream(); - ObjectOutputStream objectOutputStream = new ObjectOutputStream(os); - objectOutputStream.writeObject(bd); - - InputStream is = new ByteArrayInputStream(os.toByteArray()); - ObjectInputStream objectInputStream = new ObjectInputStream(is); - BaseDocument bd2 = (BaseDocument) objectInputStream.readObject(); - objectInputStream.close(); - - assertThat(bd).isEqualTo(bd2); - } -} diff --git a/src/test/java/com/arangodb/SerializableTest.java b/src/test/java/com/arangodb/SerializableTest.java new file mode 100644 index 000000000..c1e770530 --- /dev/null +++ b/src/test/java/com/arangodb/SerializableTest.java @@ -0,0 +1,57 @@ +package com.arangodb; + +import com.arangodb.entity.BaseDocument; +import com.arangodb.entity.ErrorEntity; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.JsonNodeFactory; +import org.junit.jupiter.api.Test; + +import java.io.*; + +import static org.assertj.core.api.Assertions.assertThat; + +public class SerializableTest { + + @Test + public void serializeBaseDocument() throws IOException, ClassNotFoundException { + BaseDocument bd = new BaseDocument("poaids"); + bd.setId("apdso/02193"); + bd.setRevision("poip"); + bd.addAttribute("aaa", "bbb"); + + BaseDocument bd2 = roundTrip(bd); + assertThat(bd).isEqualTo(bd2); + } + + @Test + public void serializeArangoDBException() throws IOException, ClassNotFoundException { + ObjectMapper mapper = new ObjectMapper(); + JsonNode jn = JsonNodeFactory.instance.objectNode() + .put("errorMessage", "boomError") + .put("exception", "boomException") + .put("code", 11) + .put("errorNum", 22); + ErrorEntity ee = mapper.readerFor(ErrorEntity.class).readValue(jn); + ArangoDBException e = new ArangoDBException(ee); + + ArangoDBException e2 = roundTrip(e); + assertThat(e2.getException()).isEqualTo(e.getException()); + assertThat(e2.getResponseCode()).isEqualTo(e.getResponseCode()); + assertThat(e2.getErrorNum()).isEqualTo(e.getErrorNum()); + assertThat(e2.getRequestId()).isEqualTo(e.getRequestId()); + } + + private T roundTrip(T input) throws IOException, ClassNotFoundException { + ByteArrayOutputStream os = new ByteArrayOutputStream(); + ObjectOutputStream objectOutputStream = new ObjectOutputStream(os); + objectOutputStream.writeObject(input); + + InputStream is = new ByteArrayInputStream(os.toByteArray()); + ObjectInputStream objectInputStream = new ObjectInputStream(is); + T output = (T) objectInputStream.readObject(); + objectInputStream.close(); + + return output; + } +} diff --git a/src/test/resources/META-INF/native-image/serialization-config.json b/src/test/resources/META-INF/native-image/serialization-config.json index 7eba81efa..2871e9998 100644 --- a/src/test/resources/META-INF/native-image/serialization-config.json +++ b/src/test/resources/META-INF/native-image/serialization-config.json @@ -1,5 +1,23 @@ [ + { + "name": "java.lang.Exception" + }, + { + "name": "java.lang.RuntimeException" + }, + { + "name": "java.lang.StackTraceElement" + }, + { + "name": "java.lang.StackTraceElement[]" + }, { "name": "java.lang.String" + }, + { + "name": "java.lang.Throwable" + }, + { + "name": "java.util.Collections$EmptyList" } ] From a5d004d095ce529dec54c95ddf47b8b78392256e Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Thu, 27 Oct 2022 10:58:18 +0200 Subject: [PATCH 166/254] code analysis fixes --- src/main/java/com/arangodb/Request.java | 10 +++---- .../com/arangodb/async/ArangoDBAsync.java | 12 +------- .../internal/ArangoCollectionAsyncImpl.java | 2 +- .../internal/ArangoDatabaseAsyncImpl.java | 10 +++++-- .../ArangoEdgeCollectionAsyncImpl.java | 12 ++++---- .../ArangoVertexCollectionAsyncImpl.java | 12 ++++---- .../async/internal/ExceptionUtil.java | 4 +++ .../velocystream/VstCommunicationAsync.java | 5 +++- .../arangodb/entity/AbstractBaseDocument.java | 21 +++++++++----- .../com/arangodb/entity/BaseEdgeDocument.java | 17 +++++++---- src/main/java/com/arangodb/entity/From.java | 2 +- src/main/java/com/arangodb/entity/Id.java | 2 +- src/main/java/com/arangodb/entity/Key.java | 2 +- src/main/java/com/arangodb/entity/Rev.java | 2 +- src/main/java/com/arangodb/entity/To.java | 2 +- .../arangosearch/ConsolidationPolicy.java | 4 --- .../analyzer/IdentityAnalyzer.java | 7 ----- .../internal/ArangoCollectionImpl.java | 4 +-- .../internal/ArangoEdgeCollectionImpl.java | 12 ++++---- .../internal/ArangoVertexCollectionImpl.java | 12 ++++---- .../internal/InternalArangoCollection.java | 4 +-- .../internal/InternalArangoDBBuilder.java | 4 +-- .../InternalArangoEdgeCollection.java | 27 ++++++++--------- .../internal/InternalArangoSearch.java | 8 +++-- .../InternalArangoVertexCollection.java | 29 ++++++++++--------- .../internal/InternalSearchAlias.java | 8 +++-- .../internal/cursor/ArangoCursorIterator.java | 2 +- .../internal/http/HttpConnection.java | 17 ++++++----- .../internal/net/ConnectionPoolImpl.java | 2 +- .../internal/net/ExtendedHostResolver.java | 12 ++++---- .../com/arangodb/internal/net/HostSet.java | 8 ++--- .../serde/InternalAnnotationIntrospector.java | 15 ++++++++-- .../internal/serde/InternalSerializers.java | 2 +- .../velocystream/internal/MessageStore.java | 2 +- .../java/com/arangodb/model/IndexOptions.java | 3 +- .../arangosearch/AnalyzerDeleteOptions.java | 3 -- 36 files changed, 159 insertions(+), 141 deletions(-) diff --git a/src/main/java/com/arangodb/Request.java b/src/main/java/com/arangodb/Request.java index f4b626eb1..f3c8e9429 100644 --- a/src/main/java/com/arangodb/Request.java +++ b/src/main/java/com/arangodb/Request.java @@ -32,7 +32,7 @@ public class Request { private final DbName dbName; private final RequestType requestType; - private final String request; + private final String path; private final Map queryParam; private final Map headerParam; private int version = 1; @@ -43,7 +43,7 @@ public Request(final DbName dbName, final RequestType requestType, final String super(); this.dbName = dbName; this.requestType = requestType; - this.request = path; + this.path = path; body = null; queryParam = new HashMap<>(); headerParam = new HashMap<>(); @@ -75,8 +75,8 @@ public RequestType getRequestType() { return requestType; } - public String getRequest() { - return request; + public String getPath() { + return path; } public Map getQueryParam() { @@ -128,7 +128,7 @@ public String toString() { return "{" + "requestType=" + requestType + ", database='" + dbName + '\'' + - ", url='" + request + '\'' + + ", url='" + path + '\'' + ", parameters=" + queryParam + ", headers=" + headerParam + '}'; diff --git a/src/main/java/com/arangodb/async/ArangoDBAsync.java b/src/main/java/com/arangodb/async/ArangoDBAsync.java index 0c3c8ec61..adea1eee3 100644 --- a/src/main/java/com/arangodb/async/ArangoDBAsync.java +++ b/src/main/java/com/arangodb/async/ArangoDBAsync.java @@ -20,10 +20,7 @@ package com.arangodb.async; -import com.arangodb.ArangoMetrics; -import com.arangodb.ArangoSerdeAccessor; -import com.arangodb.DbName; -import com.arangodb.Protocol; +import com.arangodb.*; import com.arangodb.async.internal.ArangoDBAsyncImpl; import com.arangodb.async.internal.velocystream.VstCommunicationAsync; import com.arangodb.async.internal.velocystream.VstConnectionFactoryAsync; @@ -41,12 +38,7 @@ import com.arangodb.model.UserCreateOptions; import com.arangodb.model.UserUpdateOptions; import com.arangodb.serde.ArangoSerde; -import com.arangodb.ContentType; import com.arangodb.serde.JacksonSerde; -import com.arangodb.Request; -import com.arangodb.Response; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import javax.annotation.concurrent.ThreadSafe; import javax.net.ssl.SSLContext; @@ -312,8 +304,6 @@ public interface ArangoDBAsync extends ArangoSerdeAccessor { */ class Builder extends InternalArangoDBBuilder { - private static final Logger logger = LoggerFactory.getLogger(Builder.class); - public Builder() { super(); } diff --git a/src/main/java/com/arangodb/async/internal/ArangoCollectionAsyncImpl.java b/src/main/java/com/arangodb/async/internal/ArangoCollectionAsyncImpl.java index a850af8db..f521ab329 100644 --- a/src/main/java/com/arangodb/async/internal/ArangoCollectionAsyncImpl.java +++ b/src/main/java/com/arangodb/async/internal/ArangoCollectionAsyncImpl.java @@ -155,7 +155,7 @@ public CompletableFuture> getDocuments( final Collection keys, final Class type, final DocumentReadOptions options) { - return executor.execute(getDocumentsRequest(keys, options), getDocumentsResponseDeserializer(type, options)); + return executor.execute(getDocumentsRequest(keys, options), getDocumentsResponseDeserializer(type)); } @Override diff --git a/src/main/java/com/arangodb/async/internal/ArangoDatabaseAsyncImpl.java b/src/main/java/com/arangodb/async/internal/ArangoDatabaseAsyncImpl.java index 4d723b1be..180f2671c 100644 --- a/src/main/java/com/arangodb/async/internal/ArangoDatabaseAsyncImpl.java +++ b/src/main/java/com/arangodb/async/internal/ArangoDatabaseAsyncImpl.java @@ -228,7 +228,10 @@ public InternalCursorEntity next(final String id, Map meta) { InternalCursorEntity.class, hostHandle); try { return result.get(); - } catch (InterruptedException | ExecutionException e) { + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new ArangoDBException(e); + } catch (ExecutionException e) { throw new ArangoDBException(e); } } @@ -237,7 +240,10 @@ public InternalCursorEntity next(final String id, Map meta) { public void close(final String id, Map meta) { try { executor.execute(queryCloseRequest(id, options, meta), Void.class, hostHandle).get(); - } catch (InterruptedException | ExecutionException e) { + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new ArangoDBException(e); + } catch (ExecutionException e) { throw new ArangoDBException(e); } } diff --git a/src/main/java/com/arangodb/async/internal/ArangoEdgeCollectionAsyncImpl.java b/src/main/java/com/arangodb/async/internal/ArangoEdgeCollectionAsyncImpl.java index 9edaf9a91..05cb56af3 100644 --- a/src/main/java/com/arangodb/async/internal/ArangoEdgeCollectionAsyncImpl.java +++ b/src/main/java/com/arangodb/async/internal/ArangoEdgeCollectionAsyncImpl.java @@ -43,12 +43,12 @@ public class ArangoEdgeCollectionAsyncImpl extends @Override public CompletableFuture insertEdge(final Object value) { return executor.execute(insertEdgeRequest(value, new EdgeCreateOptions()), - insertEdgeResponseDeserializer(value)); + insertEdgeResponseDeserializer()); } @Override public CompletableFuture insertEdge(final Object value, final EdgeCreateOptions options) { - return executor.execute(insertEdgeRequest(value, options), insertEdgeResponseDeserializer(value)); + return executor.execute(insertEdgeRequest(value, options), insertEdgeResponseDeserializer()); } @Override @@ -66,7 +66,7 @@ public CompletableFuture getEdge(final String key, final Class type, @Override public CompletableFuture replaceEdge(final String key, final Object value) { return executor.execute(replaceEdgeRequest(key, value, new EdgeReplaceOptions()), - replaceEdgeResponseDeserializer(value)); + replaceEdgeResponseDeserializer()); } @Override @@ -74,13 +74,13 @@ public CompletableFuture replaceEdge( final String key, final Object value, final EdgeReplaceOptions options) { - return executor.execute(replaceEdgeRequest(key, value, options), replaceEdgeResponseDeserializer(value)); + return executor.execute(replaceEdgeRequest(key, value, options), replaceEdgeResponseDeserializer()); } @Override public CompletableFuture updateEdge(final String key, final Object value) { return executor.execute(updateEdgeRequest(key, value, new EdgeUpdateOptions()), - updateEdgeResponseDeserializer(value)); + updateEdgeResponseDeserializer()); } @Override @@ -88,7 +88,7 @@ public CompletableFuture updateEdge( final String key, final Object value, final EdgeUpdateOptions options) { - return executor.execute(updateEdgeRequest(key, value, options), updateEdgeResponseDeserializer(value)); + return executor.execute(updateEdgeRequest(key, value, options), updateEdgeResponseDeserializer()); } @Override diff --git a/src/main/java/com/arangodb/async/internal/ArangoVertexCollectionAsyncImpl.java b/src/main/java/com/arangodb/async/internal/ArangoVertexCollectionAsyncImpl.java index 018b5ee57..a5e490850 100644 --- a/src/main/java/com/arangodb/async/internal/ArangoVertexCollectionAsyncImpl.java +++ b/src/main/java/com/arangodb/async/internal/ArangoVertexCollectionAsyncImpl.java @@ -48,12 +48,12 @@ public CompletableFuture drop() { @Override public CompletableFuture insertVertex(final Object value) { return executor.execute(insertVertexRequest(value, new VertexCreateOptions()), - insertVertexResponseDeserializer(value)); + insertVertexResponseDeserializer()); } @Override public CompletableFuture insertVertex(final Object value, final VertexCreateOptions options) { - return executor.execute(insertVertexRequest(value, options), insertVertexResponseDeserializer(value)); + return executor.execute(insertVertexRequest(value, options), insertVertexResponseDeserializer()); } @Override @@ -73,7 +73,7 @@ public CompletableFuture getVertex( @Override public CompletableFuture replaceVertex(final String key, final Object value) { return executor.execute(replaceVertexRequest(key, value, new VertexReplaceOptions()), - replaceVertexResponseDeserializer(value)); + replaceVertexResponseDeserializer()); } @Override @@ -81,13 +81,13 @@ public CompletableFuture replaceVertex( final String key, final Object value, final VertexReplaceOptions options) { - return executor.execute(replaceVertexRequest(key, value, options), replaceVertexResponseDeserializer(value)); + return executor.execute(replaceVertexRequest(key, value, options), replaceVertexResponseDeserializer()); } @Override public CompletableFuture updateVertex(final String key, final Object value) { return executor.execute(updateVertexRequest(key, value, new VertexUpdateOptions()), - updateVertexResponseDeserializer(value)); + updateVertexResponseDeserializer()); } @Override @@ -95,7 +95,7 @@ public CompletableFuture updateVertex( final String key, final Object value, final VertexUpdateOptions options) { - return executor.execute(updateVertexRequest(key, value, options), updateVertexResponseDeserializer(value)); + return executor.execute(updateVertexRequest(key, value, options), updateVertexResponseDeserializer()); } @Override diff --git a/src/main/java/com/arangodb/async/internal/ExceptionUtil.java b/src/main/java/com/arangodb/async/internal/ExceptionUtil.java index d31c2000d..422e779ed 100644 --- a/src/main/java/com/arangodb/async/internal/ExceptionUtil.java +++ b/src/main/java/com/arangodb/async/internal/ExceptionUtil.java @@ -29,6 +29,10 @@ * @author Michele Rastelli */ class ExceptionUtil { + + private ExceptionUtil() { + } + static Function catchGetDocumentExceptions() { return throwable -> { if (throwable instanceof CompletionException) { diff --git a/src/main/java/com/arangodb/async/internal/velocystream/VstCommunicationAsync.java b/src/main/java/com/arangodb/async/internal/velocystream/VstCommunicationAsync.java index 9f33bd3c9..e0eab0092 100644 --- a/src/main/java/com/arangodb/async/internal/velocystream/VstCommunicationAsync.java +++ b/src/main/java/com/arangodb/async/internal/velocystream/VstCommunicationAsync.java @@ -137,7 +137,10 @@ protected void authenticate(final VstConnectionAsync connection) { Response response; try { response = execute(authRequest, connection).get(); - } catch (final InterruptedException | ExecutionException e) { + } catch (final InterruptedException e) { + Thread.currentThread().interrupt(); + throw new ArangoDBException(e); + } catch (final ExecutionException e) { Throwable cause = e.getCause(); if (cause instanceof ArangoDBException) { throw (ArangoDBException) cause; diff --git a/src/main/java/com/arangodb/entity/AbstractBaseDocument.java b/src/main/java/com/arangodb/entity/AbstractBaseDocument.java index 889c34542..8c1367242 100644 --- a/src/main/java/com/arangodb/entity/AbstractBaseDocument.java +++ b/src/main/java/com/arangodb/entity/AbstractBaseDocument.java @@ -20,6 +20,7 @@ package com.arangodb.entity; +import com.arangodb.internal.DocumentFields; import com.fasterxml.jackson.annotation.JsonAnyGetter; import com.fasterxml.jackson.annotation.JsonAnySetter; import com.fasterxml.jackson.annotation.JsonIgnore; @@ -39,8 +40,12 @@ abstract class AbstractBaseDocument implements Serializable { private static final long serialVersionUID = 846874908582L; - private static final String[] META_PROPS = new String[]{"_id", "_key", "_rev"}; - private final Map properties; + private static final String[] META_PROPS = new String[]{ + DocumentFields.ID, + DocumentFields.KEY, + DocumentFields.REV + }; + private final HashMap properties; AbstractBaseDocument() { properties = new HashMap<>(); @@ -58,29 +63,29 @@ abstract class AbstractBaseDocument implements Serializable { @JsonIgnore public String getId() { - return (String) getAttribute("_id"); + return (String) getAttribute(DocumentFields.ID); } public void setId(final String id) { - addAttribute("_id", id); + addAttribute(DocumentFields.ID, id); } @JsonIgnore public String getKey() { - return (String) getAttribute("_key"); + return (String) getAttribute(DocumentFields.KEY); } public void setKey(final String key) { - addAttribute("_key", key); + addAttribute(DocumentFields.KEY, key); } @JsonIgnore public String getRevision() { - return (String) getAttribute("_rev"); + return (String) getAttribute(DocumentFields.REV); } public void setRevision(final String rev) { - addAttribute("_rev", rev); + addAttribute(DocumentFields.REV, rev); } @JsonInclude diff --git a/src/main/java/com/arangodb/entity/BaseEdgeDocument.java b/src/main/java/com/arangodb/entity/BaseEdgeDocument.java index fcf082256..625fcaf1d 100644 --- a/src/main/java/com/arangodb/entity/BaseEdgeDocument.java +++ b/src/main/java/com/arangodb/entity/BaseEdgeDocument.java @@ -20,6 +20,7 @@ package com.arangodb.entity; +import com.arangodb.internal.DocumentFields; import com.fasterxml.jackson.annotation.JsonIgnore; import java.io.Serializable; @@ -33,7 +34,13 @@ public final class BaseEdgeDocument extends AbstractBaseDocument implements Seri private static final long serialVersionUID = 356629614444L; - private static final String[] META_PROPS = new String[]{"_id", "_key", "_rev", "_from", "_to"}; + private static final String[] META_PROPS = new String[]{ + DocumentFields.ID, + DocumentFields.KEY, + DocumentFields.REV, + DocumentFields.FROM, + DocumentFields.TO + }; public BaseEdgeDocument() { super(); @@ -57,20 +64,20 @@ public BaseEdgeDocument(final Map properties) { @JsonIgnore public String getFrom() { - return (String) getAttribute("_from"); + return (String) getAttribute(DocumentFields.FROM); } public void setFrom(final String from) { - addAttribute("_from", from); + addAttribute(DocumentFields.FROM, from); } @JsonIgnore public String getTo() { - return (String) getAttribute("_to"); + return (String) getAttribute(DocumentFields.TO); } public void setTo(final String to) { - addAttribute("_to", to); + addAttribute(DocumentFields.TO, to); } @Override diff --git a/src/main/java/com/arangodb/entity/From.java b/src/main/java/com/arangodb/entity/From.java index 0ded39c1e..1e82ae341 100644 --- a/src/main/java/com/arangodb/entity/From.java +++ b/src/main/java/com/arangodb/entity/From.java @@ -21,6 +21,6 @@ @JsonProperty(DocumentFields.FROM) @JsonInclude(JsonInclude.Include.NON_NULL) @JsonbAnnotation -@JsonbProperty("_from") +@JsonbProperty(DocumentFields.FROM) public @interface From { } diff --git a/src/main/java/com/arangodb/entity/Id.java b/src/main/java/com/arangodb/entity/Id.java index 2e3cd61b9..f0e55dcb6 100644 --- a/src/main/java/com/arangodb/entity/Id.java +++ b/src/main/java/com/arangodb/entity/Id.java @@ -21,6 +21,6 @@ @JsonProperty(DocumentFields.ID) @JsonInclude(JsonInclude.Include.NON_NULL) @JsonbAnnotation -@JsonbProperty("_id") +@JsonbProperty(DocumentFields.ID) public @interface Id { } diff --git a/src/main/java/com/arangodb/entity/Key.java b/src/main/java/com/arangodb/entity/Key.java index 8a5fb15ce..fd146d011 100644 --- a/src/main/java/com/arangodb/entity/Key.java +++ b/src/main/java/com/arangodb/entity/Key.java @@ -21,6 +21,6 @@ @JsonProperty(DocumentFields.KEY) @JsonInclude(JsonInclude.Include.NON_NULL) @JsonbAnnotation -@JsonbProperty("_key") +@JsonbProperty(DocumentFields.KEY) public @interface Key { } diff --git a/src/main/java/com/arangodb/entity/Rev.java b/src/main/java/com/arangodb/entity/Rev.java index 241e0ed8a..63189e565 100644 --- a/src/main/java/com/arangodb/entity/Rev.java +++ b/src/main/java/com/arangodb/entity/Rev.java @@ -21,6 +21,6 @@ @JsonProperty(DocumentFields.REV) @JsonInclude(JsonInclude.Include.NON_NULL) @JsonbAnnotation -@JsonbProperty("_rev") +@JsonbProperty(DocumentFields.REV) public @interface Rev { } diff --git a/src/main/java/com/arangodb/entity/To.java b/src/main/java/com/arangodb/entity/To.java index 4ebb0006c..113496d86 100644 --- a/src/main/java/com/arangodb/entity/To.java +++ b/src/main/java/com/arangodb/entity/To.java @@ -21,6 +21,6 @@ @JsonProperty(DocumentFields.TO) @JsonInclude(JsonInclude.Include.NON_NULL) @JsonbAnnotation -@JsonbProperty("_to") +@JsonbProperty(DocumentFields.TO) public @interface To { } diff --git a/src/main/java/com/arangodb/entity/arangosearch/ConsolidationPolicy.java b/src/main/java/com/arangodb/entity/arangosearch/ConsolidationPolicy.java index 9148ff7c7..cfba95e74 100644 --- a/src/main/java/com/arangodb/entity/arangosearch/ConsolidationPolicy.java +++ b/src/main/java/com/arangodb/entity/arangosearch/ConsolidationPolicy.java @@ -35,10 +35,6 @@ public final class ConsolidationPolicy { private Long segmentsBytesFloor; private Long minScore; - - public ConsolidationPolicy() { - } - public static ConsolidationPolicy of(final ConsolidationType type) { return new ConsolidationPolicy().type(type); } diff --git a/src/main/java/com/arangodb/entity/arangosearch/analyzer/IdentityAnalyzer.java b/src/main/java/com/arangodb/entity/arangosearch/analyzer/IdentityAnalyzer.java index dbb412397..7cf1b12e7 100644 --- a/src/main/java/com/arangodb/entity/arangosearch/analyzer/IdentityAnalyzer.java +++ b/src/main/java/com/arangodb/entity/arangosearch/analyzer/IdentityAnalyzer.java @@ -33,11 +33,4 @@ public final class IdentityAnalyzer extends SearchAnalyzer { public IdentityAnalyzer() { setType(AnalyzerType.identity); } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - return super.equals(o); - } } diff --git a/src/main/java/com/arangodb/internal/ArangoCollectionImpl.java b/src/main/java/com/arangodb/internal/ArangoCollectionImpl.java index 8c1c6aa0a..0f8f8834f 100644 --- a/src/main/java/com/arangodb/internal/ArangoCollectionImpl.java +++ b/src/main/java/com/arangodb/internal/ArangoCollectionImpl.java @@ -40,7 +40,7 @@ public class ArangoCollectionImpl extends InternalArangoCollection implements ArangoCollection { - private static final Logger LOGGER = LoggerFactory.getLogger(ArangoCollection.class); + private static final Logger LOGGER = LoggerFactory.getLogger(ArangoCollectionImpl.class); protected ArangoCollectionImpl(final ArangoDatabaseImpl db, final String name) { super(db, name); @@ -159,7 +159,7 @@ public MultiDocumentEntity getDocuments(final Collection keys, fi @Override public MultiDocumentEntity getDocuments( final Collection keys, final Class type, final DocumentReadOptions options) { - return executor.execute(getDocumentsRequest(keys, options), getDocumentsResponseDeserializer(type, options)); + return executor.execute(getDocumentsRequest(keys, options), getDocumentsResponseDeserializer(type)); } @Override diff --git a/src/main/java/com/arangodb/internal/ArangoEdgeCollectionImpl.java b/src/main/java/com/arangodb/internal/ArangoEdgeCollectionImpl.java index 4793c45e9..1b593beac 100644 --- a/src/main/java/com/arangodb/internal/ArangoEdgeCollectionImpl.java +++ b/src/main/java/com/arangodb/internal/ArangoEdgeCollectionImpl.java @@ -44,12 +44,12 @@ protected ArangoEdgeCollectionImpl(final ArangoGraphImpl graph, final String nam @Override public EdgeEntity insertEdge(final Object value) { return executor.execute(insertEdgeRequest(value, new EdgeCreateOptions()), - insertEdgeResponseDeserializer(value)); + insertEdgeResponseDeserializer()); } @Override public EdgeEntity insertEdge(final Object value, final EdgeCreateOptions options) { - return executor.execute(insertEdgeRequest(value, options), insertEdgeResponseDeserializer(value)); + return executor.execute(insertEdgeRequest(value, options), insertEdgeResponseDeserializer()); } @Override @@ -80,23 +80,23 @@ public T getEdge(final String key, final Class type, final GraphDocumentR @Override public EdgeUpdateEntity replaceEdge(final String key, final Object value) { return executor.execute(replaceEdgeRequest(key, value, new EdgeReplaceOptions()), - replaceEdgeResponseDeserializer(value)); + replaceEdgeResponseDeserializer()); } @Override public EdgeUpdateEntity replaceEdge(final String key, final Object value, final EdgeReplaceOptions options) { - return executor.execute(replaceEdgeRequest(key, value, options), replaceEdgeResponseDeserializer(value)); + return executor.execute(replaceEdgeRequest(key, value, options), replaceEdgeResponseDeserializer()); } @Override public EdgeUpdateEntity updateEdge(final String key, final Object value) { return executor.execute(updateEdgeRequest(key, value, new EdgeUpdateOptions()), - updateEdgeResponseDeserializer(value)); + updateEdgeResponseDeserializer()); } @Override public EdgeUpdateEntity updateEdge(final String key, final Object value, final EdgeUpdateOptions options) { - return executor.execute(updateEdgeRequest(key, value, options), updateEdgeResponseDeserializer(value)); + return executor.execute(updateEdgeRequest(key, value, options), updateEdgeResponseDeserializer()); } @Override diff --git a/src/main/java/com/arangodb/internal/ArangoVertexCollectionImpl.java b/src/main/java/com/arangodb/internal/ArangoVertexCollectionImpl.java index 148aea746..7fb752905 100644 --- a/src/main/java/com/arangodb/internal/ArangoVertexCollectionImpl.java +++ b/src/main/java/com/arangodb/internal/ArangoVertexCollectionImpl.java @@ -49,12 +49,12 @@ public void drop() { @Override public VertexEntity insertVertex(final Object value) { return executor.execute(insertVertexRequest(value, new VertexCreateOptions()), - insertVertexResponseDeserializer(value)); + insertVertexResponseDeserializer()); } @Override public VertexEntity insertVertex(final Object value, final VertexCreateOptions options) { - return executor.execute(insertVertexRequest(value, options), insertVertexResponseDeserializer(value)); + return executor.execute(insertVertexRequest(value, options), insertVertexResponseDeserializer()); } @Override @@ -85,23 +85,23 @@ public T getVertex(final String key, final Class type, final GraphDocumen @Override public VertexUpdateEntity replaceVertex(final String key, final Object value) { return executor.execute(replaceVertexRequest(key, value, new VertexReplaceOptions()), - replaceVertexResponseDeserializer(value)); + replaceVertexResponseDeserializer()); } @Override public VertexUpdateEntity replaceVertex(final String key, final Object value, final VertexReplaceOptions options) { - return executor.execute(replaceVertexRequest(key, value, options), replaceVertexResponseDeserializer(value)); + return executor.execute(replaceVertexRequest(key, value, options), replaceVertexResponseDeserializer()); } @Override public VertexUpdateEntity updateVertex(final String key, final Object value) { return executor.execute(updateVertexRequest(key, value, new VertexUpdateOptions()), - updateVertexResponseDeserializer(value)); + updateVertexResponseDeserializer()); } @Override public VertexUpdateEntity updateVertex(final String key, final Object value, final VertexUpdateOptions options) { - return executor.execute(updateVertexRequest(key, value, options), updateVertexResponseDeserializer(value)); + return executor.execute(updateVertexRequest(key, value, options), updateVertexResponseDeserializer()); } @Override diff --git a/src/main/java/com/arangodb/internal/InternalArangoCollection.java b/src/main/java/com/arangodb/internal/InternalArangoCollection.java index 7d31e31d5..2b8e625c0 100644 --- a/src/main/java/com/arangodb/internal/InternalArangoCollection.java +++ b/src/main/java/com/arangodb/internal/InternalArangoCollection.java @@ -56,11 +56,9 @@ public abstract class InternalArangoCollection, D private static final String KEEP_NULL = "keepNull"; private static final String IGNORE_REVS = "ignoreRevs"; private static final String RETURN_NEW = "returnNew"; - private static final String NEW = "new"; private static final String RETURN_OLD = "returnOld"; private static final String OVERWRITE = "overwrite"; private static final String OVERWRITE_MODE = "overwriteMode"; - private static final String OLD = "old"; private static final String SILENT = "silent"; private static final String TRANSACTION_ID = "x-arango-trx-id"; @@ -191,7 +189,7 @@ protected Request getDocumentsRequest(final Collection keys, final Docum } protected ResponseDeserializer> getDocumentsResponseDeserializer( - final Class type, final DocumentReadOptions options) { + final Class type) { return response -> { final MultiDocumentEntity multiDocument = new MultiDocumentEntity<>(); boolean potentialDirtyRead = Boolean.parseBoolean(response.getMeta("X-Arango-Potential-Dirty-Read")); diff --git a/src/main/java/com/arangodb/internal/InternalArangoDBBuilder.java b/src/main/java/com/arangodb/internal/InternalArangoDBBuilder.java index 7efa13c3a..28ba4d254 100644 --- a/src/main/java/com/arangodb/internal/InternalArangoDBBuilder.java +++ b/src/main/java/com/arangodb/internal/InternalArangoDBBuilder.java @@ -78,7 +78,7 @@ public abstract class InternalArangoDBBuilder { protected Integer responseQueueTimeSamples; - public InternalArangoDBBuilder() { + protected InternalArangoDBBuilder() { super(); hosts = new ArrayList<>(); user = ArangoDefaults.DEFAULT_USER; @@ -320,7 +320,7 @@ protected HostHandler createHostHandler(final HostResolver hostResolver) { hostHandler = new FallbackHostHandler(hostResolver); } - LOG.debug("HostHandler is " + hostHandler.getClass().getSimpleName()); + LOG.debug("HostHandler is {}", hostHandler.getClass().getSimpleName()); return new DirtyReadHostHandler(hostHandler, new RoundRobinHostHandler(hostResolver)); } diff --git a/src/main/java/com/arangodb/internal/InternalArangoEdgeCollection.java b/src/main/java/com/arangodb/internal/InternalArangoEdgeCollection.java index 897623e35..89bb70423 100644 --- a/src/main/java/com/arangodb/internal/InternalArangoEdgeCollection.java +++ b/src/main/java/com/arangodb/internal/InternalArangoEdgeCollection.java @@ -37,8 +37,9 @@ public abstract class InternalArangoEdgeCollection extends ArangoExecuteable { private static final String PATH_API_GHARIAL = "/_api/gharial"; - private static final String TRANSACTION_ID = "x-arango-trx-id"; + private static final String EDGE_PATH = "edge"; + private static final String EDGE_JSON_POINTER = "/edge"; private final G graph; private final String name; @@ -58,7 +59,7 @@ public String name() { } protected Request insertEdgeRequest(final T value, final EdgeCreateOptions options) { - final Request request = request(graph.db().dbName(), RequestType.POST, PATH_API_GHARIAL, graph.name(), "edge", + final Request request = request(graph.db().dbName(), RequestType.POST, PATH_API_GHARIAL, graph.name(), EDGE_PATH, name); final EdgeCreateOptions params = (options != null ? options : new EdgeCreateOptions()); request.putHeaderParam(TRANSACTION_ID, params.getStreamTransactionId()); @@ -67,12 +68,12 @@ protected Request insertEdgeRequest(final T value, final EdgeCreateOptions o return request; } - protected ResponseDeserializer insertEdgeResponseDeserializer(final T value) { - return response -> getSerde().deserialize(response.getBody(), "/edge", EdgeEntity.class); + protected ResponseDeserializer insertEdgeResponseDeserializer() { + return response -> getSerde().deserialize(response.getBody(), EDGE_JSON_POINTER, EdgeEntity.class); } protected Request getEdgeRequest(final String key, final GraphDocumentReadOptions options) { - final Request request = request(graph.db().dbName(), RequestType.GET, PATH_API_GHARIAL, graph.name(), "edge", + final Request request = request(graph.db().dbName(), RequestType.GET, PATH_API_GHARIAL, graph.name(), EDGE_PATH, DocumentUtil.createDocumentHandle(name, key)); final GraphDocumentReadOptions params = (options != null ? options : new GraphDocumentReadOptions()); request.putHeaderParam(TRANSACTION_ID, params.getStreamTransactionId()); @@ -85,11 +86,11 @@ protected Request getEdgeRequest(final String key, final GraphDocumentReadOption } protected ResponseDeserializer getEdgeResponseDeserializer(final Class type) { - return response -> getSerde().deserializeUserData(getSerde().extract(response.getBody(), "/edge"), type); + return response -> getSerde().deserializeUserData(getSerde().extract(response.getBody(), EDGE_JSON_POINTER), type); } protected Request replaceEdgeRequest(final String key, final T value, final EdgeReplaceOptions options) { - final Request request = request(graph.db().dbName(), RequestType.PUT, PATH_API_GHARIAL, graph.name(), "edge", + final Request request = request(graph.db().dbName(), RequestType.PUT, PATH_API_GHARIAL, graph.name(), EDGE_PATH, DocumentUtil.createDocumentHandle(name, key)); final EdgeReplaceOptions params = (options != null ? options : new EdgeReplaceOptions()); request.putHeaderParam(TRANSACTION_ID, params.getStreamTransactionId()); @@ -99,13 +100,13 @@ protected Request replaceEdgeRequest(final String key, final T value, final return request; } - protected ResponseDeserializer replaceEdgeResponseDeserializer(final T value) { - return response -> getSerde().deserialize(response.getBody(), "/edge", EdgeUpdateEntity.class); + protected ResponseDeserializer replaceEdgeResponseDeserializer() { + return response -> getSerde().deserialize(response.getBody(), EDGE_JSON_POINTER, EdgeUpdateEntity.class); } protected Request updateEdgeRequest(final String key, final T value, final EdgeUpdateOptions options) { final Request request; - request = request(graph.db().dbName(), RequestType.PATCH, PATH_API_GHARIAL, graph.name(), "edge", + request = request(graph.db().dbName(), RequestType.PATCH, PATH_API_GHARIAL, graph.name(), EDGE_PATH, DocumentUtil.createDocumentHandle(name, key)); final EdgeUpdateOptions params = (options != null ? options : new EdgeUpdateOptions()); request.putHeaderParam(TRANSACTION_ID, params.getStreamTransactionId()); @@ -116,12 +117,12 @@ protected Request updateEdgeRequest(final String key, final T value, final E return request; } - protected ResponseDeserializer updateEdgeResponseDeserializer(final T value) { - return response -> getSerde().deserialize(response.getBody(), "/edge", EdgeUpdateEntity.class); + protected ResponseDeserializer updateEdgeResponseDeserializer() { + return response -> getSerde().deserialize(response.getBody(), EDGE_JSON_POINTER, EdgeUpdateEntity.class); } protected Request deleteEdgeRequest(final String key, final EdgeDeleteOptions options) { - final Request request = request(graph.db().dbName(), RequestType.DELETE, PATH_API_GHARIAL, graph.name(), "edge", + final Request request = request(graph.db().dbName(), RequestType.DELETE, PATH_API_GHARIAL, graph.name(), EDGE_PATH, DocumentUtil.createDocumentHandle(name, key)); final EdgeDeleteOptions params = (options != null ? options : new EdgeDeleteOptions()); request.putHeaderParam(TRANSACTION_ID, params.getStreamTransactionId()); diff --git a/src/main/java/com/arangodb/internal/InternalArangoSearch.java b/src/main/java/com/arangodb/internal/InternalArangoSearch.java index 22b536312..e4c3d5fc9 100644 --- a/src/main/java/com/arangodb/internal/InternalArangoSearch.java +++ b/src/main/java/com/arangodb/internal/InternalArangoSearch.java @@ -31,22 +31,24 @@ public class InternalArangoSearch, D extends Inter E extends ArangoExecutor> extends InternalArangoView { + private static final String PROPERTIES_PATH = "properties"; + protected InternalArangoSearch(final D db, final String name) { super(db, name); } protected Request getPropertiesRequest() { - return request(db.dbName(), RequestType.GET, PATH_API_VIEW, name, "properties"); + return request(db.dbName(), RequestType.GET, PATH_API_VIEW, name, PROPERTIES_PATH); } protected Request replacePropertiesRequest(final ArangoSearchPropertiesOptions options) { - final Request request = request(db.dbName(), RequestType.PUT, PATH_API_VIEW, name, "properties"); + final Request request = request(db.dbName(), RequestType.PUT, PATH_API_VIEW, name, PROPERTIES_PATH); request.setBody(getSerde().serialize(options != null ? options : new ArangoSearchPropertiesOptions())); return request; } protected Request updatePropertiesRequest(final ArangoSearchPropertiesOptions options) { - final Request request = request(db.dbName(), RequestType.PATCH, PATH_API_VIEW, name, "properties"); + final Request request = request(db.dbName(), RequestType.PATCH, PATH_API_VIEW, name, PROPERTIES_PATH); request.setBody(getSerde().serialize(options != null ? options : new ArangoSearchPropertiesOptions())); return request; } diff --git a/src/main/java/com/arangodb/internal/InternalArangoVertexCollection.java b/src/main/java/com/arangodb/internal/InternalArangoVertexCollection.java index c3407cb95..58a3d6d9f 100644 --- a/src/main/java/com/arangodb/internal/InternalArangoVertexCollection.java +++ b/src/main/java/com/arangodb/internal/InternalArangoVertexCollection.java @@ -37,7 +37,8 @@ public abstract class InternalArangoVertexCollection { private static final String PATH_API_GHARIAL = "/_api/gharial"; - + private static final String VERTEX_PATH = "vertex"; + private static final String VERTEX_JSON_POINTER = "/vertex"; private static final String TRANSACTION_ID = "x-arango-trx-id"; private final G graph; @@ -58,11 +59,11 @@ public String name() { } protected Request dropRequest() { - return request(graph.db().dbName(), RequestType.DELETE, PATH_API_GHARIAL, graph.name(), "vertex", name); + return request(graph.db().dbName(), RequestType.DELETE, PATH_API_GHARIAL, graph.name(), VERTEX_PATH, name); } protected Request insertVertexRequest(final T value, final VertexCreateOptions options) { - final Request request = request(graph.db().dbName(), RequestType.POST, PATH_API_GHARIAL, graph.name(), "vertex", + final Request request = request(graph.db().dbName(), RequestType.POST, PATH_API_GHARIAL, graph.name(), VERTEX_PATH, name); final VertexCreateOptions params = (options != null ? options : new VertexCreateOptions()); request.putHeaderParam(TRANSACTION_ID, params.getStreamTransactionId()); @@ -71,12 +72,12 @@ protected Request insertVertexRequest(final T value, final VertexCreateOptio return request; } - protected ResponseDeserializer insertVertexResponseDeserializer(final T value) { - return response -> getSerde().deserialize(response.getBody(), "/vertex", VertexEntity.class); + protected ResponseDeserializer insertVertexResponseDeserializer() { + return response -> getSerde().deserialize(response.getBody(), VERTEX_JSON_POINTER, VertexEntity.class); } protected Request getVertexRequest(final String key, final GraphDocumentReadOptions options) { - final Request request = request(graph.db().dbName(), RequestType.GET, PATH_API_GHARIAL, graph.name(), "vertex", + final Request request = request(graph.db().dbName(), RequestType.GET, PATH_API_GHARIAL, graph.name(), VERTEX_PATH, DocumentUtil.createDocumentHandle(name, key)); final GraphDocumentReadOptions params = (options != null ? options : new GraphDocumentReadOptions()); request.putHeaderParam(TRANSACTION_ID, params.getStreamTransactionId()); @@ -89,11 +90,11 @@ protected Request getVertexRequest(final String key, final GraphDocumentReadOpti } protected ResponseDeserializer getVertexResponseDeserializer(final Class type) { - return response -> getSerde().deserializeUserData(getSerde().extract(response.getBody(), "/vertex"), type); + return response -> getSerde().deserializeUserData(getSerde().extract(response.getBody(), VERTEX_JSON_POINTER), type); } protected Request replaceVertexRequest(final String key, final T value, final VertexReplaceOptions options) { - final Request request = request(graph.db().dbName(), RequestType.PUT, PATH_API_GHARIAL, graph.name(), "vertex", + final Request request = request(graph.db().dbName(), RequestType.PUT, PATH_API_GHARIAL, graph.name(), VERTEX_PATH, DocumentUtil.createDocumentHandle(name, key)); final VertexReplaceOptions params = (options != null ? options : new VertexReplaceOptions()); request.putHeaderParam(TRANSACTION_ID, params.getStreamTransactionId()); @@ -103,13 +104,13 @@ protected Request replaceVertexRequest(final String key, final T value, fina return request; } - protected ResponseDeserializer replaceVertexResponseDeserializer(final T value) { - return response -> getSerde().deserialize(response.getBody(), "/vertex", VertexUpdateEntity.class); + protected ResponseDeserializer replaceVertexResponseDeserializer() { + return response -> getSerde().deserialize(response.getBody(), VERTEX_JSON_POINTER, VertexUpdateEntity.class); } protected Request updateVertexRequest(final String key, final T value, final VertexUpdateOptions options) { final Request request; - request = request(graph.db().dbName(), RequestType.PATCH, PATH_API_GHARIAL, graph.name(), "vertex", + request = request(graph.db().dbName(), RequestType.PATCH, PATH_API_GHARIAL, graph.name(), VERTEX_PATH, DocumentUtil.createDocumentHandle(name, key)); final VertexUpdateOptions params = (options != null ? options : new VertexUpdateOptions()); request.putHeaderParam(TRANSACTION_ID, params.getStreamTransactionId()); @@ -120,13 +121,13 @@ protected Request updateVertexRequest(final String key, final T value, final return request; } - protected ResponseDeserializer updateVertexResponseDeserializer(final T value) { - return response -> getSerde().deserialize(response.getBody(), "/vertex", VertexUpdateEntity.class); + protected ResponseDeserializer updateVertexResponseDeserializer() { + return response -> getSerde().deserialize(response.getBody(), VERTEX_JSON_POINTER, VertexUpdateEntity.class); } protected Request deleteVertexRequest(final String key, final VertexDeleteOptions options) { final Request request = request(graph.db().dbName(), RequestType.DELETE, PATH_API_GHARIAL, graph.name(), - "vertex", + VERTEX_PATH, DocumentUtil.createDocumentHandle(name, key)); final VertexDeleteOptions params = (options != null ? options : new VertexDeleteOptions()); request.putHeaderParam(TRANSACTION_ID, params.getStreamTransactionId()); diff --git a/src/main/java/com/arangodb/internal/InternalSearchAlias.java b/src/main/java/com/arangodb/internal/InternalSearchAlias.java index 3341c1a6a..410918742 100644 --- a/src/main/java/com/arangodb/internal/InternalSearchAlias.java +++ b/src/main/java/com/arangodb/internal/InternalSearchAlias.java @@ -27,22 +27,24 @@ public class InternalSearchAlias, D extends InternalArangoDatabase, E extends ArangoExecutor> extends InternalArangoView { + private static final String PROPERTIES_PATH = "properties"; + protected InternalSearchAlias(final D db, final String name) { super(db, name); } protected Request getPropertiesRequest() { - return request(db.dbName(), RequestType.GET, PATH_API_VIEW, name, "properties"); + return request(db.dbName(), RequestType.GET, PATH_API_VIEW, name, PROPERTIES_PATH); } protected Request replacePropertiesRequest(final SearchAliasPropertiesOptions options) { - final Request request = request(db.dbName(), RequestType.PUT, PATH_API_VIEW, name, "properties"); + final Request request = request(db.dbName(), RequestType.PUT, PATH_API_VIEW, name, PROPERTIES_PATH); request.setBody(getSerde().serialize(options != null ? options : new SearchAliasPropertiesOptions())); return request; } protected Request updatePropertiesRequest(final SearchAliasPropertiesOptions options) { - final Request request = request(db.dbName(), RequestType.PATCH, PATH_API_VIEW, name, "properties"); + final Request request = request(db.dbName(), RequestType.PATCH, PATH_API_VIEW, name, PROPERTIES_PATH); request.setBody(getSerde().serialize(options != null ? options : new SearchAliasPropertiesOptions())); return request; } diff --git a/src/main/java/com/arangodb/internal/cursor/ArangoCursorIterator.java b/src/main/java/com/arangodb/internal/cursor/ArangoCursorIterator.java index bf451c34b..e6d681045 100644 --- a/src/main/java/com/arangodb/internal/cursor/ArangoCursorIterator.java +++ b/src/main/java/com/arangodb/internal/cursor/ArangoCursorIterator.java @@ -63,7 +63,7 @@ public boolean hasNext() { @Override public T next() { - if (!arrayIterator.hasNext() && result.getHasMore()) { + if (!arrayIterator.hasNext() && Boolean.TRUE.equals(result.getHasMore())) { result = execute.next(cursor.getId(), result.getMeta()); arrayIterator = result.getResult().iterator(); } diff --git a/src/main/java/com/arangodb/internal/http/HttpConnection.java b/src/main/java/com/arangodb/internal/http/HttpConnection.java index e7be90706..b620e111a 100644 --- a/src/main/java/com/arangodb/internal/http/HttpConnection.java +++ b/src/main/java/com/arangodb/internal/http/HttpConnection.java @@ -69,7 +69,7 @@ * @author Michele Rastelli */ public class HttpConnection implements Connection { - private static final Logger LOGGER = LoggerFactory.getLogger(HttpCommunication.class); + private static final Logger LOGGER = LoggerFactory.getLogger(HttpConnection.class); private static final String CONTENT_TYPE_APPLICATION_JSON_UTF8 = "application/json; charset=utf-8"; private static final String CONTENT_TYPE_VPACK = "application/x-velocypack"; private static final AtomicInteger THREAD_COUNT = new AtomicInteger(); @@ -94,7 +94,7 @@ private HttpConnection(final HostDescription host, final Integer timeout, final LOGGER.debug("Created Vert.x context"); }); - int _ttl = ttl == null ? 0 : Math.toIntExact(ttl / 1000); + int intTtl = ttl == null ? 0 : Math.toIntExact(ttl / 1000); HttpVersion httpVersion = protocol == Protocol.HTTP_JSON || protocol == Protocol.HTTP_VPACK ? HttpVersion.HTTP_1_1 : HttpVersion.HTTP_2; @@ -103,8 +103,8 @@ private HttpConnection(final HostDescription host, final Integer timeout, final .setConnectTimeout(timeout) .setIdleTimeoutUnit(TimeUnit.MILLISECONDS) .setIdleTimeout(timeout) - .setKeepAliveTimeout(_ttl) - .setHttp2KeepAliveTimeout(_ttl) + .setKeepAliveTimeout(intTtl) + .setHttp2KeepAliveTimeout(intTtl) .setUserAgentEnabled(false) .setFollowRedirects(false) .setLogActivity(true) @@ -134,7 +134,7 @@ private HttpConnection(final HostDescription host, final Integer timeout, final webClientOptions .setSsl(true) .setUseAlpn(true) - .setVerifyHost(verifyHost != null ? verifyHost : true) + .setVerifyHost(verifyHost == null || verifyHost) .setJdkSslEngineOptions(new JdkSSLEngineOptions() { @Override public JdkSSLEngineOptions copy() { @@ -166,7 +166,7 @@ private static String buildUrl(final Request request) { if (dbName != null && !dbName.get().isEmpty()) { sb.append("/_db/").append(dbName.getEncoded()); } - sb.append(request.getRequest()); + sb.append(request.getPath()); if (!request.getQueryParam().isEmpty()) { sb.append("?"); for (Iterator> iterator = request.getQueryParam().entrySet().iterator(); iterator.hasNext(); ) { @@ -221,6 +221,7 @@ public Response execute(final Request request) throws IOException { try { resp = rfuture.get(); } catch (InterruptedException e) { + Thread.currentThread().interrupt(); throw ArangoDBException.wrap(e); } catch (ExecutionException e) { Throwable cause = e.getCause(); @@ -240,7 +241,7 @@ public void doExecute(final Request request, final CompletableFuture r .request(requestTypeToHttpMethod(request.getRequestType()), path) .timeout(timeout); if (contentType == ContentType.VPACK) { - httpRequest.putHeader("Accept", "application/x-velocypack"); + httpRequest.putHeader("Accept", CONTENT_TYPE_VPACK); } addHeader(request, httpRequest); httpRequest.putHeader(HttpHeaders.AUTHORIZATION.toString(), auth); @@ -287,7 +288,7 @@ protected void checkError(final Response response) { @Override public void setJwt(String jwt) { if (jwt != null) { - vertx.runOnContext((e) -> auth = new TokenCredentials(jwt).toHttpAuthorization()); + vertx.runOnContext(e -> auth = new TokenCredentials(jwt).toHttpAuthorization()); } } diff --git a/src/main/java/com/arangodb/internal/net/ConnectionPoolImpl.java b/src/main/java/com/arangodb/internal/net/ConnectionPoolImpl.java index 597445d4b..05cd39b4a 100644 --- a/src/main/java/com/arangodb/internal/net/ConnectionPoolImpl.java +++ b/src/main/java/com/arangodb/internal/net/ConnectionPoolImpl.java @@ -75,7 +75,7 @@ public synchronized Connection connection() { } if (connection instanceof VstConnectionSync) { - LOGGER.debug("Return Connection " + ((VstConnection) connection).getConnectionName()); + LOGGER.debug("Return Connection {}", ((VstConnection) connection).getConnectionName()); } return connection; diff --git a/src/main/java/com/arangodb/internal/net/ExtendedHostResolver.java b/src/main/java/com/arangodb/internal/net/ExtendedHostResolver.java index 9ca115c38..d5a535249 100644 --- a/src/main/java/com/arangodb/internal/net/ExtendedHostResolver.java +++ b/src/main/java/com/arangodb/internal/net/ExtendedHostResolver.java @@ -76,15 +76,17 @@ public HostSet resolve(boolean initial, boolean closeConnections) { lastUpdate = System.currentTimeMillis(); final Collection endpoints = resolveFromServer(); - LOGGER.debug("Resolve " + endpoints.size() + " Endpoints"); - LOGGER.debug("Endpoints " + Arrays.deepToString(endpoints.toArray())); + if (LOGGER.isDebugEnabled()) { + LOGGER.debug("Resolve {} Endpoints", endpoints.size()); + LOGGER.debug("Endpoints {}", Arrays.deepToString(endpoints.toArray())); + } if (!endpoints.isEmpty()) { hosts.markAllForDeletion(); } for (final String endpoint : endpoints) { - LOGGER.debug("Create HOST from " + endpoint); + LOGGER.debug("Create HOST from {}", endpoint); if (endpoint.matches(".*://.+:[0-9]+")) { @@ -98,11 +100,11 @@ public HostSet resolve(boolean initial, boolean closeConnections) { final HostDescription description = new HostDescription("127.0.0.1", Integer.parseInt(s[3])); hosts.addHost(HostUtils.createHost(description, maxConnections, connectionFactory)); } else { - LOGGER.warn("Skip Endpoint (Missing Port)" + endpoint); + LOGGER.warn("Skip Endpoint (Missing Port) {}", endpoint); } } else { - LOGGER.warn("Skip Endpoint (Format)" + endpoint); + LOGGER.warn("Skip Endpoint (Format) {}", endpoint); } } hosts.clearAllMarkedForDeletion(); diff --git a/src/main/java/com/arangodb/internal/net/HostSet.java b/src/main/java/com/arangodb/internal/net/HostSet.java index ddcad12bb..39c8d784f 100644 --- a/src/main/java/com/arangodb/internal/net/HostSet.java +++ b/src/main/java/com/arangodb/internal/net/HostSet.java @@ -34,7 +34,7 @@ public List getHostsList() { public void addHost(Host newHost) { if (hosts.contains(newHost)) { - LOGGER.debug("Host" + newHost + " already in Set"); + LOGGER.debug("Host {} already in Set", newHost); for (Host host : hosts) { if (host.equals(newHost)) { host.setMarkforDeletion(false); @@ -43,7 +43,7 @@ public void addHost(Host newHost) { } else { newHost.setJwt(jwt); hosts.add(newHost); - LOGGER.debug("Added Host " + newHost + " - now " + hosts.size() + " Hosts in List"); + LOGGER.debug("Added Host {} - now {} Hosts in List", newHost, hosts.size()); } } @@ -53,7 +53,7 @@ public void close() { for (Host host : hosts) { try { - LOGGER.debug("Try to close Host " + host); + LOGGER.debug("Try to close Host {}", host); host.close(); } catch (IOException e) { @@ -79,7 +79,7 @@ public void clearAllMarkedForDeletion() { Host host = iterable.next(); if (host.isMarkforDeletion()) { try { - LOGGER.debug("Try to close Host " + host); + LOGGER.debug("Try to close Host {}", host); host.close(); } catch (IOException e) { LOGGER.warn("Error during closing the Host " + host, e); diff --git a/src/main/java/com/arangodb/internal/serde/InternalAnnotationIntrospector.java b/src/main/java/com/arangodb/internal/serde/InternalAnnotationIntrospector.java index ce05a0b63..d0655cfd5 100644 --- a/src/main/java/com/arangodb/internal/serde/InternalAnnotationIntrospector.java +++ b/src/main/java/com/arangodb/internal/serde/InternalAnnotationIntrospector.java @@ -3,10 +3,14 @@ import com.fasterxml.jackson.databind.introspect.Annotated; import com.fasterxml.jackson.databind.introspect.JacksonAnnotationIntrospector; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; + class InternalAnnotationIntrospector extends JacksonAnnotationIntrospector { - private final UserDataSerializer userDataSerializer; - private final UserDataDeserializer userDataDeserializer; + private final transient UserDataSerializer userDataSerializer; + private final transient UserDataDeserializer userDataDeserializer; InternalAnnotationIntrospector( final UserDataSerializer userDataSerializer, @@ -52,4 +56,11 @@ public Object findContentDeserializer(Annotated a) { } } + private void writeObject(ObjectOutputStream out) throws IOException { + throw new IOException("Serialization not allowed"); + } + + private void readObject(ObjectInputStream in) throws IOException { + throw new IOException("Deserialization not allowed"); + } } diff --git a/src/main/java/com/arangodb/internal/serde/InternalSerializers.java b/src/main/java/com/arangodb/internal/serde/InternalSerializers.java index d721e5eae..7e9688aad 100644 --- a/src/main/java/com/arangodb/internal/serde/InternalSerializers.java +++ b/src/main/java/com/arangodb/internal/serde/InternalSerializers.java @@ -70,7 +70,7 @@ public void serialize(Request value, JsonGenerator gen, SerializerProvider seria gen.writeNumber(value.getType()); gen.writeString(value.getDbName().get()); gen.writeNumber(value.getRequestType().getType()); - gen.writeString(value.getRequest()); + gen.writeString(value.getPath()); gen.writeStartObject(); for (final Map.Entry entry : value.getQueryParam().entrySet()) { gen.writeStringField(entry.getKey(), entry.getValue()); diff --git a/src/main/java/com/arangodb/internal/velocystream/internal/MessageStore.java b/src/main/java/com/arangodb/internal/velocystream/internal/MessageStore.java index f8cb1e5a1..d9391b9b8 100644 --- a/src/main/java/com/arangodb/internal/velocystream/internal/MessageStore.java +++ b/src/main/java/com/arangodb/internal/velocystream/internal/MessageStore.java @@ -77,7 +77,7 @@ public Message get(final long messageId) { public void cancel(final long messageId) { final FutureTask future = task.remove(messageId); if (future != null) { - LOGGER.error(String.format("Cancel Message unexpected (id=%s).", messageId)); + LOGGER.error("Cancel Message unexpected (id={}).", messageId); future.cancel(true); } } diff --git a/src/main/java/com/arangodb/model/IndexOptions.java b/src/main/java/com/arangodb/model/IndexOptions.java index 9f47117ab..69df19a8d 100644 --- a/src/main/java/com/arangodb/model/IndexOptions.java +++ b/src/main/java/com/arangodb/model/IndexOptions.java @@ -30,8 +30,7 @@ public abstract class IndexOptions> { private Boolean inBackground; private String name; - public IndexOptions() { - super(); + protected IndexOptions() { } abstract T getThis(); diff --git a/src/main/java/com/arangodb/model/arangosearch/AnalyzerDeleteOptions.java b/src/main/java/com/arangodb/model/arangosearch/AnalyzerDeleteOptions.java index 776d3def1..f4115efec 100644 --- a/src/main/java/com/arangodb/model/arangosearch/AnalyzerDeleteOptions.java +++ b/src/main/java/com/arangodb/model/arangosearch/AnalyzerDeleteOptions.java @@ -27,9 +27,6 @@ public final class AnalyzerDeleteOptions { private Boolean force; - public AnalyzerDeleteOptions() { - } - public Boolean getForce() { return force; } From 55d55a4e0ac03833a95d151afad552403ee4c0a3 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Fri, 28 Oct 2022 12:33:55 +0200 Subject: [PATCH 167/254] set connections pool size --- src/main/java/com/arangodb/internal/http/HttpConnection.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/java/com/arangodb/internal/http/HttpConnection.java b/src/main/java/com/arangodb/internal/http/HttpConnection.java index b620e111a..3bd43813a 100644 --- a/src/main/java/com/arangodb/internal/http/HttpConnection.java +++ b/src/main/java/com/arangodb/internal/http/HttpConnection.java @@ -100,6 +100,8 @@ private HttpConnection(final HostDescription host, final Integer timeout, final HttpVersion.HTTP_1_1 : HttpVersion.HTTP_2; WebClientOptions webClientOptions = new WebClientOptions() + .setMaxPoolSize(1) + .setHttp2MaxPoolSize(1) .setConnectTimeout(timeout) .setIdleTimeoutUnit(TimeUnit.MILLISECONDS) .setIdleTimeout(timeout) From e49f9dcf1ebb0971072202fc7ec6563ff5ec9220 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Fri, 28 Oct 2022 12:51:44 +0200 Subject: [PATCH 168/254] connections parallelism test --- src/test/java/com/arangodb/ParallelTest.java | 40 ++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 src/test/java/com/arangodb/ParallelTest.java diff --git a/src/test/java/com/arangodb/ParallelTest.java b/src/test/java/com/arangodb/ParallelTest.java new file mode 100644 index 000000000..16ac5a702 --- /dev/null +++ b/src/test/java/com/arangodb/ParallelTest.java @@ -0,0 +1,40 @@ +package com.arangodb; + +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.EnumSource; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assumptions.assumeTrue; + +class ParallelTest { + + @ParameterizedTest(name = "{index}") + @EnumSource(Protocol.class) + void connectionParallelism(Protocol protocol) throws InterruptedException { + // test that connections are internally async and can have multiple pending requests + // BTS-1102: the server does not run pipelined HTTP/1.1 requests in parallel + assumeTrue(protocol != Protocol.HTTP_JSON && protocol != Protocol.HTTP_VPACK); + ArangoDB adb = new ArangoDB.Builder() + .useProtocol(protocol) + .maxConnections(1) + .build(); + + ExecutorService es = Executors.newFixedThreadPool(3); + List> tasks = new ArrayList<>(); + for (int i = 0; i < 3; i++) { + tasks.add(es.submit(() -> adb.db().query("return sleep(1)", Void.class))); + } + + Thread.sleep(2_000); + assertThat(tasks).allMatch(Future::isDone); + adb.shutdown(); + es.shutdown(); + } + +} From 62cf7519398c58814c15a9898ecbac0534700467 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Fri, 28 Oct 2022 13:04:31 +0200 Subject: [PATCH 169/254] set http2 default maxConnections to 1 --- src/main/java/com/arangodb/ArangoDB.java | 46 ++++++++++++------- .../com/arangodb/internal/ArangoDefaults.java | 1 + .../internal/InternalArangoDBBuilder.java | 4 +- src/test/resources/arangodb.properties | 1 - 4 files changed, 32 insertions(+), 20 deletions(-) diff --git a/src/main/java/com/arangodb/ArangoDB.java b/src/main/java/com/arangodb/ArangoDB.java index e17937755..60181e2f1 100644 --- a/src/main/java/com/arangodb/ArangoDB.java +++ b/src/main/java/com/arangodb/ArangoDB.java @@ -159,8 +159,8 @@ public interface ArangoDB extends ArangoSerdeAccessor { * Returns the server storage engine. * * @return the storage engine name - * @see - * API + * @see API * Documentation */ ArangoDBEngine getEngine(); @@ -176,8 +176,8 @@ public interface ArangoDB extends ArangoSerdeAccessor { * Returns the id of a server in a cluster. * * @return the server id - * @see - * API + * @see API * Documentation */ String getServerId(); @@ -297,8 +297,8 @@ public interface ArangoDB extends ArangoSerdeAccessor { * * @param options Additional options, can be null * @return the log messages - * @see - * API + * @see API * Documentation * @since ArangoDB 3.8 */ @@ -499,9 +499,8 @@ public Builder connectionTtl(final Long connectionTtl) { /** * Set the keep-alive interval for VST connections. If set, every VST connection will perform a no-op request - * every - * {@code keepAliveInterval} seconds, to avoid to be closed due to inactivity by the server (or by the external - * environment, eg. firewall, intermediate routers, operating system). + * every {@code keepAliveInterval} seconds, to avoid to be closed due to inactivity by the server (or by the + * external environment, eg. firewall, intermediate routers, operating system). * * @param keepAliveInterval interval in seconds * @return {@link ArangoDB.Builder} @@ -513,8 +512,8 @@ public Builder keepAliveInterval(final Integer keepAliveInterval) { /** * Whether or not the driver should acquire a list of available coordinators in an ArangoDB cluster or a single - * server with active failover. - * In case of Active-Failover deployment set to {@code true} to enable automatic master discovery. + * server with active failover. In case of Active-Failover deployment set to {@code true} to enable automatic + * master discovery. * *

    * The host list will be used for failover and load balancing. @@ -540,9 +539,8 @@ public Builder acquireHostListInterval(final Integer acquireHostListInterval) { } /** - * Sets the load balancing strategy to be used in an ArangoDB cluster setup. - * In case of Active-Failover deployment set to {@link LoadBalancingStrategy#NONE} or not set at all, since that - * would be the default. + * Sets the load balancing strategy to be used in an ArangoDB cluster setup. In case of Active-Failover + * deployment set to {@link LoadBalancingStrategy#NONE} or not set at all, since that would be the default. * * @param loadBalancingStrategy the load balancing strategy to be used (default: * {@link LoadBalancingStrategy#NONE} @@ -588,9 +586,23 @@ public ArangoDB build() { JacksonSerde.of(ContentType.of(protocol)); final InternalSerde serde = InternalSerde.of(ContentType.of(protocol), userSerde); - int protocolMaxConnections = protocol == Protocol.VST ? - ArangoDefaults.MAX_CONNECTIONS_VST_DEFAULT : - ArangoDefaults.MAX_CONNECTIONS_HTTP_DEFAULT; + int protocolMaxConnections; + switch (protocol) { + case VST: + protocolMaxConnections = ArangoDefaults.MAX_CONNECTIONS_VST_DEFAULT; + break; + case HTTP_JSON: + case HTTP_VPACK: + protocolMaxConnections = ArangoDefaults.MAX_CONNECTIONS_HTTP_DEFAULT; + break; + case HTTP2_JSON: + case HTTP2_VPACK: + protocolMaxConnections = ArangoDefaults.MAX_CONNECTIONS_HTTP2_DEFAULT; + break; + default: + throw new IllegalArgumentException(); + } + final int max = maxConnections != null ? Math.max(1, maxConnections) : protocolMaxConnections; final ConnectionFactory connectionFactory = (protocol == null || Protocol.VST == protocol) diff --git a/src/main/java/com/arangodb/internal/ArangoDefaults.java b/src/main/java/com/arangodb/internal/ArangoDefaults.java index 370158c59..ac5e3c2de 100644 --- a/src/main/java/com/arangodb/internal/ArangoDefaults.java +++ b/src/main/java/com/arangodb/internal/ArangoDefaults.java @@ -40,6 +40,7 @@ public final class ArangoDefaults { public static final int MAX_CONNECTIONS_VST_DEFAULT = 1; public static final Integer CONNECTION_TTL_VST_DEFAULT = null; public static final int MAX_CONNECTIONS_HTTP_DEFAULT = 20; + public static final int MAX_CONNECTIONS_HTTP2_DEFAULT = 1; public static final Protocol DEFAULT_NETWORK_PROTOCOL = Protocol.HTTP2_JSON; public static final boolean DEFAULT_ACQUIRE_HOST_LIST = false; public static final int DEFAULT_ACQUIRE_HOST_LIST_INTERVAL = 60 * 60 * 1000; // hour diff --git a/src/main/java/com/arangodb/internal/InternalArangoDBBuilder.java b/src/main/java/com/arangodb/internal/InternalArangoDBBuilder.java index 28ba4d254..78ab6a7f1 100644 --- a/src/main/java/com/arangodb/internal/InternalArangoDBBuilder.java +++ b/src/main/java/com/arangodb/internal/InternalArangoDBBuilder.java @@ -139,8 +139,8 @@ private static Integer loadChunkSize(final Properties properties, final Integer } private static Integer loadMaxConnections(final Properties properties, final Integer currentValue) { - return Integer.parseInt(getProperty(properties, PROPERTY_KEY_MAX_CONNECTIONS, currentValue, - ArangoDefaults.MAX_CONNECTIONS_VST_DEFAULT)); + String value = getProperty(properties, PROPERTY_KEY_MAX_CONNECTIONS, currentValue, null); + return value != null ? Integer.parseInt(value) : null; } private static Long loadConnectionTtl(final Properties properties, final Long currentValue) { diff --git a/src/test/resources/arangodb.properties b/src/test/resources/arangodb.properties index 54638964b..c47741102 100644 --- a/src/test/resources/arangodb.properties +++ b/src/test/resources/arangodb.properties @@ -1,5 +1,4 @@ arangodb.hosts=172.28.0.1:8529 -arangodb.connections.max=20 arangodb.acquireHostList=true arangodb.password=test arangodb.timeout=30000 From 55784edabc8de221aab92171990dd1e7fae8e3b5 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Fri, 28 Oct 2022 13:55:29 +0200 Subject: [PATCH 170/254] disabled failing updateJwt in async tests (DE-423) --- src/test/java/com/arangodb/async/JwtAuthTest.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/test/java/com/arangodb/async/JwtAuthTest.java b/src/test/java/com/arangodb/async/JwtAuthTest.java index 562b9684f..5750e7ecf 100644 --- a/src/test/java/com/arangodb/async/JwtAuthTest.java +++ b/src/test/java/com/arangodb/async/JwtAuthTest.java @@ -9,6 +9,7 @@ import com.arangodb.Response; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import java.util.HashMap; @@ -73,6 +74,7 @@ void authenticated() throws ExecutionException, InterruptedException { } @Test + @Disabled("DE-423") void updateJwt() throws ExecutionException, InterruptedException { arangoDB = getBuilder() .jwt(jwt) From d36ade9d5f88b4afc137a49f7aeb3e952c036a9a Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Thu, 3 Nov 2022 15:29:19 +0100 Subject: [PATCH 171/254] [DE-413] mvn multi module project (#465) * spotbugs fix * driver module --- .github/workflows/maven.yml | 6 + .github/workflows/native.yml | 2 + .gitignore | 4 +- README.md | 6 +- ChangeLog.md => driver/ChangeLog.md | 0 dev-README.md => driver/dev-README.md | 0 driver/pom.xml | 398 ++++++++ .../spotbugs}/spotbugs-exclude.xml | 0 .../java/com/arangodb/ArangoCollection.java | 0 .../main/java/com/arangodb/ArangoCursor.java | 0 .../src}/main/java/com/arangodb/ArangoDB.java | 2 +- .../java/com/arangodb/ArangoDBException.java | 0 .../arangodb/ArangoDBMultipleException.java | 0 .../java/com/arangodb/ArangoDatabase.java | 0 .../com/arangodb/ArangoEdgeCollection.java | 0 .../main/java/com/arangodb/ArangoGraph.java | 0 .../java/com/arangodb/ArangoIterable.java | 0 .../java/com/arangodb/ArangoIterator.java | 0 .../main/java/com/arangodb/ArangoMetrics.java | 0 .../main/java/com/arangodb/ArangoRoute.java | 0 .../main/java/com/arangodb/ArangoSearch.java | 0 .../com/arangodb/ArangoSerdeAccessor.java | 0 .../com/arangodb/ArangoVertexCollection.java | 0 .../main/java/com/arangodb/ArangoView.java | 0 .../main/java/com/arangodb/ContentType.java | 0 .../src}/main/java/com/arangodb/DbName.java | 0 .../src}/main/java/com/arangodb/Function.java | 0 .../src}/main/java/com/arangodb/Protocol.java | 0 .../java/com/arangodb/QueueTimeMetrics.java | 0 .../src}/main/java/com/arangodb/Request.java | 0 .../main/java/com/arangodb/RequestType.java | 0 .../src}/main/java/com/arangodb/Response.java | 0 .../main/java/com/arangodb/SearchAlias.java | 0 .../arangodb/async/ArangoCollectionAsync.java | 0 .../com/arangodb/async/ArangoCursorAsync.java | 0 .../com/arangodb/async/ArangoDBAsync.java | 0 .../arangodb/async/ArangoDatabaseAsync.java | 0 .../async/ArangoEdgeCollectionAsync.java | 0 .../com/arangodb/async/ArangoGraphAsync.java | 0 .../com/arangodb/async/ArangoRouteAsync.java | 0 .../com/arangodb/async/ArangoSearchAsync.java | 0 .../async/ArangoVertexCollectionAsync.java | 0 .../com/arangodb/async/ArangoViewAsync.java | 0 .../com/arangodb/async/SearchAliasAsync.java | 0 .../internal/ArangoCollectionAsyncImpl.java | 0 .../async/internal/ArangoCursorAsyncImpl.java | 0 .../async/internal/ArangoDBAsyncImpl.java | 0 .../internal/ArangoDatabaseAsyncImpl.java | 0 .../ArangoEdgeCollectionAsyncImpl.java | 0 .../async/internal/ArangoExecutorAsync.java | 0 .../async/internal/ArangoGraphAsyncImpl.java | 0 .../async/internal/ArangoRouteAsyncImpl.java | 0 .../async/internal/ArangoSearchAsyncImpl.java | 0 .../ArangoVertexCollectionAsyncImpl.java | 0 .../async/internal/ArangoViewAsyncImpl.java | 0 .../async/internal/ExceptionUtil.java | 0 .../async/internal/SearchAliasAsyncImpl.java | 0 .../utils/CompletableFutureUtils.java | 0 .../velocystream/VstCommunicationAsync.java | 0 .../velocystream/VstConnectionAsync.java | 0 .../VstConnectionFactoryAsync.java | 0 .../arangodb/entity/AbstractBaseDocument.java | 0 .../entity/AqlExecutionExplainEntity.java | 0 .../arangodb/entity/AqlFunctionEntity.java | 0 .../com/arangodb/entity/AqlParseEntity.java | 0 .../com/arangodb/entity/ArangoDBEngine.java | 0 .../com/arangodb/entity/ArangoDBVersion.java | 0 .../com/arangodb/entity/BaseDocument.java | 102 +- .../com/arangodb/entity/BaseEdgeDocument.java | 186 ++-- .../com/arangodb/entity/CollectionEntity.java | 0 .../entity/CollectionPropertiesEntity.java | 0 .../entity/CollectionRevisionEntity.java | 72 +- .../com/arangodb/entity/CollectionStatus.java | 0 .../com/arangodb/entity/CollectionType.java | 0 .../com/arangodb/entity/CursorWarning.java | 0 .../com/arangodb/entity/DatabaseEntity.java | 0 .../arangodb/entity/DocumentCreateEntity.java | 0 .../arangodb/entity/DocumentDeleteEntity.java | 100 +- .../com/arangodb/entity/DocumentEntity.java | 0 .../arangodb/entity/DocumentImportEntity.java | 0 .../arangodb/entity/DocumentUpdateEntity.java | 144 +-- .../com/arangodb/entity/EdgeDefinition.java | 184 ++-- .../java/com/arangodb/entity/EdgeEntity.java | 64 +- .../com/arangodb/entity/EdgeUpdateEntity.java | 84 +- .../java/com/arangodb/entity/ErrorEntity.java | 0 .../main/java/com/arangodb/entity/From.java | 0 .../java/com/arangodb/entity/GraphEntity.java | 0 .../main/java/com/arangodb/entity/Id.java | 0 .../java/com/arangodb/entity/IndexEntity.java | 0 .../java/com/arangodb/entity/IndexType.java | 118 +-- .../arangodb/entity/InvertedIndexEntity.java | 0 .../arangodb/entity/InvertedIndexField.java | 0 .../entity/InvertedIndexPrimarySort.java | 0 .../main/java/com/arangodb/entity/Key.java | 0 .../java/com/arangodb/entity/KeyOptions.java | 154 +-- .../java/com/arangodb/entity/KeyType.java | 56 +- .../java/com/arangodb/entity/License.java | 0 .../entity/LoadBalancingStrategy.java | 56 +- .../com/arangodb/entity/LogEntriesEntity.java | 0 .../java/com/arangodb/entity/LogLevel.java | 0 .../com/arangodb/entity/LogLevelEntity.java | 0 .../java/com/arangodb/entity/MetaAware.java | 0 .../arangodb/entity/MultiDocumentEntity.java | 0 .../java/com/arangodb/entity/Permissions.java | 0 .../entity/QueryCachePropertiesEntity.java | 0 .../java/com/arangodb/entity/QueryEntity.java | 0 .../arangodb/entity/QueryExecutionState.java | 122 +-- .../arangodb/entity/QueryOptimizerRule.java | 0 .../entity/QueryTrackingPropertiesEntity.java | 0 .../arangodb/entity/ReplicationFactor.java | 0 .../main/java/com/arangodb/entity/Rev.java | 0 .../java/com/arangodb/entity/ServerMode.java | 56 +- .../java/com/arangodb/entity/ServerRole.java | 54 +- .../java/com/arangodb/entity/ShardEntity.java | 0 .../com/arangodb/entity/ShardingStrategy.java | 0 .../entity/StreamTransactionEntity.java | 0 .../entity/StreamTransactionStatus.java | 0 .../main/java/com/arangodb/entity/To.java | 0 .../arangodb/entity/TransactionEntity.java | 0 .../java/com/arangodb/entity/UserEntity.java | 0 .../com/arangodb/entity/VertexEntity.java | 64 +- .../arangodb/entity/VertexUpdateEntity.java | 82 +- .../java/com/arangodb/entity/ViewEntity.java | 0 .../java/com/arangodb/entity/ViewType.java | 0 .../entity/arangosearch/AnalyzerFeature.java | 0 .../entity/arangosearch/AnalyzerType.java | 0 .../arangosearch/ArangoSearchCompression.java | 0 .../ArangoSearchPropertiesEntity.java | 0 .../entity/arangosearch/CollectionLink.java | 0 .../arangosearch/ConsolidationPolicy.java | 0 .../arangosearch/ConsolidationType.java | 0 .../entity/arangosearch/FieldLink.java | 0 .../entity/arangosearch/PrimarySort.java | 0 .../entity/arangosearch/SearchAliasIndex.java | 0 .../SearchAliasPropertiesEntity.java | 0 .../entity/arangosearch/StoreValuesType.java | 0 .../entity/arangosearch/StoredValue.java | 0 .../arangosearch/analyzer/AQLAnalyzer.java | 0 .../analyzer/AQLAnalyzerProperties.java | 0 .../analyzer/ClassificationAnalyzer.java | 0 .../ClassificationAnalyzerProperties.java | 0 .../analyzer/CollationAnalyzer.java | 0 .../analyzer/CollationAnalyzerProperties.java | 0 .../analyzer/DelimiterAnalyzer.java | 0 .../analyzer/DelimiterAnalyzerProperties.java | 0 .../arangosearch/analyzer/EdgeNgram.java | 0 .../analyzer/GeoAnalyzerOptions.java | 0 .../analyzer/GeoJSONAnalyzer.java | 0 .../analyzer/GeoJSONAnalyzerProperties.java | 0 .../analyzer/GeoPointAnalyzer.java | 0 .../analyzer/GeoPointAnalyzerProperties.java | 0 .../analyzer/IdentityAnalyzer.java | 0 .../analyzer/MinHashAnalyzer.java | 0 .../analyzer/MinHashAnalyzerProperties.java | 0 .../arangosearch/analyzer/NGramAnalyzer.java | 0 .../analyzer/NGramAnalyzerProperties.java | 0 .../analyzer/NearestNeighborsAnalyzer.java | 0 .../NearestNeighborsAnalyzerProperties.java | 0 .../arangosearch/analyzer/NormAnalyzer.java | 0 .../analyzer/NormAnalyzerProperties.java | 0 .../analyzer/PipelineAnalyzer.java | 0 .../analyzer/PipelineAnalyzerProperties.java | 0 .../arangosearch/analyzer/SearchAnalyzer.java | 0 .../analyzer/SearchAnalyzerCase.java | 0 .../analyzer/SegmentationAnalyzer.java | 0 .../SegmentationAnalyzerProperties.java | 0 .../arangosearch/analyzer/StemAnalyzer.java | 0 .../analyzer/StemAnalyzerProperties.java | 0 .../analyzer/StopwordsAnalyzer.java | 0 .../analyzer/StopwordsAnalyzerProperties.java | 0 .../arangosearch/analyzer/StreamType.java | 0 .../arangosearch/analyzer/TextAnalyzer.java | 0 .../analyzer/TextAnalyzerProperties.java | 0 .../internal/ArangoCollectionImpl.java | 0 .../internal/ArangoCursorExecute.java | 72 +- .../com/arangodb/internal/ArangoDBImpl.java | 0 .../arangodb/internal/ArangoDatabaseImpl.java | 0 .../com/arangodb/internal/ArangoDefaults.java | 0 .../internal/ArangoEdgeCollectionImpl.java | 0 .../com/arangodb/internal/ArangoErrors.java | 0 .../arangodb/internal/ArangoExecuteable.java | 0 .../com/arangodb/internal/ArangoExecutor.java | 0 .../arangodb/internal/ArangoExecutorSync.java | 0 .../arangodb/internal/ArangoGraphImpl.java | 0 .../arangodb/internal/ArangoMetricsImpl.java | 0 .../arangodb/internal/ArangoRequestParam.java | 0 .../internal/ArangoResponseField.java | 0 .../arangodb/internal/ArangoRouteImpl.java | 0 .../arangodb/internal/ArangoSearchImpl.java | 0 .../internal/ArangoVertexCollectionImpl.java | 0 .../com/arangodb/internal/ArangoViewImpl.java | 0 .../com/arangodb/internal/DocumentFields.java | 0 .../internal/InternalArangoCollection.java | 0 .../arangodb/internal/InternalArangoDB.java | 0 .../internal/InternalArangoDBBuilder.java | 0 .../internal/InternalArangoDatabase.java | 0 .../InternalArangoEdgeCollection.java | 0 .../internal/InternalArangoGraph.java | 0 .../internal/InternalArangoRoute.java | 0 .../internal/InternalArangoSearch.java | 0 .../InternalArangoVertexCollection.java | 0 .../arangodb/internal/InternalArangoView.java | 0 .../internal/InternalSearchAlias.java | 0 .../internal/QueueTimeMetricsImpl.java | 0 .../arangodb/internal/SearchAliasImpl.java | 0 .../cursor/AbstractArangoIterable.java | 0 .../internal/cursor/ArangoCursorImpl.java | 0 .../internal/cursor/ArangoCursorIterator.java | 0 .../cursor/entity/InternalCursorEntity.java | 0 .../internal/http/HttpCommunication.java | 0 .../internal/http/HttpConnection.java | 0 .../internal/http/HttpConnectionFactory.java | 0 .../arangodb/internal/http/HttpProtocol.java | 0 .../com/arangodb/internal/net/AccessType.java | 0 .../net/ArangoDBRedirectException.java | 84 +- .../internal/net/CommunicationProtocol.java | 74 +- .../com/arangodb/internal/net/Connection.java | 0 .../internal/net/ConnectionFactory.java | 0 .../arangodb/internal/net/ConnectionPool.java | 0 .../internal/net/ConnectionPoolImpl.java | 0 .../internal/net/DirtyReadHostHandler.java | 0 .../internal/net/ExtendedHostResolver.java | 0 .../internal/net/FallbackHostHandler.java | 0 .../java/com/arangodb/internal/net/Host.java | 0 .../internal/net/HostDescription.java | 0 .../com/arangodb/internal/net/HostHandle.java | 0 .../arangodb/internal/net/HostHandler.java | 0 .../com/arangodb/internal/net/HostImpl.java | 0 .../arangodb/internal/net/HostResolver.java | 0 .../com/arangodb/internal/net/HostSet.java | 0 .../internal/net/RandomHostHandler.java | 0 .../internal/net/RoundRobinHostHandler.java | 0 .../internal/net/SimpleHostResolver.java | 0 .../serde/InternalAnnotationIntrospector.java | 0 .../internal/serde/InternalDeserializers.java | 0 .../internal/serde/InternalModule.java | 0 .../serde/InternalParameterizedType.java | 0 .../internal/serde/InternalSerde.java | 0 .../internal/serde/InternalSerdeImpl.java | 0 .../internal/serde/InternalSerializers.java | 0 .../internal/serde/JacksonSerdeImpl.java | 0 .../internal/serde/JsonMapperProvider.java | 0 .../internal/serde/MapperProvider.java | 0 .../arangodb/internal/serde/SerdeUtils.java | 0 .../com/arangodb/internal/serde/UserData.java | 0 .../internal/serde/UserDataDeserializer.java | 0 .../internal/serde/UserDataInside.java | 0 .../internal/serde/UserDataSerializer.java | 0 .../internal/serde/VPackMapperProvider.java | 0 .../arangodb/internal/util/DocumentUtil.java | 0 .../arangodb/internal/util/EncodeUtils.java | 0 .../com/arangodb/internal/util/HostUtils.java | 0 .../arangodb/internal/util/RequestUtils.java | 0 .../arangodb/internal/util/ResponseUtils.java | 0 .../velocystream/VstCommunication.java | 0 .../velocystream/VstCommunicationSync.java | 0 .../VstConnectionFactorySync.java | 0 .../internal/velocystream/VstProtocol.java | 0 .../internal/AuthenticationRequest.java | 110 +- .../internal/velocystream/internal/Chunk.java | 176 ++-- .../velocystream/internal/ChunkStore.java | 140 +-- .../internal/JwtAuthenticationRequest.java | 0 .../velocystream/internal/Message.java | 134 +-- .../velocystream/internal/MessageStore.java | 224 ++-- .../velocystream/internal/VstConnection.java | 0 .../internal/VstConnectionSync.java | 0 .../model/AqlFunctionCreateOptions.java | 162 +-- .../model/AqlFunctionDeleteOptions.java | 104 +- .../arangodb/model/AqlFunctionGetOptions.java | 100 +- .../model/AqlQueryExplainOptions.java | 274 ++--- .../com/arangodb/model/AqlQueryOptions.java | 0 .../arangodb/model/AqlQueryParseOptions.java | 96 +- .../model/CollectionCountOptions.java | 0 .../model/CollectionCreateOptions.java | 0 .../model/CollectionPropertiesOptions.java | 174 ++-- .../model/CollectionRenameOptions.java | 94 +- .../com/arangodb/model/CollectionSchema.java | 0 .../model/CollectionTruncateOptions.java | 0 .../model/CollectionsReadOptions.java | 98 +- .../com/arangodb/model/ComputedValue.java | 0 .../com/arangodb/model/DBCreateOptions.java | 158 +-- .../com/arangodb/model/DatabaseOptions.java | 0 .../arangodb/model/DatabaseUsersOptions.java | 0 .../arangodb/model/DocumentCreateOptions.java | 0 .../arangodb/model/DocumentDeleteOptions.java | 0 .../arangodb/model/DocumentExistsOptions.java | 160 +-- .../arangodb/model/DocumentImportOptions.java | 324 +++--- .../arangodb/model/DocumentReadOptions.java | 192 ++-- .../model/DocumentReplaceOptions.java | 0 .../arangodb/model/DocumentUpdateOptions.java | 0 .../com/arangodb/model/EdgeCreateOptions.java | 126 +-- .../com/arangodb/model/EdgeDeleteOptions.java | 154 +-- .../arangodb/model/EdgeReplaceOptions.java | 154 +-- .../com/arangodb/model/EdgeUpdateOptions.java | 188 ++-- .../arangodb/model/FulltextIndexOptions.java | 158 +-- .../com/arangodb/model/GeoIndexOptions.java | 188 ++-- .../arangodb/model/GraphCreateOptions.java | 544 +++++----- .../model/GraphDocumentReadOptions.java | 0 .../com/arangodb/model/HashIndexOptions.java | 242 ++--- .../java/com/arangodb/model/ImportType.java | 56 +- .../java/com/arangodb/model/IndexOptions.java | 128 +-- .../arangodb/model/InvertedIndexOptions.java | 0 .../java/com/arangodb/model/LogOptions.java | 304 +++--- .../com/arangodb/model/OptionsBuilder.java | 0 .../com/arangodb/model/OverwriteMode.java | 0 .../model/PersistentIndexOptions.java | 316 +++--- .../com/arangodb/model/QueueTimeSample.java | 0 .../arangodb/model/SkiplistIndexOptions.java | 242 ++--- .../model/StreamTransactionOptions.java | 0 .../model/TransactionCollectionOptions.java | 0 .../arangodb/model/TransactionOptions.java | 0 .../com/arangodb/model/TtlIndexOptions.java | 150 +-- .../com/arangodb/model/UserAccessOptions.java | 90 +- .../com/arangodb/model/UserCreateOptions.java | 186 ++-- .../com/arangodb/model/UserUpdateOptions.java | 158 +-- .../model/VertexCollectionCreateOptions.java | 158 +-- .../arangodb/model/VertexCreateOptions.java | 126 +-- .../arangodb/model/VertexDeleteOptions.java | 154 +-- .../arangodb/model/VertexReplaceOptions.java | 154 +-- .../arangodb/model/VertexUpdateOptions.java | 186 ++-- .../com/arangodb/model/ViewCreateOptions.java | 0 .../com/arangodb/model/ViewRenameOptions.java | 0 .../com/arangodb/model/ZKDIndexOptions.java | 0 .../arangosearch/AnalyzerDeleteOptions.java | 0 .../ArangoSearchCreateOptions.java | 0 .../ArangoSearchOptionsBuilder.java | 0 .../ArangoSearchPropertiesOptions.java | 0 .../SearchAliasCreateOptions.java | 0 .../SearchAliasOptionsBuilder.java | 0 .../SearchAliasPropertiesOptions.java | 0 .../java/com/arangodb/serde/ArangoSerde.java | 0 .../java/com/arangodb/serde/JacksonSerde.java | 0 .../main/java/com/arangodb/util/RawBytes.java | 0 .../main/java/com/arangodb/util/RawData.java | 0 .../main/java/com/arangodb/util/RawJson.java | 0 .../java/com/arangodb/util/UnicodeUtils.java | 0 .../native-image.properties | 0 .../arangodb-java-driver/reflect-config.json | 0 .../arangodb-java-driver/resource-config.json | 0 .../serialization-config.json | 0 .../main/resources/vertx/vertx-version.txt | 0 .../com/arangodb/ArangoCollectionTest.java | 0 .../java/com/arangodb/ArangoCursorTest.java | 0 .../test/java/com/arangodb/ArangoDBTest.java | 0 .../java/com/arangodb/ArangoDatabaseTest.java | 0 .../com/arangodb/ArangoDocumentUtilTest.java | 0 .../arangodb/ArangoEdgeCollectionTest.java | 890 ++++++++-------- .../java/com/arangodb/ArangoGraphTest.java | 0 .../java/com/arangodb/ArangoRouteTest.java | 0 .../java/com/arangodb/ArangoSearchTest.java | 0 .../test/java/com/arangodb/ArangoSslTest.java | 200 ++-- .../arangodb/ArangoVertexCollectionTest.java | 960 +++++++++--------- .../java/com/arangodb/ArangoViewTest.java | 0 .../test/java/com/arangodb/BaseJunit5.java | 0 .../java/com/arangodb/ConcurrencyTests.java | 0 .../test/java/com/arangodb/DocumentTest.java | 276 ++--- .../java/com/arangodb/InvertedIndexTest.java | 0 .../test/java/com/arangodb/JwtAuthTest.java | 6 +- .../test/java/com/arangodb/ParallelTest.java | 0 .../java/com/arangodb/SerializableTest.java | 0 .../StreamTransactionConflictsTest.java | 0 .../arangodb/StreamTransactionGraphTest.java | 0 .../com/arangodb/StreamTransactionTest.java | 0 .../arangodb/async/ArangoCollectionTest.java | 0 .../java/com/arangodb/async/ArangoDBTest.java | 0 .../arangodb/async/ArangoDatabaseTest.java | 0 .../async/ArangoEdgeCollectionTest.java | 0 .../com/arangodb/async/ArangoGraphTest.java | 0 .../com/arangodb/async/ArangoRouteTest.java | 0 .../com/arangodb/async/ArangoSearchTest.java | 0 .../async/ArangoVertexCollectionTest.java | 0 .../com/arangodb/async/ArangoViewTest.java | 0 .../java/com/arangodb/async/BaseTest.java | 0 .../com/arangodb/async/CommunicationTest.java | 0 .../com/arangodb/async/ConcurrencyTest.java | 0 .../com/arangodb/async/ConcurrencyTests.java | 0 .../com/arangodb/async/InvertedIndexTest.java | 0 .../java/com/arangodb/async/JwtAuthTest.java | 0 .../async/StreamTransactionConflictsTest.java | 0 .../async/StreamTransactionGraphTest.java | 0 .../arangodb/async/StreamTransactionTest.java | 0 .../debug/ConsolidationIntervalMsecTest.java | 0 .../arangodb/async/example/ExampleBase.java | 0 ...ueryWithSpecialReturnTypesExampleTest.java | 0 .../document/GetDocumentExampleTest.java | 0 .../document/ImportDocumentExampleTest.java | 0 .../document/InsertDocumentExampleTest.java | 0 .../async/example/document/TestEntity.java | 0 .../graph/AQLActorsAndMoviesExampleTest.java | 0 .../async/example/graph/BaseGraphTest.java | 0 .../arangodb/async/example/graph/Circle.java | 0 .../async/example/graph/CircleEdge.java | 0 .../GraphTraversalsInAQLExampleTest.java | 0 .../graph/ShortestPathInAQLExampleTest.java | 0 .../async/example/ssl/SslExampleTest.java | 0 .../arangodb/async/serde/CustomSerdeTest.java | 0 .../com/arangodb/example/ExampleBase.java | 118 +-- .../com/arangodb/example/FirstProject.java | 268 ++--- ...ueryWithSpecialReturnTypesExampleTest.java | 0 .../document/GetDocumentExampleTest.java | 0 .../document/InsertDocumentExampleTest.java | 0 .../arangodb/example/document/TestEntity.java | 94 +- .../graph/AQLActorsAndMoviesExampleTest.java | 0 .../arangodb/example/graph/BaseGraphTest.java | 222 ++-- .../com/arangodb/example/graph/Circle.java | 0 .../arangodb/example/graph/CircleEdge.java | 0 .../GraphTraversalsInAQLExampleTest.java | 0 .../graph/ShortestPathInAQLExampleTest.java | 0 .../arangodb/example/ssl/SslExampleTest.java | 0 .../arangodb/internal/HostHandlerTest.java | 0 .../internal/QueueTimeMetricsImplTest.java | 0 .../velocystream/CommunicationTest.java | 222 ++-- .../mapping/annotations/AnnotatedEntity.java | 0 .../annotations/ArangoAnnotationsTest.java | 0 .../com/arangodb/serde/CustomSerdeTest.java | 0 .../arangodb/serde/CustomTypeHintTest.java | 0 .../java/com/arangodb/serde/JsonbSerde.java | 0 .../com/arangodb/serde/JsonbSerdeImpl.java | 0 .../java/com/arangodb/serde/SerdeTest.java | 0 .../java/com/arangodb/util/MapBuilder.java | 0 .../com/arangodb/util/MapBuilderTest.java | 86 +- .../java/com/arangodb/util/TestUtils.java | 0 .../com/arangodb/util/UnicodeUtilsTest.java | 0 .../test/java/helper/NativeImageHelper.java | 0 .../src}/test/java/perf/Benchmark.java | 0 .../test/java/perf/SimpleSyncPerfTest.java | 0 .../test/java/perf/SyncBenchmarkTest.java | 0 .../native-image/native-image.properties | 0 .../META-INF/native-image/reflect-config.json | 0 .../native-image/resource-config.json | 0 .../native-image/serialization-config.json | 0 .../test/resources/arangodb-bad.properties | 0 .../src}/test/resources/arangodb.properties | 0 .../src}/test/resources/example.truststore | Bin .../src}/test/resources/logback-test.xml | 0 formatter.xml | 419 -------- pom.xml | 383 +------ 437 files changed, 6494 insertions(+), 6878 deletions(-) rename ChangeLog.md => driver/ChangeLog.md (100%) rename dev-README.md => driver/dev-README.md (100%) create mode 100644 driver/pom.xml rename {spotbugs => driver/spotbugs}/spotbugs-exclude.xml (100%) rename {src => driver/src}/main/java/com/arangodb/ArangoCollection.java (100%) rename {src => driver/src}/main/java/com/arangodb/ArangoCursor.java (100%) rename {src => driver/src}/main/java/com/arangodb/ArangoDB.java (99%) rename {src => driver/src}/main/java/com/arangodb/ArangoDBException.java (100%) rename {src => driver/src}/main/java/com/arangodb/ArangoDBMultipleException.java (100%) rename {src => driver/src}/main/java/com/arangodb/ArangoDatabase.java (100%) rename {src => driver/src}/main/java/com/arangodb/ArangoEdgeCollection.java (100%) rename {src => driver/src}/main/java/com/arangodb/ArangoGraph.java (100%) rename {src => driver/src}/main/java/com/arangodb/ArangoIterable.java (100%) rename {src => driver/src}/main/java/com/arangodb/ArangoIterator.java (100%) rename {src => driver/src}/main/java/com/arangodb/ArangoMetrics.java (100%) rename {src => driver/src}/main/java/com/arangodb/ArangoRoute.java (100%) rename {src => driver/src}/main/java/com/arangodb/ArangoSearch.java (100%) rename {src => driver/src}/main/java/com/arangodb/ArangoSerdeAccessor.java (100%) rename {src => driver/src}/main/java/com/arangodb/ArangoVertexCollection.java (100%) rename {src => driver/src}/main/java/com/arangodb/ArangoView.java (100%) rename {src => driver/src}/main/java/com/arangodb/ContentType.java (100%) rename {src => driver/src}/main/java/com/arangodb/DbName.java (100%) rename {src => driver/src}/main/java/com/arangodb/Function.java (100%) rename {src => driver/src}/main/java/com/arangodb/Protocol.java (100%) rename {src => driver/src}/main/java/com/arangodb/QueueTimeMetrics.java (100%) rename {src => driver/src}/main/java/com/arangodb/Request.java (100%) rename {src => driver/src}/main/java/com/arangodb/RequestType.java (100%) rename {src => driver/src}/main/java/com/arangodb/Response.java (100%) rename {src => driver/src}/main/java/com/arangodb/SearchAlias.java (100%) rename {src => driver/src}/main/java/com/arangodb/async/ArangoCollectionAsync.java (100%) rename {src => driver/src}/main/java/com/arangodb/async/ArangoCursorAsync.java (100%) rename {src => driver/src}/main/java/com/arangodb/async/ArangoDBAsync.java (100%) rename {src => driver/src}/main/java/com/arangodb/async/ArangoDatabaseAsync.java (100%) rename {src => driver/src}/main/java/com/arangodb/async/ArangoEdgeCollectionAsync.java (100%) rename {src => driver/src}/main/java/com/arangodb/async/ArangoGraphAsync.java (100%) rename {src => driver/src}/main/java/com/arangodb/async/ArangoRouteAsync.java (100%) rename {src => driver/src}/main/java/com/arangodb/async/ArangoSearchAsync.java (100%) rename {src => driver/src}/main/java/com/arangodb/async/ArangoVertexCollectionAsync.java (100%) rename {src => driver/src}/main/java/com/arangodb/async/ArangoViewAsync.java (100%) rename {src => driver/src}/main/java/com/arangodb/async/SearchAliasAsync.java (100%) rename {src => driver/src}/main/java/com/arangodb/async/internal/ArangoCollectionAsyncImpl.java (100%) rename {src => driver/src}/main/java/com/arangodb/async/internal/ArangoCursorAsyncImpl.java (100%) rename {src => driver/src}/main/java/com/arangodb/async/internal/ArangoDBAsyncImpl.java (100%) rename {src => driver/src}/main/java/com/arangodb/async/internal/ArangoDatabaseAsyncImpl.java (100%) rename {src => driver/src}/main/java/com/arangodb/async/internal/ArangoEdgeCollectionAsyncImpl.java (100%) rename {src => driver/src}/main/java/com/arangodb/async/internal/ArangoExecutorAsync.java (100%) rename {src => driver/src}/main/java/com/arangodb/async/internal/ArangoGraphAsyncImpl.java (100%) rename {src => driver/src}/main/java/com/arangodb/async/internal/ArangoRouteAsyncImpl.java (100%) rename {src => driver/src}/main/java/com/arangodb/async/internal/ArangoSearchAsyncImpl.java (100%) rename {src => driver/src}/main/java/com/arangodb/async/internal/ArangoVertexCollectionAsyncImpl.java (100%) rename {src => driver/src}/main/java/com/arangodb/async/internal/ArangoViewAsyncImpl.java (100%) rename {src => driver/src}/main/java/com/arangodb/async/internal/ExceptionUtil.java (100%) rename {src => driver/src}/main/java/com/arangodb/async/internal/SearchAliasAsyncImpl.java (100%) rename {src => driver/src}/main/java/com/arangodb/async/internal/utils/CompletableFutureUtils.java (100%) rename {src => driver/src}/main/java/com/arangodb/async/internal/velocystream/VstCommunicationAsync.java (100%) rename {src => driver/src}/main/java/com/arangodb/async/internal/velocystream/VstConnectionAsync.java (100%) rename {src => driver/src}/main/java/com/arangodb/async/internal/velocystream/VstConnectionFactoryAsync.java (100%) rename {src => driver/src}/main/java/com/arangodb/entity/AbstractBaseDocument.java (100%) rename {src => driver/src}/main/java/com/arangodb/entity/AqlExecutionExplainEntity.java (100%) rename {src => driver/src}/main/java/com/arangodb/entity/AqlFunctionEntity.java (100%) rename {src => driver/src}/main/java/com/arangodb/entity/AqlParseEntity.java (100%) rename {src => driver/src}/main/java/com/arangodb/entity/ArangoDBEngine.java (100%) rename {src => driver/src}/main/java/com/arangodb/entity/ArangoDBVersion.java (100%) rename {src => driver/src}/main/java/com/arangodb/entity/BaseDocument.java (96%) rename {src => driver/src}/main/java/com/arangodb/entity/BaseEdgeDocument.java (96%) rename {src => driver/src}/main/java/com/arangodb/entity/CollectionEntity.java (100%) rename {src => driver/src}/main/java/com/arangodb/entity/CollectionPropertiesEntity.java (100%) rename {src => driver/src}/main/java/com/arangodb/entity/CollectionRevisionEntity.java (96%) rename {src => driver/src}/main/java/com/arangodb/entity/CollectionStatus.java (100%) rename {src => driver/src}/main/java/com/arangodb/entity/CollectionType.java (100%) rename {src => driver/src}/main/java/com/arangodb/entity/CursorWarning.java (100%) rename {src => driver/src}/main/java/com/arangodb/entity/DatabaseEntity.java (100%) rename {src => driver/src}/main/java/com/arangodb/entity/DocumentCreateEntity.java (100%) rename {src => driver/src}/main/java/com/arangodb/entity/DocumentDeleteEntity.java (96%) rename {src => driver/src}/main/java/com/arangodb/entity/DocumentEntity.java (100%) rename {src => driver/src}/main/java/com/arangodb/entity/DocumentImportEntity.java (100%) rename {src => driver/src}/main/java/com/arangodb/entity/DocumentUpdateEntity.java (96%) rename {src => driver/src}/main/java/com/arangodb/entity/EdgeDefinition.java (96%) rename {src => driver/src}/main/java/com/arangodb/entity/EdgeEntity.java (96%) rename {src => driver/src}/main/java/com/arangodb/entity/EdgeUpdateEntity.java (96%) rename {src => driver/src}/main/java/com/arangodb/entity/ErrorEntity.java (100%) rename {src => driver/src}/main/java/com/arangodb/entity/From.java (100%) rename {src => driver/src}/main/java/com/arangodb/entity/GraphEntity.java (100%) rename {src => driver/src}/main/java/com/arangodb/entity/Id.java (100%) rename {src => driver/src}/main/java/com/arangodb/entity/IndexEntity.java (100%) rename {src => driver/src}/main/java/com/arangodb/entity/IndexType.java (94%) rename {src => driver/src}/main/java/com/arangodb/entity/InvertedIndexEntity.java (100%) rename {src => driver/src}/main/java/com/arangodb/entity/InvertedIndexField.java (100%) rename {src => driver/src}/main/java/com/arangodb/entity/InvertedIndexPrimarySort.java (100%) rename {src => driver/src}/main/java/com/arangodb/entity/Key.java (100%) rename {src => driver/src}/main/java/com/arangodb/entity/KeyOptions.java (96%) rename {src => driver/src}/main/java/com/arangodb/entity/KeyType.java (96%) rename {src => driver/src}/main/java/com/arangodb/entity/License.java (100%) rename {src => driver/src}/main/java/com/arangodb/entity/LoadBalancingStrategy.java (96%) rename {src => driver/src}/main/java/com/arangodb/entity/LogEntriesEntity.java (100%) rename {src => driver/src}/main/java/com/arangodb/entity/LogLevel.java (100%) rename {src => driver/src}/main/java/com/arangodb/entity/LogLevelEntity.java (100%) rename {src => driver/src}/main/java/com/arangodb/entity/MetaAware.java (100%) rename {src => driver/src}/main/java/com/arangodb/entity/MultiDocumentEntity.java (100%) rename {src => driver/src}/main/java/com/arangodb/entity/Permissions.java (100%) rename {src => driver/src}/main/java/com/arangodb/entity/QueryCachePropertiesEntity.java (100%) rename {src => driver/src}/main/java/com/arangodb/entity/QueryEntity.java (100%) rename {src => driver/src}/main/java/com/arangodb/entity/QueryExecutionState.java (95%) rename {src => driver/src}/main/java/com/arangodb/entity/QueryOptimizerRule.java (100%) rename {src => driver/src}/main/java/com/arangodb/entity/QueryTrackingPropertiesEntity.java (100%) rename {src => driver/src}/main/java/com/arangodb/entity/ReplicationFactor.java (100%) rename {src => driver/src}/main/java/com/arangodb/entity/Rev.java (100%) rename {src => driver/src}/main/java/com/arangodb/entity/ServerMode.java (96%) rename {src => driver/src}/main/java/com/arangodb/entity/ServerRole.java (96%) rename {src => driver/src}/main/java/com/arangodb/entity/ShardEntity.java (100%) rename {src => driver/src}/main/java/com/arangodb/entity/ShardingStrategy.java (100%) rename {src => driver/src}/main/java/com/arangodb/entity/StreamTransactionEntity.java (100%) rename {src => driver/src}/main/java/com/arangodb/entity/StreamTransactionStatus.java (100%) rename {src => driver/src}/main/java/com/arangodb/entity/To.java (100%) rename {src => driver/src}/main/java/com/arangodb/entity/TransactionEntity.java (100%) rename {src => driver/src}/main/java/com/arangodb/entity/UserEntity.java (100%) rename {src => driver/src}/main/java/com/arangodb/entity/VertexEntity.java (96%) rename {src => driver/src}/main/java/com/arangodb/entity/VertexUpdateEntity.java (96%) rename {src => driver/src}/main/java/com/arangodb/entity/ViewEntity.java (100%) rename {src => driver/src}/main/java/com/arangodb/entity/ViewType.java (100%) rename {src => driver/src}/main/java/com/arangodb/entity/arangosearch/AnalyzerFeature.java (100%) rename {src => driver/src}/main/java/com/arangodb/entity/arangosearch/AnalyzerType.java (100%) rename {src => driver/src}/main/java/com/arangodb/entity/arangosearch/ArangoSearchCompression.java (100%) rename {src => driver/src}/main/java/com/arangodb/entity/arangosearch/ArangoSearchPropertiesEntity.java (100%) rename {src => driver/src}/main/java/com/arangodb/entity/arangosearch/CollectionLink.java (100%) rename {src => driver/src}/main/java/com/arangodb/entity/arangosearch/ConsolidationPolicy.java (100%) rename {src => driver/src}/main/java/com/arangodb/entity/arangosearch/ConsolidationType.java (100%) rename {src => driver/src}/main/java/com/arangodb/entity/arangosearch/FieldLink.java (100%) rename {src => driver/src}/main/java/com/arangodb/entity/arangosearch/PrimarySort.java (100%) rename {src => driver/src}/main/java/com/arangodb/entity/arangosearch/SearchAliasIndex.java (100%) rename {src => driver/src}/main/java/com/arangodb/entity/arangosearch/SearchAliasPropertiesEntity.java (100%) rename {src => driver/src}/main/java/com/arangodb/entity/arangosearch/StoreValuesType.java (100%) rename {src => driver/src}/main/java/com/arangodb/entity/arangosearch/StoredValue.java (100%) rename {src => driver/src}/main/java/com/arangodb/entity/arangosearch/analyzer/AQLAnalyzer.java (100%) rename {src => driver/src}/main/java/com/arangodb/entity/arangosearch/analyzer/AQLAnalyzerProperties.java (100%) rename {src => driver/src}/main/java/com/arangodb/entity/arangosearch/analyzer/ClassificationAnalyzer.java (100%) rename {src => driver/src}/main/java/com/arangodb/entity/arangosearch/analyzer/ClassificationAnalyzerProperties.java (100%) rename {src => driver/src}/main/java/com/arangodb/entity/arangosearch/analyzer/CollationAnalyzer.java (100%) rename {src => driver/src}/main/java/com/arangodb/entity/arangosearch/analyzer/CollationAnalyzerProperties.java (100%) rename {src => driver/src}/main/java/com/arangodb/entity/arangosearch/analyzer/DelimiterAnalyzer.java (100%) rename {src => driver/src}/main/java/com/arangodb/entity/arangosearch/analyzer/DelimiterAnalyzerProperties.java (100%) rename {src => driver/src}/main/java/com/arangodb/entity/arangosearch/analyzer/EdgeNgram.java (100%) rename {src => driver/src}/main/java/com/arangodb/entity/arangosearch/analyzer/GeoAnalyzerOptions.java (100%) rename {src => driver/src}/main/java/com/arangodb/entity/arangosearch/analyzer/GeoJSONAnalyzer.java (100%) rename {src => driver/src}/main/java/com/arangodb/entity/arangosearch/analyzer/GeoJSONAnalyzerProperties.java (100%) rename {src => driver/src}/main/java/com/arangodb/entity/arangosearch/analyzer/GeoPointAnalyzer.java (100%) rename {src => driver/src}/main/java/com/arangodb/entity/arangosearch/analyzer/GeoPointAnalyzerProperties.java (100%) rename {src => driver/src}/main/java/com/arangodb/entity/arangosearch/analyzer/IdentityAnalyzer.java (100%) rename {src => driver/src}/main/java/com/arangodb/entity/arangosearch/analyzer/MinHashAnalyzer.java (100%) rename {src => driver/src}/main/java/com/arangodb/entity/arangosearch/analyzer/MinHashAnalyzerProperties.java (100%) rename {src => driver/src}/main/java/com/arangodb/entity/arangosearch/analyzer/NGramAnalyzer.java (100%) rename {src => driver/src}/main/java/com/arangodb/entity/arangosearch/analyzer/NGramAnalyzerProperties.java (100%) rename {src => driver/src}/main/java/com/arangodb/entity/arangosearch/analyzer/NearestNeighborsAnalyzer.java (100%) rename {src => driver/src}/main/java/com/arangodb/entity/arangosearch/analyzer/NearestNeighborsAnalyzerProperties.java (100%) rename {src => driver/src}/main/java/com/arangodb/entity/arangosearch/analyzer/NormAnalyzer.java (100%) rename {src => driver/src}/main/java/com/arangodb/entity/arangosearch/analyzer/NormAnalyzerProperties.java (100%) rename {src => driver/src}/main/java/com/arangodb/entity/arangosearch/analyzer/PipelineAnalyzer.java (100%) rename {src => driver/src}/main/java/com/arangodb/entity/arangosearch/analyzer/PipelineAnalyzerProperties.java (100%) rename {src => driver/src}/main/java/com/arangodb/entity/arangosearch/analyzer/SearchAnalyzer.java (100%) rename {src => driver/src}/main/java/com/arangodb/entity/arangosearch/analyzer/SearchAnalyzerCase.java (100%) rename {src => driver/src}/main/java/com/arangodb/entity/arangosearch/analyzer/SegmentationAnalyzer.java (100%) rename {src => driver/src}/main/java/com/arangodb/entity/arangosearch/analyzer/SegmentationAnalyzerProperties.java (100%) rename {src => driver/src}/main/java/com/arangodb/entity/arangosearch/analyzer/StemAnalyzer.java (100%) rename {src => driver/src}/main/java/com/arangodb/entity/arangosearch/analyzer/StemAnalyzerProperties.java (100%) rename {src => driver/src}/main/java/com/arangodb/entity/arangosearch/analyzer/StopwordsAnalyzer.java (100%) rename {src => driver/src}/main/java/com/arangodb/entity/arangosearch/analyzer/StopwordsAnalyzerProperties.java (100%) rename {src => driver/src}/main/java/com/arangodb/entity/arangosearch/analyzer/StreamType.java (100%) rename {src => driver/src}/main/java/com/arangodb/entity/arangosearch/analyzer/TextAnalyzer.java (100%) rename {src => driver/src}/main/java/com/arangodb/entity/arangosearch/analyzer/TextAnalyzerProperties.java (100%) rename {src => driver/src}/main/java/com/arangodb/internal/ArangoCollectionImpl.java (100%) rename {src => driver/src}/main/java/com/arangodb/internal/ArangoCursorExecute.java (96%) rename {src => driver/src}/main/java/com/arangodb/internal/ArangoDBImpl.java (100%) rename {src => driver/src}/main/java/com/arangodb/internal/ArangoDatabaseImpl.java (100%) rename {src => driver/src}/main/java/com/arangodb/internal/ArangoDefaults.java (100%) rename {src => driver/src}/main/java/com/arangodb/internal/ArangoEdgeCollectionImpl.java (100%) rename {src => driver/src}/main/java/com/arangodb/internal/ArangoErrors.java (100%) rename {src => driver/src}/main/java/com/arangodb/internal/ArangoExecuteable.java (100%) rename {src => driver/src}/main/java/com/arangodb/internal/ArangoExecutor.java (100%) rename {src => driver/src}/main/java/com/arangodb/internal/ArangoExecutorSync.java (100%) rename {src => driver/src}/main/java/com/arangodb/internal/ArangoGraphImpl.java (100%) rename {src => driver/src}/main/java/com/arangodb/internal/ArangoMetricsImpl.java (100%) rename {src => driver/src}/main/java/com/arangodb/internal/ArangoRequestParam.java (100%) rename {src => driver/src}/main/java/com/arangodb/internal/ArangoResponseField.java (100%) rename {src => driver/src}/main/java/com/arangodb/internal/ArangoRouteImpl.java (100%) rename {src => driver/src}/main/java/com/arangodb/internal/ArangoSearchImpl.java (100%) rename {src => driver/src}/main/java/com/arangodb/internal/ArangoVertexCollectionImpl.java (100%) rename {src => driver/src}/main/java/com/arangodb/internal/ArangoViewImpl.java (100%) rename {src => driver/src}/main/java/com/arangodb/internal/DocumentFields.java (100%) rename {src => driver/src}/main/java/com/arangodb/internal/InternalArangoCollection.java (100%) rename {src => driver/src}/main/java/com/arangodb/internal/InternalArangoDB.java (100%) rename {src => driver/src}/main/java/com/arangodb/internal/InternalArangoDBBuilder.java (100%) rename {src => driver/src}/main/java/com/arangodb/internal/InternalArangoDatabase.java (100%) rename {src => driver/src}/main/java/com/arangodb/internal/InternalArangoEdgeCollection.java (100%) rename {src => driver/src}/main/java/com/arangodb/internal/InternalArangoGraph.java (100%) rename {src => driver/src}/main/java/com/arangodb/internal/InternalArangoRoute.java (100%) rename {src => driver/src}/main/java/com/arangodb/internal/InternalArangoSearch.java (100%) rename {src => driver/src}/main/java/com/arangodb/internal/InternalArangoVertexCollection.java (100%) rename {src => driver/src}/main/java/com/arangodb/internal/InternalArangoView.java (100%) rename {src => driver/src}/main/java/com/arangodb/internal/InternalSearchAlias.java (100%) rename {src => driver/src}/main/java/com/arangodb/internal/QueueTimeMetricsImpl.java (100%) rename {src => driver/src}/main/java/com/arangodb/internal/SearchAliasImpl.java (100%) rename {src => driver/src}/main/java/com/arangodb/internal/cursor/AbstractArangoIterable.java (100%) rename {src => driver/src}/main/java/com/arangodb/internal/cursor/ArangoCursorImpl.java (100%) rename {src => driver/src}/main/java/com/arangodb/internal/cursor/ArangoCursorIterator.java (100%) rename {src => driver/src}/main/java/com/arangodb/internal/cursor/entity/InternalCursorEntity.java (100%) rename {src => driver/src}/main/java/com/arangodb/internal/http/HttpCommunication.java (100%) rename {src => driver/src}/main/java/com/arangodb/internal/http/HttpConnection.java (100%) rename {src => driver/src}/main/java/com/arangodb/internal/http/HttpConnectionFactory.java (100%) rename {src => driver/src}/main/java/com/arangodb/internal/http/HttpProtocol.java (100%) rename {src => driver/src}/main/java/com/arangodb/internal/net/AccessType.java (100%) rename {src => driver/src}/main/java/com/arangodb/internal/net/ArangoDBRedirectException.java (96%) rename {src => driver/src}/main/java/com/arangodb/internal/net/CommunicationProtocol.java (96%) rename {src => driver/src}/main/java/com/arangodb/internal/net/Connection.java (100%) rename {src => driver/src}/main/java/com/arangodb/internal/net/ConnectionFactory.java (100%) rename {src => driver/src}/main/java/com/arangodb/internal/net/ConnectionPool.java (100%) rename {src => driver/src}/main/java/com/arangodb/internal/net/ConnectionPoolImpl.java (100%) rename {src => driver/src}/main/java/com/arangodb/internal/net/DirtyReadHostHandler.java (100%) rename {src => driver/src}/main/java/com/arangodb/internal/net/ExtendedHostResolver.java (100%) rename {src => driver/src}/main/java/com/arangodb/internal/net/FallbackHostHandler.java (100%) rename {src => driver/src}/main/java/com/arangodb/internal/net/Host.java (100%) rename {src => driver/src}/main/java/com/arangodb/internal/net/HostDescription.java (100%) rename {src => driver/src}/main/java/com/arangodb/internal/net/HostHandle.java (100%) rename {src => driver/src}/main/java/com/arangodb/internal/net/HostHandler.java (100%) rename {src => driver/src}/main/java/com/arangodb/internal/net/HostImpl.java (100%) rename {src => driver/src}/main/java/com/arangodb/internal/net/HostResolver.java (100%) rename {src => driver/src}/main/java/com/arangodb/internal/net/HostSet.java (100%) rename {src => driver/src}/main/java/com/arangodb/internal/net/RandomHostHandler.java (100%) rename {src => driver/src}/main/java/com/arangodb/internal/net/RoundRobinHostHandler.java (100%) rename {src => driver/src}/main/java/com/arangodb/internal/net/SimpleHostResolver.java (100%) rename {src => driver/src}/main/java/com/arangodb/internal/serde/InternalAnnotationIntrospector.java (100%) rename {src => driver/src}/main/java/com/arangodb/internal/serde/InternalDeserializers.java (100%) rename {src => driver/src}/main/java/com/arangodb/internal/serde/InternalModule.java (100%) rename {src => driver/src}/main/java/com/arangodb/internal/serde/InternalParameterizedType.java (100%) rename {src => driver/src}/main/java/com/arangodb/internal/serde/InternalSerde.java (100%) rename {src => driver/src}/main/java/com/arangodb/internal/serde/InternalSerdeImpl.java (100%) rename {src => driver/src}/main/java/com/arangodb/internal/serde/InternalSerializers.java (100%) rename {src => driver/src}/main/java/com/arangodb/internal/serde/JacksonSerdeImpl.java (100%) rename {src => driver/src}/main/java/com/arangodb/internal/serde/JsonMapperProvider.java (100%) rename {src => driver/src}/main/java/com/arangodb/internal/serde/MapperProvider.java (100%) rename {src => driver/src}/main/java/com/arangodb/internal/serde/SerdeUtils.java (100%) rename {src => driver/src}/main/java/com/arangodb/internal/serde/UserData.java (100%) rename {src => driver/src}/main/java/com/arangodb/internal/serde/UserDataDeserializer.java (100%) rename {src => driver/src}/main/java/com/arangodb/internal/serde/UserDataInside.java (100%) rename {src => driver/src}/main/java/com/arangodb/internal/serde/UserDataSerializer.java (100%) rename {src => driver/src}/main/java/com/arangodb/internal/serde/VPackMapperProvider.java (100%) rename {src => driver/src}/main/java/com/arangodb/internal/util/DocumentUtil.java (100%) rename {src => driver/src}/main/java/com/arangodb/internal/util/EncodeUtils.java (100%) rename {src => driver/src}/main/java/com/arangodb/internal/util/HostUtils.java (100%) rename {src => driver/src}/main/java/com/arangodb/internal/util/RequestUtils.java (100%) rename {src => driver/src}/main/java/com/arangodb/internal/util/ResponseUtils.java (100%) rename {src => driver/src}/main/java/com/arangodb/internal/velocystream/VstCommunication.java (100%) rename {src => driver/src}/main/java/com/arangodb/internal/velocystream/VstCommunicationSync.java (100%) rename {src => driver/src}/main/java/com/arangodb/internal/velocystream/VstConnectionFactorySync.java (100%) rename {src => driver/src}/main/java/com/arangodb/internal/velocystream/VstProtocol.java (100%) rename {src => driver/src}/main/java/com/arangodb/internal/velocystream/internal/AuthenticationRequest.java (96%) rename {src => driver/src}/main/java/com/arangodb/internal/velocystream/internal/Chunk.java (96%) rename {src => driver/src}/main/java/com/arangodb/internal/velocystream/internal/ChunkStore.java (97%) rename {src => driver/src}/main/java/com/arangodb/internal/velocystream/internal/JwtAuthenticationRequest.java (100%) rename {src => driver/src}/main/java/com/arangodb/internal/velocystream/internal/Message.java (96%) rename {src => driver/src}/main/java/com/arangodb/internal/velocystream/internal/MessageStore.java (96%) rename {src => driver/src}/main/java/com/arangodb/internal/velocystream/internal/VstConnection.java (100%) rename {src => driver/src}/main/java/com/arangodb/internal/velocystream/internal/VstConnectionSync.java (100%) rename {src => driver/src}/main/java/com/arangodb/model/AqlFunctionCreateOptions.java (96%) rename {src => driver/src}/main/java/com/arangodb/model/AqlFunctionDeleteOptions.java (96%) rename {src => driver/src}/main/java/com/arangodb/model/AqlFunctionGetOptions.java (96%) rename {src => driver/src}/main/java/com/arangodb/model/AqlQueryExplainOptions.java (96%) rename {src => driver/src}/main/java/com/arangodb/model/AqlQueryOptions.java (100%) rename {src => driver/src}/main/java/com/arangodb/model/AqlQueryParseOptions.java (96%) rename {src => driver/src}/main/java/com/arangodb/model/CollectionCountOptions.java (100%) rename {src => driver/src}/main/java/com/arangodb/model/CollectionCreateOptions.java (100%) rename {src => driver/src}/main/java/com/arangodb/model/CollectionPropertiesOptions.java (96%) rename {src => driver/src}/main/java/com/arangodb/model/CollectionRenameOptions.java (95%) rename {src => driver/src}/main/java/com/arangodb/model/CollectionSchema.java (100%) rename {src => driver/src}/main/java/com/arangodb/model/CollectionTruncateOptions.java (100%) rename {src => driver/src}/main/java/com/arangodb/model/CollectionsReadOptions.java (96%) rename {src => driver/src}/main/java/com/arangodb/model/ComputedValue.java (100%) rename {src => driver/src}/main/java/com/arangodb/model/DBCreateOptions.java (96%) rename {src => driver/src}/main/java/com/arangodb/model/DatabaseOptions.java (100%) rename {src => driver/src}/main/java/com/arangodb/model/DatabaseUsersOptions.java (100%) rename {src => driver/src}/main/java/com/arangodb/model/DocumentCreateOptions.java (100%) rename {src => driver/src}/main/java/com/arangodb/model/DocumentDeleteOptions.java (100%) rename {src => driver/src}/main/java/com/arangodb/model/DocumentExistsOptions.java (96%) rename {src => driver/src}/main/java/com/arangodb/model/DocumentImportOptions.java (97%) rename {src => driver/src}/main/java/com/arangodb/model/DocumentReadOptions.java (96%) rename {src => driver/src}/main/java/com/arangodb/model/DocumentReplaceOptions.java (100%) rename {src => driver/src}/main/java/com/arangodb/model/DocumentUpdateOptions.java (100%) rename {src => driver/src}/main/java/com/arangodb/model/EdgeCreateOptions.java (96%) rename {src => driver/src}/main/java/com/arangodb/model/EdgeDeleteOptions.java (96%) rename {src => driver/src}/main/java/com/arangodb/model/EdgeReplaceOptions.java (96%) rename {src => driver/src}/main/java/com/arangodb/model/EdgeUpdateOptions.java (96%) rename {src => driver/src}/main/java/com/arangodb/model/FulltextIndexOptions.java (96%) rename {src => driver/src}/main/java/com/arangodb/model/GeoIndexOptions.java (96%) rename {src => driver/src}/main/java/com/arangodb/model/GraphCreateOptions.java (97%) rename {src => driver/src}/main/java/com/arangodb/model/GraphDocumentReadOptions.java (100%) rename {src => driver/src}/main/java/com/arangodb/model/HashIndexOptions.java (96%) rename {src => driver/src}/main/java/com/arangodb/model/ImportType.java (96%) rename {src => driver/src}/main/java/com/arangodb/model/IndexOptions.java (96%) rename {src => driver/src}/main/java/com/arangodb/model/InvertedIndexOptions.java (100%) rename {src => driver/src}/main/java/com/arangodb/model/LogOptions.java (96%) rename {src => driver/src}/main/java/com/arangodb/model/OptionsBuilder.java (100%) rename {src => driver/src}/main/java/com/arangodb/model/OverwriteMode.java (100%) rename {src => driver/src}/main/java/com/arangodb/model/PersistentIndexOptions.java (96%) rename {src => driver/src}/main/java/com/arangodb/model/QueueTimeSample.java (100%) rename {src => driver/src}/main/java/com/arangodb/model/SkiplistIndexOptions.java (96%) rename {src => driver/src}/main/java/com/arangodb/model/StreamTransactionOptions.java (100%) rename {src => driver/src}/main/java/com/arangodb/model/TransactionCollectionOptions.java (100%) rename {src => driver/src}/main/java/com/arangodb/model/TransactionOptions.java (100%) rename {src => driver/src}/main/java/com/arangodb/model/TtlIndexOptions.java (96%) rename {src => driver/src}/main/java/com/arangodb/model/UserAccessOptions.java (96%) rename {src => driver/src}/main/java/com/arangodb/model/UserCreateOptions.java (96%) rename {src => driver/src}/main/java/com/arangodb/model/UserUpdateOptions.java (96%) rename {src => driver/src}/main/java/com/arangodb/model/VertexCollectionCreateOptions.java (96%) rename {src => driver/src}/main/java/com/arangodb/model/VertexCreateOptions.java (96%) rename {src => driver/src}/main/java/com/arangodb/model/VertexDeleteOptions.java (96%) rename {src => driver/src}/main/java/com/arangodb/model/VertexReplaceOptions.java (96%) rename {src => driver/src}/main/java/com/arangodb/model/VertexUpdateOptions.java (96%) rename {src => driver/src}/main/java/com/arangodb/model/ViewCreateOptions.java (100%) rename {src => driver/src}/main/java/com/arangodb/model/ViewRenameOptions.java (100%) rename {src => driver/src}/main/java/com/arangodb/model/ZKDIndexOptions.java (100%) rename {src => driver/src}/main/java/com/arangodb/model/arangosearch/AnalyzerDeleteOptions.java (100%) rename {src => driver/src}/main/java/com/arangodb/model/arangosearch/ArangoSearchCreateOptions.java (100%) rename {src => driver/src}/main/java/com/arangodb/model/arangosearch/ArangoSearchOptionsBuilder.java (100%) rename {src => driver/src}/main/java/com/arangodb/model/arangosearch/ArangoSearchPropertiesOptions.java (100%) rename {src => driver/src}/main/java/com/arangodb/model/arangosearch/SearchAliasCreateOptions.java (100%) rename {src => driver/src}/main/java/com/arangodb/model/arangosearch/SearchAliasOptionsBuilder.java (100%) rename {src => driver/src}/main/java/com/arangodb/model/arangosearch/SearchAliasPropertiesOptions.java (100%) rename {src => driver/src}/main/java/com/arangodb/serde/ArangoSerde.java (100%) rename {src => driver/src}/main/java/com/arangodb/serde/JacksonSerde.java (100%) rename {src => driver/src}/main/java/com/arangodb/util/RawBytes.java (100%) rename {src => driver/src}/main/java/com/arangodb/util/RawData.java (100%) rename {src => driver/src}/main/java/com/arangodb/util/RawJson.java (100%) rename {src => driver/src}/main/java/com/arangodb/util/UnicodeUtils.java (100%) rename {src => driver/src}/main/resources/META-INF/native-image/com.arangodb/arangodb-java-driver/native-image.properties (100%) rename {src => driver/src}/main/resources/META-INF/native-image/com.arangodb/arangodb-java-driver/reflect-config.json (100%) rename {src => driver/src}/main/resources/META-INF/native-image/com.arangodb/arangodb-java-driver/resource-config.json (100%) rename {src => driver/src}/main/resources/META-INF/native-image/com.arangodb/arangodb-java-driver/serialization-config.json (100%) rename {src => driver/src}/main/resources/vertx/vertx-version.txt (100%) rename {src => driver/src}/test/java/com/arangodb/ArangoCollectionTest.java (100%) rename {src => driver/src}/test/java/com/arangodb/ArangoCursorTest.java (100%) rename {src => driver/src}/test/java/com/arangodb/ArangoDBTest.java (100%) rename {src => driver/src}/test/java/com/arangodb/ArangoDatabaseTest.java (100%) rename {src => driver/src}/test/java/com/arangodb/ArangoDocumentUtilTest.java (100%) rename {src => driver/src}/test/java/com/arangodb/ArangoEdgeCollectionTest.java (97%) rename {src => driver/src}/test/java/com/arangodb/ArangoGraphTest.java (100%) rename {src => driver/src}/test/java/com/arangodb/ArangoRouteTest.java (100%) rename {src => driver/src}/test/java/com/arangodb/ArangoSearchTest.java (100%) rename {src => driver/src}/test/java/com/arangodb/ArangoSslTest.java (97%) rename {src => driver/src}/test/java/com/arangodb/ArangoVertexCollectionTest.java (97%) rename {src => driver/src}/test/java/com/arangodb/ArangoViewTest.java (100%) rename {src => driver/src}/test/java/com/arangodb/BaseJunit5.java (100%) rename {src => driver/src}/test/java/com/arangodb/ConcurrencyTests.java (100%) rename {src => driver/src}/test/java/com/arangodb/DocumentTest.java (97%) rename {src => driver/src}/test/java/com/arangodb/InvertedIndexTest.java (100%) rename {src => driver/src}/test/java/com/arangodb/JwtAuthTest.java (94%) rename {src => driver/src}/test/java/com/arangodb/ParallelTest.java (100%) rename {src => driver/src}/test/java/com/arangodb/SerializableTest.java (100%) rename {src => driver/src}/test/java/com/arangodb/StreamTransactionConflictsTest.java (100%) rename {src => driver/src}/test/java/com/arangodb/StreamTransactionGraphTest.java (100%) rename {src => driver/src}/test/java/com/arangodb/StreamTransactionTest.java (100%) rename {src => driver/src}/test/java/com/arangodb/async/ArangoCollectionTest.java (100%) rename {src => driver/src}/test/java/com/arangodb/async/ArangoDBTest.java (100%) rename {src => driver/src}/test/java/com/arangodb/async/ArangoDatabaseTest.java (100%) rename {src => driver/src}/test/java/com/arangodb/async/ArangoEdgeCollectionTest.java (100%) rename {src => driver/src}/test/java/com/arangodb/async/ArangoGraphTest.java (100%) rename {src => driver/src}/test/java/com/arangodb/async/ArangoRouteTest.java (100%) rename {src => driver/src}/test/java/com/arangodb/async/ArangoSearchTest.java (100%) rename {src => driver/src}/test/java/com/arangodb/async/ArangoVertexCollectionTest.java (100%) rename {src => driver/src}/test/java/com/arangodb/async/ArangoViewTest.java (100%) rename {src => driver/src}/test/java/com/arangodb/async/BaseTest.java (100%) rename {src => driver/src}/test/java/com/arangodb/async/CommunicationTest.java (100%) rename {src => driver/src}/test/java/com/arangodb/async/ConcurrencyTest.java (100%) rename {src => driver/src}/test/java/com/arangodb/async/ConcurrencyTests.java (100%) rename {src => driver/src}/test/java/com/arangodb/async/InvertedIndexTest.java (100%) rename {src => driver/src}/test/java/com/arangodb/async/JwtAuthTest.java (100%) rename {src => driver/src}/test/java/com/arangodb/async/StreamTransactionConflictsTest.java (100%) rename {src => driver/src}/test/java/com/arangodb/async/StreamTransactionGraphTest.java (100%) rename {src => driver/src}/test/java/com/arangodb/async/StreamTransactionTest.java (100%) rename {src => driver/src}/test/java/com/arangodb/async/debug/ConsolidationIntervalMsecTest.java (100%) rename {src => driver/src}/test/java/com/arangodb/async/example/ExampleBase.java (100%) rename {src => driver/src}/test/java/com/arangodb/async/example/document/AqlQueryWithSpecialReturnTypesExampleTest.java (100%) rename {src => driver/src}/test/java/com/arangodb/async/example/document/GetDocumentExampleTest.java (100%) rename {src => driver/src}/test/java/com/arangodb/async/example/document/ImportDocumentExampleTest.java (100%) rename {src => driver/src}/test/java/com/arangodb/async/example/document/InsertDocumentExampleTest.java (100%) rename {src => driver/src}/test/java/com/arangodb/async/example/document/TestEntity.java (100%) rename {src => driver/src}/test/java/com/arangodb/async/example/graph/AQLActorsAndMoviesExampleTest.java (100%) rename {src => driver/src}/test/java/com/arangodb/async/example/graph/BaseGraphTest.java (100%) rename {src => driver/src}/test/java/com/arangodb/async/example/graph/Circle.java (100%) rename {src => driver/src}/test/java/com/arangodb/async/example/graph/CircleEdge.java (100%) rename {src => driver/src}/test/java/com/arangodb/async/example/graph/GraphTraversalsInAQLExampleTest.java (100%) rename {src => driver/src}/test/java/com/arangodb/async/example/graph/ShortestPathInAQLExampleTest.java (100%) rename {src => driver/src}/test/java/com/arangodb/async/example/ssl/SslExampleTest.java (100%) rename {src => driver/src}/test/java/com/arangodb/async/serde/CustomSerdeTest.java (100%) rename {src => driver/src}/test/java/com/arangodb/example/ExampleBase.java (96%) rename {src => driver/src}/test/java/com/arangodb/example/FirstProject.java (97%) rename {src => driver/src}/test/java/com/arangodb/example/document/AqlQueryWithSpecialReturnTypesExampleTest.java (100%) rename {src => driver/src}/test/java/com/arangodb/example/document/GetDocumentExampleTest.java (100%) rename {src => driver/src}/test/java/com/arangodb/example/document/InsertDocumentExampleTest.java (100%) rename {src => driver/src}/test/java/com/arangodb/example/document/TestEntity.java (95%) rename {src => driver/src}/test/java/com/arangodb/example/graph/AQLActorsAndMoviesExampleTest.java (100%) rename {src => driver/src}/test/java/com/arangodb/example/graph/BaseGraphTest.java (97%) rename {src => driver/src}/test/java/com/arangodb/example/graph/Circle.java (100%) rename {src => driver/src}/test/java/com/arangodb/example/graph/CircleEdge.java (100%) rename {src => driver/src}/test/java/com/arangodb/example/graph/GraphTraversalsInAQLExampleTest.java (100%) rename {src => driver/src}/test/java/com/arangodb/example/graph/ShortestPathInAQLExampleTest.java (100%) rename {src => driver/src}/test/java/com/arangodb/example/ssl/SslExampleTest.java (100%) rename {src => driver/src}/test/java/com/arangodb/internal/HostHandlerTest.java (100%) rename {src => driver/src}/test/java/com/arangodb/internal/QueueTimeMetricsImplTest.java (100%) rename {src => driver/src}/test/java/com/arangodb/internal/velocystream/CommunicationTest.java (97%) rename {src => driver/src}/test/java/com/arangodb/mapping/annotations/AnnotatedEntity.java (100%) rename {src => driver/src}/test/java/com/arangodb/mapping/annotations/ArangoAnnotationsTest.java (100%) rename {src => driver/src}/test/java/com/arangodb/serde/CustomSerdeTest.java (100%) rename {src => driver/src}/test/java/com/arangodb/serde/CustomTypeHintTest.java (100%) rename {src => driver/src}/test/java/com/arangodb/serde/JsonbSerde.java (100%) rename {src => driver/src}/test/java/com/arangodb/serde/JsonbSerdeImpl.java (100%) rename {src => driver/src}/test/java/com/arangodb/serde/SerdeTest.java (100%) rename {src => driver/src}/test/java/com/arangodb/util/MapBuilder.java (100%) rename {src => driver/src}/test/java/com/arangodb/util/MapBuilderTest.java (96%) rename {src => driver/src}/test/java/com/arangodb/util/TestUtils.java (100%) rename {src => driver/src}/test/java/com/arangodb/util/UnicodeUtilsTest.java (100%) rename {src => driver/src}/test/java/helper/NativeImageHelper.java (100%) rename {src => driver/src}/test/java/perf/Benchmark.java (100%) rename {src => driver/src}/test/java/perf/SimpleSyncPerfTest.java (100%) rename {src => driver/src}/test/java/perf/SyncBenchmarkTest.java (100%) rename {src => driver/src}/test/resources/META-INF/native-image/native-image.properties (100%) rename {src => driver/src}/test/resources/META-INF/native-image/reflect-config.json (100%) rename {src => driver/src}/test/resources/META-INF/native-image/resource-config.json (100%) rename {src => driver/src}/test/resources/META-INF/native-image/serialization-config.json (100%) rename {src => driver/src}/test/resources/arangodb-bad.properties (100%) rename {src => driver/src}/test/resources/arangodb.properties (100%) rename {src => driver/src}/test/resources/example.truststore (100%) rename {src => driver/src}/test/resources/logback-test.xml (100%) delete mode 100644 formatter.xml diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index 96a57d376..8013333d3 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -67,6 +67,7 @@ jobs: - name: Info run: mvn -version - name: Test + working-directory: driver run: mvn --no-transfer-progress test -DargLine="-Duser.language=${{matrix.user-language}}" test-ssl: @@ -101,6 +102,7 @@ jobs: - name: Info run: mvn -version - name: Test + working-directory: driver run: mvn --no-transfer-progress -Dgroups=ssl -DSslTest=true test # test encodeURIComponent() and normalize('NFC') comparing to Javascript behavior @@ -117,6 +119,7 @@ jobs: - name: Info run: mvn -version - name: Test + working-directory: driver run: mvn -e --no-transfer-progress test -Dtest=com.arangodb.util.UnicodeUtilsTest test-jwt: @@ -164,6 +167,7 @@ jobs: - name: Info run: mvn -version - name: Test + working-directory: driver run: mvn --no-transfer-progress test -DargLine="-Duser.language=${{matrix.user-language}}" jackson-test: @@ -207,6 +211,7 @@ jobs: - name: Info run: mvn -version - name: Test + working-directory: driver run: mvn --no-transfer-progress test -Dadb.jackson.version=${{matrix.jackson-version}} sonar: @@ -260,5 +265,6 @@ jobs: env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Needed to get PR information, if any SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} + working-directory: driver run: mvn -B --no-transfer-progress -Dgpg.skip=true verify org.sonarsource.scanner.maven:sonar-maven-plugin:sonar -Dsonar.projectKey=arangodb_arangodb-java-driver diff --git a/.github/workflows/native.yml b/.github/workflows/native.yml index 3112392fb..d847b8861 100644 --- a/.github/workflows/native.yml +++ b/.github/workflows/native.yml @@ -40,6 +40,7 @@ jobs: - name: Info run: mvn -version - name: Test Native + working-directory: driver run: mvn -Pnative --no-transfer-progress test test-native-ssl: @@ -74,4 +75,5 @@ jobs: - name: Info run: mvn -version - name: Test Native + working-directory: driver run: mvn -Pnative --no-transfer-progress -Dgroups=ssl -DSslTest=true test diff --git a/.gitignore b/.gitignore index bdc7bc636..7cdb4ecd7 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,7 @@ /.classpath /.project /.settings -/target +**/target /.idea /*.iml /bin @@ -10,5 +10,5 @@ /docker/jwtSecret /docker/data -/test-results-native/ +**/test-results-native .flattened-pom.xml diff --git a/README.md b/README.md index b3f6600df..d50d4ec1d 100644 --- a/README.md +++ b/README.md @@ -9,9 +9,9 @@ The official [ArangoDB](https://www.arangodb.com/) Java Driver. ## Learn more -- [ChangeLog](ChangeLog.md) -- [Examples](src/test/java/com/arangodb/example) -- [Examples Async](src/test/java/com/arangodb/async/example) +- [ChangeLog](driver/ChangeLog.md) +- [Examples](driver/src/test/java/com/arangodb/example) +- [Examples Async](driver/src/test/java/com/arangodb/async/example) - [Tutorial](https://www.arangodb.com/docs/stable/drivers/java-tutorial.html) - [Documentation](https://www.arangodb.com/docs/stable/drivers/java.html) - [JavaDoc](http://arangodb.github.io/arangodb-java-driver/) diff --git a/ChangeLog.md b/driver/ChangeLog.md similarity index 100% rename from ChangeLog.md rename to driver/ChangeLog.md diff --git a/dev-README.md b/driver/dev-README.md similarity index 100% rename from dev-README.md rename to driver/dev-README.md diff --git a/driver/pom.xml b/driver/pom.xml new file mode 100644 index 000000000..f44e0a0f2 --- /dev/null +++ b/driver/pom.xml @@ -0,0 +1,398 @@ + + + 4.0.0 + + + arangodb-java-driver-parent + com.arangodb + 7.0.0-SNAPSHOT + + + arangodb-java-driver + arangodb-java-driver + ArangoDB Java Driver + https://github.com/arangodb/arangodb-java-driver + + + 2.13.3 + arangodb-1 + https://sonarcloud.io + false + + + + + doclint-java8-disable + + [1.8,) + + + none + + + + no-graalvm + + 1.8 + + + + + org.apache.maven.plugins + maven-compiler-plugin + + + com/arangodb/util/UnicodeUtilsTest.java + + + + + + + + native + + + + org.apache.maven.plugins + maven-surefire-plugin + 3.0.0-M5 + + + org.graalvm.buildtools + native-maven-plugin + 0.9.16 + true + + + test-native + + generateTestResourceConfig + test + + test + + + + true + false + + --no-fallback + + + ${SslTest} + + + + + + + + + + + ossrh + https://oss.sonatype.org/content/repositories/snapshots + + + ossrh + https://oss.sonatype.org/service/local/staging/deploy/maven2/ + + + + + + + org.sonatype.plugins + nexus-staging-maven-plugin + 1.6.13 + true + + ossrh + https://oss.sonatype.org/ + 84aff6e87e214c + false + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.10.1 + + + -Xlint:unchecked + -Xlint:deprecation + + true + 1.8 + 1.8 + + + + org.apache.maven.plugins + maven-resources-plugin + 3.3.0 + + UTF-8 + + + + org.apache.maven.plugins + maven-source-plugin + 3.2.1 + + + + jar + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + 3.4.0 + + + attach-javadocs + + jar + + + com.arangodb.internal + + + + + + org.apache.maven.plugins + maven-surefire-plugin + 3.0.0-M7 + + + **/*Test.java + **/*Example.java + + + + + org.apache.maven.plugins + maven-deploy-plugin + 3.0.0 + + 10 + + + + org.apache.maven.plugins + maven-gpg-plugin + 3.0.1 + + + sign-artifacts + verify + + sign + + + + + + org.codehaus.mojo + flatten-maven-plugin + 1.2.7 + + oss + + + + + flatten + process-resources + + flatten + + + + + flatten.clean + clean + + clean + + + + + + org.jacoco + jacoco-maven-plugin + 0.8.8 + + + + prepare-agent + + + + report + prepare-package + + report + + + + + + com.github.spotbugs + spotbugs-maven-plugin + 4.7.1.1 + + spotbugs/spotbugs-exclude.xml + + + + compile + + check + + + + + + com.github.spotbugs + spotbugs + 4.7.1 + + + + + + + + + org.slf4j + slf4j-api + 1.7.36 + + + com.fasterxml.jackson.core + jackson-databind + + + com.fasterxml.jackson.core + jackson-core + + + com.fasterxml.jackson.core + jackson-annotations + + + io.vertx + vertx-web-client + + + com.arangodb + jackson-dataformat-velocypack + 3.0.1 + true + + + jakarta.json.bind + jakarta.json.bind-api + 2.0.0 + + + com.google.code.findbugs + jsr305 + 3.0.2 + provided + + + ch.qos.logback + logback-classic + 1.2.11 + test + + + org.junit.platform + junit-platform-launcher + test + + + org.junit.jupiter + junit-jupiter-engine + test + + + org.junit.jupiter + junit-jupiter-params + test + + + org.assertj + assertj-core + 3.23.1 + test + + + org.reflections + reflections + 0.10.2 + test + + + org.graalvm.sdk + graal-sdk + 22.2.0 + test + + + org.eclipse + yasson + 2.0.4 + test + + + + + + + com.fasterxml.jackson + jackson-bom + ${adb.jackson.version} + import + pom + + + io.vertx + vertx-stack-depchain + 4.3.4 + pom + import + + + io.netty + netty-bom + 4.1.82.Final + pom + import + + + org.junit + junit-bom + 5.9.1 + pom + import + + + + + + https://github.com/arangodb/arangodb-java-driver + scm:git:git://github.com/arangodb/arangodb-java-driver.git + scm:git:git://github.com/arangodb/arangodb-java-driver.git + + + diff --git a/spotbugs/spotbugs-exclude.xml b/driver/spotbugs/spotbugs-exclude.xml similarity index 100% rename from spotbugs/spotbugs-exclude.xml rename to driver/spotbugs/spotbugs-exclude.xml diff --git a/src/main/java/com/arangodb/ArangoCollection.java b/driver/src/main/java/com/arangodb/ArangoCollection.java similarity index 100% rename from src/main/java/com/arangodb/ArangoCollection.java rename to driver/src/main/java/com/arangodb/ArangoCollection.java diff --git a/src/main/java/com/arangodb/ArangoCursor.java b/driver/src/main/java/com/arangodb/ArangoCursor.java similarity index 100% rename from src/main/java/com/arangodb/ArangoCursor.java rename to driver/src/main/java/com/arangodb/ArangoCursor.java diff --git a/src/main/java/com/arangodb/ArangoDB.java b/driver/src/main/java/com/arangodb/ArangoDB.java similarity index 99% rename from src/main/java/com/arangodb/ArangoDB.java rename to driver/src/main/java/com/arangodb/ArangoDB.java index 60181e2f1..d7de287d3 100644 --- a/src/main/java/com/arangodb/ArangoDB.java +++ b/driver/src/main/java/com/arangodb/ArangoDB.java @@ -605,7 +605,7 @@ public ArangoDB build() { final int max = maxConnections != null ? Math.max(1, maxConnections) : protocolMaxConnections; - final ConnectionFactory connectionFactory = (protocol == null || Protocol.VST == protocol) + final ConnectionFactory connectionFactory = Protocol.VST == protocol ? new VstConnectionFactorySync(timeout, connectionTtl, keepAliveInterval, useSsl, sslContext) : new HttpConnectionFactory(timeout, user, password, useSsl, sslContext, verifyHost, serde, protocol, connectionTtl); diff --git a/src/main/java/com/arangodb/ArangoDBException.java b/driver/src/main/java/com/arangodb/ArangoDBException.java similarity index 100% rename from src/main/java/com/arangodb/ArangoDBException.java rename to driver/src/main/java/com/arangodb/ArangoDBException.java diff --git a/src/main/java/com/arangodb/ArangoDBMultipleException.java b/driver/src/main/java/com/arangodb/ArangoDBMultipleException.java similarity index 100% rename from src/main/java/com/arangodb/ArangoDBMultipleException.java rename to driver/src/main/java/com/arangodb/ArangoDBMultipleException.java diff --git a/src/main/java/com/arangodb/ArangoDatabase.java b/driver/src/main/java/com/arangodb/ArangoDatabase.java similarity index 100% rename from src/main/java/com/arangodb/ArangoDatabase.java rename to driver/src/main/java/com/arangodb/ArangoDatabase.java diff --git a/src/main/java/com/arangodb/ArangoEdgeCollection.java b/driver/src/main/java/com/arangodb/ArangoEdgeCollection.java similarity index 100% rename from src/main/java/com/arangodb/ArangoEdgeCollection.java rename to driver/src/main/java/com/arangodb/ArangoEdgeCollection.java diff --git a/src/main/java/com/arangodb/ArangoGraph.java b/driver/src/main/java/com/arangodb/ArangoGraph.java similarity index 100% rename from src/main/java/com/arangodb/ArangoGraph.java rename to driver/src/main/java/com/arangodb/ArangoGraph.java diff --git a/src/main/java/com/arangodb/ArangoIterable.java b/driver/src/main/java/com/arangodb/ArangoIterable.java similarity index 100% rename from src/main/java/com/arangodb/ArangoIterable.java rename to driver/src/main/java/com/arangodb/ArangoIterable.java diff --git a/src/main/java/com/arangodb/ArangoIterator.java b/driver/src/main/java/com/arangodb/ArangoIterator.java similarity index 100% rename from src/main/java/com/arangodb/ArangoIterator.java rename to driver/src/main/java/com/arangodb/ArangoIterator.java diff --git a/src/main/java/com/arangodb/ArangoMetrics.java b/driver/src/main/java/com/arangodb/ArangoMetrics.java similarity index 100% rename from src/main/java/com/arangodb/ArangoMetrics.java rename to driver/src/main/java/com/arangodb/ArangoMetrics.java diff --git a/src/main/java/com/arangodb/ArangoRoute.java b/driver/src/main/java/com/arangodb/ArangoRoute.java similarity index 100% rename from src/main/java/com/arangodb/ArangoRoute.java rename to driver/src/main/java/com/arangodb/ArangoRoute.java diff --git a/src/main/java/com/arangodb/ArangoSearch.java b/driver/src/main/java/com/arangodb/ArangoSearch.java similarity index 100% rename from src/main/java/com/arangodb/ArangoSearch.java rename to driver/src/main/java/com/arangodb/ArangoSearch.java diff --git a/src/main/java/com/arangodb/ArangoSerdeAccessor.java b/driver/src/main/java/com/arangodb/ArangoSerdeAccessor.java similarity index 100% rename from src/main/java/com/arangodb/ArangoSerdeAccessor.java rename to driver/src/main/java/com/arangodb/ArangoSerdeAccessor.java diff --git a/src/main/java/com/arangodb/ArangoVertexCollection.java b/driver/src/main/java/com/arangodb/ArangoVertexCollection.java similarity index 100% rename from src/main/java/com/arangodb/ArangoVertexCollection.java rename to driver/src/main/java/com/arangodb/ArangoVertexCollection.java diff --git a/src/main/java/com/arangodb/ArangoView.java b/driver/src/main/java/com/arangodb/ArangoView.java similarity index 100% rename from src/main/java/com/arangodb/ArangoView.java rename to driver/src/main/java/com/arangodb/ArangoView.java diff --git a/src/main/java/com/arangodb/ContentType.java b/driver/src/main/java/com/arangodb/ContentType.java similarity index 100% rename from src/main/java/com/arangodb/ContentType.java rename to driver/src/main/java/com/arangodb/ContentType.java diff --git a/src/main/java/com/arangodb/DbName.java b/driver/src/main/java/com/arangodb/DbName.java similarity index 100% rename from src/main/java/com/arangodb/DbName.java rename to driver/src/main/java/com/arangodb/DbName.java diff --git a/src/main/java/com/arangodb/Function.java b/driver/src/main/java/com/arangodb/Function.java similarity index 100% rename from src/main/java/com/arangodb/Function.java rename to driver/src/main/java/com/arangodb/Function.java diff --git a/src/main/java/com/arangodb/Protocol.java b/driver/src/main/java/com/arangodb/Protocol.java similarity index 100% rename from src/main/java/com/arangodb/Protocol.java rename to driver/src/main/java/com/arangodb/Protocol.java diff --git a/src/main/java/com/arangodb/QueueTimeMetrics.java b/driver/src/main/java/com/arangodb/QueueTimeMetrics.java similarity index 100% rename from src/main/java/com/arangodb/QueueTimeMetrics.java rename to driver/src/main/java/com/arangodb/QueueTimeMetrics.java diff --git a/src/main/java/com/arangodb/Request.java b/driver/src/main/java/com/arangodb/Request.java similarity index 100% rename from src/main/java/com/arangodb/Request.java rename to driver/src/main/java/com/arangodb/Request.java diff --git a/src/main/java/com/arangodb/RequestType.java b/driver/src/main/java/com/arangodb/RequestType.java similarity index 100% rename from src/main/java/com/arangodb/RequestType.java rename to driver/src/main/java/com/arangodb/RequestType.java diff --git a/src/main/java/com/arangodb/Response.java b/driver/src/main/java/com/arangodb/Response.java similarity index 100% rename from src/main/java/com/arangodb/Response.java rename to driver/src/main/java/com/arangodb/Response.java diff --git a/src/main/java/com/arangodb/SearchAlias.java b/driver/src/main/java/com/arangodb/SearchAlias.java similarity index 100% rename from src/main/java/com/arangodb/SearchAlias.java rename to driver/src/main/java/com/arangodb/SearchAlias.java diff --git a/src/main/java/com/arangodb/async/ArangoCollectionAsync.java b/driver/src/main/java/com/arangodb/async/ArangoCollectionAsync.java similarity index 100% rename from src/main/java/com/arangodb/async/ArangoCollectionAsync.java rename to driver/src/main/java/com/arangodb/async/ArangoCollectionAsync.java diff --git a/src/main/java/com/arangodb/async/ArangoCursorAsync.java b/driver/src/main/java/com/arangodb/async/ArangoCursorAsync.java similarity index 100% rename from src/main/java/com/arangodb/async/ArangoCursorAsync.java rename to driver/src/main/java/com/arangodb/async/ArangoCursorAsync.java diff --git a/src/main/java/com/arangodb/async/ArangoDBAsync.java b/driver/src/main/java/com/arangodb/async/ArangoDBAsync.java similarity index 100% rename from src/main/java/com/arangodb/async/ArangoDBAsync.java rename to driver/src/main/java/com/arangodb/async/ArangoDBAsync.java diff --git a/src/main/java/com/arangodb/async/ArangoDatabaseAsync.java b/driver/src/main/java/com/arangodb/async/ArangoDatabaseAsync.java similarity index 100% rename from src/main/java/com/arangodb/async/ArangoDatabaseAsync.java rename to driver/src/main/java/com/arangodb/async/ArangoDatabaseAsync.java diff --git a/src/main/java/com/arangodb/async/ArangoEdgeCollectionAsync.java b/driver/src/main/java/com/arangodb/async/ArangoEdgeCollectionAsync.java similarity index 100% rename from src/main/java/com/arangodb/async/ArangoEdgeCollectionAsync.java rename to driver/src/main/java/com/arangodb/async/ArangoEdgeCollectionAsync.java diff --git a/src/main/java/com/arangodb/async/ArangoGraphAsync.java b/driver/src/main/java/com/arangodb/async/ArangoGraphAsync.java similarity index 100% rename from src/main/java/com/arangodb/async/ArangoGraphAsync.java rename to driver/src/main/java/com/arangodb/async/ArangoGraphAsync.java diff --git a/src/main/java/com/arangodb/async/ArangoRouteAsync.java b/driver/src/main/java/com/arangodb/async/ArangoRouteAsync.java similarity index 100% rename from src/main/java/com/arangodb/async/ArangoRouteAsync.java rename to driver/src/main/java/com/arangodb/async/ArangoRouteAsync.java diff --git a/src/main/java/com/arangodb/async/ArangoSearchAsync.java b/driver/src/main/java/com/arangodb/async/ArangoSearchAsync.java similarity index 100% rename from src/main/java/com/arangodb/async/ArangoSearchAsync.java rename to driver/src/main/java/com/arangodb/async/ArangoSearchAsync.java diff --git a/src/main/java/com/arangodb/async/ArangoVertexCollectionAsync.java b/driver/src/main/java/com/arangodb/async/ArangoVertexCollectionAsync.java similarity index 100% rename from src/main/java/com/arangodb/async/ArangoVertexCollectionAsync.java rename to driver/src/main/java/com/arangodb/async/ArangoVertexCollectionAsync.java diff --git a/src/main/java/com/arangodb/async/ArangoViewAsync.java b/driver/src/main/java/com/arangodb/async/ArangoViewAsync.java similarity index 100% rename from src/main/java/com/arangodb/async/ArangoViewAsync.java rename to driver/src/main/java/com/arangodb/async/ArangoViewAsync.java diff --git a/src/main/java/com/arangodb/async/SearchAliasAsync.java b/driver/src/main/java/com/arangodb/async/SearchAliasAsync.java similarity index 100% rename from src/main/java/com/arangodb/async/SearchAliasAsync.java rename to driver/src/main/java/com/arangodb/async/SearchAliasAsync.java diff --git a/src/main/java/com/arangodb/async/internal/ArangoCollectionAsyncImpl.java b/driver/src/main/java/com/arangodb/async/internal/ArangoCollectionAsyncImpl.java similarity index 100% rename from src/main/java/com/arangodb/async/internal/ArangoCollectionAsyncImpl.java rename to driver/src/main/java/com/arangodb/async/internal/ArangoCollectionAsyncImpl.java diff --git a/src/main/java/com/arangodb/async/internal/ArangoCursorAsyncImpl.java b/driver/src/main/java/com/arangodb/async/internal/ArangoCursorAsyncImpl.java similarity index 100% rename from src/main/java/com/arangodb/async/internal/ArangoCursorAsyncImpl.java rename to driver/src/main/java/com/arangodb/async/internal/ArangoCursorAsyncImpl.java diff --git a/src/main/java/com/arangodb/async/internal/ArangoDBAsyncImpl.java b/driver/src/main/java/com/arangodb/async/internal/ArangoDBAsyncImpl.java similarity index 100% rename from src/main/java/com/arangodb/async/internal/ArangoDBAsyncImpl.java rename to driver/src/main/java/com/arangodb/async/internal/ArangoDBAsyncImpl.java diff --git a/src/main/java/com/arangodb/async/internal/ArangoDatabaseAsyncImpl.java b/driver/src/main/java/com/arangodb/async/internal/ArangoDatabaseAsyncImpl.java similarity index 100% rename from src/main/java/com/arangodb/async/internal/ArangoDatabaseAsyncImpl.java rename to driver/src/main/java/com/arangodb/async/internal/ArangoDatabaseAsyncImpl.java diff --git a/src/main/java/com/arangodb/async/internal/ArangoEdgeCollectionAsyncImpl.java b/driver/src/main/java/com/arangodb/async/internal/ArangoEdgeCollectionAsyncImpl.java similarity index 100% rename from src/main/java/com/arangodb/async/internal/ArangoEdgeCollectionAsyncImpl.java rename to driver/src/main/java/com/arangodb/async/internal/ArangoEdgeCollectionAsyncImpl.java diff --git a/src/main/java/com/arangodb/async/internal/ArangoExecutorAsync.java b/driver/src/main/java/com/arangodb/async/internal/ArangoExecutorAsync.java similarity index 100% rename from src/main/java/com/arangodb/async/internal/ArangoExecutorAsync.java rename to driver/src/main/java/com/arangodb/async/internal/ArangoExecutorAsync.java diff --git a/src/main/java/com/arangodb/async/internal/ArangoGraphAsyncImpl.java b/driver/src/main/java/com/arangodb/async/internal/ArangoGraphAsyncImpl.java similarity index 100% rename from src/main/java/com/arangodb/async/internal/ArangoGraphAsyncImpl.java rename to driver/src/main/java/com/arangodb/async/internal/ArangoGraphAsyncImpl.java diff --git a/src/main/java/com/arangodb/async/internal/ArangoRouteAsyncImpl.java b/driver/src/main/java/com/arangodb/async/internal/ArangoRouteAsyncImpl.java similarity index 100% rename from src/main/java/com/arangodb/async/internal/ArangoRouteAsyncImpl.java rename to driver/src/main/java/com/arangodb/async/internal/ArangoRouteAsyncImpl.java diff --git a/src/main/java/com/arangodb/async/internal/ArangoSearchAsyncImpl.java b/driver/src/main/java/com/arangodb/async/internal/ArangoSearchAsyncImpl.java similarity index 100% rename from src/main/java/com/arangodb/async/internal/ArangoSearchAsyncImpl.java rename to driver/src/main/java/com/arangodb/async/internal/ArangoSearchAsyncImpl.java diff --git a/src/main/java/com/arangodb/async/internal/ArangoVertexCollectionAsyncImpl.java b/driver/src/main/java/com/arangodb/async/internal/ArangoVertexCollectionAsyncImpl.java similarity index 100% rename from src/main/java/com/arangodb/async/internal/ArangoVertexCollectionAsyncImpl.java rename to driver/src/main/java/com/arangodb/async/internal/ArangoVertexCollectionAsyncImpl.java diff --git a/src/main/java/com/arangodb/async/internal/ArangoViewAsyncImpl.java b/driver/src/main/java/com/arangodb/async/internal/ArangoViewAsyncImpl.java similarity index 100% rename from src/main/java/com/arangodb/async/internal/ArangoViewAsyncImpl.java rename to driver/src/main/java/com/arangodb/async/internal/ArangoViewAsyncImpl.java diff --git a/src/main/java/com/arangodb/async/internal/ExceptionUtil.java b/driver/src/main/java/com/arangodb/async/internal/ExceptionUtil.java similarity index 100% rename from src/main/java/com/arangodb/async/internal/ExceptionUtil.java rename to driver/src/main/java/com/arangodb/async/internal/ExceptionUtil.java diff --git a/src/main/java/com/arangodb/async/internal/SearchAliasAsyncImpl.java b/driver/src/main/java/com/arangodb/async/internal/SearchAliasAsyncImpl.java similarity index 100% rename from src/main/java/com/arangodb/async/internal/SearchAliasAsyncImpl.java rename to driver/src/main/java/com/arangodb/async/internal/SearchAliasAsyncImpl.java diff --git a/src/main/java/com/arangodb/async/internal/utils/CompletableFutureUtils.java b/driver/src/main/java/com/arangodb/async/internal/utils/CompletableFutureUtils.java similarity index 100% rename from src/main/java/com/arangodb/async/internal/utils/CompletableFutureUtils.java rename to driver/src/main/java/com/arangodb/async/internal/utils/CompletableFutureUtils.java diff --git a/src/main/java/com/arangodb/async/internal/velocystream/VstCommunicationAsync.java b/driver/src/main/java/com/arangodb/async/internal/velocystream/VstCommunicationAsync.java similarity index 100% rename from src/main/java/com/arangodb/async/internal/velocystream/VstCommunicationAsync.java rename to driver/src/main/java/com/arangodb/async/internal/velocystream/VstCommunicationAsync.java diff --git a/src/main/java/com/arangodb/async/internal/velocystream/VstConnectionAsync.java b/driver/src/main/java/com/arangodb/async/internal/velocystream/VstConnectionAsync.java similarity index 100% rename from src/main/java/com/arangodb/async/internal/velocystream/VstConnectionAsync.java rename to driver/src/main/java/com/arangodb/async/internal/velocystream/VstConnectionAsync.java diff --git a/src/main/java/com/arangodb/async/internal/velocystream/VstConnectionFactoryAsync.java b/driver/src/main/java/com/arangodb/async/internal/velocystream/VstConnectionFactoryAsync.java similarity index 100% rename from src/main/java/com/arangodb/async/internal/velocystream/VstConnectionFactoryAsync.java rename to driver/src/main/java/com/arangodb/async/internal/velocystream/VstConnectionFactoryAsync.java diff --git a/src/main/java/com/arangodb/entity/AbstractBaseDocument.java b/driver/src/main/java/com/arangodb/entity/AbstractBaseDocument.java similarity index 100% rename from src/main/java/com/arangodb/entity/AbstractBaseDocument.java rename to driver/src/main/java/com/arangodb/entity/AbstractBaseDocument.java diff --git a/src/main/java/com/arangodb/entity/AqlExecutionExplainEntity.java b/driver/src/main/java/com/arangodb/entity/AqlExecutionExplainEntity.java similarity index 100% rename from src/main/java/com/arangodb/entity/AqlExecutionExplainEntity.java rename to driver/src/main/java/com/arangodb/entity/AqlExecutionExplainEntity.java diff --git a/src/main/java/com/arangodb/entity/AqlFunctionEntity.java b/driver/src/main/java/com/arangodb/entity/AqlFunctionEntity.java similarity index 100% rename from src/main/java/com/arangodb/entity/AqlFunctionEntity.java rename to driver/src/main/java/com/arangodb/entity/AqlFunctionEntity.java diff --git a/src/main/java/com/arangodb/entity/AqlParseEntity.java b/driver/src/main/java/com/arangodb/entity/AqlParseEntity.java similarity index 100% rename from src/main/java/com/arangodb/entity/AqlParseEntity.java rename to driver/src/main/java/com/arangodb/entity/AqlParseEntity.java diff --git a/src/main/java/com/arangodb/entity/ArangoDBEngine.java b/driver/src/main/java/com/arangodb/entity/ArangoDBEngine.java similarity index 100% rename from src/main/java/com/arangodb/entity/ArangoDBEngine.java rename to driver/src/main/java/com/arangodb/entity/ArangoDBEngine.java diff --git a/src/main/java/com/arangodb/entity/ArangoDBVersion.java b/driver/src/main/java/com/arangodb/entity/ArangoDBVersion.java similarity index 100% rename from src/main/java/com/arangodb/entity/ArangoDBVersion.java rename to driver/src/main/java/com/arangodb/entity/ArangoDBVersion.java diff --git a/src/main/java/com/arangodb/entity/BaseDocument.java b/driver/src/main/java/com/arangodb/entity/BaseDocument.java similarity index 96% rename from src/main/java/com/arangodb/entity/BaseDocument.java rename to driver/src/main/java/com/arangodb/entity/BaseDocument.java index 62207db9e..db6de1d47 100644 --- a/src/main/java/com/arangodb/entity/BaseDocument.java +++ b/driver/src/main/java/com/arangodb/entity/BaseDocument.java @@ -1,51 +1,51 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.entity; - -import java.io.Serializable; -import java.util.Map; - -/** - * @author Mark Vollmary - * @author Michele Rastelli - */ -public final class BaseDocument extends AbstractBaseDocument implements Serializable { - - private static final long serialVersionUID = 733033350470L; - - public BaseDocument() { - super(); - } - - public BaseDocument(final String key) { - super(key); - } - - public BaseDocument(final Map properties) { - super(properties); - } - - @Override - public String toString() { - return "BaseDocument" + super.toString(); - } - -} +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed 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. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.entity; + +import java.io.Serializable; +import java.util.Map; + +/** + * @author Mark Vollmary + * @author Michele Rastelli + */ +public final class BaseDocument extends AbstractBaseDocument implements Serializable { + + private static final long serialVersionUID = 733033350470L; + + public BaseDocument() { + super(); + } + + public BaseDocument(final String key) { + super(key); + } + + public BaseDocument(final Map properties) { + super(properties); + } + + @Override + public String toString() { + return "BaseDocument" + super.toString(); + } + +} diff --git a/src/main/java/com/arangodb/entity/BaseEdgeDocument.java b/driver/src/main/java/com/arangodb/entity/BaseEdgeDocument.java similarity index 96% rename from src/main/java/com/arangodb/entity/BaseEdgeDocument.java rename to driver/src/main/java/com/arangodb/entity/BaseEdgeDocument.java index 625fcaf1d..28b582447 100644 --- a/src/main/java/com/arangodb/entity/BaseEdgeDocument.java +++ b/driver/src/main/java/com/arangodb/entity/BaseEdgeDocument.java @@ -1,93 +1,93 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.entity; - -import com.arangodb.internal.DocumentFields; -import com.fasterxml.jackson.annotation.JsonIgnore; - -import java.io.Serializable; -import java.util.Map; - -/** - * @author Mark Vollmary - * @author Michele Rastelli - */ -public final class BaseEdgeDocument extends AbstractBaseDocument implements Serializable { - - private static final long serialVersionUID = 356629614444L; - - private static final String[] META_PROPS = new String[]{ - DocumentFields.ID, - DocumentFields.KEY, - DocumentFields.REV, - DocumentFields.FROM, - DocumentFields.TO - }; - - public BaseEdgeDocument() { - super(); - } - - public BaseEdgeDocument(final String from, final String to) { - super(); - setFrom(from); - setTo(to); - } - - public BaseEdgeDocument(final String key, final String from, final String to) { - super(key); - setFrom(from); - setTo(to); - } - - public BaseEdgeDocument(final Map properties) { - super(properties); - } - - @JsonIgnore - public String getFrom() { - return (String) getAttribute(DocumentFields.FROM); - } - - public void setFrom(final String from) { - addAttribute(DocumentFields.FROM, from); - } - - @JsonIgnore - public String getTo() { - return (String) getAttribute(DocumentFields.TO); - } - - public void setTo(final String to) { - addAttribute(DocumentFields.TO, to); - } - - @Override - protected String[] getMetaProps() { - return META_PROPS; - } - - @Override - public String toString() { - return "BaseEdgeDocument" + super.toString(); - } - -} +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed 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. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.entity; + +import com.arangodb.internal.DocumentFields; +import com.fasterxml.jackson.annotation.JsonIgnore; + +import java.io.Serializable; +import java.util.Map; + +/** + * @author Mark Vollmary + * @author Michele Rastelli + */ +public final class BaseEdgeDocument extends AbstractBaseDocument implements Serializable { + + private static final long serialVersionUID = 356629614444L; + + private static final String[] META_PROPS = new String[]{ + DocumentFields.ID, + DocumentFields.KEY, + DocumentFields.REV, + DocumentFields.FROM, + DocumentFields.TO + }; + + public BaseEdgeDocument() { + super(); + } + + public BaseEdgeDocument(final String from, final String to) { + super(); + setFrom(from); + setTo(to); + } + + public BaseEdgeDocument(final String key, final String from, final String to) { + super(key); + setFrom(from); + setTo(to); + } + + public BaseEdgeDocument(final Map properties) { + super(properties); + } + + @JsonIgnore + public String getFrom() { + return (String) getAttribute(DocumentFields.FROM); + } + + public void setFrom(final String from) { + addAttribute(DocumentFields.FROM, from); + } + + @JsonIgnore + public String getTo() { + return (String) getAttribute(DocumentFields.TO); + } + + public void setTo(final String to) { + addAttribute(DocumentFields.TO, to); + } + + @Override + protected String[] getMetaProps() { + return META_PROPS; + } + + @Override + public String toString() { + return "BaseEdgeDocument" + super.toString(); + } + +} diff --git a/src/main/java/com/arangodb/entity/CollectionEntity.java b/driver/src/main/java/com/arangodb/entity/CollectionEntity.java similarity index 100% rename from src/main/java/com/arangodb/entity/CollectionEntity.java rename to driver/src/main/java/com/arangodb/entity/CollectionEntity.java diff --git a/src/main/java/com/arangodb/entity/CollectionPropertiesEntity.java b/driver/src/main/java/com/arangodb/entity/CollectionPropertiesEntity.java similarity index 100% rename from src/main/java/com/arangodb/entity/CollectionPropertiesEntity.java rename to driver/src/main/java/com/arangodb/entity/CollectionPropertiesEntity.java diff --git a/src/main/java/com/arangodb/entity/CollectionRevisionEntity.java b/driver/src/main/java/com/arangodb/entity/CollectionRevisionEntity.java similarity index 96% rename from src/main/java/com/arangodb/entity/CollectionRevisionEntity.java rename to driver/src/main/java/com/arangodb/entity/CollectionRevisionEntity.java index a65db6d7a..645849eba 100644 --- a/src/main/java/com/arangodb/entity/CollectionRevisionEntity.java +++ b/driver/src/main/java/com/arangodb/entity/CollectionRevisionEntity.java @@ -1,36 +1,36 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.entity; - -/** - * @author Mark Vollmary - * @see API - * Documentation - */ -public final class CollectionRevisionEntity extends CollectionEntity { - - private String revision; - - public String getRevision() { - return revision; - } - -} +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed 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. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.entity; + +/** + * @author Mark Vollmary + * @see API + * Documentation + */ +public final class CollectionRevisionEntity extends CollectionEntity { + + private String revision; + + public String getRevision() { + return revision; + } + +} diff --git a/src/main/java/com/arangodb/entity/CollectionStatus.java b/driver/src/main/java/com/arangodb/entity/CollectionStatus.java similarity index 100% rename from src/main/java/com/arangodb/entity/CollectionStatus.java rename to driver/src/main/java/com/arangodb/entity/CollectionStatus.java diff --git a/src/main/java/com/arangodb/entity/CollectionType.java b/driver/src/main/java/com/arangodb/entity/CollectionType.java similarity index 100% rename from src/main/java/com/arangodb/entity/CollectionType.java rename to driver/src/main/java/com/arangodb/entity/CollectionType.java diff --git a/src/main/java/com/arangodb/entity/CursorWarning.java b/driver/src/main/java/com/arangodb/entity/CursorWarning.java similarity index 100% rename from src/main/java/com/arangodb/entity/CursorWarning.java rename to driver/src/main/java/com/arangodb/entity/CursorWarning.java diff --git a/src/main/java/com/arangodb/entity/DatabaseEntity.java b/driver/src/main/java/com/arangodb/entity/DatabaseEntity.java similarity index 100% rename from src/main/java/com/arangodb/entity/DatabaseEntity.java rename to driver/src/main/java/com/arangodb/entity/DatabaseEntity.java diff --git a/src/main/java/com/arangodb/entity/DocumentCreateEntity.java b/driver/src/main/java/com/arangodb/entity/DocumentCreateEntity.java similarity index 100% rename from src/main/java/com/arangodb/entity/DocumentCreateEntity.java rename to driver/src/main/java/com/arangodb/entity/DocumentCreateEntity.java diff --git a/src/main/java/com/arangodb/entity/DocumentDeleteEntity.java b/driver/src/main/java/com/arangodb/entity/DocumentDeleteEntity.java similarity index 96% rename from src/main/java/com/arangodb/entity/DocumentDeleteEntity.java rename to driver/src/main/java/com/arangodb/entity/DocumentDeleteEntity.java index 77d12d8b6..26af4f671 100644 --- a/src/main/java/com/arangodb/entity/DocumentDeleteEntity.java +++ b/driver/src/main/java/com/arangodb/entity/DocumentDeleteEntity.java @@ -1,50 +1,50 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.entity; - -import com.arangodb.internal.serde.UserData; - -/** - * @author Mark Vollmary - * @see API - * Documentation - */ -public final class DocumentDeleteEntity extends DocumentEntity { - - private T oldDocument; - - public DocumentDeleteEntity() { - super(); - } - - /** - * @return If the query parameter returnOld is true, then the complete previous revision of the document is - * returned. - */ - public T getOld() { - return oldDocument; - } - - @UserData - public void setOld(final T oldDocument) { - this.oldDocument = oldDocument; - } -} +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed 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. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.entity; + +import com.arangodb.internal.serde.UserData; + +/** + * @author Mark Vollmary + * @see API + * Documentation + */ +public final class DocumentDeleteEntity extends DocumentEntity { + + private T oldDocument; + + public DocumentDeleteEntity() { + super(); + } + + /** + * @return If the query parameter returnOld is true, then the complete previous revision of the document is + * returned. + */ + public T getOld() { + return oldDocument; + } + + @UserData + public void setOld(final T oldDocument) { + this.oldDocument = oldDocument; + } +} diff --git a/src/main/java/com/arangodb/entity/DocumentEntity.java b/driver/src/main/java/com/arangodb/entity/DocumentEntity.java similarity index 100% rename from src/main/java/com/arangodb/entity/DocumentEntity.java rename to driver/src/main/java/com/arangodb/entity/DocumentEntity.java diff --git a/src/main/java/com/arangodb/entity/DocumentImportEntity.java b/driver/src/main/java/com/arangodb/entity/DocumentImportEntity.java similarity index 100% rename from src/main/java/com/arangodb/entity/DocumentImportEntity.java rename to driver/src/main/java/com/arangodb/entity/DocumentImportEntity.java diff --git a/src/main/java/com/arangodb/entity/DocumentUpdateEntity.java b/driver/src/main/java/com/arangodb/entity/DocumentUpdateEntity.java similarity index 96% rename from src/main/java/com/arangodb/entity/DocumentUpdateEntity.java rename to driver/src/main/java/com/arangodb/entity/DocumentUpdateEntity.java index c64d62d38..0fa122454 100644 --- a/src/main/java/com/arangodb/entity/DocumentUpdateEntity.java +++ b/driver/src/main/java/com/arangodb/entity/DocumentUpdateEntity.java @@ -1,72 +1,72 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.entity; - -import com.arangodb.internal.serde.UserData; -import com.fasterxml.jackson.annotation.JsonProperty; - -/** - * @param - * @author Mark Vollmary - * @see API - * Documentation - */ -public final class DocumentUpdateEntity extends DocumentEntity { - - @JsonProperty("_oldRev") - private String oldRev; - private T newDocument; - private T oldDocument; - - public DocumentUpdateEntity() { - super(); - } - - public String getOldRev() { - return oldRev; - } - - /** - * @return If the query parameter returnNew is true, then the complete new document is returned. - */ - public T getNew() { - return newDocument; - } - - @UserData - public void setNew(final T newDocument) { - this.newDocument = newDocument; - } - - /** - * @return If the query parameter returnOld is true, then the complete previous revision of the document is - * returned. - */ - public T getOld() { - return oldDocument; - } - - @UserData - public void setOld(final T oldDocument) { - this.oldDocument = oldDocument; - } - -} +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed 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. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.entity; + +import com.arangodb.internal.serde.UserData; +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * @param + * @author Mark Vollmary + * @see API + * Documentation + */ +public final class DocumentUpdateEntity extends DocumentEntity { + + @JsonProperty("_oldRev") + private String oldRev; + private T newDocument; + private T oldDocument; + + public DocumentUpdateEntity() { + super(); + } + + public String getOldRev() { + return oldRev; + } + + /** + * @return If the query parameter returnNew is true, then the complete new document is returned. + */ + public T getNew() { + return newDocument; + } + + @UserData + public void setNew(final T newDocument) { + this.newDocument = newDocument; + } + + /** + * @return If the query parameter returnOld is true, then the complete previous revision of the document is + * returned. + */ + public T getOld() { + return oldDocument; + } + + @UserData + public void setOld(final T oldDocument) { + this.oldDocument = oldDocument; + } + +} diff --git a/src/main/java/com/arangodb/entity/EdgeDefinition.java b/driver/src/main/java/com/arangodb/entity/EdgeDefinition.java similarity index 96% rename from src/main/java/com/arangodb/entity/EdgeDefinition.java rename to driver/src/main/java/com/arangodb/entity/EdgeDefinition.java index a450726b0..45b76c795 100644 --- a/src/main/java/com/arangodb/entity/EdgeDefinition.java +++ b/driver/src/main/java/com/arangodb/entity/EdgeDefinition.java @@ -1,92 +1,92 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.entity; - -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; - -/** - * @author Mark Vollmary - * @see API Documentation - */ -public final class EdgeDefinition { - - private final Options options = new Options(); - private String collection; - private Collection from; - private Collection to; - - public String getCollection() { - return collection; - } - - public EdgeDefinition collection(final String collection) { - this.collection = collection; - return this; - } - - public Collection getFrom() { - return from; - } - - public EdgeDefinition from(final String... from) { - this.from = Arrays.asList(from); - return this; - } - - public Collection getTo() { - return to; - } - - public EdgeDefinition to(final String... to) { - this.to = Arrays.asList(to); - return this; - } - - public Collection getSatellites() { - return options.satellites; - } - - public Options getOptions() { - return options; - } - - /** - * @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.satellites = Arrays.asList(satellites); - return this; - } - - public static final class Options { - private Collection satellites = Collections.emptyList(); - - public Collection getSatellites() { - return satellites; - } - } -} +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed 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. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.entity; + +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; + +/** + * @author Mark Vollmary + * @see API Documentation + */ +public final class EdgeDefinition { + + private final Options options = new Options(); + private String collection; + private Collection from; + private Collection to; + + public String getCollection() { + return collection; + } + + public EdgeDefinition collection(final String collection) { + this.collection = collection; + return this; + } + + public Collection getFrom() { + return from; + } + + public EdgeDefinition from(final String... from) { + this.from = Arrays.asList(from); + return this; + } + + public Collection getTo() { + return to; + } + + public EdgeDefinition to(final String... to) { + this.to = Arrays.asList(to); + return this; + } + + public Collection getSatellites() { + return options.satellites; + } + + public Options getOptions() { + return options; + } + + /** + * @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.satellites = Arrays.asList(satellites); + return this; + } + + public static final class Options { + private Collection satellites = Collections.emptyList(); + + public Collection getSatellites() { + return satellites; + } + } +} diff --git a/src/main/java/com/arangodb/entity/EdgeEntity.java b/driver/src/main/java/com/arangodb/entity/EdgeEntity.java similarity index 96% rename from src/main/java/com/arangodb/entity/EdgeEntity.java rename to driver/src/main/java/com/arangodb/entity/EdgeEntity.java index 48107a1e1..39d9017db 100644 --- a/src/main/java/com/arangodb/entity/EdgeEntity.java +++ b/driver/src/main/java/com/arangodb/entity/EdgeEntity.java @@ -1,32 +1,32 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.entity; - -/** - * @author Mark Vollmary - */ -public final class EdgeEntity extends DocumentEntity { - - public EdgeEntity() { - super(); - } - -} +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed 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. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.entity; + +/** + * @author Mark Vollmary + */ +public final class EdgeEntity extends DocumentEntity { + + public EdgeEntity() { + super(); + } + +} diff --git a/src/main/java/com/arangodb/entity/EdgeUpdateEntity.java b/driver/src/main/java/com/arangodb/entity/EdgeUpdateEntity.java similarity index 96% rename from src/main/java/com/arangodb/entity/EdgeUpdateEntity.java rename to driver/src/main/java/com/arangodb/entity/EdgeUpdateEntity.java index 67b72e76b..495cf229d 100644 --- a/src/main/java/com/arangodb/entity/EdgeUpdateEntity.java +++ b/driver/src/main/java/com/arangodb/entity/EdgeUpdateEntity.java @@ -1,42 +1,42 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.entity; - -import com.fasterxml.jackson.annotation.JsonProperty; - -/** - * @author Mark Vollmary - * @see API Documentation - */ -public final class EdgeUpdateEntity extends DocumentEntity { - - @JsonProperty("_oldRev") - private String oldRev; - - public EdgeUpdateEntity() { - super(); - } - - public String getOldRev() { - return oldRev; - } - -} +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed 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. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.entity; + +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * @author Mark Vollmary + * @see API Documentation + */ +public final class EdgeUpdateEntity extends DocumentEntity { + + @JsonProperty("_oldRev") + private String oldRev; + + public EdgeUpdateEntity() { + super(); + } + + public String getOldRev() { + return oldRev; + } + +} diff --git a/src/main/java/com/arangodb/entity/ErrorEntity.java b/driver/src/main/java/com/arangodb/entity/ErrorEntity.java similarity index 100% rename from src/main/java/com/arangodb/entity/ErrorEntity.java rename to driver/src/main/java/com/arangodb/entity/ErrorEntity.java diff --git a/src/main/java/com/arangodb/entity/From.java b/driver/src/main/java/com/arangodb/entity/From.java similarity index 100% rename from src/main/java/com/arangodb/entity/From.java rename to driver/src/main/java/com/arangodb/entity/From.java diff --git a/src/main/java/com/arangodb/entity/GraphEntity.java b/driver/src/main/java/com/arangodb/entity/GraphEntity.java similarity index 100% rename from src/main/java/com/arangodb/entity/GraphEntity.java rename to driver/src/main/java/com/arangodb/entity/GraphEntity.java diff --git a/src/main/java/com/arangodb/entity/Id.java b/driver/src/main/java/com/arangodb/entity/Id.java similarity index 100% rename from src/main/java/com/arangodb/entity/Id.java rename to driver/src/main/java/com/arangodb/entity/Id.java diff --git a/src/main/java/com/arangodb/entity/IndexEntity.java b/driver/src/main/java/com/arangodb/entity/IndexEntity.java similarity index 100% rename from src/main/java/com/arangodb/entity/IndexEntity.java rename to driver/src/main/java/com/arangodb/entity/IndexEntity.java diff --git a/src/main/java/com/arangodb/entity/IndexType.java b/driver/src/main/java/com/arangodb/entity/IndexType.java similarity index 94% rename from src/main/java/com/arangodb/entity/IndexType.java rename to driver/src/main/java/com/arangodb/entity/IndexType.java index 3fbd025c3..d3303b5f5 100644 --- a/src/main/java/com/arangodb/entity/IndexType.java +++ b/driver/src/main/java/com/arangodb/entity/IndexType.java @@ -1,59 +1,59 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.entity; - -/** - * @author Mark Vollmary - * @author Heiko Kernbach - */ -public enum IndexType { - - primary, - - hash, - - skiplist, - - persistent, - - geo, - - geo1, - - geo2, - - /** - * @deprecated since ArangoDB 3.10, use ArangoSearch or Inverted indexes instead. - */ - @Deprecated - fulltext, - - edge, - - ttl, - - zkd, - - /** - * @since ArangoDB 3.10 - */ - inverted -} +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed 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. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.entity; + +/** + * @author Mark Vollmary + * @author Heiko Kernbach + */ +public enum IndexType { + + primary, + + hash, + + skiplist, + + persistent, + + geo, + + geo1, + + geo2, + + /** + * @deprecated since ArangoDB 3.10, use ArangoSearch or Inverted indexes instead. + */ + @Deprecated + fulltext, + + edge, + + ttl, + + zkd, + + /** + * @since ArangoDB 3.10 + */ + inverted +} diff --git a/src/main/java/com/arangodb/entity/InvertedIndexEntity.java b/driver/src/main/java/com/arangodb/entity/InvertedIndexEntity.java similarity index 100% rename from src/main/java/com/arangodb/entity/InvertedIndexEntity.java rename to driver/src/main/java/com/arangodb/entity/InvertedIndexEntity.java diff --git a/src/main/java/com/arangodb/entity/InvertedIndexField.java b/driver/src/main/java/com/arangodb/entity/InvertedIndexField.java similarity index 100% rename from src/main/java/com/arangodb/entity/InvertedIndexField.java rename to driver/src/main/java/com/arangodb/entity/InvertedIndexField.java diff --git a/src/main/java/com/arangodb/entity/InvertedIndexPrimarySort.java b/driver/src/main/java/com/arangodb/entity/InvertedIndexPrimarySort.java similarity index 100% rename from src/main/java/com/arangodb/entity/InvertedIndexPrimarySort.java rename to driver/src/main/java/com/arangodb/entity/InvertedIndexPrimarySort.java diff --git a/src/main/java/com/arangodb/entity/Key.java b/driver/src/main/java/com/arangodb/entity/Key.java similarity index 100% rename from src/main/java/com/arangodb/entity/Key.java rename to driver/src/main/java/com/arangodb/entity/Key.java diff --git a/src/main/java/com/arangodb/entity/KeyOptions.java b/driver/src/main/java/com/arangodb/entity/KeyOptions.java similarity index 96% rename from src/main/java/com/arangodb/entity/KeyOptions.java rename to driver/src/main/java/com/arangodb/entity/KeyOptions.java index 65bd435e5..7206c9dbb 100644 --- a/src/main/java/com/arangodb/entity/KeyOptions.java +++ b/driver/src/main/java/com/arangodb/entity/KeyOptions.java @@ -1,77 +1,77 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.entity; - -/** - * @author Mark Vollmary - */ -public final class KeyOptions { - - private Boolean allowUserKeys; - private KeyType type; - private Integer increment; - private Integer offset; - - public KeyOptions() { - super(); - } - - public KeyOptions(final Boolean allowUserKeys, final KeyType type, final Integer increment, final Integer offset) { - super(); - this.allowUserKeys = allowUserKeys; - this.type = type; - this.increment = increment; - this.offset = offset; - } - - public Boolean getAllowUserKeys() { - return allowUserKeys; - } - - public void setAllowUserKeys(final Boolean allowUserKeys) { - this.allowUserKeys = allowUserKeys; - } - - public KeyType getType() { - return type; - } - - public void setType(final KeyType type) { - this.type = type; - } - - public Integer getIncrement() { - return increment; - } - - public void setIncrement(final Integer increment) { - this.increment = increment; - } - - public Integer getOffset() { - return offset; - } - - public void setOffset(final Integer offset) { - this.offset = offset; - } - -} +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed 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. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.entity; + +/** + * @author Mark Vollmary + */ +public final class KeyOptions { + + private Boolean allowUserKeys; + private KeyType type; + private Integer increment; + private Integer offset; + + public KeyOptions() { + super(); + } + + public KeyOptions(final Boolean allowUserKeys, final KeyType type, final Integer increment, final Integer offset) { + super(); + this.allowUserKeys = allowUserKeys; + this.type = type; + this.increment = increment; + this.offset = offset; + } + + public Boolean getAllowUserKeys() { + return allowUserKeys; + } + + public void setAllowUserKeys(final Boolean allowUserKeys) { + this.allowUserKeys = allowUserKeys; + } + + public KeyType getType() { + return type; + } + + public void setType(final KeyType type) { + this.type = type; + } + + public Integer getIncrement() { + return increment; + } + + public void setIncrement(final Integer increment) { + this.increment = increment; + } + + public Integer getOffset() { + return offset; + } + + public void setOffset(final Integer offset) { + this.offset = offset; + } + +} diff --git a/src/main/java/com/arangodb/entity/KeyType.java b/driver/src/main/java/com/arangodb/entity/KeyType.java similarity index 96% rename from src/main/java/com/arangodb/entity/KeyType.java rename to driver/src/main/java/com/arangodb/entity/KeyType.java index 215ec6d0f..4ac2da4f3 100644 --- a/src/main/java/com/arangodb/entity/KeyType.java +++ b/driver/src/main/java/com/arangodb/entity/KeyType.java @@ -1,28 +1,28 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.entity; - -/** - * @author Mark Vollmary - */ -public enum KeyType { - traditional, autoincrement, uuid, padded -} +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed 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. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.entity; + +/** + * @author Mark Vollmary + */ +public enum KeyType { + traditional, autoincrement, uuid, padded +} diff --git a/src/main/java/com/arangodb/entity/License.java b/driver/src/main/java/com/arangodb/entity/License.java similarity index 100% rename from src/main/java/com/arangodb/entity/License.java rename to driver/src/main/java/com/arangodb/entity/License.java diff --git a/src/main/java/com/arangodb/entity/LoadBalancingStrategy.java b/driver/src/main/java/com/arangodb/entity/LoadBalancingStrategy.java similarity index 96% rename from src/main/java/com/arangodb/entity/LoadBalancingStrategy.java rename to driver/src/main/java/com/arangodb/entity/LoadBalancingStrategy.java index 9508dff48..525744fb3 100644 --- a/src/main/java/com/arangodb/entity/LoadBalancingStrategy.java +++ b/driver/src/main/java/com/arangodb/entity/LoadBalancingStrategy.java @@ -1,28 +1,28 @@ -/* - * DISCLAIMER - * - * Copyright 2017 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.entity; - -/** - * @author Mark Vollmary - */ -public enum LoadBalancingStrategy { - NONE, ROUND_ROBIN, ONE_RANDOM -} +/* + * DISCLAIMER + * + * Copyright 2017 ArangoDB GmbH, Cologne, Germany + * + * Licensed 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. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.entity; + +/** + * @author Mark Vollmary + */ +public enum LoadBalancingStrategy { + NONE, ROUND_ROBIN, ONE_RANDOM +} diff --git a/src/main/java/com/arangodb/entity/LogEntriesEntity.java b/driver/src/main/java/com/arangodb/entity/LogEntriesEntity.java similarity index 100% rename from src/main/java/com/arangodb/entity/LogEntriesEntity.java rename to driver/src/main/java/com/arangodb/entity/LogEntriesEntity.java diff --git a/src/main/java/com/arangodb/entity/LogLevel.java b/driver/src/main/java/com/arangodb/entity/LogLevel.java similarity index 100% rename from src/main/java/com/arangodb/entity/LogLevel.java rename to driver/src/main/java/com/arangodb/entity/LogLevel.java diff --git a/src/main/java/com/arangodb/entity/LogLevelEntity.java b/driver/src/main/java/com/arangodb/entity/LogLevelEntity.java similarity index 100% rename from src/main/java/com/arangodb/entity/LogLevelEntity.java rename to driver/src/main/java/com/arangodb/entity/LogLevelEntity.java diff --git a/src/main/java/com/arangodb/entity/MetaAware.java b/driver/src/main/java/com/arangodb/entity/MetaAware.java similarity index 100% rename from src/main/java/com/arangodb/entity/MetaAware.java rename to driver/src/main/java/com/arangodb/entity/MetaAware.java diff --git a/src/main/java/com/arangodb/entity/MultiDocumentEntity.java b/driver/src/main/java/com/arangodb/entity/MultiDocumentEntity.java similarity index 100% rename from src/main/java/com/arangodb/entity/MultiDocumentEntity.java rename to driver/src/main/java/com/arangodb/entity/MultiDocumentEntity.java diff --git a/src/main/java/com/arangodb/entity/Permissions.java b/driver/src/main/java/com/arangodb/entity/Permissions.java similarity index 100% rename from src/main/java/com/arangodb/entity/Permissions.java rename to driver/src/main/java/com/arangodb/entity/Permissions.java diff --git a/src/main/java/com/arangodb/entity/QueryCachePropertiesEntity.java b/driver/src/main/java/com/arangodb/entity/QueryCachePropertiesEntity.java similarity index 100% rename from src/main/java/com/arangodb/entity/QueryCachePropertiesEntity.java rename to driver/src/main/java/com/arangodb/entity/QueryCachePropertiesEntity.java diff --git a/src/main/java/com/arangodb/entity/QueryEntity.java b/driver/src/main/java/com/arangodb/entity/QueryEntity.java similarity index 100% rename from src/main/java/com/arangodb/entity/QueryEntity.java rename to driver/src/main/java/com/arangodb/entity/QueryEntity.java diff --git a/src/main/java/com/arangodb/entity/QueryExecutionState.java b/driver/src/main/java/com/arangodb/entity/QueryExecutionState.java similarity index 95% rename from src/main/java/com/arangodb/entity/QueryExecutionState.java rename to driver/src/main/java/com/arangodb/entity/QueryExecutionState.java index 987044880..aa56f92e9 100644 --- a/src/main/java/com/arangodb/entity/QueryExecutionState.java +++ b/driver/src/main/java/com/arangodb/entity/QueryExecutionState.java @@ -1,61 +1,61 @@ -/* - * DISCLAIMER - * - * Copyright 2018 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.entity; - -import com.fasterxml.jackson.annotation.JsonProperty; - -/** - * @author Mark Vollmary - */ -public enum QueryExecutionState { - @JsonProperty("initializing") - INITIALIZING, - - @JsonProperty("parsing") - PARSING, - - @JsonProperty("optimizing ast") - OPTIMIZING_AST, - - @JsonProperty("loading collections") - LOADING_COLLECTIONS, - - @JsonProperty("instantiating plan") - INSTANTIATING_PLAN, - - @JsonProperty("optimizing plan") - OPTIMIZING_PLAN, - - @JsonProperty("executing") - EXECUTING, - - @JsonProperty("finalizing") - FINALIZING, - - @JsonProperty("finished") - FINISHED, - - @JsonProperty("killed") - KILLED, - - @JsonProperty("invalid") - INVALID -} +/* + * DISCLAIMER + * + * Copyright 2018 ArangoDB GmbH, Cologne, Germany + * + * Licensed 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. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.entity; + +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * @author Mark Vollmary + */ +public enum QueryExecutionState { + @JsonProperty("initializing") + INITIALIZING, + + @JsonProperty("parsing") + PARSING, + + @JsonProperty("optimizing ast") + OPTIMIZING_AST, + + @JsonProperty("loading collections") + LOADING_COLLECTIONS, + + @JsonProperty("instantiating plan") + INSTANTIATING_PLAN, + + @JsonProperty("optimizing plan") + OPTIMIZING_PLAN, + + @JsonProperty("executing") + EXECUTING, + + @JsonProperty("finalizing") + FINALIZING, + + @JsonProperty("finished") + FINISHED, + + @JsonProperty("killed") + KILLED, + + @JsonProperty("invalid") + INVALID +} diff --git a/src/main/java/com/arangodb/entity/QueryOptimizerRule.java b/driver/src/main/java/com/arangodb/entity/QueryOptimizerRule.java similarity index 100% rename from src/main/java/com/arangodb/entity/QueryOptimizerRule.java rename to driver/src/main/java/com/arangodb/entity/QueryOptimizerRule.java diff --git a/src/main/java/com/arangodb/entity/QueryTrackingPropertiesEntity.java b/driver/src/main/java/com/arangodb/entity/QueryTrackingPropertiesEntity.java similarity index 100% rename from src/main/java/com/arangodb/entity/QueryTrackingPropertiesEntity.java rename to driver/src/main/java/com/arangodb/entity/QueryTrackingPropertiesEntity.java diff --git a/src/main/java/com/arangodb/entity/ReplicationFactor.java b/driver/src/main/java/com/arangodb/entity/ReplicationFactor.java similarity index 100% rename from src/main/java/com/arangodb/entity/ReplicationFactor.java rename to driver/src/main/java/com/arangodb/entity/ReplicationFactor.java diff --git a/src/main/java/com/arangodb/entity/Rev.java b/driver/src/main/java/com/arangodb/entity/Rev.java similarity index 100% rename from src/main/java/com/arangodb/entity/Rev.java rename to driver/src/main/java/com/arangodb/entity/Rev.java diff --git a/src/main/java/com/arangodb/entity/ServerMode.java b/driver/src/main/java/com/arangodb/entity/ServerMode.java similarity index 96% rename from src/main/java/com/arangodb/entity/ServerMode.java rename to driver/src/main/java/com/arangodb/entity/ServerMode.java index b7f95040c..4cb13610d 100644 --- a/src/main/java/com/arangodb/entity/ServerMode.java +++ b/driver/src/main/java/com/arangodb/entity/ServerMode.java @@ -1,28 +1,28 @@ -/* - * DISCLAIMER - * - * Copyright 2017 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.entity; - -/** - * @author Mark Vollmary - */ -public enum ServerMode { - DEFAULT, RESILIENT -} +/* + * DISCLAIMER + * + * Copyright 2017 ArangoDB GmbH, Cologne, Germany + * + * Licensed 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. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.entity; + +/** + * @author Mark Vollmary + */ +public enum ServerMode { + DEFAULT, RESILIENT +} diff --git a/src/main/java/com/arangodb/entity/ServerRole.java b/driver/src/main/java/com/arangodb/entity/ServerRole.java similarity index 96% rename from src/main/java/com/arangodb/entity/ServerRole.java rename to driver/src/main/java/com/arangodb/entity/ServerRole.java index 71e1b7473..a897651ff 100644 --- a/src/main/java/com/arangodb/entity/ServerRole.java +++ b/driver/src/main/java/com/arangodb/entity/ServerRole.java @@ -1,28 +1,28 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.entity; - -/** - * @author Mark Vollmary - */ -public enum ServerRole { - SINGLE, AGENT, COORDINATOR, PRIMARY, SECONDARY, UNDEFINED +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed 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. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.entity; + +/** + * @author Mark Vollmary + */ +public enum ServerRole { + SINGLE, AGENT, COORDINATOR, PRIMARY, SECONDARY, UNDEFINED } \ No newline at end of file diff --git a/src/main/java/com/arangodb/entity/ShardEntity.java b/driver/src/main/java/com/arangodb/entity/ShardEntity.java similarity index 100% rename from src/main/java/com/arangodb/entity/ShardEntity.java rename to driver/src/main/java/com/arangodb/entity/ShardEntity.java diff --git a/src/main/java/com/arangodb/entity/ShardingStrategy.java b/driver/src/main/java/com/arangodb/entity/ShardingStrategy.java similarity index 100% rename from src/main/java/com/arangodb/entity/ShardingStrategy.java rename to driver/src/main/java/com/arangodb/entity/ShardingStrategy.java diff --git a/src/main/java/com/arangodb/entity/StreamTransactionEntity.java b/driver/src/main/java/com/arangodb/entity/StreamTransactionEntity.java similarity index 100% rename from src/main/java/com/arangodb/entity/StreamTransactionEntity.java rename to driver/src/main/java/com/arangodb/entity/StreamTransactionEntity.java diff --git a/src/main/java/com/arangodb/entity/StreamTransactionStatus.java b/driver/src/main/java/com/arangodb/entity/StreamTransactionStatus.java similarity index 100% rename from src/main/java/com/arangodb/entity/StreamTransactionStatus.java rename to driver/src/main/java/com/arangodb/entity/StreamTransactionStatus.java diff --git a/src/main/java/com/arangodb/entity/To.java b/driver/src/main/java/com/arangodb/entity/To.java similarity index 100% rename from src/main/java/com/arangodb/entity/To.java rename to driver/src/main/java/com/arangodb/entity/To.java diff --git a/src/main/java/com/arangodb/entity/TransactionEntity.java b/driver/src/main/java/com/arangodb/entity/TransactionEntity.java similarity index 100% rename from src/main/java/com/arangodb/entity/TransactionEntity.java rename to driver/src/main/java/com/arangodb/entity/TransactionEntity.java diff --git a/src/main/java/com/arangodb/entity/UserEntity.java b/driver/src/main/java/com/arangodb/entity/UserEntity.java similarity index 100% rename from src/main/java/com/arangodb/entity/UserEntity.java rename to driver/src/main/java/com/arangodb/entity/UserEntity.java diff --git a/src/main/java/com/arangodb/entity/VertexEntity.java b/driver/src/main/java/com/arangodb/entity/VertexEntity.java similarity index 96% rename from src/main/java/com/arangodb/entity/VertexEntity.java rename to driver/src/main/java/com/arangodb/entity/VertexEntity.java index e8348336a..4dfb6a55a 100644 --- a/src/main/java/com/arangodb/entity/VertexEntity.java +++ b/driver/src/main/java/com/arangodb/entity/VertexEntity.java @@ -1,32 +1,32 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.entity; - -/** - * @author Mark Vollmary - */ -public final class VertexEntity extends DocumentEntity { - - public VertexEntity() { - super(); - } - -} +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed 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. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.entity; + +/** + * @author Mark Vollmary + */ +public final class VertexEntity extends DocumentEntity { + + public VertexEntity() { + super(); + } + +} diff --git a/src/main/java/com/arangodb/entity/VertexUpdateEntity.java b/driver/src/main/java/com/arangodb/entity/VertexUpdateEntity.java similarity index 96% rename from src/main/java/com/arangodb/entity/VertexUpdateEntity.java rename to driver/src/main/java/com/arangodb/entity/VertexUpdateEntity.java index c5e8f0ff2..ef19a4386 100644 --- a/src/main/java/com/arangodb/entity/VertexUpdateEntity.java +++ b/driver/src/main/java/com/arangodb/entity/VertexUpdateEntity.java @@ -1,41 +1,41 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.entity; - -import com.fasterxml.jackson.annotation.JsonProperty; - -/** - * @author Mark Vollmary - */ -public final class VertexUpdateEntity extends DocumentEntity { - - @JsonProperty("_oldRev") - private String oldRev; - - public VertexUpdateEntity() { - super(); - } - - public String getOldRev() { - return oldRev; - } - -} +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed 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. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.entity; + +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * @author Mark Vollmary + */ +public final class VertexUpdateEntity extends DocumentEntity { + + @JsonProperty("_oldRev") + private String oldRev; + + public VertexUpdateEntity() { + super(); + } + + public String getOldRev() { + return oldRev; + } + +} diff --git a/src/main/java/com/arangodb/entity/ViewEntity.java b/driver/src/main/java/com/arangodb/entity/ViewEntity.java similarity index 100% rename from src/main/java/com/arangodb/entity/ViewEntity.java rename to driver/src/main/java/com/arangodb/entity/ViewEntity.java diff --git a/src/main/java/com/arangodb/entity/ViewType.java b/driver/src/main/java/com/arangodb/entity/ViewType.java similarity index 100% rename from src/main/java/com/arangodb/entity/ViewType.java rename to driver/src/main/java/com/arangodb/entity/ViewType.java diff --git a/src/main/java/com/arangodb/entity/arangosearch/AnalyzerFeature.java b/driver/src/main/java/com/arangodb/entity/arangosearch/AnalyzerFeature.java similarity index 100% rename from src/main/java/com/arangodb/entity/arangosearch/AnalyzerFeature.java rename to driver/src/main/java/com/arangodb/entity/arangosearch/AnalyzerFeature.java diff --git a/src/main/java/com/arangodb/entity/arangosearch/AnalyzerType.java b/driver/src/main/java/com/arangodb/entity/arangosearch/AnalyzerType.java similarity index 100% rename from src/main/java/com/arangodb/entity/arangosearch/AnalyzerType.java rename to driver/src/main/java/com/arangodb/entity/arangosearch/AnalyzerType.java diff --git a/src/main/java/com/arangodb/entity/arangosearch/ArangoSearchCompression.java b/driver/src/main/java/com/arangodb/entity/arangosearch/ArangoSearchCompression.java similarity index 100% rename from src/main/java/com/arangodb/entity/arangosearch/ArangoSearchCompression.java rename to driver/src/main/java/com/arangodb/entity/arangosearch/ArangoSearchCompression.java diff --git a/src/main/java/com/arangodb/entity/arangosearch/ArangoSearchPropertiesEntity.java b/driver/src/main/java/com/arangodb/entity/arangosearch/ArangoSearchPropertiesEntity.java similarity index 100% rename from src/main/java/com/arangodb/entity/arangosearch/ArangoSearchPropertiesEntity.java rename to driver/src/main/java/com/arangodb/entity/arangosearch/ArangoSearchPropertiesEntity.java diff --git a/src/main/java/com/arangodb/entity/arangosearch/CollectionLink.java b/driver/src/main/java/com/arangodb/entity/arangosearch/CollectionLink.java similarity index 100% rename from src/main/java/com/arangodb/entity/arangosearch/CollectionLink.java rename to driver/src/main/java/com/arangodb/entity/arangosearch/CollectionLink.java diff --git a/src/main/java/com/arangodb/entity/arangosearch/ConsolidationPolicy.java b/driver/src/main/java/com/arangodb/entity/arangosearch/ConsolidationPolicy.java similarity index 100% rename from src/main/java/com/arangodb/entity/arangosearch/ConsolidationPolicy.java rename to driver/src/main/java/com/arangodb/entity/arangosearch/ConsolidationPolicy.java diff --git a/src/main/java/com/arangodb/entity/arangosearch/ConsolidationType.java b/driver/src/main/java/com/arangodb/entity/arangosearch/ConsolidationType.java similarity index 100% rename from src/main/java/com/arangodb/entity/arangosearch/ConsolidationType.java rename to driver/src/main/java/com/arangodb/entity/arangosearch/ConsolidationType.java diff --git a/src/main/java/com/arangodb/entity/arangosearch/FieldLink.java b/driver/src/main/java/com/arangodb/entity/arangosearch/FieldLink.java similarity index 100% rename from src/main/java/com/arangodb/entity/arangosearch/FieldLink.java rename to driver/src/main/java/com/arangodb/entity/arangosearch/FieldLink.java diff --git a/src/main/java/com/arangodb/entity/arangosearch/PrimarySort.java b/driver/src/main/java/com/arangodb/entity/arangosearch/PrimarySort.java similarity index 100% rename from src/main/java/com/arangodb/entity/arangosearch/PrimarySort.java rename to driver/src/main/java/com/arangodb/entity/arangosearch/PrimarySort.java diff --git a/src/main/java/com/arangodb/entity/arangosearch/SearchAliasIndex.java b/driver/src/main/java/com/arangodb/entity/arangosearch/SearchAliasIndex.java similarity index 100% rename from src/main/java/com/arangodb/entity/arangosearch/SearchAliasIndex.java rename to driver/src/main/java/com/arangodb/entity/arangosearch/SearchAliasIndex.java diff --git a/src/main/java/com/arangodb/entity/arangosearch/SearchAliasPropertiesEntity.java b/driver/src/main/java/com/arangodb/entity/arangosearch/SearchAliasPropertiesEntity.java similarity index 100% rename from src/main/java/com/arangodb/entity/arangosearch/SearchAliasPropertiesEntity.java rename to driver/src/main/java/com/arangodb/entity/arangosearch/SearchAliasPropertiesEntity.java diff --git a/src/main/java/com/arangodb/entity/arangosearch/StoreValuesType.java b/driver/src/main/java/com/arangodb/entity/arangosearch/StoreValuesType.java similarity index 100% rename from src/main/java/com/arangodb/entity/arangosearch/StoreValuesType.java rename to driver/src/main/java/com/arangodb/entity/arangosearch/StoreValuesType.java diff --git a/src/main/java/com/arangodb/entity/arangosearch/StoredValue.java b/driver/src/main/java/com/arangodb/entity/arangosearch/StoredValue.java similarity index 100% rename from src/main/java/com/arangodb/entity/arangosearch/StoredValue.java rename to driver/src/main/java/com/arangodb/entity/arangosearch/StoredValue.java diff --git a/src/main/java/com/arangodb/entity/arangosearch/analyzer/AQLAnalyzer.java b/driver/src/main/java/com/arangodb/entity/arangosearch/analyzer/AQLAnalyzer.java similarity index 100% rename from src/main/java/com/arangodb/entity/arangosearch/analyzer/AQLAnalyzer.java rename to driver/src/main/java/com/arangodb/entity/arangosearch/analyzer/AQLAnalyzer.java diff --git a/src/main/java/com/arangodb/entity/arangosearch/analyzer/AQLAnalyzerProperties.java b/driver/src/main/java/com/arangodb/entity/arangosearch/analyzer/AQLAnalyzerProperties.java similarity index 100% rename from src/main/java/com/arangodb/entity/arangosearch/analyzer/AQLAnalyzerProperties.java rename to driver/src/main/java/com/arangodb/entity/arangosearch/analyzer/AQLAnalyzerProperties.java diff --git a/src/main/java/com/arangodb/entity/arangosearch/analyzer/ClassificationAnalyzer.java b/driver/src/main/java/com/arangodb/entity/arangosearch/analyzer/ClassificationAnalyzer.java similarity index 100% rename from src/main/java/com/arangodb/entity/arangosearch/analyzer/ClassificationAnalyzer.java rename to driver/src/main/java/com/arangodb/entity/arangosearch/analyzer/ClassificationAnalyzer.java diff --git a/src/main/java/com/arangodb/entity/arangosearch/analyzer/ClassificationAnalyzerProperties.java b/driver/src/main/java/com/arangodb/entity/arangosearch/analyzer/ClassificationAnalyzerProperties.java similarity index 100% rename from src/main/java/com/arangodb/entity/arangosearch/analyzer/ClassificationAnalyzerProperties.java rename to driver/src/main/java/com/arangodb/entity/arangosearch/analyzer/ClassificationAnalyzerProperties.java diff --git a/src/main/java/com/arangodb/entity/arangosearch/analyzer/CollationAnalyzer.java b/driver/src/main/java/com/arangodb/entity/arangosearch/analyzer/CollationAnalyzer.java similarity index 100% rename from src/main/java/com/arangodb/entity/arangosearch/analyzer/CollationAnalyzer.java rename to driver/src/main/java/com/arangodb/entity/arangosearch/analyzer/CollationAnalyzer.java diff --git a/src/main/java/com/arangodb/entity/arangosearch/analyzer/CollationAnalyzerProperties.java b/driver/src/main/java/com/arangodb/entity/arangosearch/analyzer/CollationAnalyzerProperties.java similarity index 100% rename from src/main/java/com/arangodb/entity/arangosearch/analyzer/CollationAnalyzerProperties.java rename to driver/src/main/java/com/arangodb/entity/arangosearch/analyzer/CollationAnalyzerProperties.java diff --git a/src/main/java/com/arangodb/entity/arangosearch/analyzer/DelimiterAnalyzer.java b/driver/src/main/java/com/arangodb/entity/arangosearch/analyzer/DelimiterAnalyzer.java similarity index 100% rename from src/main/java/com/arangodb/entity/arangosearch/analyzer/DelimiterAnalyzer.java rename to driver/src/main/java/com/arangodb/entity/arangosearch/analyzer/DelimiterAnalyzer.java diff --git a/src/main/java/com/arangodb/entity/arangosearch/analyzer/DelimiterAnalyzerProperties.java b/driver/src/main/java/com/arangodb/entity/arangosearch/analyzer/DelimiterAnalyzerProperties.java similarity index 100% rename from src/main/java/com/arangodb/entity/arangosearch/analyzer/DelimiterAnalyzerProperties.java rename to driver/src/main/java/com/arangodb/entity/arangosearch/analyzer/DelimiterAnalyzerProperties.java diff --git a/src/main/java/com/arangodb/entity/arangosearch/analyzer/EdgeNgram.java b/driver/src/main/java/com/arangodb/entity/arangosearch/analyzer/EdgeNgram.java similarity index 100% rename from src/main/java/com/arangodb/entity/arangosearch/analyzer/EdgeNgram.java rename to driver/src/main/java/com/arangodb/entity/arangosearch/analyzer/EdgeNgram.java diff --git a/src/main/java/com/arangodb/entity/arangosearch/analyzer/GeoAnalyzerOptions.java b/driver/src/main/java/com/arangodb/entity/arangosearch/analyzer/GeoAnalyzerOptions.java similarity index 100% rename from src/main/java/com/arangodb/entity/arangosearch/analyzer/GeoAnalyzerOptions.java rename to driver/src/main/java/com/arangodb/entity/arangosearch/analyzer/GeoAnalyzerOptions.java diff --git a/src/main/java/com/arangodb/entity/arangosearch/analyzer/GeoJSONAnalyzer.java b/driver/src/main/java/com/arangodb/entity/arangosearch/analyzer/GeoJSONAnalyzer.java similarity index 100% rename from src/main/java/com/arangodb/entity/arangosearch/analyzer/GeoJSONAnalyzer.java rename to driver/src/main/java/com/arangodb/entity/arangosearch/analyzer/GeoJSONAnalyzer.java diff --git a/src/main/java/com/arangodb/entity/arangosearch/analyzer/GeoJSONAnalyzerProperties.java b/driver/src/main/java/com/arangodb/entity/arangosearch/analyzer/GeoJSONAnalyzerProperties.java similarity index 100% rename from src/main/java/com/arangodb/entity/arangosearch/analyzer/GeoJSONAnalyzerProperties.java rename to driver/src/main/java/com/arangodb/entity/arangosearch/analyzer/GeoJSONAnalyzerProperties.java diff --git a/src/main/java/com/arangodb/entity/arangosearch/analyzer/GeoPointAnalyzer.java b/driver/src/main/java/com/arangodb/entity/arangosearch/analyzer/GeoPointAnalyzer.java similarity index 100% rename from src/main/java/com/arangodb/entity/arangosearch/analyzer/GeoPointAnalyzer.java rename to driver/src/main/java/com/arangodb/entity/arangosearch/analyzer/GeoPointAnalyzer.java diff --git a/src/main/java/com/arangodb/entity/arangosearch/analyzer/GeoPointAnalyzerProperties.java b/driver/src/main/java/com/arangodb/entity/arangosearch/analyzer/GeoPointAnalyzerProperties.java similarity index 100% rename from src/main/java/com/arangodb/entity/arangosearch/analyzer/GeoPointAnalyzerProperties.java rename to driver/src/main/java/com/arangodb/entity/arangosearch/analyzer/GeoPointAnalyzerProperties.java diff --git a/src/main/java/com/arangodb/entity/arangosearch/analyzer/IdentityAnalyzer.java b/driver/src/main/java/com/arangodb/entity/arangosearch/analyzer/IdentityAnalyzer.java similarity index 100% rename from src/main/java/com/arangodb/entity/arangosearch/analyzer/IdentityAnalyzer.java rename to driver/src/main/java/com/arangodb/entity/arangosearch/analyzer/IdentityAnalyzer.java diff --git a/src/main/java/com/arangodb/entity/arangosearch/analyzer/MinHashAnalyzer.java b/driver/src/main/java/com/arangodb/entity/arangosearch/analyzer/MinHashAnalyzer.java similarity index 100% rename from src/main/java/com/arangodb/entity/arangosearch/analyzer/MinHashAnalyzer.java rename to driver/src/main/java/com/arangodb/entity/arangosearch/analyzer/MinHashAnalyzer.java diff --git a/src/main/java/com/arangodb/entity/arangosearch/analyzer/MinHashAnalyzerProperties.java b/driver/src/main/java/com/arangodb/entity/arangosearch/analyzer/MinHashAnalyzerProperties.java similarity index 100% rename from src/main/java/com/arangodb/entity/arangosearch/analyzer/MinHashAnalyzerProperties.java rename to driver/src/main/java/com/arangodb/entity/arangosearch/analyzer/MinHashAnalyzerProperties.java diff --git a/src/main/java/com/arangodb/entity/arangosearch/analyzer/NGramAnalyzer.java b/driver/src/main/java/com/arangodb/entity/arangosearch/analyzer/NGramAnalyzer.java similarity index 100% rename from src/main/java/com/arangodb/entity/arangosearch/analyzer/NGramAnalyzer.java rename to driver/src/main/java/com/arangodb/entity/arangosearch/analyzer/NGramAnalyzer.java diff --git a/src/main/java/com/arangodb/entity/arangosearch/analyzer/NGramAnalyzerProperties.java b/driver/src/main/java/com/arangodb/entity/arangosearch/analyzer/NGramAnalyzerProperties.java similarity index 100% rename from src/main/java/com/arangodb/entity/arangosearch/analyzer/NGramAnalyzerProperties.java rename to driver/src/main/java/com/arangodb/entity/arangosearch/analyzer/NGramAnalyzerProperties.java diff --git a/src/main/java/com/arangodb/entity/arangosearch/analyzer/NearestNeighborsAnalyzer.java b/driver/src/main/java/com/arangodb/entity/arangosearch/analyzer/NearestNeighborsAnalyzer.java similarity index 100% rename from src/main/java/com/arangodb/entity/arangosearch/analyzer/NearestNeighborsAnalyzer.java rename to driver/src/main/java/com/arangodb/entity/arangosearch/analyzer/NearestNeighborsAnalyzer.java diff --git a/src/main/java/com/arangodb/entity/arangosearch/analyzer/NearestNeighborsAnalyzerProperties.java b/driver/src/main/java/com/arangodb/entity/arangosearch/analyzer/NearestNeighborsAnalyzerProperties.java similarity index 100% rename from src/main/java/com/arangodb/entity/arangosearch/analyzer/NearestNeighborsAnalyzerProperties.java rename to driver/src/main/java/com/arangodb/entity/arangosearch/analyzer/NearestNeighborsAnalyzerProperties.java diff --git a/src/main/java/com/arangodb/entity/arangosearch/analyzer/NormAnalyzer.java b/driver/src/main/java/com/arangodb/entity/arangosearch/analyzer/NormAnalyzer.java similarity index 100% rename from src/main/java/com/arangodb/entity/arangosearch/analyzer/NormAnalyzer.java rename to driver/src/main/java/com/arangodb/entity/arangosearch/analyzer/NormAnalyzer.java diff --git a/src/main/java/com/arangodb/entity/arangosearch/analyzer/NormAnalyzerProperties.java b/driver/src/main/java/com/arangodb/entity/arangosearch/analyzer/NormAnalyzerProperties.java similarity index 100% rename from src/main/java/com/arangodb/entity/arangosearch/analyzer/NormAnalyzerProperties.java rename to driver/src/main/java/com/arangodb/entity/arangosearch/analyzer/NormAnalyzerProperties.java diff --git a/src/main/java/com/arangodb/entity/arangosearch/analyzer/PipelineAnalyzer.java b/driver/src/main/java/com/arangodb/entity/arangosearch/analyzer/PipelineAnalyzer.java similarity index 100% rename from src/main/java/com/arangodb/entity/arangosearch/analyzer/PipelineAnalyzer.java rename to driver/src/main/java/com/arangodb/entity/arangosearch/analyzer/PipelineAnalyzer.java diff --git a/src/main/java/com/arangodb/entity/arangosearch/analyzer/PipelineAnalyzerProperties.java b/driver/src/main/java/com/arangodb/entity/arangosearch/analyzer/PipelineAnalyzerProperties.java similarity index 100% rename from src/main/java/com/arangodb/entity/arangosearch/analyzer/PipelineAnalyzerProperties.java rename to driver/src/main/java/com/arangodb/entity/arangosearch/analyzer/PipelineAnalyzerProperties.java diff --git a/src/main/java/com/arangodb/entity/arangosearch/analyzer/SearchAnalyzer.java b/driver/src/main/java/com/arangodb/entity/arangosearch/analyzer/SearchAnalyzer.java similarity index 100% rename from src/main/java/com/arangodb/entity/arangosearch/analyzer/SearchAnalyzer.java rename to driver/src/main/java/com/arangodb/entity/arangosearch/analyzer/SearchAnalyzer.java diff --git a/src/main/java/com/arangodb/entity/arangosearch/analyzer/SearchAnalyzerCase.java b/driver/src/main/java/com/arangodb/entity/arangosearch/analyzer/SearchAnalyzerCase.java similarity index 100% rename from src/main/java/com/arangodb/entity/arangosearch/analyzer/SearchAnalyzerCase.java rename to driver/src/main/java/com/arangodb/entity/arangosearch/analyzer/SearchAnalyzerCase.java diff --git a/src/main/java/com/arangodb/entity/arangosearch/analyzer/SegmentationAnalyzer.java b/driver/src/main/java/com/arangodb/entity/arangosearch/analyzer/SegmentationAnalyzer.java similarity index 100% rename from src/main/java/com/arangodb/entity/arangosearch/analyzer/SegmentationAnalyzer.java rename to driver/src/main/java/com/arangodb/entity/arangosearch/analyzer/SegmentationAnalyzer.java diff --git a/src/main/java/com/arangodb/entity/arangosearch/analyzer/SegmentationAnalyzerProperties.java b/driver/src/main/java/com/arangodb/entity/arangosearch/analyzer/SegmentationAnalyzerProperties.java similarity index 100% rename from src/main/java/com/arangodb/entity/arangosearch/analyzer/SegmentationAnalyzerProperties.java rename to driver/src/main/java/com/arangodb/entity/arangosearch/analyzer/SegmentationAnalyzerProperties.java diff --git a/src/main/java/com/arangodb/entity/arangosearch/analyzer/StemAnalyzer.java b/driver/src/main/java/com/arangodb/entity/arangosearch/analyzer/StemAnalyzer.java similarity index 100% rename from src/main/java/com/arangodb/entity/arangosearch/analyzer/StemAnalyzer.java rename to driver/src/main/java/com/arangodb/entity/arangosearch/analyzer/StemAnalyzer.java diff --git a/src/main/java/com/arangodb/entity/arangosearch/analyzer/StemAnalyzerProperties.java b/driver/src/main/java/com/arangodb/entity/arangosearch/analyzer/StemAnalyzerProperties.java similarity index 100% rename from src/main/java/com/arangodb/entity/arangosearch/analyzer/StemAnalyzerProperties.java rename to driver/src/main/java/com/arangodb/entity/arangosearch/analyzer/StemAnalyzerProperties.java diff --git a/src/main/java/com/arangodb/entity/arangosearch/analyzer/StopwordsAnalyzer.java b/driver/src/main/java/com/arangodb/entity/arangosearch/analyzer/StopwordsAnalyzer.java similarity index 100% rename from src/main/java/com/arangodb/entity/arangosearch/analyzer/StopwordsAnalyzer.java rename to driver/src/main/java/com/arangodb/entity/arangosearch/analyzer/StopwordsAnalyzer.java diff --git a/src/main/java/com/arangodb/entity/arangosearch/analyzer/StopwordsAnalyzerProperties.java b/driver/src/main/java/com/arangodb/entity/arangosearch/analyzer/StopwordsAnalyzerProperties.java similarity index 100% rename from src/main/java/com/arangodb/entity/arangosearch/analyzer/StopwordsAnalyzerProperties.java rename to driver/src/main/java/com/arangodb/entity/arangosearch/analyzer/StopwordsAnalyzerProperties.java diff --git a/src/main/java/com/arangodb/entity/arangosearch/analyzer/StreamType.java b/driver/src/main/java/com/arangodb/entity/arangosearch/analyzer/StreamType.java similarity index 100% rename from src/main/java/com/arangodb/entity/arangosearch/analyzer/StreamType.java rename to driver/src/main/java/com/arangodb/entity/arangosearch/analyzer/StreamType.java diff --git a/src/main/java/com/arangodb/entity/arangosearch/analyzer/TextAnalyzer.java b/driver/src/main/java/com/arangodb/entity/arangosearch/analyzer/TextAnalyzer.java similarity index 100% rename from src/main/java/com/arangodb/entity/arangosearch/analyzer/TextAnalyzer.java rename to driver/src/main/java/com/arangodb/entity/arangosearch/analyzer/TextAnalyzer.java diff --git a/src/main/java/com/arangodb/entity/arangosearch/analyzer/TextAnalyzerProperties.java b/driver/src/main/java/com/arangodb/entity/arangosearch/analyzer/TextAnalyzerProperties.java similarity index 100% rename from src/main/java/com/arangodb/entity/arangosearch/analyzer/TextAnalyzerProperties.java rename to driver/src/main/java/com/arangodb/entity/arangosearch/analyzer/TextAnalyzerProperties.java diff --git a/src/main/java/com/arangodb/internal/ArangoCollectionImpl.java b/driver/src/main/java/com/arangodb/internal/ArangoCollectionImpl.java similarity index 100% rename from src/main/java/com/arangodb/internal/ArangoCollectionImpl.java rename to driver/src/main/java/com/arangodb/internal/ArangoCollectionImpl.java diff --git a/src/main/java/com/arangodb/internal/ArangoCursorExecute.java b/driver/src/main/java/com/arangodb/internal/ArangoCursorExecute.java similarity index 96% rename from src/main/java/com/arangodb/internal/ArangoCursorExecute.java rename to driver/src/main/java/com/arangodb/internal/ArangoCursorExecute.java index e9a6512af..7efc5eef9 100644 --- a/src/main/java/com/arangodb/internal/ArangoCursorExecute.java +++ b/driver/src/main/java/com/arangodb/internal/ArangoCursorExecute.java @@ -1,36 +1,36 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.internal; - -import com.arangodb.internal.cursor.entity.InternalCursorEntity; - -import java.util.Map; - -/** - * @author Mark Vollmary - */ -public interface ArangoCursorExecute { - - InternalCursorEntity next(String id, Map meta); - - void close(String id, Map meta); - -} +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed 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. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.internal; + +import com.arangodb.internal.cursor.entity.InternalCursorEntity; + +import java.util.Map; + +/** + * @author Mark Vollmary + */ +public interface ArangoCursorExecute { + + InternalCursorEntity next(String id, Map meta); + + void close(String id, Map meta); + +} diff --git a/src/main/java/com/arangodb/internal/ArangoDBImpl.java b/driver/src/main/java/com/arangodb/internal/ArangoDBImpl.java similarity index 100% rename from src/main/java/com/arangodb/internal/ArangoDBImpl.java rename to driver/src/main/java/com/arangodb/internal/ArangoDBImpl.java diff --git a/src/main/java/com/arangodb/internal/ArangoDatabaseImpl.java b/driver/src/main/java/com/arangodb/internal/ArangoDatabaseImpl.java similarity index 100% rename from src/main/java/com/arangodb/internal/ArangoDatabaseImpl.java rename to driver/src/main/java/com/arangodb/internal/ArangoDatabaseImpl.java diff --git a/src/main/java/com/arangodb/internal/ArangoDefaults.java b/driver/src/main/java/com/arangodb/internal/ArangoDefaults.java similarity index 100% rename from src/main/java/com/arangodb/internal/ArangoDefaults.java rename to driver/src/main/java/com/arangodb/internal/ArangoDefaults.java diff --git a/src/main/java/com/arangodb/internal/ArangoEdgeCollectionImpl.java b/driver/src/main/java/com/arangodb/internal/ArangoEdgeCollectionImpl.java similarity index 100% rename from src/main/java/com/arangodb/internal/ArangoEdgeCollectionImpl.java rename to driver/src/main/java/com/arangodb/internal/ArangoEdgeCollectionImpl.java diff --git a/src/main/java/com/arangodb/internal/ArangoErrors.java b/driver/src/main/java/com/arangodb/internal/ArangoErrors.java similarity index 100% rename from src/main/java/com/arangodb/internal/ArangoErrors.java rename to driver/src/main/java/com/arangodb/internal/ArangoErrors.java diff --git a/src/main/java/com/arangodb/internal/ArangoExecuteable.java b/driver/src/main/java/com/arangodb/internal/ArangoExecuteable.java similarity index 100% rename from src/main/java/com/arangodb/internal/ArangoExecuteable.java rename to driver/src/main/java/com/arangodb/internal/ArangoExecuteable.java diff --git a/src/main/java/com/arangodb/internal/ArangoExecutor.java b/driver/src/main/java/com/arangodb/internal/ArangoExecutor.java similarity index 100% rename from src/main/java/com/arangodb/internal/ArangoExecutor.java rename to driver/src/main/java/com/arangodb/internal/ArangoExecutor.java diff --git a/src/main/java/com/arangodb/internal/ArangoExecutorSync.java b/driver/src/main/java/com/arangodb/internal/ArangoExecutorSync.java similarity index 100% rename from src/main/java/com/arangodb/internal/ArangoExecutorSync.java rename to driver/src/main/java/com/arangodb/internal/ArangoExecutorSync.java diff --git a/src/main/java/com/arangodb/internal/ArangoGraphImpl.java b/driver/src/main/java/com/arangodb/internal/ArangoGraphImpl.java similarity index 100% rename from src/main/java/com/arangodb/internal/ArangoGraphImpl.java rename to driver/src/main/java/com/arangodb/internal/ArangoGraphImpl.java diff --git a/src/main/java/com/arangodb/internal/ArangoMetricsImpl.java b/driver/src/main/java/com/arangodb/internal/ArangoMetricsImpl.java similarity index 100% rename from src/main/java/com/arangodb/internal/ArangoMetricsImpl.java rename to driver/src/main/java/com/arangodb/internal/ArangoMetricsImpl.java diff --git a/src/main/java/com/arangodb/internal/ArangoRequestParam.java b/driver/src/main/java/com/arangodb/internal/ArangoRequestParam.java similarity index 100% rename from src/main/java/com/arangodb/internal/ArangoRequestParam.java rename to driver/src/main/java/com/arangodb/internal/ArangoRequestParam.java diff --git a/src/main/java/com/arangodb/internal/ArangoResponseField.java b/driver/src/main/java/com/arangodb/internal/ArangoResponseField.java similarity index 100% rename from src/main/java/com/arangodb/internal/ArangoResponseField.java rename to driver/src/main/java/com/arangodb/internal/ArangoResponseField.java diff --git a/src/main/java/com/arangodb/internal/ArangoRouteImpl.java b/driver/src/main/java/com/arangodb/internal/ArangoRouteImpl.java similarity index 100% rename from src/main/java/com/arangodb/internal/ArangoRouteImpl.java rename to driver/src/main/java/com/arangodb/internal/ArangoRouteImpl.java diff --git a/src/main/java/com/arangodb/internal/ArangoSearchImpl.java b/driver/src/main/java/com/arangodb/internal/ArangoSearchImpl.java similarity index 100% rename from src/main/java/com/arangodb/internal/ArangoSearchImpl.java rename to driver/src/main/java/com/arangodb/internal/ArangoSearchImpl.java diff --git a/src/main/java/com/arangodb/internal/ArangoVertexCollectionImpl.java b/driver/src/main/java/com/arangodb/internal/ArangoVertexCollectionImpl.java similarity index 100% rename from src/main/java/com/arangodb/internal/ArangoVertexCollectionImpl.java rename to driver/src/main/java/com/arangodb/internal/ArangoVertexCollectionImpl.java diff --git a/src/main/java/com/arangodb/internal/ArangoViewImpl.java b/driver/src/main/java/com/arangodb/internal/ArangoViewImpl.java similarity index 100% rename from src/main/java/com/arangodb/internal/ArangoViewImpl.java rename to driver/src/main/java/com/arangodb/internal/ArangoViewImpl.java diff --git a/src/main/java/com/arangodb/internal/DocumentFields.java b/driver/src/main/java/com/arangodb/internal/DocumentFields.java similarity index 100% rename from src/main/java/com/arangodb/internal/DocumentFields.java rename to driver/src/main/java/com/arangodb/internal/DocumentFields.java diff --git a/src/main/java/com/arangodb/internal/InternalArangoCollection.java b/driver/src/main/java/com/arangodb/internal/InternalArangoCollection.java similarity index 100% rename from src/main/java/com/arangodb/internal/InternalArangoCollection.java rename to driver/src/main/java/com/arangodb/internal/InternalArangoCollection.java diff --git a/src/main/java/com/arangodb/internal/InternalArangoDB.java b/driver/src/main/java/com/arangodb/internal/InternalArangoDB.java similarity index 100% rename from src/main/java/com/arangodb/internal/InternalArangoDB.java rename to driver/src/main/java/com/arangodb/internal/InternalArangoDB.java diff --git a/src/main/java/com/arangodb/internal/InternalArangoDBBuilder.java b/driver/src/main/java/com/arangodb/internal/InternalArangoDBBuilder.java similarity index 100% rename from src/main/java/com/arangodb/internal/InternalArangoDBBuilder.java rename to driver/src/main/java/com/arangodb/internal/InternalArangoDBBuilder.java diff --git a/src/main/java/com/arangodb/internal/InternalArangoDatabase.java b/driver/src/main/java/com/arangodb/internal/InternalArangoDatabase.java similarity index 100% rename from src/main/java/com/arangodb/internal/InternalArangoDatabase.java rename to driver/src/main/java/com/arangodb/internal/InternalArangoDatabase.java diff --git a/src/main/java/com/arangodb/internal/InternalArangoEdgeCollection.java b/driver/src/main/java/com/arangodb/internal/InternalArangoEdgeCollection.java similarity index 100% rename from src/main/java/com/arangodb/internal/InternalArangoEdgeCollection.java rename to driver/src/main/java/com/arangodb/internal/InternalArangoEdgeCollection.java diff --git a/src/main/java/com/arangodb/internal/InternalArangoGraph.java b/driver/src/main/java/com/arangodb/internal/InternalArangoGraph.java similarity index 100% rename from src/main/java/com/arangodb/internal/InternalArangoGraph.java rename to driver/src/main/java/com/arangodb/internal/InternalArangoGraph.java diff --git a/src/main/java/com/arangodb/internal/InternalArangoRoute.java b/driver/src/main/java/com/arangodb/internal/InternalArangoRoute.java similarity index 100% rename from src/main/java/com/arangodb/internal/InternalArangoRoute.java rename to driver/src/main/java/com/arangodb/internal/InternalArangoRoute.java diff --git a/src/main/java/com/arangodb/internal/InternalArangoSearch.java b/driver/src/main/java/com/arangodb/internal/InternalArangoSearch.java similarity index 100% rename from src/main/java/com/arangodb/internal/InternalArangoSearch.java rename to driver/src/main/java/com/arangodb/internal/InternalArangoSearch.java diff --git a/src/main/java/com/arangodb/internal/InternalArangoVertexCollection.java b/driver/src/main/java/com/arangodb/internal/InternalArangoVertexCollection.java similarity index 100% rename from src/main/java/com/arangodb/internal/InternalArangoVertexCollection.java rename to driver/src/main/java/com/arangodb/internal/InternalArangoVertexCollection.java diff --git a/src/main/java/com/arangodb/internal/InternalArangoView.java b/driver/src/main/java/com/arangodb/internal/InternalArangoView.java similarity index 100% rename from src/main/java/com/arangodb/internal/InternalArangoView.java rename to driver/src/main/java/com/arangodb/internal/InternalArangoView.java diff --git a/src/main/java/com/arangodb/internal/InternalSearchAlias.java b/driver/src/main/java/com/arangodb/internal/InternalSearchAlias.java similarity index 100% rename from src/main/java/com/arangodb/internal/InternalSearchAlias.java rename to driver/src/main/java/com/arangodb/internal/InternalSearchAlias.java diff --git a/src/main/java/com/arangodb/internal/QueueTimeMetricsImpl.java b/driver/src/main/java/com/arangodb/internal/QueueTimeMetricsImpl.java similarity index 100% rename from src/main/java/com/arangodb/internal/QueueTimeMetricsImpl.java rename to driver/src/main/java/com/arangodb/internal/QueueTimeMetricsImpl.java diff --git a/src/main/java/com/arangodb/internal/SearchAliasImpl.java b/driver/src/main/java/com/arangodb/internal/SearchAliasImpl.java similarity index 100% rename from src/main/java/com/arangodb/internal/SearchAliasImpl.java rename to driver/src/main/java/com/arangodb/internal/SearchAliasImpl.java diff --git a/src/main/java/com/arangodb/internal/cursor/AbstractArangoIterable.java b/driver/src/main/java/com/arangodb/internal/cursor/AbstractArangoIterable.java similarity index 100% rename from src/main/java/com/arangodb/internal/cursor/AbstractArangoIterable.java rename to driver/src/main/java/com/arangodb/internal/cursor/AbstractArangoIterable.java diff --git a/src/main/java/com/arangodb/internal/cursor/ArangoCursorImpl.java b/driver/src/main/java/com/arangodb/internal/cursor/ArangoCursorImpl.java similarity index 100% rename from src/main/java/com/arangodb/internal/cursor/ArangoCursorImpl.java rename to driver/src/main/java/com/arangodb/internal/cursor/ArangoCursorImpl.java diff --git a/src/main/java/com/arangodb/internal/cursor/ArangoCursorIterator.java b/driver/src/main/java/com/arangodb/internal/cursor/ArangoCursorIterator.java similarity index 100% rename from src/main/java/com/arangodb/internal/cursor/ArangoCursorIterator.java rename to driver/src/main/java/com/arangodb/internal/cursor/ArangoCursorIterator.java diff --git a/src/main/java/com/arangodb/internal/cursor/entity/InternalCursorEntity.java b/driver/src/main/java/com/arangodb/internal/cursor/entity/InternalCursorEntity.java similarity index 100% rename from src/main/java/com/arangodb/internal/cursor/entity/InternalCursorEntity.java rename to driver/src/main/java/com/arangodb/internal/cursor/entity/InternalCursorEntity.java diff --git a/src/main/java/com/arangodb/internal/http/HttpCommunication.java b/driver/src/main/java/com/arangodb/internal/http/HttpCommunication.java similarity index 100% rename from src/main/java/com/arangodb/internal/http/HttpCommunication.java rename to driver/src/main/java/com/arangodb/internal/http/HttpCommunication.java diff --git a/src/main/java/com/arangodb/internal/http/HttpConnection.java b/driver/src/main/java/com/arangodb/internal/http/HttpConnection.java similarity index 100% rename from src/main/java/com/arangodb/internal/http/HttpConnection.java rename to driver/src/main/java/com/arangodb/internal/http/HttpConnection.java diff --git a/src/main/java/com/arangodb/internal/http/HttpConnectionFactory.java b/driver/src/main/java/com/arangodb/internal/http/HttpConnectionFactory.java similarity index 100% rename from src/main/java/com/arangodb/internal/http/HttpConnectionFactory.java rename to driver/src/main/java/com/arangodb/internal/http/HttpConnectionFactory.java diff --git a/src/main/java/com/arangodb/internal/http/HttpProtocol.java b/driver/src/main/java/com/arangodb/internal/http/HttpProtocol.java similarity index 100% rename from src/main/java/com/arangodb/internal/http/HttpProtocol.java rename to driver/src/main/java/com/arangodb/internal/http/HttpProtocol.java diff --git a/src/main/java/com/arangodb/internal/net/AccessType.java b/driver/src/main/java/com/arangodb/internal/net/AccessType.java similarity index 100% rename from src/main/java/com/arangodb/internal/net/AccessType.java rename to driver/src/main/java/com/arangodb/internal/net/AccessType.java diff --git a/src/main/java/com/arangodb/internal/net/ArangoDBRedirectException.java b/driver/src/main/java/com/arangodb/internal/net/ArangoDBRedirectException.java similarity index 96% rename from src/main/java/com/arangodb/internal/net/ArangoDBRedirectException.java rename to driver/src/main/java/com/arangodb/internal/net/ArangoDBRedirectException.java index 8b7c37010..bf8e0c9cd 100644 --- a/src/main/java/com/arangodb/internal/net/ArangoDBRedirectException.java +++ b/driver/src/main/java/com/arangodb/internal/net/ArangoDBRedirectException.java @@ -1,42 +1,42 @@ -/* - * DISCLAIMER - * - * Copyright 2017 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.internal.net; - -import com.arangodb.ArangoDBException; - -/** - * @author Mark Vollmary - */ -public class ArangoDBRedirectException extends ArangoDBException { - - private static final long serialVersionUID = -94810262465567613L; - private final String location; - - public ArangoDBRedirectException(final String message, final String location) { - super(message); - this.location = location; - } - - public String getLocation() { - return location; - } - -} +/* + * DISCLAIMER + * + * Copyright 2017 ArangoDB GmbH, Cologne, Germany + * + * Licensed 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. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.internal.net; + +import com.arangodb.ArangoDBException; + +/** + * @author Mark Vollmary + */ +public class ArangoDBRedirectException extends ArangoDBException { + + private static final long serialVersionUID = -94810262465567613L; + private final String location; + + public ArangoDBRedirectException(final String message, final String location) { + super(message); + this.location = location; + } + + public String getLocation() { + return location; + } + +} diff --git a/src/main/java/com/arangodb/internal/net/CommunicationProtocol.java b/driver/src/main/java/com/arangodb/internal/net/CommunicationProtocol.java similarity index 96% rename from src/main/java/com/arangodb/internal/net/CommunicationProtocol.java rename to driver/src/main/java/com/arangodb/internal/net/CommunicationProtocol.java index 5f1d8f16b..799fd03d3 100644 --- a/src/main/java/com/arangodb/internal/net/CommunicationProtocol.java +++ b/driver/src/main/java/com/arangodb/internal/net/CommunicationProtocol.java @@ -1,37 +1,37 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.internal.net; - -import com.arangodb.Request; -import com.arangodb.Response; - -import java.io.Closeable; - -/** - * @author Mark Vollmary - */ -public interface CommunicationProtocol extends Closeable { - - Response execute(final Request request, HostHandle hostHandle); - - void setJwt(String jwt); - -} +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed 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. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.internal.net; + +import com.arangodb.Request; +import com.arangodb.Response; + +import java.io.Closeable; + +/** + * @author Mark Vollmary + */ +public interface CommunicationProtocol extends Closeable { + + Response execute(final Request request, HostHandle hostHandle); + + void setJwt(String jwt); + +} diff --git a/src/main/java/com/arangodb/internal/net/Connection.java b/driver/src/main/java/com/arangodb/internal/net/Connection.java similarity index 100% rename from src/main/java/com/arangodb/internal/net/Connection.java rename to driver/src/main/java/com/arangodb/internal/net/Connection.java diff --git a/src/main/java/com/arangodb/internal/net/ConnectionFactory.java b/driver/src/main/java/com/arangodb/internal/net/ConnectionFactory.java similarity index 100% rename from src/main/java/com/arangodb/internal/net/ConnectionFactory.java rename to driver/src/main/java/com/arangodb/internal/net/ConnectionFactory.java diff --git a/src/main/java/com/arangodb/internal/net/ConnectionPool.java b/driver/src/main/java/com/arangodb/internal/net/ConnectionPool.java similarity index 100% rename from src/main/java/com/arangodb/internal/net/ConnectionPool.java rename to driver/src/main/java/com/arangodb/internal/net/ConnectionPool.java diff --git a/src/main/java/com/arangodb/internal/net/ConnectionPoolImpl.java b/driver/src/main/java/com/arangodb/internal/net/ConnectionPoolImpl.java similarity index 100% rename from src/main/java/com/arangodb/internal/net/ConnectionPoolImpl.java rename to driver/src/main/java/com/arangodb/internal/net/ConnectionPoolImpl.java diff --git a/src/main/java/com/arangodb/internal/net/DirtyReadHostHandler.java b/driver/src/main/java/com/arangodb/internal/net/DirtyReadHostHandler.java similarity index 100% rename from src/main/java/com/arangodb/internal/net/DirtyReadHostHandler.java rename to driver/src/main/java/com/arangodb/internal/net/DirtyReadHostHandler.java diff --git a/src/main/java/com/arangodb/internal/net/ExtendedHostResolver.java b/driver/src/main/java/com/arangodb/internal/net/ExtendedHostResolver.java similarity index 100% rename from src/main/java/com/arangodb/internal/net/ExtendedHostResolver.java rename to driver/src/main/java/com/arangodb/internal/net/ExtendedHostResolver.java diff --git a/src/main/java/com/arangodb/internal/net/FallbackHostHandler.java b/driver/src/main/java/com/arangodb/internal/net/FallbackHostHandler.java similarity index 100% rename from src/main/java/com/arangodb/internal/net/FallbackHostHandler.java rename to driver/src/main/java/com/arangodb/internal/net/FallbackHostHandler.java diff --git a/src/main/java/com/arangodb/internal/net/Host.java b/driver/src/main/java/com/arangodb/internal/net/Host.java similarity index 100% rename from src/main/java/com/arangodb/internal/net/Host.java rename to driver/src/main/java/com/arangodb/internal/net/Host.java diff --git a/src/main/java/com/arangodb/internal/net/HostDescription.java b/driver/src/main/java/com/arangodb/internal/net/HostDescription.java similarity index 100% rename from src/main/java/com/arangodb/internal/net/HostDescription.java rename to driver/src/main/java/com/arangodb/internal/net/HostDescription.java diff --git a/src/main/java/com/arangodb/internal/net/HostHandle.java b/driver/src/main/java/com/arangodb/internal/net/HostHandle.java similarity index 100% rename from src/main/java/com/arangodb/internal/net/HostHandle.java rename to driver/src/main/java/com/arangodb/internal/net/HostHandle.java diff --git a/src/main/java/com/arangodb/internal/net/HostHandler.java b/driver/src/main/java/com/arangodb/internal/net/HostHandler.java similarity index 100% rename from src/main/java/com/arangodb/internal/net/HostHandler.java rename to driver/src/main/java/com/arangodb/internal/net/HostHandler.java diff --git a/src/main/java/com/arangodb/internal/net/HostImpl.java b/driver/src/main/java/com/arangodb/internal/net/HostImpl.java similarity index 100% rename from src/main/java/com/arangodb/internal/net/HostImpl.java rename to driver/src/main/java/com/arangodb/internal/net/HostImpl.java diff --git a/src/main/java/com/arangodb/internal/net/HostResolver.java b/driver/src/main/java/com/arangodb/internal/net/HostResolver.java similarity index 100% rename from src/main/java/com/arangodb/internal/net/HostResolver.java rename to driver/src/main/java/com/arangodb/internal/net/HostResolver.java diff --git a/src/main/java/com/arangodb/internal/net/HostSet.java b/driver/src/main/java/com/arangodb/internal/net/HostSet.java similarity index 100% rename from src/main/java/com/arangodb/internal/net/HostSet.java rename to driver/src/main/java/com/arangodb/internal/net/HostSet.java diff --git a/src/main/java/com/arangodb/internal/net/RandomHostHandler.java b/driver/src/main/java/com/arangodb/internal/net/RandomHostHandler.java similarity index 100% rename from src/main/java/com/arangodb/internal/net/RandomHostHandler.java rename to driver/src/main/java/com/arangodb/internal/net/RandomHostHandler.java diff --git a/src/main/java/com/arangodb/internal/net/RoundRobinHostHandler.java b/driver/src/main/java/com/arangodb/internal/net/RoundRobinHostHandler.java similarity index 100% rename from src/main/java/com/arangodb/internal/net/RoundRobinHostHandler.java rename to driver/src/main/java/com/arangodb/internal/net/RoundRobinHostHandler.java diff --git a/src/main/java/com/arangodb/internal/net/SimpleHostResolver.java b/driver/src/main/java/com/arangodb/internal/net/SimpleHostResolver.java similarity index 100% rename from src/main/java/com/arangodb/internal/net/SimpleHostResolver.java rename to driver/src/main/java/com/arangodb/internal/net/SimpleHostResolver.java diff --git a/src/main/java/com/arangodb/internal/serde/InternalAnnotationIntrospector.java b/driver/src/main/java/com/arangodb/internal/serde/InternalAnnotationIntrospector.java similarity index 100% rename from src/main/java/com/arangodb/internal/serde/InternalAnnotationIntrospector.java rename to driver/src/main/java/com/arangodb/internal/serde/InternalAnnotationIntrospector.java diff --git a/src/main/java/com/arangodb/internal/serde/InternalDeserializers.java b/driver/src/main/java/com/arangodb/internal/serde/InternalDeserializers.java similarity index 100% rename from src/main/java/com/arangodb/internal/serde/InternalDeserializers.java rename to driver/src/main/java/com/arangodb/internal/serde/InternalDeserializers.java diff --git a/src/main/java/com/arangodb/internal/serde/InternalModule.java b/driver/src/main/java/com/arangodb/internal/serde/InternalModule.java similarity index 100% rename from src/main/java/com/arangodb/internal/serde/InternalModule.java rename to driver/src/main/java/com/arangodb/internal/serde/InternalModule.java diff --git a/src/main/java/com/arangodb/internal/serde/InternalParameterizedType.java b/driver/src/main/java/com/arangodb/internal/serde/InternalParameterizedType.java similarity index 100% rename from src/main/java/com/arangodb/internal/serde/InternalParameterizedType.java rename to driver/src/main/java/com/arangodb/internal/serde/InternalParameterizedType.java diff --git a/src/main/java/com/arangodb/internal/serde/InternalSerde.java b/driver/src/main/java/com/arangodb/internal/serde/InternalSerde.java similarity index 100% rename from src/main/java/com/arangodb/internal/serde/InternalSerde.java rename to driver/src/main/java/com/arangodb/internal/serde/InternalSerde.java diff --git a/src/main/java/com/arangodb/internal/serde/InternalSerdeImpl.java b/driver/src/main/java/com/arangodb/internal/serde/InternalSerdeImpl.java similarity index 100% rename from src/main/java/com/arangodb/internal/serde/InternalSerdeImpl.java rename to driver/src/main/java/com/arangodb/internal/serde/InternalSerdeImpl.java diff --git a/src/main/java/com/arangodb/internal/serde/InternalSerializers.java b/driver/src/main/java/com/arangodb/internal/serde/InternalSerializers.java similarity index 100% rename from src/main/java/com/arangodb/internal/serde/InternalSerializers.java rename to driver/src/main/java/com/arangodb/internal/serde/InternalSerializers.java diff --git a/src/main/java/com/arangodb/internal/serde/JacksonSerdeImpl.java b/driver/src/main/java/com/arangodb/internal/serde/JacksonSerdeImpl.java similarity index 100% rename from src/main/java/com/arangodb/internal/serde/JacksonSerdeImpl.java rename to driver/src/main/java/com/arangodb/internal/serde/JacksonSerdeImpl.java diff --git a/src/main/java/com/arangodb/internal/serde/JsonMapperProvider.java b/driver/src/main/java/com/arangodb/internal/serde/JsonMapperProvider.java similarity index 100% rename from src/main/java/com/arangodb/internal/serde/JsonMapperProvider.java rename to driver/src/main/java/com/arangodb/internal/serde/JsonMapperProvider.java diff --git a/src/main/java/com/arangodb/internal/serde/MapperProvider.java b/driver/src/main/java/com/arangodb/internal/serde/MapperProvider.java similarity index 100% rename from src/main/java/com/arangodb/internal/serde/MapperProvider.java rename to driver/src/main/java/com/arangodb/internal/serde/MapperProvider.java diff --git a/src/main/java/com/arangodb/internal/serde/SerdeUtils.java b/driver/src/main/java/com/arangodb/internal/serde/SerdeUtils.java similarity index 100% rename from src/main/java/com/arangodb/internal/serde/SerdeUtils.java rename to driver/src/main/java/com/arangodb/internal/serde/SerdeUtils.java diff --git a/src/main/java/com/arangodb/internal/serde/UserData.java b/driver/src/main/java/com/arangodb/internal/serde/UserData.java similarity index 100% rename from src/main/java/com/arangodb/internal/serde/UserData.java rename to driver/src/main/java/com/arangodb/internal/serde/UserData.java diff --git a/src/main/java/com/arangodb/internal/serde/UserDataDeserializer.java b/driver/src/main/java/com/arangodb/internal/serde/UserDataDeserializer.java similarity index 100% rename from src/main/java/com/arangodb/internal/serde/UserDataDeserializer.java rename to driver/src/main/java/com/arangodb/internal/serde/UserDataDeserializer.java diff --git a/src/main/java/com/arangodb/internal/serde/UserDataInside.java b/driver/src/main/java/com/arangodb/internal/serde/UserDataInside.java similarity index 100% rename from src/main/java/com/arangodb/internal/serde/UserDataInside.java rename to driver/src/main/java/com/arangodb/internal/serde/UserDataInside.java diff --git a/src/main/java/com/arangodb/internal/serde/UserDataSerializer.java b/driver/src/main/java/com/arangodb/internal/serde/UserDataSerializer.java similarity index 100% rename from src/main/java/com/arangodb/internal/serde/UserDataSerializer.java rename to driver/src/main/java/com/arangodb/internal/serde/UserDataSerializer.java diff --git a/src/main/java/com/arangodb/internal/serde/VPackMapperProvider.java b/driver/src/main/java/com/arangodb/internal/serde/VPackMapperProvider.java similarity index 100% rename from src/main/java/com/arangodb/internal/serde/VPackMapperProvider.java rename to driver/src/main/java/com/arangodb/internal/serde/VPackMapperProvider.java diff --git a/src/main/java/com/arangodb/internal/util/DocumentUtil.java b/driver/src/main/java/com/arangodb/internal/util/DocumentUtil.java similarity index 100% rename from src/main/java/com/arangodb/internal/util/DocumentUtil.java rename to driver/src/main/java/com/arangodb/internal/util/DocumentUtil.java diff --git a/src/main/java/com/arangodb/internal/util/EncodeUtils.java b/driver/src/main/java/com/arangodb/internal/util/EncodeUtils.java similarity index 100% rename from src/main/java/com/arangodb/internal/util/EncodeUtils.java rename to driver/src/main/java/com/arangodb/internal/util/EncodeUtils.java diff --git a/src/main/java/com/arangodb/internal/util/HostUtils.java b/driver/src/main/java/com/arangodb/internal/util/HostUtils.java similarity index 100% rename from src/main/java/com/arangodb/internal/util/HostUtils.java rename to driver/src/main/java/com/arangodb/internal/util/HostUtils.java diff --git a/src/main/java/com/arangodb/internal/util/RequestUtils.java b/driver/src/main/java/com/arangodb/internal/util/RequestUtils.java similarity index 100% rename from src/main/java/com/arangodb/internal/util/RequestUtils.java rename to driver/src/main/java/com/arangodb/internal/util/RequestUtils.java diff --git a/src/main/java/com/arangodb/internal/util/ResponseUtils.java b/driver/src/main/java/com/arangodb/internal/util/ResponseUtils.java similarity index 100% rename from src/main/java/com/arangodb/internal/util/ResponseUtils.java rename to driver/src/main/java/com/arangodb/internal/util/ResponseUtils.java diff --git a/src/main/java/com/arangodb/internal/velocystream/VstCommunication.java b/driver/src/main/java/com/arangodb/internal/velocystream/VstCommunication.java similarity index 100% rename from src/main/java/com/arangodb/internal/velocystream/VstCommunication.java rename to driver/src/main/java/com/arangodb/internal/velocystream/VstCommunication.java diff --git a/src/main/java/com/arangodb/internal/velocystream/VstCommunicationSync.java b/driver/src/main/java/com/arangodb/internal/velocystream/VstCommunicationSync.java similarity index 100% rename from src/main/java/com/arangodb/internal/velocystream/VstCommunicationSync.java rename to driver/src/main/java/com/arangodb/internal/velocystream/VstCommunicationSync.java diff --git a/src/main/java/com/arangodb/internal/velocystream/VstConnectionFactorySync.java b/driver/src/main/java/com/arangodb/internal/velocystream/VstConnectionFactorySync.java similarity index 100% rename from src/main/java/com/arangodb/internal/velocystream/VstConnectionFactorySync.java rename to driver/src/main/java/com/arangodb/internal/velocystream/VstConnectionFactorySync.java diff --git a/src/main/java/com/arangodb/internal/velocystream/VstProtocol.java b/driver/src/main/java/com/arangodb/internal/velocystream/VstProtocol.java similarity index 100% rename from src/main/java/com/arangodb/internal/velocystream/VstProtocol.java rename to driver/src/main/java/com/arangodb/internal/velocystream/VstProtocol.java diff --git a/src/main/java/com/arangodb/internal/velocystream/internal/AuthenticationRequest.java b/driver/src/main/java/com/arangodb/internal/velocystream/internal/AuthenticationRequest.java similarity index 96% rename from src/main/java/com/arangodb/internal/velocystream/internal/AuthenticationRequest.java rename to driver/src/main/java/com/arangodb/internal/velocystream/internal/AuthenticationRequest.java index 8e8310791..dd48dbc4b 100644 --- a/src/main/java/com/arangodb/internal/velocystream/internal/AuthenticationRequest.java +++ b/driver/src/main/java/com/arangodb/internal/velocystream/internal/AuthenticationRequest.java @@ -1,55 +1,55 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.internal.velocystream.internal; - -import com.arangodb.DbName; -import com.arangodb.Request; - -/** - * @author Mark Vollmary - */ -public class AuthenticationRequest extends Request { - - private final String user; - private final String password; - private final String encryption;// "plain" - - public AuthenticationRequest(final String user, final String password, final String encryption) { - super(DbName.of(null), null, null); - this.user = user; - this.password = password; - this.encryption = encryption; - setType(1000); - } - - public String getUser() { - return user; - } - - public String getPassword() { - return password; - } - - public String getEncryption() { - return encryption; - } - -} +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed 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. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.internal.velocystream.internal; + +import com.arangodb.DbName; +import com.arangodb.Request; + +/** + * @author Mark Vollmary + */ +public class AuthenticationRequest extends Request { + + private final String user; + private final String password; + private final String encryption;// "plain" + + public AuthenticationRequest(final String user, final String password, final String encryption) { + super(DbName.of(null), null, null); + this.user = user; + this.password = password; + this.encryption = encryption; + setType(1000); + } + + public String getUser() { + return user; + } + + public String getPassword() { + return password; + } + + public String getEncryption() { + return encryption; + } + +} diff --git a/src/main/java/com/arangodb/internal/velocystream/internal/Chunk.java b/driver/src/main/java/com/arangodb/internal/velocystream/internal/Chunk.java similarity index 96% rename from src/main/java/com/arangodb/internal/velocystream/internal/Chunk.java rename to driver/src/main/java/com/arangodb/internal/velocystream/internal/Chunk.java index 4b0689e93..294aa18bb 100644 --- a/src/main/java/com/arangodb/internal/velocystream/internal/Chunk.java +++ b/driver/src/main/java/com/arangodb/internal/velocystream/internal/Chunk.java @@ -1,88 +1,88 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.internal.velocystream.internal; - -/** - * @author Mark Vollmary - */ -public class Chunk { - - private final long messageId; - private final long messageLength; - private final int chunkX; - private final int contentOffset; - private final int contentLength; - - public Chunk(final long messageId, final int chunkX, final long messageLength, final int contentOffset, - final int contentLength) { - this.messageId = messageId; - this.chunkX = chunkX; - this.messageLength = messageLength; - this.contentOffset = contentOffset; - this.contentLength = contentLength; - } - - public Chunk(final long messageId, final int chunkIndex, final int numberOfChunks, final long messageLength, - final int contentOffset, final int contentLength) { - this(messageId, chunkX(chunkIndex, numberOfChunks), messageLength, contentOffset, contentLength); - } - - private static int chunkX(final int chunkIndex, final int numberOfChunks) { - int chunkX; - if (numberOfChunks == 1) { - chunkX = 3;// last byte: 0000 0011 - } else if (chunkIndex == 0) { - chunkX = (numberOfChunks << 1) + 1; - } else { - chunkX = chunkIndex << 1; - } - return chunkX; - } - - public long getMessageId() { - return messageId; - } - - public long getMessageLength() { - return messageLength; - } - - public boolean isFirstChunk() { - return 1 == (chunkX & 0x1); - } - - public int getChunk() { - return chunkX >> 1; - } - - public int getChunkX() { - return chunkX; - } - - public int getContentOffset() { - return contentOffset; - } - - public int getContentLength() { - return contentLength; - } - -} +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed 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. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.internal.velocystream.internal; + +/** + * @author Mark Vollmary + */ +public class Chunk { + + private final long messageId; + private final long messageLength; + private final int chunkX; + private final int contentOffset; + private final int contentLength; + + public Chunk(final long messageId, final int chunkX, final long messageLength, final int contentOffset, + final int contentLength) { + this.messageId = messageId; + this.chunkX = chunkX; + this.messageLength = messageLength; + this.contentOffset = contentOffset; + this.contentLength = contentLength; + } + + public Chunk(final long messageId, final int chunkIndex, final int numberOfChunks, final long messageLength, + final int contentOffset, final int contentLength) { + this(messageId, chunkX(chunkIndex, numberOfChunks), messageLength, contentOffset, contentLength); + } + + private static int chunkX(final int chunkIndex, final int numberOfChunks) { + int chunkX; + if (numberOfChunks == 1) { + chunkX = 3;// last byte: 0000 0011 + } else if (chunkIndex == 0) { + chunkX = (numberOfChunks << 1) + 1; + } else { + chunkX = chunkIndex << 1; + } + return chunkX; + } + + public long getMessageId() { + return messageId; + } + + public long getMessageLength() { + return messageLength; + } + + public boolean isFirstChunk() { + return 1 == (chunkX & 0x1); + } + + public int getChunk() { + return chunkX >> 1; + } + + public int getChunkX() { + return chunkX; + } + + public int getContentOffset() { + return contentOffset; + } + + public int getContentLength() { + return contentLength; + } + +} diff --git a/src/main/java/com/arangodb/internal/velocystream/internal/ChunkStore.java b/driver/src/main/java/com/arangodb/internal/velocystream/internal/ChunkStore.java similarity index 97% rename from src/main/java/com/arangodb/internal/velocystream/internal/ChunkStore.java rename to driver/src/main/java/com/arangodb/internal/velocystream/internal/ChunkStore.java index e636b9e68..e95be998b 100644 --- a/src/main/java/com/arangodb/internal/velocystream/internal/ChunkStore.java +++ b/driver/src/main/java/com/arangodb/internal/velocystream/internal/ChunkStore.java @@ -1,70 +1,70 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.internal.velocystream.internal; - -import java.nio.BufferUnderflowException; -import java.nio.ByteBuffer; -import java.util.HashMap; -import java.util.Map; - -/** - * @author Mark Vollmary - */ -public class ChunkStore { - - private final MessageStore messageStore; - private final Map data; - - public ChunkStore(final MessageStore messageStore) { - super(); - this.messageStore = messageStore; - data = new HashMap<>(); - } - - public ByteBuffer storeChunk(final Chunk chunk) throws BufferUnderflowException, IndexOutOfBoundsException { - final long messageId = chunk.getMessageId(); - ByteBuffer chunkBuffer = data.get(messageId); - if (chunkBuffer == null) { - if (!chunk.isFirstChunk()) { - messageStore.cancel(messageId); - return null; - } - final int length = (int) (chunk.getMessageLength() > 0 ? chunk.getMessageLength() - : chunk.getContentLength()); - chunkBuffer = ByteBuffer.allocate(length); - data.put(messageId, chunkBuffer); - } - return chunkBuffer; - } - - public void checkCompleteness(final long messageId) { - checkCompleteness(messageId, data.get(messageId)); - } - - private void checkCompleteness(final long messageId, final ByteBuffer chunkBuffer) - throws BufferUnderflowException, IndexOutOfBoundsException { - if (chunkBuffer.position() == chunkBuffer.limit()) { - messageStore.consume(new Message(messageId, chunkBuffer.array())); - data.remove(messageId); - } - } - -} +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed 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. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.internal.velocystream.internal; + +import java.nio.BufferUnderflowException; +import java.nio.ByteBuffer; +import java.util.HashMap; +import java.util.Map; + +/** + * @author Mark Vollmary + */ +public class ChunkStore { + + private final MessageStore messageStore; + private final Map data; + + public ChunkStore(final MessageStore messageStore) { + super(); + this.messageStore = messageStore; + data = new HashMap<>(); + } + + public ByteBuffer storeChunk(final Chunk chunk) throws BufferUnderflowException, IndexOutOfBoundsException { + final long messageId = chunk.getMessageId(); + ByteBuffer chunkBuffer = data.get(messageId); + if (chunkBuffer == null) { + if (!chunk.isFirstChunk()) { + messageStore.cancel(messageId); + return null; + } + final int length = (int) (chunk.getMessageLength() > 0 ? chunk.getMessageLength() + : chunk.getContentLength()); + chunkBuffer = ByteBuffer.allocate(length); + data.put(messageId, chunkBuffer); + } + return chunkBuffer; + } + + public void checkCompleteness(final long messageId) { + checkCompleteness(messageId, data.get(messageId)); + } + + private void checkCompleteness(final long messageId, final ByteBuffer chunkBuffer) + throws BufferUnderflowException, IndexOutOfBoundsException { + if (chunkBuffer.position() == chunkBuffer.limit()) { + messageStore.consume(new Message(messageId, chunkBuffer.array())); + data.remove(messageId); + } + } + +} diff --git a/src/main/java/com/arangodb/internal/velocystream/internal/JwtAuthenticationRequest.java b/driver/src/main/java/com/arangodb/internal/velocystream/internal/JwtAuthenticationRequest.java similarity index 100% rename from src/main/java/com/arangodb/internal/velocystream/internal/JwtAuthenticationRequest.java rename to driver/src/main/java/com/arangodb/internal/velocystream/internal/JwtAuthenticationRequest.java diff --git a/src/main/java/com/arangodb/internal/velocystream/internal/Message.java b/driver/src/main/java/com/arangodb/internal/velocystream/internal/Message.java similarity index 96% rename from src/main/java/com/arangodb/internal/velocystream/internal/Message.java rename to driver/src/main/java/com/arangodb/internal/velocystream/internal/Message.java index 5a2e74724..b2b7cc34e 100644 --- a/src/main/java/com/arangodb/internal/velocystream/internal/Message.java +++ b/driver/src/main/java/com/arangodb/internal/velocystream/internal/Message.java @@ -1,67 +1,67 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.internal.velocystream.internal; - -import com.arangodb.velocypack.VPackSlice; - -import java.nio.BufferUnderflowException; - -/** - * @author Mark Vollmary - */ -public class Message { - - private final long id; - private final VPackSlice head; - private final VPackSlice body; - - public Message(final long id, final byte[] chunkBuffer) throws BufferUnderflowException, IndexOutOfBoundsException { - super(); - this.id = id; - head = new VPackSlice(chunkBuffer); - final int headSize = head.getByteSize(); - if (chunkBuffer.length > headSize) { - body = new VPackSlice(chunkBuffer, headSize); - } else { - body = null; - } - } - - public Message(final long id, final byte[] head, final byte[] body) { - super(); - this.id = id; - this.head = new VPackSlice(head); - this.body = body != null ? new VPackSlice(body) : null; - } - - public long getId() { - return id; - } - - public VPackSlice getHead() { - return head; - } - - public VPackSlice getBody() { - return body; - } - -} +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed 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. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.internal.velocystream.internal; + +import com.arangodb.velocypack.VPackSlice; + +import java.nio.BufferUnderflowException; + +/** + * @author Mark Vollmary + */ +public class Message { + + private final long id; + private final VPackSlice head; + private final VPackSlice body; + + public Message(final long id, final byte[] chunkBuffer) throws BufferUnderflowException, IndexOutOfBoundsException { + super(); + this.id = id; + head = new VPackSlice(chunkBuffer); + final int headSize = head.getByteSize(); + if (chunkBuffer.length > headSize) { + body = new VPackSlice(chunkBuffer, headSize); + } else { + body = null; + } + } + + public Message(final long id, final byte[] head, final byte[] body) { + super(); + this.id = id; + this.head = new VPackSlice(head); + this.body = body != null ? new VPackSlice(body) : null; + } + + public long getId() { + return id; + } + + public VPackSlice getHead() { + return head; + } + + public VPackSlice getBody() { + return body; + } + +} diff --git a/src/main/java/com/arangodb/internal/velocystream/internal/MessageStore.java b/driver/src/main/java/com/arangodb/internal/velocystream/internal/MessageStore.java similarity index 96% rename from src/main/java/com/arangodb/internal/velocystream/internal/MessageStore.java rename to driver/src/main/java/com/arangodb/internal/velocystream/internal/MessageStore.java index d9391b9b8..62fd4ae2a 100644 --- a/src/main/java/com/arangodb/internal/velocystream/internal/MessageStore.java +++ b/driver/src/main/java/com/arangodb/internal/velocystream/internal/MessageStore.java @@ -1,112 +1,112 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.internal.velocystream.internal; - -import com.arangodb.ArangoDBException; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.Map; -import java.util.Map.Entry; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.FutureTask; - -/** - * @author Mark Vollmary - */ -public class MessageStore { - - private static final Logger LOGGER = LoggerFactory.getLogger(MessageStore.class); - - private final Map> task; - private final Map response; - private final Map error; - - public MessageStore() { - super(); - task = new ConcurrentHashMap<>(); - response = new ConcurrentHashMap<>(); - error = new ConcurrentHashMap<>(); - } - - public void storeMessage(final long messageId, final FutureTask future) { - task.put(messageId, future); - } - - public void consume(final Message message) { - final FutureTask future = task.remove(message.getId()); - if (future != null) { - if (LOGGER.isDebugEnabled()) { - LOGGER.debug(String.format("Received Message (id=%s, head=%s, body=%s)", message.getId(), - message.getHead(), message.getBody() != null ? message.getBody() : "{}")); - } - response.put(message.getId(), message); - future.run(); - } - } - - public Message get(final long messageId) { - final Message result = response.remove(messageId); - if (result == null) { - final Exception e = error.remove(messageId); - if (e != null) { - throw new ArangoDBException(e); - } - } - return result; - } - - public void cancel(final long messageId) { - final FutureTask future = task.remove(messageId); - if (future != null) { - LOGGER.error("Cancel Message unexpected (id={}).", messageId); - future.cancel(true); - } - } - - public synchronized void clear(final Exception e) { - if (!task.isEmpty()) { - LOGGER.error(e.getMessage(), e); - } - for (final Entry> entry : task.entrySet()) { - if (LOGGER.isDebugEnabled()) { - LOGGER.debug(String.format("Exceptionally complete Message (id=%s).", entry.getKey())); - } - error.put(entry.getKey(), e); - entry.getValue().run(); - } - task.clear(); - } - - public synchronized void clear() { - for (final Entry> entry : task.entrySet()) { - if (LOGGER.isDebugEnabled()) { - LOGGER.debug(String.format("Cancel Message (id=%s).", entry.getKey())); - } - entry.getValue().cancel(true); - } - task.clear(); - } - - public boolean isEmpty() { - return task.isEmpty(); - } -} +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed 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. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.internal.velocystream.internal; + +import com.arangodb.ArangoDBException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Map; +import java.util.Map.Entry; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.FutureTask; + +/** + * @author Mark Vollmary + */ +public class MessageStore { + + private static final Logger LOGGER = LoggerFactory.getLogger(MessageStore.class); + + private final Map> task; + private final Map response; + private final Map error; + + public MessageStore() { + super(); + task = new ConcurrentHashMap<>(); + response = new ConcurrentHashMap<>(); + error = new ConcurrentHashMap<>(); + } + + public void storeMessage(final long messageId, final FutureTask future) { + task.put(messageId, future); + } + + public void consume(final Message message) { + final FutureTask future = task.remove(message.getId()); + if (future != null) { + if (LOGGER.isDebugEnabled()) { + LOGGER.debug(String.format("Received Message (id=%s, head=%s, body=%s)", message.getId(), + message.getHead(), message.getBody() != null ? message.getBody() : "{}")); + } + response.put(message.getId(), message); + future.run(); + } + } + + public Message get(final long messageId) { + final Message result = response.remove(messageId); + if (result == null) { + final Exception e = error.remove(messageId); + if (e != null) { + throw new ArangoDBException(e); + } + } + return result; + } + + public void cancel(final long messageId) { + final FutureTask future = task.remove(messageId); + if (future != null) { + LOGGER.error("Cancel Message unexpected (id={}).", messageId); + future.cancel(true); + } + } + + public synchronized void clear(final Exception e) { + if (!task.isEmpty()) { + LOGGER.error(e.getMessage(), e); + } + for (final Entry> entry : task.entrySet()) { + if (LOGGER.isDebugEnabled()) { + LOGGER.debug(String.format("Exceptionally complete Message (id=%s).", entry.getKey())); + } + error.put(entry.getKey(), e); + entry.getValue().run(); + } + task.clear(); + } + + public synchronized void clear() { + for (final Entry> entry : task.entrySet()) { + if (LOGGER.isDebugEnabled()) { + LOGGER.debug(String.format("Cancel Message (id=%s).", entry.getKey())); + } + entry.getValue().cancel(true); + } + task.clear(); + } + + public boolean isEmpty() { + return task.isEmpty(); + } +} diff --git a/src/main/java/com/arangodb/internal/velocystream/internal/VstConnection.java b/driver/src/main/java/com/arangodb/internal/velocystream/internal/VstConnection.java similarity index 100% rename from src/main/java/com/arangodb/internal/velocystream/internal/VstConnection.java rename to driver/src/main/java/com/arangodb/internal/velocystream/internal/VstConnection.java diff --git a/src/main/java/com/arangodb/internal/velocystream/internal/VstConnectionSync.java b/driver/src/main/java/com/arangodb/internal/velocystream/internal/VstConnectionSync.java similarity index 100% rename from src/main/java/com/arangodb/internal/velocystream/internal/VstConnectionSync.java rename to driver/src/main/java/com/arangodb/internal/velocystream/internal/VstConnectionSync.java diff --git a/src/main/java/com/arangodb/model/AqlFunctionCreateOptions.java b/driver/src/main/java/com/arangodb/model/AqlFunctionCreateOptions.java similarity index 96% rename from src/main/java/com/arangodb/model/AqlFunctionCreateOptions.java rename to driver/src/main/java/com/arangodb/model/AqlFunctionCreateOptions.java index 23e6e5f4c..14c7fe999 100644 --- a/src/main/java/com/arangodb/model/AqlFunctionCreateOptions.java +++ b/driver/src/main/java/com/arangodb/model/AqlFunctionCreateOptions.java @@ -1,81 +1,81 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.model; - -/** - * @author Mark Vollmary - * @see API - * Documentation - */ -public final class AqlFunctionCreateOptions { - - private String name; - private String code; - private Boolean isDeterministic; - - public AqlFunctionCreateOptions() { - super(); - } - - /** - * @param name the fully qualified name of the user functions - * @return options - */ - AqlFunctionCreateOptions name(final String name) { - this.name = name; - return this; - } - - public String getName() { - return name; - } - - /** - * @param code a string representation of the function body - * @return options - */ - AqlFunctionCreateOptions code(final String code) { - this.code = code; - return this; - } - - public String getCode() { - return code; - } - - /** - * @param isDeterministic an optional boolean value to indicate that the function results are fully deterministic - * (function - * return value solely depends on the input value and return value is the same for - * repeated calls with - * same input) - * @return options - */ - public AqlFunctionCreateOptions isDeterministic(final Boolean isDeterministic) { - this.isDeterministic = isDeterministic; - return this; - } - - public Boolean getIsDeterministic() { - return isDeterministic; - } - -} +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed 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. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.model; + +/** + * @author Mark Vollmary + * @see API + * Documentation + */ +public final class AqlFunctionCreateOptions { + + private String name; + private String code; + private Boolean isDeterministic; + + public AqlFunctionCreateOptions() { + super(); + } + + /** + * @param name the fully qualified name of the user functions + * @return options + */ + AqlFunctionCreateOptions name(final String name) { + this.name = name; + return this; + } + + public String getName() { + return name; + } + + /** + * @param code a string representation of the function body + * @return options + */ + AqlFunctionCreateOptions code(final String code) { + this.code = code; + return this; + } + + public String getCode() { + return code; + } + + /** + * @param isDeterministic an optional boolean value to indicate that the function results are fully deterministic + * (function + * return value solely depends on the input value and return value is the same for + * repeated calls with + * same input) + * @return options + */ + public AqlFunctionCreateOptions isDeterministic(final Boolean isDeterministic) { + this.isDeterministic = isDeterministic; + return this; + } + + public Boolean getIsDeterministic() { + return isDeterministic; + } + +} diff --git a/src/main/java/com/arangodb/model/AqlFunctionDeleteOptions.java b/driver/src/main/java/com/arangodb/model/AqlFunctionDeleteOptions.java similarity index 96% rename from src/main/java/com/arangodb/model/AqlFunctionDeleteOptions.java rename to driver/src/main/java/com/arangodb/model/AqlFunctionDeleteOptions.java index f821c7e78..42affff7a 100644 --- a/src/main/java/com/arangodb/model/AqlFunctionDeleteOptions.java +++ b/driver/src/main/java/com/arangodb/model/AqlFunctionDeleteOptions.java @@ -1,52 +1,52 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.model; - -/** - * @author Mark Vollmary - * @see API - * Documentation - */ -public final class AqlFunctionDeleteOptions { - - private Boolean group; - - public AqlFunctionDeleteOptions() { - super(); - } - - public Boolean getGroup() { - return group; - } - - /** - * @param group If set to true, then the function name provided in name is treated as a namespace prefix, and all - * functions in the specified namespace will be deleted. If set to false, the function name provided in - * name must be fully qualified, including any namespaces. - * @return options - */ - public AqlFunctionDeleteOptions group(final Boolean group) { - this.group = group; - return this; - } - -} +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed 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. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.model; + +/** + * @author Mark Vollmary + * @see API + * Documentation + */ +public final class AqlFunctionDeleteOptions { + + private Boolean group; + + public AqlFunctionDeleteOptions() { + super(); + } + + public Boolean getGroup() { + return group; + } + + /** + * @param group If set to true, then the function name provided in name is treated as a namespace prefix, and all + * functions in the specified namespace will be deleted. If set to false, the function name provided in + * name must be fully qualified, including any namespaces. + * @return options + */ + public AqlFunctionDeleteOptions group(final Boolean group) { + this.group = group; + return this; + } + +} diff --git a/src/main/java/com/arangodb/model/AqlFunctionGetOptions.java b/driver/src/main/java/com/arangodb/model/AqlFunctionGetOptions.java similarity index 96% rename from src/main/java/com/arangodb/model/AqlFunctionGetOptions.java rename to driver/src/main/java/com/arangodb/model/AqlFunctionGetOptions.java index a043bb60e..87146d99d 100644 --- a/src/main/java/com/arangodb/model/AqlFunctionGetOptions.java +++ b/driver/src/main/java/com/arangodb/model/AqlFunctionGetOptions.java @@ -1,50 +1,50 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.model; - -/** - * @author Mark Vollmary - * @see API - * Documentation - */ -public final class AqlFunctionGetOptions { - - private String namespace; - - public AqlFunctionGetOptions() { - super(); - } - - public String getNamespace() { - return namespace; - } - - /** - * @param namespace Returns all registered AQL user functions from namespace - * @return options - */ - public AqlFunctionGetOptions namespace(final String namespace) { - this.namespace = namespace; - return this; - } - -} +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed 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. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.model; + +/** + * @author Mark Vollmary + * @see API + * Documentation + */ +public final class AqlFunctionGetOptions { + + private String namespace; + + public AqlFunctionGetOptions() { + super(); + } + + public String getNamespace() { + return namespace; + } + + /** + * @param namespace Returns all registered AQL user functions from namespace + * @return options + */ + public AqlFunctionGetOptions namespace(final String namespace) { + this.namespace = namespace; + return this; + } + +} diff --git a/src/main/java/com/arangodb/model/AqlQueryExplainOptions.java b/driver/src/main/java/com/arangodb/model/AqlQueryExplainOptions.java similarity index 96% rename from src/main/java/com/arangodb/model/AqlQueryExplainOptions.java rename to driver/src/main/java/com/arangodb/model/AqlQueryExplainOptions.java index a0f58805d..0c7d4bfff 100644 --- a/src/main/java/com/arangodb/model/AqlQueryExplainOptions.java +++ b/driver/src/main/java/com/arangodb/model/AqlQueryExplainOptions.java @@ -1,137 +1,137 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.model; - -import com.arangodb.internal.serde.UserDataInside; - -import java.util.Collection; -import java.util.Map; - -/** - * @author Mark Vollmary - * @author Michele Rastelli - * @see API Documentation - */ -public final class AqlQueryExplainOptions { - - private Map bindVars; - private String query; - private Options options; - - public AqlQueryExplainOptions() { - super(); - } - - @UserDataInside - public Map getBindVars() { - return bindVars; - } - - /** - * @param bindVars key/value pairs representing the bind parameters - * @return options - */ - AqlQueryExplainOptions bindVars(final Map bindVars) { - this.bindVars = bindVars; - return this; - } - - public String getQuery() { - return query; - } - - /** - * @param query the query which you want explained - * @return options - */ - AqlQueryExplainOptions query(final String query) { - this.query = query; - return this; - } - - public Integer getMaxNumberOfPlans() { - return getOptions().maxNumberOfPlans; - } - - /** - * @param maxNumberOfPlans an optional maximum number of plans that the optimizer is allowed to generate. Setting - * this attribute - * to a low value allows to put a cap on the amount of work the optimizer does. - * @return options - */ - public AqlQueryExplainOptions maxNumberOfPlans(final Integer maxNumberOfPlans) { - getOptions().maxNumberOfPlans = maxNumberOfPlans; - return this; - } - - public Boolean getAllPlans() { - return getOptions().allPlans; - } - - /** - * @param allPlans if set to true, all possible execution plans will be returned. The default is false, meaning - * only the - * optimal plan will be returned. - * @return options - */ - public AqlQueryExplainOptions allPlans(final Boolean allPlans) { - getOptions().allPlans = allPlans; - return this; - } - - public Collection getRules() { - return getOptions().getOptimizer().rules; - } - - /** - * @param rules an array of to-be-included or to-be-excluded optimizer rules can be put into this attribute, telling - * the optimizer to include or exclude specific rules. - * @return options - */ - public AqlQueryExplainOptions rules(final Collection rules) { - getOptions().getOptimizer().rules = rules; - return this; - } - - private Options getOptions() { - if (options == null) { - options = new Options(); - } - return options; - } - - public static final class Options { - private Optimizer optimizer; - private Integer maxNumberOfPlans; - private Boolean allPlans; - - public Optimizer getOptimizer() { - if (optimizer == null) { - optimizer = new Optimizer(); - } - return optimizer; - } - } - - public static final class Optimizer { - private Collection rules; - } -} +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed 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. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.model; + +import com.arangodb.internal.serde.UserDataInside; + +import java.util.Collection; +import java.util.Map; + +/** + * @author Mark Vollmary + * @author Michele Rastelli + * @see API Documentation + */ +public final class AqlQueryExplainOptions { + + private Map bindVars; + private String query; + private Options options; + + public AqlQueryExplainOptions() { + super(); + } + + @UserDataInside + public Map getBindVars() { + return bindVars; + } + + /** + * @param bindVars key/value pairs representing the bind parameters + * @return options + */ + AqlQueryExplainOptions bindVars(final Map bindVars) { + this.bindVars = bindVars; + return this; + } + + public String getQuery() { + return query; + } + + /** + * @param query the query which you want explained + * @return options + */ + AqlQueryExplainOptions query(final String query) { + this.query = query; + return this; + } + + public Integer getMaxNumberOfPlans() { + return getOptions().maxNumberOfPlans; + } + + /** + * @param maxNumberOfPlans an optional maximum number of plans that the optimizer is allowed to generate. Setting + * this attribute + * to a low value allows to put a cap on the amount of work the optimizer does. + * @return options + */ + public AqlQueryExplainOptions maxNumberOfPlans(final Integer maxNumberOfPlans) { + getOptions().maxNumberOfPlans = maxNumberOfPlans; + return this; + } + + public Boolean getAllPlans() { + return getOptions().allPlans; + } + + /** + * @param allPlans if set to true, all possible execution plans will be returned. The default is false, meaning + * only the + * optimal plan will be returned. + * @return options + */ + public AqlQueryExplainOptions allPlans(final Boolean allPlans) { + getOptions().allPlans = allPlans; + return this; + } + + public Collection getRules() { + return getOptions().getOptimizer().rules; + } + + /** + * @param rules an array of to-be-included or to-be-excluded optimizer rules can be put into this attribute, telling + * the optimizer to include or exclude specific rules. + * @return options + */ + public AqlQueryExplainOptions rules(final Collection rules) { + getOptions().getOptimizer().rules = rules; + return this; + } + + private Options getOptions() { + if (options == null) { + options = new Options(); + } + return options; + } + + public static final class Options { + private Optimizer optimizer; + private Integer maxNumberOfPlans; + private Boolean allPlans; + + public Optimizer getOptimizer() { + if (optimizer == null) { + optimizer = new Optimizer(); + } + return optimizer; + } + } + + public static final class Optimizer { + private Collection rules; + } +} diff --git a/src/main/java/com/arangodb/model/AqlQueryOptions.java b/driver/src/main/java/com/arangodb/model/AqlQueryOptions.java similarity index 100% rename from src/main/java/com/arangodb/model/AqlQueryOptions.java rename to driver/src/main/java/com/arangodb/model/AqlQueryOptions.java diff --git a/src/main/java/com/arangodb/model/AqlQueryParseOptions.java b/driver/src/main/java/com/arangodb/model/AqlQueryParseOptions.java similarity index 96% rename from src/main/java/com/arangodb/model/AqlQueryParseOptions.java rename to driver/src/main/java/com/arangodb/model/AqlQueryParseOptions.java index a5a4b22b1..064fa0685 100644 --- a/src/main/java/com/arangodb/model/AqlQueryParseOptions.java +++ b/driver/src/main/java/com/arangodb/model/AqlQueryParseOptions.java @@ -1,48 +1,48 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.model; - -/** - * @author Mark Vollmary - * @see API Documentation - */ -public final class AqlQueryParseOptions { - - private String query; - - public AqlQueryParseOptions() { - super(); - } - - public String getQuery() { - return query; - } - - /** - * @param query the query which you want parse - * @return options - */ - AqlQueryParseOptions query(final String query) { - this.query = query; - return this; - } - -} +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed 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. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.model; + +/** + * @author Mark Vollmary + * @see API Documentation + */ +public final class AqlQueryParseOptions { + + private String query; + + public AqlQueryParseOptions() { + super(); + } + + public String getQuery() { + return query; + } + + /** + * @param query the query which you want parse + * @return options + */ + AqlQueryParseOptions query(final String query) { + this.query = query; + return this; + } + +} diff --git a/src/main/java/com/arangodb/model/CollectionCountOptions.java b/driver/src/main/java/com/arangodb/model/CollectionCountOptions.java similarity index 100% rename from src/main/java/com/arangodb/model/CollectionCountOptions.java rename to driver/src/main/java/com/arangodb/model/CollectionCountOptions.java diff --git a/src/main/java/com/arangodb/model/CollectionCreateOptions.java b/driver/src/main/java/com/arangodb/model/CollectionCreateOptions.java similarity index 100% rename from src/main/java/com/arangodb/model/CollectionCreateOptions.java rename to driver/src/main/java/com/arangodb/model/CollectionCreateOptions.java diff --git a/src/main/java/com/arangodb/model/CollectionPropertiesOptions.java b/driver/src/main/java/com/arangodb/model/CollectionPropertiesOptions.java similarity index 96% rename from src/main/java/com/arangodb/model/CollectionPropertiesOptions.java rename to driver/src/main/java/com/arangodb/model/CollectionPropertiesOptions.java index d83109e24..a3144b9f4 100644 --- a/src/main/java/com/arangodb/model/CollectionPropertiesOptions.java +++ b/driver/src/main/java/com/arangodb/model/CollectionPropertiesOptions.java @@ -1,87 +1,87 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.model; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -/** - * @author Mark Vollmary - * @see - * API - * Documentation - */ -public final class CollectionPropertiesOptions { - - private Boolean waitForSync; - private CollectionSchema schema; - private List computedValues; - - public CollectionPropertiesOptions() { - super(); - } - - public Boolean getWaitForSync() { - return waitForSync; - } - - /** - * @param waitForSync If true then creating or changing a document will wait until the data has been synchronized - * to disk. - * @return options - */ - public CollectionPropertiesOptions waitForSync(final Boolean waitForSync) { - this.waitForSync = waitForSync; - return this; - } - - public CollectionSchema getSchema() { - return schema; - } - - /** - * @param schema object that specifies the collection level schema for documents - * @return options - * @since ArangoDB 3.7 - */ - public CollectionPropertiesOptions schema(final CollectionSchema schema) { - this.schema = schema; - return this; - } - - /** - * @param computedValues An optional list of computed values. - * @return options - * @since ArangoDB 3.10 - */ - public CollectionPropertiesOptions computedValues(final ComputedValue... computedValues) { - if(this.computedValues == null) { - this.computedValues = new ArrayList<>(); - } - Collections.addAll(this.computedValues, computedValues); - return this; - } - - public List getComputedValues() { - return computedValues; - } -} +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed 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. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.model; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +/** + * @author Mark Vollmary + * @see + * API + * Documentation + */ +public final class CollectionPropertiesOptions { + + private Boolean waitForSync; + private CollectionSchema schema; + private List computedValues; + + public CollectionPropertiesOptions() { + super(); + } + + public Boolean getWaitForSync() { + return waitForSync; + } + + /** + * @param waitForSync If true then creating or changing a document will wait until the data has been synchronized + * to disk. + * @return options + */ + public CollectionPropertiesOptions waitForSync(final Boolean waitForSync) { + this.waitForSync = waitForSync; + return this; + } + + public CollectionSchema getSchema() { + return schema; + } + + /** + * @param schema object that specifies the collection level schema for documents + * @return options + * @since ArangoDB 3.7 + */ + public CollectionPropertiesOptions schema(final CollectionSchema schema) { + this.schema = schema; + return this; + } + + /** + * @param computedValues An optional list of computed values. + * @return options + * @since ArangoDB 3.10 + */ + public CollectionPropertiesOptions computedValues(final ComputedValue... computedValues) { + if(this.computedValues == null) { + this.computedValues = new ArrayList<>(); + } + Collections.addAll(this.computedValues, computedValues); + return this; + } + + public List getComputedValues() { + return computedValues; + } +} diff --git a/src/main/java/com/arangodb/model/CollectionRenameOptions.java b/driver/src/main/java/com/arangodb/model/CollectionRenameOptions.java similarity index 95% rename from src/main/java/com/arangodb/model/CollectionRenameOptions.java rename to driver/src/main/java/com/arangodb/model/CollectionRenameOptions.java index 11f531e28..6748f811f 100644 --- a/src/main/java/com/arangodb/model/CollectionRenameOptions.java +++ b/driver/src/main/java/com/arangodb/model/CollectionRenameOptions.java @@ -1,47 +1,47 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.model; - -/** - * @author Mark Vollmary - */ -public final class CollectionRenameOptions { - - private String name; - - public CollectionRenameOptions() { - super(); - } - - public String getName() { - return name; - } - - /** - * @param name The new name - * @return options - */ - CollectionRenameOptions name(final String name) { - this.name = name; - return this; - } - -} +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed 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. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.model; + +/** + * @author Mark Vollmary + */ +public final class CollectionRenameOptions { + + private String name; + + public CollectionRenameOptions() { + super(); + } + + public String getName() { + return name; + } + + /** + * @param name The new name + * @return options + */ + CollectionRenameOptions name(final String name) { + this.name = name; + return this; + } + +} diff --git a/src/main/java/com/arangodb/model/CollectionSchema.java b/driver/src/main/java/com/arangodb/model/CollectionSchema.java similarity index 100% rename from src/main/java/com/arangodb/model/CollectionSchema.java rename to driver/src/main/java/com/arangodb/model/CollectionSchema.java diff --git a/src/main/java/com/arangodb/model/CollectionTruncateOptions.java b/driver/src/main/java/com/arangodb/model/CollectionTruncateOptions.java similarity index 100% rename from src/main/java/com/arangodb/model/CollectionTruncateOptions.java rename to driver/src/main/java/com/arangodb/model/CollectionTruncateOptions.java diff --git a/src/main/java/com/arangodb/model/CollectionsReadOptions.java b/driver/src/main/java/com/arangodb/model/CollectionsReadOptions.java similarity index 96% rename from src/main/java/com/arangodb/model/CollectionsReadOptions.java rename to driver/src/main/java/com/arangodb/model/CollectionsReadOptions.java index 18f3ce42c..11e563fad 100644 --- a/src/main/java/com/arangodb/model/CollectionsReadOptions.java +++ b/driver/src/main/java/com/arangodb/model/CollectionsReadOptions.java @@ -1,49 +1,49 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.model; - -/** - * @author Mark Vollmary - * @see API - * Documentation - */ -public final class CollectionsReadOptions { - - private Boolean excludeSystem; - - public CollectionsReadOptions() { - super(); - } - - public Boolean getExcludeSystem() { - return excludeSystem; - } - - /** - * @param excludeSystem Whether or not system collections should be excluded from the result. - * @return options - */ - public CollectionsReadOptions excludeSystem(final Boolean excludeSystem) { - this.excludeSystem = excludeSystem; - return this; - } - -} +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed 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. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.model; + +/** + * @author Mark Vollmary + * @see API + * Documentation + */ +public final class CollectionsReadOptions { + + private Boolean excludeSystem; + + public CollectionsReadOptions() { + super(); + } + + public Boolean getExcludeSystem() { + return excludeSystem; + } + + /** + * @param excludeSystem Whether or not system collections should be excluded from the result. + * @return options + */ + public CollectionsReadOptions excludeSystem(final Boolean excludeSystem) { + this.excludeSystem = excludeSystem; + return this; + } + +} diff --git a/src/main/java/com/arangodb/model/ComputedValue.java b/driver/src/main/java/com/arangodb/model/ComputedValue.java similarity index 100% rename from src/main/java/com/arangodb/model/ComputedValue.java rename to driver/src/main/java/com/arangodb/model/ComputedValue.java diff --git a/src/main/java/com/arangodb/model/DBCreateOptions.java b/driver/src/main/java/com/arangodb/model/DBCreateOptions.java similarity index 96% rename from src/main/java/com/arangodb/model/DBCreateOptions.java rename to driver/src/main/java/com/arangodb/model/DBCreateOptions.java index 9b018c3fa..16b82beb6 100644 --- a/src/main/java/com/arangodb/model/DBCreateOptions.java +++ b/driver/src/main/java/com/arangodb/model/DBCreateOptions.java @@ -1,79 +1,79 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.model; - -import com.arangodb.DbName; - -import java.util.Collection; - -/** - * @author Mark Vollmary - */ -public final class DBCreateOptions { - - private Collection users; - private String name; - private DatabaseOptions options; - - public DBCreateOptions() { - super(); - } - - public Collection getUsers() { - return users; - } - - /** - * @param users array of user objects to initially create for the new database. - * User information will not be changed for users that already exist. - * If users is not specified or does not contain any users, a default user - * root will be created with an empty string password. This ensures that the - * new database will be accessible after it is created. - * @return options - */ - public DBCreateOptions users(final Collection users) { - this.users = users; - return this; - } - - public String getName() { - return name; - } - - /** - * @param dbName database name - * @return options - */ - public DBCreateOptions name(final DbName dbName) { - name = dbName.get(); - return this; - } - - public DatabaseOptions getOptions() { - return options; - } - - public DBCreateOptions options(DatabaseOptions options) { - this.options = options; - return this; - } - -} +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed 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. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.model; + +import com.arangodb.DbName; + +import java.util.Collection; + +/** + * @author Mark Vollmary + */ +public final class DBCreateOptions { + + private Collection users; + private String name; + private DatabaseOptions options; + + public DBCreateOptions() { + super(); + } + + public Collection getUsers() { + return users; + } + + /** + * @param users array of user objects to initially create for the new database. + * User information will not be changed for users that already exist. + * If users is not specified or does not contain any users, a default user + * root will be created with an empty string password. This ensures that the + * new database will be accessible after it is created. + * @return options + */ + public DBCreateOptions users(final Collection users) { + this.users = users; + return this; + } + + public String getName() { + return name; + } + + /** + * @param dbName database name + * @return options + */ + public DBCreateOptions name(final DbName dbName) { + name = dbName.get(); + return this; + } + + public DatabaseOptions getOptions() { + return options; + } + + public DBCreateOptions options(DatabaseOptions options) { + this.options = options; + return this; + } + +} diff --git a/src/main/java/com/arangodb/model/DatabaseOptions.java b/driver/src/main/java/com/arangodb/model/DatabaseOptions.java similarity index 100% rename from src/main/java/com/arangodb/model/DatabaseOptions.java rename to driver/src/main/java/com/arangodb/model/DatabaseOptions.java diff --git a/src/main/java/com/arangodb/model/DatabaseUsersOptions.java b/driver/src/main/java/com/arangodb/model/DatabaseUsersOptions.java similarity index 100% rename from src/main/java/com/arangodb/model/DatabaseUsersOptions.java rename to driver/src/main/java/com/arangodb/model/DatabaseUsersOptions.java diff --git a/src/main/java/com/arangodb/model/DocumentCreateOptions.java b/driver/src/main/java/com/arangodb/model/DocumentCreateOptions.java similarity index 100% rename from src/main/java/com/arangodb/model/DocumentCreateOptions.java rename to driver/src/main/java/com/arangodb/model/DocumentCreateOptions.java diff --git a/src/main/java/com/arangodb/model/DocumentDeleteOptions.java b/driver/src/main/java/com/arangodb/model/DocumentDeleteOptions.java similarity index 100% rename from src/main/java/com/arangodb/model/DocumentDeleteOptions.java rename to driver/src/main/java/com/arangodb/model/DocumentDeleteOptions.java diff --git a/src/main/java/com/arangodb/model/DocumentExistsOptions.java b/driver/src/main/java/com/arangodb/model/DocumentExistsOptions.java similarity index 96% rename from src/main/java/com/arangodb/model/DocumentExistsOptions.java rename to driver/src/main/java/com/arangodb/model/DocumentExistsOptions.java index a14dfaf16..3af420a78 100644 --- a/src/main/java/com/arangodb/model/DocumentExistsOptions.java +++ b/driver/src/main/java/com/arangodb/model/DocumentExistsOptions.java @@ -1,80 +1,80 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.model; - -/** - * @author Mark Vollmary - * @author Michele Rastelli - * @see - * API - * Documentation - */ -public final class DocumentExistsOptions { - - private String ifNoneMatch; - private String ifMatch; - private String streamTransactionId; - - public DocumentExistsOptions() { - super(); - } - - public String getIfNoneMatch() { - return ifNoneMatch; - } - - /** - * @param ifNoneMatch document revision must not contain If-None-Match - * @return options - */ - public DocumentExistsOptions ifNoneMatch(final String ifNoneMatch) { - this.ifNoneMatch = ifNoneMatch; - return this; - } - - public String getIfMatch() { - return ifMatch; - } - - /** - * @param ifMatch document revision must contain If-Match - * @return options - */ - public DocumentExistsOptions ifMatch(final String ifMatch) { - this.ifMatch = ifMatch; - return this; - } - - public String getStreamTransactionId() { - return streamTransactionId; - } - - /** - * @param streamTransactionId If set, the operation will be executed within the transaction. - * @return options - * @since ArangoDB 3.5.0 - */ - public DocumentExistsOptions streamTransactionId(final String streamTransactionId) { - this.streamTransactionId = streamTransactionId; - return this; - } - -} +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed 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. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.model; + +/** + * @author Mark Vollmary + * @author Michele Rastelli + * @see + * API + * Documentation + */ +public final class DocumentExistsOptions { + + private String ifNoneMatch; + private String ifMatch; + private String streamTransactionId; + + public DocumentExistsOptions() { + super(); + } + + public String getIfNoneMatch() { + return ifNoneMatch; + } + + /** + * @param ifNoneMatch document revision must not contain If-None-Match + * @return options + */ + public DocumentExistsOptions ifNoneMatch(final String ifNoneMatch) { + this.ifNoneMatch = ifNoneMatch; + return this; + } + + public String getIfMatch() { + return ifMatch; + } + + /** + * @param ifMatch document revision must contain If-Match + * @return options + */ + public DocumentExistsOptions ifMatch(final String ifMatch) { + this.ifMatch = ifMatch; + return this; + } + + public String getStreamTransactionId() { + return streamTransactionId; + } + + /** + * @param streamTransactionId If set, the operation will be executed within the transaction. + * @return options + * @since ArangoDB 3.5.0 + */ + public DocumentExistsOptions streamTransactionId(final String streamTransactionId) { + this.streamTransactionId = streamTransactionId; + return this; + } + +} diff --git a/src/main/java/com/arangodb/model/DocumentImportOptions.java b/driver/src/main/java/com/arangodb/model/DocumentImportOptions.java similarity index 97% rename from src/main/java/com/arangodb/model/DocumentImportOptions.java rename to driver/src/main/java/com/arangodb/model/DocumentImportOptions.java index 154a629d5..42612a8e8 100644 --- a/src/main/java/com/arangodb/model/DocumentImportOptions.java +++ b/driver/src/main/java/com/arangodb/model/DocumentImportOptions.java @@ -1,162 +1,162 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.model; - -/** - * @author Mark Vollmary - */ -public final class DocumentImportOptions { - - private String fromPrefix; - private String toPrefix; - private Boolean overwrite; - private Boolean waitForSync; - private OnDuplicate onDuplicate; - private Boolean complete; - private Boolean details; - - public DocumentImportOptions() { - super(); - } - - public String getFromPrefix() { - return fromPrefix; - } - - /** - * @param fromPrefix An optional prefix for the values in _from attributes. If specified, the value is automatically - * prepended to each _from input value. This allows specifying just the keys for _from. - * @return options - */ - public DocumentImportOptions fromPrefix(final String fromPrefix) { - this.fromPrefix = fromPrefix; - return this; - } - - public String getToPrefix() { - return toPrefix; - } - - /** - * @param toPrefix An optional prefix for the values in _to attributes. If specified, the value is automatically - * prepended to each _to input value. This allows specifying just the keys for _to. - * @return options - */ - public DocumentImportOptions toPrefix(final String toPrefix) { - this.toPrefix = toPrefix; - return this; - } - - public Boolean getOverwrite() { - return overwrite; - } - - /** - * @param overwrite If this parameter has a value of true, then all data in the collection will be removed prior - * to the - * import. Note that any existing index definitions will be preserved. - * @return options - */ - public DocumentImportOptions overwrite(final Boolean overwrite) { - this.overwrite = overwrite; - return this; - } - - public Boolean getWaitForSync() { - return waitForSync; - } - - /** - * @param waitForSync Wait until documents have been synced to disk before returning. - * @return options - */ - public DocumentImportOptions waitForSync(final Boolean waitForSync) { - this.waitForSync = waitForSync; - return this; - } - - public OnDuplicate getOnDuplicate() { - return onDuplicate; - } - - /** - * @param onDuplicate Controls what action is carried out in case of a unique key constraint violation. Possible - * values are: - *

      - *
    • error: this will not import the current document because of the unique key constraint - * violation. - * This is the default setting.
    • - *
    • update: this will update an existing document in the database with the data specified - * in the - * request. Attributes of the existing document that are not present in the request will be - * preserved.
    • - *
    • replace: this will replace an existing document in the database with the data specified - * in the - * request.
    • - *
    • ignore: this will not update an existing document and simply ignore the error caused by - * the unique - * key constraint violation. Note that update, replace and ignore will only work when the - * import document - * in the request contains the _key attribute. update and replace may also fail because of - * secondary - * unique key constraint violations.
    • - *
    - * @return options - */ - public DocumentImportOptions onDuplicate(final OnDuplicate onDuplicate) { - this.onDuplicate = onDuplicate; - return this; - } - - public Boolean getComplete() { - return complete; - } - - /** - * @param complete If set to true, it will make the whole import fail if any error occurs. Otherwise the import will - * continue even if some documents cannot be imported. - * @return options - */ - public DocumentImportOptions complete(final Boolean complete) { - this.complete = complete; - return this; - } - - public Boolean getDetails() { - return details; - } - - /** - * @param details If set to true, the result will include an attribute details with details about documents that - * could - * not be imported. - * @return options - */ - public DocumentImportOptions details(final Boolean details) { - this.details = details; - return this; - } - - public enum OnDuplicate { - error, update, replace, ignore - } - -} +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed 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. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.model; + +/** + * @author Mark Vollmary + */ +public final class DocumentImportOptions { + + private String fromPrefix; + private String toPrefix; + private Boolean overwrite; + private Boolean waitForSync; + private OnDuplicate onDuplicate; + private Boolean complete; + private Boolean details; + + public DocumentImportOptions() { + super(); + } + + public String getFromPrefix() { + return fromPrefix; + } + + /** + * @param fromPrefix An optional prefix for the values in _from attributes. If specified, the value is automatically + * prepended to each _from input value. This allows specifying just the keys for _from. + * @return options + */ + public DocumentImportOptions fromPrefix(final String fromPrefix) { + this.fromPrefix = fromPrefix; + return this; + } + + public String getToPrefix() { + return toPrefix; + } + + /** + * @param toPrefix An optional prefix for the values in _to attributes. If specified, the value is automatically + * prepended to each _to input value. This allows specifying just the keys for _to. + * @return options + */ + public DocumentImportOptions toPrefix(final String toPrefix) { + this.toPrefix = toPrefix; + return this; + } + + public Boolean getOverwrite() { + return overwrite; + } + + /** + * @param overwrite If this parameter has a value of true, then all data in the collection will be removed prior + * to the + * import. Note that any existing index definitions will be preserved. + * @return options + */ + public DocumentImportOptions overwrite(final Boolean overwrite) { + this.overwrite = overwrite; + return this; + } + + public Boolean getWaitForSync() { + return waitForSync; + } + + /** + * @param waitForSync Wait until documents have been synced to disk before returning. + * @return options + */ + public DocumentImportOptions waitForSync(final Boolean waitForSync) { + this.waitForSync = waitForSync; + return this; + } + + public OnDuplicate getOnDuplicate() { + return onDuplicate; + } + + /** + * @param onDuplicate Controls what action is carried out in case of a unique key constraint violation. Possible + * values are: + *
      + *
    • error: this will not import the current document because of the unique key constraint + * violation. + * This is the default setting.
    • + *
    • update: this will update an existing document in the database with the data specified + * in the + * request. Attributes of the existing document that are not present in the request will be + * preserved.
    • + *
    • replace: this will replace an existing document in the database with the data specified + * in the + * request.
    • + *
    • ignore: this will not update an existing document and simply ignore the error caused by + * the unique + * key constraint violation. Note that update, replace and ignore will only work when the + * import document + * in the request contains the _key attribute. update and replace may also fail because of + * secondary + * unique key constraint violations.
    • + *
    + * @return options + */ + public DocumentImportOptions onDuplicate(final OnDuplicate onDuplicate) { + this.onDuplicate = onDuplicate; + return this; + } + + public Boolean getComplete() { + return complete; + } + + /** + * @param complete If set to true, it will make the whole import fail if any error occurs. Otherwise the import will + * continue even if some documents cannot be imported. + * @return options + */ + public DocumentImportOptions complete(final Boolean complete) { + this.complete = complete; + return this; + } + + public Boolean getDetails() { + return details; + } + + /** + * @param details If set to true, the result will include an attribute details with details about documents that + * could + * not be imported. + * @return options + */ + public DocumentImportOptions details(final Boolean details) { + this.details = details; + return this; + } + + public enum OnDuplicate { + error, update, replace, ignore + } + +} diff --git a/src/main/java/com/arangodb/model/DocumentReadOptions.java b/driver/src/main/java/com/arangodb/model/DocumentReadOptions.java similarity index 96% rename from src/main/java/com/arangodb/model/DocumentReadOptions.java rename to driver/src/main/java/com/arangodb/model/DocumentReadOptions.java index ec711724e..f19aa3e43 100644 --- a/src/main/java/com/arangodb/model/DocumentReadOptions.java +++ b/driver/src/main/java/com/arangodb/model/DocumentReadOptions.java @@ -1,96 +1,96 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.model; - -/** - * @author Mark Vollmary - * @author Michele Rastelli - * @see API - * Documentation - */ -public final class DocumentReadOptions { - - private String ifNoneMatch; - private String ifMatch; - private Boolean allowDirtyRead; - private String streamTransactionId; - - public DocumentReadOptions() { - super(); - } - - public String getIfNoneMatch() { - return ifNoneMatch; - } - - /** - * @param ifNoneMatch document revision must not contain If-None-Match - * @return options - */ - public DocumentReadOptions ifNoneMatch(final String ifNoneMatch) { - this.ifNoneMatch = ifNoneMatch; - return this; - } - - public String getIfMatch() { - return ifMatch; - } - - /** - * @param ifMatch document revision must contain If-Match - * @return options - */ - public DocumentReadOptions ifMatch(final String ifMatch) { - this.ifMatch = ifMatch; - return this; - } - - /** - * @param allowDirtyRead Set to {@code true} allows reading from followers in an active-failover setup. - * @return options - * @see API - * Documentation - * @since ArangoDB 3.4.0 - */ - public DocumentReadOptions allowDirtyRead(final Boolean allowDirtyRead) { - this.allowDirtyRead = allowDirtyRead; - return this; - } - - public Boolean getAllowDirtyRead() { - return allowDirtyRead; - } - - public String getStreamTransactionId() { - return streamTransactionId; - } - - /** - * @param streamTransactionId If set, the operation will be executed within the transaction. - * @return options - * @since ArangoDB 3.5.0 - */ - public DocumentReadOptions streamTransactionId(final String streamTransactionId) { - this.streamTransactionId = streamTransactionId; - return this; - } - -} +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed 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. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.model; + +/** + * @author Mark Vollmary + * @author Michele Rastelli + * @see API + * Documentation + */ +public final class DocumentReadOptions { + + private String ifNoneMatch; + private String ifMatch; + private Boolean allowDirtyRead; + private String streamTransactionId; + + public DocumentReadOptions() { + super(); + } + + public String getIfNoneMatch() { + return ifNoneMatch; + } + + /** + * @param ifNoneMatch document revision must not contain If-None-Match + * @return options + */ + public DocumentReadOptions ifNoneMatch(final String ifNoneMatch) { + this.ifNoneMatch = ifNoneMatch; + return this; + } + + public String getIfMatch() { + return ifMatch; + } + + /** + * @param ifMatch document revision must contain If-Match + * @return options + */ + public DocumentReadOptions ifMatch(final String ifMatch) { + this.ifMatch = ifMatch; + return this; + } + + /** + * @param allowDirtyRead Set to {@code true} allows reading from followers in an active-failover setup. + * @return options + * @see API + * Documentation + * @since ArangoDB 3.4.0 + */ + public DocumentReadOptions allowDirtyRead(final Boolean allowDirtyRead) { + this.allowDirtyRead = allowDirtyRead; + return this; + } + + public Boolean getAllowDirtyRead() { + return allowDirtyRead; + } + + public String getStreamTransactionId() { + return streamTransactionId; + } + + /** + * @param streamTransactionId If set, the operation will be executed within the transaction. + * @return options + * @since ArangoDB 3.5.0 + */ + public DocumentReadOptions streamTransactionId(final String streamTransactionId) { + this.streamTransactionId = streamTransactionId; + return this; + } + +} diff --git a/src/main/java/com/arangodb/model/DocumentReplaceOptions.java b/driver/src/main/java/com/arangodb/model/DocumentReplaceOptions.java similarity index 100% rename from src/main/java/com/arangodb/model/DocumentReplaceOptions.java rename to driver/src/main/java/com/arangodb/model/DocumentReplaceOptions.java diff --git a/src/main/java/com/arangodb/model/DocumentUpdateOptions.java b/driver/src/main/java/com/arangodb/model/DocumentUpdateOptions.java similarity index 100% rename from src/main/java/com/arangodb/model/DocumentUpdateOptions.java rename to driver/src/main/java/com/arangodb/model/DocumentUpdateOptions.java diff --git a/src/main/java/com/arangodb/model/EdgeCreateOptions.java b/driver/src/main/java/com/arangodb/model/EdgeCreateOptions.java similarity index 96% rename from src/main/java/com/arangodb/model/EdgeCreateOptions.java rename to driver/src/main/java/com/arangodb/model/EdgeCreateOptions.java index 7e340bc25..2429d9405 100644 --- a/src/main/java/com/arangodb/model/EdgeCreateOptions.java +++ b/driver/src/main/java/com/arangodb/model/EdgeCreateOptions.java @@ -1,63 +1,63 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.model; - -/** - * @author Mark Vollmary - * @see API Documentation - */ -public final class EdgeCreateOptions { - - private Boolean waitForSync; - private String streamTransactionId; - - public EdgeCreateOptions() { - super(); - } - - public Boolean getWaitForSync() { - return waitForSync; - } - - /** - * @param waitForSync Wait until document has been synced to disk. - * @return options - */ - public EdgeCreateOptions waitForSync(final Boolean waitForSync) { - this.waitForSync = waitForSync; - return this; - } - - public String getStreamTransactionId() { - return streamTransactionId; - } - - /** - * @param streamTransactionId If set, the operation will be executed within the transaction. - * @return options - * @since ArangoDB 3.5.1 - */ - public EdgeCreateOptions streamTransactionId(final String streamTransactionId) { - this.streamTransactionId = streamTransactionId; - return this; - } - -} +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed 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. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.model; + +/** + * @author Mark Vollmary + * @see API Documentation + */ +public final class EdgeCreateOptions { + + private Boolean waitForSync; + private String streamTransactionId; + + public EdgeCreateOptions() { + super(); + } + + public Boolean getWaitForSync() { + return waitForSync; + } + + /** + * @param waitForSync Wait until document has been synced to disk. + * @return options + */ + public EdgeCreateOptions waitForSync(final Boolean waitForSync) { + this.waitForSync = waitForSync; + return this; + } + + public String getStreamTransactionId() { + return streamTransactionId; + } + + /** + * @param streamTransactionId If set, the operation will be executed within the transaction. + * @return options + * @since ArangoDB 3.5.1 + */ + public EdgeCreateOptions streamTransactionId(final String streamTransactionId) { + this.streamTransactionId = streamTransactionId; + return this; + } + +} diff --git a/src/main/java/com/arangodb/model/EdgeDeleteOptions.java b/driver/src/main/java/com/arangodb/model/EdgeDeleteOptions.java similarity index 96% rename from src/main/java/com/arangodb/model/EdgeDeleteOptions.java rename to driver/src/main/java/com/arangodb/model/EdgeDeleteOptions.java index a82d68ec1..6d14fbcf7 100644 --- a/src/main/java/com/arangodb/model/EdgeDeleteOptions.java +++ b/driver/src/main/java/com/arangodb/model/EdgeDeleteOptions.java @@ -1,77 +1,77 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.model; - -/** - * @author Mark Vollmary - * @see API Documentation - */ -public final class EdgeDeleteOptions { - - private Boolean waitForSync; - private String ifMatch; - private String streamTransactionId; - - public EdgeDeleteOptions() { - super(); - } - - public Boolean getWaitForSync() { - return waitForSync; - } - - /** - * @param waitForSync Wait until deletion operation has been synced to disk. - * @return options - */ - public EdgeDeleteOptions waitForSync(final Boolean waitForSync) { - this.waitForSync = waitForSync; - return this; - } - - public String getIfMatch() { - return ifMatch; - } - - /** - * @param ifMatch remove a document based on a target revision - * @return options - */ - public EdgeDeleteOptions ifMatch(final String ifMatch) { - this.ifMatch = ifMatch; - return this; - } - - public String getStreamTransactionId() { - return streamTransactionId; - } - - /** - * @param streamTransactionId If set, the operation will be executed within the transaction. - * @return options - * @since ArangoDB 3.5.1 - */ - public EdgeDeleteOptions streamTransactionId(final String streamTransactionId) { - this.streamTransactionId = streamTransactionId; - return this; - } - -} +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed 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. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.model; + +/** + * @author Mark Vollmary + * @see API Documentation + */ +public final class EdgeDeleteOptions { + + private Boolean waitForSync; + private String ifMatch; + private String streamTransactionId; + + public EdgeDeleteOptions() { + super(); + } + + public Boolean getWaitForSync() { + return waitForSync; + } + + /** + * @param waitForSync Wait until deletion operation has been synced to disk. + * @return options + */ + public EdgeDeleteOptions waitForSync(final Boolean waitForSync) { + this.waitForSync = waitForSync; + return this; + } + + public String getIfMatch() { + return ifMatch; + } + + /** + * @param ifMatch remove a document based on a target revision + * @return options + */ + public EdgeDeleteOptions ifMatch(final String ifMatch) { + this.ifMatch = ifMatch; + return this; + } + + public String getStreamTransactionId() { + return streamTransactionId; + } + + /** + * @param streamTransactionId If set, the operation will be executed within the transaction. + * @return options + * @since ArangoDB 3.5.1 + */ + public EdgeDeleteOptions streamTransactionId(final String streamTransactionId) { + this.streamTransactionId = streamTransactionId; + return this; + } + +} diff --git a/src/main/java/com/arangodb/model/EdgeReplaceOptions.java b/driver/src/main/java/com/arangodb/model/EdgeReplaceOptions.java similarity index 96% rename from src/main/java/com/arangodb/model/EdgeReplaceOptions.java rename to driver/src/main/java/com/arangodb/model/EdgeReplaceOptions.java index e30b64ffc..ebf54eafd 100644 --- a/src/main/java/com/arangodb/model/EdgeReplaceOptions.java +++ b/driver/src/main/java/com/arangodb/model/EdgeReplaceOptions.java @@ -1,77 +1,77 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.model; - -/** - * @author Mark Vollmary - * @see API Documentation - */ -public final class EdgeReplaceOptions { - - private Boolean waitForSync; - private String ifMatch; - private String streamTransactionId; - - public EdgeReplaceOptions() { - super(); - } - - public Boolean getWaitForSync() { - return waitForSync; - } - - /** - * @param waitForSync Wait until document has been synced to disk. - * @return options - */ - public EdgeReplaceOptions waitForSync(final Boolean waitForSync) { - this.waitForSync = waitForSync; - return this; - } - - public String getIfMatch() { - return ifMatch; - } - - /** - * @param ifMatch replace a document based on target revision - * @return options - */ - public EdgeReplaceOptions ifMatch(final String ifMatch) { - this.ifMatch = ifMatch; - return this; - } - - public String getStreamTransactionId() { - return streamTransactionId; - } - - /** - * @param streamTransactionId If set, the operation will be executed within the transaction. - * @return options - * @since ArangoDB 3.5.1 - */ - public EdgeReplaceOptions streamTransactionId(final String streamTransactionId) { - this.streamTransactionId = streamTransactionId; - return this; - } - -} +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed 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. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.model; + +/** + * @author Mark Vollmary + * @see API Documentation + */ +public final class EdgeReplaceOptions { + + private Boolean waitForSync; + private String ifMatch; + private String streamTransactionId; + + public EdgeReplaceOptions() { + super(); + } + + public Boolean getWaitForSync() { + return waitForSync; + } + + /** + * @param waitForSync Wait until document has been synced to disk. + * @return options + */ + public EdgeReplaceOptions waitForSync(final Boolean waitForSync) { + this.waitForSync = waitForSync; + return this; + } + + public String getIfMatch() { + return ifMatch; + } + + /** + * @param ifMatch replace a document based on target revision + * @return options + */ + public EdgeReplaceOptions ifMatch(final String ifMatch) { + this.ifMatch = ifMatch; + return this; + } + + public String getStreamTransactionId() { + return streamTransactionId; + } + + /** + * @param streamTransactionId If set, the operation will be executed within the transaction. + * @return options + * @since ArangoDB 3.5.1 + */ + public EdgeReplaceOptions streamTransactionId(final String streamTransactionId) { + this.streamTransactionId = streamTransactionId; + return this; + } + +} diff --git a/src/main/java/com/arangodb/model/EdgeUpdateOptions.java b/driver/src/main/java/com/arangodb/model/EdgeUpdateOptions.java similarity index 96% rename from src/main/java/com/arangodb/model/EdgeUpdateOptions.java rename to driver/src/main/java/com/arangodb/model/EdgeUpdateOptions.java index 2ff7611fe..356f6609b 100644 --- a/src/main/java/com/arangodb/model/EdgeUpdateOptions.java +++ b/driver/src/main/java/com/arangodb/model/EdgeUpdateOptions.java @@ -1,94 +1,94 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.model; - -/** - * @author Mark Vollmary - * @see API Documentation - */ -public final class EdgeUpdateOptions { - - private Boolean keepNull; - private Boolean waitForSync; - private String ifMatch; - private String streamTransactionId; - - public EdgeUpdateOptions() { - super(); - } - - public Boolean getKeepNull() { - return keepNull; - } - - /** - * @param keepNull If the intention is to delete existing attributes with the patch command, the URL query parameter - * keepNull can be used with a value of false. This will modify the behavior of the patch command to - * remove any attributes from the existing document that are contained in the patch document with an - * attribute value of null. - * @return options - */ - public EdgeUpdateOptions keepNull(final Boolean keepNull) { - this.keepNull = keepNull; - return this; - } - - public Boolean getWaitForSync() { - return waitForSync; - } - - /** - * @param waitForSync Wait until document has been synced to disk. - * @return options - */ - public EdgeUpdateOptions waitForSync(final Boolean waitForSync) { - this.waitForSync = waitForSync; - return this; - } - - public String getIfMatch() { - return ifMatch; - } - - /** - * @param ifMatch replace a document based on target revision - * @return options - */ - public EdgeUpdateOptions ifMatch(final String ifMatch) { - this.ifMatch = ifMatch; - return this; - } - - public String getStreamTransactionId() { - return streamTransactionId; - } - - /** - * @param streamTransactionId If set, the operation will be executed within the transaction. - * @return options - * @since ArangoDB 3.5.1 - */ - public EdgeUpdateOptions streamTransactionId(final String streamTransactionId) { - this.streamTransactionId = streamTransactionId; - return this; - } - -} +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed 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. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.model; + +/** + * @author Mark Vollmary + * @see API Documentation + */ +public final class EdgeUpdateOptions { + + private Boolean keepNull; + private Boolean waitForSync; + private String ifMatch; + private String streamTransactionId; + + public EdgeUpdateOptions() { + super(); + } + + public Boolean getKeepNull() { + return keepNull; + } + + /** + * @param keepNull If the intention is to delete existing attributes with the patch command, the URL query parameter + * keepNull can be used with a value of false. This will modify the behavior of the patch command to + * remove any attributes from the existing document that are contained in the patch document with an + * attribute value of null. + * @return options + */ + public EdgeUpdateOptions keepNull(final Boolean keepNull) { + this.keepNull = keepNull; + return this; + } + + public Boolean getWaitForSync() { + return waitForSync; + } + + /** + * @param waitForSync Wait until document has been synced to disk. + * @return options + */ + public EdgeUpdateOptions waitForSync(final Boolean waitForSync) { + this.waitForSync = waitForSync; + return this; + } + + public String getIfMatch() { + return ifMatch; + } + + /** + * @param ifMatch replace a document based on target revision + * @return options + */ + public EdgeUpdateOptions ifMatch(final String ifMatch) { + this.ifMatch = ifMatch; + return this; + } + + public String getStreamTransactionId() { + return streamTransactionId; + } + + /** + * @param streamTransactionId If set, the operation will be executed within the transaction. + * @return options + * @since ArangoDB 3.5.1 + */ + public EdgeUpdateOptions streamTransactionId(final String streamTransactionId) { + this.streamTransactionId = streamTransactionId; + return this; + } + +} diff --git a/src/main/java/com/arangodb/model/FulltextIndexOptions.java b/driver/src/main/java/com/arangodb/model/FulltextIndexOptions.java similarity index 96% rename from src/main/java/com/arangodb/model/FulltextIndexOptions.java rename to driver/src/main/java/com/arangodb/model/FulltextIndexOptions.java index 84735b5b0..d476c8bba 100644 --- a/src/main/java/com/arangodb/model/FulltextIndexOptions.java +++ b/driver/src/main/java/com/arangodb/model/FulltextIndexOptions.java @@ -1,79 +1,79 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.model; - -import com.arangodb.entity.IndexType; - -/** - * @author Mark Vollmary - * @see API - * Documentation - * @deprecated since ArangoDB 3.10, use ArangoSearch or Inverted indexes instead. - */ -@Deprecated -public final class FulltextIndexOptions extends IndexOptions { - - private final IndexType type = IndexType.fulltext; - private Iterable fields; - private Integer minLength; - - public FulltextIndexOptions() { - super(); - } - - @Override - FulltextIndexOptions getThis() { - return this; - } - - public Iterable getFields() { - return fields; - } - - /** - * @param fields A list of attribute paths - * @return options - */ - FulltextIndexOptions fields(final Iterable fields) { - this.fields = fields; - return this; - } - - public IndexType getType() { - return type; - } - - public Integer getMinLength() { - return minLength; - } - - /** - * @param minLength Minimum character length of words to index. Will default to a server-defined value if - * unspecified. It - * is thus recommended to set this value explicitly when creating the index. - * @return options - */ - public FulltextIndexOptions minLength(final Integer minLength) { - this.minLength = minLength; - return this; - } - -} +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed 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. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.model; + +import com.arangodb.entity.IndexType; + +/** + * @author Mark Vollmary + * @see API + * Documentation + * @deprecated since ArangoDB 3.10, use ArangoSearch or Inverted indexes instead. + */ +@Deprecated +public final class FulltextIndexOptions extends IndexOptions { + + private final IndexType type = IndexType.fulltext; + private Iterable fields; + private Integer minLength; + + public FulltextIndexOptions() { + super(); + } + + @Override + FulltextIndexOptions getThis() { + return this; + } + + public Iterable getFields() { + return fields; + } + + /** + * @param fields A list of attribute paths + * @return options + */ + FulltextIndexOptions fields(final Iterable fields) { + this.fields = fields; + return this; + } + + public IndexType getType() { + return type; + } + + public Integer getMinLength() { + return minLength; + } + + /** + * @param minLength Minimum character length of words to index. Will default to a server-defined value if + * unspecified. It + * is thus recommended to set this value explicitly when creating the index. + * @return options + */ + public FulltextIndexOptions minLength(final Integer minLength) { + this.minLength = minLength; + return this; + } + +} diff --git a/src/main/java/com/arangodb/model/GeoIndexOptions.java b/driver/src/main/java/com/arangodb/model/GeoIndexOptions.java similarity index 96% rename from src/main/java/com/arangodb/model/GeoIndexOptions.java rename to driver/src/main/java/com/arangodb/model/GeoIndexOptions.java index d71c10555..4a95e2274 100644 --- a/src/main/java/com/arangodb/model/GeoIndexOptions.java +++ b/driver/src/main/java/com/arangodb/model/GeoIndexOptions.java @@ -1,94 +1,94 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.model; - -import com.arangodb.entity.IndexType; - -/** - * @author Mark Vollmary - * @see - * API Documentation - */ -public final class GeoIndexOptions extends IndexOptions { - - private final IndexType type = IndexType.geo; - private Iterable fields; - private Boolean geoJson; - private Boolean legacyPolygons; - - public GeoIndexOptions() { - super(); - } - - @Override - GeoIndexOptions getThis() { - return this; - } - - public Iterable getFields() { - return fields; - } - - /** - * @param fields A list of attribute paths - * @return options - */ - GeoIndexOptions fields(final Iterable fields) { - this.fields = fields; - return this; - } - - public IndexType getType() { - return type; - } - - public Boolean getGeoJson() { - return geoJson; - } - - /** - * @param geoJson If a geo-spatial index on a location is constructed and geoJson is true, then the order within the - * array is longitude followed by latitude. This corresponds to the format described in - * @return options - */ - public GeoIndexOptions geoJson(final Boolean geoJson) { - this.geoJson = geoJson; - return this; - } - - public Boolean getLegacyPolygons() { - return legacyPolygons; - } - - /** - * @param legacyPolygons If `true` will use the old rules (pre-3.10) for the parsing GeoJSON polygons. This - * allows you to let old indexes produce the same, potentially wrong results as before an - * upgrade. A geo index with `legacyPolygons` set to `false` will use the new, correct and - * consistent method for parsing of GeoJSON polygons. - * See Legacy Polygons. - * @return options - * @since ArangoDB 3.10 - */ - public GeoIndexOptions legacyPolygons(final Boolean legacyPolygons) { - this.legacyPolygons = legacyPolygons; - return this; - } -} +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed 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. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.model; + +import com.arangodb.entity.IndexType; + +/** + * @author Mark Vollmary + * @see + * API Documentation + */ +public final class GeoIndexOptions extends IndexOptions { + + private final IndexType type = IndexType.geo; + private Iterable fields; + private Boolean geoJson; + private Boolean legacyPolygons; + + public GeoIndexOptions() { + super(); + } + + @Override + GeoIndexOptions getThis() { + return this; + } + + public Iterable getFields() { + return fields; + } + + /** + * @param fields A list of attribute paths + * @return options + */ + GeoIndexOptions fields(final Iterable fields) { + this.fields = fields; + return this; + } + + public IndexType getType() { + return type; + } + + public Boolean getGeoJson() { + return geoJson; + } + + /** + * @param geoJson If a geo-spatial index on a location is constructed and geoJson is true, then the order within the + * array is longitude followed by latitude. This corresponds to the format described in + * @return options + */ + public GeoIndexOptions geoJson(final Boolean geoJson) { + this.geoJson = geoJson; + return this; + } + + public Boolean getLegacyPolygons() { + return legacyPolygons; + } + + /** + * @param legacyPolygons If `true` will use the old rules (pre-3.10) for the parsing GeoJSON polygons. This + * allows you to let old indexes produce the same, potentially wrong results as before an + * upgrade. A geo index with `legacyPolygons` set to `false` will use the new, correct and + * consistent method for parsing of GeoJSON polygons. + * See Legacy Polygons. + * @return options + * @since ArangoDB 3.10 + */ + public GeoIndexOptions legacyPolygons(final Boolean legacyPolygons) { + this.legacyPolygons = legacyPolygons; + return this; + } +} diff --git a/src/main/java/com/arangodb/model/GraphCreateOptions.java b/driver/src/main/java/com/arangodb/model/GraphCreateOptions.java similarity index 97% rename from src/main/java/com/arangodb/model/GraphCreateOptions.java rename to driver/src/main/java/com/arangodb/model/GraphCreateOptions.java index 1b7e3b322..a0db68f4c 100644 --- a/src/main/java/com/arangodb/model/GraphCreateOptions.java +++ b/driver/src/main/java/com/arangodb/model/GraphCreateOptions.java @@ -1,272 +1,272 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.model; - -import com.arangodb.entity.EdgeDefinition; -import com.arangodb.entity.ReplicationFactor; - -import java.util.Arrays; -import java.util.Collection; - -/** - * @author Mark Vollmary - * @see API Documentation - */ -public final class GraphCreateOptions { - - private String name; - private Collection edgeDefinitions; - private Collection orphanCollections; - private Boolean isSmart; - private SmartOptions options; - - public GraphCreateOptions() { - super(); - } - - public String getName() { - return name; - } - - /** - * @param name Name of the graph - * @return options - */ - GraphCreateOptions name(final String name) { - this.name = name; - return this; - } - - public Collection getEdgeDefinitions() { - return edgeDefinitions; - } - - /** - * @param edgeDefinitions An array of definitions for the edge - * @return options - */ - GraphCreateOptions edgeDefinitions(final Collection edgeDefinitions) { - this.edgeDefinitions = edgeDefinitions; - return this; - } - - public Collection getOrphanCollections() { - return orphanCollections; - } - - /** - * @param orphanCollections Additional vertex collections - * @return options - */ - public GraphCreateOptions orphanCollections(final String... orphanCollections) { - this.orphanCollections = Arrays.asList(orphanCollections); - return this; - } - - public Boolean getIsSmart() { - return isSmart; - } - - /** - * @param isSmart Define if the created graph should be smart. This only has effect in Enterprise version. - * @return options - */ - public GraphCreateOptions isSmart(final Boolean isSmart) { - this.isSmart = isSmart; - return this; - } - - public Boolean getIsDisjoint() { - return getOptions().getIsDisjoint(); - } - - /** - * @param isDisjoint If set to true, a Disjoint SmartGraph will be created. This flag is not editable after - * creation. Default: false. - * @return options - * @since ArangoDB 3.7 - */ - public GraphCreateOptions isDisjoint(final Boolean isDisjoint) { - getOptions().setIsDisjoint(isDisjoint); - return this; - } - - public ReplicationFactor getReplicationFactor() { - return getOptions().replicationFactor; - } - - /** - * @param replicationFactor (The default is 1): in a cluster, this attribute determines how many copies of each - * shard are kept on - * different DBServers. The value 1 means that only one copy (no synchronous - * replication) is kept. A - * value of k means that k-1 replicas are kept. Any two copies reside on different - * DBServers. Replication - * between them is synchronous, that is, every write operation to the "leader" copy will - * be replicated to - * all "follower" replicas, before the write operation is reported successful. If a - * server fails, this is - * detected automatically and one of the servers holding copies take over, usually - * without an error being - * reported. - * @return options - */ - public GraphCreateOptions replicationFactor(final ReplicationFactor replicationFactor) { - getOptions().setReplicationFactor(replicationFactor); - return this; - } - - public GraphCreateOptions replicationFactor(int replicationFactor) { - getOptions().setReplicationFactor(ReplicationFactor.of(replicationFactor)); - return this; - } - - public Integer getWriteConcern() { - return getOptions().getWriteConcern(); - } - - /** - * @param writeConcern Write concern for new collections in the graph. - * It determines how many copies of each shard are required to be in sync on the different - * DB-Servers. If there are less then these many copies in the cluster a shard will refuse to - * write. Writes to shards with enough up-to-date copies will succeed at the same time however. - * The value of writeConcern can not be larger than replicationFactor. (cluster only) - * @return options - */ - public GraphCreateOptions writeConcern(final Integer writeConcern) { - getOptions().setWriteConcern(writeConcern); - return this; - } - - public Integer getNumberOfShards() { - return getOptions().getNumberOfShards(); - } - - /** - * @param numberOfShards The number of shards that is used for every collection within this graph. Cannot be - * modified later. - * @return options - */ - public GraphCreateOptions numberOfShards(final Integer numberOfShards) { - getOptions().setNumberOfShards(numberOfShards); - return this; - } - - public String getSmartGraphAttribute() { - return getOptions().getSmartGraphAttribute(); - } - - /** - * @param smartGraphAttribute The attribute name that is used to smartly shard the vertices of a graph. Every - * vertex in this Graph - * has to have this attribute. Cannot be modified later. - * @return options - */ - public GraphCreateOptions smartGraphAttribute(final String smartGraphAttribute) { - getOptions().setSmartGraphAttribute(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; - } - - public SmartOptions getOptions() { - if (options == null) { - options = new SmartOptions(); - } - return options; - } - - public static final class SmartOptions { - private ReplicationFactor replicationFactor; - private Integer writeConcern; - private Integer numberOfShards; - private String smartGraphAttribute; - private Boolean isDisjoint; - private Collection satellites; - - public SmartOptions() { - super(); - } - - public ReplicationFactor getReplicationFactor() { - return replicationFactor; - } - - public void setReplicationFactor(final ReplicationFactor replicationFactor) { - this.replicationFactor = replicationFactor; - } - - public Integer getWriteConcern() { - return writeConcern; - } - - public void setWriteConcern(final Integer writeConcern) { - this.writeConcern = writeConcern; - } - - public Integer getNumberOfShards() { - return numberOfShards; - } - - public void setNumberOfShards(final Integer numberOfShards) { - this.numberOfShards = numberOfShards; - } - - public String getSmartGraphAttribute() { - return smartGraphAttribute; - } - - public void setSmartGraphAttribute(final String smartGraphAttribute) { - this.smartGraphAttribute = smartGraphAttribute; - } - - public Boolean getIsDisjoint() { - return isDisjoint; - } - - 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); - } - } - -} +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed 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. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.model; + +import com.arangodb.entity.EdgeDefinition; +import com.arangodb.entity.ReplicationFactor; + +import java.util.Arrays; +import java.util.Collection; + +/** + * @author Mark Vollmary + * @see API Documentation + */ +public final class GraphCreateOptions { + + private String name; + private Collection edgeDefinitions; + private Collection orphanCollections; + private Boolean isSmart; + private SmartOptions options; + + public GraphCreateOptions() { + super(); + } + + public String getName() { + return name; + } + + /** + * @param name Name of the graph + * @return options + */ + GraphCreateOptions name(final String name) { + this.name = name; + return this; + } + + public Collection getEdgeDefinitions() { + return edgeDefinitions; + } + + /** + * @param edgeDefinitions An array of definitions for the edge + * @return options + */ + GraphCreateOptions edgeDefinitions(final Collection edgeDefinitions) { + this.edgeDefinitions = edgeDefinitions; + return this; + } + + public Collection getOrphanCollections() { + return orphanCollections; + } + + /** + * @param orphanCollections Additional vertex collections + * @return options + */ + public GraphCreateOptions orphanCollections(final String... orphanCollections) { + this.orphanCollections = Arrays.asList(orphanCollections); + return this; + } + + public Boolean getIsSmart() { + return isSmart; + } + + /** + * @param isSmart Define if the created graph should be smart. This only has effect in Enterprise version. + * @return options + */ + public GraphCreateOptions isSmart(final Boolean isSmart) { + this.isSmart = isSmart; + return this; + } + + public Boolean getIsDisjoint() { + return getOptions().getIsDisjoint(); + } + + /** + * @param isDisjoint If set to true, a Disjoint SmartGraph will be created. This flag is not editable after + * creation. Default: false. + * @return options + * @since ArangoDB 3.7 + */ + public GraphCreateOptions isDisjoint(final Boolean isDisjoint) { + getOptions().setIsDisjoint(isDisjoint); + return this; + } + + public ReplicationFactor getReplicationFactor() { + return getOptions().replicationFactor; + } + + /** + * @param replicationFactor (The default is 1): in a cluster, this attribute determines how many copies of each + * shard are kept on + * different DBServers. The value 1 means that only one copy (no synchronous + * replication) is kept. A + * value of k means that k-1 replicas are kept. Any two copies reside on different + * DBServers. Replication + * between them is synchronous, that is, every write operation to the "leader" copy will + * be replicated to + * all "follower" replicas, before the write operation is reported successful. If a + * server fails, this is + * detected automatically and one of the servers holding copies take over, usually + * without an error being + * reported. + * @return options + */ + public GraphCreateOptions replicationFactor(final ReplicationFactor replicationFactor) { + getOptions().setReplicationFactor(replicationFactor); + return this; + } + + public GraphCreateOptions replicationFactor(int replicationFactor) { + getOptions().setReplicationFactor(ReplicationFactor.of(replicationFactor)); + return this; + } + + public Integer getWriteConcern() { + return getOptions().getWriteConcern(); + } + + /** + * @param writeConcern Write concern for new collections in the graph. + * It determines how many copies of each shard are required to be in sync on the different + * DB-Servers. If there are less then these many copies in the cluster a shard will refuse to + * write. Writes to shards with enough up-to-date copies will succeed at the same time however. + * The value of writeConcern can not be larger than replicationFactor. (cluster only) + * @return options + */ + public GraphCreateOptions writeConcern(final Integer writeConcern) { + getOptions().setWriteConcern(writeConcern); + return this; + } + + public Integer getNumberOfShards() { + return getOptions().getNumberOfShards(); + } + + /** + * @param numberOfShards The number of shards that is used for every collection within this graph. Cannot be + * modified later. + * @return options + */ + public GraphCreateOptions numberOfShards(final Integer numberOfShards) { + getOptions().setNumberOfShards(numberOfShards); + return this; + } + + public String getSmartGraphAttribute() { + return getOptions().getSmartGraphAttribute(); + } + + /** + * @param smartGraphAttribute The attribute name that is used to smartly shard the vertices of a graph. Every + * vertex in this Graph + * has to have this attribute. Cannot be modified later. + * @return options + */ + public GraphCreateOptions smartGraphAttribute(final String smartGraphAttribute) { + getOptions().setSmartGraphAttribute(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; + } + + public SmartOptions getOptions() { + if (options == null) { + options = new SmartOptions(); + } + return options; + } + + public static final class SmartOptions { + private ReplicationFactor replicationFactor; + private Integer writeConcern; + private Integer numberOfShards; + private String smartGraphAttribute; + private Boolean isDisjoint; + private Collection satellites; + + public SmartOptions() { + super(); + } + + public ReplicationFactor getReplicationFactor() { + return replicationFactor; + } + + public void setReplicationFactor(final ReplicationFactor replicationFactor) { + this.replicationFactor = replicationFactor; + } + + public Integer getWriteConcern() { + return writeConcern; + } + + public void setWriteConcern(final Integer writeConcern) { + this.writeConcern = writeConcern; + } + + public Integer getNumberOfShards() { + return numberOfShards; + } + + public void setNumberOfShards(final Integer numberOfShards) { + this.numberOfShards = numberOfShards; + } + + public String getSmartGraphAttribute() { + return smartGraphAttribute; + } + + public void setSmartGraphAttribute(final String smartGraphAttribute) { + this.smartGraphAttribute = smartGraphAttribute; + } + + public Boolean getIsDisjoint() { + return isDisjoint; + } + + 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/GraphDocumentReadOptions.java b/driver/src/main/java/com/arangodb/model/GraphDocumentReadOptions.java similarity index 100% rename from src/main/java/com/arangodb/model/GraphDocumentReadOptions.java rename to driver/src/main/java/com/arangodb/model/GraphDocumentReadOptions.java diff --git a/src/main/java/com/arangodb/model/HashIndexOptions.java b/driver/src/main/java/com/arangodb/model/HashIndexOptions.java similarity index 96% rename from src/main/java/com/arangodb/model/HashIndexOptions.java rename to driver/src/main/java/com/arangodb/model/HashIndexOptions.java index 633910c16..1924debe7 100644 --- a/src/main/java/com/arangodb/model/HashIndexOptions.java +++ b/driver/src/main/java/com/arangodb/model/HashIndexOptions.java @@ -1,121 +1,121 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.model; - -import com.arangodb.entity.IndexType; - -/** - * @author Mark Vollmary - * @see API Documentation - * @deprecated use {@link PersistentIndexOptions} instead. Since ArangoDB 3.7 a hash index is an alias for a persistent - * index. - */ -@Deprecated -public final class HashIndexOptions extends IndexOptions { - - private final IndexType type = IndexType.hash; - private Iterable fields; - private Boolean unique; - private Boolean sparse; - private Boolean deduplicate; - private Boolean estimates; - - public HashIndexOptions() { - super(); - } - - @Override - HashIndexOptions getThis() { - return this; - } - - public Iterable getFields() { - return fields; - } - - /** - * @param fields A list of attribute paths - * @return options - */ - HashIndexOptions fields(final Iterable fields) { - this.fields = fields; - return this; - } - - public IndexType getType() { - return type; - } - - public Boolean getUnique() { - return unique; - } - - /** - * @param unique if true, then create a unique index - * @return options - */ - public HashIndexOptions unique(final Boolean unique) { - this.unique = unique; - return this; - } - - public Boolean getSparse() { - return sparse; - } - - /** - * @param sparse if true, then create a sparse index - * @return options - */ - public HashIndexOptions sparse(final Boolean sparse) { - this.sparse = sparse; - return this; - } - - public Boolean getDeduplicate() { - return deduplicate; - } - - /** - * @param deduplicate if false, the deduplication of array values is turned off. - * @return options - */ - public HashIndexOptions deduplicate(final Boolean deduplicate) { - this.deduplicate = deduplicate; - return this; - } - - /** - * @param estimates This attribute controls whether index selectivity estimates are maintained for the index. - * Default: {@code - * true} - * @since ArangoDB 3.8 - */ - public HashIndexOptions estimates(final Boolean estimates) { - this.estimates = estimates; - return this; - } - - public Boolean getEstimates() { - return estimates; - } - -} +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed 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. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.model; + +import com.arangodb.entity.IndexType; + +/** + * @author Mark Vollmary + * @see API Documentation + * @deprecated use {@link PersistentIndexOptions} instead. Since ArangoDB 3.7 a hash index is an alias for a persistent + * index. + */ +@Deprecated +public final class HashIndexOptions extends IndexOptions { + + private final IndexType type = IndexType.hash; + private Iterable fields; + private Boolean unique; + private Boolean sparse; + private Boolean deduplicate; + private Boolean estimates; + + public HashIndexOptions() { + super(); + } + + @Override + HashIndexOptions getThis() { + return this; + } + + public Iterable getFields() { + return fields; + } + + /** + * @param fields A list of attribute paths + * @return options + */ + HashIndexOptions fields(final Iterable fields) { + this.fields = fields; + return this; + } + + public IndexType getType() { + return type; + } + + public Boolean getUnique() { + return unique; + } + + /** + * @param unique if true, then create a unique index + * @return options + */ + public HashIndexOptions unique(final Boolean unique) { + this.unique = unique; + return this; + } + + public Boolean getSparse() { + return sparse; + } + + /** + * @param sparse if true, then create a sparse index + * @return options + */ + public HashIndexOptions sparse(final Boolean sparse) { + this.sparse = sparse; + return this; + } + + public Boolean getDeduplicate() { + return deduplicate; + } + + /** + * @param deduplicate if false, the deduplication of array values is turned off. + * @return options + */ + public HashIndexOptions deduplicate(final Boolean deduplicate) { + this.deduplicate = deduplicate; + return this; + } + + /** + * @param estimates This attribute controls whether index selectivity estimates are maintained for the index. + * Default: {@code + * true} + * @since ArangoDB 3.8 + */ + public HashIndexOptions estimates(final Boolean estimates) { + this.estimates = estimates; + return this; + } + + public Boolean getEstimates() { + return estimates; + } + +} diff --git a/src/main/java/com/arangodb/model/ImportType.java b/driver/src/main/java/com/arangodb/model/ImportType.java similarity index 96% rename from src/main/java/com/arangodb/model/ImportType.java rename to driver/src/main/java/com/arangodb/model/ImportType.java index 17e4d5573..3cbd123e0 100644 --- a/src/main/java/com/arangodb/model/ImportType.java +++ b/driver/src/main/java/com/arangodb/model/ImportType.java @@ -1,28 +1,28 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.model; - -/** - * @author Mark Vollmary - */ -public enum ImportType { - documents, list, auto -} +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed 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. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.model; + +/** + * @author Mark Vollmary + */ +public enum ImportType { + documents, list, auto +} diff --git a/src/main/java/com/arangodb/model/IndexOptions.java b/driver/src/main/java/com/arangodb/model/IndexOptions.java similarity index 96% rename from src/main/java/com/arangodb/model/IndexOptions.java rename to driver/src/main/java/com/arangodb/model/IndexOptions.java index 69df19a8d..31a62c04e 100644 --- a/src/main/java/com/arangodb/model/IndexOptions.java +++ b/driver/src/main/java/com/arangodb/model/IndexOptions.java @@ -1,64 +1,64 @@ -/* - * DISCLAIMER - * - * Copyright 2019 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.model; - -/** - * @author Heiko Kernbach - *

    - * This final class is used for all index similarities - */ -public abstract class IndexOptions> { - - private Boolean inBackground; - private String name; - - protected IndexOptions() { - } - - abstract T getThis(); - - /** - * @param inBackground create the the index in the background - * this is a RocksDB only flag. - * @return options - */ - public T inBackground(final Boolean inBackground) { - this.inBackground = inBackground; - return getThis(); - } - - public Boolean getInBackground() { - return inBackground; - } - - /** - * @param name the name of the index - * @return options - */ - public T name(final String name) { - this.name = name; - return getThis(); - } - - public String getName() { - return name; - } -} +/* + * DISCLAIMER + * + * Copyright 2019 ArangoDB GmbH, Cologne, Germany + * + * Licensed 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. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.model; + +/** + * @author Heiko Kernbach + *

    + * This final class is used for all index similarities + */ +public abstract class IndexOptions> { + + private Boolean inBackground; + private String name; + + protected IndexOptions() { + } + + abstract T getThis(); + + /** + * @param inBackground create the the index in the background + * this is a RocksDB only flag. + * @return options + */ + public T inBackground(final Boolean inBackground) { + this.inBackground = inBackground; + return getThis(); + } + + public Boolean getInBackground() { + return inBackground; + } + + /** + * @param name the name of the index + * @return options + */ + public T name(final String name) { + this.name = name; + return getThis(); + } + + public String getName() { + return name; + } +} diff --git a/src/main/java/com/arangodb/model/InvertedIndexOptions.java b/driver/src/main/java/com/arangodb/model/InvertedIndexOptions.java similarity index 100% rename from src/main/java/com/arangodb/model/InvertedIndexOptions.java rename to driver/src/main/java/com/arangodb/model/InvertedIndexOptions.java diff --git a/src/main/java/com/arangodb/model/LogOptions.java b/driver/src/main/java/com/arangodb/model/LogOptions.java similarity index 96% rename from src/main/java/com/arangodb/model/LogOptions.java rename to driver/src/main/java/com/arangodb/model/LogOptions.java index bc5a25f17..a8d29071d 100644 --- a/src/main/java/com/arangodb/model/LogOptions.java +++ b/driver/src/main/java/com/arangodb/model/LogOptions.java @@ -1,152 +1,152 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.model; - -import com.arangodb.entity.LogLevel; - -/** - * @author Mark Vollmary - * @see API - * Documentation - */ -public final class LogOptions { - - public static final String PROPERTY_UPTO = "upto"; - public static final String PROPERTY_LEVEL = "level"; - public static final String PROPERTY_START = "start"; - public static final String PROPERTY_SIZE = "size"; - public static final String PROPERTY_OFFSET = "offset"; - public static final String PROPERTY_SEARCH = "search"; - public static final String PROPERTY_SORT = "sort"; - private LogLevel upto; - private LogLevel level; - private Long start; - private Integer size; - private Integer offset; - private String search; - private SortOrder sort; - - public LogOptions() { - super(); - } - - public LogLevel getUpto() { - return upto; - } - - /** - * @param upto Returns all log entries up to log level upto - * @return options - */ - public LogOptions upto(final LogLevel upto) { - this.upto = upto; - return this; - } - - public LogLevel getLevel() { - return level; - } - - /** - * @param level Returns all log entries of log level level. Note that the query parameters upto and level are - * mutually - * exclusive - * @return options - */ - public LogOptions level(final LogLevel level) { - this.level = level; - return this; - } - - public Long getStart() { - return start; - } - - /** - * @param start Returns all log entries such that their log entry identifier (lid value) is greater or equal to - * start - * @return options - */ - public LogOptions start(final Long start) { - this.start = start; - return this; - } - - public Integer getSize() { - return size; - } - - /** - * @param size Restricts the result to at most size log entries - * @return options - */ - public LogOptions size(final Integer size) { - this.size = size; - return this; - } - - public Integer getOffset() { - return offset; - } - - /** - * @param offset Starts to return log entries skipping the first offset log entries. offset and size can be used for - * pagination - * @return options - */ - public LogOptions offset(final Integer offset) { - this.offset = offset; - return this; - } - - public String getSearch() { - return search; - } - - /** - * @param search Only return the log entries containing the text specified in search - * @return options - */ - public LogOptions search(final String search) { - this.search = search; - return this; - } - - public SortOrder getSort() { - return sort; - } - - /** - * @param sort Sort the log entries either ascending (if sort is asc) or descending (if sort is desc) according to - * their lid values. Note that the lid imposes a chronological order. The default value is asc - * @return options - */ - public LogOptions sort(final SortOrder sort) { - this.sort = sort; - return this; - } - - public enum SortOrder { - asc, desc - } - -} +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed 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. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.model; + +import com.arangodb.entity.LogLevel; + +/** + * @author Mark Vollmary + * @see API + * Documentation + */ +public final class LogOptions { + + public static final String PROPERTY_UPTO = "upto"; + public static final String PROPERTY_LEVEL = "level"; + public static final String PROPERTY_START = "start"; + public static final String PROPERTY_SIZE = "size"; + public static final String PROPERTY_OFFSET = "offset"; + public static final String PROPERTY_SEARCH = "search"; + public static final String PROPERTY_SORT = "sort"; + private LogLevel upto; + private LogLevel level; + private Long start; + private Integer size; + private Integer offset; + private String search; + private SortOrder sort; + + public LogOptions() { + super(); + } + + public LogLevel getUpto() { + return upto; + } + + /** + * @param upto Returns all log entries up to log level upto + * @return options + */ + public LogOptions upto(final LogLevel upto) { + this.upto = upto; + return this; + } + + public LogLevel getLevel() { + return level; + } + + /** + * @param level Returns all log entries of log level level. Note that the query parameters upto and level are + * mutually + * exclusive + * @return options + */ + public LogOptions level(final LogLevel level) { + this.level = level; + return this; + } + + public Long getStart() { + return start; + } + + /** + * @param start Returns all log entries such that their log entry identifier (lid value) is greater or equal to + * start + * @return options + */ + public LogOptions start(final Long start) { + this.start = start; + return this; + } + + public Integer getSize() { + return size; + } + + /** + * @param size Restricts the result to at most size log entries + * @return options + */ + public LogOptions size(final Integer size) { + this.size = size; + return this; + } + + public Integer getOffset() { + return offset; + } + + /** + * @param offset Starts to return log entries skipping the first offset log entries. offset and size can be used for + * pagination + * @return options + */ + public LogOptions offset(final Integer offset) { + this.offset = offset; + return this; + } + + public String getSearch() { + return search; + } + + /** + * @param search Only return the log entries containing the text specified in search + * @return options + */ + public LogOptions search(final String search) { + this.search = search; + return this; + } + + public SortOrder getSort() { + return sort; + } + + /** + * @param sort Sort the log entries either ascending (if sort is asc) or descending (if sort is desc) according to + * their lid values. Note that the lid imposes a chronological order. The default value is asc + * @return options + */ + public LogOptions sort(final SortOrder sort) { + this.sort = sort; + return this; + } + + public enum SortOrder { + asc, desc + } + +} diff --git a/src/main/java/com/arangodb/model/OptionsBuilder.java b/driver/src/main/java/com/arangodb/model/OptionsBuilder.java similarity index 100% rename from src/main/java/com/arangodb/model/OptionsBuilder.java rename to driver/src/main/java/com/arangodb/model/OptionsBuilder.java diff --git a/src/main/java/com/arangodb/model/OverwriteMode.java b/driver/src/main/java/com/arangodb/model/OverwriteMode.java similarity index 100% rename from src/main/java/com/arangodb/model/OverwriteMode.java rename to driver/src/main/java/com/arangodb/model/OverwriteMode.java diff --git a/src/main/java/com/arangodb/model/PersistentIndexOptions.java b/driver/src/main/java/com/arangodb/model/PersistentIndexOptions.java similarity index 96% rename from src/main/java/com/arangodb/model/PersistentIndexOptions.java rename to driver/src/main/java/com/arangodb/model/PersistentIndexOptions.java index 1ad5be93c..583a2e107 100644 --- a/src/main/java/com/arangodb/model/PersistentIndexOptions.java +++ b/driver/src/main/java/com/arangodb/model/PersistentIndexOptions.java @@ -1,158 +1,158 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.model; - -import com.arangodb.entity.IndexType; - -import java.util.Collection; -import java.util.Collections; -import java.util.HashSet; - -/** - * @author Mark Vollmary - * @see API - * Documentation - */ -public final class PersistentIndexOptions extends IndexOptions { - - private final IndexType type = IndexType.persistent; - private Iterable fields; - private Boolean unique; - private Boolean sparse; - private Boolean deduplicate; - private Boolean estimates; - private Boolean cacheEnabled; - private Collection storedValues; - - public PersistentIndexOptions() { - super(); - } - - @Override - PersistentIndexOptions getThis() { - return this; - } - - public Iterable getFields() { - return fields; - } - - /** - * @param fields A list of attribute paths - * @return options - */ - PersistentIndexOptions fields(final Iterable fields) { - this.fields = fields; - return this; - } - - public IndexType getType() { - return type; - } - - public Boolean getUnique() { - return unique; - } - - /** - * @param unique if true, then create a unique index - * @return options - */ - public PersistentIndexOptions unique(final Boolean unique) { - this.unique = unique; - return this; - } - - public Boolean getSparse() { - return sparse; - } - - /** - * @param sparse if true, then create a sparse index - * @return options - */ - public PersistentIndexOptions sparse(final Boolean sparse) { - this.sparse = sparse; - return this; - } - - public Boolean getDeduplicate() { - return deduplicate; - } - - /** - * @param deduplicate if false, the deduplication of array values is turned off. Default: {@code true} - * @return options - */ - public PersistentIndexOptions deduplicate(final Boolean deduplicate) { - this.deduplicate = deduplicate; - return this; - } - - /** - * @param estimates This attribute controls whether index selectivity estimates are maintained for the index. - * Default: {@code - * true} - * @since ArangoDB 3.8 - */ - public PersistentIndexOptions estimates(final Boolean estimates) { - this.estimates = estimates; - return this; - } - - public Boolean getEstimates() { - return estimates; - } - - /** - * @param cacheEnabled enables in-memory caching of index entries - * @return options - * @since ArangoDB 3.10 - */ - public PersistentIndexOptions cacheEnabled(final Boolean cacheEnabled) { - this.cacheEnabled = cacheEnabled; - return this; - } - - public Boolean getCacheEnabled() { - return cacheEnabled; - } - - public Collection getStoredValues() { - return storedValues; - } - - /** - * @param storedValues (optional) array of paths to additional attributes to store in the index. These additional - * attributes cannot be used for index lookups or for sorting, but they can be used for - * projections. This allows an index to fully cover more queries and avoid extra document - * lookups. The maximum number of attributes in `storedValues` is 32. - * @return options - */ - public PersistentIndexOptions storedValues(final String... storedValues) { - if (this.storedValues == null) { - this.storedValues = new HashSet<>(); - } - Collections.addAll(this.storedValues, storedValues); - return this; - } - -} +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed 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. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.model; + +import com.arangodb.entity.IndexType; + +import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; + +/** + * @author Mark Vollmary + * @see API + * Documentation + */ +public final class PersistentIndexOptions extends IndexOptions { + + private final IndexType type = IndexType.persistent; + private Iterable fields; + private Boolean unique; + private Boolean sparse; + private Boolean deduplicate; + private Boolean estimates; + private Boolean cacheEnabled; + private Collection storedValues; + + public PersistentIndexOptions() { + super(); + } + + @Override + PersistentIndexOptions getThis() { + return this; + } + + public Iterable getFields() { + return fields; + } + + /** + * @param fields A list of attribute paths + * @return options + */ + PersistentIndexOptions fields(final Iterable fields) { + this.fields = fields; + return this; + } + + public IndexType getType() { + return type; + } + + public Boolean getUnique() { + return unique; + } + + /** + * @param unique if true, then create a unique index + * @return options + */ + public PersistentIndexOptions unique(final Boolean unique) { + this.unique = unique; + return this; + } + + public Boolean getSparse() { + return sparse; + } + + /** + * @param sparse if true, then create a sparse index + * @return options + */ + public PersistentIndexOptions sparse(final Boolean sparse) { + this.sparse = sparse; + return this; + } + + public Boolean getDeduplicate() { + return deduplicate; + } + + /** + * @param deduplicate if false, the deduplication of array values is turned off. Default: {@code true} + * @return options + */ + public PersistentIndexOptions deduplicate(final Boolean deduplicate) { + this.deduplicate = deduplicate; + return this; + } + + /** + * @param estimates This attribute controls whether index selectivity estimates are maintained for the index. + * Default: {@code + * true} + * @since ArangoDB 3.8 + */ + public PersistentIndexOptions estimates(final Boolean estimates) { + this.estimates = estimates; + return this; + } + + public Boolean getEstimates() { + return estimates; + } + + /** + * @param cacheEnabled enables in-memory caching of index entries + * @return options + * @since ArangoDB 3.10 + */ + public PersistentIndexOptions cacheEnabled(final Boolean cacheEnabled) { + this.cacheEnabled = cacheEnabled; + return this; + } + + public Boolean getCacheEnabled() { + return cacheEnabled; + } + + public Collection getStoredValues() { + return storedValues; + } + + /** + * @param storedValues (optional) array of paths to additional attributes to store in the index. These additional + * attributes cannot be used for index lookups or for sorting, but they can be used for + * projections. This allows an index to fully cover more queries and avoid extra document + * lookups. The maximum number of attributes in `storedValues` is 32. + * @return options + */ + public PersistentIndexOptions storedValues(final String... storedValues) { + if (this.storedValues == null) { + this.storedValues = new HashSet<>(); + } + Collections.addAll(this.storedValues, storedValues); + return this; + } + +} diff --git a/src/main/java/com/arangodb/model/QueueTimeSample.java b/driver/src/main/java/com/arangodb/model/QueueTimeSample.java similarity index 100% rename from src/main/java/com/arangodb/model/QueueTimeSample.java rename to driver/src/main/java/com/arangodb/model/QueueTimeSample.java diff --git a/src/main/java/com/arangodb/model/SkiplistIndexOptions.java b/driver/src/main/java/com/arangodb/model/SkiplistIndexOptions.java similarity index 96% rename from src/main/java/com/arangodb/model/SkiplistIndexOptions.java rename to driver/src/main/java/com/arangodb/model/SkiplistIndexOptions.java index e608632e9..bb1cc87d4 100644 --- a/src/main/java/com/arangodb/model/SkiplistIndexOptions.java +++ b/driver/src/main/java/com/arangodb/model/SkiplistIndexOptions.java @@ -1,121 +1,121 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.model; - -import com.arangodb.entity.IndexType; - -/** - * @author Mark Vollmary - * @see API Documentation - * @deprecated use {@link PersistentIndexOptions} instead. Since ArangoDB 3.7 a skiplist index is an alias for a - * persistent index. - */ -@Deprecated -public final class SkiplistIndexOptions extends IndexOptions { - - private final IndexType type = IndexType.skiplist; - private Iterable fields; - private Boolean unique; - private Boolean sparse; - private Boolean deduplicate; - private Boolean estimates; - - public SkiplistIndexOptions() { - super(); - } - - @Override - SkiplistIndexOptions getThis() { - return this; - } - - public Iterable getFields() { - return fields; - } - - /** - * @param fields A list of attribute paths - * @return options - */ - SkiplistIndexOptions fields(final Iterable fields) { - this.fields = fields; - return this; - } - - public IndexType getType() { - return type; - } - - public Boolean getUnique() { - return unique; - } - - /** - * @param unique if true, then create a unique index - * @return options - */ - public SkiplistIndexOptions unique(final Boolean unique) { - this.unique = unique; - return this; - } - - public Boolean getSparse() { - return sparse; - } - - /** - * @param sparse if true, then create a sparse index - * @return options - */ - public SkiplistIndexOptions sparse(final Boolean sparse) { - this.sparse = sparse; - return this; - } - - public Boolean getDeduplicate() { - return deduplicate; - } - - /** - * @param deduplicate if false, the deduplication of array values is turned off. - * @return options - */ - public SkiplistIndexOptions deduplicate(final Boolean deduplicate) { - this.deduplicate = deduplicate; - return this; - } - - /** - * @param estimates This attribute controls whether index selectivity estimates are maintained for the index. - * Default: {@code - * true} - * @since ArangoDB 3.8 - */ - public SkiplistIndexOptions estimates(final Boolean estimates) { - this.estimates = estimates; - return this; - } - - public Boolean getEstimates() { - return estimates; - } - -} +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed 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. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.model; + +import com.arangodb.entity.IndexType; + +/** + * @author Mark Vollmary + * @see API Documentation + * @deprecated use {@link PersistentIndexOptions} instead. Since ArangoDB 3.7 a skiplist index is an alias for a + * persistent index. + */ +@Deprecated +public final class SkiplistIndexOptions extends IndexOptions { + + private final IndexType type = IndexType.skiplist; + private Iterable fields; + private Boolean unique; + private Boolean sparse; + private Boolean deduplicate; + private Boolean estimates; + + public SkiplistIndexOptions() { + super(); + } + + @Override + SkiplistIndexOptions getThis() { + return this; + } + + public Iterable getFields() { + return fields; + } + + /** + * @param fields A list of attribute paths + * @return options + */ + SkiplistIndexOptions fields(final Iterable fields) { + this.fields = fields; + return this; + } + + public IndexType getType() { + return type; + } + + public Boolean getUnique() { + return unique; + } + + /** + * @param unique if true, then create a unique index + * @return options + */ + public SkiplistIndexOptions unique(final Boolean unique) { + this.unique = unique; + return this; + } + + public Boolean getSparse() { + return sparse; + } + + /** + * @param sparse if true, then create a sparse index + * @return options + */ + public SkiplistIndexOptions sparse(final Boolean sparse) { + this.sparse = sparse; + return this; + } + + public Boolean getDeduplicate() { + return deduplicate; + } + + /** + * @param deduplicate if false, the deduplication of array values is turned off. + * @return options + */ + public SkiplistIndexOptions deduplicate(final Boolean deduplicate) { + this.deduplicate = deduplicate; + return this; + } + + /** + * @param estimates This attribute controls whether index selectivity estimates are maintained for the index. + * Default: {@code + * true} + * @since ArangoDB 3.8 + */ + public SkiplistIndexOptions estimates(final Boolean estimates) { + this.estimates = estimates; + return this; + } + + public Boolean getEstimates() { + return estimates; + } + +} diff --git a/src/main/java/com/arangodb/model/StreamTransactionOptions.java b/driver/src/main/java/com/arangodb/model/StreamTransactionOptions.java similarity index 100% rename from src/main/java/com/arangodb/model/StreamTransactionOptions.java rename to driver/src/main/java/com/arangodb/model/StreamTransactionOptions.java diff --git a/src/main/java/com/arangodb/model/TransactionCollectionOptions.java b/driver/src/main/java/com/arangodb/model/TransactionCollectionOptions.java similarity index 100% rename from src/main/java/com/arangodb/model/TransactionCollectionOptions.java rename to driver/src/main/java/com/arangodb/model/TransactionCollectionOptions.java diff --git a/src/main/java/com/arangodb/model/TransactionOptions.java b/driver/src/main/java/com/arangodb/model/TransactionOptions.java similarity index 100% rename from src/main/java/com/arangodb/model/TransactionOptions.java rename to driver/src/main/java/com/arangodb/model/TransactionOptions.java diff --git a/src/main/java/com/arangodb/model/TtlIndexOptions.java b/driver/src/main/java/com/arangodb/model/TtlIndexOptions.java similarity index 96% rename from src/main/java/com/arangodb/model/TtlIndexOptions.java rename to driver/src/main/java/com/arangodb/model/TtlIndexOptions.java index bca69e759..65aa5af58 100644 --- a/src/main/java/com/arangodb/model/TtlIndexOptions.java +++ b/driver/src/main/java/com/arangodb/model/TtlIndexOptions.java @@ -1,75 +1,75 @@ -/* - * DISCLAIMER - * - * Copyright 2019 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.model; - -import com.arangodb.entity.IndexType; - -/** - * @author Heiko Kernbach - * @see API Documentation - */ -public final class TtlIndexOptions extends IndexOptions { - - private final IndexType type = IndexType.ttl; - private Iterable fields; - private Integer expireAfter; - - public TtlIndexOptions() { - super(); - } - - @Override - TtlIndexOptions getThis() { - return this; - } - - public Iterable getFields() { - return fields; - } - - /** - * @param fields A list of attribute paths - * @return options - */ - TtlIndexOptions fields(final Iterable fields) { - this.fields = fields; - return this; - } - - public IndexType getType() { - return type; - } - - /** - * @param expireAfter The time (in seconds) after a document’s creation after which the documents count as - * “expired”. - * @return options - */ - public TtlIndexOptions expireAfter(final Integer expireAfter) { - this.expireAfter = expireAfter; - return this; - } - - public Integer getExpireAfter() { - return expireAfter; - } - -} +/* + * DISCLAIMER + * + * Copyright 2019 ArangoDB GmbH, Cologne, Germany + * + * Licensed 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. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.model; + +import com.arangodb.entity.IndexType; + +/** + * @author Heiko Kernbach + * @see API Documentation + */ +public final class TtlIndexOptions extends IndexOptions { + + private final IndexType type = IndexType.ttl; + private Iterable fields; + private Integer expireAfter; + + public TtlIndexOptions() { + super(); + } + + @Override + TtlIndexOptions getThis() { + return this; + } + + public Iterable getFields() { + return fields; + } + + /** + * @param fields A list of attribute paths + * @return options + */ + TtlIndexOptions fields(final Iterable fields) { + this.fields = fields; + return this; + } + + public IndexType getType() { + return type; + } + + /** + * @param expireAfter The time (in seconds) after a document’s creation after which the documents count as + * “expired”. + * @return options + */ + public TtlIndexOptions expireAfter(final Integer expireAfter) { + this.expireAfter = expireAfter; + return this; + } + + public Integer getExpireAfter() { + return expireAfter; + } + +} diff --git a/src/main/java/com/arangodb/model/UserAccessOptions.java b/driver/src/main/java/com/arangodb/model/UserAccessOptions.java similarity index 96% rename from src/main/java/com/arangodb/model/UserAccessOptions.java rename to driver/src/main/java/com/arangodb/model/UserAccessOptions.java index 19c597ab7..9ac9ebfb3 100644 --- a/src/main/java/com/arangodb/model/UserAccessOptions.java +++ b/driver/src/main/java/com/arangodb/model/UserAccessOptions.java @@ -1,45 +1,45 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.model; - -import com.arangodb.entity.Permissions; - -/** - * @author Mark Vollmary - */ -public final class UserAccessOptions { - - private Permissions grant; - - public UserAccessOptions() { - super(); - } - - public Permissions getGrant() { - return grant; - } - - UserAccessOptions grant(final Permissions grant) { - this.grant = grant; - return this; - } - -} +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed 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. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.model; + +import com.arangodb.entity.Permissions; + +/** + * @author Mark Vollmary + */ +public final class UserAccessOptions { + + private Permissions grant; + + public UserAccessOptions() { + super(); + } + + public Permissions getGrant() { + return grant; + } + + UserAccessOptions grant(final Permissions grant) { + this.grant = grant; + return this; + } + +} diff --git a/src/main/java/com/arangodb/model/UserCreateOptions.java b/driver/src/main/java/com/arangodb/model/UserCreateOptions.java similarity index 96% rename from src/main/java/com/arangodb/model/UserCreateOptions.java rename to driver/src/main/java/com/arangodb/model/UserCreateOptions.java index 4279e60d6..cc210b004 100644 --- a/src/main/java/com/arangodb/model/UserCreateOptions.java +++ b/driver/src/main/java/com/arangodb/model/UserCreateOptions.java @@ -1,93 +1,93 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.model; - -import java.util.Map; - -/** - * @author Mark Vollmary - * @see API Documentation - */ -public final class UserCreateOptions { - - private String user; - private String passwd; - private Boolean active; - private Map extra; - - public UserCreateOptions() { - super(); - } - - public String getUser() { - return user; - } - - /** - * @param user The name of the user - * @return options - */ - UserCreateOptions user(final String user) { - this.user = user; - return this; - } - - public String getPasswd() { - return passwd; - } - - /** - * @param passwd The user password - * @return options - */ - UserCreateOptions passwd(final String passwd) { - this.passwd = passwd; - return this; - } - - public Boolean getActive() { - return active; - } - - /** - * @param active An optional flag that specifies whether the user is active. If not specified, this will default to - * true - * @return options - */ - public UserCreateOptions active(final Boolean active) { - this.active = active; - return this; - } - - public Map getExtra() { - return extra; - } - - /** - * @param extra Optional data about the user - * @return options - */ - public UserCreateOptions extra(final Map extra) { - this.extra = extra; - return this; - } - -} +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed 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. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.model; + +import java.util.Map; + +/** + * @author Mark Vollmary + * @see API Documentation + */ +public final class UserCreateOptions { + + private String user; + private String passwd; + private Boolean active; + private Map extra; + + public UserCreateOptions() { + super(); + } + + public String getUser() { + return user; + } + + /** + * @param user The name of the user + * @return options + */ + UserCreateOptions user(final String user) { + this.user = user; + return this; + } + + public String getPasswd() { + return passwd; + } + + /** + * @param passwd The user password + * @return options + */ + UserCreateOptions passwd(final String passwd) { + this.passwd = passwd; + return this; + } + + public Boolean getActive() { + return active; + } + + /** + * @param active An optional flag that specifies whether the user is active. If not specified, this will default to + * true + * @return options + */ + public UserCreateOptions active(final Boolean active) { + this.active = active; + return this; + } + + public Map getExtra() { + return extra; + } + + /** + * @param extra Optional data about the user + * @return options + */ + public UserCreateOptions extra(final Map extra) { + this.extra = extra; + return this; + } + +} diff --git a/src/main/java/com/arangodb/model/UserUpdateOptions.java b/driver/src/main/java/com/arangodb/model/UserUpdateOptions.java similarity index 96% rename from src/main/java/com/arangodb/model/UserUpdateOptions.java rename to driver/src/main/java/com/arangodb/model/UserUpdateOptions.java index 09c3786c8..4f9077791 100644 --- a/src/main/java/com/arangodb/model/UserUpdateOptions.java +++ b/driver/src/main/java/com/arangodb/model/UserUpdateOptions.java @@ -1,79 +1,79 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.model; - -import java.util.Map; - -/** - * @author Mark Vollmary - * @see API Documentation - */ -public final class UserUpdateOptions { - - private String passwd; - private Boolean active; - private Map extra; - - public UserUpdateOptions() { - super(); - } - - public String getPasswd() { - return passwd; - } - - /** - * @param passwd The user password - * @return options - */ - public UserUpdateOptions passwd(final String passwd) { - this.passwd = passwd; - return this; - } - - public Boolean getActive() { - return active; - } - - /** - * @param active An optional flag that specifies whether the user is active. If not specified, this will default to - * true - * @return options - */ - public UserUpdateOptions active(final Boolean active) { - this.active = active; - return this; - } - - public Map getExtra() { - return extra; - } - - /** - * @param extra Optional data about the user - * @return options - */ - public UserUpdateOptions extra(final Map extra) { - this.extra = extra; - return this; - } - -} +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed 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. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.model; + +import java.util.Map; + +/** + * @author Mark Vollmary + * @see API Documentation + */ +public final class UserUpdateOptions { + + private String passwd; + private Boolean active; + private Map extra; + + public UserUpdateOptions() { + super(); + } + + public String getPasswd() { + return passwd; + } + + /** + * @param passwd The user password + * @return options + */ + public UserUpdateOptions passwd(final String passwd) { + this.passwd = passwd; + return this; + } + + public Boolean getActive() { + return active; + } + + /** + * @param active An optional flag that specifies whether the user is active. If not specified, this will default to + * true + * @return options + */ + public UserUpdateOptions active(final Boolean active) { + this.active = active; + return this; + } + + public Map getExtra() { + return extra; + } + + /** + * @param extra Optional data about the user + * @return options + */ + public UserUpdateOptions extra(final Map extra) { + this.extra = extra; + return this; + } + +} diff --git a/src/main/java/com/arangodb/model/VertexCollectionCreateOptions.java b/driver/src/main/java/com/arangodb/model/VertexCollectionCreateOptions.java similarity index 96% rename from src/main/java/com/arangodb/model/VertexCollectionCreateOptions.java rename to driver/src/main/java/com/arangodb/model/VertexCollectionCreateOptions.java index a832f3f88..d7ab02a70 100644 --- a/src/main/java/com/arangodb/model/VertexCollectionCreateOptions.java +++ b/driver/src/main/java/com/arangodb/model/VertexCollectionCreateOptions.java @@ -1,79 +1,79 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.model; - -import java.util.Arrays; -import java.util.Collection; - -/** - * @author Mark Vollmary - */ -public final class VertexCollectionCreateOptions { - - private final Options options = new Options(); - private String collection; - - public VertexCollectionCreateOptions() { - super(); - } - - public String getCollection() { - return collection; - } - - /** - * @param collection The name of the collection - * @return options - */ - VertexCollectionCreateOptions collection(final String collection) { - this.collection = collection; - return this; - } - - public Options getOptions() { - return options; - } - - 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.satellites = Arrays.asList(satellites); - return this; - } - - public static final class Options { - private Collection satellites; - - public Collection getSatellites() { - return satellites; - } - } - -} +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed 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. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.model; + +import java.util.Arrays; +import java.util.Collection; + +/** + * @author Mark Vollmary + */ +public final class VertexCollectionCreateOptions { + + private final Options options = new Options(); + private String collection; + + public VertexCollectionCreateOptions() { + super(); + } + + public String getCollection() { + return collection; + } + + /** + * @param collection The name of the collection + * @return options + */ + VertexCollectionCreateOptions collection(final String collection) { + this.collection = collection; + return this; + } + + public Options getOptions() { + return options; + } + + 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.satellites = Arrays.asList(satellites); + return this; + } + + public static final class Options { + private Collection satellites; + + public Collection getSatellites() { + return satellites; + } + } + +} diff --git a/src/main/java/com/arangodb/model/VertexCreateOptions.java b/driver/src/main/java/com/arangodb/model/VertexCreateOptions.java similarity index 96% rename from src/main/java/com/arangodb/model/VertexCreateOptions.java rename to driver/src/main/java/com/arangodb/model/VertexCreateOptions.java index 156476a93..62397a68d 100644 --- a/src/main/java/com/arangodb/model/VertexCreateOptions.java +++ b/driver/src/main/java/com/arangodb/model/VertexCreateOptions.java @@ -1,63 +1,63 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.model; - -/** - * @author Mark Vollmary - * @see API Documentation - */ -public final class VertexCreateOptions { - - private Boolean waitForSync; - private String streamTransactionId; - - public VertexCreateOptions() { - super(); - } - - public Boolean getWaitForSync() { - return waitForSync; - } - - /** - * @param waitForSync Wait until document has been synced to disk. - * @return options - */ - public VertexCreateOptions waitForSync(final Boolean waitForSync) { - this.waitForSync = waitForSync; - return this; - } - - public String getStreamTransactionId() { - return streamTransactionId; - } - - /** - * @param streamTransactionId If set, the operation will be executed within the transaction. - * @return options - * @since ArangoDB 3.5.1 - */ - public VertexCreateOptions streamTransactionId(final String streamTransactionId) { - this.streamTransactionId = streamTransactionId; - return this; - } - -} +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed 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. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.model; + +/** + * @author Mark Vollmary + * @see API Documentation + */ +public final class VertexCreateOptions { + + private Boolean waitForSync; + private String streamTransactionId; + + public VertexCreateOptions() { + super(); + } + + public Boolean getWaitForSync() { + return waitForSync; + } + + /** + * @param waitForSync Wait until document has been synced to disk. + * @return options + */ + public VertexCreateOptions waitForSync(final Boolean waitForSync) { + this.waitForSync = waitForSync; + return this; + } + + public String getStreamTransactionId() { + return streamTransactionId; + } + + /** + * @param streamTransactionId If set, the operation will be executed within the transaction. + * @return options + * @since ArangoDB 3.5.1 + */ + public VertexCreateOptions streamTransactionId(final String streamTransactionId) { + this.streamTransactionId = streamTransactionId; + return this; + } + +} diff --git a/src/main/java/com/arangodb/model/VertexDeleteOptions.java b/driver/src/main/java/com/arangodb/model/VertexDeleteOptions.java similarity index 96% rename from src/main/java/com/arangodb/model/VertexDeleteOptions.java rename to driver/src/main/java/com/arangodb/model/VertexDeleteOptions.java index e43c6d016..98af70ace 100644 --- a/src/main/java/com/arangodb/model/VertexDeleteOptions.java +++ b/driver/src/main/java/com/arangodb/model/VertexDeleteOptions.java @@ -1,77 +1,77 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.model; - -/** - * @author Mark Vollmary - * @see API Documentation - */ -public final class VertexDeleteOptions { - - private Boolean waitForSync; - private String ifMatch; - private String streamTransactionId; - - public VertexDeleteOptions() { - super(); - } - - public Boolean getWaitForSync() { - return waitForSync; - } - - /** - * @param waitForSync Wait until deletion operation has been synced to disk. - * @return options - */ - public VertexDeleteOptions waitForSync(final Boolean waitForSync) { - this.waitForSync = waitForSync; - return this; - } - - public String getIfMatch() { - return ifMatch; - } - - /** - * @param ifMatch remove a document based on a target revision - * @return options - */ - public VertexDeleteOptions ifMatch(final String ifMatch) { - this.ifMatch = ifMatch; - return this; - } - - public String getStreamTransactionId() { - return streamTransactionId; - } - - /** - * @param streamTransactionId If set, the operation will be executed within the transaction. - * @return options - * @since ArangoDB 3.5.1 - */ - public VertexDeleteOptions streamTransactionId(final String streamTransactionId) { - this.streamTransactionId = streamTransactionId; - return this; - } - -} +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed 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. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.model; + +/** + * @author Mark Vollmary + * @see API Documentation + */ +public final class VertexDeleteOptions { + + private Boolean waitForSync; + private String ifMatch; + private String streamTransactionId; + + public VertexDeleteOptions() { + super(); + } + + public Boolean getWaitForSync() { + return waitForSync; + } + + /** + * @param waitForSync Wait until deletion operation has been synced to disk. + * @return options + */ + public VertexDeleteOptions waitForSync(final Boolean waitForSync) { + this.waitForSync = waitForSync; + return this; + } + + public String getIfMatch() { + return ifMatch; + } + + /** + * @param ifMatch remove a document based on a target revision + * @return options + */ + public VertexDeleteOptions ifMatch(final String ifMatch) { + this.ifMatch = ifMatch; + return this; + } + + public String getStreamTransactionId() { + return streamTransactionId; + } + + /** + * @param streamTransactionId If set, the operation will be executed within the transaction. + * @return options + * @since ArangoDB 3.5.1 + */ + public VertexDeleteOptions streamTransactionId(final String streamTransactionId) { + this.streamTransactionId = streamTransactionId; + return this; + } + +} diff --git a/src/main/java/com/arangodb/model/VertexReplaceOptions.java b/driver/src/main/java/com/arangodb/model/VertexReplaceOptions.java similarity index 96% rename from src/main/java/com/arangodb/model/VertexReplaceOptions.java rename to driver/src/main/java/com/arangodb/model/VertexReplaceOptions.java index 9111f11e0..0efe64298 100644 --- a/src/main/java/com/arangodb/model/VertexReplaceOptions.java +++ b/driver/src/main/java/com/arangodb/model/VertexReplaceOptions.java @@ -1,77 +1,77 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.model; - -/** - * @author Mark Vollmary - * @see API Documentation - */ -public final class VertexReplaceOptions { - - private Boolean waitForSync; - private String ifMatch; - private String streamTransactionId; - - public VertexReplaceOptions() { - super(); - } - - public Boolean getWaitForSync() { - return waitForSync; - } - - /** - * @param waitForSync Wait until document has been synced to disk. - * @return options - */ - public VertexReplaceOptions waitForSync(final Boolean waitForSync) { - this.waitForSync = waitForSync; - return this; - } - - public String getIfMatch() { - return ifMatch; - } - - /** - * @param ifMatch replace a document based on target revision - * @return options - */ - public VertexReplaceOptions ifMatch(final String ifMatch) { - this.ifMatch = ifMatch; - return this; - } - - public String getStreamTransactionId() { - return streamTransactionId; - } - - /** - * @param streamTransactionId If set, the operation will be executed within the transaction. - * @return options - * @since ArangoDB 3.5.1 - */ - public VertexReplaceOptions streamTransactionId(final String streamTransactionId) { - this.streamTransactionId = streamTransactionId; - return this; - } - -} +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed 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. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.model; + +/** + * @author Mark Vollmary + * @see API Documentation + */ +public final class VertexReplaceOptions { + + private Boolean waitForSync; + private String ifMatch; + private String streamTransactionId; + + public VertexReplaceOptions() { + super(); + } + + public Boolean getWaitForSync() { + return waitForSync; + } + + /** + * @param waitForSync Wait until document has been synced to disk. + * @return options + */ + public VertexReplaceOptions waitForSync(final Boolean waitForSync) { + this.waitForSync = waitForSync; + return this; + } + + public String getIfMatch() { + return ifMatch; + } + + /** + * @param ifMatch replace a document based on target revision + * @return options + */ + public VertexReplaceOptions ifMatch(final String ifMatch) { + this.ifMatch = ifMatch; + return this; + } + + public String getStreamTransactionId() { + return streamTransactionId; + } + + /** + * @param streamTransactionId If set, the operation will be executed within the transaction. + * @return options + * @since ArangoDB 3.5.1 + */ + public VertexReplaceOptions streamTransactionId(final String streamTransactionId) { + this.streamTransactionId = streamTransactionId; + return this; + } + +} diff --git a/src/main/java/com/arangodb/model/VertexUpdateOptions.java b/driver/src/main/java/com/arangodb/model/VertexUpdateOptions.java similarity index 96% rename from src/main/java/com/arangodb/model/VertexUpdateOptions.java rename to driver/src/main/java/com/arangodb/model/VertexUpdateOptions.java index a66e9b450..62554a193 100644 --- a/src/main/java/com/arangodb/model/VertexUpdateOptions.java +++ b/driver/src/main/java/com/arangodb/model/VertexUpdateOptions.java @@ -1,93 +1,93 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.model; - -/** - * @author Mark Vollmary - * @see API Documentation - */ -public final class VertexUpdateOptions { - - private Boolean keepNull; - private Boolean waitForSync; - private String ifMatch; - private String streamTransactionId; - - public VertexUpdateOptions() { - super(); - } - - public Boolean getKeepNull() { - return keepNull; - } - - /** - * @param keepNull If the intention is to delete existing attributes with the patch command, the URL query parameter - * keepNull can be used with a value of false. This will modify the behavior of the patch command to - * remove any attributes from the existing document that are contained in the patch document with an - * attribute value of null. - * @return options - */ - public VertexUpdateOptions keepNull(final Boolean keepNull) { - this.keepNull = keepNull; - return this; - } - - public Boolean getWaitForSync() { - return waitForSync; - } - - /** - * @param waitForSync Wait until document has been synced to disk. - * @return options - */ - public VertexUpdateOptions waitForSync(final Boolean waitForSync) { - this.waitForSync = waitForSync; - return this; - } - - public String getIfMatch() { - return ifMatch; - } - - /** - * @param ifMatch replace a document based on target revision - * @return options - */ - public VertexUpdateOptions ifMatch(final String ifMatch) { - this.ifMatch = ifMatch; - return this; - } - - public String getStreamTransactionId() { - return streamTransactionId; - } - - /** - * @param streamTransactionId If set, the operation will be executed within the transaction. - * @return options - * @since ArangoDB 3.5.1 - */ - public VertexUpdateOptions streamTransactionId(final String streamTransactionId) { - this.streamTransactionId = streamTransactionId; - return this; - } -} +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed 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. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.model; + +/** + * @author Mark Vollmary + * @see API Documentation + */ +public final class VertexUpdateOptions { + + private Boolean keepNull; + private Boolean waitForSync; + private String ifMatch; + private String streamTransactionId; + + public VertexUpdateOptions() { + super(); + } + + public Boolean getKeepNull() { + return keepNull; + } + + /** + * @param keepNull If the intention is to delete existing attributes with the patch command, the URL query parameter + * keepNull can be used with a value of false. This will modify the behavior of the patch command to + * remove any attributes from the existing document that are contained in the patch document with an + * attribute value of null. + * @return options + */ + public VertexUpdateOptions keepNull(final Boolean keepNull) { + this.keepNull = keepNull; + return this; + } + + public Boolean getWaitForSync() { + return waitForSync; + } + + /** + * @param waitForSync Wait until document has been synced to disk. + * @return options + */ + public VertexUpdateOptions waitForSync(final Boolean waitForSync) { + this.waitForSync = waitForSync; + return this; + } + + public String getIfMatch() { + return ifMatch; + } + + /** + * @param ifMatch replace a document based on target revision + * @return options + */ + public VertexUpdateOptions ifMatch(final String ifMatch) { + this.ifMatch = ifMatch; + return this; + } + + public String getStreamTransactionId() { + return streamTransactionId; + } + + /** + * @param streamTransactionId If set, the operation will be executed within the transaction. + * @return options + * @since ArangoDB 3.5.1 + */ + public VertexUpdateOptions streamTransactionId(final String streamTransactionId) { + this.streamTransactionId = streamTransactionId; + return this; + } +} diff --git a/src/main/java/com/arangodb/model/ViewCreateOptions.java b/driver/src/main/java/com/arangodb/model/ViewCreateOptions.java similarity index 100% rename from src/main/java/com/arangodb/model/ViewCreateOptions.java rename to driver/src/main/java/com/arangodb/model/ViewCreateOptions.java diff --git a/src/main/java/com/arangodb/model/ViewRenameOptions.java b/driver/src/main/java/com/arangodb/model/ViewRenameOptions.java similarity index 100% rename from src/main/java/com/arangodb/model/ViewRenameOptions.java rename to driver/src/main/java/com/arangodb/model/ViewRenameOptions.java diff --git a/src/main/java/com/arangodb/model/ZKDIndexOptions.java b/driver/src/main/java/com/arangodb/model/ZKDIndexOptions.java similarity index 100% rename from src/main/java/com/arangodb/model/ZKDIndexOptions.java rename to driver/src/main/java/com/arangodb/model/ZKDIndexOptions.java diff --git a/src/main/java/com/arangodb/model/arangosearch/AnalyzerDeleteOptions.java b/driver/src/main/java/com/arangodb/model/arangosearch/AnalyzerDeleteOptions.java similarity index 100% rename from src/main/java/com/arangodb/model/arangosearch/AnalyzerDeleteOptions.java rename to driver/src/main/java/com/arangodb/model/arangosearch/AnalyzerDeleteOptions.java diff --git a/src/main/java/com/arangodb/model/arangosearch/ArangoSearchCreateOptions.java b/driver/src/main/java/com/arangodb/model/arangosearch/ArangoSearchCreateOptions.java similarity index 100% rename from src/main/java/com/arangodb/model/arangosearch/ArangoSearchCreateOptions.java rename to driver/src/main/java/com/arangodb/model/arangosearch/ArangoSearchCreateOptions.java diff --git a/src/main/java/com/arangodb/model/arangosearch/ArangoSearchOptionsBuilder.java b/driver/src/main/java/com/arangodb/model/arangosearch/ArangoSearchOptionsBuilder.java similarity index 100% rename from src/main/java/com/arangodb/model/arangosearch/ArangoSearchOptionsBuilder.java rename to driver/src/main/java/com/arangodb/model/arangosearch/ArangoSearchOptionsBuilder.java diff --git a/src/main/java/com/arangodb/model/arangosearch/ArangoSearchPropertiesOptions.java b/driver/src/main/java/com/arangodb/model/arangosearch/ArangoSearchPropertiesOptions.java similarity index 100% rename from src/main/java/com/arangodb/model/arangosearch/ArangoSearchPropertiesOptions.java rename to driver/src/main/java/com/arangodb/model/arangosearch/ArangoSearchPropertiesOptions.java diff --git a/src/main/java/com/arangodb/model/arangosearch/SearchAliasCreateOptions.java b/driver/src/main/java/com/arangodb/model/arangosearch/SearchAliasCreateOptions.java similarity index 100% rename from src/main/java/com/arangodb/model/arangosearch/SearchAliasCreateOptions.java rename to driver/src/main/java/com/arangodb/model/arangosearch/SearchAliasCreateOptions.java diff --git a/src/main/java/com/arangodb/model/arangosearch/SearchAliasOptionsBuilder.java b/driver/src/main/java/com/arangodb/model/arangosearch/SearchAliasOptionsBuilder.java similarity index 100% rename from src/main/java/com/arangodb/model/arangosearch/SearchAliasOptionsBuilder.java rename to driver/src/main/java/com/arangodb/model/arangosearch/SearchAliasOptionsBuilder.java diff --git a/src/main/java/com/arangodb/model/arangosearch/SearchAliasPropertiesOptions.java b/driver/src/main/java/com/arangodb/model/arangosearch/SearchAliasPropertiesOptions.java similarity index 100% rename from src/main/java/com/arangodb/model/arangosearch/SearchAliasPropertiesOptions.java rename to driver/src/main/java/com/arangodb/model/arangosearch/SearchAliasPropertiesOptions.java diff --git a/src/main/java/com/arangodb/serde/ArangoSerde.java b/driver/src/main/java/com/arangodb/serde/ArangoSerde.java similarity index 100% rename from src/main/java/com/arangodb/serde/ArangoSerde.java rename to driver/src/main/java/com/arangodb/serde/ArangoSerde.java diff --git a/src/main/java/com/arangodb/serde/JacksonSerde.java b/driver/src/main/java/com/arangodb/serde/JacksonSerde.java similarity index 100% rename from src/main/java/com/arangodb/serde/JacksonSerde.java rename to driver/src/main/java/com/arangodb/serde/JacksonSerde.java diff --git a/src/main/java/com/arangodb/util/RawBytes.java b/driver/src/main/java/com/arangodb/util/RawBytes.java similarity index 100% rename from src/main/java/com/arangodb/util/RawBytes.java rename to driver/src/main/java/com/arangodb/util/RawBytes.java diff --git a/src/main/java/com/arangodb/util/RawData.java b/driver/src/main/java/com/arangodb/util/RawData.java similarity index 100% rename from src/main/java/com/arangodb/util/RawData.java rename to driver/src/main/java/com/arangodb/util/RawData.java diff --git a/src/main/java/com/arangodb/util/RawJson.java b/driver/src/main/java/com/arangodb/util/RawJson.java similarity index 100% rename from src/main/java/com/arangodb/util/RawJson.java rename to driver/src/main/java/com/arangodb/util/RawJson.java diff --git a/src/main/java/com/arangodb/util/UnicodeUtils.java b/driver/src/main/java/com/arangodb/util/UnicodeUtils.java similarity index 100% rename from src/main/java/com/arangodb/util/UnicodeUtils.java rename to driver/src/main/java/com/arangodb/util/UnicodeUtils.java diff --git a/src/main/resources/META-INF/native-image/com.arangodb/arangodb-java-driver/native-image.properties b/driver/src/main/resources/META-INF/native-image/com.arangodb/arangodb-java-driver/native-image.properties similarity index 100% rename from src/main/resources/META-INF/native-image/com.arangodb/arangodb-java-driver/native-image.properties rename to driver/src/main/resources/META-INF/native-image/com.arangodb/arangodb-java-driver/native-image.properties diff --git a/src/main/resources/META-INF/native-image/com.arangodb/arangodb-java-driver/reflect-config.json b/driver/src/main/resources/META-INF/native-image/com.arangodb/arangodb-java-driver/reflect-config.json similarity index 100% rename from src/main/resources/META-INF/native-image/com.arangodb/arangodb-java-driver/reflect-config.json rename to driver/src/main/resources/META-INF/native-image/com.arangodb/arangodb-java-driver/reflect-config.json diff --git a/src/main/resources/META-INF/native-image/com.arangodb/arangodb-java-driver/resource-config.json b/driver/src/main/resources/META-INF/native-image/com.arangodb/arangodb-java-driver/resource-config.json similarity index 100% rename from src/main/resources/META-INF/native-image/com.arangodb/arangodb-java-driver/resource-config.json rename to driver/src/main/resources/META-INF/native-image/com.arangodb/arangodb-java-driver/resource-config.json diff --git a/src/main/resources/META-INF/native-image/com.arangodb/arangodb-java-driver/serialization-config.json b/driver/src/main/resources/META-INF/native-image/com.arangodb/arangodb-java-driver/serialization-config.json similarity index 100% rename from src/main/resources/META-INF/native-image/com.arangodb/arangodb-java-driver/serialization-config.json rename to driver/src/main/resources/META-INF/native-image/com.arangodb/arangodb-java-driver/serialization-config.json diff --git a/src/main/resources/vertx/vertx-version.txt b/driver/src/main/resources/vertx/vertx-version.txt similarity index 100% rename from src/main/resources/vertx/vertx-version.txt rename to driver/src/main/resources/vertx/vertx-version.txt diff --git a/src/test/java/com/arangodb/ArangoCollectionTest.java b/driver/src/test/java/com/arangodb/ArangoCollectionTest.java similarity index 100% rename from src/test/java/com/arangodb/ArangoCollectionTest.java rename to driver/src/test/java/com/arangodb/ArangoCollectionTest.java diff --git a/src/test/java/com/arangodb/ArangoCursorTest.java b/driver/src/test/java/com/arangodb/ArangoCursorTest.java similarity index 100% rename from src/test/java/com/arangodb/ArangoCursorTest.java rename to driver/src/test/java/com/arangodb/ArangoCursorTest.java diff --git a/src/test/java/com/arangodb/ArangoDBTest.java b/driver/src/test/java/com/arangodb/ArangoDBTest.java similarity index 100% rename from src/test/java/com/arangodb/ArangoDBTest.java rename to driver/src/test/java/com/arangodb/ArangoDBTest.java diff --git a/src/test/java/com/arangodb/ArangoDatabaseTest.java b/driver/src/test/java/com/arangodb/ArangoDatabaseTest.java similarity index 100% rename from src/test/java/com/arangodb/ArangoDatabaseTest.java rename to driver/src/test/java/com/arangodb/ArangoDatabaseTest.java diff --git a/src/test/java/com/arangodb/ArangoDocumentUtilTest.java b/driver/src/test/java/com/arangodb/ArangoDocumentUtilTest.java similarity index 100% rename from src/test/java/com/arangodb/ArangoDocumentUtilTest.java rename to driver/src/test/java/com/arangodb/ArangoDocumentUtilTest.java diff --git a/src/test/java/com/arangodb/ArangoEdgeCollectionTest.java b/driver/src/test/java/com/arangodb/ArangoEdgeCollectionTest.java similarity index 97% rename from src/test/java/com/arangodb/ArangoEdgeCollectionTest.java rename to driver/src/test/java/com/arangodb/ArangoEdgeCollectionTest.java index d99bf927b..d25ed0e69 100644 --- a/src/test/java/com/arangodb/ArangoEdgeCollectionTest.java +++ b/driver/src/test/java/com/arangodb/ArangoEdgeCollectionTest.java @@ -1,445 +1,445 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb; - -import com.arangodb.entity.*; -import com.arangodb.model.*; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.Arguments; -import org.junit.jupiter.params.provider.MethodSource; - -import java.util.Arrays; -import java.util.Collections; -import java.util.UUID; -import java.util.stream.Stream; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.catchThrowable; - - -/** - * @author Mark Vollmary - * @author Michele Rastelli - */ -class ArangoEdgeCollectionTest extends BaseJunit5 { - - private static final String GRAPH_NAME = "EdgeCollectionTest_graph"; - private static final String VERTEX_COLLECTION_NAME = "EdgeCollectionTest_vertex_collection"; - private static final String EDGE_COLLECTION_NAME = "EdgeCollectionTest_edge_collection"; - - private static Stream args() { - return dbsStream() - .map(db -> new Object[]{ - db.graph(GRAPH_NAME).vertexCollection(VERTEX_COLLECTION_NAME), - db.graph(GRAPH_NAME).edgeCollection(EDGE_COLLECTION_NAME) - }) - .map(Arguments::of); - } - - @BeforeAll - static void init() { - initCollections(VERTEX_COLLECTION_NAME); - initEdgeCollections(EDGE_COLLECTION_NAME); - initGraph( - GRAPH_NAME, - Collections.singletonList(new EdgeDefinition() - .collection(EDGE_COLLECTION_NAME) - .from(VERTEX_COLLECTION_NAME) - .to(VERTEX_COLLECTION_NAME) - ), - null - ); - } - - private BaseEdgeDocument createEdgeValue(ArangoVertexCollection vertices) { - final VertexEntity v1 = vertices.insertVertex(new BaseDocument()); - final VertexEntity v2 = vertices.insertVertex(new BaseDocument()); - - final BaseEdgeDocument value = new BaseEdgeDocument(); - value.setFrom(v1.getId()); - value.setTo(v2.getId()); - return value; - } - - @ParameterizedTest(name = "{index}") - @MethodSource("args") - void insertEdge(ArangoVertexCollection vertices, ArangoEdgeCollection edges) { - final BaseEdgeDocument value = createEdgeValue(vertices); - final EdgeEntity edge = edges.insertEdge(value); - assertThat(edge).isNotNull(); - final BaseEdgeDocument document = edges.getEdge(edge.getKey(), BaseEdgeDocument.class); - assertThat(document).isNotNull(); - assertThat(document.getKey()).isEqualTo(edge.getKey()); - assertThat(document.getFrom()).isNotNull(); - assertThat(document.getTo()).isNotNull(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("args") - void insertEdgeUpdateRev(ArangoVertexCollection vertices, ArangoEdgeCollection edges) { - final BaseEdgeDocument value = createEdgeValue(vertices); - final EdgeEntity edge = edges.insertEdge(value); - assertThat(value.getRevision()).isNull(); - assertThat(edge.getRev()).isNotNull(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("args") - void insertEdgeViolatingUniqueConstraint(ArangoVertexCollection vertices, ArangoEdgeCollection edges) { - edges.graph().db().collection(EDGE_COLLECTION_NAME) - .ensurePersistentIndex(Arrays.asList("_from", "_to"), new PersistentIndexOptions().unique(true)); - - BaseEdgeDocument edge = createEdgeValue(vertices); - edges.insertEdge(edge); - - try { - edges.insertEdge(edge); - } catch (ArangoDBException e) { - assertThat(e.getResponseCode()).isEqualTo(409); - assertThat(e.getErrorNum()).isEqualTo(1210); - } - } - - @ParameterizedTest(name = "{index}") - @MethodSource("args") - void getEdge(ArangoVertexCollection vertices, ArangoEdgeCollection edges) { - final BaseEdgeDocument value = createEdgeValue(vertices); - final EdgeEntity edge = edges.insertEdge(value); - final BaseEdgeDocument document = edges - .getEdge(edge.getKey(), BaseEdgeDocument.class); - assertThat(document).isNotNull(); - assertThat(document.getKey()).isEqualTo(edge.getKey()); - assertThat(document.getFrom()).isNotNull(); - assertThat(document.getTo()).isNotNull(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("args") - void getEdgeIfMatch(ArangoVertexCollection vertices, ArangoEdgeCollection edges) { - final BaseEdgeDocument value = createEdgeValue(vertices); - final EdgeEntity edge = edges.insertEdge(value); - final GraphDocumentReadOptions options = new GraphDocumentReadOptions().ifMatch(edge.getRev()); - final BaseDocument document = edges.getEdge(edge.getKey(), - BaseDocument.class, options); - assertThat(document).isNotNull(); - assertThat(document.getKey()).isEqualTo(edge.getKey()); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("args") - void getEdgeIfMatchFail(ArangoVertexCollection vertices, ArangoEdgeCollection edges) { - final BaseEdgeDocument value = createEdgeValue(vertices); - final EdgeEntity edge = edges.insertEdge(value); - final GraphDocumentReadOptions options = new GraphDocumentReadOptions().ifMatch("no"); - final BaseEdgeDocument edge2 = edges.getEdge(edge.getKey(), - BaseEdgeDocument.class, options); - assertThat(edge2).isNull(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("args") - void getEdgeIfNoneMatch(ArangoVertexCollection vertices, ArangoEdgeCollection edges) { - final BaseEdgeDocument value = createEdgeValue(vertices); - final EdgeEntity edge = edges.insertEdge(value); - final GraphDocumentReadOptions options = new GraphDocumentReadOptions().ifNoneMatch("no"); - final BaseDocument document = edges.getEdge(edge.getKey(), - BaseDocument.class, options); - assertThat(document).isNotNull(); - assertThat(document.getKey()).isEqualTo(edge.getKey()); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("args") - void getEdgeIfNoneMatchFail(ArangoVertexCollection vertices, ArangoEdgeCollection edges) { - final BaseEdgeDocument value = createEdgeValue(vertices); - final EdgeEntity edge = edges.insertEdge(value); - final GraphDocumentReadOptions options = new GraphDocumentReadOptions().ifNoneMatch(edge.getRev()); - final BaseEdgeDocument edge2 = edges.getEdge(edge.getKey(), - BaseEdgeDocument.class, options); - assertThat(edge2).isNull(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("args") - void replaceEdge(ArangoVertexCollection vertices, ArangoEdgeCollection edges) { - final BaseEdgeDocument doc = createEdgeValue(vertices); - doc.addAttribute("a", "test"); - final EdgeEntity createResult = edges.insertEdge(doc); - doc.removeAttribute("a"); - doc.addAttribute("b", "test"); - final EdgeUpdateEntity replaceResult = edges - .replaceEdge(createResult.getKey(), doc); - assertThat(replaceResult).isNotNull(); - assertThat(replaceResult.getId()).isEqualTo(createResult.getId()); - assertThat(replaceResult.getRev()).isNotEqualTo(replaceResult.getOldRev()); - assertThat(replaceResult.getOldRev()).isEqualTo(createResult.getRev()); - - final BaseEdgeDocument readResult = edges - .getEdge(createResult.getKey(), BaseEdgeDocument.class); - assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); - assertThat(readResult.getRevision()).isEqualTo(replaceResult.getRev()); - assertThat(readResult.getProperties().keySet()).doesNotContain("a"); - assertThat(readResult.getAttribute("b")).isNotNull(); - assertThat(String.valueOf(readResult.getAttribute("b"))).isEqualTo("test"); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("args") - void replaceEdgeUpdateRev(ArangoVertexCollection vertices, ArangoEdgeCollection edges) { - final BaseEdgeDocument doc = createEdgeValue(vertices); - final EdgeEntity createResult = edges.insertEdge(doc); - final EdgeUpdateEntity replaceResult = edges - .replaceEdge(createResult.getKey(), doc); - assertThat(doc.getRevision()).isNull(); - assertThat(createResult.getRev()).isNotNull(); - assertThat(replaceResult.getRev()) - .isNotNull() - .isNotEqualTo(createResult.getRev()); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("args") - void replaceEdgeIfMatch(ArangoVertexCollection vertices, ArangoEdgeCollection edges) { - final BaseEdgeDocument doc = createEdgeValue(vertices); - doc.addAttribute("a", "test"); - final EdgeEntity createResult = edges.insertEdge(doc); - doc.removeAttribute("a"); - doc.addAttribute("b", "test"); - final EdgeReplaceOptions options = new EdgeReplaceOptions().ifMatch(createResult.getRev()); - final EdgeUpdateEntity replaceResult = edges - .replaceEdge(createResult.getKey(), doc, options); - assertThat(replaceResult).isNotNull(); - assertThat(replaceResult.getId()).isEqualTo(createResult.getId()); - assertThat(replaceResult.getRev()).isNotEqualTo(replaceResult.getOldRev()); - assertThat(replaceResult.getOldRev()).isEqualTo(createResult.getRev()); - - final BaseEdgeDocument readResult = edges - .getEdge(createResult.getKey(), BaseEdgeDocument.class); - assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); - assertThat(readResult.getRevision()).isEqualTo(replaceResult.getRev()); - assertThat(readResult.getProperties().keySet()).doesNotContain("a"); - assertThat(readResult.getAttribute("b")).isNotNull(); - assertThat(String.valueOf(readResult.getAttribute("b"))).isEqualTo("test"); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("args") - void replaceEdgeIfMatchFail(ArangoVertexCollection vertices, ArangoEdgeCollection edges) { - final BaseEdgeDocument doc = createEdgeValue(vertices); - doc.addAttribute("a", "test"); - final EdgeEntity createResult = edges.insertEdge(doc); - doc.removeAttribute("a"); - doc.addAttribute("b", "test"); - final EdgeReplaceOptions options = new EdgeReplaceOptions().ifMatch("no"); - Throwable thrown = catchThrowable(() -> edges.replaceEdge(createResult.getKey(), doc, options)); - assertThat(thrown).isInstanceOf(ArangoDBException.class); - ArangoDBException e = (ArangoDBException) thrown; - assertThat(e.getResponseCode()).isEqualTo(412); - assertThat(e.getErrorNum()).isEqualTo(1200); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("args") - void updateEdge(ArangoVertexCollection vertices, ArangoEdgeCollection edges) { - final BaseEdgeDocument doc = createEdgeValue(vertices); - doc.addAttribute("a", "test"); - doc.addAttribute("c", "test"); - final EdgeEntity createResult = edges.insertEdge(doc); - doc.updateAttribute("a", "test1"); - doc.addAttribute("b", "test"); - doc.updateAttribute("c", null); - final EdgeUpdateEntity updateResult = edges - .updateEdge(createResult.getKey(), doc); - assertThat(updateResult).isNotNull(); - assertThat(updateResult.getId()).isEqualTo(createResult.getId()); - assertThat(updateResult.getRev()).isNotEqualTo(updateResult.getOldRev()); - assertThat(updateResult.getOldRev()).isEqualTo(createResult.getRev()); - - final BaseEdgeDocument readResult = edges - .getEdge(createResult.getKey(), BaseEdgeDocument.class); - assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); - assertThat(readResult.getAttribute("a")).isNotNull(); - assertThat(String.valueOf(readResult.getAttribute("a"))).isEqualTo("test1"); - assertThat(readResult.getAttribute("b")).isNotNull(); - assertThat(String.valueOf(readResult.getAttribute("b"))).isEqualTo("test"); - assertThat(readResult.getRevision()).isEqualTo(updateResult.getRev()); - assertThat(readResult.getProperties()).containsKey("c"); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("args") - void updateEdgeUpdateRev(ArangoVertexCollection vertices, ArangoEdgeCollection edges) { - final BaseEdgeDocument doc = createEdgeValue(vertices); - final EdgeEntity createResult = edges.insertEdge(doc); - final EdgeUpdateEntity updateResult = edges - .updateEdge(createResult.getKey(), doc); - assertThat(doc.getRevision()).isNull(); - assertThat(createResult.getRev()).isNotNull(); - assertThat(updateResult.getRev()) - .isNotNull() - .isNotEqualTo(createResult.getRev()); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("args") - void updateEdgeIfMatch(ArangoVertexCollection vertices, ArangoEdgeCollection edges) { - final BaseEdgeDocument doc = createEdgeValue(vertices); - doc.addAttribute("a", "test"); - doc.addAttribute("c", "test"); - final EdgeEntity createResult = edges.insertEdge(doc); - doc.updateAttribute("a", "test1"); - doc.addAttribute("b", "test"); - doc.updateAttribute("c", null); - final EdgeUpdateOptions options = new EdgeUpdateOptions().ifMatch(createResult.getRev()); - final EdgeUpdateEntity updateResult = edges - .updateEdge(createResult.getKey(), doc, options); - assertThat(updateResult).isNotNull(); - assertThat(updateResult.getId()).isEqualTo(createResult.getId()); - assertThat(updateResult.getRev()).isNotEqualTo(updateResult.getOldRev()); - assertThat(updateResult.getOldRev()).isEqualTo(createResult.getRev()); - - final BaseEdgeDocument readResult = edges - .getEdge(createResult.getKey(), BaseEdgeDocument.class); - assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); - assertThat(readResult.getAttribute("a")).isNotNull(); - assertThat(String.valueOf(readResult.getAttribute("a"))).isEqualTo("test1"); - assertThat(readResult.getAttribute("b")).isNotNull(); - assertThat(String.valueOf(readResult.getAttribute("b"))).isEqualTo("test"); - assertThat(readResult.getRevision()).isEqualTo(updateResult.getRev()); - assertThat(readResult.getProperties()).containsKey("c"); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("args") - void updateEdgeIfMatchFail(ArangoVertexCollection vertices, ArangoEdgeCollection edges) { - final BaseEdgeDocument doc = createEdgeValue(vertices); - doc.addAttribute("a", "test"); - doc.addAttribute("c", "test"); - final EdgeEntity createResult = edges.insertEdge(doc); - doc.updateAttribute("a", "test1"); - doc.addAttribute("b", "test"); - doc.updateAttribute("c", null); - final EdgeUpdateOptions options = new EdgeUpdateOptions().ifMatch("no"); - Throwable thrown = catchThrowable(() -> edges.updateEdge(createResult.getKey(), doc, options)); - assertThat(thrown).isInstanceOf(ArangoDBException.class); - ArangoDBException e = (ArangoDBException) thrown; - assertThat(e.getResponseCode()).isEqualTo(412); - assertThat(e.getErrorNum()).isEqualTo(1200); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("args") - void updateEdgeKeepNullTrue(ArangoVertexCollection vertices, ArangoEdgeCollection edges) { - final BaseEdgeDocument doc = createEdgeValue(vertices); - doc.addAttribute("a", "test"); - final EdgeEntity createResult = edges.insertEdge(doc); - doc.updateAttribute("a", null); - final EdgeUpdateOptions options = new EdgeUpdateOptions().keepNull(true); - final EdgeUpdateEntity updateResult = edges - .updateEdge(createResult.getKey(), doc, options); - assertThat(updateResult).isNotNull(); - assertThat(updateResult.getId()).isEqualTo(createResult.getId()); - assertThat(updateResult.getRev()).isNotEqualTo(updateResult.getOldRev()); - assertThat(updateResult.getOldRev()).isEqualTo(createResult.getRev()); - - final BaseEdgeDocument readResult = edges - .getEdge(createResult.getKey(), BaseEdgeDocument.class); - assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); - assertThat(readResult.getProperties().keySet()).hasSize(6); - assertThat(readResult.getProperties()).containsKey("a"); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("args") - void updateEdgeKeepNullFalse(ArangoVertexCollection vertices, ArangoEdgeCollection edges) { - final BaseEdgeDocument doc = createEdgeValue(vertices); - doc.addAttribute("a", "test"); - final EdgeEntity createResult = edges.insertEdge(doc); - doc.updateAttribute("a", null); - final EdgeUpdateOptions options = new EdgeUpdateOptions().keepNull(false); - final EdgeUpdateEntity updateResult = edges - .updateEdge(createResult.getKey(), doc, options); - assertThat(updateResult).isNotNull(); - assertThat(updateResult.getId()).isEqualTo(createResult.getId()); - assertThat(updateResult.getRev()).isNotEqualTo(updateResult.getOldRev()); - assertThat(updateResult.getOldRev()).isEqualTo(createResult.getRev()); - - final BaseEdgeDocument readResult = edges - .getEdge(createResult.getKey(), BaseEdgeDocument.class); - assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); - assertThat(readResult.getId()).isEqualTo(createResult.getId()); - assertThat(readResult.getRevision()).isNotNull(); - assertThat(readResult.getProperties().keySet()).doesNotContain("a"); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("args") - void deleteEdge(ArangoVertexCollection vertices, ArangoEdgeCollection edges) { - final BaseEdgeDocument doc = createEdgeValue(vertices); - final EdgeEntity createResult = edges.insertEdge(doc); - edges.deleteEdge(createResult.getKey()); - final BaseEdgeDocument edge = edges - .getEdge(createResult.getKey(), BaseEdgeDocument.class); - assertThat(edge).isNull(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("args") - void deleteEdgeIfMatch(ArangoVertexCollection vertices, ArangoEdgeCollection edges) { - final BaseEdgeDocument doc = createEdgeValue(vertices); - final EdgeEntity createResult = edges.insertEdge(doc); - final EdgeDeleteOptions options = new EdgeDeleteOptions().ifMatch(createResult.getRev()); - edges.deleteEdge(createResult.getKey(), options); - final BaseEdgeDocument edge = edges - .getEdge(createResult.getKey(), BaseEdgeDocument.class); - assertThat(edge).isNull(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("args") - void deleteEdgeIfMatchFail(ArangoVertexCollection vertices, ArangoEdgeCollection edges) { - final BaseEdgeDocument doc = createEdgeValue(vertices); - final EdgeEntity createResult = edges.insertEdge(doc); - final EdgeDeleteOptions options = new EdgeDeleteOptions().ifMatch("no"); - Throwable thrown = catchThrowable(() -> edges.deleteEdge(createResult.getKey(), options)); - assertThat(thrown).isInstanceOf(ArangoDBException.class); - ArangoDBException e = (ArangoDBException) thrown; - assertThat(e.getResponseCode()).isEqualTo(412); - assertThat(e.getErrorNum()).isEqualTo(1200); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("args") - void edgeKeyWithSpecialChars(ArangoVertexCollection vertices, ArangoEdgeCollection edges) { - final BaseEdgeDocument value = createEdgeValue(vertices); - final String key = "_-:.@()+,=;$!*'%" + UUID.randomUUID(); - value.setKey(key); - final EdgeEntity edge = edges.insertEdge(value); - assertThat(edge).isNotNull(); - final BaseEdgeDocument document = edges.getEdge(edge.getKey(), BaseEdgeDocument.class); - assertThat(document).isNotNull(); - assertThat(document.getKey()).isEqualTo(key); - assertThat(document.getFrom()).isNotNull(); - assertThat(document.getTo()).isNotNull(); - } - -} +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed 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. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb; + +import com.arangodb.entity.*; +import com.arangodb.model.*; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +import java.util.Arrays; +import java.util.Collections; +import java.util.UUID; +import java.util.stream.Stream; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.catchThrowable; + + +/** + * @author Mark Vollmary + * @author Michele Rastelli + */ +class ArangoEdgeCollectionTest extends BaseJunit5 { + + private static final String GRAPH_NAME = "EdgeCollectionTest_graph"; + private static final String VERTEX_COLLECTION_NAME = "EdgeCollectionTest_vertex_collection"; + private static final String EDGE_COLLECTION_NAME = "EdgeCollectionTest_edge_collection"; + + private static Stream args() { + return dbsStream() + .map(db -> new Object[]{ + db.graph(GRAPH_NAME).vertexCollection(VERTEX_COLLECTION_NAME), + db.graph(GRAPH_NAME).edgeCollection(EDGE_COLLECTION_NAME) + }) + .map(Arguments::of); + } + + @BeforeAll + static void init() { + initCollections(VERTEX_COLLECTION_NAME); + initEdgeCollections(EDGE_COLLECTION_NAME); + initGraph( + GRAPH_NAME, + Collections.singletonList(new EdgeDefinition() + .collection(EDGE_COLLECTION_NAME) + .from(VERTEX_COLLECTION_NAME) + .to(VERTEX_COLLECTION_NAME) + ), + null + ); + } + + private BaseEdgeDocument createEdgeValue(ArangoVertexCollection vertices) { + final VertexEntity v1 = vertices.insertVertex(new BaseDocument()); + final VertexEntity v2 = vertices.insertVertex(new BaseDocument()); + + final BaseEdgeDocument value = new BaseEdgeDocument(); + value.setFrom(v1.getId()); + value.setTo(v2.getId()); + return value; + } + + @ParameterizedTest(name = "{index}") + @MethodSource("args") + void insertEdge(ArangoVertexCollection vertices, ArangoEdgeCollection edges) { + final BaseEdgeDocument value = createEdgeValue(vertices); + final EdgeEntity edge = edges.insertEdge(value); + assertThat(edge).isNotNull(); + final BaseEdgeDocument document = edges.getEdge(edge.getKey(), BaseEdgeDocument.class); + assertThat(document).isNotNull(); + assertThat(document.getKey()).isEqualTo(edge.getKey()); + assertThat(document.getFrom()).isNotNull(); + assertThat(document.getTo()).isNotNull(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("args") + void insertEdgeUpdateRev(ArangoVertexCollection vertices, ArangoEdgeCollection edges) { + final BaseEdgeDocument value = createEdgeValue(vertices); + final EdgeEntity edge = edges.insertEdge(value); + assertThat(value.getRevision()).isNull(); + assertThat(edge.getRev()).isNotNull(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("args") + void insertEdgeViolatingUniqueConstraint(ArangoVertexCollection vertices, ArangoEdgeCollection edges) { + edges.graph().db().collection(EDGE_COLLECTION_NAME) + .ensurePersistentIndex(Arrays.asList("_from", "_to"), new PersistentIndexOptions().unique(true)); + + BaseEdgeDocument edge = createEdgeValue(vertices); + edges.insertEdge(edge); + + try { + edges.insertEdge(edge); + } catch (ArangoDBException e) { + assertThat(e.getResponseCode()).isEqualTo(409); + assertThat(e.getErrorNum()).isEqualTo(1210); + } + } + + @ParameterizedTest(name = "{index}") + @MethodSource("args") + void getEdge(ArangoVertexCollection vertices, ArangoEdgeCollection edges) { + final BaseEdgeDocument value = createEdgeValue(vertices); + final EdgeEntity edge = edges.insertEdge(value); + final BaseEdgeDocument document = edges + .getEdge(edge.getKey(), BaseEdgeDocument.class); + assertThat(document).isNotNull(); + assertThat(document.getKey()).isEqualTo(edge.getKey()); + assertThat(document.getFrom()).isNotNull(); + assertThat(document.getTo()).isNotNull(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("args") + void getEdgeIfMatch(ArangoVertexCollection vertices, ArangoEdgeCollection edges) { + final BaseEdgeDocument value = createEdgeValue(vertices); + final EdgeEntity edge = edges.insertEdge(value); + final GraphDocumentReadOptions options = new GraphDocumentReadOptions().ifMatch(edge.getRev()); + final BaseDocument document = edges.getEdge(edge.getKey(), + BaseDocument.class, options); + assertThat(document).isNotNull(); + assertThat(document.getKey()).isEqualTo(edge.getKey()); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("args") + void getEdgeIfMatchFail(ArangoVertexCollection vertices, ArangoEdgeCollection edges) { + final BaseEdgeDocument value = createEdgeValue(vertices); + final EdgeEntity edge = edges.insertEdge(value); + final GraphDocumentReadOptions options = new GraphDocumentReadOptions().ifMatch("no"); + final BaseEdgeDocument edge2 = edges.getEdge(edge.getKey(), + BaseEdgeDocument.class, options); + assertThat(edge2).isNull(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("args") + void getEdgeIfNoneMatch(ArangoVertexCollection vertices, ArangoEdgeCollection edges) { + final BaseEdgeDocument value = createEdgeValue(vertices); + final EdgeEntity edge = edges.insertEdge(value); + final GraphDocumentReadOptions options = new GraphDocumentReadOptions().ifNoneMatch("no"); + final BaseDocument document = edges.getEdge(edge.getKey(), + BaseDocument.class, options); + assertThat(document).isNotNull(); + assertThat(document.getKey()).isEqualTo(edge.getKey()); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("args") + void getEdgeIfNoneMatchFail(ArangoVertexCollection vertices, ArangoEdgeCollection edges) { + final BaseEdgeDocument value = createEdgeValue(vertices); + final EdgeEntity edge = edges.insertEdge(value); + final GraphDocumentReadOptions options = new GraphDocumentReadOptions().ifNoneMatch(edge.getRev()); + final BaseEdgeDocument edge2 = edges.getEdge(edge.getKey(), + BaseEdgeDocument.class, options); + assertThat(edge2).isNull(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("args") + void replaceEdge(ArangoVertexCollection vertices, ArangoEdgeCollection edges) { + final BaseEdgeDocument doc = createEdgeValue(vertices); + doc.addAttribute("a", "test"); + final EdgeEntity createResult = edges.insertEdge(doc); + doc.removeAttribute("a"); + doc.addAttribute("b", "test"); + final EdgeUpdateEntity replaceResult = edges + .replaceEdge(createResult.getKey(), doc); + assertThat(replaceResult).isNotNull(); + assertThat(replaceResult.getId()).isEqualTo(createResult.getId()); + assertThat(replaceResult.getRev()).isNotEqualTo(replaceResult.getOldRev()); + assertThat(replaceResult.getOldRev()).isEqualTo(createResult.getRev()); + + final BaseEdgeDocument readResult = edges + .getEdge(createResult.getKey(), BaseEdgeDocument.class); + assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); + assertThat(readResult.getRevision()).isEqualTo(replaceResult.getRev()); + assertThat(readResult.getProperties().keySet()).doesNotContain("a"); + assertThat(readResult.getAttribute("b")).isNotNull(); + assertThat(String.valueOf(readResult.getAttribute("b"))).isEqualTo("test"); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("args") + void replaceEdgeUpdateRev(ArangoVertexCollection vertices, ArangoEdgeCollection edges) { + final BaseEdgeDocument doc = createEdgeValue(vertices); + final EdgeEntity createResult = edges.insertEdge(doc); + final EdgeUpdateEntity replaceResult = edges + .replaceEdge(createResult.getKey(), doc); + assertThat(doc.getRevision()).isNull(); + assertThat(createResult.getRev()).isNotNull(); + assertThat(replaceResult.getRev()) + .isNotNull() + .isNotEqualTo(createResult.getRev()); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("args") + void replaceEdgeIfMatch(ArangoVertexCollection vertices, ArangoEdgeCollection edges) { + final BaseEdgeDocument doc = createEdgeValue(vertices); + doc.addAttribute("a", "test"); + final EdgeEntity createResult = edges.insertEdge(doc); + doc.removeAttribute("a"); + doc.addAttribute("b", "test"); + final EdgeReplaceOptions options = new EdgeReplaceOptions().ifMatch(createResult.getRev()); + final EdgeUpdateEntity replaceResult = edges + .replaceEdge(createResult.getKey(), doc, options); + assertThat(replaceResult).isNotNull(); + assertThat(replaceResult.getId()).isEqualTo(createResult.getId()); + assertThat(replaceResult.getRev()).isNotEqualTo(replaceResult.getOldRev()); + assertThat(replaceResult.getOldRev()).isEqualTo(createResult.getRev()); + + final BaseEdgeDocument readResult = edges + .getEdge(createResult.getKey(), BaseEdgeDocument.class); + assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); + assertThat(readResult.getRevision()).isEqualTo(replaceResult.getRev()); + assertThat(readResult.getProperties().keySet()).doesNotContain("a"); + assertThat(readResult.getAttribute("b")).isNotNull(); + assertThat(String.valueOf(readResult.getAttribute("b"))).isEqualTo("test"); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("args") + void replaceEdgeIfMatchFail(ArangoVertexCollection vertices, ArangoEdgeCollection edges) { + final BaseEdgeDocument doc = createEdgeValue(vertices); + doc.addAttribute("a", "test"); + final EdgeEntity createResult = edges.insertEdge(doc); + doc.removeAttribute("a"); + doc.addAttribute("b", "test"); + final EdgeReplaceOptions options = new EdgeReplaceOptions().ifMatch("no"); + Throwable thrown = catchThrowable(() -> edges.replaceEdge(createResult.getKey(), doc, options)); + assertThat(thrown).isInstanceOf(ArangoDBException.class); + ArangoDBException e = (ArangoDBException) thrown; + assertThat(e.getResponseCode()).isEqualTo(412); + assertThat(e.getErrorNum()).isEqualTo(1200); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("args") + void updateEdge(ArangoVertexCollection vertices, ArangoEdgeCollection edges) { + final BaseEdgeDocument doc = createEdgeValue(vertices); + doc.addAttribute("a", "test"); + doc.addAttribute("c", "test"); + final EdgeEntity createResult = edges.insertEdge(doc); + doc.updateAttribute("a", "test1"); + doc.addAttribute("b", "test"); + doc.updateAttribute("c", null); + final EdgeUpdateEntity updateResult = edges + .updateEdge(createResult.getKey(), doc); + assertThat(updateResult).isNotNull(); + assertThat(updateResult.getId()).isEqualTo(createResult.getId()); + assertThat(updateResult.getRev()).isNotEqualTo(updateResult.getOldRev()); + assertThat(updateResult.getOldRev()).isEqualTo(createResult.getRev()); + + final BaseEdgeDocument readResult = edges + .getEdge(createResult.getKey(), BaseEdgeDocument.class); + assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); + assertThat(readResult.getAttribute("a")).isNotNull(); + assertThat(String.valueOf(readResult.getAttribute("a"))).isEqualTo("test1"); + assertThat(readResult.getAttribute("b")).isNotNull(); + assertThat(String.valueOf(readResult.getAttribute("b"))).isEqualTo("test"); + assertThat(readResult.getRevision()).isEqualTo(updateResult.getRev()); + assertThat(readResult.getProperties()).containsKey("c"); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("args") + void updateEdgeUpdateRev(ArangoVertexCollection vertices, ArangoEdgeCollection edges) { + final BaseEdgeDocument doc = createEdgeValue(vertices); + final EdgeEntity createResult = edges.insertEdge(doc); + final EdgeUpdateEntity updateResult = edges + .updateEdge(createResult.getKey(), doc); + assertThat(doc.getRevision()).isNull(); + assertThat(createResult.getRev()).isNotNull(); + assertThat(updateResult.getRev()) + .isNotNull() + .isNotEqualTo(createResult.getRev()); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("args") + void updateEdgeIfMatch(ArangoVertexCollection vertices, ArangoEdgeCollection edges) { + final BaseEdgeDocument doc = createEdgeValue(vertices); + doc.addAttribute("a", "test"); + doc.addAttribute("c", "test"); + final EdgeEntity createResult = edges.insertEdge(doc); + doc.updateAttribute("a", "test1"); + doc.addAttribute("b", "test"); + doc.updateAttribute("c", null); + final EdgeUpdateOptions options = new EdgeUpdateOptions().ifMatch(createResult.getRev()); + final EdgeUpdateEntity updateResult = edges + .updateEdge(createResult.getKey(), doc, options); + assertThat(updateResult).isNotNull(); + assertThat(updateResult.getId()).isEqualTo(createResult.getId()); + assertThat(updateResult.getRev()).isNotEqualTo(updateResult.getOldRev()); + assertThat(updateResult.getOldRev()).isEqualTo(createResult.getRev()); + + final BaseEdgeDocument readResult = edges + .getEdge(createResult.getKey(), BaseEdgeDocument.class); + assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); + assertThat(readResult.getAttribute("a")).isNotNull(); + assertThat(String.valueOf(readResult.getAttribute("a"))).isEqualTo("test1"); + assertThat(readResult.getAttribute("b")).isNotNull(); + assertThat(String.valueOf(readResult.getAttribute("b"))).isEqualTo("test"); + assertThat(readResult.getRevision()).isEqualTo(updateResult.getRev()); + assertThat(readResult.getProperties()).containsKey("c"); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("args") + void updateEdgeIfMatchFail(ArangoVertexCollection vertices, ArangoEdgeCollection edges) { + final BaseEdgeDocument doc = createEdgeValue(vertices); + doc.addAttribute("a", "test"); + doc.addAttribute("c", "test"); + final EdgeEntity createResult = edges.insertEdge(doc); + doc.updateAttribute("a", "test1"); + doc.addAttribute("b", "test"); + doc.updateAttribute("c", null); + final EdgeUpdateOptions options = new EdgeUpdateOptions().ifMatch("no"); + Throwable thrown = catchThrowable(() -> edges.updateEdge(createResult.getKey(), doc, options)); + assertThat(thrown).isInstanceOf(ArangoDBException.class); + ArangoDBException e = (ArangoDBException) thrown; + assertThat(e.getResponseCode()).isEqualTo(412); + assertThat(e.getErrorNum()).isEqualTo(1200); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("args") + void updateEdgeKeepNullTrue(ArangoVertexCollection vertices, ArangoEdgeCollection edges) { + final BaseEdgeDocument doc = createEdgeValue(vertices); + doc.addAttribute("a", "test"); + final EdgeEntity createResult = edges.insertEdge(doc); + doc.updateAttribute("a", null); + final EdgeUpdateOptions options = new EdgeUpdateOptions().keepNull(true); + final EdgeUpdateEntity updateResult = edges + .updateEdge(createResult.getKey(), doc, options); + assertThat(updateResult).isNotNull(); + assertThat(updateResult.getId()).isEqualTo(createResult.getId()); + assertThat(updateResult.getRev()).isNotEqualTo(updateResult.getOldRev()); + assertThat(updateResult.getOldRev()).isEqualTo(createResult.getRev()); + + final BaseEdgeDocument readResult = edges + .getEdge(createResult.getKey(), BaseEdgeDocument.class); + assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); + assertThat(readResult.getProperties().keySet()).hasSize(6); + assertThat(readResult.getProperties()).containsKey("a"); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("args") + void updateEdgeKeepNullFalse(ArangoVertexCollection vertices, ArangoEdgeCollection edges) { + final BaseEdgeDocument doc = createEdgeValue(vertices); + doc.addAttribute("a", "test"); + final EdgeEntity createResult = edges.insertEdge(doc); + doc.updateAttribute("a", null); + final EdgeUpdateOptions options = new EdgeUpdateOptions().keepNull(false); + final EdgeUpdateEntity updateResult = edges + .updateEdge(createResult.getKey(), doc, options); + assertThat(updateResult).isNotNull(); + assertThat(updateResult.getId()).isEqualTo(createResult.getId()); + assertThat(updateResult.getRev()).isNotEqualTo(updateResult.getOldRev()); + assertThat(updateResult.getOldRev()).isEqualTo(createResult.getRev()); + + final BaseEdgeDocument readResult = edges + .getEdge(createResult.getKey(), BaseEdgeDocument.class); + assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); + assertThat(readResult.getId()).isEqualTo(createResult.getId()); + assertThat(readResult.getRevision()).isNotNull(); + assertThat(readResult.getProperties().keySet()).doesNotContain("a"); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("args") + void deleteEdge(ArangoVertexCollection vertices, ArangoEdgeCollection edges) { + final BaseEdgeDocument doc = createEdgeValue(vertices); + final EdgeEntity createResult = edges.insertEdge(doc); + edges.deleteEdge(createResult.getKey()); + final BaseEdgeDocument edge = edges + .getEdge(createResult.getKey(), BaseEdgeDocument.class); + assertThat(edge).isNull(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("args") + void deleteEdgeIfMatch(ArangoVertexCollection vertices, ArangoEdgeCollection edges) { + final BaseEdgeDocument doc = createEdgeValue(vertices); + final EdgeEntity createResult = edges.insertEdge(doc); + final EdgeDeleteOptions options = new EdgeDeleteOptions().ifMatch(createResult.getRev()); + edges.deleteEdge(createResult.getKey(), options); + final BaseEdgeDocument edge = edges + .getEdge(createResult.getKey(), BaseEdgeDocument.class); + assertThat(edge).isNull(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("args") + void deleteEdgeIfMatchFail(ArangoVertexCollection vertices, ArangoEdgeCollection edges) { + final BaseEdgeDocument doc = createEdgeValue(vertices); + final EdgeEntity createResult = edges.insertEdge(doc); + final EdgeDeleteOptions options = new EdgeDeleteOptions().ifMatch("no"); + Throwable thrown = catchThrowable(() -> edges.deleteEdge(createResult.getKey(), options)); + assertThat(thrown).isInstanceOf(ArangoDBException.class); + ArangoDBException e = (ArangoDBException) thrown; + assertThat(e.getResponseCode()).isEqualTo(412); + assertThat(e.getErrorNum()).isEqualTo(1200); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("args") + void edgeKeyWithSpecialChars(ArangoVertexCollection vertices, ArangoEdgeCollection edges) { + final BaseEdgeDocument value = createEdgeValue(vertices); + final String key = "_-:.@()+,=;$!*'%" + UUID.randomUUID(); + value.setKey(key); + final EdgeEntity edge = edges.insertEdge(value); + assertThat(edge).isNotNull(); + final BaseEdgeDocument document = edges.getEdge(edge.getKey(), BaseEdgeDocument.class); + assertThat(document).isNotNull(); + assertThat(document.getKey()).isEqualTo(key); + assertThat(document.getFrom()).isNotNull(); + assertThat(document.getTo()).isNotNull(); + } + +} diff --git a/src/test/java/com/arangodb/ArangoGraphTest.java b/driver/src/test/java/com/arangodb/ArangoGraphTest.java similarity index 100% rename from src/test/java/com/arangodb/ArangoGraphTest.java rename to driver/src/test/java/com/arangodb/ArangoGraphTest.java diff --git a/src/test/java/com/arangodb/ArangoRouteTest.java b/driver/src/test/java/com/arangodb/ArangoRouteTest.java similarity index 100% rename from src/test/java/com/arangodb/ArangoRouteTest.java rename to driver/src/test/java/com/arangodb/ArangoRouteTest.java diff --git a/src/test/java/com/arangodb/ArangoSearchTest.java b/driver/src/test/java/com/arangodb/ArangoSearchTest.java similarity index 100% rename from src/test/java/com/arangodb/ArangoSearchTest.java rename to driver/src/test/java/com/arangodb/ArangoSearchTest.java diff --git a/src/test/java/com/arangodb/ArangoSslTest.java b/driver/src/test/java/com/arangodb/ArangoSslTest.java similarity index 97% rename from src/test/java/com/arangodb/ArangoSslTest.java rename to driver/src/test/java/com/arangodb/ArangoSslTest.java index 9155e0419..068e812eb 100644 --- a/src/test/java/com/arangodb/ArangoSslTest.java +++ b/driver/src/test/java/com/arangodb/ArangoSslTest.java @@ -1,100 +1,100 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb; - -import com.arangodb.entity.ArangoDBVersion; -import org.junit.jupiter.api.Tag; -import org.junit.jupiter.api.condition.EnabledIfSystemProperty; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.EnumSource; - -import javax.net.ssl.KeyManagerFactory; -import javax.net.ssl.SSLContext; -import javax.net.ssl.SSLHandshakeException; -import javax.net.ssl.TrustManagerFactory; -import java.security.KeyStore; -import java.util.List; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.catchThrowable; - - -/** - * @author Mark Vollmary - * @author Michele Rastelli - */ -@Tag("ssl") -@EnabledIfSystemProperty(named = "SslTest", matches = "true") -class ArangoSslTest { - - /* - * a SSL trust store - * - * create the trust store for the self signed certificate: - * keytool -import -alias "my arangodb server cert" -file UnitTests/server.pem -keystore example.truststore - * - * Documentation: - * https://hc.apache.org/httpcomponents-client-ga/httpclient/apidocs/org/apache/http/conn/ssl/SSLSocketFactory.html - */ - private static final String SSL_TRUSTSTORE = "/example.truststore"; - private static final String SSL_TRUSTSTORE_PASSWORD = "12345678"; - - @ParameterizedTest - @EnumSource(Protocol.class) - void connect(Protocol protocol) throws Exception { - final KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType()); - ks.load(this.getClass().getResourceAsStream(SSL_TRUSTSTORE), SSL_TRUSTSTORE_PASSWORD.toCharArray()); - - final KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); - kmf.init(ks, SSL_TRUSTSTORE_PASSWORD.toCharArray()); - - final TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); - tmf.init(ks); - - final SSLContext sc = SSLContext.getInstance("TLS"); - sc.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null); - - final ArangoDB arangoDB = new ArangoDB.Builder() - .useProtocol(protocol) - .host("localhost", 8529) - .useSsl(true) - .sslContext(sc).build(); - final ArangoDBVersion version = arangoDB.getVersion(); - assertThat(version).isNotNull(); - } - - @ParameterizedTest - @EnumSource(Protocol.class) - void connectWithoutValidSslContext(Protocol protocol) { - final ArangoDB arangoDB = new ArangoDB.Builder() - .useProtocol(protocol) - .host("localhost", 8529) - .useSsl(true) - .build(); - Throwable thrown = catchThrowable(arangoDB::getVersion); - assertThat(thrown).isInstanceOf(ArangoDBException.class); - ArangoDBException ex = (ArangoDBException) thrown; - assertThat(ex.getCause()).isInstanceOf(ArangoDBMultipleException.class); - List exceptions = ((ArangoDBMultipleException) ex.getCause()).getExceptions(); - exceptions.forEach(e -> assertThat(e).isInstanceOf(SSLHandshakeException.class)); - } - -} +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed 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. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb; + +import com.arangodb.entity.ArangoDBVersion; +import org.junit.jupiter.api.Tag; +import org.junit.jupiter.api.condition.EnabledIfSystemProperty; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.EnumSource; + +import javax.net.ssl.KeyManagerFactory; +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLHandshakeException; +import javax.net.ssl.TrustManagerFactory; +import java.security.KeyStore; +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.catchThrowable; + + +/** + * @author Mark Vollmary + * @author Michele Rastelli + */ +@Tag("ssl") +@EnabledIfSystemProperty(named = "SslTest", matches = "true") +class ArangoSslTest { + + /* + * a SSL trust store + * + * create the trust store for the self signed certificate: + * keytool -import -alias "my arangodb server cert" -file UnitTests/server.pem -keystore example.truststore + * + * Documentation: + * https://hc.apache.org/httpcomponents-client-ga/httpclient/apidocs/org/apache/http/conn/ssl/SSLSocketFactory.html + */ + private static final String SSL_TRUSTSTORE = "/example.truststore"; + private static final String SSL_TRUSTSTORE_PASSWORD = "12345678"; + + @ParameterizedTest + @EnumSource(Protocol.class) + void connect(Protocol protocol) throws Exception { + final KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType()); + ks.load(this.getClass().getResourceAsStream(SSL_TRUSTSTORE), SSL_TRUSTSTORE_PASSWORD.toCharArray()); + + final KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); + kmf.init(ks, SSL_TRUSTSTORE_PASSWORD.toCharArray()); + + final TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); + tmf.init(ks); + + final SSLContext sc = SSLContext.getInstance("TLS"); + sc.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null); + + final ArangoDB arangoDB = new ArangoDB.Builder() + .useProtocol(protocol) + .host("localhost", 8529) + .useSsl(true) + .sslContext(sc).build(); + final ArangoDBVersion version = arangoDB.getVersion(); + assertThat(version).isNotNull(); + } + + @ParameterizedTest + @EnumSource(Protocol.class) + void connectWithoutValidSslContext(Protocol protocol) { + final ArangoDB arangoDB = new ArangoDB.Builder() + .useProtocol(protocol) + .host("localhost", 8529) + .useSsl(true) + .build(); + Throwable thrown = catchThrowable(arangoDB::getVersion); + assertThat(thrown).isInstanceOf(ArangoDBException.class); + ArangoDBException ex = (ArangoDBException) thrown; + assertThat(ex.getCause()).isInstanceOf(ArangoDBMultipleException.class); + List exceptions = ((ArangoDBMultipleException) ex.getCause()).getExceptions(); + exceptions.forEach(e -> assertThat(e).isInstanceOf(SSLHandshakeException.class)); + } + +} diff --git a/src/test/java/com/arangodb/ArangoVertexCollectionTest.java b/driver/src/test/java/com/arangodb/ArangoVertexCollectionTest.java similarity index 97% rename from src/test/java/com/arangodb/ArangoVertexCollectionTest.java rename to driver/src/test/java/com/arangodb/ArangoVertexCollectionTest.java index 7861f9217..5b5504d80 100644 --- a/src/test/java/com/arangodb/ArangoVertexCollectionTest.java +++ b/driver/src/test/java/com/arangodb/ArangoVertexCollectionTest.java @@ -1,480 +1,480 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb; - -import com.arangodb.entity.BaseDocument; -import com.arangodb.entity.VertexEntity; -import com.arangodb.entity.VertexUpdateEntity; -import com.arangodb.model.*; -import com.arangodb.util.RawJson; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.Arguments; -import org.junit.jupiter.params.provider.MethodSource; - -import java.util.Collection; -import java.util.Collections; -import java.util.UUID; -import java.util.stream.Stream; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.catchThrowable; - - -/** - * @author Mark Vollmary - * @author Michele Rastelli - */ -class ArangoVertexCollectionTest extends BaseJunit5 { - - private static final String GRAPH_NAME = "ArangoVertexCollectionTest_graph"; - private static final String COLLECTION_NAME = "ArangoVertexCollectionTest_vertex_collection"; - - private static Stream vertices() { - return dbsStream() - .map(db -> db.graph(GRAPH_NAME).vertexCollection(COLLECTION_NAME)) - .map(Arguments::of); - } - - @BeforeAll - static void init() { - initCollections(COLLECTION_NAME); - initGraph( - GRAPH_NAME, - null, - new GraphCreateOptions().orphanCollections(COLLECTION_NAME) - ); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("vertices") - void dropVertexCollection(ArangoVertexCollection vertices) { - ArangoGraph graph = vertices.graph(); - vertices.drop(); - final Collection vertexCollections = graph.getVertexCollections(); - assertThat(vertexCollections).isEmpty(); - - // revert - graph.addVertexCollection(COLLECTION_NAME); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("vertices") - void insertVertex(ArangoVertexCollection vertices) { - final VertexEntity vertex = vertices - .insertVertex(new BaseDocument(), null); - assertThat(vertex).isNotNull(); - ArangoCollection collection = vertices.graph().db().collection(vertices.name()); - final BaseDocument document = collection - .getDocument(vertex.getKey(), BaseDocument.class, null); - assertThat(document).isNotNull(); - assertThat(document.getKey()).isEqualTo(vertex.getKey()); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("vertices") - void insertVertexViolatingUniqueConstraint(ArangoVertexCollection vertices) { - ArangoCollection collection = vertices.graph().db().collection(vertices.name()); - collection - .ensureSkiplistIndex(Collections.singletonList("field"), - new SkiplistIndexOptions().unique(true).sparse(true)); - - VertexEntity inserted = vertices.insertVertex(RawJson.of("{\"field\": 99}")); - - try { - vertices.insertVertex(RawJson.of("{\"field\": 99}")); - } catch (ArangoDBException e) { - assertThat(e.getResponseCode()).isEqualTo(409); - assertThat(e.getErrorNum()).isEqualTo(1210); - } - - // revert - vertices.deleteVertex(inserted.getKey()); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("vertices") - void duplicateInsertSameObjectVertex(ArangoVertexCollection vertices) { - - // ######################################################### - // Create a new BaseDocument - // ######################################################### - - UUID uuid = UUID.randomUUID(); - BaseDocument bd = new BaseDocument(UUID.randomUUID().toString()); - bd.setKey(uuid.toString()); - bd.addAttribute("name", "Paul"); - - vertices.insertVertex(bd); - - UUID uuid2 = UUID.randomUUID(); - BaseDocument bd2 = new BaseDocument(UUID.randomUUID().toString()); - bd2.setKey(uuid2.toString()); - bd2.addAttribute("name", "Paul"); - - vertices.insertVertex(bd2); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("vertices") - void insertVertexUpdateRev(ArangoVertexCollection vertices) { - final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); - final VertexEntity vertex = vertices.insertVertex(doc, null); - assertThat(doc.getRevision()).isNull(); - assertThat(vertex.getRev()).isNotNull(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("vertices") - void getVertex(ArangoVertexCollection vertices) { - final VertexEntity vertex = vertices - .insertVertex(new BaseDocument(), null); - final BaseDocument document = vertices - .getVertex(vertex.getKey(), BaseDocument.class, null); - assertThat(document).isNotNull(); - assertThat(document.getKey()).isEqualTo(vertex.getKey()); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("vertices") - void getVertexIfMatch(ArangoVertexCollection vertices) { - final VertexEntity vertex = vertices - .insertVertex(new BaseDocument(), null); - final GraphDocumentReadOptions options = new GraphDocumentReadOptions().ifMatch(vertex.getRev()); - final BaseDocument document = vertices - .getVertex(vertex.getKey(), BaseDocument.class, options); - assertThat(document).isNotNull(); - assertThat(document.getKey()).isEqualTo(vertex.getKey()); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("vertices") - void getVertexIfMatchFail(ArangoVertexCollection vertices) { - final VertexEntity vertex = vertices - .insertVertex(new BaseDocument(), null); - final GraphDocumentReadOptions options = new GraphDocumentReadOptions().ifMatch("no"); - final BaseDocument vertex2 = vertices - .getVertex(vertex.getKey(), BaseDocument.class, options); - assertThat(vertex2).isNull(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("vertices") - void getVertexIfNoneMatch(ArangoVertexCollection vertices) { - final VertexEntity vertex = vertices - .insertVertex(new BaseDocument(), null); - final GraphDocumentReadOptions options = new GraphDocumentReadOptions().ifNoneMatch("no"); - final BaseDocument document = vertices - .getVertex(vertex.getKey(), BaseDocument.class, options); - assertThat(document).isNotNull(); - assertThat(document.getKey()).isEqualTo(vertex.getKey()); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("vertices") - void getVertexIfNoneMatchFail(ArangoVertexCollection vertices) { - final VertexEntity vertex = vertices - .insertVertex(new BaseDocument(), null); - final GraphDocumentReadOptions options = new GraphDocumentReadOptions().ifNoneMatch(vertex.getRev()); - final BaseDocument vertex2 = vertices - .getVertex(vertex.getKey(), BaseDocument.class, options); - assertThat(vertex2).isNull(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("vertices") - void replaceVertex(ArangoVertexCollection vertices) { - final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); - doc.addAttribute("a", "test"); - final VertexEntity createResult = vertices - .insertVertex(doc, null); - doc.removeAttribute("a"); - doc.addAttribute("b", "test"); - final VertexUpdateEntity replaceResult = vertices - .replaceVertex(createResult.getKey(), doc, null); - assertThat(replaceResult).isNotNull(); - assertThat(replaceResult.getId()).isEqualTo(createResult.getId()); - assertThat(replaceResult.getRev()).isNotEqualTo(replaceResult.getOldRev()); - assertThat(replaceResult.getOldRev()).isEqualTo(createResult.getRev()); - - final BaseDocument readResult = vertices - .getVertex(createResult.getKey(), BaseDocument.class, null); - assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); - assertThat(readResult.getRevision()).isEqualTo(replaceResult.getRev()); - assertThat(readResult.getProperties().keySet()).doesNotContain("a"); - assertThat(readResult.getAttribute("b")).isNotNull(); - assertThat(String.valueOf(readResult.getAttribute("b"))).isEqualTo("test"); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("vertices") - void replaceVertexUpdateRev(ArangoVertexCollection vertices) { - final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); - final VertexEntity createResult = vertices - .insertVertex(doc, null); - final VertexUpdateEntity replaceResult = vertices - .replaceVertex(createResult.getKey(), doc, null); - assertThat(doc.getRevision()).isNull(); - assertThat(createResult.getRev()).isNotNull(); - assertThat(replaceResult.getRev()) - .isNotNull() - .isNotEqualTo(createResult.getRev()); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("vertices") - void replaceVertexIfMatch(ArangoVertexCollection vertices) { - final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); - doc.addAttribute("a", "test"); - final VertexEntity createResult = vertices - .insertVertex(doc, null); - doc.removeAttribute("a"); - doc.addAttribute("b", "test"); - final VertexReplaceOptions options = new VertexReplaceOptions().ifMatch(createResult.getRev()); - final VertexUpdateEntity replaceResult = vertices - .replaceVertex(createResult.getKey(), doc, options); - assertThat(replaceResult).isNotNull(); - assertThat(replaceResult.getId()).isEqualTo(createResult.getId()); - assertThat(replaceResult.getRev()).isNotEqualTo(replaceResult.getOldRev()); - assertThat(replaceResult.getOldRev()).isEqualTo(createResult.getRev()); - - final BaseDocument readResult = vertices - .getVertex(createResult.getKey(), BaseDocument.class, null); - assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); - assertThat(readResult.getRevision()).isEqualTo(replaceResult.getRev()); - assertThat(readResult.getProperties().keySet()).doesNotContain("a"); - assertThat(readResult.getAttribute("b")).isNotNull(); - assertThat(String.valueOf(readResult.getAttribute("b"))).isEqualTo("test"); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("vertices") - void replaceVertexIfMatchFail(ArangoVertexCollection vertices) { - final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); - doc.addAttribute("a", "test"); - final VertexEntity createResult = vertices - .insertVertex(doc, null); - doc.removeAttribute("a"); - doc.addAttribute("b", "test"); - final VertexReplaceOptions options = new VertexReplaceOptions().ifMatch("no"); - Throwable thrown = catchThrowable(() -> vertices.replaceVertex(createResult.getKey(), doc, options)); - assertThat(thrown).isInstanceOf(ArangoDBException.class); - ArangoDBException e = (ArangoDBException) thrown; - assertThat(e.getResponseCode()).isEqualTo(412); - assertThat(e.getErrorNum()).isEqualTo(1200); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("vertices") - void updateVertex(ArangoVertexCollection vertices) { - final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); - doc.addAttribute("a", "test"); - doc.addAttribute("c", "test"); - final VertexEntity createResult = vertices - .insertVertex(doc, null); - doc.updateAttribute("a", "test1"); - doc.addAttribute("b", "test"); - doc.updateAttribute("c", null); - final VertexUpdateEntity updateResult = vertices - .updateVertex(createResult.getKey(), doc, null); - assertThat(updateResult).isNotNull(); - assertThat(updateResult.getId()).isEqualTo(createResult.getId()); - assertThat(updateResult.getRev()).isNotEqualTo(updateResult.getOldRev()); - assertThat(updateResult.getOldRev()).isEqualTo(createResult.getRev()); - - final BaseDocument readResult = vertices - .getVertex(createResult.getKey(), BaseDocument.class, null); - assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); - assertThat(readResult.getAttribute("a")).isNotNull(); - assertThat(String.valueOf(readResult.getAttribute("a"))).isEqualTo("test1"); - assertThat(readResult.getAttribute("b")).isNotNull(); - assertThat(String.valueOf(readResult.getAttribute("b"))).isEqualTo("test"); - assertThat(readResult.getRevision()).isEqualTo(updateResult.getRev()); - assertThat(readResult.getProperties()).containsKey("c"); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("vertices") - void updateVertexUpdateRev(ArangoVertexCollection vertices) { - final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); - final VertexEntity createResult = vertices - .insertVertex(doc, null); - doc.addAttribute("foo", "bar"); - final VertexUpdateEntity updateResult = vertices - .updateVertex(createResult.getKey(), doc, null); - assertThat(doc.getRevision()).isNull(); - assertThat(createResult.getRev()).isNotNull(); - assertThat(updateResult.getRev()) - .isNotNull() - .isNotEqualTo(createResult.getRev()); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("vertices") - void updateVertexIfMatch(ArangoVertexCollection vertices) { - final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); - doc.addAttribute("a", "test"); - doc.addAttribute("c", "test"); - final VertexEntity createResult = vertices - .insertVertex(doc, null); - doc.updateAttribute("a", "test1"); - doc.addAttribute("b", "test"); - doc.updateAttribute("c", null); - final VertexUpdateOptions options = new VertexUpdateOptions().ifMatch(createResult.getRev()); - final VertexUpdateEntity updateResult = vertices - .updateVertex(createResult.getKey(), doc, options); - assertThat(updateResult).isNotNull(); - assertThat(updateResult.getId()).isEqualTo(createResult.getId()); - assertThat(updateResult.getRev()).isNotEqualTo(updateResult.getOldRev()); - assertThat(updateResult.getOldRev()).isEqualTo(createResult.getRev()); - - final BaseDocument readResult = vertices - .getVertex(createResult.getKey(), BaseDocument.class, null); - assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); - assertThat(readResult.getAttribute("a")).isNotNull(); - assertThat(String.valueOf(readResult.getAttribute("a"))).isEqualTo("test1"); - assertThat(readResult.getAttribute("b")).isNotNull(); - assertThat(String.valueOf(readResult.getAttribute("b"))).isEqualTo("test"); - assertThat(readResult.getRevision()).isEqualTo(updateResult.getRev()); - assertThat(readResult.getProperties()).containsKey("c"); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("vertices") - void updateVertexIfMatchFail(ArangoVertexCollection vertices) { - final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); - doc.addAttribute("a", "test"); - doc.addAttribute("c", "test"); - final VertexEntity createResult = vertices - .insertVertex(doc, null); - doc.updateAttribute("a", "test1"); - doc.addAttribute("b", "test"); - doc.updateAttribute("c", null); - final VertexUpdateOptions options = new VertexUpdateOptions().ifMatch("no"); - - Throwable thrown = catchThrowable(() -> vertices.updateVertex(createResult.getKey(), doc, options)); - assertThat(thrown).isInstanceOf(ArangoDBException.class); - ArangoDBException e = (ArangoDBException) thrown; - assertThat(e.getResponseCode()).isEqualTo(412); - assertThat(e.getErrorNum()).isEqualTo(1200); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("vertices") - void updateVertexKeepNullTrue(ArangoVertexCollection vertices) { - final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); - doc.addAttribute("a", "test"); - final VertexEntity createResult = vertices - .insertVertex(doc, null); - doc.updateAttribute("a", null); - final VertexUpdateOptions options = new VertexUpdateOptions().keepNull(true); - final VertexUpdateEntity updateResult = vertices - .updateVertex(createResult.getKey(), doc, options); - assertThat(updateResult).isNotNull(); - assertThat(updateResult.getId()).isEqualTo(createResult.getId()); - assertThat(updateResult.getRev()).isNotEqualTo(updateResult.getOldRev()); - assertThat(updateResult.getOldRev()).isEqualTo(createResult.getRev()); - - final BaseDocument readResult = vertices - .getVertex(createResult.getKey(), BaseDocument.class, null); - assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); - assertThat(readResult.getProperties().keySet()).hasSize(4); - assertThat(readResult.getProperties()).containsKey("a"); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("vertices") - void updateVertexKeepNullFalse(ArangoVertexCollection vertices) { - final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); - doc.addAttribute("a", "test"); - final VertexEntity createResult = vertices - .insertVertex(doc, null); - doc.updateAttribute("a", null); - final VertexUpdateOptions options = new VertexUpdateOptions().keepNull(false); - final VertexUpdateEntity updateResult = vertices - .updateVertex(createResult.getKey(), doc, options); - assertThat(updateResult).isNotNull(); - assertThat(updateResult.getId()).isEqualTo(createResult.getId()); - assertThat(updateResult.getRev()).isNotEqualTo(updateResult.getOldRev()); - assertThat(updateResult.getOldRev()).isEqualTo(createResult.getRev()); - - final BaseDocument readResult = vertices - .getVertex(createResult.getKey(), BaseDocument.class, null); - assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); - assertThat(readResult.getId()).isEqualTo(createResult.getId()); - assertThat(readResult.getRevision()).isNotNull(); - assertThat(readResult.getProperties().keySet()).doesNotContain("a"); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("vertices") - void deleteVertex(ArangoVertexCollection vertices) { - final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); - final VertexEntity createResult = vertices - .insertVertex(doc, null); - vertices.deleteVertex(createResult.getKey(), null); - final BaseDocument vertex = vertices - .getVertex(createResult.getKey(), BaseDocument.class, null); - assertThat(vertex).isNull(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("vertices") - void deleteVertexIfMatch(ArangoVertexCollection vertices) { - final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); - final VertexEntity createResult = vertices - .insertVertex(doc, null); - final VertexDeleteOptions options = new VertexDeleteOptions().ifMatch(createResult.getRev()); - vertices.deleteVertex(createResult.getKey(), options); - final BaseDocument vertex = vertices - .getVertex(createResult.getKey(), BaseDocument.class, null); - assertThat(vertex).isNull(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("vertices") - void deleteVertexIfMatchFail(ArangoVertexCollection vertices) { - final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); - final VertexEntity createResult = vertices - .insertVertex(doc, null); - final VertexDeleteOptions options = new VertexDeleteOptions().ifMatch("no"); - Throwable thrown = catchThrowable(() -> vertices.deleteVertex(createResult.getKey(), options)); - assertThat(thrown).isInstanceOf(ArangoDBException.class); - ArangoDBException e = (ArangoDBException) thrown; - assertThat(e.getResponseCode()).isEqualTo(412); - assertThat(e.getErrorNum()).isEqualTo(1200); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("vertices") - void vertexKeyWithSpecialChars(ArangoVertexCollection vertices) { - final String key = "_-:.@()+,=;$!*'%" + UUID.randomUUID(); - final VertexEntity vertex = vertices - .insertVertex(new BaseDocument(key), null); - assertThat(vertex).isNotNull(); - ArangoCollection collection = vertices.graph().db().collection(vertices.name()); - final BaseDocument document = collection - .getDocument(vertex.getKey(), BaseDocument.class, null); - assertThat(document).isNotNull(); - assertThat(document.getKey()).isEqualTo(key); - } - -} +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed 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. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb; + +import com.arangodb.entity.BaseDocument; +import com.arangodb.entity.VertexEntity; +import com.arangodb.entity.VertexUpdateEntity; +import com.arangodb.model.*; +import com.arangodb.util.RawJson; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +import java.util.Collection; +import java.util.Collections; +import java.util.UUID; +import java.util.stream.Stream; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.catchThrowable; + + +/** + * @author Mark Vollmary + * @author Michele Rastelli + */ +class ArangoVertexCollectionTest extends BaseJunit5 { + + private static final String GRAPH_NAME = "ArangoVertexCollectionTest_graph"; + private static final String COLLECTION_NAME = "ArangoVertexCollectionTest_vertex_collection"; + + private static Stream vertices() { + return dbsStream() + .map(db -> db.graph(GRAPH_NAME).vertexCollection(COLLECTION_NAME)) + .map(Arguments::of); + } + + @BeforeAll + static void init() { + initCollections(COLLECTION_NAME); + initGraph( + GRAPH_NAME, + null, + new GraphCreateOptions().orphanCollections(COLLECTION_NAME) + ); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("vertices") + void dropVertexCollection(ArangoVertexCollection vertices) { + ArangoGraph graph = vertices.graph(); + vertices.drop(); + final Collection vertexCollections = graph.getVertexCollections(); + assertThat(vertexCollections).isEmpty(); + + // revert + graph.addVertexCollection(COLLECTION_NAME); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("vertices") + void insertVertex(ArangoVertexCollection vertices) { + final VertexEntity vertex = vertices + .insertVertex(new BaseDocument(), null); + assertThat(vertex).isNotNull(); + ArangoCollection collection = vertices.graph().db().collection(vertices.name()); + final BaseDocument document = collection + .getDocument(vertex.getKey(), BaseDocument.class, null); + assertThat(document).isNotNull(); + assertThat(document.getKey()).isEqualTo(vertex.getKey()); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("vertices") + void insertVertexViolatingUniqueConstraint(ArangoVertexCollection vertices) { + ArangoCollection collection = vertices.graph().db().collection(vertices.name()); + collection + .ensureSkiplistIndex(Collections.singletonList("field"), + new SkiplistIndexOptions().unique(true).sparse(true)); + + VertexEntity inserted = vertices.insertVertex(RawJson.of("{\"field\": 99}")); + + try { + vertices.insertVertex(RawJson.of("{\"field\": 99}")); + } catch (ArangoDBException e) { + assertThat(e.getResponseCode()).isEqualTo(409); + assertThat(e.getErrorNum()).isEqualTo(1210); + } + + // revert + vertices.deleteVertex(inserted.getKey()); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("vertices") + void duplicateInsertSameObjectVertex(ArangoVertexCollection vertices) { + + // ######################################################### + // Create a new BaseDocument + // ######################################################### + + UUID uuid = UUID.randomUUID(); + BaseDocument bd = new BaseDocument(UUID.randomUUID().toString()); + bd.setKey(uuid.toString()); + bd.addAttribute("name", "Paul"); + + vertices.insertVertex(bd); + + UUID uuid2 = UUID.randomUUID(); + BaseDocument bd2 = new BaseDocument(UUID.randomUUID().toString()); + bd2.setKey(uuid2.toString()); + bd2.addAttribute("name", "Paul"); + + vertices.insertVertex(bd2); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("vertices") + void insertVertexUpdateRev(ArangoVertexCollection vertices) { + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); + final VertexEntity vertex = vertices.insertVertex(doc, null); + assertThat(doc.getRevision()).isNull(); + assertThat(vertex.getRev()).isNotNull(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("vertices") + void getVertex(ArangoVertexCollection vertices) { + final VertexEntity vertex = vertices + .insertVertex(new BaseDocument(), null); + final BaseDocument document = vertices + .getVertex(vertex.getKey(), BaseDocument.class, null); + assertThat(document).isNotNull(); + assertThat(document.getKey()).isEqualTo(vertex.getKey()); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("vertices") + void getVertexIfMatch(ArangoVertexCollection vertices) { + final VertexEntity vertex = vertices + .insertVertex(new BaseDocument(), null); + final GraphDocumentReadOptions options = new GraphDocumentReadOptions().ifMatch(vertex.getRev()); + final BaseDocument document = vertices + .getVertex(vertex.getKey(), BaseDocument.class, options); + assertThat(document).isNotNull(); + assertThat(document.getKey()).isEqualTo(vertex.getKey()); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("vertices") + void getVertexIfMatchFail(ArangoVertexCollection vertices) { + final VertexEntity vertex = vertices + .insertVertex(new BaseDocument(), null); + final GraphDocumentReadOptions options = new GraphDocumentReadOptions().ifMatch("no"); + final BaseDocument vertex2 = vertices + .getVertex(vertex.getKey(), BaseDocument.class, options); + assertThat(vertex2).isNull(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("vertices") + void getVertexIfNoneMatch(ArangoVertexCollection vertices) { + final VertexEntity vertex = vertices + .insertVertex(new BaseDocument(), null); + final GraphDocumentReadOptions options = new GraphDocumentReadOptions().ifNoneMatch("no"); + final BaseDocument document = vertices + .getVertex(vertex.getKey(), BaseDocument.class, options); + assertThat(document).isNotNull(); + assertThat(document.getKey()).isEqualTo(vertex.getKey()); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("vertices") + void getVertexIfNoneMatchFail(ArangoVertexCollection vertices) { + final VertexEntity vertex = vertices + .insertVertex(new BaseDocument(), null); + final GraphDocumentReadOptions options = new GraphDocumentReadOptions().ifNoneMatch(vertex.getRev()); + final BaseDocument vertex2 = vertices + .getVertex(vertex.getKey(), BaseDocument.class, options); + assertThat(vertex2).isNull(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("vertices") + void replaceVertex(ArangoVertexCollection vertices) { + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); + doc.addAttribute("a", "test"); + final VertexEntity createResult = vertices + .insertVertex(doc, null); + doc.removeAttribute("a"); + doc.addAttribute("b", "test"); + final VertexUpdateEntity replaceResult = vertices + .replaceVertex(createResult.getKey(), doc, null); + assertThat(replaceResult).isNotNull(); + assertThat(replaceResult.getId()).isEqualTo(createResult.getId()); + assertThat(replaceResult.getRev()).isNotEqualTo(replaceResult.getOldRev()); + assertThat(replaceResult.getOldRev()).isEqualTo(createResult.getRev()); + + final BaseDocument readResult = vertices + .getVertex(createResult.getKey(), BaseDocument.class, null); + assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); + assertThat(readResult.getRevision()).isEqualTo(replaceResult.getRev()); + assertThat(readResult.getProperties().keySet()).doesNotContain("a"); + assertThat(readResult.getAttribute("b")).isNotNull(); + assertThat(String.valueOf(readResult.getAttribute("b"))).isEqualTo("test"); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("vertices") + void replaceVertexUpdateRev(ArangoVertexCollection vertices) { + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); + final VertexEntity createResult = vertices + .insertVertex(doc, null); + final VertexUpdateEntity replaceResult = vertices + .replaceVertex(createResult.getKey(), doc, null); + assertThat(doc.getRevision()).isNull(); + assertThat(createResult.getRev()).isNotNull(); + assertThat(replaceResult.getRev()) + .isNotNull() + .isNotEqualTo(createResult.getRev()); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("vertices") + void replaceVertexIfMatch(ArangoVertexCollection vertices) { + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); + doc.addAttribute("a", "test"); + final VertexEntity createResult = vertices + .insertVertex(doc, null); + doc.removeAttribute("a"); + doc.addAttribute("b", "test"); + final VertexReplaceOptions options = new VertexReplaceOptions().ifMatch(createResult.getRev()); + final VertexUpdateEntity replaceResult = vertices + .replaceVertex(createResult.getKey(), doc, options); + assertThat(replaceResult).isNotNull(); + assertThat(replaceResult.getId()).isEqualTo(createResult.getId()); + assertThat(replaceResult.getRev()).isNotEqualTo(replaceResult.getOldRev()); + assertThat(replaceResult.getOldRev()).isEqualTo(createResult.getRev()); + + final BaseDocument readResult = vertices + .getVertex(createResult.getKey(), BaseDocument.class, null); + assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); + assertThat(readResult.getRevision()).isEqualTo(replaceResult.getRev()); + assertThat(readResult.getProperties().keySet()).doesNotContain("a"); + assertThat(readResult.getAttribute("b")).isNotNull(); + assertThat(String.valueOf(readResult.getAttribute("b"))).isEqualTo("test"); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("vertices") + void replaceVertexIfMatchFail(ArangoVertexCollection vertices) { + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); + doc.addAttribute("a", "test"); + final VertexEntity createResult = vertices + .insertVertex(doc, null); + doc.removeAttribute("a"); + doc.addAttribute("b", "test"); + final VertexReplaceOptions options = new VertexReplaceOptions().ifMatch("no"); + Throwable thrown = catchThrowable(() -> vertices.replaceVertex(createResult.getKey(), doc, options)); + assertThat(thrown).isInstanceOf(ArangoDBException.class); + ArangoDBException e = (ArangoDBException) thrown; + assertThat(e.getResponseCode()).isEqualTo(412); + assertThat(e.getErrorNum()).isEqualTo(1200); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("vertices") + void updateVertex(ArangoVertexCollection vertices) { + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); + doc.addAttribute("a", "test"); + doc.addAttribute("c", "test"); + final VertexEntity createResult = vertices + .insertVertex(doc, null); + doc.updateAttribute("a", "test1"); + doc.addAttribute("b", "test"); + doc.updateAttribute("c", null); + final VertexUpdateEntity updateResult = vertices + .updateVertex(createResult.getKey(), doc, null); + assertThat(updateResult).isNotNull(); + assertThat(updateResult.getId()).isEqualTo(createResult.getId()); + assertThat(updateResult.getRev()).isNotEqualTo(updateResult.getOldRev()); + assertThat(updateResult.getOldRev()).isEqualTo(createResult.getRev()); + + final BaseDocument readResult = vertices + .getVertex(createResult.getKey(), BaseDocument.class, null); + assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); + assertThat(readResult.getAttribute("a")).isNotNull(); + assertThat(String.valueOf(readResult.getAttribute("a"))).isEqualTo("test1"); + assertThat(readResult.getAttribute("b")).isNotNull(); + assertThat(String.valueOf(readResult.getAttribute("b"))).isEqualTo("test"); + assertThat(readResult.getRevision()).isEqualTo(updateResult.getRev()); + assertThat(readResult.getProperties()).containsKey("c"); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("vertices") + void updateVertexUpdateRev(ArangoVertexCollection vertices) { + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); + final VertexEntity createResult = vertices + .insertVertex(doc, null); + doc.addAttribute("foo", "bar"); + final VertexUpdateEntity updateResult = vertices + .updateVertex(createResult.getKey(), doc, null); + assertThat(doc.getRevision()).isNull(); + assertThat(createResult.getRev()).isNotNull(); + assertThat(updateResult.getRev()) + .isNotNull() + .isNotEqualTo(createResult.getRev()); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("vertices") + void updateVertexIfMatch(ArangoVertexCollection vertices) { + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); + doc.addAttribute("a", "test"); + doc.addAttribute("c", "test"); + final VertexEntity createResult = vertices + .insertVertex(doc, null); + doc.updateAttribute("a", "test1"); + doc.addAttribute("b", "test"); + doc.updateAttribute("c", null); + final VertexUpdateOptions options = new VertexUpdateOptions().ifMatch(createResult.getRev()); + final VertexUpdateEntity updateResult = vertices + .updateVertex(createResult.getKey(), doc, options); + assertThat(updateResult).isNotNull(); + assertThat(updateResult.getId()).isEqualTo(createResult.getId()); + assertThat(updateResult.getRev()).isNotEqualTo(updateResult.getOldRev()); + assertThat(updateResult.getOldRev()).isEqualTo(createResult.getRev()); + + final BaseDocument readResult = vertices + .getVertex(createResult.getKey(), BaseDocument.class, null); + assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); + assertThat(readResult.getAttribute("a")).isNotNull(); + assertThat(String.valueOf(readResult.getAttribute("a"))).isEqualTo("test1"); + assertThat(readResult.getAttribute("b")).isNotNull(); + assertThat(String.valueOf(readResult.getAttribute("b"))).isEqualTo("test"); + assertThat(readResult.getRevision()).isEqualTo(updateResult.getRev()); + assertThat(readResult.getProperties()).containsKey("c"); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("vertices") + void updateVertexIfMatchFail(ArangoVertexCollection vertices) { + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); + doc.addAttribute("a", "test"); + doc.addAttribute("c", "test"); + final VertexEntity createResult = vertices + .insertVertex(doc, null); + doc.updateAttribute("a", "test1"); + doc.addAttribute("b", "test"); + doc.updateAttribute("c", null); + final VertexUpdateOptions options = new VertexUpdateOptions().ifMatch("no"); + + Throwable thrown = catchThrowable(() -> vertices.updateVertex(createResult.getKey(), doc, options)); + assertThat(thrown).isInstanceOf(ArangoDBException.class); + ArangoDBException e = (ArangoDBException) thrown; + assertThat(e.getResponseCode()).isEqualTo(412); + assertThat(e.getErrorNum()).isEqualTo(1200); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("vertices") + void updateVertexKeepNullTrue(ArangoVertexCollection vertices) { + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); + doc.addAttribute("a", "test"); + final VertexEntity createResult = vertices + .insertVertex(doc, null); + doc.updateAttribute("a", null); + final VertexUpdateOptions options = new VertexUpdateOptions().keepNull(true); + final VertexUpdateEntity updateResult = vertices + .updateVertex(createResult.getKey(), doc, options); + assertThat(updateResult).isNotNull(); + assertThat(updateResult.getId()).isEqualTo(createResult.getId()); + assertThat(updateResult.getRev()).isNotEqualTo(updateResult.getOldRev()); + assertThat(updateResult.getOldRev()).isEqualTo(createResult.getRev()); + + final BaseDocument readResult = vertices + .getVertex(createResult.getKey(), BaseDocument.class, null); + assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); + assertThat(readResult.getProperties().keySet()).hasSize(4); + assertThat(readResult.getProperties()).containsKey("a"); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("vertices") + void updateVertexKeepNullFalse(ArangoVertexCollection vertices) { + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); + doc.addAttribute("a", "test"); + final VertexEntity createResult = vertices + .insertVertex(doc, null); + doc.updateAttribute("a", null); + final VertexUpdateOptions options = new VertexUpdateOptions().keepNull(false); + final VertexUpdateEntity updateResult = vertices + .updateVertex(createResult.getKey(), doc, options); + assertThat(updateResult).isNotNull(); + assertThat(updateResult.getId()).isEqualTo(createResult.getId()); + assertThat(updateResult.getRev()).isNotEqualTo(updateResult.getOldRev()); + assertThat(updateResult.getOldRev()).isEqualTo(createResult.getRev()); + + final BaseDocument readResult = vertices + .getVertex(createResult.getKey(), BaseDocument.class, null); + assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); + assertThat(readResult.getId()).isEqualTo(createResult.getId()); + assertThat(readResult.getRevision()).isNotNull(); + assertThat(readResult.getProperties().keySet()).doesNotContain("a"); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("vertices") + void deleteVertex(ArangoVertexCollection vertices) { + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); + final VertexEntity createResult = vertices + .insertVertex(doc, null); + vertices.deleteVertex(createResult.getKey(), null); + final BaseDocument vertex = vertices + .getVertex(createResult.getKey(), BaseDocument.class, null); + assertThat(vertex).isNull(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("vertices") + void deleteVertexIfMatch(ArangoVertexCollection vertices) { + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); + final VertexEntity createResult = vertices + .insertVertex(doc, null); + final VertexDeleteOptions options = new VertexDeleteOptions().ifMatch(createResult.getRev()); + vertices.deleteVertex(createResult.getKey(), options); + final BaseDocument vertex = vertices + .getVertex(createResult.getKey(), BaseDocument.class, null); + assertThat(vertex).isNull(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("vertices") + void deleteVertexIfMatchFail(ArangoVertexCollection vertices) { + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); + final VertexEntity createResult = vertices + .insertVertex(doc, null); + final VertexDeleteOptions options = new VertexDeleteOptions().ifMatch("no"); + Throwable thrown = catchThrowable(() -> vertices.deleteVertex(createResult.getKey(), options)); + assertThat(thrown).isInstanceOf(ArangoDBException.class); + ArangoDBException e = (ArangoDBException) thrown; + assertThat(e.getResponseCode()).isEqualTo(412); + assertThat(e.getErrorNum()).isEqualTo(1200); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("vertices") + void vertexKeyWithSpecialChars(ArangoVertexCollection vertices) { + final String key = "_-:.@()+,=;$!*'%" + UUID.randomUUID(); + final VertexEntity vertex = vertices + .insertVertex(new BaseDocument(key), null); + assertThat(vertex).isNotNull(); + ArangoCollection collection = vertices.graph().db().collection(vertices.name()); + final BaseDocument document = collection + .getDocument(vertex.getKey(), BaseDocument.class, null); + assertThat(document).isNotNull(); + assertThat(document.getKey()).isEqualTo(key); + } + +} diff --git a/src/test/java/com/arangodb/ArangoViewTest.java b/driver/src/test/java/com/arangodb/ArangoViewTest.java similarity index 100% rename from src/test/java/com/arangodb/ArangoViewTest.java rename to driver/src/test/java/com/arangodb/ArangoViewTest.java diff --git a/src/test/java/com/arangodb/BaseJunit5.java b/driver/src/test/java/com/arangodb/BaseJunit5.java similarity index 100% rename from src/test/java/com/arangodb/BaseJunit5.java rename to driver/src/test/java/com/arangodb/BaseJunit5.java diff --git a/src/test/java/com/arangodb/ConcurrencyTests.java b/driver/src/test/java/com/arangodb/ConcurrencyTests.java similarity index 100% rename from src/test/java/com/arangodb/ConcurrencyTests.java rename to driver/src/test/java/com/arangodb/ConcurrencyTests.java diff --git a/src/test/java/com/arangodb/DocumentTest.java b/driver/src/test/java/com/arangodb/DocumentTest.java similarity index 97% rename from src/test/java/com/arangodb/DocumentTest.java rename to driver/src/test/java/com/arangodb/DocumentTest.java index 3293316c5..0ce14ff53 100644 --- a/src/test/java/com/arangodb/DocumentTest.java +++ b/driver/src/test/java/com/arangodb/DocumentTest.java @@ -1,138 +1,138 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb; - -import com.arangodb.entity.BaseDocument; -import com.arangodb.entity.DocumentCreateEntity; -import com.arangodb.util.RawJson; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.Arguments; -import org.junit.jupiter.params.provider.MethodSource; - -import java.util.Map; -import java.util.UUID; -import java.util.stream.Stream; - -import static org.assertj.core.api.Assertions.assertThat; - - -/** - * @author Mark Vollmary - * @author Michele Rastelli - */ -class DocumentTest extends BaseJunit5 { - - private static final String COLLECTION_NAME = "DocumentTest_collection"; - - private static Stream cols() { - return dbsStream() - .map(db -> db.collection(COLLECTION_NAME)) - .map(Arguments::of); - } - - - @BeforeAll - static void init() { - initCollections(COLLECTION_NAME); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void insertAsJson(ArangoCollection collection) { - //@formatter:off - final RawJson json = RawJson.of( - "{" - + "\"article\": {" - + "\"artist\": \"PREGARDIEN/RHEINISCHE KANTOREI/DAS\"," - + "\"releaseDate\": \"1970-01-01\"," - + "\"composer\": \"BACH\"," - + "\"format\": \"CD\"," - + "\"vat\": \"H\"," - + "\"carriers\": 1," - + "\"label\": \"CAPRICCIO\"," - + "\"title\": \"BACH ST MATTHEW PASSION BWV244\"," - + "\"barcode\": [" - + "\"4006408600466\"" - + "]," - + "\"conductor\": \"MAX, H.\"" - + "}," - + "\"stock\": {" - + "\"status\": \"RMV\"," - + "\"lastUpdate\": \"2016-11-01 00:00\"" - + "}" - + "}" - ); - //@formatter:on - final DocumentCreateEntity createResult = collection.insertDocument(json); - final BaseDocument doc = collection.getDocument(createResult.getKey(), BaseDocument.class); - assertThat(doc).isNotNull(); - final Object article = doc.getAttribute("article"); - assertThat(article).isNotNull(); - final Object artist = ((Map) article).get("artist"); - assertThat(artist).isNotNull(); - assertThat(artist.toString()).isEqualTo("PREGARDIEN/RHEINISCHE KANTOREI/DAS"); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void insertAsBaseDocument(ArangoCollection collection) { - final BaseDocument document = new BaseDocument(UUID.randomUUID().toString()); - { - final BaseDocument article = new BaseDocument(UUID.randomUUID().toString()); - document.addAttribute("article", article); - article.addAttribute("artist", "PREGARDIEN/RHEINISCHE KANTOREI/DAS"); - article.addAttribute("releaseDate", "1970-01-01"); - article.addAttribute("composer", "BACH"); - article.addAttribute("format", "CD"); - article.addAttribute("vat", "H"); - article.addAttribute("carriers", 1); - article.addAttribute("label", "CAPRICCIO"); - article.addAttribute("title", "BACH ST MATTHEW PASSION BWV244"); - article.addAttribute("barcode", new String[]{"4006408600466"}); - article.addAttribute("conductor", "MAX, H."); - final BaseDocument stock = new BaseDocument(UUID.randomUUID().toString()); - document.addAttribute("stock", stock); - stock.addAttribute("status", "RMV"); - stock.addAttribute("lastUpdate", "2016-11-01 00:00"); - } - final DocumentCreateEntity createResult = collection.insertDocument(document); - final BaseDocument doc = collection.getDocument(createResult.getKey(), BaseDocument.class); - assertThat(doc).isNotNull(); - final Object article = doc.getAttribute("article"); - assertThat(article).isNotNull(); - final Object artist = ((Map) article).get("artist"); - assertThat(artist).isNotNull(); - assertThat(artist.toString()).isEqualTo("PREGARDIEN/RHEINISCHE KANTOREI/DAS"); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void documentKeyWithSpecialChars(ArangoCollection collection) { - final String key = "_-:.@()+,=;$!*'%" + UUID.randomUUID(); - final BaseDocument document = new BaseDocument(key); - final DocumentCreateEntity createResult = collection.insertDocument(document); - final BaseDocument doc = collection.getDocument(createResult.getKey(), BaseDocument.class); - assertThat(doc).isNotNull(); - assertThat(doc.getKey()).isEqualTo(key); - } - -} +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed 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. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb; + +import com.arangodb.entity.BaseDocument; +import com.arangodb.entity.DocumentCreateEntity; +import com.arangodb.util.RawJson; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +import java.util.Map; +import java.util.UUID; +import java.util.stream.Stream; + +import static org.assertj.core.api.Assertions.assertThat; + + +/** + * @author Mark Vollmary + * @author Michele Rastelli + */ +class DocumentTest extends BaseJunit5 { + + private static final String COLLECTION_NAME = "DocumentTest_collection"; + + private static Stream cols() { + return dbsStream() + .map(db -> db.collection(COLLECTION_NAME)) + .map(Arguments::of); + } + + + @BeforeAll + static void init() { + initCollections(COLLECTION_NAME); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void insertAsJson(ArangoCollection collection) { + //@formatter:off + final RawJson json = RawJson.of( + "{" + + "\"article\": {" + + "\"artist\": \"PREGARDIEN/RHEINISCHE KANTOREI/DAS\"," + + "\"releaseDate\": \"1970-01-01\"," + + "\"composer\": \"BACH\"," + + "\"format\": \"CD\"," + + "\"vat\": \"H\"," + + "\"carriers\": 1," + + "\"label\": \"CAPRICCIO\"," + + "\"title\": \"BACH ST MATTHEW PASSION BWV244\"," + + "\"barcode\": [" + + "\"4006408600466\"" + + "]," + + "\"conductor\": \"MAX, H.\"" + + "}," + + "\"stock\": {" + + "\"status\": \"RMV\"," + + "\"lastUpdate\": \"2016-11-01 00:00\"" + + "}" + + "}" + ); + //@formatter:on + final DocumentCreateEntity createResult = collection.insertDocument(json); + final BaseDocument doc = collection.getDocument(createResult.getKey(), BaseDocument.class); + assertThat(doc).isNotNull(); + final Object article = doc.getAttribute("article"); + assertThat(article).isNotNull(); + final Object artist = ((Map) article).get("artist"); + assertThat(artist).isNotNull(); + assertThat(artist.toString()).isEqualTo("PREGARDIEN/RHEINISCHE KANTOREI/DAS"); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void insertAsBaseDocument(ArangoCollection collection) { + final BaseDocument document = new BaseDocument(UUID.randomUUID().toString()); + { + final BaseDocument article = new BaseDocument(UUID.randomUUID().toString()); + document.addAttribute("article", article); + article.addAttribute("artist", "PREGARDIEN/RHEINISCHE KANTOREI/DAS"); + article.addAttribute("releaseDate", "1970-01-01"); + article.addAttribute("composer", "BACH"); + article.addAttribute("format", "CD"); + article.addAttribute("vat", "H"); + article.addAttribute("carriers", 1); + article.addAttribute("label", "CAPRICCIO"); + article.addAttribute("title", "BACH ST MATTHEW PASSION BWV244"); + article.addAttribute("barcode", new String[]{"4006408600466"}); + article.addAttribute("conductor", "MAX, H."); + final BaseDocument stock = new BaseDocument(UUID.randomUUID().toString()); + document.addAttribute("stock", stock); + stock.addAttribute("status", "RMV"); + stock.addAttribute("lastUpdate", "2016-11-01 00:00"); + } + final DocumentCreateEntity createResult = collection.insertDocument(document); + final BaseDocument doc = collection.getDocument(createResult.getKey(), BaseDocument.class); + assertThat(doc).isNotNull(); + final Object article = doc.getAttribute("article"); + assertThat(article).isNotNull(); + final Object artist = ((Map) article).get("artist"); + assertThat(artist).isNotNull(); + assertThat(artist.toString()).isEqualTo("PREGARDIEN/RHEINISCHE KANTOREI/DAS"); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void documentKeyWithSpecialChars(ArangoCollection collection) { + final String key = "_-:.@()+,=;$!*'%" + UUID.randomUUID(); + final BaseDocument document = new BaseDocument(key); + final DocumentCreateEntity createResult = collection.insertDocument(document); + final BaseDocument doc = collection.getDocument(createResult.getKey(), BaseDocument.class); + assertThat(doc).isNotNull(); + assertThat(doc.getKey()).isEqualTo(key); + } + +} diff --git a/src/test/java/com/arangodb/InvertedIndexTest.java b/driver/src/test/java/com/arangodb/InvertedIndexTest.java similarity index 100% rename from src/test/java/com/arangodb/InvertedIndexTest.java rename to driver/src/test/java/com/arangodb/InvertedIndexTest.java diff --git a/src/test/java/com/arangodb/JwtAuthTest.java b/driver/src/test/java/com/arangodb/JwtAuthTest.java similarity index 94% rename from src/test/java/com/arangodb/JwtAuthTest.java rename to driver/src/test/java/com/arangodb/JwtAuthTest.java index a5b87e803..57d9f3001 100644 --- a/src/test/java/com/arangodb/JwtAuthTest.java +++ b/driver/src/test/java/com/arangodb/JwtAuthTest.java @@ -2,6 +2,7 @@ import com.arangodb.serde.ArangoSerde; import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Disabled; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.EnumSource; @@ -10,6 +11,7 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.catchThrowable; +import static org.junit.jupiter.api.Assumptions.assumeTrue; /** @@ -64,13 +66,11 @@ void authenticated(Protocol protocol) { @ParameterizedTest @EnumSource(Protocol.class) void updateJwt(Protocol protocol) { + assumeTrue(protocol != Protocol.VST, "DE-423"); ArangoDB arangoDB = getBuilder(protocol) .jwt(jwt) .build(); arangoDB.getVersion(); - if (protocol == Protocol.VST) { - arangoDB.shutdown(); - } arangoDB.updateJwt("bla"); Throwable thrown = catchThrowable(arangoDB::getVersion); diff --git a/src/test/java/com/arangodb/ParallelTest.java b/driver/src/test/java/com/arangodb/ParallelTest.java similarity index 100% rename from src/test/java/com/arangodb/ParallelTest.java rename to driver/src/test/java/com/arangodb/ParallelTest.java diff --git a/src/test/java/com/arangodb/SerializableTest.java b/driver/src/test/java/com/arangodb/SerializableTest.java similarity index 100% rename from src/test/java/com/arangodb/SerializableTest.java rename to driver/src/test/java/com/arangodb/SerializableTest.java diff --git a/src/test/java/com/arangodb/StreamTransactionConflictsTest.java b/driver/src/test/java/com/arangodb/StreamTransactionConflictsTest.java similarity index 100% rename from src/test/java/com/arangodb/StreamTransactionConflictsTest.java rename to driver/src/test/java/com/arangodb/StreamTransactionConflictsTest.java diff --git a/src/test/java/com/arangodb/StreamTransactionGraphTest.java b/driver/src/test/java/com/arangodb/StreamTransactionGraphTest.java similarity index 100% rename from src/test/java/com/arangodb/StreamTransactionGraphTest.java rename to driver/src/test/java/com/arangodb/StreamTransactionGraphTest.java diff --git a/src/test/java/com/arangodb/StreamTransactionTest.java b/driver/src/test/java/com/arangodb/StreamTransactionTest.java similarity index 100% rename from src/test/java/com/arangodb/StreamTransactionTest.java rename to driver/src/test/java/com/arangodb/StreamTransactionTest.java diff --git a/src/test/java/com/arangodb/async/ArangoCollectionTest.java b/driver/src/test/java/com/arangodb/async/ArangoCollectionTest.java similarity index 100% rename from src/test/java/com/arangodb/async/ArangoCollectionTest.java rename to driver/src/test/java/com/arangodb/async/ArangoCollectionTest.java diff --git a/src/test/java/com/arangodb/async/ArangoDBTest.java b/driver/src/test/java/com/arangodb/async/ArangoDBTest.java similarity index 100% rename from src/test/java/com/arangodb/async/ArangoDBTest.java rename to driver/src/test/java/com/arangodb/async/ArangoDBTest.java diff --git a/src/test/java/com/arangodb/async/ArangoDatabaseTest.java b/driver/src/test/java/com/arangodb/async/ArangoDatabaseTest.java similarity index 100% rename from src/test/java/com/arangodb/async/ArangoDatabaseTest.java rename to driver/src/test/java/com/arangodb/async/ArangoDatabaseTest.java diff --git a/src/test/java/com/arangodb/async/ArangoEdgeCollectionTest.java b/driver/src/test/java/com/arangodb/async/ArangoEdgeCollectionTest.java similarity index 100% rename from src/test/java/com/arangodb/async/ArangoEdgeCollectionTest.java rename to driver/src/test/java/com/arangodb/async/ArangoEdgeCollectionTest.java diff --git a/src/test/java/com/arangodb/async/ArangoGraphTest.java b/driver/src/test/java/com/arangodb/async/ArangoGraphTest.java similarity index 100% rename from src/test/java/com/arangodb/async/ArangoGraphTest.java rename to driver/src/test/java/com/arangodb/async/ArangoGraphTest.java diff --git a/src/test/java/com/arangodb/async/ArangoRouteTest.java b/driver/src/test/java/com/arangodb/async/ArangoRouteTest.java similarity index 100% rename from src/test/java/com/arangodb/async/ArangoRouteTest.java rename to driver/src/test/java/com/arangodb/async/ArangoRouteTest.java diff --git a/src/test/java/com/arangodb/async/ArangoSearchTest.java b/driver/src/test/java/com/arangodb/async/ArangoSearchTest.java similarity index 100% rename from src/test/java/com/arangodb/async/ArangoSearchTest.java rename to driver/src/test/java/com/arangodb/async/ArangoSearchTest.java diff --git a/src/test/java/com/arangodb/async/ArangoVertexCollectionTest.java b/driver/src/test/java/com/arangodb/async/ArangoVertexCollectionTest.java similarity index 100% rename from src/test/java/com/arangodb/async/ArangoVertexCollectionTest.java rename to driver/src/test/java/com/arangodb/async/ArangoVertexCollectionTest.java diff --git a/src/test/java/com/arangodb/async/ArangoViewTest.java b/driver/src/test/java/com/arangodb/async/ArangoViewTest.java similarity index 100% rename from src/test/java/com/arangodb/async/ArangoViewTest.java rename to driver/src/test/java/com/arangodb/async/ArangoViewTest.java diff --git a/src/test/java/com/arangodb/async/BaseTest.java b/driver/src/test/java/com/arangodb/async/BaseTest.java similarity index 100% rename from src/test/java/com/arangodb/async/BaseTest.java rename to driver/src/test/java/com/arangodb/async/BaseTest.java diff --git a/src/test/java/com/arangodb/async/CommunicationTest.java b/driver/src/test/java/com/arangodb/async/CommunicationTest.java similarity index 100% rename from src/test/java/com/arangodb/async/CommunicationTest.java rename to driver/src/test/java/com/arangodb/async/CommunicationTest.java diff --git a/src/test/java/com/arangodb/async/ConcurrencyTest.java b/driver/src/test/java/com/arangodb/async/ConcurrencyTest.java similarity index 100% rename from src/test/java/com/arangodb/async/ConcurrencyTest.java rename to driver/src/test/java/com/arangodb/async/ConcurrencyTest.java diff --git a/src/test/java/com/arangodb/async/ConcurrencyTests.java b/driver/src/test/java/com/arangodb/async/ConcurrencyTests.java similarity index 100% rename from src/test/java/com/arangodb/async/ConcurrencyTests.java rename to driver/src/test/java/com/arangodb/async/ConcurrencyTests.java diff --git a/src/test/java/com/arangodb/async/InvertedIndexTest.java b/driver/src/test/java/com/arangodb/async/InvertedIndexTest.java similarity index 100% rename from src/test/java/com/arangodb/async/InvertedIndexTest.java rename to driver/src/test/java/com/arangodb/async/InvertedIndexTest.java diff --git a/src/test/java/com/arangodb/async/JwtAuthTest.java b/driver/src/test/java/com/arangodb/async/JwtAuthTest.java similarity index 100% rename from src/test/java/com/arangodb/async/JwtAuthTest.java rename to driver/src/test/java/com/arangodb/async/JwtAuthTest.java diff --git a/src/test/java/com/arangodb/async/StreamTransactionConflictsTest.java b/driver/src/test/java/com/arangodb/async/StreamTransactionConflictsTest.java similarity index 100% rename from src/test/java/com/arangodb/async/StreamTransactionConflictsTest.java rename to driver/src/test/java/com/arangodb/async/StreamTransactionConflictsTest.java diff --git a/src/test/java/com/arangodb/async/StreamTransactionGraphTest.java b/driver/src/test/java/com/arangodb/async/StreamTransactionGraphTest.java similarity index 100% rename from src/test/java/com/arangodb/async/StreamTransactionGraphTest.java rename to driver/src/test/java/com/arangodb/async/StreamTransactionGraphTest.java diff --git a/src/test/java/com/arangodb/async/StreamTransactionTest.java b/driver/src/test/java/com/arangodb/async/StreamTransactionTest.java similarity index 100% rename from src/test/java/com/arangodb/async/StreamTransactionTest.java rename to driver/src/test/java/com/arangodb/async/StreamTransactionTest.java diff --git a/src/test/java/com/arangodb/async/debug/ConsolidationIntervalMsecTest.java b/driver/src/test/java/com/arangodb/async/debug/ConsolidationIntervalMsecTest.java similarity index 100% rename from src/test/java/com/arangodb/async/debug/ConsolidationIntervalMsecTest.java rename to driver/src/test/java/com/arangodb/async/debug/ConsolidationIntervalMsecTest.java diff --git a/src/test/java/com/arangodb/async/example/ExampleBase.java b/driver/src/test/java/com/arangodb/async/example/ExampleBase.java similarity index 100% rename from src/test/java/com/arangodb/async/example/ExampleBase.java rename to driver/src/test/java/com/arangodb/async/example/ExampleBase.java diff --git a/src/test/java/com/arangodb/async/example/document/AqlQueryWithSpecialReturnTypesExampleTest.java b/driver/src/test/java/com/arangodb/async/example/document/AqlQueryWithSpecialReturnTypesExampleTest.java similarity index 100% rename from src/test/java/com/arangodb/async/example/document/AqlQueryWithSpecialReturnTypesExampleTest.java rename to driver/src/test/java/com/arangodb/async/example/document/AqlQueryWithSpecialReturnTypesExampleTest.java diff --git a/src/test/java/com/arangodb/async/example/document/GetDocumentExampleTest.java b/driver/src/test/java/com/arangodb/async/example/document/GetDocumentExampleTest.java similarity index 100% rename from src/test/java/com/arangodb/async/example/document/GetDocumentExampleTest.java rename to driver/src/test/java/com/arangodb/async/example/document/GetDocumentExampleTest.java diff --git a/src/test/java/com/arangodb/async/example/document/ImportDocumentExampleTest.java b/driver/src/test/java/com/arangodb/async/example/document/ImportDocumentExampleTest.java similarity index 100% rename from src/test/java/com/arangodb/async/example/document/ImportDocumentExampleTest.java rename to driver/src/test/java/com/arangodb/async/example/document/ImportDocumentExampleTest.java diff --git a/src/test/java/com/arangodb/async/example/document/InsertDocumentExampleTest.java b/driver/src/test/java/com/arangodb/async/example/document/InsertDocumentExampleTest.java similarity index 100% rename from src/test/java/com/arangodb/async/example/document/InsertDocumentExampleTest.java rename to driver/src/test/java/com/arangodb/async/example/document/InsertDocumentExampleTest.java diff --git a/src/test/java/com/arangodb/async/example/document/TestEntity.java b/driver/src/test/java/com/arangodb/async/example/document/TestEntity.java similarity index 100% rename from src/test/java/com/arangodb/async/example/document/TestEntity.java rename to driver/src/test/java/com/arangodb/async/example/document/TestEntity.java diff --git a/src/test/java/com/arangodb/async/example/graph/AQLActorsAndMoviesExampleTest.java b/driver/src/test/java/com/arangodb/async/example/graph/AQLActorsAndMoviesExampleTest.java similarity index 100% rename from src/test/java/com/arangodb/async/example/graph/AQLActorsAndMoviesExampleTest.java rename to driver/src/test/java/com/arangodb/async/example/graph/AQLActorsAndMoviesExampleTest.java diff --git a/src/test/java/com/arangodb/async/example/graph/BaseGraphTest.java b/driver/src/test/java/com/arangodb/async/example/graph/BaseGraphTest.java similarity index 100% rename from src/test/java/com/arangodb/async/example/graph/BaseGraphTest.java rename to driver/src/test/java/com/arangodb/async/example/graph/BaseGraphTest.java diff --git a/src/test/java/com/arangodb/async/example/graph/Circle.java b/driver/src/test/java/com/arangodb/async/example/graph/Circle.java similarity index 100% rename from src/test/java/com/arangodb/async/example/graph/Circle.java rename to driver/src/test/java/com/arangodb/async/example/graph/Circle.java diff --git a/src/test/java/com/arangodb/async/example/graph/CircleEdge.java b/driver/src/test/java/com/arangodb/async/example/graph/CircleEdge.java similarity index 100% rename from src/test/java/com/arangodb/async/example/graph/CircleEdge.java rename to driver/src/test/java/com/arangodb/async/example/graph/CircleEdge.java diff --git a/src/test/java/com/arangodb/async/example/graph/GraphTraversalsInAQLExampleTest.java b/driver/src/test/java/com/arangodb/async/example/graph/GraphTraversalsInAQLExampleTest.java similarity index 100% rename from src/test/java/com/arangodb/async/example/graph/GraphTraversalsInAQLExampleTest.java rename to driver/src/test/java/com/arangodb/async/example/graph/GraphTraversalsInAQLExampleTest.java diff --git a/src/test/java/com/arangodb/async/example/graph/ShortestPathInAQLExampleTest.java b/driver/src/test/java/com/arangodb/async/example/graph/ShortestPathInAQLExampleTest.java similarity index 100% rename from src/test/java/com/arangodb/async/example/graph/ShortestPathInAQLExampleTest.java rename to driver/src/test/java/com/arangodb/async/example/graph/ShortestPathInAQLExampleTest.java diff --git a/src/test/java/com/arangodb/async/example/ssl/SslExampleTest.java b/driver/src/test/java/com/arangodb/async/example/ssl/SslExampleTest.java similarity index 100% rename from src/test/java/com/arangodb/async/example/ssl/SslExampleTest.java rename to driver/src/test/java/com/arangodb/async/example/ssl/SslExampleTest.java diff --git a/src/test/java/com/arangodb/async/serde/CustomSerdeTest.java b/driver/src/test/java/com/arangodb/async/serde/CustomSerdeTest.java similarity index 100% rename from src/test/java/com/arangodb/async/serde/CustomSerdeTest.java rename to driver/src/test/java/com/arangodb/async/serde/CustomSerdeTest.java diff --git a/src/test/java/com/arangodb/example/ExampleBase.java b/driver/src/test/java/com/arangodb/example/ExampleBase.java similarity index 96% rename from src/test/java/com/arangodb/example/ExampleBase.java rename to driver/src/test/java/com/arangodb/example/ExampleBase.java index 967c57a6a..77a2bfce1 100644 --- a/src/test/java/com/arangodb/example/ExampleBase.java +++ b/driver/src/test/java/com/arangodb/example/ExampleBase.java @@ -1,59 +1,59 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.example; - -import com.arangodb.ArangoCollection; -import com.arangodb.ArangoDB; -import com.arangodb.ArangoDatabase; -import com.arangodb.DbName; -import org.junit.jupiter.api.AfterAll; -import org.junit.jupiter.api.BeforeAll; - -/** - * @author Mark Vollmary - */ -public class ExampleBase { - - protected static final String COLLECTION_NAME = "json_example_collection"; - private static final String DB_NAME = "json_example_db"; - protected static ArangoDatabase db; - protected static ArangoCollection collection; - private static ArangoDB arangoDB; - - @BeforeAll - static void setUp() { - arangoDB = new ArangoDB.Builder().build(); - DbName dbName = DbName.of(DB_NAME); - if (arangoDB.db(dbName).exists()) - arangoDB.db(dbName).drop(); - arangoDB.createDatabase(dbName); - db = arangoDB.db(dbName); - db.createCollection(COLLECTION_NAME); - collection = db.collection(COLLECTION_NAME); - } - - @AfterAll - static void tearDown() { - db.drop(); - arangoDB.shutdown(); - } - -} +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed 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. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.example; + +import com.arangodb.ArangoCollection; +import com.arangodb.ArangoDB; +import com.arangodb.ArangoDatabase; +import com.arangodb.DbName; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; + +/** + * @author Mark Vollmary + */ +public class ExampleBase { + + protected static final String COLLECTION_NAME = "json_example_collection"; + private static final String DB_NAME = "json_example_db"; + protected static ArangoDatabase db; + protected static ArangoCollection collection; + private static ArangoDB arangoDB; + + @BeforeAll + static void setUp() { + arangoDB = new ArangoDB.Builder().build(); + DbName dbName = DbName.of(DB_NAME); + if (arangoDB.db(dbName).exists()) + arangoDB.db(dbName).drop(); + arangoDB.createDatabase(dbName); + db = arangoDB.db(dbName); + db.createCollection(COLLECTION_NAME); + collection = db.collection(COLLECTION_NAME); + } + + @AfterAll + static void tearDown() { + db.drop(); + arangoDB.shutdown(); + } + +} diff --git a/src/test/java/com/arangodb/example/FirstProject.java b/driver/src/test/java/com/arangodb/example/FirstProject.java similarity index 97% rename from src/test/java/com/arangodb/example/FirstProject.java rename to driver/src/test/java/com/arangodb/example/FirstProject.java index 31adecc12..454bfabc7 100644 --- a/src/test/java/com/arangodb/example/FirstProject.java +++ b/driver/src/test/java/com/arangodb/example/FirstProject.java @@ -1,134 +1,134 @@ -package com.arangodb.example; - -import com.arangodb.*; -import com.arangodb.entity.BaseDocument; -import com.arangodb.entity.CollectionEntity; -import com.fasterxml.jackson.databind.JsonNode; - -import java.util.Collections; -import java.util.Map; -import java.util.UUID; - -public class FirstProject { - - public static void main(final String[] args) { - final ArangoDB arangoDB = new ArangoDB.Builder().user("root").build(); - - // create database - final DbName dbName = DbName.of("mydb"); - try { - arangoDB.createDatabase(dbName); - System.out.println("Database created: " + dbName); - } catch (final ArangoDBException e) { - System.err.println("Failed to create database: " + dbName + "; " + e.getMessage()); - } - - // create collection - final String collectionName = "firstCollection"; - try { - final CollectionEntity myArangoCollection = arangoDB.db(dbName).createCollection(collectionName); - System.out.println("Collection created: " + myArangoCollection.getName()); - } catch (final ArangoDBException e) { - System.err.println("Failed to create collection: " + collectionName + "; " + e.getMessage()); - } - - // creating a document - final BaseDocument myObject = new BaseDocument(UUID.randomUUID().toString()); - myObject.setKey("myKey"); - myObject.addAttribute("a", "Foo"); - myObject.addAttribute("b", 42); - try { - arangoDB.db(dbName).collection(collectionName).insertDocument(myObject); - System.out.println("Document created"); - } catch (final ArangoDBException e) { - System.err.println("Failed to create document. " + e.getMessage()); - } - - // read a document - try { - final BaseDocument myDocument = arangoDB.db(dbName).collection(collectionName).getDocument("myKey", - BaseDocument.class); - System.out.println("Key: " + myDocument.getKey()); - System.out.println("Attribute a: " + myDocument.getAttribute("a")); - System.out.println("Attribute b: " + myDocument.getAttribute("b")); - } catch (final ArangoDBException e) { - System.err.println("Failed to get document: myKey; " + e.getMessage()); - } - - // read a document as JsonNode - try { - final JsonNode myDocument = arangoDB.db(dbName).collection(collectionName).getDocument("myKey", - JsonNode.class); - System.out.println("Key: " + myDocument.get("_key").textValue()); - System.out.println("Attribute a: " + myDocument.get("a").textValue()); - System.out.println("Attribute b: " + myDocument.get("b").textValue()); - } catch (final ArangoDBException e) { - System.err.println("Failed to get document: myKey; " + e.getMessage()); - } - - // update a document - myObject.addAttribute("c", "Bar"); - try { - arangoDB.db(dbName).collection(collectionName).updateDocument("myKey", myObject); - } catch (final ArangoDBException e) { - System.err.println("Failed to update document. " + e.getMessage()); - } - - // read the document again - try { - final BaseDocument myUpdatedDocument = arangoDB.db(dbName).collection(collectionName).getDocument("myKey", - BaseDocument.class); - System.out.println("Key: " + myUpdatedDocument.getKey()); - System.out.println("Attribute a: " + myUpdatedDocument.getAttribute("a")); - System.out.println("Attribute b: " + myUpdatedDocument.getAttribute("b")); - System.out.println("Attribute c: " + myUpdatedDocument.getAttribute("c")); - } catch (final ArangoDBException e) { - System.err.println("Failed to get document: myKey; " + e.getMessage()); - } - - // delete a document - try { - arangoDB.db(dbName).collection(collectionName).deleteDocument("myKey"); - } catch (final ArangoDBException e) { - System.err.println("Failed to delete document. " + e.getMessage()); - } - - // create some documents for the next step - final ArangoCollection collection = arangoDB.db(dbName).collection(collectionName); - for (int i = 0; i < 10; i++) { - final BaseDocument value = new BaseDocument(UUID.randomUUID().toString()); - value.setKey(String.valueOf(i)); - value.addAttribute("name", "Homer"); - collection.insertDocument(value); - } - - // execute AQL queries - try { - final String query = "FOR t IN firstCollection FILTER t.name == @name RETURN t"; - final Map bindVars = Collections.singletonMap("name", "Homer"); - final ArangoCursor cursor = arangoDB.db(dbName).query(query, bindVars, null, - BaseDocument.class); - while (cursor.hasNext()) { - System.out.println("Key: " + cursor.next().getKey()); - } - } catch (final ArangoDBException e) { - System.err.println("Failed to execute query. " + e.getMessage()); - } - - // delete a document with AQL - try { - final String query = "FOR t IN firstCollection FILTER t.name == @name " - + "REMOVE t IN firstCollection LET removed = OLD RETURN removed"; - final Map bindVars = Collections.singletonMap("name", "Homer"); - final ArangoCursor cursor = arangoDB.db(dbName).query(query, bindVars, null, - BaseDocument.class); - while (cursor.hasNext()) { - System.out.println("Removed document " + cursor.next().getKey()); - } - } catch (final ArangoDBException e) { - System.err.println("Failed to execute query. " + e.getMessage()); - } - - } - -} +package com.arangodb.example; + +import com.arangodb.*; +import com.arangodb.entity.BaseDocument; +import com.arangodb.entity.CollectionEntity; +import com.fasterxml.jackson.databind.JsonNode; + +import java.util.Collections; +import java.util.Map; +import java.util.UUID; + +public class FirstProject { + + public static void main(final String[] args) { + final ArangoDB arangoDB = new ArangoDB.Builder().user("root").build(); + + // create database + final DbName dbName = DbName.of("mydb"); + try { + arangoDB.createDatabase(dbName); + System.out.println("Database created: " + dbName); + } catch (final ArangoDBException e) { + System.err.println("Failed to create database: " + dbName + "; " + e.getMessage()); + } + + // create collection + final String collectionName = "firstCollection"; + try { + final CollectionEntity myArangoCollection = arangoDB.db(dbName).createCollection(collectionName); + System.out.println("Collection created: " + myArangoCollection.getName()); + } catch (final ArangoDBException e) { + System.err.println("Failed to create collection: " + collectionName + "; " + e.getMessage()); + } + + // creating a document + final BaseDocument myObject = new BaseDocument(UUID.randomUUID().toString()); + myObject.setKey("myKey"); + myObject.addAttribute("a", "Foo"); + myObject.addAttribute("b", 42); + try { + arangoDB.db(dbName).collection(collectionName).insertDocument(myObject); + System.out.println("Document created"); + } catch (final ArangoDBException e) { + System.err.println("Failed to create document. " + e.getMessage()); + } + + // read a document + try { + final BaseDocument myDocument = arangoDB.db(dbName).collection(collectionName).getDocument("myKey", + BaseDocument.class); + System.out.println("Key: " + myDocument.getKey()); + System.out.println("Attribute a: " + myDocument.getAttribute("a")); + System.out.println("Attribute b: " + myDocument.getAttribute("b")); + } catch (final ArangoDBException e) { + System.err.println("Failed to get document: myKey; " + e.getMessage()); + } + + // read a document as JsonNode + try { + final JsonNode myDocument = arangoDB.db(dbName).collection(collectionName).getDocument("myKey", + JsonNode.class); + System.out.println("Key: " + myDocument.get("_key").textValue()); + System.out.println("Attribute a: " + myDocument.get("a").textValue()); + System.out.println("Attribute b: " + myDocument.get("b").textValue()); + } catch (final ArangoDBException e) { + System.err.println("Failed to get document: myKey; " + e.getMessage()); + } + + // update a document + myObject.addAttribute("c", "Bar"); + try { + arangoDB.db(dbName).collection(collectionName).updateDocument("myKey", myObject); + } catch (final ArangoDBException e) { + System.err.println("Failed to update document. " + e.getMessage()); + } + + // read the document again + try { + final BaseDocument myUpdatedDocument = arangoDB.db(dbName).collection(collectionName).getDocument("myKey", + BaseDocument.class); + System.out.println("Key: " + myUpdatedDocument.getKey()); + System.out.println("Attribute a: " + myUpdatedDocument.getAttribute("a")); + System.out.println("Attribute b: " + myUpdatedDocument.getAttribute("b")); + System.out.println("Attribute c: " + myUpdatedDocument.getAttribute("c")); + } catch (final ArangoDBException e) { + System.err.println("Failed to get document: myKey; " + e.getMessage()); + } + + // delete a document + try { + arangoDB.db(dbName).collection(collectionName).deleteDocument("myKey"); + } catch (final ArangoDBException e) { + System.err.println("Failed to delete document. " + e.getMessage()); + } + + // create some documents for the next step + final ArangoCollection collection = arangoDB.db(dbName).collection(collectionName); + for (int i = 0; i < 10; i++) { + final BaseDocument value = new BaseDocument(UUID.randomUUID().toString()); + value.setKey(String.valueOf(i)); + value.addAttribute("name", "Homer"); + collection.insertDocument(value); + } + + // execute AQL queries + try { + final String query = "FOR t IN firstCollection FILTER t.name == @name RETURN t"; + final Map bindVars = Collections.singletonMap("name", "Homer"); + final ArangoCursor cursor = arangoDB.db(dbName).query(query, bindVars, null, + BaseDocument.class); + while (cursor.hasNext()) { + System.out.println("Key: " + cursor.next().getKey()); + } + } catch (final ArangoDBException e) { + System.err.println("Failed to execute query. " + e.getMessage()); + } + + // delete a document with AQL + try { + final String query = "FOR t IN firstCollection FILTER t.name == @name " + + "REMOVE t IN firstCollection LET removed = OLD RETURN removed"; + final Map bindVars = Collections.singletonMap("name", "Homer"); + final ArangoCursor cursor = arangoDB.db(dbName).query(query, bindVars, null, + BaseDocument.class); + while (cursor.hasNext()) { + System.out.println("Removed document " + cursor.next().getKey()); + } + } catch (final ArangoDBException e) { + System.err.println("Failed to execute query. " + e.getMessage()); + } + + } + +} diff --git a/src/test/java/com/arangodb/example/document/AqlQueryWithSpecialReturnTypesExampleTest.java b/driver/src/test/java/com/arangodb/example/document/AqlQueryWithSpecialReturnTypesExampleTest.java similarity index 100% rename from src/test/java/com/arangodb/example/document/AqlQueryWithSpecialReturnTypesExampleTest.java rename to driver/src/test/java/com/arangodb/example/document/AqlQueryWithSpecialReturnTypesExampleTest.java diff --git a/src/test/java/com/arangodb/example/document/GetDocumentExampleTest.java b/driver/src/test/java/com/arangodb/example/document/GetDocumentExampleTest.java similarity index 100% rename from src/test/java/com/arangodb/example/document/GetDocumentExampleTest.java rename to driver/src/test/java/com/arangodb/example/document/GetDocumentExampleTest.java diff --git a/src/test/java/com/arangodb/example/document/InsertDocumentExampleTest.java b/driver/src/test/java/com/arangodb/example/document/InsertDocumentExampleTest.java similarity index 100% rename from src/test/java/com/arangodb/example/document/InsertDocumentExampleTest.java rename to driver/src/test/java/com/arangodb/example/document/InsertDocumentExampleTest.java diff --git a/src/test/java/com/arangodb/example/document/TestEntity.java b/driver/src/test/java/com/arangodb/example/document/TestEntity.java similarity index 95% rename from src/test/java/com/arangodb/example/document/TestEntity.java rename to driver/src/test/java/com/arangodb/example/document/TestEntity.java index 6e42a3aad..8a59c2b60 100644 --- a/src/test/java/com/arangodb/example/document/TestEntity.java +++ b/driver/src/test/java/com/arangodb/example/document/TestEntity.java @@ -1,47 +1,47 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.example.document; - -/** - * @author Mark Vollmary - */ -public class TestEntity { - - private String foo; - - public TestEntity() { - super(); - } - - public TestEntity(final String foo) { - super(); - this.foo = foo; - } - - public String getFoo() { - return foo; - } - - public void setFoo(final String foo) { - this.foo = foo; - } - -} +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed 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. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.example.document; + +/** + * @author Mark Vollmary + */ +public class TestEntity { + + private String foo; + + public TestEntity() { + super(); + } + + public TestEntity(final String foo) { + super(); + this.foo = foo; + } + + public String getFoo() { + return foo; + } + + public void setFoo(final String foo) { + this.foo = foo; + } + +} diff --git a/src/test/java/com/arangodb/example/graph/AQLActorsAndMoviesExampleTest.java b/driver/src/test/java/com/arangodb/example/graph/AQLActorsAndMoviesExampleTest.java similarity index 100% rename from src/test/java/com/arangodb/example/graph/AQLActorsAndMoviesExampleTest.java rename to driver/src/test/java/com/arangodb/example/graph/AQLActorsAndMoviesExampleTest.java diff --git a/src/test/java/com/arangodb/example/graph/BaseGraphTest.java b/driver/src/test/java/com/arangodb/example/graph/BaseGraphTest.java similarity index 97% rename from src/test/java/com/arangodb/example/graph/BaseGraphTest.java rename to driver/src/test/java/com/arangodb/example/graph/BaseGraphTest.java index d60239fa3..d9f5e811b 100644 --- a/src/test/java/com/arangodb/example/graph/BaseGraphTest.java +++ b/driver/src/test/java/com/arangodb/example/graph/BaseGraphTest.java @@ -1,111 +1,111 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.example.graph; - -import com.arangodb.ArangoDB; -import com.arangodb.ArangoDBException; -import com.arangodb.ArangoDatabase; -import com.arangodb.DbName; -import com.arangodb.entity.EdgeDefinition; -import com.arangodb.entity.VertexEntity; -import org.junit.jupiter.api.AfterAll; -import org.junit.jupiter.api.BeforeAll; - -import java.util.ArrayList; -import java.util.Collection; - -/** - * @author Mark Vollmary - */ -abstract class BaseGraphTest { - - private static final DbName TEST_DB = DbName.of("java_driver_graph_test_db"); - private static final String GRAPH_NAME = "traversalGraph"; - private static final String EDGE_COLLECTION_NAME = "edges"; - private static final String VERTEX_COLLECTION_NAME = "circles"; - static ArangoDatabase db; - private static ArangoDB arangoDB; - - @BeforeAll - static void init() { - if (arangoDB == null) { - arangoDB = new ArangoDB.Builder().build(); - } - if (arangoDB.db(TEST_DB).exists()) - arangoDB.db(TEST_DB).drop(); - arangoDB.createDatabase(TEST_DB); - BaseGraphTest.db = arangoDB.db(TEST_DB); - - final Collection edgeDefinitions = new ArrayList<>(); - final EdgeDefinition edgeDefinition = new EdgeDefinition().collection(EDGE_COLLECTION_NAME) - .from(VERTEX_COLLECTION_NAME).to(VERTEX_COLLECTION_NAME); - edgeDefinitions.add(edgeDefinition); - if (!db.graph(GRAPH_NAME).exists()) - db.createGraph(GRAPH_NAME, edgeDefinitions, null); - addExampleElements(); - } - - @AfterAll - static void shutdown() { - arangoDB.db(TEST_DB).drop(); - arangoDB.shutdown(); - arangoDB = null; - } - - private static void addExampleElements() throws ArangoDBException { - - // Add circle circles - final VertexEntity vA = createVertex(new Circle("A", "1")); - final VertexEntity vB = createVertex(new Circle("B", "2")); - final VertexEntity vC = createVertex(new Circle("C", "3")); - final VertexEntity vD = createVertex(new Circle("D", "4")); - final VertexEntity vE = createVertex(new Circle("E", "5")); - final VertexEntity vF = createVertex(new Circle("F", "6")); - final VertexEntity vG = createVertex(new Circle("G", "7")); - final VertexEntity vH = createVertex(new Circle("H", "8")); - final VertexEntity vI = createVertex(new Circle("I", "9")); - final VertexEntity vJ = createVertex(new Circle("J", "10")); - final VertexEntity vK = createVertex(new Circle("K", "11")); - - // Add relevant edges - left branch: - saveEdge(new CircleEdge(vA.getId(), vB.getId(), false, true, "left_bar")); - saveEdge(new CircleEdge(vB.getId(), vC.getId(), false, true, "left_blarg")); - saveEdge(new CircleEdge(vC.getId(), vD.getId(), false, true, "left_blorg")); - saveEdge(new CircleEdge(vB.getId(), vE.getId(), false, true, "left_blub")); - saveEdge(new CircleEdge(vE.getId(), vF.getId(), false, true, "left_schubi")); - - // Add relevant edges - right branch: - saveEdge(new CircleEdge(vA.getId(), vG.getId(), false, true, "right_foo")); - saveEdge(new CircleEdge(vG.getId(), vH.getId(), false, true, "right_blob")); - saveEdge(new CircleEdge(vH.getId(), vI.getId(), false, true, "right_blub")); - saveEdge(new CircleEdge(vG.getId(), vJ.getId(), false, true, "right_zip")); - saveEdge(new CircleEdge(vJ.getId(), vK.getId(), false, true, "right_zup")); - } - - private static void saveEdge(final CircleEdge edge) throws ArangoDBException { - db.graph(GRAPH_NAME).edgeCollection(EDGE_COLLECTION_NAME).insertEdge(edge); - } - - private static VertexEntity createVertex(final Circle vertex) throws ArangoDBException { - return db.graph(GRAPH_NAME).vertexCollection(VERTEX_COLLECTION_NAME).insertVertex(vertex); - } - -} +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed 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. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.example.graph; + +import com.arangodb.ArangoDB; +import com.arangodb.ArangoDBException; +import com.arangodb.ArangoDatabase; +import com.arangodb.DbName; +import com.arangodb.entity.EdgeDefinition; +import com.arangodb.entity.VertexEntity; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; + +import java.util.ArrayList; +import java.util.Collection; + +/** + * @author Mark Vollmary + */ +abstract class BaseGraphTest { + + private static final DbName TEST_DB = DbName.of("java_driver_graph_test_db"); + private static final String GRAPH_NAME = "traversalGraph"; + private static final String EDGE_COLLECTION_NAME = "edges"; + private static final String VERTEX_COLLECTION_NAME = "circles"; + static ArangoDatabase db; + private static ArangoDB arangoDB; + + @BeforeAll + static void init() { + if (arangoDB == null) { + arangoDB = new ArangoDB.Builder().build(); + } + if (arangoDB.db(TEST_DB).exists()) + arangoDB.db(TEST_DB).drop(); + arangoDB.createDatabase(TEST_DB); + BaseGraphTest.db = arangoDB.db(TEST_DB); + + final Collection edgeDefinitions = new ArrayList<>(); + final EdgeDefinition edgeDefinition = new EdgeDefinition().collection(EDGE_COLLECTION_NAME) + .from(VERTEX_COLLECTION_NAME).to(VERTEX_COLLECTION_NAME); + edgeDefinitions.add(edgeDefinition); + if (!db.graph(GRAPH_NAME).exists()) + db.createGraph(GRAPH_NAME, edgeDefinitions, null); + addExampleElements(); + } + + @AfterAll + static void shutdown() { + arangoDB.db(TEST_DB).drop(); + arangoDB.shutdown(); + arangoDB = null; + } + + private static void addExampleElements() throws ArangoDBException { + + // Add circle circles + final VertexEntity vA = createVertex(new Circle("A", "1")); + final VertexEntity vB = createVertex(new Circle("B", "2")); + final VertexEntity vC = createVertex(new Circle("C", "3")); + final VertexEntity vD = createVertex(new Circle("D", "4")); + final VertexEntity vE = createVertex(new Circle("E", "5")); + final VertexEntity vF = createVertex(new Circle("F", "6")); + final VertexEntity vG = createVertex(new Circle("G", "7")); + final VertexEntity vH = createVertex(new Circle("H", "8")); + final VertexEntity vI = createVertex(new Circle("I", "9")); + final VertexEntity vJ = createVertex(new Circle("J", "10")); + final VertexEntity vK = createVertex(new Circle("K", "11")); + + // Add relevant edges - left branch: + saveEdge(new CircleEdge(vA.getId(), vB.getId(), false, true, "left_bar")); + saveEdge(new CircleEdge(vB.getId(), vC.getId(), false, true, "left_blarg")); + saveEdge(new CircleEdge(vC.getId(), vD.getId(), false, true, "left_blorg")); + saveEdge(new CircleEdge(vB.getId(), vE.getId(), false, true, "left_blub")); + saveEdge(new CircleEdge(vE.getId(), vF.getId(), false, true, "left_schubi")); + + // Add relevant edges - right branch: + saveEdge(new CircleEdge(vA.getId(), vG.getId(), false, true, "right_foo")); + saveEdge(new CircleEdge(vG.getId(), vH.getId(), false, true, "right_blob")); + saveEdge(new CircleEdge(vH.getId(), vI.getId(), false, true, "right_blub")); + saveEdge(new CircleEdge(vG.getId(), vJ.getId(), false, true, "right_zip")); + saveEdge(new CircleEdge(vJ.getId(), vK.getId(), false, true, "right_zup")); + } + + private static void saveEdge(final CircleEdge edge) throws ArangoDBException { + db.graph(GRAPH_NAME).edgeCollection(EDGE_COLLECTION_NAME).insertEdge(edge); + } + + private static VertexEntity createVertex(final Circle vertex) throws ArangoDBException { + return db.graph(GRAPH_NAME).vertexCollection(VERTEX_COLLECTION_NAME).insertVertex(vertex); + } + +} diff --git a/src/test/java/com/arangodb/example/graph/Circle.java b/driver/src/test/java/com/arangodb/example/graph/Circle.java similarity index 100% rename from src/test/java/com/arangodb/example/graph/Circle.java rename to driver/src/test/java/com/arangodb/example/graph/Circle.java diff --git a/src/test/java/com/arangodb/example/graph/CircleEdge.java b/driver/src/test/java/com/arangodb/example/graph/CircleEdge.java similarity index 100% rename from src/test/java/com/arangodb/example/graph/CircleEdge.java rename to driver/src/test/java/com/arangodb/example/graph/CircleEdge.java diff --git a/src/test/java/com/arangodb/example/graph/GraphTraversalsInAQLExampleTest.java b/driver/src/test/java/com/arangodb/example/graph/GraphTraversalsInAQLExampleTest.java similarity index 100% rename from src/test/java/com/arangodb/example/graph/GraphTraversalsInAQLExampleTest.java rename to driver/src/test/java/com/arangodb/example/graph/GraphTraversalsInAQLExampleTest.java diff --git a/src/test/java/com/arangodb/example/graph/ShortestPathInAQLExampleTest.java b/driver/src/test/java/com/arangodb/example/graph/ShortestPathInAQLExampleTest.java similarity index 100% rename from src/test/java/com/arangodb/example/graph/ShortestPathInAQLExampleTest.java rename to driver/src/test/java/com/arangodb/example/graph/ShortestPathInAQLExampleTest.java diff --git a/src/test/java/com/arangodb/example/ssl/SslExampleTest.java b/driver/src/test/java/com/arangodb/example/ssl/SslExampleTest.java similarity index 100% rename from src/test/java/com/arangodb/example/ssl/SslExampleTest.java rename to driver/src/test/java/com/arangodb/example/ssl/SslExampleTest.java diff --git a/src/test/java/com/arangodb/internal/HostHandlerTest.java b/driver/src/test/java/com/arangodb/internal/HostHandlerTest.java similarity index 100% rename from src/test/java/com/arangodb/internal/HostHandlerTest.java rename to driver/src/test/java/com/arangodb/internal/HostHandlerTest.java diff --git a/src/test/java/com/arangodb/internal/QueueTimeMetricsImplTest.java b/driver/src/test/java/com/arangodb/internal/QueueTimeMetricsImplTest.java similarity index 100% rename from src/test/java/com/arangodb/internal/QueueTimeMetricsImplTest.java rename to driver/src/test/java/com/arangodb/internal/QueueTimeMetricsImplTest.java diff --git a/src/test/java/com/arangodb/internal/velocystream/CommunicationTest.java b/driver/src/test/java/com/arangodb/internal/velocystream/CommunicationTest.java similarity index 97% rename from src/test/java/com/arangodb/internal/velocystream/CommunicationTest.java rename to driver/src/test/java/com/arangodb/internal/velocystream/CommunicationTest.java index c9034cf9c..d08c1e4b0 100644 --- a/src/test/java/com/arangodb/internal/velocystream/CommunicationTest.java +++ b/driver/src/test/java/com/arangodb/internal/velocystream/CommunicationTest.java @@ -1,111 +1,111 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.internal.velocystream; - -import com.arangodb.ArangoDB; -import com.arangodb.ArangoDatabase; -import com.arangodb.entity.ArangoDBVersion; -import org.junit.jupiter.api.Test; - -import java.util.Collection; -import java.util.Iterator; -import java.util.concurrent.ConcurrentLinkedQueue; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * @author Mark Vollmary - */ -class CommunicationTest { - - private static final String FAST = "fast"; - private static final String SLOW = "slow"; - - @Test - void chunkSizeSmall() { - final ArangoDB arangoDB = new ArangoDB.Builder().chunksize(20).build(); - final ArangoDBVersion version = arangoDB.getVersion(); - assertThat(version).isNotNull(); - } - - @Test - void multiThread() throws Exception { - final ArangoDB arangoDB = new ArangoDB.Builder().build(); - arangoDB.getUsers(); // authentication and active-failover connection redirect to master - - final Collection result = new ConcurrentLinkedQueue<>(); - final Thread fast = new Thread(() -> { - arangoDB.db().query("return sleep(0.1)", null, null, null); - result.add(FAST); - }); - final Thread slow = new Thread(() -> { - arangoDB.db().query("return sleep(0.5)", null, null, null); - result.add(SLOW); - }); - slow.start(); - fast.start(); - - slow.join(); - fast.join(); - - assertThat(result.size()).isEqualTo(2); - final Iterator iterator = result.iterator(); - assertThat(iterator.next()).isEqualTo(FAST); - assertThat(iterator.next()).isEqualTo(SLOW); - } - - @Test - void multiThreadSameDatabases() throws Exception { - final ArangoDB arangoDB = new ArangoDB.Builder().build(); - arangoDB.getUsers(); // authentication and active-failover connection redirect to master - - final ArangoDatabase db = arangoDB.db(); - - final Collection result = new ConcurrentLinkedQueue<>(); - final Thread t1 = new Thread(() -> { - db.query("return sleep(0.1)", null, null, null); - result.add("1"); - }); - final Thread t2 = new Thread(() -> { - db.query("return sleep(0.1)", null, null, null); - result.add("1"); - }); - t2.start(); - t1.start(); - t2.join(); - t1.join(); - assertThat(result.size()).isEqualTo(2); - } - - @Test - void minOneConnection() { - final ArangoDB arangoDB = new ArangoDB.Builder().maxConnections(0).build(); - final ArangoDBVersion version = arangoDB.getVersion(); - assertThat(version).isNotNull(); - } - - @Test - void defaultMaxConnection() { - final ArangoDB arangoDB = new ArangoDB.Builder().maxConnections(null).build(); - final ArangoDBVersion version = arangoDB.getVersion(); - assertThat(version).isNotNull(); - } -} +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed 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. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.internal.velocystream; + +import com.arangodb.ArangoDB; +import com.arangodb.ArangoDatabase; +import com.arangodb.entity.ArangoDBVersion; +import org.junit.jupiter.api.Test; + +import java.util.Collection; +import java.util.Iterator; +import java.util.concurrent.ConcurrentLinkedQueue; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * @author Mark Vollmary + */ +class CommunicationTest { + + private static final String FAST = "fast"; + private static final String SLOW = "slow"; + + @Test + void chunkSizeSmall() { + final ArangoDB arangoDB = new ArangoDB.Builder().chunksize(20).build(); + final ArangoDBVersion version = arangoDB.getVersion(); + assertThat(version).isNotNull(); + } + + @Test + void multiThread() throws Exception { + final ArangoDB arangoDB = new ArangoDB.Builder().build(); + arangoDB.getUsers(); // authentication and active-failover connection redirect to master + + final Collection result = new ConcurrentLinkedQueue<>(); + final Thread fast = new Thread(() -> { + arangoDB.db().query("return sleep(0.1)", null, null, null); + result.add(FAST); + }); + final Thread slow = new Thread(() -> { + arangoDB.db().query("return sleep(0.5)", null, null, null); + result.add(SLOW); + }); + slow.start(); + fast.start(); + + slow.join(); + fast.join(); + + assertThat(result.size()).isEqualTo(2); + final Iterator iterator = result.iterator(); + assertThat(iterator.next()).isEqualTo(FAST); + assertThat(iterator.next()).isEqualTo(SLOW); + } + + @Test + void multiThreadSameDatabases() throws Exception { + final ArangoDB arangoDB = new ArangoDB.Builder().build(); + arangoDB.getUsers(); // authentication and active-failover connection redirect to master + + final ArangoDatabase db = arangoDB.db(); + + final Collection result = new ConcurrentLinkedQueue<>(); + final Thread t1 = new Thread(() -> { + db.query("return sleep(0.1)", null, null, null); + result.add("1"); + }); + final Thread t2 = new Thread(() -> { + db.query("return sleep(0.1)", null, null, null); + result.add("1"); + }); + t2.start(); + t1.start(); + t2.join(); + t1.join(); + assertThat(result.size()).isEqualTo(2); + } + + @Test + void minOneConnection() { + final ArangoDB arangoDB = new ArangoDB.Builder().maxConnections(0).build(); + final ArangoDBVersion version = arangoDB.getVersion(); + assertThat(version).isNotNull(); + } + + @Test + void defaultMaxConnection() { + final ArangoDB arangoDB = new ArangoDB.Builder().maxConnections(null).build(); + final ArangoDBVersion version = arangoDB.getVersion(); + assertThat(version).isNotNull(); + } +} diff --git a/src/test/java/com/arangodb/mapping/annotations/AnnotatedEntity.java b/driver/src/test/java/com/arangodb/mapping/annotations/AnnotatedEntity.java similarity index 100% rename from src/test/java/com/arangodb/mapping/annotations/AnnotatedEntity.java rename to driver/src/test/java/com/arangodb/mapping/annotations/AnnotatedEntity.java diff --git a/src/test/java/com/arangodb/mapping/annotations/ArangoAnnotationsTest.java b/driver/src/test/java/com/arangodb/mapping/annotations/ArangoAnnotationsTest.java similarity index 100% rename from src/test/java/com/arangodb/mapping/annotations/ArangoAnnotationsTest.java rename to driver/src/test/java/com/arangodb/mapping/annotations/ArangoAnnotationsTest.java diff --git a/src/test/java/com/arangodb/serde/CustomSerdeTest.java b/driver/src/test/java/com/arangodb/serde/CustomSerdeTest.java similarity index 100% rename from src/test/java/com/arangodb/serde/CustomSerdeTest.java rename to driver/src/test/java/com/arangodb/serde/CustomSerdeTest.java diff --git a/src/test/java/com/arangodb/serde/CustomTypeHintTest.java b/driver/src/test/java/com/arangodb/serde/CustomTypeHintTest.java similarity index 100% rename from src/test/java/com/arangodb/serde/CustomTypeHintTest.java rename to driver/src/test/java/com/arangodb/serde/CustomTypeHintTest.java diff --git a/src/test/java/com/arangodb/serde/JsonbSerde.java b/driver/src/test/java/com/arangodb/serde/JsonbSerde.java similarity index 100% rename from src/test/java/com/arangodb/serde/JsonbSerde.java rename to driver/src/test/java/com/arangodb/serde/JsonbSerde.java diff --git a/src/test/java/com/arangodb/serde/JsonbSerdeImpl.java b/driver/src/test/java/com/arangodb/serde/JsonbSerdeImpl.java similarity index 100% rename from src/test/java/com/arangodb/serde/JsonbSerdeImpl.java rename to driver/src/test/java/com/arangodb/serde/JsonbSerdeImpl.java diff --git a/src/test/java/com/arangodb/serde/SerdeTest.java b/driver/src/test/java/com/arangodb/serde/SerdeTest.java similarity index 100% rename from src/test/java/com/arangodb/serde/SerdeTest.java rename to driver/src/test/java/com/arangodb/serde/SerdeTest.java diff --git a/src/test/java/com/arangodb/util/MapBuilder.java b/driver/src/test/java/com/arangodb/util/MapBuilder.java similarity index 100% rename from src/test/java/com/arangodb/util/MapBuilder.java rename to driver/src/test/java/com/arangodb/util/MapBuilder.java diff --git a/src/test/java/com/arangodb/util/MapBuilderTest.java b/driver/src/test/java/com/arangodb/util/MapBuilderTest.java similarity index 96% rename from src/test/java/com/arangodb/util/MapBuilderTest.java rename to driver/src/test/java/com/arangodb/util/MapBuilderTest.java index 53633d646..0496a685a 100644 --- a/src/test/java/com/arangodb/util/MapBuilderTest.java +++ b/driver/src/test/java/com/arangodb/util/MapBuilderTest.java @@ -1,43 +1,43 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.util; - - -import org.junit.jupiter.api.Test; - -import java.util.Map; - -import static org.assertj.core.api.Assertions.assertThat; - - -/** - * @author Mark Vollmary - */ -class MapBuilderTest { - - @Test - void build() { - final Map map = new MapBuilder().put("foo", "bar").get(); - assertThat(map).hasSize(1); - assertThat(map.get("foo")).isNotNull(); - assertThat(map).containsEntry("foo", "bar"); - } -} +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed 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. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.util; + + +import org.junit.jupiter.api.Test; + +import java.util.Map; + +import static org.assertj.core.api.Assertions.assertThat; + + +/** + * @author Mark Vollmary + */ +class MapBuilderTest { + + @Test + void build() { + final Map map = new MapBuilder().put("foo", "bar").get(); + assertThat(map).hasSize(1); + assertThat(map.get("foo")).isNotNull(); + assertThat(map).containsEntry("foo", "bar"); + } +} diff --git a/src/test/java/com/arangodb/util/TestUtils.java b/driver/src/test/java/com/arangodb/util/TestUtils.java similarity index 100% rename from src/test/java/com/arangodb/util/TestUtils.java rename to driver/src/test/java/com/arangodb/util/TestUtils.java diff --git a/src/test/java/com/arangodb/util/UnicodeUtilsTest.java b/driver/src/test/java/com/arangodb/util/UnicodeUtilsTest.java similarity index 100% rename from src/test/java/com/arangodb/util/UnicodeUtilsTest.java rename to driver/src/test/java/com/arangodb/util/UnicodeUtilsTest.java diff --git a/src/test/java/helper/NativeImageHelper.java b/driver/src/test/java/helper/NativeImageHelper.java similarity index 100% rename from src/test/java/helper/NativeImageHelper.java rename to driver/src/test/java/helper/NativeImageHelper.java diff --git a/src/test/java/perf/Benchmark.java b/driver/src/test/java/perf/Benchmark.java similarity index 100% rename from src/test/java/perf/Benchmark.java rename to driver/src/test/java/perf/Benchmark.java diff --git a/src/test/java/perf/SimpleSyncPerfTest.java b/driver/src/test/java/perf/SimpleSyncPerfTest.java similarity index 100% rename from src/test/java/perf/SimpleSyncPerfTest.java rename to driver/src/test/java/perf/SimpleSyncPerfTest.java diff --git a/src/test/java/perf/SyncBenchmarkTest.java b/driver/src/test/java/perf/SyncBenchmarkTest.java similarity index 100% rename from src/test/java/perf/SyncBenchmarkTest.java rename to driver/src/test/java/perf/SyncBenchmarkTest.java diff --git a/src/test/resources/META-INF/native-image/native-image.properties b/driver/src/test/resources/META-INF/native-image/native-image.properties similarity index 100% rename from src/test/resources/META-INF/native-image/native-image.properties rename to driver/src/test/resources/META-INF/native-image/native-image.properties diff --git a/src/test/resources/META-INF/native-image/reflect-config.json b/driver/src/test/resources/META-INF/native-image/reflect-config.json similarity index 100% rename from src/test/resources/META-INF/native-image/reflect-config.json rename to driver/src/test/resources/META-INF/native-image/reflect-config.json diff --git a/src/test/resources/META-INF/native-image/resource-config.json b/driver/src/test/resources/META-INF/native-image/resource-config.json similarity index 100% rename from src/test/resources/META-INF/native-image/resource-config.json rename to driver/src/test/resources/META-INF/native-image/resource-config.json diff --git a/src/test/resources/META-INF/native-image/serialization-config.json b/driver/src/test/resources/META-INF/native-image/serialization-config.json similarity index 100% rename from src/test/resources/META-INF/native-image/serialization-config.json rename to driver/src/test/resources/META-INF/native-image/serialization-config.json diff --git a/src/test/resources/arangodb-bad.properties b/driver/src/test/resources/arangodb-bad.properties similarity index 100% rename from src/test/resources/arangodb-bad.properties rename to driver/src/test/resources/arangodb-bad.properties diff --git a/src/test/resources/arangodb.properties b/driver/src/test/resources/arangodb.properties similarity index 100% rename from src/test/resources/arangodb.properties rename to driver/src/test/resources/arangodb.properties diff --git a/src/test/resources/example.truststore b/driver/src/test/resources/example.truststore similarity index 100% rename from src/test/resources/example.truststore rename to driver/src/test/resources/example.truststore diff --git a/src/test/resources/logback-test.xml b/driver/src/test/resources/logback-test.xml similarity index 100% rename from src/test/resources/logback-test.xml rename to driver/src/test/resources/logback-test.xml diff --git a/formatter.xml b/formatter.xml deleted file mode 100644 index 0485cd4ba..000000000 --- a/formatter.xml +++ /dev/null @@ -1,419 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/pom.xml b/pom.xml index 3cb091dab..16ae8611b 100644 --- a/pom.xml +++ b/pom.xml @@ -4,14 +4,15 @@ 4.0.0 com.arangodb - arangodb-java-driver + arangodb-java-driver-parent 7.0.0-SNAPSHOT 2016 - jar + + driver + + pom - arangodb-java-driver - ArangoDB Java Driver - http://maven.apache.org + arangodb-java-driver-parent @@ -23,10 +24,6 @@ UTF-8 - 2.13.3 - arangodb-1 - https://sonarcloud.io - false @@ -41,86 +38,6 @@ - - - ossrh - https://oss.sonatype.org/content/repositories/snapshots - - - ossrh - https://oss.sonatype.org/service/local/staging/deploy/maven2/ - - - - - - doclint-java8-disable - - [1.8,) - - - none - - - - no-graalvm - - 1.8 - - - - - org.apache.maven.plugins - maven-compiler-plugin - - - com/arangodb/util/UnicodeUtilsTest.java - - - - - - - - native - - - - org.apache.maven.plugins - maven-surefire-plugin - 3.0.0-M5 - - - org.graalvm.buildtools - native-maven-plugin - 0.9.16 - true - - - test-native - - generateTestResourceConfig - test - - test - - - - true - false - - --no-fallback - - - ${SslTest} - - - - - - - - @@ -144,297 +61,9 @@ - - org.sonatype.plugins - nexus-staging-maven-plugin - 1.6.13 - true - - ossrh - https://oss.sonatype.org/ - 84aff6e87e214c - false - - - - org.apache.maven.plugins - maven-compiler-plugin - 3.10.1 - - - -Xlint:unchecked - -Xlint:deprecation - - true - 1.8 - 1.8 - - - - org.apache.maven.plugins - maven-resources-plugin - 3.3.0 - - UTF-8 - - - - org.apache.maven.plugins - maven-source-plugin - 3.2.1 - - - - jar - - - - - - org.apache.maven.plugins - maven-javadoc-plugin - 3.4.0 - - - attach-javadocs - - jar - - - com.arangodb.internal - - - - - - org.apache.maven.plugins - maven-surefire-plugin - 3.0.0-M7 - - - **/*Test.java - **/*Example.java - - - - - org.apache.maven.plugins - maven-deploy-plugin - 3.0.0 - - 10 - - - - org.apache.maven.plugins - maven-gpg-plugin - 3.0.1 - - - sign-artifacts - verify - - sign - - - - - - org.codehaus.mojo - flatten-maven-plugin - 1.2.7 - - oss - - - - - flatten - process-resources - - flatten - - - - - flatten.clean - clean - - clean - - - - - - org.jacoco - jacoco-maven-plugin - 0.8.8 - - - - prepare-agent - - - - report - prepare-package - - report - - - - - - com.github.spotbugs - spotbugs-maven-plugin - 4.7.1.1 - - spotbugs/spotbugs-exclude.xml - - - - compile - - check - - - - - - com.github.spotbugs - spotbugs - 4.7.1 - - - - - - org.slf4j - slf4j-api - 1.7.36 - - - com.fasterxml.jackson.core - jackson-databind - - - com.fasterxml.jackson.core - jackson-core - - - com.fasterxml.jackson.core - jackson-annotations - - - io.vertx - vertx-web-client - - - com.arangodb - jackson-dataformat-velocypack - 3.0.1 - true - - - jakarta.json.bind - jakarta.json.bind-api - 2.0.0 - - - com.google.code.findbugs - jsr305 - 3.0.2 - provided - - - ch.qos.logback - logback-classic - 1.2.11 - test - - - org.junit.platform - junit-platform-launcher - test - - - org.junit.jupiter - junit-jupiter-engine - test - - - org.junit.jupiter - junit-jupiter-params - test - - - org.assertj - assertj-core - 3.23.1 - test - - - org.reflections - reflections - 0.10.2 - test - - - org.graalvm.sdk - graal-sdk - 22.2.0 - test - - - org.eclipse - yasson - 2.0.4 - test - - - - - - - com.fasterxml.jackson - jackson-bom - ${adb.jackson.version} - import - pom - - - io.vertx - vertx-stack-depchain - 4.3.4 - pom - import - - - io.netty - netty-bom - 4.1.82.Final - pom - import - - - org.junit - junit-bom - 5.9.1 - pom - import - - - - - - https://github.com/arangodb/arangodb-java-driver - scm:git:git://github.com/arangodb/arangodb-java-driver.git - scm:git:git://github.com/arangodb/arangodb-java-driver.git - - ArangoDB GmbH https://www.arangodb.com From 84e0cf16e03f3eb2768cf8ffa9a8e31e9d0ab7ac Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Thu, 3 Nov 2022 16:18:13 +0100 Subject: [PATCH 172/254] fixed jwt tests --- .github/workflows/maven.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index 8013333d3..3d308ab67 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -163,7 +163,7 @@ jobs: echo "Active endpoint: $ENDPOINT" JWT=$(curl "http://$ENDPOINT/_db/_system/_open/auth" -X POST -d '{"username":"root","password":"test"}' | jq ".jwt" | xargs) echo "Setting JWT: $JWT" - sed -i "/arangodb.password/c\arangodb.jwt=$JWT" src/test/resources/arangodb.properties + sed -i "/arangodb.password/c\arangodb.jwt=$JWT" driver/src/test/resources/arangodb.properties - name: Info run: mvn -version - name: Test From 93415780cf18ffdc50a845ef9217f05302c57304 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Fri, 4 Nov 2022 14:05:38 +0100 Subject: [PATCH 173/254] ConfigPropertiesProvider API (#466) --- .gitignore | 18 +- .../src/main/java/com/arangodb/ArangoDB.java | 30 +-- .../com/arangodb/async/ArangoDBAsync.java | 13 +- .../config/ConfigPropertiesProvider.java | 25 +++ .../arangodb/config/ConfigPropertyKey.java | 31 +++ .../com/arangodb/internal/ArangoDefaults.java | 2 +- .../internal/InternalArangoDBBuilder.java | 189 ++++++------------ .../config/FileConfigPropertiesProvider.java | 52 +++++ .../test/java/com/arangodb/ArangoDBTest.java | 20 +- .../test/java/com/arangodb/BaseJunit5.java | 13 +- .../java/com/arangodb/ConcurrencyTests.java | 5 +- .../test/java/com/arangodb/JwtAuthTest.java | 7 +- .../test/java/com/arangodb/ParallelTest.java | 2 + .../java/com/arangodb/async/ArangoDBTest.java | 21 +- .../java/com/arangodb/async/BaseTest.java | 5 +- .../com/arangodb/async/ConcurrencyTests.java | 5 +- .../java/com/arangodb/async/JwtAuthTest.java | 7 +- .../debug/ConsolidationIntervalMsecTest.java | 2 + .../arangodb/async/example/ExampleBase.java | 5 +- .../graph/AQLActorsAndMoviesExampleTest.java | 5 +- .../async/example/graph/BaseGraphTest.java | 5 +- .../arangodb/async/serde/CustomSerdeTest.java | 5 +- .../com/arangodb/example/ExampleBase.java | 5 +- .../graph/AQLActorsAndMoviesExampleTest.java | 5 +- .../arangodb/example/graph/BaseGraphTest.java | 5 +- .../velocystream/CommunicationTest.java | 21 +- .../com/arangodb/serde/CustomSerdeTest.java | 2 + .../arangodb/serde/CustomTypeHintTest.java | 5 +- 28 files changed, 306 insertions(+), 204 deletions(-) create mode 100644 driver/src/main/java/com/arangodb/config/ConfigPropertiesProvider.java create mode 100644 driver/src/main/java/com/arangodb/config/ConfigPropertyKey.java create mode 100644 driver/src/main/java/com/arangodb/internal/config/FileConfigPropertiesProvider.java diff --git a/.gitignore b/.gitignore index 7cdb4ecd7..5f384eeab 100644 --- a/.gitignore +++ b/.gitignore @@ -1,14 +1,14 @@ -/.classpath -/.project -/.settings -**/target -/.idea -/*.iml -/bin +.classpath +.project +.settings +target +.idea +*.iml +.directory /docker/jwtHeader /docker/jwtSecret - /docker/data -**/test-results-native + +test-results-native .flattened-pom.xml diff --git a/driver/src/main/java/com/arangodb/ArangoDB.java b/driver/src/main/java/com/arangodb/ArangoDB.java index d7de287d3..c001e823e 100644 --- a/driver/src/main/java/com/arangodb/ArangoDB.java +++ b/driver/src/main/java/com/arangodb/ArangoDB.java @@ -20,6 +20,8 @@ package com.arangodb; +import com.arangodb.config.ConfigPropertiesProvider; +import com.arangodb.config.ConfigPropertyKey; import com.arangodb.entity.*; import com.arangodb.internal.ArangoDBImpl; import com.arangodb.internal.ArangoDefaults; @@ -39,10 +41,8 @@ import javax.annotation.concurrent.ThreadSafe; import javax.net.ssl.SSLContext; -import java.io.InputStream; import java.util.Collection; import java.util.Locale; -import java.util.Properties; /** * Central access point for applications to communicate with an ArangoDB server. @@ -333,25 +333,21 @@ public interface ArangoDB extends ArangoSerdeAccessor { * @author Mark Vollmary */ class Builder extends InternalArangoDBBuilder { - private static final String PROPERTY_KEY_PROTOCOL = "arangodb.protocol"; - protected Protocol protocol; + protected Protocol protocol = ArangoDefaults.DEFAULT_NETWORK_PROTOCOL; public Builder() { super(); } - private static Protocol loadProtocol(final Properties properties, final Protocol currentValue) { - return Protocol.valueOf( - getProperty(properties, PROPERTY_KEY_PROTOCOL, currentValue, - ArangoDefaults.DEFAULT_NETWORK_PROTOCOL) - .toUpperCase(Locale.ROOT)); + private static Protocol loadProtocol(final ConfigPropertiesProvider properties, final Protocol currentValue) { + return Protocol.valueOf(getProperty(properties, ConfigPropertyKey.PROTOCOL, currentValue).toUpperCase(Locale.ROOT)); } - @Override - protected void loadProperties(final Properties properties) { - super.loadProperties(properties); + public Builder loadProperties(final ConfigPropertiesProvider properties) { + doLoadProperties(properties); protocol = loadProtocol(properties, protocol); + return this; } public Builder useProtocol(final Protocol protocol) { @@ -359,12 +355,6 @@ public Builder useProtocol(final Protocol protocol) { return this; } - @Override - public Builder loadProperties(final InputStream in) { - super.loadProperties(in); - return this; - } - /** * Adds a host to connect to. Multiple hosts can be added to provide fallbacks. * @@ -461,7 +451,7 @@ public Builder verifyHost(final Boolean verifyHost) { * @return {@link ArangoDB.Builder} */ public Builder chunksize(final Integer chunksize) { - setChunksize(chunksize); + setChunkSize(chunksize); return this; } @@ -617,7 +607,7 @@ public ArangoDB build() { return new ArangoDBImpl( new VstCommunicationSync.Builder(hostHandler).timeout(timeout).user(user).password(password) - .jwt(jwt).useSsl(useSsl).sslContext(sslContext).chunksize(chunksize) + .jwt(jwt).useSsl(useSsl).sslContext(sslContext).chunksize(chunkSize) .maxConnections(maxConnections).connectionTtl(connectionTtl), new HttpCommunication.Builder().hostHandler(hostHandler), serde, diff --git a/driver/src/main/java/com/arangodb/async/ArangoDBAsync.java b/driver/src/main/java/com/arangodb/async/ArangoDBAsync.java index adea1eee3..07bdc3861 100644 --- a/driver/src/main/java/com/arangodb/async/ArangoDBAsync.java +++ b/driver/src/main/java/com/arangodb/async/ArangoDBAsync.java @@ -24,6 +24,7 @@ import com.arangodb.async.internal.ArangoDBAsyncImpl; import com.arangodb.async.internal.velocystream.VstCommunicationAsync; import com.arangodb.async.internal.velocystream.VstConnectionFactoryAsync; +import com.arangodb.config.ConfigPropertiesProvider; import com.arangodb.entity.*; import com.arangodb.internal.ArangoDefaults; import com.arangodb.internal.InternalArangoDBBuilder; @@ -42,7 +43,6 @@ import javax.annotation.concurrent.ThreadSafe; import javax.net.ssl.SSLContext; -import java.io.InputStream; import java.util.Collection; import java.util.concurrent.CompletableFuture; @@ -308,9 +308,8 @@ public Builder() { super(); } - @Override - public Builder loadProperties(final InputStream in) { - super.loadProperties(in); + public Builder loadProperties(final ConfigPropertiesProvider config) { + super.doLoadProperties(config); return this; } @@ -399,7 +398,7 @@ public Builder sslContext(final SSLContext sslContext) { * @return {@link ArangoDBAsync.Builder} */ public Builder chunksize(final Integer chunksize) { - setChunksize(chunksize); + setChunkSize(chunksize); return this; } @@ -535,13 +534,13 @@ public ArangoDBAsync build() { private VstCommunicationAsync.Builder asyncBuilder(final HostHandler hostHandler) { return new VstCommunicationAsync.Builder(hostHandler).timeout(timeout).user(user).password(password) - .jwt(jwt).useSsl(useSsl).sslContext(sslContext).chunksize(chunksize).maxConnections(maxConnections) + .jwt(jwt).useSsl(useSsl).sslContext(sslContext).chunksize(chunkSize).maxConnections(maxConnections) .connectionTtl(connectionTtl); } private VstCommunicationSync.Builder syncBuilder(final HostHandler hostHandler) { return new VstCommunicationSync.Builder(hostHandler).timeout(timeout).user(user).password(password) - .jwt(jwt).useSsl(useSsl).sslContext(sslContext).chunksize(chunksize).maxConnections(maxConnections) + .jwt(jwt).useSsl(useSsl).sslContext(sslContext).chunksize(chunkSize).maxConnections(maxConnections) .connectionTtl(connectionTtl); } diff --git a/driver/src/main/java/com/arangodb/config/ConfigPropertiesProvider.java b/driver/src/main/java/com/arangodb/config/ConfigPropertiesProvider.java new file mode 100644 index 000000000..2e3f6af0c --- /dev/null +++ b/driver/src/main/java/com/arangodb/config/ConfigPropertiesProvider.java @@ -0,0 +1,25 @@ +package com.arangodb.config; + + +public interface ConfigPropertiesProvider { + + /** + * @param key the property key + * @return the configuration property with the specified key if present, {@code null} otherwise + */ + String getProperty(String key); + + default String getProperty(ConfigPropertyKey key) { + return getProperty(key.getValue()); + } + + default String getProperty(String key, String defaultValue) { + String p = getProperty(key); + return p != null ? p : defaultValue; + } + + default String getProperty(ConfigPropertyKey key, String defaultValue) { + String p = getProperty(key); + return p != null ? p : defaultValue; + } +} diff --git a/driver/src/main/java/com/arangodb/config/ConfigPropertyKey.java b/driver/src/main/java/com/arangodb/config/ConfigPropertyKey.java new file mode 100644 index 000000000..db82cd09b --- /dev/null +++ b/driver/src/main/java/com/arangodb/config/ConfigPropertyKey.java @@ -0,0 +1,31 @@ +package com.arangodb.config; + +public enum ConfigPropertyKey { + HOSTS("hosts"), + TIMEOUT("timeout"), + USER("user"), + PASSWORD("password"), + JWT("jwt"), + USE_SSL("ssl"), + VERIFY_HOST("verifyHost"), + VST_CHUNK_SIZE("chunkSize"), + MAX_CONNECTIONS("connections.max"), + CONNECTION_TTL("connections.ttl"), + KEEP_ALIVE_INTERVAL("connections.keepAlive.interval"), + ACQUIRE_HOST_LIST("acquireHostList"), + ACQUIRE_HOST_LIST_INTERVAL("acquireHostList.interval"), + LOAD_BALANCING_STRATEGY("loadBalancingStrategy"), + RESPONSE_QUEUE_TIME_SAMPLES("metrics.responseQueueTimeSamples"), + PROTOCOL("protocol"); + + private final String value; + + ConfigPropertyKey(String value) { + this.value = value; + } + + public String getValue() { + return value; + } + +} diff --git a/driver/src/main/java/com/arangodb/internal/ArangoDefaults.java b/driver/src/main/java/com/arangodb/internal/ArangoDefaults.java index ac5e3c2de..ce452eed0 100644 --- a/driver/src/main/java/com/arangodb/internal/ArangoDefaults.java +++ b/driver/src/main/java/com/arangodb/internal/ArangoDefaults.java @@ -38,7 +38,7 @@ public final class ArangoDefaults { public static final int CHUNK_MAX_HEADER_SIZE = CHUNK_MIN_HEADER_SIZE + LONG_BYTES; public static final int CHUNK_DEFAULT_CONTENT_SIZE = 30000; public static final int MAX_CONNECTIONS_VST_DEFAULT = 1; - public static final Integer CONNECTION_TTL_VST_DEFAULT = null; + public static final Long CONNECTION_TTL_VST_DEFAULT = null; public static final int MAX_CONNECTIONS_HTTP_DEFAULT = 20; public static final int MAX_CONNECTIONS_HTTP2_DEFAULT = 1; public static final Protocol DEFAULT_NETWORK_PROTOCOL = Protocol.HTTP2_JSON; diff --git a/driver/src/main/java/com/arangodb/internal/InternalArangoDBBuilder.java b/driver/src/main/java/com/arangodb/internal/InternalArangoDBBuilder.java index 78ab6a7f1..88264b25b 100644 --- a/driver/src/main/java/com/arangodb/internal/InternalArangoDBBuilder.java +++ b/driver/src/main/java/com/arangodb/internal/InternalArangoDBBuilder.java @@ -20,8 +20,9 @@ package com.arangodb.internal; -import com.arangodb.ArangoDB; import com.arangodb.ArangoDBException; +import com.arangodb.config.ConfigPropertiesProvider; +import com.arangodb.config.ConfigPropertyKey; import com.arangodb.entity.LoadBalancingStrategy; import com.arangodb.internal.net.*; import com.arangodb.internal.util.HostUtils; @@ -30,67 +31,38 @@ import org.slf4j.LoggerFactory; import javax.net.ssl.SSLContext; -import java.io.IOException; -import java.io.InputStream; -import java.util.*; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Locale; /** * @author Mark Vollmary */ public abstract class InternalArangoDBBuilder { - private static final Logger LOG = LoggerFactory.getLogger(InternalArangoDBBuilder.class); - private static final String PROPERTY_KEY_HOSTS = "arangodb.hosts"; - private static final String PROPERTY_KEY_TIMEOUT = "arangodb.timeout"; - private static final String PROPERTY_KEY_USER = "arangodb.user"; - private static final String PROPERTY_KEY_PASSWORD = "arangodb.password"; - private static final String PROPERTY_KEY_JWT = "arangodb.jwt"; - private static final String PROPERTY_KEY_USE_SSL = "arangodb.usessl"; - private static final String PROPERTY_KEY_VERIFY_HOST = "arangodb.verifyHost"; - private static final String PROPERTY_KEY_V_STREAM_CHUNK_CONTENT_SIZE = "arangodb.chunksize"; - private static final String PROPERTY_KEY_MAX_CONNECTIONS = "arangodb.connections.max"; - private static final String PROPERTY_KEY_CONNECTION_TTL = "arangodb.connections.ttl"; - private static final String PROPERTY_KEEP_ALIVE_INTERVAL = "arangodb.connections.keepAlive.interval"; - private static final String PROPERTY_KEY_ACQUIRE_HOST_LIST = "arangodb.acquireHostList"; - private static final String PROPERTY_KEY_ACQUIRE_HOST_LIST_INTERVAL = "arangodb.acquireHostList.interval"; - private static final String PROPERTY_KEY_LOAD_BALANCING_STRATEGY = "arangodb.loadBalancingStrategy"; - private static final String PROPERTY_KEY_RESPONSE_QUEUE_TIME_SAMPLES = "arangodb.metrics.responseQueueTimeSamples"; - private static final String DEFAULT_PROPERTY_FILE = "/arangodb.properties"; - - protected final List hosts; - protected Integer timeout; - protected String user; - protected String password; - protected String jwt; - protected Boolean useSsl; - protected SSLContext sslContext; - protected Boolean verifyHost; - protected Integer chunksize; - protected Integer maxConnections; - protected Long connectionTtl; - protected Integer keepAliveInterval; - protected Boolean acquireHostList; - protected Integer acquireHostListInterval; - protected LoadBalancingStrategy loadBalancingStrategy; + protected final List hosts = new ArrayList<>(); + protected Integer timeout = ArangoDefaults.DEFAULT_TIMEOUT; + protected String user = ArangoDefaults.DEFAULT_USER; + protected String password = null; + protected String jwt = null; + protected Boolean useSsl = ArangoDefaults.DEFAULT_USE_SSL; + protected SSLContext sslContext = null; + protected Boolean verifyHost = ArangoDefaults.DEFAULT_VERIFY_HOST; + protected Integer chunkSize = ArangoDefaults.CHUNK_DEFAULT_CONTENT_SIZE; + protected Integer maxConnections = null; + protected Long connectionTtl = ArangoDefaults.CONNECTION_TTL_VST_DEFAULT; + protected Integer keepAliveInterval = null; + protected Boolean acquireHostList = ArangoDefaults.DEFAULT_ACQUIRE_HOST_LIST; + protected Integer acquireHostListInterval = ArangoDefaults.DEFAULT_ACQUIRE_HOST_LIST_INTERVAL; + protected LoadBalancingStrategy loadBalancingStrategy = ArangoDefaults.DEFAULT_LOAD_BALANCING_STRATEGY; protected ArangoSerde customSerializer; - protected Integer responseQueueTimeSamples; - - - protected InternalArangoDBBuilder() { - super(); - hosts = new ArrayList<>(); - user = ArangoDefaults.DEFAULT_USER; - try (InputStream is = ArangoDB.class.getResourceAsStream(DEFAULT_PROPERTY_FILE)) { - loadProperties(is); - } catch (IOException e) { - throw new ArangoDBException(e); - } - } + protected Integer responseQueueTimeSamples = ArangoDefaults.DEFAULT_RESPONSE_QUEUE_TIME_SAMPLES; - private static void loadHosts(final Properties properties, final Collection hosts) { - final String hostsProp = properties.getProperty(PROPERTY_KEY_HOSTS); + private static void loadHosts(final ConfigPropertiesProvider properties, final Collection hosts) { + final String hostsProp = properties.getProperty(ConfigPropertyKey.HOSTS); if (hostsProp != null) { final String[] hostsSplit = hostsProp.split(","); for (final String host : hostsSplit) { @@ -106,122 +78,81 @@ private static void loadHosts(final Properties properties, final Collection String getProperty( - final Properties properties, - final String key, - final T currentValue, - final T defaultValue) { - - String overrideDefaultValue = null; - - if (currentValue != null) { - overrideDefaultValue = currentValue.toString(); - } else if (defaultValue != null) { - overrideDefaultValue = defaultValue.toString(); - } - - return properties.getProperty(key, overrideDefaultValue); - } - - public InternalArangoDBBuilder loadProperties(final InputStream in) { - - final Properties properties = new Properties(); - - if (in != null) { - - try { - properties.load(in); - } catch (final IOException e) { - throw new ArangoDBException(e); - } - } - - loadProperties(properties); - - return this; - + protected static String getProperty(ConfigPropertiesProvider props, ConfigPropertyKey key, Object currentValue) { + String defaultValue = currentValue == null ? null : currentValue.toString(); + return props.getProperty(key, defaultValue); } - protected void loadProperties(final Properties properties) { - loadHosts(properties, this.hosts); + protected void doLoadProperties(final ConfigPropertiesProvider properties) { + loadHosts(properties, hosts); timeout = loadTimeout(properties, timeout); user = loadUser(properties, user); password = loadPassword(properties, password); jwt = loadJwt(properties, jwt); useSsl = loadUseSsl(properties, useSsl); verifyHost = loadVerifyHost(properties, verifyHost); - chunksize = loadChunkSize(properties, chunksize); + chunkSize = loadChunkSize(properties, chunkSize); maxConnections = loadMaxConnections(properties, maxConnections); connectionTtl = loadConnectionTtl(properties, connectionTtl); keepAliveInterval = loadKeepAliveInterval(properties, keepAliveInterval); @@ -263,8 +194,8 @@ protected void setVerifyHost(final Boolean verifyHost) { this.verifyHost = verifyHost; } - protected void setChunksize(final Integer chunksize) { - this.chunksize = chunksize; + protected void setChunkSize(final Integer chunkSize) { + this.chunkSize = chunkSize; } protected void setMaxConnections(final Integer maxConnections) { diff --git a/driver/src/main/java/com/arangodb/internal/config/FileConfigPropertiesProvider.java b/driver/src/main/java/com/arangodb/internal/config/FileConfigPropertiesProvider.java new file mode 100644 index 000000000..99763ca39 --- /dev/null +++ b/driver/src/main/java/com/arangodb/internal/config/FileConfigPropertiesProvider.java @@ -0,0 +1,52 @@ +package com.arangodb.internal.config; + +import com.arangodb.ArangoDBException; +import com.arangodb.config.ConfigPropertiesProvider; + +import java.io.IOException; +import java.io.InputStream; +import java.util.Properties; + +/** + * ConfigProvider that reads configuration entries from local file. Properties path prefix can be configured, so that it + * is possible to distinguish configurations for multiple driver instances in the same file. + */ +public class FileConfigPropertiesProvider implements ConfigPropertiesProvider { + private static final String DEFAULT_PREFIX = "arangodb"; + private static final String DEFAULT_PROPERTY_FILE = "/arangodb.properties"; + private final Properties properties; + private final String prefix; + + public FileConfigPropertiesProvider() { + this(DEFAULT_PREFIX, DEFAULT_PROPERTY_FILE); + } + + public FileConfigPropertiesProvider(String prefix, String fileName) { + this.prefix = initPrefix(prefix); + properties = initProperties(fileName); + } + + private String initPrefix(String p) { + if (p == null) { + return ""; + } else { + return p + "."; + } + } + + private Properties initProperties(String fileName) { + Properties p = new Properties(); + try (InputStream is = FileConfigPropertiesProvider.class.getResourceAsStream(fileName)) { + p.load(is); + } catch (IOException e) { + throw new ArangoDBException(e); + } + return p; + } + + @Override + public String getProperty(String key) { + return properties.getProperty(prefix + key); + } +} + diff --git a/driver/src/test/java/com/arangodb/ArangoDBTest.java b/driver/src/test/java/com/arangodb/ArangoDBTest.java index 8e3336a02..d54647b58 100644 --- a/driver/src/test/java/com/arangodb/ArangoDBTest.java +++ b/driver/src/test/java/com/arangodb/ArangoDBTest.java @@ -21,6 +21,7 @@ package com.arangodb; import com.arangodb.entity.*; +import com.arangodb.internal.config.FileConfigPropertiesProvider; import com.arangodb.model.*; import com.arangodb.model.LogOptions.SortOrder; import com.arangodb.util.TestUtils; @@ -206,7 +207,7 @@ void createDatabaseWithUsers(ArangoDB arangoDB) throws InterruptedException { Thread.sleep(2_000); ArangoDB arangoDBTestUser = new ArangoDB.Builder() - + .loadProperties(new FileConfigPropertiesProvider()) .user("testUser") .password("testPasswd") .build(); @@ -368,7 +369,9 @@ void updateUserDefaultCollectionAccess(ArangoDB arangoDB) { @Test void authenticationFailPassword() { - final ArangoDB arangoDB = new ArangoDB.Builder().password("no").jwt(null).build(); + final ArangoDB arangoDB = new ArangoDB.Builder() + .loadProperties(new FileConfigPropertiesProvider()) + .password("no").jwt(null).build(); Throwable thrown = catchThrowable(arangoDB::getVersion); assertThat(thrown).isInstanceOf(ArangoDBException.class); assertThat(((ArangoDBException) thrown).getResponseCode()).isEqualTo(401); @@ -377,7 +380,9 @@ void authenticationFailPassword() { @ParameterizedTest(name = "{index}") @MethodSource("arangos") void authenticationFailUser() { - final ArangoDB arangoDB = new ArangoDB.Builder().user("no").jwt(null).build(); + final ArangoDB arangoDB = new ArangoDB.Builder() + .loadProperties(new FileConfigPropertiesProvider()) + .user("no").jwt(null).build(); Throwable thrown = catchThrowable(arangoDB::getVersion); assertThat(thrown).isInstanceOf(ArangoDBException.class); assertThat(((ArangoDBException) thrown).getResponseCode()).isEqualTo(401); @@ -567,7 +572,9 @@ void arangoDBException(ArangoDB arangoDB) { @ParameterizedTest(name = "{index}") @MethodSource("arangos") void fallbackHost() { - final ArangoDB arangoDB = new ArangoDB.Builder().host("not-accessible", 8529).host("127.0.0.1", 8529).build(); + final ArangoDB arangoDB = new ArangoDB.Builder() + .loadProperties(new FileConfigPropertiesProvider()) + .host("not-accessible", 8529).host("127.0.0.1", 8529).build(); final ArangoDBVersion version = arangoDB.getVersion(); assertThat(version).isNotNull(); } @@ -575,9 +582,8 @@ void fallbackHost() { @ParameterizedTest(name = "{index}") @MethodSource("arangos") void loadproperties() { - Throwable thrown = catchThrowable(() -> - new ArangoDB.Builder().loadProperties(ArangoDBTest.class.getResourceAsStream("/arangodb-bad" + - ".properties")) + Throwable thrown = catchThrowable(() -> new ArangoDB.Builder() + .loadProperties(new FileConfigPropertiesProvider("arangodb", "/arangodb-bad.properties")) ); assertThat(thrown).isInstanceOf(ArangoDBException.class); } diff --git a/driver/src/test/java/com/arangodb/BaseJunit5.java b/driver/src/test/java/com/arangodb/BaseJunit5.java index 3e3b35ca1..7e2ecc2a6 100644 --- a/driver/src/test/java/com/arangodb/BaseJunit5.java +++ b/driver/src/test/java/com/arangodb/BaseJunit5.java @@ -1,6 +1,7 @@ package com.arangodb; import com.arangodb.entity.*; +import com.arangodb.internal.config.FileConfigPropertiesProvider; import com.arangodb.model.CollectionCreateOptions; import com.arangodb.model.GraphCreateOptions; import com.arangodb.serde.JsonbSerde; @@ -19,12 +20,12 @@ class BaseJunit5 { protected static final DbName TEST_DB = DbName.of("java_driver_test_db"); private static final List adbs = Arrays.asList( - new ArangoDB.Builder().useProtocol(Protocol.VST).build(), - new ArangoDB.Builder().useProtocol(Protocol.HTTP_VPACK).build(), - new ArangoDB.Builder().useProtocol(Protocol.HTTP_JSON).build(), - new ArangoDB.Builder().useProtocol(Protocol.HTTP2_VPACK).build(), - new ArangoDB.Builder().useProtocol(Protocol.HTTP2_JSON).build(), - new ArangoDB.Builder().useProtocol(Protocol.HTTP2_JSON).serializer(JsonbSerde.create()).build() + new ArangoDB.Builder().loadProperties(new FileConfigPropertiesProvider()).useProtocol(Protocol.VST).build(), + new ArangoDB.Builder().loadProperties(new FileConfigPropertiesProvider()).useProtocol(Protocol.HTTP_VPACK).build(), + new ArangoDB.Builder().loadProperties(new FileConfigPropertiesProvider()).useProtocol(Protocol.HTTP_JSON).build(), + new ArangoDB.Builder().loadProperties(new FileConfigPropertiesProvider()).useProtocol(Protocol.HTTP2_VPACK).build(), + new ArangoDB.Builder().loadProperties(new FileConfigPropertiesProvider()).useProtocol(Protocol.HTTP2_JSON).build(), + new ArangoDB.Builder().loadProperties(new FileConfigPropertiesProvider()).useProtocol(Protocol.HTTP2_JSON).serializer(JsonbSerde.create()).build() ); protected static Stream dbsStream() { diff --git a/driver/src/test/java/com/arangodb/ConcurrencyTests.java b/driver/src/test/java/com/arangodb/ConcurrencyTests.java index 2140a0f07..1103cb6df 100644 --- a/driver/src/test/java/com/arangodb/ConcurrencyTests.java +++ b/driver/src/test/java/com/arangodb/ConcurrencyTests.java @@ -1,5 +1,6 @@ package com.arangodb; +import com.arangodb.internal.config.FileConfigPropertiesProvider; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.EnumSource; @@ -17,7 +18,9 @@ class ConcurrencyTests { @EnumSource(Protocol.class) void concurrentPendingRequests(Protocol protocol) throws ExecutionException, InterruptedException { ExecutorService es = Executors.newFixedThreadPool(10); - ArangoDB adb = new ArangoDB.Builder().useProtocol(protocol).build(); + ArangoDB adb = new ArangoDB.Builder() + .loadProperties(new FileConfigPropertiesProvider()) + .useProtocol(protocol).build(); List> futures = IntStream.range(0, 10) .mapToObj(__ -> CompletableFuture.runAsync(() -> adb.db().query("RETURN SLEEP(1)", Void.class), es)) .collect(Collectors.toList()); diff --git a/driver/src/test/java/com/arangodb/JwtAuthTest.java b/driver/src/test/java/com/arangodb/JwtAuthTest.java index 57d9f3001..c56a5fb57 100644 --- a/driver/src/test/java/com/arangodb/JwtAuthTest.java +++ b/driver/src/test/java/com/arangodb/JwtAuthTest.java @@ -1,5 +1,6 @@ package com.arangodb; +import com.arangodb.internal.config.FileConfigPropertiesProvider; import com.arangodb.serde.ArangoSerde; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Disabled; @@ -23,7 +24,9 @@ class JwtAuthTest { @BeforeAll static void init() { - ArangoDB arangoDB = new ArangoDB.Builder().build(); + ArangoDB arangoDB = new ArangoDB.Builder() + .loadProperties(new FileConfigPropertiesProvider()) + .build(); jwt = getJwt(arangoDB); arangoDB.shutdown(); } @@ -85,8 +88,8 @@ void updateJwt(Protocol protocol) { private ArangoDB.Builder getBuilder(Protocol protocol) { return new ArangoDB.Builder() + .loadProperties(new FileConfigPropertiesProvider()) .useProtocol(protocol) - .jwt(null) // unset credentials from properties file .user(null) // unset credentials from properties file .password(null); // unset credentials from properties file diff --git a/driver/src/test/java/com/arangodb/ParallelTest.java b/driver/src/test/java/com/arangodb/ParallelTest.java index 16ac5a702..2df8079bb 100644 --- a/driver/src/test/java/com/arangodb/ParallelTest.java +++ b/driver/src/test/java/com/arangodb/ParallelTest.java @@ -1,5 +1,6 @@ package com.arangodb; +import com.arangodb.internal.config.FileConfigPropertiesProvider; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.EnumSource; @@ -21,6 +22,7 @@ void connectionParallelism(Protocol protocol) throws InterruptedException { // BTS-1102: the server does not run pipelined HTTP/1.1 requests in parallel assumeTrue(protocol != Protocol.HTTP_JSON && protocol != Protocol.HTTP_VPACK); ArangoDB adb = new ArangoDB.Builder() + .loadProperties(new FileConfigPropertiesProvider()) .useProtocol(protocol) .maxConnections(1) .build(); diff --git a/driver/src/test/java/com/arangodb/async/ArangoDBTest.java b/driver/src/test/java/com/arangodb/async/ArangoDBTest.java index 51980226b..7d35cdaa9 100644 --- a/driver/src/test/java/com/arangodb/async/ArangoDBTest.java +++ b/driver/src/test/java/com/arangodb/async/ArangoDBTest.java @@ -22,6 +22,7 @@ import com.arangodb.*; import com.arangodb.entity.*; +import com.arangodb.internal.config.FileConfigPropertiesProvider; import com.arangodb.model.*; import com.arangodb.util.TestUtils; import com.arangodb.Request; @@ -54,8 +55,12 @@ class ArangoDBTest { private static final String PW = "machts der hund"; private static Boolean extendedNames; - private final ArangoDBAsync arangoDB = new ArangoDBAsync.Builder().build(); - private final ArangoDB arangoDBSync = new ArangoDB.Builder().build(); + private final ArangoDBAsync arangoDB = new ArangoDBAsync.Builder() + .loadProperties(new FileConfigPropertiesProvider()) + .build(); + private final ArangoDB arangoDBSync = new ArangoDB.Builder() + .loadProperties(new FileConfigPropertiesProvider()) + .build(); private boolean isEnterprise() { return arangoDBSync.getVersion().getLicense() == License.ENTERPRISE; @@ -413,7 +418,9 @@ void updateUserDefaultCollectionAccess() throws InterruptedException, ExecutionE @Test void authenticationFailPassword() throws InterruptedException { - final ArangoDBAsync arangoDB = new ArangoDBAsync.Builder().password("no").jwt(null).build(); + final ArangoDBAsync arangoDB = new ArangoDBAsync.Builder() + .loadProperties(new FileConfigPropertiesProvider()) + .password("no").jwt(null).build(); try { arangoDB.getVersion().get(); fail(); @@ -424,7 +431,9 @@ void authenticationFailPassword() throws InterruptedException { @Test void authenticationFailUser() throws InterruptedException { - final ArangoDBAsync arangoDB = new ArangoDBAsync.Builder().user("no").jwt(null).build(); + final ArangoDBAsync arangoDB = new ArangoDBAsync.Builder() + .loadProperties(new FileConfigPropertiesProvider()) + .user("no").jwt(null).build(); try { arangoDB.getVersion().get(); fail(); @@ -446,7 +455,9 @@ void execute() throws InterruptedException, ExecutionException { @Test void execute_acquireHostList_enabled() throws InterruptedException, ExecutionException { - final ArangoDBAsync arangoDB = new ArangoDBAsync.Builder().acquireHostList(true).build(); + final ArangoDBAsync arangoDB = new ArangoDBAsync.Builder() + .loadProperties(new FileConfigPropertiesProvider()) + .acquireHostList(true).build(); arangoDB .execute(new Request(DbName.SYSTEM, RequestType.GET, "/_api/version")) .whenComplete((response, ex) -> { diff --git a/driver/src/test/java/com/arangodb/async/BaseTest.java b/driver/src/test/java/com/arangodb/async/BaseTest.java index 520fe6aa0..354e689f8 100644 --- a/driver/src/test/java/com/arangodb/async/BaseTest.java +++ b/driver/src/test/java/com/arangodb/async/BaseTest.java @@ -24,6 +24,7 @@ import com.arangodb.entity.ArangoDBEngine; import com.arangodb.entity.License; import com.arangodb.entity.ServerRole; +import com.arangodb.internal.config.FileConfigPropertiesProvider; import com.arangodb.util.TestUtils; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; @@ -44,7 +45,9 @@ public abstract class BaseTest { @BeforeAll static void init() throws InterruptedException, ExecutionException { if (arangoDB == null) { - arangoDB = new ArangoDBAsync.Builder().build(); + arangoDB = new ArangoDBAsync.Builder() + .loadProperties(new FileConfigPropertiesProvider()) + .build(); } if (arangoDB.db(TEST_DB).exists().get()) { diff --git a/driver/src/test/java/com/arangodb/async/ConcurrencyTests.java b/driver/src/test/java/com/arangodb/async/ConcurrencyTests.java index e01a76156..504c550a7 100644 --- a/driver/src/test/java/com/arangodb/async/ConcurrencyTests.java +++ b/driver/src/test/java/com/arangodb/async/ConcurrencyTests.java @@ -1,6 +1,7 @@ package com.arangodb.async; +import com.arangodb.internal.config.FileConfigPropertiesProvider; import org.junit.jupiter.api.Test; import java.util.List; @@ -13,7 +14,9 @@ class ConcurrencyTests { @Test void concurrentPendingRequests() throws ExecutionException, InterruptedException { - ArangoDBAsync adb = new ArangoDBAsync.Builder().build(); + ArangoDBAsync adb = new ArangoDBAsync.Builder() + .loadProperties(new FileConfigPropertiesProvider()) + .build(); List>> reqs = IntStream.range(0, 10) .mapToObj(__ -> adb.db().query("RETURN SLEEP(1)", Void.class)) .collect(Collectors.toList()); diff --git a/driver/src/test/java/com/arangodb/async/JwtAuthTest.java b/driver/src/test/java/com/arangodb/async/JwtAuthTest.java index 5750e7ecf..e0c8717cc 100644 --- a/driver/src/test/java/com/arangodb/async/JwtAuthTest.java +++ b/driver/src/test/java/com/arangodb/async/JwtAuthTest.java @@ -3,6 +3,7 @@ import com.arangodb.ArangoDB; import com.arangodb.ArangoDBException; import com.arangodb.DbName; +import com.arangodb.internal.config.FileConfigPropertiesProvider; import com.arangodb.serde.ArangoSerde; import com.arangodb.Request; import com.arangodb.RequestType; @@ -26,7 +27,9 @@ class JwtAuthTest { @BeforeAll static void init() { - ArangoDB arangoDB = new ArangoDB.Builder().build(); + ArangoDB arangoDB = new ArangoDB.Builder() + .loadProperties(new FileConfigPropertiesProvider()) + .build(); jwt = getJwt(arangoDB); arangoDB.shutdown(); } @@ -96,7 +99,7 @@ void updateJwt() throws ExecutionException, InterruptedException { private ArangoDBAsync.Builder getBuilder() { return new ArangoDBAsync.Builder() - + .loadProperties(new FileConfigPropertiesProvider()) .jwt(null) // unset credentials from properties file .user(null) // unset credentials from properties file .password(null); // unset credentials from properties file diff --git a/driver/src/test/java/com/arangodb/async/debug/ConsolidationIntervalMsecTest.java b/driver/src/test/java/com/arangodb/async/debug/ConsolidationIntervalMsecTest.java index d6c8ebccd..5a3d0ddad 100644 --- a/driver/src/test/java/com/arangodb/async/debug/ConsolidationIntervalMsecTest.java +++ b/driver/src/test/java/com/arangodb/async/debug/ConsolidationIntervalMsecTest.java @@ -29,6 +29,7 @@ import com.arangodb.entity.arangosearch.ArangoSearchPropertiesEntity; import com.arangodb.entity.arangosearch.CollectionLink; import com.arangodb.entity.arangosearch.FieldLink; +import com.arangodb.internal.config.FileConfigPropertiesProvider; import com.arangodb.model.arangosearch.ArangoSearchCreateOptions; import org.junit.jupiter.api.Test; @@ -49,6 +50,7 @@ void consolidationIntervalMsec() throws ExecutionException, InterruptedException assumeTrue(isAtLeastVersion(3, 4)); ArangoDBAsync arango = new ArangoDBAsync.Builder() + .loadProperties(new FileConfigPropertiesProvider()) .user("root") .password("test") .build(); diff --git a/driver/src/test/java/com/arangodb/async/example/ExampleBase.java b/driver/src/test/java/com/arangodb/async/example/ExampleBase.java index 22ca7f7a8..9c1ce81e2 100644 --- a/driver/src/test/java/com/arangodb/async/example/ExampleBase.java +++ b/driver/src/test/java/com/arangodb/async/example/ExampleBase.java @@ -24,6 +24,7 @@ import com.arangodb.async.ArangoCollectionAsync; import com.arangodb.async.ArangoDBAsync; import com.arangodb.async.ArangoDatabaseAsync; +import com.arangodb.internal.config.FileConfigPropertiesProvider; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; @@ -42,7 +43,9 @@ public class ExampleBase { @BeforeAll static void setUp() throws InterruptedException, ExecutionException { - arangoDB = new ArangoDBAsync.Builder().build(); + arangoDB = new ArangoDBAsync.Builder() + .loadProperties(new FileConfigPropertiesProvider()) + .build(); if (arangoDB.db(DB_NAME).exists().get()) { arangoDB.db(DB_NAME).drop().get(); } diff --git a/driver/src/test/java/com/arangodb/async/example/graph/AQLActorsAndMoviesExampleTest.java b/driver/src/test/java/com/arangodb/async/example/graph/AQLActorsAndMoviesExampleTest.java index f619b5c40..259cc4451 100644 --- a/driver/src/test/java/com/arangodb/async/example/graph/AQLActorsAndMoviesExampleTest.java +++ b/driver/src/test/java/com/arangodb/async/example/graph/AQLActorsAndMoviesExampleTest.java @@ -29,6 +29,7 @@ import com.arangodb.entity.BaseEdgeDocument; import com.arangodb.entity.CollectionType; import com.arangodb.entity.DocumentCreateEntity; +import com.arangodb.internal.config.FileConfigPropertiesProvider; import com.arangodb.model.CollectionCreateOptions; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; @@ -57,7 +58,9 @@ class AQLActorsAndMoviesExampleTest { @BeforeAll static void setUp() throws InterruptedException, ExecutionException { - arangoDB = new ArangoDBAsync.Builder().build(); + arangoDB = new ArangoDBAsync.Builder() + .loadProperties(new FileConfigPropertiesProvider()) + .build(); if (arangoDB.db(TEST_DB).exists().get()) { arangoDB.db(TEST_DB).drop().get(); } diff --git a/driver/src/test/java/com/arangodb/async/example/graph/BaseGraphTest.java b/driver/src/test/java/com/arangodb/async/example/graph/BaseGraphTest.java index 7e3c7a190..8a16b9231 100644 --- a/driver/src/test/java/com/arangodb/async/example/graph/BaseGraphTest.java +++ b/driver/src/test/java/com/arangodb/async/example/graph/BaseGraphTest.java @@ -25,6 +25,7 @@ import com.arangodb.async.ArangoDatabaseAsync; import com.arangodb.entity.EdgeDefinition; import com.arangodb.entity.VertexEntity; +import com.arangodb.internal.config.FileConfigPropertiesProvider; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; @@ -47,7 +48,9 @@ public abstract class BaseGraphTest { @BeforeAll static void init() throws InterruptedException, ExecutionException { if (arangoDB == null) { - arangoDB = new ArangoDBAsync.Builder().build(); + arangoDB = new ArangoDBAsync.Builder() + .loadProperties(new FileConfigPropertiesProvider()) + .build(); } if (arangoDB.db(TEST_DB).exists().get()) { arangoDB.db(TEST_DB).drop().get(); diff --git a/driver/src/test/java/com/arangodb/async/serde/CustomSerdeTest.java b/driver/src/test/java/com/arangodb/async/serde/CustomSerdeTest.java index 270a15872..1b8e71a97 100644 --- a/driver/src/test/java/com/arangodb/async/serde/CustomSerdeTest.java +++ b/driver/src/test/java/com/arangodb/async/serde/CustomSerdeTest.java @@ -25,6 +25,7 @@ import com.arangodb.async.ArangoCollectionAsync; import com.arangodb.async.ArangoDBAsync; import com.arangodb.async.ArangoDatabaseAsync; +import com.arangodb.internal.config.FileConfigPropertiesProvider; import com.arangodb.model.DocumentCreateOptions; import com.arangodb.ContentType; import com.arangodb.serde.JacksonSerde; @@ -61,7 +62,9 @@ void init() throws ExecutionException, InterruptedException { mapper.configure(WRITE_SINGLE_ELEM_ARRAYS_UNWRAPPED, true); mapper.configure(USE_BIG_INTEGER_FOR_INTS, true); }); - ArangoDBAsync arangoDB = new ArangoDBAsync.Builder().serializer(serde).build(); + ArangoDBAsync arangoDB = new ArangoDBAsync.Builder() + .loadProperties(new FileConfigPropertiesProvider()) + .serializer(serde).build(); DbName TEST_DB = DbName.of("custom-serde-test"); db = arangoDB.db(TEST_DB); diff --git a/driver/src/test/java/com/arangodb/example/ExampleBase.java b/driver/src/test/java/com/arangodb/example/ExampleBase.java index 77a2bfce1..c99610836 100644 --- a/driver/src/test/java/com/arangodb/example/ExampleBase.java +++ b/driver/src/test/java/com/arangodb/example/ExampleBase.java @@ -24,6 +24,7 @@ import com.arangodb.ArangoDB; import com.arangodb.ArangoDatabase; import com.arangodb.DbName; +import com.arangodb.internal.config.FileConfigPropertiesProvider; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; @@ -40,7 +41,9 @@ public class ExampleBase { @BeforeAll static void setUp() { - arangoDB = new ArangoDB.Builder().build(); + arangoDB = new ArangoDB.Builder() + .loadProperties(new FileConfigPropertiesProvider()) + .build(); DbName dbName = DbName.of(DB_NAME); if (arangoDB.db(dbName).exists()) arangoDB.db(dbName).drop(); diff --git a/driver/src/test/java/com/arangodb/example/graph/AQLActorsAndMoviesExampleTest.java b/driver/src/test/java/com/arangodb/example/graph/AQLActorsAndMoviesExampleTest.java index b7208f6a1..682bed1b1 100644 --- a/driver/src/test/java/com/arangodb/example/graph/AQLActorsAndMoviesExampleTest.java +++ b/driver/src/test/java/com/arangodb/example/graph/AQLActorsAndMoviesExampleTest.java @@ -25,6 +25,7 @@ import com.arangodb.entity.BaseEdgeDocument; import com.arangodb.entity.CollectionType; import com.arangodb.entity.DocumentCreateEntity; +import com.arangodb.internal.config.FileConfigPropertiesProvider; import com.arangodb.model.CollectionCreateOptions; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; @@ -51,7 +52,9 @@ class AQLActorsAndMoviesExampleTest { @BeforeAll static void setUp() { - arangoDB = new ArangoDB.Builder().build(); + arangoDB = new ArangoDB.Builder() + .loadProperties(new FileConfigPropertiesProvider()) + .build(); if (arangoDB.db(TEST_DB).exists()) arangoDB.db(TEST_DB).drop(); arangoDB.createDatabase(TEST_DB); diff --git a/driver/src/test/java/com/arangodb/example/graph/BaseGraphTest.java b/driver/src/test/java/com/arangodb/example/graph/BaseGraphTest.java index d9f5e811b..514af943f 100644 --- a/driver/src/test/java/com/arangodb/example/graph/BaseGraphTest.java +++ b/driver/src/test/java/com/arangodb/example/graph/BaseGraphTest.java @@ -26,6 +26,7 @@ import com.arangodb.DbName; import com.arangodb.entity.EdgeDefinition; import com.arangodb.entity.VertexEntity; +import com.arangodb.internal.config.FileConfigPropertiesProvider; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; @@ -47,7 +48,9 @@ abstract class BaseGraphTest { @BeforeAll static void init() { if (arangoDB == null) { - arangoDB = new ArangoDB.Builder().build(); + arangoDB = new ArangoDB.Builder() + .loadProperties(new FileConfigPropertiesProvider()) + .build(); } if (arangoDB.db(TEST_DB).exists()) arangoDB.db(TEST_DB).drop(); diff --git a/driver/src/test/java/com/arangodb/internal/velocystream/CommunicationTest.java b/driver/src/test/java/com/arangodb/internal/velocystream/CommunicationTest.java index d08c1e4b0..bfdeb444a 100644 --- a/driver/src/test/java/com/arangodb/internal/velocystream/CommunicationTest.java +++ b/driver/src/test/java/com/arangodb/internal/velocystream/CommunicationTest.java @@ -23,6 +23,7 @@ import com.arangodb.ArangoDB; import com.arangodb.ArangoDatabase; import com.arangodb.entity.ArangoDBVersion; +import com.arangodb.internal.config.FileConfigPropertiesProvider; import org.junit.jupiter.api.Test; import java.util.Collection; @@ -41,14 +42,18 @@ class CommunicationTest { @Test void chunkSizeSmall() { - final ArangoDB arangoDB = new ArangoDB.Builder().chunksize(20).build(); + final ArangoDB arangoDB = new ArangoDB.Builder() + .loadProperties(new FileConfigPropertiesProvider()) + .chunksize(20).build(); final ArangoDBVersion version = arangoDB.getVersion(); assertThat(version).isNotNull(); } @Test void multiThread() throws Exception { - final ArangoDB arangoDB = new ArangoDB.Builder().build(); + final ArangoDB arangoDB = new ArangoDB.Builder() + .loadProperties(new FileConfigPropertiesProvider()) + .build(); arangoDB.getUsers(); // authentication and active-failover connection redirect to master final Collection result = new ConcurrentLinkedQueue<>(); @@ -74,7 +79,9 @@ void multiThread() throws Exception { @Test void multiThreadSameDatabases() throws Exception { - final ArangoDB arangoDB = new ArangoDB.Builder().build(); + final ArangoDB arangoDB = new ArangoDB.Builder() + .loadProperties(new FileConfigPropertiesProvider()) + .build(); arangoDB.getUsers(); // authentication and active-failover connection redirect to master final ArangoDatabase db = arangoDB.db(); @@ -97,14 +104,18 @@ void multiThreadSameDatabases() throws Exception { @Test void minOneConnection() { - final ArangoDB arangoDB = new ArangoDB.Builder().maxConnections(0).build(); + final ArangoDB arangoDB = new ArangoDB.Builder() + .loadProperties(new FileConfigPropertiesProvider()) + .maxConnections(0).build(); final ArangoDBVersion version = arangoDB.getVersion(); assertThat(version).isNotNull(); } @Test void defaultMaxConnection() { - final ArangoDB arangoDB = new ArangoDB.Builder().maxConnections(null).build(); + final ArangoDB arangoDB = new ArangoDB.Builder() + .loadProperties(new FileConfigPropertiesProvider()) + .maxConnections(null).build(); final ArangoDBVersion version = arangoDB.getVersion(); assertThat(version).isNotNull(); } diff --git a/driver/src/test/java/com/arangodb/serde/CustomSerdeTest.java b/driver/src/test/java/com/arangodb/serde/CustomSerdeTest.java index c80665c1f..249d7fcca 100644 --- a/driver/src/test/java/com/arangodb/serde/CustomSerdeTest.java +++ b/driver/src/test/java/com/arangodb/serde/CustomSerdeTest.java @@ -22,6 +22,7 @@ import com.arangodb.*; +import com.arangodb.internal.config.FileConfigPropertiesProvider; import com.arangodb.internal.serde.InternalSerde; import com.arangodb.model.DocumentCreateOptions; import com.fasterxml.jackson.core.JsonGenerator; @@ -69,6 +70,7 @@ static void init() { mapper.registerModule(module); }); arangoDB = new ArangoDB.Builder() + .loadProperties(new FileConfigPropertiesProvider()) .useProtocol(Protocol.VST) .serializer(serde).build(); diff --git a/driver/src/test/java/com/arangodb/serde/CustomTypeHintTest.java b/driver/src/test/java/com/arangodb/serde/CustomTypeHintTest.java index cf3569bd6..2de790a5e 100644 --- a/driver/src/test/java/com/arangodb/serde/CustomTypeHintTest.java +++ b/driver/src/test/java/com/arangodb/serde/CustomTypeHintTest.java @@ -26,6 +26,7 @@ import com.arangodb.ArangoDatabase; import com.arangodb.DbName; import com.arangodb.entity.Key; +import com.arangodb.internal.config.FileConfigPropertiesProvider; import com.arangodb.model.DocumentCreateOptions; import com.fasterxml.jackson.annotation.JsonTypeInfo; import org.junit.jupiter.api.AfterEach; @@ -46,7 +47,9 @@ class CustomTypeHintTest { @BeforeEach void init() { - ArangoDB arangoDB = new ArangoDB.Builder().build(); + ArangoDB arangoDB = new ArangoDB.Builder() + .loadProperties(new FileConfigPropertiesProvider()) + .build(); db = arangoDB.db(DbName.of("custom-serde-test")); if (!db.exists()) { From 8888ef67acbc7a4d8caee0819e39cd384190a0f4 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Fri, 4 Nov 2022 14:23:49 +0100 Subject: [PATCH 174/254] throw exception if ArangoDB.Builder.hosts is empty --- driver/src/main/java/com/arangodb/ArangoDB.java | 4 ++++ driver/src/main/java/com/arangodb/async/ArangoDBAsync.java | 4 ++++ driver/src/test/java/com/arangodb/async/ArangoDBTest.java | 3 +-- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/driver/src/main/java/com/arangodb/ArangoDB.java b/driver/src/main/java/com/arangodb/ArangoDB.java index c001e823e..661d77b30 100644 --- a/driver/src/main/java/com/arangodb/ArangoDB.java +++ b/driver/src/main/java/com/arangodb/ArangoDB.java @@ -572,6 +572,10 @@ public Builder serializer(final ArangoSerde serialization) { * @return {@link ArangoDB} */ public ArangoDB build() { + if (hosts.isEmpty()) { + throw new ArangoDBException("No host has been set!"); + } + final ArangoSerde userSerde = customSerializer != null ? customSerializer : JacksonSerde.of(ContentType.of(protocol)); final InternalSerde serde = InternalSerde.of(ContentType.of(protocol), userSerde); diff --git a/driver/src/main/java/com/arangodb/async/ArangoDBAsync.java b/driver/src/main/java/com/arangodb/async/ArangoDBAsync.java index 07bdc3861..949dedd02 100644 --- a/driver/src/main/java/com/arangodb/async/ArangoDBAsync.java +++ b/driver/src/main/java/com/arangodb/async/ArangoDBAsync.java @@ -505,6 +505,10 @@ public Builder serializer(final ArangoSerde serialization) { * @return {@link ArangoDBAsync} */ public ArangoDBAsync build() { + if (hosts.isEmpty()) { + throw new ArangoDBException("No host has been set!"); + } + final ArangoSerde userSerde = customSerializer != null ? customSerializer : JacksonSerde.of(ContentType.VPACK); final InternalSerde serde = InternalSerde.of(ContentType.VPACK, userSerde); diff --git a/driver/src/test/java/com/arangodb/async/ArangoDBTest.java b/driver/src/test/java/com/arangodb/async/ArangoDBTest.java index 7d35cdaa9..5aa0cfbeb 100644 --- a/driver/src/test/java/com/arangodb/async/ArangoDBTest.java +++ b/driver/src/test/java/com/arangodb/async/ArangoDBTest.java @@ -79,10 +79,9 @@ private boolean isLessThanVersion(final int major, final int minor) { } private boolean supportsExtendedNames() { - final ArangoDB arangoDB = new ArangoDB.Builder().build(); if (extendedNames == null) { try { - ArangoDatabase testDb = arangoDB.db(DbName.of("test-" + TestUtils.generateRandomDbName(20, true))); + ArangoDatabase testDb = arangoDBSync.db(DbName.of("test-" + TestUtils.generateRandomDbName(20, true))); testDb.create(); extendedNames = true; testDb.drop(); From 5b15914d346897898daeb3324993e5c8bae3b936 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Fri, 4 Nov 2022 14:39:25 +0100 Subject: [PATCH 175/254] enterprise-hex-smart-vertex shardingStrategy (DE-422) (cherry picked from commit ef5eae7f7f2185e34c515a6f50f83d7160375d9f) --- driver/src/main/java/com/arangodb/entity/ShardingStrategy.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/driver/src/main/java/com/arangodb/entity/ShardingStrategy.java b/driver/src/main/java/com/arangodb/entity/ShardingStrategy.java index d00108c51..847c16440 100644 --- a/driver/src/main/java/com/arangodb/entity/ShardingStrategy.java +++ b/driver/src/main/java/com/arangodb/entity/ShardingStrategy.java @@ -30,7 +30,8 @@ public enum ShardingStrategy { ENTERPRISE_COMPAT("enterprise-compat"), ENTERPRISE_SMART_EDGE_COMPAT("enterprise-smart-edge-compat"), HASH("hash"), - ENTERPRISE_HASH_SMART_EDGE("enterprise-hash-smart-edge"); + ENTERPRISE_HASH_SMART_EDGE("enterprise-hash-smart-edge"), + ENTERPRISE_HEX_SMART_VERTEX("enterprise-hex-smart-vertex"); private final String internalName; From 8f245db79e045f40ecb8971d902502207468d923 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Mon, 7 Nov 2022 15:46:56 +0100 Subject: [PATCH 176/254] [DE-417] resilience tests (#467) * resilience tests * skip request timeout tests for HTTP/2 * CI integration --- .github/workflows/maven.yml | 6 - .github/workflows/resilience.yml | 32 +++++ driver/pom.xml | 21 ++++ pom.xml | 27 +--- resilience-tests/README.md | 15 +++ .../bin/toxiproxy-server-linux-amd64 | Bin 0 -> 8822784 bytes resilience-tests/pom.xml | 111 ++++++++++++++++ .../java/resilience/ActiveFailoverTest.java | 75 +++++++++++ .../src/test/java/resilience/ClusterTest.java | 75 +++++++++++ .../src/test/java/resilience/Endpoint.java | 45 +++++++ .../java/resilience/SingleServerTest.java | 60 +++++++++ .../resilience/connection/ConnectionTest.java | 79 ++++++++++++ .../test/java/resilience/http/MockTest.java | 60 +++++++++ .../reconnection/ReconnectionTest.java | 119 ++++++++++++++++++ .../java/resilience/timeout/TimeoutTest.java | 73 +++++++++++ .../java/resilience/utils/MemoryAppender.java | 30 +++++ .../VstKeepAliveCloseAsyncTest.java | 54 ++++++++ .../vstKeepAlive/VstKeepAliveCloseTest.java | 55 ++++++++ .../src/test/resources/logback-test.xml | 13 ++ 19 files changed, 918 insertions(+), 32 deletions(-) create mode 100644 .github/workflows/resilience.yml create mode 100644 resilience-tests/README.md create mode 100755 resilience-tests/bin/toxiproxy-server-linux-amd64 create mode 100644 resilience-tests/pom.xml create mode 100644 resilience-tests/src/test/java/resilience/ActiveFailoverTest.java create mode 100644 resilience-tests/src/test/java/resilience/ClusterTest.java create mode 100644 resilience-tests/src/test/java/resilience/Endpoint.java create mode 100644 resilience-tests/src/test/java/resilience/SingleServerTest.java create mode 100644 resilience-tests/src/test/java/resilience/connection/ConnectionTest.java create mode 100644 resilience-tests/src/test/java/resilience/http/MockTest.java create mode 100644 resilience-tests/src/test/java/resilience/reconnection/ReconnectionTest.java create mode 100644 resilience-tests/src/test/java/resilience/timeout/TimeoutTest.java create mode 100644 resilience-tests/src/test/java/resilience/utils/MemoryAppender.java create mode 100644 resilience-tests/src/test/java/resilience/vstKeepAlive/VstKeepAliveCloseAsyncTest.java create mode 100644 resilience-tests/src/test/java/resilience/vstKeepAlive/VstKeepAliveCloseTest.java create mode 100644 resilience-tests/src/test/resources/logback-test.xml diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index 3d308ab67..03874be61 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -255,12 +255,6 @@ jobs: path: ~/.sonar/cache key: ${{ runner.os }}-sonar restore-keys: ${{ runner.os }}-sonar - - name: Cache Maven packages - uses: actions/cache@v1 - with: - path: ~/.m2 - key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }} - restore-keys: ${{ runner.os }}-m2 - name: Build and analyze env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Needed to get PR information, if any diff --git a/.github/workflows/resilience.yml b/.github/workflows/resilience.yml new file mode 100644 index 000000000..b3c3edd04 --- /dev/null +++ b/.github/workflows/resilience.yml @@ -0,0 +1,32 @@ +name: Resilience Tests + +on: + workflow_dispatch: + push: + tags: [ v** ] + +jobs: + test: + timeout-minutes: 20 + runs-on: ubuntu-latest + + strategy: + fail-fast: false + + steps: + - uses: actions/checkout@v2 + - name: Set up JDK + uses: actions/setup-java@v2 + with: + java-version: 19 + distribution: 'adopt' + cache: maven + - name: Start Database + run: ./docker/start_db.sh + - name: Info + run: mvn -version + - name: Start Toxiproxy + working-directory: resilience-tests + run: ./bin/toxiproxy-server-linux-amd64 + - name: Test + run: mvn --no-transfer-progress -am -pl resilience-tests test diff --git a/driver/pom.xml b/driver/pom.xml index f44e0a0f2..d3a035714 100644 --- a/driver/pom.xml +++ b/driver/pom.xml @@ -267,6 +267,27 @@ + + org.apache.maven.plugins + maven-enforcer-plugin + 3.1.0 + + + enforce + + enforce + + + + + + 3.6 + + + + + + diff --git a/pom.xml b/pom.xml index 16ae8611b..e4625ef8e 100644 --- a/pom.xml +++ b/pom.xml @@ -9,6 +9,7 @@ 2016 driver + resilience-tests pom @@ -38,32 +39,6 @@ - - - - org.apache.maven.plugins - maven-enforcer-plugin - 3.1.0 - - - enforce - - enforce - - - - - - 3.6 - - - - - - - - - ArangoDB GmbH https://www.arangodb.com diff --git a/resilience-tests/README.md b/resilience-tests/README.md new file mode 100644 index 000000000..4cd121c14 --- /dev/null +++ b/resilience-tests/README.md @@ -0,0 +1,15 @@ +# arangodb-java-driver-resiliency-tests + +## run + +Start (single server) ArangoDB: +```shell +./docker/start_db.sh +``` + +Start [toxiproxy-server](https://github.com/Shopify/toxiproxy) at `127.0.0.1:8474`. + +Run the tests: +```shell + mvn test -am -pl resilience-tests +``` diff --git a/resilience-tests/bin/toxiproxy-server-linux-amd64 b/resilience-tests/bin/toxiproxy-server-linux-amd64 new file mode 100755 index 0000000000000000000000000000000000000000..8b474e1a647af884b5c5f1b69efacc9bfc9c850e GIT binary patch literal 8822784 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≦h2*qHm(ENJ8O?svZWU+i@ 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

  • 1TDxiw8C z8)tf-+rH+~+LJRn+?9busxhqy# zU_}nWsQlb6HOqd)$FBWIm2B5s&)P3_TlvkK$PtYC;>p#g3Ky0E0nEuO(!597Fi3iWyWfn z4q-{TaFN&x`*#YVTL-(bcRPdx9W4^O=~~xL@q;aMF`1%f)!k2mmnWW2o$^oLdA}e{{nb;8r;n=y z{2psi(T69DU`(L}1Y+Rhmmv-#io^8Uizt>E6q1*5>EiZzB}m`r!R43+v2T!aI@tds zJT8lU!&qH-YiPl8dftuwzE+|a_V2KghW&{4H0G;F{4S$mT02HaM3m>E8f6!Iz)`}m zefnezE5S)T60 zfp{((sE%*0Gtu)D*o-EJKXlfFymOE}^%5-AUb5(!YXajNtDh1J*ijpLbPBR%mC+yO z{kGpxw!J!WhZty0^4hN2_^C%$!%<%rkTQV{x-Tc{F$W#5&ZvIXEp*F4XGi`)g zkLe*_2J_}VuGmk$2rx|G2C0aU4ZxBMHJ&%v+bvFxA8qOd@bg*vs*e5%@Eo9{zyO~- z>gnzy(WSfP?Tx&+3IF$9tg!OLiWXb?Y@^!8?5|54-g;2=?}1O(j+#)%uO!)6v~5lo zF9YBNp@8YGG`Uw7ABT(ew5aAWYS^5TbV*%uTuEL06EwK$_)F3FJMMQl5!A%@)Wv6% z#wu%l*82E4Bhv@hCFhKE{~*~yge|(b?C|>dxN_E{BkSUm#?*x;6`6hhY1?ub|6E<- z)Y$HRp*FiNtv#iaaO5lUihhe%^jW{appuKcq8}|QWnOi<9jAM(eWVZ@ac{7dkWuI# z5AW?-Ch8T4B7rb}^g^jft?QZ!-4NX1U=J8(KdY9HiO}Zv&^y=&!gx>2wT$9l6Mub2 zb?DJ?RaC!5k==$d4F|hNaf+ga!EA9WH?*fP870*T(>#*%x~c=!Y+ruUuneg*4$Mp$ zfRZlKpFaF)S`5#z_V2x2?NeiFCWvh98%ZoMQG(TY0P=&#d!fbG3B{4nqd!y%omz{* zsqqDypDDZXEm?TIfBGier5^ON?@dTN)VN6?+sn8j~7{H$!G2DmNebu5dF}*6buMbDH;;WZQL$uf&sEN~sDuc>h5}j|e zyKEsk)OPW5Z3L1jLoNN?+X!0wYSP>|2qOJfO(2VwlAK3q8YT<>VqN*6g$sC~$@q>x zC}cfVeaA>c_!D{bw{E1421}8|`C}sS^U)i(y06g-lUoK(cNjJ2D0lwPszf6K8x^zO7h&Qf(+W-&UXb>5Szl8EQ`7v{qhX~ zxQBizDq#_-U1BL$FcYE^t&*c9-t4z-p#eh(+9oGN!E#ExGf*d#EB=uifvGGz;F8{R zw!ixt-L$X5Qbg(-G)IG?w9@J)g*DDE#DhxH&5^_f!1jWoo~^9li1nwmBK*J|`n#Pt zoBfBDQlB&Ibt`Wx6Z4R+yXs=QSlHb~U!uu@505eF+QDJP_^#?FjTmY|k6w_azRuKc z030M6+2tk&g3ijNf8f4GuiDeK?kIM~daMxB6`$5Xs8uJ3QyP=HH{rrCWATq_CX_kFrw(Jv}3t=vM zMzy)I6oqa+vC{kr0UW;;T9VG1S=0!Q45?h~-DW~Z;5O(reXnzC<&iv(`a`iM{?;c7 z*3~D9a@Gf(p|*3?Jbi9Z@1aU_&EueREo<*u;z61Q^a?aAW;T^TAq!5Mkau=h*-Mxd zYT}*M%TcOK??GWgV$`;-Yy1|bdG;vrUzX{a5Yoyb8l3ucz%Hi4QdYIMZkA=GnxgX}yF6N;fQmUvD8AH(YkPi6PX)YxXLw5q3Z#}TBItd0v$;<%@ zD{R$JLux(9&Wyt-4*kuKL-fs9Lao|6&nj2>f6DbEa>>;%WZpHe!G!RyGrVTWFIm{NHdtv{`|jQ@jB5TEL-~M=f^W0L zr>}ThUCRi?)VsZ|`SbHbn?3)Df3m%#_!nIk?W;7Hu*P5UNZd5<+<>1BfS=mz+~C{a zp8ik#?HBGyETP8V()V_+KMyqB-Ft84jz*n8KEnr6qoK`=Owavgd?hR$H3569FI9WF zz%)jpy>oxjzF?I?KCrS*{0O^ktXCj4Y-1qsj>w(%bGxjTpEXX<+*4I7M2-UIaa z_nP2b86AmV&g|`Uqv*FNu3VF##J!yQHw572+mY%RJcXk(1aFh4n9w#8jVUEU^F8Z4A|k03mf|Z(Adk(V zTYp6tqIiNtM==h}$(@nA>vj_9v>`tldU*4==9i8RC~ZYfTfotu-L zW|Byl8Jq*-_pq+9NGRf+lb;rtP2;o`H0xVdAO8bt+l@s=dK!{AUzuY{s_bb>N`FcA zp|R|A2h}56DmLdRs%9S?OWjsAQ>@UhmmrOH_mdN~STeBK2~k@#RVii%le)C)MZaONNH#&^V;NLS8dDM*+;|Qs%A%=hnc>Z=G(+K>4kn1Hk^auD)ZRHZA$ihcV z4G64F;0MX)EtBvuXxLkPgg|tGAVzn(h`>O`-(+e`whH~yHESqRCe)6U6UG;!iNUX0 ztl88kIDr;Dlk38rq1c`1{ud;Nt%+6MSJ|pH?FI3{YjkY$wR*fvu8~6p(V_4_;m$=gC=#c?UoEL^1ky8f^(IoDcWo4Z5NKJ+v)U6foVMXk!&5=-6lgp(&tf~d& zquo!TiUU>GU6U^tOT&JjD?rt0!qVX;1HPt(}vC%49#3C_KJv7^{OnA#I z2*#WG;zkd#$~VU{Oy&psOJ=9k?a^j_bk|THe(l?Hrw&$F{>xfnMbH!BOp|p#&^EUd z=Oq>$?pyZzdM(#^*T(;1{jZDt3u(ia6Z-p?o&HwY=`<%&4z}EKnr!{lV*{`+NT6?Xv*Is+?Oq;og^|(BJ@NZO;K1&?v!)Vn; zE{vgh%MqOp_|EhovYJEwJ#djf>6g^q*Wu5915TBfUrf0F7%tUshF>T3o&7TNk8bdl zrk~7l8)QukCtvP`oscic`I{=;{*+Fv)9N$14r7@zpJg&#ApBMb_^73&_!;xvZLi?ulA3(6IA(eW~GEq zDUvc(vhobt8h@N~K$VKWY>Wl>doBF~`u{Q-%fg)d;NU;b>8}dGk42+D%&x+!9wQ0a zf?YG`D04Fd*GID!OLeHe(iAF5?$CUh8eVb;y7m(3s5wVko6ywQV#AU0zUQJhLpBqVy?P=`ZRit2#`EssboE+5E*;qTF6yJL7p6S;`QbX|O-&kYC3yV3s zGAoInHD`ayP+qDWXL-p%yV&8u`p<_gN5t#Sb6LFv%^YCo6>pfA{tk%Jtkxj#*UvQN zc+-5Sz#R9ul}DICUpMuBUB_dNLEziDSfA$d->c(+ku4NCvsC8?z+brt@AK^N|Jvun z|6i5O>41IWzs;uag@3tI9i{e-|3B&ckM3HWlf3Kh=9(ZIP`lx^ndMkPTk!! z{TA3^BfK&FKM>|!od3Y!vhw%h#Go!Ka7;A|!ReFWbY(kX9PFd4Vum5{x>J=u+J9W) z^e&cxp0^PW;`2CRCO)aR!%6<*d-ido7~n1YX!Q6>@7I;Rk4x;MOi%MTk3I|ih{t_1 z%SfV8_r)yf?bf2qXAtqnbd1L3swaoOYD2K!QyxMUdG!YVy>c*Hskg>{=8RNgQDU zm6>C3x94dQ1_whT$lMF4m3_Nsgsue4 z3RJtF(HE{*fW&8Pgz3)wEb;2cAK$fC|1{z3SSQcd>X?4?PtZ@YfLaLJRtUZajuLzT zkBg(zTg})Ls_K@J2s-G`FL~m|!sOs5dGHbk^63$tY!&D7U~1_>FZ?-A2=-F*z#G&j z(UqRCuTD7n*b~0?zJr5p1s4h4DLPLfCcw}dt)_$R4zarR%YhL4D7N@MnW8OUm-N?8 z#@Po&QkN7qB|eVS-q%G+W2j*Rj1!SDG9{82QmF^FdJ(Fi`-Ed;(F<(+N@!6_7En-{d#@UB|H|i) z-wD|teemOsLJD`db0ivYEB@d0Hnz><)a9@wuK8DqhNb;((#F)!PrjA9gyOfr)Ws1)EtoPl$Ko|S80Gx;Q2f7m$rf`BXbv%nFwjFT?6_x`s%yeI7)h|SWqomi`F5G`8)rwZClrAG`PhcJ{}?n4DIYwvlf0c0@Vf@QWNK41WO8?31n^w>sK-2opOIsp9a@Ui4>sEgEt)Ahv<%6jB~zdEKl|UN9SvG+vBs1K=Zs@Caqctl zYDvspx`XOlqK+FwNKf`<6ECjej`o9tc6C-pV!QC;x4l2-mRqE~#vW| z{Fk-%#o>zm*Ew(IabDQU6@LZheI}oI-|*UcY)1wMWO_Zr{e=O2DuMz{^7X);m@fUi z)N?{cdMi%bEJ4QQG^qVe_H~Ve^JHF-60Dm@zEr`K$Q9!K!yS0i8~ENJM)k~3){7sN z4IxqGEK0ITyoR;!pg~;WS^gikuUSuD{jEiE7k^3q|v@YLYuBbjDDON2#g~`|FM~H9s_3#~yk$@B*uh_oa){o%>KlPCwhIgg)^(c8{fv!LjqLSQo&l<*KH{_Qu+-mUFFq zrb|)X`pV5gZ!x88)Dp*fdkfoY!fM4|V+E2wWrM74&X+mTOI=tf`^VkC+c(|gBr?ny zFEsvTer6B$;)_L*!YI>SZsU7pDznUzvSnB&o6rl)v_MV`kZnN#<&#;}H#x^hi zBP{J>f78wRwq;&y>4kV;KT_avheaZy{$MU8ZtJ$T8Bn>c3YKKnq z6Pwl)V>@Gl}glD z-Cc$A5H#sNHd2~HRvTCAt!&_7e1n@wQ;Bv17cXKdn2=J3VvN&%tB-y=_v+=MdQxobCN2;lu={KZ(ugEohBug&nW*S04{^HUEE6yO_n zT_vl3v-OMpgVNHTw5>{4pwT;AvtBoMbSi11uT*uvOi=CbGUNQmX{QJIT{V^l5Xo^= z_al4G_>3`Qj(ZpsLE0xhPr-hVCalNDO|WS9@D&^dsy)j`LU*O$YHg=zsA~XaNhG zI_*3CEWe{Rux;v`9`*QWMzfW0*2W6fFz_$FHRmttWVPy}FPE;b(6C}-1=Orze*E9N z{V29(^H;y~)yaCA&tf{UeyQ3w+y9J4?CB<)`u2k_PG0&##l^|tFEW8?c|W}a)s?)Y zEM18SNT{mK@BFLFY@y|iwQt>CesS`eH!8*_E7v#G{=VgXo1Q*hCBIabzL8&CEUu;b z6mrZbh5=eR+%R-1%u8#0KJ24G)6=pnnIj#2`FujYeqe4M=R(r%clvRQXO*d?Z@seJ zvb=58!GCpLgL|ES{?Me2*(th;5G7q2O3VQGCzsaNeS|S=#py9#3VwsAflqY%5;bi0AXgdqzt*X1cHkfXCuSn4lHac4!y(je4&y@( zF-#*Wpx2188!Ylrp7&z)<9KjWBiX=)F#W-zs}kT=FD36bwhwe|u|iwC)hl2kKwwDN z^&fT+o6G*n7l5y3?ANR?t61R4JgkNs{_j`0Jo_lm2DrRhNUg>&s&B`Tn=4DeuHw-x z`{F`3UBg5L!HA!lE!yHMglmRLfO4lw5q)cwcSC9%VaQgYD+2j5^mt(LAU4gxfNZgr zZlrfv9A)tXf6Kf8Kd9@A8Lf8DS$kn@$ws-4qKB<&(?cQl@{-Lw<>z@ng@Y%E7;ncJ-&dD7Mtr-*S!@U#fZwqQ{F3!@^kA;{Ewxx9Jk9KhIOqfvC*A_5tL3J6P3 zo{j%py;z52=5dpqML^mCwi8U(SIxDZ7cRq2tE5Wm-vpP3QPhq9VZRqbFI&kptvQ!) zJ_Q~BJ+T-3LPRsZzm25mUk**ZM8{^npaHG^>#s+R`&7yJ|Enu7H`)bp=>t4E2~@-i z=geU*TdL$Yzd-$W;0Cf?hf8cMQbNXugk-gj7$O9A@nAmKLo+pu;Ql{h-k7ov+#vG1 zN~6>+P)%3m^wafkv~*P7`npe_F4{roRW~JLVkfU>t~$(>$PBc`_~L3s zdbYR&;lmbWFT!Rz6#`6n=x${ft9gydm~wMoP;n^!tiGm(9`_4b-9s>$un!iG)W=@o z5PpuC1!X@qHH09g+jxo8-m#gV=owiFlQUDST70bX_g2s=U3R|D{eBlj61KF%ER5v9 zw3;&uX3b(^ymBk4w&5v);+Iq+Mw$pCO~_Z;4D zOngT@TC9PYHx3*8)|~Zce%;N0|5aA1^gdYmayj+qjQ>YtEhmWZRrpN9iz|CO6b$lh zg!IT|3W3NK-#jNsc$tJ=F`RX|nlov>*T=f|{@njo8=p14y&gMCxS)PB*`lZ95U*1- zaFXaaJ>}_ydVuNVwvvP`7YvAO5e7$Rz+E+qwU%PXLY7`deqTU--fhy zMnf-NgC~n$ov+6r)3i%-uf@Y@ERR~>F%EA&wFb~a=6PF%8(-fQbb0vEgv-tkYD;c? ztgT>n5l(UT$-vK)4aQl{$crTAZYIHEp=vJ{#%Rd0aJ6+FGx%#3%k!8wAc7IKb=zK& z!d&v4kCwETgAoV+|Fix*vKNwo*S=z5`2S7+ehZmmsk#sSdr|)Q$YH>t#Urs6ttuSR z3t~PWF4>wpD9rIRlzB9lKSJ}ZahEp+k>w+*+K~*)?%;fXc??eNZ8orv79agtZH}SM z%!$1vq(DA9_o4X^cKilmq(E(eboBeC+R3+Hsj*D*YuMxT4rZLhfvW>JaCI%sro7{l z&D@$d=q@kSctmm_hu{!+|e#jYoIzMV{%OUJgw8u>T^-+f@-vnih zl}VcH`&H@*|J0^u0=n&U{Yv+9m1Fw5BVeY((Hwy|89vq#h?Df2@_*;;m_1N2c=OI9 zQ-nC*+D~*5)C6Xa&NI?Jl!WBazf740qcm2t)bRsi&kB+WR$z!@em8n>_xnZhPl^-@ zRS>#>;~-w6eI=+UPX){YJtkWdk9JNUY zAr=5xL*ly1(G1mRDoZWAgf=`=Y0s#$*CVylin?)AaDUi{cX;LgARX&gZc8kztmZe8 ze6$%jBgw@R`QeJ(NOBS@YvtB{X@Yc^mhQatQC*1alNHFknW{4iNwoV?I%ZX#%+wZ9 z%3_vkq=hH!?=zJTkuw4=yXduA7K!EIwb29A`;g7Yv5owyon7RMBp$Yxh^wdNHa{ou zsXWtOumm?ObUnbgs(QTCtzhRF+Z#cr-kBdh*2DS6)-Tiv4657V=|LY!&-iyYWf8RU zZL$eLEN@wGsNRC(HzOCWz}KZ(0xObqV5&*m?WF5wgm`du+a4SU*z6KeT%i0>ERNwr zh*H?2QsD@KM+a+z)X6%D@JF_o!-AKLIrY`7_fiWj!Uz#Piz%*> z9lTw{BmuO4)sr0~Z7V0!6o_S8|zw^(a zBf{93sQaSX1nPRqdD$iBhg9<{r2f+Q(|{hB5nOumXZ;MmWHH;mb#o~ z8wPWt^TTSroDb$#kDwd+j&VTI0Jc)vAp@yA=@{bACW#!D1tr0Ks|b8p5k-ADMIt&= zbt)3^r@}-exm1|Yd6uH40wzzQQcKGK5f9pq2Yo>9*aD8yeS4BQKVVSq{mKzA4m%H8 z)c#ZK(3gh*#@?)={t~6^xVxd_I;L-d^)wbE^@v zbb&OS!aQ|Qm3xZuB%W0o{)dIU2DNH{if0O5rXBbhHQ~{#CM3H<77)e0%^cmr1E5K=&B7eYoyl4mP%9uU(2CE zx%${`l?O$SZb-a9#$9PgTe}tf3aOVyiS9>xXI+OR?Fx z;eDkRY}sOe%c+9j*(=x=YRY0Jmo)0ULsLG9s6RCCA$c9BAO^gFmLjYK6Zw8i@H+`hZRiRYH2pSxT6 z256?Z6Ud@v0$p}CaxlFRa2qk9vlw@iiAdswp7rglp*~UU@T>e7&!3Ize;GChLtlOm zwM)*4=Y(}x_-yR`Szy<^$K{#d0%E9;*`Gf_QfS`oe3cV$5^*yc7wQHi+ z|68zAxG%5t0zL&01I5*py0wt~$yagvt`$)KA_f0hBSdD{Se*LUOfD)Jt|1^Vu~R3L z{eiA8nM*h+`nWO4uj&5Z|H;4q_jzdn4Jb^zYS4`F`sc=;-!>JlZyJ#fAaKZ*6i~G` zvPb053-`n5{=-^~;q)(&*n&d+v?4%<^2mriP4Zr1S&g}&b1AMr;`@&i;|XV2sP7g| zv-8MDZ6_$k6<_Xv{mh(P5+=U~32U8E7rK{dl3=L2Hbm+U+xxy_;?@YoC6ljw$>zSjtmn#YHOhh`pZ=Fap6jS7`hP%L0o7Nc^&Vd$tBe;Lw< zC(Umoi7n%k*ZqALV>UWlqyARShIy$@=o zBW-zEx1)No8`y98vWA$oTYaC>pa+46J_T&8T-_U4ice--75PVsQ$M51Og+Z zjL+tsP1ZzN+Z@b?H&{c&Pko-#2QXm%aEWgTnWy|zRc!_kJ3;DU)ufhCsrindss@ct zE->%1PG|Mw9<@XNWk-5R>~&_L0!t?d0*ftig@fgkF!f0}n+tPWyWhdGek7@sEHG8M zt<7|)yH6q&)xh~(erk*t{A+vOwy<7#N&xHo0$xK~G{pZ#x;YbQ%>*BcV~JV)0);L8 z%$_c?CooMmq_1RsLtJ2S@T0eEy$@`oUi@kW=5D`UYvR4+On(F=5iL^ z)V}J0lO1XM+JV@ARUj)>vgaGr6jD1kT7VdE8Xs%GYG_eo5#r($%ifkjoRW9&Z@SN^ z`R$a|NYbcA*K?CpW0`mDz({Hc7m2$egPhScQG;2*2$QV`K*8PN906#(gQIpZNd5YM z($k|$q`oPlUYor{>PPT}r%R-ey=q#+Q%#RaUV7J{20m)ZttmBx3*j#*st+wXRe|Q$ z_}^p)s%HXh3OzzRzf&-klf+#BzI=MJ4qpZ;o)nhRY`?;cA{bh5yl!3W^0@viMQBZ*fq z?XZol{{ahzNY=AD4eL`GFKLo(wbF(GZbW|R!M-{wpnsqZ`|2WxQ>(UmnZxph^k%`d zQg`ZcW*TAO_{pK>G&T`utscbr<*a}FGbo%A`8>LjbBZmm)0NIKBJd&bNKS)hz<)cM zP4Q_vWuLTl_+Rz|m$%cWuXGjkwP%t~k^g&lC_37Ec53t+EjN7qzi=+&;8E7vv!W-p z%_;rr%~QS{t-QW%&Y*AH5FH+ybHKIHL);$!R9zgIq#Xx-2?o*>No5r`*S+q@ZtH@3 zrkG1yT*|h}fadjzOEJrA#)WqF(w94hvaorRp=O3CTdHJ-N>hJ<=|^eJFK3cqcKpt! z9y-NmJ@eilUGuiraGiQ>*6Cxa4i8@iY{7qB16O_&+SOp}AjR{A3Dd03(=|IE|)TqEGc3JdTdArV@1 zMN!A4dutVQ$KBA98UuwgS$vSIPzJHta&&1^YED+M*oi`*U4o7T&ADH>)hwM6{c7HM zpMCbSI!CDSywp?HCCF$uUuFW^Db@3~$lI%Wek``hQ9W{cI3P!VCz2}u4pEmy^|6|v zQQt4hR-l0`Blvqz%P{^P(87gw4hOnoOE^jYNt)k(VZ~{7Wn(JL2e&GuX@#>-T`3Na zN6sRXiN-R&e~&PdWtRW*P7@~PvTuL?ed3QhyBf; zU|7lqrf>d?Fdy@>_${XW{>Ww@8a>ov;XsRp{e^{SrInAE>$AD(d=1A>V}zCw&L@tU zc2ZMf^lJqBTK-}=G+?p5s-rV~gFWAAony3%R~8hwr-tm)**r0lhE8XkDGbCUp8h*# zR#ttOT3Ik~=Q{No>sAyom0GB_`hQ>4ZP4-__*skW4lXO)ZURfi6z%HK zff|wI1F}jX1h?!TigVJj;T8k2d<8 zXu~@u6C}_|Qw6IUDp{~j)qP}zx3x`Cq+q>OnP=I|M53`vPPxgLwtT`C7ir#y^bKN7 z^isAcZVM_rsnALjU9pfkLNlnCvSsf9MbK~+vE%=`$4CmrYpE0?`((yaF_*)6>~SLS z?D|fI%KwEHEF%w3d!mLHmn~o2d_NWZo+@lC8ed)lrtM{$SN{r>Y<5l13j%%iyfQ?2>kwwy)~L z1?d`B|KCIH9NwXpK8=3KZ{-UbKg)h=`|-%|pdUX~ZO5oK`QOb0F1_`?g3jEb^b*o7 zp8NDD{e46kjo=hm3usQtYXtdCo^392^_`V%?`+lgYkk$Yad;7$ECrotvlwHirXy91 zikVHC5#Qtz-8uaV4% zNM_8ctPuV8e4hPlI(8{PMhjj&6u(LhD}#uw7V28G%j?GhU&%vbdrGGrMR0g(X4lR? zg=0No@35Yoo7j*1>K1RrZtvCi^%q%2fJGSkzvwW}{l^lbCki)=UF2DjTo!Br>DIKd zM&4Q2exb6bN=`l;c7dO;KV{$Su$A0|0F1A!UIARC9oJM21jhZ$IrocNd{J$dDEp<4 zLlXEh5b(L`8|Q~Tk)vf4Q7$KiYj#cRzgV@e@UGpFc#{QxIZg^c<~owY<8KeJ4Zr$M z`&*%Jcdc;wawKa0ql*ukPi5e5qM}jY82v%iGYe*Kc=C&-k!zP*H~R-PDFs*%3(eci zkBB)b*gJ0Hb5#Nf(5P&H7^$*(i`f%AOsq1AU>;NvS0F5hD5FA) z_R}7?4?*%#f~ML^S}hSbuyL}fU7}ZCYYPb@WhX}R)b6eQK%)l6QF1SaxUjd(i*MbP zDM1S;C}g|cYb&J0*_p12!eUgrztTL=DeWvyqt_K?;aW@o?=OV@ENDXi4UT`{M5W)v zt62>@m@O{n``3}POgZoRg|BBzd&h^p3(Rh0F~7u$?=wgQGkpd-cAG^$W!;) z7O?-6VlqqxqP0i)wOWnSV$r_c)-WN4t0I(oPf#VFS!r94SN1hNus?rI=*}0E#L+zm zAw%6A;D6@JxWwp}Ie)X|*Ot5tR@~)7-(4AFs&FZr4cHWfPn7$NIOdDcE@r5-ZC*M| zt;l7R8dQd}-wF#RX&V&CiUnl8rb|>(B}?yy>~{ObRqGssRGBAG8s;(B!mRRdTA?83 z1eOxp`ZRetZXkD$SuL<{6r}qjIq;Josl_kBqkmq?J)3HlY;A2wXRGwdAf?X_N2sh> zV&_7S@dH(zh$`z9(vAsF`nI~~ORF47?U?YJFj^lbbn<1kz{uObp%y$gZB~ii4ATl2 z#(Z-gW69spdYlG9wX#)dz&Whk~uyHApAeIYo=Y43$ocy=^~47|E#pFd{M24;mjS@RB5k_@uGrN z9A065CyBS6tmbR_vuYK8-d0HnGzkJtW=khzQRf`bnH6{Yq*7-br=`bZJne(OrXQ8B z`!TWIU=I{-pSm>=E6i8+ZonEHnV;o0A^w)CO3vNL3)dYP zeh>=8IPWlDwg?Ddu=~wTQ{K0I!u7&kdv)BxmA<8Cuik5Z^l;@G(BkC#$AY5m1L=Il z$3CH7IRs&)xXZ{RgaKSq4u4?7hhUKK7V~DbmzMQIX-7fL8$#r z9wW&ghDi?gKPq&my_@fi@zIrJ(Mr4~t6jFK2P@au-=``!^K19HEV#pNHc5_0F+ZuA zxN%GJ^O?#RMYD<}s6SW!FQsZ5{)yKsd6!?-os-C=$X$qFW-+lD798Tvem{KTuiQ@q0 zR%uE`dL;3VNNME-GDJH`6Q@@aQd+;{I_hLw>KL6vZBBWWp@V#5gED(RxjwI;bLtuH zD1;#}k!pb1Cu`KuwgYR_jz0C6^ag5)@47B}q~<5Xy6yN|qFqfm{h7bNz}T9nuk>0S zGp+Vov4xKO$%H1SvY>GDOdzDK5W*uu(PMP{y%sW+HvL!1=>~OLgi}3atMHP8pn>L0sL;r4 zhmNpSP2!{qXpNU+R8Qhl4)a{d!VKp2FH})jD8VkJsF5+0x!)spX7Y7RW1fH3LU`>P z0araG^>vDc(2Xv$<#s=Q+nzr$!nFtFVQuhWztqvRWE*gbI*g(|RQ0zOaz3`N@I)Ur zyGaZ9#x)h>XaOs!o#pW>0%HX9KIxdgY;Vor2xZLkrJ1$Iu_ zb)VYYbsssDSoAqQSo9g;FZvv27kv&67Jcr-5YUpoveV-lk+9iBpK-k1Y@syQJJaP` zLtrnh6q?KUVAhezT%??-lAA6MteUf}fx^I7(Xcte6uEizvcF?+al&R(6VSS^w(q(Im)c&(Nnn`LvTC-gacIc zTV=7}vy9e)p&VuHfD~8p1o*|3#w-wj=N(yQ$7QfLa$n-ue9S28(`9GY=-QG#LO18t z+F#c*c60h3Nshw+xQf2q28E|quuZNilKe{8OP*g!WX<#wwR-@UXmO=*qg!O9f6bFG ziVdVm*jkUonFyUGxr-XjuYU%W%rEFzCY95=f4%@Y^L-<@MOf>d&OTJvhP{Gv4ae@d zru;p3+{>nuN;jIbY|DX+Q;1l%xj-%M3sX+qtpt>Pq03FQuFvAk;^zk7s}OHMRQ-XQ zAtrMqZ7GZ|{To;)nmSTCztZ0fWzSezBc`Zb9}P*-)0&FLIZiY2Nn&S1VwJO>uFgy9 z1F&^Z$PGP0p3I}o0eeGjeH8K=jQ7aAv2@TnMHuy zh1JN^4(-?)lZ>fL7Cr?-4`bgJ&itbK#TvEsp$pb=>#pxVsMiIO-{gi9OdhS2^U%Tk z3%B3U=m_kmaO~58E#>?@sO2F39?&uf@_>nIFj2EY^D`;b_?}SoTyIHs5xllEdP-ZX zTl_xu`nFarejgcYW%0XQ)AVMJ!R|$>t13$r2vzJ(+QfZYcCxu`-0q(I(S(vLFPJsS zDew3vrL)StrP-ztg6RH(i2+%aIk3<7Q9E=;L4`+|*@uuRdSGbLMWwM%>ZkJOs?c}3 zGlOyX543i8rfAe!xdDQ%=5{;F551t5TImJq%0=_TMDxR~d>l4UtP|*E`I12aIYjcq zv9E@GmS%Rt%+Y^8r=KCX=Iiiq4M(^`%ft(zr5_H8f3n}S!%$n@?-YBfGsZQ?XmIpt zsDsl=J2Qi<1;w(*cl(cJwYxYP4lR1(3Cao;qdKAKu&D>~-Ck};w*S2m{WRR`-b!6Z z%)ZLjbtH8i$=z7Rx*Mxll#)E;-W5D{l7iJOCGk)CMK9qLtVgN2pv5!AIJ@$xmV~P4 z2hTg9O_{VCaB+C-`18Ko6KRwKap(J9_wJ*;?mg#uBRQ&T4d--;2F`NhlzLkRDQp^l zZPm~Tiuc-&uck)E7$~kXCp+c1y`Qh4;Ll-xA`(&l#X-E91=K+PAzY+AXxcEd>nU5| zN|~DjRN*$MtFNdTaxvz270x=-Y;d`r4eB=CWCmBcmUX9#;=7BMS`B}}3yBx~qZ_(Z z2O{!|m)qWSf&fU;~6e@?KV%3P=itWM9rj6!pM>9cB#xXJzn8klF4 zhb(SIuSV+Hqm=@FoArxgzD7SV8+MWvcrXwRT4h^f$JZX~9t^aVa+R7#+9;$k$N2hO z=bQTYp%D#t#uwZ&j@!&QW~TQ1(&zvu5jb6GP4GO(4Z!#({oNIJM_Bln+Mb9e)pblv zA`S+G6Op^OV|%JfNlcUcB}m#TdKZE-K^ZoOGRG2f!c3~!{&rz?OKt9KyC{0Rxs+m< zeP5f&s`HuP#9RQ+X@0v*3AUCeIR+xbT5Ar*LH3@%sP3S7ho5b8{zd%UFa3~z{$X-L z6$=4)MRv3t%+mj~{dwYuOE2*eH<8&#EqEZYS{&`FMK`qWGyZfUa2jH1wUlyX)bxHj zY>*-qX7ZD^uXkL=K(H(RS1b+s`18d!X@|y0325N_K0mF-+~v|l^sIl*O|$ueQFLbDC=FtMJ@# zU48$>Bj^Lx--^Yf^|1I{{mnD|?2D5xkE*|UXLxsr*vVK8Ju@4>L67kR-WpouRmMI! zu%#sS$$nAakSJqVl&^?=QWhO4o%sAT$U@q+kvmTP;@A7oDA&;R0kN@pFE zXL>LodzH7V-YIYQY=;2gvAbXNoq4;DD6KD+*^Ah6d+GZ3q3hpd$%jdj50g~O6ixyB z_^}v*{ivKt1sms?Y=rIKW)3{V=Ue*IQB)vj?&S4@dm#k_>l zFsq;7&lY8ZZn!nNl}2lyRNTJ54%QyBh8c78aUo<9=#z8U*1b;0HO>)_RGDi9a<;e) zEnL^PhBe~mDl)>&QlF>D%*d%!vh?a%K7P_4=5tQ2eWJ^a`p5@Hdu#8~fOY;A;vK-X zVH2#UM)8xiuZ9+WL&d>NnLIQ<)r;@{@RIfA;+%0pca1sa5*SG$LLEa`W2owtQD&ba zD4i33?l9@pz4X77(sY&%&0QpAhME18BUMu5f&4PMZaxvpTli}J`ZJqUHa06E82?JW z+}7$3@+9Ypp$DUCA0XD4`zG`SD=e@O3%-!kaf>3n`c4u6`TPyE_B<*_RZMf}z( zw)@S3in4$n?S%Dl&g-)W zc|{UCyxJ$b=u-=uwgwOX?{Qo<&ciu8upI3r>z;fx2KC`#wsr1uNABm0RP)xYJ~Wwc zYt6zexaP~PsuUTJo{={t&7%S$odyeAxTncGH2yX# zP2GRh{Avbnz@a_QUc$w3L>_c;US+%s%QfCrqd(31L#TlN+WW0q8Yi~_N8dYy{X8DC zIFS7_Q>v9UgYkahkd_mye2?uujBPN<`f9TQ)4sRAEP`+9eX|*!%*)`M zV-@Bcnl|6bOH$jV=KL7}dM180di?qOH4?0O_ouOKXE5x9G8tU^(X4{Zp-x4?vMWJO zGEqSZ(N~g&HHW*(B^7JeO?{VDp$hxFecDFv+84c4@qS+Is?gjU^bvCUH2`8or#;d3 zw(c1F1D@TDI5}cA&xn}?t>@{c!boz1Aa|D{8n2*Ad zFxmX}5i6%IzX;(e(~S8)x(X(lB==$nF-!H=$%2yGQuRMTy11yqeCV`ZdbBTief=w4 zx5HI?%7?QG(w5c~sLAh5*h_X;BryIE?wuA12vyFnbcK&+e(R=hReqDzmOosp$x>1o zC9MDWss8%x)smN&{||p|Q9U$FOEHIj>;th@j6N+Li{X8;EuSJA4Ocry)Uu!0J~xc> zF=BoS5`2WH{XI_I)N9kn0V;ookVFQcv-YJ+@7xi{^BetiAHHRzn?;ZEXT59bzy3f? zBP@2U{jxBKije>}KWh;iz@IYvXg@vkA50DzXl{J9?TbI{`2!s6W99Zee}zf?18DP@ zR17+VuzJyEMurCwX8IOufr-CKzE(05tlm|oW>O`kbIvPBa762?i4U>g2kXFDi)WO9 z%cr`4AD;Rc{)YV%j^(>Ub0?6L!x(uCU+#D}@hlAAu*@=iif3BBP(G-!k=?3{~bpm%8d>pOYPbKj5b`{(lNkAAkun!1e48Z&A+(^=wfh zkBPV4lEcL5EB_G(JN{iSuE;w-F5uhWe*nrk2e#x}i$vm^;KR5*J=scF?9W{GO$Y3| zIWu6?S_?nvp?Pb7Q9{3*AvV#mP31EZkYVh@#g@_ZPAex(vy3*;T(@6eM*CLLOvwsY3Dmm1B926GBSi_VLriW@IZ71t|VW!8T*#&?CA z4qIE#MHk!VU@vi?v-j$@$cR_G!rk>dmdB#YH2pewAC-4{sX^Ro(a2HWgRGCV)Jqog zz*QuHp=Iv4k-lY3oPEF_T2!`Uc~J`-IBG-Zzt@M*LLEBrPy6w-SNImKY|0cj3M;A8 z_X8)`&vOXf&Bw|4d381B;bf1+$#2wm$~H2$P~Wf7N;G}%?f6|czyu5V)7$$%|Jaa= z{52Ygc!0%3u_flFOnE>@w+Le)79IC|1}U9?0D^`VzStKT`5pL^?ZD$Oz){>va+LZn z0yrM3!}=dW`2zLtTrCQs?OtdZkQ{U_0&@sz3P1REGh_$XG~SG)QimOc9yo1erxQ43 z!sFv~5PUYMQO6R@I;}DO34FGpKCvg@v$dAb-mrYOA{PA(O&$(NV$*)!}htLwuI(gamOl)?V;`<8`N`@kO`;z_4YnGP7K0YyrZb zvG|PLw{9P-wSZ%2&M6*oQ(aOHsX4GpHWc^2ZEPDS<)!ZNBeDDwe^Mp;&pVIL{vJ2! zw?9Z?554reF>I6#ErWH7gD%3xXO`)&pi3g4iI$!Jez9O~uZ+PektE@@FL*oOVnyS; z_!f>nX91Zl%OrWJ8K~Qq%2r%LoR8@DjaVYOx&lv+t}3kkFqHaF0S$vqiBRW5DwrJ2 z{FvVG+?4ESCS8XxEVi$m6YZ-`=i8K?s-p4dWNdLi#baEUtW@M{Csq(sy!7wYqce8@ zD#pjlajPA%O^?aC?fR*GV_K8?(Lrg-TtgY6#kmyTtpA7$UlM~~AXmI@#q&(3bw69l zPkGnnuysG+!F-^Vdl`33VuDI&BQZ3o%2T61j@NbAqC>qz@y7~u>QY0AxdJzHwE3A` z`FGv)QukVm5pH9T@ZGj%0zZGLzAKDKeJ7^S_711#v2e$1&7W0V0o4zYL!n-RLEE$@M{s1N=BZvy>&7I9-`|vcNZ=C; z7ai1e?WU%F_sOnhKT)crf6IAL@0|v&R6M6>4?6|R0~fN6jJ%IJ>$yV94#|?+=AKtz zhLX#kY_FWHW$Kl3(c`OWBEnrYk=oVMP8Meol2CHt$O}X@;`7Zg+;)-F1(4Ylu>msH z-SUcJdma`1m^KsTHf|;;8v<=xA=(b`5<@=jawf6xX$Bpw z%Zde=y@;rpQDMUensEXBP?d0hu!U8vaO*<)K8qiAuX3u3tpNL}gZ+~+OApN=<*)L2 zg7`y6VMy!M?h2*8U`vxLIeI?OHbkyn9qBh$NYx;Df(q-C9_=~k0QNk9HE$INK#=L$ zv{(d91oH|0G=6eAC8fuw=QgWxHuh z(9Kb@X9#VeC;DV|E})OY^${b6Kt0<>ixaqVqF1~9_63sW&0dlXo_=_h6=druZ67uV z58HW=P_r77b5e7J+WRT>L_+OB|AdbRD^gCx5sQEGo5v;rRVPo5%~gzJODsYo%c ze`JfyrqH~*q&>j7D}IkF1{b+%p9+ePRB`%mYY*yZ*+Lx_J+?HpsFeKE>q6~EQ?dM8 zi5Ky3g%(XcG`{sHKYk)y^Kxk3c4R+3lwlo_%EQe#oiY#5yM%6J!DQiFm6>XL{=C8# zYhUF2Ehi$C&3va)n|z{ne(j^9ZKbfJ`&Ar1%-w#y52;?iO8nb1ZKZD8C6g7LU5evC zzcD=V4`_Za+z~rAc4*1$8adzLXRj^U(7$F$ba0d|eW+55qvF7hi?f z@KbIA|6m{$aR2L*@*Hl@Qj;V0wN2YnGWnktAd!#yAAmPmYh{<_LPz*yV_3y(*4lBz zfn-;M@-PdGKBpw7G9&RvRPBr!yK{=zU$yw9Y)j@e+L6l0Lm(iDT|!UKK2=J=vP^w# z>#4ZeMS!O-uC5O~-CBKp?JLo5bQ0fl@es_V!j=JxJ(4pei);8n=JxmeeKiXd>#+uoydJqXTzVg=S;p1_;6#`n=tB zoyVjLee80aC}G79D+6S;ygDJ5SKl8Yg0|G<;17gn@fYS$X~Zka*z#YxnX$1qFnfRL zt#03>Hos(}BV$DS+Bg6;pxyb<&L?*ADxRItF!RW~Hv+PSAZxZzFNvG?E~N4IPf8uW zcPR>Gu?cP-bc|X1#c*_{m%O0bjQtSk@_^ul#j z*cUTye82!p;fK93y!V&I@Jm5oH0|@_-evdxvaf=jZhvLpHk=zkdeF*82Y9wewHrgJ zKL8qbHWVEfChQ^<-^zzbsyG};Ud+df!@>SHr9H1S6zC+4467kAl#Tkv$C`1;;??Fg zU7(YL@`*z4BsFRCCr`(?-fkYZ*X%^tc$D2=A*pt*fXNZp+m6)c%NPw4WrGzZWikDz4$|$i!Pip-893m%RQ)*CGBzXlN z$HO7gf8vi{So%?+_~TLVp#!8g+h2FKbA57n7d!mS#akWzWfF-xVKIm@GBt)l+c{x~uU-Na{tOJ{M>7ynBQkcqNzNi#SaBrTI@c~26yXfEMmVI-=1u+NTIs67@bLeSQVCZS7 zKXirfX6(+; zqRaQz!=a}yKecU34oIF%YJl+O}2oSzDp-)5gNC(9=7z@@;2m!7o6yoB{agxjEb$`KdH) zMI`mjpq0k%PtLPK6sI@u4kG#}d2D>H7J^e4Qk;6K4wj zh$p4bOj`f)b3ed;d?fueH{PRj6dJG#Hy;ImU40i0uSF^TtamxTd@nhVAg3E2Gj9oe zVH$5t^CB$7{NzfLi2SfKxonF3Xbjy&Ao&-o;Kq>!50>~^L(4yP+mAX7MgnoFQcCeEjWo^ z%-!y-{o|X@8@QeR$9K&M-KnT+FLkAjx_8U*S^Yzm+e7g-F#tiCp*u6`_@Yb8xtlh| zBPXp;{p+3B3>UuC1LwDXo zmQ-f}kq2$N?U(t;V8PU{*MSQtyQX~uF#65rG)fCXSnW@}Dz^K%8J7{&TwX-ncx>u8 z{ysND;q2x8M#rX}Gy1t1XT`S;=-zseZGX_f*W=sH>)zIX;HMS~v`c&(?e>HUW*k79 z$fv+t&RZd2d4TedKEa#p7&s7{+d3!TG^==YUgmw!H{LU628*lhbdUlZ?K%Go;6L0^ z<1=*7w#83dkI*rLyAAdfhIB0>T-@E$KmJM=1>$d?7hfCe@Ct2UeJ_X<>M5fyh=D9d zXAEF-7)JjAN~FdMoqw8oi$e1|{CWq)U)fB(i5I#*>7T6}r0L@D=Ay;Sm~s$d;iG)N z>E{WigW|7j_sb5-mQAeh-rYZ2LGZcXVvO>fnq0*=qh7v^yS9py#!I(ez>Ix)iWi6G zpYqh}!FTI#Vd~4r^ePp@4LFedFjO`MEaFQ`gypXyfTHB6=c?ur6{_hF*&Qe)a%z;npw=j1K(i$ z;CpSk-b+oa@KRICInroSB;`$x*Hu0l$0;)i-$|=B{IpKW)W~U__!H+ub11HPZ@S>y zsmHf?j3id;@fG{^4Lz>3kFPW))(dd9ttfIW;Ecvpq_VJa8HDWVIgiq{Z-(NdAWmcA zCGK`DjwDYE1^m@C@6Vxj-Mt%0&I*-A`n8rd#{b@b&Mo{cj+Su6Lgtq|mPD)KbyJ=Y z%>5&Y){4yc9JJhH5n-#~&Zt1-8q-%Y?JDk8%;I(D+7cYv-&&rY3@o!|LnW2w^OtrZ2K_NPD&kL5f{ z)N*bFZe{JYR%8(Q+RiOoQsj_k8cFwwL+_{lG4n>XKyHK30W4s=zT^m|(m6}X= z9*ozV8h&N!>f(6an~z(vc!?=tE@Mx%hRtL(xg@Aq>SDp+Dmd~@$})fRYP_9qvKynw zLoItF-t-FB$LsD6s`099HC3j28i!YfuPIFb7|83B`_%(`>XssJX;8ECzkL*%`ztcw z9w`dV{T@$vdq0gN!d@eSQUAmn;pV2)`K75rhq3k;uRGSY#peLz-_aIZnPyzg;=JSMae@x|gLY^tIVGfh4W>TJ@d2 zj~RAfzhdz2DzW#x$(b_QFv<{T6GbOf2|Ycb==z<@ z3k#yH$q9p!x0KdSD~oR)&KAdsR*BSlD+4jMG!d2pDzWdkx3R|~o7Vr>> z$V+x1b3lr;lKw?fgQJwySuw536yqD-S|!I?uPJExLL@nO;dkdC;)dSNk3Di-;b=1wonxJB-ISUIFouU`YS-2k1}B|KpXwD zNV@_832EDVkrwDLi@cLbx40Qo`_+llQOoNX%9*pX_?+lFU$RJTsT>VrYcdyz+pVhw z)Uh-apocpL3Z4Fm)V>hN9u1_IY;lO$T3NUorY_V(OOCAAbNw{6VW5 zp1kDj^7a8NOxGv6$ESu6X)yeaCUhA4LWgyZN&LP({!WO4=ZjiO#<0(;qQ2{cV$LW0 zzrvRO{4I)x{QUi|uaBRD@#LiC6r^P_TA&Zt&c+tP8^6@e}iY~>983LxR!T+-85^^v&w1k5>~ljS+dUx`i0-OUH=u`^W^*w^pOuQK+os#-W!K zd=xschM7{n?LYHz+LN+FN5TEZ{00%&L3=xFFk+%9e21erU6uldbEmR=>gZJeccTrmx#fhh#JTT$w;w-NQVH zzsxygWRKC1DRVF*yA~G|lv{R%pm&!AjYZVh&dKCYm6Wjn zN|8}2k}COOoqZc-D*$bAVr|UeM%GCm&EXhEb(KbSg+_HntnO=SLdVVMunOo?W)43> z)`JKQY52y0v8Ml{LZ?c_S61c4%ja{S^>5_WzyDtKFU3*VxBg=v`4{R3rkhY+z+WA! zd+bMo|5$w11Ago02OMjRE?K)Fi_EN=7F)QGZ?>i|8?f4y;#cDU!h*O^8w-?7vk(m zyqMtrRp~w7ncl{EVo(me4c1Q{u^&Hsvy!d< zE7YHZAK|xJ2!QglWJg6{(`gB{$!q(7c-@a-`hw^IUSfdbti;&T%)w^ee*r>#H3C_D zyvpZ71-Fa9bQe<3;fV~%^w zL0krZl{@~jq%$W6)mk-@Ssui9e(3Z^E)OM}8RfTW*3bM4MmW`L`&24%`mxE@OG8Vy z1?Q{9?pV;MUZAf~TVz9kk z7>b`_Yn)Ij{tC?-!CPaS%{60KZ?3rm`F?$8Lrr)>Xx`reEVSs7p|Rbip#^`kFLQ=k z`w>?spO*2-Iw5|p2f~FD+c{!m)P}~LAL{cw>rBN{)rwP{c)^`J`5L`yaVfcjOwqIb zS3i~bxHY5JvOnV2dEAjId3<)h|NAQIKYyl$ufwU&+~__W{yRP#s}EQ5!L*!fvu%E! zua)|G0beD*u67A)hmmlQ5{`G}mki~@f%?ONRm@Ws(2mK@6Qw#=IQ#} z>YWV!iEF^te>(N&XhBJsu=&cTpVf%ds=eU%N+i>?cS}|pW$xW;WahMge&6;r*+asW zqhI#?M)bXu5BBy}Cch{yIUCMDKyhn(E4E%}tbAM+-mC8pqInho+y6$|r@@<0#Ef4s zp{Xod0r}0kkZCP+A$+Ww>H=8{0z;Jrf-v!~c7Kja#W|XJUr13URpzwMfWtaP($TCz z*#}P+KFOCH*AoHJ-!1%?^&LOf(V@`Icxx$_ z>DutpjS5Lr%q?rMubcLl2$p8_2E%5jVsTHgyU%(*N+8Ns?H$r~ENR}!^cwq0_UGum zuwnVnjw{VTt%s>5{l$Hcuq^(ODOvr!z=vZm{r!!+#sd94{nGsL6RTT$udICfM)zAr zSW%{qAUwdrC!B!t{K2BIzF@1-G@tjF>aVIR|7gUSKeOGoS5f3xdoBC!-b{3%d&nD$v;L z>`_Cct5lh{{7iV>pRhwv;R7iX#7ziXDwj75EG zIddLFmuh15Ue;Fa^3a_Rl1FVZiPVj1m%??)Bffh>j1J;3q3f?h1|pKU-hRS)1!nS2 ziH|ZD32l$o!MTG+h@eMXRAp8-yk17F1(}7Ex|ek(F9kKtpTF)@McD3um%AJKGWQ$4 z(@R~Aby#u}S+yOWIxKwYMhIv3A>a8I`n!pxwM4rc8k5i{I=Uin6qrmceaV^%mIKoF z=1iFTj8n_sr-6G$lJiZ(>yG=jW*>4KESl{51b)tgX}(fb`%`h-F5_!v&|c=LK2_US zN8h9noNq%Uhj!luR_1j*D>Qkb$STa0*;ng)fyTwBT=$#S>yDWIP^91d3Rt6Y$)>8O z9$G)U-?pYv*oK_C-o=iF#+`3_qn2aW-0$t=LK~Y?cHyC3>WhVTA)BpD>!0gK_2z%q z|KC210sQ|px%je6eYyRx_!$T672-`dzqJm2xMA@3cTp>x3GU=yz;(nE2N)iA)?SBq z<;~N~g+Zg8ng7mhZSQB>{;*v7n32WuSUWOwt}wf4EVFU%lJ1Mc|L@)SVi?`T2x5FO zjO18Ol??w@yuiG%KQ;29iU{tMSEVk6JHeoxpU>HiDT+}At4^o@znp)r0F8Omsgr~W z959mo=5`m`%?uMtSJhV+bap1MEaMtt{&L4);k1Ji8{;1rZ4W)k`#mdg6d*S?F?9au z_0-pNa-_h5E6csrZSwKypV!kya6^Ghs32jpzVgpYBn&@97+r}lNIt0o$y;&UZj8TJ z%<)MLp~wm~duv%@SA1Jh!@$+Fd8^uN-_&9lPmGYTwa?Cpsef!zJKfgH1GKS6Xq{eC zQ4n)Imo7;TEzZm=NDQeYi>`8ED9}-a1)P9;TVkWk{G64zykpyBjqZFC!B|Bd`2I>B z6W1fztIXR)Y*f|9Yu|LfRF47OjP(d1+~ErThg8W0FELfHlaZI2>{Q`fukztIfH2GW z0Igs>v;7R8mDByR1K!d9j{-OEe2-Xbwe{a|;WKIA!-KYKMO)4@oTu@sZ=B!7$Nu^l z{i+%X^RZOesw4;3c>}5*l0!{8iyOs1*g?T6KN}h4-1rVF*Li3G5kKs7hzOgFg<@#= zz~r_f>5+Hn-AJmD{*KrV|KS5Z9nUB8g8OjC6MXoBJ}lvbkAc5HL@WH##lF6S0XDli`d!}{fHf=&R)~bcX#*`-+&`@&{@AuKNNSRiixSHWmhc0g&OAY5oCT+`c6x*3 z`--4t&iJK_JDcqs``in|{yt*1>>DvakcXI-`}5oE>TTchrl2b`<4^O+qsCahLI0*V zWm$EfB251O#cus|On*wZeXvHj#Q)!=-<1E$D$Y9l{lUtO_IF|BW_~5ln!yVD%ixf8 z<{P(3b3bGA#^zMRU!i%QD1Y)^NsvhLUX_v}8rWF7fy=vA=nDHyTAK+s;I=$Bl6=@U zz=G-QFREV8Ty;}l-cA-*Dqh(Fk{ZtW=bJn~jG||b7rJ<(vtxWP?6sf7dQo{};`h4W zO&}1ZGPPw8{7HOBn)m2{Na7KJNWzSkfw^CmU3(+GTHP5*{=#+RIelckuOWFwSwrIO z`uI!51k%)pA}`e^UW%{f6kF`1$lIAp#}Sjw88d|#ADL|{h2s^SDh*l3Bz{*P-%>PY z;1*PGL&9ut2t9d4nQk@%K5hbUc^$l|T|!T0502DY9Fn|JxO=yu1IN_-KGgnoX{?^HHEhIG)djOJLF>9@ zLu}GRCdJ?ZF7P8Il3HN&0}DLLuOe9W*-MQLvvpI2BgyeKqt^wI7b00p5t zpQKQ{?(HPCbt)d|=82r7s^w&?l=sc?swA=6c1N<8?u`9X%yvhwIo(-oQ@I~Uzlj-> z;&mz2sVc`#=FIlg6_a(f0ed^obakquk;M2ZIejOPyP4|+CMs9+Xt$CGUR)n?!6)X{ zwiAC&KhR@6f3<(>o11y?sq&zx0@qLRdKPr@8R{stVD^{Cw7(m@#`Y=3JAIn=pE27f zz2@{u^bm>k*-I_B&%SLy>4~VkTI9kWo3_HhdW^>UQB31hx zLIei4OU5#=P%EdU))b`P55}u0KSSb`^q)u#01n-$?pgkQH#F~gp5t}Zwoc5rq2IrZ z^Q#gTAKc4mQOwr_U(HRb)Tf@sKyql}KVr70dd=yn>zWIB_YzMpwr#wW5ZuIwE$HH% z%2W61!6)O*u5up}k;FIGC@l|5UhSNMT3##6Bb}vr{qviIJ^agTaR-h0j1)aXV zC^HrGqLDd-Luzs|`t_U{8u`k_O3ScL8e||{1 z2}Mp3!eB1YOvp=)#p|)Fu;pZd@&)ye5E<1qz8r~!H2S^7YqO$#scwB{KgAzrn3n3M zt##=P>ZVsC2^ZyN@rgpHjCZLeH)U%7#JO0V{vLs8kZ(V!j&QHJ%tAcdA3`m{C2}El zE4sz%x6r&-88eu|g|cu1dp5LaLN#5v-;IVRH$y9Hy{?P1xnSNVWb^Wd#Pa(18cxdF zf!JP`W6KVFBQRxUzhch5M@<~_myeXPQ5%Gm2_Qu#FGx|>2$lsYZ-JBzI<-Q7RT%Ps z(G#;6Ewe?lw4rc|3V*7?98b!1mqnv?NTpZE-$K*3PAq5{>!s?$=4b5Pjn}=WkP_W= zCW~=(cq0A7vXU4Ld#UjVBc#?Vqc$-9%&-Wk)fEn^jdrMQi5<%=XM3qO4I(qq)_Iq$ z6X^_obH_WUld0Oa)hflX|LH}DU3!ISs`{_CG|}8Xk9FT|%jNIOIe9`Q>|u$$gW$Qm zOrvb395Xfk3rtWM!sg8LvnJ@*Fj6furMu;&7ynE@EZ_DM?^KwgY#C=9of;Ihq{^)7 zoxe?&|Fyi=c68;JQ+}UTRvOFMLf|U;%|7j_;A5V#8hp(8?bEWw5uS_+)9>xv=5tEq zKjx1b9fjP}Rw^x$f{f6ovG(FAp}9vez9O(vS>x*Y5^wtFj!m{RK6O~r!p$}Td|#Nh z1}%|q%q~b+=O@JKW)5kS@;X*c2-vhjR%3O$-kyWQ?JPTUuV9Apya9TVL76aeU=~3H zKM$%jlbKlM%~oP{m8zED5}R8~Z^>V(O|c%Q8h;wyKY90q^r7~0&dsCxi<_lDiYt+? z!}?Zc>(C7rYS>nFx2ozne~3Mg(#}H6F&yCIa;y$dQRkGi=MG^mw)jbXV5+t{T*l7r zo(xw7m2&*;L;c7`#P_P$)5;L5d*gdC@*V6PWZ(K9yAP$rywCYL;+tyCwzNNUf?qLk zpBzEOrH@f_7P0ky+w5sg22ieQv(;y-SYc}LOXlIr?;En!&I(i&gAZ{qp*lHnNbPrp zsusKp*#BlG>%V;p%Y0Uugr#fxDrtaJ$$r}zZ70z&vxX(NAc8)Jqml_rl4}cddAgBv z{X2U)gt*+#Stk8|Esx|ZzWtPVUGnyLLE-FUlY=jKFjmlSa6Nx}y5aBI!8ejJd$8kX z3t^@o^Tgy`oq&|Q{~rG0zqoH8FH7|D|FQQj;89gq|L`PaU{K%;8YIeX(5S&{P_#)Q zGEpukGH4L0v3Q9WBDNGFWB>)p#7P3!5Lo zFakQ<`XDr*eSuNd&ILRdA!mTrUfGVROcKOyh8X3_qx!c9iUA~@kf5RY6YjZUdI0j| zgP_!`pK~&5VBLZsmRqA|!F%@Q1!%$pmN5hk=^a?Djs1V&{U*3zgjq01l-Vc@*acGw zD16!70*~|iJ(m?YjN89f0}rI&b_nExg^48xale?64IyOz)-u_g$S2`#ePaJb0~nl4 zmKAN@&zF+ECw`Jdp8-H7eWQUP==*>n7Ja=tqE9EF@MT2;kMwmTeGeSyjJ{FmH%^GY zg!+X_F|M9`qIF9qsQNvm>NmL$fqe4(OXWG-Irn3FwHoM2M_Eam!FKp(Ho?F zBfhKuqN==EcTc~|ui+_+jA>K+-Q@gC^fCnBJF7wkPx%RgPh!S_#@K_$a3Mv7JJcZi z8(j@M(u3>Lao!(#1A6Vbdu0$EDEKWs6d>_n7k)Gur&T}k`@3Mz}gKl@J z9=7>R2kOZh=e6vl<$?BvrOLi=74>J;=Q~ga?F(D!Moc%{^RWp57zWn!0;Aq~_(qHs zi+F+2c8sAgq&Dw{L2E%9;_6n!dFJE-v0ur)86Sdh6JG6mpg^~b6*z;*@r};MW0z!! zBH;BiZSUxZKGqwKjSPNOO?!9mN@A z>k0uXlv0i*r?P*>rfG`?6P{`3!1m}O8pbPL(2#4_}>~LfmNd&!aRt0j&mTXqaQUVQ|C1G=QIX73c zBr0VPE;Ecs=432~He=)YP0em!q(^hG;Hr5f5EIc6%`IM;6CD95xM>f^n~a5C=Kncl%4~{C_>c{CE8+b^aMA zn7;{Qv6S?u&ac(>hhU+9&SC%TVgKx*TEh*jkeH9SH21S9=xl-o|AgP+FE-Xbas;!m zTa})~I^J4@%N=8@n3(JL#_uJ`h**+8TS_ICVhqIEwrYz%UNI_-sA1_}Gz<7H_CUAfA4E(&osx~rj=B$wC zKCqgLixp)wUWm7qn^$7U;xOKOkqhV`-}v`!YW|o9;q%rtDpO0YaX=VL&LddKr0Dd? zr<>wPo!&A&)-cTqRQ0zFMI`FCuq#}g!THmMim9UO^avInDd04;{jrp_$ek16Yenoa zoVllh{Og7(ex;k21aj@-Fc^s4G#`>bk-1sMJM@H_!rH=XGwMiAmN8uL##}s#SGp{H zB34f|zM6b1<&<-EOkvNH?dLz>YGRi()O{mHj6 zsYRIG_e1crnb$I4&7!&q6y#r>>o?><8=6*w1%qap5~))nBOEv4=8R7a9WstF3nlU! ziav$*T9L?G!E;G+wo1ZjAQ-paKOk7J$x1pF>!uV+bNqU_Wv%kz^nz`*&Jxl+pm`9fBRS5G>z#z)FrZ9W!3$&d!}DVp-bOhQ{dp1E1~_ZY@{K)MCrDv4 zv8MROo<5Mkw?xJy|K*AKLBY)h%0PwvJ5U5kuq-&D|CbO}=lzFPd$N*W8~-4M7oeQ` z(MZhKDvd|)kewFJDQr0S;|*tymS^CLT$vU;TsSK?w7S7?g7aOp;PVK^V|;fbEpDsS ze*fXDkF=LR4B_HRj6JPN3HSK{;<4rDOpHGxeRO=t%mfDVOJsQx_VLXX+vMh7tOxkV zsk<2>eFh@s(1T{OYHTns2d^b-^v?kFE(9N2!5$cTa3P=J*p1K7um`wr47knzxMdJh zgSate5CaTZVgJ40zirZG8XF<_bw(MOs^*tUzGM`hV8g}am94AJf9hK2FW^hV9u(&| z2H`JwxOCQ4!VJu>4|kbWh>7i3#D)7;>5(2)+Ml;9JRLz^ThPl0!UA{CS*j(NBkLHa z6ml06IcW!PLF^#3uDaveR}!!W(ZByMh`xkG7oHEH75SP2`SK?Ay}8EfmSeczkXmyj z6`04EunV~1RnsfjFGEylbLITYwElRE;zHFp(KRvwkXN0Fb#b-z#i_=fX#90bv$kT} zJzJnl&Kk!wtMUkb$>XOzUgqF%BsP8$3xOIyJ!8Qm8g6!lS)J@JhDBSC?N`&g$ny>Q zYu0`>Y*6Ed@I$+R>l56{rVnjSuvLj&@C5RAklpM*MymFg$2!QR{=(+LYDyAJ7WL-+ zIN-OJHujvN@WbUy54C(HD)gf#N8x=Fyx~p_o5Ryb=l+CB9sB*fdSvItGY zFwi+R?`p>iD%dyqBkkKbf07!$NlUCygrCczsxaalw;U z)HJ4qB@~6GPaPk=rWh9@R5*=OVEeb{R6v0L2owKf?PE7?EYr2=jb+-JhKvJRc|8_o zXRIsJ_Bx$2g7D}40~)>6J@W#sx(4OJ@6l?jl+UZxzCmAAYXFW`I}uHxvp4q2WTzEj6q3_evuxr6tS9cwNZtuYo@SpdO^|l{fTd=MXiG8jeD)sF@W$HXf zk9E;^1r?yWpq@!w(Ki60=RMOEj_VQR#{W$&oN3n-4p{()JQ$_zt>@2r{%q#YcK+<< z&lmhT$e*^d(O^Wq{H~YZ&GNfles|077xH^he*bTz-@67y?fpA{KH$$M{8`PPxB1h+ zpSCg|MGt&8rKNpc?EbN;i_eui;A`cc{f%-j%z!dSU0v2gxdoZxo={zkas|j{pR10} zB-c_pH@RM*^Ia=MZ(ENu4c$QGx2hLNz61Xd5Rngx2kMs~_)8&R`{VC+q$u^`XKFEi z%1iMxw_IW<8*C)}rF5W~=uYYq;H1_32rBp6V)cI^{kM=7Q~&zH!$kk0BY^tnYzrNM zXMDKK!;AaRC~8^*k{ui2LV-GPUdoz~`8Z4&pMOENe|u3VJ3IQmtyhS9@3g_!3ExZj z-cI3r(aGqIgkOB(@M9NE%*I}ll$T6cWuDufrsuK)AWk>$i7@VhK_L1EUqsz1BRIS* zG^#mSoVtx0WAyPMkGT*Eu0;t7vP%L>9}e(M2PnFoq96&Y*2q$~vAY{k_#IJjGauQU z5{1O_G3JSv&%Tc3(`ET^J1?IJQ9hhTa9euh~-U6v2G^YWPx<-=(- zc4O7jq@VdtuzU=J;^m_fg?_p$A8zO6Ga<@{1N!6TGvD#cFAD80g4|)SHgilI2M!8Z z2Xu)8+|F@eLf`EI(kDPnYGx?Yw*@MEP()f4qF= zJE8L163a)Mminj5^5J$~J`uT`~9ub48;-)*gP=Z&y?$ojGNyO8ttAHwJocAk1Zpu%V{6xN?XyrZXS zHG%0(4RqR?VfR>c6Ox3}bf?BlAN*4o3R)~{LSTEEh?;3;}caOo( zQ)3Ck`ImPlIEsx!_$V>%0e;3bz-~n0+0c4SFu(XZ0Og(ooRx7;Vvt4LmnxYU<_(C=*da5NXXal6^UJAEP5-4}(+^02agW?|cVB`t>#-vJIC1jn$T z(ZO}69#*x5TLW|T;a3$`OxDAv@+QEE`tV>q_~gIN*o-^<6KAV~^I%HO10>Xr%CQHvGY}Qm*8KM_F?8B_0JgspknrSOJ$&h%dcIo7#+-@!A!af0O2v-n7SCLe6ycC*+SvI6AGzOfffP}_?p6OHd(DlW7 zxF2x03ce%HxQsIA2E=53$^{QC*JI$&4s{7Af&dqx!J=Y)*j|abc~%kT=AQA8$(->B z%N-9JecpH^@s<^8AB@V@>EMPTIym4)2iqy=+=&h2aBzDXor>(abY9O6fTb&*-OoIPsuqAhT-)tGfX{IluR5bC<2R$D8ogt!{ORO;*Xsjp7Cgu zIk@c>_`_h7Hy%m62MVBJX3HyX2@emtU|nINL6<$Bw&Wj z!2T?i1_%k9o3Yi)3`tiZ<9ftGGE_)D>^o)}mkK!-x1N|GxaOIh>4R~P8RAhPU4W_? z;#DF0;~@bR@=5Pl8b_MI`8#?sGnXS>Lb$+Ug=9#`Gce9uAub8|1=cvM5LHt(ScS1d zJd$Qs-*|{uLT<~Fkccy{ke<}-FFwBFxc(k=r0653K^I_l;^bn1 z5Bqp@184SNl7%r;X;~F`Ax6kd2XP-k)d`g}iJjADdfF#?+Q+y;*Z7e}(LWz@su32@AsQ@ylsHixd33C|8f+S7O`_R9HH$3t}%o{7Q@nN@F_U z=OcbzrpQgeZ$p&%tXZHj+>W1`4|a|pa7dm73Vx+17s}J*-&|ug0JC)Lm9p@gYkYzI z(o6^ZrV+nVrYKIp?>rMfHH$QsAV-XUYCf3~zu5dytNjg>TIX{}t)_-)%%f`9ru8&G z74A>T_ALXiqXB)Te=G{js2mcZ@`Rtveoi1+N8`*LaCU*X@!y1$G(}y5^DQkSMJ(d8 zRITQ2gitzKO5ve^#N@+1KaG*t$s9FKq6f+g=;pwQk(h@M!vi`NtCG3K+ntr z5-(s@>}w+=X5f@Iq0VNvC=#hBIsApwXzavnu4RNtqBRRnCNYsdbN(Br4_dZ^Ik1gB zBqFYoR>beA>^yuJUJxPl;loBBqox2iGY{!wR?;Uf=%Z_|!k-%^eT)Eoa2k!Y1o{xf z#@#u6=KMNNANmZTk1ppIa80FTqYr_^Rnl7Y;ln5e0zw}?Z1gdz=8&Qfe$od==o1(8 z(Y4dJjL)M$L|H!RgVSgX28?+9A?Wz@0U^$v~Y# z6HcRXBVe=)v)UnoQqh^Z_q6GsxP2lO{T?C$y6KXBxb5jjAZd}b7XA1z76U<{A0IaQ z8MO*CP%{tdXI9cLF6gJ5K>u!&enxmQMn9ugVa9CcA^prs`o#tPbQ9>`Wzx?G z&<_Xn14f*F1br9!VIN9GKRQ04pDyW#+n#;|k`_s8(T@*fvAk7?`p1Wjenzdrq}$9x z`k9sViwpYcCeXjrq@NL>9}egTj5z%W`cCwxrKUgKq#v%(pPq{TbVWbY#^_H6{XkIa zACoFO{fJtH$3298WF`H`D)iGO{RCwjdw;pZq8|~YKb`aghK+t;mZG0NQT^A}B{lsS zCjD@Q{)|-gXDIraHb#F2=m&y|{)`0r5w!|WvPApIGn zA24k61GDc!f49{1yG;7w3jMBB^t%-OOdF%$1^R)YqTiK3KcZIQjX0qnSxG;#3jK6R zKS9~)|Jb4*5v1Qm`T@g6KQQ|)^lPccUE6#Yya zqu&GifuN$_lR!VBR$($N^dl?jM^>SqF6k#IJN^H#=tl(U_mF$Q`7G? z>4z)ydsETxRrE7$jD9cZ7mES)zc+z?M6JSPSm;Mq(vPe{KV8yKP^m|D^ zVA$vfX5WSW%GC4+O#0yp{ee{U2NeBG8>2q}`envX`U45{BWe}q&O$%3l73_r`stE> zg0j>9kwrfuNPmFz1BQ)$VD??;Z%a)-UKZl`2OYnn-+=>avIK9N$01T^VcHn|jx=Mj z7zjweBhB9bA!-#S)@B}|pAQ(Z|EEj(3Cd3YHj92lkbXxR=m!iN{lM%y(Vv!b{NqSB z=}$N5PftaEx}pVX&3`Kti=m!it{Tbhl{%)!1cbW9#Ha=+wu2l596fH;_r{85P7VCr1j~9`Y zu@EL4JY`|5!o=Ooqv*$4n$$mBp&y{^^nVbeA2%{k{#~FSFzocZz8n2oYWlIdBy_{F ztlU)eyA>@+8>ioGEEem8(C<#5-)*eIgx<`f=*K#u&<|JW2PixJ@5ktOEBf7_A296n zyT2R#gHqG)G3oc1^m|g#?@_cMZJd6Ou~@7YLcb@0evh#V6M8d`qTgfE4_D|1C_DY{ z#pw4a`aPf@Fzobuz8n1`Q`7G?>GzuSdsETxRkR>&oPMvdSgaO8zc+z?udxafdNYrr z-)qtjSLg>QJN;W?^m`TkUeFI1cKW^FhJGybxen9?jWmC2iq*l58&d|_CR4JRo68Xp z)LmF7P@9GIV4I`jE?;4b}p<`9aoO zDqZ>z?0&~yd7Op9>1}LDPzy10T>AOgUXQ$HA)&9a$cpzJto+ykkc%GLVP1}5Wkw#| zOlm{i^b&O}8k=ju?Wz5Hm*}zfx#A%p*<1q8FLljv8XIAU(}#QDTMb|1#y~;FDD1-U zyS21dy~ce!3aeJYGAJxDXvE=pymB zYZB-8!j6_7Gg;Zwt!A=7!KdG2{tL>~M(yvP=}6~pV&@%&YWK7AN0#RvdSs7u%V&5I zP$3g2_`T%6Q03P(0Kn5|0C1+2Z;0i|jRSD@HUVJmaog?Kq7fOe`A#_9x9ZPeDbk@m z4!I+@m$Sm!vpvR%I^(0WaS|o=o$QINFYt_2%S988C9;R_C(q@ARyh|0aU;N;coGkv z*!MmiE8Bl*M(N|jf0&A8&GERY!aY8u{KNlHj-VpQ*FInP;_=9FxS}tY;7WaANN}z{(^dWiJg~^KuaB-lI2SjkCC13X|=H-YbM!{JS*D&(4 z9ja!8K;}mTUKC`0G>VdzyCG!BEJ^s*A2nLB>Y_i|0gv^c z8rvBE(~jaFGgdJEv5w+@Zal&GpLY;nRA=0a_@cUw;vY3`WPFGCRein`bwuU6m@YbB zy5ycmPTR0H!QeZ|VC+#a8I1i2=Isw$gG5E3%2;1W0&#deJ3v^_uyu6JOEYxbi=n&?nG*9N`mMkTC-R|3`05Kox=IQ132m zEpS*IkJ1Mex#`)gIdr9q5Wt!Zh|B7hhKjZ{RTiY#mgIU5v>>xBp;b|QR7*pfW79(G zGbOHS%~F8sKzx(mX9sYPAPW!LzLF2rj@p>5whSb;&(PZ~hu`_8!$yop8(QYR+gbcN zTq@G?pN^971R&!5%^iR+O&l;;09c+_A}+n&}w%ppG$k-Q~0!M z^BX%zK2|X}5c*H$!-3Ep^i>@Vpuf~=zfd0>_-M76=tBbquUyWlR8J(q!Vg|H=Cyl) zf+Y;qs(*nG9BHc@$)8HM{Cea!SAM|Z|H(8o^IQA3IQp@v#<*Bzk&6a0} z<=F?1UKJ&pxFc6NM+NENbPUermV&oh_tq0>ha-K~jJJ+ecEkTz4}ZM;DMkK(fN4^W zaA4L4h#NI%hy2#d?^5{_i%9eC@%d%EEtIN-<2pN??QoT{6Y09RkLzVBu}MR z^0%w-`GW!qNS$()D(3~|)GH^s9828Wxs?CV#~4MZCcs*hCa^>KGPDO;;DflUZ#0C@ z_+9;l`bI`|SZ;HiVi@?fB z5F4%Xrlh3Tdyw*$T>RWQupYnD1~%ijLIBK91aJeAR^E!Fm3Kn6w909NkhHQwz=|;1 zFo=UK^8()VV*Jc5#m|CrNXv{-11V6TfC2?{DNw+d0ws9BAtG>y37ig5xeMScX8?TV z9DuK^BzUL*f(Kg&9)uG-C?|Nq9S)I)L+s%IeQf^U+tz5RB_K);3p0;HN^Jnr0vIzM zHkILwpD#5-er+nl8Go!dL!LL4;f!TF%#b&z41qYSQK~7<<&>l?45*Bi@-hK&|HV=> zx%ztJovfZi=SIc^|ZBb{TI6bzm?ZQ?^fOb zy<2%JLYt6$&bxYAqn>tjO~Zo9GojzXz#jvf%2{>znaAQQuaX)c$AT*-N_|gesg-x^ z!@ZV01_I4#5JVDS! zE2&7TT1!@$-3iIsL$daOtSYlFlb&tP-_VbcHjko>oUSCImBQM}LZM9%t(+jV38Iy^ zfws_L&~p*~XS<=H;4bixk}+Gbo+kDu$8;^&rtUiGCSs&ecOR#rVLYbh%WQF|F>W}eev ztF9anQ|`vkT%uR$&E>C7yef-}`CCGqDoe}REC~c$<;9?6E>0qJipU-!vWJN5AtHO) zA@Z`xUQ={V9G8th&_n-v5}WDE*(_*fftAvwt`&o=42Ddc1rlR?{Lx2wt%t@o7&7mq zooyNnDo9sKquf-j_o(c0t@lIOLSt`bV$*u7<2_pMr{qYI)>}Peq4j=6uD#{cGdsW& zOem|f*{b1rNKRzKgLM!f2hWqTK^>l_vU63)bJB8`Ybqm_2VC*Hg5i15@ECI4E!l;z0HLRas-Q0dO-m>JaPA$N& zf9KNlY26>wKbw_?%NKEgg_VZ;V_@uxShS$Rm{w;$2OM$0b7iSv~?knlrZS^5&CJqSHas%ic+9k$9 ztQ)?;GM1ku1<`bw!e$s_E)qbuH(>vx8cRmtf|{ zosOjOigsDdc)>nZ1;qKwHI1xxg~s@+qB%@XU@+rRG?uqe{cJN?%RjNFVf^x4R)|z- z9C`SX%f}6<2?Zq94>!Tf!Q5~TDn$=J=Ajen0ksH@=@D6#xf(4)#fK!`H~i&#K=oru z2ydm_&h<=G+U|XFf43ePhQ$KsKL_IQbr8q3ui$bfS~P3G7uv0wcqlC8gjtS)e0RNL z!!L)Mi-k}LmKX;hX$hs8IorRsdKd%IXa81?jeV{D#4`j-VqieQrH|M#f!-*G2uQJq^x%n$KOHC}P3ukeKz@pu((u)0zY zFRBL{d7IVcxXZqro(p~906VPlNIE#YXoMuid#d4{KR_9{s;ieMJLg>}rENzG$FRY+ ze*S~9NGdn=`XU2m#-TRJQM9TO(3$Y-;uWXsa3*Dg|t@)2(UP4#>i;Y0=Bgwhdyz^1h&6*jS^r~oAL z58TGp({=?T@eqA>FPWmh*xd_zbCz$g(k5KlmO!74ywymJB`?#d=NG$T^uj)@g`#K9 z!Q+LFimakwtE1wS@sS!Xg%t(su~X_@Y?N{=&%-y^Lp8)cjCJ?5WI0E&c+4K6C^T9h zAG$jicM+(&8^(v;F)}}CYr`qjH)jBb*+)me0;X~LL3>aYpgQK`D4sa~b2vWnuz&Q3 zkpaf4rlxc^+D=pbuRDTBfk1NHO`gE6b|1^L1VV?YZ1}SQEZ-=}!5wn|K>ja(-wJHs zzeqgqy^vljbv*ko05`iYu?NM*5V87Y>C*g)n(9%UWBKV8P-`gCjy48J{-(9*$bp+Y zkj1fF$4{(ZPn7TfQ~et_kNyqiVD=2zMq~M=ui3$sv^Cp1zTF6CJLYmZa77P*PVVmY z(z}6V)dyl|p@&{peIUBa(96>M;_mGx+Yrb%wu5$r}dB{gB>7E|@#F{NKm@ zxYXMH_`Xw^*DtR#e4AS_+_cKX{liN>Yqeg#-M5NEQH)ok&&XkK-rvi;R{mGz!1s%( zkodOcKes8V{C@HB%l`-EgL3Rs;Els*U!W4>OZjU^2zkn+yG5ji9sX1@44M#s%R zd96Y?Ay=Fe$Zwy2pnMDuuup>nADt3W%z;5kB2Eh*RCj83JgtZokXW;%591RMk_hmF zYV|yM`@wWVx|UwQO|F*+=(oSmQG$zVN2jVejtAf#9JT@ls z=c0cmQM{iC-umngOE>mJh3dS*($P zEkOymgSF7`OcTVL88IM9`H>1b1~*cp`R66%H%|HF7^m?v)QbZV{RzBNUF&hN+@+7} zpP{$E{?e{DsnA@S+z-FxRZD5V62GBitq@)hEMxF(RBFqL&&`{7ZiRDbeO>gV73ZLv zGajF#;491oKKbu9wp;K?mOJ{_80E^73cg$boL`((k%3#>Pm-4+jA0$YpLYWAXD4%+ zTR|}w&E@;T<6Qo$^)PNT&Yzd%2Y2Us;Pdz|R|9v@0R6lVdxVS^XSd=N^NInSq~+@2 zAEG)Zv9_*+=jtrur-;V8r1kMiwsGP8WhR$}3oT`sxhVR>uKbhncse(y0u$}=dOT$m zmk#Uwv}ZVyNR+g&dcR!HKUJ$)!02!>KumP`D*z0`2;R6=?k0U%{@XxR4yelU-_VY# z?S7%^3X3X_Iei@i&ow!9#!3~B$0;b9!Fo_mmINDfS9n*gf{HoB*Jvx6DKlFD;H!!asAs{+UfW5H1D|XkcweSn{ePvogX=H{fV+rp znRd}S|IPPJ)|M@5#%ErbzkVM+H_0b|{ROt#k1X1XAU*P!II;`QxEQ2E!a=UZ>J@}- zygIAnIyR2HoKV5z6443uh+PV1~;0Hx?+qYdbwV}6&r*?3K@D}C_*us=u>)V0fs3(Z=;jn zfLARVc4WZbfupRG(jlAcFvwyRxY25Gaa=kM>OlVv|G;cKa%|0CD~%^$u{UM=8%yj) zXv;9dbp%@b&Fm#_aNs`IZI1zyOub&K2PeSP!;=LVjvTwbg&}5&N zQlE~M8utkQuS(QE(wgn#OIWbyqRW}*#@;+NmYg!J<6gsf`nd!FcrspEdtWO3Bd^Hg zomello~47nelLNbe+oe#n&bN-K*1>2S_QTA*l1IKX6s=zmvR?|Q;`9W+%v|pf+ln0 zwsQ5>kFr7-KV=D`W{f?5HVMG{Z@B+?8t%uW83_ABaL@X)2}GpAKUsg~CE}i-KgoZs zHbhBF=tIM9^ze7b2F1792gNcb9?vl`$Nv}=7s8(lU#|aq@xIZlsg*yn`hPVXfgr0< zKRj1se7pqlosNH>wO3|~FRA~>_^k{6T^PSL_-EaB5By#ie#S9mU0I#~*86T|n44j4 z8Rd)f4O<%a{WEv8Jah4D702x z(sU!CZupU^eg?9AVfuu@lNbf#QuZ*cgSMXTL#gmh?SR?>Qo(Om|A|mj)cgqs<8n0etFhIywfp^J_$)YEeYhfx1M<_+rycWOqeo_@=?$MDcz#y|R}7SK`u7l= zZU$e<;9Le*yu|nU9$Udy;gi(MFJhl??qn3$D>GoLMk!tDrW$lxM_pSNaZ#u{S zq8R>ArNzL1VvZkgZWrfK|4htFqGgb+R_aoVQpWv5?4s0;n64%<(7!LKO8HB?QVbnd zHjeWl+!znG&F#95(2e}YiM zK#=MwWk4=9X}tWDy;4Mhu>G}chb_a#uVk;{pZPvBl#$hk6S9|(b?~3-O2PTrUhJ#> zr^!fk=t@7JCh_iBpHGjdnlz#p8&mIBsN@MR*CWPwf3jFqe8w~@4tf5HnCPoyrPuGb zSg9LDNK5>sc$wm(tEAo&OC*`BMhxU6UP)6-)@h{t>kpYzRzDDB+9wfa9Gu_Qrs%K) z$pjH`_IpLxJ*pavedJ}~wMzvJMiAbYL|8j!kNJH&X1BbQlF^F4k7D5vEg_HmRhDM* z7dYb_EqDKwa35eP9v9TAuVYdS5p+Ie+XM268-TT%Aq<85dN~zE1myR!@>Y@GuOPo8 zSv|T#tJ#U_F^qW%JFoD+2+52efD6_2T1|CAJb;{!*yyunDKD^c(GrDK9`lg3tXj#& z93l&JbU)5Pa1ULm8T$FCGP(3nN+%cH7hk0#rqVWiyrLM1jV(74Da%H#QkZpD%DOvH zqUx?hqKw`6r2HDgL5!%NcxGEs&~FiE$xBj&FFt@O-1wqY;b;}~FoRa8pi5NHj~Vnw z1SMB0>j5-l?~QTSZ`)Nbm(o1w%(HV^hS)1wUkE;I?O^hT#>V#vLR~qx=qXsw9-Z*|eVkO=}hgmYw~gu&md7Fyo0Azzk#7(zdo} z`=OTP=liSn{Ft+8P^$^=%i{fs7X;>O^8j-+VcNQkK7h`ORb58(nHc`OcDhd81-sP= z>8tvDpJwKYx!r+cUqF;)Fhx=+Z+c8zuLr^>?iy4kAi)KoODN z79tEWW~V^H;!kV3ws4?gAb9@>DZ!XjtC6roMC%!8@=Ui7oeD$`o(DuXbrD22NL>rh zpuiQ+rYc0AKO93;KqVl`5aaK%#h_DeEw>@zwU8(U68p~w5oGxFK`bEAi^bh)Jbr^}K}-1!{qe<>=KH2A(}gROD1jkY zu;AH4F&@-OUVCLR#9042B}O`Q9q*9eD;Y4HeaI|~t4|MQOF<#s6Fn0(Eg?k3c!-%J zSYtDj81n>LryOl29%i+odr|T?7gP*lwH`?m0$z@Dw8Y}*T*c8355`CmPzfAmh;eY` zaT~!p8xqA966HYRj3Ge6uaJ00agp39wvZ@SNL&|3LO>-T!4Tt~R7gae-(Oh->XR6R zaZk$N0S}!rn(FASpIG&~9riOHRA+$rN1UIp0JcpIu&l}JGR=0EoHvGb&nl5rY!n!) zMVys+S2&FCKbzPUob*fb%IXSQj^dK}SZ~nYqsC9GS$Obs@MIbWMwp+Yb*z!2><8*6ZqlGTFzhJ zo^@)t$FD;@YD1a7P5`dP@52fI^8X2ZJ)F5#;jf2#;0S4twR$M?_()x=C?h|cVat*2eF5o|# zpC<^^XiK1E{5CChEmJ-yNn^<=puLu8UqWX2A{ieC3qILTL{G9f7wu{E5>%UvbJ`*G z_-jDw5&YPY68W3=vjoJF*Dn(>les>vgI$NNAG$f($C|CFX}=yBhwD1`=^-MEdqOMI zv}GfKYSA^3jKVr>`kp@;!!hsp)7KY zj}+nJ%N{T{@Yn&(4GBvJd+N|yl`cwwpSH|>aCLe`H=Bh{ z$KDc@{PQ>%IN_oEn>&?INxg&<8B$r>qgfUY)D|AWn3Z+3gZfhAGt`>)(A&w(NF?AB zA>et`@}R3DBLJ)DoukB1|8OFf|7Jt5D<_ zK#8*0rDYb{oblYlVB(+fquN28(eE)+{##zO&l|0tE>XU)$hCd5EOPw=j@dr%??3B` z_)^zRYN;z$Z7`+H?yZNh2=+r%sHG<`MGiG6{g0hP#%XA;_FA<{-?$N`{LF(5X%#v= zeSA{A*oNCOu1O}SQtrHw=*&8sE*Kts#-pe1%?t}H{--7ievCnu|Zt{A7=${!$ zRH9S%giCS+zsX>maquXagg#bVRs?j?E6%|w|FoIs>1}WGxcs5*dc)C?!B5llw5_tt zW|0{uSWE;%*Bcu_u429M+eaW`9>qFb_sGtdZdmvtD&XuIs|I7R_f18DOhd*mP_Gb&V^T*60%_ z``J2^>}U`;Ncmor?`GSDtmDV5YIFYBn#rk^*ULg&Xc)NhbS(IV@k2aBIvS%m201=| z7x*_P(x+r9qau&lJjN4jb)dFi7$YkNOuYwHj(Lo!yNx}(eT zwc01q{@dd~`8wE;QPI#r*Pld01aejkAhJGn|ZGj&QNJk5{pLZN_;$XSGhb*XXa>pv%{{Qez4jW~b# zYZ)d#b~}d2y?$*ePUF*vS>G+&Qt3@g1{D96rl|k&zA)#2zGJ8Q%e7_YncjnI(<-{H z(2+FiT#*L{tuHs;`g)>&#Zex#J)B=3hFYElYB6p!*)sWGsTdCVK|8@I-p8@)2Tc)A z4m`;1RS{?7uY|0Pw}Gth{mLSXlM=Vl&7zH_QFlvTOd2ez;;yu>8`{Y>RkhWARsF>z z4B7an_2`fTA=pp*(QYm9U>0OWwl9u!!@OCxnzQ?gS}0AO%6cRY4mV)F+WT!9>k} zw=c5O$w5+9%eir46@AL8`8lZKYCPz}NS&JoK#-U8-2&Wyxr4ZG@#AcRtgVS*ME3TV zbagneMYWq+>BWX=S!cqcjo7crI*{kV&;T0~P)(5mcR7T@rIW987%TA-BZzr#vCubw z#OR9?s!E74PHj&I`{$P7aat^$V|Vr7+$@LovyQgMZRGmFI<(`n40ExXiSo7Tg_6EHyI$NUvuR5+P3)9kWbt?BRIlZ;bOPRLtp6G{ zg7M5qwCap_|8Z)<=uKPrgd`t@Yf&-DM19bvguCZijLhk7;WCzqX4M*Et@d*#2ewZ} zA;`m~ah`OY>I(sk4Ytf=QQ#;jn2fSIUw(rY`4>bKmxbddjBCBHjcLKJD66IfAO8l|G&8t294^eF8 zkb${gJ^zS?OYD`@c=gaLrqtl^*>L|4jGs>-kcXuH_3#8_xyQ>DQ!ngqhqT~RcG)p+ zhYt5Y0@Uh^$;@g>i}592GQvlDVR?@+c47IEU0ANaN;cn6h^}KQ6s~S4wgf^1GuJH2 z5}V?bVsny7i=>K)4W)~fuoSK-Hd7V38ODJI-fVZ}7B1}}Ttj7{&cmm{fRCa0GX38wo?Aul!j1^oFf?VuB z!7IGMeQD5xIF2W(j?HUSb}@1RUY2SU(&l2Iuvc%L#WfQzm9?l;WffF%%&aP~l=wAb zItkc02G4b{*SDx*eY5(dFPEJX-bL680samT*!fG4KnZ&#v}F?CvIOFnBop>e#s8OF zm?Q*055PJ$FRzRL7UOj30oi$ggHx$Q zsNRfp3C6Jh6K&ZmYUvZKM-PKU#uR9H>3_IsM@DzZMvbH`Gm#Ig-3I1J1;Z4~``^i6 ztxe3sbT`(1g2xc?J4WOe=ZWOz8w;gRYll&}1b2WD?f^%-w`hyCIFr+qZJ~G2tbL&-V>c|4lrQr%8FqM^`!&W!=K`&kn zF~lP9Ul8DnWO%VEjKFJD;A0G=TIUJwQYta1btt>5!x>FR#lLK9_L8B{+mkqCAGU$( z2a_0&P=I<{tGSQ`TCCpoeGWdf>MX$mBQ}o9ONzobHRCEblvEU+zX^s{=jmH80fSZE zZ0$xBR=&}{Yt>sohqml-(E-()D^R9cdWjy+*kIgy9Mt$em4%wsfk084f-oG|ss7^* zs|>Of)ZtnPXzGt~Z3;S$@nPRqcTs+;e<&#axG3CztG4WNn9N*W?PqJXW&I8|y0o7) zdh-rw)i{ISX0Nz!>rbj^WxL)u0>UcY1`8latK_M->lWX2haF$#wJsfTsC5pXp)1-m(V|6n*hM?xd2R`Yv`>8s_JRDGrl zSqEXrI!Hs-++3J?UOkAR{+zkI|2qGJ1-B7HXs9j5yp(E#A_(=2`N!nr=#R+<75Wok zC$LLek`$?t>%+eiDH^*-q{!`q$gErlkqI?(;!>}{uxODFJ6wlinTcA$Lg{68V@-R`3@%2y? zj?XM<_?&eD6A$`_?XWJ3pI9LlW}#>w0fLijvdb_p>Xcw+&t)p8OkxmRgH^wX^GL0b z{rl@c_Vn5WvSl=A5a<*mFQS^PT=qn|CC8Q6Ur`XN<$6||C&Er?T@Yy^5 zCQF|?>Ev%(a603)+CMQbj_8jMUx3r`lQLa6(qFS)tF1ve!m<%YmILW>Y_K@{-D9Jn z<+IguHZW|lbBhcpz8a^_db5~_^XY%^4(cqg`E4nj>+`SHtO&m5Bq+fs_;mSLw zjByxOZmXd2{^u;YiQwnTQkAEqRnVX@=Q-eAYD zykl*K_Oiu`w}K;p{wP%AaNuv8)((c_(gc>yBaD6D1B|y{vS3sJ2KLuKfczhD{nF0R zDL+NiQ1Ed$+{V@O-vL+sgHkhfuN(XEo&`XQp`5>Ae?oMtV(E;T7E9l4YF^bHM8PsE)r@rd%zj(wO!q2bBXHE=NWIxw`E)Ot`!*0IDe&b=W;JQU`|%P^L;g+!cd z9-)AODNC?_luYTTnDW$O#gv4`enT(t+T$w5HC{{vrNqAco0k$Sk$C$oq^*G(mCWAM-S77^rn(301q+(iQODx(l|h&voNnYl3=Jx)W9_~sCE*neS^l%6c!@Wq5i6_!I(a$DX{$vkKRCBMHT zNr`8402$)Ubqh3gKhDaez09*R=isc21HNEE8mXxBch^G$4!vX^miZDM3B3DwyFNwk`aX&4ZW zZK3gpVX&WQH5W)vW#$Ykku-vM6&T|m&fjm8_{UX=Sl`Fdc9odpqsixxn>YkEDSK`m zMXFQ}y<^HEmW2S0lUO}C+~Ggh$~SboTw11wP3o%FkZ5QOGcmvim?^X$;{$45R5sd< zX2dbJ-gqBacuRy?bVvtz2ohcW~4l0IEKreH(r*Q*K#R_a0xxP z`bccG*3B6=v(aKD3uN@!@U+Z|-lmh^u%P$s%i^0saqkHZxnTz=ZV17cmEH9^SpbeV zLC#GMJp>EODQMQlg^!vSEU4R17Rv<-DYpH@Fr|Kx^Mjsv-?*X&xwh+EFbr+o>}_Hy z&KNS)&XE(jU+Su)zL&Qd9q0ZN6yDLT8OGDH@M}%Pqn+P>61#;W^-fNuU%4m%981W9 zV)jqa^e~#KCI>M<<3sb{RC&aT9jL_NMycnM<`}8+&SoUey zE5YmLwoQvhWy_Ke8Xy}g`zW+jbNQ)-yGW~LBsvuorIQW?X* zUIbI{xkB z`I^EBfy0#$0D{z_A?CJihOPX1Bn@4Uqy(Zm&|j(?*yD;JeiXOZ;d~cY!_4su=3g~q zp#GzAW4ZVXJMpWzt07xJT@ed5pTXK}q?&&BWs3!bQ_ zwnaBvP>1j6X?o}gh8orI%lLSE4b>VRWVaTjUROOCZ1z<8ln<<>&BXj=pBzu!FUM2O z`O720NE3;OH?RVP)sd4#Q2S6Wh${;+AU7q0z86; zF@0N?4m!v`gv-_I~FX&Hf*5^F(}pO*6w zVm1#`R;$)fgfUu>F|6#kL0uY`aJ`W_CpNcZetckg6zL(kpFB;;9j1r+d<-AX|Ezid zlG}^@7q%Jo+=M_}s~9O*2ag1De6u8ow(FEn8RKy16#zUIHJ9`6%@tg+y{_-*(3V2% z!5SZWuSk3C-rf?_3H2qik)F3s9fP(aGO5RB>#N!d zaQ~djwLgGd8+q?ve2(AmR+TGZI=hIOu2Pv^zef-n&C+ubga+GwE?^uiW!+dk7DYzs zF0`-7SUZgM#_c`QKPTUR8tLgAHyqUXU=_si7&j3|jkz(#1=Y2BV>4*-na@VN2_qZL4&@@&|mw3`KJ$V)(3CExfqH5k`%|CtcHhu6GzJ@3<8N7Y|HO>5ErqCw6;omp`fsF{vis#5opGS{m^bYQ* zOwmPaH>{WIsk&<6UxG^9SJiX)8}=;#i?bwwx9uu zbpJ^Brmsi3J_m9n-KN=nm}?4Pe5KvkfF}|*vU9?{ymcy*pf;>(XB!T`0xei<1L<74 zUV&uz(*pWnkVTF=96LtB)Wv+$8sPg|Fgfc`kUv?PrLR2}_0L~Z^Ic-qi^Ea(S*t*e`T zQXSws-vY!&@y((SX-M?_xDG%7T#gSWd*fWl6|Wz2RsbP=d7LNBdL&G+xV&nZ-hCZ; zvW^UH)TyBP2gWrsxW3U|%_83m632&iMpty{D5dAeC{L;%x0C5@>$Dr{ztXkypcpJM zWoyILXT9;@{Y;dea3eO+{1*TK4QY8uiP|6lU{)gYST(jqek3p^+$@E{YrB70gzBXG zC|v6yT&L9OqKqAm!<9lz^cJ!aG1qH1Y=*blKj^*zh*_{s7ej<19QXgOPhH_v(L*9n8%*j zeYvcPYOB;SY8<@Us*`<{*zBx5%=s_NZY0aQ2+J>S&=y{#WszzxXqtQs90PepKhkS>TH*Zsz zMNr%^k>1ya-3k88mXQOMrUy~?bgSTqcd}9}imAv5gjYmfD+f)M-xvkp6=Oai& z&Js;cKAX$5NzEYH`LDCs@UL&y8=}LiK4n!@Maf1sV2B`->_U>SwAHJf_!ywlPudC* zl*sobvIO5ZZb6v9+^ND=muWd4eWl&974D~q-wpS3xL*LyWdkJ5jsJmyxNNY^f1%Ak zLHR#p`v06Myp{B=Hh&+L=1ai&7m+o;QO7spzhnp8e<1wq`&FKu2*dYHXn|}(H}+I; zZ-OZIhFuy4Mv7Bh^@!TD%OTaEU9DQ`f%h|FJW6u`X0>kS^I*kBt1d$YV4o{?PMz_` zdGHP6iMV}QkQKv=a=Llz_hxvtWo=jJFmQO} z99#}|tjmIN*Z|liQXT*zBU1wi?&{XC>y+TmkqtY0bl(u%GqPb%*X~DxJ4SYIUWv(> zt*GEGtzlOWN!e9Wc0UqoUI_uRrAdV%2Cxmgx*}iq4M?AU-1H5f4QeAE)Dw&aOmL&B()M+IqCFK*es%zyS(7caF}KRY6R(=VJ;o z1g|>d`2IU`u&Wh^x>_-e|uu74KJwFwF5*a9^)?peNTRr3+oo&W> zV2Erq-zN5t$#bp!5~9S!pksVCk?<4dL!GYQeNA4pU%&gG@lOr>~)S=O@K?3PpLhhSUf9GtzcrT|gCv|7He=3SH*v$DBm`9|~)CVl8!=Uk}t z_!r0#YHeui8hp1N8K4J)>jR7QG}*Bd*I>xhhC{TyBEN88$+PN+favxn)nBw1BLQ)Y zwSIXtU8|+Vg>ZWW-`xSYp$!eKRI&I1`04_^Bru~QMBNrfgjSS@bL;hU~zyk{aN_p3ONOTX@`q; z?@Gqm`THya{y)IqF0*3%J&bKV zKHB@Y8DDUR57&sc8N1+3$=_&Syv_r4V`;A7r?AN&_ZGA@*ZiJg_sPW>hgJvhSMdRi zc3pVKPX0D6(wFib93xVmnHD$_m<4+=?n{VV_Tdt#gz_^m&ImO}-$BqC1mOa!(*j5K zYt@_B{6EC#%@@fy2@<6}^fE%?Bg~$cGiPMPy%02<5vmlCR{BE(yD34irx)fOopX0= zf5wq?tk6Q|=#hKV(ZOl84;CDnv3I3+v#CiJ;! zU4kI<$VjdBbi}Cj2&Edotv^Y#vOR>*{c(IZ`5x8?*uBjthS#j8(Gn{4^nG~a`X)AT zH$5rz&;R-Q>-$TozZbIN^_PL56R*G7%=!P%`dh-SMymem;5F;7Mna|j?t}MR)t}72 zcp?M}ye@F0XpS#%_nU1}g=v`MxudDgqMz3}b zENondh;{XKjmaUnP-Qg+G_Z`I6_r8NrbiaMiB@*{oG!t&7!w}pGHWFIxsNxF27M#? zdh-rd{9Ub2qA@tUSz5oi^)7=r%vvF&gHH0^9_6Dn!KJO)5Fshmz83tt3iQLFv3-XlPrs zw_S0eqImz_Chg%>1Xg<*rnBVIsp#%+t=OsbEBqJv2YRd9w3;wd`N9D{BkKzV_=K#y z6dQdNX>w=I$8Y|e+4SRX`rvXV!~Q(%+H70Iv}%kI*26C_2EfhwsXE5*`_IsoM+;U$ zzDF&}z_A1=D%z7EE4r->3`M#$0n<{Lq>s6DSWSB>5Up^6CfpCJ3erO_$YZx8^C=-y zx~XNuP7S^T0dQcPHASm=5Ha$aL;n5+cWbrWu8tn!j5Mr&2indD4Z+n|&-g$wGYerC za%_fY9-3CO8AhEFqa*hqt@ihld&H%p-;p+V=1KU?pOb+K7;CS9j{LyiI=!g`KDqm7 z!%cnr7hJ^3x>T5dmN37sUe)&huy!u+QB~LePk=~xIS~T}1xYk2sn!OCN)#lc3C!q> z2Bk{XR#b}E+7?LyC;t+uySZ);oa!?su3TB~3s0p+C?LaZS80DN%9(ekk6 z5tR9Ve|w*qOdg>9-^=Gi&YW}h*?aA^)?Rzb-Ddd?PP! ztXfY(OA?ng8f--O#UI3*mHxZiIIoVMZmYR&bYHUf&x$H~zubHNXRh5asa?OGng#y4 z#?SJ-gxS68!3e*bHE{4I@aN^c~7oUNm~dK+VFSsxf+a^nQl z3OlxOPk$?~V}JTW@M%D=CwddIgni{Z!_l3==68DtCbp4Z4Mz_Ln|CE|-)@&LqQ@&> zRD`)ZXhmEheDX4*zl>_fZ1>gwhW9LJSS79U-Mf$*-`%;k>&`OCdHY)+l8!A|Ertj{TExd)uKS~zQLZW_BGG_oCn^rh*}7!A~I^TswC^6y25vu^qVSePVUu-ZUM~PBaChp9<|0 zVUV$i6U6OU{+7%+!_b#$#fZccLebqJ=bWc6cSe0T;LP3_e~}0ACg_v6vAQ3>{m(%Z zR)L7gSAv=A%cAeIu3`MV34eO))F<&U@_s%hXCu3gda(WHeWn0&`s;38`_nu5nQp1+ z!|c^=+=?wbW&#B(Uln
    tc8eX%U{tXS*}OOm|?E7KRXeVHEk?)!s?wW#fB;I27A z#;Aa-`lTb+#oo~y4t7Pt?w9wC{S|1q2yPu{ zzZvfHDf$u|_GyS5GarjT>4iBh;__^qgh~TLHrb=+TXzKt+5$Z}fi|&zbA<7-qmAj$BeE#-`0Ep^XKS|-=p$|am~7vytc5v zt^e1C|9p3!0Rm}ibNolFh9P_f4zq~BX$XQOS%Uar;0Q-s!$s@E&SjZm3NwENTX%+`v~yP? zRI*_qeqA&Y`x0Q_5E69eWfE41)9?ryFvVevK*7F1{mNl^Hv;b9Evm9vf+@ z(07j`1V#=IUVuaQfF1XU9R_XE#kuqYoOZ27No@~ot$>f&z+1muK|-qkIVycF zPNUDq-P7k|yffB+oTSgkVC=-KH2QoXI&`K_j_)4Xm!VJJ1z!LY1$P_z4AjNBl(1#! zvy%eUHu=FVAB#BB4ORL7^x_bvbJx!qpqoFKn{G+-3P)%|@)f#>G+HY0Nv{W~tutzY zk0oSVUqh82+7Iv6#iI(}_F@8ATM4`meQlhhD_%0b$GCbeC50219=u~`6#k0Gsw)5SRG<+aqjGC1=G5q z1~-{Hb_ZKO3fIS~NfxfyzLwo2hRF=|*}w-L|0gnM_X#X{Ub?CKfB zIV~LhyUHuJ&shM3hk90*1)VE1H64YcJHkWW4JKano3RmW-5xG@AslsqDO~ab$^mNU zi-E}Mp23or1HQ5&;pofZ=!+;mY60nqcm?Dz-EI9SRR2$kv;|ArYUIbcF7_%6A|0w& z$~`)i$rWT~w<=9WWrcx8{6QDq>d$bm`Z3{;!OWaE$98e5D7$w7_eU5=naI}6m1AetGrB}e z^CRQlykFmtkACKeIQdfMj&N_Mr0t`WyW${9nJCc=v?I@%lmSy1j-m76h7*H^ciy!u z^bwN{i!#5Nyn?N}&?LgnL==j(!Lv0Tv{)@K*t#QFus7)3kq8tVp?skA{ZPUC!9IH= z%k|Z#;XW@)$0VuiCaX}qNOr@*gLjdbp|$$N>3%%RKK5N_{I{$+Jw1q5S-U64C!PL)$gmg#@7QE^AcmUooM^z=5>SjI)Xc|=KG3rWwpzth!pqh zO-eIvlIvq7tGMTBRSi)Yj+<&p7yU%xB6S}LSV3?FEad9R@IKn``|8Wu2VK1ArW5%kAZr!31(!sstLqk8D%{QBotJlu3nty}rv;Kt`uG{A2m6XFvYRE6Wg&}|ILmh_v zUpIS0eyM3!qdqe3l17H6J)h|Tk8vt;%=t`=Y5T<3N9TP-P!IaBO5XCL-_#{KlcC+i z`<}sFksRDts;o0$hI}^(Sp#K(>1ODN8_WdInI{e>W*iD??S;hs3Uyec&!_Z z?z#7~;rpV6?|&){Hh-pz!RAxu+jRJPrr;ZL4EQwUy5mYQ(4uQK!kgVYxi+>7EqC2{ z!co#WBK9C7x3kn~znA>ko{~SKto*TZ=J$n04k3T6JR%dQkrNLWKFQU+c~@uoV_w7I z=5a02l;cYcu(&;$e%x%db`LUQ=c;+x{o1Ib%0K#WDf($gKE(W0v6fx@Owt~ ztWTFc0c6hwl09FxvS&B30+KyT(`C;EW>M%?<{R1bZONW5BYV((kv*kCB-wX2dM^zE2-B8&uXA;Nl$V z$)5`Cp+Fo7&y)a4Lp}aQPS%vK1M~SEVUBF-2Ik|{rt(Nw0WJyDE`J2E8@ABC@?8V% z3SA7euYONoro(zVC9V7^G2j~c(}iz=ZrRs>?uS3@fYJ9_x`A${X~W3JBtFySqk-=a zR~l@dYvCK7f^Sq8_#%|F@cjfIQcpg1fv-Dm7V~7`fW?*k3Wu-iD19zJR}dtnPh;$% zV~QUyKK;A0fpoNAp*mQ@l=~B7Aeqc9x=P(J-Qn~$3nziM3xJ#ry!t#-#GfB%xD$I~ z)|bAc;JI4Zn%7xFxJ%|et1zP)BN28+YoUoAR)0okm@H^gsM}2f$nI9TOAe{2Zt)j97K=?tF%`jzU}Xw}ac#H$=hpr(LZt1K|4f04 zR9m6-8PJ==344rX#{KoR85z$GFz~ElT_XsG?c7<;`62(bl%a!WcxSzN$96$tAw%0p`CnL=299~k2 zfghWSZ-+l4O35Z%cei|XpEUVplA>AP=9vg+vuKSSEC0%Wi2t*$0skh0jL8sY@PEx= z@PDs(1Nc(-|Jv8V|BvtOivLLDX!w6TVDKNg#^V2aecX=!%guM);{OhP*pB}Kl{^~$ z%S|H#e(Fo&|Kr6ex^}^To~ih=@n1~dv-YX+Kf!;?G562wv^5oQCLO_$a@w4MIAjMU zjaC}@{fLGELErVaQmA%Jv9CU&CwQvVOeJYxCcCw@Z8ulridWGi`5wFuN1Nl{ z^lAUo6uh9e?Yq^)@_8jBGgKm={d-k(Qf=GZ>Vc{EIo|sb)R&-O@W7T}^TF{lq+jOb zW<0O&pu`J-<`1XD_%I$4kM zojVdui1J_Prab3=T#fQ@Ujw{M@UTg)=M4CcX-$dm^3=P?xbM_@Oeh6K%Bg3f(GP+pqv4Y0PJ)7M}7>5VMP zNfXo0Z`=*S(f8u7l{@n{8v3w5+GqAqf8_7^6uil|_-(k1Uw8TL`3Ju!_FMlLGW?I{ zCRp;SFY*gIf~Udz)V({L`CenV7@2H=+qoQ6R!-(&#)n=Xc)n`+eAbifNN;1_lU+&ymC(IWl(<4Dup z91;5%r8%kerd_Rm^cHJV^dkny?MMc!k%$MD#FEbn*6Xd;NInF9j$EvUYYz;6wE)}G z&28f&J2^OUrB1ewzJ^L0$Nlq*99rU3B0Bd34!jj;J~BS?K4n((B7PiRO&rj$DK$*RxlMptC z?@ICT6rSY7Ph^vcHTYy!Z+R*;>VR0{ zG1vj(^hsihd+&I|yos+H=G~)G)cRWB?S zVXwIaQ6c|T*cmp;!qS0L7)Q>qZI79SdDU_j=J$OSJej92+NWRF(>r}T7C z3O!ww`q)lmc(L*!uLsQ1HUDQ)J{SXF7ABQCyJ)d!j3tN*oOxJm## z&_O1k0cLtek4V1sm`$IujZu4UEEQRDR$#y4Y_Z>!65f* zx)|inGT)@LXtPQ>!?qe7-P6DF;Y^)EhW@o$I$Try>(5Hh9GP%8DdnRx=yxj4M&LOT z2!b#&?j%#S1i}qJ>mU%q+`88pfaJ+$s!lXt>EzaGBl=3G*CgcI2H(9(@5y#w|Kt6U zX523i^_dN2vvvgikM0aeA-lL!Dezq3rBnheP!N;LaIlp^`d*<$!aUfOGduMmUo|*E;$8tYxy~x zS#u`5BmSgGg(jTM@5cN$9mpTw1FN2ei8G!r=1=^1T-3Hb|8@QBX`E_X=HFg<7Y=?L(VFz9o^AYxQ4fYF zweN;}-rO`RhriS3^tH9T$P4*CSND$`DXu>8`5RT=laV7gR-O2Kfqp+~hpRPPrT?Z3 zXU?VDuvkj8xKH4U)X{xH{w=Wh?Xo5E$Jq08%-=jFT9!=nirJs&k0%>qY7bs!%$~FP zfD{{l_fTx+>37I{(-TwG4+1T_6gEme*I9Obw+cW5YijeEV)c(@U?P5e>5@?_O3g!w z!um}$r-9}?Uu21jH2helnSF9|8p+h6n^}L4-x6qO)XzZF_zRNxI1n`jlh5&&BfHae z$^@fwm1j^xj|2|##Z~{H2`m|FYBkgApHMS`0aMIa++uvi-5+QiC2#7@&BkZ7uyN;_ zo3-}lTim4Kup@t&(7u!9i4U!NFaT>gU3;Ru*jdR1qWh3V@~bc|2d~Sj*NT71k!r$^ zP1hEjfa9a-?sKsv=o^eL{JnhjN@kFbLx8t54>UYubeE#dfdrN$bCW)cCpJi5IwkB( zEuOFht4m^KQ1W5uLx6T&*eTtJe6THF;I-_FyiJ!87P&Z=tO^qCTd*fsa5%W=kb&zj zF-5k8oL)Z&wrtn<0lwMi;e}>P;`iv4obRh#7>qR0Y_DwEjK8dcYrG(c`17IY64lq( zEfr4_6_fVyuEcz$J7RkHNYd}c3uXUbYbpCo`pxgSVa83x2Rx*gPOla82lQ}s4m}Cg zuda$i9`GOg$&vQ*?sq7hMtnvQVr|gL z%_hb+0g?O5XGz{H^kFRuPt9!0Z1Q&LUmQg62TA=Deckw{93r@)Z;+*bY81$^qFt zC&})gs@e#M9UTM&?n)D&F#2hG{lCz#bncYAIW-Y~f_kbRUmda4|J)nnp-h634a2tM z&kUFv4Q@fI|DjAX&b#HU|42e~Vyc;A$fU0Z-08_*5q(SAstanL5g9Xx$E)AAz{d`D&qQS9 zMwWH#5B5{AxjypUzmje3;{qIW9{*;eC)?#;(Jt*iTi)j!L*93y<}XOv>>Zv?a%cto zmQ?OetX#r~(qv~wDe%3xI%A~ATMU2$Tg+*x(@<)DXww}h0!S2=w9LNrvW8qV14e|Z2xPXYQM}cI zzKQ5B2RQu4fPBP!#i_56wuDT_qxg95?EdtP^m;0ltnvU{=2UeOIv2M#blMZKcEVozNAt{o`y!%ZCIi=4=yWFe9B+aoe z2Ntc$K+lIl0pG;d0FebP|0FF`5BuQb0Ir{bMTd@HIhu8xS7GzcQK@`=8G(Ymfj-E6 z0_2v(#`}FwlOc2)%iR_ezG*3Czw5%B8sAC!;;EK(&z57-SEoSzf6{mKz|TwH=fyhX zHPQ-R3oc9E1WWc+Uy-Cz`DG2GEQz5gMxsts4&tT1BKcvcWOMZyhRDO2<+DR2&9eu4 zSWJ~sB_j7;kvru0&kRNm%4ZmI!>2(g()!O(!E0&c9vZ5Dn+=8N-pKoq`bZk7_lnee zv0p8OyyI_h|>Zl$GL~;bSw{ zVkWrZiw~qWn~m2&Kv7QPwLv%6I4Zig>r=DWJhI8I|6kR1t6Ge3IFV^6n|5>5Zl0jX zcc1B>OiU=}V~kgNgPAH{`WH*a4ii!*CYFB~o-Ce!>hC!)i7obGF)IG4W?Rtlu51gB z;W@O;uRcM3YtwxTRuVY<_{(=?#7`2*ef2s?+@zV*i$C%rJ)LgA)cSB?Dc5krP1)gw zqAQ)T=g3!D+7mwJkx%&5$}fHP2$+!1xOe+wZjC?n=3wgwaw5lrynrmRJCeT7p@v88 zHwCW-9m0{!+gNJ*C&ZSu>IfHn7>0mow>$KO7EIxS_rmpCgC(1N^?%oG{YO>D+o*SE z&=XF1MtnH0c_eEBMuZjj@~D6E?lJBdSpBr6{)h@RJXdIXT5_QB0?}uNIbU&1mgzv6-%x912b?Q(^k5r3Z z5CvD+^+lq(AK+WJYmB>n{>~lYp5dN%vVbT4IdL=26CwctP&fd}sm znR>(!i;tz)tsE3ukNbVh3tx-=3upcJR3aGtdno$8`X{i^PX>73Sw;y(mm0^05cb=- zif^2mq^kk=H(=ZRc#J2hER-UQhL)GcEG<%%g>VLyI65fOJCOD8Iqb*FAie zSA!D)e z^0zTbqM%#|GrWE1s0tw#Q+P>M7PggLF8ehUiK4P zAsJQTB#_O1JYxRzM(>(XWVr(dw zvw#5POhISJ3l>Bd_Zt5E-^0K}AXu1U1w#r?BGa5A{+3r2i9X1u5bz3}VdT@-1-!-W zCg#5zDe(=CZ6J&{?M3`@9#5|>2ow>qyJ-cKmO|T>UV`*OWk$5!T1|*>s(w=UThZe+ zVa~QVEMX!9C#8%Ko02ku-bk5J-@_dA=#3w6sG*@v)LXSB4Wnv2xyBn80kWMN{0}u2 zS#Zh#0}G)RGrUbmmpPzbqprxDaiOdjV-#{%>MqF?gC$KiMj#kJIW=X2yNYz40a8Jq zK+w|Izp)Z^(wx)R2U(hrA|Il--7YVC{Xq;o0@j58Ipo-Y82UT0>gHHEyu#0KR9`B; zag0p!wl?Eh$oPe~wDRC0kWbSZOIXEdw5oU%YaY zsm}dQzx2xRU?8L0-pUJg#)*`!vL(qgPY6jwq+nsmI(!1k_TVKb+bT^LO+m?|wS2L< zSKb*oIOJg$F&POgc0UJ{hAzlwcN^P}?fnxYju9i4iV*{viYmm2lT4_LTq&lyeG)py zRprE5Vn4GAtPuN6G7%$?hJt2%#U48L{+#9~7q1K(U$~qB!~FDP;hg!YQCH?CbCsjW z&n2c%ai25=I1|lW;Z$84u4S8wW&C7D5y$TmmS- z1M>@6YkIX4BS;+#L=emmBkZQ=Gp4ht=Gwsz`iepgLCt0Tu_ynbi`EeWp zi|Lx-KenA}a)XNws%BrL)D|ktB&W}FDx+2PT!Y=+^YchQWsCKv7(D#kSdo;XD^#?6 z%sW*~6qY}128lS{Lf*Y^**h7t1`|)-gLrZh@jPH4#R+L;yeCNZuMfum44C?$F6 zn%UXQXd)wiP9raT}=C7f!hfi1WEk))tQ*!&2QL(^~WNyO#Ig=6a3~= zyMfGhBhX;J!_2v0Xuzq!lxp^iDo=$~vWZV7As12n7(rLif~wWO_@A&Io1Gr^S5$ZO zpxyWR4mX&m?afW*#@juf%uQo=)403!kQJ9~>}h_N`fg_HSf=J=#fKcU!Y@-!)QdjU z%qQVjt1H6KT$zoVbdRpIoom^WI-0u->q4nL=q9$(SE%&;zN(ZAr1-zqCcD+CJ5qdRTtcVLRVRJ}q#@_)43w>5 zUubI(r=W#)%*BR4b&1nQRK)9VO2C9lw)z%VP(m;Su5=3fg`pTsFby>s8JqG@yv!Lo zFjTUma-=XYRZ}QhxrO+BARc8PUgw4YSB!wUlwyK0;2GIiI^cbt9mK6sdl%8YW_-BI z&k%2S>YM!g0%D~Z278)~=f)->Quvz9j=h!V2wZGG0)W<^?ql%fzOvBh5t*Rd(p&({ zWRD(}WIh1_>Qj>Z{%3fA_ENTy;XS`EeO>-V9>lYjpRJNiFBRHcVP>l2&@FpQ-LyNJ(^qqfk(3xqpq0>_}WEiNM-8>65 z+K*bKuQMTQMsZ|i@g++pXJp1MfLo|z+Wa}D4mzE-_q;i9-~)Dn@FQhsyFWYIJ3>Vy zlHXf-o;m_Iqc(anX3+~0J*&WNHV%p_!z6cO{a*4~O(;wn$%K2+Ul8MPr;Fl4hofS~=))cLT zrn(O4xVzIm#ZObfDrI87ZA)A0NWOaK@AlO=Kl=H*8x2oCWh~Q@s%7F>PMyG!qcgj4H+XZRbPm8Wi403`ms~t9LXw;&~V9mL>f6$yb+9ie}u=@{t+r!?_1m( z$sno)E_ZU_S{V$W=4j0pB6)iAOS5eAkIticYSQ~;)1n~Ks?PgpX<;od6)}Un68&?G zZ@72k1*IXB2~qG%-dLA76a|TRG4;0K|9Drj zN;BG%#LGDsRrWNsEbT>o@D4F%AR#0f9UF~&W_|qJUsR9|U4>78Z7`J2X!=9Ety$slPtW8Pw zS#oMBqkwN>q;Fu1t&EkJD;t?D?vsP`Xq`J^@UaG(TeSBWV=VSNjEQNM1iQbe^?T?2 z#WEebSZ8pjT?uIq8depCsp(~@=17QGrMMZ^yKHiLOWthy=$?LOlK+iCic(@jQ9_tj zZ5m;X))seZgHm*T_%C86~K4rkK_c zobjY)0%u={uTu?T_Zp_wmRW4zB;w}_ZhBCoTE$hc)Fi5ePw9y}-Bc>-r~rqPFd9l% z_bNVH;O@g1-2`VDcs*eMQ9wftw|l#!o%Bep!t>SO2r&j$VFgu2c6U)LWe?6*Q!GnV zj^R4yv*M%E^v^HLLUVNeQ#c87s&QoH3(|T_YNTzjy8k&|V1Oxm)nr^G$n($T5GHw++$aHElCXx&Hh2Vj0=ws}-e-w^xF#c(rKnUCF zpD$Ffo~eS}(s04S$SL-hZh-z_?iq$yJ>INxXOOPmfgVw z>o1<;7c+%3A)Nsa5krCJs59UfCbq&Vy0URUNoBIJp_SBV=Hy^u&A%+2s=g+cB|5C~ z3Q0`E6Vcb%>@qwn8_l&DFzl?^Nrts$d{5g-#ZN~2M0=U34Xzo&6SSFYr-(pwD`KiA zIk_s~B@@^IL$y%9l~iqsi^%^%Qh}y^cFjhBtnQVAGhJ0qCTI&b?;b1El{+_* zA?k*l9>L}vy{uYMpO}A*sC0$qB=zzlIGP#A>!6c$rvP}M+V(Elwh=W($&i(ilw`I` znw`##-6k_mePY3sWR;h8s`5-#>F-o!JED+cN2!|R?%!k@kM1+sugefAWA;_|es(6r zi)TGs!3AB6Ui_m&h5jZJN)yhiY*F zLkmlD!$d3u4}1{H+$4RKIVMQ>Q>ci1(nfO)7p+y-AdulxB^4om(We&y9uRO|wsPFL zu}afDqb?)OZm=5R6f-)T(E*p_4)Hq`#Y-j+VSN>gA-aQ$+FY>eb8M!kSqLd$YFB2H zFr}1P^jixi##lkxu5cSQmkw|MY8xr)4gx)1Yq|J^?+i!R28&uyL29`P7Hu-~r}_h# zSON;gsFfHT=~PzdPUYH8F#za~#46K)K7#qYo&`A82hG;>Zj$Mp-?>WH9@aDrEWfSED&#H-d9PZ3%l0y0PxbkK-DQ!pXp=g8ndz&<`b2eI9nSrv6BSRN zWvEE5Q93NiK2hvShbf=l>t}wt``4>4zaZ)l9&o{Vwk5C-0e$_B!9))a6VP=n8b7Wh z(rRkOfS%G{wnRSutQOws6_#vUnX(U+yzRR;LP@Do=(0+=nPV_OAm zJEW3bmEA*!d=Pxh`bnrfAUg=ypR@tmQ!~>*OG0&2XzsGm(Er#SSaCYd*PpR{vu;H9agpx~o_p^zw+)ZtHxe)S38(qi*Efs4n9{Hotp?ZYfQmo>ji zM@amR>~M04_P8n&|GrJk?L+1lFkp5mkScN{zkCQDnd{JPTHh%vSaq4xzb`g#Bo2#B zbv+Qct;Iho6J}bO_x@1aHF2uIAA#4!0q0uMuD6}Cun#5#zwf`Tg;Mk|*$PjGaSF8x zHG->=lnht~ea>|nuZ-+s$l50uIoP){zYOLtERQxR9-?la_>qAyB6#3+(vg44t&n%R zw%N!+8aWKa>x{Bz?X>>Zo#h4V{fYJd=&Dw?tYB?82V^+F@Nih z@`C1aG`%6!ryBd(3EWhlDCPBdYyjJFo;BOP@w20xiX3f@ZiyFktf)NN;&1(+ynx)i zZJETOl7yw4bHsa$OhgW3qAqG?&?*+E&FG=%W_ONOrt~)uYPcj{9V?ckPc((1m*lq- z$wZ)c3kdBnK1MR;gT&?EzyG%jQ!&X zA7VfFH^*x`!xAsxh;SWygFI@rkKWLuiS|*Gee|pzjp9+G;d4lqBlRfHu(^AfliJjm zY=(2Xb@LXx?_<{oH(35ezfl$n__H*{pOFOqJ*Vq^2fi$YFUb|+`&(=JQ8DtEjvTpQ zJ`p0bu)T>n<(F%jGtl}@D8-%Zei${b4C$KU&Zo2d>D!dgMO7Qt9sCfL z|Jt%>IEt#CWKpR#@aPQDwZh}kR=VXG;4F`h>Bys&U}-#xQ>SaZr7&IF}M^- zZP@fB%ckQ$Hf%a~B@FoIeTGfXv5&sOBcngK5AobGrl^(9nK$k1Ue3m5q-{weHDP4M zQ^A!)2pq}vMgAymbO!x=&^&sayH8P?L*Y&xGQprMle2YeD2gy);yZ{R5#gG%uI$t^ zjD031E`;u5ta&jmw{ZFkP8dxUr^bpub}LNCDR5oQEmyeY)@H#c%Q7UfFjg$#H*4p zi0ge%pMw7%-`|5>DG@uM9@TG}%|g5vQ&p*FKl8vbM`Qp;py8`*w3Oh!n{UABKPk-i zEYS1`a5%=@KcfRx1jKC719bIr}`=Dm4Beli}(XmcW0Td0rsBs2BoKu=Y-=UKeYGTimt zw8x{Qt?zefRd$s1y*Ag+F+zCVLVv*bT&qOtf!7s(w!Y?kyH-yGTH}F&w_yk@HD;hQ zGTd#dwUaifj~mF8V^;Wf3P#EW3z(={ahumhebIW1Xof#ps)vb(i8w#`AtR<(l|x;a@I(3w>8L-pQ&0Cs7*Ga$RLiwp>A1? za?Sh{uK%>UuW=6ORoA4L&Xv6C!&IwJv|Z0gvFwQq;)GPb$G=O+wi~aZhRe_hMYf_A z21F=&S$=0a=v<S&q7NTpB4}V5?Jt=PVgo3t1u(^z^ zIvfOMkM)!5i&mp-%1+Gh1Ab4U5E1|ztj3Hjw97Ckg?NuqR<-zz50mLsc8x?;Qj>r-CFVz%q$w;FUaH zn<4=QHuqL~WQc_Qt_oGzeVR@HvNn0*hmUlx54Zc1x)V2dKN8X`5V4+CN$#j06Z74B zSPWP9*IqO_M-fEd8hpWM0MtRA5v$IF8^G82n{t{

    gu&E*aYw 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†Qg2tTjsDp;*aqs&gPin#*G_-&HgFEp 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%0DY1J=#w1iS{DdsKG_69GZu|_h~FKt(kuy$p(w%c z<|H9*l)nD`>!$Wlzz~+8IX-nt0O{Inga11yvcUk|AwW_W*t#&%ZDV9~VW94Z=H${b zfsEgoU0Qf*q%HnHDjCMDC0(eB0BlU@zKQKgRL7wyd9&qbo9!J*Itn_{*JE zpL8J=kVky#lI9{phv486p|1E80#bqHKgN21u10ZZ`Icdz+nRKH*0oX3+|%=!UeT&D z+FEhZsnbR_5B=_QA97!tCDs?-qNUY+e!O%Krn(PTHWS$dx)=9Zi)@$NY zmH-Grz0&@0I?Ca6{HJ=PsZ?pr_grFjs0syx%tGP&2SV657s*m+hR4+I!ob9hfGYPIX`ZO3EX4CH`_uFY`y!tEMZh*2M{QJ|*go=nRGw=9Re1AG0jpq}rvf~en{rl6M zvKbnV{pn8TNn`udy?(kDmzU;4T+Z8Fi_0+|L0ta4)eK>QeSw1R#xYPR6wPL3Z zEe+F;PaXLsMV7Q=i>pt%Dz*3&JHWG5I5)?r3vPR`%B~;6LQNj8I%OlKo&D)f#);jZ zZiYyYP1e9K=*Km5X3a78dHEIQS3>1d4_p)%xMG+rjplR<|BV;84=?ZrPo^50(_IwQ z%(WYeKdno4)y&o5LonAJA4tHePxPX%(9}ZN2fd?LZukIK4#kzVoT980qE_@zJ1j9X zrde?(^rs`f8eg{J8?vHX68%T{GTOI(Y1TT@pY=;m;!OKtDTS+gFHSN(J6v^j6z+_^ zmp)PQZwJ>e4fsY4FUJwT8vHv{Nx09&IA|JWjIO-IdOMc;~8#c*1)Zk!x z2j6hiPV8^@qUe}L1f`PJFV!t~MW9*-wk-k`?QeGo%v?-wJ`P6GCTyZ~`@RVgs4tl1 z;2VL${zyoC5`!~|P<-(?WXio1U4Zv2^#iiz8OrV*$j9nBKLTzOOj|`y+j$2+-~;oap+cbt_|5oH?Y_ zxvw7kztK9wD&3;T-ux}tLgSZuj9efpzLBF9xpmAOGabx+-cGMy>i;2ChKe6mY#7!g z7;beL4lanyjvs~F-S;&loKO8yUv--kJ#S;Mmht)5! z6@Qs7Vq&a7WtwhQu>pxsZ`s#@h?U31hr0OHFXco2bXcyIIh)$-jQ({`EK|>m)h~s< zAgDDI7zRQ_6Xe4MM4Qv=U-#;9dU`|Xj$wVdQBUtZi!i zm$uj~mjELE$?BK-Qh|8HhfexVMC8dhxJ0BYK7!QoJ0hf!QFT=KsDJ;usn8kGz=L;uXlK+fo%ab8 zoTGl}Onz=`{nDhKT5O)R2gK%#4O(mto~P=U*4BAQPTM}6_N-Y}YWsBO)-Qbz*&m&z z^y5Q&yh)Lj7$5qR)h`YBh$fC5Kg>LnpJMe(r!EmM>j17l#9#+8-N3G2ItpLKg@Mwp zU;210p2hm5k9cCPUpl6{%~HxfL3ax4+#fYtwVVrWeBc)^;)+pc zMQJ#7VNx32PL6n{dkQp6hoX!hu6@#T4jt)7?@afDaQjJmEjyQ({b{^y6x>Nx~jQWuPBfD|@08FnF`qxQmd-azc};lQG)1 zd_S;0i}@m%eV)g#*0fES@*iZ@v- zY==?9t=7{}4ENc9gMtkm-~FP#`*-4ZTp*tDkXmcbyc)3v69Pv4Tq^P4eeJSp5_cjcZRMwad8UPZ55M-ovL?vO!J9`3{bImLw2Op~cpL zuLwTX`{)?Yl{Va@msbS@R;7=?68S&&F@JtbvVR!scRnjYkUe|SYHo5k{=4ZUNa#sL zn23FZYs@S=X5G<6u8r=G3;t}HJz)d>ra1KtUggcH*;8)d1*pXdgbx6@TL&YjXO#3> zJhDUc2SR7GuIbaf8Ckh`Ak?C^A=B!G2tFk~ z(y^!zFhS+P$jKSO&?#A=w$E!mwg)nP!F0R;Mec#03O9GcL4)AJ3$ZJ5)fF8*uaFo= zwH^@Ay?_h}qbRio!_>k0jfOd3EKSW**UELcrr|`q#xz)$SXB4oV0ew%`N7Uhf}NKZ zqx^Bx2h2Vx?zkkFu{ao79t?dV_eZ9iH0CDJTiVs#CqezREDC3x6neAoOVmLn6PIL9 z8IKdGenGLzWn%spf$D`e2omIaU|N|j%ZX%eeaaPqxcR791Om1X20|fH!Pd3le~C5C zV-gSizR7qP{i89^#LpG?`XGDK(U5vl0Q2a_GUUf_FbsJ<3t-4(#i6URNmW&Htqp3L# z6Hxa}Q)`xdf_RcSf%M9Wmm@`?W;u{x!O+q`uT9sUOHoxDjGWeN29f>(?d`{JO!W;eQ|}$o-1qQ|JMO{6UU$VU&s%fDlLj@K-6tG3qj)XMb4+ zs~mxfcKhR`>eQ%FdI*VEDBDulMrqM3x_5=xU*_UunGtSUuC|ce)OvANAdREiC7!CoV!?U ziZ&^bgm0Be%O-orW0JTqP&1Flz&x5Sc1!^CoyA#d9c$FBpyy*BFq20d?ArRVF)b%-C*()lC^Y1L zo$TM7ee*2d7OzlB`GQqpTScH2v=%rPJ1^u@rdP{#ED?!9<@eePC`j4EdJ|kGa#&|5 zS6KVJEGuZLT4KH0eef0*5sG_xH}0>p9G|Ps)@v!d<|N8ZJR2)9=H&hI9QZ!Fb8Ib@ z)pMr@R9!<(iR3}2&#+DH@e4Q!YEjuQh;@a9-={+-y{_h?QkecphtKrVS`Mqj3OR3l~R2Jr4y`6DRR)I4N~XeRo~DXy)Uw7sp5$0-(ah~ z4$@#fXHUG1_C}2sb}PQJ)`j`b2aHI z)>vSX7y&1BUE7dV6wZ+_HH!p}=PW{k#nmR*+ndZ;GOS7Q;4Oj>CsYYsirJCPO)gm} z^DqPl^E_b1W9=rX5*UoUs#=p>B!;1ISP`RR+^Bkx)$TsUsEd z)%AzOxSaewdUSI6eV4SS(DHlY+^UuslS6XXp%jot)v~~%`Q*<)cF}u?rbXJWh@6E= zw{M#VA}w!HazD~+H|H&Ep@iJ$WJb-^jjsiVR6g*6f7` zWhD|{;vcH}6ZFP=VAx)nzb=fE@0lC$xvHF;QWl7u3kz}_L~*axBU;c^8`DtDTfr&M zY%>Gi2G|St-Vg|_vO0F6v_Bg^;4c-%T2X&GCdV`i2>0Xn*TVg4bi}aweyAn;rpF=K zM?9W}WViC}F>{DntgnhOyk;Exm=b>Fhkrij01`TpPrxiO)%d{^7~L-&W2%u$p;7qf z-ATs09q`Y0#qE0z2fBUn_^0}Ami{hE#qEZFKAV(=x06Gj$xVTV+RI4=QKo&c_D+AI z?iBpP8^80p0FSll;DgvAY zxm^Fhihn-k;5Y;R`G~?l_mA;hqwvqE{`~eohkyQG9R9f{zz7i;-84wQ{tzK zf6_b;_vwU#355eRnX9ho=y^p_{PTqr@lV*h#6NK`yv84le?I8OKlj}(_~&97@?$s{ zhHSz=zvp~s7Khq2>=6iUW^m!+=P0%o;gcEQj^UrkwKCfIL_h2bub#L1%Ah|T{`puO z{wbe!6#n@DbjZ}4?Tmlk;w!fPB>3l}l;V&t#6ORpW8)f1du?7!@pW!p(TB+u(1e-!??b|xsy^jPfioCN=TUE!ZNnCAgv z-3R}i;b9k<@z2SM%iUfYxm}pcsQg7_yAu+)v}uOX-nQb9sz?tT|h zP+Qe0AT(zWihTuyic-Kc3+ovsGYtn)zRm8ol;{3As5nM_zZUY}-3}pt>FsF0@>GL8`GE9oiHLvVyJxw6<<^h9Fx%4enQ7<4!{!@^9gU_37?-( zJ7NzP;K}5ZQ|`4VgYjciO76+zvI}?LKGSjc4gS-?_E}MyIZsmJzflJMll)Oozo~-> z&zP2!2}`G9)K~1beMbG@c;8V|zSO6*zupeZFWtX4hCJpQ;;UDEWW-meO~*J=!&hrz z2xEcVii5&M9Qf)~_1*1>-}&IH1FIDs-I{y5;;XZ%APo6iI+MbXUz+a}P*7z_GfYb) zLkquX_OfEfVEANY0W5-ipL3UkC!e5#f+mdxhhDiA6STTTj3-MQCg~NON{*@3;d);_ ztp6XuR|_eup@TCoEpXziFEs~s;_%gnKXBr!A0YNEPIY?urSo9Of}7{#U_$wTug+Ch z)OlW!3}4-4dTRJ;Z}pJl%n#WK_-YZ2KxlV6B@`cECNb0<$^5j33tv4lGdaErj5~$= z(!ldV`C=SQluyhrowYgvUv0*Ohg9&@4)=Tb5e|HH^;lmSv}5tr0d{SNDmRAEC*OGra$Pa%#^J&2Z&ceZg3Cte?YM|-u z*$)kC61AS=GEtFx%S_ax)z6P{{oH9x8qOuZ$p@dE&E6GJ$2MJj_MWTFBuyKiU9J50 zN5z@7GbQ1_PnXZ`{8VFJs!m$n?7(N&et^M2uLjc2Pd%LcP(GwMd)VA4w@Sd%9ZQW%2^Hnx0}5{vsYk&UjBk!pt+MEH>XWZ zXML7bnVHGx%d7Pn@6WrJfbuWHDd(@+sjI2?=N^kz0de>(i}(ePdc(dm`ss9c@c9=jQY%Eyn(^FG1B<9WVN?!I?` zE#rD6l*PJd|5e@pZ(jFL1;tgj;~2U)x@X@C>OwyzPh<_+iL6qZqO)1q{CY^=>|rRf z+W+H!#?jB!`I`5~x}J0{R)wUs-u#%5>lPf$`g{C#1PLDc|OA#z*zN$0R6-j5fP5np_{wmou?*_uWv1He7o2e#T z$*#0dkH?QpqXNu3Vv|-38<#>cocXj?3@xgm7;d;e9mUXXxS3;&ilKgCbQ#$AT9&S7 zGwFxXSD5iNLh3MC0Vr;~QGpm)W;k&Z$Ft`qQKVU<8Z^BW8>V059~_osoHn-W%>Ncq z0(>{4sy9Somb1PeZ_;{p7L|});J*weCOrP-I0(RtPRy|i|M%3FEA^K)p-{LTU*PYe zq|&e4x6Ffvs0}p{pR|4xaJ+Sy7a(bf9*P=B&^1t+`N1N$#ZeZOne zvCBlhR+`5?0U6|b#>W2a#H3???mCS9?O#$FJ7+zMQlK@ZKn~HjTt|*;ixfuNPmNa1 zpS?dB)Da;~)E~m5E6TI$`!lj9{!8Z9o4v+e0zN^3KaA}Dd?!bR|Fn@9*2d*TV1Hal z7$YIWb)PWiCWgRr>9j_PKiVGa)G-In+7dP{c(@e~2^ef^^JQamxPx$-!}rsPCV4ng7c2!C&qA#7}6Xd(|gSujbt8!rK@bmkYXI zh}zW{tlR?O_-Z~k)b=MS^XDdf4G4F)s=H4HJr4)tpz%Xac&yC-sChE!Oml^dW11`L z_nE5T0%E7*XL=GE){L560K`Q&h3OKg(U;ukw8%rJVKscV7(+GV^=R`f0Ffn> zIJ|QvxbATa{)Fm&Lx$^G^`nnmKhhSS*mpko=@_(bO2AKP45U=wfBr>g>ZFaIHmbf~ z=efq=sZRWK+5!wtv7{lt)xW-XL zQVJlYDk!g@y>+p_uJgBf$Qn4$g^$jKEW~=wo;a04F@}$d@2czj;Q*-met1w~Kj;Gg zmUqY+Z-s+njmI!e`a`*aa3y#yGbaoM->Am13vZXFEW*L#DFVPGEAZcCd^G;uhSIzX zWp6>Oi)=sjh$62?q=Jm9+qsd^YSNWhKuc$Re-QQkG{pSs`@aZb=yv;8@BG$@Q-wg2 za4-|d7YMCE)|Am8G6A7h_rEGGce`k26g18H{@JfP<+mCCq*0ZuzW+^5FY+T(tM4B& z$h>Hi;-8JE?{}B>+qkGxzRzK6CMDk+hkuSD@f7~Ki}f}>0sriq4*nTPQsCd1`u=@x zjFaz~ZSXl(-wzAYqrSiEmGO{g-!CZb&&Cgkm%?*~k&?8&|8E~_;okg3*i0ARqa}O$ zD)?TUY1m6VWAT@FGn`79+uriXtH@F(jI z$3H8Rj{UjIF!r}UO=;{DSU@{G@y`@SyVLN`3Jh!GD}sMMYsNoEV{TH$KO@4!t#DAF zg##OHt-foM_#McV1b0|-j$#hCa{a^bPw8(;pAh(v0sn+|oCN}7vb;Ggozk$;*l{;Bg%=}aTM6OVsh z1PwBCjSK%Q71t+%|zsebg4>qlwfpJ?5*4ftn?nL2+K{PSrH4yzKjg8~2a zukY9R=O0(!-|G@tK~em3pD}U%al1D7Y{Eawoz_y@zk%(KS{YkQjjQi(zg#b?FCMY+ z&#+!u8wTPLLkFg@vIPG;&CEV#NBIxHKWA)T{Byjl@m4rE*0>q}EEo+1-#GlUTAs29 z2al)tgS9%ykX8bdtxZLfci4h>- zm2If+pZ&N~e(x0g^Az)ZVI3?CB+A^>-#nSX)5qn_@_?%gjtkYeSeP;5b?Uczbih(>ie_! zvPtUu4=W=IYO6X`-(T z{rdhuQIY|B)c2>9{|PIQ_$Q6QMEp~Ixl(^=8-N&w)b|fzfq$E8vdzW)p5(RjA0*V5 z*h3*kW7PM{6ZX4iUp`@;6!#lz`>z<3bRveHL;hO2T_%F{CDxo1{U@WnDRWd2Fs1xa z&-#84sHuYqhYw6T_R9Vkd-%=mGInczU*B=3Uf;hR^GhYuHJW4^$sD`o&?eR$j}TwI zZe08$~za_IVz5LQoM+q~3hJy*=1HSsPy5bYhD}3?Q4&|_a z{P5Lt)nf*DJZ6XCtH>vm{8C*2l#pi{$?Uy}Gl8~BYBD~tPJJUezKZBWYWbxXjuh%& zgoBCtEc2&{7|Snx_f7-8+JTerkFR#S(8HZ@;H&F<`^upmgs(2A32cy0j{1H{za{`! zF80=h{!X)cw0v^ltFHQfWoE_d`$bZrT0hHO-)}3^`1<~W63D2t=X2Wo!92DTOdSBL z5|wGz_up`=ui#?+l>h!w-o_P7jP&zM?bK2vnF_wz;cUup44V0+?_6Tzt8e2ZDZbh) zXydCL=EY8cgI5?dC`O?n-75sN!JgkYB$ENE2QR=rogIs>>Q<>b zzcj9os?-1OeGdkQWe>4xz*l!ne(CnD%m3gESwT^JHFQxtzB(SCP53Ij`B*f1W&mve z?rX8N)VTc8t*`23RfE1A#7Eaw>6LZs$#_J|lhasP{QaEnX7(|A-yZnt4y?c5a;FPl zT?Abt`K7WcZMylTPhKHwd@7bJ|{$KJ$Q}6nFbk$(}{UsMfsh3cDUyVno z`ulTOvV(nVGxt#A$@Ur#>zFHIeGd{_9#}2QJnSSB>?-_!wBmoa^JYd~8&!W_01X(E z?>hs3{kp4pQJe8syZ%0{{8M``C_t`KgoT9h>6lGJ{%P;2QTgAf{L_J_l6X4*v;?0t z{;I0K;y0zz_-i#;%ido~B~XO73`RPs-sJuyE2 zv~D)FK^pm|O=oN2KWPeVs&&J)N=#YLXa8h&*7A0&wu(I#KV^aYJhf02$jFGdkRob@1O9&M9Iw;cWn zLE!bMBC;0R`P%{h5t0Gd>2%C8G_fj2YH890#UV!~p{|YaHWg4&jsH_Z(fN z>Hxg{1&bDd@pK##z_16^cMm0ghoR?t7h7L(gjt?Cz_2U_oT|qEOSP9FyEbpg$wsZ=HA*s7#(tfpZQ& z+@Et6JBrm6{k~N614j?#Lg0T~KUg2Anr@msQTU5RDpv4x#Y5L}2Ejuzmt?MEK9(^S z!;a8ApTqSv?PtYZ;7xMZ?l+RVb|rW1D)@PCJ3gNq$72f3?)cic{#lP(*vBywdtp-EdOEd9DYA3cJ(<==1Alq2FELgA;}$nX6>@7HmO4U*r?ErWUfQ^S@chy!qC=C zu#Me11%kFI`VY__qx@aV=(vh*!4Q$3bBlNA{fr+JDZ2#1*r}Dmd6?WKQ+2I)zz(Y? z2xbW1hhefp_&$O|g7AG@efLD-cgcnCh=UZxZ++VQS9E-o z|9asx75?km6Z{vPksALkI7^MDR9OJ;uWpo3_zOMgNcUT=bqWO^&OJ2GmvieEMhU6t zm*>NuR+K-3G?&PqFKPaa@uYRs`y6HVgz@;UHpaGxqhU(7ZXjOvP2|*IM9`$&-U zkM1Xo>b4&SHn_QT@pb$?cMoi6j{Ffj{+__5w*9bnf0D3IaGcA2_~JZa;V*GWVBv4n zcUIze$yxa61ASR|N|f?SLePFdA1;(Hk7|zh*x0aJ*SYfpHS^G-WpN;UO;#}b)kVdN zr0lsQyQnT031py9{**|wxhF*m3ybTl=E00bfnCOq31s{p?6u_j1@J%`UenS?%jXVi ze#g+hL*r`x2hY2jQy2@e03n*0H=TcD=M^;R=&IFEB@D7L$PtxAZXUt+NdMvOHNUv4dw{WWg*9+Iy=kSl1R=llOx!9Uq{}naW zHLrRG)cWeI=wCtlmy`Z@QH6ZeDg*mFAv>b%Rs)R`F0fbaKS62O0=v{wqc8h^)V&LM z6h#&`94;f_5+)#l2qIB~22=<)O@v5rK|3%=6vQCzZWP3zpaBzz3uD%e7hqL71_cxmM9KfYr>c9pCo>^g6Tk1r$8=Xub=9d;=e%|5 z)TwHm6APg^8zXC?FLXh((V6S7zmRRnWg9RV^}LnNO(BP^Ma%chd!FX2T*a5;iOT0t zg*4EwU5SrYoxpi?Q3~fHF)-s`4_za zpB*;f^C2$Kvwyoq{pPRzTir@Fvd2-C?ACB+DE?piKgs{VNcqS9 z-W>mGTmDBwMFanX3amfNQUT1bUqhl^@{cYx-+R(6|DtkKf=K!IDIVpk(dUv)GWw*m z9;yU2IU7en;`}H2ukJXhwqjJp$um}9P3KTcRw!8pq$9Hwnkry8iuydz{pjj*ak$4U z%~4m?f0Lv3AF)cQPa1#6{ItMaGE}S2AyFUk(r92Z%sbvwnx%!L<-O7AI=@ztmOrk%lR|$2?_Mc1~5}{qvC%G}SYxitD zwn4ivN&cw9?8f)$8VIYG;<_H+4tHjcWKAn}^++(G#aL0jmbh4|r+X`y&`SLlU;DSZ zRqy?7ik39W1f(g7iRO#wNcP{XahSWM5c`seeU{gNMWD~J&Ad72GwOx~MLzy^le)on%yEnnku6T=fSxgY0jvbz*Ku`dcdf~z_5Y)3{jMTFeml*Zbc4S6dB{J_%j;=P*mx#V`vB)8x7dMuC z8vW`cpKE3xMLwIcn0mq2SY?-H`8W!3Qnh-tr~*-Q1TUGCuca3b2T) zLP~S%I%)TC=hVpj!{lV7V`X6j(?}cW;W$C0kE$JiNot68EOBXv zHNTO`sDF0^e{)$q;F)&8el5+ySD>x+nMP2V40dd;zKUdmVES4F9fC6fk8-;GJ2fAg z%W!ZF#;A9Ub!#ww;C8s2=#$0?M$PI_yA7cnobX+BjL{6tF9N7H+b7dnquC*rf}VUw zj+grc2gcvL2%qc-Gn1T(C#i`f0Xfn8GLVUXd}62QGAD!Cl!~gO_@9U$E7bYudli0& zuQ{+JwURO!($~PMR5iz6mb#bEu^zi!t`Dbfm8&{m)raS$l0K+Dp@H?GSqdh=duu7x z!CM`lvz_k*by=7_ZbZ5oZ-l?8q)pg|^>XlDFiXu3=SZA6znM|9nw-pL@1TnW%$KRd zO8IS#gF=@6wnhorS;&D|BA@XFMqu`*HH@Q6S^H9X>0$j@Px&0?s?<_GL{9apEIQ+x zPiDu{+0e4o#r#E5_zp{v{(bEb<*Ui6!dyMm{u;aK zS$wYQXmk%`=b~gIIB5S6qAbNsVZ#^DgPP4+Fy+)ySX5$d+GYh%Q`G@r4Jk5ik4;8B zQFC}=Lr`;k1ZsxuU-3V=m#vz5{e454HT|W3`Zc6#$$ymf_m@uO{P#YG>}T6nZmsqA z^Rg6op!NUL`uo@I>(GWM>+i=a`GQFBWg!7Yu6&Un z09AaLY(1d{hu{PbnS*8iC<2W7jQ}Dd1Z@JBV6J-OR8BYL#C5#brCQyY>vZ@*dU(#6 z2Q5L^LNMXE;WDpWf{Qh;w10bE{kF9BZ=$MbC>mxN1CGG+*$L5w+2Q)H+rK80{RsTw z{3{~<1EFeT;8?|kKfHcA_!LVT&2-$lMbWW-3jTzF_>>+H#$oq3gb_be@dY#Vlq*k9 zxmM~xZ{WV3=w+Lpe~C#a5dnabNFmjjgr0T$2qU(At85yvH(#mjH4D0G+Yf^A!xvz# zW_E3NbXi^=6CV`5pM4bhK4Q!F>3y_(zpo#GCnBnlXVd$-^1sMhHb68D{4L)=!T0RH zTm=7Q+-~R&2TQ2?PCfw&zeg$l&)o!Mm|WUM6Yv-9&Ne4Vcy|m5e`rcn3IFOe#gtkS zuDvQxc*y9i&d@g+YPN*`W0*+)KXIug{V%BBUab9F-O_(Uo1;qqteE}te?9)-@JY7* z?8R+N{Q+8s_2=tu(4S^^IrOIvFuy?usK*3z%T23$3EYmS&?QnOlf|5Ns6*Sl7nfXD5c0RGA3u)#QLM`}vN|fPEBpPSR!5cY`(sMCHNWei z_+P;BHJ|fmjI)!kWyrch4Nbls&+b1UhMmBEB+^>Pi-bhf6t$tNN)*xy>S1eV~#55u)nGvs)PA3 z6BYhv97Xs0`$Mv1v;_KLVe-iwopvu zSM%cmb!ft0^P_6QE*)x6OA|EuKUFi7=%4(j2=sq`uxQCrTwGd0C3#8xwygGVb))~B zmPgf(k~+F5*7|Ys|GVqQm`44E_2c02mM&}m0MfM;T0-7j3VnSNhMe1jQI)yY`tdOm z|K3>Z$M-isswP&|ZQssO`d32yD?)tM(!zXv^t;}yB{(}XBO0`l}a~ZW$uR;$v5lrGLG`BF@t7D-~v((a0plAyU zFCq;^TM~`XkS+eKH{|`cdhd^28$VboeOgPQI>OH}w=Qi}KtUuq%N zr$xV*FWUMv7=mZTog5#JCXdw%rQQW-USvpSqSAS>2}tW|fGb!l<3$gBya zR_zCOIStMa&!hm~I}Q=W2VDe_rVX!{L^9%ITZi8s!Plr!5@gM_bVwOX(-Z$3XJ4xR z`)f@7RP+DKZS`z-qE^rTZuJCNdFGzy)%f@`IE%uERhudSehpO%&mtgy9oD$5FM>4XUmEe&xkzhPQ>oV;IKORqRV zX-zFH)r0U!2W1exd%WsCTT6Qn6b(KNms%R!NB!2f_HW>CT1-pTJn)O^_B3{TIys*~ z4me{Ek9GEX*nh_UKic|s2F?a*%=K+UQyVFyzt{S9d=lCNh8C)k1v+g|XG+}b+vnmS z9_9krYqd7q>)We4A%pm$YVEvnfyv4QfXN4bH<)NM9Fqa}`nFGpmph=q@{2E^McUx? z?QK8Tfe5u6<1yB^+betkE5h>^<+tYgwzvEpkY?_qB}3EsK@#e64Yr1BaC7dAxau>= z(F}~LkGFG;+b`osbLlPQk$79gE0{sJ1stpqhakpP>|NVu_LgZNP@Xt}juVfHteYSz z!3cUj=}G+(S2nzpQN7qtrHeEDX(<$@>?r34&MIu^}&fUm-~NUeeioP8(P2h!BZ|#dF!!0_z;VYM9CQIgLlLODWAQ` zfs~E5KKQ|p(Zx&*qgpT+ULSPCul$Q37%RSNmHvL`GFfltYM}~= zScc~ECPk`Jt_Rg}w3&d@rnp+jm&Lvjc$M&H6aYYE44=KWtKY_wAxkq0yMWaM;5AYv z(2x0LZH54R;V27$8De{KD;EF{#E)j*8{Gg5nJ1=30Pr(1J)vC-04}7R0U$)^n1Mz3 zQr0ZJEz6DFN2d^sVb^nj%~cDHGPD(ldB~R?5bX|Y0SX`KEkIp^iwmf0W&BZPJWzMW zdV}_pKQsiix7w@8VY|w@^MxKyO@qm=LKrSSMnou2Z09AZxx6BTL9URALU~@6nlIOf zQw!vZ#e1^01c~9^4y#gAtebS}CY$+!6|&$T*a|K~R;2GCD+^U=!8^=#DjY?Z4O9ug5Y0&b~%DoljsGC#|u^~JQQ z)AzF+%W7obgju~xcx*n}vKd+=5y-;f3(<0=1b8U6C!j$rbqNT$%VH(eL|7T}{B3&w zIP<|vu+1GR1R=l{r=X9snfCmAoKzafjj!%tgi7MAC+6FXgg^}jN6=IJU$-*+@5LK| z!bGNfs&pdK$^NW!q%id5G9Bwsn8GHK5O0UOex#R%jXEKwNQAv>4%WFl(HukMS|fl4|$C*<)+ z>4@((=R_@^ott3fN9p8PE_a(G6;)YsnC`limne+LK+giP|%y zZ83T->52FZaB)$pft=N;L)yv11ui0`7&XXK+BGunpSChWQ{q{GI3Mk$mb=id@ArqDPH+ zYxD3dYMhknpKZIN8$MN69AX@~%>PHi|CY_U9cE_ygJB_Ec|%7+rVuxTfj$iuih043 z=5c1=^}Wz|j{2Cwq?@mvO4|6EAG_X(Jn<|b(Og~athxFgYe;lmX@Smv!2yanYlSFYNN6XF7I`*-vp9>Y;{sMG9ZBQ)bX#$Wl5G@I3%kBT}}eNXoL z4|Se(9R7B}DFFV#ao$C1s(T{Y)my#=KYL%@+1h)HA7tSU=TBVU!U%TbH^djMDcf9h ztra@Q&Qv1^DL4xhkT$^?w2FA7NP$9^G7;?0&2$owak$?Gb4t&Bc!B$!a=6Vd96}~< z0x}BC$9`fjEmGsE|1arr-ZE98W`T=<<*)4(vvURNTF@z#?^Uu|^gGzNNE@p>l@^JO z`WJ|WrT~sbU+Q%}{8ozJd?=coMY^^!FVfrPs`|}*I)M*$56@f64#x^q6uLORbo*UN zJA-%_Nm|I$xd&jNLoRS^U3UDjY)dHN>h}hML0}I>CSX9+-UMLmUVJ*vXFl`|C5lFf zsFIBGFp;wzF+-1;(M?Q_(#kL3<^HCsZINF@cd3tF-;{2T5b|8{K36{LieA1fbqvS)LXImKMpeP)!DKRx zo*~&bXCnYb7(#+@U`PDIbGw|VK<)w5nZ@CuJ{1PDZl>VVCBP>TISt4Pd@{srg%Ns| z!l=L44av|kV^2MWR_t7%U@C(pXN&LqEORs&0a6W+n(F{7l$LBJx=5o;Cs$O>3De@{ zyh<9LA>FVKrNDuGDcIajw)5 z++^@(fGQu!eoUs~CYv|ia5I!Q9YsHoIuR*v`H$cRhfG$Dm7x@0u+1BwD~|fqcUa9P zvIC+(Di?gRx5mmkI=FyTjt*X!GCG)(Had6_gh($0VF|ioSj}c;Wu6>=NqSt-A5|H{ zQHHE9&H08+UZ{HoHa=h=u#v*kSAKs8lXq}?y)*FM6>uMF*USjzG^?n}hlk!G3oQT$ zM7Cgc)eyZ>l8#fEKp4*N>3SVYHlSm_}+kpBzfeX!G3;E4|- z;YOqx{w{_OW`o&yZdM$l{Tp}7uXBmJWnwE4cM-qXWBhe)=qD^{+#HCsz4Fr?>G1K7qE-l+lA~ zPTO9Oy*}&8EG=g+yRU*-JtY0m0jhUT33Z=dGt=w`q0cUlfUoQrfEJU@Y*zF^OjaOXeR z%v&}RzxWR}FM?~Lh@;OcMKTy-k`9a{`7}YcBT;oK0GSn22u5Rg$r~L!)fe~}aQU$K zLxwLnK9wyfU~SL}jE4`4`-O=_CQ9@#$-`Enthix;PvmsSD%tw7N*gxIq&B(_^L>Gz zht+&Ay1cSzERvT|de{_>nG;#w0-qZA~9uv4n6tLS=H4(*F#YHVC zhqNhMOBF%_bj7NmoB(35v5`lytg1EJ=HO2HZ{ZHgs>K}=Pp^W=6sUoKS=`BOT<%n7 z$7D_5Jxd%kYr%oQ7Z`&?RKh%h&>fV{>G?`$2wi5@)3|uc|IRi5FqX=7mCU_}63Jv9 zz@t>2D}M;}XED-*Fgl`qfrA`ErP#m@^QRYf;arho3>_-FMKW0=#iL_V_!|0Mibp;v z4nicwMaU0TrWDn|ei&U|Q#7Zl42cT6MXZLh$Nr|+v6>28hpkA&T+Q6DpBh~`cgAle z1Ht<^fBa+b{PPdj)KrZ{jl?{k5;V4*mb8ok)+{xcaC(veN0 zBVU1en9oCV3#v{&C^oozd|&Xtj_=%H5+2_%NK0DJ51~v3c>`r5kIbi!9Dr>_nZ`q| zXRP9lT4Jyqv}*9N$A3sXi!_3CvLb{F8|Nf>6UKbyR>2oNfI`X%<_q3liXy4Cl`I-3 zd|}Kt;Hdky3n$iP%FzPJpf=LDSRvW;2#V4-N;+&1u$V}LU_`%d*x#rWFkv8!R2T+> zaEUIn3H?=$0WosKFbpVIDbiGnNJTUZ2G|E90`I^+fUN)%0k*<$8J`(xoXUAFIFljm zQ*(N9r>%bv|G+eOA#57V)20C#MEgU`gArl#V1l*`s9PL@ zSb??-s4(@g4BB+CEQ5I5iDfVzt$=0VE$@w+(!?@X1aIzDzPxK z7Yu=gp_W^?_y-F^E$}d`8y1H0)KW)*E0%)v>g0h9GGcEpEOtDJ|yytq+vKLsr=5^Ad z_Bhbn0w;{WFc)sXBX9XVep+QgM`EbDTrBpW#=7f{QlDSOA4A=_3z<=p{ z+4zi@33;TLIV?KawJe6MV+rhHjyBT1OT(?O>=-2wG!jUJvJjrZooyjZa9RjTES8B7 zX$#@0-46Y(^e(*he;`InWni^f2cZ*WoXUm7LTT9xVl*qJ6q$@DjsX>nbdBCP?~66Zo=$2)8Zthd_EvW41^ zTciy+^<4;}vHH2vx&=e+F`?+f#AdKnvi54;pL% zG@}LJ3r$YluKe@Q0opOSUrb>L=&kuwab>*am5vPkPB zp9-;2GA+{P>LO(oE3fq);nyOy4iLPJ#lTyWm=he9JUTcM-Wq*OnD}@Uco4%e!G}Rp z0sqkIn(1*xXX0i%Z_dEY7raUJ(!YvS6;qvYWAY{eH}B&H8jaDQf<31+L`~s{rupXl ztqSy)vMs@x>9oc$UcBjDu1Dd(Ui0smW$}47)mW)7P04e#@05WRD7zFTV0;!=RZif0 z?{Zi!c;pLgW_!f%=Y9QqW8FH;ym@NFPe#pKp@9cNv*4=x4z9WnjnI%|jL^-^SXd?A z+Y)g9KQz=fDAs5eO^OKoH0`a={NrbSahF{W8JE>>Kz-*Bqu8UBqbN zV4^#G-rB{;3%9-1w!b8sORHHE+}!4qa;Lj7coF#XKFcgXeO3evcdBCuHs`bhn_`se zYiM_)@3#DkP8@1OH2arN*zG27=t%sDH{GoM-^UcYeJgIfOcvuE<0{g>#zH?a3Mv9E#co*jR zG0a{_$;-7%VO^2(vXSxv7x|FpF@+)F8@Di^a0-Lf_YQgZL4;s*V66xW%t;K#bx8t; zAxe2paBQwGc+%+LD4?V@|16>fqGlON-dI>pTJ=i(m&>5ujR~qVLP0e zr*HoT3&B~p+d1bTr}?3sX(2PULZ%8bGKJld#_oU!&gIG`mI7#v8MMN3X?vW1Tx|?r+cJu?^0EaP4!W&gPf93><_^8(}C()>kzJAHEpUOy+nz&Cx z{HjQ&CBbqpezcqkoQEhZSToGOy+@A!psW;3iLbtzD+K^JHE6SNkw`clxMzNodF!i$ zC+!ji#U&KlO4bic;(ocRS7?(iMw;d*t49BWu$;hJ3J~jt{q<#0?yv)IHY)}Pt@6)L zVpBBM+VxoOQZ?jN56KB^(vI&MVW>lEl{;dQ%p8Ns9d*cygOeL)%6ggjDwb@B8kuR1a+0&E|$k&{9W{pJEY{xHhLqSGR#}%X% zD#hoNm&LpyZAx0=GIghd9gwwEI>ZdCxH>v4zC6(QT7xP@#T_dn`0m-ONi z7*#2>^JH2DqrPBvA{j`L^YNfsYpSDoI68PK8g?)z@R@M23VWi=wqGjU5Wz!Vl(I4nl^=8jjClB|~!l#+;%3y_UelBLMwQWB{iC6@AK z2q3C=S8Lw#V@(auSEwnLcm%4M-bhs-8>u#MDU6}1TdN+IRWUb53IE^|W&Y@DV!phg z!CJCY7UtFZ?_8S3uJ1qc)Odpc>o!SrHC zZ!#DDiJgLkcX?ZehD?Ll`qviXNM`s)ZsB*zqy{8g%e3 zoW}x$%5hG<`wt})x4{ee|I!WB?NM)gZ+Tbb#fxq5(ed@(`yADQ3(4Mczs<)WY(<1h zWxjL$)kbI_`*bh+bT1@qARLG5*|Yvb$&iTP0AKJA@zp)4Sa}?p)8MBfG(WJLB8PNN zU@JG*VobsB+^gdYtTP|FWfxZ)+?^TNYCiT2H7;pdyXl;RO~+-{*~aSaEioiDhvsx@ zj8_M-;InFH{q5V)rL2_gbQ8azV}_lYylKHU}8GyPdRtS3Dj){}H2!g`ke z2ev0jH>*H;$kPmOqeKvijM7)>@`x+) zn%=hT8gxq4BY2?v;H=BPHV^jST-Zn7q92(fy&9N=3-}9L7T+F{u#0r_T?y(Di`I%R zK~1wzQQgrcAO<7M%zVzj1K-zt1c@wqgy^Cwk01p#XPCF3;wcrVdM7E#FfT&YW@tTR zon|Uxy98g%Zfk#~d>7$tAFDJrAnMR#Uht-~b0UnfszMB7kzK|4g+AZ+a-vkM{U>^1 z(HhW$7iJ*f0o@{7=I*-%@lc!ZCh0Ij^;qF^O*4`GFWDUGOVKkbj7qg{BHz7NzgtLa zT;=dlMkHpEp^!lP>*FzaVDi!Cp9&6gX&Lgc0v3u-px1s=fn;3E+Rhm#bd-?(u(rF zx~uiftMRwh^*9I&*)Y4s8SlKqDhNEud}RcB^t|x=`dl>pQtaX~kNt)0(SAJkFXV+| zDr^(O9RD8MB!O={M!;^^ChRYWR}x!LJ)K6KSWMO?O}tTH{``{SyNh>uEUf_JmwEVQ z7EKEj1`ydrn>^29E4e9IC=pgHcPGp*%4hNYwdxIdt~}63?H@8Hp6Y_PWlz}n0&TaV z7SAjJzHHi9J5C7aV^-D@*{Z9;69md_n2HSv@mb90 zZu$J_X2@9oJIN>OfJ^Pb1Fsip>vJZ0N{OhHAg9A|e#v(aRH%2wNVMtzLZOKfBAP-G zz3Msg95Z?Lq$&*}swae$($7JoNGW98l2X`FE-A(EKO8NgsCKBzr*8Tor5G(CrCtgh zHtZ`YwPbWKGKq{9hGn$GmeCTojQYYYw`KIYLu{rkqncL`(-MkluKD~sY?tM*bhU4j zd6x$yg1@C`8>c9`XXdS~!~-Cjl%hQe5XHrKN>MBr9oUh>FT%?j_WgLO>T25U95k*l!`^h}~B64MV7Ve(T&#DEF6(ggq+4ADO zdbk#M4U|`oSqpW-p#dAJdvh!*#2Ea?jo9`d>OM;z!^=n;Vd{Bm1EIK_05cL9WjO<| z{=eGXC6VdY^aeu|o0M;+AK6t?QJQtob1g=zKA1v&F@}c4$c6&f^O{E>nEEQBEG=T|OEP<0<8oe`YaTJ6# zdUDa}vi@ow{&#JyHs4xRTdDg;4K${HZ&mu8sPtQAZqRS(PUyGlR=tuA-BTjs8h^UX zg^pena*BhV!GrUb+bFExQi7%5+veci&iY+JSE~+mZ0#XP^!wJQD4QCoRcWH%@;dc< z8@fjHyN*%FrQe@Xup{&vfZ*2e7048+-vzdQ7evwTO3;DzBp{oNL3c0~#HrtcXV6Tj z42Plj*Rfre+`8Jg$%OR;6L4r@ zhgBuw|F*DB6l>0aK2yn8BRjo|m2zcA56i|R0^t)z&;UcX)@(ALIKa9rr3<^*P=)Sq zF76Z!#`yULbIO($R+}?ta+N<4ZMbYT1HvbipdIsK#mXrR+d@xW!&@9Zd zU}B`u9|8zU<`obmS4i8_Ob3(FubqmYE0k|8=_HjB-()bUlS)b43nVO!Z)7GNnLahH zD2F1KE=4??njzN&&mK-slMZ}`C8CxXc;IN+Xr|q^tA-Kxs=~4jMHudNQC6*sQu9y% z{S%o*fd zFe)rbG6D+}Cl>007Nsgm0tzQLV%5=q5V8K4P_PAy=A{d+tY_7QEFd#!<1~v~CDI6( z`EpIT^;>C72`*u7{k$NeG2j*=VfaR10sFyBPUC0QUg$t+g?+DTHUjhLLdBc{eo2yI zgzn%2Ilbq7bM1d1h5@XQUYH2{Ne2F8a8q-cEMwR)eL*8z@Q6QDQrj_g!y;zL)APRm z+CJVk1l9t6&PCbiVEBf#_ZP>t!)o2mx6t&xa=jElS0)jDSQdrtD8FWI_1-?YHM6N8 zYGvH2Y!!;AI3XNT#cOcERu)E_WEl(4Hb_&*v*{l|m1!4Hg`th;E|`l(s4(6Ltx6U9 z65z0x;IP+x@e3*;n2jo>?BIoIq>SaGMtowOTTxGn@pI4svY>YV-ewERQW+V7InmT; znWvC`n~A8bLb~k>@l2EEUzdUAyy-D%t{|dmqJRB7Omqp`hBlhQ)X|Wfp`({bl@{OhE?$du;K#G_d-rR; z0DD88ARG z2L|A^MuQoQF5KT%bS@=9Ivmzb8VxOUdb(VfMRxwnFgR7`Kb%^CEHD?V$Ua*Z?p!QQ zu-e2i`*GdqZ0SF}n;yJV!lMM!Ec^_v3~(q-Is;*`a$T63Ay;g|kn6Hk16Lna23PLl zW_~ZW$g|l@Ge6U8J=4t3v|@td6Lm^;z6z5@BT|u#j};qWCNK>)te2}|gY7uC{kLKH z`l|%FQYjF6Pu5|PL{?oQ+DS&Ks?~~>dC<$upo5)+evD&$22DT-n}axnfBN zSGJ4!*)FTy%+IvdZsun?R=Y`DRUcLwN+^5tEU9~=B$IBGB&NQS^qhG%M)y0rK+Qr4 z-z1PajOKc8Cr$wHXBD+0c;Z+9jWL0|L^&1!;HW!y%O(P5S?YFG;+L6p5Mcf_Sd}_3 zTB#>QDfL)GHkzwaX+P+4rI8`eLX>On>MWF&wu?gP+ij0VX)j&kUQ&v_S|PHl#05dp zm2{L;%Cl9e+j-4A;+>x>jzb+}&AyZjwwAlG0&G~u-w|FGTBdA(uo#{FNm#v#I2bmQs^^18Wf=YU!>@T4ZF*}8% zRR6B3ybvRrrN1^0DabNQ>fDEATuHDPbOhk1~lNLRpy@Lcteljrc<25%l$-Lb6xMT3_Zz*H1!;@z3`{ZCHKz z5c)ZB5WOMVgbLijeEzHv@gyIV_kRfbn&pGSV;+Oqu-Y(d%0SEt zc^gQzP`@2tHTwY9b}>g$kIWB2QPmZEh$o5%w%u2#Osw^!2J+8pV8?Z1&aHgL&+b4@ zcndD`XZFAR6wJjui|6Iw2YEnK?qCoBvd8%!L7 z6!O}7u|w+x3sh|gFQ~IPGx5z|YpRA*z3ra96l@uZvj{wk9stMg_*T}^#JGd6%)qP; zW*p3-A(-`?eK}@5;5m!7DZu*iy%{LmTec35kw}xo7$n}BKMeQH=pa`w8NvA?1i?q7 zXM?v>R?KeIyHtEd9&*FWHHt?V0YfBd(TQ|Ee};Jt3065hkGAa1^|5h`p0FiX)$l57 zz|?O;1-2X4Ali4ek$LdOuD)Q)w?+iB^N0BlCeGb8EU;nIj$xVW=YCe*0{6p07dA5{ z;Xq$~Mo`F;vV?N}j+xw#BEHCmK4EU)KI)DUxGxbGf7V!!CGl}ci^TJWyW$}6vogAn(07LzlP^Z=Y ztZ!PfqGLt{2ClBg3<5FCADOe?mg1{lFnH2?@O%JiP9d#-L*#E0*GF%EK;+G0)Gdlp z52~)XO}e6@3f;dB!h@>$Pe6DnTY-m_`XRdLX+ay5#Gk+yDTA=D)9Jh-y+WrIzhH35 zbLm2P74a|48UHetJ!t9OFf?F7vf1*Vuod;g1@p4`rhg?>1`(9%w8E8@DkX!6Kd=HR z;GyT59xxEzYA*)D7b`e&!hCtT1(}v)6-Xxq=6@^>^FKMKbWUydL;SyjPb%yz1Z?YNIC9*d$UvgqXr!jJ1-)#N|XJQ_dvQgsg}`CR`HF0ABl z=JRg}{e-f(;_)c_NOu%IK^11%q z+ErzsD)Vl;o*dS*_GPa1ALN0fhX4+M_pmdwf`y<~Mu`_{vXdfe%gVV5r;+OL@_Hub`J>=bd6Mw)p%Xw(N^ceZXB%Ha4 zRV}s45Us{2HVrOII5r?aJhtaHMeSWeExuoj1`J#ioCTuaxxSMTZ1+j#jC}9k&`!SL zUz-e{&Q^0QE4_e~y8MlDe#jWqlFnMRZ#6g)wVaFEa*UcyD~}gma#c-2PQLp9(ITFL z-8%kw&VMcW>$ePYvE(Iqea)}`jy0dht^S+Upz?2L`A=MBmEX-Sf744S-zVkI{|)8$ zVfiEM@?YC&(LaOb?|zZ=pW-UtJAWft;Nnr~3XT$S6-Be)uSz4l;|!y+MIuI>@WG>j zZ4nbvJW4yKi|AmchdShWZXjy;I-VZAFMcfq4uQ=+_N;udwq=`Y^x#|^w$fq^d=U$Cq3(Y!9*X@9Xc6kYTRrmeQ7bmmA$uP^ z>XN;9Eqm-g`j;7Zq5R9Q4@N`h?dF7^{$+6hg!B~(pC-?hBS4HmNyAYiSHz2}ktK^12U<50e7Go3cnDQQ(e6~pn$1I6$SHEihkw;4SYZ31WPsC- zCER%0QA#*2W(j=#(vzL9+fFb|LtAgzSU9#1srMPEuX3gdA)U*kkxW;6S77pn~V^v zf0}vAw+$4w>}e6E<_EdAsoAfSO-2pal3aYE15_gs&s&xxNEZzW__DWbphTiy{)T{ud#B<)e`kO?tFhxJggQz1^fIb+Qqfgo;WWqt#sZXmw-L zj#je%DR?*`UE2JuqZ{|RyYc(qp&Kz&ZR{(AeAztAd{gdi=2z)tBQQUvJb{q&6(QRk zBg7Z(5n_AOj}Vx((5!i_k1*v9hp~6J+t^#w)W#kN0aN-bLe6uH-y_}Q_o&}t{02v! z!3mI1onIY@^5z#-F z{eQaH|5JV*YT5tkaBHY0V2`c@ufX_!4%yJenj_O}@9oyN)X7F_eFPN_|GQu8 ze?`xAj$!S3_pnyfc*7c%Hi90dCHG*?2(C=^grQ@)+}m8aRwtW=E1&` z<+im88rRmY%?l`Mptta%yQ4==boa{flf9V6|nX9qzNzl2gAC1tK8dEEYQiuqe6QSh#;FGrAIUL=WA1{ zwq#*%U0+52AL7G(dA{7+^cyjrb zxwqRqPA40o%~41}pFw_KK1Hb5;9$tRZic+qqznNSK$gCWiZ>61<#(Oj+q_t>lTF48 zQ1MJp;l=9?L|N@dlr>F?C=PssHPTH{bDd+xaJ_rRP}F!chUoGEp4@|lCP-;7hv|HV z+jQ>JxTbS$d;l-Jii-a_sMzJE!m{TZMLwe1Rkl}^`?KLzokMqU$TQ}9+pH>#;a0s6 zIl;rP_J^grO73mx{zfMoh58sC47gO+pCp7_=1{YIx0+qvxN26LBig@`S}~-Bx2$_izbekh5YOseF+8iu}?`=7;dF9_}u^;dS)JvF_gJ)OfuCeE8Z?(KqgjsvEVU8-EGQ*F3qm zj1* zG8Y8RoN4M{(E>hUyoDBL9fyKo1rDX=nzz+%o~P-oK*X|yRUn9Eg``)dR?5{n;#+-k zg%R}3uOlYZ8GvE0sS2ZJy1|WN=obi%44ZJaYX-g}#Gsv{wCmYrs$E-!e!T||?J^~; zj<@E9i-Sn}5Vgm6UD+AnY!@>-+r`X{*{&GF1gwL^&US}|hXLq38je^z`Mhu4Q#LhY z+mM7}LZ0qB?HOB!!x5fav&lN2U4mgALT&*4^Si>*`jXt+(z;A18{DzcgJB|wf%0O? zmZYfYqQq-mbntMkl;l;@g6X;a836$1&CQx)L82_TE=>AieKdb5>yvW)S=EX3%w|Q}{PBslM9P$C4OjOkL{UJ=v z0J*oR8K{#@Lya2z|C1;@>GfrpiZkTirlOBdHYF8f6cr~sbmdgHuB0`!t^mb0V9zRa zdGN2((VfQhZ@!Hp6X1pQy zHZv-9vT2xsKD7Oh-4rd)?+MfLlHA+0EYr!Rp+({6J&3agN2WSDX1cp$u5GlAiP0}y z|5sE@a*S+Oxkt8w#vR#eO9w`@0QQT67k~XC+#`?5z1<^!*U6^o5eI%^v_Fja7*O;6 z$6;!=$h}R?2Rhk!)Yxm@dE#+6+M0I@J<$X=!*6Q;4Psm8Xb-IG=bFv*&noZh$y!kf zh&bR7bvpc^$W^bf)+Lyx>2ktE2>C$W10x2X9#)uId#LH~{Hu|dXN#D*F_MZCaso9dv@vQn!7!oVx-iE~0I@t)2h>DK=DqK+)xwk7y*2zYwD7v+R@#qlt zY=er?4r}E?x3zLnlUggvLbzU0asEePUW}4^n-@NvY%*S8Ht{Wn8t`J+=V2;F$h}R) zc{OpxK}C(5inu1V5N!Jq9N8wi?Rnl|t-R#6R+cp>EszdyVZKnVtK?K2f?_Gs1jPk%Rj2L{9GPG6k5{Bi zboyzXW`6#@LZ|PSw9F;dxeHD(l}xrXd|_&-SSNMw9h74zYx}`1m#>;Gs!fy}^71)d z%nnZ%om)lm0h+$yUjnX)SyyR1lS&aI+{qhYsYvTBYSL4@qaxBMol`}9}Kw+(jer;({49LIt@Z(vM7h9lJS-|kQ{G1N{8uAx2etlYtbAzwEVtt}s9T;4*S#9twdsIeA zoW#IlgLYIrdl?3=audk<9Q^~m;FAKw`mWdhfh5lgY}?0y0NKFNX1J$8VBnt5c@KJI z+rNa~^Bi4eOz~s@tkDRp+Fy7}TJdVQuw}Tn3ghzz7k166aA8;B-YSgG8(i4utHXtT zf_tklK5uYg9bO9;mVkS!Fg|Z^VQU>7Q0eFZK5uYgue=hb>?Pb=l<|3k3ww51xUeU2 zZxzPp4KD1j{|XoO0Pd~A_`Jb|ZFKPL-wvMfd4mh{JB0RThtTqQg9|(GQn;DlEIckH@L7*9lg2L(VKkU;KIBPp0#!GjL#cf*e#C2ZgLdH=M66GM@M1% z9EI_Dg9|HgDEefFqVst}3$p-P4a^FiHN?va3{fGTCvr~5SjN%2UihBF(+xwOJ!>p{ z|LTRXK<>aj$tJ$@c|)6!biYG}7CB^y&l_CWsO4eG&d0q)8J{<}uzxvv>QzTi@p*#_ z+vjNJw~l7=d4mgk{KarH7vtV)CZ9LBu=^andAFlC`Mkk}-S*EgW%F@wQO4&DF6_pY z;lggfy;T^WH@L99&xZ@!jeDywK5uYgC%+sntOxF`!uY(wh285Y>@G)PeBR)~T01nr z^Cf=IsA_>pMSzVD<#tKc|!?E`sdPc zVb9{;DvZw?T-fCf75t+^1^K+eg?->Ku{JtPEIw~=VXYkc+`^&HeBR)~UUlg6a)&1+aVg zyupR-cUZuC9TqU3H@L8?9D*~+Avk>A;KCksj4Jm!MioA9aA66K4ruM@06uSUVWp13 z<~j=F^9C38gQKuLj>7o7p@mt>ro2tsrC+cDLm$x_UC4MPE&FIg8Af$2wg^RmXg1 zIfc~ujO$sHe>Va&r}4v){DUUs(!G?&yAV0>FazKD1y zi6=MG_!!@$cR68F=!8i#ubx7(dEjOIy+e_kmHF3ZU_ssKu~C_E{^wx9%epd|2QOf) zb{0?xubb<`xaP|jIolt0kyTV3#^HD|d}Dkp=PO(fFs}od|y1B5_RFc zKR!z&gXFx23?rC}M_ajm41~u_Nj|21869&z9udh>{A<%BiU9JHqhyFj=GwnRX@(qz zX;xhry)FDETUym9$KijPe((Ha5tD#66tWEkY(oJ_Eun8xx(pu!5E+BVS@o-Qg>uRT z(8sPb>ISRH+TT|W#rHk+DRtTQs(G1|P_x+;pBs-?d_m70)6POiC1l(?9ha<3xePj6 zE^6t65#LJKlO`drK7SLWX0SuSS|5+N^qhYsj(xr2m0dVO9EAD;JpXt}A=EPj3%??&SR_ZJ{!C?4?-Z2vXV{^Wb4{m02=P*=IsZa?zIYX4J{ z*#70N_CI&j_7}R_&ll>`e!doNKU32FhbrpZe#FGY$E)^VE$u(JNZNl$E`xrSOYQa} zZ>;v8dNtesva9{i9<}|~x!cbd>eGI{7H&UN(*A4is&D%d{}SIywSTI#f5lzW{*`hW z^r~EHw;y?9w*Sv;|1wwmpE+v#uXVSdFVv^~d@bC5rlkFEhU(k?|?YAi!&64v^`t4z1{VlVCo7&_sdzdiI#0dG z%L9FD0m{8oz|amaIT_mgX~iEmq~J>e>HujHDBl<9Hr>V6cb;NDL<5!M@u~t9bJsK{ zPd{c#czWv{E}n)w=iGG$zAx}1hIU~Nj}pIHDsWTf2D*S<-k#fC7;m{&{GM^v{=fh|GT_mqB04rIyTJhrChy=flg; zKQmr%_Rkeh)~|o&T;uAW)A-ua`saMUW6OLdQ_??Of=A=0uoK}9U0|G{@sC_7jo+mj zZ>q*uMQ{8}bG0K*R~oH$unn0mX&PfxiFIz=wEb7+L*TJ>;hq-?15asK8?6Pl0;L4?+<>0=%H{f0`tX zKR+amH{>!XM=rG*-yeCSHhuydKk%Q<#`ly~)FnT|Ni+aMTTA=@UXNxc@*TU`&Fy9z z5zV$lf>Dg>gPd}pzGE$!qeXZD-Nz5uT6P_#CFZ*MGSw=5`3%e?5$#?^+?D+kNnQ@&L9UeyDn3 zf0UVmnm^siNs50rtmoZAyvy6*uvL6)CFw6SrpMtszrmy#xWVE2{kCy3 zk`ME?K+M}T^oX~t9L@2*x}){Xo5Am!-=;jnYIei}*=EO9=>Mm3pVHR z_xRFrQOnWzncqFmbpb6@Uo$L~zOQ7`;0n`aDqeZ!^`u+3ep8_Ae$3+{!4z zm)U)2A&w&{{|Cu0ukqfu#=Cs8FXY)V_3F5sP^XRfHOp}9=7|T7Xo)YH{yXm z>yf`vtMHkkq++Dylgra^WA2*FPc9?(=if6o=F{@=1I~8R$iE)=(z1aMEx$d?zoW(r+=m+c+@%-mx*X1>ax#Lkxzl5r)eAISaaxLf+v^ zKm23O<-kQvfjRKO1Hg`?Z};JoH<=sp9ea|Q3^G$9ztF0*^viRjS6h9%donNeUl*%> z*f&ta;i87E;e`3;I_O|G3Jy4Kkv3r(#S33q;?rPmypb6%rjFO(M2RJ|TOw-E_vaR~PsZQo#q9)|j9|wp71h~%UYtwkMh4svo%yl(pIa8= zQws9njn4SsjsIs)aU1nuQs?USNFP&tf=UPR^*7JDX+X3|Z@UmJcQ$U7{13#UH?-S+{bvPsv2x-+22)(!5ByW0V{+}pd2>GfL z4J)F<;d6h928ZT#e*zZ1eY2&SrMXbe!(&`nxMZrr!r5Ug%#DGCvVX^XXlQgrs#^0a zhdU)dZR^56Xp3QFcE92pOaT&bb2)Cj!JHtl2H*0*cT6{$>u-vMf|soZ3evA?wtVOSK9G`) z?*oB;B?KMDfZYo(h=GLWMd!p| z5FZae>cYqU-e~yv;rGDD8KdgN$BQZ(4L`m z!~~6xzYJ@9e0=(bSok<(m4%OA0*?eA2ZMfvkNa}K?rAx(@Ueep3`RBzKJLFm*^k-v z#K*@oqEqwR@bTK$qu}FlSJaJo;SKDKAT`fr@yUbM=MkIgTyH$Iky z?Z<_!6+XU!LAsXx*m`z<*nX{C_TvS360fa8@AA&o=OEphF&8i&y{~kx?t^q2%)yur zcE;xi{Xe(0tjl2M3b7{J6?b=7lMh@mJua{*!kGNv8aP?re^_B9PS~I=*}Y>ltbF!c zVC9JOoLCt|eq~F}lQ%u5ycPv3k77zjwtA51NC$p|N0 z^831fR)9G(Y*2EEG3w-c%%B(|x?F5Y_sk}2|9I!u$G$x2a*dxS;wFrruU#+rdGd`G zem*M}V^TLf@MjIFu<-L(qy<0Q;KsaioW{?&O<-RZ6ve{Ntt+ir_Tv>AKM#X`g`Y1B z2menW9t%Ie9}t7Nje?)cZWH{RUSIoiatvyI8-Dg#5d}X#zN~Kiyunj1{Cu&04F3HN z^Y3FC0Y5vw;>OQ46YGtibHn)QYpL+F5F?!ZkLKM!9k`1#-2HhzjlnY0ZL z{8_);X5r@+qy<0U#*Nu?jD?>~V1K5G=R2C0^8RHOeohW*{Co}cEBu@>6#cOKoLKnz zVxQ2b_8#qi#=+GR$} z9YgGPI{cHJlze1IU7ykZ$rs0K{Cfd6I7uG-1pBXD$1a)Ty{WRoESxG(xOJulg@5}J zs}X^ujd$9b!Woj=<*MZR!f$j|cDtHl8VwA$yZ|sn5KNqT z$$Tu?ya?(Q5Eh&bzW+Bf77#wuD+WiGMsZZu*FRZQs_^f>^<2M6jX}h3#J_(;!@rA; zf`5m#()o`6Q;AF!|g*y&Wf z=(rbRpwEJk3-VrT8x8U%eSR9_B{bQXmz=9G?}qRc`l48-V7pUdNZAk3?LcM!)eHYFwD1o%4*X+Z z0Q`QKEa10oI>8Sy;7L2b5b)cA2mY-6r55Ao z@$br*__xHyzj?$zG(h9uAmZP^nE00(gT=oI|K zVsnyseRcdzG98S^8o}%1;ZH=!zjC7RLii0{b}T7b5q1cXG|=BJMF|6V$?B;^JU#!LgF z(EkQwNI^0Mv`z z|E1p+GNg$OY{BH=`2eN~BPW8`sP5Z}9x=LRcGRx1{SUM15#KXzmUPRzee1bC(=rAv zzYQPXdn^h*-XO{tJHF?*ef7e}i%y8ay(Yy+p5J4R9y}${JHL=l#(BHtaGSsqy^ls; zftF8G34oSMqJXU3>XObp--WpFbXlgJ= zPM{KNAHxtch8;ilQv|?qeR2f0r(FZ2E`!wxq%M~W%L?EN0-RsJM(=W_XZOhIjKtF* z-PWA^5&|S65gIU^3z*I`oG`69JZ~-A@}{v4hY#U~XHv}tLIpj&b?&@=8;oE?W;>eb zF1(?TT?Vy~C-qUM-CBs!R;89AlMCDn34kRAzC-znTnp#S$`YaH3$6XVE4p~@P)&2~f8IO13q zJBt6eQw;fW#;1ybA8Y)`?EZW@^)QZ>|UJN&|071&0rv9K+Kg z@ma4O8;gIo{?*5RUv#yMFQKmWwBLuvsP?ywFYWJ-GQO-FQup{W;j4O$FL!l}!Kfy; z-}U*MtCjsuQ_g_>E_Qs#I)5|r`)1a8oO5Z)$|%GEDAIoa949O|ogKFiR+xw}X&ka+ zTNB>Ko+4G6ZNHyRN@PC~{Ci(2K+MzjyG$c$+wYx=t|Qo{!-$QaIhLEZl4#FX%*5E^ zxkL_n0D;wBj%KJBn`g{sAf^Jd-%S3>Y5Et^@~vk4B--9QA>su5WM;xcQ=Q^?vEYe4 zH7p6$g`biOKtyq#z!UQZ$QA$awjWs7$Ev*c8%~ci1LL4R2+JQ}pIPcMstZ_1Aqy^0 z7Q1wWeOjpY@?b7Ab895ejeY?=lj~?cfB9#{`Q{!T*&jc>M!&?MUZ$Wp;}a%_Cj?osCIn}BqpKF*Km1FS zU3K9|G0tzFR`c6^SnI<4b}Na8er%LR=qu*8raWJmx>v4csoUkMLDXDE`9b7y0+u^P*UaYd&X0Z%3F{8>AuVvMNZ?yc^x z;6Zge_;vn?8#AXbT8pX{OBH(JZOwe47(KkpFYFTdQ1-oiWO!fwrd9TVw^9u6@SiKH zUcfv3YWi*Hx2@{Q@a;n^$=*pzYf{bZYBo8>Z;)9CGP??yu!B6u37Kb;Orf%aMP)px ze2f7Ipt3?!DN>3$Bn>K$k4_piY$Vipr6)sCHsD^QBWj5bCQ{fj1aMbaa_zLWm z`yK~!_%h$Z$_6%YkQykWO!N<$ul$L-9SIkqq<463N9HDP`Ay6Q5|9mE*!A=)^!-9% z-FV<%1z$j`#2tZV!H;&R)9h|WXvTMj|46f0XIks~hdLE?sQQkr@E__t3-P0ex)cMP z$PNGCxNPsDx2n&^!>;(I6*75W-P!tj?6Snq)qg^w)%Do8#Js@))nFCx;B_cJ!1p+Q zXO|r)I+K%Aux6)XO=~%Mgse$WtO4aO4LnabtE4XPKKd$(c5U4#ph2#o+#2dK# z6wJo%(>2(Ax(vs8RChI}OF7zT&ga;Gi8rXi?oFjpqk~3#4jtnAMQ-42+<=k7{P8n# zuBZnI%9j_&KA7HGKj*Eb+KMYXL$*&nf}{evMJy=f86fA0_)_x);+Eo}+*I<{FxIJa z(+GDf_=A>$Xr2#w5m>jL`9huvBW$cwE-)MJy7mIx6_2#w?lf3-=966&+^MFRmkboR ztGZmUZbOv-UC6V2D5hT97zYOXT*qe&++*A4=nTs~U%ndl`Gr!bl5}qw;Yu;!b46i) zIs73~e=ds05Si7PzhxfrmOsqA=*nC**TiO~Z4>v@L}3}YpGNs%M_-9KX*|yzCs#T0 zE>niM z#c}=NUmJm(VGV9KK(Vq5St%M;zM<+nn4;>Qeh2_Uuom;V4UAj$ZtNo3zn}$ZAsc`7$npBW zFmi0A@RZ}s+uQi6br3qGb_M`Bkjrs{fV=>A{;X#v6>2~(MOuc9*|;$~G9m&sKtTl$ ze5r*PAK8B?v7xx4>M_)*M+~+=--d(|S@BTL2YfL#tVW=0Dk$4C#-i*y-1)P-Hf3KU zEtGwR8?%Iw4}uz?46qF)C0TWi5Q&No?B8^Z5$S9hw1O%C&6SZRSbL1{mWh<3nsmm` zY#{XMQK9`p2rJ+yTN#ol1_hcc(g}W!0+rJ2z-b*7qBR^!S$76ok;W~6Pvof)0jEhN zt>md5nVV!!FM_xvn;sFkzWwpnC|rxlytR}bfw6QqWkoDRDC;&O}(NQCN45~f|;xj(2eAN(Qv;AnTj{ZwbY$aH4?}cwqJ$+L*YAw z*s&_CU8Yb9F>?Xkd4RU{W}f&&T(o_)&qbS5v9E=$qWW2P`QG`L5!(E_^H~RuQ{W%G zQb3spoamJU=pD?A3dO3ex_x4lokD&=v3d3q0Eh=Kxjrk_#as5K1{CD7KZk^j^8GV! zd9F6%++|38s&cdF1wy>oV_Y^3c_tml2*)_{A%?9<^>ke>{1d?u`@eyH7(U~<|3>>R z3(chxfxw={!0OM+m%QTU1aslCWY%Q9nr4@PpXPCz(pz4t4-(4Um>lh9OGPIz+GLgNH z@DKW20^pQ{eB{RC=L0=dcltf^Ak zF-D*;r5a~el%$vk`EoGnnF}C3SRcq&x{q3L_a=N8fsGu%gwNJ0C5X$A{>3P!X1vN4 z72^nBrYWN&!pwwaIXAVjRv-V9Y1@<#Q(N>N=nm1_e~u-3&w61{_Vg+P92~|B&HONp zAY8xI$G4B{1~+ImMu_DMhgjMGs>YYT6o?3n7CS(ufPz|EwIMj_a&d$X96b~YlC2z9 zpNi~^MUA7-yDch=zolXHX^V-$S0>10bP287vo`wcNDRp0y+sTonk!y^LAQLkZ}KQ1_xs(_t+qBs`0k z&CFOP$pyd0;Qc+ZRyY;^|4Ih>cc*ats(nU`>ok_Okw6tckq_Gz3Hf&ZD!#2ka>VgCOPL$jXZzm9bqT%+?&zdb&9bAT+MhGRJa%j7M zx54&jv;DB|L3yD}&TqIGm1X|yEq{kx0uOTO5&46U1}7zO0)97(=vcvTpu@3v`$z}y z=K(~Ikw2n&{;a^oHh+*=_yayU_>*R?V<178KPlz`i7ep6-ZfO5BSks+^R8q}y2()d zNhe7e*)fNsa{_RuvT0;I6 zl7EFqiQmNVL`Fr4-)wu6d&qz7Bq}!ZODixcgKIM6m!doDA%C(x@FoGB3%D$df~4X=!4Y0hpqPx2=H zbe`&lY<7de2H-B-4Mz?CteK1V(e`v1rqy7Lsk!6Cp6;&)irHd#QyH)FUzmOB>W7(a(&Pq3qnp`bhlx086GRaEWTrmV*H2 z9f(0{fdeR%eBVh?s^9oEYP1lV3L>=qP&~4(@vGY$8NWX0K{1z*x3CYP71y8EH)PB* zm;CtuG503$QCH{wex@h!F4efSrqzq_iZw!_5m1AZ zDC00ST5PR)dueZLt)fz;ic2jZ3aC{;t602>`!^0MYRe+k{NA7Ee7}>)2KLwA|MmLQ zn)xp0d(Ly7^X%t2=k(F3!?QY-v5tKFe`Edi;~Bl^uRR3%4)oV!E54Eb`uy*GK)zG` zb!D`>Z5R08iXGr!B?ugNYZa*J;^>=wb?o+@p7_N9D8#pZnT4!gE=~XM%>TClOBetD znJ;^``q>vg0($!Y7L4y|ze+DBBl&HeGZ@YmCH>f+!8p+9Pxk1p>Fb<5YS!q`%)G^Z zW}oia_(Pj}z#e6~0(bsE3OwkKDLvD}PKygs(sqe2ytz*UsJvM3*XHCYDckAPqDb;elt3^{(9Emq3;WhB zFU{Jc&^sl7#{7@=nZ5H>0Hu>3k2?8LFBp-<`a>kzMXH0X`E9>`%ha{-|19~Ec#0Sz zQgSiZg_!ccS9#AabG;}f|8})7uUQ#7TqE&jnzAXYR|rd+z*{YdF(HT+&^KJu#G6qK zm_MacV`|nr@N3mA5aY}1+p>DzDLUOb1rt8&onhtRmbCYCc*%+n94;08ujVgXfXkpK z9O4^g;KLtI?TGsL(q0e{IMzg;XMnpCD8DI^*sk(7`Q@vHFmNn49{o9AL)1wLU2s+} z%+z(fYHGMCvcgR>^8s98!**A3v)u$c-^xY=*AY|Rk<_f>rl;t9P87TGKG`#U;r@Yt z3isW7d78-UuDhQ3w0GRM&+TTdIr=l`y5>)58Y5Xv!1Bo7A10mp8ET4_B5ihBg(RkK zOVx0RkW|#k8W2px+fQ>kT!B2506{QN#`I2wp6(!1H8uMDWyj}uM|ZUQGdTGSE83^mo=~#5COu!Us!#a}fE9=Y5qK+tQB%IsNU7P*ne}EbXSB zHKI;^A(btY#~Udz2Bv&Lg_7JPooVhvcZxiv-5d~b;xpe0$%Q|@r_<={K3 zSJ8Jrufr-Wb-b0SG_fSRQrIu3)UlX1+^^LCE)|-;k)b;Fbm!SLMHF8jcd}fO9c}zQ zX{cOni+jlv+WuXAU_o}2A3^pJL6F_W552wo^0cai;^#ZdBNieh78Ea0g(cpmA*$Nf z9E9QnY`GA3o3OdYL}=zrY2k%{PA0$&hUOMG3k^t|YO~LtIFSCOhBchy;@pS`35HZ? z^f6g+?#{iy#|^@rxl!MkJ5#ZJY>v11%Ya0M@%&Cbrum7PA7yj5Is)%1%Kd9|SR8!~ zck~60|84*Fpv$}Zx9dkBlV}y{>bB%Yc*yv-SzDxC@}%=`R|rq3(79=-;K*u61sW4Z zb^ntzsuq!E+~77_d)CFjy>M_h|Mpfr@Eu7hLTSxdqLPU8YZFylwtqXt%1&e4Pe(6Q zm&7X`&Xg&&sCB7#f|V(_^LVriE-0+1I%U(r*U`0(%lH=D{J-&k_v_vN9U%X= zBp{ff+aQ=5x3+@{U$^1^?k2U-#sBSd|M78NALR7#zvutXn`Ca~Nfpx7JNAF0_c{L; z>7e=T;y(S~5BmW1-}8TuH$a!)`%V4dsm}k+7aR2E|33Dw`M)3Z(W(D8{_mx|`M&~v zNB-~PZ|48L-v{J7_kSmJ)30zEI>VH#O%HjS%|#Df8&S5mUoU>|@(A!*pB9AnabuYw`6@0!mJQCL9^o$SIKG4aY*iF=K5-#;*j_vnplMs z5lOsSl~`%|=}x(k*iyGGk?OQGN_zOd^Ze!T@Tcii3m-tB{&56swx z8X>1&*INIUH*1WVG)8Dz|D-tlWH+O{$Ynm0xwTNG`E~wt1IdfvyDnw}%DH?oxiySs zEU}vWUNg07H5fG-ax4sgwIn@7#i^&J@T+x-0wYtek-^u?Dwm-H?1I{8Vrew-w`k&d z7f=u};9J-vam0JzOJ~J4F<8yLl7YF-g11!ga{k=*w|mEvdC{7BE{(}LXn(nzW9PGw z(f5yOu3ET@2zQWn*R}IHtFSwL*L0=tlg6)NOLfkbuwFSre<2|B4c@EUT)#+?)ynwZ z$oud<`q6%Fm+|(&&iuIXU+L((UVRASBi()K>Jog_ulAGv`#juwz0rW*Pe#_Pec}Y( z^W>Ye-go&>*84JX=q&G&Hr69E)Tfs^dH`9z?_cJ}MxKo(*1_A-`b{E(T76oB{yY!8 zt!oOJLvOBq#>Qp-ag+JEEf3@8PTtgqq3IQD=zWyizRCHN;T!%#-bwHNaa~XUxDNMA z7%58=%v0{dRj+<(o0@$hq}h}G*J?n`XV!$<3>fB0Ewqj#wjv{lGMS7()V-!ikqkEw zRw)K51-XX~VXK*=U4B7%D5|@$JdWt1h>Npzv3v0TG~Es2aTynlS2+NdzuXA`5@&|^ zuulL0lx`k|4D;hva50cbnlUJq(ZuHnvk5wrG~7BEa+4&kc5ZyPf{qS3X(YO1j7=5>X(q-_xAHA79WbM;;z<)jcf4WpjmwNU8gL?me>i=s>_k$Bb zO_u+^tXKbkp85YD2Waz3|JTP@`~QXizr;zHp8o$Eex<$p|8PZ#qy~X3{eeo$M5S8( zcwDhLoB2~#^e@iMy(c$(+r;8sR07q^Y<2jN^NVxCkDSRfPH%bPh0gbERG>Xa$e~XaeEa$FIsW>B@-y;?*pv@DHjg!o z1Z@TorP*cts>DiHnUjxxd2^^5+^aiV^b(^cy1X$>L^;gdcI*Fosr?gC0w|MCn-aHx?0{GqN~_^TuIL zbTgK?s2HvKB3mzbq@LsiYxc9)&8C!BhHXmuhc}fHAG&jQ-~Xug^4Ghetj?m3Sn4;$ zS|I9DxIfgyVh zwT&k!FS6bWxDUP0&@zg^1S{R_Yx=8NBT4tQ@S=|O1#s@&HwC}Ijue>!o_Ma5^ynrwM7kH$fIZ43j*qZkLG95kW%tLEwZ#8TIF z#1b9REpJ7sX+r$N+-UAwF%E!Aoz~HAB0j!tmsz9{J~A`6Z9;QL^Yn2O;_qJvm^ZJ?Rz+(C`u(mL*n1AGA_LR?jvsZ`(iET)c&MJZ)Vcp4)*? zRpe%g9+W>HzHyYDhwJKzj(saK_Vud7b|2u_KHEiIsk+9ONb`^8dMcfeW>x+!hZ*&PV(G2t7_fe|ze1c&{@ zEgb{&!2-8P!ap53#wv+9>H!@WB4QVAizV;L1I}2oEl1#%e|7E9@C}DBG?SAfzfAui zlDxf8m`R2H@gh@J^;hT&zWe|>VZ;#HTMtEOVz^F1b3L^#F?4h{mOS{)T`!~YinsWI z{K73i7BGOhfiJ5tai?&;(Aq}M16$jEQ9r@Cz<+g3U2uL}>*jDv9euA#4yM|>ip!{C z;+(yUH3pSd-9-|9zbTIRH%K!we4@Eq7-|TmD&fTvxI`_6WF6paID%gk18tk2bqA|- zzUVg?#%SU%Q3yA&EUTA2vE>lc{!?OZVn5f{bFr{5Dz2>>^hPv3qX>JVWqo64{Mxp3 zNFto(cR)RvW~&nKPDs4cv&8^(zvVq>IiR2_n6dR;dI}8)b+Ph-Tjti~gj-%x@0mXp ze*Y2T1(KnuD)IWM$-PHKb3gC=eto$00eugZZL(jt)7goI}8Nl2(utt}I=bVh{lGGcP`@8C`p zbVg^Fg5l_6NCko$(f~Twp-z5t6?>;xy^VpnTb>&M}i9~f;G zoQy#mD?eCvZMgMTJ!6pb4O0uuTa`RNJB9$APxmFsO`3?KkoIg)R7w8j-7cDYBA>UZ z(S?SoyD}J)Y}0TCY}dy9gvI#>h(`JTiS~ck;-tA7XqOJVapADQ+=gKqni?LrOTY#< zRmuM;;ntTAvGVI`bE&{E7fxOXVbCF%!v;IO{vhB_p#fLIWJ8^ym7UFbQ zetV_0p8V+30-((YT%**pp}lOf(}>4d${K%aOGih0vwD*pb{}>khQ1&m5{()hC=vV7jHdLfHQ)F$@{)t4u5W{|)B<&-)+w{~MS$NQG9qN3(gv{y02~CAKmKUcJ(a z66?GYzHAe(;koz;A2=-pFBBY#Oyoti_ufm+R>qN35f^|^5rR#TiSSEx`%;}(+tq%a z(O2|i&s=m;$yXbF>+dER7;j?U`gUe z)J%YdPp?#9cCM)!o)+P=o$pgXgo1=`h-@-0l#=~?h2OO~sulOFjs+CA4`6W1hb8!F z9A!(wEkj_BUzr4M-MiOzPpPy?OJ`%^P(Eog+%5|Fz}t%h-I$+z<+y`sXRb4nkUbKg zjMDku_M!Iv??)YE@AC|<7UNBgYMpeSKmR$`w5xF9pmuUc1oeHUuD-3Fq+APs#@M5} zuZd3``zCUh2Hhu$U#3DA4?j4^+xG|>#+;~Uf{vNt-Nqu%8WCVY?fGdeJ(j1qd+!X= z67XA6!){u9JXNny_EuLP2KG3$zp=+;etKgMTWQa(rwxkV+VYgu%DKAzwSRU*;!P!J znMeKZH(O^Mv3O1I^1eJYeB0EVhQSh}dYe8VxSG&BGe4&R641KT1q2m?y+6cG)O_0N^rmqBOBtD}wr!iy+K9zGCiqCCxfi;AfX%ks=T7W&@ zK6LybpK77q`wQJkDO$q4{xNs+=X)1xCe^}^s2m-xZr`8TDGRvVvrG84rEP8T4Y`S@O^A1kvGAhX zldf?ZeZOP}B`kh^8BwGn#a4Q(O-U6TRHlgY%Z(wt{xnw1bAD)rV06>bdi6!)?h(ze zJdbDmV~rmn$6!io9T`xMe?6Wt9d^dm48TtY^qh>XoTF^SzprwL!3t482_z7VQX0Z} zI}D%u^Cxk&+a(8*C*{hEMn!V}mfVe?$FRtSm?cxuR&g>Ry;J-?+HIS^ipITDBcO;5&~9Pa?7O|X zbWH6Qwx8VDCl}xPhZwHQ9EJmYqFWeP8A&cIQ<3r`M*>=7|M6?n2e(=Mia)gcTJKUL z4<}d3OX5#tdRHll1i{x(fhV{j$FfLr@g}>TRa`3jr(d*VNwj?HHCLXR9Qte(tA=oX z8q!tCbMT=pzR{xPW0_;Ri%v}y?=_+Mv1aPXX=@mS!?#xzNPH}s#B$kyzQkYF{80nQ zO^qZ;miDtC;yEDDw(QlC^!2R8EfM_5Bg?L>ql+ NN5CL8F|8;qou(pIa|KbVz!T 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 }Ln=_} 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%0AW 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�cD4QNTYXToR@wV}->f+` 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�j`ana{ z3PXJhL)U}3XQrY47pZKS8hcI6UM;a7!2>yQB@RXjr>eU_--TbVK~e6dxZ7FZUB$aE z;ci_VNmRyDjR;YnY)q)`|8m{`Y}!va3H%3Sh0TUJUaHo?a~H7?R^S2Bw!^N2c65P! ztA4FCpHZ;=#C;cl&#?b8OsANb0xs0K3mqKRdo=wtt~aG6O~jrxw5XXsOlmps5s#>@ z-Qb&>^jW)GB^2!*fZDJCR99lu<*y7aAok>XzGK{>OsMWpnr_#3ijEh~v5&uX|9{i{ zuVnwBtNh2_&tvWHu@sAkQkUX%kZgwm-FCdwfHEK<1{52L`)r}n+J%$f2KHWM+fdtp zV*kJZtvFYb;$@)g3(FCt*?b6tG++I02s)B>DjK9IQ#~XX!ff_o!D=3I$*hbQ>_?A)*rQHS|f>(;i(>F24b@)A7g$M$sud}>Xjr( zEb?*UzMuTDr`MSLu?+`nU)CgiMh4k)0!S;jp3U7$B8e*qsg3SCgS*T5$A*Tm zRzns(cg0Yk9&7%-ARI$Ij|2r~@3AQW4+s=M#eSV3m<##h`hPfe4YtrT`36qnIy%R& z9I!0N2w`a&Xj6&CP0tiKTWksJFls%@**|!7B@i`*W-canImFWos_tC{6iA5>)~K~wDfpNBpF)BKQsarZaDb1CPo7xwwh^9}Bxi`9H+ZI6iPA zUPVg~c;^3%|1m|EFu>{GZYUy+Hm?_xT0NX;Az2OLMzBlAg3Jq2ne zCPf<;8aK=_eVnQt!GeH{+rH2Vwx} zh9{F?Hen=bZ=BXL_=_1-Wr7>^QoQO_NqWGzfj1CiC>1~%SZG!qF@{`K3sCoLf7apd z*&ouLkt)S7rX}(ID7)xUe|yMjw`3CQo{a~{U)<2V{X%a>L4=yj9~AqxpZuzldU%HS zHz4yUf67jFK5>54%DF(&4xlf5lM@u9x z^+fJsMqZnlrE|o?`1~xmwrwAeIg@=?e2#e?AQ#i1W~*WjoIuGjaLceD(E=UgJl?`W z1_&Xvc3di&Z~?XdQjlPLm+dTElj5PV>|=>?V+V```6Dufn}Hfb+(gFeC~BxrdMpB& zJ=qH^P04T?PW=NMG(&btqnPsUpU4tt`c~N-lF}K$^i=1svcT*`%rQ0?W+PVS){8cn z73l0MU{b@CnOk=W0Hj*<#kq8qt3H*y2gV%3sV(mWk6C?-y#&#6<8+iEI@=Zhm8YQ6YD`Sc7+3YLSz8Hh&Z8e-cNeUrmgrr*aqEem5 z7W|xt5&&i|ym~~bx|M1+Y7j9=@wTDe)FxQA|MNlaqP|yeD|*#zVxs_I6$%tQ!@DM9 z9&fJoGg`Hd1Skao%HoHZXvl*?p-W$=tosvpR#Yxp^#b)5W98N1I?GS)58tKZkDQ_- z{wUrJ;*V9NN!a|wY*_~fX6k+65NsX)aMzqIvaFMt)eoI1;aH|S9(TtM06|VC(v`Fm zpf1+*#L|*nARHV6(y?3$c|h3j=>cJ1wkt;1pXg+S-KtOryXjoAd-#WVd2c1@747_? ziyiWQg9h^lOS2B9b)ms&KR-i88sA~1U8b4>*}MD!RSPqUVqxa`~~!-+!u1@S73uxmq0SQw#ZyCUDsu>PiO?Fph4W}4xAX0<7uCdRAfPTLnTEn;Mh zeUT=Oed&e$~*#sRPs}dAbr`vwl6T+al_4V-$$j0LXoB(onXF=cMHgNpOhkW~K#ZcXNh-iF9+L$?u!lO{q03+@K}p{${cNyrcRF z{^=dKr3c*wuX~>>KPl@MGV91n$*{ab+~0!jSWvn{2nn~z>Z}z)d#c66Pr3=BD$xG0n{rAEG0{us^-Ecl38U(d5VdqaeriWQhWpr zX^n;De|O4iDUB@X;<~OIm^fp53=?}FW_w3f_*NrvowzApTqBY!5XZ-JEHImon*>ZW zg?#KI0Ai(pk8?OIRW}(>3Ma(1RTLBk%{dn+Q^N$59uZGJBX7m5m5_;;E$OujxIN+2 zWbPdb=l2+?IjkQZfDO|%;SQd>KVCa(!gY=tGGpwRWBfdhMy%=aa~V{N7S;aR>TLJ8YXB8O8y5Abubqp9}JaoPv>_Js3q9nlzs z9nB`A#Ouu^x4cwkOnIzI*_SIpOWn0?umoFGc~E)9QS~jjK3}~z z*F%>C&ik@Vklz`l1nL2h^?`H^E;B zj_i6QNQv5v+yG`LBdn1A+PlaI3Z48U{{+h+2A9jXkRMm<)A`>%^(J!(!kPcN0esZs zjiK74MIT79U_-%1zFe|PBX`=HVcsx6NVVVmCWKX`KU%zempsqB=0)HhwpOU$)+iwLgD4dubP&!w?Kw;gc|Nt+ z3i#qZ1Y46N1?P6Eeo4DSuGD+Y5Hp{gf-9<{O>H}ZU4`{A?3#K=0(ND6wLf-UB1s9_ z-vPUR{*o^Uv+y-1vx;$kAc>!T6Xv#fgwbZP0E;kaqC33?-cc^ox*2mGh_+r%wu&go z6b$D>F-;(x+5Y+_SZn2>h_YDhMj8mEdJCpzQK^R6<$#FvAtYy?ybRBf|C20d*6PSc z1?IJ3*M}WI#AFpi#Nh`UB3epV0-68%3qwRp9(-w$4)iH4388)1`vj#%55%D3i}H@p z5$HJSSf+Lm6r8LiJPZy=IUx#PiaWWH_S*YGv3))NnI|tTRd37}+uCa)Etw1~!=Wmt z$?Na~2m53m1A5Cm<}xM_1V5EY$J}yKRwg7dGz2Cow0~()cT8Pf#oq7%j4S#{KMh~= z)c0wkilO$u{@wi9TPuKCO#ZC@ZUm7p-{N2n@>Inz0T++XpB=n`d~xQ_{!Q{F9Qm^! zhe;-Du{bV&HXC2H%z%9TNocXopG{p&BeYz(p5-d8BY$>g7u&Ptp{H6*WiWx z*;m#Rueki#y^__SQ3EK5&9$u>0fm@|BkWw;%23bq4LVt_Lt=W-Wd7`&Tb)d+|Nlb% z>}A=Ex*lNu?7CZ={fo_?rT_P!9$fF^*f(jLB6AQQ-N?TfT;(qYS25M_|I%o9Ly+yW zu)!5W=^h-2at`mI4rIllv^K~&?2fiDb|4}s|CY(W2n=F0k@#x}O`}i-;ztv%G09oU zV$j8>FmVv^EpUDzmQB^v?;twxGN%D6o{2RMwJ)J!m^-^3S}_XGpW3Gft5*Ra-yK)j`c3?nbNO6v-qj5~*56js<%}EMmT`?tkI|zXraba1^0@9uL?V1L3OBV2~4p4Dm{_@wd7wyr0Km0!d zo_V_o9$&C!1jo}@8MzGYhg~~^(BFH8a!LAaBLY(-Wmolml+q*(sqRRr9*BQdAqft#Y6$pH zG$w2@hjHV#7H#>VyDID|R}Wn!5?;}k>-@bNn37v7I9Rh5DR6|v6Uy~Oce~^)b?}bg z#e8Cr6aQM18lzq%Sn>SFw6Uwz6VsT@pdZnv=Sdk-69})U0c~{J58Q>XKwB1p0w_h5 zEbv;ZGljvQ3xj*=Z^3=(4da>Mv zSK)$hGw|#Dtm6w8e3w?#YQ0>XfQyu(R;vZ(MBFW$hYuz3L@(U+hte;6ZWR2x6>zF+ zHx#_hXJZGt2QJb-3*7_P6uAd}p|9|3jX$_{KyWb}!onc37FPSQ019al2HFR7Bp8&} zRVEe``uFu463;uVNiyZ9PTR-twEXM6FCR6>>de%xZ=8Mno$t^-cA@`~Y9T1Aq8Y0VMva>($_oI7JW@a9aY? zWFbuTM!Z5(G=qOBS1Ye18e@f(umXY;%d z!MQZcU$|fsg=<_^QQ?Bk5Uy= zPySl(ot3NY+FiJ7Pva<+?%Hkae+WmGUI@o^SQ?I-L4xogSncs1)wdg6jSd(;^z@BZ zD#eWxDM>9}Wbh&hjq)O!7aYFGLLn<&dsQIK8+cBcrd-NPxL#_m`5xaFu|r~MhAv+Z zFC07)BH*k`z+gpjs_raz@L2sb{l)ks{SWJkX zUZv}+!ysCvZsc9jq;JRw>%hbTSP|RciK-9f+E$;9=0eoR(j`$Jss$xnTVHKx$!vK8 z%$_c9Hm^>Ngh6O9X%R^y>LVT0>O+;HcOd2i>LY!G`b@)j)M$DyP@kChtqy{Jd)qSc z(daxzl@bgicVfjMN!Q_lsbWH8eA|1k=+92( z$5{H45El~rgu|oCQzcX~%A++&>j@9pEhRnWCN=3lCl=;1svSM0cuIvbTQjy5N<9>R zv}VL$AIiM)1$llI{v>$bl;%VSBeSac^R>sB(rYxx%l98-@b^R*CW4YNl12G(q-IEKdn9)e$itVkyMe9!ajT7Dh= zplcX;Lu{ET`v9!C42dpCwpyWf?SP6PBIS+)qN#U%U4018bjN~A ztbMw?B?vZY8I$kMWWi2tDxWPAdHVmBBL>@7}29m>a4 z?I&qlsQYLQ5rzhsk&`79Jkp4QCo~Id+pK;|sQHb^p+2SO9A_&>-w#_kYgLS`JhUv{ zR!&{g*j93#8TM4$O0^nU4N_KQ8S`xDv#)Dxj2fY2b7*JAzhyaP|IdGqzKG(gQI{t& ztEq3myN7L=i9d-LD{g%D{+6dOf0}ot)@(Stm^bS{2BHXFni}W&)Jc}bjP*dY{ag$) z)YSU9mDk6u+KqNDciQfO3O3rgZ11nrTbO@CjS|^848;XFw=kl0N+xHASDhf`67i>c+Cf zq~ZK;Zxe(uL_&=O=x_=A_N5D*bhCcbej&__X&K5q0|s2a`Cp!-c`ir-U*L0;bf`>8 za!*|l(PyYTn7|%UAr#YN@!sWOb&L4h~^O+2?>g>x6jS|(b9n6s?wtj=N{$m;+L&kGJ0oFeq z>5PA(G|{(IKlq-YBK$p&sOO$c)PMR|8D%iPrQ3St zmq(Inft5$=p9&mP>nc&Y2o91Dt5Ta6nC7q`#Vo2^)knbe`UL{7iv+-4zpxkd{78qW zzeDJZZk%EAe>|XZqWY)Uw1uhVH@!8rHI%0I=F2Q<|Cj2Yp4EK)(_NtdH_Kz_-|~lM z=s$CQJpGR%72@e1w!otF?<#O{^uNr4v*|xm(hzL=4-kOF^uL0jvVQcQ$>?BDTGN4?ZhFU1*YU(WqI#p;##{W~6l<IoYRl5g$biM(rCE4L*7W&zU+<&gYk z0szYEOb1)?ajDz_${vMN`=1S}>P!_6?Ti;X;Ir(^Vs6|C=YM~Kro4V8l23x9MHghT zfB0g<36AeDwa_rVB73_SW<5Tc{Vj><-`iN9Vs)aG>1OSpNl3v4h4{jajYEc$m5Fq{5E1Ryc}@41~H*7RS< zlpl-!i2uiII{NHdC*fl^9Yq<1O-SMVu4BlmlTSO|`9>mEsorCn;MD&2w_K^m4_M!E zbcFa1<||b)EX>pkPoheC;)M(Xl?7I6{{Zn*ssDwcqnOeIA;8)gbqaG_NoLe(537C# zV^f#JFm}^so3Y?Q+?cX)UOZ!mPcn=h;$ZAt4d%zXwo$CfHkgC4_t{_;W5)=X&V+zs zT_*s-*b>B29Ew$c->-T9NbBdH+@Eo|FqiD7|93$9Gm@{4=A>3IuZ{-a{*Ue8 zZ!Xg=F6a$KZoe9Se zMnMzscf&;CZwG%Yf8je|t0A=#xyY`L?B&bVhZ!5yCfpJn9$+W z?|b5p{iI2em0+G)HL4l8l>q5~DL?)pDcFtl<^#=-uPk%QYAKmWTQuSaFmVdg*rKx9 z?mNRoEAu%{T+e?qUR;;ooPdufTVS@hE)p;rK}oagAOIq+z{hEhO4WG=l)?#dt)IzH z3TPSbIL4teb%KCm5gE+8xRAVUDnEV`xA=tfT|G31%OTDF?ek6%y5_KK3TyW>2I2 zl6)OEjsE_x()pAu-FZF5md>j-R?q&^`qW2>0oCKc59ZJGk;ASnTOn%Q(GiLo z!!F=gFH6)|Cm`M|?tDF7&MraH1y=hL)Tdr5u;8PkKJ_`0qCqN(3_T+tB16E*DMJ}* z>y4lv_Pq}VarA=FIOP1u1i5j2>VI$sjXI-8YD#K2P09DqH8N8FU#U;MP&ROB`hE~k z-#h9--vw{S(D$Qnj4CIh@6^}g>Dv-yNKD@{fsLi_FOsle(|4eNB&P3O0F^-Uf`O!P z6ZNTQKI5dQDXVbeIiz-ead+o4P3@8ASkz8bKelJ1_>aB5%F@%@Nk4JmHwz^Z2~sUB z`r`Qlx$BJoDA0Gzyckni{Y5kM?el6peV+>0^mXo=glm=}u%K^ow7&W|facs1^2^G| zn_ppbps(nZvodmqYE4iHFO&{&(#c9sH8L7@eZv`WIP)Nn6G~I_;E{%!b@lU__n#$n zSO7ouyt0JxMQz`tghOl%SI&R*`pN$4Q+FQFRDJ5lw}1`n=V~@!>5Ho9{mf6;51;?)5L zxD@&drf~FG!i9;4JE4RNaRZUM?kvNU_(;Qp&9F$*KTpd)upGxA4*rRe|0F(^vBq5^ zOSKpW;T%eR>aLezd8AQ&>P4avB7HbI(=zMs&EUt7Ihr5Injf!4`2nXnjvtvXMft&? zPnw!?z0D55+UIjYEqjz%;ml8p$&A$P-83`w6Ri?I7aQu=Kkpjh%E;%4HSq+6=zN*@-{& zv?Np6>05P$)xTpa(_VbjDrs6U>6WBRuNX7V)UT*L58v}68bbe@dp38-U)_&rKi@W) z&Lg?TA4d$Pn7u4-X)17ySaMTB!%(ebe#1)CT^+#6twKU9jxGf-d0x)stod@G+vm!u z&=0dS!2{2USMOhu6&oqqPaD=(t+otLnrKt^9|cd{HP7J_WZ`6@!d!;JP$4j1(Xg@( zsGqr?&ocJ`Surcv2s+6|xTa3Lby>{FkbkFz#FPNOfe~C_540BjL4IGLz!%C~G+DAl zKENN&hK$(iBC-o11P7yXEACDQQWSu3SKLq$xOgmnCSP_<;5=WjPZnoEDJ*S}Mjtst zj>1Ilt?q)FiK><@pgZ3i(1-Fm(;7mEt(!K zO-`+bYy9aOFg=iqGK`(5f??eU+xasqb3-qm%wGOQDMW(*M+^@t?!d zB%$Y~SBS}<@#EuU3v<)qTEO7HJcq8F`>JLIMA;!qXFLb8v*K`ByqzP#sb@}-R_@D0D6uuiy zZ%=gcR=aC=i7wrQ1#i~Zch_vF%ls!j=#ynvztY!`s)B|&N*$vkD(|cdm zq}9%orKOvmiY4vIk~|?*bea12fjky32u&hwm=04KG0st~1(YElSR9{mgs|M)`@_h= z`2QdnW9B|!o8oU|MKM$xRU5;u`${?i-^{LXRMo*HYa5l(=8A?#eKgp~C_O>JcRclH zJG~|=`#_)XZ0cu8p_~J(pM}9zY(^-pfLnaLa3?fKF<(N`wcIK3T;j6&#RbV)_oTG-?;v&{Oo{?2W zTul)zVE4$m!uBk<#L9hc6KszQlBvZ56H7td>Wt*CG{1jA>-W{q~ zHp19EdW+1#^3vvIo+RWl((7@*Mdsk%!(ZZFC-~RY#of5~78!#F-M4w*e+|P1g>!Mf zvOjNG;5dp0L<~u|6c5PAL@g~SMX&;=+xvqbs*2<_4K?!vUBqFzlN0Z7YEnCG;c}ot zxm2MOp9H6meNl57w!>j7+fR$-^rezuK~7WXWKqqo_ZdEUY@S|OgVb-p0vGkvd?b{) z=T`CL_Tmq{8OM`S{bWr1ldx;nNMZ6BUBKjHM>fY~73tp$YwL^RwOsS>3C%xHZX5&> z{s~m8iGnV7PW~4KkM8;8){cW-s zxqIM>doWda`Z-3?|M4g(E>U!t|7aFtiP|(Knx$6?xhvyZCS*|mrl_P)7Sbpc88Y;V z4OAa_o1sm8Tib83MnLheu0-EG?7Njem!xWjGXcuW_^!^sWZ3)_9$~TdS&9EYVq*>* zqL`#5;3yNR4=qyh=3h+oe) zGD5y?m|k`zb#i=RUpHS^D6~}lZQce5G4FLFUHp+MrNVd{!S+y%;)Q2)RHUfm9OXLjm@A5oY`DX^O!Y z57}Z+>J$Tv|B@iV4GwS&s`K9vKyek&PH~EOgrFiO%WBt!>l+q(Gg|10xTBI3kB zO1vh((ge`ilnrNY%7*JNIPYy80esIKP&EyO?2 znELcd-Bvf<)~i?OqA55jP`7p4c(yg&ZtF%|vnFx=HTa=cj+T~&u%%kl5)uN5)nCuG zT56+P>LD#%Xt$JUwbX$v-KkqjVoUu@ONZ%}I%k-c(%(Od{Y!sQTIyi8^b}iS{~pE< z?%&gG&Abk6ZGS@duY+#ummU^YdJfmpzsK-H{WwbccO_eT#i5wgYMb0b_)z9tG~vy zP-eGqaBK^|A=Iy4)Gb_Uw?M>Ix@mzy=IZ>Ob_;hch{0h3F4Yyfg(K}2=*6qmEYJZx z(RA1}m2|*xnd(BvP1-f6ms&9vdx!wCozRxF$uc%hYk;pw;W0`*PJ zkr!U$3qno>C}GRj1YggU^RVl})fWCi0l(eR{u1kjclpBe`h}J@{w4Cl2)q617Wm@? zznS2n{Qftd2L((Wz&~M^%hxGsUK)`bJ#SsZ5-)bsU>ING8Z&WJ5^v+@h302<{%>^_ z=BMLc1pCtRPsR_K|EaFJ`Ay@c`OW+jc0D`TG>`qmZ%O+blagAX(QhW$?SEx{R_FiS zZvS1}llI@l58eJeSqjgu(e2mj_6J4Vf5dM8AmSfw|3bU{Q|(Iwn#&Yk_T!qX`Uom$xB?r@QyrK;u>mx zqW+cLFojNqq6`? z=BlY0<|_~uuifE*xfza*^h1?vm_fRoiybiI>~{PbrdY$A?tt;nMLS{-vo(yI*8u)I zV2-z8k~Pddx}9GKL~(9w!5IEaRp_KIG~mY$z^xP}`QU5~^NsG@^A4EbNO>W^{Tk*P z-A=6o=1}W{>RJu+oo;8017@w=&QJ}b-5FQD1Ll}F@GT0iI$FaZZ7-%O4Us4XML7Q} z+!YA;zjDX5=CUq`FaIsZS2@BQlNV0?TPN`^uDz084>H8fKz2E4OJ!OKw3w^&dZbVE8zz^6QrVc?DZ~%x>vpTuV!f@Ix&bCM|i{(gf2|FWu6%otDpY zkZ$QvX=$Y0QcJc(|7lN|_)iniRvoIS?mhQBTC+Lu`uU%4UW?!Ey^)LBzF?-Fx1?EZ zq{q%%&eQ#R{Ze4_!&Kd`HheLhy5}3KUlkpNLYaci;-E#LbYes6*akn;_9FBPlX@Kk zG~?$9>l^CN{jsSjEVIU%3y}Q({kg=)&Ww%U6@|una3FEuG@akZcs62H*k8-NxCq%# zmL2De_Hk>g$~(t8lUCi`iwr_QEb^QmQKsy%bwzo-vI4UUgIQUT*P>B{=r8#`&qv2# z$521s%CWwG4I`8|Ax@u`j^lYzCcBszpkx&zrP$vb{MwIdnw=`0YY1xkNDHC35U2Xr zaRxscaP*0>Pg&gyz1`gFF@QP)`CKVbTRGATaBio?CK zEV`URk{sv5rf2MHP78FX%4-O?-Lnc?RDa{H+TDU1ov{ka)iAtQy(nd&`rFx{2>X{N z{d-UPH}~J}UujJL^4PczgWi4Yzs3JQD}Q5RzCZUY`}=MGC*Plbe$4mtqTj#!nEyrp z%Px%h{@fAK{{K(DAK(Az_wUaBpY$Kcmva~}`Zc#W+W-H__a~Rfd_OPx{kxC;xBCB| z+P~i})(Gh}R5g9LMUY1JucyK9ziR)oFO8v3XB!=LjrIKlwtqVQ{7o4BP6FcfewPI^zW7W;A8v^UAZa%aju*O&Y zej8u)lAZ6;?~lBp@`})r=-_g@AbOKQ6!>M3YnU^0^wFM$yY?x(D*l_WO=c+=-hndx zu}Et{V_^#Um$&p55V_Am-l}~K72ijC;B0~h98`^*%Sf_s!8a{UDHzZd-9!?fuVLZJ zE#6-jR|S4C_@it^xV#0t$R!JbR72z)U&CTw-Y2)bdBb7uS*QKQThmbSgZ1nQ)TUF} zK1{+d@taC6kC1r>5xkcntI?94xea-4Cc0FPM zUG7`?9TnCCVSDCeEN%xsXMFvIbuf0~s4zVW>*v{^&~bA(F@pyke%=E>tU_Y6w^AjB zgirJO!nZ-P-G$+j7QVdYw+uv259dh%E59oU?)J{#p6qqcf~2MQLl(iAc-W}`&ck5$ ztTwHYM0Ud|!@?cB1(W*@4WEXO+=eFBUjICkPw}CZz2~cEw*o0dJ_UClJ5-4H_~Fg5E#qD znK>jz2)|@&k+sHu8;(}uYzO_@3ygnzEaVR60wzQJTR4?)Fm+xG;>Z11&DGXgKffc+ zPSm!lzjtqBRwH+?pSjxq{kvduZ;axa3oSn~`);Huw)|`+uPHw-i~PWGEr)JY;R5>c zv%7jSe=PVe*&j+qt?F6+_9^&xWP9vLIIX=e@5dWTp(x3|P;zVctcuorc7E$tFo0cB z224J`3!wV6uFgMeBIjJF@RHmm;!?F(V23#b@Z^!LTjBg4{nQ^!ZXJO?`kUG$ITW_i zLHvS0s_g@e4E(4z;V1D|T?-QsY^13(8v$Q3S>8yr(lUboVgWY_qjCt z>YMMVxwhmS=CcT)F1Iki`4NwaoQPZgs))%8G2c%l{~am+hcYX|lKxqPW2FCUY3Oq{ zbYSm~Z}NTV|JAYd#XJz2*WMS(!TyfCp(#wjugvh}O~?qGN;)Ir#!_J{ExcNF{c1H5 z%PJ0+J{T~xQl6E9D3P3xX0K%j5em#Kq`}~|32=CwYTjEDC z->*OcxtNZb3%h^+O8lJq;l5*CWBIeCOLcx?qsWzZo~gN^vr8Do!6rM5FU2M9+9`ZL zT#O}#8*=B$GJrU=qMz$Unyxl-F{)Tx6kli%ehe!?eusWuWC>9zgs9Atwldg{L8XBl z^~*MCah$7+on&r4zIXznthGZBSkB8Fk3SU$ z_nwdOp{-r(P_2kKM>Msdz#33Q2*j6EZ8|$iAdX{wC2S@~nQR$l?h<5c46>BJCR9Tp z@I0?M`Ns2ynh-sC-;&R%^@-(^-*5hXB;Nz5q6r{8`n-Al*YD5V-sJapH=&vafBpW> zCXAHbzpYKS-+5c&M;3iQZ$h=L=XuTX$NGLBmG~o|Pv_>}*Zph8KHk)X>5HMy$fo)8 z(1Gx0Y7_ji``5Jm%x!}77X5B&j=z+jNMh2N{vl8dpfy_(1L4u!=HEB+*8~vx(}ZZn z(06AOLWKA84un5_n&6K`-!~G$LZh<31m7cr_ovO&}s-;<@8h#ARP=oa2eCsj%EX>O> z=;6n(Y<0AL44;?IaP|BghT9OFTbMIf)-Mlfrq60f`UaTjuSS?tTwonZ{47tNNN*>;}%r7~9t(75RrD-zePh$T68UKHk zP_k+Nf8~Do4}4`wNkWzh`9Hq-{=cH5kyiiP{rUc%keI$;IAotuh{6n{IAa2%zabMC zbvr&Jh)3oLwPo=ASSYh=d@L}F#B+8T_bvkp)~P2m~{1&+bNgPrNl@$%I(L6+Yd##-T0UA|4-rvZ1;~} z%m4TA10na1-z9DT@91|C`0J(p!vqEY=(T|w*m#_y#r1*PY3{*mADLK8CYErwOBpv} z6a^Q^AxQhI6V?!aSfP5X*G3~3M$_wvNJIrdw#&%QBDJec;;zV`Ap42x&oM5zPscm2 z#U*6}=eJyX0QUVP^bbU}_ODp>eJHzwnLD(HM(C`JhE+5|9^h>DrNj&EznZ`_@*ssa zM@-ZUBD7B%Q5E^*`fP&lmyxD98VS%8;eleRj=lYMf9U8PN28j+NvNmy_e7Bk3vzcx z^$7mY=h(myy%G1zqLo|7Wals}WRqN9kS>2Gt$rEzs$5#{BQWaE%FwULJKHt?BHt%^ zD|%1pSKL@W8Gn}fU$F$AixGS-!GRXDOF==H$gc{6OACX${c?!g0PL}ux*8{wfw@f! zq-u9)VllMme*1q7aIAQXLmK>5BWZ}{wDhVK=#S2 z=6=@blTp1F)~H`o67#}}KWoiT6o3A+{U5ic5i+XM`ucyT|GSN7I!NBA|A+j${Rib! zd_lz79r-tQd}!KT$T_D+AC1KK%K3BgAxpkp?%7_adD$U)u=OMBIgo(;3GQ-OpdSR} zKQtHg9N#oiLRkQBW|!AhQ!fmPkRZ=Ob4oeop;y-?3fRhZj|G46me*Qc1qr>w8=H znCp8B_#;$|!90hBc~7HFEob%2QeU{uS-x-~mRRY$gk3eAIwkeq0ROn(6s|H!DG$OT zo2`V0XGVHrCH=$b%5WtFxoY8{$!*en4GXZgY1dE7Tj>t}g`Y*kJ}eC;w`D@aAS_Sc zI@})~+QOgr=?z}?5`NR?I9Nq;q+Kq2UeDjVhSwpuIJAYqfp9SJ|30i z(KphvF!*^O=ljDw-dgTS!n$*EvOjO_4MqI+U~bihZ^60*{@`cm z?B6@$nBLdXQGfVs>qFKz2D2&z&QHeKs)NwnRcOxo>Y&NVDMjHkTNG4(CrjH$`SX^z zt9Nmo5hN{Ry2oJo%t};`z-My!nW6HT{;{6{Aa{cUDczs?H_(W6_@a7nxwRTzAHsc= z-OCEhf}1ILrh8UeZu`Jl zjlwT*z$!fmXm|oRo;Yq9ZtD9o<3cK@EZ^waRyG0zn05{Er~n=}8CIWjkkfi5I-leL z+Q1kbWoXoMKu!VSN< zXX^fyk_XT}{)7HN>adMGTmH?Je|-`WkdtWC#R$(ML8I$o%;b>SrR*Q46v^V}D2czQ zej03NI}Mi0hQUZFn80opX44X2^&Wf1A+|E0b-j;gLIwgPPLzOA zKnIN)1R+7x1d=j=fD;@rB5D9_qeVAr2E+8#yCI9C+_kG`)$%3}u|BugyyzkuiF6W+m&bjBFd+xb&pK4`%Zl~nL zAXU4y*W&y?Zd2y@5FBaIU){K;X;l|Cio>gcPqBNg^_+Cj3IFzWYR^9c{W3%7-X_F+ zqi3`-Q&>(!YJT{Gf*n*G;aZng8$km_+9#;I>0X{ zeg%F+jTwzYFS)CDTu?gW+3Pgq`)Z>{MHuShh?TJZ(wV3pUEPATgbFnG3%-*VOi9w* zAMqKlxf^{aJ5GhK1g4-oN{!R)yzTKfuI#GpzEitt?$6-DJmsS7RPTkHAG0r?d|s%F z=C1RdjGGdlJ;587eMeb4l+Nxy6)__5eQF}|=4W5-9UlAu;A`$rSV5-d-of(pho1Wa z(zE+}Q-ja(C1QB1?O3NBr$j))nxp zz-86hze4tz(j)nll-fU1nwa`SuJ6QUj>Z{svetU8?KFS%=Mk_ zIMt4CnaaDW&BD_}%=_o*6Rsql);+*Lk$@?L1lg9dqme#*?+rG4BWt?_$N?BMD(7PhU2` zQTZCwDB$B7Z>QiAyrMMYpPoegQ65!9(;cU_C-9+P01Ypw`3;rZrzYa}>-<7Ed*KJb zF_Ih1P00UU45g=Xx5Ym(bO?d+K(mD9|W$jeq zytkj|LvarAS7k8G?Dga&sG%yaUTtQ5t*xx?-a9x=9N+J*Jw3$TYoFWJ$WG0)%f1hL z;W6v@b(?i)BjInk$uaLCxOlQ{kP_mnndNS1vm7F!UI1s-vSjH0z*KZ6pq{J|%~M_$ zp-Rjv>Oy&5Ts|KO?rn$YA=>*W?}Sgh$* zBeeufuhdsG`*)qrN9tz%)mfYd7pfS-m{*I?A>K3Z@N6RSRHLvvYmYaX6Lh&=e!0?5 z$~o~CF?uc=C8=RTR4p^+u9RvXMc3#9qe<1E5Eed(`Pw*}rC;Y~?QuLdL&Ta5J%Sud zNXhk`gv`nTUb%1?l~wPUyAL_=&65HNbrU4asg6@p@%94bhvKK3guiaG`0FO&ukENH zRw`JaD!4rbBI?&lL|uxv7r;=$pTCy!zeaiEx5=Le!Jj*;iD8Zb@BQtRpS2y6(iN!D z8XDZNDg&Y2iiL@RK*Zc#iXvP${fa|Tk~e=MmRy>>xFdDRBUn3e{lTGt&}P;!77cE0 zhCME&xN>7PflsOJ80hw(T}Boo40-cYuMRR~w=4>Q%RY|EiNGb<*-`mN)YZeV z&%w*NA-tFD*gFn6*MH6V$p_v*!xPxEPw0qTf8@=i`^0!lg5;)E0?QuLYLFbTWK?!qtTP z0hvBb_FW<)(3*t8h<_gk!qs}#Z|D=F|2l3r&uRZ%CB4g}0+rODl3qd*?H?-f9hImt zUmB7iIC0zp-zTK(Gk)j=c*W8M>H2WK;@&P*>i7 z%(X{KF#TA|jf{x+>{S#9v%gs?V{HVuhJGiq68atIDl$0fnhd`ZPeZ@!PFd=5HwjCq z?|UgmR1ro|&Dt^ZQL20{YI{zcw@BgvnTs)F;XFjJ_n~_g%JM20?ZvOVlw6~cr`acDZsoXJyM~& ztJlf8x3HEkM|m^XnEMnlZ$&~+HxJ2|+4qa2NHk8nOx zII%hopwbkC(0(B+6k^P4v6{+$0pEHs2PUn}?yN>{8s#DAW0N><8`&+a{Vm+FxorM__eSv)~ zFqj!UU&fYKu0gO9kvLL} z(8**T(EF|AI7U&(I{guP2w`9zHlDx1Q=f=Gh`o>T)5kHrsTRjzW_ATw@h)GJv+O&b zi@3Bdu2Y}TKdtJwzTdKXo~%J7$x``|4_tsszaBqYaP*Vkx8P`uZ*Xwy_hOr?IM_X+ z?k|SbHtM`Ozr!wuW6!t*+3_BXRe?qcRG!fw_9|sRFzg=%v>&+L8vmeNDTNNSb(W1^ z1#J@S(5U}W^k}H@zG=>wYVR;+a#1p2?C6v~K1H(Xb0i;qQ?;D^4?1IvfcQ0#=|C8y zy-Vcd;(c?}AHAl8SmN{MIY{7Lh(o`=x0ggN^e0`w;}XHtnAK2afzzL}Fq{=k zP>{w57Uhucm<#m1bTH6*p7$BoceSKlB0N4&DVSvkN}L$jeA5ntfj^x_u4Kct?y?zsc5Ep%QkxOSmsE zVMlg5Q!f<91l*~i#!4Sm^Gq#I-q3vrXCS)i*P;N@wjvy6SG_9bLtQ7r^pP~jP z^fw+?W&A3S1A(hDVngS^*#t65*RWOZ!6p}Ckyq}K1?Y4T0Vp9;FU^8zfW`)X_!SCY z!or9@hvFSVc73eu@!yWjfNn+{&Jv67EGCaQgq3$S36)`FpDuPHzTYzL=9D2m6brCU z{0X#afH#EOO{NkvKe2>KfY8cmv2!$5_sSZWw4dTQeA zd(1u_yA_~miC!z=vVw!y9ix35@>7%jVTB!nFIW%&3}bYTSv9;S8$t-?f4UuppdoY# z5dIp{+JL z<~_kmFo8JTy=&e6T2!{heSELG_9RSZfQq*Y*iJ%%%Nu}9!`XDqpj=;y<-f|G=(DIxrHKaNRH2F;wHzLgyh9`hYkx8}(1< zV1T_4EI|?sDg$ytS5q}S%|(Ev;i!?nP{^dCK_(;;9+Z!(8;axBYM+R=k74|D-i<+J z3{LOdKT^|=$(La1Xc_^>|F%1%#0H$6rj+QXq(sWQrqJq8`JyTkiVZY3H1O_lz6+Z+=rInyfl-sKxq}LMGx8w1w=FqB12O=&-fAxz#F&NrM? zh_hD>(=X$SgWtFSnwKcm8xv$vH7Tkb3~@Ek!axbuFcw3L;DzAOCeP&kpf8RuM@Ni1S zJfW5*9lj*+M)?LuB;!_+8Z{LXaYpXFUjTTF_9M(9Gc)&o*PY@GHHhDcW7$d= z$@Nh;-kf8{m?_zwz2TV&fhQ2H$pq8Ld1V?3(~NjxFJ{UZ9}1CgR2n9yvw8?is>qY~EE z{-j~5<>VXh%bbA89zqotyF~9>R%|!#9ZGZ;nbef!0EPHZ;NqMD@-5^<4RCJK2h1b$ zV%Rb`4dMdU3sY9?p{;^eGK5KJPbUl6<>W@#AUe>hNZkiFgDtAs{N9REfiLzAgKN2Wr@f@h^pCDUs7PMP)~vjej( z6Vlr$DksA)=&<|vr|#M_m>qvGLH59rLCHs8jF!3NZd}P;OaI#<+PUXT6KbL^#Qho8 zL~Zlfuoa`sD;Z7juZFyb_BBjh%g9x5$FAV=yy1$=#mPZS?6uYj;K1eRP(vMgyp@eI zj84TpoZDe2(-N=Z0HII#d04;YdZX)a@;hWLyDj=L6@qW15JWyos+}^!bPxLK{<(0k zy5ok72pI{gwbqy1DSJiAi;Eh?JV$y*vsqz{G1778V`f-|p~C&b2VhX=`nB@60wtEN z#D57{qd0<4V3TsWdqEysbs);Y4uO;N3u-|n-eln%*rvpcXlxx4)B@@;s1$ppFdJCb zlXCsem*95N%2r)#6}6Toc2L?%#n!z}Khgt3rX~LI+ipPl0>ds`k-C(f)9fcs!e8h@ zc~{>=yQa&~-oN2~T4jw8+eq^+n7b&76_qYo`57g!=%;OTy|tcEf>hBB3%W)-JbA-O z*6tY(U~cSjJ~q*P0B=Tnk9LnOgrR_;9iwIln+yFeQ z|4u3Dl7YDfX%(w4ooEZI{>^8@DjoZ?*3E!L`@MvAxwB82J-^u&f=q#* zgvk8#p)bni@fBEP)&5GZzZRW^M(_e8(dFool0-f5rk{t7Mu=|x;JzrqeRHeoo5VkK z%_eFne)EqA1w#014WK0#pun$O{+zF_;T+Y$9k@QTn!!D9 z1K;n~&pWkOtrGS4uP`>$hA=;4aaTqsO%7Le#5YnLl#@hXGu4@QkKfF=la03dc z6+3Uo2rLljc<1$zus1Y<#TrvKy? z)qjk?d4@?4$2k>a&sETNZj>k|q$imf({GYtk?A}25?EwXrzYcXFYjKydv}B~mH!NW zUFO{oT8C%O)bq5Nb+GQ+ro6+S-am!9RO7|v{R93^@VuOPz`Cjq`kx0xlco_J8k#`{8rP!C}`Df1oL0^2b@upVO2`DGE@xRyR_y$Am=!NYQLthOSP@!_YEV|5~cw*mJN4iXaREg!Ko;l?l zJtD5b%zp!@v|8MTL~Di;$tPWJm~*5y5VjAw-p#xW+L*Jmj!(u(2DL*<1r_8-JE>;> z=ukJh3vok!=k44^GV(yym*i6;5pVlquKY@<)Gk9aH)wG-eT15KRsD%y2(oIJJ%{~;cL(gEqzS|}c`OIUCfb4HYAz$rx z=WB6EdV@G(!%ks#N)>Gb`9WuUK#oAgF^K!%FHfhj&R_0~aa4@Q;=os47z5K-RQgb) zs}z24g$ukv9GwkGA9QRDN!BpNTEmBKa(o0oyC-LIwn1;;^^GyT@(XiJ75|S{xGARw z4-x~yfEYD`lQza(-M_zuhJd1bYtdR&;Kcd@i=tABcSs4CLZN~|l~uIZfS#K}3J;gWR!)oM(Tt-PuEvC!Wx{F(gaGDiozl@95O^Ap(C`c{zB zs8%npL3=tI9c8u(ZX4rZu4avKkX5MR?PQF@p3m8f9s1$h)HoFI4qHVZwWDISw7gJBBLB2>FeKe{ z>AR=o&L|qKJ(?m`_&9<-6T!-sSVGl8#)g>mXd~cmX0Fl{CxE|j>G?0 zqfHahGdVCnXo<;I!iH-j_E#1xk&Z`B63wKqjRqu>Ra??;3&Fzqp|9drh!*nV&d)4L z4&FjC5NYeB*r7zBB^MX3s!R25@KD4E zv^lZgT^>kQz1)&4p5sPH=npoW1@49Q(8Zm{nIvcdDd8O!`D6jaErlFlnty8my9%ne=Csl%|qwNW%VrN=sI0 z-#&+I^Hq{fCGBHUnM(R@kMv<9lkQSU`&H6AOuA7e)vKfzkp%x=q*cpmTu-VeO0g~v zwm)j_MRNU9uhu_b3%>8sTKOp@B430=Z9u^66G zU{E*rmuN*gS4aIDT`8Dr07v440w-wA&D|OhyX>sPB~I@HFHnxYfIWLXdt-RrMW+c$ zus%FpXCeh*;#zLda(z5yBG$%fk+vC{Wib8!f&yRZgNT2h*fU1gX0bPLdZRvnj=6d_ zOd?g72XUium1!es_PLqG1Xe`lRkYm#>b($` zd9Vs<_WA$m7Nh%d2%8B`){LCo9DA@Ak>A>N+3y|#mT0Jh{=r;S zg#Av4L0o|3O5)R>bE#Ps-53J##x@}bXylhf`2Dae`qyV-{T|(If{X&*)HMCh4aUfX z5x^D!Fun$ju-B^phW{428TMbolx%1i++Kj}(d-X(?g`h#J-63 zi46k9RREm7AagOx2uax={lpTy1*0g*=zbBn5mzp|oWz#l-{a+uzY@ZT_m0C9#HhRW z5Dq5GmP_8%@z_SY8vbum3Is0e{J5(_KsR3XtHou2;L}gEZLHj|{%lx5D9dOX7Wy5~ z8vRC)?rohwy5|Lm2$MFO0if?(*P_|b%OFLmf8bBlf4n2=FZJzg0`A*vp|q72Ui=&7 zldj~`ZO{~8pIJmYgM5;ufo43R2vEo397KhHe*Gbgr}{8Y1)WkX zfj{0!^+{O}2HaE=Uw_Qlkd*c9qXVECgBFSn7V@wv&^K7ISWmT`j5+X()u>n~jL3?_TzYr^pe8=#5E<6Y* z-cJObtjq!nbGzvbp(?PW0yRIQ7H3mf=s+<^-mUML z(}GWkAB$H?Q1r&_7O$j^RJ;PtBd;X)jNldb=TW>u>kmSD2(QQqi?JrJeAeG<#Ma0urYJN3y#XI79p2U(9``;5TYdi>@!2AcTHquO~S* zXE*&&O$%xdmZEgD?By?y_DX6D#zK+kJGAA@{>CS?wLDd*0VFC(*u+F!%4n^Y8Sp2sGzk44&j# zVC1$>X%7Z`cmz&z)(~$P(uGnX{P(U=vycJg?Dd2l>QaRi1^!lx|A$bQQLu)PkYY%X z1PAo#s36;oszPi{gj&OOB0N4Yn8wU<8YUa12zDzmUDl#=mp5VtvboVSZ8BEH%mw9C z<$@QZP@_^Zjd_es*B*#Ng|U>QvHqO37lJl;zpp2d5F5M!L!ei~)gqWHjA1U7F|v*N zq9&M>p&e`X-yeXM6u9>vz!T_5=oc1Gc(f^dl{g3DomYnvi)v7sp~lFIu%$_`4My%H z>+B^ae=LCO<+U8+DSO-IfY`r{19QQmc=uFt6Q~{%sDROIAcR(+3>dk>D13WriQ?r8 zHiNbSFXYyCFH~`v$<+#m%QzMT;Fyh#^Q1h+gvnp+|G2YuIUaWdC&5echa+|X`SS@p z-k0HB#1#X)pfl16#;cm?0Eu}$RqZ{XKPpn5s?qU0NeNf*HG-U&YDdK<_`tRH!c-D7 z4`_DvXiMY==yz1sKCFNI?NAs?QRd(|NqHKXSdxeyrQHQmSZ*MHO)3?MN!6aLuO{Dx zk$Yz=*LNYDI`ae$>2<@&6bmE|nL`bj0k?Dlh&jN<&`AY3pfF-Hi7Q>J<_>+Qkw25oFt43BAt948Lm;j_w$YK^AQB;g=&uqbJh z$Wqow4g-lwtU3IlR;zzz0b{gSK)ygCNOmAr8ZfN>3iGP7oC~f*=i<>hW%Z~0W#5_) zRg~SI)nS#IBecJgAORJHLi;RVkEJUX~F*`ePyOpT8#yo8k;Xu-#v#`q9dd-yxbJoy2a zEoe{30y%!p@G!sdpyK5M;o>219Se5DAJWezKnCaKD#){On`DK$T_wH2q!B9VBbBs> zNmr|+H7T1Z94&c*qWOVF zR90QjcZ@7YlJOI3CyyfiF2hf?p3>}BY!(8?@`1+MtXxImGV~xGRzTvD5@uu2p`dBf zNMjmn*(S)o|4PuIaw?F+PNA#J3Hbo)nY~`e11>u?+?W3p9zRBn#{AC%k9R;A&A*)o zj_c`$p(VOA4NP+Wz5=Q#ofzPZ-49+A+e2^j=;{d4d=W=u1)D(!m&%ixEknBG!q>fD zKg_S090b7+q>*&Zf6C^Va{*T29&KdPsKBQD<9qYrn~n>zY@=-TNIVnV1BiIj+x68r zh>%EoSPg0qZonVK%ls+yXNe!CDDhK?!e%ecK{BhbfI$!l3QGdSL)^susI1MCZvk%v z8Yo+#Y+$PRj7Q@a4QYLVmZA_(28^JFi?iA0rX*$uOrZv5Ad8C7CpjEXG{C-oUjJ|> z2!AKSofxF!6lcmBu+K_XXWJK^2nu8gDaKKAqnA~fQV9^S2!9g-s)EL-vyWj! zggejm!5k{h{xdd4K*{XKy~s1MDq=7qqku%prYS>v4XWgp2!a_j0vXR6Eisu|3Q;F( zYoq^UUgCpuMjBACbE7$D=)s&;hRc{SlwFgRk##UF7&c0SM%|#znF+o}Z2imH^GItG z)_mZJ9n|*^ur-67(BR7(M1oGA3)y)729coED(N>&ic?85RMM?XI(>tfl5c1dYnlCqKwB=K||bbtIJ2p1|igl;H_{NB+)k1zXm@DwQxiwv1o_Ed#Zg zaKITbpB~&1{I!kurGA52V%KnpYmH>fH2 zu605{gDXH9yVmZ)(8Hv(UB3a2P9oAX8b}}dYW&u(#UC}vQtT$t3YsF8F8Ig3WlXx% zdZ3i^3&fE#IOhcCV6h}3pl_?e_e}c>@9%Tc_LV|QENT{y!#p;$ht6E*i#cJxH$gdU znNE7*G?=7k0eR*r8}n1N^VaUaw16>WgdkS-x0flhqhcfzh61V;ZjkNN8XVF)F9k~; zB&2h7Qc%$z{!a;5!j%EsjS*JlZ}+pU2V!tgi93HsP&|{x-=4`8lN6^3$NvZntP&p| z3m;tMPzrUU1SZTkq)r&+QbOqcM(B^*;eBN%F~G9MLJmCOWf6~u6X&}JKtkwKcEgzs zuEu)eaY#F*S+gzbpS!sFl6LQh)z{B(=l(}hV!U2|&M%}f_*J@`z+p_NGY-|_P_};0 zHuPbmE1ik{oD?fpnw5(OhI3Uem&)}+XCi}jWm>s1k*hm%RYf%I!Upc|k;V7OIOr#i zN^uADKY|^>%6UkJiMa^qfY>j=A-*M2E6#Hj${D`$BE2)~^FLA^Q-%YG<4cgW99iKN z_pp_X@M5*nbkvPw zWnHbh(|7`~JWa1qd7S>7lbzUcg6NcQPQ94l%=2OUKjDbba1DxbawH1$jgnSN1rxu~ z4!-DPWItaPMI0{uuAMCh4)uUez-M~gpV=+`B-;hAY1O!6@)sy4^6paXX%>-%0gVfI z&cois(@sU)3KrpFJvXEPK$>CgR(2+R{-2DtLoXWs!|Q;y=KKTJ!G)VCyr-AJcdmsD zj-7rRC*A)2%Wf2NH7v|p&ae6zu?I40^nR1~;5@`$Zg`?^?ob-`mxzYS{SuwP?a2ES z>S1q`z$+Z1t(>y4+yTO-IK~UEDk#ED^2Hf7*x=^jd@bk9RaSt5#!;|eY$)B+6oOp< zzG-O6qE6yhfBj9Pdz62{pL0J;Z}c5vfYAaVzaRwNz!{uV0`-8Os6h+ZQ{nBk(!%v- z3$R~(NGn|1|HM9x6Q6C?KbZ9^#kpB4pD#Cu>4US^@0gpd*!fptAXKbuT<2k2>baNmlr)_dXgvO5^Tz6vtWGafZ!B z9m$B#g`+HRhLEFH-qe(Qtq>JqS0-Er$8Yj&aFh4o{C-1_p;hp3;vpW=!ETbk@qzbr ze`)yy@E}VQgeaVIfJo_$W^ag4@JIEk&$rcwAKuUzfWcb1oiPfbn3Fpq4xkTc z;rWYkwoo5+s090~H<3y>6aXIF3VB2gB{Mg$HXkZIJCN&Ni&F;(nf6E6>3%OG5PDYb zc-jm4Mx)h2)=Dtl_eX>3L@-qc7q=yu6io_!_XB-9!}Gs>g~&&WLdb*A0R1Pb8&xuhQ~-r-xWKU?}) zQ|L}8e_GG0(s0}zEy91`egcNA9Tl&jv>k^Eic^P>9r1gCQ|x1gs~C$aXhv|%xrXra zRIzzdkVpM&7$~f`xibtzx~Q-V&T0?h(q+Ios>+iTpI?=ngjtN?4;n(3kJREiG4cU` zT6Bd8RN_690;opuzN;FH5A9Y$CN$tgu$BxJcZ?A&0nXuC&)ZQ}-!&<^SVaR)EkKRa za&qul&3(cQ58Q`NhrvYrw0A*yQxnzfT|gc#r)oMe)*#$S)pU%gVo|E;?^ry=t5j1I z=N1}Jo~C~xMtjZypx$B#p%P07y}sF6Awa)ej9(G_A3@l6zS;(1r$vYa;eQCZ$ob8@ z6JZe6Pjpj2c(ZuSr}5Nuzxe~W)SBqn{+1n<{qGM(gQ3@X4~LWVD|flPFE=UtrL|e` zziq$otIgW)9&W$ne{A21Zyg~6p+lh0yn|V8HTaErcW~LSL}(e}>oBNRe{P~2>VOqU zq&RP2hJyhvtHTTKvYVzpo2Q3{I-xe>tK=PtfDJ>P#?`AgO+8DD_=T@T4rXvTWfT7i z{-!jOtrqOGPvcGoh*abLXcuk}bm9iV)66isQ3oC+Ms}PBTGX>7T{G830_90>$ezL zUX92C;j6OXWwc8lU}TZG)F3stnFTMS3v`EM@lG`1C^A3eWpuHA_)ZyML}gHfT4H|2 z%jj}_oBDjY@!43i2?@;c30%J=D)iTpuT4Vu=EX=tKzzB=5yGYw0ig7Q?^u0Q{Gh1& zJLGsIq;8Sg4z--gWOEeiVL5kAHGAV%oa~fG)eikGEZ|yk%z@99a?CmS7t3P!es49E zxs)3;)r&M zLg3?vA`zH-HxbA}ew@$K->Pp3Hst^57g~TD`Yj>E?Gf2_HSgH)1xd$ErrgyQ`p) zHX0hI!W!&z8(X4Huls!qqy@)7W(wX2zoYVg{FEX6wIxg2#NQ1+HNL58eE6>)Ka*pe&M{7p;%}SCR`E-q>P-G#E<+-Uv^XNtW`_}i zoP!$TAtBpsJG;R@^>jOohR9{;O%M?DLp*eX4BUx=tk4}uvSN%B>Q{XT#B26f{|Q7u z*>aM-P$#x;^Z~y_MH`#@Aucwnk_aGSKg2YB?HZ0D`vX73b^22qS|U$Ow2G^DE@?61 zVy0DGO}6FOyVTg@!eSYF(0}lY<{TYO1;Rf?82=RF7E(~`A30q=8;1@icH;wfpDD1R zZ97h+BvMW;yA;nc8PK_D+ zR{`c2K=|)Bv1(ay$)2W-F%L|<2J0Yrw^Vhhc5Dh1#8urKw=pkuATq+8WD^Vp1M{$C z7?>Au#phKGi^n%Hq*muT>hn-*`bScyzbUD-gH#{72n*d+IJ_D2VUlWX9$S0qQcenJ zhqa}nwgl9cfZF;>OGa%lBb-d0e5u%)w|zF6=A11N_Y;h$cTFK;8RUr;OqVp$~qdHctpJP@=vH?SQl%c55traA@wMT*WMp+Xd z(JRDPn>!d)r3Iw&0(WoN!XF+>s&m0>p|liN-W0mgAGh?!?Z93ajojL}+ud28!5)ro z7gpnFKUzUkoGCQ>0{}%_GZ3x=i&gaRQ49*-!P|165sk5yz*yT@EMZN<0Vq^%H-Vkx zl)j8i7%*bJPQZ_9j&{7h;yHsyf`=@nLD9#3iasLbw*bWX0k;`UkDoo5RN=iE5WcbX zf*Ab}J+{Ehy=6QS{|&c3lBf7^-8;JvSi_js;6Lm?c{^h9AtUGr!E@@rESphWUKN5)k*?siX8Qr(%vdu1LlNH+JQ{{wzJC)g>(+X7 zt492M7|=+T>=Bq43u;)FR=EHW=O=x&;l`a#B&Vnaw|3)lBcPlAb62&yDxtI6fdFpq zLjUJO@F*~?AWoUNfs|*q04dwfD5PAfkh0wofs|W(5lB&1Qo@tO!55&M`gx05mteth zXOmDOpT;(mPw+pP+5_FA|NdY=RsB;^M2%efdIhACQ2Oj=K{=t{o06pU=Ss5SS%lC^ zBKj=f75#No_8+hTwK&Kp5V)wL9$JEE>9M&BVfLnro#U}1sM3m`<39!dX3PhryGk*w z6me>VQnDES8cYF2pC+69UX3HQWC*-5Nr;*0g%oH6qv-D&KHF%54T2Dg4Aot{1JNvK zD}Vp&#RH$krbEeIF~Y}N;wT+VvSJpkTN~hxF$~C3*|4^1+1yv)Bu_8KRCp# zm98T1A>0?ea`Jl}p|#Y1qJv}ZQr2epU$|>OZ#Q(lCjkV!#a$bW9~$r^WJtO1(k2ZJ zcoVM4uhlb0%+E_eB>a)sl7uz;BR4A0H%nM=!OytJ!nC4A`M;!vx9@t#46 zDf%N%Ds-j^m*U~96j+}d_(yJFOKxCyURC?tz_#3shM`(TO!+JK?#}JCH#cKjUe$=WJX?Kj zO^4h-gKbZ4#@?aY!q{8i->B#Iszq*mkI%Dhs$H9q8`x`Go10NPR9j%%U*b&7?SrMFiH?)}DhW zGc9TN$Bpj=b9-$9@Te+Ta&61A?Eplz>ykkq3amSl`tP#9N|RizfOT_nUaSRHc3WW0 zKJ?-q6RZ(QZNXK4ddF85T&Zorb?D>Ids%R0wguO&4%e--;7Vu#+a40u>|+nlBS}FlP*zaRbfz3xOM1HG&fh(NkC`Y& zK}8{xL?I${l#u!5kN6meVw6&pFy~W(ZDyN!Uw`-tJ|?x==IdKOy#XJ4wAyCT4Xcmg zV_K_imaO^cLwp?AYMXU47pGCiw${y4SG@Q&3MRDLWM%sIJMl54)h6vd=VKusYw1(}$?XUV0TFCQmUJV_x~@o4Bff6jgu5eQNoWbnlYdKiJQ9|)maxqD z*Y{14u*9{5W!oJUm65PGTf%bV%w-Qn!jjz*mIH_So{5Adr6nxM!)z}{!ZNTWEH9oL zKRObYq?WMEnR)Z^NLc!|gyota2K_Y>miU&itlqx+%1BsJTf*|hj=7--SPV+3HHIk9 zb|B9d%CjBGL+ELL9Sj&}9CLmNXS=}gn7|!zfl=`Rs4dWLlzBL;YE!>nq4euq2BDh$ zji}ksuj{F6LBEzK)IOR3B!tWDvRGS^dVmSW2giHq^m^})5O@7W_4MJRyijG6mqq5w zGV_IcGqvn$K2ecRp2o>Y{9a-FW**|?=lyv$2FPY?(gkV_ftCaUDDOTNGxyfvmq1Y6SwA@D^kDcaEJmTz zJ8s;Hnmg)5di^mjL@ROPY) zHykVyL%r3;`ae5FZLBAI*aKrUX0PWUA;h-}K;dedfp%bH?%k-?xL>G$8C32^aPISD zXdeO+_H$HjYe)B^TwJHVuB6SCi*E=1#{q)RJe5#r=gRFm8ic%0j`~8A4#E6;fggy z_dh?Yenu~ce-3IO7UDS`Wk9cmh2RR5HxaPqS%rYP3I8(!b|E}H8Z!`J_W$kwQ~%!q z{lX7EzMshuKfnJR|6Y!{_o4=q3eML5XN>-L{=fA9-*GMaFHYwF%lPMG{QXN%VRZi? zgGeFRAD)bF7ig@J5;okyN>N$yv6$pkVvM8WL*u8x zOj`}2fW<>)A#Fxd7UE{jzy(V&4*yr+T{!3^WC?>M^Ex?LSxov3-i?ZBsUm+p^fb>G zz^JiTPwn)7!SH>QCyK=sgMG3hlE7%}!umXu_Lc+aiNR`XgqNFhS$@_@hu?t;iD8Sw zf^TvbGmr-9vY7}83!BIJ(_l6_mHGI)vH?@gFZwl`YM$UH2pH^5*dJV|=wM)FI%_-#_W4c-FJ%j!=dJ6wv^Ax{oY@)Bj%hd zQUM*T;YXM+=T-8>n(}r{EukPTH#$Z$B5Z^G^Q~@y2zc#0Y>l`-7pH|oeb|($U7eXG z`lR-D#!b3E1&2PZklS^Gnn zl|bx2z)Tx4dY`Z_7!nsR5btMAJeKfOXLn_O!1=?O7pVKgh}L~ z3OQ?p!F}RMQa9k=i~Du{XX^f;bh0tF(!L_^W8!da$`9^ZwIFZab1hxre8m}r!^=}| ze-@0ukAb|xQJB2&~@g!n|h4pUpt=Y~G1gR6e3hzqI{`rp=hl63OJstXm zf|DIMD%DQKAMu^)?+v=Oo5c@)6Sh~TXBuIv`HP`~FQ=y(Z8?N)Sf}y>#y;6@2zI-_D)*=EB4#&ECZEv?2Uq7 zbi`;M0^INV)&-0&c2Mma8n+%@TH%D~fi*etl8M-j3nX@5GY*d0-rd+#hf*G}cfoI- z|H?oov07;C`W zd;}OjB_7|@5-*eU>g;dIIl*9wSHdTjc=F@|jK9UZ$BPqP=fR0>JLqt4RSI(NfP4Sr z-=eRE+D>t=@{fc8T{hYg+{eDai_1H%h=q7WzNH*?D_Li8fobr6-@?K zBkrJ~sX?5B)GUtsVBSgfNwzWgO#j5%1K?ON5swz?x9n0QvsAK}3t8+D>Wg0^eHrfJ zgx=l}KvA%&ny15m{kA~_i5nga6ojjU{5k7(67NaOCv^tmgM&auf_jyte-3wq>R>8U z4J^TP*GcqSZY{s4|m3UGo>d*drM^jx4F2qqb1N|Nw`(s>*3~BmuL`e+%$Ry4}9M=4* za(K;`z^B2!<6#i)gL0XXIrIi&%wA7^QCoF--*Tc8@+0^Xj;S&}k!3$g;`w6_n z?87~9Fwq&%afX9MK&-qR3J@~|-=UM0)CIz;Q3Vbq(XZ=)@ zIGvA^HJ-o$ah2JcANUvbLMeh{KL!ju8eHHp76Rn|A`&adlj@R-=aZM>2lUs&4g_0b zuW#qp{J^!<`G`5rFh+*{bJQ_+6Bkql$9X_7g*?vWhHSUzSB*`_hFok@Bj>$gR2UAR zTDp1Qpt3|wQdGn-ag&B!9C$V@x3P#H5Mu&Rcm$6@DPlV!399D%0G6l9S1u1#aemcv z)%cm86_BiIm4`?A9eRom0_YI$Lqr@?oJxWRmyDs= zkCuZD{0A>V=Tu$;`Gpp=9CLy8c&vh!2?n%Z{3i@8nlZ?#736=gwI%Yu;s$+d$Oj(s z1E=x{eRBd0J_30G=ar7Qr{EIaZ(1QMP!Kv6SzZV?&0YX7$-PJPL#K92r;1ol35>Z@ zaNK4c?1P%U4>IYO19~AFapzX93FJSYbP%G7$GUCOYsHlM!l4u^Mh<8=aOK|`;nsk| zfA(!Qg{75J$rkECMevU}ji!JXDFgm0a`VP3iFpK0Qh8Oi`EbVReJY>x60YR*^g=|) z9*}UN8bCXgH5$4q6n!$rkM#2LJ9eZv|c*^y@VQ?@X5P4bKN@s-ou0U!NlmhxI zX!b)f?5eV2=#S(QHAY{cs-s>b?ocx!+J;*$6-wEHpsk_kQ@4IkCR#qcTmcU8lIm32}&a%K^#*Y zjd&i=tT_h;ZcmTT4|vj(^0n;rQCb52=c9I~)ZQgO5SLB?My!rPu9Q$$eFPfdHOiQ` znXErkP1=J-JO*SkR!mjxd`b(H0fv-u={Jey0d>O+(^{26`}Xe1L)m}fbm;d}XyL*} z$S(cGaEs8Qpbh!LHJ zNDv@IH^%GJdSkqjXad-%_m?4S)W7nwNBg}!WDX$DoWKCdoF-66a9{!=!>8G=i-+#~ z#CqQQrc;X22; z(G589s_`GF1QqGrWX*a120XEZM@u{{LI;N)j%;LSWmPC3a;XEp7cBAiRBKhpuX?Hm zvVx1GnMLoy1WK`+3@LUP4H9}UWmmQQP=NCH5&?LjP>Na=*`K_VvP>P#3Q(#ot0N*oFxSUJe~XlBTYpQI7rBNiBjlPi1i6MFU_UL_+)}?K*NA5& z*HZKc(SRY>1pVNz)m7ww3@iEwJqoUj_OwTpXj9mL!?-@B52yGj(Pjy@14M#mfBRue zu+{$%CCI@j?`|*{r9;TB2YFd?Sg;x4b)kzCN<6G&2sSQ!T6mi0dUZnk5&1`?hSOIcn%y43b2QC3Wj!e?;En)1N zVe5%;oE4Ow=O$sDfNrMnK#pEKpEy9L(Scdu?DHjWNB2fLf5wD5Kz$i5SxkeUzUv;C z$R386j|5HLm3?mw`yF)#kR8SeJ&3^?Z+psPF@_0hH2XcL7#|ep@eyBQ@b@GZIWS7B zqC+rpDY!HCgFkS)AI~LlNp2n$bosOw!mr3M+0cP^HdFUV&UkukE)7c zOp==XtixqEII2SLxi#*2i}}X|G==RyoL$88+CKMoa3~N6)viF#f^rrbK;5j_4FYgT zSlBXEg9f2jeh=YJfx>C(HrkF-luDby_o@(s$c5ivo@15qsP1OTlM)c5~g zByrhmEdda&Z2=Vs1F{dsV~3p2=sqcuA%hE=xfm1whn0Tc#V+{gR6*rpKA%u7|{s9AkJDB$7FYNR9uMH?2FVj=#CFQk0~uNZ9&i<8CB^LNWBZ1DzfXw%zVhH`XN9 z1;#03%@F8n2g4Xs1JRI1$NNx6;X;dR2L$K12#E)g$e3s(ut?-myUyA?a~gIdF~6EY zaopO&wotNuRj0j8G>>4l!0NbE@SmDBbF=D%{@}}^^IYNOT*gH{CV8L0YtQU~(Ct?? zhaKndZU*qIN6b#B6b#;=j*Dpana=^Kt8gBh6k;GX``R#4e{n+_NNufSlkx&_g^Vg> zobAC81OK5|x9zywUyB7)9rsqLMiXFo4|Nd!0{z$=bDu*Jf+g8(dPzO+$cF{cH=ZslIM6|if$rF z70Ol$LWSyg4*92OGpvY#eje`E`hY1hfqm1Gx!AS74}aWE&`m1D(qSAD0h^uFjjb-8y5$nn6l7@h7o=*`hF_MhtR4v)^#{I*7?MxTfy{jCiWKnKV( zZ&ctm^8VV6Q@$oFU!uha+2ZRsvCS5{vU^(MwwuE(_B%_9KcuzZ;(Sw{au_jDQp>3; zf)vMk2O0r)>B3sho6T>Dj$XfsXHHw|H??l#ETz_Q3sTcXbeQSuR;8my`jvA}P?q*Y zcZc-H_RR-4^-Vq!9^Hr>P%(z!<6X~OAp3Xx3~XG0bYSC}a=```v6r}s{aQ7xMCy95 zCv(4)1Fy+<^$h0N$aa9Js>Q$8l&rz`qKV&0dd+=X)rCpv7 zVmAYU)koX%t5UGJkp%y^t&{Tstrua9AXymvHu#lNZ>2+Wd&I5}BGlVXvpAvA&;hLm z*Pxy-bX^D>F-wf%#VguCEFkiZVj}b$g;s<$#m;y>{a6HZ6mN!qucQo_^r;We} z{|QcI)eM|2MS>eR_nj3~@PEX*9rel%T`ZO>&Pn&gs| z|D>K8ywqXYjw0cr%t77bdYM4<4;H8j=93PvXpqmCy;+v#qqgKLgH z`**;m)^*T>99b1_opc&6^i6%DD;R4&$dbC<69qAi*} zl`X&SOT#*@b>05}s%Kd&><}jJJw(i^_vgH_k`yz5{wKu5=s9QYWIN~JNEQW5{wFV> zext8mt7vwB)R9;{Qk@FcdJfHNgJw~91Pbf3jgn+rNQN%M&64qFDVe~M*Bd4Ks*=T* zm?gIiYpYG56U=D2G*nKA)JjEw2Dderom?SMKQ+!*{(=S( zu0ZAC3ew0=S0KLZ0|D0KErAPj>J^j^MeKW;EYL_mnS^{k(F%?s33P`xshyrnE=p5xT)W2!N7T8*NX3#H1$JEl3&62xU|l`H-Xua9OJ^(%$t zpSc)nkY#i$(e>o9AJ+OR=j`yk^*G@B_9F#f7X{zxA^!z@|L_~53X860AJ!Utim648 zK>Jkku~1Q>D61tLjq>2U@R?t={vIvE{!Kc2gR#UP8R#V1CY%5jn1Ct(gB=W^NxrP} z9Tjx&XZ^A)^<|}auLn$9A43;A8C~qjVp?L{bE=DI7>Wd!;+WQ)aHW~!A}`fRY*L(* zHf;qoawO@MLXTw(cR!7lzWbrV+r_HVS#Pva=~ZW|w0fElCjy9x^+aI7VQ(`AgyEc| z+2h&bFr!67uY2~+Hd1!5yg z&oj*=KUqz*$b0fuqoW*Ur8A=cKNTN0LjGOCrFGl#PjCeJC-XC;NDXkN#F6}M$3m|a zaOVCN;M9Jgz)4f!r2P2*44mVG&koM<0KgewfODw=XU4YwXW$f{6`W?8M)#XruwC%A z@FpDjYpJq-xpB4#{B?lvgW&c^Ka3}4Vd|08FAnorb#uA9>TRFAR>^!_wVH$`yGTd% z5pNuqHQ6#rTB3LcJSn_s=%ng=6U-yAj>kiG6y?1tm46d1>)G}3LSZ)5*hoxHL*dwv z*dEDc9rdryWgx(^Y)Jp<^MU&JS4I(L(dSMQCa;l8%!aw%vXM!b!Z+eBoq}zsM_Cp) zD?w!r4-)P*5(@k|zkHKgw8Y_p<{gg1Rigi)6j%ihs}33~)9R^;gEx`iF^d(rs}SMU z$fWf=_ce%n&qS5yUdhAtk#-a0vz6&@chhveO;1HWQ+~u+d9hvRpOzGZYiw#lU44VN zKLxXT4VG|-@vrP0Jel=0(avE1ld5N;0sFHq?*F}yj)GSK6>JNg_GXrS%qVLZ19FSQWxJfE?D;G^#wgoE zwfk~Kxa{uh+UPIstDx`7PdIgH_WpFf?ZkROaOto?oOuO17<7nM(nu&mLf`9<@S2g}_UA1ABggkLQLr)SqFs@enEXN{{R}|Hs=P&TIV%5?jchxko z>lifRrGZn;tyJelOh6MsqGA})KPSlaTGm0RH%&T*G=N;V`WQ5Wv%h&Ok6N|+YFQRlZR(5_`04;yV5_JHjJ!$RrU)ot`d)|%WM`K*PQgo#M8#7$s{hl}A7 z0hUmUS~?6bVwW)`F69$;sTw@_Pt?(Ryih1q%Tom{(lhQ=v^!C#+jK@U_VmzNBQopD zKSoKqLCB;5F_XqcLZP|cM1$1|R*KDK zw1IlCmFszx;zT&G(3Bo10CyPhEtVn$DWL(%xeVLwioWin^iaaWr9Ys4iI~Y${Ld6? zd_F$f9k8{SaGvpDe73DnG|*3wlGyj+@c7(1ppEeX{fuYXr;V~sRrb->oj|_Q5H37R z*^5|qoKf~7RkrM@aM@2Y+G-bwguvud_4$0tM{^AotirJ+we=gZz7v~Zv=4we5^k#2 z1+r90lD|$0G?y%c#s2jGslwYHl-Lj&f&Sh*3o!rT&k9$@>h$0kff@3&uRttTZ+aT| z5&9DokjL>xJyz;&+_IdHL+Eb*iHdaFtYY=??nwNR6jOqA)>2umk0+5OTAp8GEuc>L+rT1)nHGoxjT+k8 zK_G5YH7A1~IIyTU)9r^nEXLczmt`wEU**OU@M3-UIK_ES2?f~GZp2>Ius;#Qy!u$! z!z_D+FDtg}63*`!r=DjfP@BX2j)wJ{#>+?{8a+Q&rO;@6u@cW=85q7pZ>r(z zrAV&N+hLNsufIid5v9slYDILZoo|IpUDIl*AuKg5y3~w_Qce9@wq+5vj1K&dMzkEB zd#vFx&Szbw#s{=~KS`H=U|KFFnhH2bkR>z)0!{d7jL*>f)%d^{PqRNg9gsFIS6I11 zVddp7rGF@Z3}Xo@*2*rBv>RvBrl%Gf_Q}P}-Ku?(tzmrA#5k#p{U3`q;>{%OLu3!2 zj*v#$Nas!@YzP>$D{}pZeYuYJYMORIzk{2_6A=w-_OBlWsFxX_Uamm>{L=_fU%x66 zRGC4-fJdWO?Y0#TZ-HWQuc7=5E)L^5LabP?T;Cb@$4d~pw(gIwP;o?nrviYitP~Pm zHPia(A{L$2&$L!I#Y99E%ipkN1=|EWQI3`hD6KM4a8n3x7;f$dXy!?mxD1~nNPsc$AAqQhoi!eRZQiT+jv7PFLQdJXi(umeVrwr(RnGp(Jml6a8UPUp9by8oTk|apLY?u zgGmN^n>aeNOYgKWkD5IPwGV<3-el&v{*HOUMuOXrz5{F2K{f{ThC6voP(f?!=#8J+!ZBRhqy}(%m#Q` z;`W=k&uG|KKrl7zADj?Q!Y797Y;$AHt*Jb^Ekk*hxHv;$PBJ}99F^-p2>L;s+@^fn z@2EVFgaOG^BDa!N6{OLtD+RV5`u~(5{zV0@8`jt!szD}WcMk-kHZ}@D{>%ts_P5%#UuwP4jn@6asMD(4dAO9-sFbd;4P?J{c&6S1IdkT z?YN`C=fS4>*S~@+%LwtdTf=BldV!5|5o?;5|8sGt8wN+ zv-@TNz@ALQAhMc|VkN^FePC+-XDrnD)rjXd^g;oQ0cPr-)7ph>OMK z=OSd#Yj+6ELEjbG6VWe=_HeEp=RPvxA#*bPIoC+(jyUR(5$p=%s(v?W5c~w&<0snR zIT-`tcts6FFT$xMHZF4l9r0=)p1Q2nf%r-Mul{EQ{(XV~OcKO@Z5aQ@rVIZ6JgQav z|MlNz!T#n|Q23Vug8!q>M&SR7+neFv>Q@{1 ze^*K?{6CFtbp1>0uPgk|#ZTaWY$@>n_)7}^#!61BjKF`F)Ry?C%){_t6(`EB(#EbF z4B)Kw9A^P6lIY=m1nwV}-etZ-=wF>_1Z-RXT1w=B^%YGTr)D+79mZ6OuM$g`_Z+VF zGPYw8bqt4!$Dx1Thta=3zZgYdU0;*_@yOy{7=Z#?u&3wI5_@0D-Hf%$@u`}v8k&%t zb2{M;AVxN>Z`;Omo?(}r24fB=Bq~I0D=~C zWwIu4D|1kDEB91g_Hk(;-mm%)k5QFhc|_1B6JzVGfyF1T#Ms2ko+igH~xa;AR8y zGHX&LRl2e0{P+%8qsJ@$3f%yFU-%&Kear6^zAuqV6WhNT#y4CQc3%wH5vWrf z_5ZQK*ZX)_A^`~#kU$Vp0tN+C3<{cnkpx-Zff)^m62&F%sZ|?g0#R88Cee(; zTcXv9%h$$=l~$@$DTbvrEQO%022co~C5X#Aj7tSyiY5B6_n-~C)n_D5o~7q*)ncEuKiGEuZ0 z+c7bc-TL?FHpCZvfnG4AFTMZwBF?(n+5ZdrY9z)XzomabUrqA7LAK`QRjyX^KcwTl zi1RVdV>o|G!xiSKi6Rqa(gfSAOmZ;U;YZH&s->{idT`J-+*Tw5BQl%FKN-6YU>?krNWd{dATNd^wJD`ZG_5n{7*P^O?s;uy>2}{izH{S&Ws2rs{tT1 ztxSIF1tz;6$$U*6LdhZpY!5Cj*F4LC5f+;=#Ccnad+)r=N!VM2%VaRiW%5;rnN)%F zYS~7$e(Wg!8NLhCfDJ}}$;9GwZhA5&@(wDv_>n8*7y&!(nhw@xg1B3Dy8@Y+^t8Zc zpLsmk;bTg3xLw>v@`o`&Mbog~85p8mf#sQvfWnC$H!#FgUaOPKu(r@31040`$= zwN6J~Hz;C-XIJ2pCx^{r0?ZKLG^e+92wXc z6-s43zOgoo-++4Us8~iiv=J#C3q;nU{hX@T@%q0&WDzPRB8vsaMl+1aLc9nKgihjw zrHBs_`eYC12PdWxmpJ6Q8w`6RRnb z^EQ=}_^e@0!6)yma|Qn^Gn*tm*jv(%lJvcaPYW+NbOWC|p`Qpw`Odm;I%SOd;29(= z&k=*xPsmw}^g5P+-frz!qkM+*E1$^BMt+(eC))nj^+dT&_#aEcAa?bgkfK#jDJiOr zlKZx201-(__L%9t`cVjLfB5L~k-ZPIPt)18`Sr*5VzTc_YcG53I4?>xV-XLfi*c45 z(amr&dDeYdZDg=Ab0T0b{GgZ^c*^E@loz~BJIlJv<(bVGX!I7YUPQ|ml_E8vit!2+ zK(3$)N*;>nTDgL7dF7TsbXzv=Wz-j)8hhsAMDH2q_J8g6f9m#s==Q^uh*@uwwo8yV zp}E0VNtHzD$yy-4cA)Pl@5v<$yOSlAEBlPgzg+vPsZ9@b^jan9)MS=+zzn2kAfGhJ zrxy&v3y9id4Pw5S)!|QMe+d)gWkK}ILOh_iCj%!M7v^)4O(_^VW+>HRJ!L3Tus{PT zSca10EX?|&)p?pu?Bl$h-755AntDi%4)U%(sh z@rQ9_yvFv{j?nUfaJ=WMYPpuHZ6uISRr36tQm6oqU=-l3zd_h4oPyNv1^gwi$>`x9`~JX8P|Rn%H-tD?F9uomns>=G}^!(f~R z!(wKZFZZvHaER!^FKmI!pP3aJAZqC6gb01g*Va)N#|W8R{jbR3TWseJcZ1dE7t#ri zi{f@dpJeQD$P!E}$t3b^vm(c@hx#|_4HHBFShgBh{;?NV@Es^+6|N9Y(Gz(Xr<^>p z3Zaa&fLpYs63Mt2b_?7i)>BN&>Z1Ro)#ra*2?bIWYNNnfCfDTxxS&Kqja`rpGPm5} z^#9=UZ*%(_-Tr^N{d?X1J#PPDxBo;N$h9$iJ```78#zA57{t%C{#hTkhQ|^u4PI{r z4`H$x?v>VbZ8iN|dg%{i;`Y+!Adq%05pTx!lGV`ff89j^XBs9YEj!j`NJobkA#SbA zfPdGQN}@E%HyBgVqfg$10l0oC;KvYHq}Cy7%SrqadQm0iftYmKQs!c-!<4=4P?niG zq$fvf3^M3D654-7V7i+agE`tNY;X(gnbz?4qPi%F<%7E^>exk_!@XnOQY^jEKPPT) z3_IAK;F^*aEx4j92z9355{vLA8BUUo6$2HsS>IJ16gL<1M?gZQl@NjdXnG$`l(8W1 zm=SQ5Gp~iP_?K~Xzp?SeINzZThS~W{nIvz5i=<8|Q~Gzvzx!t@ktb_p;ntD%qCvAf zcS>u|&yL&L3x7asm0wFN?ZN-1@Bf_mT7mY!G`0W%&khS}R%?Bp#x}jt(H7cSz>x^; zJ1#*p(5-x-?FSdV77^NYEGQzhiRvh!owPVCw27iPLYuFx@st0P(8k_J1V@A^v%NvP zJ*6Nx3Qjof_f_5P(pQTvj@wrcA8)6xtW~N1^R8+~PK+&woOmIqgHpprj4Y~>qjTv zjuIEmYzk&X@E?LW5BHFD@omy0Uyq90BR_uFj;tVm_U|1nF2WUrW?u7?;X+ zkAW7K3-q z^TK?ul1BKR&(^{G_W3@s>;DhF=UD(79VY#a;3joxQaM71V^-k#EOZ;fxi`)|7r)-Q zy&MB42y1xq`Ro}RnuKeu=OU)@oF9UFD8GAKn&5PBF7Ego;AcM-$Kza74X)^Cc~v#D3UPItT~LrD z|8?iW>`_d!M~U{3SFZD%>RSRsV%=o;@E@vBoryIk?B|Egql|90zTCGT4EJgilVe+o zt@ZKQIz5lPZDcSDYA6`$%Y90+M2CP(lMs+tw^ZB1t=;303DdP@0)QI%t8h>GEz(JC zCk|aotfeTdbsXJKq*MkU)f&PDFGr-56h)iJMlu=mV9JJIx!nX9cz38^xv+`~&gRDKh6}#& zWt`Pp?!R81xgu;|TG$iiV+lZjgt?Aa*q7uQsA|G6;tDLYsC!}~Y)|Fy28=Z#or)@> zJb)xUtao_5*=-hOyErL2Bnz3e5K&)p2hO5#Xc>~^J5nxBav*3OXNG)0>?EbJ^I<3- zYVn1WU?%4pBvUH>aQc3Pe|^Piu(tRv&4hc|gK|4BGbvH{%Te)j{URmZQE>zA-86GM zeOtbj?@r$jeI1XC#e4Wj{qk4mCX8>%JVaF2pbC-jx+UBstK;B#B{S;zzX$(luTgp&swTVwGA>^^Q5%!ZhXtWi;~Hzf3|z`>QKqpz!6s zHkYgcSD-3}jAlIk8s1pVm$JJ#ZvsygvovCOqzRY`BYxvySKSp@V z>Hmk*|7J7ZyZw(Oz~bb~_1anAYGPKz(QZUm-YW}=^uP5i+#Q_$EpGo)Dahsa|29oB zU#>E{{Y#VZ9O~{g-{Otc9k_P-pBgG@U(1rTeI;#AxBuk~JaZ`#E!rPSM;^Wa7P$gG zUHmHO;R#1{|0YMpN5G=f_ZFL*Pb)+@Db#HJ8Xbui! zHSKlC+8vP|u3RifrTL#JMqOI}b5xW7lC6u2@CvT+>-Z_b@xUoR7et9S`E%itTQ!qa1o5j+|GXEI3S{zr%6;>#W7(X6*P4bP!em-!5D zgpdwcGr6>nv4AH7R;nIv+f%UcmXWzm(WYA6raIjwsxg!;#lRl_M7EURfwH9*FKE8z zM`hq{%2l%EDrw~t%D@dnJ#)x5PbF4D3%z5!9#P53aUra%YhyUPaG+tdSTCa>Z6D?S zfp?^{Re6*yERV9P3|G6qAgh)knaf{Yjf*e0(`;K-F`m81D&ANw@q%bg#lVf6>ewC$ z|7L$o*JPt4bWNVr^z{99*JQD#KIj_WsIGzi`eM~L{?`le*5zMZD7kL6bFDL&s~2+d z1`B5{{{ib^WK!b`js$X4jFB(#W#Mw*R@AfLGq`gFa>rZ=SD&2o$Kq0&jD`)6%m_w$ zL}_tzPDKG!N+P?bltTr(N4?ih97&h5d&-eCf&1?(Qc**&L1;_$a6IDkVo{xRpmt7` zBg~@OBe*I9xn1TRu!by4BdCFzp?rf;mds7LT#c*S-@vXXpSyBCclZ{eC>ND;igHZR z?xs&i;=QZjbV1+O&#X?*Ls!y5-S97EnZDdFOLSj7!m2{4hWV7#NjH)`RtlXIz(!GG zL9J?2q!w`fx{PB6yh?ObXMzoiQ!U7x14pDo^xrtd;FX7bxeKK>1g|{rQ0NTtLpp5z zL+aQU>cj?_*CLeVKF88Rc(w({F}jhNc=}Y#G$uU+zA0|DUfo5SDjmGD< ze;5uVX{AUjIocH5`Yp)W%Mt)S)^b{BspBGVo3{$L|JSVI(8^Iwbt z>!P?|HRF7nIHjG<(r(tJovlhcx-zP?Pfx^YB=+Yzk#AURzPF`ZWRv7%M` zTi`cDu5jgq9Hs@sw#)x7cVNJWpaf^2_W^W_2k{q!8hl(k4N9Yn*4H=Kc z!;kQn05{|eOj@YF?#HTn@C+_q znu%9V29Z2EH-<=FN6gGH@Afzrm#q6T-}Kmg4@T$P-5fXHfl0`BW^BIk(fOW_myZz+ z>m4RHk+}osZH61+7I)6qp3j4$*$VkO|IFwwA-ki3=gKajHl5kGA*M6yi0Ht&dR%m8 z*76oT`AgM@Z8pB} zFKjgldk8QOIhQHa`oFk){c$u4@Z2fxS%{B#w`NmG1~!#M6{tnvXm;``59;#Lfmv_1C>u4?Kchb4BX2Vb~w4B4|p{b zYi@@ey^3%`FmSwN|JZ4YgjV40sq+-;XUPk>;7YJ$_65yVFyWt@;qp(0k?}$S3wFJkX(5MU z&P{`}BFCSH&Qm}WJS0C45?^|wmv?#N<$_&%=C3XOHB|*Q@D4&+7sd!@hCq4 zUHEqh|BSs*@y`?838gM1Acd&;`%cG_%lNGY4hgDkMxR*PbUNOdiO-FIt#xjR>RXzH zVCE{mDIArBFj&h5s49HO;>&g3PW&TmyxyH$WLqR1*-D8ZYoQb&LW+tM2hZwbRs{hPV9_qY(MGi zDrN<0BsD~g)Q*m1Y9mK&wM0~<$Le;{j~8KJ63-q7$$9fH6=&uPfXNq~ueObu=~ffb zuRR5YcMwwvZm9*3YL9_cm4u^g0DCoF@lRl1 zftzU9tMRNzn!#3+g2!S`WR3deN?BEXTiC{Pg_K)Byj!+{-jv4FfBb8ghOV$c4VG{pTw1 z@8_TkJo7WbXEuW0EYD%^u~slS&zHNU$Ob=4z{l#wQ7eVugG{9eThyKyuF4la1y<7l zF8>6!48m^bfc)S`h1D&{X3LLTWf+XGHb$;;DFgfy#h*V=(rf-^K_n%q0Hib&&sNqS zPRZZtwtN78%Nj~s{ysiJS3&+>O-Ta`Nm|s!1i+c(?X5|= z2n(sDtY-Tr2`!K}D`XggO;4^1>!bQ<{4l$pumHu+KrRcg3NYu#{dWR`f)?W!4eomZS9=XB;YbxyqlcH0y?XYclMVo`+~1hJ;7_2lqapP0ZB z$LbO@RQnI!WS6+fYOnoKLA_(Ohs0MeMv1{YRO>EKB|iP3U1CYQCBpv4oUiGey;aU> zUsFD@FD^bs&N0kc8k@6kIOh+ax6=x>*{>D+Utvw$8m7zYqo7#bVnea2{j#t%+NC0$ zwkq*CmbixwY3T1XRifWvW8}v6ON`TB1uQF|%hJ&G2}9Sby|SW%u(yKlGRgmXS~ik#0g=iXam zxcy*(U1!lLa^8lVg5PIjbH5nQJ@^#4&t|zw@+mVR-LU9a^?`)&Q=LgYLrHs{E2 z&R5&b31bQe1W5Ot9E31fRPhmiBF>jZ%Vdlb{HO$T|G{c}xS827jPeUL56OXHwi?gY z8tQHk?FCE(4~s&%F3BvyHLr3*X0beD=8Y@I+A_H=$@KC)#%Prfdo}UQn99uWfZs)i zerA3?XX$6==W`yeZk!-r@rpnN?F%nNFOnfM} zLW?=pStC}D7;YdY!<{9q@sGcF3FS(==Me?e0v(GDLmo)ElC0EiXW{b*ZYuZFhT%JQflReZt>YK^`x zfbP4wQJ+6B4Jv*w&-4;B?e_)HxBoLe!TRI|fQ@z*R}cm*7->&yMMe1^dVfsVTxh(~ID+=tVEYYPnD=8hyL zQq8?nNgaEw)8U$yT3ql z>~%b%+P4XNo*^pF^70H|g#z=d58LLE&@XUupd0eLAEASWF?U;{{q}=6 zM2q-gCaD(j!-U4o#K4Cz$bNQR+#>F;>%;9L%<17=S zK%r{XS)*-pX1_R%G84~29`?^Ho$YFs?a`5TwvYF>#f6zX`BhR7{dW+Zp%{j3Fy4gB zqV>G9et8it58vzpIP)NPhPSNL|}(%=;+6uq4=3}_vDtwO7&uao<2TG_O(O)KH) zV1+=qB44b7xZ~_{qqPTjRjtMBE#I~kv#+)}BFSammbpqT?)>^Rv~kfF^=v8@cj|aG z^%c^!QQq4Qa9F^R?}`2Qf!^j6q7l&hR`4B2SJFbCQfYGMzTb-O8j#K!6gUc~aooxU z9L7~v9x?kMJUbKLKUc*cHF8Gp;B5sD0ReMfNaloFUL|XyYY_0bY#+Gh$V`CHw(1Q# z<5m6pM~~|DBVnEAS(uqvwG9KuEAh)2wJT0JLfd+s(@*|EBrF zT!HS}+=1S;?wq$hA)t8V@Iu57&l%0Dqk>%m{H_zg#~0(c;u1uEFSBr}ij0co3*`%< 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

    ?B1#1)U|k?anNeJ>!ym6T?lgFZjY5+J`kirAo9 z^UKTNWz1?lImG49w(=M0d$5Ir6d%CXF?&FsU_Z0iPsS__=H^OA03ve*5FVz6+?w&O zUXajx(*n_lGHG90Ao_^~;tWgM!Bj}Xk>wKINzy&Em9tzuDb{5RN#%I8Rel%tF|frn zneNz{ESc?vf3YmKyd(5> zUEP5Wp71N7&1p5Iz&IfA8Ix-#7d~~qHm4EkJfU~4@EF-0q0#`o4%qy^>Kj#lF3P`J zTY3Ju#ox1%Zo?LGt41JLCDJD~ZuGXhQ^HX*wcQk)urxP8A5 zcpJ|4REFVhWOT4kh#Mdk54DPZev8f~>u(YXj&m;%&W(V>=8EAsqImQn0*%^zcmutUli1o+okEZpTF%U0)J1wUY zp7_$C9fC)n)E;P18{bxB%EsA8%*NN@M4sgc6M;_(6D1}_HbNX+M4u!qNb3SsrQ@vI zw3U~4K~Us@X;{Fr(%VHEa2O4!kM+lEHsA_0#A<-QONZbQG(aM>VdTcf;h&qG-vnF{ zf@+^-V=XuXQmVV8b^-otZc^j$cU+z0P&F(G&mL%33w8QGC}bbc|6$v$7uPYBF{-1@ zAKf*(FetOH2o=^YqI3dFSdR7s9&=H<97!3^wVF40eRw=X^DU)pRV_0i2}_I4kb5yC zQ7|-Wm&*%83vI*tNr*~xk{00|7xgazsRttWFGWUL*NZ&CHQedr3~m1JB?VsbeF3E2 z`}qN*Fy3`}aq6Dp8hM8Fea7@tJsYd|F{L(^2eUfY>Rb6JQ_~K2FSZ=1o zGL9043}of-ac4Z98KEk!+{!u|^_aZo`Tf#L#bbBcr{$j+#`wiAM@ZyRpE~2wjmb6MkmMRV_D@A-o0LN!?wS~ z-+jt|*PTtR`fv$b0soyCYz^xgS-njlSJNby<-2fEyRdhp?(05!uZDr|+T9b{UkCmW ztcZ%XsKe1FiVPqyg;HNhY!K4<=_LZfj54wja$_X{Oflx7svuq5zu-Qq8N)GLoNJ*# zVoh6_{LaL$wGJ1%iv*?7_VWsH*d%-5%7*Oy4|&_*Rk9p$t-NivuT87Y#hk>EEK-=l zh!QbTaq|m%bDl*CqO#SOY>N?IM5xARM%gE0iXW!DP+?_6Fx4NPPx!|)y{eHnw2${; z90p@Y5Z85(h$G`xwP6V$0=8?R`Y=_1%~Y_yLQoz0#XTiN8VlK-dCkYcX)Mf|exZ$7 zFUB!T;S$f69*f>86yk~qpwK`Wucy_44nUzid9If86A(Qk9S1UiuoXUG0Hx-L;FWIe zqzsoXJL$K!H5$?!{T=!w!%m!%o8|UR9c~C)DaUsA0-I*CG=5|VMUYpZWD~BG!+>wL zLzr&4e)h>wDB;Wn$TxV@jxxz&m)`_)`$tIVr5LayjQuCPWew16Y!1VwwMK$YOzm)3=7mOtE zWmdZ$!WB$#f$L%1#J6)HAvzz%!h?Ks3b!D7(2BZ&o15Lf{;P%z?Llj1*Q)2zJYYe{ z{1dpB{UGr(lh7?0)==T*8lq|+c=b7W{6kdQpc^=$)o>o;-XL3{k-x*Z1AA)A%tQin z8(x{`xi~f!&Qxt6Dq*pBgFh7l0~J}fm^`(GCQ1hW(;}yZh7(UB+1ohD=yBag{P(v1 zDV<5+Td-V{z5$y@!|fC>9vFxZ;7OAta%if{SDgAD=Dv>-`bCg6&F8cgaDS-H=UQL5 zG6VVV1>CWKcFh|B$Xf^j`vxxT_uyoNqW>sITIm;l_YST4at$7n6Ng=&EjeS%^DQRzm35l@8bN??%%g~Daf_WzS(8p5L8au z*eA~xZSbR$HV(>1i#Ax69?o{zG%@IPCr$W_G)&c;pxyP;W-$Z?NHiF&)5E_|%*`SY z?oss*#oS~oPT3Yf?ersy#~+?&O~n5o&Tz@-I@c0ZE&R<-Jek8$;*48l&63FoVt$F> zBsE3eg*$I}pFbQ`_Nl#i#)JAe8V|HC1yQ(JFAtWp_KVSRW*0t}BLZs#@h92`#;~^2 zX8aBL-(k>(wM8vMA+bf9z~E`?`~&L>zEg|$pl?bHLN=WPi05Ve#}Oc4?Vs^lPO@9b zU{Zf%@lw1X#?+#$Yh-L zB)(D|?&}G?cg5Al)P4wcxEnE#t3L8s8uNUdmKmFCTsJ5gXcg#(0MIm*!sEYZUtAw?qv`v#%)1=_D%f)%KcBNUh3fX#{;#AdrrHI%cu-Z6bR>gO;;FAo)3Gq6x$w zX-}7=_QXRHwg*z9XiG&=q8%6fTkY^wwXhl5!r$XJx=FA{L|x9EWFx?y1+Im-@l@5< ze$dh~*;93-)9K~o!GK9|z)5ux9`27UA+6fui}Nv`K#2(sZ_XjLGH#2R_!sMjXbr>} znSaxHkm7cK_-L%FFZ?>t8@GY*CjrKv;`}o#)J9-cGx30s1=iPazfv#c_e-oH_NC&p z47Sj(-z}=n>|1NG|AADT1uN3W*Yv~SDX~4@4}}MXNa)v2Z}?@uk@+&dn*-1o1af(B z_L`BijyWQWcX61)N(pNWF16YpW!x|0Q0ver28(4$vT6xm0&qC01m$2{5$eUUrqWWN z9-FL39ajikOK|Z=x^Nphrl*L(gv6>MxvrBVCl~@&B1wY^v$uI#wqx2(!8=Uusk|(3 zb-;y_dq=shaHZkO$vqucncUfO&gaZ#BXC^LN$l__9Rt>8NpjUO5yUS6Y?h2BY}AlA z*iI0@2(BhMLpeOR8|!(@#h2VA3*z_6#r%frB-gCs)OWl!^6Uv7J7apcjX{1(d6oc< zonKu2Zsl3d+z{cRRaU~J2cw!~Q_2L+&%uPAiW3yUQDpq_*g>m~h+KJum22}K$V3y2 zn=q5V&Ux6q3*kaIfRvnLKR5@X(G=&f@aKby^FUv6y5?^4rE3#(p6Gudss9{~I0N$* z)cgg{+MERvhTlnRLhC!~VY!WWj`EZHccckz;a^!l<|q>tkrejviuMe|SMy;Ad^95T zbTpE!Q;8mwOuq0A*_+QAdW)O`#?3fDP~hQr3;Aga%MdOACR2x!!7@ocfw}KibPu@S z(B{oUBroQzN!h6}7t)Z_;%xPGY@%p=&Plc8Gn}d$)aH!NKr-Vd)CA#O=2u%j@++E3ZE{uHCj%4Wd75A) zo+)x&r;bSiz0bt6KVs3l#C%qZgb#W@g64qUkK#glKPJ}|uCH+=y?=wN&^yIEq7s#g zIJzji26|40Cc&u|-A=C6=AYJuIVko+exAUtT4Y=5npB*+-CHBiP}a(>qjpyh*ZC7)Vbg#8gYk@|9>P>~9!q?fmEdH=@XlCA5t3@re&J8?{w)Iv>&8!m zJ}dw{^rp{!(5Lwi#$#;Lz}156yx-kOepaXULj`|1Mm@^r8x|9f18{P!EgH-p!SV%u zknGxp9~aPY!iLo#x!Va&Vw-9n6TU?Jh;9&Azw&d!1E%NU<8%PoWtH>06;reJtLe)Y;&VockHi+oyfL{Y-AbW>ppD_dDgxyQO z#hml472?X#!BP*4|B(H$o=ELBTo46ZG0x98=yDVjpcVWU-sJDbY9r{7I1G5VFCQ_p z#~`Eb9%c0HZj%5aR<-JxY!ahZ>&>oIhpgddE0^F?Y#gdtjcRPx#flDr-+_Llu6?*q z)MXtchclv4QBQ`%_OS|IHmYsmaRj{|h3Lj&cJuilYBf{0DJuXc8FK}}(+Y1wh5wpK zwBP`_uHpa*X*f*U!!z;PEciZ$23v&LmKntp$mTc*u}LTTcs20ghIlov7Pni?b9ilT zFJ$kQtKna+W@yZo+u*dI9>)3Y15~F+7Rk5BDm8$QZ~(Eta>XE>aGgsI#{sP1P5vI8 zo{XJ3;xi?fbqB&OFN)5SavtHB0O6MN!n~K;dC!x)yDiv?ZmMg3L_5wWc;hC(Eqdzb zx_ei}nVgt&Sqh8@2rAibrjJx3B`;wxD2VG>_29cmAw#5xu@IR3BPp~R9J`z7it!Gc zTNuQzHlM3FDBmpMJEP3TbExdPk#-4UF)chtzgoe^FMS-!`U#%_yvg5<)2aPHa2&9$ z=kHL*Y47nFeTTANKPESI@wtYQmEu~I$K26|fv8kS6{GEs6HXyvlhcPae0DmA{$ zZz>B=u!jEEJ~NCgUyW3u!lRW$VJtLJxEps8gd}ERxr4}wBNzF3_(%(e%92k4c%J_* zp8fgF2|V!+XvT(pM30mhLNA4Qfto}VDc~vGfQfs_E0BL79^uv@){9(i}V0{#B&C}GgxsVS& z^&kQS_Q#T^-R9?)OBTE}r>Ivler6we*d(1YUq&Lje6PYwv)+1e^Wh6T2qK#2;t_q4 z42=J=QuSo2h1SCSHsArCq{4yXNt%At zm16$=9ENS7l>O%WKyJB>ntO4pYUwWdkEn+<=C>_rtUvy6rz-g!9?Nd@>&udFM9C`K zOHyzX!@fpHaj+HaF;^wto^QWBVD86TV6tj&w!BB10{pcrla=y3cgoKNJ`1MRa1<8{I4YBqj zK)XRtJreg|ybl;4{+j*^KN);v7^Z53FvO*I^2fON)mP?#p9Y~-Q0~+RU@J{oTEz(f zo%M?U0-jZCO?%vbaU@8H&)Vg25ii4}q5tx}L!emSJaUa~}tXB}t3T z7xqJXJYc@BJjEmNjsj=23Bo$n~R7qboY*%3JM-^Fq z_ik<8dMJ-DA@w~kb|wJDwp$h?`T86CtCFu^u7v%Fyun*j>blw=ezLXEw-(8SlQyR}Z{U8)r@_b44E+N(L*lm-L#MniS>J&^ zC|R3%gM25Jgg4oeuqcKmpijlHgp%-w6q>+}US7vNj-lVQhQpk9nGpuJ|NNjN0>W*Q^5EYy|MIlh;e8Om$my2z3vZB z;*KJ+*j?G-#raF&AizAh<>{FakxEg>1tyF zfEU2P=xpL;fon4^9Gxw4UEz8WSB}n0xXS3fj2pt8*$DSKT%}dHcB}I2o58rDoVgE4 z=y@9`&ya!`x5JMN{~ybsodS7Kg%P`0mOtE8;&wRvLpJ#!7c5xI2!(1_J!0@dDTRul?J8OhYFAUh-|4B5;b8+Fk4q$MD8S0Gxk?NxW^;% zfwS~Zv+H@FKU;dtya7qgBaA1YU*@p+@*Ya{)`V)&8)%0dTjE0`_Jem*D81ed;Z@1I zNVA+>z_fZ09di)lVf9D=&?T9{Q~(ZBu^0SI@TSQ76_yLTT16aLbG60QsCA5fR%sn9 z&U{?*CO6hxFo<$jlUa?c+D+!@1r*AflmhlwJlM*s;J3LKZ2^{79*5gnCA}QXKn4-juEGK*6@u|U)8Aqh4oC*kKL;eq z9PnsEl9L-D8I1t+rHkS!G@T=vzPDqcgW+BBSspH?#-{OoC6K`C!_#v^EdKVFQY(irzMI>%& zvqE474JV5eXH%T$AJ3;^&f*B~RMt`}%EhHLw@6gBJ8rYYgv_Q3Nr)<{ETOVx{vEH) z>T|5g{?d5zHIC#7l`ZoLCchrZF}?31nW*708yp(=|HJy*+Kbq8rKSIG>u+20@u#ujpH{X{lOgJ5-)uKE|HPr(BJl^vHd5}-_GK=hBgGbK4PYB z@CP#rDc+&N{j3kvv`FU9mk`x3zt`vG)8`jUbOgr`jQ(~M|S)uYJ z96W@&Q*T7vD}p>_`L0sO94!8>6^b#jVdSrC5zoK{J2Ro*1}!ylen$(Y*q?AMh%O%O z*7ip9M+ovtf1E{D0R54dFlG*3sXxjyygIl-4w&VdBEJmehEymZLqrLs6ZK$$Et2!v zHP-_AXEoxYV{LG#rxXNfL9TEQISTeg(l&6O03aB>7{>WHhar&p!k;Pa64=ILps~Jn zDYizl{cF{GwYi2+Jq#$co`ZKvsYd$#>@4ojALdqlqG&&;>Scu4Tq_FzuDV6Lbh`Ot zC?`PHKMlZ<&J9yuQU|lwvV(?YN;78fOSbO-BM%ZI51MNS66$vYkFdHx%Sz>Zo`()< zS)MH34`yfa4SieSDv}QvVt&!(p<1BF=dqH~1`py8ol@khKdqAd?R$P9zW` z^M-TDQDLma>ri3Kc%nBpTD8o9Vc3Rd;$Q7ar{*tGl-2%95-!hgKbylafxtAZoS@%4 zfMgNR!U0|aLs7qy5AH#Df`~+H2}B}XFbGfx_zd96V4wy2`M=xs?(B2Bglkr=ox_<}1L6*Sp@far6HOf1eQ<;5hjE zNS_lBKRf9 z$$VrBLX%cGdZa6&y2%%Dm|Yr>ta&1UqtIzQDO}2c; zg*5|lDeCCkkCMXxG0M|mCwww-F%H7$}RsuxeusQ<)d`!F_mZY}#rx8nCo5t7-!g4qO`|ir;vmmOYC6 zS`^mEFPK!1JXUuIgWO-5# z#|AnVsapN8*RT3o>iyv^EsZih-h#&RUm@HWHluPkwn)i76(zo9MU|HK#+%1-sr(lg z?5No2EEKk#H9<7SJPJIag8mut#ol!8Jv_)+1k|tV6mxk3gG}L$J)m&MD}_5=t-@Hgxd zT-t35dGF}he|saF3SI<`wobJrvWO(0M`XWbJ@UH@JozJkB3k+*%ZQJNLFER@$`lzL zh&NjQB3NZjwJo&$#qX}u<{V(v`E~HXrP5_r5(qa0@=fgN1t(g=HAdQ*y8E+oH(M~% zZz&pT;y2PGU7*OoQ1tuYcG$6PjRAu9X0pPWWKd7j88C9A^vN<+4XEv zwG#Cd$0XGuq$<2iCLU&hbc74&(dxUkVRU#AxnZbq;B{nWu#XED!1+j3jf93d=5!V< zK(j{GE(ny0P3P_>C*bV?^D5kWYr3B5YpKKP34r82=o^cOr~b$zBz$-p%kMxqV=5dm zT{{pOSnveFkCFb@*q{h@R-jls8?&ZSo@zIkstaZ)I17-}h75)hkcoxaQLG&2a>vg| zpQpi*h1Nm3HwS|~IVMoWzt(=`BpvBI|+!W<|`6)O)aDEEh?C<<9H zi}+>sNp4^3^VLXyhZX&;Rg=4#eh{IFF(&=V6-Y+f^1?{F4OjZ#Y!Vbh7G}I9cuxx} z$%n>OAs^%;{ciNSE`|XWt2kmE{o%I*2v%G8ij3xyDm_q%=^3Yu4Uo1()6o`Op&uSV zGVaxyDP;tVTU%fRU(5ap8c)E0xK>^ z9-8(&`D!~PJi(u3q|{c((s{&Y%j#xo{&baA^pCzpz<{>pQ-L(RP&Tuk%eVn~z7xOW zxjuEOs|-F;1TlJX9(#BL`2(?m(<`w6$rM^d^PtREeh=H4Y(W&VPb)@9nthgmg-D2{ zMh+mUoRyIL5)+SLMkY$(e!EMg4yD)z+)*v`23~N{ncEZmCO8e@Q-}}V2ZED+^H_!C z^6d5rW&7NlbfBRmKPaWc1VgcQ;K7bE?Q zj$(DX@l{xz9_T>ZG(wl6W+P&Y01Wm|0P;0hfzN%UJd2$lAf4YA{QxhK9#InJBS`OH zOyqyLt@c17t`#UOsDW;5rhVpQTLb_E3+@^PX?mb+i9{5|mg@>{kR`gkz4!&{2StFC zVj*iNUR8ZqL|nuaUcf6@2(L8@)ba&z1YJHqCN86DU{QSiQx-lrrte(!Xd9(DWrF=J z!NnqWrYEs8A!qbFNntyAlz%5q`QQR-1r$*ie2hVXXw(C^(Ao5zmp9J@{r?P1LH0ld z0kBLVIun($78`voV%2Empk6F&%1(w%mo#pje zAzmNK7#U0)&c=coRjoPsx1b#`Fa&Qv;lbDF3aQ*eiK-36koC2QYngP)S!h(|kK|G~ zSuVqG#|1{wDSUDmMVJ496lvj)RaLBqlFJ3vta7P;1=$_I&wTVz?mu1u?6!rPn*HwJF0@`-cnc>0pfjs-AaNZY9dIRMaLAy$@R*FmOiv&) zA;*o3g_4R&xk4O;*2JZxIpA&>X@I-Gz=gOQk?RWA0$k}RC^fu-1K7Cx z6Al<~lJAMTC3ffHP8Z^VGllNNT7MjCaXw^g$IAtAlr3S=t<22|Wjj;*3!-wOCYJTk z@2-$^F7FaZ%IVwz%q8m4M$+Yy*g{e!CH$C%@LMWZOAf)&|Zq(R)9^}vi;hUHgl zm~hCqod`hWZ0sn=*(8_3O>!B&85bbu7Ct$Uv*+&<$Vr-D6*26oZ{3aOoG}(a#e{)H z?FxzGU%wA5L>t;PB9Vz(Gh+P6+TjAj8mX`9uc*}2<_eIQ>Z6@F54K+lECSDbt$`Ew z`}k!{H2Gg|rIFwX^=dC)orYJA2?R1#uK9M%IYY3{+-Nr#^PSqMy+7V$kOE{}OgcR1 z2QqFJ1+;;fAGsQ7-sSkLt?VghiGB(g$XTL0aWfhCv#)#{hkn)w1dcB}bPW>nkj_!5 zSgVBmJg0M7_aSxG49b#2I9(N1_P4=T*HWaS=&RnUBbV(b;lFZdDCq=sbeuIEb(|Zo z=y&0sp3D*M%1?dX7Z#2b-ZU3drL`^K>ukXDnL(WkaoayZ3){$CN>+VS$1v)Z0%^y^np@3vZXAhEF3NSv3H{4bw zx&6rk+DH#+Xu;vOs>OD_J7 zI|q^`q#W~-s1sEa!VKUS9oI@BOGaO7|F-`W{=WQ$J%A_2-!lQ@e+Pf>jMwoW!QV$g zhW{!2-TJxR{r?{RGKlfNfxkO`c4GYPd1?ZGJ2~!;b+PgHQ{1)2U&J@R-v)P`_II%# zOi1Rfp<{!}&#r&x6m8{pBdxbym;!%e`5@5Pg{qC71V;?5Zw9Ns#Eng8uSJAr;=>wd z0)3d{;;o{|0GvPDG~ctDM1K|;e|EGIlT$0oQI9Hq`9DQJAG->K_!`TsBCb)1BL zR6G8g{Qr{zyZa}nA8Fl5_`mAG|3CPDc@Lbndm{edDM3Gtj{CK^xA;HqTGNkcx#lJB zw4ou(1N&d*|AQ{E2k?K7|8Kt7uH!#~zyC@8e_^Ypok)K9PvP%>i~s*qJ2C$DOi$o% zC&&FU#1AR_{SDYuhmKHvW{h7V)&C`Dn-s#QXJbC+ptBmX}2yMoO zkn5+H`i;Kxu#?(E93ZjkJlu@y=q=bkE!$hLdpdshPwR4((X~r44(N%k^kQR#zkBod z<19{(wybG{k(QsB3TZ&Fbq09aO&_9@xT+b)1Hpc98Do{`6WDGJ#%=2ZwAK9g281X; z0%rH~u|Wg=Bk6qx@JQ#(uDpaZ=MLd1sogHMJR|A%;u)S1qp$)u<|W?};OU3+BukW+ zaOQ22Wv|=LaAyXv1VyD^!mJ2MEF6Rz zyq=HOW`j8X(_=V_5bgX>E;%3Z63#rE>B2eZ;1Vhv8*f4* zC=s~rW8H=dUGXOLDU>FBfgEsI8-+34pb2Sst>CMgQLUOWS2bgvYQ|ek8_wB>OQ>*r zfenc|mc?eQ!i{t=+?{ZqcO&$nI7!^+do%e4A@CT{S06keMzOWOJIv=^(io$R#V zc9pdKnf3{!)gu_o(1wil<}0r^w?t_tXe9-Sd^R3qUqs!vfVyu1Jutdx>JkPq(45g% zT=9cHf)Wk|exPyy8R>8B?3J?iG}5Jkx6cEK@cmoUJh~e-v!Kw1B8NZ6q45->IkYT; zoFJnmG@fW{|Bkfp+T`|Gt=ivPTGji^9?7lh5k;$V+qCN1q*l?%B;&VsZ*vP95__l> zWYi=5OG}h-cySkWuj<2n(#xlneao<}@I}%9Nn@5+9${89nJ!Y2i`}IwI}d3d@)b|T zK+NONme;TqmnYn$t+W#}I)*kCW(m$rPtoS)vMv-_E0w`!f>N}(bLD$lO2urLB`SZ; z#iSPkH4e|tNioYkfJS3c29f~TCIJJu2U*;1n}uBixrKzX_nLn=M%*u=^9^wg>35Io z1^Zf&48&N30NPE1^-!wF$=T*Ydp6pQlu#2ItmI~?eM1wKylKJ>o6jV)W-h@sHoz{` z!?lq(uPa_0&4;R|2!#=&8;yQ-$b|LtDz~;UA2e$9*z$~XeTca>8&zPFy}6GfIRhSw zxScnAX$qV%&A#&lXQpwT0zFqY9Aw8t;^EBL^#J6u`vAyuivUPT6xI=T(tG%cAvum= z5eZ0s?`8{dv1G*UqelZF~1J2s1$k#(N^HQ)m3P6Olg$NF-Lk7K3b(Wbqz8`?B zimF>G`m~#(HhL%Ui;X5=NT&o0&D5lIO6tQ_KS+%tO{CPS|A}9cu2%hL+zB6Cf*TIZ z8GuD;Y717o531Ax#+VkogiA3H-X1$e-4b)*r-swHqB9nreS?hm-3Us5;paJMJ^9CF zmy_JbGqi3j$o;$_BzK82o1llYxPF&x6RS7OpE44`qI4KL-RO)SF2j_ad1$jMCDvPF zF}TY#5H;3SHqNx3WOWlL+nOw@Hta(?u#m9M=7=g>192OKWF0=n@yqX4NTe;CK_frF z8N_G87J-Ed>gH;VtGlAx0a*!zc?%tU0(?l!O6JXH@->6qLBIu^gNvwjg3mVCB_s&+ zuUSZp-s*reU8zN251;WxJVFs(ap6$~B=<5|-^|r$Kw&nF?dPxwv#pqp^L=o7)=#XO z*#>MzdI}C7xZ=K>(a0-)27deOrHbF8Y2>$mxsU_Ug>|CES#kK6nV){)gn!POQo^5s z6RJuK$xk+MmJ$X*de#|zlT6ygTw*Y>$4C0c*1Y!(#JoRuLoT_Elw#RwUOUxyTgZ=SqY@YQjmxcw~wUyJt` zKGd;YoBIg|1UK{OWJD-OX-X>igEn_3-`gPG%m*X=x#>VacR|vGpMSxLC;U4Zc>p#* zJ_gaLYOYH}CmYCEzhZ7o5|*OB;Sv%=-7WvJxy5`6KNvmi@S^z7qwI(p_4lG)3Z`?!Q2W{GPDQl5-E6=k)!qIIcT%C zDyhv;qE0&!I^#FW@JWg2)k;KXTm|Dd#IFw#UHSLzEy5nNw#`$Uky0`r(!%5ExJ0>G zc8tbC<&R?D=Vo_|$RGs|a0FIyxZYE>?=Vv0 z6s^f#t+-CMmkAhsdr$U+4tJb!8|)vr=}?J7cb^m(f#*$irD87%k06QXUq#GatQEfy zt>qoFRo>%BeZET)XW*mfUl3JPVwEp8L6x6d(TN!cR-R^ORNp9H~0~tG-Z@A43Y0vlx}#Zwb`|Qz&4^8(Jf${-vOcC{>UU(8TMCne=!Z| zCGypd0Z_~^Hj>ebGPMBJW!#MPz*|t!F^sFxVC=^04}W0Zd_C7(SScZbFr~DFb7K=8 zeBl>~kt~U9oUcY2X_xxLF~(-Cm9TF`0XEN-JsCPs-9TR_;0Ql${>Ko38Fp0y;Rm}s zGSt^M0Qj&#`h-rW3gWPBtbipgm8)tPjvg_GoCTC4mfG=;$zuV$rv@}C+RX+s@zc*E zG4G)K4fuk3SSZ^;ID;3erC1OM+rk-}>>-4n3ozV=ra|6N(2ZR}z14zd%NtH;)|*-> zL1~4MvJzWkAWd3QJ_m)UJkrR<2w+LwHgo0?vS53HtbjUW3_DFXrg!A9Fm1dAb$EzD zbyAWrCa8O@7VraM#z8V`u46N-G^iOx^Zn$;w5(5_-{{Ti@Gk+>31Rtpv=O+b=qID{ zLU1*|2*CmnrA{e;P-s|=(%IErxJKW@Y({i1s{FbA4N5?TK#&P|;=Cmv08|_g^O15a zXCK=6B?vJXz!S6!^JxsSblcWoF@!xr(Mi&Ps>5|D6{o8KbhcLojA3xbYLuS@KRlRJ zh5j6P!G@g}FC>3_XjZdpS5WdJtQ|>P+1CLF{ z#6d+pN?QjsK0!E5t&X@IRN34!pvgFr|##A=A1exu)vCg7Y_ya(q(^t~Ul8$RyBN4$EQM90aW zT_JZ?Q$FT-S!~!KQ$6*zR#Q6Fo=eD|CLd}{$`j7od3S4gy#vt2!2&pQ z*}U!=Ct6zhz<-zz0uAI$OAJvG$S9m-jtK>Qxk%34 z1VbkFXtgR5VA$bk)i_5vY~whnW#-zG!hx#0YY;V#ppa(+OcxNI&CpBc3@oo z(6Qs!oX43BGQ?onj5k5#yLFtY9PWx!0ns$X_-73={oxl|inSYCCix@7&cX@I(rg&v z^ns-4T*;sh#;$xVl^O7qp#f$1T7r9AW+D+jx;Ib5j!#FXouTI+;lSBE<%n*i4RJI# ze3q!8?xZL9b^q%PqNj_?o;>VNQSQ zgs14?tFvO*knYATNJdzs#P(fA-#tl8Or|B2l63$CRg~qbaXVOko{U-8kMS}t?+_~7 zc!pJ6-wv^K)BP@c$To*I6u@2bsX6}x8v+TH&g`+?0tBl-@lf-qA0KNEDhV(t_~;N? zTj7_W1AqjW!6F30Y2F}##!_+-2fJWM9ro{;1}Wr`+jCOP9{Ea523TmP>A*fruBD~M z&q6XROAQ{(a|jct$fy-OKJz+&8JPeytawk~yowyw!r9vOsGPEIEP0^*RoUuqKgZH2zZcIUjk#4Ny_4-X@cxdIGc6wR|y@9A(s<)q*}9WSW-AsX}eq#W#T(TA-8YEDpSf2uSG_F;OF!Wp)G7*FPq z)Sg$c+91(_;AIz7U@>cHua@A^3o3EUQ2H=bW-dD`sjlDkK3>;1GQuIz^{=jQcKwdz zs%CaXC%K<2xDnX37xXzFZkTYxSy;S7TTGTT;GYxGfI-O(IODhtC{Av`jHCvb|8(}1 z76uahTSkKI>`Vcavi_OjLo$e{+egB@}E z!ui+XhC970_nbapODzsG>sWa;cFOB}2Fw)4-VRpwhCn#!j1D-s#i-2itcDQ>JBBb> zEKL%_wj$|zAYCcb9bJG8LRUitM$Lavs7(*Pa8lx{qk{xND%#xcn#rP3nB1 z!x>uWA9#Zu(l76HR>xdHg51h8kRGe7VVteS$AFR65HN~5!GKzTK494+{7-ZL0X~FN zhGFT$Z<^rEJ+}gHzB)4rao<1vc!-<%hC*DxfiuG$mpc)6`QM#*lRSoIIj9RBlQm?X z=46su_%P_#94EK1r*1N{!0>pj!K*fGYR6h+NfyB<-$lo@w<;_#fBND7-=&O;AERpc z|Ch4q;ip|oqzl#+GVXFdbMhIA&QTIqVzKqX$o%PLmat(?Ij|@0-;?zlA_>#B4P`@e zxwlt<-`IJmbfl#MNUEfES{vsx2Ef+L;diBZGkU!k zYgFktC{+3YhXiG6wwp9WNm%++wSk{GC;aXfjBW1$99yelGWB;ljl(O!1=4AFX)w1- zZ~>o99U&D7?v&FF9jBuPEZE3=aT&%q+(;2VxjGIvPRU_0$sgDi0)+}Gi>HP$cF5l6 zblg85#80d*4MjD$8xhX_y_e2roGr5pbnEqoj|E^LS~!C84^6LNL%Jut*RzfY==qlm zztJD?BY4ULz3ST(OjMfjdrbAHMK2B?^W^V@`?Qa5;!e-HGe7wLTEDjJZJec*&(kbC z`LEQ*x_J@IQU6K*V#9U1XZzQ>aYHIXHL5p(ZXxgBq(xu&RZr-fmWoq;3)T6~l-%iBuDi}+$u)Q^pucCb{h#q?Z1umuZ0)PDOX!$i>Y?fJy z@m^F1MV_+kr~dHA<^T^c&A1L&3D~q91*y27KX5eVzUDxi@IlUyJw5jv*1>CKN|6ObsQz`uCv6zQa|i zpGsIbKCq3{AZyV`vUl-qCZkwV=TJ=aS5gH;hpj+eXo4F;+p&^fmXWhFiDm4)*ugS>_0(}#2CDn! zW>hz`O?5vyNp*jGEvdSx&g#xRL3ImRUFSB{eU)|M-d&Ph-8aJ>y;}=^O}h*cz3b2F ze%+@vFz277x~5l?dbiM7o&N;YEx!rXo!6$i+>=yyQ*w3voz=bZ=i~KmVzXymY)Q8R zK5f}6V5Vn<>ReSvX_KD)ZuCPsOpWwBw&zhs`6b~}jdo&aZ+a!E`-_G-pdC0~d*E@Q z=KazxiV#ur1zd&yn)fW*+G0+}57w|k%`{`cRByQJYI3LWYml!#)fTQNBLTOW06OhD z7-xqD@#5Z7{Fn=3qd4!(q++iSEp!iv%}c$VY`lzmwb&y7vlpM$VE?>~oSPelB+O*-qP>uBi#UlQ-)6f7 z(R`9G9h^s_5tw~UFS_ZFq09&W!RFc)tmu0hEeWZ%U1gVFQ=qnT_B$VLZ(vH?n^99#iEc3Lc62vFO!9^D6XDOB6(B2m_11Tjk%0 zok3Fl?zhWt@M1`H+v$j*6(l74uVSU}8&P;wH>LM*Ta_qcc7H>cJEiG9&bbkP&u z8D$^?;6AVveDC);itj0Mp~bDXOPud1+DVArd^Wdl1s=wY0y&Rd=-_+TKk4AZN&WY` z_i78r0~s(bWdQtCjtyidziT`Nm0XWHJNaHfV0{dxRNLdEe2%1tT2wBO*=>GYsvtw4 z@--kd6#yu+$$=0WZ%0HCK2yA~%2Yt)wFsmRnQTncDE}6_Ke@L%_kBmui%|mjL?>Zb zwME6aC6Ux1LveVkXN?OtY;|cd4xxPmX)O8*9qCa@56D~MGKt@F$_qdY+~70G!?Ct3R4g?|5;3L#$hI_%L;ctBveVp6y3N-$Hu33v!~@ zxC*Rrqc^Y{@rUAEF2_~5C38>^}BJUiTge4cQ#-T!3Oqh)I` z;tN2f*v1Gh4sUp)JvNMg34bW#5&eMDF7&@KK*ZiXTO(qpj1wcG{!$VmcDulVh%Y|g zJ|eEavIbc1F-j1np;$NAU}+${2YW8r@WrI)51Z0L{*)Hyzvso2R9fub7Z+lC7aQYU zy^GzuJZmixHfCq%TsgBC`|vE-kM0%cM=fC%2gYmF5=IT=UM*Yn`&{GNTVuWW3TGAowT=O`C<~}hz^WuPJq1 zN%;ON;W&kRNsa)2)BN*A#JF*(Fz+B$g6%4_V}~ssBjf{=^Mzl4-wYqP<;|ohjWjyM zt7k3os=2jz^#ZzY{{D|!$^XqqaYa)~*P_a*6~~>j5C5mu-~RY?du`$W-ulHZ@jBXD zzgUDIFKhpW@3#K-Ke>MKC#TunKhFAF)w)-KifWZ|d+Tpinm@$ToMiun|JM4&&#yf0 z`bDT!)Tai}j0`a}pocFq6>V7Q0mtc+~p!fp(K1MSQpQ>wf_Mhkpek)l}LF z`Ge9R;M+k$B8Aq&PTdhEU~o1i+@Su+ow8blw+U_W?0B@~~L4W|er zrrkTshsFVBq<2K!jGO2q)hjr1YGS72HbM`7P91Un4#uyRx&~Ffow5(kysD!q`znUP zI=^x^{FjlOKgk8HV074P6g9P(KWZy76*)Nk|RP0cOX>eQQ&>KSs_TZ2s(S^!1_I6$S^a_^bt z@R^rkzPY?7#=Zv{=Z|D|#0B4R(DsZMV(Ex%i2VsU*t=*GKn!R7eq3wKz4(<_PQ*GQw5Hs!Vqylzad zwr)d(fp4#ex|W^7qA>IX?5YoJVy$!m!97A1eTtbLh^A8Tl|*u|8$&R;#_|kh)mAo zZnM*fp9n1+tw%B#v4QBLSzLVDWWK-uMF=gKzxxMi)UhCS^l#c-ka}aCb3v*(W%G;H zM1c5{wT~-?krDkVRSIAc?6v2+Dnq`o%LVy`x>>xnZEvLgcccAz#KK%+Aw(Y??d^$> z7}EEs46g8-nX9|+$*n|msh3^AA~{eKyffzB2`_SgH=Jl#ig&U%aw%PXtBWm1}$_IfEHbXSFzLdmd%(|6Z5_V zlzqnKLOI&XA=s!aui|z5cCL6WmWH%gKh|8)9gg_!@H^w%hw=?kdn&M-^z~ZhX;y0( z;AKTrW2v>K#kFv1$WD>tKKE z{>e8>e4^Dzo9#xf$=_&N6YE`*lgBk3zzfG1j}%j?mO7Bs0*KeUUUv(P@Q2Lf&%CX39~ zR=VMm7vQxJc%6`z`Nh9Hl(xQ=vr_51&#QP3znv@IiuT3ZINmETvBR5D5w^;;+UJ9O zV*CvdqE)nW+!`8yK`(~WKq-h&A`}1n!4V2nW68?^Dq;-AgOihuCDc%hYs~WDD+s~MA+hj&04huICxnJ##y)| z;P+!Zar6=0F}M!xg8(xH*V+V$JM`GUJ<1-m)nlVM@O`yq{&=J4|B#ZuL6TF+ndB#Z zz+bzktj$5^AsIcB2_p({3p4}Adgg{Phy}nBJ5ISrpYEPw4j=zg%f=MQ$LTRV3M+Fa zGjrnKw>ZB47U2`mW64vB`Qmr#ilu$G;Dce~@6PY9#=l1#-(QZm{~7fi>z}`%NY{--09;M4Y=T^eb2AF3 z;znMYBUh6~h~l9QgKO8DKVJ;-?#mO?#{skf^W#9$M;_?|WkcTQPcCPX0w8|#{imgv zfBhB{Io@XJI3KX3B?Z7m++ESeA|18+nOH9g70&ydjg%lfFl&9R90dZd!`RcO(7amn z1uQlR75*@hE=v!4@-Y3tDh2WP8q~j4?91jos}OShuq3}QIr%{B_hKbS!x2)l)f|n) z;E}bBo?)tKP4G{miGUWwH7lmoA)qn7`4J~eiGB#C>trNczeo{Ng&1X0V6Xa60@A}z ztF1%~>k7d^t!q^KMbm}G1ql>1WPt*7{lR$V{<#Hw-&iySP{-1F9r1t9;*LO!loYv3 zhH3Nmf$A`Ymm*4eioN^;LTVYr>#Tpz@G{B{D9MPs{c;xLlyyFWQKG&DDQ4Whi^fL56_-9(hqUP z?`|j`hTfi{8Y`}Vjb^U2_sUduR^_wG;>-sZDyl<+XZsDkD*7hK)mhTIKMCBdl3wn| zo}aL!nzW0eLpYs4=950d!?FvF)v~Ik?;4Ka*=Ieo?|eRp=b-YeLat>r6uUa4Ifn5` zl(M{4DYQtlRJ)WWJTpDt>m98F5+JGA<$2ttu3_3Q8?gO{4+iY(zVoQ?;F?!t=MN4H ztlHPvMM8eV{t?qTIBI-XNFOOJaD3^#W$Pe5Jt*VrBdmRt8GIo2G6YGPeI&BY9*|ow zxYv|n|C>+9A)uLFJt4Y?{V{HwpnT-!FaAjy-Wt2-JJ%WjWjkuE$#(hZmNiBH+1qaY z?|#hsxnN*ItcRoWOjWraxe=o3)nHlILdXXOMy{EnM`n~EsGy}8L4*t#e^BA8d&HCq zu;YFgy+{U}IgA%>=LH*&#TcqKkYB8arDpo~0jaJRc|x0l-kPo#`NLNO95(_S*W1mx zWkM{ZnsXQ^N&RZAw5Tz9hsc>?;K=}&3xv1eOo!P%?b&Fjt7^J-^wq~YK`IO|2m*^y zDfuCM8}U~v*kPJCfcQl^kvD>T8lU9iBgm%kq`hYD?oFhp2RWI1XwO6Fm1q+rq*%l* z!;LaRNo73r9m`--(Z(n@0cb4Z#{QVA6pO1B^j0h`QZg*=$p^Qa7O*+hC8)VGYF4a{ z@aZEp)Bk5LPFs;=15_N(W>`_~LSz?4PO|Rzc46lBUW)CVxFqmSpZnA4*!Vd6qR{3% zJo>{rhH)l_ap8v+R*#(!H6=!7<^=QT-!cF0;SOGrx7*T zr*iQ8;XPRHNKI)97co+u6#YOsxTh7XAb_3a8_?)ZXf%pqe2dvfTFuczP7WdANWx?Z z$!tGXV;8~!Y00LSp+_Qr7Y0gfRSw2j3a1^w;@=qI{?aU8lF zNTTaaOr~H5NEUtM_&zwL zzcdmQNj5lEth3@0Ry9LxnF{Y0e&x9i3NBfbnhwTa@Dy`fx_TFs#z*Mj*WQR3@~ zAZEU3oE%)HLq;Qfrn>-^Cygrh1pOcTS1Nd7G2ey~hiKi39>jmZS*gH_))aYb;1&}2?2VjYz&QmC zmV;t|ip<6XgY;-)0s$2KL?8=&2sR8!fbc_4F?mt;COf1AO>ROcE|IHRVNED5$1}?= zBOsrnG8{{Pjyf-+S47mpHHc?ewu%D1>HtCpP!XwpJN5?#)CUX?_Z^#t^-+lEgO6;4 zOup=JQ5@LU{|272vYrW01G=hMcCkoiS;j%A3b(=qlpDz35`ZWg<>sb#(QtstwsS^$ z8VVHn^=ZFQM^SxqA$zi$DcDIwVG8=1v8D)bYJn-6bob}w!@vu3J8zb;SDXA$$Xkje zf&pAj=?`x-1L!wt88Z2XDH!ctG=0td8|9G(PiP>E`lny#vZbBU*ydF#iPiroisO_ zhU%hR!$%YW*BDQ&)lar9&I`Ed*kYVz1WOok6|sKcjOImQg{N7h5fBJ-fJz3kaX?Y# zz&m0nvmi~0=&vU`AAs?h2bFS}0<42_sSx&QHGdn{6^Kg&CPH&0xercVtdAezQK&Hc zbgYrTZr5l=u4nfQqyp-jVRz->qAEF8yDX9HD+I&f-R-2;ALxkr3F)+Xf0S>e_R!JU z)5cH(^1JJK0N_>(dK~9!e+?KvmBkUFip2ClSt%GSK~NWp0^7GSEf;$hHB>=A{Fx|R z?H70j3%vQe6bQVG?ji1lzJ)5NQ(DCWdkBeKJ0EZ0C%-~@T~MARI6>Q>0ait2&7D;e zyXq|I4=72-&s?jWxVWO4VYz-IZ77kZj8FrO(p^o=7U&u2V^J6_w`D8}U@IaAb%HD5 zbl`gWRG7ApVVVYIkUy_bc!&8L8Wm;JAOI|G00{8gsAY(xSG9qNgI$l3=rAizhoCjA z%MoI<>Ci*`!Me9{MTclD>F_U$Rcjl%+2SzrwQeyHUXMLs7jUuNT^4YMRY28A3jj4{ z0av5zK#klQ>63HOGxTr?d+6RVy_dFfSXSueAYcqaRTlr<(G<~y03J;6kgxtsak|+d zPGhUb0}!X11GIWWA7#f&bV~~L$;OW8Gu$X@gxKVjkBCBKzMPrpbII|Ln|+@^Wk|>T zO7MN(S=3!tQK9c#6eQ9Vv{fR0$&)hLlPAr8R-a&=j6QR`RdOP~+;lwI(el{BL4lp# z)auiLteqC6@*lvbNaL$+z=JCbU$}YjQ%^YkiHY`_J(3z2o2MikslWaGfj#TRnR#i1 z_=YN27AxM~zjw;obJ|oqv~9&4|3^a>Tw)K}GL`e1XkbDhDXM{hPI7__ILnolQjrmK zU#dM=&$%$%wBDKB@*f;wYm(#(mT@5qFC)AlX;_{>a9omOQH@f>1i*vk7gGa#xWFn) zKA&mvmj;1C#V-{U2D8ip#v%tIwL1ovh>?O>OIHdGh_d5LXgJrod$GCBc8e@BwZ;O)xLM4C9 zX&*1SICmiU|JsDCmIPSqfh}o`@YeWncJ4?sH@tMogW@Pi$$vZ8-y|PDij8CPuC1_K zfBwOXusDDCI<>p5N|S-%8tVh0+<_rOvoW&}2*LJbQLx__e*?B1p5-kgrrE zK^!*bGeNZrHieI@XeV&MIQ+(z92Yo9BlLG6U;`i{;KMlIRgJ)q_x2JDFn^6L`aiV2 z34ByV);^p-8X6>a5YWgn28bF2Gze+}L=zUdjU5Px5*9TmU{r)iIuHdhp%Y9`b2Z~K z&bW-Iv!F7HjthwIOacsHQ4B;`T@YNVZ5$CDWKr{fo>TYsl7$)H_xt=wy1Q=OT27t4 zPMr#MAOO@P39~>AAF`207KQnPqt`d|aun?OwJP5@UH9*}-pD>}1sNZfINE-rnf95u zSZUGuV$8Hv_gTXsAVRh8`13PP+duWIHCn&Aluec&-b`G9^S*|k(68hZ`c=J@KPk>! zlJf!i{kA@y0t4a*e$#n>9G^6owcD3&Dk2IUwFmeKckc@8H{amz)%Zl@Q?k((c~~Hf z40!QV=qu-o^m4A?r|CHITkJG$yNco5tkejBCz?c(<{a|3fRdQ+Q9YOUU>@dC&WVg> zSGMAA2|qFYaT7WF2;7L>Pe{oeju+OMCE7?WoGUZ2@h3k}vC_y+kPlqP0iLlub_&!*S3TsB~Of@?+{|*EbAv zNP{nHw$vRM27$j*gJJTY+etWbTCUFV{L1;bI_D&XfVz&=7qb8F3{yi+^UqUb2`_ux zItLnAeNkjZU-MDr$o4oJ?h9OMqR{F7jo2vf}$E-aksEU zgE4qNC!T$EJMbcNA0QRVL}xg}RqpE8gz0+_l;w$s-O}K?UlSA-9-`2dl%2#c2EL^5 z3-G+#Z_yH)kw8qbvullhdk6waPP6P^Y|!jfHZIT=2Pr0{CXF+@Zp}3(I&&;=B_nay z)>!Zf=Z!J#D8kZn)?n}gsY0-#BAiDO%MZ2TgB_N9vgre*umT}KZTTpp`Z%kbIUZnQGeS!O6w zQC%3PnUYZlWf-sMpH$zro(UtY@_^naPBZAbB>Ze{H$m$`g?zD89+|y<;K-mx6_Vir zok*MJB>vRa4*O&5#e1$U$p6o#%|su$xgW=_&i#Ol2loaL^~q)|25I=O&PIMDFuYQf z;i1ZVoG5L@eVGeEZE$P+pw9h0nH6%-V;yaC*3Q7E%~|zZn&!adO1EILJ(nq^M*rVa zKf|;85;v6-Z{v|DVN2+aYNIYkPp__=HTd7A@@jryA{V@TR-Br_V7|I+Cj$U5p|<0B z3`Yl1X5;t4f>ivL03JF}Ovj+>yPzH-kX8FP2;Ewg^|~9CpuSHcIP=)LEK5FVIGt~2 z$XbQX#z33Kda|c8Um!iD|6kf~ zI%bKw{J)J^-LVLVWAtofhB7&su*@~qT5gHCEBC^dIeKt)3qcf`fAg|)a6$m5iT_r7 zt~BcD$)#RfDr_q-9{@$RoO_b=UUXgYXf5ka$F>v^vhcfT`8KSv9`liGXB4yjcM{vN zaoRrALG zp{_uuand;?EVdNXGb1TkIic1(yP~M8yGvSzmskM7{ioOeMgO}3uyY!It)CJq73~pV z3);?-(Q})YdaAE3Tg`ctomqOS*#F+0jiI$RyKDBT*Jq_(AMl4cuqPm?QV;_S;;que zyJblU=r!A-*Rn9Zmf7^W;6>2uEBj;U_1bG9^a|;mc05>x_Aq46Ripk-s&nRIla7QY)YEiRffIP`Sl*RoG}>20k3Kr*F%C&|e59U-z! zB&;N_h}Z@gtd{v_7L}G|z%BvNpd*lsN;&K|buahX^{eG+$i`$OkL<3p+@a zNgvAa41r?+4F*=1;h85O&~r28Fq0{H`oT$M6nOfLBA3io}e@1qYBcAy6zO0+1 zBdl&-zE~mo>ZM1hf3&_5U{zpR7&>y%91ERq<)i^Tt(~XvbBi1RKwxia0U~T($LN&g zaSS9r{rW_B_c&g-nH+xn!j_iinA0IA)M$o$m!uK?!YJ_#3i+m`F4JmtEl%v!?($4?D)dSoL{g6B;Kn#n#WdI4}9o|S9`2eF_p0eK=(p+l%fW? zG)$2^2R`}8q!=9eZREGdU!yi5XsNnI=Cyo&%fuLLXjuo<^uZtw;7>Z~0|JwO0(tow za?2RK;Ckb%W9!RYm0tq@{$0Lixn^0eAiPKU4vhJtaOdz**Kb3VyMj#(Z0YVIv7OnxzaK3pFL05Uq zRawl}!(yERC7VQUkg>r2QJmA<@42mEnK*FzlYh~c<&sdTTY*oyrdIMdR5BrdNc95R zN32W*yO2LvlRrw4fZkQ{qSU8$ZS@42#URCM%md4Kbem=wLI@;hdR2r{4YjY@N>IBR zjX-C3TU_7rWwSI(@rV}-sO_;12fRj}$R;FZCWc-kPhLya?>s3ru?eDhw=fl#J$!E6 z+#;F@)ESVk+W!);#7yj3r12<^Aj}6I9r9>A%2R7s*?9EcJmOJoTe8~^2sbSSYu5g+ zdG`8uZf*U4r~MC#s8xPg$wXF(x4oUULVbZEfVi}fdu(z!(_Id{PfYNm zA%P!POule^<;zMo4%fsHe3so~#8rEf=ni1pde2hdx5eK`3Z4U}=cp=A>J^MaUv`x5 z0y-JQEufXCo{%D9#n-E|j%wVJr2%f$NcH7lZbNO*lfsRq&0B7Z~H@rmiftqTN$~IgY zfbobt#LfZj2C6q#RI5{56}-5@dXXz2FY(Y|uTrRObQJuZO< z`l=;(a!ZDD{bU$nn@JNccKR$|66H>V>isnq#2yvi5d=c=RIF+Z9aXDk0CpNJ+h(!6 zO)!!;Qt%h4Wuc)36NngIj|7}Qz^A7zjnGGQU9N(&3NAXLQL;LAheagZzfa;)CI=6S zHm&84B-o3UKVWUyd>M#HuQ|M2`3!9-fS(|bw*w7;3jyoz$wZa=+VdlSNit5wz4%v( z+g_{W!^E2c(oAm=8C|k%c#N@aY_P8X=id?H>V8bG@n(#6f{f9RZmI96joc2ZC<>r^U+U z1k-r3a$g;KrGxyNU-QtYh7t5C#(S8KsVkrxKUxnOgDu;aLx9x&RHQh*^_-~b5=@0q zHywA3(R7)ia{gk|<>cE*mvgWn+R`|J&A_PNrsLSt=wp!8#~9tmf!}opM6|t}fu3HS z(4?pMa8JAcZ1?o_ZLvLJh1HbXYz{uJIS1GHxsxD{*Zu)9C4qtetp-dPow9dRuZN(XqSX zU~X?XtHvVzLpJbx>-=6Gb36hpwjzm+yY|FYi2ICp$M5x+H)1hDL(umo?L%JuK#2%9dNA`x>gR6Unj5|fB?qU$bK~LEy0&q&Ka}J9{64rM+zp@S_Ws-x|5eVh4Q1ZR z9y7narcbx;)K&AJB@Tj`y(A@~r0JMBnrP6g7lxrS{)FWLJwn&^kUOxhdD)1<)Hqx; z7d=Rs(>BS((b#Ne-D;ngnXShM)inC4qh@Y8I+tRL&Fs~2Eb?VkE<~yfu#=|rtvt8# zng>4M21A6ZgWt8RKU2S}(ek~5lA!!>4Pock2}KOZcP$6?MGH}WHgae9PA;L`1_KJa z!$gdi;h~fliv2bp8ZBkaW)xGzQg8vy5S((cXo*UK6aij@j#7w{8GP3k%n?$7@8kxi zf@kjc&h%vNS#VQp9pX^=f|UZoTls;O(452^2-~4k4$iYOv`5&0XIRM#ASPsvbZlSGYqLuVdC>{>~CWIko`L!ig3cX+y; z@_pK8xF6X}{C@vAu+=uZD(j_XFmKq2Bc13FCn-iI^K;Y46s-hNcnTO-;0v}vGX#8= zP&K=CK-<(a$Y7~!N-c=|l~UWPhUfMQVH?B>whv6qlaMEz{+9!Xwp+>a4?PA@e z8=>bnA_b5ala%1Z8sw2yGK6aw{g9&Rq{Ri0w9{ku9LB()85u zZ&%;JpMgb}aE4l4fPavRSRrSK^_G>7T6D%Z6}7hV7&hf~U5+*E96jtDS(X-YoKr63 zl#7HES{+8~Bai{cA|MYVC`=PUZjfoUfbPQn(a>!Ph5#R(Xqt%%___jojBw(5*?arZ z;A;gyHf&&;;KVIes5L|@i#9CMlXVHVsv`zKea=4#^_}=*EcHbeLa5G$Ma$H8+8$(G zVQE>bDCqXHL_Y1Mjq!^HJB_0ZI6VKC!HWNG8Kf_iO*3)Fwxl>U=P8^|SAU+Row(3D zWX>_XM^9X^)S5^vkcm`H`MUO0&YNLL`XdnyMZM!!Y>;etzJWxt*OppQ-mFgBUa zO11N2FsiVmRkswtFImfc1!K6+Jqy1$1Uf@TRKaN>fGJ6a8->^Dc zclmY~SRgvknQPRu=m7g0e{b4i>~F2Vybe~2KC;;dbS3@)4uY92rrAv=85n(jb)eh8 zb=Sqg2DuO{xDUQUT<)*x8K=(vkaJ@_P`E6LupY>OZf&cfZ-Y`mYP&Sj>s$IlNJv-1 z_^7%ieJM*)klzI9hHDQwb2}U&XG+E~VJFTJJA(#zzLbP8z)8IJVQL38vMs$~&^ldj zxS`}B)a9IPD-(!=qxW59OXXda$8I=TYsZkCeb0%ujU$uZr>f7n}gBHK6@ z`qLihUhdwfkTLy~5$Jl7C)Yhrn+fG;hCf3@#DH7;RyO0cf2?0h(ykWz@i|pay`Fq`wWmy&9^0EkS zh(zLwKrDgDV9|Mz9gHh3P4IdR#EyCfXT;2a^M6{;Uq0;lw?xZggQ@3kXqlF|rteN)0Rd)KXgPh%IKRbxbezv*sOvnd?KJ6^W|?`} zw29+EKXX!#kSvcVk3`Yk30EYp6ENNJM)?Wa_4nQ`hIC-k@-$EgwrYCavT7W3z#(UV z2bZC%&}~RDXViY0fE9Fh0K0QKeVdN|@G-M8j6Qd#4qnHGHGxbSe6-&;?RO0Yt^!aa{ufS)O`Byg6?F zkcQ9}m5u?05VTXjmUYw&get*5G!@$>3v6_ZWzP7e`STdfp9_fy1w;hl%0={hQeory z1uC`3Os}uZ?1Ulaa9?0A{WJ*Sen4;WKx@n?JMJu*%8Z!S__q{aO=d6NlMz@YM)}&O z2>w0?Sh@FLJtDe!f=;$EP?bsy`=h?E6-HP@NFbXW7ix=i8sNqfa=v2x__#5F)Q3m; zXCkAnIk5hD2|-7m$lxlxEmuJVCjy|O`_*Gu#6w8>QU2PThR;U#ejjJK8mn`86YwPf z7g!QgWV{Dh0LiS-k=J?sW%k=0r))fl%5;mS8*Z8z6Fi3PH?wiOjmbgn*yZW$yoQ6I z#zl|(X3hp`5wsTxd9ijm%A{Ct;Mlpb-GM0(6pr~`9ko}a(%uEjB(Z{jVtigl@F|h^ z>{MFAvvhtdWvv3*x@?y}(4977qNc>gyM-Hn5&Ln$TxpM4vao%Czz;0a{f!)&+35*} z%Jlo#({F>j_S3dT?I~>M?j36m?}%1hag1GPP#4NIMH*%v=*FB0F(J3#W-yS(8ti+b zX)%tmQ+)4am+x^ry~Z3~26OmlU)I&Hkgc8rTV@zA;Adndq?-?ir#ml74*i2*gA(g_ zrm-9R*H6Usg(r4rq2J;vA>h}0aEAKX-&kB@HlzcB;1+_{&rhb9+e5Hen?`8yn_1!^ zI(`K_M7Pic@t;&Z?h*P@58n;yK~}wM@LN(30ewb+%P*30D5MyjK5ZsnRo*O_-WX?!L-p5C zr_a+gD`p0*6VtKx4v^O)ok*sv=0%ba!fh#lqFvG1;PB1v5Mv$DFHkLf1Xb5;l|^!H z>B@a=G{h{6qe(>PKS3ZO%QgHqa)Dy}_fVgcHUHSQV4%?tLfY}^(ur|isE;^jfmlUS zLB!*|C;A8Ma)D}^`~~*zQQaOAEZRPkSR}rB@dF9aM__;DH}d#p>oH!@&h{_o0(+1E z1=xd^!l?6Q(cVTif=vqI9KRWeQ+#s_;;4}mqoEM&3YpVPc|k#xe2|^kR^)@}7+eJx z{@gX_6Wau5%a9Vg4P zRI4RsM*?{bNwQmdQMdG(wDi*|yQNijOV6>T3v^3Qv!#7+>M`MNLbeo~YPU2)w{(xR z^tW(J^Vw1&H2mA}1?RJhWKfgX)Pq)2eRWflx7tmet($6mh|?Tywq2g^%x{vbbc{s0@3K2`YZ5h1i*OPBKi#s!k{>%EaZz6kbHsbduwNi##&WtN#2LZg=*9AMO`gH3$gM~O&AADr6u{W;6LT3)M^4{ zG;Lb=RdAXN!P$@mX#_p@d(OYGrPE}PU(@D9pC?mu7KHOt*5(3+KuqU<%1`-Uj8FT# z)6~1mvCL-Trb#h;)O6es#PBW@{3D};K8jWTnet=Z9Wmp3rzAYS-v9OZ7R34w#kCTh ze{?M3Jm6?T{?TmL8>K1P8H-X%aHLYSL)pPSLak~-C&@(Gi|Co&EEB1^6pvd=M5;98O9~{WRONIfgOC2t>ddc1qQ>k9E+5&)~*DCma-7oa#h;NzBDuhKz%l!{$|G0{{)&A+>#n~|IT_S^Hq|=LIJ6$WC z{w>^D3tuR|tn=5uq7~9|e7pr0SLIo(gOCvG!cL5j9!g=3P(5t`;bb0oD6GIsge0^y z4|6S%+{me>^~ZI;7L4>x(-;Y6BAnL_QBY6l=aa1Gg?wHlC;vcb>wu@tkNrJ)JXwzY z34fTT-|uR@4>qU+Z$OhvMg!@!D2BQfKK-|)kQg5uD6QU~AIAHBV=Y`_`*Oa|W3H0j zG_JI(@u~z~ygl%|HL?)>&>ce=bHbFN$1CHz z99Wu6DzW_YSb`L_9y`TU4pR(YZIZ-DZB{QyneC$IQUOD-kF5S}ME4SUJ`4=4KW-zx zX(9g}31G7-<;JoQy&t=Y<~_;2tkge}vBSSLKN6fbR3tjsE#*@K5hwlC6F_>{E!-1f7wW zG?#?^!en^pkpBs6FZM!oFs76^*HbkSzMx|WG-HxQQM1Na>k;HtU9m%o`K8zAZMr_1 z@Oq=Fr z9uDu~{_|%recXQ@p8qMC|7_0x6S~>bg+FwS65Hl1~oI7QWrkpvrAG{A)xWM>h)Bj}9sk!boKOtBwxKl-|kfQ0CW zIl#io#*&MT@>6k1%v4<+TuUegvI=1E0|qnjA^UhtL`~NUy%jWoz!4;ZB=H}M2&Jsm z_$awlDD^vaOSgA;{|~}r;qU17IUZrB=L=SpOgy1cTvWhNxA4(?X<<7)c$5RQ{+;TL z7OL?+rk3@Au=LAz;X|)gy1d?eSdH80Vxcd+t;C|_V;=Vd25dJ)c_=-pq9 z2EV@_K{SEO{*4ce>li-ND_uWq9E7;6=t)uzoXD}@9DKRCE}-Fir-pAnWo#Zb(LD0W zLd;*{pRVL%$dm%I&?0$6(3OgIl}!=(?=sP%{$*$_3T3h(NzYXPoN0h0}+tYDuLnKnBV+oubR7wUx~Hy5vgW>(^5~r%!Ss6O032xp+z+zNI^QldzF{n z3PDV6zHYXV6#32kYiV3N7^(cjz@M@}uo0yqoJ_xGi!gL>smhY7ZvBbo#;Qa8x!F9z}g@jylaH^-QL|pu4%`X?$@k zbeKz?4|Ot^{6l_anM<}H_A;sDZ7{%xO27c$Whf#TU=Ma^CZ0djVt~CST}THNf{8fx zBrHfWH*{{~JHNNy>8aoO89p~*n!Qq5c*kFFFN8Ew4Mq^N5^CF(%@!f}!+(JPZB1Zf zI{xXk&)1y#qn;7+yK+Xaq}eQe=>_6)TL<3j%XP4{O0LH?40eUCb(VPW4Jc8BC)dEvy*8<2D5njS z5$m>|+^RT9q(W~|BV2Dz02bjaR`u-6Yg0-(x!$<8PsW5k;T$bo1c_UXhM%g=iUwV9 z1~ohAlEF2(pSG&v{Ws5#|EKq_IZgXi|22(aBri>BS~H3U@qFCaX3tTY+^jSLfBilx z6}LP{&MzOVCGtk>H$G3!JI!+$Kii+sVkO&S02d-8aDM}9x_JZ5ejf41{)ia=hr|y5 zD7I()D;9I@)`m)J8fkzC*=YzWoqwLeQ-t4IhX{?{M~rw7Q-mJXYD7ed%OOR2T_?T1 z-cqlTGP_3yd(i`zmygKHUupZaA4Z8qWHu7c%zo#5k^gRLp?nlhRHE7svk;N-Sp-J1 zw29jyak0wQNay$_{4+h4e(d(IwCKZwwCUc7x*Hv>-IQtkc4#!_iz*ZPQzZ86P3icR zn2xO9d#h?wD+ym z-qB>EZcMTi){RNwr!VW)N6Bp3<5X`_HM1{|2W%yM`-4+34gYS-^f1T)Qmh05zN|s= zR!4GY3@0vhhGCXE2klh%Aix5JX)MH<)pTE0d%JxjqgoExWT?wn39A%k18T~l^iz{F zn}IKQ2s}6JzH(Lmgr9_B@cUR^Y_ApZC%HBJ=?~aO$w&JgocV^Kq1IX$lmZM&Ybp=4 zWPT%~*#N2er2xPFz(J-9eyx^eej#R=1;2>DSS2!XR8F${A3*#a2Idu^AwjGvdMrlT zUCNQ2(3|W=)72K~#>%>Ly7v1EeKc>MEJYo?9B zS@%z65`O7wujh26vB>TxqUDEPU~g#={&X7ppnq_)4j!wb6 z@7GKmuorGPd&{>@??ljQfE1qcp?8`>#flW{o5kE}QK^q-)AI9l1x7=;@abh?WsV*l-*Pe5zJJb-n)+WGZraxCcSFs`B7(VbE!Kd}FI9q|}k1U2Dx z2}n)Zr^958B&t%#po9t;YPD4rAT-i^Sp|`*7?P19RUz%*noyNiRqUp0aXp%yZUiiZ zE8j@`+o1k91m{%1pZ`;SQO)1KBv4~`klcS(?5xIak)x!0`OreIx2WW-vU?JWnH?=J zBQ!K+ZzcaiHhtj;416tE>hX(xE<66g@sMoGyuAIz5kln9(MrqBO zzacR(8bCxT-QYkXz-^DZ9GUAPMo+rB0Hg-X6<4%Dyx0n}^?ulrY5BKsFj--3|1TOG z%{rUi@1f!2)AnZ}c}xL$OaYrI68jU!p(cs_DQW&ts?x4L4s4O}6JslBDvX#q(~tqr^G89FH#ZdSGUly)J}t zx)!Iu3Kp9%i7 z@-)%<9lcr6H`Or-v`-!J))@rO$_w5qY2HRI+&&s*(+o>otW5QA@@}A51~bv-^UHrmor&`fpI3`AtR(%?lG4L zB7Ne@6X=d{Lx-LQYY-k4;&nECl1Q2iXCCg##&sla22F+#&R(6<*Z?>QrWYXSm7dK) zcV@$V6~WtK-Zh^Zhg6MWoNh>5hXRk^su<{+nu}JQm~-nR+7lj8<4%lch<4>fjpzQz z{PhCGz#;fF@VEJ3BfN@3N>=Y(9F6oMRf0WQj?1(uAohNuZ9K*PAMPi@o{~6cHf#QP ziZ@eWsUh5!%Z(lt%)u|z)5xp`_6CcD^JYv*;-+zez%{y;0W*!vD?!{*htC$I?MWh9ib#o47IseQ`40<#=FVOs zP2#3PGx7F;+SSb~dXWF-HwkR#RD4N?vW$yd6;JUe$&Ky(4t=Ph4_dr~o3SKMzKA%N zJRLnU6?i>1KNpFir-j40asS0}i9nSb$TUwO=G)4u7V*-j5q*%!I*=m-S_RcfZzP{EG)Wga0F2 zQrN7jL;e!97+fX$OL{^?+(MP`CYhIg@NF^J8a92V0PHvbVJ2Q}Z3l3w!FhPOEMr;; zuG4_ixa{N&B?B0fZR-ywaliBh0>lkCYqrn$VLyXLeTQ&Rc@OLtBqQ91a4OI~xQ;af zNR~X(Mk&J{-daxhVwdVGfh!+j|AnKd!RD6@@L-VKADd;1JM-X4>Fk{HjEgR2f{PIL zb5MZOcsLvcXL=(H4EvsJ9A$Q!2}vPrG=Ndn$Yt3@n2zg>q$*s80Q@dHd9k-Agz=;o zA&fBqfVB=0^f*+w^qYEEgb2VF=2jtG2hsSdqr*CVN|7LXH~F=E+06GVaVpS?19go? z1iGE5fz7x^!|`jS?nk9E*2f~$@DnT&vPI|HV0^)tvJ)4(9<>r*B3*ME1SXj}FN*r& zR;sTS@doY!WTzAufxC+&6(_QJijZ2tR!zrS{}xol@h$bc;GDL&KeLAVClqQt>~`fv#KW$GaVP`-?gJj)Aq|3bM-6s{+QYy2 z1Y5%S-hNSQ*$aRcfbGE$<;wy4%MlJ5Fyj+~iVp}C#m^{^Nj)26$NA87q<_pa=Q_iy z+Auo?M9_t%7yuD88qA;xh#vbs45C%9#DEB-`uhqSM6sm0p4;E8gUBM)Zo@e77!VoK zAoL)Bs2cn2ce5cgac5ctLKK=sjP-&9HE`#I>%k6403Q6Fyw`NBoPl`GwhxLzx0r8n z3$NP?tOTzPbYSf^5CVGHi%O1pK9g6^WjKJWQYAd$q_%we~`c z03_@Tx=u9PtEc{VTxjRYxD8iJ?Y4Gg4Fz~kZ*!vfhR)smR%n&xRPr$ZX&RL;odB$)^68m zyui?YY!D7cR+8=4bH~PR6e5?Y`WzWoBEb1?%mx`?s!IHCw?gj^RzVU74vE|wJXDPi zZEGI&kQ}%83P95A_2oBxEoNnFSOp%S#b1(<1PE*r$|JZfRVf4ctq#{WhAyOTLi+|3 zQvl!p9e+-alaq>^25Le(Qad0k4 zp$h6qf={Q(5G~_t;-6#8B5q39Ai*5F)wy>=0EN33oFvL5iOweeISF@{NJmP83?3ZM zR&8QNBg&lk>`1$5gljtCisK5X94z5pMN9u_`}8^DZp{7LJj+ki%@y)!9xL>^;z`^^Kmr|JUC>L`9Y!Bb*T?^F#`&&l^J_EV(Mbax{9R750 zTVt4ZU=HCd4zKs&I2eou6XLouc)t)oImYT9P=fjrKYx+jz`Z-_25z(GrS8lV(o0Y4 zq}SEbe6vQqmlBFtZLD$Bf_8RiZj;xY9_UjY@h+Fl+CS6lr?(Ys=6fqxH0DeHlA4C^ z)x@r*3rpCwys*wbEiWvO*~8RpVPP+C#y9L`*6Z6{uP-o)E`0cB(v3 zq@cYUpGSMphxSpLqDNi^)H4xn2uYc8fy3}8iHAd{qIlph@cCj zp_|zd;)meUPBj0>roi_F%8r$J*n$PPF+Rt9JW>m}F>hv7qg?8!*|JklSon}nQ9YId z9e!tvFckjA{iWpQ{(q$Xz_}Ijy_n9>YY`v)Ch^hN zV3E)=niwEA3)uS#=hDY{WayE$q_!U*pjVSOz&f);5Lh z*z_m+PfU+a(t^OPfi@n%4~seDd{c2WcUA+~jST<4;L)^Sr`hupq46Ks^f<6-LLnW- zO$7#}_cvXYH=&#pk~8i$>dL3aUpbxYJ6ymyLc_!#Jx6PQ%_X|W+o@$}&||48c79R@ z8_Nx;)(Hz5k*vo}cJR^`f{%$J;H21E;%q>oG+1yKmnynlxV{ua-vu4={C_Op7wsui z^L$)!p;?yN_0hI)5N$rzvtWbTaP=<$wEA~13yc06C~pQP6UvPLA+jKN4kZHLT}_c( z!@LEE60>nc$_=ETAs1Z;;+$9F=&WL)y@C+%B(oqH-JBA6aT_KOx7PEfpq!xhW6-)Q$QjYk#80FIf8l z*4pP=_^;RhDtrB#2@2tF|KFUi_;%kmDn+fGuh@yltp$>+ZZUI=I$xpj^C=Q+jD7-3 z1pFQw9O*{pHO`V^Bd`dOF{Q~Rx4{TNxWl5flACZABpqi#(o3!*Lj!}9Xqh8)ij3A{ z#SxA0SrBNIM&RlsBQP#mUC?AIDS|}Wtu{7IwLjfd#&(ZhE;(!-!_i`Y(EeJf?XSn^ zfhj+%E%R0SY7o=<1mDi4*?xe4FiCOdeFr4|4HSEX6njMVlsLgVAqgSSxjkt*e%^wc zd(K_)4invFP*bs*E8oao;B^r7)eQ;6Ek~1^Gj}{oJBmL6nha25M*=T{$5o2rO5PQ5 zw--&fy-4SuShNCW4Qdop>y_aJx+7A~bSy>R^iKq|o&mGS8g`iXHyQtQ5y}`pxTc<` zooO5Fii z4lp1mI^7bH-RP?L3tEKj(#V8ihZkpR)XL znZSEhYAHW~!tx0ezJVxQ#X@~xxjpt=mJsV4My4D8ZvJeh-((KHvxL zf2ae{&E-;AWg_Jj@cT-Q-_lq4Mh*e^yxw|3%>s-YXp43XQ4CbtfE>#Pgb(-sVnuq)FUof-fB99gfWaIU z$Kbb8LxVXU;BTtbwerBqk`4L!TsO+kMWsY4@M&MxygLb2uq>UQoKg0E*e@e+vYZ!^ zjKHaKoGecok%mub;3G2dnSqSaZhkKl_W45%SHmi zMlrB;B0+=!|EX3p;4+L^t$9os@a=F(TATU@I29}HwJ+<`qc&NOVGM zdTfqStfxR&AJL?w_WYh0)`Ci+M;Xnm@9Yi!r5@8N3Dz7g9vnayedK5jcx<9iLlgAg z;uQBtv>SP}fWg8>)A2fAuKz8^Vd)@6nmgM%h&9xKGE}i2MGet7D%@F)$6_J%8}`xl z7Pzy}Z*x85p%hFlQ5Ft*h;2U$fBul*M$_3?-!m{$jvo40SRZ+lnV&__g*kKIJGdso zne!~pOnoFu9a);L88eF)7Prcj8C#ETANhyXt;LZ?p-W30S#vwPYO0PLx4^l zt`>$Y7zv&mtdrAT^}zog2-G6|J&aF_{?wUK^!G&6VWSwzi|8kXVf|!RBJuLDNKB9* zw_mBB$R`;05rHG!VLM-e*GWedI@bOjYd?u;Bx!RXnx~i&gX;Cu<(-j2MU_6PnWj)S zc%(FACO#0=MhV+Uk~W|b!e~JZR}bbAqWDA@5B4;tlSk?65_u&Gba9sIBtRi-p*s5A zdL0wC@D!9a;^#1N)6W|L)T2exc)Sx6-i`S~z8d9H{iFccT7)s*8fd-;~t5YKo z8o>SkUm@<eX4APRoA18>G^=BL#0}P6s!RKXE@G5g?!u$P2P;PH8BsL*U zL=vL1{B>&GK;lQe+-sP4Y`HZEHFNPkkuP$i${#Q+PN0BIQD|}>J^`_ih=7F%Y9y~r@xG709lYD|x1)D6{w8|Y2hXsY zV0C&0aQFGl&W%!CN%e!We)7(4d1puPOw=m;U2GGg8@%Tu?^>H2 z*(Evzlq*|a>Hsn!^A35(GY5nx)dFvJ~~AGgHrcHsk=*`2*nki znY)*aMAc56N1GE4Ahq00#TOz+XCH4*9Up=3!@OtU@AQ%#s0&REf3T~t8=YnD=0U| zR`W6M7F)wFcDefJMa23FD~Aj$O`;2lL}DyL9o)E?T-J|T^#gC<0iA3}Z#gc|v%|Q+ z%nnYZ9K!`@alv80$Xq`Pd|58(yhE8axjT0#EFojd?A-yvj6&wRS&9 zzxJ&!D{UrM63in3_ro(3`4qy4)U|1Z=qI9Ff}O(n-Y59sg?w>0zLV?!-2KCc?%E$g zYM&v0|Djy}VLk_7ycdAf`sbAWl;Yimza6|t*7#FL?^cU`eoFNIgIU|&p)0=PH=5Mu z^tIx9{e@gKGWEB3N6#PF4{72nT zBL6t~r!D@x1+ZYxntxpn9K&C(f`<63#19k3V&A$eHW^ zR1KE(g9rpF@vHr%1LOnJY(j(J7<(knq6L+aNArS z;?n>^CmFu1XJ-I9`h5N5bm=AC>LnzhO4jIO4o$AmS1Nmo4T8E>0hYpyyubNFrR{ zQ?Kve1(Dn6En(F>U3G%4IyYPuERJI%D=?G~Z(w|UDcc?h6wdpy;s276B;w#y9;(L$ z-=kB(oD4Y+!*MqP*;G3XV)DON`4F7+I9rCY6UT{xgE{e8U2VADI&f7nR%X4i1%_^4}w=+Mc}cSP{&9uo=#y?{Ex)P=fq9vCQLDtvynH! z@MW1d5r%MH=#huciyiiOhD7-5qFQea6MsacPkF|jGfD@#DmSBhF5rw?U6pU+I~EYA z@+!VTZ(_vVo-fcWG@^do9=x15V}#ulG+mbcnlQqkS77jEL(@xKHoy_zIiKxR)>y%% zZr8XPZq$8d;*jkw?98H#yx=iKcP^gyLuwHU#J`EhDdj9Vh?^Uwev4$ACN(W48+cQgV&G}bzaLwHZcfL)w-$qS z$MWx-vxI+xB*?FUtmT3QF6KDOaQZx7o`%gaUg6WF8gvksHK9E~`=@k)E0T*1>L)97H7Y4$G*GC%& ztXu&tdUui)Y)PX`qAt^<85n$R860ET5v1X^Kxa)ncC}Cix8CXd5-7>D>uERv@%V$fQV|pU=@E+-s|Ud9^dhq+Cu)yg@4qEivrEo`25m=A z=6Y{pkU+F27aoy01PiS54U&0qZdCZB>C7LBky!hY)H03)QV5LNx*iYbqdL3L7!@*g z*Zq2iQVmn8L3KBjJNg3UrMFZ0h>q<8_;i~Iogshr58yPdq`l}w&(QA7nk1g{6%Im1 zWG&IUEEK9KN0`s+5eq3sfV!t9s|2KYiJ3g~1ZzD3gkHfPU1-j+3}c77mum;HjtluGoY~_rv$_B z3FE!B{Q)Nhp@DG!_BLwR7%TT*6hk;hoD*d-3CAdxrF?EuQz|uH5Ivc>k~M7in#}XP zx`e^QQu1chjT+n*dS4cs6ZpfEK}00FX&k>N1qTn(KvMVr2}c{Pqn#7Z1IZ6L_w?(1 zh@PeY<9b7Zu-qN1IZ5C#r-IQ;#+C5gwVqeOnMxgdt)(XLNov|_Y=^i+ueI9Q?|(rE z_Cg1yV&h~4+*UZv$BSRp%x=(~fq%T+^g98(CJ>~n#>VQ{uzwQR;9B-J+&VdBnHQIw z?QYzh>tFBwVUN4^I4r3Hu%v23ZBf(=f1VVQ0sia({@jWNn&XeILVDi=I5AieE~PLs zb!duAxJsq?x)xCBM5iz+o#|^GmB_B79|-3{kEuJ?_~m|kSjs5q`nS!cJ+cXL=dI#c z44HJAE%QqZdVy;6vIAse7DoRx3ss`N?%1<$C6;FsGH)AI2NOQljlhsC1j*b76#BUXr`(hw+aT9i15E|)1&b+!h34+!?C?5(!pb-l z)3KqWV2y!eAA8E81(RMeyYmQwjD|rqe-;sBHW-n!IEyT~Wj17!(#?qAy*>?*9o}DDgkB9_#0ne?|+1ug8&E zVU^J7%Ks=aqzn^gRc@BNol3|LI+nAh7d|~^;>!cig)XvQ0@12qisi0A_=v`*&OTu|J%ro$sR)u3kHr&(bEO*1X_>SZ!ED?E+ZQ+28T zdsYYrS4gJz0J&Z)*8&{0NYg@Zc6)-(QVK8~tpYR?dd)D7d@77_)MP;Fd+xQvQgUJb<=pDQIX1z#S*+7muut+SPcO-r% z20bu}DSWli3d`LV@wugWmE*n(@gHtdzg_f8=4HT7Fdm||tHx_M3;?W_IBD5EMVP?r z%_iXD1kRHA1&iCZI16mj{dcRgE+IUN`g?xKEUtwEkMf}F;MRtZ0F6=}$#gxq4O8Ih z23G}BfJ#}VL5XLxV$1y6ie-5aXNk z>(asm-T-55VFIupE%I$)BKzuM4mCI~ zu<}>GTs-KUmA;b+uF97=ua+jZ6%SgNn0V8~4uJ&Lw%_jJj22cVuZ_JjYF6ogyDD6i zar5TR;;O)<-SVnX2hbLfc0X_;aw==?KH%D|Z$8_y)r_SE#n{TGef83%A! z7yT1OLSJf{E`MK_|CLp-3&^Uqy6ABhU8aj((na^PsE;msLKk^iC3q8YkqD2qPOMdNhQg)CaHi-zfAvxg?{Zq!=#Vq~_#^FcMi-wU-kp6-j}HT$lGvX6s8R{F-rdg=s; z3_^C?_(5MV4UWmTF`ET<@{N_&8!)MXK8YX2MZGbg=^MlN#sce&B>l!0Z|d_t(#Og7 zWBO>Ufrgf3WR6H)atHS165>Xi2KLQP+*EuPc9#2iJK^szZ#(>*Ua}Lm#bO3Ncl$S2 z0R|+$_d9ER+*q?K)Jn#N<5r`E*sC~SdPWSAZM3MHKiq>Avgd|Qam-7aO zifu9@U&&=qkPsVxrsPlxzl6r8_hJ5@i5i4f*39hAQ2^=DYD-8Iz{GZU*xSy#l7Ya$%{;^GltdR|AzF^VQKED9-9=WZ162p@WWqyi zDa&;rdqzeD)W~q{E4Y!7-V?xHs2c~!uVn8KYI;*UD6u3=T!J%#pnu#xdS88T80gR4 zxFzpdTcn8a)Gy!-IC1LHA}40t=`E50RqH*$Y?3u``%FbrJdCv|0i zS?Xhd81=C~jJmsmOtFs}>)nVBN8klFSnU1w2Ew3}&g6fm!^_H^!C$1j-c@8lJ1;G^=2aOE>mnU?8+YMQ-g&Wj))7cqLoE$?8kT;c3l1ZV%d@B}2j*06~=HLt5Z)Y&iMGWRSA7?Ey zxqpP)Il}=xKU?=(+W|d43_4aF)LBbT-}X4R4TLG;`V`QKvjRgC{0?5qXUGQ!=_(+w zQ4oownWQSdB@ zE!ZUXd*;vgGQK8ZP?%35z6N|U9A5)&iTE0D%Xf{;pBZ2CGvjN1W_-=h5?LVeHTV8U z0J|lm&o=RhE;yfZHUe#apG%UL&1dF{^N+X=d!Q0%qtPr9Xv5!XYkO*E*w@y9HdCd# z1lpA0F$$vsZCIjyFE8+*agN$QlN9R?YWCW%J9U=D)>xLZZ?6lRsI&i=w;vZRS5 z0wX#2tOOQo`Fw9@`G76(Jvb( zM7g*V&rI;xC^KiS0qJA%t^AA(SrvXBJ=!2yO{)ruehp}Q1@gN$qJ#S`D$BUIq??**O9j89W9~nO>dNwNqow=fB;x#j|N{}b|xmtIQUaEmuDzn#9FGppj z$fhXEaN}Zb99V2vNim0$n^?;{1bnka;zD#;_-PpZpx+*fS)7``Ls?>Kz|^?A!HL6PB{;hfHYXaI=1)&*|H9e)EfD;-sSban^_=QMBrTD&pAlK z*(m#GAe@&-Z+SFC$$$}R*ijUz=$xOIeegZ?LvE6qSsk3?G4M`c1U#1$9)<2*_3s02 zW+r}ilrPxa&XSm> z1}`$6|2U&vAut4l6@2!x0J&{H-Ls&O{e^}wU-5VOxGq7`!7(EcToRp&|q zM9#p~jYy?npKQ9caTnB8ge-ZHJ3?-8TZ}WfnRWBAMTaIreKFeF?=VH67#c(n*e10D zBlXC|ym$$W5`>B@OQWhfr3Y^UR#9Vu;6*#qMDQAvX}OMMP~Dy<_BNSO7)v?gWCm%b za1GMbmj|M8R@fyQPT_FVg8pbdmGrq_0%#NO&jD+NZ3Lb>Dm5i4f6A|P{*;vYj$n&1WaGrM|r)@ii{rSNIkT z;g4C>a25O*=n75q{JmNA9t!X~#kFiB>kEF)&YFa`UgKM@voNc&X5p0CS$EVd9B5Xp z)GxGkEu&}Ita?`eMuR^5w%)(Frnoe;*sOX;KTKS3yIHlA-}Q6!zaW2h*3z2diJ|Lf zXFXN3@B*`{H1>IhS>@Glw_Pw`cGg2R#TSGwGOG%7S^R=zvue8iy^~p$Z+&0bPDCC# zeC(n{{Sy2c+2rgo?guz>CQ^070Sb|Y`(x@G!#}qD3iL0AX?YRpV~$P~vO!(?@s7rp z?`K%hy!~0yzEiiKEbUuA?g+QvJGT9uAN_*%9nwC`X^wx*Opf3BaYnfP+IcbKpZ`nR z|I;^wPl|3oU)r~Ryx7Zz&y3ji&-x|pkCyhcb^FI};rOi|*M!@Tk8S_e4_kweYuRt& z&{E9#a+^H_x{d9Ph{Zs!Yxn`BC3Ek+@Z5LZYGkfo{4w?)eJ32nV;~Ov@Ekn&BI=kp zXZFR^1`2`u<^qD5n~|d=(AEfC3#0ZLFdtZHHd659hMAarbrSMd;qD?F_+1MlI!?_- z98)#flvADBZ}Ga|1dwnPX6mn6|M*0YA6%XHx5kR;iDauJlaeu??`jBB>w(bSasp~E%AFJ=gbQo|` zug;%>31S-A&^CA(PrV-ZON~2t>Sr+zIqi}5)f3&(s+su6LB7iaw-^}I97oR(bfIL9 z8{VHQVo#&`lJ5u&Jrz1LP9=wIx0rBTkp}9}zGgC@_54OZwUPBLC43;l`3D+B zl|ZdDEzXO~4Hc&OEJe-~OrFu=I7SoBF9KtGkTj2m zTn{kwGJF@f^;_qEar=(PmmnhI>Lep@xd(SVcmjDy17Gi2${lO&|8I3I9fPmA{kGyP zPA;-xAP+`v?`@v=k3)FRNR|kS9;ksvoSpz~Gg^>@{R`L9AHm3T`@zSs&E4-?>#b|d zAzc_?k%=UYo8654%KX@iJo&JBnE)n_0EE2eBJ0K2!@EP?6bng1fYMZStTZj#X)cSi z12>Jkmfnj#!?S>!sk@PdtjDGLA`)!6p!m^Hy-tQUlpLoo!NFdU4_H~m6GQWeH97ZU|WFNPuf`Nf$BYmy9fVLu(5iW_o?0i1phw#I@8)0?2mVU}| zOaSv)Ol-QoF`UmM*@)i<^h&sc_{LK=2!d0){zBB&?Rf&YVu<&d0}nyJ$WOJ*lx~=V z&K$D9T{r5;5fsGn%W?T)4nKmkyULgK_2BDhoAQa`6PzEw8FqEf3F0D#n7L^_tV!H_ zR5yaCjS=M#Cs=oShN28jBKQjEIY9GF82Xvkk z;=EO@a{ROdz>}{h!_U+4O$v9Y&*dwEJJzem@wHlbNrZYtm$K+{cQZN?T`IU9b}I4{ z@mh~&TqjbX`Hx)d={uYq@jtUKtd97Zc@ELPHFTK~KQ#safH6}+Ajrt!#y#HsKEYK| zRzQ%a_XZ>WI{}&~t0zEeIB@5x__e^2u39vk&XrGrlQ12}e91vwo_&fM3YixiO7oFw z=DYa|jDFCOsT5{@f*POj&{DtcM(xkIiEfh-e}uYXI@f;_d_!mz`XQp?zEdwIX!imd zVj*kU&A5C+!Gdv&Cvpjq<=Ez}Oea*)DK6R(iqu*7+9J?Z|6Q%X`&H0G1g`cs4c|nP zT}=KXg0|3dl+s-`5IlM!2DFtuL*UM;4Z^1h zF|@)PwU)r$*#;i$B;-nCs$I)Qz><<}n2x{QdL}ln@FtuhKl3oe!5gTuFD5(T_02oe zNg6np*B&W1+x?r9lqOEP+4sjJw>*M0Tc7Cw0g~4I(~mgae$SC4H)ss;@6yN_Zhyj& zP)CiQ>%K=*bt6)+zF6SM1Z)S2+V_4mK!e+2!KmRU_!D#g9A-5DjJ{W!iE&`+IN!b( zGI-uRvWX-fKdjjAO(G)F(6YsxmTZ{F05!UcNVO}!Xd=~0KY~;{heM5#YHu9X-gPZ5 z(YI6e#jw$oGdQ&+v2HKF&hIr5Yac~h+Rv|Q&yq0=?b11p%LUq?|HpLv>VGhXuGSbL z`xTd3W6&teF^GTmi3UB6(4*l#qrXJi?_-FBt=sP_*(1V~R^t=&G(hX`LcY(*BN6^! z*E0M9`5UpZ)pwm`Hitjc5G@b{7g+DrPbQwF=UK!ju)EP5{5L$0i`%k!WZZTJOKyE@ ztJrj0G6oiR9}5}<;Y)f`zvYU=8k{nuZ26m~ZqdC?x5fkTgO|y8-1^D-&U!p~d;(XG z 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

    Xk1BItvuE|wg+z-v~}6-Q)BYFK_Ic6kE1D>lOy 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®v31=`x;!kBssn9;ffGDIgZGxr3%mC`fx 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

    PGoC-r}S5vZR$al>r4|2*mY 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 o`K#PhuD>0%^2AGW?O!xa=Wky5`0u#9 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

    ?zc^D!kAP zi62M8j6+A~o@bpgR_GiPx=yl(D54;BjK@sY$wydud$Mes8)8swt0I8k_?rm_9okO7 z>tgsw7Cd0#?J_6PP?VZn4-Tjq{In^wRDUJn6$M5`#`|kpU6097NX;hZ%LIPDSegWVql6IdCg_xIRj|V?v?@{+mNz{k?5bjac zqT*&?rU`y>*zu@`jT8YatBcS8{xeTP@#Ls&aZZ}g@E2`H8O!xM5Fk+h!0cks*q6`T z#0uDfui3zWtF3w+|3w5Ee5Ur*V1mW7g){%W&r4JtO&2rl_y2s~7vUGg< z3A}s(JWvYtkQI|WLaJ+FU{A%$99Z-l>wJZnX0fNNhT%2ltRk0XBHfKA2Y|L6OgxaF z0u=H{iA8QUqP=Rl6r8j%kTF2u2}_(Z{zISAqkI{cvEm0yUEOnWA)=m*%fv*{6srXh zq)xEt@z{X=LZ#i3=G+6%s4tl5{Ldm9WvO0^#E7jwf9mx2T&Y`XK6l$<$5#V_v_HKV ztymOqt~nr?p-QwR#q%ASfl@u~R|9x0)YN*%O@7Z<#82P(n0cDiULbKDwWwu8s#KC> zrVj3)HL{YN=;o?Rp_4gl4!t|4G0;6}>|kxs9EetN8@b8@OINcUFNPJ?8V0*$g#lYg z1|Aroh)F{ySI5A?)Ed?-N)1T!9Nyvs8qbQn$L-kgoLVVp12aDIeW^ypXkXp>v8?!( zt(R4a;@TT$)k)pG^h4btDAoKH8Wb635>%w6poR?t(==SjUg`7@?3yYwUj7=$ zL81P-nVO&xKo-;)OF`g&(FwNmDhF%U(o|KvG~V|oMSD@auPJ5LpN-KHAvNTS*Y6EZ z;gTVg9sz#;Q{vB9G1RDTlx7?xi1EnhaM-S`eo0x2zp zN{k{|!Qxyw)Bai^=tQ5k<5+aEnE1gKyd^*L;D-+vn7}#1XSUoVu098=qyiVeMEi^* zoROxjbz|<`5rqI#tzg@@h5C})4k00=W}~)Hk5xBJ>-c-zekD&X2%&rAe4S`D-{KC> z(4ZSKj>C_Oi(YgOOvZ4OFQQ-8^@lj8zVD~PoA`mHipk{erVCnwaT+P3>4V{hI|Ss3 zu!mIp(wlh+@15jLzF_CGz;LLYITh}S(;ZG;+XYvV`bjt&fex%*l;P!kTt5x4pmG;{ zp|t>Pb|!gLTH;{CzqaX&cp6#za0ItD+4|8TaoBxBG&sEyGkaVw4z8ad9PwG?7A6- zU$ChnGcrZo1(5RI&r7T?dc+9AtW`a%{-al52NEohU2-EA><{ZRC&n?HyJI}N+sqS5 zI9M*FXgWs2(d@H`BEAb1(8) zJ?p#K#7;s~9Fnrv1TtBMe1gI*4V~#XEeeCVE&$9NkFeo+y zD!OY44a>g>1V8MbWaRyd7fwSQPcA_FCd1B(oovLmz_@HFJy`Xu2yzF{#>!G9);*vN zgYRKdv_=43Fz%=Jg+2<)mRyD;iF)6QM3Gr>gCpel+gu$Y3EW3D^r{_|)U2-53)OHcVWXx$V3OnC zNwW#wlaN$%_Yy{!0y~9gf#U6a19#CWw3~o^@WfUp`)dnDfGhBmy7`~QVU?{QS5#>} z$Ko+FzVLhu14x|8n|yLYUfSF#MgtUl7xp2#Ijigd!SA~8ma!|fbR4X6-UHQEES;QF z56&$Jhm}0~iVAo4eSTb7dRmE=NBjD2(rMc%DRf@$^69w*0|M!YI34nl6{g>Md5%BN zH|OhN91{77y#u-i25DJ`xBhsSa(coV7+`WVJaQP|ev@$ghR;HL1&c z6I8$v`3U-~1oNUwvu}&q8cku=3#|oPcRO>EX5AGq@zsvcG71&g81Jnc?fF0ZnwwcJ zTv7HHtKh;YNu*6j{p7wJQbaaSq}5?_>!dE-g?J71#&5P>N*<1OdFFl=c9>UyOdU+E-q0Qw)lG&^GU;9KL5uEx}+{6 zT@(@Z7M)L=!+EnaqY3fMsU+)waE0Pv{S1ysP5bS8xXoF@*Sj8asgPs5Rj3UMa7;1Y z+XPK3M(8qZydS^Kp8R65t3HD>w>sUhi?lhJx!=Q=v5G6iRDl-Hut}v=k_NTG=SXL* z%ge=Y4|sJa$k)l?xPYrpR?XW#;o518&gyBI`?TgqTFV8eg%B?Qxegm~A1sNMRJjUx z$npib+mZ*O31i}{CgFqzv&o9=MUr^!5Z&-^AVHl}9I&q!Va`8fI5tci=H+EhU(H{m zjZkGk>&je7jNfI6VyWR0P^c{r#2nATlp9Cxb^8bk$eZ!bku~0d^;k)8h)?f2viN5x zUz(rlgp+iQi%<#N<1pyARdz9S&(ik#RRd|?>ug|h*51R=vy!_=lK6aFgjBa>AMn-H z$$HK9X&pe8Sqj6#co>rHP=+Rv)o3P-`Cp6UWf|Cd8YmS95zfW~eEi58HUwph;^w}~ z2$aXL2=nsSgcbUc>)!LD>CTD*zxj!VX3>M1hd&r8&^i|_b?aXvhX7!{~eM$M$ z5NNfRWJYs|A*PfBblTzgXdD5JlWJ6gV!;~58Ou5!J`Js_ocj1uL+ZD*BV{!eC4peB zVXYQgj#q*I_-7z>eMCi&P$6P?Z>j|a&o9EjcO30&rtmNjIoAsx6`%4kg}&bA$BB6@ zn0{xDat;Sv)gR~v(|dsmnIhnSa%zDO88c5Q!pt>ezQsjHpBErFZU!%sg11NJiu=j} z-bpUP%qy(>!R)foQvwA)~ERN^|T{kLQb_(uH;f)+;G2y;8nUDjid%Yx_SvBslN;9KVuVB zh?7&{g5bviYn+;OFmEXR`>bmhK@eD!Q{KZneDHwfFLzCdb#L3;Po29!xI0|e5ikhb zPA+WRjVYYXqKSv$g3h4-91!xQKr}Q<Tl=#&`mOnEN!_XyfEw4kfgqM-%>)gsbLWJWwQWIcyKBYu$!K`#*kw_5K2Y zbZiUonJI>+run}}CZ5>7Y@p?Z>luVSuMyLR7C&<|c&+m!s-kaNUhb@%Bj(g~gV%-z zT^J|}3XO6RLJ1T;3frtGW+s*0KkdnZ2(Et`S+hL=A!w z6ICEyI!DBY%o}A4?+)0TD-0tY@RaIyk_#Z~|g7yPSd&&}qGCM(%v ze1=5bx`NIBxPid&@zdg76vT7@;M2$Nr+?7j)joAENL_RjsT`F zkqSyHKslqA$B+TQ5Iil`{S^O-!HF4H2~EbBy8h(=DC#7F!NsZh47og!pB&1bOB(un zHRa`u+`$W$3d8Of^Vw(OIDI8-?}_^cZK7n;nwcmgSgYzL%apfimZe*`AFC*>l&a8H z^S|5$0;Zv(fS%VBuhzpNUKmgO$Y=JqYo#wE`0757k-X4JNaAo#QV=HC~Y@WdfVy-rx%EDX|6TR1rGIZ-haGwb^Enr#0dW9 zQ|ZZZ7|Mh7)W6uYTpZ{{f_RPII6+6?Jn8kNG8u#LOJCR2$&CJY#0qy_qH->VNawXu z{xuy?f>fmGhq0PULg$l;7od#jZBTMr?=9;AvfO~?ogiqs=A>HOF`qms4;E}fr`KfY zGh?-mFuJ=w0%Q@s0;AP0wp$p+~@!WJm8g1`wxI-uR zW*FP+a28wASZ@pkj2=nE_1F7{tFq!N?D!GUom>t+VCTfQjX%S@Q7SpTk(w`XE$K4B zm8YbA8x^q&;|dEJQ6l34$h!Vic%Dvaf>1i@xIq5o!Tyis3lhXBoiw=n71_|hA32nt zQMwRRr%wmO5m^cq_SRi5!yncw^!LnXmTrO z-P5ENYpDW-d}Dq+J4Ow2D+9+TZ$d^`eQP#V9YlR3iJs8sNWX7$O+X7#eZ7R|&;y`< zmX-Y%Phs~Z+nCEWq2S<2YNvxPdzED@_~6^kjoLt6os*TNw2SsP7XoxBd1O@s5_YYG zd=7MuUui^;L&%%hO&F<#UE1^abg;mmyJIC*j);o*s^-!Le7+wRLxwG3vI|pGqr0=8 z>S+keckko9V-Z6OMv%OTHJX9s($@n`f~U4ao=>hbhNg&|2eWM<+3o)T;E3IkKuEn3 zpW1-3*Njs>k%o^&Q>_S&Y##up{}o-o=Ek^E-4zl6q%?w5ML=6UEuC8bkU@}2w(kG1 zi+^B9q^zS=DrcZDTxPwDH(7u4b2WdXrTpa4eQXcw{IH6wRHbDptae5xZ1wvWAlLV- z*=sK@W=A3rh>!e1?>p6nvlMz!(WiEOr6=Rs+=5>piCkS#o(ExL*Jpp4FjJ!up4f)3}tAnXrPsgZ`}+n(#1avDw#@!5YLv7k@6u zg59rM$`9IK!4wAHtv9Zyr$exGOmlIbp|7SpE)PYVenZt2u|nc!{)1Rb!c!S6!o5RL z`Snw4e9oz&nQa#vm1QJk8wgyvHjOE<=AN1zxLZ(DuyDHaVV-Y4Q`Gv3$rgUlYD(+p zyOb86j=Zou+0N_V3pw+#^4E68auT+sj2n8NsVCvW$-ll%zn9rv3{V0_4rS?)-}aDMf>$7{ddKu3>z4LUuXD1hMS1j5@CHk4I>f18$C{vh4+ znxmQMR_R%tz*cY2k7&x|a(M#Z4fl$qonV??1P>o+4kuym&4S&j(-`ldW6A@Gy`yYB zHSV{c1AX+XoS?L)j^1Y+0ovM3k`{}AY)vN^Y5Ka>8#MVV(;h0isntSFArm~-#m8+i ziAt8zQ5aFm29|Zvy?f=)4#6(5wZfn^R<_52y=NR2&DF=<%rZKzg^4cXDODQLM3lOE z8u}+B0_|k!3U{F-EjcI^%`e9iEY4D)hY`j2>Yw)Qr%fJo>}R_LMMDt?G7sNJv67d& z2g~|aAFSJ8 z>TV8$_o4>cgv8h*TT{wVuoP#Bn|j&nL^h4ww09w~`uT1UoLx;*Wb~W&3pT5!NuxI< zPjn2RQ$oeZ)M?N9zc78iH1a0H867!U3rOD9|{V=wK240M33dS|usr!bXPn3(muu64k(P7pkcA7$O9nK$sY3GckU#MunE6QG7R9wUD z(O~wYZznP8XL0u)XHKUm|CnVA#ZeSvx~JI9BMBwr%D_FNW#kQj)dz>@r+tS5bJ|P%k#F z*Y7WI!?5oUT}MDNcKl?7pwb0 zkc#9~qT6d%C<~6--2E!YyzU3+zjr0{Z8OscB?;ocM8c?IXXxCI!T_|UqH}iWWs7%H2!MnmKD4?89z^&MzV9JM68;hTdtGROE_ZtbcBwSK zfqn8L??_*f;s|!a!_^_B`a=slgmTJbCi@e1H@Hn5v?*7AYf?K{m`JgQ(bKKFrZTqx zmg7huCiDW1^GKcy`7(f;cfQ%L)~z8h(qU7&bk zYyTHky`IVA#WWivY88YRE+l09-)CKEFGvPL5x^(z4$fz}T?@z|Q8(LVpv)elJXU%x zexNu~PW*4>RM^fkW+`kvg}8998hxGVS!8G}*}B88Te`>$M!$HRqgs_18I?m?6yxMy zs28>PZ;-hB&@=+(BO31L5XJ+j7K9Jq+Z~*R>1JP z{*)E4Q%l-{2!`AGk!Mo(_RVyAErXr}Gzz)G%z-te46$I7xSnHk8>i&qA2Yg78ToR6 zlWYBNGLUCw94Aw5&T>NWL}VamG*~mTqcr!xU}*1%oTc{nfl-B0Sq~>G=8brWDXH(n;)3BhEgS*{B7U z#U&tynv(b#MMQ@=YDd2kW&gGTk$ukz*kp=X%2vLUNq6km6*jZWg_nsCt>f+j{gR-# za8eX7H9c#nb+!_P#+W@a547uIg~y9a-kd){R39*XWLB#yPy6JhBkaE%EhQ@*4H9?Z zyLQ$5G#Yb*K7B$2j&6hPjsm$We998G_|IyyI>*`5@8yrUvrg*m#%n6RckGTxGcmbC z;RbQBX7wNRGWt$sa*>`!qd&qy1P@5GE}EFZur6`5r<|gb54y`dj6xaK6kH%~h8ASA zS9#lzPK&HX9ceNIPyT{0N3;jP0m!Bl|rHMI_UJ*`P7B7 zT$OK;y4wGl;IMn;Qqi#LG%%zn_|B=gqW?Au8U^gRen1yha^`62mSB0D`*%G1`?WoV z8l`0DsY^#8iyMk=nRX^@C<+pkCN_e6+ogkpNSYqzZ6So815np}h0Q~)2Mq$NS;i9D zNUk@Otx{Cx>%vK7!PogL987%7tL2sMYKR~c3>U7xR*-wUV%EUhP_m`S10x;5G8EWO zpLPQu5^1J=D40`({iVk`0^Q6zl-k-9(XjS@A;W}=B0rOSdPk{Jf(u0bigNZ|UcKaO zS=c*VJ}oTr^?-|!#caE`Kv0b~9HEsap+aG{aOxTBI#{e=HzcbLn7e#2$W$g?RgA!l ze=ykQAZ0E7lZirC^GEUN@ofFl6n&guu***^WYFxR_d#=x@cx6XToGeBpd&wIL$_My zt9XjjoXG7pv2}dEX!Q+KE_K*Fg2o8rc1m3MH_wXZvQ?Q(g|9NJJ>Nv7lk{Ao^}~)! z>n~y&WG9bJNxaeTeQ1y`BCM4<)SQ~Ps573JiFfmims&`LSX=iCXmgtrSzq z?)JF5a4)XQQ3knD>!_-e1-!)Xne-jqiH6ONrDyXZsG05>#dLzMxrNk~oU<@}Mbs2* zf$zb*3#tCP?V?$vdNE&oCqnd2br2x|mh>RpZtZ)a%~P0xB;?-==PVxgm@;`2doaG+ zcrYJ4Hks~r4#LrGAgVko`P{q9wadSY}i{Z;5HZ4zCr& zJ)~Niu-!hv_PCzZPap((a28M3{JquCSOxr6hT@kt-nz~KadRLLE2u{XkmiS9PX$1a z)DDi212~0w)HC*}QnDyYnmo~tWDiCkcJ?klHe=8>n+uauo0r6otaETQmsQPP4h}ek zIXwQvYb>(k-|Ks9Q-MmlSu|-Sx3)U+5i61ua5ubD+hF`!tH?!0qw={RRU-nb2gMK0 zOqHTi=fdH9yD=w>iMWsC!jW)l2Azs~6D)`(;-G>XV}?nhEfp9wHrGys$0u&sZ$~dE z-0!ah%Gyq#P2(A1yly3ni`Rz-=@X<@P`-3p9R}`#^>3lx#DN#&qR79Q9>}oZEq+uB zX-!XJEoPl@(@GQ_+ezEO@|CFO}fNI>n@$ zsNW$QDtP86Wq)1lQNoFRhd?=y7FLf8vl?me{2ZQOAq%qUzW@U&^!gOBtuIr*(e)cr zxxkMy-ZuO@Jo!<*U|&vp4h4zX!rRhLJ&-SGgDpFJ$XU7$HIsgvO~{>&*Cw(KupygY zu6ri0l+!!ot`#o6CCrAZ0L6}KefA4aSO#PHM5;zuc*5Z4IJ$;sZ!U{i&WFDVI__Ua zB5*r$lp|T*%vy(!=*jtikji zm%HDn;VvG)qkJV?VQIrB6gspYB=d4K%cqpp5WWg#B*0$5?Mz{7Nz`_+g}B>dO>+bb zhqc`{##6T}3^dIY=71cUtHQ@+Oii<|gzClO=MY96wMsmf8*M*{#HCx5>DSGp?iWM` zgGo_fE8lCaJhE97!zTA!LBp~mN;TFpHI{-p&F62xmR9!Z6*~QzS1<-q?O;xwNrfVePxBTMb3>q3Dvxs~i#fUA*likO1S^EYNjugT{6c6^G_0)Y-F%OnwvQnGv z_$%lz#mVCwDtEgLLM3KR6mr4YU|QlCRr(@#O!&MLr}v)t4$6umRn$KHFHY721j**z z^^n8yis5*6rcxAhShJq&!b)-HaY!o^gv+hU~c&+OI8X=~;!UxN+5~w-9QlkCCaF;mUl>4hkZG*WW?$*#&K7LG79HFdz6`BJRiI}nwtjDMmoE<8 zkvqdJ^M8vo-gfCP^{)2ZZa*1A9QPdc<9ER5#6;v3Mym;Q`v8wGvWen==6HSu(dCG! zECS^N;^gg}8WD#)3q}ce91fdX$E(S4Qpi!~$sNqcC{C1%2>Lu7`X3-qNx+{EE&h05 z8qxMZP?w$Ax4={gmzu7JdHVvBoUqRHKd3S+XaO%!Bv5FvaVIq%87p~a^7ajv{fCX5 zyU+*q&LL+$T#)<%OlPyu+Hft^qz!=>%H_gcncZnzbFze~q+H&FCndRK#NJZKa+n-1 z3EtzvlQpmyFWeKD0Sng|vN&Tx&OlBT$%v|!0I)23CHYaU`~k_;5bn@^Y$3f`WZ`}I zSJlIFZBaSl+|fE|dQ`nWI(v4sf~oW%Ov1CcDIMIVEo*>6MB#Dx2>=7rc9Qg}Gqe7o zOTY`qo;z5zAYW;fc)qY5wGz;Y5g3I0Ll*W0a`FjeC^3lDbV1WVdwf<1&7k{aRQt=K z4O!~Ra}8}17I$xE4WsfnNS2^1sSHjJBt@lvOSrzlr~xzYD!F334wK78>dUs91;2zxt*QsP-)3~*K)7Z}=v#6FF(R_<6=rVcv+9e1LAx#`7JOH$wcfL$;o z`1Td5?XkH^JcQELSSip@i(uf-Z&*nETYTQ04AiKmAM=tiI@g^ zL0=HfbRM|f8PDOd%D7iii7hWjg}9yW2(WJmG0`RuaMfHkTK>0YUAm_LR$cuCtaOHf zS6UPVJg|>wEQ8gTh-JZcr>jL0*xc}->Gnq$s(c6C(5*BL6jKBF?LD_h5q#q!Q*geb zy8=rn)~307#`nA2Fs1h(oK+=6$Y+Nb`Yj)p#DLszHI)70AVGNWV{1(iB5_tz!7EvR zcddx_MiRXC2CxdZYeWA19U7S!8PVrgu)x$bC_+>^1cbFR)Ex;XnfNLv{B047cZU%) zhurv4yzr;rK%?-$-IuLa_NB!l>D?6%1xz6Yf-7GQsCIg!Vk_ukFij=9?p4V?;9sB- zHk(qNZuGBy_C21D0TZiLn07IlapPmetw-9-I20xQPKo>5^CB_f7)vM4_IaDW->O*3 z<(;I3QFBNUSa+2qnUIsaVecIgls3^ON|$OKJ0<+n&a`wyUa?(F=7khG7;n}d?1tX! zL(U)8Ymi+cP1nBY)(5Lxw_1fKe_`Yn-NXB`-KuD1Ti@-9Pe`@xtuN1Q=pc`WnO0w6 zd`T8H;;egc=&o2%Rvc~k#uSZ3;=Z}TT=DA_z??S^X5ST{VbLxiqw7qv@I6Z)hxS-S z1WYEr?T!wKw~OA85Qn$5X&xB*>^}njgZVMF*G z3RE0oU2XbtA$J23|Mv9{QF}aY^S-jHn+AG;1s#U&7fxL=RSPZ6Dvy*5_{J_#mq0#HVik3r9$#Y&+OVxt`>|Q#CXq7u&a)( z&zQxYx&`Jvt|>50uG2Fa76lZWz54QN9MGp(Rs1b+W@A^<;Hp0V_#ALZ`3K}S)Jq?< zi5=qYsqb!PTrVlbrp=VHwl7zMG@k>xb-(FsA-h}&@Dku4+VEr08_cetux&z{xC_%`E;M7T01^o379BR6gZQmAjo}fo|=0AyaNZt6o#yTbJ+}f=tC=$0E9B;4ccW&avZ&6?-%AclozfI+v6VqjJbQ zpzaNKgV{=A+wY|lWHYPEM?wvH0?-{f)vglrT@6_|tYs55$pR=-D&nGeMS?EfhvvR6 zrKZN1F~`AH`djwR5c1w~CllyMrL}{AK^dV=CAI7SPwL!1a=%df8S1K4477zR3f#V5 zpYlY%RM~G0$^htzF|`ni{RmPN7YzPTH@XzJ)4)TX%$gW94j_F(z~UC>PvYJM!BiOT z$n+(gb1F2Cr6Mv-QpqQvPk;vqZ!(WA__x2h8KoswBCMS4so>fU8k`XESrSrMm2b8ga5GfF|ah$i=SltgJof)7=( zU#jLZy@nV!L=9elXHUKH#TldfcCwBI zN~M2)5|KL7t1T*%w83ETzuCumP9i$aBPgj0j5x4wfp~anigPiIw*bup0_%n?8LO_X3salon?UFC@nin#i2xTbx@DBoB+8moBI)+I`k45nj zk{fZQZ8e+T?32`el!2{)f(H5IbC)pw!Fq;)Jdt><{+8Y8wYTnu6t!M5jFg>2A}rhslgGioo4(VPrBoEX_L#y4w)g zox}ri#H4sjC>q%LnF|=*=-AQzNjW;xKQoNonIpHkE#KeGCRKQhKINvZwBfzM?Z4lk zPStlLfons@=tVN;LDuXikj$6h@pq55W?W(`9%7>!59R8qu3g+nSfNsV!mI{YT%wVw zqEQtJ>$DA*Y6Mh9OMd?~O-;Tlxi6*|=W2!7j?${+9^(r+Jy~D*D z2)#tz82&!ENhH{fr@q!p4%zwIBr%stOxQ9r42j!r8-%-?<~csXZ9c9CMKzDZL0Q%0 zt!3yvhd?+mUi#YJn~U*IyGlWCXj1O_Lh9+BN?N5i7OD>>xszW36r~yKm^GZ9((Bhz zju$c+ZN)!Q$nnpb2;Ih?4YnnlFRbVwOkCO2t1u}ddr-0!POx_#>)M2*G?VH#u#%0G9i8(Qqo4TNQEw<L(mDls>BTo4K>Ao2Fb=2Q zeC8h|@0JSCbiS19D;mJqbxZvWI7BKAEb_gDvd0^T^dg2lD3t%7K!iq&k1}qza1X9A zm*K@=yqt3EchPP5qL=jZFg1Z8=l&pB!ICk5cp+Xj6fe=0H;6(n!?__nzXCK59&5>Sp7T#a$-nn(me$brS)?t>P8GO2 zo!0R@wCyld7MnuCb<@xlibuxNYd7S5e+DyNVp$-|T`-I{npp%rou5GAvcXq?C%Wu} zv4Fjz=d6;pk}o@W-Ohda;x*u2DEPHAek6LxK`7dmOc1M(LEPGH2c(72fjV;Ns0L@Xi3 zsvz91s8SD7R!;4)%^C`DwhvadftH#5bNwUey5Y2JA6=2!qX52c7y$zf&8Yl|$*@m! z3l7@(+W`%iZ`Uz-WX0GDYPnhVzc*L0+9Ka;oO<&Z--6tbFGIZVQ8sX0j_)kRrGc2) zpnHgd9qb^v+MVotJB>c=jIy zx!R+WU?ePAD#DW>S}jD%?K*JPF}=|1wudrh{VIXb^Ka25jzy8rF{t8Evo`FV~o`0g^X_jg}1Z5uMq6p9=3TU^S&(5dY;m33`P$L2Z zCTvSglZ@_R&WV#50450F``WYy-=f2+YFq!^00*x{pr0L#By?E{i^d;0 zeF#7nJ*9upK|Z7=#arWailiW?7Y~5omjAT{A%pN9VUPFMN$<{YR zE~Wxwpjb)DNotXi)742anOI3xJl>I?3j&Qda8c4tqdB-oSn{_xL4_qK?0tSi_Y_;| zozIaSCmrMD3bJ>z{nRzfClg);MIPRCbv|$?8{?QVIWqy?H*yG7#sSeI0rSf;+_0+X zBDxL7xmy)IJz`QyM2`WmHiz(Z_0UGN7c`*svZf5AFRG+w?O@xw@Of4t?@m54S{ZRT z7Aut?!$1j-eP5l2Vyun+b?BzSBetAmLvD>TLG`cf%+*0fbKUn=%80y{-X_$w!=lrk zYfsrooG17$yQ5TN@@E(eTSj%&QBfk5|FD_w*Z@WOh@Ii{2*ExRhmdNbz`YVDpJ~Ni zsU$+tO+S#9fP3UAB$=f>TDsf$FL4*Q$&q7qO8`=yoFSde9ieIFeZbbyglld)SI=F@ ztTpu86;zMNSXOjl2Ux`yntnDWZ^e+xrFYOGc23};SR(iP1>^>9K3$f&RQcxPZ_p%H zbQ&drb<{^b+v;y;YQXMaBJ*jT#hXO@m5ADWUVDulrxY_9!A;d(z=`N>uF?@2*(>c# za(St;_Fif*iD}PnNutP%d({yZ_k#Q2Q31NR!ir|qCI=P`uo2f3SfVRp^5Q>#SM}X$ zHI$rd93F!!y(T!f3I;mPi4P%I|RD68dt5}g5A8qdSf7-)^qmx7h-*BEG%f$yP97mR@8*>!p|$j zX9pZ)u<7ccEt*V*En`I+Al5D8XfmjhqDgpSpUFOvf`~UP`u*7L{)}(#KJ%8ZrKmsL z_8H!DIFm}h zQ#C)l=f0oJtI*~sg`H$%#% zO9!-4R9L2;Gq*30flo^ss@^4~dR@EHdRMdN!g?soI{*^)r;Jk9xBwI^@wWYnjoqR~ z(=Iv?ITPY8O~v@gAT3%ok{bb!tnx+^pZvywOVXwV@IqkQXO$oL)simjaD-`1>Xpk> z>w!$*D9b8eWbDrP#J?UKBXr;fte<(0g$(*PnO`DuMBDT<7KY8Rk&rBPSz*IomieR& zW8;wgLD{jY=&1Pc_wa`q`8UOsOVU&3x+N=zaGn-nB%OwZrXLh-Px z?Vz#x83YaF5VP-5&h`xrzV(fjv@ToAS&kJpDV{~vHsfX#x#FsVHl`XuIf`ZbGpWGT z#q3gXwCGl;``qF#hOu+&}vitwSr;Xa+y z4QprT)BRy(7hrJv|1}O`sQF~_PeRT%_kkwbpFzXKNEW!8b}{$>&>%5og|wd5V!X;s z^mTpFvHVH5f`6biR8{-Chxa-x_=DnN(9~|Qpc9gzpNJw?w8!(@UI;4|dJiz`+6~z@ z0qC{u{C&@zOeEEGXtG>nqB@Q=dG05nyB%LwQ_PA;9v0?+g?5RgOcS}7J`!$ znSJJ~ALog2FAZlh=aJ7|NQXnlA$oP&SB`ZR<(vvB_z8VNdP+Drk1%S4nJaU!w5-Fb z8CZlD2@sT?176Oj5uwYKjs!c_R1rZ0p+?6+$BKgcymJhpDJz$qk-j-(t^1-w zu(b0_Kp|tRKFl4?mRdo#_M$o#E@*?} z81gzV)V=;j+q(U_eo&y08sbvUO{=I(bNhT7E`#u+$yCEWQvQm1%B_w!e#w!pyD~eh znZ-$TRYn{Oal;v=eyE-IYD_L^YS}p6hFw4Z?7#>dLJu;<>|N}Syz-`!YvT73WuI%Jqc})O5$Tvk`OXs3A2>$X6q05B@1zVRZiG%~)|;5K+7Wj{F6o zNFJa!jHH_=N_CxffFT^!;ctwI7TUo+&=Gi7=o|_lPXVEaaj^dev!yj7GV4(qdjBOnVgO^T1|=-M)%_%9bD*($n8_Yww$0mNDe*SS_R{p zhxV7bza2vd(3+AALfg`W6=Lzu%_xWm@AD0{W=p+oo!W^-1S_1`Zt*luuXYsSpJ^?C| zA{)CI9|J@|STUmqt8+=0CS^7T^xmpxmR(b>88Fq?#_OWvr`!5+7M&(_r4u8gE|Lwk zX&U;MMJpi6&nRw8kqZ!L01>^nU24g5jX^HpMpb~0+-{!wK$v5Kc;?{1J!HPOq*w?; z9$(KG6eL0&uSxHpVhjLYK%u{x1u`AOUd`Y}NYsVDx~NCnMt`4ms`1HYU!iR3miOcn z5OFAZA1d5@Rz;0vTyQA2t(XpA&PxBm_c^U>OIL=vp(wN(D*x1BEUUgnmn(o8cn5IKay>|gjgyp+)sp_*T22CfM zDX-dUg?tXWCb+U(c9fBu6Nl5Ey_@GDdvOdLB${@Qw3AwLi#BNEgW;B2A5~AC@1PKw zDx^7a#&%u_PNK-+aq_qsCpLdCAr}(*06*(>pSEp2G;WR&PCuEpC0SLyn1%W-vlP`0 zw4vi9dVp0he#2K-cTkngeXzlsED{l81?k+S0@a1CZgN5EG^)uz<@Y#A4xfx+N1kzm z+-ZH(Sj=P^^dlNf*JhuBwP@fdUG`=KAt`m!*!WJS#xE7|Dtc+4C9;`GZLG z_SC=E71IH&gB_< z;>w5EpkKUcqYyVn2X0`(Sx)E1^C}U+6`&J(egH7KO7*I{iATGG^gk#4pY~7)Qv=2B8 zO0I4TxdoU{g_H&DOEMJ;{i9rq*+>}oiSM&H@ciW;&@S40VlFd*L_t0WrPu6y=FRM! zibfV`E}?BY16pEf{R50R&qKJadyLOD5v^MPUOVAB{Skc03^uM0Wo zxf8%;{-iWb?6Z8idOd|tiwJr`av!b!E@=FNIB1Pc{GlXr-QBMppG<^KTz#7n6^_wB zf9q(%w@lH-dEtq!!d1w$Wun=ze3`olHCsx?E?Z+PyeufOd>Y*-xH^|cz9x2!pt9Bo z=Rl3GYxA?NO`#uGa+v)s@-K6-g^du00H*<~hk780S*ZT1s#OQ@Y4|e8%o?4I%7qb+ zNYdVi*?q_Itt4T@VDLFGU-XsWadivVNvYL(vxHP~f-Red?y~$1QrEh9XiddcbqHLrcFICg4-OJx)D zgqmc!V6H>eV9v|^)h#EGn3d^0&k#CsJ}N`=b+{*j;-5zoUdYY*{;3{Txc#a!gP@n9 zred3bbG3^Nn{NYS4E-GX(x|;;y;bWLdM7@?DvFNe_w}ig070d`Q0|l*-w=Jqx-q;bx1n=AB`9uaF!CJGvpZU9Fgd^rq#HVTmi<8r zPSnj)0-Dq4p*V&($0ojjWPihtxCTnr@)NiWp4g)q)<bAS6np9RIbq--!Kclc3ZQhBqWk5nXzZX?)ED~3Bl~}+Qv{QRY)MoTUE~MNe2^wRHkdT-H3vaO>H% z)hM#N*XP|@H!=$x42Fy7F{;}>7sP1w(E{IDRD=AI6@Hq{5BtFCD+)VD8@T=%+)J)+E!fIil`mg=@cR^6?8nZd~yz3m)~X#sc?2( z{Zss3BCWW!wXV|M`g8wntItU_Z4c!$)Lv%I`fq77Z?yao&aC}gX<(RquTtU;fh@aO zap4a|WqUP?b-upe_j2l=)^vUaD@7M`l6rB4)bH1JvxIhSje*+LNUQ?CJ)9GX8(KJ} z`p%~yXobs7P$r!k=0zcxz^^4;tTJp|^TM+yPG_P!s>OP2pP-{@F3*Mw^Br7jkcaOF zP5fqWv0)+s)Y`&zsU9}G59Uah=Ene;EjBfvq7SO}eBnGQABQ;Op*lp>fZw!7TZ<&x zY8rAp-3Ys%ADkkxMt=FBlly+UF-EQBPNNX6^QBy>YXkypbUyrneG3MfEAWuao~Mjx zdoLDP+uy-d^_ePn^z=*IXM9ew?R$bsszb-*%PaWL`t@>@BAZGq&w{(}Eb)IfS-1vn zICZbhqj*^)GMKRkm~GR&E$I=3x962~Lno)*cV%uCG|#H4KEb1;wm@Pmox(}YoMWLY zq&Bk>2a+s|N^ zZ0j!h)IT7<$eT{5e&i|(DLs8U7B`co9~7kThv;4@&_5^m`8Pm>R9LG)<6@{rFbn*~ zI8*7L`^b5ftmxvDac&#OznNPZd%QV@TiPLMssy@V^97VhG8t@6NDe5p1!G zeTirkx8p}q->r4Oq6LdLTaq5yC1y)E{t{<){{VqZ`(Q@M%Yb8GyyUGAY{_mWC#UST zdbPr8v;gQRyVrBZ{r=;?BOqU7wJ0lAFkcQsb_Uq$HW11|XOj|tlQB?kzwnwVB5n!8 zG9ukYAz`tj)-#4)*H@59Y`wzqIZ<|*rS+>HYi$gWJ7au9=N4!w=n+g7cGAG7I1Yp< zocWayA3q7XSF^bi85hVo_ypAn{@qL6y*vA4A2dY-+gt5I@5mwOw3Xdp6;4vQa8R!~ z-e}0tt?89%dC5$gGAOu^mt?MDTeqU?9xuV;*Y?wUVIgEQ-yCs%+s_Ay*Eb3LebtK^ zgqeDih`K=vT}{HJxgLgWwgQAHSp3a#O!#iwnb}M>=BldVY1zk%WEhn2OK&`J>*>O? zTEbFp3|Q55Y7zio#yq;FXLBG60QA zl=&r4d`K#kntkJ#kLN{PQ&Dp@Q-B|dL>%!!{*c3>U7X?hAc}3h+Arp5A7#6$CoZ<0 z8@0Q;JvW01yV^1~g2{+GectC;r}K1)Y;1>8JqUPZN!ZOr;JkBWwMXYu01kfTT~mr2 zR+44Y1g$QA%6QWTYTH@(6d+b%v-tQK6c>@PPBNK0U?oMr(3n`Eoy|o){1lBcd2yfU zUJQmd?&v~ni7mntLH$ke+7m($M7Ouw8tRnOAE96UO~DUuHu+>YK=n{{&5!Hdm06j})HrC*M=Zzy_{ldd|h^ScB1QC8d(k z-h$4YoyWJ6Zh2X5%qO0^F_LiP;h-s=s)H~Kw?yWJH+32qzaBpdT*&Cwj(@|4e3B%s zyp6Zxp1WfE{YJXZ%Xj3c>r39Q?y!v0H@4n(dFYtL3;Rc5YXnS`vI&+S_ccEfi_p0O z6hEP}(__ecEW<%GS8hIxSHvDLOMdm*3dG58!lTZUbp0FWmR1z_8b3>2(2rn@YKkh# z+IF%f2lfZ=Q+QcJ$M7TIx)~1RAc)9Pv9E9X<3$!EoM1kJgu#_va~D&U19Np51C>cT z@Tmez3jjtZa9Q8&YGg$YG!EZkX9syCPzSHP5?iRX#VN#Hj1C$$WT%sGXS7@;aW z*sBSNFw;A?8Y>jj?1ZcJvsu4|YR06#@@NV&JRek~Z8*h^t%ecAx3Et0>e5N9M%Kx- zrm1=pgA07eLO5C?X#4=sBnRo?FUZeh50xK8#v8EFB9BCl>>2kseY&xKcwhQ6o8MRg z8KM2$l*$?kNhXuWV*+bZL7d%W%UF_^qLC$cyGD4~NN_1wKc_n(e9>@g*3{0R=(X#Q z!ofHL!7&(-Yx5=nzlq~i4V!3#wEiw6Kw`o=QTEeyC34%Q49GVC^WsZ}n1asy$t^ZX z0sj)AgmLLg9D;S_m2CK2l&Gd<%2%#42axyI>6G1k@LZ#1e^`7*O>7G`^+?f)k35qd^ci1JcvIf$$fs$9~ z`WU22_V>EitdAv7K4{pVq0{Sfz&qWI+Z;$PVN%#+8dTTew5!C%#H^L?07h&Is_oJ? z6_7`FLxw;pVG!CsH0UL-RPxp({f*iApQOHdRo|A(AEZwTYm1S3iF8=%{)2@U{cXrfh10pxc*zY!MDG=TqA$Quuf^wGV ze%dy8rEt<0whLCboH3lu@R0sh~-lNYdnzoU2A4$7>Vwe4%uVQA~Y@`3kj8|GUZ=sgR9V6t=Qnti<>j zg5(w;R7b_kqlJ6w9&D#R<6ijGl3}z`BfAyhuQbyE@uPK-h?Ek%`X%`@Qozk?e^u;% z=i36P;90h5fOUJcy>z{g`Q8#<9J}4viC9K#W$2FcaBi|Nh_Dh8-dz14L$d9nWDbte=mBEt+eXP`mY(3wiZ^07n= zhOAXszoe`HJH9us`k<=zs|f5J=E^?yy(0|2cs2;LRk-x#at!Mq0@> z3vAm)UZk$7AOET-8N+qu%51sIa4MEOCaEORyec*{;Em-fJSf{B@dwrR{z;9ax&1)# zAA&0VvEb*fATTc$y-67*%haV8PCXocPlL8;+i2z<`8t67>+0zT|2w7d}a#2F{Tz{=CV*d7(i z$>a$F#+;_1*|kb^dXImT6pIAqZ3L_p;n+AC7t$7M96$;8edm;pe`B_;rj+n3DvmfX z!F)4sc%5;!&3!op=h7U&+3zo0RUkh~4JlW& zr2iMW9zi^2P@XB?>d$mKJpz(?N)MT{DLq`Vr&-UusR)warQFP;W-0mdLlk@hNVKnv z3A>|2;IE9-U=SniCr!99I(1enRM)=U{7~KV%P`onK^7kaB_|#X%N>R6r`vU|wcw8& ztRNx92v>DXvYrD6)^QHIA4Www%@yKsE0I7lQyuWqGMljq7zqECx2nWfJcfGMGAEkE zx38S-DwqvpF|1y*pQ9i?T;Gh2Ge8O0PK!1aFx}2?dREZpXP;M>%1MkMeD;?$qJern z{^Dv0egZNeUS^ZCBz?)d4aRDo%<|0CQAz6)b1@hoFC={ zedz{`awU^QLcHG^iyJxxemU8}ZU^_;X2<0#?yJWNffOFPfOPRN^?2th-HV-DAbQy~ z1k_e%1!VBJZVn;%wu_4B)#}-w>@D#Q2Wp4RI|Y@5P2)^Jr#Mrm5?^6^rwt4Hit)5%G0ayZhoeWEa9t|F#?aAMMh;>n7OCh#tmffEa6qtMX_EyTG zh`ja<7l^km{`qsH|MUjx3^P6G#I=F#LyJiLUU^va*$++YoeyG47L;>ptlN8%#sd$Y zpZATzMXBM}{2pd#DDg<6|Iq04eBd~RIfTO0YZ-=`D3PETCUdcIW?*i4?=r@akmW{B zX8ZVN9@JuhqfRGt1t3avY?KoxspMyS&>#-nYqBE}Ij02*>+zEr32t^`Pf0-vfyP zOsuatoQPuMuB!xO6ft~++!%Q2q}ad&W07YcsiNFbuKb>=n~*`iD#3c3RrKQ0**bTh z{839U=p5*CKqoM9r~H<+`>by#zzp|JHA?NQ!m)<<(_}NDAWikZe=jO-I-H%L=i zo5e5DPYVia%gim%C&M;q`@+0vdV&eiS}l=Y08F$b8~)rMfe+Gy%nZ73X2E_^HZ?|d z6qkXNX~L;(Rj9Gt{IW8qfoDRKr5zX)r|lFH>_M|`Zu8@6{2nx@PV2`L9rRu5UG z@0DcdC#yOQ2Q!PT{oc7dUK zpB7H{HXQ8<_0K*!7LlYtJRjETYO4I`-~5$~6>p@?6K)%sqtLD|G!-OBd2m^4X5L%6 z^WC;;vb^R}9X;I$hUcM+c7|mK>MGkXN%|Vx=M-00*%ye#_kF*|A8hIF+0Cp+Yd7qS z<@F>P!h5wDHDZOH5>>V0K}F5 zd{nfEfW1uaV~Px(n)fn)+sj8JYZ%mbvzsAs)2f2$At+H(nSa^h|+f?Lh6NO5=lAd7MQ<)H@%{e9=?xjk^FnM4m> zfAcnuVGfgWX})`aBe-{bD^UL@%LOF31j?>B z)Gj5S3d=j4!)uj8-D52)vjEC58W?&(T(~oF*2qHiE|5o#(0~bCCFvT=n4fb>D}iI! zOQA(d9^o-uS})tMoc>i^9x2TAj|LlNbo8XS4xcz{0wj!tSfn9qQ?PQ}f$aEOF05*Z ztC=-sZ~*(}VO1pHJ<);ED|bTjL{uvu&7eU^8jF8l5bUt&_%Q*x#nsSCmkv)m36HmHGbojQ@(7+WUN_Jbc$=CRlbw;q|5|S$cW#W2?CS7&bqzH=kyxRMb2^{1;K@QROM6IBPo&!gLvQcxU= zpdQnGi-w{Lqjbt1nGUH7*SW%C=PVRX3GWksteZpXh!lOAjXxBsWg0KbAT7_}|Iun3 zIPrUXgiQ;`iWIo@R`RdTH5f!21n>N%&A^C|-p;s#;G0os<|R3wmp*tMxTlFsuL=|W z9{Tqi{X`*LQl45S8w6=7OSWa(xiprJ?TVdQ12QhiHS=RNKu@Ko+N(G$0_ zMZsEW9FsP9P2bKsPLE1w5m{3G+W8`TY(Q;NTH!? zP_*#yZa$~3cQK2S*-j*?Uh-_fMQr!qbn-|sfLsC?bRh{wwuBpL))mOwaASgI+!{XyV=p{&j)HX zTir-+Fgj?u)WJ7oEVbuqJJe6MRH4DZ`Os2S?Ya$SkPlN(D3v}xLV-;uM+TxY6m$i! zefab1%o{ka63&$FHIUlOhHMvqI?Cz>Mt)^F#@__ZLx7{@nnoKX?G=sen`BCwYB1~MP_4fZEo|usyT7*O$2NC=UL0pv)2p(n;@g%yFo&@U!v4qsl?Rd2$^r4&F zmT8ba=(lE%zZQb+*Yr&-htIw&j(771zf?Epn3>ptLI{Veio0LP{#!W_MIAvX)86>a zHc+>uC`oMp#V~_a_Y3BF@0}PyfT};i+C`J<(De4 zgq7hICY^VN|_^OZ}>re+1zeejpRsGgva3*}XfEFkCCI_<*T zYFg}*07xTBbFVhbL%xq4`sAmmq#U@1+|Z|Ab|SyE6L3>%9q?O#S(w{^LY?BJXX6}e zcW;qXPbT)=GavR(aRbqXppGL3LgSu*<+s#O93AWUg$+fYnI-c%qOk-yUy!X>8uz9q z(Cs9+);1?pL%3vD4C;s@RS~ic!^qxtoN*{8t4{Iv>56|22EqN?h~fV>*GHp2vdCq3c59S{!5v!RZFO1Tg!BJb&>L!W=~HA5$9k zf~?3OqvZ920iTY3g=7lykSlh^Wqm+`p#a(o3%NK3;%Gc%R94Vv5~hbKMw(GuQ$t5 zd%9=0m_cRu{DAWfy-ES0WK{E%Q6=^@OfK@lLL2qF_u}(#noRB?2xLJuACeiy3$*Hk z6`zN49rntQbh77a_w(6`nfF%_q)-_c9)3F7=;q7x4jWU{c>dalg3Zp$kNktjAZac-}TFBd*PJ7^r8%@J>rxo z@%SZE8VlAJd2D|}3SG;|mWBl9nb^a#{f=Ax^0L>+{aHoWRggkjU8F+gj$cF@7lV@r0Zgqif#V_1o9Kr*$pzxyjE{^i$x=Z-<~`J{FsWjca$4|!$wRU0 zVrc0GJLOb4PqFqaB&~HF{$70nA8tWci<{|mc9t_!H=v00=)jb1ZeIBo+5gK0WZiFWnJMkRw z;Wxzdpy)U9l=fd#@Ue@(z(4E|-Qm-GtZZqCPv*ZQU+fe&?FM(RU)ZreHZsg7z)fJi z{K$odugAufU#bC*FV4up)GBFoB{IHC#Au+T)Oa)ixZ6C+F6G9Le3{b(>}#d(b1 zk1ohtu+o!9^nX!3b~`pz!`+U~7H$oK_z(B;N(iN4cGA>-%W_m1-A+W)K}nX{IJBbv z7XYHPu2z%wn?0PdYLQ<%p{8Jy+!UNqz;WS1F6kOq!uiZW?PIGk%TI;KwRXkxH=&Xv z#v2*sW;?~tYZCTLi` zGV~H&pKt>FWT}RfQs$X6k_-*H34m~yI!9PIHnwVN47lO=OdckJ1Z-TIkp@W4< z!Mi7Oq+EDe!nR^+f9VPF+8|L@R~X-`i1905@^ZX1zd-7PVj^lG4CELt2Sy-0S2lsZ z5o!++5gUf&)`Tka5HWQr?&99T z$@6)-dFTrb{_6EFQdU|_$4*gwZ18!*N}r+**8~)jWN`9n0+HoDMBss-M4=b`CTOS8cEkCbn}b4(LXMLqDYG+Dq4 zIn`FUF5eOp1Yf=CzoXK8`nX26A}fw zHGSoLF55-xpED|zANkHj z+^~|gp<^iBvuS%3bz(h1#ZJe>;>W~ay!W3nzS^DoVCpJbgNMsSbglIl@f~R$={6?x zo8)`Ik3urc3y`YmX|7x#TVD5^IV*B$Z#64}+4y0y=Hb^X9Pisr$K|jC z1vgBZ;5iyLYIB7D=LmJxfB5Zo$7lUH8H$8l%W!;z(9r|lT9H%rPd>tFMrzM)1s=kO?qz@u=E#$uI6;?&iCWf`~6FY;H(z4 z{iE}N#u;FQJ+L4ad|d7l3jxJrE8Vncx*o-7W-`qKtXsj#^3GY9st*INH2l=oy>v%ZQ{+<+QM{ttI?N7DgY|Lay7$)=LcC*! zY`<6i{2d#R);&1V-ot%ZwY2+5J7QmA2aTXa{bIN2omb}a_i7! zRP}&<(WeupXQ$!QiLHIf$Y2tAcjwFS=3->>B35w?FFODcj!IE5;FCfzc4xE+7nQiw2&4;zVm29Q)iT9^6-~)?~{%h^2PnLagF~nPe+?;zqhoGWAe{ z;jgNUJ<4>}_3|p%^BxUgR_zZ7!Ux_^S?}OTMe9#mc0U5}vXE!-IWrIgv$M#fVI6pq zrVed~GE_Lc2m^ZpDEkG^zAxdiqu` z_307zi3&$jNbH@4k{OYz_u{H;PIoSU?YtQZp5x#;dwyrGk%~Vl(;s2TMa!^b(>v*! zFwYzvzTwIsIp+)bqXFNJNp!lbs*tSpvPvp#9`R5$BR}xPU@rYyk`a{9)TZTF(!*t2 zscI~cpS8~!8faXt^*RBDwDUNYmv(1Rq9_ZFqtLW65>I<-)3}63rk18=0-mAIe@pwr zlKo^KUf&sQP!UO$ZJ|7RY2lxkpM9t&BaDqmeix&C11Qczr5IH_`F0%#>N{-;B1rvT zSOX5%=baZ-R&YhAa$F2}KAZwj9m})=!8z!4@YTI>J|ei7wD9y`WTlNuZEWCzCe%Qu zmdR7DPAqVVWABTd!Epb^!i{n@hczPH#V-=pdHHwZ83WMuBgc&G-6c-wehP@qW3aEN zkzlWMHO8ktKSF=r0)*WB3{s&QvoCqjVpSG9?y^Ukm0LZC?A^JU#{@W&w}79(Ex0`` zJ&5ROuJj7$B`;oG!G!<>1U$iE%D0F5f!$c91 z;6jtR_$)pHweiMJ@l?;+++a8ReWiPi*f9!P(sxPsXv;6{O$R`Bnq^0b@yGPs@@cW1 zhidt4(baWLbhYoyzN+>8K*!f1HtFqF&%t)JQqHL|wkKe3n&>(}(_~tB=nVx5W-eud zmPgj}5CXouPv2g$cwI61wB8SK$@w(`9-07%523gqNGCw;FF+9phOD=8zT;yNU~(oF z)ar2zb*-Zw_v4G)uRw7$0&AvP#wl;+rO1yt2W0HW^P)JJ7h`7$6nD5B9B~f1PtSbM zd@m|*+GXAw2~HX$k=Xok9>Z2B%)=Z+5`2ERz^WwjOA} z)Ny=!4@lXRE94I+;qOV{~f^m0v5S^v|LJ=te|gBHxThE+-&5`m<2Rn3@bK z5ODuz?eygfv1kyZsW?`U<4<(ECE$fP)vSGyFmpBb%y$)}WZ>C*GLE$1Z znGTpmGUu&T)&Oz_fmfFGrr~Q7+rA_G$O3r$k97# zY)0bkf*x?uJx^=i{BLBW$^cG)A0$bXaERPPhUsnibD|u7qnMb8D3YHUqu)v%3|P8z z!tjE;Wv@654?E4K__d0%*p5w!b%o%j?iDi04w$(@MxQjDDGC=Ex4N}9yek$gv!XoG zONDba1{Hz!-;!cM|C!shOXEDFxw*lx`g5+S5woj> zHlwMQsjohl0v%U0DX*Jv|L8z`B_V;U6q6@fNAX81gHrEe_znL zJNJbJ9zv!H);KV_^A&E#^T;=Irl`B7N9OXEJI#9)>h zdg;x`q0VQc<>RYya;b}zoy`>%J+^-T^ROVU_0A0_qTKkDH>5;kCN^9=NIH_r+@KJh zKfh~hE%UwEfy%`ovy}?9NB<}eVsSI@&H+0n9^)PCrlLi*KjqFHSQI}< zkC7wqx;xP~(fr*lZ9+P9(hlX#RA+wK8N$JwhayjxUJ|j}#8fpfV9lmv* z02B19IL9%{YzUden;q5*wI00U^^8iJO00u#l=sDK>nN-L>->}2CrtL(Ol0hm#8G>l zCy>{oSXNTUAH^T-3>Pp%kL`+OKI>W91um3f3nDk%4WnQ^x`%%*bkQ6!d~O@C_U`|4 zWKn!2cJCSGJm+`R7}FS7Z@}$ic>^v2tMm2Ii-|fw@X9k_NuZ58}mkF^dY^j38c-8+C?W7W8*yU7IG1j*%NeMBZAB(z;~y zdBR>B?IteQM=a!JEhhPAo^<7yfkb|EG&pAlK}S@6? zSODmiRc_7ta~LD3GPC`B8McS4B|)gZo_Y*XqxS{aOpZcs;F_7=B%DQYP2AN@)jXiM zAWt%c6eqcKG1>AYc~IUu`M<2VLI(viI0N{PMn0uCK;KRC2Bec|jX)aBa3a9vLzfj= z_jO0$9WvG zs$Pi53D3RJk?&a(%7!Ib^H(7VY8;hOIh3WY*#_sgq9pIDSE8{lE*^5FKbX#HQLOH0 zJl}$c!bhE_|9e*!PGg_ey=>IdX$XP4MOrq665FE zd-8y7U;AY6rbkwsJwO#q*P-Uf{aO=?*2YNMm;b+Q)_Hje!W~l}>bb3!0`SPPN)2-} zqca&LdMgr_uSGK>!JIV5Hn0HnbBNxDRG2FvK4=VC9 zIP{{28X5*+#%otaOZLfl3DRHtZ9J^2w~!m)w*YGMCpMl!>CH3uXv^ro+<`_qmE*z# zK_vf{hB+c10-s{`NEMEwjxlm)U7^e{^lm8LDn=rEg zFLX%+v~P+Kc4pF1sNlI9fWeT7zrLB!4PkJ7Q3|qN5rg(EY%?_ecW3;@&BxtvXoKE| z3y1|_vA*5J*~)}9G~!EjJseLKvy{l@!8+|R2TYJ_Pwag%CRI2b#;$uNDLehaSe-)u z>$sB(jKGH2B2$UmEwTV!%D345!xsTF&-MYFf%?Xp)Kt9>JiVscZO@`ffM_suky>_g zc02}Z3ctBW1!T^nH#4TOn8=yHLSbp{1r30!wbrbq5m`T$@naAmMpt3(x(XqdrAemQ zHjERe8)HMzu13w)Sc=`o6w)+ijIbh24c!AGkZwB zXU%@3!yN5L4~MZHbQFtO=U8s$nQrGF^>!$NHi;$H5zG;2iWpZSMrD5d!_C_-$e%3V zw_6~4-BL~+I~3%iM|hN#wn!1F?~~W$1$CA#{YKP&v@av`>*CN3kKHaR#hwrN|Jz@+ zbu+Y@tq}|^(}7*cny2wrYlMHc9y^vB|2Zgnuz#I9xJ-=P2eoF%^NggQ2kt8 zlOU|Df-^HPiVm=tQN%cuLL`nKT09t;Kk!x3o%$HD{ib4n!jOxxxskzcIrlR6=&Oe3 z3z02KQuUz43h%8lU6l4Em)6u%n~Ay*1;%zN101nfS6N+~q(Dz)$df3A3rCbUQuOvd zwhU=r5Gj3?)Ua7)WMe}}eU6HFNjxX0^r=+NG`MU)?wi_g_zxx=9#BV>4s?0FoyOAn zWQg7&0WKqj*+P3+E_WA2Q^mu!Rr|S|QAg!dyA5C{gr5O4@fvx7;C3-bS_lmLHDe+^ zFW__KXTCTn`%A=xK)D@>1;xU_mU9y^kxN8a*+2U0YQa@*<>}m>vp&uhDs1C1i>?eG$J$;u53k_83P{D$T zS=rE&!ci=zq#}wLJY@D)Z1@mYIUul+tCzsra2afI;hOk8<;8#*GH{9w;}j@o8zEgE`1X^=c#Rcge?iRbqApT)j*w-l)K&(R>fD z-Qv{rl}~W|LxK_*=TO?K#gu$%y8|_JlmZmLk9n(8p#n}QFM7x(@A%xF`2}5)Jcivh zn?UA)ZI^J7>D-xGI`8Hk6I1Mfys9;`K*?l$K^f_nZm;!DMNynE7VWH?Jaz;~MuANi zZQ_@788wDNTA&HB?X7Y85TtJRmD;z;8FC-dh`#3|!*o0l+p^Y?yW!));*zmFS-!y~ zUbMV4Hpv%ylP(ZT6H2R@9LR_|FS1D~e9SDd^@e|#-UZki z_M&ika_w>+w*cz>FI%CDmA^i+$MUMWY-u?lv_qCO zz5TFozB+<_2S?t2ASx&+hGqP8!#l(T22>pm)HUsINIE*Rq!yv1L+)%z zaFMTyl&#_0N*9^mQB(?}M~b157oO3*%6uyE{Omfl5^>VTwfdE_9#)5w9ta7cZKEhy zlZ@AZm-`j4K;<$6l-2rX^xzw{*U54A+15eLt@;43w;YV!BjWqx9yg@#AIGPv-aoVXfU3&KF3NDA4cUp(h zDJ@Mghsrb8hsHkK4*JK68OupXi5z7{CJ#NSgs6B1Ae--GsV(L-m;i?xH9SkS#Nwat zvabwzCNoED4_Hbj0t+DpNVwvZp+e&Mri%_duwJ%mn@Qe3ymC}|oAJ_sI&Pd>Yp9=r zLTw0jH{_$}KD$shX2D+vGO_#=>vi@t*m?%Z%&7e@>E?7KYU=Toz|*TV**S4-x8%NI zvIK-_KId?0E*%leUtT-1pNEiC*WYq%P!YlLykUjVmpTVJdVFJ0y!BP5g)4yAc01h+Ccmf>VX4tV) zs^zA3Z)VS;6JU9_&*e54QlqUJIvt!}_fY=?Ry-mrb$;{RjvW{gnmpZf@D6)zxXg0F z|IqS~eFNj{(W`8QRbbW!^W(2=OnxYnFG8SsNHb=vDv<1xaaI}=v~~;U_T^eIJg?pB z9s@bOhm|qtyK(s530G;hvJQip1y?C>TZbFYfK3*xWCN&uii4|z9KItRLoXi3K)FnZ zQjR)HU)!lQ86m?R8!(atHIyKRl__mx(lZ1Uk?%{^uom=QJeukyADwtCHA?FM@*pU* z&`T_zl0!~iBRFO!f#;YqZb@goVjRd@7e5SUc!N#duNR5o1Wk+vsD%L*s4|6`vXbHC zSlc^_4abICrsz9BpqNf?4qu+1Ea>JoM$|(PI>UUp9dQNhimGE0LvO02L?;ar|3jO1 zcdjpqz0-o9+>FT#{_wo9#qs8UU&?Ztl0<^0W6a=6i9ffJBrMJtU$^D+o%PVlQ;*U> zw|tZm@WlItwLTa3$1;Wt+80bel&@QPjO)@-eD<|J;!a7Kh-h_n81HZYjk7-5G$`n6 zW9m{Y0lxS*-C>L)Eh*bVfsa2@R1Vk$Y6CX39^?POlOF%g00s(my-1p8pM- z;mFYNBIu+Mpg#Bnhg#8kWV{c8#!xj|F}v(*=eIrVJ%-1>7w|e={{bn2YnM4h1t2>O zy$d(We+CadUVmiXJ@%EToL*9peH7nvAeSD~O)p$^#^#RNZ=qOa8PESFXvUQ|^bDhR z8XtQJ!-L=i)~OB-Ic5oikm3Jc$g@-T3#HG@_pKGY*>$ktq2Jc!qk(?Gn>v^TFMP!6uwB=|;o~Z&cW~g>6@ze8MXhN zqiVIY5Ved=j-R4Ev{|1^OrHHQ&Zq%AFu^9iAP&h#?&yMX7#IP8xqaJwXxa8p;h{|q zQhIXLHi)_im_o+osomwlDrlAbsmgLZ4NgSrD|ggxpH-a58&r!zJx<`cOx0x<-zQ<&(wHH*Aau3=%O%IilKzZp&jrzQZ`s zCUG`>K`hW&ajJ)IC@iNSxS2d;S)mb-^d$dA^I9~?=Z05BOS6XPPUjEeuXI`VuO z`p<{fT_8j{5LlvT?G3}0w^u154n(^nrOX6P?{lJaMlw0<5k55EI9dJ?($^a-I$d?BwfBl4TP2`q zp0ZSD_lkalGqo*X*HH5VRGMUPN?~HnL79Aoawjaw#j2qN@Bsap2RM z_T-t@np6FsKY^4#MW*+{TQ^8Njm4Hu#$By%GP6|UK(eXIuR5vcp{xT58y%py5fW#Y z>r9{!7sz=olwQ=W%qKQVepL)@&r4RkqH+wl*Cs<>?g<$$Db(rPaBCQA@na@T_f{&j z`!)BlJ;Fc$;cE812DVr&1BXW5v>xDjEM9{>PsJne1YPuvfd{lfJ!ig=Wm)Q`@tr9*dyTVVZ>$i>_mj{>JG^EPm`m0~cpOKqIAsVdu zdXv(mW*;1>44yF)>?8BXOc{_Cp^7>bC9MdawF!-_K)wowQ0JQs);CN;zs3l#Q*0N- zJ{{1YVWzGjBT-UDbeNbWsqB%ZObF{g%N@y`yQx6Jw0KoR#T4AH3}HJe)?RCbI2$)F zQ3qjx3)7twF}@p_Cva0vE=G}ld1zV~PHPI{KSBq$ z*+PEC@`4+I_e^LP$R%C5TLfMJQ@#CYj-9?q_T?Z$1RFC258IeC!{D>&{r0ZU$Yz@$ z^pZ=Ra~jOA(dpi}ilSeqt_jfb#_F|SHx#9Mk8ohMAY?(@RAQV-uAY8=gL))6DSoFU z1qqD6u5|KMZ;cs}EBM9E0u(NmJW1y;FZvhC7oW>{xasJF*Sud8Z(0C@n{hhZv$)K>W>n8nW*WVW6b2qb9efp=3L_zb}j?f|Hc*D!V6%w5=9^9(vCCT!Bq%8Np0Q?(t>F5-&@o*I|fJpsiDd5X&s^cM!z9fp{! zS691QlO7Ep-i3POO%=2d{ob|foHml<*|@$W6Ly>L)l?>a@pQUDV@>4U!Fb5ypuqhY z*@uC3*QOIX$^sQ&hi33tX7ijrF~@!d_;DQXGsIehY8yskGKEYzhJ2V)@W`RWgX!Ol zIsY-aw*z8(xJXS5qG?If055;X0RV zr>BvbiAw*wZ$ZzUN)7$}Wu6k>O_WHU!h2?Dg*@4k8oc7)m~I7WJSVuO`pp>R{Ar)Y zVNfI3YhWi{_iCV()IuLRhiwJb(~fFevT8vnRj(sO8Y{>Dz{Uff$sv1!7^@p;G>}M! z4hER>$CD5F2T}{s_=3xpN}uET&^md|aozP)I{eZ#^n`zSGmcxu150y8IHq;^Lhtao zQBd~;bN|AJ9CX~FtQdg)OD(4$@m4HzJ_S8Hg8dfCH+AICyb)`eS{rnnY~T9BPmsql zbM9(maiC~Q&v3S1iz%*)1GKz z)z~^#Y;os!VI8D*x+jkRp=dx1$mBit6AGCS0d@069i|~Q^Lx8xvk;CU{|a^L*AE03 z0)Zu|v!sgsqXp))J)2+WDY*OPQ%$9H+-u_(C)EPnr3At*r0FkEuZDu-FedxxXNa4K z$-Zt}guji+N6Ye&^i&cm40*aA38RZ}55jo;_SY9)-mEaJX{Fb+QfSbY`Os9Z2}ZR` z9pz!rt_>G`qd!6WxHN=@sABPC`<}h5qM7pHNMv3bT(@bUwL%(|nfm7@J1>cDm2F2- zhuUD6aP*_yf+TrS(K_&geF5VTLDu9H)cP!qk`yE>&@NbC6)W)@g3B8e8c5ppflqM9 z;}U^`|DWYuoaB_qzFRUf1rfxEO-0O6(4ZSrjvt)3ZBIlxR?5~t{xrFY+E^7LTz{eP zbd+rYMT829eam4@(-#>)M;s72osRqNEY&F{|H>;YV!<*#&-n!!2kAUsxzvn9locPQ zy!+qYssyIywjMx9;b`now#!1H(--o9hcN0yS>5FIML1#S zjohQxBzAqe>T4eHO)&kMa2{3!7Xo%eHkD*c`N%p;AirqJfL463Q%-bs#^6c^CI$8? z+3fhv*p*sz(QJD9x#r}6#sBS06JPE}j1Kk?1u&2CP2`Fw`fb6IBwM zrR|ULHdXU9A>4)nAzUo}QL2n(s~qmCXg`v2HTesmBUrw=ST`Or zpA@=&8*&u)?6E2_qcNE9ec^%C#MSK9FWa-B&W~@I0{u_%f_OfrpW@ug#s@Xr_Q}w` zg1B!j@7|~mGMHfL1c!%X|)-a$()Bu>8MW*Y}>vqI_ZxWN)$T zkM%|w^*JlKbmBy>h++i%O@HMn!|E#YkqR-os@6*%C!CqOQR6Ca5^f&yG_|6eHX14rkA2ha+r=)w*6a(@GzE|iN}hf z_xTdREr-a8uF_e=!*j|)2Kv^>-{*m8DHTe&wI5JK&1X0L-45{_#}3Ecj+(RX<;N&c z*?~QdtO8x*uyAtmhyddsh~cXr1njDRp4qr@&tk$N^5Cc5Lr_9d=5nk;oiH%X7Lwha z{*>(ghYx+6Q`XnVDnopw#RCx9e=_haX>#6}1}I<1DD1I=!hS~kF(Y@RSLEuB6`%#& zZSLDwn9*?-#26$}CbL)#EIfYv{Xg1#?j}@HIy$Js0^ex}8#KtjJ90w5BcPEcMHDIk z6+JNe?S)J-_g>ob)Q41MmnDV_wcNm4FEwnbGDxr|X^%|#@>ROwj?nr=OEj5pnQC1{ zs;G_2GvW8ajdkoH2VFTeDkkaY%JZJpaAqByqIoyR5ZXBl&rjpq&3B2qcy*{1qP25e)aOWsOxF z&aez4_lyU&zY7ITQ(HSW77i2f9`1sknY4PU;3q*WHhC?q9nP?9yOEF#l4m5}BO+ss zWF9DwF5~Z>eGmQgmICotRd+VDQR<_1${hs=mHS|i>GSdT9E0jI|1nE(ERFGdK4i)& zoh~`UwPYhL+-l66{i&N9a?I?PBm6WtgZi5DLuq1#GNvLIl_C)Qa6#2Q)`4v<%&w26 zU!Oagedi^IY_{O*gk$PlBN0mCMOYZYs0Oi<(Cdb>HvxUcjBfkWBT_~5vt#bObg=~?;74*mCH(vZm$J}Ajl$oqwG+^*;S1TD+H+(%`1eFb0o zcAAm(y^U0$WPBP5_qTaIw4L9;!41}9{!!ve3T?lN41Y4?)!^vPek(QrRsRT31zq>% zpgvE?O7btZ-Y~Zoab5jsX_I*6;SH4r70|{j_vzDJ9Ru*FC?#73e$R$S6~;jQP>r z?XtuWUpK7=&Rl(uYzqJTx8X0(}xy<5=vlhqS#m*>f(C{@!aejJtHBRO}qYd?@T zDY<`6giY;)$!UU$E=m`&RMR#=Ec@L`y(Qr$OBCMpE%*Hz5azI*s?fO6o8+qRMMScb z6*KNm#a#>WO9{E-HTu%lE5vGjR@<(YAG>H|_-&4|Lr5B1{tiI0d1D2;8(NhhG=6usyYHDiCo;Gt6OV zk@;yYrG*oyPuiquR9P=jI5Tc|*B!+=mQyJ2xHKgji5mDB@W6G~OHT}!8McA;8NTyc zDvT%>?3e`GW0bKEcP~`wo!MSf*GwSB!I%8b2|q~0w$u2uV_FrjCD-gA9>7o1l?)#e z=bDss)8Fj3ckFW8ZGEn!Qv*Al2mY&`^8t9mV(Y4;vkEjh-Y1R9f~g>N(fjSjz2w4v zfmjo)#xdS_EitApAPIKAgOuUe#v-=3O7?W#faRQ6-`YAy=rW-tX@ZV*FSYn+Um zz)vE4?CtGr!IgvX4;kJM-jt8*623DuErqxm6Adb<+ z`rt*^q-O8#fPK>$0lFJg61EloQM18t=Z2S~)q?oex~~uczYVw?UmiUMd7r?F6D3xm zMkg=Qo(Pc=aD{&0tU{<^KpELSd6b2u^w-ut=rB$H?)hnQ?4AXHoeWvJtdP;Uc^+7# z>|Y*gP#q^!zK^HRIV6rOE2G|xi+x=ijT!qltBnT{Ec0|Yxk7ErU-5)b`9V*&-I1~+ z6(wqsm;>tyMahJtFn0+gE%cb;PSWrRPVP&5UzeT#_!}Z zDPbu|aOM|VHL=tM1EN-;v{-5rsfg@#(zJz{H@u58uWm7si*X61Qqg*vB4O!z6-C7N z2@(2;fcvL>8PCO*+)YPvLIHMhcQ6W7(xM&r3{9ArMpMSBDmu6~>1>;g^IF3l`RSP` zzsQ5Fm?ai$Q?fo_ze_7-Ya8ziUssJxKA+>^+zgK5PVL8i5Vj%h=)p6;T9l0 zDX4Zuz!>uCxdG^3q;Xk1FS73w~s^l&EQNCK`gPLm96p4r7L1X)n}+To50D2kp|i5AVUscJV&j`CB}+^q_(kZ-*@NB@o#iZKZ!NOmD78OqFF>&31j()%YRR9KV^ zwSlQpNLjj!YT^SjmFh?RU(DsAF>Kpfx4j2h}*kPpN^e=V+ZxB3esuY%yP1CQmr2PvbTi zmYC@u7lv#}Cpp9$nV8pMhsIjlZ_d`1p0fP@BnqQutmUTvEyvkva2~ZaZxY|@sl&AE zoVk#VV85@4Q>R#%$i`1R5q7Gz;+L?F-hc!Xxns;C5Pob1%xnd=+B*RG?XpC%%QIVw z;EFmFgS4hA3+ADZCr_NO2K`;$x6F&B_zIkmrkZ8p}s?4wc zG4-rho0(NG7vI;FW2+DNa{QMae|zRiD5lwwnn-Jgt!XjT=0}%*7dbQK<&%KxSuBby zT_Z-t>6CYA-tB`!lhwR+Litlhg6zL>FRY3^&=+S3QWVk^_j++;7sQrI6VR0P_u^K` z9;EMc7%T)6f_L_`=j2K^)rgn>$mLr-f`DUQkt^bl?y^(~PVa<2m5`G~iI}xQh z7zAc`L1Nbl^A5{c%9TkX(4w8p0&TlG{kTiDMTg2-&e{R-dKG7)rV;YI{lp1|oWwx$ z-P&bJVChnyr=$r8uZZZfZZiL*xy9;^%I6u}F95xoYxyJ^HY)A}vw7g8IXIh2%Ez%PeVcrbj8%Ual zw7MUU*|^1|>Mu|N1wotw34AXTRvULh`qbq$658=svh1&}Mrv3geqpXYWz+!k?_~ih zRs*dQdiE!9$8d-Gf0ZvB!A6k8@`)G-)z{VryuIR4zJg%E-xHOXal!UF3vqRX-C;vU z)e9-$L`Bn%ilKeGKitpK8sUm~=y{vhcd^y+LUiB&_|~iA;AYVWR!2ub#WJUa?7kEM1(!+&8I%?fNQXgI))Sa({pLS~HWF5dZZ9A5jYDF?D*}2-Bj?Zw;M-60{0c>71;~DKE zQ39+Q5Pt>+t&{JQZt>BD&qhdz{)rBej`zz99piZRVbvU~tGqKP$%n}0F>{Ufat;nOtqk&WRv>PUh?&}<|PC_h? zuGIDS5fkwNjIVaEIu&=p0$zhm$u2m2uJ{MQ&|Z=ObUj>pux+z#<6kPAUcN?9>2`Y6 zxz+L@x{l{EtW;8?xp9xm5${;0nEyUEUNC32K7s(D<^Rv_jNAaow??IuS%EE_`}P9CG?$b)wHQUX(aV z6kMi}f?9QcnV!}MZu~~*a0PutbRJ|AXyW4XA9BtR7r#B|6!;kkMe5ReY3&QA@FzAu zYY3T`HjvxTM%(;A|LMe(eqI%4QX9Xs0GGvUn7Al0j0{jmSi{ZCD-3lAvV1hqBXPlADp;YBb>-#h0@{;l!HIeH<5rypM zRmTK4pW0~Snlzj=WTE~C4@afCVui^}FV*u6DJzDaO2;G`M?*ELq0(Pc6m8 z7j@i>QRb}oBJX5+gumv4wBCvO;F4HH2=!nwSevH87_^j;<+RlNbiV)NgFLG4c=4O^ zmg1H8QQ%6r&IUMABhYL95#i2A&RRuP1RO~^;Z*fLM` z@w6xWCl>OrJKod;bKlrmmaC2qA^#iC8@FJ+Ki7*xqN(1r5nUh6l|`L}HAtE=4V+eP zyL~MU4@ypolHXpA1IAR*T8|-?LdibgqNF>xgSca(Pb+$>>GwM+FBH0OC1$E397Ytw(AVE;?qRmtPYlAnhkQl+NeG*ASseo1z!9FE<~3Vn(xn zrdRAa-+Ufc68RU8d~fpRJo>@yFL>u|!34zTItd!V;{LIa-aUnVdNtf5Y0mO$6KFO? zhK@v=stPY0s{T?mwH8&`Mp@C6^yuSh6+2NDF}3I8QNDfs>)kPE0)IgKB@5ACeOBu9wrR@_TB)2y2icTK9|G5=w;S zqYsiTKk{NUA(41MxnR9&AN2ryjN6W%p~k!KrN_bar7H?tm0a3T@PtRP1N(V z3C1%_mJ5Ka#5e`TL%|zG`QC{*e)rH-N1<@Lx&#mQGulcE6NR;-j**KqhoQ$iYEl z35&xDR{DgHaALe`5gt?MWGv1ysNL+xAi?T zL!I4I;_;HOucOa4%iDSDr^F+Xs-qQeO)f&yO*o94|1%65Esqz57O-LkZM}Wiu4d?F zq)x1MF+h915FQMVO%+R|(O7o(bzcQJr85wivdIClf28$uy;l2Kzx#xSB{nOBOolk! z$U_5%PW6&yM)AdX2GNqkHxY`F)$rbesD{up5G_s8;f^NhcH?5E2SMdb0g{kyD=%WbRE< zZ;9X@>)Y}prFJI~S<(qJ!QpK7Os!WPZ-=R)cD0GeGRDZ)4QcWrz|U>1gzGZuRnKOX z1#&C5aA7F&rOyynp!*uXOoPciT$#m3$Lp$B0MezLv6={i`Ur+Pr*eB+pH zui&&et0>t*L*>et90~_ex9IX%BjB%w&hID^lIm8txH0@^910Q{Dg{}suH&Sh2DBOQ zja8mQQJ*I(ajd$e4I?C47**pLiBV9Gw}jpN&P`fOeWbDv*{7ZW4zs_StW|T;?sQqh zFa58N>f20$Ew_o1eebohom5%@e;KIMfF!n)1jGwj)nPFMcyBJXRXVV(o-h@G>p&&O z<&s+7r`}pUYRvF4)?{Jb=#zY%UY*@5$OMg8dK>+nG59o90BC@f>)5qbir#_BTaDU= zs9sGADkT95Q|O_f>NWnf{~KeK>DaL-*eZw3`IYr<>3!wkgdRa)Xc?1Cqps70+odw6 zb8s2E)%n2J&udox(zyD9>+?2WcSTr>|NYDivWyVHbc0{ESr(dj3^O96w7A@Jsea`_ zS9C6qh#+vv09^5${YB5?+bwlklu+pdTICCO9@h&H(nuYGY2O`P@Jgp&1)Z!we4ffZ8p!8(Vi>^}bQYWwN@ z7qr8T`|d`7k);5XAOfry({qb>g__zmrEAnC2EDEWAJSypbLdBmp9y}+jsZyrnlnqr7<2Kxyld;P%ReH98E-?-M&&H(CtsRG}d}y zSQ6p*V7*FV1)h6T$JoVRujgjRCjBPaD_DWGUG$F z25zF{rag5MJPHBIdk21%Y~)MkOWNb4Y_xdpb&h7*o2BxY-lT+4gF$Ge)=rWi`);=E zWUtR`qOWx)*GrdA1?F054-{Lg%e&t1NaLimalB*Mmdw6VF8mmfU0z?m3KemORs^Om z7`=m^GjL(Rv^50=HxaYBK}S`y30?Pc`bTO^6nd<28ac}2wwUz52nYZ<<$v$lu70{O zsO6=iSMmHxmnV_HKGA)dhYP0=*LX>cukM=ZD2XW7ByK&YdhTo$E9b%oP)r?)K<&j> z&tC*~1-3b!ai717hQa|nG<_{T5PnM~$}FP3G4ZK5>*f&|AkFO4;V0|Ba;23dG&7P zq=@$}5XyuL?_Gaqy_UI|-j{o*Z|PGNzD~jZ(_PJVLVo5$S1}`lw6P^I@qu-YNlo3c zuf*Bf6+eBBR)n~7uA>{K1JN-aoubG`={tUzX!HN_qa z+Jt81!PFrnxZsyRv%~hF^lpvYH`4K-|PJIMWgfHhR_ScdgD&lHwenCNTOv;6Swi@lV znkT^7vP2QiSNgc{3oWq$ZBN@6S3scX5s$)aJm)(aS)h!&5v(yq%nDkX&=T|$-skRg z@ymkNPXy*Geiv}BNF2*_^<{j^VVRO)*NPB_UK?@lH;!4m~4uaq)g)$$|JjLbAcYU zE>F}*w$YD2xmpI!w=w?o;+gIURHXz&+}ex!#2e!-q1rT++YX#4_ocRhL2>4Se@__*S+?ilOJ-@ofT$o<{y!*G(Wsmgn`5pmLQi3+wbTvF-0sbebk{Z( z9aJt{hI{aMC&QN#E? zb*{(&R@Jm(=ZjBbKC=@vjs?-=o+|nU*k@^Dj+WQIxP6gAg-}<`j3WCmsyEn?I&E0c}zyA4tHH1$$C!eq$@9U+_CTka3e?haU00rzNu7vB!n&4XHy=c|MP z7ooK;U{ES#Be2bem}mg|;iiz#Xw`oqSpvr*8C&E*F~r#%gOhIfl?;b9%HJsHidK3B z!rpDcJdq`dk5*c5qTy{@ycn*T^!2_Iq~Ce_@kjdAwMtqCUE&{KTzdGo#Gc#Q_)`aI}+Q7J$m4w2=A;7YIi~jkRcSq{st=& zP=2tKM>3^+@JfqMblrQ&Kh_8@p)j3oVs;u2WjS|*qaXK28xT(t+|(Igfjx?~ZnBlG zX%&YU`;~~{&BGyobM(6}#(u2z31X|I+t|LX`K77XwIpcA9j5mveQ@fTsmcpR5qHew zk{nGJd%7*Z)EH)~OFVhfi|c^N@VLK`26-}xWu2}zw+4v?VeM`^*1!ZWEOC!WJ;v2< z@LWNTSlO&UHkW=SlPhBPn;*`~dS=A`(W%cK1`4X7^c*9aQNXfw)+pmrX;1!?zn+Rp zDWYe$i}LmJ3jR$iQH2d^v6-lgl^CZ;b-D~g!j%=~YoQPu4YN$QzlE2(>*GZ>=CWQt zwFfdn$b?7bSH92H6mk~AdDqH1ngY#fd10UzaEi@ncG2j5o4%USw0CwF7Mzm~{aA8} zmeud{#Hb_6{nBN)?tzu~j?4(|6OPqg&fF6MmqG&3$LpDTC z)doYjjtygNjou1s6hdPaGH@a`s$TLYsEdb(6NbH5dLlO+C=firwnP8kK`)hhvjVq? zJLa0DL=I8;KNQ?oGH3LoTCz zR|AU4@eMAr7~?qIDo~9rn!9Swgi3mqes5*yf%o~Cd%{H%PMMPS;Zg2kli?QC2MF(q znfvcth!Yoz4=?G}Bhr8Z(&!K%XGoZ=ej{N00&nMj+M2DuQOrm-A3bM{=L0~NWa?7Rmmh0QLO#okUKk4VZLGgXcTs@s zR;`o%kwed1lkh+tfddaFYlgm>d!M;SAbEr>#QeI!EXm{JQ zmn}Hphe9*>@@e)a%B(UB-?OGE$dk`|&G$2-);g}rP#|?4E z&e*cxF|rdkR_6kYmaK)+gkrW0L+*)SB{5cSgZ9{)&aOtFh5JkVOh~!1nH4NP9`3I$ z5bl&a|Z2peP80!X^}X@7u)im(9sY}GJ}%e;bCZRhs-~y)t^pvqS-F+;0!f9~ zqWr!6uoL?5qPFMR%Rz?=Lsk&+z4^HrO_d{}1=rqBDwkaR&~)l|DUsIx%ge8&S7^{AlSCjHO7YqDz%scDO2Nr}AEUFj`qE0Xb~;dcEj zht;t>_nFS4GTWLID|Koki9pbs@$?H0Juwn&AUm?I{sZ$3=X2oi(VOd_+X)3zPW&>} ze@uFKJ?ZWLlGhMWB;?}6EyumPW(0lI;O9eJY*targ>FXhmo*v5`Oiw(lt~QfRFi#@ zMt zRFJWK8sU`S_H#I#8^e*ig?qJE???-&S`2TiJFjW6-rj{aH!X9m5atz*x&q&DIPr1! zr;N7kHv?<~EVf7YtmJ`CxwdxIA=%4zJnqP&2J>zoD$^qt@jO=PV`yZn)#fH#09?LI ziaRH}=A5M|)!c8f)C5whuf&acBY7rDVz8@!Fl+X0<%Ja1orN@0K05Bm&=^}=N1WAB z%?BS12xBHgi@2uHz{zhZG{TXF$r`qQh?Jy*3M%rP>I^3oQC9T=NTTSbFjB7*>AXG1 z53S1wibZ=^o{)+R@YICb028ccM72oJTtdIt>5#s;oV5-cLq6LU7McI-8dG`^s?$5% z^jXuAuaP!fL?8#^K6-RpOp7G#SeinE|}NzT+k_T9D57mScmdqo>m~t zt^X}dR9P=NU9eML|DVD27QSPoOiu3)GqPjMW;KU$@4NsBc+bkxVbOhpR9iX4T@%I| zzb7sQk7I10-v{s{q7d34Gi_~HbLo#P6(%@W42zgxRk@27LvV&T9Dv`UkU$c-XPf^3 zn03e?CL;s`Tt3R~+;B@golA~n9~c!pExTMaGj2E7f%$qV@(i0OCbkb=zB0W`$DMT( zpcl8ib#$?E*igxLghM^n;s1Gf#?EkzSJ)I_0Go?zyLhOXt;q&B`w@-+nP;=gM9no6 z=+ETR@}9x|KM{ZGpw)hM_8SUJaRXlW|5xtmBML4;Jfg3I4^%B{U)`rh>Q#Qi!omm= zDrZJQYwLPXW3Km^HPQE~gqW3;Xo;psvj^jwm9d9>6g*cBC6@SM4Ba~W4z6A@jLKeg z0PS!;|Lm3)kvtvLnlWX(taIiy?+axHlSKH@DbrDK?IYj<>PYEJu^Q zk1$iNMeEvc!vZc^%|?ZTq`Ht!J!)W?zMU@SRo&<9fhwSCK%u8jC;1fJU}%O(pQ6@cgWmj_7-8x#YJX1= z?^y*^J89eqOd_>IAtsRwwSlw=yDLw~sH_RsZo#Mwg|eLuA*R+;%L#h+jcueE2~gnn z?vYn06AytC_K=GL)%Zu=&YHLe*v_ag8V7h3e`z#fE+W6%{HtC47TmZ~8xp@RkwkpL zmLzmGl&r8O{2y!=qmC@U-V>}O;k-8bQHGQZZ5@AjUDFn4nO^gotTWC4I-@9bbDw9ewa+>5&i(H9z4!ZZf7}D7*Ise2y>>YJ?6c3Q#!bIYzV(Sy zhP}7%%Fh;dJ8tV4dybhf|El`c6F1D<_2sf3ZvMXJio+%xf8HCHUhnFkd+4iSe?9-h zr*1!~&)+Jq-PUczH#5FDzhLFEH#Xff=d4j{f2tdE&fEPje|62NmF-vmaml&MADlYy zuKqv%bp47yuX}X#W6!NA`fmT*?`T(dbo1-WI$yY9w=>F@Uw+ud1*0zRHn{1i)Dc^A zgI0XAbohG*FCDbclxxzNgWOH8J^1*5BYyn;;{CVX^xTM>&fM_l;r}dpe8g+HeTS64 z_V%uA2fzMnx9^7j_~#$zKCouUw|!69cJYQz%L)f3?zy4s=MBdU|MZKE6Bf_;c+XeM z`rKOcP4~adT6+DO#0jhBue)sgkjI~?UV8Z#F;~3gn60&UKY3}Nf1x#xN6bcyPPzlqQ~)9J@b6+o8zA9_{ZMwTs7ynr*G?f);+h5f9aV0 z$`idWyJY5@6Tkm#s=MU)JBHlw`Eh$}oImu+ZV$c`zhlM+GZ&Wh-EaCGcMt#b-`4Nj z(y#Wyhx?5<>XY5;KA+SuaO{a)@BI0|mlnKy?UEb5Yd)>r+)IxCX~Mo&FDky`qh)&FcJ@WIx9UNE-pwO1{gz4GdfZNK^G+(*_{Z5>#9!zEK+{N4NW z_PVR>%Bm;+`tBnio^kjs2cLf2#)ge^Z~p$Jk*~d9@@diSJ8w9u&1u)a_|K(>oOavZ z|2TX3nxi_Lbl#ZMq!GVORvdom7aJQt==$16)9-yE_4G@xKe3_uo+IOTZGGdqi!Xm` z>+v^rc)xwortij|{`uU=lTS>3_U#$2|FE48-RJcipZL?610OnbW%lVepFE;r-CusZ zW}j2%lnhHAa{q^2MjvPcFD=zvsHH9hl7)6fGS(eBkNt|M+0}jN{%d8sG1kh0j;~ zx+j!c=M_k>l+?><%#o8uABIM>4sbTb^Yf0`mKW+ zSMR;C=(|@dKfCkwx-+WZ+}z=^hlh>7<&odkyuIPsh3|j&^4fd0p0J`rL7S6q-sh)I z2hAJRIC0m_Pi!1}&>ncqameI9jehZ+`#+m8q&-?lxsw43Grs)gQXN-k%zkNoVu?^cW*_4`woFZ`h!>U%cV2gWsI`uk-h~WB4}*tSDaBZ}wS79`NK* zQ@D#_OpQ+ko&@a74lwLG= z_X7^i9`d)=1Km&KPHeD0ZS?^-`{%!-45dFZ`Pd+yq$!|vBzJ?0Mw{&2xrAHUqK?}ZDiXSNw|*?r&M+y922 zKRNlxS5CgDV)7IJ`f&W2?GAY4oq^;3RX%vxz%TCZdZ+92<-Hr8{9@N{&VR4#(O=Cz zDsji4hYwzV`<~NY{IqG;&*Sq(jLlz`_;&c_<_|kwUUSL#gFC*yY|@zT`#!q+`~fGt z_R6D5B$S3o#q@lzs*O(uUW9= zof&gSpZVLt{nqYs+oo)D*{hrP>QleEnhkHpy7rt>vE{}!JB>W&#rLKz zSo^op_n!F0gY$*I~{y*%aXk=JaJv!c^i(oXyvHYD~`DR&}pB|dTYW5r}y7&-q(LP>gR`_UfS?L zbyH^aw^xo__}cp1w`c$T-jZ8SS$(C^*!X;->%rwu(fR5vNi2u ziM4|#tvUJ+58OAS@%{JC-#De+$KUoj^;P`z=M(3>zUx|7)BE(Dc3O4w5g(qh_}d%n zevJ1&bJls^uli(Jo5gjFON#IP%XxcG9{td)qKTUq{cXngXU3mBEp^2??O$H~Mcp1h zE<0}IvuzLCF!H?Lcii=$hufaFa;Nh*EPH<8=y#4yw!8R+=CaAhUqAiKOBeJjSheZd zie5`@{AJ*v1zRRG);`&QU8NT+>_2a(`ux!N*2ar#Kl|c>HwHa=dC8X5NAz8A((k|i z?)*PBj7$7&*vs?ZopQ)s7ffi{qki0%WA@nT`i6rZt@_v4PiMXM-9hszA8b3n{Ib?A zttb9=(g7_m-&MD~;FH43e$AhC_MrveE!c46Wmj~4V8(;7xi#-UIAY>EXFgs&zvay8 z=3k~=@%)#S-QN7e-S>7r?Yo=09NN0@@>#i!$KHI+u)VX1f~Wrc`MAecu6;Ih{gyw} z)%4n>b;v$%%^&*GD^K=%dc>hqe!qVHfCJWEGVGq+J2mbzWO4e$cgyGO{=3-dQ@+^r z&L1lCJ)c`M8#w{7s;f4Jknmzs1Te@Cz z%uho~x}T7KXZeGlW}f+Y-muTc@BaN8OQt>ZCvCdF zdvwzy7nbdR(1=4O{ZM=I1>d~#P)*Zmsh)#dy3AVgYMU*8T3GYp>8}i2_|2W$j@^CX z--m2FZvB|wym#vLA8tM3%pcRIUJ~#1(5ky1=+tlaH8=mfc}r?Z$$6iCwyO8FF1gqK z$6bC(-<@}U{g(D4PyFc0rlskzkF_~t#MR$+TRmx2;*Mb#{ycu-wP)RYd)>6yT`$(` zJ^S%(=RNRA=Ie9+7<+N%oqP9Qcg3)p!~fEy@Ytu$o;`T%H9hy3GJRq3npY0~Y~H+X zH_S`)UUT`1e*bQKdgLd~f9N!~VQbyA!+)KB>r3CgKYHWz+izU9J~w>d_;>5Sed(f? zo_pi&CvLfU&JVqBJZIb~PxqKS@zH;8+4;gTlQ$oG;lAA;N&occd6$fd&sewlukT#( z{nK|ob@NTd)om+p>wVZ^Z+>*o2Oamj^y@Zv4I00Ge70)t=N-3oZvWZq?@W2*n|#R! zBhrWT`Q2rs_TK06E?*3LeQV>i_l{ojK=;J%u?Jf=<EE=|!DA18>$rz5U-xv&ANE+?ecj9xHVj%n zc<0scZ|-{EpPs+BX5z4aJo8P>w&>v&SG&nB9254z72t&P}a$-_*MT=T5K3 z|Kzq*a$7pNZ4Cv+J9ko}t7>$E7rF99ZdAQHdx48Jx}#k6;JyyoBGbC0tA=6c7CWlM zj)*0li#u21XmdS$ajw$2Lg$7%X5H4g8s`Q##gh9|vfD!bEq1Q6b7#B6wuV@8S`3d> zi<1t2L42mKE9gL(mXr9mi*q0B!o)5I@$W+CIyv~`+DvxwY8T6FjycyM;}V(Vwwx=- zxkS!Ys_<*G`U z%N{A0OS$@#OQl?6%3ZL)6=W&ar`~O@#{W^99sav-og3s_lXJ738{*uOfz&N^_`1G? zhT)mzP$%w4=axFxka96sUg26}HL>I<`Ze0Qb9QCvW2nj@)PBslU7c&^+?M)ri=FFR z?Ft8zUhZPsj%EV?%cjJV)yZuOT+sps{t(9)EOM@gbNw4#WxZQ6m09<8ZVYP5#kaM# z0R4?~UF#`^>Ydg?1w{XjrZE07Y95)^U zCpow2-_CvZRr3Mu+|99A63u02G>1RK;y>O>&`5nZc*)jKg%fzy<=Kzx9Ci>Vzk@tl z3@Sf{dMpAgEY9Ctf&5}-Xr z(9$`?$(2|Bl8hyu^I{{`n~IIqL`7*3SG=qGA04lToyx8$*9+x7Y2hp2-wyk! zZRip+%Uycka+k-M-mlzEqwL4P7xaT}0==RdEpfrO&doaqX+*nz6v|z-7B*fjq<{6O z^VB)HL;6F0k5A!mh3mW%(lPpphMz&)Do;S{Dl=D&bk9J~jU4GRAC7SDeVncXWCo8P zjC`{*hr7%HIHwJF*>{J#=KYbLF&qtbxLeD(bgpn00X~h`-bdWU3(&O2z|Zn(SB(lt z6lN#IUG8u+F_%E6j-eZOg#GHS&ebATtatqAuPZHkOkx{@el_T$VIzgMn3>b)8izEx zY6PxmWGaX1{-oG7(YMcvU4CP+%WeYgU&XHZr(&0Tw#el=7P&lN`k7Mq417u-SLQM& zmLdOwvLAsjZJ?i(Rp~E=f`*n03=W{@p#!)L=t$@m#FJ>a{~Itz-7d5#R(^@y7n53# z6=IZfZ;&yJW6IgF1#t`_puH4BH+mZMcu}c?AKTzUf`4MP(1O!_NbZC=ko%Da@F$s! zZ_6YXKzMWP7t)FyP|>&-n7f&Omh#ViZc#ETMY@3fwb-TDMfoSz>SFBOsGoyB62?)e z&lm=Di<_t$b198aqP#Owq4WB? zD4tzEU-NNuReq!5tbHD-8H#82F}Q7x(3=+>DbPKxu=%e_&sQp**;8R|xx#GH@Y$MA ze*JNxpPj3AbMp+gSU$TQrS=VGk2C*{RhTk7V|ez1->AL$7`}PTQ5meUZ!4g*Ir?BTZQR5gT)GSg@z{#k1NbOg{f_7KbKTI+u7)y6y`c8 z%-0&f#`x6=-3s$_vBKBbdgPETcPyMVgZ?Ji@;^|)$x?dIM3}&||-fVW$TTQOTLGQ6kx)5ZMjXmGv4=I<4{FO2??!ra#iGoKjzQla}$VXBkb&knHs zx+_d|wtRalOm{WdQ(?Y?!pugslZ_j`+3-yYGg}qrel+-tLbpL-c8kpyzEhZf$>RN# z!G0>&JWgSLu)_3Cra#j71B^dZVWyA4MaI8Wp<8P7GZbc*E6kl`{PT=|n!@J$%&)&F zbe|b~+~_Zw+vQE!*DWTA?sitgyL8VYSl%ctBn3zgDVa0X?{&H zfA&@A_Ey+D)8K4_(-dZRSC~0OVQ!YuCmK9l?KhvIFhAe&o2@W=obit^{sN;PsxWnr z!pyS@a}OE)PYTmdD9o-g{v*b}%lHLGuThxy<3fev8E5q4)!+Ov3f)45sl^I2CmH`J zqo1MB%~O~jVsMCb~4=* zW_y|4jz<5%^zgWfNB&<5Q(KH~{k3_kw)@oIt^L1j@XreKzF+R5df9;r-Ef0_4W4QI z3l%n>ZS-XZPgj_`U+p%(qcHP@1R9hSh z6{aSsUS_7ky!D&heu}#Z2Cr0@x>aHBYK7UGjDLmE_cOcuD9jw7(9JRW428Kp3_na^ z`e23GNeW%Y?4Mw8j^%TV!qj03bH05)rFiB(qd#iU+IQ-HyKX+H@l3sE@Ee8cCl$JX z>-99%OXbu36lVG;bT^sYG{sW}a|ZKMmEOFY!t}l-x1Yf#qwk|IbFjj!!PFtfH#~i) z$r*HqDV{PsKV5M*Lt(SQoY9*PPhNmYeo_@gU;}M0;YYa|Oetu7r+r!{w zh0e;8J>2lw3UdaX(Q`AEo;R4?U-4#-&obO#`XI$K9&gZk$;Px^vu&+@OB7~oUejEu zcyq$&WeT%4ugThcruj@QU)JU^&gL(6?)LV+DZT^zB`AhzJr8}Fy!sh!7=8XTm!rUVY-CBdsDa>D`>yVjY zhe|nfFDpzp>H14vE~b73SVom>GVI$YnDMn|D7>@SH(sFl8`pFk>)lFh9xk z47v-=p23{K^y;J4uPYTcx2RmIRbl?$3bWIX6*)IXVdfl#*>9Aee%bIJ6{h-X{&|C$ zK8m}0PZvAQiG^COxr*m|FA_Z6M`0$d{OnSNd4sv*PE-Aj3e#7es<=USwc;6rIgfWy zJE^{AufM^2RX*FGc=kJmZllt3Pn!L|D0H6~{-(n0w}$^qVd@_SpI4ZF-{1!dGiR#b znU#vC4K}aP`ft8aVb);t7+v2>PgCgjG~6l79i;6&bA-aw8&f16saF*?zoRhsyulX~ zX4Wc9zo#(&qT#O@|5=6ZErq$a4S&;cqc{K6=r1d5UZ*hooWjh4$>NV+H*~j75IpmZ z!u(!_@2xPkkKqQ>lP8LNwsw-h+~eBsyuI`k<)5~*@&o;P3p<8P3 z@2a00q%iH_P{lJN6*imQoWb;1)z4qPo8yrgp)miD!seaS-~9R}<$t8Gd5V?uCBqG- zURFH+n!?;Vh3<8QX%D|sJYz7GQ#{{C{mk|-c$(&)?r#2j*xT^SR4->RZ_r(?^pwH0 z!Td_4yDJo?4Q4#NSm{~An+@g+<_)@4X5V1iV8&q9V6%s2H)pt8ZTbeY26HBtH|Q== zx#krLa|ZJUv%dV+Zrr%E)KmUGt-oAZR`4u0N8rd$NE5j1ZVFQd(*`pJou`jhx%@5) zv#Ye-<_u;%{U>WbyIcD)nAyYdCWWaDqQ&u0<>%(A ze&$~$zed|@_5p=HpVV08XOGtLExTE-ukL|8r6jrg6sF%&n0ZoR^HawE*!Zt1bXO_N z{GhP;1BI!Z_Y!-VB?`0UduyZ?8@*J=v2?YKS~Z%2LN|4;tz$p2sAtf#2G|6g!!!jK31t=waBBI}`V(zYs)(sCl7@=GPjo&szU z;1&hl#$fvxlJ&BMAz2-(OXvoNYTBXUmg>Yd#*SsBFD?bFdR7m}Ds zwyLX0`}Vvj*_usW$ZS(d7NBKYHraY%awQT}F=upNLlkdqQ5L1D-5R%%8*X%SLp?U^ zV9U;@*gPX8kqr~c)@tsg!3K)fa@jP2ofO=(Asvkr?xu(pLPob$a3hDR$FR+%^~B^N zcr-QHIxCr>v$`*X23uiBEhCOKvNZ$=^i)x=)*T(mSc#WO)R{~ILD$V0D%>L5IG}~i zAaqQQunw@-L+RLh;`eZ%0Ddz^vOco+WBYM}br|h0JN8Fyk8x`&VZNnEwoz2-mUz@o zc?4(Mpq*j}FwOdIkJHoLDoxXuUPh-a&MGNGpE#CzU2Z}R(lF-JT}*~{e4Avx4;fwj z1B3FUw?^qrN+*v3)MuG^kVajI1iD#EOWTd4yIET7SemwIkTmA&(<~Pc(&=*#OEWL( zkWLx;5$IZ)xIgJb+X(J;N$+5E+8=Id_B}7dH1qTJuZzfVU?QEmJtH#rTblO09f|Gk zDlajq4bz<>y2~w1o82wVJbYeE(f%WHD@&8_W5~R^8lCC7NV+DH?r3S+L~{%5 zUutQw2?NZRzKx5>+-zyu_r6Kpq3~Y5!DL7$jVIGSKD4=0gkEK7+C-=V`4UT0o`<(X zzkRyG(v123mL`97gw7ch<>_zK=Q5*<|7cj0VO|4`&UAlEQ;+^pM(Q_0r<|vA*5vad z^l2(F&Ad1sFim^D?r5Kfr(`i__>$ho=#-xrNiUA1Cs>;Ka=fBV z%1^g6?fLl7<{+apo-anycUhYC$;12H&eBpA7$coBzTTNHhAW{nFE(n*FfVS%@%~`1 zzoeOO%rYTwM_lx%i-UZg{`gP0$n(UXwInt$WFo_9dYHB3SK3j!K@pk3_XIlC){`fSn9bRTS zmc%_Bjg}VpX6vnQtmm_6g=c$MV%ycG~2;h;}I7yL*^d z2TWW%o!1DaC2mpwixWbZe37CI&teD)M4A&vuUiuFhXXt5061fkChm&W4)b!cwnArJ z&~NgY7bTb$`G`M-s5R0Uw|&#fS399@+~OcU$2DKdLp;#kt4Y(0Nq3W%y4Z8iAYT++ z()8<+OG4cy7@`lN3+U4f9@F%v11`n^-Rg^WF2$9PbovIeq)GR&qD{UgLm8fA_%!V@ z%~+K}$*0SVE^)vB>g9_f{`1C$bg|#7XD96a6m}sYcQ1IS!6L$KYIy{_P2|VjTNMOA85a`^=s;)h(W%* zHxb)_uDgycq6=lxS!QpacW?cbX;0R zUUXs5+vf#|Y0<4=X{;_H<9THyCZ(2UJb9Bwc`a9%_BO?Tt2?o8bwu4MlOsOZ7(zSI zYY^xB-ZxzKC9UmK)8zS6=sPJ+`+TL!>$X9{r(IhuFXj80ZxWN$D@8`zgUXYBzU3kQ z*Vc**%Y~OzB`vzoJ{!R%b(+<~U0vT%$q_?x!N*pXEQZ5KnUUV#m zq&HX@NiPDy%dq?+3s?cep6)O>GR?er-{)mGAbL9Iw4PpOZHam9WU-ZU;k8l9NSs|- z(!^=l>pI-bGc9!UndRb1nv^TvSJL!{2kGitILG4}m$yS5FXP7(;>9pZsP-d$H05Nwz?U`Ej!Wk z6MGcdmXSyC*1*r)5eT(QfAF@QEp>v8wN`ZkNl(?FrlfGKgxI`SpgsxLoR-zdbUD@Ts6^jUp9VEjgdQ^t+VJo~-Ng%0O z^2Q*8hlBl}eP9Y36OXW+;6+YK_NDK!Xw=y!q+hs-I3fFmn~>g(X=%@xJTcAoJ9zM5 zNlUxM1j5UJ#VMS$*J3nirs+a~>2jRey0I~^)1yZZNz3?y0gke~58&Z-IcZ~>{_KT` zzE5*8g=zW#r!edH&&5U!_PV%E#hBKQAEtxg z>6rJ5F8yB`(S?A>OS#~gx7iWbFR$yM%ryO{e_n-lR{luJ^Yxs!U8|D91KT8ru>NugjZN zrdgJeh?_6tO5i^IM=cH5#1&~>PzDbMq<=}d&?YI5qRL;N@6aBu z2h%(;H<0!z{qeFe4)}CL1^JRM227uJh3dcPVj+M~(#fbUhH#^^E`6Gn>C-5>q#1`Y z+(44fwnJ~3mbyli83*a_fJ}3~z}MiJX4|+Dr`Mg*q-iO8T*q6MohN04ju+>drhb9- z1*xRwC?hc}=orWsS$|=^#T-NcC9gicQ%sAU znl?4G!#EALn2^WyB|@IAG7^)%VZU=&*a~E-B5j~cH=)xm=jxQ94@K4{r4OdnHe-&k zi41+~0UxL*aR&6hwHjU9q}pV8S1-+qF3Zv-GA?mW?(@ZyT1iV;Dk=kdv9%@U+Z`E^ zuRiNIfT7$CUaNG`#rWWDx?&xRB(}JidEEl@LE_x2r;Med>&j%@kUBcNvWhf`e|wD; zadd^iexdnHe+n@8digF;Vp{yfdJfZ)7vfAB>yZu4%e&e(GCqsE`9_~1BV)U?d9y=0 z%mn?n*vd#h84KFvSyomiP<%rdA(U|jf5@lJ6Ec}Vp6fHDOWBt#JD+L#Ja9nYK&AqY zlP-SZ57YDqRTNyWFTPmmB_USfg1WZ#V4lkM3Sm||>=^ijdI(?pq zlWCs(bPb`}*Kt5%YkcxBR?9d;88iVId!>vQhjp>P)dc{jMN$^#J9OyKz&-;=dr~jO zg^@8|{in^qhi=C8hm{lYCfe_3ENUKrFV+{8$rRO}sAeuLJuiInzAZKM854jkQ}Tm*pjCn}bPRRHZ~-Vi<`7n!m)J?P@t3 zA)o1cY+PbIafIc<7fG0}*a2jk{x4sqX{qa!=0)EyPphU4KF8)kd2K)8oX~aEzDb|a z6#_qziPSaa+t#=m>hk1uf>6p8FOWH{#L&g0P0|i|l##UcapJCA=dq$29rI(6amKEv zR>rXGXu{s6OK857K{UiqNyiIBo^58vw5G5uaD=*y1)5dh8-wX>7Gtu=G*3zrO1Vsz zc%{WhWh!K>V;NmsuWJ%p^PlMs_4Q&$(wO&BkAC8#DM4NDkARXcHnCJjNI&_9Y4M@> zR7p!-=9|b{AJMXh{jNupZu5Cw$CpEpdg`afiuSK=*DkQn3Z;zX6)O&6%RIbp8?#TG z>%gAw+SY|>i<{WN1|2Wc)^xQlB5{sah>Z02f?^pTL>Egw)Fpj4vnl1ZF^&GOs;w4X z%41qBY3g90m-&_0oIF`>N9EcICi!Y#;~@Un{Tg|GykcAJ)iW$(4K5PG7yXF;sg%&A zzE-YWO&Ol0Hhz-6x=kCYch*HOs|)&2XxC_#3)iO5zKx}{!%01%`6+2>SJhf}v2VIk zt~ev1?G58$AYTJ{<|A{Dl=9i9_s7~P<$0D^Ta|d456p{ukjU4#6-wWi*w%)9hjwY7 zWxUSHC^Fr2&PILQ&Wat0m5cQxO~wQmW}5O%)=s3YR%sa}-M&-M$K8^XM4tKa8H)F< z*xDQMGGszX-8L30u>>Bvx+Ey(UveY)1NK8Ro9k zqx_vnkS~5F!dP+5Gt`a9pmd(@N;ECH_{1LDU%4j_n%lNFZtqbFj4eiqt@6SB* zhx)ksN?T&O6pQ1O;dSr;i<`(4>AC^S(mSGC1$pwNE(W0b9HFEu8-k2H7_#^ew&>%KNrcF(79mH*!%!^3pIxy`pF1*0d2K&MO1GV1dULd1s z`hSo4Pu=$Iv~5eiSoZe*`#!5>3H>jJfS19r5$0=S7k&2kI8tBeYLplIHa{fJ=Q4y6 zw`q~J7gR50>8Gy3tFDX}pz-j0t*H>lP!aGc&*v^YynK{T`-K{L;j_;~<^Q|5eELQI zY-7G`N5K)SLt?d)i>%>Vq>A{>9^7W)7l?IX6Q8OJcAd!LsIJ$_QmQWD%6e_EZfc9H zSl`u69<~IEO&%$(<@%LRBHI4wE5}71Y!`}SP%~WmSh;+WF63)d6P$I4@kGR^FKriV zmpq6|JK_SG;lhbwpo!wV;V_&!*oz@%m{!lwxJkxILEHxh`jUw8n~ut70_&?iw!<45 z#18f8=nYGk2KGchA)giu{Dnxsmo|&|P|xeTD^^~;(s1FIaRp5I>W}sh$_wAcN+{s{ zx2aJyKk0t~KOV+I45NbRkhh05j3C}(zZ^H-QTvhjOT0L#Fg|UxiSVubBnSTSK0AtI zObFs({)iftm_Y3Y{)zoKCLE;Wq<^Kdiy*}DInHv{ljpf{X#fGgvO>BOarJD6 z`YGGNKMhxCAI-(rA2ZSwP|aWBBdbMGf4Hkiad9k$8wJC)K1;YwCWx0zo+A9RGSL#g zR1|8L;|l#3LvemOS8>u@b?1(}-ZCxYVu9dZ>5&s3($F*U81(=kYzQn&&!XM_BXxEv~ zb!lJ9H@0^lZ(r)W91|DgOCnJi;1XXlaZsN))^Nm3;I9r>!l(aSn`8mJysN}Q%yxKK zzmicL4|Sj})o>}Vn=11R+7o%5=8AohkBk@OBl>bb@AJpJTP~R1U;4+x^Idtl zOeKi(bnR`}FVYK=$BX0KjiT~W zAIb7k9}kTucV>kAl9C`rFwr<3sjqmgS;c(FSAVyUH`hmbkk7NOj&C7oTG|^vzUp!DFA>%caq93OB#t#T z7FTfUPpb*97c|7@q=bRIUJeA8crj!VKBMGuaRk#9kBjHA^6mXA+Tr@H>Op?E4;GjC zhbP-652k5|>zh1?i+!8$cs_)-_Ycp8y+4$}C#MDQkJTrsLH=kRfxebUI}qiWAD@5m zATIGwG>94E-akT*!(nD0;=nv#6mh#qJCx_i8uINy>r05jllp2BbAqcr9#G++uE-;N z-j?`>{u$-tf*bfld2P+APX?Mtz!!h&+wyfPu_-NiXobrfPJKRe;NkPfC(vcYB2JDh zkQrYji>iY0jd(?Qc`%S;e-$-j!fIn+N&gFFUZ|%&3V74zG{;qFKSk5v*H!TR@Rk;ETOR9A=LUwl+e_il9M{Yio@7i|Ghs;{CD9 zqu``<>Qp9Xn3kG~J#!r2$008D0my^61OnO8VJh{+=?~9mdyJ0PWf;IIL%zgs@|4MY z8P4+cXh`92m>&#rF;qb!3NQ194uUd(=R*|Bsq#pT<8z=xxa$~#3es{mL(O?{r+jS$7#;P#g{z@Fb;hiAbh{jx$l?MX{`8=_2hp(4PTKoaQ>k~pC=)dG+EjMVN zo=+*-()vONHk>rBhkIP?xReLg<^7fN>hKiW z)8Q}h5BI|oM(Xp#6Yl`G@(3W0<Xds<#>G{fQf#ui){ zk?R-biwpUiGAb{L1U7U<@XnF>5dFhicHpnr8(S63cZ3lS=kMZ}{89Tdo<-K5Xb;1) zkeRpmugk^auQ2p-Cb;-l-?ba*ObaeoTun=Rzz<(||7j1?Zy{4w{OyU&9i~e=KcrGF zWjOV;cGaHfN9?OTEfDQ7rI^Z#ek|ht75zQm^> ztS|8=7T#ZIypp&0^&gSfN6CS{=C1Z=6EA^F5tx?vxPrbU2mT;@^ntkgqaG3GiB)_d zcpUvtIv{b$UvD2pmKCA18P%1FDGAqGHJ;m#SNdc|u;&Dkt+P~<# z9o8qfan|%D-Vu3;7iK%OOMk>a>}mAn6F$acUmh{E!+an075F3N!SKu*Om9yXn!;$%}w+FSrAN1B>JzwM_>%q*! zCGk+&R7$gxfQ$VLpb%4cMxa4nHnEc`nd z`W^y*cdEsIZU^6&+5W+re_|HA!ok-KB9G7P-D!MBN3EfX@DoJ%P7ObL69$gH;dVDH zDUjf03y1veB@3GN>4_s_=&i1|v!=A8MTS(~+tBw_d3J%H> zGXwfIhJTv^U+ED8Rvf%#VVP=^=nDh*L9j4xDklxbw;cp0d=ms&HUzJQz!n~F(wo45 zx@N5^@Xa#S_te?=f+Emsv~RX`_7jZL(oczV9GsHI0qFU>4pELcPuHjuA*QY0N=IXF zk^$c6Az$wdX+svITpB60r9ChqGkMAr=Y2Qr5|@6DSr-R3&&MySVdfU$msZJeK)!VF z0sWX&s9#hmk7{U}6S!ka7s$FA<$1bMLxvBtG-a^=L?#;K(Gc!qgYwIDqF$df1^S6f zSx6yHfBiZGZRsVKDb0)i{r>jb1AirfX+=HmZKyB#v-k)Aaq`==so6drc=?BZkT3om zab$+S<>>RrV^Vn#Mc@6Hj$~lZRo8dMwn4!qUfGq`uD&YN$Gk!Eqc1w<-zoJ>`x01Q zSCH`em0_a8JKwOp(wu~^B@g!vYI$`ZB=wp9yKg@`fp#e?72{e&&D*CCZ&ir%bUn*! zc`F$5ODd^HT;h?4O^y18pG+)ezJWZ}6?x$%&U3J92+FJNx0{=7`AK|+VjVK8{;`~E z6BpsH>WbgC&cU=y&>ERizLwXO$MBLi3#IWqKei0^DJ8eGjbXg#j~hR9ND6>yu`k|* zIEZqcC!aQ@%u#up2L*gv$f7M3_*e86ZOc!}5{Obzt@@ z%1gZPpv&9S`X~(irA&hsH_Q*~GPD!g*Ah`ya{>)#e zpg%Ipw)Q3dM8;PMO~fDKR{fGc^XT1MUIh?b;*Fh5d>6v|i**VyLtM)nj^Ac47+)yU zy?e@~0GXz}`x+aG3NHGL4iw4fIdI^>LViqxX|=Bl*DM?3vJxi`@+JPLe##M-cobF1 zW>Jsx+ZsHG^W2Gtr9~gliM>8?zB9tZ>sOZRjl0+H(a_M~{iW$k**aH*@-A7veS9#_ zq=VF#mX~hYGd)>x=7(i+8Q+=K{-4%j0HLxJ)dn0O_&UWPbkJIp-r56__`4uL)V zQY)CWuj6CiSbuA8r14z>9^QUMg|-;tJkcL3*>IVrq_);j9us-F{*y2L)gCl^+|}!i z5q-ioS{_09q&?s#F}bord6v(w3wa!l%lJoqx!$gkD2P1$_xofhPkVT$a0)=cM^c__ zQda9%*dZVLw5UhE)*li$h-r@AE^x4rxB#e2MfT+5F%Qp(W~nHEE@ZGM?P5*L5%!47fp9rFjaBjSV| zBK=kLFkq7x=%c!rr>CJ+$%8E78n5vBDebdb7YYJ>E<55sar*bbQXGKH%f?67*j@Qz z53GcZ544B(AAg}@|W;e(#eyKz&|)WUj{Rfi1S2IrCvOr>&$!<=y9-P$!L9Mmu1h(Dqr$X z=td#R({b@0i9kP|C}h7O&Um9W%6yGD$E7{^@*fP*7RMvJP7st|>aR%0d&*1u0OUbj z;%OTrJ+7<=g%bV5T_p%`0y`4 zfb*ROk5dj(G9UN)GJZjkJhuNK4K4)`)Cb@1N1?%f)T}p$#mo1@|W!FC~*Nf}@5E8*Z{P-;mOT z`T2b-l=TJm@glV93;gHzCV2S#vF#z4U(!Ep%#CwzF8LBqtY7eY>G2Ab&)ZjjiG_T; z$?;#xYP>k$Yh7?Y(6_L!nDP1JdL;hP9z(}(aqu9Y493^zFY&;; zo*XmDrw$%72iGTQkGMae9na^!pQt_za)b-`&=)gao^O|sKwSI>@bMAHxsS=>EA6!o zHy|c2xU28n2`lxqq4Ag}W{BH-2`S|Z?pCI+Nk{TSfAId&UPo+%XS)piLuomKBThMn zhXoAywr`NQ_ycS7o47cF`!zzI(e)9JPeGRgOZXiB(AU`A0(s?gb+|s+%GKFMuBKy! zw>loYp%SdY>vFVTq{S+Hhw$k^i+?b{>$feW`xR;~@^c+ISmgE#?ZHYgmbqnNSeCp5L#Z_HxfhNXoFiTKJ@) z;nwrZI81AuXr&OBKAA{h39K}*k81#@EP?)BZpvObw$leYg0qfeg0mf={RcSfO*#Z> zHIhHw5S+9rlP3rHsXRty7$HyENPUMcylxPueG~$-q)^{YZkn{)Zs|}S&!*YtC@bM8-_hpX+c5U^%=!7$h3-FUGqe z=bo#$#;+}3^B2DOgUaRObLvZbN;UNA(IXY`8EYQo^F)7;e3_j(=Jh6vyiEmpGH@+4J(`i}K%)J&^?u^3*P6%e|d3mN9Ho?-7H?li2enUmsZ+qfA8f_p9K+}5_tJPA&$wi>j+ggq z4#d@e46jH8@>nG1O=Ey3%i*1lFVg<7#Ktj=d~IL9d+oAR1dqF-T^ke^`w~FKwf&+( zQ4!Q)8MHitqvh^s&G0(=rq?2!g93exp;f@}NKoAQW!DK7vXuhQlh_|vPGHW1Ip z^&E%Vmw489?9|o9U$Ni0b2T60d3ktP!dWs5!dp< zAG1fAtHwWZOO&I;LH@2fUdjeTdC|w5c-mA=OMi2zf)3bSl15PWXwp%%wRGmr1+r zR?&?l;TKX{Wq%AO-rP*%_xe!P@7LfgT@KJ}M+j~i@G;Ot@JUV1`pLvTAhav_k}3AN z_+2k@#{he+w#P`ec5uUv+5>7|F;(CEb``nx(0c;4r1v87wtefCEiF8^U=xnsGjOj9 zeoGE0?<-nxPcury+p+doJV-UYe>z$Gt8*tG&G(z0!6L3*e_*^UU#m`+yt-8Qfh|FDOZ9*8|Fh#^Ek$-+u^|c0)+~3=|Dis2C{EA-VqxP! z13{nf82Pd;jBy_qgnj##Mho0JrN8-RC$_BhtG)O!x3;<|E@*ht{eyhj-L%n~*V0OZ zfl2d4IpjKumw?Og)mDy)#IbZOn}s+A>J>)Unuv4JqGzn9>j}uw*9#6%v0+Hm+RVKx69z+jU#>jw8Miq<*~k7gQJ?bUU!keK{;LPLdY=BAzyTp zod8ubZN<3o{wDlK`7puNkI^6xl~e~ z<@L`#z5V`js4r{}{1zAwFYnyU_<`}6@}`K^mwro}d|jKPd{Iz-d~=~|m->X@QWv<% zMNjePmwLCykUdpTe;$Y6B{izAX)c&gRfuA@iukCYgoU5_4#}oNgR^5J^c%|)w zpCBxdc>3~jK|GLe95rkRa;H6A`!15Wl23oa?q_>CoQe)0&!C46!Hm zUsybSs+%VH(I)O8OW7DHFaFCqpT3tU@-8uT)*%Z5K4o}NSIa-CFpUUMU+k5`&18YB z*R%fXNW@&i`{UvhY7+zWdw?1reU?Zu_J=zM-#HjS>`~vv>f%ME)q;yZ^=UktO2~KX ze0|{gaF~Cr1k-5kFCw2l@|0ue>>lw~-;rj1GJY`+9Q2PT)?pBv=H|fPljk3E?9o~_ z=2sWPrhXjcOL_5y3EauZ+KBjD-&x+`BcJVkr|vRbh^+cs;wGCuWj1ke!@UaA8h;L$ z+P}sBj7!%XG`Wa;=2wEN7}Fj{B3X{@a>4_ht&ZbJz%Q=CR9xc`wr7o()FsA0HgM|e zc%y*WhFp43Nmb?2H+p?({@1Io=@f&XG% z`Pv?Fal$|5$M)^_qOz>~PAJ+;3PAkP@jnsgx?7N6UAy)i4Ja=!Pf!>K?dkaL(pz_P z=|JAaYD(;TbIRY0Vr;{mn#RKo7|?h0n08`6tUt|9>P&}v;cL7b8eMJ2c0u_t7BPOr zdAdZ;Vfc(oA=8WxpT*<0U3gNT_`~rl)JJ>35&EB*n3<^ZQhyk%I3Sa+@oSCoM~bQM z$1|Woee#_q-se)D@mq#s%%dUL|7k|(;fb5+591UfK=}(H7&?L?s*^$FG{j_lr-K`I7IC-XF6sH5m1m`a%9|%vRqrKAb%N z=wpsm`_f)DXd)lxsroDr+N%usw8s<8kq>jTOjDlAj%5WUp}vf4DoZ~#dWzFuj!g{4 zcK)G51oo@(ZOBBjhPdXB%_P`8806=YSO+bV_AK_Lcj|oB^5bwU{gve#QiEv}%1C{d zf6A1}X&i#H{%i4VSo{}U^GnEAqrzBhD`*9S`qI8JA5LO+L!9RWH}hc5;lXlp?BfSz zd4?+b5N=Ln0N3z*WY2%D90ei3C|;JW~t+nw5^$L|LWR! z{i)zn&esR3Ljpt^W23uskig+-q~j1kn)Fp%MpD&vHI2YYlRPlJYs$<`PB0ql1fNy0 zSwu8nFzlc%>$56!S?oz3u4kj`F}NSQ0p(aW?w^ykZ8WL(nvU&ilhUk2j&<)`Dpp-^ zd73He*}F&6SM|hy;It=g(jt-M+5Ei-FEqk6)To4Tju2?_L%p7KUO{4%-gG zBFVvo>^s&f6&mwkzWw|4>zhjT>qjDKzRrpBAWh;|UDBmXNtq0R-k$7Rl9r+Q@;dDI z>Uv%AncI2bHPf`GRs1Ny{B0o$N@qo$FlX3_M*+4 zEZaK^am|}Ft#c&MI(g;r<@NWSsC2pzDVx-!bQ;P@yYD*y z1(#`t)RDz12p8q(51*^z5PQUJe{mp3nqJ{p2x6Kqo51?_UC!llB#AHN^7@3^O}Pdz z55{GDH+;IJOP8SSG8z(N?dGB@KF85xY7%L%g(l5x#K_?_9ZFm_O3UV&S6;a6+@+u~ zPul~iK{h$&>rxFphmGhR^bgAyS*s}hBlGuo!Hx%2JZ&`(5^#_f=vrNpChfoqLO)1j z9aS&{OyCH0QDhd|Xp-6Fbkl@66Q_DP@wu@YGI%x#B5hjVQin~KbpQMYNy$U()g?+N zyNQJ*P)DzY;wNRp z$4Vy-lh2g~`QniyT7gy^^QDryp?^u!^3uD|Kb5lpKqk;d+8?Az{g#)fFjJNNl%z2? z?6;Jl@DFJg1GXXw5oywhpV@R@%Tr6w11d5$#vXgShBVNXYpq?osB7hb!=cYoO1xI% zzd;w|vHSe5kD51kBJ+so5|x8AiQn9lPE0j+?@J z@P@lBj{8-5^8>l~36oO%V;uiPEu3P>q^-3tpVvhnd&%@@J4*P&g8H0Ep7_~R4=-d#$zTIkuakY`ryxYMb-EPA>}hSWWi@_lktcx z**YtkiALB5172bx7eYyU?V)!zBN}l$ak?o?R z`v(zU8r5t9(hd*XRA7@|3!O0aGr`nV80I&b}JSaz-x-NHTur5W~l~_5F3nS8$(>z>u^93&Z z%LQQ`D{ajSA`!W`o7jC)cTdwi&c%2xLzCo5n{6W(pGY3?y-Lc?F|C0{a4;r3Xp3oI z2GXd@`){n+V1;CL;%ba|l+$rCm1r2e3%5@QO=6nO#R_^19mBDea(a!*%sH~5?|{yj zl##|kQ|_F#5`vfx!y1IeLTI`!wzasWc$=7^FN}Q;>?g5LaETn($FsH`hNR>n<CY%9=jA5d4Hr^u^SqD@`Wv4qF)aA`zvEpN>IqK!DnS7%QeeCjeK zm0?v9=F#Yey7AzKZA0gdLXt8BagOL}zLddMAvnuCB+f2TQFZIhF}|l3lsDDbbJzfV zZ^_4n&nEeg7D!`#yilkAJdJI`&&x=oJuPNBo@nZ@3-_^-CUMcVPibz%&A&SOo<%O+ zmtL+HOChs8%IUa~!}c?c6={^k(?vN+B~Cl~E*i9vrku8+u-%i!%0Z;FI#Q~fu9Z%O z7kGRLF6}W^w=I+B>schlo^NZV(%MvxHaq#l{x<@^2lk>XI zlc#(tr|pXE0c{_KXp5DgGe?~~k|yIHDiK#fU=ca%(A&oVJLalm9g`?LZS@chwc&Ls z&(j~wL+TP+i)T)S9!~m9dQTYX=~DO?^_exGYkQRQ?Qb*sIqiC%ackwb1BYePDwDs| z)i|>bD&+Su17Fhk_QOu$?|x}rGN#(N2fQpQ3fiMK_cKhcAb$G^uK+ zn{nxR6Xs2zoX_J*+@bOxk3d&~A|#QMa>xqw4m6jlPE|Kl4?=}eS7L=#OdR5j&x0*m zf7wW7w4ZOqn)Eg{)*xRQPl3~I>N4N`YxlQOD7`yqJUlV*S;_L3y4rTRmy*%-^Zdxn z)=#MAW&zVtrN zN9Ce%VcGcNfnNcj9OHs-O4%zQZ6puUw`Pr%0b;&gDC-D1NDUF}RMGC_5gu2o73F=C_@*fq#!+1}_S}eZ6tOiIkpKI{u zkd%cqA1f0J{40)3Xebxf5nJ_k`+)yTUr<7$eD*EaV{1~;+iu*;$}O>9xCo#9gtzzB zCAo^g>uO7jt!LQ%I6DZ4q15)vBqHU_+fqPy(;2AowiA{jUAr-Qn;lCft#d~P3M_`m zatEwq(L~&^3}7pA3)|wQRHRk5Rno8Rq(I=^v5igq(w`dJhR|=n!K;4WGM z!xb8iN?091Wdz56k`I_j{5Sa9si0D$5k)oovC)5fPzz_ZlLTKk6t{4o#To$y7L8~S zg=j=|oZT)*1|?kN5bG8vRWv*1m#-bxAUq8hRJ>c(bR(6@)iSpYF=T%^4`(lo5#0ev z+Y@ji&igRAm>r=_HQEso+6hP(V%QxOp)E1mun297(FR3m{0b9wheT+*f_6MEd|r2N z@c0bp3eb3MrGL`^F_m!Fqa)9Z(B>iC1bdeojbrXvIFH8Ug1%Fi^QG5u&V;cUMmq?Q z>;6~a&n`wg81Pe^OR(s>-e?%^+*LU5gfEXpXxt$;3Jd)^8;vuL>oADDjCF)XM&r78 zAILGLhec?=V(=vGW24Ol+=%mN3~r1geP;Qu$Jrr;KR7(CJ#<%NGXI6qxSw}6&h|)L zWVHE!Lviu}LazvISEJEa+M^s}O}QxTe9(RmMNi}JI~{`az}^lUS5=p^({R2G8q>5# zxbi>Ho(Am_#DVi4FZaC3AzT4%B4pm|hkN}9Z3<}2!^@?>`z_8q=-xll@Kf+o=iV36 z24lcKdm#Kqn)#CUF=&UPK~9a(PDM;f^X-6gM}zin(0&tseb3xhw!2NJujE23;Xl$cna6UgREClC4FF&bk@dz8BX zWg7{t)#=F3aD(@_p?p&9^4|4`L#B+hFx;doElD)@KD zT;~=e?d1+Ydttk3XEfH&9Gq$*irCbZn2SK|yLgV;Hdy@$v$GY8u z7`KPdY)_sx9=^Pc#!0@XooKYK5!&gXZG@c9m-2Hkfu3=kb1b{posIF8^wU-oMk^Xy1yK?P<_BMzGC#xemA%9WYPFX-~Tev~%E3 zDk4{m{+B*o?>W5O5k`B?{h~@lcM>4$`s(wsCT+Bx z0e^kaNPCrBke7t`T8JjgV9ErJ<=wiY?tixKiGTkI4i0<{(I)`-Q5c;vMi|B;4VcM zY@ni8xikeUcI=C&*u_|avE3C5sEODy#sm|43HBNlu|!SmMomm&kH$oUMk9%`Jnzpb zGw047^ULdb{(OG3d+yAA&-a}3J>S#Ml$++8+VhtQTWiy=J2^4E6-M=UlYnglQ~8_f zbe7z)PHu=}d^K&(OqBC=RqS${80Io*6VpvZd-RH;Upc07y#s9YWl`j9a0u*4+`U(% z>6P5t$f>NY%du=Vn0*_GKlQ3qPE5ZN^m7=dNaXZva#n6=j@%}&^C^5C&hOUjZzr8< zi+y@0`<(ZE5>L@}ocS zas48@<|$po`jU?lMtH>^Qr)5&C3R8IAE@E?Y*!&FRYjia38T@X@ zUb=`~kJ}twb`RLm1X{WyZC^NL^p>2rf#TIT=xZ|kd(N-es0>qiJ`eX5g?W39y}h%IzXeZALNZE+`=cOB=%REE_K4PR`>Ri54Hn0`dtv-cg_ z(1j+wp*Vi#Ud&V7sAuOCmxTw=P0C-y_CSjHuydPe0h7? zhc>}fZ_Xh+Uw@nV{vz(Jr_=EoRm#-W!+xF4t;BSVaNsj(8SeqR6sPcf*%f;ew*cnL zpV(h;`{Fm0`v^8KV6yXA+c7Dn3=o~)wrtJDS#Qwp@$-hbKzS!Cn{^KyBZ^OhkhDmNMj-{X2 zd?&YFz!t#PdO1z6kPtsGl#vC!#>Vos&vvhjF(q%*D*b(k(JvG zCR^GTuFqj_I5s2j`?(9RBVYxT%!W7Bv4MfyI4YfVStnro!Loie z=9k=nK<;pu?C0}HcDdEbh3R-LC%kua*aK9~to@#Z{TsXZ@wnp94-sVby8|Zu)K2?+ zYiqIk?HI7%!&F|b4A@7G{UBifaBR2`4<@qwC zw&AV+M9~8-4w@=6-r)X3vq?_u8rp+nzD@fmvFl+MWthgXlJjk``aA9ShU8uVbO#({ki)&yjn^vHgQMexJjZITqT5=OvAPI|P1t zgt;!gn>rTir>Db}w$KJ=Zv!9J#;du>UxA zWDrMB8Zw1`p$KdD3E1z_v%1@AETs7X)k$ zOmgD`b{Xuq493ci(Z!g)X()Fc`SB1%&&(lyjNjFX%hzA6mx<|miDw#n?@4%}-&H90 zVyC+}6y6Znc0s&i<6-|%9D&?hoOl~KKPQpgR_Oc$gV}8Yxv7o~c8sr)%IuC$r|pZ_ zE4XKS#mO}ru`SSf2&|RBl@82qY&4IAt-`UGHpHU+VP*CqYh}`v?Nc7(B~Mv)Kn|Oo z!*0%Dm*%inbJ%amx2%3QVACv{iT$$d9^{5)(#9jfb?JBlxorP2J136Ua@Y|$tPkn% zx=;j6-W>91I!0ocV(zID+bpiN{iQ5oX6<}a4tqR@{VrgNw+~Kpp$*t8f5l$I4d$Jd ze!NCAXXX=Q){K+>NbEy|UmBFk4T5QGx%?aE9PAaI!f40+q$7?lc8uhhwYv@1jgz)c z<06JW(c>^*kHq?B*hYL;oAv$mVskA`aj3jri>rK{j>io{KgH3>Imr!RPq!T%!lc`` zyJDJyiK!3wa+knlXKkL{%2(O%Q^$s~?}xh$UA(Qtq+gb)jD>6*-`B=TziEW4I41C2 z;XU+RI(``dn z0qb^5`S1N6MFRWMAo_6$BGEp$&$&qL()*-K7r7stGQ zD&r~>e;FGm^J%e8oZ8sc*vqfjVUDd6uzzuUdL@oN3D~YEbTG!*IbZ{cTx<)+O6)&? ztu`^uBe9r_$}(M3Dou)$YekaN^#CznUO>hUU!%)lj=fzj;&|S+vQWw%;`k-llz{z} z@cyw~9L)&W7cklH_<(8L^7@q8I1bKXvX$gk4g5agn4g!akCNTy?~s-&X{v`awLWw* z$37j`a4cPXp34SjIOgl6{LaKZx_6vhpAowg_XQPjOZEy+oA|cK`8HPh`yp`Y_}J7> zpXXXv4jEI>=v&-lN5tm3isZz!#@F_6Ivy8O|9kUMX`doSc1OdGj*~TWvAtjlZxqKq zyv`hUWDdImHV(hu1`2N>Yzu_TL3r20zRs{)V588_%OP&;a^3!^&YrCW^S1JAdXC&w ze#p<4KQFiNfciN8v|oK3ov>^iKg*GuPaJ+M<>Ls`>)9dLxy+X^&t-$`SU~p6#=F}w z_4>(HS-&qJmyKh|vGwe)f&DOhbQA6m=hn7sYKyZ>_aBID%{iq*euq1@Z@_kj9gE!1 zfbrGTna+US0lRr_oYW(#cr=8MN9V=nJ^{rc_68s0&X1G(1;ls*uwjR|@Kk3;<5Vx- z4Oq5~B}&t-{O5u=dcw(x9Y*`tjV^NnHU}pC-f&ED{0w)@{5ToE$nOH&=ljMHQ73j$ z9o%F>txfe?ELz{463ESPEVSQAj`?{MUnAL1es>D|cA%f)J)LttKgKzBcOdr+On$>S z-f%3`MSVb4?q4}_+%s7xx3Xhlc!P7~MmrX!ZM>`uukUL$?wR2HYK$kp8vC_7wn@NreDXPIIpwP< z`x`JR93IGZa(vh$akMC4b2(lLd(`QoIHcdzkHyg~fm|c!#pXE1SJRHaL4)l38L_Ky z>Qjc1FVb0Kplxv%J(IS(Vk#$DCYxtjUjjYuwOYSzu+KA0*NVE|vhSku@qPu{@7H{= zd8Qwe(^zF-z;ta^?b@-9DL<~mo6>QcONZFQj%^jN*I|o@+=tg2xs7oO@B5rnykgrs zru2CBDNJ#E&EB(9TpS_0%jxX%TxCP~s&w>se#N%Hsr+3Wumd>G%3YnqKFVR52W0(j z0lU9gNbYA)yi*)|n1m`FVn56HZG&ZX7TXgS#vyh_4tpSn{WXWJloKz*__{bW#|Yyk zC{t&qQy8-S+Y$rH#jGbb8_Tf&0&A# zVrMqI^|+v)We4WS{UV3mwsO4*2_Kh?{r-3Z9g}Mee`X; z+|2<~p52ApacACf#$I_T_N8M-2kZ<^jNGM=T$|vOk^S>d^)`4A=G#~=cQ0|2`Qqcy z-0;slUU!6J8p~gY8%L+<=RIN?%P)ed9?P$o+5=rn*eGC^!A^LV`wQ56xijgH?%2JM zjD6&HA|D<57oxkJUyTpSxHEPwB=;VPO?S-qJ!1Fc#vfRSE_QKxZpVBd zAjUA%_@xOn`iU`=H0P4r`(!6Y>s6EZ6H$) z%Irhdo3gQShCN8x$jZGQFomT6)pq*%K1I)5Zy9%FA-VTRY#Q#ZBMLS1+G}CD#(X)t zOBaQ=6YfVWXq?a9v!8JM0!(eZXIk44^Zm5^(v%wJ$0}kAU>6-zs2ShirSP(-)K_NPfb6)N+*w0QXL^nG*m5l>9|Na@N zeqy@c=fP?r8S{(1>KMy-COomP6h|=L0NK1FyfVk3{eFCUn&)2bfgH9phxH=7RWsqO z9mLVhxr1<;N4@0a#Ey52Wd);)*q?AOV|%|gM{>-Xmdc;M#w@lk?ymC+$rw&;t=hPW z=NFRkxY!Jw)`rhzuk>oHthLSW|Iqv-wqfdD=i@HCw2-VfiJjxvWcKnab~;Wr9U8DE z6gvBYw2hVA*^c@8CN|G8zfL3eHteQ_X}={_Am7A7ziLaw26Nu)atZ81D$Xte)0|0i z?ExF;*oc5_0n>GHU$;hcPVqf`W5L)*aft2USed=-aj0e-`YtpfJ0lT%z?m))_!>WgZ1p^6*k`)=uSj$>hZe+E13 zj#|GDIOf;pG#iju#h}Q zpm-NJ7N+A)$HH{z+UM_S6jZLgT|RIuOveh?VlHO42XZ}{EDO_dJWOjrVLIl)?#ra( z7fvor$I4XV@?*8SY~Wa!j_n-teVNib9d`8MTE9PVEKJAcuw5RnO~=n13)7*O3TN|U z5Ul&Q+Wgqu$%W|{*OPk=pRLtpU&q39oZwiPjvvC_ey-N<4UUEBcpUchZ)(%=8^^+Q zY}~6pKX!m^naPhsom`lX_h6?naaujd^RHm4GunK4*}TP;@nXOR_OACk3Z`-z`aKDz zauxdBmj#1tym!J*d8=0L3MT1eGy2^OQyB{5_!Oo*594^HwchWCFy&k5cQ}o{>>T=C zsjc4cp|G|7Rx7tNgM~9cD{UYsu zB{#vbP;MG*Bsa^<4E&yu!>)C#leW?8@+$0XI{)#3-+wt4#xZ#1dbuf%g>py2%FAkX zzS6N!?l#y_8J%Bq%!N75OyM`g0?h+oFhS(GKQGVF)A6@`ZAYbPgm zJubXYOYD&x_PZSRX%5pGSvI`2a@gn`wtEgcHiw-GQ(v|X@%yx0nj`n;9QGdUs(ua0 zGZO8Dv9U|XBp068W{#BurhZpx3+499kvjvnaP@}d`i#Q65U240#m4Bo8v6}!VR&L1 zV}36V_lo@bxVFVFA8-T$oC<*xj!x>*O|mB zIF0|jo!8>~+Kz3`Ub={>{g&MR0aKZ5xUgXE$(Gy*z8`?oIMLfctTTrxJjqE1@Aq_$ zHSQei*m~?$mz9n~19qBYKXz;s`>h>YnY>qcVmIIv-URlZX-!q(`8XuUQew0|^=Nb; z$E5|c#yC9)PxEfAJN_V$`xESpd1*Qn9?LN``773!x~jF(!GYh6VA93gU=Zi3xC<^T zB;$6mYjJ9u+Sw}|Vz=Scz9_H6#?p!O78^*EvH&jae4$om@ zU>etjepPnVzlDCKPnPWpQ=b?5Ree*x73!?|mSrmA>dQjEvta7CLcb^GusJaGWuf1B zuw#Fp_FK|dZD*GK1g8Es^!szzfWOxIRawijdtvGuL%*80sc)o-Pwf1dV`}GpUcSJw z`aJJf<5byR1~iR2WX+K7kPD{W#MP(NPyQNdh$5L4T%w5fjh@+@{W?zbxn z$@8^hx~?FmwL$Oq7mm&6yx1n}70>K(4T+t_)MsXy@*&GQa#$6n^!l=<@Xp3PH?tvX zV(;T!#hdaUNtzFc`Z>6~Sn>t@;J%!$i*3gb{-X64Shs-8WQ!_?1Y{q`)U`Qi0bTc`Fh zjQ8S;>eoh8hE~nU?X_V;ozBFbP-cX|#xWb69y4%(`o?Y3n-8_ME<+DoNF z`LhNeJ#J3p6&sRaUKh#vv`Owl+~r(=S2^+FJ(I&U4$I1o%VB5cut##(UtnAE;OK!t zynlmf&8UCC)}wq%&Wtr(dPl*sa$1Yb%F#{K$ql7aN$&U{j^VIuczPdz*P)d;??uN*?3oLwDE@a8wktFy^tgK zYL47fG(bv67~XTRYO2S*UW$Z%ldZm!aM5OWsB1G zkE&z)x7+IFcE|~DuiNYW4&VXAva5qWyjSk2XI~)a+g&d=_}+TC_wK7_E0D|j-T3}` zxzP{Svr!M!`~4utE=%sJ_xsYFsb88oGjG#6|3sHwvFW(ORx2j!)M6Sdi;ZNjK1E|G z_0MPUD+HctufAAJb1%t>-Hdx~&0?}PBK8?>$y&weDf$QBM``U^eVxCW4uv0O5mUEu{9sWA3 zJ&-GLKFc~B+Y~*$-6!_G~U>Y!)!B8HJ2f#xAeyUaT8CJ^(8_zh3TdIc$?XQojUm)*w&eg(U-=U+JoA>7)>Fck;8;L#UOfM$)HH+zoVZ}NEzr%CbMvnRR1#y$Vd-0H7w(UGR zV5nj8P4`X@b#ZvVtIVt~2X7sgGR@1T<2J(YLiVzO*vXFh@<(@UuCLBNsu&F>Ldj{v z%+YN}7L&2OXU`syGRaKEY2Ljhd-)aX!-v@DfUWA7Z%-wsvLQLG1A4#198>%2nXXG` z<@V+LU|z)J%d^6(;M50v$QSSTT*rJ~^3~{g0)Df$-wjsgy!X2X#{-Tpns=6n75T0_ z6x+)IWYqBX`F|7k< znc5~XKfjdRFJRlBp7vW}i($9GHV?x4tz(k{_A2Z%`0F~kvXf(H@_a&9ZT@Oqs5~!CFF~2UeM?@R7q&U$;phJ_Wen}j zn$r9qrGCXEck4yP(^nUh^&v6c8z4JRNShO|lN?jJeRyASta>yeU?&iso&`NJ zVCp|6JY1}~Us-c@+2D>qu7AO@Y3zL*r*ZrMexE^JOu2O@uGbZDwA3-#`2^hG9!<-T z*tNLvj}?>qg2cw*N4jjlvBDEO4yNZI{kkK_*lRvED03`1ZHPrj=dkx4NyGDU+o8*F zzJz{DNC!ebw zBmEI0D1T?T@FX{Zk4Y>n__T>>eeiMEx`7{Hi|c86BTCv8{2Fy3_QEsT|9%?=QvFKWCZdR^4%VI`T^uWQ`6amjpg)M=7j=X1FTBu{chP_#COxiy`mOpoBWAq~zhuCYlrLYqN_8DP6 zzILN|@1f$5T$S*``^E@tOBaTLW<6?K zUdFPY3r~zo*v9sM{1Tc;vDwd9QFst*d^g9KNMcbRzint99pZ&GCdCw zrcL^3zW+8akn!!V*e_su|AFQqN{9N7i8#GqK=u(+|FtS^pAFJ=1~Hx2v-&%;_j2B^ z<_KcboSbw~c^BKBz19~_-6FM>m~_apO)^Ya6gz1{JdYFqOYKV;hrq4oKhMrS4%0$XcBT0bPGauqV!;u_o*6H{HpH0BZWx`;jM znAb(@OWX~}mDwv^u^1h)Oyx9WDnBD|>ZkX1bxZ6h+^X9)CildMsjU-JTcJ3_<~p`< zz%F;}djb17$LHhsCjq;~vAqKJAje_-P#h2A?%ps?*0aUl!zsM0*-IB~BrQ6Z_Eh!_ z*~65z;Tbk}v(#3cGJcPv4*GG9XFsK1)!a1SJMBZo zSZXqBf}1)yb|&71do|WQ$8tApa7OM2unjWo=^VKq2H`1Q*&{nnJONhSC+*MGzNp?P z9V$CYul%a~ZMHw-wSc|v7>~{-av#8yZ+?AJe!s?zIv}-kJKtZXjG3~=vEoplyDP%y zAKVyejomZVAH9p=;6Uz&Fs*G)3D}kR`S*;*WUYm-=D7)tmDT}bbMW-q^D zpWw3dD6Kz#du-azNKW-k_WKii@Ap8CmA2`Q?WpfKJ)ifXV@mH`xQQn=ChPoSgZS9% z(gRk+F89xFjQ-5A;uULy>3Mdwd7h1@jIX&zTq8Fhw#liD$vkg3 z^4yXUEju%9>%{b&dblns_PJvdTpVJ0ch;-;-6LQ-JEnGCx=8LA*j;C(bx=&t2Plq% z1G!h6-%|qi4=1;!W9zfOm<;&jyvArp_KHJw@nDXX9}`HU*m^LP=>#vyZ8+l`X zWAeKrVj5=;y13D_q290h8OixNC^?l~$%X9iIqY3n*01LKS-&qkIbZ%12UWMuuiD+L zU#&f5*}@#Zm*>b;bJ#99c6pKVmrcjxuxz|P%VF0#b|!Ion_iwHcLgjP2e+-(v4bgp z*?14jVcafO@0T)>^?Qh8zO2di({ki?&S4CrqG6PcwS%-VBr$P>jG=~MCpozd*}sgP zRdy$_mtE8@Eh4=yFKUb~Lw7NDW{p(k+1Den>G%=bhhxb#v)=-z>k9`2tm2sOqa-)k zv9;KHzk4}0GGI$M-s0Z0|J{i1V{r5DYm7AJlV357Db~85y6@5S*jDU}fazLIHoS+N+|)pB1o<1T-6)RD zVBJTh_ZW)p2%EH|F?q%bWYRL5bog*v}rEn%Ot0aepkSHI62Rr3mD#_g}8&CZ>(8Ie*pFZtdqUZ zH|ZLd7x|r!+wjH4Zrv5T(=R@B~%N61#y_W_|ajb&VHRkQv`#5HBeBvkRxL9&0;vW1s9V3aIfPnpc>BS! z@s7-q)BS{5xi?^{AM=8EKXh!@fGu@wpMWiFVZ6FZQ;p7-_vV`6sDGtpWyxd(*Zri}`6Ep~lV?e-Oc5HCKUUzI%z>X&(`3>c^pkw&q zh^AzmC|x>e8g`28aTp={cAUEQ|rw*+!knC8E_|Hh|n(b~+FX-kF# za(j2MuEmdWhPJ;Dw&UhaW{m6o-Zxz9olVJo3exWr$L@CFQOwNqS{fs1d@a9X1Q%&M zq;b7xTXL-N5Xni{t{iJDH85a%aeVbwO$nRGcjZ?Z-blAv|^~Nt(^CiG-K+dt?q<_y>YX8_WUOG z?1LP+-{j;+2XXlR&BuFUj@+8`0a=}w(pO~j<4)S_Y&!PdrQYw_yVl41{e#mw=ye$n z^Wnw7c0P1J>znLVFU7X!Lu;>NITq6<{&H6uujU9_(=c8!rzv^wjOrM#cQfpJ9LulT z&N6Pdv(t7>?W*P?V!n*4zF&b`=iH{~Yr>GncZ6>0sITqB8o3FiA0>AXEo;r)}n{ED59(>>8% zZZp0Q#_t2aNXvoPe_(1m_vKiAw_!gEx7V#r=6AisDt!MCr#YQpBNO`#eswQ|+FQw~ zO+FE~&x5IcV!D?-ELUQBSKahSo1!z=d%s#+dSnUla^5qoEscAksqUKG`1|VX>fMX# z^P~Ho`f~77^vkx1Pd!l2-V5Xy8kqU-)-N?hhdBLuu)hrbb?r{&S~~O9tWWlQJ+-sg z&bTal+Oc8mz2DzD=Jk``-#NBbAorGIg9G-iV-o}RQAVy8-*>`Y^QWfdckIM=&tXbu zR_;vL_ugoVK4&kT<@Z-Pax^1#eqYOB@8qz*=dfitj9W$P;?UY=R%hMkk!2k@Y?B;T z$zi*~w*R2ketYN09gxFjI5w8_c>5iZBd4{Xtj-s~vhnJk-Yok?j^CRdJ0Xa7QAUoc zX6pZCA2lW8Ix*Ep>7u$VoyAnHHvTxR=VBV`Nltx)m(%+Rv#hUUYNx!M&!f<<&!dp- zgkP1vn*zTF!M-NmDFHjn$-Nn{2VA^ic+cgqKjyH{a+nN}OvwVv z+c$@?#9!x^*8$cs9?3V%k1hBb@d&+PYJsJ*gqUo zJLu!(l_YgK$Bf5i7tLF}Tu;Y*z768s8aRz#RF))H=DWu8X3oxDtcCqGj>S$+jPA~i z8GJh~_BHO(zceN5?P9vGMRh@at`AS^0b&<(UQ8P(dX~k^GW(F7|F5(U;FOX3&-?Xq zhyJsEysJ7rArs#1=(lQyU4UP27azw*Z>Q@Kp6!WEv*BI)VH%$1!GlQ1nGMa6-VLa9 zh;5X^Cgw2Rw~_U`e-6{NZOPrp-pBE8jvGtO$@p3E4x?;nK7BXGk{ikXW1Oz{`1ERx zv8L-D3J2YUw z&GGvtY^B!be&u~9KoAw2ru_-PVTJ`djj`i zTWV)9l|S7(qxMp9h;0lzrKO3Zl$`+6GbVm)t8>!jg?`O-_2WF^P5 zjNC7f^KB=mOdLlAOmV7C^ZOeZ%V_b}vrhoxtA9X{>j1x!F9M z=^0BrCVzdIx-P9gNfaY(-?gt z_6kqw-W+$#=FN$n#r}x<9ZdJyNKTv5as@A;EVB>U@b#PPu8qyfVU-R4-~0Vv2*(IAzp8v0Y|F7KtH{1XJ#eQl>F2HF$LSs3#C1L|{YIBAJtbs-= z=D|(BZm~7zG_E_jBkfbfG*1!pb8Ip7yJ|bNDGs%BY9|%1?^DFor-$qJVp?mFoNp(^ zc6H3p&&3XLY(4ghLv8FVoZ8qO0(LIPuN+@Wu4`!hMPnVsp=&(yE2e%%%%@lEWykzj zp0CDUl3Ryk`PC*HHnG^ykA29Lwya#g!%B&q{2hVQnEFVCf$M=&h;cN|gsX9~`kqGq zwP~C!ChJa##%YVi(>PumVHDXFC8z$*Zq4wL@vAV~d&K5X z=Tcot=w#mom-;Pmex>Le0+l~>i&mC$MY9Edzlqut1_ei{SuOjYCP zDbdI&9H)LYwras|oajQ$D2y&_Qs6!5T)pyn)In%Ax1@{oH<`^|UlfPR+|YkF4*hp= z=)Z-4$jZ>kh2-z)a4AM)I&1S+=x!;kp z?YC6Fk@2W_(|EIZq^7v$TA5_5c7a{0s9}qhvB63%pdaznXA*|sdgCT+B7@5*1SQlQpB>5z{Gw<+e@bhI%qv+avB5tVb1ugqdoC5L)|m%#UqJf+kF(hOKDr zr;DUBlfoc=&T%EIizw-<>-p!YZe8afIyAlU_-BDiEq*VubFfR4TQWmUj;*l}jC^4;K2n$+jg-gpN>?Iwu{#PhKA4#`DtSC&yzFdMPz>%fp z#BPH`C*t=wP|2e)vAi!Ym5fGZWIN*F@p3O|Qv^gKA5oyYpz=leW~+s%R;CRQS8jPD z=?q^@KGtvqJU4cA9^}z;lj9>>)W}35TLunPxm5V7-;-33*&}SKRuV5P+{6{m#zTe- zDHO=Phy%WhyZjVPHgSbJC>k_q4e~nF$E4Q|A?xJ(`7u-9*bEgCeSEr{53f(O!G`Os zzwSz_H1#i<$|7#cT2D4IR-3$toA#`wXRJO=R+rx5(nsyOHY&a`mk&oxQ_?s&`OwZ% z3v9wM9$QDYl{(_~s5o>Z&s};=lfg$Z>h50di+ndF%#>qW4t+T?h1k@BuxzlI-%1IITpSQ}qz_#h995DiWl7Bn2LkplTZb zz>xWflyIL)tC5mvHWPvm*|!58)>cn%KBJYZUouOfXWUX)Dee=u#(m?q0y?rvkJYdlD-NUp4JVUr}|W9;_84r;pqNp96WEvlNnLDv4>*Oxu@2Cs;s|B zWsY%P-nEss;vpw_+vk-kJu0Q~Ju5vcrHbY1Z*H~&D30tVdG$+S|Ee=Sd^gNcQZz6& zTzlIV_>qd`CcSn%>9n`;Dy%4~4y_LD!Yv(o(NN26f2ehXPUhM_FzdC_$J#lrws$pD z8~KZ?R^F=K6WjOUnX6mOcuH~VK7{P1aIC!ENj`)*nOZR$j+;|r_TBcJ%Ae=bXBhd> z7#H;?Z0xE2{hp@Fn)){}!gSgxO(x$Z6l{vujzbtPbFA5!8eJV*4dgH8d9VE;)^0WB z$51P8?IYjo;iI3KFDe}A^K6m7=vnT&sPHY6=RRRpR_q&EEVuSt+NTtK+vlr3Uz_AB z9Lr10Ay?zrj&{VY{+jWZ$nW0fySVH*r7(qAOUcD*!%y{jJbD}%ZE5&-R3EHXt7lic zo}BY!TCQvd;JSLszvRt0igY&ct&w>3OrE&xFo_ag;mr+|AiZ9GReIJ{jg@Wqcr({Z z*(IC8vFUmzdY50L?~az5bK=Gz74tRu5Vz&0%8_!YfD833aqs?t(SGJl24OxXO@XQ2 zUVp8G&8DOuZ0-QH;aGhXGT{@MN}P}PGBcY|c}w%fmRo64#?P8bzF0fpnWls{-Wdxi z92 zjB({(T>4DeaZ1bNmP$*-Ru|Jg$XY>rXxgSUoTc3FI+}MMZH82h-OP9YAzhS@16tWU zWG}9qNXAz-TZ}%ozMRZj;{?;j%B+gl*_m~;sK2pW!TsL@r6y{D=D^p z(?m=&u{50L`SyIt|5>hhN5$>@m7_Ap+7ynngZXYh?9d_Y!lsfp->$GdSGR`XlNn36 z{+x~|Gdf_@Pwz&E!dk1hg4RTS=1qa*`;+kripT(l+7lSn^8m(@mNZ za9}>0YV2c!vL2*oI?tz8OtDrZYqO1^ zT@9$2P-~j5_QDQkeI-q2?{1K5Ydb?)#_d+VW;&EiQ+!>g!CF} zMc5RnWwULFX}C02_Y(~xtaS{vXRI2S)d`MlV<-iaNmw#3>~_*Yq|(r~XT_GdE^LC0 zyOj@xxPc*EW84%s=PyY}6W{W>nT$^kmNFp}i=|>>Unv-3CLzqSn5THVYH@`LjFN*5 zQ+qQ7DOjv*sF`edlL*ToW&(qEW5Ej2W|C7>j%-z|l)SoO&L<(8`LgdPj21+v9wtqt zoiZgIMg0U-3i{G}(~1=<)DO!IC=YNolKYe38Y#-%*_`r`@Rwk6LwgR04oBTgK9u5b z)9}m4O?K|HAe=GZ5$^-=Jo%5i^YxsKyyB4i^3|3^|HI)U9Y1_fs{c#h!F{}A@bhe- zXD9LtVRB!T(r_L?pE67?jJJw>6(+Y=ApZAH(43JOQ#!DovMruZ|E?~>OwJ>-Vr zhT_a7?$_dlyu5T#+pi0hZiU&bGb?;M?$$NVUeV7B3u*j{Mo-22N>P7pruF1&k}eLb zakXgvcwu2x@s@Gg)OyC9qoRF|9%bY;UQ?L;=>^(cnx&88eri(9hE%FQ=i|~9<+v9v z)$@slB@JIRJR09c(#|qmV?VZXu}rUkJ8N)5*~@GG)T5BvP4OxYH=jfrHYmxq)wr*V(5MSBmB@suU{XHh){tVs+AK zLJjikT;8i!g_n`kwP7z`j7h@;)=dJOCQ;mwD^s0R)1ah&=yyB zj0!kyY4{b659SU6#cIp5^t_bo8kh3d*I3NfQTcgV11`oz{FzP6mMa;CN-5f5e@9LC zV`_7vMnB2>deqb0xzU68(|9k7brDfkx0~dZHf@We4&Jw+k&0cru;r(~e0)OVxW?&Z z$Nr6ymkumV^ViCsiPogo&KK8+4s6_)ztv6O;N_#JGir+4;swMeJ1S14$Y!@$`Qn?k zo5HzFt%4!;L&v_HM2n}G@wCn;e80ZZtNDWFp7G>(gXS%oCGYRIu$Gf_8ve7zc|7|+ zFY2=Dn{cch)~pVywpJtlTB<8mQ~jsL`m;H%Sx0(ZdjOLOIc<`c{V!vET{3{AIq>TSHG;dN47xqVw2J!m-bTabegK%yl{An<`i2;8T-T{-lBj_L1Z>mq0 z`#k917rs{ZRZM0Ohx$SV*0*2#hN92)53(HxefvjtA~oUYlMY{^5kb0NJ^?-aXRthOJRlK%>NGgD(S6~NwaXrF;4dRn{vwnuJLnT_zRF%na$ey8Tc5u+*3jMoCTi`Q~0L@LeJGO}{t zW&f}|jQkFHUw#x$SZ+VYZr_z(l9jtV(ElaE9|@BS>rok=7fv;h*Z7|-GTUN!g(JE5 z1O6sl_LRFRDCgp3m|SRwR`lnm>7$QvGkT@r--P@$WaVa&k2$Svk8s{MpKxXo#^JcZ zK{&qr98Ngf2IXNX;g?`?VLPdMmzR&;{yG=753=WflP@DbH?YG(p))RGcVo&aD|c8Q_SGkP=hxxdG@bm1Z{FSWSJsCZv z`$*i|LA&kKH5ncS`4WaRJJ3gB(qD0h`4xtX$}fa>!l&WF@$J$;|FFJS;Z-G#;mNwRx!cX&z-E^%lZ92*Rs90DS+#Ww z+17(wZ`Nw5Ums2HE-{zb+=-goKK$h`dp(G*$jwKkoxa&kQ#;JZ{K0`>r*lgC@7VU7 zG)YeYaQ|#PP9i$jfNR#R9yS2(`ebwGe0*t4oN(t9=JWPqxw%VBw@mqSJ}AEs!9F=B zsXoa?q%`D27YPR*nd#?U5v;_uOVnmD+nF)BSeUNQ>(-pq@OA6gKBsa{ph~z#U*f5U zZI7zSk z=sHGsIc|>!$3u%9MXru`W#z+O#42|8FAgaB>nA31bEef^K1mc?;R>yfmEy-mbe6f4 zN7mNibuyJssjEClven#)MnU%`N`|a9r?^Og&9oS*`kLO8$<3MEmf4pIrE{ubT-9Vt zDwV#NH8Q&%xg=g3zY~8PFXL|P58^M86}RVDmF1Y5+T*?A1LNH|r|`z(@;3RgYkM!T zR`*WyWVD2KNiD2xXNH?2eb{<$)Z&}g2iPM|modu5n5om1Pu23mhHlb3OOiE>Icl~+S^_!;hPXg_NVvzP*qgx1}B`V&+!7UO{nAR?`>PoyX zLholXcMpa6N6_yLias%!XF7{imnR#ZYWSex%Z7h7bT=$Ck?NeBLN=v^m2b`FDvB(P~nuVoV@|Ner3{MohG4xV7TwROYRbz93El~Fz@gDjWJ%I3Po zK<(wvtQ{9uX%7BW^i28NKnL2&Ms>R+Po(l^^Ii9{4TxHrdpGkGl(}0(=VUW?-D|wR zt^f-2fdH##M(3UxoqeXx1a;cp&&X{f$w7@>yiH^u?@vbe*K^DrL@hLGE=(!4p9C{o zP$r^ndDX7|O@PP+=Q_+&>gzIQTCd5RPHg6`WUU#Md1u2`CUp68_a|TiYPYT6JRxV( zC!KD;`Q~fQ7V){TTGcs)DHoBZ`SG>!!uTwX&o(tlVY+qse7N!Y${z3U7P(6*b+V@5?5axb|;)33E@c?cjiEKM{7Kp)Xo-(*>zt zG~Hs2FV}_oA%SkUvK>yg8%bhRN8rv>(V&4(f#Z})gb(_1pA~Z}o z7=K5C8|@^0d)Q@JRZJhGHbaK?CDFFGGIfJ#PgL%D^)l6kqjZx$o$H|{+BVhZq_WPR zTWKY3?$M@8FuKu)>rdJE{8K8*Tb+~twAD93nvXQhl~nxAbzOUr*T!f1k|Lc6O4;Hg z{p@e0nl#wQ6w&}WO5;nTG<^;Yda3*H(kx0x_v})&G?#<@(UgV6jx4y8#Qc^w!=(DnHrPRbY^RgW=YgDJ6!p%=Q9(cpo)CEVnCssJV#+P znd+(?;o6b3Q{UF-&eGwktKX)BCs)%u{dE@nsUNiMGnYnr0#T!Y-J==N?u7}ak5pfA zSr6{6N&aldAb;u)+KR!SYkhRijxC1J&aA=v|5l@nm}ba?sdF2RV)<$$2f>#5A&M7{BJz1$LR4+BpHF8+1%R7Uj{c$l)o8oiV z#XFbY9A4{B^-OUq9&M?fi{r)7DAp~xrOlivnsYAyNL34V??b-y zrpC4y|7#jK+cqiO&@OfyAYVOAI3?g&;=O1+t*UW_ z+CS;3yd@mn10+}SVWxJeaM$d%ydz@Ys2rE0cI2i1V4OBvBki&OJ~jQyQQBX9r=Dm| zbLpD$q<^>fOVhq+avZyU-#qQJZfsjx77)_btWum9tG|zJIP#}9IT$@mji;4NyA_`6 zHh0a@Moum6p?e8^d>Rb6IB6lZG(fjPJ4jyYggK{MOh!2EkoV&v&V_g5 zamF^Iq+0RWhS&BCYLBI+Z+A2Pe2At^{?360@ujN*%QY~eIhTz~N`ofkb}?dro;cM+ zy_=ajNtdlvj2Oh3n;~1`-m!hcOy`0jmwJaz*K^Rv(yuV(53Fs{XW}D$E{_sRb(_AW z)7%^HEjyVd5Vz`LQXCsw`wSox={b|}95Jq_xfe7I+9Z)HPP0qh8Y|34M~xM3a=Mx| zCymifS*$W*(!Z%bt}<~>187s9*yn9JuR6fXDeQ*DyIl88|Nyc&bxU5 zYSPl$j>c%H5Om(p<#?K8epKOI0Bz9}&yw^jLD|jum(0+AuWbHlN9?~zy$xUEIW~2Y z+)l*2ttA>>h$`l57{6~pZeFF~CjQNNg{@Yj*$#x0@vy#1AV?qK+kdc)%bj;=Ir~y| ztaC0coNo@~+xnM%*$V#s9F0-6@se+&s0vj0Zmnc^6c4{EUO$S5Me#aO+)nFaYmq5_ z%WG>Hg)*7K*n5mSD0Z&t;ACwRXUBVf_@8^y%sNyl)2hYjFlgkczbn!fkdfQ+$;G4v z)XBi7PO5>k&7(P4^U!Kp55n4Z6;U+=cBxM5?lzsIB;GvULhGRJEEQ3AJ7*RWU5Y2i zQ)(-146St}%^?rd6h6uvQzxI<0Bcti9#+JK9N7!C5;tu>E{1 zWqT2RRp!|bvEUPT=)%Yc(L1IJsJ@yu#V#yp zDK2tPU+U24C;ul6J9HSU9mC2+^ophrYd1%setNFUGz4ZOrg@h(#c#(l<9bZ$v1gB! zX}PBK=*2TrjXe&cRlkaMC;$$ui8An z8P7C3bDFEMMuzWDp%lKHwhAp}i4oKY)5@j#$$py@HsSd(8z(Ice|D2!YhP9Lp5}KT zG&brgR128Lw0CM8?9A4Dx|KVcw)dXW{*u zW=8k?HB_Us7!j7qZKf6`enmtRr3lG_WG8I=+wd1Qywh)CuLt_v(ewH~*Y+s)I?J?a z3g6m)JlC!({3-S2Xqfr+22VnUXU_-aOJz$N z^L9S5q5i#p<<4M6#^2*}?dW9QnS2HTm{AAy+%yTT_Q3`7*!&nXehF%(ZL(;hTp!O! zB&QwmQs1tqmbz^(?HflokYLfCddt~*Zau5cr_G{i`F2d3H_oENceQWwo2~&MRdc<- zp0%Sq+ww8|u#w`+o;8o$yM-d($g3@~XVvm;AA1vMeZd-mv)^=o^UZSO!gkQMfB(I8 z#FBWeZ$G`?u+0qT@SS#?6-H;DlkuxkMrYe5yHTHg*2Ofb8uw+#cCIuiU-4_pmq{Sq zK~6htWd8g45_y$gHN)Ht_gpt&wXb@J2F=~GN?IoJ9fKL| znz4IE%xeGbifKgcighNPwo6JM#zZR@DW%P5N8&XOQw4X8jWtH_sq?Dfy0Bt4H>9F@ z(WY_!EI+33lN{5>+1PEinDXf@Yey9JG2{FB`vVxqrOmB!;n+zZR>s4EKgBz zxio2FD94&64AJXpC=zCHp4RI!Lx7hT4bep&TGv{nu4&&_w1L+-Br?*_4yFvD$eO1%##;2bx)Enmi zV#?6dTm|Ed>0$i%ex&&Yip}|5k5)ZU%~v+X?Rv|fiU0b5?ZC}aNo_GOQVKoY=Ks#~v9d~{#Ft_3S zh95OFH8eLg7RrT@g;~fj^vGS;@M{|i-}%=FprNbb@rHLBK5tmo@U3~USLf|mredDw z*n@G-w8FH8)1p24zt+ECMlGuIe!bk(WPR8=&6p>dpOIl3@ggCUf7|%{Q~oI3a(SEd zFS`@UM}1d$yw)*&m;JKO@aVf-624c+wth&y9JQ7QlqZu+Jp;b5f4rK`+w!UBf%?ZgGNL)0>x$bGm+YqSH6;S2J$#RH!t}Doky7iL1l<1>0Q<)3{2U=1)>`%mMZ{TX0^%)olu2 zPCbjB=_{jU1+B>wbFoy)I~zZe#7}#X z#IIPKe&eI^gs8lireNhgy4&~fZm&dTop<4XFjg~!O?Zd**y#DO(TighzI1c;?^o#; z^=s`{>R0YpG{x6gTRR%Rc2qI{e3gG& z{z_40;>3x2Ox%`t^1Vh2S>en~bKbW9WGBh4lC-e>RQ}2mX3SuwC+^7Yf^n_uHmBB% zY|HgmaFQ{M8J~W~n81#6zGY-Q)em~=2LOz>`~ctd!hYmydr~vPo$Y-4E;Q`pUFWZ{ zfj{lX$G(d-<3Y{Y*2d9ZT|y4>_MqfL*H|&d&B64I~%4Kjwnr-lZ0da?KNvg)(QYjBSgfCYlNQ9?6U|oy8D( zb}ys2*z^b^ZCEv;np11sS57D{Tc@awQ6(PFTQ3)Lr`7c6cw{HbZ=lb5v?n7dUmHa0 z#kWVdnHp(j)bF@_Hh%Ix6qoJ4qPW7dfV1LR4W|x2efTNEmks~-@TJ4$C)KBdHj8;0 zk+zn%W_MzRD1L`zg!)A74ef>Y@$K8UAK5;ly=QxCd$~PoAK0FTvq`LVkL=$_MP=f0 zc}iNJDJ(8LS6G65<7j^2Cxx?>93x}xj5UgfbLZ3XQD@;DGxb3fSwIw+WaDidEH1q*ENb5D-qWOpP>U(yhgBrKdq!$M{hm zJ(MZltwzT6R}~d}by>81^jdfsrrfh-+l5nE#(G&4FKaF?Yc4ZNYK+D-Mr9g9m4DYS zoz0czh@u_;DvEF7zZBn6qSlye8D6Hsuk@+1L=zZVo434o5&&BeP9=_~$5bYb6kDmg z^Wq-!;yw84WrqGc&i(h{s4ruyoE23lhiy@*Es9BNTRCbYl{PMy_QhkPcg99b#zs$$ zb$z|_tg$9miF(j!Gc1Woy+eXR>I<%2 zb`MLStt^PRTVKATB-)~$f7182|7F6wykc)DNh^PS_hqzFlIUG*dvDwPYII3-2gJQo zqA-=G+}p^%GnO2x-=-3k|@z`;s zbg^xt2suukYu3RZuR|ypkjQi3p!bw%YWfme{1jP38@ zsA_JT&~y7e`CaA;O~Z9bIChL$#d-^w``yVIwt_+}@E(R@5SLD{6)WbP4$Fj6Bv#GC zn{cCt`K_^BHs|$;i5eS+NgwrR5&88ve!B3h_k>8J4yY_E8P%PBTscun^{0(zgGib^ zR-XEKqpEgk@leh&)@I)e*MgIbzwafYMW~LD1g7M8ID5q>nKDirFM5hr!!_b`++eYh zQQDY0*4(?`=8`7fG+mWKrLD7VR@>6HWo@6gEp7d(-{<|l?)TLiU#%LJL&A%h_sOqu zq#>q^8l4qa<4%{9yyI)lcg1D%Yc*`A^$Hq7j_g{z_BLHU?aF^5iA|{`(Y|c|pBt8M zS7`39JYBzB=Jgw9BXi5;ax`?PKK&*+mB7oj+1=UIsySOd8x(U!-y|oy>OEuh1N`S~ zoTtP`>*MTpp1wx<9de!kHlMCJH@XcKW^>~@j!a4oGe>-Aj;(mLD&=CtA~HRjfcdm` zb@Rc_NKb^#=66GuH@v&N;e+K3#O!UScEFZnUEEnra~?(I=y6TK3S5oD)+OF>Xv1U5 z?zYLMU{7g{rpzx*Ijc0KTH2vnnq0+jL3nf%($&ONGCdGU+p1x!Uh9zn<+~4WMO0i7 z^<5D)uF&nY7xDvMQS_OMNpiZj%~oQVtILD5PsORGlOAVJ=u`1Z_P)YKg~5fv#OhOM zkMt=b8P~U>ZPf@l$(snBw5y2Od>f&IU^6F-^;4+)5D#)+#|}tN$2I9C1w<`RCWA*t zQN{clHB?5|)){RHvC>XYb1FzjB`S=I3X7w{(x~u`{1kSM3cPJ)vW_L^?QA>})L<4T z<7j17wP-Q_3RiM!rPvypqFzN6(m7lzU%?b%u=EYw+r=f)rUYBmC{+FEGLM6RUy zE7GVHNN(`$!7Ajq24-l?)s8PrH(L5~AV0+4fM;7#uz8g~^*xoE@T%D09o~GpEc%jn zp#Fc=`$!g=8%(YD;PLPZUK%#Z=^*U&#rasYR9%`{~&H0ZG9C_k`uebv41(XE8jI9 zksP=17&);|9lPE!rDLXJm$FxQVh7_^qOn*zkb4bwDa@C#PQK5={T!yc;r+4%{6EQ^ zgxo9mJrKXz6z{1x>8$vDc-Ok{d|m0}oR4=MCr2i6tsOrUiqQd^%JC|#QS?{BPp7O(2**_J)%Tx4 zL+$;Fso%T=HlDrwifx0FocfE9NzSuQ&OM1cg7hBb3ZQ z2DU1l_hgQ}+>NyT=QH>Z7SXg#$#(1{|?3Wx5fzi&H@Fb_-hn1W!&tj{< zB=^Cs^Rh{?jDy~uZ5A`TK zFQ>de3|p!G4s(9R^xhe<-5nzvqD45_bjN_*!?D6U$FU9A--_QKY?a!tFKk1c+6{#x z{ghXWuz|{?>V;?bICgx%)+TL7QSk}ZY(x0mA9pcKoBXO=uY8rO!)zB(}P_9gi(C4rGPH=2H=T~XevC=F3v~}WqdVT$n+*F*>yFPnuoj9Lfl{>|&JlF|c9z8sb zS8Ny9%P`-ri5*sCoq&S4dEoa5*aol#0sArO-~1Rm-tuu=2Rr5{duNwtcd_X3A&vO> z!0+9#=kR-Iz%=<$I+TanI&nT7{Wc?iR6ovTuQ(*9G9x>a?Plxb)7$wxjwPpZy_`7qI5RDOo5Ix29RXW4kh`3+(QuHR z%Xz;G9NR6ByAIaBtJd%JPHv);(_Z?iZe0_w^*G-4Ec`ngNbX?A4hiIRJQukO9aHRDE9t)i{_rv`op zJN9(IHi7+|@Kn~cDc<#AvVqzuAMaNGqZ|+Cn()+qXbZzr9{TWRBKIlrjt|&zj{VrN zvFxA3M#}da0`?N$-@%^4oJ}S7V+xnrwT?jU8kpL|jU1CsGw`dl4bQL#sB3COuSAre7xBcyIr9F3)& zvBz=py90a0tMY#*el9Ji{V&a9^nKE%zFV8*2D5*3CGMPPPx}h7_h4@vN5ALd-4^y6 z+)@U78?)CY_9X7&HB*}+&Um;Z4XSava z@etK2Qn^yRVOu;9zWc*zItKH7DDFVme(ZhP265c;(e!r|Y2wUSW&o@b$gR(@em__F z<^75sl3~(6D<_tf8${Z^`c>_^K!;=JyEv5IKCqP^tF?>91@9B@)$FAUO_G@>|9vs# z*ZCFO64&r}6#YJ6bQ6)}E)Q52$Dy2x;#IimOBmZZIk9VTC&SKkOt#tv9VS0PpFu`Q z7qJ~+Pa^lSV|+Dhc3B(H4H~=5VK2YU?BB$lLjm3=U~hB$7LDI(7({X|KE}!6&8$N_^jtbF5u=(%Vhn#wyd*ms&&M|}P+tQ!!Le5YHU*oP zUrOt_{HniS>9=V;7uyNBlW9Eq2Yz>f&A{)7fGx|B`xe&qa$3(7-hiSF&!<;xP1x$h zyIBz4`Lvy9yvn))Oq=8$BGEsE`Tj#}2Ml)LYy3_&Uu1i+9bu=y&T^~?b_;I!i?)s6 z(8!&`dDX!K_%6SaqiKomWbowM2(deHXZEvWVK28ay4--y>u}C9mGJ}Kh|IMp&yIzS zf~gJg>^RsWn8sS3oth(eT8`ZNDD*ake_Y^KOnDTtmgagnv8>z^uzr7}4hP{ahAC}> z1GWJLUFitfhA^dLgFtQkQZnIdU(;WYaLc zZ{^7SF-L9<%6Qg(Yr>R{Fy2u)avQ<2@ow(q)Cc)8xrLLP5wPbS3(LU^uxvSa!^wr^ z;7unNmV>W**)q9V5XUmu`jqF10o$JrL*+iyPwbiJQ--)5n^4b(=?fcGJo5E?FOHQq zZB(sj5B!$(g-v;>wF24Ck7LCpcQ^5>57H*NU(jAjZXm~Dcqjh8R&ICNuspd%899w@ z^W=W?=i2ZZdgjZWfPQ6k(I)-4o|Bu7g`{`5k+O2XbaK9}(OW@hBB zcXHYA9>7*%yjl-adb4tu!a_SwadKHZ- znv>f+BR4%G_wIMdjm_xy0Oelk&FXhb#(pcg{PlLB+HUWSBOo;?fVSx>SnKaF}qn4+2xxk z`XR^K#OB~mfbGxT%U#Ryb+ArF$R;`Ut53lWhDmNszE^Nv9Q%4MwjJ(j*iG!c+`dk3 zbiighxiFmS1nzE~S{g_bkUJDE3mFjQsu}(2g^b>oXk4<4^juoER zfsB3b=cRZAk+A8G`MyVT=fUo7jLkgS``~;tM!(7U(Iz>KPv!Rr_R>Y{mH$z0 zD8k*P*sSk+zq(IAY^NZ+6KR_i@2)UyVZ0Oh?)_fuiq@4$VR7Do9Z};>J1A-1o#z+%I1;vaQXp({n#Dob)5d(^1LW~T-6*FcG z>!PlL88f=Nj;^}s8Zl?obr&=4>KfMY{;#@D_nB+6&U>%mOjZ5;pK~hRs(b6+z74Oh z!-hrP-VS?L*oxYjwlW{Th)0{Q;V=e2?N^8x#{%ylc}5qqgVl}%`kXOHpAQj+Jpv!k zmc4aDu2^5LE3OpA^F5yTkuaN2X+N$FC`%8eJ?|~~@b-R`ojug{>G^MhFwYwi{jMAR zDoXw-*}G$=^c)k|6_SI6t)>{iV4F(%>(PX@6cfPKmwbI&`CbRuR+5(RhO~f38!!(r zui=-nfUPH)w^~MTaVcZNm3~9mNW}zrCrNhH%|zpA=!N^|$LeB_cEKLl0g*S|Vb7`U znL8P$#(P=VPn!SQsG?x>`6-e;`iS9*!C>mBw< zfNqn*F4l2mn7SwVKz>_omPz)A zJg~nD>n*Hj#2CBhN$wRkSTOIAuU4>^BMy_VyHSUt#w+-Us60!ylJ_kJ#mox2yv1lM1}MbRbd> zzm{>n3&wFm`DzsJqOz>9X{L0K6l{NC9R_Cf&ABp9h(kM&5~HznSS(gkBYnJ#NB*vyD28`jRRwkaRKU}GdJ zYg6Jl$2(lg*41KUqhGc=Q^n@ZR$VeB0;PaE%4r8gDtI)`yQ?j>w< zhtdB>3j1BOrzqS@AF*BeyovI)mt6a>&b=J(U{(6d?K8>U`V7D59ul#&9q-(T4RSp0 z;i7w*!>)~(^)L3W6Ly3aSLR0Z@wmn~?Ki+-PYSz8yz3n{PU%-imgj8jRl=APzYwpx zVgkIsNYLF$vH9(w502ADEqm;QY6)w~9AUM>j5kMV_G4|{g?^F#u#dTm(#E?y^450P zm66xrus=i|1rws`M|$t%v@bYX+WX2N>obx#%cdel`E#>bLz8T)=nIM4Y=b~sjt zrFeA*H0OO0d3LOty`K*+pHH?HsHHOL@TcM&Kv|5p%2CB@EAsH>i8oLevi+6zydA~s z1xW$k4dQ((o?Z8V3ra4SR6Z|;cbUM!Dhq3|xA(i0y_?0`=!mjCY`rAuvQK&5Q1^sq zG|v!rRea*Ef7=Drbv(+j>fM>-W5op4>G_hKMQ{rKx0F*^@aHp%M`Yu;?vR^5fIxqBx0EMkoHArj^*(gen& z%~u7b@ylliNSG(rau{QbdEBmN;Bnov%`=&>XQ^b+y-M)~i!-HrWAHAKz_a-t%y_FS zZGJgNhSyUu!SgyPZ#>SmTEhE4yv*~Na8F6eVDAUT>GCa$Jny#>kAB78Z}C29A@9=` z@;+-J@ADS&IJQ>QE;iO^d+xuT{8sb+WgbYk-^|GK?NW)S=`h%%FA4ZC-iAtB|DN4K zdzylRz2EZ7IT!W#E#4)OH;}?9`11MjH@AiMu4p0eA@Sya(7c_W6qau1MqcqtV@8ZZ~J~E8+4eYHNeW2S`>9oC7gu&a}+1o|f*SD3g?a^iL241!7 znh&l?u=kYHJv{QBix~6sXvysFb;RR- z*80G7)KhGVJO|<1y;yo<`7fjOclRI7d9L$bObU%!kjSaAmg*_$SVNqAv z@cpP0^w8c@4tqdpFs>yiUn}J~ZytJDwsal~)=$`h!d{L%+WsEN3_b97uZ*J$rlt!R z-_bB^zCN#N%q9hWX4nE@AD*7oJ4%X}%qDpW*8#rYx<_oLVszorhqUt!iV0mL*3L&O zZM~Sn|T~VdYpNAc`qtaYovW~#xynTUW^u^g=$7AQFus6ix zIKM$LfqL6U=|RomN}G=pgi${Fnc&N3?TqfEXm69iYHpA9#_Zi99_2eX^43;t<-6PQ z{wv<0+B|Em*mS>9`aLz6Zx;>kV6VMCBY1mULz^zozTtP(3OsGAmU#aVZ^685X|I5~ zeIkr@VJw-w%`~^$2&dpxV|;s45jgF^9%Mk7x*+~?;>INWzII; z&mymz!~Pw4(;ddS40}A?QyBI<)iZ&$|y!=A@(5_a&B&D$Of zUf$`x8ZqV<^9zQq$M`<%-*l}z!SQ|)4{U}$Gu@q)Uj2^d3bslo5Z%QKP3v1;Y(Edso54(lh3^38PEAYtsebx&dNJa%N% z^=$=)uE%Z`c9Qznx8KDP^X>PsFxrpvd@J*(!fv=XlN215%@uk6m;r0Gu=#PcM&$K# zx_M#PobHj)-XRWqOBijnM+&2S z9{YFn;g1h6+SFt1s*82I!r24EhsRD5cIE@waBsxg;ACO+Z&#HrYtk3q)TJeR-$mYr4jWTb`)|PQud1`TD}>k6zBl2EwSvc!&L77;SZE3WMjdd!rA3OoP#;9(z9exW(B6!-vPV zYNPvVPcTMJ8%)59arkJCw!*T?zzov`<`*m&NVk>|(hB4JNz^TqQXj66S1JFQgY z`Ek02Fv{2H{Pq);KF-0?<8+^h`7sHGuE*vI+bVUOPmh=%r>_ZPJzB$+}^mT-zeAuhZ3U#QbWVSv~Un8r4G>_wKfIy6Z&U?HyJS#yaEsXlS%I&GAl+ zJm1cnIEbiZvCdA{EYk=NJx*j*Uwo1ZuK zjJ$r1cYv^Tzm1Q&zTZw2#yaTxZJIF3=lg9@< zFxI@0t{&e-%kyu#?_u-fw@3_Rer+`8x7^ zzx^0_M>*bMtF)~B^cL!0t(WHsTcmbb&)K^>@_IRJQRMlx@fl(1b?~{!+tBI0CXD9_ z{5JOl>M&qI3%qkMiI+D91c zw}hWFERZ+WXS^0K=Zg{wj?1*N?xaqOR|^FC)+Q+t-oj`>nQp zasBo7+6bdvHgsj_C@kG?U81h3+LV zSi0XX6ULhC`|Y-<>-!BXJr6Av){=hvGTQTf1cp72RcRxq{^REJP_;1X;pd@lk>}^3 z?!waZ&@f>~X@kl4+ji03My}sR2}}3eZc*3w+mXW7`m}k!9UblYd1yi8`F>j%d43*x zTo}*s40mM#OZVHy5%c{4hOS>1*6i4_{#ai;eE7Bp!=A?m37hss^L>lK!usp{nLT2g z@As>~8&`pMb_L!Ak>}gs_Z4{8Rp31+?3(4-B=5@dP~>gxu(vDl-mSpXo9mLge`T9p z`>i63`d;en^{v3$F!JU)-WXvVA3cN-bV-}o`PDF`t^E!W?;7p7jfJGpN^+g#ZDA7> z8}H1>+esL~^ZfjLS@b)qNNeVIjxe*gFxumKi{S0Osl4$X7jM=#&Bwu$!j4FdgZC@& zK8!ryzpHfqwY^Tlu;+OjRp4zNdH%eqL0JB~=KVH4@-B7tXsp1S8F@E2-i^Xq(r*un z$MZScNS8qS&6n_e&Si?N{ho^Ueycw|jP}lwF2URDk}29-RXFF(JS%j9Vtjz*BWB|d z>=nt(3w52W3qs?)BaHjq&s3K&?(x0wQ?|6%jP4L&=<;k4x|<7YE8%;A%$)@8SJ?Lg zZ7-;sFxEBhYn-o`0MG8b?5;HS;Bh}_=&DuWyi>_g-}@Bz?^IQKMi?ILfj#UHyuG~g z*jr68#}xNrHRM8oXZK-yDQ&z1l^(3QZa;?|r1VN%t4jL<*rR=a%kNs^z+J2jVvcWo zfZ=R?zLMnDeTSE-gMAs$_Vk;8pb@&oI-c@N`)a z+Hn5+#rHVC^Y_)xh`jX`Un=p>3$Sk5^IQWWZ$rf!O9tuY%eM}r-$x1K-VT20d+N)5 z@l7KSjPg?t?o%6YGo`tgu$$uzh}gpp)8i7sUOt7LepY#I@2b!CmvFq%mjr)&oU1&3 z;TXg-ce2u7b*u{afQ)yi5{$p=9q$IEng8rO0v{abVAcjhl&Af)=G#I{jv_D)fneI#E#?ookx z-X+5P^&9pskJuo^X74to{rMHVg%R_-Cxx+2d%sUbY^-AJt)h5}q_ghB<{dUGVn;gc zLZ#n5yFA~cOPP0;uASe5O^ZC%U-K~|@)$#4wEI^PWBe0VmJFBRqqkz?X?Y5m*+W;$ zd+@uV$8Gh z-qd)#wP+hZ<-=j|EK+v6VjjdwSWkYdkvn+QwWyR-uDvI@MmT1eC7 zYbPviZ>I{poh$IJtiZdf0`JWVJnm_x{jO8}>+x98H1RNAjI%;TJo5tt(uOPHVS9K>+e8PBtICe34h z_B@++(>&%~&$Ib7&0{|GJew!eJk}4-v-QJxnwG+K#UZQZO3ziT2s;9j&)NcTb0Lj_{!#3b{RE z^wDbi!+7!Q!s@~pFIza?iNgFi&=geiYvTZWoX>flFQ4a)5pPJJTsRL?GVJM2RD6Ok z&Kal&_8KKE;Voz(@3j{4TFH4!{Bj-N65fOs@~&d`d$|AM!&buAyJrYvCZYoaLZ zTYetXuw5M{S~y0&(@U!JWE7|y?aTL4?fOW|SkgnXaJ}+8R0&fR!h4jiJSG>e#gz@; z*X^dbN!Y21tuHT9dPTe$kw=+FMc(0x30krev$uoN*i*NJ=XX0FmkZy4Fl>7j2<&*r zyG+=nqq3#%KA?Mf#LkI4+F-DR^5LK0{o1?+kNNhuc<9STvY&o(CQn8I-PI+$kC8dg z+T~@XFFrXJ)=4FU-qwoe39D0Vb))VbPsxRAVI{-5u)pG-!gf?_yf@^y$LYo22Q%Ka zaz5oTjSt5gDh$6|FA^xP`JJe=+3TuKsctN`i($Oa66~*$#~QVppU>ZMftib zMi-3Z9PBKIy`%JnGjicK1B~~r3It|-gl<-4-gag#8KR8w)>ayOn>u?sg-FH=TTeEO zw?X6;9B zF=YWWzpV9!;TPTnhvE0`i*u##KA_9q61?>sk97@<^C#>nn>0#JIW4DOiY{Z*BX*hy z#=BG4{W>nYJ6;-Vug^A%ykU_Cwt2*uYq1BmUBnoNE5bVHGui;Zog!~V*vXnJ2hf^M2zvrGw*Ldk_+o8_P}~Y z%+^&fzJq$@K7>?L77I8m{cc^{>#|B)-bFG$(o zXZ}a!bqihkf%BY$6r)Q3KQzVLNSNorc~|oJmd)Q!_))}ORE$0PjrD-?&53gu7}rQ( z&qs_ohhye7jZ+KESDY(3TS$Uk&1{|a5^N7L1I4{8-fwFg#a3027;qBe@ zMRR+V&PzC6_qab-+PlUt=dxg9qCM)dRKh!nSpTgaA4iO_35M=LlA(I(A!CFYF4c$ArQo<9H0g}K`>>I=4$<5A{5dz8OFi0&GZM?0F|r<9)bOD-uWCQz16`m@J_ zS_4!8yO13)8_r~ih>>goP3ozb+k!R8!>o!0u!uCTow z?;qlQAdF*>fW7Y{Z)c^=?|7wokHZlTo2>M_m8zRv3!N5u109d{{an2H4m(KcYui=_ zf8GZe!LXwukG?nT=!oSVwp0agx3YdyRv3YLEYY8r^d$@W*>pdNSRaRdC2X{G8yv>> zj?rD&VfDgx6}GX%)~~=@C-V9^-sX|#>%s4GoG-uYI^GOn!&a#dj~%yWsaAVFd5@K;_|4 zCd#szUT8a5F@d=eo4i+Ypkm`~sWd#+3WDbqlsDcWrB}oo;&{XU2e06GJG78DI`WQG zOz`EiHI(}9DWQDK_XN+g^%vfLl9upj-xbxjpwFyb4vRd-F2VcVMS0^LrF2W|9p6IU z$&q)AVuJVEpuG8QR2skI6%#zqw+n0DZ}FHTSTC73@`?#yuS=LWSd;M!hCO(!9|X@^ zPkH0bReD9du8zlAyds{rx3Go0Z(GRYc-isoTGVQ9cX4zMN;7 z?n*j-;jzXOJa0SYjaLwlx$_i<@%`UKWm!wUjK@29nK!t0C-`||fbz!sD%z`ex_Z`|7BCGh+{*XzRkc!4+f zfAD(iGwf}vn7*bBc8&D_V-EYPE^gO|^#Hq6f?qo>efezOfOos(>weYY`6?wtJ^oHY zKImus(l2?*wYt&#wPM4lJAGtrI#&6$Bk!}w1M4C2JkD8|Z?VT(iajunO?c--jJb+- zrf&5qjCtH+-7E0GJa2#HnIAdMnO6yZJ{YMyWr4@M(h?rmvn}DB5qT#lCV0QhjreU) zZ0lAxwLQV}tUuZd$FCo!V9beroPwPjdDd277f4pwraCDo#xK}h3HChiDq)2bk8^=# z!aR?CnxBQS2ARF}A}{Z-e!>pa4{{E7*j5#I+Y00T)Z07WP8E2gggqsDj3xYX9?kgs zt>Y5jILV|z)yWNtO_#N7rZC%YI#7Aq=C}Hny_x9}-ydMJB)&hunk1aZZmgIvRAT3` zHjj4}#(ef$^?*lTVvn_!;O*IbN?+|L@#OySU^?u7#oI*K_~GSoAX>OCVP0F8j6#*f z=CwVP#s@*Fp`B?<0=(BH%+DJs_Pl=z%L^mG`#{Ry3hS@5=iRHh)BF8Gyn?V1DIWdC z`7mLq#Ku7vrM*3PwtjdX?E#NE&_~=y?4g)I`KC*_kH|b|Jm$8R@O~%W5BqAI%DCyC zEsXuOqaxN#`7M;@nsbuU@W8ef)odWlrFA6@Q{+%LB{j8(_@Y zyyKF&412W2C6YC#<-+=^WN{xz@g~A~)evt_D4$25o5r%j_#M6{4=IjQWy86^ zH;UOe8=@F{1Qj`%C!X~$y6;Hfja2M;*vktez%zR`4zP8QgncghlAxvtX}{0K{PvyX zzT>J(&oG1iD533-Rg7PJaDK&pqK$E|w)(T@lhwdyDAMqv&5oN%y&`3HMjD8?RR zQ$sIce|6Z(!WaiOHsER64Es&PRVmXQER6StJ`ge5EUR|L$JiA1-L&dvSU2%_KXCWx z7u`O>{wr*2hiO|q*xNw$!7n^8>>1Wi*bVx8|drz@p zn<`D2`K@)s_LlB2z5Jt>!}b#f?}3Q*l^*X|>Uv>y>6v4&)gs3Hi#;$+RY|Wo)nPmv z)?XO9PedMj8ys(Yo>Cp|4J#Y^s801gN!S3#Yl?Maj=~sKV2Q3 zwZ?~v5$589o~;hwJu_^iKA82K_O2Bh_MW)!KVP0B&|NC&@j`WJ9tZnE0*`sxbeC7) zwH0}zCFL~~-FEuZ`^D;{N-?^sc4&iI&3}7Fdtj+vKk3K(GGW6BrI56x0VaE#N z+8B)XJ4W*1TV=msQzf0X!FgBoOIh?9y=3eM)y>}754KJUV@^DES#{}qS?I1Wc|h1J zit!7^b@w43m#-zk?vxz&spbe};8C|DCD?0FY}ipsWA8DC-LCZ7UzX3Q(Y-^G`=mO2 z&&PD{j~LfUhB5Ar7jJckWmJa2nmey^SXLPCQC|`<#?bkaabK6)8SKi4y%+1DDA`u> zv&JOH2Y$f@OL*`3ScmZe3%J|{=%>~-0?0GhVEJpyIk03?P^N<#po`Ix~DlFzp;tE zvmLfZn_~I$4(l!qAE!F(3Ss#8kHh9h9&4ht%lE?m+o7g(|Ch2X7xw4Rs!Q(z2Akhj z^J8reX&hPI&85p*3fMn_L4CAcTLy!V|0Ks*ZJ|Xk1*y$ zO$DX?IH3aXq{v(Bc+cxZ^QD0`rQf%rZcBvyAna701-lQe{imZZLssaoIi!U%&T%t@Sw*}Q@7H#t2Mr~Y_U zX#(}#Rr00k@t9)s`yVwJ_00<-z+-GvUk!&6kMF>A-=QYi)?qcZ#WtAau(R6~F&od6 zJG>{e5Ho(62Cm5RLXPPd&f+T~k^-72ih&c*Q}IJC>}G(S@o9Zse4%@7990zQn# zn6Uct4y)zc)|9?it|m_O_(izSIo$DHj`oHLBY1nXx!L{Sy9C47$Gm)8O=?ss(9SHk#R+MA+1 zeH6}XE?uRjw2#C*)T6cfy|$)wPGh{4#bb;U;H@g&?QLpG`>fzHofJ~`_-*Y<_KryL zx~6#83eUG|-1o+~0%OF+J$+8w!(%SFa7In(IRJX*JJ}np@l09asrq3a*iiT5w{utz zrTGotSrJ=ZG1uMj_IKE7!p`lR3HyN9%jvVOl6%jrDc!pRV?4bp>5m@8&WCY@Ik zo@G)pJoj_3V!lse$M0C>XUPZ8!FN)OF4*}>e=6+Oh_UuDPX1mfkLS&m-$&zMQJ0$1 z`7^vjQ})1^i_`Y57sj<8?TlY|e~j2himkp63E%(Xn$qvyP+!i&*SoAHTr0w(o$r=V zkH-~z48MlaF2_jtE^$%$8&`}ZK_cacmNX8pT`@@GnVX(RMQwFQCk z-&yIl!v3w8vcT)8G{*;Pi(x#+^U{MlFOT&t=riWg`L~znFt9-p!xy?k6lbNo&c@~E zMJr(&iT8|b57LWF*Nr~F7At+Bu)juoio%%g^gwz3gLk}SZ(+8UNiFQRzxZlR>0HXN zHYsc$aW{CaIS(w&J3V6F2iQKZH}^ZM0uSt-6z}W`Jg~Yqn%kRGfd@7z#k;Hm53Kj| z&Fx)Xfd}?Q%HDMqcwjrc+1%cO3Ouj{Dci%m751o<824b?NH%}B zCj4%dVH`8t%iee$6NWL?uy?p(!^TDI9cOQ1#CCH$FvhsYj;p`}V~l&=`NAkOpPAoF zls;CxcCLK)38Q=*+r|T9+oF&*PbtG!Kk%>UrFcO7p-Nr=B;c0uPLF>Uq0X;DIqtJ&!pq z?H7!3>Uk$r;DIqtji*bL6%~c;m_OKK-j|)u77#|2Z3|UJ`%2f_Yg+;;0=)Ow5nD~`xN$R zt~s_tJzS35{MJ?pDQn{*YTa~WC zs2l6m@Ak`;*0TP>y2u{qyLP?GTw&+ClmWk7E1V_WKkQq)uV&bp!q^|0;CPos>~e=) z8FinGn4-|XOWL*yW0yQW7>hp%+fr$K5CkR1v}?}eItJckeFm?U;#$dz?OT=3<-yuS z%&v)5jPN_2A9ZL|+EV})#q-T*tiDy;XRgTghOLGPLi}D!ExPeyJCI z2XA%71ne1)zO;HAs`NABaSmkIVM*tR{T7-mpetdCjLI9glW~XX74wXGt0ks4d-d z0J}(Xt+106o4ps6e))*n(!LZt`k%JqS{)vJd8&lpo8|o2uxUy!Ii@z8cYtlH{2<9j z$Jdtjn!&b~U~gx|1nd#!{PN2$b&8Ste0?%c`39x&JFK?88IN{G8oJge3&ewiY~XlJ z!t=t+-qKXw{JtRE?A_U_K3SH^8*j02U%uC)J&x^VDu?k#|NP4@YMRgvo!ZnV_2Mm4 z{&h*c^2Wm+eode9Svjbe@%jrNAYLEIBH@QAKUe8FlA*23JnG@g_rK~}iD%_7zjIUe z7AQYfJ`vx};NIRMzA|wi^svZO!@CzJsMN?7#H>8AiiDl zDIV=a*$`j8h7@mdw3n_gm#Ax=x?7ld&`8Q zYvoZg)YbCFTPj|@1w1RC>6;#X#BpWz;Ncg%?^@+?Z+YV}&cVzcCr%5X+2UB>bIKG z1b95Wo|BA}R7+Y(2-q_o`A(8c9`BjCR5D9)uH<|PWm*M-tjTANRCaVSx}Bc%XssDJ zqbCBosTHutI;rQyvXb!Jn2*sT!0Q@P#WeL0y=Yi5Ya)4gYf93A>cXMCYu@1N(U@u7 zVO}%wy4JQEJ+;wOn$7jM_)nb1A`iSck4K;g$G?=x2kfm}1Zrp1&T8G*u5qO#lh1U^ zDLf0J$sN@ud%;^5b>(<^EhE3cKWG3D3lTaZ0J{+h(Yhv{RVF-6<^cCOUFd2x_t z^FhkqQdf?<-Em2M@rxh&$@9ED%I(KNx*S&Du_<1v`BW9ys-|c3x3^MG0*Jm-Z+2dS-8~j@P_CLufDN*ZxW)zI^F+n5uH1 zgZOryE1dqY@wPCPH^20U=PgR*jfXueJN2Ocj4S*e*0tPz)-G`2(Jp3xp=;+64(E6< z+t!}uw~{@4B7Xg#+#Y}3mCv`!0^#P1@-0@rzic7Cf2T%$%FcBU?bM)jLE^_%eac=R z<*mN{IByc3moCC_L%aBVy1v#9p6Ba3!0A)J6_wBXMc>==$1gnJF0{L~%g1iq(_U6T z`g2A0Ca3H*I(vRR&rb0uM?q~gK*GH4+lBHl<`&5>fxp&H#`|CO@O~G{PhR>6?dR+3 zdEmaj%VM6kV*Hq2#+z?H2>UiQ zUcBFQyIc7v5B3n+%XsPX8PEK#h)22Mc%HX!e&P9gEKil=w|HjXc-GF8oAGAt+(-F) zlsBFqSG2#?!|HFm71cNG7ao}5W-r}->~HvXu=7){W%|1FQ_AOg)=ug2rP~YtUeD?= zJ7sUK@(tn^Bz_*pp0CGusl3@+6zy4k7b`zNw)#l?dAqV%d!m{T`v zUfsM|bxkwy%ISytEOG(!k*xpr0%mebzVFGQkxfW z^|bygz@>Z&Y=?)Jg7!}q=)cm{#qX`C4fMarZBIf$Pk@L2`u^8``h~LM4_fNcJTr{l z4uNT{7BUt8!0lN4L{-&)3NPgjlyO-2-ukdYG~>8JROGYS%}p+tmOMW#`Epuv&a~vJ zX~}~Dgu5!A67rc$esGeXndGNu^2$~x`PNCkeUk5%C>z=#a@A&fdyjTO!vFR3;m6rT z&ztK1(ohQQ#x_f`O^w;68QCT!W@nq8$~L``ZCaFVI+yG+@z}>0D{+BaD#g%fi6kM3 zT^kPvXKN46)*YP99h@De9edr3EbTL>QFI?8@)hMWx#_t?|8o4*tDW*HWv(Wh)Mab4 z1raFpbV*ABb{TI9Z5!Ka$D?&^>prdXt^2ng-MX++(z>p7mHy?_M#VA|_eYe?=kiG= z+dt{wm=x5anS8KQYa1xeZZ^pjLVbC2@8H^@JhxR_H!rVUmD+5rx)d&h@sjK%`hMuF z3jacN#VB%%<*lpgRCP%e@83#l>#OEgy0s&uC~JtbwleOs~fWBkm9K_he_#s;7S(N zYzJ(W=DpuT1RP`(6#dV@Kv~BabfUUfA+){XrGr$VrGtvKr(W?GYD{vsCb^rF+=EH( zq9ivX$t_57)013dV~svig8O6ZN{XRPa`7ljHI7%ZtcU(~3 zI7by`*VfLi&CjmQ=?4>L*EY_s&Caf^n_ZjX_Y*kcv70BUKv~h<>5AfhW?!W#v&}Vp z7ROE|o2$y^hGui)v$=m}bIM+j&7GOe%?xt9yi7$NC#ezdO^&?ph4Om%glhM`m09>R%=s{)KXp zg3G;Ng*qnfy7qNlI&>M`K54JDw$toRXLVZ8X&y^&-RLg8M50~R??XVPLeMAqq_&o3 zrp=hM_h^;=Co?sn;5wk}vm!s1C6mhx%WRi6RYKAdS-gD z9pm_G)M4>smDFl~tWrz$|FNq5k5!#{nO!pE$EpS;RCDS|`xirADtZn){8v{httyVt z6DHwc5k2tZTvOMkwo{whOWM?~*`{{WHnpSM)Yh$}skgR$ZM(YKb{%Tl)z|9ogmkb! zVMunu5dDq+g;WmIvYUM*=b;2KulZ#(4L-U!d#nYl5gzUhM@lIQs>+4qSutfNV844v z=}#cd&=H)J{}g=|rv_0-tP%MI#f3)wX>6=c8fR5!B*_fPMG}S9%5$LXOr{jpEv42k zrOF9DWjt?EmC5LThG(OR_)9_|M*5tTxXfp1TgCbnYhCq9fY{GHPS19qmc8!u zY=_gcZBEageR?*l|5LNuP0c_B#jM8t|2KjB-w@}(~#sFc(|di zA*od&;9?hbbO;wi-70mN3-rG}b53pMoVJ<9+GI{G!>bUA+mJ23+8RF`7sa3+$}3f$ z6c*)@MY-IfT#XV7^?LtY=D}Q@-gWUORn2sIeqUYje;66XhKP2H?N;uMV*AkcI$1=w`)Ae^=%!a6zDY4VcXn<@?xN~B)pgY>VpyA6EAE(KG<3{pl8yhE+}i7qusmu070YJF zK&XvsWKFx)kW6xx9x7T%@;3?3CFavQkTXfHQE@?%mvEnjYuTJ6D`8;!Ht64|Hqdxk zID2;O9Hh3fcCO?i$t;$dvz~Ud~wxw2D6pBU1YvW0ltc4i~jkbzR@6e4`39S#pE+KTL0` zuGbmY2>Vf$_AmVBrZ+k62Y9`_v$H^-k5wMw`47|UpYm5w9zBHpf(GR|ZYldBmD}{# zSEv`J&ItF_UP$GarShiNC*tU`4}!n`O6Mi)cTkTJN`t*2|E9WxsI=U_~aey0q`GL1j_ z&*%MkneE2sf)vk>Pk7kvFPjMW-^?H5#oLEx?alnQB7grk=`||fsKJf&U8&sf`INu@%6t2xm0u`d$Z>9-Uz92r z{psh+r71gB&Zd;!3o%dGt>3*J)5E^6U#0ow|3?p9KkssU^%sV4KfO-=eV%@5&}RjS zA1{SeKa5W08BclXAa}Xrmh&iYe{u``Efmk!yQTd=`K=s`Bl^YXm!|URez0-X(tgON z=B56re4=(~P@9a9_<5-zmZMHM_i-Cj<(j8FdIgE^hq1!Zv2q?3^I(j#smeDhJz2tY zQC7c#@VqdD`GfZD6Z3~DPkk-#k3Y(RZL@EBa354Zn;!XlUB53%=~@5Lr<_+V)#rJo zu}l4}oR##vfBd0`_<4|V<#~mTRI&3Nwk=eZ5a(;%IK#P`F3lzm@6+LQX_rGxnKSxL{@kM{KC z#J|;#cJSqFQr_#W$luhIUZr+wP#FsnU%#=j{P<+NV~4gwSZ}GvSf!CA?zqjz`2(Ei zCRy(mDZNngq4Meb^j5#cnuk2ErFyevpE4qpb8ad>K;>Ml&zdCPxN=hddSQ&GWomb8 zPs_iq&-3~WVcc0c;o-}8^q04@ER{DscwTR5D!)9HH@*6Zqsx5RCzYpu_(%M@*_h(Z zN#*A$-yofW#P_?E!~9WC(w4`M&s#aEH(YBM?D+h5sl4e?j=a-rO68ZP@}~EKaH}`- zjklg#qkZjMfer{;*Tpe6O3G zt76CyanmwEiYdhfU9yDmYu)nBEPHyzz}4HY1G=L^p{pV!|5W*Q?N)wIG}vdtXqP#T$9rxr)CKV^4m(`EzPtKd#VOf4B4X^? znvY4suxE8+Y!_6Pb+qBYJC@*q?IG;AO*9WV?C^-aD*y1-5pN9*_q8?n@j>V>Ss1Btm54pzcwYc9!ifGTRhH`4ez7cOz~l(iogHhu{VbnG3*_o4{nhhFiw4>HYA|; zM+tSKT?t^}?_5Zb#}p5Dr@|>@i_GJB;`Gy(;W%hkX>W`3^fxb4$9+(}Ynz<_+^ZGh%ZbHfSZ; zpH%#P1>+47wwF3ka7lNlup>2}p6{^D+UtE^hZgVK2@ZAZB#e2Nwjxm9&cc{?H9Si8 zzU-`da*N_IZM;V`X^j+*_Or75EArlp*fxrp_cm9X-k_KOHb}y{FjX-oq2p~8c~?8^MU8`B z8jHS6cZo2@>3z=cD{;J7S=5x_xa>ExTo16fCFiSue~h|d??~Wre-R&GUrBmu&hDm| zAeHd$%B_XbH^%#3X>^+$Hc|CpzCXxeM+u{yuW{Hh!hX>WxYr$auIj-t)7N2_3VT(3 zKHXv03q$vrh-sQH{$8%IR~&Y<(v!xkEcjC0;9bt=;%!q?#=g|&Kb@($gwG<6HLqTs ze5x=tP0;PA#74rpJKpzEH>~$j_a|ZSCO970sv4&r+onoupm?;o`Q<&IXA84qkTUNi zjP|=A@&+mHEsW!rzCjmkJz=bGJ1I?>8zlWDtZzFjHr__!T`bJjP1_R&2xVpE;&mBRd-15ZEGolMfa!7*h%{vZs$M>}k@ z>R;<_AuO%S`(wTC_OiiyDleE)e8&Smz&;ShShIS7eJkv6jg4ocU$E6w7I-}!);(fp zIjpy^347_CBN3CSg!dHPc~SZK5HQ`H(C>T~=Q{cb>~1CKU)qE6ja2-qaDb48GQ~m&|%fW_MTh3#(+0ipYi*qjJ0(m53IW|#@fkBOC@QL*jTeQN|f-7!k7nj z+$c?;U0%=!+ul=rM?F5^4Uilq-W`g;;5{b!=Aq)dNDTWtVxP&WVQrO$cdHB;)?4X` z59__;j<=z((}Zy!!FU@90RWQT;EbLlgH$+Tbo#Z9h z(=r!$V6@vm9x2W_=z{GlfwwT01x$xaD4*9oURYZ9#>l%p>S~CFcg|0dk4Iuzz>d`C z7Yds!Ov%vB$0_ll3Vuc8wGlp9*x8R3zY|aSz>bO7T1p$nc|E+fBc|>T*P`D%rr+gL zngGW8Mce&F^S$`!f=!e>F5aJ_-&V?BCwc41^0f=t!ie3Z7+tXYBF67}fhkI^ko@y$ zt>I)8hAPHtuD;8z%Y%(@$3px5N9d{!q8u9d8XaVp?}CVU)$|>Z#&i>E0)- zqb8$$oV`le-O-+}+xXgI-Bi6&J@yrLhbFxJgb^sS)%Ojht-ce*qs+`*hD{PinVTG@ zSL_6PvmN%O4kp^5;IRJ)qu+LS*v}EOaX?x2Z(AG(UiT1T_o)(k>NSirc%$`)vhc27 zE8m*!G`7U+r_TxSZqPV@*H>xJd++rk&#-RNJt?KTvJS+wF1)mEZ(--AbjMZj3oos^ zehYQsrFHuYYe{|KrFAzG){^?dOY067Ht*Ty?Rk8jb#6RgDr}L;*H1hGx>@~6kIBo$!|#jw9D4+rN!HiA zv2Mr}b(`WG!TAXRdw+@Z%XUhmtHU|GtM1r;7k>}NuzDE;({fwlaqNM8@32jUT`g=Y zhiw+IOB}}UyTEITn7ShPJ@D)D9vK*Z!R~fE{DOVyF#JvzM%^egy7&d7?G3{(*y9d+ zRoD~4Y_3E1jfjnNJbse_-VBdrb)EZD@wY_HhrS3FuzMYkYoR&fz3Z^7)?##RZpSb0 zp$GH29fhI$e$-Vq8LmG+=mFO49k!dWLQN+8E`W*}&f%ET+Y0-^@vai@89hsEYZ>-_ zAMH(XJg~MpA@$gQ?Xrnt&!bJ@8OAknOLXC-b#H5-F1)nv@mfEYwa%2T zB`NcT(Ow^=t-e+d-&XoLsn8$mh(|!z#=!`st#11Hr{rfn2t6}m$|kdAxMSN)={J$U zE{)g&iqQqTE@FGjI2dzDAC2)V`0=mEGi*T$+g!YZbq;Lrb(U(V&(%ENPDX(;bNxmi z6#x_rqpb?c>Xe+O4ZPhJ)j;^)Uwn|$Y?4k47zt(8 zG#hkRQoNd^MibN(iV3P#!kW`f*oFWKU^*2F_9iOEFS=Vw(7jSI;kR^;5C>fifv|V- z|KbzY-Y@+@@P1EH9>4T$4+(8w z?=Z$T*i45FiP*CdTU9aTzf~7Pd51BdJtmC4#|OLeO)DBfkGOjsMyg_oBcC~R}Zlm(1)s7ku0rgS+k znB#QYDBnRsyV!mwb!&Q)lUY6^Q&G;qia0Q!{8alUfTTki*tqGFehH2 ziE+A4!sa>Nb>dN$4)TSr%qQz(R6mHljUocr$|~2Hx;d#LhA|JOQ;pC^H#^-eqi#=q zM)0~S&aZTLak{MMlx3KBR+f3f@cU{7-EST5Zt>cy%sV;ko~S#vf-c9C`PfQruz1T% zY3`)VTMNVQ+7;@{J_5R;Bv&bY(BSfX4|a{P>xAW%Rx<2S9IN;dVIK%U7yM`ang4$I zIRTv}C)P(7Ds4Q*$$M{T55Zx_EB)%oOtQDbj)|C^PvT=r#F*F29{UhyJl=f1I$PMB z9m~H< z@{rQTn-qCEy(nSJBJXg=`&=01d&Oa&2;(>F&UYBUzsnvY=b{AWA=_i5U(7H2f7^^M zj(fv6XH3uS-G$BDGm|tbmb)NpDSl1ZWX0&_6fe<-`;N%Ns`ps>0FGRbL*;h_7463d5VO7{oB>2rRwxL&d8vR?7KbIi$xovQSk z!iG4EIV4?Qbiigh9`9-gd)8q?mEPvO@^2kc7TSD@u$R@g|&#SX0-A-`hDl>Vh$z_zj+y9QKIP%*E?PU2OK3e5ISf)>bNJcu)Su z+I!tg8GL{pE;87i5kvPw3GZh1V@;>4p^v^-3gOFAn3ci+Il~Ce%tEkf8fEfP!IX2zyI;{GxlMgfh=@*dLUh`seZ* z507&)$~-5w0oY+G!=sO8!W?h*nCq^3B$J#N>jv*AVXYp^Bs}v1Z)IV#gq{3Wru3ai zuxo@}us9RGzv6jEzg*-QrsB3p7v5J+m;N|S*w?p}?SY*Vv6U6$1FTVL#=*J~YbWf$ z$m^*zJTOgF!Jg@Y9b7^8KDEdE_lx`dq9olVwho@FwAq8lI=D;36oqj!wrkeDuNuyk zIR{vxL2y|7yh`y$^2g%`0 zWJ|vp2DVegCMZq$z;+gP>+adoJ%8r4zpD*6C;XRU0(G-YA*{b6k%g`FUBFBJk^P07h%$sbNA_Yv5B zl0#*Wa{{Rc9_=?n81tX$)(HDf*bIl&3PZP>V*PKXt6>y$>2tXZzX{wo>Vi>^2O6`b zy-l#0!amfGo6n89*gRUY(~NAQt_y+rWsrp5o*yIv9I!1V{O0NOs7u}cC0RbDSU0Q3 ze}sK{MmFpZ81`+%UQ-N)&1)p{-!JY1D;bVsn{yhJ_q@~3%9i$vnX@;MuzqY8d0-nw z>_~@gp)_mC5{FS=&Uc46>^!AeKgQ{J$1nC~MrL;6$A(J02MQ;jybCk2%V82dd2QZ0^Jd*uh6O$M}sZuw9+*3st|?1^ZTI z@%DIz6ijYPem@kp`W@M@pJZkEyRaMXEnjO;7BI@!&(*EH#yh$yQpsLtVd!#=X7<3) z_1Ff&4q2ED>!0y9jJh0)9z)k-4dRW|iM)zb;vE!q3n>g;j~y3vH+Q^ig|%APynoM% zSX))j%EI${v|o3p3r2m@7=AsL)jR;t)*0Fq3|<<;hsS=@fep|1CD=w#^m+ zj%;e)zh6aNKMugq^;q}T`mOj!o9p%zMwyv&%r6+a9@{MH`mr%ySbA*i7_llhHZB*I z9vfiku>po(KQ{v?9jG&9Qpb-2s?Fb zrnDZ>FJmIc+->c5Y}D28FJUJNV}9OLn5fO>cCOP+_jm1*r0Gx1=h&--rTv~CG4J>G zsO$aSEvzMePt=9jQE!yjBkDF)*s5=4OV3Jzoht0>d&+xrV2=qq>8<8veqC6)%uh$m zm-&;Z>&yJ5u$Gj$PA5-4Yx82RYdS^JbhcT03tRb#H{E;CW+QU&6y4 zJkvcf>MjeKE7paFE;2A(y8SBX zuIqH~7Vnzn&FANPqAt9&U&>~~%e;5g{aVGT@HUGW&#J@Q2);h&8BJRo!8o}Do5JUjmyOuh z4qI0k`zl)ILZH63uhK?o)8%^|v}rzKnyQkcB<%e&cf$iaTJqwks$>n#J%;ThEIYa? z`N&~6348bK;y#k`ZWXq(yH>;AZ4&mrwoz=n_muun58n*tBuSx*YUH8^VL@K-`8{DC@P?9*S`g&jdziFl<$&=ZK8OD1i#h#jNtvgqddCsMoFIe zC7V1go?)yJ)Xn^=$-=RRj~+@JZ@$v>+rAFda14I`q?q9SUZuS0zMwRIRlO4SmeMWp z%brNuFZ(nt(d{Q*TKCQt>S`OjneL`4$7PbI53MTgxf%9?zErZBKBK;1mq*?}hrJ)M z-YE>-bsY9VvICO9+wpEs0z;nkVh6vF4bIO^-wn8_uSfCcee1V+p3a6{2bkL zC6#o?=>~FMpAq13kM~AlLt`Fnu>MriJ^bG0x~GVDm#~peciIYc&$z$2?gQezAa}vEy}w_JE05)|xP z$qT|5f9Rrdqds_58{%Ufc8jpN!gy}ac)Cmr*nJLbrLrs;l?&f{Hr}Peuy=H;vaW_o z(0#pi8GB83c9QOT&Tl1bsd$uy_Qr>*9oDxS#^%Cvo`x+I4)$}j2k$G%B4O{vGHaR+ z>)R80114($x?o#Lz%(tEuwhD1)nNTJVysoiNH#ev7xvwi4Bv5P&D>TP{j4Geti9rK znoQ49j1N^ioHKm7Uaquv2*#QN_BY34ZvSwo?8W*j8|%1rt8m-G~7b343AlK&T7?EP1N zER4|`Q(j~f6mG!7sUAh?B9}ag}vjjZ-k-SSpy#3 zF3Jzk=YP}<=HW^cs2|UvU#vFRHs--N-<>Cnb~Ig{JGgL0u5|whd%9dtww(O4No71KH5>^rF--XMjwG$AA!+FVAe-q^wINrID+wI_UI!p z>mzvd5t#K607k7tH)>3nV;G_1bB< zaGtAdSkGB=z7W<+dFlc0X~`+V&Wo5Ri5`te{?ewnrvML3m#+ak-SH*}J6wb63B|_y zM)N4wp&aJ~=2*K9-AHNAd-0)Mc#a#4e&d>M)T8Bj2<+_WWBaHJHYf6Q$r|jbyOXb# zrp)6b5A27CUG1=(KA_ASM_on90g{@<#c{7>s4s2LF>@q<0=#u1_M*~Ok3~wOJ4`VF zp6T8YkmkBwL_nAFu}3lg{o?!!mE$gb4GV9ec+WnjwMS|5d!N$uFKtSIXZ^da(#Cs8 zY5KRj!+uiw^DWEIQ_FmqN82vSB{w-~t9~U`IRMN|?6pldgJU1lO%*?{Vqus}omWk0&BF#@Tx^Vi!4VTiHRk#@XZEJQ&wW z=A#g?DGuX4V_J7i#JHX^-Q6PQbvcLo>Gk3{jq$*ac%yutqvi?ank(LfSZ3yuBP4IX zTRzUg4wWz_ZM_6ze1hqaE0txs(p&r^SNblQT!wefj}z8Q87s?a!uOJHuh>VF<$4Lv zjkIyt@xt)2jt*vY;XNhUkPkwM4fd-ddlRb*TrokNBZ{-3Z2Y$|c|A zl9_Ud&$g1hEE7)ULYp zz5=j&#T!*uU3v}x?1_l2tF+mBN?3344s_Vl5u=}tw?x<+@u-twFA4iWe!DpA4PiHl zw}HbnT_@Lcs4jhvfU^8a*zbh(Nbz3m*qq0A$T#m)9nOKx?~}s5U8Oq7OBY+ncltvc zFdpC$z+YEeQ9c6s&HoQ={{dh}RX*XV%9zb9zp(9Z` zidm|30*DkvA_{_{6h#pg1A2APNG%=Q;PhchAlz2!Fo(XZOrG=b86? zPn|Po%AFy9%B`J9i>(biA34v}O5LSl3l?%SF<{+$4Aqt{>V6%&-cTu zdlz+O7m=5;J+_2S}_jg`cbuNpsT{b$ick}+c zA#uka`@u^1+LQefXTNg36YMvH?L)uIY;%0)J`b$b1pI+kqpzhJMyE?=QL z*-&>Wob530V*S4@Q1?w-UH2{6Ej8WqVXM}3J270>?S}oTrt2|mmqNFP_$4^&;CuMy zS#~kb@p)#!oGZvYhAX!PanD(PNnJV5aFJ~aTYp4%I`+(tsq36{UfjLQ^gpK{bH9)| z#|Sx@{Uw-s?#nl>(%M&*ldUEj)7_r4%4~DlF*(nkW3MhNbY=FJQdj0UQ0ii$+K>ME z{hhnp?@E;I54#jbS4epdcG4~b*>%WWG@&Eiw=mDj-2{7O*Y5T`AQ_iB6LSt8ayNAG zEON6W{njLy*YmudSk4dXY$W!s!rl2$S9|}EO~=`mlXDuf%QEZE^YX0#(y*Oy1L`g_xJ5i&&Lu>^8;>QR8PY^ zHY1wYmHL zr)GwU%44Xk8ym`559i{%{_@)_C;I|!@y~R(??*XaY1?ZuJjR@Kw;{e1PJ4V>w9S^y z?3sdD56W$u^XzfyKEg*$?XLXYi+Pd#0k-K0j3rrD_B?F!zV2!(G7)lg`E=~Do`dZP zyYHm#YI?!;$!ug!V=UWd;MO~}yLw=7OIP*)?*22FALRVW9>JOCwR2r1hMj*P7vmM# ztd3%}>CxToXIGW;*sU&?f>ZuvW3g?zs}=TEfgN^scly1xxg2}Eg7(-h1!-u=7w_z^Z&o8`%KnD)_k+%h zL+(|=_Mv?X=Dp8<{JpzcHTPY056SGPLhkdhG5??~3pt+^|Iv%x>6|>$_zKK4%xAER zGmGm7*0X*0=$F~|v%U9Y$$me)8S!_HW{3du4Vfe#q^enPXnCB?&*Y+raZn zj~mazv>S5H3!K+&nArmO7coHnb7)T*LzI(!2{z}Dp6Y-??lRaCbM~a)n}*y$T!6S7 z7JX7(-^I1~Ts_r!Ie)T4U>m_+D(nrKqg8*_ZP@FEY47lY^}w_@q_F4vxlTeZ#w*kK zPu5+h(0wcGK2)&fhjIS1P*3}qr>^fg_1ev9MH({Ow`BVbr>&N1l^3;CR}ap^`E;YZ z{T>$W9e~_EOZ2qwk;;BCAANj8Px~H_>?zn`%k;FLr;$CKS?nLOp7~q4+YyesS{C-u z!aeDoc4Rx{<;uBQzj1P(2)RFJ-CYaaH(}dTj(ZBZVI(AbC--O5U5}M{F6()H*txXF zo@|eFPo{nCFJ)Wqkab5D=^hMQV#$_n~_bs)?RSJcPOTwuIG{A(G~uv0uuZA37JkE6cGvr(^8TPU~ske+%X@Wfiu&Fhr*L z*C#lSXE#o1DA&NAx~tcix-yqiH|E7|>%;B6DcAn-U8vghp6iXr^goj@8Fnb{7}$#V zmd!Rl9_Kq{ud1<*8asmRj&;uzau*PO;fwvp1?^pg^L-u@@LgnQ;Y?$3eA6}02jRB; za!<-D!Nfj|uN+O47Ug8-MHae;5&o#UCuCi`v_u-F%g{Z5nXb%q*T(0vNcEprTt| zWKU0GvCe|x;elvxUAyN`aNr+rP;Yx*N`TcEoJWmH!- z0{1X!?1UezLHNq2`j55BZ6^CuPy2e9Y;)XNu!r$OcMHO%F|kPFTQKcyRLIH9v#g%y zxHo}`bZ<|4Ya(PCvaNCEImRp5Hn=xm=xMjP>}H(08xaZJ8)52hi687H!shStf?Y{^ zvgK>cJj?2N-ZSTq>2!4);l1AIA2)*iXx9H_C%@Rw9P=FeSLqzwzLqOgYZw?xqo=Gj))Y-5RT?6I3-@QTi;55g;R2t9i&xgRiS){9+_Tt`?>HZ8h zi@B8ZSQpQec7b`mFphBKWd>|1j&E^}qwd`wQr9_rU3WZX-(;bl_Vsq{`K-_~`?Q{I zL?w+83&MuM;(k=h6Wh}J6c93hGNuOUx_q3|$>z!|&LK==ew@dOMew6+OwkiNwP2q@ zSGgF6$VR$$^HnbX?2zST?$ev`qxU#=+h2~t_3hr>{{6Ia%VN)Cw~Oh@mV+&ay(I_} zOwZ2j&wTO^%!hiiocuzZZL|x%i@MQ9?#J2-xw%ISZa+`RlqDU<9~w0{JyW8bY#H3+ zuvbu0PkX1}=3RPl`@2SiiQ6aC{XD+9GRG%%Psgw8o{{B-;Cq}=?qz(JGL63y*Pe3j z`=)Uc0y4*E&m&|e5X?5x-q_jXdF3qUxar((U?L7(e7%6jH zIEL_LEB5cxGPip#!Enf(0CNs(9mt3#d%H6yJb=6c4e-~*{o%kN z)kDY!+YmMn7cb_|^`hK(+$OM@G~ybBO}FEHmiOI&yz`ZqPxu1yCaxE^A1>Xr-ii6E z6Sj%;V_X-mgKa}#>N+QMu}z1}*r=KdHw-uAu8pcD4Ds|$f*JTOjkIpH&AhGf5<{Gk z&fQfl!DDef)lyy6VqMijM0=_whE+?lPI8|4axULd4YS|cwziwgtd1eGI>ycFSYuX4 z)yL^?>rH0qd4fLY3o4FIkA%J5G2`zY75_`mOi%&69V?CRoZzbI>XWXvan(t3ogG~8 z>-1L`os}#dvzKn`Hwg`QmFg_5I*m454RIywnzxBMa-FU89iLkZ14Y&0YLKgqxrNig zeXFfHQi$6*TeV)~W@z~nQ*>_R7RRN<0q`qRtKpYTt(rI+wSnux4Mpf|TqkZ2?i8Gh z`Xf?^Z9}*r1CIez7|`^9xAUDxUOW`EKRo8Fnaf@QH?K1_v1Rg#tRKeg~!Y?MpNWd?K_mLVq9sywTw zy|jwx#^|S2XS3?;ZFcV4?CkCB+;3v%r}&@LdEms(19$B_aJSCqckA45*UtU6=-hAN z&WTm$@bpi`SRXN`>TGT^-znp_nXid!=Y?eD^T8Up;eb8q3#W|+E-lSgZEs9Z z@%IWE8cKG1`rr-R@S&+S1|{L#@`Sa~8cPYZYAQWXJEm3CG@ok{cBHi?+WDJE1UKg7 z)jG6c8@hDRK%N_RsGs~HJU2H4HiUPo4dJ=cA(hwqoqKt#aBNc4eZ1YrC`0Q=U->vg zYjwJN(*m8%P97^{wX>@=Tvh2FEMCe3-KgSKLF9FT)c5(Na_4E4e_eUqMdm`+}_-5gTQ;D3(lPX6brcxwd@lixE(wHyCKs$GXv$MQe4+IvW~^N?x*6txq_ zB9g0mnpIbWK&O@H($`(}4esmhnl`0t+VNe}KG!wv;I3)CJ=1!-hBv#aj;>+emT3vM zRr2>^?W2A_cX};8qZXf8i-(;L^BrE(h;$}kr;LZ4n`+$jOF6%5TgD?l4Q%@z;;_?O zlbceD_toOlhGg$lX?p zThFCl-EP>q3AwU8W|zNm`%L5;A{@RF& zeY@(z4WS|?%p6f|i8};$@Sj_=r_zpjacK;}q0``i*kHh&K4JA%g|p52WOLPl>m{JR z{6E{6=Szo48#PJxBk!jQGLW(d|F9f4^wd z$~CSQZ{~6|u;YID1aZ?aUiRl%*p~$#Ug#;O-6q?0?oU&QPa~|`e2)J7OoI=H>8#i3 z#H|~h`_t_DcY|%ZGC%5-c5bT0XAm#-X4c|S&mU%gFVnGp!frW^T~IR@I~T2_ov&wX!qIW$2yLF7WEVL9`zIPs2}CZ{5(QD(!Y%M zaw)e*Sl{*yJI=>K&wNj;#rud)Lq~TZ{be}m%p$D2q3AzTYWeA_#i!+Xlyf@qUTidR zv_*eTv{5g$2Ir6C^buUlZoHr>UmewUFlj24V77=1=2ax zm>jM;4RrRcz&fp}=GD(MT#a@$t&h=hOLxB8cK79JbY z<=%Eg-Ey&vqXP69IL+1RX*H9x(9_>zb)Ku2T%GFF=i(97tU(v06|DztEv2ng#Mtl= ze6R1N$qxRQt`6?1AJWw~#($#C^xpuE>FP@VjWJ!r(|>hv*AVy$U7ch6AA)?ku99sv zn^m*dp3>ldVl}#ndE1RC;2Z|4J{&4k6K93Y<5;+CN1qwqx|GlZ*fHVus?|2L-t)40 zT2k=y{lO{y!InT?dyOQnwWPsOPU0^1CAw%j>F>ZdkuLnzs~J%YZt^PaJPlCTUweP*DGv1pz^S!CF z-kbXG_on{$y{YfM$5q61j_*18FFJi{9mhHrNf{50Tz{~T7uxR*@86n3xv)7_@0a@D$(BRgYX2hr0iR^M=y+NY`Pg#WU64_6a>_G}MVd9m>(Mnr#lJJR@{ zq4vgs0rR(X8_l?h-n>4m3s+%v`B+xJcC|xVZ9wSLu69WxvI||^>?$wX8yyjfXxpR} zzV}V&FhtXJ_S1}R>dFTIg>*8Pr2#JrZ`H^G;36H6~{9Bwkq>uBB=QO>^Vcbd7lnHsJae+uqu zn9n>Y=k9kuZa6#d83nsH7#+qEDt9w(8RYzZp-aggglTVY_ypV|$XNsz*>1QeVNLvy z+mi4bhjg{J$u~yF|TL6!!EHQ`}ARiT{g#EiMyEr zVPAZ8mGgPKiO3y6*gTr1*E;uw9fPkN!BjTe!@76r#YKDAMj^KcVcWy|`r7NoMSE;R zSUGJxNrg{Yp>?l2*dH_dL?P$%B+6}Cus^}hf$dzdw_yK;F{HKAcpJ9ZimiKUk;Z$l zwP0r#a&wT;iLf7JW_fnUS>9;hUgA;SCSmO<$FP{ndpUON<-GzHa_1nYy|_l$OFZn^ z4k33TVe4-f{JOnevs?q8Tjj~#GK5`vaba&+!rE)#FM`|$wa3!P-AG<{S)=uAh`O?G z!PZ!{b^HwW1K5tRo!B1C--#WM?q@SI{p)c%&)NU{pzOxXZopSp_AqYxnyud^273#3 z)apzWuq*Q(*O`NO&(SKa-|PfCE3@_39_;MQ-0y;20GqWw_cIGN2mO97$`NCUY0Qod z&2qL|*xMXtUY5^{aj}}0#S-$oR2 zBeOlny1KoMvz+<(H*USnTKAR-ro8w#-2=jWg7QzjIg}3YY*Es()}%RAEvy|W_#`fF1kk{54^9d*cha=8*UA&(?X^n~0qD4xf#^ zBMP}mS!a3 zYfcvIl*}AsW%mD<*rz|J{*>d@4ynA0(XS(aQ4XK84SWB|_GUL8MEz;ccL!L1ml($N z;=rD(s};Jfu^wi!b*y}~k^4g#3_O>YGCeXIp`(NY1 zDCD<8PJ8CLZts(Yy)!rm_%Qa)K~8(?%*Ng)3VWj{sQquXf-MI#joo4O{%1W$9gIP4 z;eA@q$p_naA9F0zeq zj_rdN-QDR(8l^;gPWPh7bszU}3)Hqw>ZkFBdC@uR#`2z#v658dquugoBRY-SAM zDP47UA?(tN3*G$*tE=38IOPt-H-Ejjkoy#2{z)8ehn4#mwwdyke$0mx=ds z*`AD75+!C|GJmp#VBbbA+E=!4X5Yzjm`}&6BW`N_wuoq|n|sOs*|4yu+?F`ycFi)@ zVaOdx*mO~=rm*3f8~gVU+0n4ie!peIxb8-nX>3n8bd}pM%LSW08++e??R0DFI%C-T zakjT}VNW^j?O3p_Da;$}fJ=V}W;yC|CBuB>`NBcSMSIA69`-bt^=JNM7va=BrC=8m zz7KXPzU3ur>AiA?{*<{OO2PIcd=hNYg6%{2Yp}gg3b_q3i{FiE?^0OZp6_)?zqP>+ z-HWnrY0tJajj%_wI*9tTt9Ce7nGB&N8;DO_9Yx_ z6PR*7XC2IIW3s*QBaH>w?r*7<$-1WNeWugzZvB=&1>Z^x_&VB zLEbfy<$^V9?1yZB;epnC4E5BHHbA%=Ip>h3tM0wHV`1a)gFQ<4T-enGdn~hPBXyt1 zY{hKPbdDR;ve!#kdostX#v@#pC9Iz8W>#}Q)cW>a$eoPbk-wr2*%r*ZALft4N}Ih7 zdlTlE682W1Vzsw@P0sJ4D;M?}$kpwQhAoD!{Uz+Jm+i%PV4juJUi2&3o-p$~xkzI# z*kixpe7s=$!@f!#%&0N#mF)SP#$kori?GlCmTN1p$lvV*z6!g(kn>#4bnhwHmh^3P zH>J*8%yZ~21B-gu207~`-aV+Czp;?{E~k(?tcP=b@;sXDAH>wH%hlN&gLz-k?|A1B z_FPPtpB1IHypJ+Q8VhE*&mf>oDfbm3A;)8fsc)REF&5>bZ%iW`a=pme=JQZzVK3Tz zURcQah_!j%snDG>Gv_KHw-n5MYxN>8E5i0>XSyiYAH}M^g6&lwZ=KtyE4vbQBW&et zPxe*V^1tNRN7($y_QkoMZ-5`V3(`i~i~U!*MPR;b_A7+#FS2;o>u<9C=80o+ zu(8zhUtqDnsXGqVc(OHL3b|Eb=FhouJ%7z2jgycwje~2xUZxl9I+))D`B7$gslMOHb!A+8-=iFsZ7l(d><6&<>GVwJ(^6-qYul}XGmY)= zgRM*0Z}{ATuZ;B{d7e%<zREg=e05Mqb!hIBvimaIfIb(xo;&{#xzY3V zv(;gD!&b-)6X|;g{@y(H51E z>+4dwUL%pQJ68=l!_(M%p&sTaqCu;;#K*_!w+A!k2O zuC(_i`77;R@geOgH#>VHYWe%lhqR|$Y0o@;5jU33KLy{#x|xOB8ul4{%c0z5xC3DS z##cu7C!BI`;VXyv%KLpiOmJrqc2VvD+(=jx-$lmIoOI8{58bb$yGo<~+ojrj8DaBx z2w@j>BY%ex4qZN3S1rsBDt?w_)Lo25xobp6dM9bfdEL=+?8tT(?L|3uCLD5avf=Mb zbX4Ci*t@Vvq%nqkhFlM6n7`6qoip^}KFbN%6#9~FE;|Ny4(vzl z1i_AlT@L#}cRxEhv-O#aC}-ZL;%-=}H9iMB4d(Hv4?ozMgx^H&q`WVvdp7Pju%`-k z1FUZEMp%;*=RNSl-tAfU#e)5i@D9j*wP4Ow>h>OinZFAPxkm|q2Hh)*ygUXoe-CE1 zEb%>Y+FJzQyvX*(eU=H(M)-&(X86we`@gZP+&(z%-GZ;K^DX<|;`~;9$%5HW$Nrb& zMNU^anZIe5xsTI)>3qxIv^&OXZxj3m?pfqE!*{WsPe-1xi}~{qwoRfU9@w;_nm4B*^PNJwZPI^SmF)@pK5{Q+d$L1d zha+d(o36~~Bffy#zY6BF5OsU!z^+7&>2k`Sx|e5rW&U>QVopvPKKj*8BeNL=J1n#1 z@k8!7!e?*RQN{Hp#M2zgI*tA(J6H}o6<=N1;h8b*Z?n%~Z{saHs{a)1ON4(48;$Rx z?rylpV5{MWJ30vz->I;pwr;)mTRn!9^!|cruzL#K)7a?s ztFIUA!fbEff_V*8xi8>H{(L^d>t=r___ZTfE4hb?$zC6~2pg?R6FR zbB2U=8jcCd4MjkiQtoXck(U+NHs>xKX>16#GR*g}?uZ|3ZNiHpcW1%YCp-rBT)}3N z|2ueT$g&0d8*Je{TJIVonEHnMz_zgO=eS(vH^#q*Z@TO*>0RJmXLnQ#32k-@8}>e{ zfB#jEPcT*sBiDtTWtH8->eI+Y{$ww+Ismyh2}c^Q!0PsVAMo+W#r~_V-!;>o$CjuU z=TgsI!nceSV6pBVBka2-;ylW-Dd#)1l{0_J#XGc*$z@aSR5tofs3QnR8ef3<4a|cI zxeH)_;bm|$@Iy}K_iszqz|PmN>Hp@oY0Qp|%yKqP*sHU-ky!v|TYdxI#c?g#?VE(v zRn9rS-!1ldO}3KUFR*R-SJ(P!tIBfbZ$qrZBEx?Dnn59?8}@_ zG}(%QhjcVzX8lPcd?GQ z#~llM0C}>L*xvXz!luGZV=m%=e0A#tDa$XB9oY(7wi?nes^*)>c{*k_cp5^!Di(CEbCzVqp;@-#;1C!CwJ^@ z&;OM3bw;uk35UJU!*1BQv;FL#a(phZn#|y?>;Y)b!FGW7TK+{eIHEr z?JPHMp?gD?`*ddWA*b^l(9Q`=!}yxGFTs3Y0-|ZIw==%)h3+ocB$&G6VCp)Stc&wS zg}dSf+l26+nDCudux$vhh}?xaFY2y`+Y$D9W~O~Lt0~;by^OH-WDG6U=`f$o3N|CN z2l0bFLRj5B^Ztu?HJa5%pXIyR*`91!R(rz!R-||A(`Z*2R)~vMm z<3es5nD%~BFq$^mV;F1O+XbdQ=TDL6Zo7Gch(J-zI_cNTj?0E8NT1^X6Q)yQ_i{NY3IQ3&9m$+ zoc0c`u}@q!ko}kK>UvBG-Qn2w8`NjOT$aQ+_w`%zC*y~lW8rhya}0G+Zc&`ysy+oj z@%$M_i*dUHg^w=lJVV*55HL zG@!1Ig@wII=vof4*k*5Jdn3&VOKES3LT(mv*2~r{u>ol;S;);zU$ndockML%PP65` zA6=92*d67aML6=OuH{`j>#oVRr*VJ1zB650R8ICB&U#)4KiCU|ZI8+Ls1In5eG9oM zWWZyda-l05``v+T_bf-Y+j27HO2%+lt$S$y_Z7{b%>3MwlM2&A6UJ8_blXI$+~4-$yPmVVEw(C?R`-FJ;||d z`#T5b@6RyvSMDEwfqj_vJ%t0ax_w2SWwvk0PJ?OhgYx(JIa>KE+xK*s?Hlt++frt_ zB|9t2%_#EHIrRUwuk2kWJCh5!zoKhDIFH7NHj*h6g>>u)Ytz5eEbeVF?D zZr1H9@*=Z+OLkMX_d)gd#4zU2lR7G|>qI&J2(zC)TCfMR+zX5|A@{2+=QV|33vhx} zx3>uF2Q_hnp&*!u@Cmi`Z zcR2H_T6w3zY`5PPa#OQhnZHxBT$#W7I2o~ILnpxewO7*d%tADti7_l zzk&HYoO9+Vhpdl0%c8tj61Kb(vYa-4jdLD03g3k)PS<*!hpj|dd&)hIQ_gv@_DZ?0 z6IafC%wwzbzikUPBD33b-%xI8+$IYRO4sWme?NeYTVPOn|3%o_2=*5qOm&XtvM}x& zjFUHUo}%4SPJ7DL?ftfpv+U-tS+FfL+qcNy)-df|gf+kL(y@|V(Q?DTny z2HPTkM-uj#i8JuEr(8TUaVcTtoL^d|GJmp0W+&%#WutJTml&8onl{y6TzjxBY~MlW zcDA1dll>m&xpT~~WPitvKcu7j6`3avocqFZ1^W(R(}?4*a^J<-z8+WW?Yko^>|I4zdy5zB zYQoxc?i+IMQ`*}Yziw}xLhdEPAEvy2Mb7eiz8Ci5nWwV6Pa{_^?=v}#vb=wRnZFoM z%l^DC+oBwgW_x9MAJ6v6@;;I6eNcJFk$>~IN|A=o1z8817HmzJ<-G=0FYm#HoY!5{ z-3aDV_LmiiM>+1!_V$O>?VVl7{UqCyxs>+G{^vCX^Y=Go>h^}SEz2fp z(^$D+oE9W|9QOW?z2gcw?~Q7&EZfX%Z{0%f&)MF^v$3~*mRkegapL&#gVK4q`3v^Q zJDmgAh%9G4TVCtsa@S4*MV5E}0^>RVme_cD8> zV0UD83WW{1hcmlyP>YQtei=IRE!kCVNZ3VoJ?;U1K(Zyix-zC8NsdoOrTQ!7R)vM! z2-4HuFRf&jQjYH1mK&Yr{tHvIl#Ay}NHXPN(AHh4pAfBNJK;vbcE>kenaAJpu=O!k zGUbAGA@eBPFWZ)~p`@Jbfy}IfV874I{W#c@u*cB77(bZL=byv_TxS<@M`rdw!Ip&` z%|}RADRgD?)R=3vxguQc-)83i*!7d@Jz1<6YZr7gI z-s<*_EbQH$?QK!mvwv#u@}e9+fL+Q>3-9ZOJ;w<1V!w{OTu&#IjVkQ<+~EzUb){!S z5KZ;+HQ0jOpmK~4U7uGn-4(OFh1hm4Vbg77xjF+Udy$uk#3PMhS7+UY6(;l6%l(E~ ztoyxi=J^?X^P-&ZJ~3U#U;YQA;d8PfHPbdF}@t>^G|uVMY{*v!r= z*zuWtyI?0~c2B{+iBav{J!ii?F3%?RV!^(h8SkoZ=jA(@H45f2KzklbBhOD|_DaE? z&a8_(h1{PrTclw3(xBS&y%ZsLe`YTg?7__DVZaT!UuL#^!Jec~YVZD`{c=xb_P2sP zo!R_F9sD`7u?722X7-6l_wCGV%V6(hwr9cK%WO(!6o>EBFqb>OD}4)2UD?T*-H3d! zQ#13~@?fWD_Go5~?Mvfc#NNvI%E^|&+5avo*l5Da?TkH(YGINYFUFELCxgRY+B$&r78J7jy>=szvp7TFh zY45hIJ7=N$qs(^7jBbce*-sp_|Ee-*Yh;gDO6u=h>>S+ETWe-^o~74|${?DE5|G&Y8= z`<`sqLU)nOJeG#sqM7}sU|%47KL@Ji3ic(!rW@CNNIt#SLUvD)my6+NaSVt#tNW_Q zx}W}x7cCNYk=gJ52#b3Jvawmt^J?p)l-ob2A)kdi`ab3s_%3Wp&!+Ui*3EI*XjVRB z=sdx=&bgHAO~TfJ_AJv8_jk3gMas5@SvKdpA-6?lJL3oQSZ8^Eni*btkCJ&g$OwyG z=a<5slM`7ry7urs$frM zR@(a`Y+2GR?LC#{eq89jp4lD+vp&r8g9ZCfW^WYit;`w}D$2o6A(F1oCInkJvlyF* zrr$uDhI5gSTQtl4pkOOxR@!r)Q8&(Kh*m3QR@!r)QLeP-zGA(cU6kX1%x)>zWW*^}ohE<TVwg z)%Ci-4lv)h6LJe>_SJ&f@0I&u!91^!EnTEBJ2n?`zeR52LT+x@`Fvb?n}S_U9o;)` zcRKHnyvUUMZXtI)>^kiI790Gh^4celoU^;S381bEsQNm(3#M2rzA)S0LU*NtEdsL~ zs}*bsn0a0oR@(b%&7RL+)$RGLRo&i-+1>^7l(TI1N$V>5xNI!!)|IhG7||s6DuE^}j@`;R@4Nj0o(<0SHizwkyKt#i zKQ)bD?=I6~+Uv%xi1W7!P5e@B5gy(hmDxi0mhG#&~O-42M6Pm zt<(==JlHbJIR<TyY8uM@5U1Rp_+c;P%46+;Z1kSt%30U) zaY??qd6(`qch#QkQ<;4;*OlxrnDf7f3+6MkJ{P`ZVUN@GWN*`gT>vxPjcRPpFZHvL zY@>Oq&3@U{zF#Z*HO_Re&gse?%4}8gWS(XBWj3Q=Uq(mWQ`r`B+F4+q?#kmsu<2Ru z2y_XiI^37=F1NR?{VTU9{5m#XG@<|5vS5~D|D1-*b6m^oIY;Qqlq=cZbWFd2epVsp zZwY1QJ#-I*nU}3|*-T@%%p5P3!>jH?M>+d!Ft6LoRx8*;nc4qB&URJq(t>SE8b?j( zs^XrUY504vdk^j(|6~Witmm=#Vb9;?%lvJKYEm)j0y$Q1%+SBcM0p-AV@mRGD?(PS;R)9Y{IqS2O`)48N zGYjT#37AWnzom)S^LJdqB7e`rB3;MAkJH{9|HIx2MP5E^{rv}>_siet+1UG_^8W3A z*!w8?`wRB&p?$Z*cdsj6Ztn{P3wxeF zM*H4N`2Fhdqm=ij*!wukd&|dc&pE)yS>CUG%=R2xKhFAd{CU6rvOe4D{pI|EMSo!$ z*X}PzXM3|7Up~tI=C$&Vv%H6Y%=w#0+260fe3bFjd$;dr@1yK*_hZlcE88Q+m)Yg- zgxR$3v#=Ns?)sSXcl*bjzwdp_`TO?AoWHC8NB(Bl9v^f(x-{FH-FUxN(Ux(%JhNc2 z|9Xs!_T_QK_w9clW&b_?W43qjp!XlIK1zA-!`=@c?n>_|ry9~RcNu)=SB@1?FW!S( z_=@iIUT2Dw;Hf9?w5Y{r&Z0wl}%!{o8kG@>w76KdArhfxVA& zeCCm$kJa8{oXB`T#rsk&&WD^=*&fdI>*bx@@$DVtq91IEz4sfRKT7?ro9)H*mvX+= zm`(nUELiNnPZjy&lEufGzX$$@y^qqL7w>uh{CyOA4}OgHR-qm*#Qp7C-R<8j%g(`h zj`$-x3yW-j_RAsP?oQ94*f(TX;$#yUAY_h5KR`#_JLuQJehl+ma&2q`^WK@vcOwLw z5pr3VP3hcV(-XR@$%K^)=Do3!?ZtNG9xCL#wv*D$`Qx&7x-MmZZV+}U``<|7WFfIQ zemEZs7X9y8n0fKKtozi*wSQ>ObN=_U_y22u(O&PzZ0}_3S)b__l^xnBHl z!{U7p)~VNko_MUgef>{%9d7Q&yQ}ZuYfEQ)ZUM7w!8Ra#E^IKs{Hg1;NYnkkLM*1; zi!L+fuD-#xV9&w+2%CuyPGint_=BJAuKoZExmO6U2J>E(jA$AkkAAs3 z?Z?3!lOBAHaS}h6l zo9qdln;>dj=*NgUMWcDe-A-CmF#*`sF?Pqb6+X}V> z_Kq&(Cc>WPVZC=?kw4$R>$AzL7HPan$Gm#Mp7c&fMAP&A%TvFO5%VL*e_}D_*!Gc^ z*U-KG%#LcW!rpfC@;vc~p7y;H^S3?h1U@vkA7Smu4j$HOqx}hoy*-iJ1i5jAy>B9{ zy-|hSb+D%>ugBN0wA$+XuUQ(Vq6Zv(!Bm_6Hu6blw?xIW5b@zM$N~%eD58xL+n) z40irnJ?R}=QQke~qEFM;ygn87mPc+pef-dzzxmjdxry}6!rm6t^U#%A<_Xs)24gXP*i&vP%BEbfmtafo+LPX=gj&kWo4N0vUda6eIqiABE_9bbZalg# z=&@+oBj2-3)`N;{iLU({Y<6oS=_8&bXWYWKiQK#pV>pXY%<$b zxkWkfny&0bbQ--q?QglrPPYMQk8ANPuk)h$aid@hv2AuN?ERDNw{O;yt{(*RogA{* z7fjET6;m;bhL` zLU$y(LpNbx$n9aiJs#dsQQ=C^yQ&Dcg3lH4@>Rc`1>zx@ez5$p)q>-gFW{=MIE3@BKW@WZg( z3pSqc(8qexJ7Ge1W7rlj&+TOFlIeY0S3bpYI_n0TIJ3n}b1B>gxY1AaRHx$yYi723 z?&EV4XUM5`e!izYzmjS51lZd6>av?w|G-@gyROE*lbQLmUtWuX`P+za$;_WD@)G&8 ze+6q2HqZRrJn5S5*V*{HfA+MWmkPG}ivyYS%^%I`skC9b%E?Yfu4LcN_Qn=+GVPV@ zhHP)^LQbZ=V2)8M!KQQ#PIEn?={$Za{+ql+ZcZx1yoB6TSj-87jmWxDS6@Q+MQ&nR z_byaLdbZ#9k8e(xFvF-Wg z2Djg#E3`!OuWUD+O)`COrSkvY~Vw^kls9NW*st$Os3 z_Vb-G_d(N$a~#>(IP*LeUwbn9n)W`C(~#YXQ|@&9kfS@M@pMn*sPc3?it*Hareuz% zu^-9z!ufrJ1@K)s)oy>^fa!74mHh_SWIPyyZ&_t@DO(H@xMI zYIzQ$EFOjWmocqi_8KYnE!O7Axm>Z>^#6BBxoY7Ks;A@N^gCl^n}ez;_&Jz0&2Nlb z1UI>8^p+Qmo}=0Fax9BZXu&BhZ+y!`T7^wp-exTig~f0SXGJG%6qYir;KkOyM%5fs zHO5rK8`Y38okPY{!^TuY8dc|*j?OVv$C$nj){SO0rnef?tQs2WYz*%lGX%+We3A6N z_uhLAe5-Vk#v)Z;Ek3;#pHYj?ti^L5s~YdV_ntPx?l|J6qkH|g!>WnIZ5-p@8@xz$ zJn`EI>pnNfBGowT-k0NN5)Zp)!tJ|5a4(Knq%wbH{I**Bky`x4T0HEkr_HcyIm`TO zr;JCrO?w^k;W7!=#Jxy)!tRusUSBOfjd%kco%M24j)z^-9mh7^PYb*1mHGL&>Os4v z9rbWsEpEM(+n*pl26^4>buFUVa9FKIGwfMwZytft)yY`3D?q#*O`7gKI z&Sm_*THLXJ(Nqdni~)Y*Q-2I@9o%iW6FQq6ha|@{&!c$v0Bmb~=bPJRw;6u8O$lpv z@obkvVl}AAs(~{zR)Rx1a#crF_2D&fOXKFlwKoGhaIIyyqDg(3K*@;G)iBq?hO!!B zXlPn_oSM^66PJ$Um5;T=bQ^>r@3gi>2D3(-yR`ew#!W74diuax_`YrFy2SJmu(YpqlfhGZ_{h- zc~dPuqZWUp7N1GHflZzJW8}A4le2%?&viG^?+>oU`)YQk6YoW~iThizA5Vgp<_JJ>#ncrW25&UW&+^+*Tryum#+w7;LdUw+NA$5HcJ=I_JS!wk~14x%1r5!Yte zt+3l5uDgZ&HHx_HIGuPe+nTttpN)Z+cGjuIC)DDTh>ydD?j`J=NxYYE6Ia^RPMKf# zi*=A`;0~tWsaM8l5O1xL=LZkY$Ta(lzX=4ea~XK3AKKGrPLQl(y$ z);~yVTeLOywOTJlS+(-gl5gn_Pu5!B2Jl?8wKO@%O*P26F{7LHsDenaclI!Wfwg=e41{L@8RCI3>K9%p$m) zk-RL@acbE-RnB#*`{au3XyudPur)UR8zUd|ZF$?{Ke(MaS+fU+?z@C9CbK8tn^rGw z3hrvyiTKJnLTtgtLpUM(YQeULT}Y?#`e(@P0K1vS{A0m(f-S-X@J}#;$==WK@4?<{ zh1_BEhug3h*C0&S=KvprZA2K+q{}VVYDMggE?6&2d-k2k%co$2(A_n&eepkqk&i14 z?R^@1Wg7dzrhJTPXz!?68vDb}{utBH-g&h&9B979KEK1r)^CNZQ&);K2v?drXgEC>wb>#AY7??QkGj5|3ETeUFBnK)eDQd za-Y$jat9%I(AuqcGzL2aW?gN@cGKv^MP0={qprVmJdDQOg0RcdxKH9PgdK=aR#X1Y z#eV~L5H8Z-)ic#{pJ?5~33dbQDC*^U6ob9O5#r)T>l!lZ={({%@@Jho{|UK&AZOj* zUoak7srGMhuez}Jc4jMLL*3<&_nPxxXpE?Pna^R#*3I^0w`R6|!MvaH1Il|J+pH_w z;|RiYap1ilKhk)avQ2@J?KXQYGv`|&$Lk5I&yD3iZNYfOK+?4jhup%HLwnKY4)dQO zy~!I9$cxPFQ&wp819d~r{J8}4e!R?s$NMqs$M?A{Mg9;^i|jfgtHE5KbbqN`;5mv z%h!uDkB%>I;fI{>MlcPZ!y@}hZVJA~!4qI1_XzE#y_nDSA`|v#lD6ERk(#_lEBb<4$K0?ml zU@NyjjNkydBMZ4tv+>g2*6*J~cLsgqrNdgkM-O&4?4;rSzl9!!jr(Cc9o~A+bI3gi z`wHxKwhzK>i0h+`29cM$35VQIn9o>OTfaZy*>5DvLJkh5M6f?1AU+!UOB=wSSi z^EtL(lIOmH`3-{UH2&m*oeSHNa=cb!2O%Ug4a?@U9qRhrS+LhL`)bi19=8vfhq4s* zo`G4mpTZCwP`3LExwnwBY|cBZt6p4`?VKWwxschLJRiVz7xVWcbPtE^PS`Z4;)+KF zQyW=c7v*k8?h@nREDbY_UfejG`}y+tq5B!+ zEXOxtrqPSjwrzABe#l+G#Ye{>^A+qOm}#5{tEchVLhg&mnZ}i{dKxi**6ykcwd{>0 z?9z*iJaZUrr@K0G^KqcqxnOI;Oyeq8J&oyEj_#fM$(zTu&Uq|{>>s%Kj&IGgKZuR3 z$-RlLERLbtuJ0ntEb_8XPNt>`J>6I2F$u&gs@95F6wF*!XdY`x~KN< zZ|XYVw61L5dR<*#=&qjAu%Ej0;v$Vc!jT4#2BkFO_+}dG<}`jzxSqz{h3j9-U`f&)X3ka$b!v+{qxKH=QGN6(-*(bBy2^tnTE{g8SGal<7>YcHwEX|eoB_Zt3Ju< zi#PX|LpG7sk6?~D#&zqnI{PM$!Gujiwl^!~P9$s^rQD~p99gTjV#5%0qdjD%(etC$ z*rcA!bF1ZHTj86AY{x7Y<5ejabtSt2xfgG2J%2$o={8}e`%B_sPq~XpP27AwEHWc~SaQofax=*H@>_k88@i{#z5{!vVA~K@*K^#E zvz|@k#|7Id%e`4J_cPP@D}LzO4@~0{8Y0*jbS{3V|2k|B@hw?h3tOwO$5btS!(saS zF#DCdomn@=4cmMHR$q9yzwgTaLtd_eMcqWK-%=)w6lXR+s zs6Vou>?t=6IlrmVm-8oE6?VWK{l_xdZmg{PQHAa&Vau~~91M#z_9fgTe_IuDduKUz zhqRw-FXYZIFfu8ARKZxAZPwor2>MjHLO+lk0R%yZq)sKgiAT= zUb$eaqN}|aH`HAXW_kV2Wyq~N7kw4o*cX&*!p@}*zDbzuq;&VDEiLbv#6wp((@-wh zhM74Y$ey~Wv=FaTYg3Xf|Nw;-}XXY3c_U6rO|I8L5PW4rR8BU3W@aLo z^AevCy&ON-f`s2e*Xw}67KWXLoO4JS#ZS+2&OfZ9eGNtCF;w;d;gECOlPy^2K9QOG zQ^-A)*8`*mi6iQ67Mi?qJ6 zO)&LK^FI={ihu?2^bXjq7veWKgw3D2*8O<|MuqZZFu&_{zyf;Y{NSd>8Hg zuQU#0d+07p*fd7f(pZ=V!hBn9Ea8t*4)eEaPJ?6yl;b$kcs-}V(3sxGY#L`1b}7rT zWD5{H3{RFu$kLXD6 z5Ds=XY)$NatFU(u;YX1BMZxT+A0~~*kgKQhCs;j=r(yLpUdd^kOrBlJazx*?UYt9c z#?yqO9RG%yhItR>G1N55IYSRdEyt}Uz*461L*k)3lntgavasjxSWROu{E(ZUuxU&! zSc9->T$fT9n8vq?G)5z58qTT0p5JCQjdcrqV+otaJ_U38he=~YKks>c)HJ^PK50zlL^t;HrAW(TkL__Bz6)yYeeeXrmRC8CDYi!( zyJaJA`z_N^-Jbh_Yz3U{adBn~5Z@K|LG7X39=NhSWP9UYVDfiZVQ(^Q67BIw!OZIi zl|y?c;VcK!y;L^YDLB(8^L!r6a=33>2ONs30|+0;1(z)e2b&CY9&uNV{ciRC-)yOS zVAlOvVQ*i;$}LExYmaC;_xC%A<#DhHmqp)DZhU6P5DDFlGy8ABHp%StA`RKX*mF+c z!lv}y1i$}!DB-YI$|+OI9bS`DS9?(}9)I6Gv!ng{BJ030eZI5!MsLoaYzofz5yWv& z_W8`H{gr_J zv8Q(o_%6mNuw%Z>xP~tO>Dtl;__oo%@wF$v1$W18>~F<9=ZjhHhdB-Rzc+CUeXk?E zx1L~n{=~WEw%GdtzV?*U_SwiiQLw=zr0z@jmVXE?bp0KYy3SoZx3|ri+NDLgAK^^n zwiZgdGTSnaDeCTp^E@Hx1{t{>EwgULEbEO})?*pxmihF6O7Q)3V&JvaWO1tzoYsbPZt_>(y@wy$d@s zkrsOyHuuA=HjTQvlX| z`>0drpCLB^w#{~(>AR%Cd_Rb3oR6Ff(RLc!5)Qdfv%znW&RyjB zD46AlckY_5%yN|MYM5!9&UP1~?KHL`9BKG25bKKOX)~{>nugcELr!KI!JJz-W`1Yy z&i4IP*^01@VNd2f%ht+lacpQ$*38Ujnu4)QCf#i)l#FPahx<-}v4n#?M)+aaMw2?@22s8wy(ub|7Kx$^OpvZD0)f$(HBl8{s|)vn^3c z*Xcije?H}izNT&?+dG=DOKHzKFpbjQRO04W7WVEW9Qhla^L%U0v--Ca_FQ+7Ea&;^ zVYn;FpV$7Ck?n`Oio%|WAI$bT=yRRvnIg-f+@5Sa1@;o*XrnU-J6 zZp%V$apa!6tTSDEPTXt~D>L1aodB~OM<7=($03F8B12pD&Z{x))tUJ#*<$E^ zn7SI1({SgF`jeSPotZ|-#%A4P3tgFV!4@L#|H18eL`S>d%ihABdSPe#cqDrlXP&=? zJ-X+BKJ?X`hH`(yX)nfD*{*E&7F;si9FXMJ5-8de}F2^a?ferpsUbqyNuK9kQc&R(~yBz~`Z_2u5 z8jc$Wk;aTd_vS43sUnSQ=%-#+{z@UI?g`)N7@&J!)-BU;46dhff0p~8G}L|fhJk6! z%(`V7e}SD)E61O++=)dw=B5wT%c1TMYUTL%Y|`M;^Z!ZXKUwa$4@g7Z^=fHsgO10K zE7;~@e~Dw%^@+4t9HU->*>{zTW7MM92xcGh7_}HI`oTdtjpf+pQl_zP3ndn5oB#`Z zk%oB*7HND77HN16QSZBF!0K)8d4+Nx)aL4X4mKmF;c;daoZk;O|E4Qj9p|xUwStW! z?6=!DEtql(o-}tZtZ_v@+&$Z{A%Ws~0|IJ0_{BWz?yVAR4g6%=T@1S2)$bAy#chH~CWmDHV z;pOPAh;RNBw+?=KY*+QOf?0olcacv=x8)og{GQ#ZREoA3a;uRzzmKek0ihdJ(=uDU-$cf(V=sxRd{%g%$nh`l(+nGfcC zV1sYR?4hQV{Fzf(^xsPG7ZOA z^HQc^9n{mAZgv^}p1atnS zZrp$KoZV}N&;Et|65j=pYG2%i*s~A2$o9j@HW#qS_Q&n^OjrBbjrKl+b1eA^ex$ns z;Xl66mC_34zAy{+BYbW3;5_d7ecIRXt$XeLmW_VT_;$jfyFFpQMeEoYY&_xmw<13* z+YDX5#kft8#^x};3%P5-j+{*zQ!*P<$bC99>niehG|V(67wkCLal8P^HVC;h=@6I9 z+g+9ICNnQ3I}heJ=~iGTz)Y&c%c(2BQ8@=J>>ZPJKT)LdOxCsEyIB9B>wX-%&my<% z@a}5cf_W^K{jOj$VcWx2DcDjRhaToTdd?5S-byg9H$76YF`32qVqTWX%=v8SHZr@j zV7w~2dWiZv1RWQ3|AyQ})XSNPwAepjZz6XmEb8jt2-_aNfkhg>!k+nCFQ?)0@+883 zW6|=uc)aAcNqSe*{P-@x{Kle8d+J_6xO-%GwI=lw>{{3oFkai4n8%ozIG?fE3ST+d zGdQ28`BK52Bdpv!ISu7r$Z|0slD&-c+lkv!*s%9HOx^#FxATD0s<`*}ySNK0HtZM+ z3xa~Z20JT)1$)Q7h}a8u>??x3pknNby~i3+W5Hfy?;6F}HL=CS5~Kg;nRkBg&c4BW zy}7yn^V!*%dEW2LZ_b=KbLO-;(Z<#N9jA?n_@VnQ>zWE1wmWs}7wkvaExnp*-wS3H z)B9?lQHLuKHb0qtwQTr*!?+}nbkWC}ww|p9dkg3H88^xK$==5Kjm2FG_8wus?fB<{ zS%2;`ci@}<8n|fp=MuKeTj4K=n`?=VZSGikW9sty#TwE*8=`6aycuk9bZ-)mv}%_h z&{Ua~-?ZVrGaK&ZrTC6x-X1#=pB4Ahpr&-*VOrVjIMW`4Pjz%k`xNoeIet->o=vUO z&6c;(T<`&e_g=lJHfEKv3Tdv|PYNBYkaT@=`P40xnd3z5PKzO_a66>33*V!Bkgz(L z<8b$*kB9`b{+ye4!E8evw-zc#kk*O{-RA0Gn-%POwEZ`4sGV1s_IBK-+?=MF*V0bT ztn6Rh*6Lm8R<~rX18sN> zR~u!1j-h1ZinJTSOdD<2w8Jv%gC925%xrjOz0mc>{jsg7cArz`Si$*bcP@0c%cZw# zs(o)>T`TTfZu$(%+el`gF1tN%k9mmymETPpV-VTbut>wR3S9L$Hc$ReWv8p3ZE&f<2d6c`UR4Hm%2s zNIQ@Wj@gIySFjZ_^ISM|D`vJp!B)!5@q6ezZkXR{nGL`{9JU~H`OTB-RCW{W@{bxT zTX(CbmE8mL{OuX)!n)cW*AwSh>e1#7-NWd9O@2M5?_g75`@>@Un%`ew&Sn38VfUM? z+l1qxWmY#gznk`m?j39ZOdCti)WOatjo(&j%I(0kH^F@N+zk==-3D_m?6_~Q?gp6c zxv40N?^(-sD)Re|O<{fmNfY_~2z!CDxZefy+K6fCQfurdbh5Dp`ysPeGFzNHx?ykT z6Pqe+IX~HKFxTy~Lg)9?-5whkY#x|4xOMt3+sJcI%V&G=NArt1kTt?CKBfAt8?sDe zY}ZK}Q}82gS9IFgllmdpsU2JaQ@0rW8=T*Qvfpx97PlGBZ!Os$X+zeRfcY^rsj-DK zI}AVa`xb4l)A@EWMuQy<^LtM7;k%fhV{dIZt|NIT8=m6?3mdP)BEPYOwQ+gDZpPlv zeKW6bkzcIGaRmz-Ul#e@LVnt~t6;VTFly%jgc$7J8j4N2!_zV{7F^c@OF}YxW z%{CT-xs*1v`#-hu^)zg(%=Z6JZjV*TuYP;1z&@jmay??3|I+pNg7uBMT9N$vabc<4 z9*<=k|EYHMc(!qQVYeTBgx{Jw2Ik^A^uzfLxh?Udd<&sl^{VQ(b7(qg-x`en^_5Mv zdu{G-3!^)bZ_<@E9)sDg7UFl8a+@zoyndS>U$AIb?#EGtn3qIZ@~V$KJnM+M$n$k?>oZUmAPNqC)#gOtWJGmJMqx%j7}S#4`QxUpXj-m zI+}92hT-!iN9DA#vv7T;bbMn>b~bJ`*qPL0q`fe+Pw|6Ynb}gV7M{HS1&t z<1F7P1v?#A!6D&V7(a|{kD7OZ>#iy z`R$iQvR!ox!Zv|DPS`diTM~8%Y=?p^1#`al3t(YmIIP~rRxoWWSLn8eY2%3^zp$}i z!NSIMMcSvQ=Uj;I+Qjy-e9ysl?9ny#D^ZpgVSYbojUw&quvT=d73?*b-xRX_N7^I1 zS8Z%iu;XFocTK@ggqdGl2eB+C=d`yJb$=R68!r^>5>~+dV@i?V<*@h9YDm{~-Hr$1 zUZ!!X`=HQWiOz2TIkt{6Uk7`lC)=%HmvSKb^Bi5%^#+osZMn`&oImp|Bi|>8wAZ2= zj&5?^KQ2P+n13Q{2=;9U!KP#uX&3CzJ7@zsz8zs5ECJge_B+C^hiqwfI(3f`j^Q&6;`!*bnEA=?r&B#=(du_-f^q1r zEX~1fHPQy-@^R(jEt_g{4nk+Ydp-H_ zmvn0FcQ3&%KPMLb?z=@$AZo&DDj)RM|LuceY2fm?n0-~_%JDGomeT5!r zs)J8p9%ptV9y;Fzot>9wX@WI25Vk06!E9r5ew&l<$sZwl>I=)5jq z-{jm$+E8cz=r@2yb?so*+XN;7JhEVCQhwi6u#H68Yhh<{JioDEx5E05;M*#NUFSNG zIc|%zSHV0cKTL(nhLgv${QmWz#@aO_neDDu_lC+1`23~web2@HKFa$5x5ofn)cw>t zo!7I~g^j-xF26^ljc;M)_lRWQXLb_dNc$tq?-AL*1^Wp$^hfS(D|riRS8 zbu%-8i63@+Qz&$O-mB`^4Cy+q*9eBec$BP`-$Z_MJ$mAYjY~5-reH^tR$Yv*Xf|oS zfUDl&nH9p?=!T1Lu(Y6${N{yQ=B@EvT>mKZE``o>2ETjawO7|mw>iIion{Uqk)Jxh zffm+^*w!mY9tlc9(+r z-BiyngLy9H_e_Qs%>Gn%ZNXM1?6**!uVd;;HiX|Vo}pW6H(|rPt(V>Lsg5+xih3!p z9j?i5epl&0{7Ab2;Z(k&o_~ZjjBKtvQs}1Rck9J#zuK4+7xg!?NK4n3zF`w}uU4jw zV5`DBF1OODZG>-GWR3^?{>}J;9Yxr*cNgqv*^bSXHwtE&jeB=X?+(vRxCNJ%o@3f8 zl{Q>nnu#xfyXcVi%3FuDx6D1Jy=6`{%?R4sdlTpMaDC?<)4mg~4c7-( zX|0Ya+{ayPuf@OKMq4`nGnURb{%8NHc2b5Z2kNZS(j)#cFlw#L)}yhtGOPb8{%dzf zJ>GvO`>)+GLfU!Lzo&W;dujpxot*y7=dWq$n*Gtti)}({!};2sH@l2as*C?m=NAt< zJ(ySDe09!;-oGy1S{EOl<58{&%#Z%9WyD?1cR7w{e)2I5Y(d;^%#R*++9|JfpmRR- z33cVax-LGYF8(U<{-o92L4CORKgtnyzNI|c2>wgvy)X4EP3F>2 z>D$5^V7P@_dJ|r@y>H9X_$%TL!40S^)-s?GN4TG^RlZouiVe8w7i+nup>NAIy>Zj^ zZRt(8_pIjE($dhSg~r9WAzATXi~kzv_W18FJsP^C|AHP3?Q_i9(4%3>?6XqmQ#`?~ zc!!^TGyQL`{x?Bh+LNZrUC-$6zW!(L(%*Xc0x~FIV{QiOMv6Z;) zUE*P9S9sbYaND)zE936BW&E7Fxb41$v^vZG81b-s4(&YbSbjC;rJc6Acza!ZQeAvX zU3_X?JnZ~C<+mPnZIn0cv=H|@K4HgrxqYr?KP|Vb`)Qev-wQI0&U{*nxcS^fJnG5q zGnM#gw7N_AK1HmL?a4aRmG#y_+%0^@8$YBS zuqNQQA36x9GsQAPYY|EB+Lm!no6>Q*#-25lY&}*BS*i7`Uqx(*H{O-%t&wZ|}@gsV+Sz zLTV%aW3dXYRdA&dSN)N1I{Uj9U%dInuPw%H2woJKf+V-Dz`wL^4YL!m)^GQ>i zS<$J@Tn(D)S-{l!{5MDSUt?uzV;BAnA=y;(nmUg6MBeFZvJ`Ec(UAX|Y7$LMJyulf@JnDZ5G3)5~JZZz&v*mn5lXTClQ_Z9=Bq4>cj5&i*Y z=M(Hs!m}^NGhWn%^-MEM_eNG{XXKUnn(i)i&W-t9!MsKyvu&E+LZo$U>-wIJ@6v{g z_0@jpP9p4j+=j1Rb+H~F7rLVfTlYT{Y!AXCTdL>O=C?3uFNeLgQuUe?(Zm*H7jO=B z+qH|j{;+0FV$UTUY2B7f!Y+Wh{^~YEcMmt*E-aYuR5};@RWQ@K|1L~|Wd~R9cLp1f z+0lh=(afe4Z1K##D%g^l%}<#kzoj!cq$HM6h!VIwp5*@LJ9?NY5tCp$c|RSL!}-lX%eW`63p9hutr!~a7@^Gw$Q zuHUG-|C(R0x7P32e`N>Z?nieVeyKBU4;ZVG&KqvVcip_kP%_ueJWOjZeH5a58+P>1KgR~4eSHnCWfW;w&upLnhLJ3# z9iMd`zdyqLWq8#t!8HC@l`>DyfM7o2uCKbUarR9fa)WWXyK)G+?F;5Tm)l@&-_U8J zFU++V~6r`>tS{!>rR*7}-?XaIr1dBOJOB=&aMjU<8wHG`@ZD;f3yCep~_@ zzE5k~75MFQHr6>KtLsKIG4JiWZq|9|zQ{WBCD=)Ke4+b$*17MyeYFw!d0))@`oMmN zTYH!4v5{b6E6>WY19k#&*H_&fFpr^bqhNEwJpN9EMSk}Xc7FJ$3+DEidGU^U{>*P9 z>cIKtS1fcsb86iWDcJV8uFfjh7O-7LRi8&Bn9Aofk>>XX@nAj^Dce5Rvvx1ZX`dnN zB8#-|B~oRPcDEw!#GH0(@(ml2)^`(vMcN->Q7^CYqxE9>g1wR1p9=O)W^v!H55Ikt z+4!O?Zq#j;==esGy6>{?g2L|PuGKn?zF6J;Fx&IKgvqkfhKu&>m@CT1<;&Dg4=n7y z2(yhd&BVX-8%Gp&FXTk+{k^Nt#6^Cx6Zh)OE`nJWkD(;*RFjxTSS6UxM-D%&`s`~kUJp)e7W`nxWESuJYhyxYA7$Niu$OSFo>A@B2v%g1an`{R z_*6}&IyjQJHq^a>+nlsF;~UrAk8^!*!LMK6TVav*Z-lk`2YeUPhF$xddb{rDk@g$H z+WiN9z1<&R^>+VRr0qq<+T9Q4QreC4k2ZL0bI*UmuE%!mUY^sH>w5*P-tLt-?W*{; z7wz^U>{8mDpLqTHIzG^@X%{E0cI|)b*O%Lp|6+Frm}$*(8`3(DH%-09d|zO-+p1%& z(2dB9!)Q&nQ)b5&Y?sW)vZmWTv)3{sn%=vqpYz;fm}S|l(EWw*IGFjFPRFVy-P;8_ zlkj7Rrs7*>b)Vy$xBUCetQ(I*ci+wUtYB+oc3r`S5I*SlY!@oYyk^Gr!p#Qrx`;N+ zuNAipY#DsFuey10>ZW9!{5hO+im!=pTAB6X^8;S?3HEx{9aXS5Vb7zBcdSkO39kFY zj8iE@q_wVmrr=EkGRysYe)m1g*uJuRVMkLS$IYR;KeO1r>K@80wy*5b%-kN4_KD2O z?R$LJs@)|E-3ghs7VIV1kuT6EGe#cvOa#4 z#dTYW&h(^$xo)P7eo`Be_JcyVdiQ^|yEW{W*xeGHcE=U@ZIIJ;p}wYofp}UW;IyPs`uJ2K(JG0O|lyyFn7Is7DG06OE3uj{J*IY-9Z6rH4vnhl_=UDK( z#)jIv?CLJd%=v{wcU@+CAqX}x(o&FMM-uk=l|9MF#r$r;`Rvdr{Lr3-d6H6e^x6! zBib8wFX3QM5_YcPI1W;b^scOP;GRs_#k6nX)SZg24Rv%6X%5`43Z~9EiQ^d=b#LRG z12>+Nl)Z;@j_r|T9{GI=)2{ozOKJBo;-T|c=G?n47wkL2+WlRwKW%ud)9!Nxqv*-5 z&jv+)ZiioD*YQKW-8o?OcISlE+x->H^)2l>M$+#6l*y%B-v^0D`P|R7>obSJe8(@@ zE$VM6n09?;Gjz+tw7WsUR)J|(8!n~Yhlxj8+m3eQeM0NhcLKHRz8Jc7VcLD9U>m{G z`W9?U*e|hbKTvOX6s+Fv&aisBd%#M&9_xMo^bA(QajMHgILFkN!Ir@1=QJkp8Ms?v zahx{oGC8fs9;&dG_5pM!5w}j%EsO4XnEQG+&-pLaO)A*znfbh_I{S!0gkM{=Aw366G_9Y~|K-Nh&0^hVJWxLu~3!U@OEL_;#?tfv|e&Cnb9aU%7^%#%akA}Gc zzKd)}+{^1Qw;sOhCL4=WcPu{Hbkg}-=sZrUy9nRyTjqC7)^Tc``nCJGSQ2ABndf;w z!l=TOPDZmxV_Xc(qc_Wh!v@)S0LJpp_Fl!nTq zj4`x32hO&(Dr^>P1ltgH5bRxauCKc7aW}%Yg++dz8#oX38GUzwr9#vl@C_cK;hyR%Ua`-Y$1uYN~^U^<`q6y5XNSKrCkhIt}M z_52RuNSpc)ei+MdYG%eo+QnhEt1_+qWu!gEeEvX8UAx=mv@_wmlHq37w!c$;dQ^~=+?)VmrX$TT)L1!J=XZOKZ7tHygWaj0VA?Al# zqhK*V)L59?N8Q;t&z(Kz2zCx(=ZCr#KWyAi*f~-cu4CGj)!Q9fu&`_Y5jMi^Z3PRv zw$rftG~s%?vj1zlA7EqYJvy(i?El*CkJGR#`@go^gAHiAUlChT_x7EB2kef5`HZK! z4et z?R9o9M6cav3cIa2zt(~|h8o2By3dAvk#bP1scYShv-) zjXwCnP9(h3o}Kq!ncH_-`|m2`$IoefV?XkIwSGUku3)hrT@Tal0Q}i;+L#~Tr6(@> zh<=H5wy_heOV-7{IJ`5mmjo*g>`i*-w50_s#7?my0db1^#W zbXnpfaL&!T626Paef!}0xmkCFc^oXaWn2$)JRA9`bAMA8Y?sX9I{I?Nt@9^#nJzu^ zp)Qznsan=xcV*qW1!I@24B^1Id%^C>I@deW%G8zY{;XTH(8=oUK9F^#-3MXyb|22V z3HV`GrmkdWUyO`fF{3xGHyQPiivu@8q zXL~Wf6ASiI*4WlXI)vAH(=&huJ0eSu3TSP{rY~Kbt~e>`pUFx z8xQtL*7Yygr-aSV?H9Vg5I%zX>&rgl@yK@Sc*Htg8>Y@{I9_XUe6{W{s4nH_^~T3OG`Y$Gz)W#P=`&SjAe$ZTY0o-;b$ z)W!{&HNi}KEHAn3hi`r|k2x~uI14r~vv|K)U0Y_}3kuy%nKgIsU_&!of5r}W6YRzP z8`CwTNbC8S^ZVXG`S|NJzwZS_neB7FB<-4%&pNRzp1U~D!RB@BMJ8{Pg^kk;GxzSU z8elQ)Fx>2iRp(q4o9A{o=l8v)uzN;M`+Z>}()x_1^ro@;eM+w-m^6AnmO&Fsb%fJGK{dL7}&&v)&u zgU5>em_9DekvhDv>oq0oWjlQSI^}m0nVa8SaL1j_uR1o{2sRftK}yD@=gL73aBiCI zs&j1lAvaJwmyP_^C9GY~0qgB915?LpS9~_9-|3B&Cl}~o7E<<2!MbENf3FT*V`gg< z%y|$@yIaA0Ze4a-!S1I4%eI-nBfkeTJFZ|4XLduuysl>27Ydf<9)f*WuqU&wSFs-5 zIJYvu4(?O5LdnRTZV zjqR~$W=j=p@yxa;nD?j6@9=^xo!NN>n@E4A?(=y%Z2Ts(d4JWx&dF@`f}NMyE(NYsW~&zL?##9=*u9x~z7X{?CA0Gi_CRKLWX2{)&vh<- zQgz-e)5;FQ{di(^9_3(TV3S~j@Pi$a*>(l949}n&U9iKmj;5BTp z*U+g?yp6bJF~9k6&M$p_-jCRw)BRfQu9S7MXK>ox3SYa{-(EP6m)3y#UX-%i@q^xTx z^6QJvdC|^***~l6mvvkQNcrKV`D`5f3?Zxy*;6>@(A>RX)`4u_f<2#Ed%+w(t2?b= zuCMIEf-OyW_c5L4>0AZoGcgwyU~Wac&+ zgtPAZ1XKWVLJx8)0jJ%+wj=-fuyIJ>a1J22zbB&bjVc3>z%M%NoZNoX)qmR(; zsW|6kKLOvkb>M#H`re0MzrH8J!tTX{*Z-)oc7NLR7vc7VrTYTZsp((Dnco)pE@l0> zADN%Jk8swN=PZFrq&lhKXoIndC# zul(HlK0umMXIkqenD-Xl=5dZgG+h%ui!n7#HR)t`;~Zx<5;3jpp3G(}7@I8V<}8@@ zOuInArewBo!7e2{prNVOo{3g2%WPZ1VfXUP?kw09nN5cux+^o=s$h;=v|+xX^IYjn zSoGOM(|otG@r4byq3o@K-JY5E7$d(sGmG;XqG>K1)BaHC4yCc)*j$~jA4#gyf5I%^ z&V`M`U~i+dKeY{*AJc*)U0DZ*qw6t!$Nb^yoYTkr%JQ8L@6Lwu*yGZKI~vy$b}W9Z zN2$|psVnc3*cX}~w=q(CE_LaADz_Ksr=5v!0_;-QaDLhaVOPK`uWl;;)ICQy*7tds zbKk!Yi}L-7wCQ^S{N{dS+H?7rz9)bmy5soK{Omu1odDDB)j4#Skai z^`2|JUH2z#SO>PdKP=ExX(8;g7H$Y^m0nHhdfv3yw9?vdlxd$OJ}qY2?)-*2Z0|%mn9qI5BJCc8O?xfAHp;XfBTHslnQ5oT-ekFU_j8KVNq0SQ^IH-B2i$dwHl_3A zU>;}QSdw{NF%axa*oiAQRsLSEzr&o@|06bJ=)Q#=Lw+r}4#LJ+g^k{5_Q5&6Ivd}# zvV${wFmFrQINZ>uIN#59W#hB%;A}(Ip4rU>J3O;bGng)a;}gy-QQY^IDgUaBg4c zZM!7rr_Qm$cyx||wX5#Etc&rGI**Cxq2o4l+P><($hw`g-6e?IXTEVv$9Gp`r@^fI zD+#;4vZFJLzDaf|%sF-U%H@+?p4s6AyB2onaZQ!iS#R@O44wV5^C<6+@8Ug&4ROw$ zeE>em6YERBvOHWckK?kqK52ft;+#i$9sICiKd?9KulT|Cr!4g~3% z?*B=izWkqD-xbKOzMl7n z)!Xe!U;Ur7I}iEQ+g%7&Z}*Y^u-!+eVfX22*nI`&dGcB8Z!Ye;{cxUl?};D#+pFm2 zW?t~W!q_d6Zqcl}vCzGS&UwZiw^O~Tj~I;aJmYb{+x>i=uK(G3{uTMv*Yg6f`g(r& zKWz7rY1n3R&8^wM+xUWc=u=fmBCa~$?0ex&s} z@E&~M;Q;i(x@9(*Z4k_P4V(wv@j)=>HL%}(w_wh3X!!=`KGyQB0P`CwKDQKU*T`xA zSlDom1@oJ^TUAH2_C1D!bAB@W`yq!gZZDY6LfpQ8Q{@u`+EC{))ciOtsWBcOP3$x3 zHguL%-FA7bhxv4F@9}pH!Y<|UcLCz2RW||W@pl})^{nnaoX6=M@I!Y7VUNF0;ZxN~ z7suZ#v(EAEf;g|qtXr@FgjajGsd7xgZ2KF+W}@ucFs;n7MZbbA2YY=}p3g3r$HY;j z9hkQV)sx;gnVFsVFmx_@OX1dnO)S`|u#;iW>gLJup8I;O?xB1Yj=TSJ?@5ScL{9#oL%|y=nkOq zT|wBg$kv2e7M}&;uTxo8D_E2z+N5cHR`K%Jn<{_8kNh?#d;>QAnHfzk-6Q(py{5{S z1sexH0d{Gw7j=_xgWqqe&4VGk1a}j6(*Wndii&_4!E4G6(TxIU$;% zxoa9r1zQd_A2(29Os#IktQ(rkCtDfzHaAcff>Fej-_@M#c|SD9dg=z}{B9}Ij^l^^ zy_jd5-^1=C*h6&OwyR(#!tSPTno#IYh8^6$V=iu@l{5KwX78@G>wmIK`M1;D%rlD}p_x;qu;||>^u<@&OP0!1RU9Sb6 z52Lvy-QvWz!r5t?tmC=$VCv#ocG*On{YDqI zv-vqjABl6$yV3;xzBfoCIcsT}eE2_h%iODXs6)#6uV7QQCMu>wbst zQtHej@_U7_c88E(z1|nr?&F@iX=Tp&Te6Wb?YiH&ly>77>QC;|+V!2w zdb{HRuA91D_@~|L>X>#*b|gCOZf_!%((WO!$nR*v+8s3wyK()%ENrLRb>5FiE7NYt z&Vgz7Z4rc?O?U7q|T7?^EjH&(_7K*2TZ5 zi-%q3O)b}FN?rWfy14VIx(+($ORbQv;i!+69FO1IiI3rT*Z&FDKkT;U@` z<(fdeXJN;BE#p(_;%;BdptGD|ck~aPx9^y`_yppm-ATkFALo0WQWu|E7jI)8+cs>j zjq6*iujTKQZ(aPRy1468>YuHPPpyl8Q5T;b`;I}X%QEek4EwR+SLwfD`lIxJay2|o zvVXys9b47>4qnywNx$}~OoDXD|08#DJ6ioR=|AU@{IFE*M~~VZPu{qv1M z&L8;y1vjWBCFXw#?=w_?WmxgWEK8*Sp5=Zq%ghcmDl^aJf6vivc@6w;H^?$Ku1^a2 zk5<>ksUy4i{$ZC!qfOO+jf5Bjb{XP7i`8Wgf0!-*YwFTvIM0~zuhON9l9rA9r>=2$ zL#4}%{xIX#M*X$jXnIb>zPQuUquTU(G^7^TqrJmx`>Dql#PHf(gR~3jwKi1RW=Ni~ zF8);MVZVS!tuT1EVI(hAMvvyIm!4hmI(jUr3aOc@U;XcIDb$jEOdB_U{8l{uWVJCD zsj*!OPYG$))o7}BgViEd=kAN+Q(}+t+I{y*O2}hUEO~TtyX3FhhLdq*66?9 z{_EjCmf3L2q)__T&i^Tca$5@AIH^mUW8<3V4_zj0oqCI^7j;x^KCKEYcv{+N2`-!s zl65muy#7@$H6MSp90Lt>T3V~IwyHO{>J6!S?Bp(MR=p4Uu5(7;b!NM?lXqD)c1hK% z3aQv~xw`t>)KXGi3F?l1+E#De#6rc0SJasEfA{FV|-U;{A*IYa?Ffdk)9r3H+`b$oD5+WxP_xcV)fL z;Wu3$evfkOS~t!aL%g&*p)P)PUEFa~3wi1sZ#YgW%hdzBZT!}X`wQ#uc8+rGUX-H( zZ$Z-o=lHUvF79?Je{ZXcx7Wod)y1dO#i!QAqdu%R%Mj)Gs4o6(UA&omtS{XPy*kQm zS*?#&eqV~P?qlMve;K!&ZT!}Xvwor+?R9qC4wgx0{YsyXrIqjsxGyP3 z3wFzR8}Ui}b`EZdV!Moimv)b@i=R^$zq&4dM_v4}y7;Sg@sEgGm)3**M0fmAxK2xZ zr&t+zw2Zt`c2B;jP+Q)m$E+<+)+!zJU>S*xk)<=?uTx8w0#;30TC!hy9To>Cd_4bQ zziFu$q6^O%>^;}i_$oN(W;`hW(uThj&iRNB#t+?U zgq?@+T6}G^;YQ<}!}dD-&}~3io!5063Af=wwA@{$7Q}6dx!AMoKWwO^J^jg7-8q8WvH5T zvR5)Ytza+17C<*1X1!Qn|gv_rl$K2-EE6j_t8lE3C!)g4LZxxhKudHE#c68h0g6Z4%UQg z!^L)U-9p!wAICj5ZwW_Q z?>AePUsEQ6oysy0rfxyF+t7K|7td*B_u`z7-SdgiO(DGhvekVr*h5(t+t;*@WZfwI z&^<@kZ4}#F-Mcuq(HTWq1`~dk!5cU&>U>VldtdVsj{G)&O`$A%!mO9RxU+Ec!uP@t z-G;=c;tna8_kK+4-fz8>X-_D052IU-dS19-kHf|+SABLmZ2SSXIc$$Yr_D!TlVH=~ zT#s{b*5B#)k@ih=U!uDTW?9r-gi~iPqi!Mmp}5Uvs9w(vwkB*jHjsTG*(9C)%Vt#G zmiVDtPe$643${LC(_V_-h|@--y@_z7-IefW=)8v;>}(2pX$!+|jk3`6(sO2~Vt3{` zc6UpaMcQ*n`^bvS?}pBLG3^Jqw_w~3No8@{KgK|Ro)+$r!mJnB1F)B8uRNIQwR{lOYA%i?|%{lO-M?lN@lN4vu;OB-%9&OSS~ zx%qmn^*J`mqlC2~`y1>l*jojg6=O@U#Wv@+(D|K*+51r*Yz6x%vug|HyJ717QLr94 zzqpRQ1h#CuKUXi-r8d;rc4wpky+jyush%fx{M;YfQ? zPJ0YY8;jywF6X$PuZ}G@4OXu^fwbzjE7I~RZ(;}6G3Uqsuh=5!z2DKYaYz3mvy7%) z4BtiOwi}4fI&wW^w%MzPSI0rYyq_T(Sm+MOHs+?HY%gVgv%^fg0^H-IePYy$tPQqt z?~Xo4wj<1KNj0Q;Zo{{HjxBb_kNifXvp>D7V7tNGZa?DJx7`>sXv03(vg}->JribG zqE6M_0Mo`^_+i)m!}6`dc9{-M8!pNh?{k>;N_3XxRCM)a@fkz&>w|6_I?LkubFlF+ z%i{H&V8_9Hl9LfS=>+R>*W$ygB=CizDITLTvjD* z-}u(h{=_kt`V;Tx`>lhch=(q|HFPY@ve@r<-^TIUiG;P$ioXcXeF4)o=6>sXa9F93 zq|%0?xT()x2|vF@cCpyQ`mCCPJ zpUCe|Fm3Fb8JjD8$Ee#l0xare|KNAok_G!Avtb2eiie~dRWRSLHf?*sJYLGqFPIHX zX5DMo`kamOyH9UbusLA1-L`_c?(T1Hd$LZyvAI)Qi?NjX^+ab|`z_(dtc&(?Bk{01 zA3FPphcjCp-*#ZzH6L{{`%&}Tf-p&v-No$ee@6(%Q z9og`{66dcER_&Trb`fkG>|??N6Pp8H-S_yRyEW@(!Pazjx&g3h=`4#jBERjkjv++l z9xBp#miiDjt?XHt^NHXR335mh9r!s*F`hc2DU}Sy+$Q-z>`*(rRPr!tMx| zX+1_-FX|%g&4uns^0Qvn-!)r&F6Kid?BY6qfphNWaroL$cM$oU-;4P!3w9K2ZeChkwP44> zoOkySGIAT4)??lSq}>5O^7FX=EbQi@EJqV|4(chSaj`5<;GBcH72ie1=1%212|w~X zmLDvO$HCI>#6HZo3JaZMQOmb)!5oV^FYu(yW+&esIO}B$zKeFFUJfN}e(G%Z*2{YZ zTa@sae=h=g5zO&no?!>~z zDX@X)rq(gjmh3ci$MLX;=YzJDR2KZ5?yWxWLlF{t7vHj+oy*cpd@a**GT`{wvdH{4 z)s|~8&nw|z!(bPpTO6JFsXG_8C%U)lbhl-lWl`t$Qa4XwL%UBDc8OMgPXga*-aG4L zcfzhYz9GG%Xjx=`&a8!k1p6wd{Y}B1$-2k!L-$hFt(Mz{`Mm)ENu6`fM}Dir#@yRbnVid_ zj$%|koX}9YA(w?{nlr)q*&M^USmv0cZjVH&Eat(x2u5*|F8X`Az#5DG{tcLA(Z=C8 z=QZ;f8tg&XyRa>CSv*FK!(Gos!0qtW$u7V-FYwb8%)H#6*T*>@@iPV65axWum$JUD zgSzc;&PP07t^@OPtl-?keREl4x8R&Bcqqq*DBoB7?ws3nZE5Mof9*PNcJ!zI^bP+O z;(|iEMp@K(UBh{}FUGg7WR8PO>$z;$_*+gp8WBb8q}w-dbJJdkTX^Y)RCabEXZ?6-~3- zZyPGJ=j|q&A+ym1+dQ+MXn2wK{LDtp+rci$?1_TyMxNUE>rx%MeKK2b=_+d>PWPYY z++LWli)HpYrr)O-Mp(No`08xq>RkVxxM<@W6)f8LX)t!Bq>DCwf5D=SKL86GOJKwK zzo%7}wd!;~R~Fk>lrPG1YGL=6lx11;2jZNUa6G=t%($UA=OuK!Ynjy@gmYfP_wmE7 zPYO8pxu#C%{;O_UX`A5IX{0@sx(MCwaP4}&7i=%Wmd|}Q*xrOK%We4eWjUZuXIa!u zD{XyQwkpc9C28vCX51PUb2vtR+rWOwe2wbr=W8s})|Vyred~S@<JicXFj^9?tjahxVbd5gP8n6#XPFLIJ zp>tlsD6?#EPHX>bUuT`3i@S&Xw#AS9EUPx$&#jkIw_l-KC+kWZjtMQx^>w=Xve^G< z>;AiX@mOYlw&SQ%+r4EuqG0MQOQ~~z zGwuHP_1oy=BJFlrXS=W8M%Na)5m{H(%Sc##y{N0NmmPE3|85(N%DVrmUM%B5v}5N; z+#cUWX4rRv_O4^jzaq2#)QvHWF8P@q1v9^Y;=3P}`OU-*STggIMSi}U=)6+TlGeqv z_Pfq2Wj`pE*-o9$>JWUAr)^^0JFnC!_>tdW@-yuPh22PdJIuV0)aImmIhRFt9bxBT zjD1k{TbOeY#`%%#Mwn&cG~!>%;(lyd)ZK;7@*RmT*xj(x$2L~p#t(KcVdqF(kwn4T z2y3@rksr-A<+pdi_J`fGPD83wvPtKg)|=lTi8%z2R7#!OqX#Z@vlL}H60v3R`&O1^ zE_AO`{_zi0@2Lj+2h2ICcFyaj?sLM{%cZ2XEZU82^h}YT{i$$!ww zF~86)h(7W=l<*_xH>US%WafDo?#0&|Yu65CV{u*HXskS*)5?y*ZSxBAw-&5DGq1U* z(cObv`qk=uZ(-vY*fOs*R+go}md$eaL#%EIB2m6y!w0-mox6%)%5QD_i>5ZF?}3&& znb!-0t%hz((#CgxEz6U*9as;qak@!l9F7w^s$dKu61zN?g&{=xcBylJEksxwvgZxc zM~uTaFURB2N8C%8_gm~^qoiGht6}LcbUlK&VqePcn41U8**Kl_RpC`|04Sbe<~PL!>!)!0+ zH%r#phC_EgI?LkN+(liKCC1*ei_opo*m-U(`b_OiU zGDp@OR_MmF@m$}NFJKxrQKckCn6uLNHAX$2E&wX%s zk=En=-Lo{Mv3zWg3t>;e#*-+Rx_7dUVA_^mH~R+GUg$jjX=7r++~<>B{K&5h8@hgO zvgu&1@1&f+WsdbYh;XF!`HiMoc_+MJ&gmd4_mAme^TFc!srlK!)WvtuWPa0qW9+V0 zw;~a*{-ykShu@j*2|-$aWU=l{IhLL zBpf=wgX?^1e}iE<>87GH?d!z(xl>yEvPkP(HP*A&>g(If0GPVz(GSG+UXZx~a$4Dn zxW!?AD%eVd_l32R*0K!7y~ldq0{fxR$v=m^jE9?ZX)?|F`%GS+nTwY(9WAo#->!?%Nc3JmYwksQiyBOV;xt+>daoRYzU?VeQy3AzP zwy_%J`fR(#G^Qe&o`YGCyuB`e0&&ZyZVhzKNB4QbHp*#z)|FtVw6>Q>>zt*|gR(Jx z$(&O&*Z|V+NV(1$+f@0Au#0Rj8oTdEJMM4^b_+W98S|5Q?cH&^*M@`b1$*JBru3{_ zFiv?Y-@-=cvY6Jn3S}|hn`|6*P3u@L(q048#(cT%)!mqNXBX_&tn=I{(%zSKM;CUd zz}!ZM6zqYl^Z5ePx-UGyI<0(6Q-$GZjlGuH!-ejTFz1$W4*p2{2uvG`7HL1sj4W$9 zuPv$DH1})TeLJ)3IsTiU@R8-Nwwb^d(`6m~5xtP^L0&?d2(Hu*730Q@@~QI&TRKwf9f`+43Cm_2;nH-maygcSoqk2 zje?oqlDTb|c2Ah=5zmdtybhu6K`W0%kK1CEAqO;7ypG@^I|=4Ic;3U)u66AB=g~Jc zRaWJk@8~@Il6h}J#$S3KFYZljN`9J|4|faBdlNASh&H|?fpz+iTrV=8`8<1E zm&(SuUSuBkpJONSoFnY|jaA$8$N0gP%`Eyg(>h0!?b-2h=(tRk>Sgi5hW8e&E9c!0 zo!1v+C+4<`m)hyWr!}STViQf*z&68o?mmyxR99l&hcfLv_`w#=%)U+==C=^;73S%C z2|w5(nOXi|?n} z{b=~te`~5-z&5ZfuE#^T!#`?D&v^!W1h&BEO||c?&Ov+!Dt7+vUDLNGh^BjnYs0j0 zG4?H=x~;NqJT@$^EOhI`Lbn?_=M!@NzhFD%wDz%Za-z4V&CS_g*|`MrnkEOefax;;$0VAfq(=-x+n$|7AkSMDgw zEOS-M;y5VQcMh0#_l2=~DZj9LTA}NS?jN%;Pf$?@^TD2kc`qZ%@_u)&PyV^7G6Nv$ z?~BZy%iGAYq|Z_G8CIR2!?MUu&1^`vE1LlG*nLI8egpHmp8HOuJw2y=x6n<54Z_CE zh3-7q4zS-9>}J?WG>mmf>q0Rr8}n~5w$TW}NE3S=zZJG4KGmAoYxwrD$Kpp>ZXv&? zIKg&533eOo4Vc&2Y%kjQf$-){4e52<(5*HT_nnxJWFo)2XlHYDj-|#E4&CbL7GPeG z2MV?Y%({9WTcO)Avr91;Y!}!@TXn6xLP3JH!B#((?+CMx$u=k7EpT7AqRTd9j$@bE zu4`?6C)pvmC74%gVzwbW6t_7#k4uqXJIwi~=E!!{9hVtHgqqHFr|zB1JU6-uchVKi zqlIsNvO94v!unB3!RT%(bM3&4rh*|o9+ZQZo3=w_yV_gb^#dYx<**vBx({-K*4=KQ=<3N~kEbCGZ8=FV)7g3Xun zd$wQ;WZi6e-S{cJS7v)TkFX0r)!NHRgtejWM%=@_y4B9rWM2QU4VCBd*6ALzbxY4- zMOvA2(D-Z?n;j^SYUK z9^5Oib75rJDQ%pus+&FQ?29c+X~VH_l-YG}7};EVE`y)a_`&t~h=_4Eb8XJ2>BuP3 z{swNHa=R^+Wm)2}5Bi)~=+1^aCs2&r%~R$aJ|!Cl`|SzMovt^n2kZJ!*V?nSrj^}; zZU-W+*RODnE!6D>3%l#XzC^bjBARr1*57lQc~4}0^Y$>mHEPVZOZ#p33# zF3q=8(gB_r!FI>G27liXyssm8Z%42_>5}&54ti5Zu)WgGrGQ>$R#-FHkI6=JI!84F z-*4`Luk$_S_PY3ly7;8J_)T^3DRuE@>*7=E;$PIodr}VTG#1NMeKMn^hrcZ|Yx>_i z{a?EJ-!bwmT2n1fss48pr|T}2N~^n2x<;h$a(~kBzmzPnC*`w=cum2@HtLvUIojrlb64N@2MxpQCPC zZ0)R@M4pj$1nfNW>s_$zVZKMYNbc9okJFfBqqV6c?Xj7)Wk!<9>97qc%Q=KyWDMa` zTJQU7S2h9N#=Wcatp__3wlnOH{O)S2TL`ub`MpLsbZ5a%r_=hRU|zF50-fWit~u>} zgwKQ>f^S;4@kh8_XjY@}U2I{#|8xWaw}0sVMtH#mJD$-u?GLz}VP6%xe-b{Gv>OyQ zeuP;EH`Ot9GODXnz3h^8ws7mH8#XMLWs&WLdj}R{A(`XKE`6(GHHx3!|2Yr;B=Ty; z1-l3~kjSqJ8wbLAk#-lFWY0%wy+;ly&qX)n{r4A4N!W{cMEqI~ZQ$u>G~+M&mAp4bSy# z`+AA6?~=?<*rg3eR_Waj`#Ei>^V*E>UfNd%dj+PARbbX%8!l|DN;q^MWSwK(VDIPr zZiiXsHe94Vi?F&y@pnaM|Kj!v<}vcCe$_e(=Kb#hq#-j6`%J&O)Htd?! zdA1$jvS@c(b+Co;!^X*kAAya?Y-x1P%GHwr^l-v1vZJP}w)?FJn^x9>&UbqbDp+sW zzN9?|Mv|mEj)42e(S>e7bVJZx1+#qScMQ6zl;i3`*AJcV@jQ~*y!bod+(zr;yR_k= zo;M(D`P6NV`?+_D_APWr5ng?I#(KF9OnVGY8_U2fUmGrL3@LP*!%gcw678-){Ew9R z>z&xo2?zTC);OyA-K1dO!L;GK4*Yep;kyo@vjDEg4KR`<-BS3z%jEMjp=-#x-@{`6 z2%XQxs9TA22T|6?Da+!7gB@-8XQ|Hr5X?5T*U0L9@L-o_7VX9SJQ~l{gKJ^ab>w#q z?Cdt4Z^w_c*Jd`dD9d%39iLer@|&5wY**}>DXpvr%wyR`1)CQ(Y5D5;fi~2&!faPv z$dBT5YF9B%RyPFQ&CS(!t|F~-I(#^qdL?bJHkj?tv3;=X7|3tBC;fI&mYZR7@6a*# zhBlspxqZJNOqOZ8k$vi~zQm9G-b8oAUZgE-d@MH9NMvcWkf5p9@a5_k)4`#le1mfi8$Mp*MhYx`wh-HI$kW;*)VN577pD6nCt6x zp!)LpJVfZOL}yv3)*8E+uy&6v*xiK9?@#z7?^J*97P^NCTNbZdhK=9BOzZV%c8gAF zxnx<>z0Pl|Q*0zm%Vo6 zI#9v9er$em?@}Ay?=ruKU0D|UlKCmTZTupB)9%bL@4whq7bhI-Cz$*6rv>wS9PZPf z6=~;$nO_?lDAK;_@96%}t%LmuHfl?+i*_*IXLUb!To`Ge%(}Z~=wMzev+h0Cy0qb< zoq9};v=5`RUt1X#+jl9#wu8+Io$u4A8xJFx@(W!Yf326dv)#uC*SEjNVcH#lzX{vH z{)J6aW1hFVpC4baL0M-zjI`@#-A4u60%qS7+guy&%jS16ex&udq3*qcc^yGrv;(TM z@*(WzGphFvh*o6x!yboud?T2c&vkk1iDR<5PjcD|2y0j7HBQssNZ9(5McQj~ytMH) z%=#;Je*mHjH*oIz8CK57}o`RtB$px{TOCi+aHI6Wba$pP{OW1*{6NZ zIo55bCG-6fndQ?)Z=AZ_3)YXYx=S-Nzm0K!ySw^)sA*+`ahKc!qaeY?X5F;~I}5fu zy6q@P=%wvGpXSb)Y!8``2 zJEdUf!k$OBV=lA#U4;7r_DaF7hIN0Ku}?0ux=C5LA(60Q`}BHwJP%{L+>126Uu++s zPUiEs`#e*27d zmVTw<-6QjB=ih)oR4P*nyGO!&2gCiB+L)PCFwa>xpQ(wy!RpJ&>Ko zKi_q>FN?GjVAhrAtTMc`|8$w1>*a)l?L%0$V$s(2&CF}Yq1!LBsRcVEv&N!b9S56- z{9Y>95m~o4Ws3ZEgDr*5K1$~LO~CEMMdkzXT_{p||I>G!4<;PC3kZKXUqkJ?uBN>V z=ljKd@hM`;&-a>#b!({XS+u_^`OWu>dlbxb5#KLft6MACtD>mA9e1R znl`@&aXzCzH<8Fs-S+gw>MTd88&6!_toWPb=H>wY1ip*Mg*$QU!`>9I1RD=~gLtI1 zZ#V4;WbXQh&b0RJB{S_7urlrJcU055eN6iZ`Ka44>pX65gZqh#4ePlAERKCXCHy>{ zv)fdx9j`}xF}R`98($ly<o{qaS9J7jiKX0`?I zH@JWFC+uQ=v41Q^*s`eG3f*S(iR%<>8`v%|`-RYL2Rj5t_g-W6aVNu;#1GvF!oF`7 z$0KcQ3G>~zCkmb4T2SY4)5Y?|dui(vj{Lk2;=Ve%TL<&rmifhVGuoIRwgrvAYgUoA zPfj~08?t1F(g;eX4OwY}$LcEEZri2yzPC2KelW)iTzl)@k>AwJmYbo2eF9q+-OC00 z3^s=Rdd=9O>q(}k!6wYo!RCeC$bHl~+1OF$Ua&1;&t*n6ruPJ{dZ#+(A)59j9-XQj z{amHeO5C*Swq)JZ9gsCtPbG90W*x~Y=OI@27-5RqDZkGOo!1i7^}~1nDD!h)&@Lv^ zyW$6P5_%@gMfL@50_s&s+9O$kU=L(AQ{Lv< za6F`q3vwHpllU;4?az8~aqJlFZ&||Tr)~qBI?L(0mb%-Cht59d7;Xv-&Ff)WneT1N ztYi1{p*Y`rjqyw9Y~y9xmCa<~gk+zkvW$s79l38Y% z+qW$9dRezTd?VVdb00V+HLYwj*b$6v!$z?Cu5U=p^05ihbxFtQ_T!Oujhx>Xxy+_r zE9V#IWx>o(X8Fqe<}1qA$aNa$a45^y4D&qTrNXYPo&01`KKBdD_g10%hJDZc%JTgK zW`1S)Wad|vFY=4>%|*T*1MI^F;=8zg<9*;(!q$try>K3nZp62Iu5%oZULYL09SLu; zSI5}QwD#X_->-6=%J#sSUlW;`SDD{Bu*lEnOe~*vUCQ!ZK|FK^qqCj%#kYKAJAJ*- zjp6qPHtmwWVHatSgjv4b3%k=|?dVRL*roOi{n%x0T=Z*u6V`^hHr(5< zb=(({?TR~+3%=fC3|%|ypz#fryK?`c?r7Xb9OOPM*f^MW$FoCQcctAaF!SpLw;q<~ zM(JYsF7x5EJA{3IJpqesXPocgo`7%txxd+8`JVIv_>rGl^LrJa;&jUI`GQ4$|Abk- zGQY2hM}Ef=9>;#(TCn2?yFJ#bV=JE1nORoTT0fEBwAd;9Zrfm}nEJo6ZFGS}TF*7y zzTO*=Ek}G`ob@sQKiK|+eU~`eRp@+|xYX^J)7oFy|Cedv+Sk`9jpWeHX%wq@6fl$ewj+eTGb(+gDvYLv{mU zk|gG~_8GF@;#)p-H1G5b8M|vLi*~%`HP7(IH0C0jY&*UmwpC*qI|j2KS_j?SCSuWZ z-&zv(W?o;J$MI35y^pZ#E4v1E1-kc$1apk{4hQbfDO|9>WZg|!=eoR$dy#hndl$_9 z)_1J!EBH(6?6nTx*=G3DiTRGTOdIC+9`3w-8!OYX!GnDSTZ6PdA7z~~Y)jXNrl5NR zyQZ57XS*DQZUsc9^_a2*PP>cX2U{{T`-WgkW#)b!Z0XDvFW9DpE%URveA?J7vsVhX zd1h}HY>Uj^FPPh{zI@wdR+i861$AZlcF3$O-_bD3_e^19Y-TSP?3m2nD%iNp;@t)7 zb${yj>?5o1pIR@nLo>6l2)18lYr+Vo{dHY@-zmQi-vv|YJsH`WxgC`3hoT)Emh(H5 zH0~dz?f`xZyEpKI?^usP6U=M+zB3!==a$*yi|)EoGMk#^Ob z*0RVf-@2zYrgyD_Sw7j1_`xintRMCxzbN1DGP9qweB&-_OwSDxO?{{3d;E;X)HeA! zebd?UeG9t~-~1x&)j6$pWtQ*OGaGB~$I2|9%(8^e^2ydJ$`a*!DKqz_D+zCSe`6Xa zXjgVQ%;%1h^Fg2s(?AwwF4MX#LTB1NiI>c@vPio(Hok|w z@Lw>Bo35v<(bDk_pUm@=Enz!R2j(aH6t@rTpLyM6pW#k`O~h8{zJy%{jB4b*>CC)*U~``%CI{A8`T?fW!U*3bFLPQeYQ zVYbj;Sy#Pq@3T(MPy0h*;|jR>eV_X^)1IB#rqg%W_54>Gf5^-{SEpPD^We#fgk5Bw z`;Ud$&$wT%7_B^`#bN$IS%4rYE z>n7V8W?d~xB=Ylo@m9^PSWa@PE6fE*vC6~`}&o}(;Tm`Qc%wxAK z+OxXvGFt)rmPO|AT-~o>O=)`(O>JW*eA}P>hxKQhjP_?A8Z6pNw_HB+>yI7=5fUQWUaWfVLlIU z`DCZz)XkCCS2h^;IBXu6<&zzcYy5;c2nwC!D(&t_9X20>4g0W2I|J9=ez?sp(x9YS$7}I`YUyREp$u#iu>KubxmUrWNBXSBk(VW%`afFPj1J_w!n|F zEJNBe7>wUguwTRG+pId@Kj^uY3vNfiT*l&_#qBhEL*=twz!n}SPHrzI{ zy9)L;?1)z0gQp%t=dp7Xx`Sq_GMYsitMuyL@lHPSiq`|aX=1K=!kA9`mv(*sehR)z z=)PxgrA`~>w+YVtz9ymd7drFXhw`bBMSiQoN}c(sGe2#Q!gYVSYvpPDU^^3D3+A<% zV7tQhWAYux4#9TIX}7IoXQC_F9$D8fw=3;BCe-dK6fW``of(I&#Fiqy7UHd@@0OnT zCYqk}^gN(-%Z@R%I>+cIbnjM~1K<2)K0hQIU$A{Mn?ILXo%eQpzy03A?hcu8nWvWD zF0l1Cp&zG`wXrH`H^9C0*RHj>s$?7DuG^(K9Vu z*tA{;!E~pzKNPx=giYHsmruKH57|itn*f`W@*RxtVxBXT_rwpoR*u7uvbevsG6*z} zU>6ZSddKF9&*ld^59Yh#ixhQmp*rmDRj|upH)3~k!LH1VDopv&9MTwmAU2jDtPR=X zxa$_}R-0=i*o`-L%s(Pq5@-2F;zwGyXHU|Os$-@t*)se-Y>(#38Tjrmx8sK6PJ#8z z^|BiAHr$a1HmB$3v?25S$i8?#{9tW_FXcV`_lvaJJBhT@=eA~A(=2^JbDG;P((VZR zJ!#j;^{nm)ocRsRbtOA0>pT`j+Uc?9_T8S}T*#ufea|b(G819jUpFc)()wJ^H-GF} zS-8m0b7tG$a*UD8%XSrQcdk5cvMl}3xqUZb%o6!IKD8Yjml@G?&F0Jxx>l|rtS*>k zmKmpdYGodp>ne0Z->>T2-m~IPj&!M{-C-8aW_zwVTgJV zj&lxzEbU6tGOiX1QvQn0!c>=zPzEj8uT-YgbYpAzJzopC&ef%c(z|n2_IeF=&#E#1 z{OPA=!aBbTK8d*NpmUyqn~3)`jBDff$B4HO*7^POkLu#hd_UcNMRzaXU0h79#%&rmBiWviD1=qYL z%ox|41FmA&T@`a&_r7nP`k$%k>we!p_qqK{O;x?;SFx+BtGlbZXLxv|(JvEZ>2TOU z)7Ef!2&b*#$bK#B$m74U^~Tk`Bk}IXhc&;YA)UDRKmHyYdx2EdvZW}nZj=KJD?dq)`Np;5M zshcU)w+zDD;o!~92IbZOb#JY!zKhSg?E;Rkg8H%E3SODM#cy41iQD5}HXP;}uG4TE zS3Ab?yVmP;?9e$+*tKI{!E7Myn9&&5cz=x@x(#!D41v<|uP)+aNY&6eUN*jcVRU6( z;)~}51K>QaNbeKyI>T*l%$kJpoe#Df(^dBkx`km^73>$-88onG3g%jf!&a=n%P+!m z>oC1%!TWTWMbY|>x+4bHpVJ0g7Us9a z&&_#J_un$VgLdj-_4U;epVx=iaAAEZc_9n6g)xq&M-S~>+h!U}-AcL%{AN9uy0|_a z2)_U`6Jdv8n}%#0#`xkoQFcXUTVaRpG2FgSU~bZ|ZKyjEsJEFxzuGZluYM_7~$Rbqk}rbFKQ^X7en2oE>d@ zi8d~q47060fjiO|Kv>(Z=UskIX~eNGpvd2%=v+fMG_%Fg`o2cr9l&LDichvY?8FiE zwL_*Ma}Db`tJmiu2U`ht9qcuJ$Juyyz+&>s2{tS4&0w2Vm~DvLCh52|jS1AHZD{L4Hy3XEq5CrHhi;jk z_4eEsw`s_hhq>Ootzc`wY~yFah`QE}i8k)Oim>aV^LxS%6wK!}w%w^P`;B%?wA~MJ zN7zl#*>*h^g8eqLC5k+6+KYQuWY}_sZX1|u_+PHDgSgPFvN6BHZm6&wiSIGk3PrjH zz^1}He?+<`XI&eWQZjWVJDc*G=K)3j&V%`mfi(+u1MCiNV0=g#*0X)5>Df>It4Q}2 zbbjA?Fd|MlX}`tyo%_M8XZebRaesI}GIa5M=jC8@7m3@C`hDkE$FnpV>jMDBFrTzVBexvuT9xjeK*IOmm@K_c|SH49s*5>-#&8gS`Z6 z&bki?pw4@W!M@C_CFjquV+s2wbSwE=4(qkKVdI&ox=)G3_bkLXLdGU6(^DQ&e^I4^iFIKuMCI_Wyd3(hXOSled0tMjApfcbM#jx}JO z8=c#1d~2f{hG`yEe{K{kwMCA>_j9`HreS>7#NqVYp*K}7{~ z>}FmjlCfYHWOhDf3^p3J81W5cun^3)A)7vjwQgR6`Cf$C%@gI2y$SQ(3yw2zCiY;~ znSZJwv0Gu*!KU~l>{~hPQ82R8CG4sAt!LASuvg%Yus#PgFE7FE+7>rJRX zOU9Y@Ps+Z}c;Eb3X^NdDaoi+Yy*hJUA!M%1&+ z=Y@uidX`1lsApM(je3^t#Xr-CdM;({FkGcQzEs^>Dk>tVJbS)}_eZretw`xd|H4#Hj(<2x?gf(^v|hkI(ZR&2v@ z*rn%ot{v-*J9O^1m0=^XZKE8D$*5Zncj%VH?fSInn@m@xu4F^9jxM?pR;DhP?P`Ah zJ@jm6+mJ29zms6|;Wp1QuZ1szMca@~h55brXdAND95&iU88+HR8TJaoST>nsDAS0x zQR<>?$QI|H`HQw8i~MbbJMtX)i?*T8v76?m>{xU%(~xywo`yX(eJ48s_T#C%?_h>bHU?%Iv&~$u z=ZMcVHm)$!kVP6J2>T&y{A_jRep-z(x&D87+-_7)Z3lkveJYVZb#3T;7m&xk@ddM= zESYnreDBXq=*(LyhAgDM&U0SL?8D+bXnfA)-*maA+G6a8NMm)F>-u-$_h5U&TnD{n z!A^v&Mmek>_oL;wi@LNNPZja`?h&ze&A8Z6Q{HtVbx^H%B>=C{xthue3ik1CjR zzs&PXnc4o%#QkkYw?@AqI~V5nPPmjx@yX7IEp!ZP%nEh^>~6w-S1{MzOgOq*dY8O; zF|6+iegCL#=^f_5u7JIUZaB8bnmXUF(4F|&3wAAT!+IPWc4>4AVqE9G33jjnxaVZu z=w=1;eCc}gIByx&eoZzl*S)MSX0z*>(sixvU<76>%op3xZxp(rFxRGjU$A9hhP6NU z7%amcpYz-b-+?f;jSX>|XPM8VWsWO@IbXuH(Kqos!P9;jNd?(nUcnza$6S-q{ZL_> zOlV5Xwqbs*!JGlJkBzXp)!l%trqqqeI?pEuVXWulunj9a5aXKIr3z-BW8H62up@9= z&*v5Fq|D|k(l{AroyK*jX?Uy{-@%3MEZC=gyQgnlo8NgcPhd>ruB@8{|K+%yv$8I3 zH_wMLXT^Q$CW|>M<|*pg{@Xb#w-szGZs)Arj%^*7#ucRD`%j+7Z9N-by#K^Jl{(ib zs|$7|Vcq9FbDo#wwuBQ}T%3DG=CFIs*co7ByXv#ei^Z#oKUSG!5%Jx9#i7 zuutHzp3AUL!VIf+8N!~oO?_Qquw^rQi{FFY0~?Rd_izWh7xoaWAIv-(-;tOpFvq09 zj)K*g=*y|05%zw<_JuuEFrQnQ#y16<1X~rIPkT+b7f~I`e%SLo);(sO?C{K-FC03b zi>dQ`6YS{B9LoheCbMS?c3ftEFW3p0%~0g!q|6pA*dH@<{1<8X?p5>B#>pkvx0&r< zu5{gjz~Ug&<#%zic4zcRCr3ieB8Tn;su37MA-GGkZO*1+ujBkT5Z zIb9Mc8s|f=8JWjYmXOf z@65dC8}Y3PJNKLB^u0Lioi3x+ig_01di^NdX|$8JIa|`R>R>FrN$cmfL{F5-bc4AD zZubgv4V)~(o{uiR`xCnBaQnqyR~3< zW#+rdLU&7MCuFuZe#avVuh`O}vtvumb8|4qFRmwxwFK&% zt09|&9lCUn0`^(KX2I=!klSelp<5N^9CyF@7R+aW>fX-dCev`)dre3l{AC zth;#n&NSZ5?8AZ$AYIo;4dS;bhkdL0`@CQt1E#wXcIdd(l-MN&8Y->vu_IB{xIX~g~;Q`I*9nLFLVdMcR{x_I{P}yq0T&e zJrMEz4rZPY$&BtJtq*d)#Tq@?QyCRJ@)Gx{&5P$0*AY#@?REs_NQ~=^-V?CNIxsT2)J7V8 zbJ#}<=6se@&@GwUm1)>FSuZ}v=8)==#$)^zEYf%iX1g-1zgxCP5m~l5V8eSc*Xq-j z+Is~X3fpQ9=IW#8FTGpZKI~kW{XxklWft)*M_AXqcy0;y8`wY5c~2|YS}@n+#XC^V z%Q`UgV*WffWb4kvKIa9f_vJc}osRB|8TdvYZa3NSw5OY4f5#nZoRf7OWSFG8=tjXp zcO^R8{f)Ve8{a9g{a_tMo@IZ^%wupl%;p&1f$IH%U|Ycq8_y<;Z}?pFO?(@5G2D@^ zb4iBJ-J|B1KA3Y!=3k)m8+eA@EVJ7RoosMlzIj@(ZD0ov?9sR%YuFuO-=Z5xoti({ z-M#C1iSxd!9o;$ThURu)ea%Rn&&Z4355;Z%Wb?tUU~=xoIbGQjF!y=Pt&nl6q;@B| z$who4VNbyp!H)QNOGPaytQL77hqho_AIvPs=E@M-$!%|XIxZC8gu)dN5^5I8=rN4=a%HU=njU3?gn&+ z(D_}E%WE3vz+5wQF9Ab$US>|NKHhVePp8%l?FPm#uKF!#qQ*r6MM+x2~M&%>~eC;gUbe4jX&x?pYSE~JjO znap_!5pL9uomwTBCXKv3G-W~*A&cW9O|YNdASVs?f@7EQG~rD zvwd?rHGht8)ZJMy$3e1h3+D3=*>bdph;JgyZ>{z%%6kcI!n_P3?$C{csq=hYGIb@J zkacSny4ztB7vr8Ac7**k=6lTkfo`Xw4t|Z@ozqx0x3%R->qX4J?(9*!3)^i*%##?u z<31Fds!sPO&mwNuBz}UQq9^ueY}Yu(m@vXlzV_E-2 zp6u($Qo3&Y0OotMOJ;v1vkuIUeW2&~KG?yWYjDkb_4SWxXiAOuww{)C=I3sHG%VRp zVP)JVNX)Ui@yQNh|Eu%Z33dtlU-m)4rlZiZB}qSYJu{23DDt$9(e+<9=CCsFjk!+D zV>`;RAk6Q>u341V=Ogxi_Rsuv`9AFXg>C>kzYpuNV0|uw@%ZuGDbK?q4X=M)^T#WZ zx-i#zmCSo0mok~Ftml_AJC3*`zE?7Ps$kx?GVCnap>s}_Z1aM7oh2Jvu(vaNw_xvN zX8&P)_N7Z>tovPH-UpytscfDp>gR#xbT(*CWtlO}LZ2~_ebO1`i1h!+^ndfjH}7fK z^nV7bsiRws2JHV@Z~ymh;{O^+6ET}o^BVR4hHWNSZ0Y~8$r=9)+dR(y^?ci3G&Xl| z+UmjUZVC_Qe|^JEp4g6=r=xp&?U)79|AqYDv|zaRs9liA1q)4tUoc<#KTrL?n!B_6 zF5Iuz-6@_6<~b2^%xaVT|G*rpmz3;#N-qc;Dw`p<8`)#~-BD=n~U!qws4X!BpI|9bncr~gv5chkj(K9KRR z&3~;~)EgOI>Zx~)s_c!7f2m&}{@OU!zabUXTyHn2;-6CS)9AYBTPyyyiod<$@2L34 zRs54G{wWo|{h6Ejv^K3(*A2c_@lUJxdlFBnZ>{)OsQ5=#{CiaV9TorBir?=Ym+3{m zYjEp2>brNvZ@$XkhgAG+6~Fl`_3ah^=!(AszxmQkWc{Q0Zp9t-co+V4@UMWG%8+1le6=8FE@z@9`Ur@iY+IZFm=1rz5;yu2Xpb z-88!54O!i8@9O=ZeP6EICFWUCZ&nG>QStv@-Vkigz1939&e%3@84^ye3)?&0W9rUv zo3~J$`nGvX&%!yjL0zig(3-8svHTmEoXy8*wOMT)9Xjh{OUGc`hDi70=9;&&JTmX6 zu1@1$1v_-!gIfxn*QmjM$+}AlHXXWm=~(V8*vvVsb3rY#X}pXvjX(2S#K$E|ZGF=C zwg}q`wkPZ$Y@4cKzreV*EXMmXrhC;MMQ5KD@$H|n>>wyy5Sjyy+sW4@DlcHM(vf1ks)!e(b|IGKTP zltcCh*fiL>xJ^Umw~n4zm~|7lEr)CuDt9XEINYJ@pX0lsVC&@gJ}a2tL3K@5JVR{d zH`m~FU$S2J5#K2}?7k!#%x^52KliU}QNk{p<6ADLA#?4jd7e}-uOBz%2KjGcmZLxB zY>exqcgCh_QrX%m+c)H8lY&KgpN2)cBZ%)X;+qDu^OzMwRJF6IaPJw1t{vT3=r-WD zV28l`cB{`SWJCCEH_Y8@)Z+-YJM1M`gjKgUW;kUVj~%*waW4dWp2+y6+2S9t_)!vPFEsmdoWetk;p<7Ot<$#hc>05c^cP`^HV( zrI=xqe?{!bi^t3^t@U}0!ECd`Nzl9m+X;62n)Nvs?5-5w!`P-VCnnhAFw^ilHo|(H z{u*H~!}jDm5OWIdDVT8>bsiJ*QW^75z@G}{JHYz)uh07o-48I=<$6q)%yqf$1Cmei zO~B#0T+;`5y`7t%*~-z{`s5!U#eCmig$ z>FT=si}-Gaxu)0sNAOxZ#(m=Y&JD36?1UV4n}SV*xxVupnC+k)GaBQ&8BWBGu-E1^ zCc?;mmo#oEbl2zjY?JPfc1*zbPp}Q#SHiAVtLbpeuy9Ax(Jq#A*i2NO1=)6y=&N`@;$X^-eG^c4s_K*_hi&M5z z=xUN~Zt`WDyb6D$yD4e7Ki1^8>i+Qj5G?kG_v|9^s74Rp>@#=G=OAdrD&|9ImNc3>InZhtBU_^BI5!+XFT)xZC)Y`*I>L3 z^Y}1qtigD{(2Yav_hx@6*wrwEPh1h5o9x%tC)$Q) zMHkO?)QyF??(i^d4y6tj&aUL|? zoip=Uj(*Mi7}J=er~})TYy+74veX@%b(ZfQ;&Gkj-Pmqg8)95%c{8?oQRg+YbGf{x zbW`Ve$+efB(?WM|)}4uM`%&jO$M_}}I>&X+(fWwI@YhARAZbK=51=#MZbW82%J{m& zLiZ6r%(rY)dKX5pzr!rs=h%kRMA?itSd_y#o)PvR{Ajw)3#gW3TA}*}-F2kVtH?_e zzpqAEzYFfU+jMrqSO+&2y6Mqb2Yco|VkR`!k?Y88OK$GFYcQ@iTP)X$y2sE>J-w;6 z20NB$(hVldwhC+((g?OO><_Rfi3pr@J7Bwplqs{Ryb<3tD$)3?1KBgAalo{uT7L== z>^a!|TQ=1O7VJLQ*EcoQ4w<1-=NQ;>^fM!DWjSVmMSS*|mc#kWO6R~tIa(-huqej^ z=&I#l>Uo#=EJw_Twj4u=#Bwn0tD##KW;uEmtUt_hJeJwKgdK))-Q2d==2_-BTXuWF zyvC6Ik-7+-?aFVM_s;ne0?## zW4fhaOTgaeMpz3Zr6lqvjy?3PF;5UyCidg%Mc>M0V0Yf(&ZW_+p zk=fT?g?V!K?zI8fC36kmq6HhDb!!&vj?B2d)Ceo{8?Pm^-;=#v=qBJc-8ko&mx)=& zw5mpY*Jk!m!LG~f<;;fQe;D^{3pCd@>xG9+rtV25c@4?sm3f@2b6z=rU34)=THS|P z_Z=eZvy88I?l)x5qw_n^Z3TM`=C_ig?$z1_p7Fuo2kqBiX$eb(`n*EPE`oz1Zhur%TxVb30JSkR*kDgS>#d=>7(aG=9#yeaLXI z%VFl_>mtuD!2IUv61l%}UoM9E(;lqh!;W^vltc-aM<2<^u9i;HKxV zgyqt*wixWdf~}a@6$P^|QRkYH2x~er&n>}L%WNR~H<)dE0(rhMGwUWD`v=v(+ow); zI%ZB-uNqJ=D9u=0x zGKcXEMt*ZM&+B3QW}RbKvXk1(_Sk-h(&H}To6EQfI~dz`Rfb&+=J6qqup1Y7nGg3= z!Y-cMsbQTTE*o4h&lR#C3bsgQKV@bb$Mer`XReOh{QW29_}+3jW(nOmnB`rMcnznC zJkzB%bk1?}JDxw1uKBfY?9cp;r|&?G_`G)Z8?U#(?01cCeT?azSm>Pl?ubB4VhTno3G`!cQv9V@xX;(G7|+}4xKdhvSj!Ggv0;G?i8 z?>402_25*P`@^ttJs9Uk^PiT?^*JO8py+8p|c#W$BcU!hIQQKddx8dbbs`~ zcH5l6?9eh2IMthPz~I%u;7+G@D{( zLFYLwbnV1F3^uM{-b1^R^^>o`Xc8%`bDB3n_iUl_p4@%t<|T5=VH%5OU2i-Q*7>Ne zy|n#>Zt=|GIig`##oWJj=l7^&J7ZiQy9##Xd9|z?flV|i-OxoFGHe^h_;$dKyoApB zj`&v3x=XPmf1$gp(5->{72NaGkX0`Uv|F?$Nuq)NbZC+s{ah`(cB}m^D+R@d)e$bZ^3JSL!~wRP)E*S__RgZK_iZdcRe_goGWh`gL!X6wo6V|-RKbq%EVdLr!6IjnI6^ZcuB1$J7n6Jf54e51mAKTpZLCui8dv4addi1dGixvs^2 zA=po_9gb~DYxIKINL(}KehbzN`~K*b^i8#3Jz&OnU@nJg`0fki^W7Gq^Zvs3Cvjg2 zX1lWg@|b<4xPWN+D}5>{>9_hQ{+Kb)Fk#&Zh|-m)t3hM+&w*%x~cFsg;Iqr_5d=&m@z~K{(d< zT}y4N8S1(v%pdXiUB)=)Ed#Tk_q%hpPohclwHL7qNk(0L893F|g}cL}>cmCf_1>s0%~%!~20VZOe)r8c@?Yr4=Q&so;ZXV_-a{r2^i+HZ1sW%J-RKKn%dhK=~%Dpl(!qla#L!Y+g^(in{HGMH^WSYMdO+v!9WY9> zqTe;XFEFO-^8njaneO-^e_!&O={{9qrW?#-*D=6PeACBk3G*!b3r1aByT~5QY{guE zvd1wm@!h4%VI-5nE{=V|Beljm4b(k}>BUWucM#DOlFl*fSak2^{HePM)4pTRbUhe( znFvee$Zbg7pE2f-rK+i2L|+SLv-axSjNwQlm%3+z%+8&D1Dh!ut}N_ijA8Px93^!b z|7WC}_01=B^{pXGd#ld+#E*^HF7@$69Z%l~dvZh9=`brNb$SbzHQc$KeMGAA0OwAB z_7T3Cy4cP>!spe+CKxw=7cjZ1Xf1xmdG--~tKiBi=<3Jk5T~)3G4H#s(;zt7qt>Rx zF8ZKw)OX-+u_r%h&bxHiAPDN3`u{TKeVRht5)RJMsm6D6QIA{Q(biOB{b-%+9*+7? z^ef3>|B@VNlS4Z>{H1v*|2iBAMFw#++Dys>paYY(N!hNA3&)snG+M^-L5>Z_ z{}l~C)YEJWNozQg-EsZ(-FgR!iq8cHM|_1qh#{4E@NE_U$cn$c;vZe{cU1gi zD*ka5|HO)aQpNvV#XqIupH}hDPPsPAWeclOJM|?>bv#`s4V`wQ0_%&I>OXbD+CufF zA)mXm=g`?E>u6SxopTpX`um{Vstsq$Yz^lY1#Rn=1+^|)oYyv`U-Vly2l8vMEn&|2 z@H)_4-i{f9an8qO*r6MZ&To0Fg(%oIFy}MxS?KnIJu(mD(?WM3%sC$naniY|9sOvG zb3RTfbo=D^=I+*+hR^;C%jIUe7AwP!%(?-@wFoD@D_ZN%kMO2vIzMAOZ?eCD&HhGq zZ)^QMqL#z30|@JPUhD(AW7PE^Uw-FhY20=O_TBNF7tgI^E3tQLrmv&T$@Du;(*-=l_9ymBTKK zZ8=Q$zhyrVW-A)agH)d7a7=H$+;6YKyf$vf#6EuwW*T0b?o2&9-`Z>XVEf~?O*(GJ znZgo%YLn|@hwk_MXc{NNh_Xu>Cl$J*b9^7d+;8oei0>oZ5#KR6KA#m%mvxb6+e7G1 z#O;3TgY7me#&L^t#Ba|!_vH{W<(%pLaJ!l2g_u*(a4@G$=CL=7I$Q_aGz{x~2+MX4 zTAV4*kr(GKgwAhZSXWbF)v|q9=r+pn{f%_0WqUvGbJN{4$M*{?_M3UMKj6`CBVE5W zZ@L~IZta-R`8+D}w+gy+{K5#HbWx6xg>F4`_D%B?dEOLepA*+C=5MQq`IVg zMGR%=1_n+3!++7Zf_L$JLF8Rm*mD*4gH~9vin^ zecm(P)DHhj*t=jy;K!NRaoCpaNNn?B*q`x#Orh2+*uOK|rC=?j;hf|>U~YzWKF0H; zaZ)06=Donb!^TwDEZcWwucKQIb|1RPi}#!7rDG;*iS@(&6u)h#wP2sYw%ogZ-@>r! zzJ$4t*u{-DIRv+De2XINztLHzcf)Yj+A+~y-1iY*3p;R=zV&;S!DfW{?V;#5OqW*$ zrn$yTQl8Mw4LbqdW(8XaX1kAPFoym8ob@~}fZMGd6M3E=cf@xTI_JQ8p6P}$Y|Mf6 zJi~5DEat#ko(Ow1VJ+`O7+L62-l%)yJ3i|k#$9cbkH8|ngR|~MShY>QROqJCZ#qwO zV8PypEy|6h0R{U2cJr|MJ^e`I+pIgT(0vDU|DFkp{T6jKrqF$l&bqn;)&o=4m3^{h zlSN&5eHrQgKv?VQb6B-()3R3<|o{dlT2FyHrP23IBj)^=! zg*$X_=J*_6S++91A-N67yeDBAaerFo{TuUq7`p0yJG=<{&#ZeCRxR6OS+@}J&4=;* z`-8B}UohXlU$O=H{S(-(*p|&P!b%w5$v*;{XX)-^#H6 z$~xTb%+b6SMGIkVRac024{ z23L-4LiarE4Q_qRNn;N70&EF7&UTn>#WY^Pw84DGjb)QjP3iqJ9XTvkdS2vw$XRlp zWnOn&v3gVOQQW2>I|JsN%LTD*lUR*8mx~l^Q@C?SFMvhZGjW@S*C}K*g*_bGd6T;s z8JqD1a~!DOW9~rA1Lh^yfqD5;j?cAUmaPoC9?W!U0=2%F0~s6-zz)_gvn>nOKeLMp zws2-s3${pRgGeyqGj7w^yNsvUQM;*a-NOvxXfNI z*x9h5dpFfCF7kIOY*+3gy;v~MCEpR>;Jh!5?*@$Dj@Y8m-3W6IgmvbIyfFu2a3XaU zb08QJr8cSVe2jg>DFw5<&WS$*JL<(g&N&b_W7{ST8*?D8#$D>11EDUM?rYwwkGVYF z$a-VWT;!3g_rnCk+b%nU2t2k_Z| zWsADfEjzAY^JGTwhHl=>;+cf;ZJk-1lVyXbY~#Brr)!?q%)0LiwpL~%a=TKuc4qPH zLbgt3uNJx^GV71Pa=4F;`=p~g=atC5hxz@M8*zv32bkYr@y>QI8;IX;aejws8ul99 z9o^FX{b1L^3>#}-)X{uui=#U<_iM84VVlBubks=0e$>32#Ey(~cg^vARlxUK!TaWsA|BXUNw^Vy*vu=%hU#8(T zqTgVdj2-dGJkDiAlj4iHPS24*usF_Vp`t9m`HSOx-GYsUdz`NaGmQoD+lHJ&ya{%& zak%{!%6-%+Nv9_hwjsaY@^G$a!=9UU8xkLXU376yR(A)+Ip=;GJJRsjbFOyZTwZl_ zueFo8Ikjz}lc_7&y|B4%ZK~ab&hwk~a1F*e=P&25=KF2TPW|fd=)#%G@-6lWeRcz!^`8l-@_uCkl*PId7 zx;N~6*zUJ7>@b-7&9)U`H-MF4S0SwJ&u|*=JFm|o&RYuRev`daF!!6xwZ#!%?6)m* zoz8&9vK@bAXW3+y?TNGN^O^ZMT^pId?_sxM8=pGMW?0XwmaPnHyRvM(FcJ0~SQ++O z!n&@=av9dL-Fi-Qy2ljEvdI=Ibe2uFW>JnP+m)G-RJslv@G5f#ahtB}8qBsZ`;TCb zY5w(EbM360KXre`?9C*GJMmaHqD}X4#-fY+gz9d??D%Hqw{v9nHL{o|C9^;EJ0%ws z`MVQlUT!JaO)%TN=Y`0hV|bb8g@NrMV?t%)8p7i0>4BGrrdm*_V{@#ds2VZCuv9jmWlA z>UM`kx|j2t>3Xhk%%v{Ur7LRatn(o}Y+MULgk6vJxxpMQX>7^QsSS36`AwJp0ygs^ z^P4WRGVHrKY_JWp?xaHZYiuMs=Qx-9d<6Al*Q-}2GyI>q z(cQgZn`Pbp1=~F94k?(&k?~C}m}3y*doeTj$JhK@dW-ruVxsQ9f!TJq;`d-)jDiyM;bqGPwG_bL2K8^Esn=UcAWj+nKqJIMQvxp{@^+nTBKfGcd+y9}vuPK6z^A zd{=enVGKKW&a=#WGO}$8c4}r97VMbJe6|#6#C5Xs{(~Kyb&i{mratQg+|C!~(zcMrqpSFnh0{hVjx8;EgUvGH0C+2WW*#?yy6SXvHEfx#OkFVR#(n?J!Q7Vi7@*{^Cw#w^CB$P>B`zLKf_kcWs_}~8K<8{*o|SPaa6%P24tTWYp4L7WIi9wf&ZIX7?022BaP{ePxb@skFbB@4)!DLI(50c z>bm#lJ_C%~Pz{~azy1Y_{$5=x%p`nI#rC2hNLuRxvS!_}7S-grku zFuxxZ?~RbzH!aCGCic$zE!f@_whX$RSK+%rdB3S!8K!Qx3iF#4!H}eDP2ZP)G;Yfw zyA9*}@>}o(^IAjZ`8wESnD5X(A|L05eFoz^>R({?EpuXQ_s*l9zc?zT8$5W$8THnw^JIo*!FP zM6K8J%%wtGf*tM2s^2r!IptsV_eOJwruVQt)Sk9~`6-8C!DZ=Dqu zVXeE3VUF27N6d{`6Suk@3f-mf-C?T`M}!>@^IOt;z-Gu{A0W&*u!&i>6MR8TpZU0F ziS0HQ<^hcFe7+Fd_|z?gv23OltS|1x3Hw;V7RkD&3N`@uI_Tan*y6Z-KlW5?&nKq) zJjOIW#*Q?WzeVhOWo@jb#qXjQYZ6V9n9+<*~o&e1^aKxyLJv+mUmrPwY-k$ zOrtFCMlj3!0e0lYF`ec85W8C5PYT`UxGirhd9Ic>uIF|_qt0~IMH-GxWm{#oGyeZ( z|EjC*Us+#FSzcLn|H=kn%Ka<*Z}zXc|7QP&&a%b+mBs$uq$uxyvwsa+-M_MRG1c-` z_piF@{+0bV`&Zq6vwuTZ?q6B#Umo41eQv#bt?K-^d2qY6V}@XyvuVF#+fcU{I_J3k z26s11J7zS-wFc4GsaqV~J~MaDC6swD)Om~j5@DXXBx`<mm%OgGl1+)(IVBkWBW*C>+vwcqw~Mf@$96vXq(b*S%(>`M_bFaj|Niys;z*+>8rzlqLJz{X zW8(O=4+!0C=!Q4*zSV+tgN-K76ALys%(ihKth#@FRvYoXMPk*m{S9Vb_9G8SyX56y z{1Mi7nVH7pFp^8UXn$pSKSgI?U*>;XqJum{Pwi_Z4ha2*d<-;H;>hbZy$8NV|^(i3wC%; z!@kzOsT~t(99-y*%xPQ)tG4Is3*AxZY|nQV>`ac0SNHFHcW^(_@S4K1ElvLT>yobb zx*~t)=CJV`)vy=9Ja6rZ&hpCQyv6PD28;8S@5l&UoVUgmXD{s9L7C2c2Kag%@_tb9v8uej)Y*e-?6?+3{)Ds)@HZ1?|wRoipSM?jM1lSLVz>X|8o3pyBYv9e})a6?cV(>3*B~w?olFH?HrCBI;IHwYs_=b z>`Ty|DMaXkeF1Zyn}&0g&C6RbtS-!Vp%~Wue2j7K>3ZnhY+Et+bX(k^`vkW-&#RWV z)Vbf>WHCo|3~u9>Ic9V&`r`!~i`zM>ld&Vd2urg}{c{=Ce!)Il7Gb@1iv0Z@{=?H8 z3;zQ%Y+wGlK4&m)!^-;eZ*$7FWx*DK?G8JrV2i?>>;2b)`HbQ;*it!Nyy>|`(>-0; z;`}fU-QIC3N|h?cW&se&us64{VB7yd@N9en%@<%y}Vwqdot@z zql)+*%>j3~7eqz7RIH&eYhGX22)hhy z#+Ig<*G|S~{%lV#Gl*CYcd&h7zPtanf_ZMd<~`0^*hG`gtGp^Jy&rpHScFw)eCmQ7 zfZO=YXRyOEJ0a)Kyc`63|7p%Ch39uw<*~;Q`@zldIeVQ^Tl9G(TTTVM?HIde}?YL3hRlkWL^uXJ0h3Y zbY(lxhm|aiBhZa2bTV}^$7)!$hcV`FB|P@oB^!mu_)B&Pe)G&QD}9U3^;|dMcJq8@ z-|Bj<+i{2PL)_}V#kN{Y-7kgi1>COPT7fts>?^Q6833D?U|s{w%K-RYSZZhZH^;aR z;G07CH<)X@e0O4mod$D_*Z6{c3H!rYO|>ry_72Q-U$f=ow-x_2#O?91A#UT7U7K0F zQ$uz=?1I_5H@;^gy8*U68Gi|PgmqkRe4ejM=6ma9?xVReSK;uz^(5KQ*?+sP%Ka8$ zo!9UMVQmN2vHSBD%n&AR#d)h0zvm`(RAFk*rS4If@!3{7Fs?Z{65EX-cv`pQnv-2{ zhwd2Mp5LZmyMMXNs>K?c%W;=F%R8mQBCO>t!=6^;VlmJv%KD)^!P2yduG|Yq?AjkY=*$)`sT|JDxj^ODSSs&YX zSH~O~bw6g^e(3n?qT3%}{?z@Hb(g?w&m`Y?7xp!U&SRyeqq)Ykk+iA1oDBToAnY9YKB0`= zlHSAZT9?o8m=9ThjPW_vv%F<|BVmR$>$728GqG1LugtKnxA3@h|7gsM>n-kv8P>8G z)-?%7An^PvGpy?w?k6Jsy)cG#J;MvI$g|~~c4vL=S}?k*#O}imc5i03hhYA0*l!9( z_n+9TxopU)R%UEK(5_gSgi2!F&kEbDf_cK?>Ty$an5S$8S6`?l2GRp?gC zx~bUqSEY{K-AMO0xW|*fdl0yP)op?C{lt^;m_M3GT1Rv60xjvj3*N+D!#);ffA(uS z%WK%sZC}xSJ-8m9FVVf6O2j-NOTN?AHWEWzNW0J1(!9sU6>^zu#Sjleq6;{<<8)5UYWg4;+w!%`_ zf?c1(M!Pbs%&;Xp752&y#ugmp=8s~hcSYImH^3ciB<|UHN!e&@HJZIKJy{QOAa>|B z!L9B@Z0obsomJ>I&AO|xJs*`i$2k$-W?Ajwk5h_i~Pw98>|n0&!HQ&ceZEQ z&KTGGe2ZFVdYi>z2y<&9E}xcU-dhV7@Ef?^i~;^XK^DecOheA%|_x`*$$xebQT* zH4|sfRu3!t4(9RkaL$X&H8!@>9ytx!Y`E2(T(Eg@AA2(UBOgcVoEK&qhs@fUhU1`{ z(2dUhkUB1xYOlcV&;6Bb^US`VzB8=%V}1Yree6iftIlhJzn|1nJ7tzmW*=hyp2}Q2YFe#7IKXp+wBRdr)v{3W(9j?|an54LD#Z^5YQ zF1ok*Em-K*Ac08NKGt*<*`Cc`q}v3e8oI>iz5QSjUt9|6!DQZf1V;eg1L(UN#rZH8v*{x`klt@&cmhpVbY7`A+^=rz+!? zRPD0UTWX7tmgnD{Ft=hxaNZvci~KEx&OBdPFm8_}b`kBxdf5wOzwH{*=W`qKoNy7w zbU(v3KH0^YMSmc>B(sf(H*}Y0c4)z_$jrVrbXR8fY{9O|Ebe8vPX=%dq_&Zdg+Z_l zGJCjS>rhU0Gv)HKOVd0zneTx$UD*IkSub>$`#FtU^48;V1n*Rl~`JG$LTV>!y^ z{xz)Ee7$=1XslzDEtb_zO*{T8=%dOj5#Y-iX9=v;qbc~`@11G{VP9<>FEyzB=18r|we z8a|JjarGXx=W?6GTRVh*V|hT)gSv<`&V^m{n;x~~9Ji1_q!(6*MeeX_oEX;Kof6HuD{8wS-BY}^mrZta4tsiq88+%b-2}|g-}S6HpT}~@?#N+X zD_Jtb#u_Shw`AQ*g-)jK6BwtY`j*!xPzALYN8^$XAO zn`Xut`ZUVj8{QkHvD~c{|B#Bmt>Pb9@wZp}qbvT7ihoSSKd$1RSn*G)_@Arzr&RpY zDt`O^#V}pBo~fVBY>0MqBGyX%z8QNe@dP;1J2;l>TZi03)olg;B~ssY_*&~7VXXr< z8*QDi9qE5t`rn%V*ORJ;veBeHX)0|gU8J>ciGhftIk}UA#Ql{l;H~Rhu{%27UeDkq zMG5s-A%@z6nDuAsoZlgP661Ua&)pWN9b@9oA@-Pwu+QUmKFbtD!9IaG@1U88%tkwA zH0BCe3oLa1f;q=!p4?xU?i(2AuJq)1^n4|=pYpjr%kdjwKY*FWCNO^LlE$Wm?wPFn z4%Vxp`#$UDg7+dJ*8pse+fDWW#x)OnVVh@}_Ycj>eg*TnmUG0%7R+(DI>$5-c6OL^ z;%_h5+^}t6j~C4AN!JB<&(bUW zybhHuNWAvn?(-$F-P$p+&zHg-x*Ks@_oJ|hrc2%LR_N@jjc*)jL_3K1jxTg~;WoaT zu<6#j#P?XCyA8Kk^dk34t7Z5r*^)pii~iUtsu^|B`?f_-ut zvVpMAiS%gP1W)(LFT~*--EkGRY=wC*VN=-nLML;s>{T%HXBw-MhV#(Z=C>aB7sh!1 z!8EqR4&8?6p5RCKo5yi0#_NQsFrP<-&TBNw@qNJ@S8dX_-qu669qb_b1fR*u1`^-A z&GosN3>E%I=K0%i8f;wX{Ko3;qDGC`S9~dvQf5GVCMPa%xpii{+-YY+rN>4z7=f*o8^seq9=NDSq35 z;aG*92GP0YFk2A1C7kRm;V3C*WD$Kl;Eb{UqI`cv{(!9zypCUhag4vJD#uw~L+~2{x zm&RW*OVPjhj_b2?JtL_-!oPW8`}14G=ds^H*pY?Kd%{bjo7BBicSqLwZdQV)G*-@O z98kn}OV)i=gnc5%cLfbC(tQfHCjNLo1m4<>nJrDD3Z3_t)~4ac{0?=~5x4WWR>Z9z zZ*4d_=W+Gq0F1C+TRYF}QH~`w8g6%`d1j;fcj~Mob(A1a8CKS-61Lw0b)9iKzVdz6n-Q<^$@;>4Kel5K z{*u`c+jm^=oBeX{LHmB}hp^pbhhx;)UqyV2Rqb zt+0sCF^xLs4VTPv$m|cwuzMCd=lB`cbFN`c=UR;K!#F|rX|=SIe_Sp)M1Z0Vdo*-MzuU^f=*dsufWl<5s=|EOCRW7w05a@+%( zA6?uJPU7OkK$)z>Lpx zcj#n>E!i!Zkz_+>Jv(P>nY=&D%f!rLZiDP*jPcEy>nfOGOJ;e^%kza!rY@N6Wns*+ zBbvHAR~-biZLF8`qR#WUY(_e4%O=|+vwaG-7wm-{c-KCR-IVtERK(MU^K6BFBf@&# zGQK5xcCv#q+oE9Z8{g%!CUJn%df0fEOFIX7#Amt>eOymB*xs;dA2ro(ovD6&aH*8; zZ*IknS?BMnqk7Uiq&MRR;}1Dq*+|S$u#>Puw=M1qVAmInQ(J8U%(fJ|yE1#WVD=G) z{eW_W?o^m*3@q4@Iqcr~I5IB}X5BZ~5q2Ez6MomNHYpzq>THt_6Cba5Y3OV(=5LpL zEU2^n$?nK(8T>TmG^cDZZa2pS>+-vE&WGYQU3K;i&N<(zV2+WTbN;)6IUaJ(`Ktx% z0dvlI^nb=DbIy6md{*L|^TTqzsGC0P;@RzgVsoH#&iUg-Sg+%q2j{ndq8#2UQ1?n^ zLrBBt6SHw6+B$QSU59y+8`jgX4J&gT@4U&LISttvnR&ezx>2~D>vM+<4!+?d8|l-RR~!j&%9m@}~9&bKc*yf=z(!0^2d?S=|G$p@coZ!VFuo zhtQpMY;)}{0!12*ZH@2s+~*kIE18Wfj)k`}V|r2}?B6oms|foEY*q3yCbLff*n(eszaYwKapPF`*UP?S^$3`0{LJPk9?hJ6`x8uJZ5%;lB6nb|qH zY_fMSrrVawA^R}1HwyOm%$CSyQ};Q>G!87-7g_gd!M@A7E%H7$>`z(8E%cOU%Xc>a ze4nuWo8^$5!$05Qd*T1W&dp&L!;Y{r!?byP*|4B~m~qvpn3ESb;hd|$79 zL<)z^EuS<8=M!vxPS-Rq@}qNbJpY@nVI3Pef5-kK*aI-1(;k@juR4!!pTD-|{U&=V zGv_2k*k@tB*LTH&J(Jlo1^a7es~7B+9N#2taO&^v^G(-vu2EOEXP@I8f*s7he{nwO zeO1AB#(nOmD#EV+by%z3buP@Z3WvSv(*c>XJ!mJ z8fom4nb&razx^`1s$h=qEpMEs`Kjjps~M~VJ#5z3F_=EEGq5ARQb)CR(Q#SQMVIQd zVBY)k-M7OD81b!}({-QP2Fi3@+gIw0PhBv-qw^y1Irk&j`Z>N&XyY?f;yWz2dyA;f z_|!$%XK|0&oA-C~d$2cQURS(Vl*6%QA0Do6T%_xG&Fhp{7iAhR!n_u;(~S6D!o3>0 z9@v(ZY@~ZOUR!yM8oJkTo5uQxa3&d8=TKhh~1YCEZUV zi>a@49I`gdb9k^-V5h-`6y#-cgC z_li7UitbGopS2Ju^6b37{?Cza!LH8n9ZO_!UWoY4fEjiU;=gIG`rHufJJ@Y7=OWxx zusdMi!aNUK-rkr^FrPC(Zz8P-`xkV+tI_ct*-pBF*uJYV?qizn7w8s5H$LZC<~RLz z*_Ut56#1J3^O|@xjXu(N5cb>dJ!(%>*oe7!ZVvPK@LJ33kE_rU19>(+uQ_Z7rOtlM&3)-M`KPY)0;W{_ z-&g#-f9|RuSn;=2{99H0qbvTCEBb=t1M@wxYSF9S0Y> zBhdMb{=9;X%VE9d_4p{mdOtJLa4c`w-3xXF%x4L%2ed7;V@6}HfSm!0u;bDBTN~Dg1BGVvKV>{y9&<=OFeQGSB-yqj&rs@%il7_#B(rZ?t2gu13H@H#qAK zz_vM+x&sT{>bRXVacZs?`*H7)`o5VM$I32*%@2#dN%k1b=e1_mbY;(F=6#M}FJ$Jt z;b3pTeDBNp1$!5^8tnOkeF57Xb{uwu_4$MBx`KU+dv}=QG3y0qZBF7j5=V^n%-{F? zZW^0#a7KL7&klh2v)6^f558s z;{BIuy?hG$PxZ1ezeRb!!EOEyD%iKUt(Q{@_G8vr7ZLU++}4ZZN!bAE{Yu)Ob1)Xg z?Y1z+dveaf*c5l@u1077vMdZ|tsN8ni_arNcMU)KPQy_JyB6kmnI{zNewgn&`X|h5 zwSJg*-%(G}4;Jq`nzdl@zN3YTay&|WmSahn*J@=sxKwH6?+JAFOo3`a|PyvaLfkt{WUAWzAJP);@%eK z_a;NP6Yis7+`4Em=d)i8i!r+U@_@|N%zcFHpv+jN&?y)tU$DRDayTb6(tS6x z-?KAhp3gnbZ3q2vyR~DY9V~)7bRIL-vtwkUNxC=(IA#u==Mv}aj4znau}^JdObH`9 zwLzGFU@mIo{DU1~9ep?-q!~Ndt2sVyBRAOVxXtr0Y!00+d5-gkWwVdCnKT^CM11xK zmScPDYJ1rs>-rJaXOF%1tRF{)mE8tg7`8rcr0IV4ZP?4hHZGXultsN5_AbJXgx!ui z;`83uD46GX>t$68x1Va=ckHYK!%jx`dvu!>`STu`b>Kbr7{A1R+pW-fPsIJ<{qIQE z`(eFF%zL@PUWQpO)>*Y)th3N@Sz7yKZ_a1rE7*rH^D+j8w9Eduq|p70&NO^x-aYH0 z4LMID;+u~48D+Cx+A+UYHkJgW_>Ly5;}>-iUq=xim$@lE&mYrgUBqX99_hZA^VdRM z^s2_nZCC2b`q);CA!AgUmjs6?f?Dlm3P75E#MJI_p8$zK3jg zZ0lt>W-*NK{@Me(3_I7+^|02<2+R@~-$Q1(L$@ty_`b3$VAhK|`+jxTVcT9zV?m5* zoQ)m2EpYq3vRkn2chz~0Q1@r-(ES#-?;*P%+xDW)XHx1Oz&0-obJKlv=M+6xusz71 zW4N6Q=Dl$D`OC0wn08F;qgQZ8e1AeWXkDI(7R+{RyXuc^y|iPj56ALxt~D<{$8pTH zBX-1h3~tkP+)+J_-Yay+;WiD=&DKjhCem>3Y{YjGzYnIoOBT%g-Lfq+bAP`BbG%D+ zrLeLOV2=N;E!gu}_jbX&hEV5u)pQLzIqTv$mpzkpw-h?Z$hV%tbGaffKk)k|eK|I| zcgE*20n_G3Jjw+#D95q4d4-jn_kJK|d}hxPrt z=B*6teWK89ly$EEq1w9Wyk-lX`Li6}leWE-@s;WHI$8S75&di?NEj zJ<)B#!`)ugpY>wDa}DMU*fi{jZ%1@@knV!Ho(;PX>?w4fyF<5MW?r)e+ZJ{xVgFJv z=N$b)*&Jtu&TDJe(7v4+r~9S#&%dc(+%mmnWut+0xgGiUZF1mZEyh!&_e)BujThK6q z-3a@DaxCAglTCmv%!&J%f_ZM*9p-!UBCKPr8)3capJe98u%E8jl-@ZX>^_*!?qb}j zZW6||th3^w$jLZI-L#xASjCO^UPiA+;tA&)!*;){`H>E z-FIf5`L4Zoo0&Z`duGDc=etw)Czxs3JJ?(--$U?SQ@6PB^5gK_e%BO_;Wf7EE+stt z??LVH46+Hq{6?TYWLF0JQt@HgYr9$0xw;z(%Rk9Jv5R^AzOtW%ZUq`p`nV6~d#}bt zdoe!C@A8-E^V2rmznG76NyCv`lo%cDMcrcr{pR;0lj%2^{h3)PY~OLU4)gkz4Tt$I ztnCY%1Lhc;8)3E=4t4GKUL9C;bD{IyRg*ELni^e>Gx}%I^|IbEMNZSN`w+(-vHNT@ zudz7JsIM^lJdQIu^S@xTK0ByGw=g!23;JuZU6gs>)#Y_S(_+8OzOCbK{$VEg$tDsU zE3{zLxol+UW~JUNm#SMl>Qc6L=x!=(qhRA{e?-|~dtxAw$rpde??%1QXi>*xC%6!hou}6;k zPFs()=3{JZtLE2Zl%wBNfSb6YugiJsOt^r?Fqb|tzW zM||om4|PYdkUGzqZ%4N;?Z76e&VKzPu(P6V$lT6ehP_O0OlO5H z9CfbkzX-;+3l(mA*?_PvwyUAL=5v^KRk!%G{b}oF=3^GL3lO|#J%(wrrI_~}Dq{;< zka=}?7Pd&RJRTX}q6F`sk0+fO-$KFeEzEN|eSBP)ZC~3wcQL+^p?fvzNVXEew0tev zkZd)Awr3Q!Ug+{(w7N|Q$6~vDv<=zX1Z|HAMv_{+gkO#x(jHSTn~yN)TfFas1@k7G zKXhIvO2(zm)(iU#Y5geDtZunrzbVXp`8nvkADgz8i!8@yYioXu@5G{8C3L?p%rek+ z)@Zxht`WAI7q(_FHj%d9^@DwZ29#;B&8$y;vu|b_ycHYYX~W^C`HkYg+svl-ah*5v zrtUU$zQ4w8U#Yr3hVI^?`vp4RUvnyq*+%zn=;n>Q8Q){9w2mfYYWif?1v5>__6~MX zEfOsIf5vwZ@jZ3wkk%8dGjB4_(e&Z9AhOrtV;GF&bokh- zu=MdLEaN+rdEXgx7E|+Y`nDjL=0hlZc10cW-BVb`w;*Ma@f}G#e#`frs5jGWpY?;w zhP2<2E%O}%t6x5(brai^4p|!gZ706`9^crS!nk z)^V8H9$VPqu-VRIA4~cs58EZe_PL@v0-fnw5uN2y)3<8L+cDweqQb_*w#0|Wt!cv6 z`Zq1ZqpaM|eU)HcewnGi+FriGvgK0S%g+nTvY$QLhVkt{ur42fSuV9MAB2&tj`$WK zzsWMb|B4wx?P;wGv%ScEO&AGV4`$ntak|u+2KEhD`q+i|ULk$FBDKv{i?m!F`&i3h z9oSsU3~jy_q^)ge4Z_r1l&$S*UD#izn7p}nox1gdEfjgvb~D2FzdpFt7ip2XJx)30 zEkqlK88o%adnm-A^5(TJ(>D5FVm3^-#2qb)TO$o2?s7ZdF$55 zhwKl885WqlJ;q=5M}qIA85a3S=6hcjD(v~xMLyKY8eL(Z1{+(_`~mE#`6q8(4@27A z!#IkmY57CZO-uTl_}IZ(R{EG6rtRV|{yJ>81@AZ=pZ=Kq;d_~vt z9bL=5N2c1p+qLX_W$OCgu4UgdQ`e8`TK2s&b-mx=t;^?hEnnBQ?0age{>854kGqzK zF`n#T%Z2dl6vNx)bR78_1~d2`n{&FBEvLHvmagUdyOu4ts((F}X*$g~xR1NmTaHyf zylZ*Ul8@`C$B``e5|`lvzDL|wmTzRe+O8Pv%S@AvWM02NVale~;rINa^BRV_&0;^g zGg{Ak{ce-{R=2&H=DY^E3;e$+D|OvvCF?FL*?&`3>awifVgB>VDs`5XI?F}2GI^7I zi)k{i6cKzz;1ojNJM-=uK*gs+JD^u4)1Dh6hX<^gAreCN3UTf+cE4D1`c61)^ z7bo0C*cNsN)71H``*E;87B&O67r@?wSytL!K={Qn{qJr}b|K98hEN99k-Dow=k>K@ z*M)A+C@cH#S2J(kR%YI`RJKZCx1*c5R{xl?L2z~U_wIw;!F*-U2Fv&!N2l!tOzk(P zt-32=sdM{LH<-vQtJLY^Mb=fOtt@TdVE*~dC>w064{fWDXVB@xu|Kw<>cjK*%Jh-v z^z)-VgSOY)S7qK`A7KQ+aj_mZOpChjqw~J1>qt(c8_o10*s@GhcR4!0m$y-2SA^|0 zF!RwzNZW0hPup`NEhAx;OCLdhrsZ2qQ+G+|j)Ji%cIb{Sx*wohWuJk4togVg(sDKP zmP;QY({cy%>ElOXdsks!o1Xhg!}_nkfSYo;l}Pr6Ey*&~(CnjEVdij{?a!Zn{T9(# zur-;Vj6hYjW<%#YRMufW{qBSh>ti!mmemO6ErZRAZfA6UAMk*}_JB<_L;tuYlHd5f zjSE_igS(Yw%gVImI5>|F$#NXr%Z24QxOZWhzWwoGJNOBVNk{p49aEj<@a7=)BiHti z0ZhiNmWK7QKH2;f#!5GFeGta##`Y#6IQ}}$DT;0(beG*QFm_5Go^Qy;7r%?bb|bzC z|A8%r?s#-wlg_k^i1@}9HaOT(Oj9>B*sX>6Jd}PP`47zR!RnVsdz$#n^S`NRzf-kv z`|Utksk@SYz6T}CO128R{T>@AE7=!=Wm(C1EobY8j}Mg9=dsn% z{f?8jEGuq9m* z<>$GkDouPowSoFu%(+vE>Rk?^Sc<9J|>TRJX+YNkro}KZV)=tH>9u+BOgC5 z%zl-+O{mDUb-alA{bKRqJu&lUKb60Zyt%(hmU&wPhIvQcrbLu1^EMSM{p!Q}ullfE zSuT11)qA*A=lxuD$ySdvZ&a9LX6_|#Q!!25CZU_NF#GG~_tL_AmP+<^DFg4tSyqRa zcJ*V}+vi$7Vng7~0jw~$8?{+5Z!EZ`dA3JQ?4wg8k}$!5r6ST9%CRGcA*1K6|1r`_$^ZPbHgy zX{Lo+^$p9hCh9C_b+)MSR2@yGLx=0OU;A3q6Q5(4jLR^AdA|YYc|)e9>g-EZ zo#%t8+lqDLh|lp-?%UPbhxZ$Bie9yng{6-JVd=x;uHU1( zv9PC^cYMcjUCi-7GPk$c2$zrmzdiR+(Ruw^TgSBNV_9^z_f`JX(;n-Y?BB2UGgde6 zT6>cj-<32O4al-`e}JTUSJKGXC#LNvE^_49QQ4a4?jzx^VU&JlH&RiRjfA-$`e)H? z5W0!Qhh?eGG36Pb*AL9cE;O{t%!kZ&wF)8g(aT9d?wc|n%XitDkBpD#TNe^$-k0~U zMEYco>-75mo=jb~T=M$<&j49g*?+kW<~FE~EHr(o7htAYd#^)0%mv!zqmE>@S^aKM z*pb0bA|Gjcbg=E%IVW@fsO_O-Hko}M*>=+nuoHtVG;DyK66^~zb~4|;CvzJ#A8V5? z-@mt9=xqBJ!wz7q$(GFflkGw9y)^qWHD9ug3BH$RJX1`Xve}WTV_YUMHO=ZSiTGw` zs?QqViZGWA8K3(D_qmpJ#@7eS_&#->wEUZ$4Mo^tJ0*ao&|y1Yl(RnGz}D{wj-gT6 zuJo}9!8E@INFRR=-8L}Gs_Kp_^|3#NasGLOoBc1crfimGy5u>$uP2r*FYi-6H-2#I z?!s0G_EceC2=;fTS?Av&0>Aq=ku;eH<6D5>cmF&tSXQiRo{{!Df)~Q7t!dHLveGuw zvTv>Xe|_}s^t7R%9X(D*Vf>rhCR6|355*$$?yX|$}azG!gsz6TZ?W?8L1 zVQ}+2f^n%ceVd#zxVgTT%=F3JXD2g#vbh22!?N-_hfk3R%gXpnpWivWj&&}3jGCL^ zcMk9AvNbK*T2?hJhZUA-Iis*l%THmM7R$=C%tjelRy8eqMp@Og92#ZCE}$u^;g=1R zmCUlb;^M*0^9V%U^y4h68_&Q8AerftEnS%DlX+d+^ckOJ<#!#Y#II!~TY%tq9o?^* zUbhj;%I`XQeo<{ri?)`PwwabIqg-T}7W;gu%e2@}&G;-U)3OoqSynYIo-^65YFciF zX-gC>-{J1Jt8O6D_IDMwTd+Ym$oTklQlmS+Fh1YYuzcT^>HZ$V22gvd70mpdV64cPkph`N6TTM6CNl#%z`7ms?A zO#@SRc43|i%NWMl`vGg^9*f2zo+hg*w^@&?krJ$vio2s!txwU_5f_D`S>nU(LD~^8Foxz zzlWUx`)y%=2==eSW}^O0%ZgEc`j{Q|b8IITHdw~>tCgb+)Qy1s4c)7h0k}WEv`_Q< zPLzwfS;NQqrCb&bcI|Wn<+A6j{kCgilV$Zy*ab6^mcsT5c4=XI2m5Vd`ve<8y<~hx z!}gkfXzMcCb+Y4O58>nGQZ6UM9B-5RA@gwp>?)YgFVh5@d*kymJ(%$}_rmyV%HUPn z(=XqG(ROM24SOn>_f>Gy!M0!>$?0JKpg>7>2Rk^*kD_bQRcoEM>CpClKiS!^Kl8Ec z%a}KBvZG=1Z#=a1abd^6#@@s6E6PRPIGFDV%HyDHENo3|ZT}e`-Kf^eYYuIH>s#H4 zuwA%l{PUut+t|94u`t_5Iji&CR!Vi;~-71{eGt(!7|O8P!E@HF|_?HO5-~m_6d305x)h1~!%eQy@_6zn7F=uFbWU*qE_wu{+#0LAg7tZvvin00h* zN%IS=e3UfbR@h^(37ZdXzCD&{@x7UEquVa_iRQy&j^As1vb2|NU{mvwmfsh)8*EwF z-s~6V!EOt}B!5Rvg5Htr$QN^N$~K$QYHfZ!19Nu-YK`g5xfX0BHOg;f&e1sHH)u?I z?nUNCZ9_#3>TA#S=3HxFZVasdcU;c2#^l`KBinOhbB+x!m1Ej-T#AVG?ZoWXwq3Vv zO0_l5Ew#aaJ=2c1+rkxVeeT+BwaZrcBrS+#epbw|;Cvjq>o0tKcE$YtQGIp=ZBQSd zUBQMj=@t5$q(!F1@i%U-G}~tU&(pCibG*^(UCWMJa$T;Ug7G+Yd3e{d-{-39SMFNg zuxokyu4Uh|RqYS%T0X98`JArhE4r3%=~}+OYx(J}<=0vEx>}Zx+q?6R6Z~F>>ykas z{D-hT3VVrp?_FQX)C#w5^WOE3n78KGRkiZo^^ciPUEaIC0p`Z3&c2QJu5V&K{l3h+ z_pa|?%C4ld8n` z`uHR3y-)4)k|eW9%V?&KSC}z$JF~nm;ROnB98+y&`x6|)buUw-&G@C;nfi_+ByHWd znRg7A{ok~`4CecIyndJLKv*3|q>uB%Hjl5#uEB@Q@}qmvd|y_-eI-6^=frQdJxx8j zo6uP<+CD+h?*qm5d$3ipeX+3dp_`Wq&oo~V?Bv3(4YpFSU0CieKiPj%e(Ji*Pu5+2 zvhMPeb(deV|5SddtK}#AZ^}%TLx_ezHlG-~I5~{?t88_)qOm-6MqB{$w`T z+WusZ6KeaD{f(e)wxML7SALFDvu&iVyZqiHKHHzye!JV>qs7+i!L~mxW4GgTe_;9+ z8Z^KLv0j$X$BRW1IJkl39MT?(KI>iBDV0ui8!lv;4*}?JmF9i|xDkw)_?>Wnj8Y z-xmv;7aN(+W@LUB3U+SMc@Aw^x&QO$e&cq6`b|L#sryXFuzD_?G_j)OpLt&1~{3VP-Mu)A}e)Taw{7-0nZ^}ZSl`g zZ1=e9h%b*@`ke#a@z}17E^U4HiD|KHEx$fOrX{xzZGF#)X*s6Y&P#mz>@_eBRow!S z=4{WhWx_A!ZNDqPt|l$p7PboPfdv_d2pdG`CG^plK3uxLzmd%6%U(tIBtJhr ze3kUs{`v@6AGVRyZH&(R{t%Y^m(1^vif&hQ50bv)ahkR}gzb7Tw_kmv?fONxd+5%G zdA?9}7Zlw#p}QN_-G8~K=s2}U+M%HU;|hZ1HW zEJHY*jdn!w@wc$GF1yRG)}{BTOv|b0y36mh65j{I*!~eLjIS&M`_4zh>bCkZ>`)42 zJ9L)c{Dkvo>+b{aR@e`N9Rkbv{t>o^!EArkc6?!JI{}uqpJHo$Tn5YScLek9OD-=u zPfn&I!9Ri7{`Bz*Y4Kf&4;7sStL`^@l9UL3Zb2iX3q?Mo~tOWQ0Lbys0yx!BL{Zhtq!(#JK-pFn=| zy*S!lAMAtBnZK>1Subj)9GZX{XNPvtw*MUMD+)`TJpa zGc_&pFA>K5tp8Y%Y-`vVx6&So*YY#I`Iw*Ly8d&!)KSE(t+4&Xb<9(gt;dOU4I0`C zOjEZjd|z~q`ASCio4g%{Et_LU-n<`{Ec3PjjH2zx+mVH3-g0~?(KgT6UH(#kn`5!D z&9P{GESnZ}`x4ac$bw~Jep7cMEOq;Z?lDAas?N-(Zgl8;PjHrB#&<{2eJgaE5Rv6q zcL)VZ%Vzvsf-|5e=`p_>tY2f^_p z4^syI)Y^w~9E|rp#bl>F4kquJYkMa_+v$m1O|^XkLw#1;H= z*m|zMA8bgpA$9i=Zh-v)X8GyE?e;xbjvZ5X55f4nFJ}3v%lNh_@%;*Jd>_IrzZ#$8 z)GR;adw{UQlRd2!N}3-Gwo@>Y(RzU}<;2Na-!1G#m}P$zOpV9pY#Vv6MgAN?+gT{6 zthe98wA~11`Bhu5d8h7G)?M{H<2PYhevWbY^tql^ev?KYZxGhT$MU5OT?x~N?=Es* zSAA>`OCLA0&iY*nk=tsm-%+q^e@L1!QhUSF_N?$Rp2F0w`uGJbbz8CS@eTXGL&R)T zUQaT857tAxRW}QT;<1NnYIILCT^Z)JsMNWyGd|BlEI%eqU(ooL>e3mXI?GR8#7YjRrb*-=VrzPV{_Kgys z{VM&QP65!2I^z3XVQKp=EYmVEY&W7%EWeuO(+W%5iLkWwxT@ckC@7B~)%LrErR`}j zZP_GRUvj%WWN>pX$zsDcX6ksYdzhME%f@4wW1n7Unzmbqtz(AN7+>0YerfxwwqJ_< zi#p$@p!O4ABEX3@c#Ifu(Wmi@ta%+MpQ5Pj@A)J+RB zzAe!imm%Zx8Qs*`=kdLvv*O=8s5_LPU&pbf&SSgrEx^=rQJ3*8$U^F7XWsN(P}pGR z?|`jV(l-QVd|SY5e=N4+8&z~uvcmNFZfLh(b(ubfV>Etehkb!OIS$5pF)cE$Bc9Lr zT(67q*Lq;W%R<%Ls}0O z-Hy!v1a>P^nnI)VnL%}4(?}nEp}R8L3yaP7kJRP6SoOObE5453Qz&@*FY0_g(D#gO zPNQ-^DSIl|i~#GXvX5ZaZ)H~ynQ4)Ihn40xuYJjmg*jf@>)BaWIbPcGQ8NeO*96~( z;=AogLc^Y6YB~FEr}S}L#CH?S^3yis`xDIc)%YAQX!*%9z8)N8e5Yb?Cxh4yqERF} zJJ@AW&P36g7;GLQOWpTi=FRbGw!fN|t6&~~Yg(>`+5T!;9)=m;l5pGj&5sUluJ5wg zobxWk)b}_2nQ7{5_h04xL!Nh=wk-&ohHklNf5ta7bbBFUwnO*lqMMwRyPi9w^&NC% zsY#2+k8!YkKHvDJK)y`vXg@4an^QXf7KA=z=G||zjblEU z*F0qQHIqF9^L0i!-_eDg8n#y!b|%cc zokD|5+v9?LF^&P|?GS=_^Szvw74DmR7v^nb7c*}%<68mUKM9*%GPJq=%xqImt1x|h zvHoj)RX6JNeqFLp(d~lmn@mlIZGcO@t;=9-g);!Py73(GIr|? z`-BQgTkjj)MSO=veW;UZTiMjGd0DX>b>#MIyS$otpRINuW&4xeK=AmsW0%f;L>`ay zVSJ|9_%bci1p7B^W;FhMPmq0Z_sxDkZy4i(>T_T0WKK-claEr^scueaBHf&hiN64SrA1 ze$t+VuHVSAOsNn2dU^-uTLTMcPC0B~fnH6I{^HjxjB+Q;Z)A_9kw1Io?H>zg+KiiD zj~$r&-B}lUHb~4gBbcx$O`tAJQx^vHtlMv+Y|MP&)P)JlmW45sTG;&}ZN6A!#XSia zQuEW_R(nzSPGs*3&&9m$SLQR<-Y4CtFpnKF`{t?ZgWbPW|Ja6P2L{V)SjKlyu5R)8g@%z_HoQ_ zUgI@=_CxiX+px@g?B;hp3N+(;8#Wy}9#Lwucf&TH@zC}*);s3xTISRC7cl+a(#3rL z%I$^u&IENIb}@DCgEPL5&}}(i|2{6+Aa>}M6{lit-B8$HMsQCaX6syla31sCclDY? zWh->C3s}Du%mYU*U+BN)pX`HR-yq*< zdk*F4H$?Zs&Yx+{Z-^ereCjSl=Y8h83cCd6edae{lM%Gd`^jFY^|e}U>>LY2qOsIXI{DJevHoh$Lqm7rt2f`Gw)DzSB36i7*TZS zPAR%;&{-cph0)YI>cexr%-c6+;RZ$`aG<=Oy4TH14HM&$ujLDWZBbI zYWp}0on_^<1|}V4HMZyu51nHly36#m(9w)r&k{`E(oFsJ5z?=HQ1hnlIfD1q*DLIW zU|%cjRpxgBe2=MRs;y;o0zStuO?FAJafMyXy!ZHzVVZtlW8V9#R~7c>VD}dGHuH`x zu$=9C>i0Z?eqSl<{9yko><7&2_amn1_Z{Xf=UK34^KA7IMibme%v#FtUD!hGa25*Y zHg_;#JR7C^A>)%-9?q|Wg9+kQ$g6&z@Z-V8uLgRZX*hLg*+FFuvT@uu39Xo7_tV8z^ zwi(~F=srX@6S`!hU_)539St|xw&e4E4nSjwE7@tVl~(J&?wgFqc3Wf6-Ax?)HGZxC z(Xh7wsT+sxSZ?wyMZGiI=ssZTdE%z9)P0$i`aQg`Zw1SKj`{W4in_&^rtM+On--tT zO13}q`u&)x?Nrds|~>ki$;ET@l6nLh?yb00bUx?k4s z%SE>p^KZ{LS#y8ZPxEOifrZW)+mT6N3AGA;H;^t*0hUkzLD zyV_2xZ63?a?~b9HkEvx^b^Ano^THP+SXLaq8^5xJ2#^13P;=ZeEwY6P>b}V|nfqPy zOA~CfWtq49?kjAC&^=QahvO!1Zx*(4=O6kgPOEMP3{!V{=-8b!$Nj3?z34n=GCq&1w!f;o zwdl?a-K#LmwCYB%kbch!o%ctk?$X^+bl(r%n@nw|OxpRKJ<1+eEzjRf-+D0HY1QR3 zjOu10Ts{Bf&AVclZN^%9-N^TYuf;Sq_9J~i_-0Hq&1vdQ&?e!FO$+45Nx0 zzeh3kJ>6WgZ`-;p`Ofg?x|r|oez&kC(di?<3#<>@y|y1v@R=5wwvKa1wi2xOgQ3lL zc#^p-s2f{!wq4`%o<-_p>h3MfwrhNgQIV_gi#6r*LUuo)`O^f_<9QJq`1DfjbJj z7v^`<^Ll_je4m-m5ZK4#@Y(SkK=uXI{W0P@7G3)A-kje}zpOB?b;v$0?ESD^foa-$ zuIabb_bAMrm}z+e=6*oG_8HB`rA6m=a(s4SHKrNgu(0($!muveb3*4nU=!jwqqqP3 zoyBH+!$Gjs=!mSsvhk^NpLO!^{jShkNN#?b&!_j$MaDQuBye4)A%zHVh z`v&v+@Y^nyv%2(=_vmDMq0`3(rTq4T>Eq-m=j!8$&@GDXBj`N$TAX=*eFXaeo^P+o z)U>F36x|tX_4l)rS^pDZ2eY0iJKpzvM;Ch*oh)rNcn3ClPk(#X$0#<>wORgG(Rshv zb0Ei6Sk8Tf(FD(d)`w+$UiX`JZSF%9_M&M<=QSS%@?@y(BI)s3PIjL-h;9)wK^3oL+5(cK0!Z#%#&=jwO!(0SZ^ zlkgtk7;G ze8)xVGQLI0M8-ES@!9_J{`a!Pc^AR&gnE2XC;Jt_?}X|%*>7OJKhSX<$zFu{EzJou zG^9rQ?ep@NxMn_6fBSU* z%y5F{-L)Q9mc%)BhG&&WK! z=wl2GB5l1MBzrIFO`XRaee_busq?*A#y3UOn>zdb+GbtKwhi3^Qw`W|7rG4#+dkO) z?6A|vmtp!{HtNIpz7p|$RG8mg)bGPlAL_h@C3}h!k&MrC5ZTJ%mm+KKh28O9=X(JU zfd6KTLCx4mZPjf|Q1?})6mP>)ww{c*6n3;T7j z8KN$=wXdS>MumAFPj+`D{!FIuz&URzn6DQ z=KXC*$oKMor6K(+-X4(5+b0tdD;)?|%F!rtY8hk^6D) zJ*LjHO?A64P3AGtYYWRXUk6JcGe%lY zXKH({X@0Tje4n0az9II1=680OY39VWiEk;`;sndSkEuRnYY-k7M`V#VncJn`>%6wG z9bta|^W8Yss{10r_X?+$5w zso2W=HhX36OVsTi+n|1B>MA=9WDUwzlEN_bQY98s@%jO4_w; zu#Yf;;Q6EXUsCsHbe<=*a# zDr|n3X<37|?*2m`nU*!9{hPOi(KTs-x&KhtPD{~^K zw&%d~dvP3_WxTGp@v(gD17xQKd%7_1mtFo6_a|ZYMW}*yU-$>Huh3SVX;znM@mUxB zo`WH?O<8SAyZb8nU5Y|Z-JW5)0*vf+=)M@o+*#qh*!mreUgrH#J?-ycEXTa@sk6_u z^&jLQ+B)9B^OYlu?Se4RYi{@)X8N?va~=D9>33n~zl-hupTlhT+D=Cq>G!Fk zTa@_|vE3xvkZG=rB5Z8GMg?e__Z!uDPP`_zKP$GCQG|`{EhIo&&rvhYOJcj&WBq-0 zx+u+g%~;m^?b6dID0N7hcPU+c^WfG5=KaYYB-n?%m}%-RU|!vinG#Kh?v|qaVd#v* zwo&7Is_1?cx~UOZ_EonS3+Z=4=zNZn&7nh=^`Y&Bp}Uj?s-Z*Y^?{7AB6ite(|ElZiQ>*>&~Rm%B1)_KhJd6P_w*P3PP#CEO^Baqei z-VX})RMAZqY=PMJwH+L6pTca%#&>gJLxW95L1kLJCa7++!Wib;u(J#En4|8M!aU~4 zmWurbi_I8b*+GR(6S}(#<92^zJ1v!wY4P5Zw%ZjpeXxrQ8y4*C!o0VqZC*2Av3X`( zcJ#CZJ|2hf%|N;1nWo=Ku|Kf>5OgyWQR-d~_LKj>K1KJ;>U(}Gze_}oprj9CUeC!-P?kl#|xw&5Uh{fAIJ_Q*niLdi|pXg?M@t~ zPj+Om+X@>Cv)?;+Y?ta}_Mpp{;ciANy3ws0I zveAarolcl#k-@FmNkr-{fsJ2gaH}u&?dq-}EWgy?)=hUBj~?nx-Sxq&w^<0UbMV@N zsXw<7`^7$^vM2MHH0%bZKBMA3zxVP{LWxnu1eTBa`Fh6qSzmuuYhO9fLTeI$%-Y%=^rGK87ZMfyP>1Sge z^qH84eU=RF^0jVihAkMen~SEB+hlP6F1L7Z$Q^^a$e_=V)*b5?4efu!PC`8WyNtG~ zA?>C9nR%G((#5(OXm4$ny~D-~MAJKrJ!JfbRoRT43&T^yvACBVUjD*nj1MEVhV?d) z^)EF0y0&c5l7e9?mxY<@nwEX-N&e=lvY8jJ5%^p|{svds;04Q?W>{v*M&^vuDQZQH zscTv_g5J8OE1A_#vyWN=vDe1`xi;e-n0LQb**b-Jy?h*C-AOREkhbmg=p3VPD$EKr zKF5&W2b<8v9FrkSzf*-RUFqgNYPDUbi)kxM+gY%kWApy^=Ia}Wj5w51Me4ky`lQ>K1*f#kZH@d z)x6JdeL9z~F`w*Wd^CM#rpYd4eiSIqRFGW&*Jqnn8ZmnpLLH9D^y znBUZCt1g*+8o$f95BuM@rC^v?zO>d3wsOZH9zk!W}5#5GcEf@dojLu2wtQ6abfSm z%*V5Z{XN*6QRmuvjz1M;e<5}5{@Ik)+1QR%Z`xp6yDe?r7MRL~dJAr;i(8cfnGpk7r;% zEKFPD(^j2zXFgu%0=0FNOr77Idl)t~^Xl~Bcjvq>oH~81c`AMSE?eW%R^3!+^f8Ky z)@OvROdo!)?F(eUGM4GX@3rM~r!sw9&c*F1qK?wm__Wmr*=ems@cVwtGW920fM9*> z9?K-DT^|QAUv2%?ptdBjv0a|2-#vW0uoZ&2ZKck0FLj>hW_+W9jfyfbEn5crR$*Jg zOy3!>DVeY7%Q0!%ntt2MB~gB|JqWfJ-`|ja_k``lO^Npk`v%PPOT%6}DfncY@h2*CO~0!K@G20tDODzD&(SZCB%2)<@d@_;;L*}z4$*d3AmavS^`j8zTWp8}ehsZ}jb=U7ndqo(hfqO(41 z_r4=4ZTEoL?!B&<%=&l?-QI;+ANn0znDrsMtT5}twA=@?K5AO(F)Hh0nIQvyvp%@w z)uhF3W-Wr>Da`tiSs!kLW0+E0&9%;FdE*E7lvp!^-7G{0O z_Jw79)`!e-v&pOv+53fAAEs|+D%bjOUzF+Vg{7_a;XZ=mYBTG@eZ<3sSsyE%#Wr1- z^`YM(rL4XgY~jMJ57V+f%=)Nl@jH&0maGr&StZN*crO@}=6wVn8~0(}pY1olGru$Q z+NQ2KP8a6*5!uATHibD(7~hs*yIs_W%yHcw8~^qn*wN@buFi^4 zrfAL$gO2;F8;R_Z3jmPBXXeqMBo2AeI) zPutmpZC9B6NNs;nnCGIh`Pflqez^?QusfrVIUn)4qfz&-!t$P*-xSc+e%E8<{datG zEyq~Meh>4Ta5oYMe~r#@jeZmEPC(kKTMwo#*^97mz&vN#V{swys_GDpygssQMeo2(Qd2_78d3>Yq9m-(8LnelZqQZR{2>xzg%=)JJ9dPg*^|mTrR?4#`pVRixsBs9{Lwm_X5m5M?D{UCD`)OUU1c% zV|r}0uc{9j&9OE9(Ejo5m^5X*kL%GL%v6o#zcImgQ=h`rGNEa<-%Wi9^BLbZ%n!YP zaBF-VAGP0}px?<^NZpr1w;0Si(zo^MG4r6p776ypV!LD5K0rdOqiQ=>$?r~~vpb4OWe%Vyd-9=4E`$j^Sp;RN5OxPY1BCmTbM%}tqN z-l4k{U9!}jjLsMJT+~ITqjVj*l#CT(E7U4D@0D+hO_pwk=Xf+pmnqu^ZJ!-39~-jeU|yH7=wv%Gv&5YJ-y==d$Bge> za37O?zejv)QEjgjHU_pKww{xx&g(Af+;=3iEz5EojDAmm>0`yB^IE>&z07+F>U?j3 zw%%XM_|Ap-euWPUJ3n;Z%T3({F!Od)N%N(!_wlh#(M^Q;-ibG19-s8;n zw&R$l54U&U;lQQVhV^2{aJuGMi6xl#*GCvZ@VSj8nQGh1^jUOMFW0}n#7(1lp6QF^ zYb~a!dk&rNjohrTKLqrLD92>SRw)6{u>YuWz-=C;*G$b8WCZtJ{$YJ6S;bAMgq8(z}q zHC5xY4BQd-5i-72i*8$VewQxK;f>F8BH4F}kMrTC`P{;6PnL_<@-iP=vFvyFUWZw4 z#y2l)<;i%zM`26CUWYvcW46(yk0}Ak(#JJu(#J-u)W`Nrt+(o9p~BLKdTnvla+~*D z@I>bQk%ad7@JY<4ZWubx``+ndyMJj=2b&6=&q}^Zi&rqNH)cAH?27PeW~o)D}TonyN# z=YyE{H=K~=d~8GdS(fw7FrsO6S?KBrevkV$I^wRj~!tovBQVg zF_NW^GhvpCK5l3J+?gh8e+N=_2h6g+r08U?pp#95W;TLlejRo0yJs@Kyv}kD%0s9v=6+P$4+~o(nESP~T|e02g>4=zugja3ZG%l4ZehOQP`HcwWH>^Ex<7$3A!xQ$*HNdjN-$P%h|JO5| z*L2FQ~hMt}Y8%nJK5_T?82(X33fFTZYK*_VF}W_!{0yV%-q->oo9 z)PDBZ!j24aH%-_)hHhhkgnQkHd;btyYK{AOLstT)q=btxMMt92>MI?B3~ z*>BV~>r!@Nu&hg&_3@wTQeBpP)}`#Uh%f6>=CMq_doZ;f$UHZceXB6*NS1wIb(3Nq z$7@}xJ0Di-QugDB?-zpx{9YBz`%k82S9HerKdDRmFKK%gwzV#e&$O72tV`Ji!Llx8 zKMZzxiEjeTeEhVqOG0N~D*av>%xx^$Wx-x7%=TNny`0 zU+c|$cppY~SkYxUfB8SKYglhxI>t8Bauf5lF7=Vye%7VTzLb6+h`L-7_B+C196Z-% zYJ9S%2#zUVzl-^q%=d2D|GvJV%r8z@g7EA*{rkjZ zBVfL3?u(IM)Auex+i$|iPRG04a+^{2Ug)ksXI<(erDSZ_4nCe5<5f{ici`^-;Vi+W;;dB?r(30>@2bTZ4p_|7Hx9Ki!!Z1`6F%zEPz zOS8{j5%x^cox{9s=+?r{V_uzQn?8yIXTiF3`^tM;yTB$7_G_lz+u9Xo|5=@N?em7mz%n1k=W~C? zH&y6-X3*#U9)h`DYI_4g+xxn7K9i@e#y65OFh1+jav4IoY!3T-(Jcnw8MZ8iVxM2# z6U^@m`$8#a+m<@V)vKwx9M3_t&H05o@1fQ~V+sFaT@BTvnccM+R>_FIYu+5lHc2MZ{E$raXjVa9QAKGRe8K3X`)yGeY&SzEC z{i?9TLic)MhX-S`Zl~plu${fI?}cuK!p4Md?ZS=><~EplJ1T7R{KGUK9lCE9-7%p% zsj#uZJg#PZjx{xJHx_nm=zde!aiM#?u<^nES(szkEk94<)5i&+%j;66`NUu=gpMd$ zGYsJzV8$U$`_xu82kgmd`MxOg$>xOl49sE(FmJBK9m&*ZV1Cx6b6kqLwDnyA4^KaY zaSsD*!SKPQv$k&0@ZtW&eKCuz^s!%;P9N&j;HnwFeL86#gO6nIyD!GCW$M0I-N*bh zZ`YT!%ol$DfSygF!|!XKqqC1x)91ap%&+m8KI2O^TljGNz5CZ{%j+sSblT=PebYQs z*e*n&a6zQQ_BJXueW=q`oy_h3TeDMd3l44WT_-yLcF>|j+wag)cM8mV;)_K&%g%)v zpZEIG_JYve6nRs33GBROhqiuJ*rmZ9DeSUf&lPrgu(u1lB3O=V*2lzPR9!nQKZo5s zf@jz%18|eywVB>bS}x##JSpaOV0@`tpN26hX8WtUZc+?ca~;>|EuZ}R-@}+1{C?#9UCU2*Ex#Virql0ne%!S@#XtMw%k{&% zmKW_>Ub$;|!>;A+yOzJ+wR~{b@^M|u=X5P!(Y1U_*Yf>c%TISLzuvX{ao6$`e6Q59 zZ0EmgdC{)rm18-}e?ykN5L`{C=QEVqZT@<~ z|LkXKS|bb zCh;@wN&I?YlW;ky{A)ewSjM>Ov%is_6N~%VU6Id2xQuJrW5d)w+A{?Ek4G>~-O|jf zJDaIdR^9PMwt72No#%6Y*CYE~>b^$sI@H4GJT9A-CkXn@`{3$!BABLJZd*#f?psXX9}2sXdF$Nsw$$AmI!<}p>=syeo&OxxUFW}m{Wo>~ zOLYHDovZ7v^Lv8*v82zk>aOz(f_ZL}d7Bjbe&|jqy32#*JptS4#9(g~-QmG%osSFV z*e?Cf#`4~DKK!OVcX8%e|;<2J;AOly1D3(d>!5Wh0O~yzT7VLv3%&<-ZH)w zL-)0c$bju(!7eWBd%>}0`P}VH*lC+%q3$Xy$0@y5Y{!S~Nb1sKQMH}Eu(ahgq{$m*%`wk0 z+b1*ck1Vy=y|!kA9mCWzRo6#25Oyt7s-V%$%T%5FsML{#W(@cPOew;S_--${J($0p z8!(?TB{|JG4At1`A-+L4%=o?z8-vc{uiZGBZR1a!*Su1<4g8B&_cZmAY)RNs*YvdB zE;^63vRPu=XH|2JUFKM#w6zRnXBV~)?1!+2VAi>5xrp$4*iVbjcCh8Oyvvw&HACnw zXL>Sh#%OE$weNG2X)bJa*hA?4Uf8<9_KP;Dt=r>wv3;+w&0wEWRzCNg`S>>MJvtzN zV4Cc3=8xNmX92p{m6Ko(PlElWiyc8cGj7bcAedU`rtf*eEa>dFk(`D-&2(khu}m{9 z-(z0eQA{n*YI_{Z*10TgCorG3W0=?0a`arZ+Fr=AeYk3SE6ZtnB=g!n$<#JqZM|+Z zU9j}~YnId2{_Eo#4sPCQH7s<-^B&B0T6LDeFqqd?^pWv>vFJ{OuS!~$FYFZ9jE z9nm)LA!#i=q_rfC%Jj+H=g3YhY|mhC73Mxi-KI3Yw0#G(;|4=oKPv1m!QL+H-C%1{ zz}ni5&Li)pZyg$1GVis^PAcreU{4kHSJ)!U_OzxYBFo4&y(=5kvvj0}z%o7_TWaFl zJ($`ZU@uT$?xWPn`e63G-(a4o8+JQW&$n>X*6obWX9QL+YL+5sGKAs@xcP`dt-n^gWefqByHkx^L z-z@A~!OTzEdQU*zFAK9D>GJ?j7dD3Zjq$N|v|ZEUHFs^dE9|^rKP>DA!G2Vj_ek{N z^B0+x2{7yJ<-#t3{TSVf(Z=^ zrbYIhVCzL%WMhKeRM@e>7Ak&E4)*=R&I^|BFfqOhgB=*hE!h>pUM=j}VB6AR$n@P5 z?B2qD8*JX#E{*T`VEJBj*{i|+U36~+%Xgrw`)jZlsN?kek6`(}b9LV5wM=iPk*02n zV2iNfCYwIk8HLRn?32RWri{<;B&4m^Fl0kwAE96G8_M=6%=`1QXM#~YtzT1Le|w6t z_0+FF*_klMl{-GgpUh`t99RBnv;*1GVap?M&AznS_C@{5ej7UPV^DP+K3*&=eN0~B zOLjUs^J{$1Mts+zqxd`HD=cmQS<<4vkI2W~B!nVt`mM{be!7Rb{}Am;A1|R>4wl~> zlDX~4=4Bz%@+nN)U&OIO-M@p~TiCkz7=qs`qg|=nA^h$TZAj+0O5@wDu-SsWI`x3x zd0|sL%|2|J0X8^vAC~%^7B)A!5gY^9eKh-b?<HA}*U~1lEj$iP2 zV^4i zq&~(M<~M3(&lTpgo3cfstc-6|uLrheT@q;F&o*Z%J5 z|7Mi7vUOpz((;=oXeP|&g-17@iBle5-)#EzkfVa&j<5;G}@~B`(^z) z_XjectNM74!L9Q!bURpuuqr{@AHdSbHeu_#5!sYFY^S2FyFaM5Q^TsQ>C={`)sem# zx^yp{(XUHeuVu{2$7g(AA=!?w=O}{}V!vTNz8vY>5$1V7&71oY&;4rpuJ5uv@w}le zZK;yx9CRn9p4aAkj*O2}x5n@7#df=3>rr?#%O-CJGqwEo>|(}O**@rOLsy_%f%#1d z13x0}&q}lJNZ!z9foI+mG9^j*>y5*Q)zthfkM_@k;MZPB(`!KU@3@$yu>FlBw2i~F zhRJ%F=Qq-S!J2s%oA`sJuVyh=Otg$&uhYQIyvzO~FC)_V=le)vvr$EZ~ub-+pEVk%(m|K zcr*F&8J@japUl2v(|4fK&91uaJN&A!JP!Xo+N-*MgzW+xBh6#AU8@{7JxA2X4-lxS zx;qO?AFsnQzGPlI%``g}#rU2iE)Go{@!f&nWNDl41kvxx$^O&WIHt)wCsKDo97kkl!91?NUzp>q)a@I`2X#JQC_8rMfwT;P zT}$59WZTO0O#?H1tCci+eO%i;W4~{FK7(gJVLIX)&a(BH{e(q|kGoi5J2;t>4Sjgd zaTEpqKN*Lf_i3~}8rwP!U3NUobEo5&PanJ%v|&Fi?8IOf7j`ntdqMXUc6#XUE9{J5 zuN1~B7#kmN7Unet&okYxQ*|BZnH#|}eY}3PvCV5A=HuL8yA|CZgZaEc+P)U-{KC!) zcF=!d-b?WO_U}b^3C#1yyq;-Vu7FuCt5MJC_bQmrr|11db&rLuea_U~%Dm_JFBaQ} zVAhfSywv%wO4)^l{RZYa>V-_z&4v%(b-cwi{o|flY}k6Fe>K=@ET?WA_801AEw+Ec zR^81-H=6aogVp;(QwF;?%0<7AVS6~bbIFHoUUoa{y=Ro;7iCX{?mcwwrmOC)Cd4sdvP8chPyCVtn~|DLNm7^!)?BW6G*#4CF54X@1yKFx$(rgog;; zUwgW+$6($gW9Vet?>wv@v>^BQV0Oh!o7Z8qow+dgx7sdTY&XDmLkwn(Hq?t|U)Z}# z(FdcBvkdkNwnfqT9O}~4(e8z94YN!aigsXpd%?EH$4tcMwcIZfMiDHlrC{umJIZS5 z@H;8oz1zgyl@%=GdAy?-gWw8O?gzLEaZIeeMsh+K=)_ zm$uu(=AjbpqcPj~xDp@c?TDh=mX(XF$n}`w*YDw7vl81(vAry8-DWbrD}v>C1=Heq zzb)q*cxSKdt1!#TtGv#u?bpy*R`$`-b{Cjs;I-XklheO3&9*ateS}PNZ9`L`)356=@9?`0 z%NgI9q1zai?IqKEnXu`AIpW0aj@?8a%|D974ba+ z%l%8n_h`|rgKi=#{#4k;;bSwH`xn!a`Ixno-)7-sFuGx(OCRn#GR>pVncwva+a9*v zUOX>Z*jHh0zkev~Fqr$MygoHQe#XPBx7{Y|Z!e}V{q7D+zbB$wgZRe6tWRy9kM?|a z(VdLW`t=%D_x|OI(0R{}?o8_=IveLQ)km_ioS0WOFYA}xi|=I>olIS2wtwUMThYnX zRmLXXS{0qwPtvbUU1dwbX1b-Pd9Km^i{UP$ zY%j7~37f$@=cvs1riW!(*qj@`&G|*xrr({5Zkf<|Z^rgg(|1nMxjkBbIey7B%k*2B z`*HG#to>Oxw!5rfwbms_10eb~A00QJl@Q zoW2)iUl;fhMf=?&TykxGvV1SdgD{fa=+0*9wfLz4$30k)eS9r^JOpza&^F)a@^oS8V>WiCwu$OvRAK33OIY>c`&admY}@dA89QCuN%i|y zVd-~i`mwgz>UYn=(r zf7)JxNT2%7a+$KQOy9;ZqG@zl=k8~dW%^EmrH`6E+e`KFbkUg>-<4!q$a160Zv@;5 zOWRD#?C5PT#+PZ?zOYP-$9;d*ug?`F%lOs;xPPhf4WUqyWqdoOAK#vJX0Fb~9mbEWtA~&8vhD3$TNXc_e)t=`t=_df`{DQT z^sQG~9gDkmE>Zwhymn*tdH*JB^%QY$=i+>m4eMOnvDljI)Vh|NCUvoQ@(ywDCNxW$u*;RXpaEj?x(O*AX50?OZ#2ydARkZ}|8->*5^UYsb{J!^a;} z7hA2h+VM0qw4{OG$kxb#1?FsTOEBGw>UegY{&tn@NZ3Ro%W)g(e6Og_Q(s?flU-NX zchULG`?Zr`*T77%@p&KRK75SpV$TMvX}Nie&a@m6>Elq}^m%K1_EFjWwtX0%EaTJG z__R%SV8nMdY}#UL`c5i3$Mu@Gv0XZSRGslzR>oI-{2IS9`z6Z}=ti{Ofw>P%-O-Vj z1E@W^p&j}70<7w$7}b9rZ`O$KJH+Gn`8MdXH6PX1{;&1xzQ%n_Ex$9mn0b?>Uu`YF zW|=BJKiwC;pG%mv=<*x@I04{`HkJ*^2GI_V;vNH& zd6oGF`Zby6`C#e8=Uz?o4D$~#ui5GMYIL@tn&wMj9;d3`C%WR(cI*NJ{hCa3AI#%c zwVepdv@pc6so&9y4KT<2Y)5=|(}p}>>LKh$1lI4ui}&kDZp(8}`;S{PZ+x;BVD=l9 z#8x}~X1`&fXp`zzW!`V?%s>Y)ZDoI=5mvTh=*}EAppy-~YjCSFuZ2m4>ke;vyIN@ytVCvrES$& zCdQXKpOHx2{zP);PX^wvpw2$xk6`18*Zq*}Fy_~Q*_Tb*sMENiY#l##6uQ$%FvZ%$m+bqn^gE9DzCv2orv50_MmHLNmcfhBHuT{!V5*;T41>)W zx>G~fS9CSLnM3EZXouos0y_6Y#&<33`0Hphu&T3M)MZ-Ic1GHy`=M$}2d+b>t-8$H z@uYca(rkOq{gBrf%-f}foe%pGx;w%a_s#odz4-bY=8aGG4)MtrMW5^+FweP$VGC~B zYMyg_1EXYlUUDVO_G~zt;Q77VV6t;yp5MO(OCSHlhxMo|O%yw06XNY}?>|dls+w;1ZwldpQ zwfzKUJCjXE1*-dm{gCHjRd>+zfMBWHn}*A6)ehb3Fw4(2J&JJrjXkXki7456uumCO z#i750-SU%8wr1!KDLUB)=qmdH%Y?tKyxAP^t~LXma?AwcN8h~$6>M2difqJjYgMMbaz z3Z76EL3#`hcB==Un)^sN8R2e;tB}&#Lq_Ivy9d z!g;sKGKR6t7hvK!N{(TgUq7(Rpwk$qt}Q0Ef&OkVS#wN0fB2NdGui2w*nZxO9T(kl z=+M+Y-P;m>)cqm448#k!gEqelB!;N_Q*_UPq5J!EdVQ9PkPSkI`Vf2fM(qiD0Y1 z>Z4CgHWg=KZi4EE| z#6(+;J=m=HY*!ejwtXemXv=*I+KxtSVAc6-dHzwE+BTOMqHPAI6_1n-;TCwW4V3X7 zd&{^l^%`^oQE#>tb!608)(q@-=-R_6R*83A`W?)hKUz98N8*aM)X|nY&94<0>(K&n z#qFSNKfX6WnbzZOi9hDoLh?IPwjX32Fm;9B{f2R0ls-nFzT9uOKB^)nm8p*r5~s{B zBDRHc3_-?yB-SGqamwwO%`XNzWt!hcW6OP3+UoN)%#ZeDb0yZW>b>XUXJSW`+c|zX zTaT$e*ksJveq^IDQTGsH1Aji0(mQn5bJ)IQyJ5--$UFS^MPp}BlIz8gdRP8Z!PXnQn+Pp8k!F~1u{mxMM& zxAy4{%6g+N7t_nATXX0bLu5~4VtqTy`XHN)>0_`rP20}`qwU9FRq)-~{s@*VY%Av7 zp<5{93w1YP`V;I+!xn;Z9c@QJs^dF#x-Q?9v4re)Of1WbILBC1bn2rGoN8OyGV6H; z)iptZRX0KMOTrFeoj`sEz^KEj52a!{Fh9=gJId0*n%@#v^qZ*EHNtcPH%za_Ty>2_ z_o87aKSO5KBovH#M? zHp4oJ?zmxHgt233nY)TD&#fwBpQew&hOu9h={YyHUw5&cYIHqBx52QU!k#d!m)O2< zSZ~plL*`nREMb)m>npZ=Moe}6M0crS1BCIpHq{LjTYX0flDu~+ux@6HyAby31s&gHeA>?!$yFe58V;Na9HZGDwwN}^Tjq|7_SA= zR$~Z@AwE+@zxLe)7YchFbIorwzSH(s!?-_A+xoITuo${X*igg9gVC1HkZXPyi|$Fo zc-+JMJ~xbGKW&qxO|j@*Q>3n|VLYB8yTmXayU=!pVLW!Bj_1m>EIcM4J7yU7|7n|U z#(VDnQ+KXm+}9_YV;GM$X#0d=Jl3G@Bg1A0D{HnDJl3FX2g7njH`cJ3!sZz^OKkbO zFj}|9sMEA=G2S^aG@ZBIW8D3CMoiKEJmvE_`~fyozWi#Mc8N%SctxnU4Ym2%ck}d@{Pf;>wm}cDrSSV9Y}GHHTV0BqgpV6` zw%GC=R@fx@%8~)bZ8H68`yBw&{P=7v>-#+#h36=2`CbN7-5~MNC&BG=+59d6Q{52B z?|L*I&r#U?dV#4fTk_ih#&Z-lzpssM7<5z7276>bg4;1(W8QjOe5e<`^TTZs$3*^) zHOFbT9a$Q_T=WvoAsE(37~_v+VSW+G?|Cqm!{+w_7*?k*zc|E|GR^Nwi8bcO>!vIp zV~Me5^XmkL=JMso>o3YQKOG~OUzX(e2Me;6;jpBL4HX|BBi6XjZ+#pDW31USHqYC!HYfWXb7f70buzjPVeC7qYbs2i;lg65l`w8RRM%QqjA4Ao2K~kw#{Fip zQigR97H3#TVF{*gorG;P+X`G#^YV)qT_VcY0MnCrsIdd)EFW1qrg%JT^qOIf@clzP zl(fsR#-fWwzG|BxOvgXw$JnPWV_0>(c0wOqFUojqKsLxQ9vje>=YCb!Ms#-@)=t<1 zhOthxec3P`FVM%ghVh&N+0TZZF1A%nTk&{-x`<&s-Y4TdR9e1>*p4@>yXbiRUUfZ0 zx7M(pqI=Y^UZT_cM%bp@4$<#nqw6C&ea9qqXN#_y^nJ2^qHAwhf6?_djK>gcKi09X?qPO+8z?WWLFF0d-}Mo#ms9f<~IQg=w9CO^hnHk->mK@ zTHVjc51SC5uDpx~^f3h!>#yK?7PCxkan*he`ug#CwG%E&l3D|BW2Xv`m+V(dijrHL3bIRrmRm=>9@cz z_Eoai4LeV4j~I5o=y+eg`d~kzZP>62#a7R&upXmDmt%BeMHe;fBGKu2721v$_N>ue zBDOyncB$x&8+N(qY9OGr%#%dd+OWx@8*UiK60Q$>@4_r$i;a%#LbQQpJXgx|Dmpf? z9y7%@L&g$iw6*L;=-8&bca~-5nDrLc!#%k1{}y~#_BPlRU`q_!A-a6S-VxpNhP^Ag zpACCY*dKS$?i!Lm2Mct3W8X3lY8MeVl!+6e%J}xrsnCS8hJ1)AlhW#nJ zLc`dW%<(dL47*Eg`Q8$3gL_2xmSL-foiyw|v27*$ zAgsp&qT@AW&2Nn`dk@Q6vE5;G>qYmsVH<=sK_F{>kBIGghCL>_1%_=D_Jm=N3;V#Z zCxrcO*ptF)VSh;dZUSRFpKTb&=T*3fZsU}(OJ?Jgu}fy-l(G8>n2pn1VKz=@imi>) zS)#LXI!AOiPUi`;amxKQ`n7SoKy)@vxxdCT+c;e$wl+=|i_XUBQeieumx-;7(-oq# zak@&FjZ^LuvdlJ4?-ren(|d*4IL#AV8>jb+&c^A3!fc#AB(^(DOmg3m?PBAU+etDT zr`%6unQfeMACEd4r;J@P8>ft2G8?CiT{0V|j9oGtr%!>=uf{2co=|0U&b5c!b#yHH z?#a3c%ZzdAszS$mj@x6-<(ioEo@1^TWqQx?J}?Xko{nPRmVw#sP3dych#s1M#t zOdseVdMbA1N#H0mkxj()vDUnEEIH(|T|nvQ0lk+}95H$dbN*>Ui(z z?v47gEOkYKMa$L0$23-ajq8SC1Df+_!KLVELb{)ql-6HhP~{p~m{vu(T3bdXOc? z{?o_8a{pwBrB21BYnI-8VQg;L`!cW?&v7g%#;_t?v8=>zcb6*&Ga(XFoV>6E78hH? z(-o_5p07lfacebhOXtqZ9)pZ&qkY0#0i~=_^xat7~gr8 ziH*VkE_+;TFEqCQDSJX}rx@G+lx>3TEhw`-ufn=*mHhbr1+547!CAKg!+5@f?2~_C zA3|55wYw&z`5h3(>uAb86UOV{%6M!}9}oOD7_SY}R-cJs-AZD-#zWnk#z$#kyA9(r zmDGK07~74k6gDziWkWHD*b>9u#CO_mGHko(-ZG5esr%kA>@s>R8D-b9V3*7*ANP%wy(7A_40~5} zBMjRqx^afRC%Sot?GoL3!`>I&ONQ+h_JLs^h%L_%Y56`BoxWFyZNEo!ZL#iEw^!IO z!}f{orH1Vn-6F#di0(nduv_Z2-$uhe7MC$SZwvZV9f7`=-xKEFGTmLuvXNe&Bun_Idb|X!n?N&ok@|Fuw1VzO)T^toR;m^9}2Y?>~WUH;mW+QhH;( zqwRT&R~=JBd>;a5dR~NW#otUH8+N}psy-e7?6yw1zG>pfihrqTP#`D2k zZ@hO&ZFvs^^V54@==Y%Hw;Od--DohDPp|1xHwdgX>hTQ@u2t6!jO(M~zp$Rr^@r^P zMmJFM+hiE8@i2xeW3E2x;5+MaXSrh55RB_wp9f+2>Va{czbHDaX74%|uW59^cjia- z2PU$ShW#mQfnk5)JFmk$ZP?%Vo(FcsuoI#?W*A&~x`q;K^h@W=kM~??Sz_@0U9gdc z#o{}C@IFn|l@hkdusD3D?Ha@4Mfaj%>~HkTYbu&w8DSg)l$FJI`qi-*i{5WylId7X zRu2D|AJ>7}mIq^5*e8@F3S-%r%VX zO33W}x3$4|-A=EOV9~q3g>0*_<@qAA!@^2KcN`P1hhRwc{E{)o$tD=a7$;k87-O8* zb+{d7nQ6-yPXc3`DPxRN*T^u&ICU2q#u%qgW0(0c#xue0F*?RLZFxMPJ{aRtDeeMbUgoVFadRF@#k?nf}jy?PiOW1MA~XBcCg z>~6yty7y_#%bHaFvd99D8m@zw7t?W#yEBJ4P%Vc?`p#s z<766Z^vf8ht;QM|W1Q@;v1N?Y_Jm=Kah9dJtRvbo#>rY4#BA7b$=RL#yE9)d`TT+oVr#ft{CI= zn`IbdoVp7QV~jJu8HO>&$(9(#80YgNge(e2+ETM|F*%<2!>pgP|Eb-DJ%9-tI0&mnr%E4u)MtUw+4puDj&N zeJ|{W`|_(R@xn3>fR67?=Kh_Q$TY1=pnI{VHYYW_qhXO0( zvmA$^n+vA4(_wpkS3Lh_*n?nfmmIWTCFX@m+lBWn0bWezm z*9NNubo@OD&F^>USl>@kPGx+qlg|tfz~H5f&mgi5wi;FqjAcFyhTU0TnU5G<4d__r zcr^TJfwJ(uJL;p3_~7r7D;tRN&4%Bv!Ro-4>*yOCaPU3v-xyt8*izR5``+~ex|Xs( zPTOYCvA%DZw%;Ia^%r#1qBYVrqhEl?N#mxH0ozOqa-w!C+Yb<=Z#EFalsTwAD7?zAy9RGgLedwfS`eW8B;P zG9|{D-!-rug8cZ5JkO8uc&Z~9eSBhcY$N)Jph0<@YklyYZ;X5EgU=ah`Dj}W`O%hf zPupgg7Ej0dKcnNmQQSD(du|xtcSpZGc4ypMznj78f?2;$2W;t=wqdbVzb_lzpYV~_ z9_z(0Zac>f!|}NEEw)wJQmFfdIF2`r+tY_G!ud`)pNQ`5-9MK(9PjAHceVl9a!mZK zG;XUb}D|5P50qgmW5(_jl?P0L`*Dmph??TLx)!spi2wh0)2lYOUQ2s5uudA>?@mw<5{%{D9w#&z_) zVY9)w&fCGE+MW(p1_x@p1C04uHdJ)$F<7ZB8S_(yDu&W9asOWT<;ggP@!0fJ%xO#3 z6cdj%elV;VzEj8jS=BWc9rwqSaU7>^uwku)jWCR{OCM7WYb&}9hN0Vg`8{D+N3qqu z#WHsiT{-D9WL<>mIW02m&Uk+N8y&|EmU)O_5z$?3Sa;DaG^~f{^xO!2oGH4kM#mUp zeGeFRmgve$|D|njVabMNiEUfM&K6ycVf}<%Y}f#?ooCoNqI=S?LBjYhEnS!AitTrX zWsB|?!!Qhcb<_8mupT2s*DkI&zw<>m(Xf%C)3J%R9P8Lte2!7eGFo&`88%jQ?;AD_ zj4|FCbJ{X)dF=J{JMO#+7DKFmLrkx2$Nk!vtL_MNjdA1BD#RMTdb$pxI~~mGW*|T6 z;M&vOB0Ak4qTer&$ynrf2Id&rys|LAd0^eaG`}zLoqoT;9K)E;?-HZ?3g4^W86O&p zw#V?~>DX6U4?S+AU*2c@4)R+s>xhioQ2O9+&2da)8))5dO01|XypBTK1Pq2+KE8{D z^;ijpT}WR&9x}Sx(9yP?jP3MWS=cPYQoz^-Jh!ht_*~PqsM|Y+ai5H3=6zY!0%g7d zOl|p0Id!wqcpUF--I8Uyz_PRx-E&|Z@2&26qw6HPsR+i}0bLa^_1hV`K`8U}VBF84 z4~{Qv13p)(I`(h2-)^w5=rj%rjgHTvw`9X7|F?kmg_1G+s%hfS)dYlg~l|K8@u zcQI@E9v9tZV2pdK8)0-$itZ&a?&nw?k99P^r$onnSMKLn-M2=!Np#(?o*DO6#~9K4 zHj8d17~|gRCK=t+qALJn+*{qFM)!>9%3$R(?yc@eqkC3#Ja@ymx4MpCTE6E*w*o92 z(CParX#2eA_?vb01G;S{zZXPT3u8`NK*#qhsNWYwcRpBpK-W)nY_H3ZH_!WI;X7@~ zCWDpgi}Oo{T?xkX2iJpPHHC68ai50gf~I4xwpT;P^9PTB;j5>cj5*H*J!*8*kXRQ! zc+N^~*&g)K5e!3{&&T;jw_bd_28N--=R?nxvK~*1j@LyoB=~gP9;x3KpgRL)nS}h{ z-fM&2=(Oj8J#BQaKsOmouc^}q&#O_V*DA@dDe|sQ4=Yvd<15isz+C+f!Fu4e#nTKs zhVT3xz%z|4*<~0k$x@Ji156iSS_0M?Y3v_qm=LV4lJO}lc$&bG~@I3kz1XI8KJx%(ZZWw>Z;A-qdzhKw}_?u}oi{b>6Nbd8}~Z}Q{5bQV|v%B1;i0UHm-_W~*#fQ(s|YY@!J zhJx`O`41X43XJ93gbje|c#k*lci&jW^%*P{y*oP(Om$n3!1Dc&R?K*=oOPRkft}kF z)cz^#JhOGqSa{#Y{sgD~Vo{h4sL;xt81;%yWq-HTYAZ$1~hw7Gt@pl4lM1U*f zvnDKald#*SV6o^qg*Aq0nLh_(|DaCGTtBs#X_-^O)CaHK@^=E})^}qV+kOuI@pl3? zn{~u{0a=#k8oEAd%hJ&>Ez1-z{Q1iAxM5nBjbQQ6S-;<4!^85O3C?|oJvX@XVEF2t z537zj&!6%*Sap^0y)-r`w_uKhM>j<32_m==NfcZsX~&YCPQ=m}`EFk#^9f zqhQ<*>w$@58S~TgTr3~LF4Pyg3D9vrjJjHwsMBlA)G?OEK(`(`?uSuV8xwV_!PGCp zDKrf_-4CO#j_5uyI<^7NG3tI8bzJw%kN1>ler$ua&`knkTT)j~bmNSUZSW#=9Lv~7 z)P*rIzcoh3Hh3Sp@4;Ai>QY6=V@35_3+!v?_*@n1L|uK+H3U;#ZLk<@Fu2dfvQpPT zbmNSUZBPTc$G}(y>JXl;d`8DMXbIi-V9c93#v$u**yz{>y`bZ{KH5;n{T=EWf@%4} zU_5`%-`?eS>ac0^bmNSUZEy{Ao51Reu9@i886DFWLC2s^6J2xBePeVDz#fFIFLW#y z{k9O@>0nwu=J6bKtH8MJr4G9RUioeYW1I4t+kf~ee=1#Gvq4Ns>=AoPiJC_A%c7-HBvJE8X zb7h-PK*C)9Mbi1-C7rVVHJ45k{#|m}ze-v`5{#D;YGftbljB1{$)*3AOVX)Ym)W^b zt3I*5vXtZ~Afcg@Mb{_$T@&C7V=)d!Ym*|ALs%<@l~TjY z#XS557lK*YWU$|npB`&7KVHA;4js?YsBSJ;-Q4(49gG#+E>YKAbh=+oMji8`PHlN# z8g20!Xz%#P+CBwlb+n~U+3jL`7#q37fZs@hUq@T&)b<{h<))ZWYpiGNc6;OJ0Mwmr zFd9sCc~aSO7ny73i?b-ZtcKJGH?U17&%pOkgmCAJZ4_|!)sSTD4}mDpiWc1Uc; z8FoK3oVMD);`BA5~V`0nVl_uCwSw@{Qj_>DS;y&{<%&8+g z7ZZ;!uEPSCkyX+0#q|KHE6Em{bno}TcpRxZWjq(g5rX;E!goHy%5zAn%LeD~hOv$% zF@(8iy9SxiR`01p7T&q|X|UDzL<&_e)&#Bmbt*_t^=pv>KHew z;k)&lXqft~BjXEoT-UTcAB_8=)^?y_YCGE4J_0@C^V&P&WQ11n037o zQ-4f+N9z*Il?}%CirsKs9&@#Q9^d)C*gg;;OgvlmH`?kk5q-QUy549ctWKZq0x-?5 zKy;U&f1n9{x(Q&adj)C7P>(MHjAbEXe`7tgEcz@K%Yr8H%DfKoTp^%aFELKtJECKM zuN2TNmYAe&H>N6hL17y(Y*xHB<<9GbINUcNaZ23>m{`7V!FbGR%lDnpeTcMM5@JG6 zq5-g}@!E9|8kfI2`3V^N8{2vpCjM4tAsCMl$@XDN1k-n>(J%8$hhOH${zkteFmWB7 zi@4D?r7g=h3P!a=r|owknCkW;jrr{dW8bp*oh93I`uzwK^J|VqW`DEw9cE(k6Vdg8 zE;XR*4W@oS63!Blq?X?(YC2idn6h2<8Qx}%N9V@@4eb4-sQ07hbtF!9*=m_Gx?bk)(8I@%(n zeY!D5mm#`KFh{8RbQ6rOF}|}b3k+kucf!XE%n=@*?J&#_fU%xh7TQur+j5v#PSwrC zch#lgJ9P^&$13*eZZ*34_|CFCX;@Eu{~5Lu|An1_bhgXyn6tmJEZTl`(4blttApI9 zs~gbKFY{B|Zurjf>9q&?hzLtGw%vuDYZ!GbA9d_+wtQz99c`(jE&H3*Wf@(2(ee65 zoq+C*Q|Q>=Y<_PBbgZvlFQKl3_{hYZ>&DvdFt%35b!~O;1a$Pl{IpFw;ydfx19Qfm zwcTZGt*%Kx_kKV}AIwjEbi#M8x7S67S?Eklf8+F&*gC6mSrZ}F1m$=VfVxH%WK4{dmD^Ccz>y~9iscf zuy?@dBR;lR$9*Z*L+}5G+tLGZ2 z`xq0;r}zJp9Tc|A*nR>=+kC?cg>5zLkT9P2*D`-9Oz#DvkIyjCuU_jT`y3PNkseoU zdstXE!x)Ry@i&3g#}{BM-xY>^DZ06aeFa9pcNzAz=pHxh8)3Y5sXn;9q>safahu2I zz5X=pdtueFF;d$fgtZe^8q2R@;{8kAF{h4fi?C^iy(a8M!`LtR{7yU?PHovQ$+QnL zKlV%dm}_+Gm(<;B82crkCE~Sn&5!+(I=xqk`LSP;{bqFRm-NB&^J>d}>6OJW_DlNU zc_P)ZUs892VLOGbGK~F_K6q_VZP_nryWcSOOZxcLF!oE@mX(-fJ=ia)(`(XX?3c`s zzki@U*e}WKdllI)X*=2I*e|KO*)aA?`sKAP&5!+(I$onw#(qh*!!Y(s`Z!`3`z6_5 zhOuAL);^zAD6Fx>B^7j?&6*%o2981|a5!-j3ecRq7;y7Uj`w@uj1hOuALhxRS%*e_{&)ackR z`TSF~lO~ zQrFNh_DlNJzCa!OC3QoLj{TBM??a`I{gOWB86Ep2+1-Y*U(!~8ONX|F!rm~tL&6Rk z_Ng%5)1vF+Gcfu{GI9Dj80(?$RG|;XBH39+$9_pR&M@{%mT!h(?3dKtZW#L|{pvmZ z^zpUmwi+G#C2bEF#(qg3#|>k@jz1MCcO4BF}v-!gty# z8+UH3kMa2)>NZP1qK?-bcusX277#|>r0*#F(dd>!$Nc7Du0H1C`$jN*R)_iB0`?5@ zE0mZdRKs|m4B0hhitDyP*gV5{9{n@at&(Big0UWp6N+u)P;j<0 zE_W2Q6&ZDw@g8-y-$NCObv41*2H%2Jm%3>iBvdSB+6Gx*H3Mxh%P?&NJ~OB5tr2|i z-HlBvx$EOt^zISndBP!Js%wk{mO0_-n`r8SrQv>&YoQ`=q8v44DR*j})k_TV0~8pXOoFvd^=!}baL zFu=Hul%Y#__dJxwizS!hJN=%DasBZ;+y=~%wKv^>InV#qlGvqf7!!ZHDjp(qS5G$@ zbLvWisSmDG=64)(bT40iyr)EUsCtOy`wZ=<>@>0c3JhJzXM4iv8Y68nZah5?1ykFL zz<7S`KIzjeb2CgVa~JegbR}Pz`FyI{wnbVMl;t|HTGE)ZQh`bRjR z>m_}L?K}z-{eFqDq`v61ZY^cZp^l7o`woobf%RJsD@gs0K^pU$j4>izbei86M%NQ* zhww7i!5AYLPmF04D^wN-i06W7e!alxw?9}0zFWU<7+n_9=ywxVIOC2w^}88N^E+E~ zvti5FvAT&>i*Uggx+s^88jqWVb@g8}O2Ub^TbZlqlR}q<^ zi}-XAF!kG8bUc@VkoM{FjINL9-T^~c`g9x&H9xL5`sIDUT>rLwIY!6zM%^MXjt5q! z`+8w;t~cs_fDWtJr>lc#>9&#ALMf|jtA7O#KisBs@P~LTLs4b*c33f6@C1Li9Uvcahqd( zTx^*7;65hptdCuWsgL);=!5+qo7B+CZ1;{xEPAXy7{{Cg$OvD(ZMBX$AAwohm&NwK zVwuQU}%6{D@yohi1wcSrr6iqY2Uu$l1MWfjISjvH(%Z5O_~ z5SuAqyXg5V>UxVU-_3!|l+Tu96UPm7lcH^RjEqCH<+UHS)t>>z@>$kjd|Zriqguen zU1022*2mp4zR<@xV$0v8=W&It+e@e{_tUKH%V64mw0#d{p)LCh+hGx=8ZY6zBADv3 zMRz;K4UPp?_kxTi^h+Jk@(0=io0zZ^HLt~OX|K*xTW5zt*?`r9BWOCmNh%>uT(f311IwmX=%3$GQj z9+?QLmI2$B!K{vLKwYaqeg$CIZSb|h5De%XH*DRq!BA|UZZ`(`_5s}oU}!F%t_1?J zV?fsu4B_F^o}mAM+2ww2m822;Ok z%X5|pEuZaLFkK&N%XhT|Z5ztiWc~74U4)UZzIvXYI`z95I*v`&me1@U6nwV!`c@B! zS>N7hP{x(DJr7LBCN1;jU|MFi-3!KTmbK+Q@;WxD?cXKXPQW->D_}bvjAIj;rzkeK zUl;WI2N=gD>$d_{c)fsaJsCTxd2~2Id&7JG)%_vr*w0yJo`dDsWNrEWX{;untv*|5 zZPQU;G=tB!2N=gD>(^d0RKNS7<9>kk%l9pEY_hhMrJq~BXhLsnvbOnP9Gk4Iz5d2_ zV|{y|pL1-ow!EK~W0SR=2Bz(-w!eXKY_hh=Sm4-XZJUDyZS%o6Hd)(kSm4-XZ4Z@T zI|>4hP1g2$Fpf>ub~zT*FUJVhm+x~(4cN8-s~@n#@){I)c{^F!7E)0<0iuM6gI=iMXA?dtDf z8!%@*g0|?IKHHHnM3?i~;xU*KZCMBFw++S@)*nN%Hzv|ApRG~993xm}-p|0X$=dSX z1uk1#y?23JZTWsqtWKXTubX0(_-xCg5<$Pbrpd9%`h5zFW0UoJs03R+E6)8UYs=q; z;@D(up9WLE9A8*p-Z#v#$=c?Cacr`-`aU`8)Rxbtb8ND+j7{?}S zn}|NmvB}!%Z%kOfPeI4A$=Y&^;MinsD@i}6j^hjKy8tXTV9Wd0IW}3_!zI|}AfvQ^ z?IJLaP1g2#Fs-lp?EpcefbB(K9Gk4|5-bF56A@Gy0oyKMO#`+U%UA;UA&yP!P~Q&d zm(9hNV-v6I^8C0m_Gz+lhOtkR-D3JQ$0oL4TLdY`Ci-ZAiG6xB7{?}Ck40cw4~{Ri zt%6{tKWoe5OZv06mw{PZ*5d#e$0pipJ>D@)>%nV*s?&NTRd)F?KAK><=i}0$2QjA) zG9G)~zNd82JG03KU`oLc2I@IvvPUsdw_ExV*~6I9-z^>b(y&U%uLX3^qaUe{ZDLyv zajNV!urdcqhw2(O2`p(}>Cg$oc8Tp<5|i}16Vo=>eqz|$qT7x}QXkvF#zS||u!&$# z?JXVZE3wA>zQQ!HuyiN~F@)9b^{+E9PlIl(a)V`3XzEU`hhPS~@u&dDCaG!gaK zVc4}`N5M|VI@0o8DY`oi+Y3e?3(R`^5bTVdr9<}`_LS%@$Ka>=Jpo1^vkWT`-EIts zs(T4+-F~b$!w!n>Vhnz&i-NJ8j~g}vjBUEJda-UM7|Yid1ESha0XrK$Rv0z`>^szr z?`a6*JI67`GuwF~nA)xYV;gM1$uMQhz|Mp2Wy7upWBe_~z^S_X#kL$WSC$9HxTS%!nr$9sm20AraOwk+0N1Xd2^TiU9aT?{rDW6ow_ z+;8B0Dtr&+ZhWT?vM?CmgIWdSjAgv;LWX4Tdi*_@^Sz~MM)w}R^PQrVAX3{8!1x|i zecvK|kn!3M8HO=0zg3doNMnnvyz57NCyD0AeKKAv!lt2!RRH6)r~74`qz|5>V%=_& zagwYI7;W_(b7arJmSrxG{RlGNE6ZzCCk#6P&i9}u%9uzU8Lxv`mH{7p59%Np6RB$s z#%okpfMMwH>U%%tyhb(G=$b;u_n>k-t%~$on1*2Db*5j8t|N53mNgLLABGMuzqOe2 zTGop)CekmjL$Ds(Wc(xh1ry&}dO*fHvenuKGOm$50LC^wVc6GTY}4OlT%+zN7_afQ zM}c)6rGxRkrRS&k8S}I3O3~da;~(=QV}6#67u{qT6R9Jk&NANfLBHc~XO@OU6#xqN<+Xk%s*R#(3^8V<&aTz*vuQhQ)%h4bBS}`;Cfi&(vbpAB=6< zrhYNo4#xglNybz9AY=a}>wsl+JMY~991l7f-B#$>R*eixLF{sTISpg6wiOx27qTvr zpN=nQ8eI}}tXmsl&7hqPw)M7n@7gsMz3mLaLP14-aDb?GYL%gk#C^zpJ`d_M#0 zQ5xeUx~9)Z88CEBpO0aNsgE~hjAfbc6(36t<2gh6*pGc%bT6Ne17P8RkH%O*%GAf5 zU|NrS@iEpg-e*Q1`B-TPbDxh5U=0I4{x(c~OsZJyW25-!WY{y}V;;5@O#(h{0?P>a z*khRb;BN_NJ$S8#>m%8)m&L~j1Q2#teDydFtYyH*TEo;wP1*KveH4g~PoY!4uZxc+ z*d8%{IBD!=fVB(wm|>Xu_#RC2<27>DgU_of+aW&wuIk<~-PZUx0oFO-qb~wnnfiE9 zwu7w4JK|%WVIP29u{gfy`E!mtJXi7A+qh= zf;sQ+b&2a(4225gd8qmT12(FcDU38Cuq@dB9I zK7_O(ux$sUk{I{RSYPflJcRsM0oCPU@nYEKoPu#&qwN}ut+d6f=Zb9a2j@F9u9R^X zN!~q5%CNiQ*;YgY(RRPltwY*E*xrZCwJer#T%%uohsLu;mk*u?+qN=3)30UNmGEpI zMFRZ}G`c&H#`}DKIR#4<+gSLc?H@+RV^i90m+_f?rwTiSz(@<&>b>XGS=;o0PT$89 z%un0pX7Qot$f&yo6Wb4aQtJL|CByW#{KJ&dytk` z>|-n#<8+E)+~+2HB*47BWf-4vBMVn3&Tk?Z{jM@>y5#qS9K&KUL>=3}>aGA|``s*k zpE|xTk~&`V(ssETjOBYvj$x_e^GR$2JqJq0b0TDVKAWs6{;{9)eIA-$J1~~{z5t_N z%Q{GYJ*7`GKmP6}b$sqb^Xn?QO484%i{Kx9oM~8hvE_YLYRhZsEVJ$Vy@gFS?RTTF zmZlA632SHAwO}mYRR|#U!FTx5M=cx#C>saHzWN7PCzO}5rrX*<*nq08h1gb+V|FZh zzrDx&t~M+U3G~|)gQME=-T~@1%JDgEGlU%$)(mVE#ufe+MH9^VIR{fiO#BUpW0*5P z>Mle&f71Y`20|E~e7{vN2+ZpETNKo>Ud)f%E#{~DYs@bP>HH0X5y*_&EHWOu^LH5Z zoEzCV=)B*KkTH?$axj*q7wW_PI{Kh3eOv~nWw};-j7CAwHGMvGTw{Jb_dp-|yd>F8 z;-d@-$8D7LkuUp0)bUwc+BT6fjEv_?_`4W54eA}Q(zYokmhZUHJt4N|%UDO-CxzW& z*m7Z?8nz9L?U#hH4x#F+TRj>7nBQ|^tIx`i{VXh2#y_(6gz-ID+I~C0xGt+;{NsL| zU6&6TT`Q~`wn4s(lgy9jJGn0TdPvQW=VAGK61>lx#}3qW#YEe7M)!%7~VqR^#Otqx%-N)bW~OT0oZtre)#%fnJ#n<1q%~Y6Vt!BiPz?K1{|$mYL_NSr5MB zsEPQ{dTcSe&rufU*BN77(?EVBW&C4)WyS9j?9((4=r)<-%l6{8JjTD40l!Dhv1teB z&c`u(A#|-JzkZlA{@TjeNxwV>VjI*j$9_G)*nU&N+KCTsXFXR++YhB~I}m(Kw{7(! zn6~rp&@m2r$T&$`GXA!TWiLy9^DuUH3FNmy##7qf1s(fV1Odr5r(d=$>lQ0xCv|s2 z$GTl^*gfKRiec-)%CEpVK^af682S?bymu<%JL`e44&4ZrvOV5=hag!Z*!!5M+k!M@ z*yMYx0@_hoIec%_I>vk7A;&~c{C&&)2{ED0M#p_U=68o-WrTeu44bb|Ph>z{a~bQ% zJ`grr#t5>i@Il=U!%~D*mob96ib$t!kHiMq24M}bz9u-zf z;)=TA=oi$DtzMkpHert#_PVfRhP@%|Oo<`p_olF04I73&Kp(RuUZ`WdlkG6<5_~7C zF56`4CI}mA*c8MBb&nV}RoF4ZrU^S!;)?lAtLtoUHSFB5V|xr6Dy)ITA8m&Vn`l^S zszwAHco#5V;mq1 zy|Iz)GOS)PyI15HKC_8Nt7NOag$PNp`D)YurvX=Foj;xjFrWwX@hPo|= zoi3~b+JZi4`zrbcb;As+D>3Fdmbztyl>Me?Gd2B@=V-1@i>=DDtVx3cW%&-p= z9GilTs+NW4-l^MyKqQMn{ppv-71QzEGCnVEnI4yMA47Fy)LF)NlrX)K;AAAmiWzq9o)REC|kTE~Y_-q($`D~EpM@HKq zqpfAzq2u#@d{IVcA{c<1`GKX#pR# zz|{6$$*+8XF+a=lL^oOXBe*WfxITi6ww65v9oNTo*oa|>@vV>fhUxlv6Rf%DbbZ98 z6f<2Px(~v#tdsKff==s3#_|Oj%V*j9VtbeD+cLksU|dJHA%NORS#%xoc`Nnt2XuTt z$X3Jtl>D{_7|Rl5EQ@77!ItmyxC{ZQK7N+`CI^_;_5tR#y&Ew5P^bustkL+xe7m}i9k>5-$W*Vp0LdRni>NF<% z!LPEF;2cZ(N?Dp=`9@5<<~j&-e%fLhf{FJK491-8M8j|G_MBOOBmHX%MAJl4jh!RKR&Vd~>6FwO54=;>n(Dyr;u@v#pKn^T_;uKV%< zAB_-8%GAdlV4B}D@iE4*d&LLeF^wVB=Y#K<#<1wC$1%gy#{}69vRzhVVm)}TxcXfS z#H6SvA{b75K3+FWedxX2^sx>TeZ*oTtv((FqmMq=Hll0#>X8M8!wsL0 zm4>O01T?bd_n7$DCEHs1eHIga)I=krEBSn!23Aj)#?{4!sgHeN>f<@+S&#b-drf?N zndt7Bwz2yaSX#ix8Q5MbQy-6ksgJGVW2#~3x?Vka{McCX)AhmQ$0h+E)e#uV)W>`< z_3@7Q7;M;n@o@(NsCmE#@84|^@WJ;+oiPR z*Q<8OyGP8nb8oQzf&5k)ruik*DK1|b;u#MlElaThBW}w`$po*BvwpHu2SQ)T6OECW;AQlwq2*r-MaTUt54S11I`&VbohB= z#$9pEbyIJgH-EvBrOWTU_n~#`^PhO`&Fwq(eq4C?BrbPGO2x&;C&VNyt(cJXVC9(P znB-Db5>n!;l}d|COGrE3uuQ|s4LdhnogR~(&^V@X#nv@iXSIoGlhmnnr`FwLd&OnN zp53Z%a{qDz%AHepP|V=UL(;Qjvg5N;vioOe5371!`uVFbh`n(9n57rRUese;?6~x+ z%T9~AF*#alW|^5)XQj=JnHx7hc0tU7xCJ#Ambm5G% zQ<>jmj+gqQ)SspPEb~{H6EP=Borph?dNSr@sgu!@xhGG?_fJkp4kz@CO~{Qa7phe4 z{KT~MghqXG8;^=<(k8yi_^KJ3>tt*`Ba+>|dvaQz^q4+B#bhl_8}#3pyJE)8kG*6=xrxh4&0Uf-KPz_rf>KM<5|$;zEK7)8 zmJq)zq1>vI(K|nVFfTu2UBAZb@=LEnO;DZuxcvNZK5LY}X>iPom-gE-y6m>JnC%0~ zeVo<*r;~9fVq#C6EEQ@Ti3!1T2qxI{ge#||R;fAt%a|}qRv({6S!oGPvc|+@ByLIS ziBHzj2a|_n$HWfFK3OWeYTJzL8uMba@fo)?t;%?OE=_!((v>lxn3*lR$Ijnct<A6I_~~{%jUNkl)k;^ z9gVBxneXH3V=o|7p`iTCS-J5QyN3}Jo<s!T{R_Y#}nHz&L zWG&4@D51dyBfMs%WhG-(6}6dW7o2?9znA`x&=0u$pT+pX%-bT-CfGQc z04gbXOftUykK%vY!?eKvgo9~}|F^qGv}bIuP&BqrY>%=r#edPH*g3wxXk6J;-(M7C zweK%FCn;?I;-aaMvcA7)Zc-2X7mB9N3Hkn_wha6p4HP3b8Yo6tY(#v;=n?f7V@^^u zP>cwQZi|td6b%$3E^3;>D-tT_D+wy+YmKt0(LgcEMt!Y;mO;_|C5Z-#(Ie__jX5Dy z&R>$idYPBlq|HTdB%O(y3j;ftr|RLySFaeFoxS|d{7b#vhr#D&XE)_R^rx7j-cEq| z7v&M7`IL=vAHsgPKjHiQmwDvgeD{MH(c^8~4&yF`_nAI@dh~byXKM6E|L4l+Xa3LF zXz#P|=~4WN&e6{T?^7Ye_{zn`nKo#2jcDTfysZ0QZIzhif;UZ1S0L2APZQmD zP7&btoilU^bL=Xg-Q9kovu4feVFb>^6=g9`+hj$(|M;SR(WO20t7FmP#j0lw!e6xU zg8O}cQNV$x@Z$NBoqC*G@=h={SyMI26HT(fZw;enA^xxb-p<~5yFtthz1VSH`%ox1 zGj~OezK!+_AA|kzTzr4)e0;e9(+o_wv=;gsN4{-Zv~ST0--|yyo8o=Cx>;V=Bi~N_ z>C%Jeo^f5*Y3;x7{Ph`*Z|rvKcboE#ZQI!Guk}Cf>OW>+<_%RJ?S1I_Ihm54*>iBW zPm+IpHFNd0sXG(y+>&{))LSbq>h*f&V^bH^*?Q&MqT87{;`aK>(z14CUOW1)1sN-M zWw!M`?`OvSvGR^P?%0=E@o;*|4R0L~ePQP9UXvfja^Z;{EskV{TK(b8cbpy_e{UX^ zz0a32{~_~Ee|(o;#;S_YgkgcI@DMg=Y@@{?iXXKdmn>M--ks`F(GQt~;8%bnhbC+FM;hk)jjE8ls&m!AYT^X{?cS6o8yKIt;YB{J`W z%OT!}*O~Yk>1N)&==_RHLEfjb%yC)C`>=fc!cy@2IWL5c=D+dY+i9bBj3v|3g`aRu z6$ayHw3~U)j`Qnf@nC51(B zp!p*2TT@vcJ;5!bb9tXPK5+U}S$?jrOXqb&em)Bxq8KUv9afEVu6J?3>H-sCbu-OV8e?aJ*aA_0V;c)3=fI zMb+Fgub=Ys+TZ^CR|l4tZ+GcoPaO(9_MuzW_NnoyTdptZ!>@Juca-HCXS(GUvi$xp zPS0z<{A>=C=hzCDj>}};CpD1Yra*ai2FlYVP@Y}^|5pUs6W#8$(Orj zt^eRI&R)lhqnlj%1!7-0*)2Dc<-3kMeNjBT?3OkD)6R3tRYd>h8fTv+%fnB&bS-~g zVEtZk$faw1ZW`&9bzB-*+U2L?+}rKlGOy3_^HE2q*ZQ>I=$3KW)%)BWh@XnnoqZ=s zziqnHw{OZaV zE9uvzID73clN$N+8~voqPuEA~z<7L9J*U_4dvYK?6B1myuK!mjyZm&#KD^4M_mJ|O z?C;W(Ww~&wTh{ekvyEG>DCq|ubIV%3^)ubFZZFQh%Ps48cT+$gzR3C4@o7wsTh{UX zxuMQp`^V+`-Lj6)?`FDX-2+_loU@-O<$HOrUw_45m#+Jd&yI5G+F#1 zySZhJhx2Q?Wn9PiKA*2~%Ub^pi`}xW&n1E7nt^yuz0>J6o)5Kl%M~U6CS%;P#?#wj zx2)^?v%vcNHPGG{1>)~yAighY;qt2>{;oR5wU=(c_FdwH$Xpa+t{f(YkW)&?0*#o#)tO#&c46c*IeeW&pUzk>2{e**ZqV3 zd!=xu1{%9?z^-l{dr=RBZx;_U4 zmKO%=&Ku z^t!*)zNuT*{&h>h{zM@E_ilIP)A1=iu)q6NVEaD)2A97cUp(K$@9(WZ`T7UeM{b}! zE)Q%!b_e{OAK1T{6&Ro5=Q{tV%liIdzpIb#Uu~b`PoGrIrI!``-VttD_a_UgxMf|x zo3^-R?Jvs%@%!#dm#+I8y938tW#XNG9p67*@ASI;IKQo1t|;Ycd6z%Gs)6N}FS>Lc zkC%0J`Rn+5zLxw zb$_mV=_?O#d)2*K3}49^8ZgA^HC`9ha?2X;w+6V0KzW}FoDcdqF#dIz@BHcZ`|y2kxtI7~AK1Uy5ZM1X7+4<_8aR7xuMUCb=HIyb z>h>iiaDMFcMJ`>(mlYFSe!4$4cbHq&_B;|eKT&R!OV{n;kbr)5pnn|=j9*U&;*&9G zKNWIZ`Sf^TdtiK86WE_^5g2bD2-I)X5?9_#adJstx2)UmYXbY{1O8m-DfM`3O5pgS zY1r9o`!8$g%9|+pkC^S2b$@m2=*uq;kH2d4#Bt$kCQS-oKKiPQ$JzQ8E?wX)=3aP{ zH_ut*mR0j_>5vaUz23634uA!;qzQR&*}5resDP;_pUAQ`htG+I)Gjms9r6lYL(>5N%iX1sa@-| znl(<<-UZ87d0C&TJtHez`l;HhK+;du9+8#KK3JdNa_>YJU%I{ASHmrrlZxlHn&*8B zuW@m4q~;g71O=D6BZ_cam!5NlTTi>^4)p>)Z;ne>`_R|UzU%j&zeoF=ngcltseLd# zoaEBgK4+54f8nbG?x0;kZ?SJJ{)6d#{P{}$FHQu)CG*ZvRr z(<3LG{pSx~caLY6=!Olo51n-Bl~*_PGRi%6u0Q|1u6+H*JUNpIIhPFarRRwKqi?V7 z#DvJV{`3M#f4o(47p52d>d!wMa``_uv)O8<=Uwc#&z1C(&+ppA^pN_O_=_aFaWpyhBrJr`k#_O1nn?J)#*Z9hn^l_K;4}0nBB)y)j-_p+h z&uVq6F+FEvAbqOS-B2UF1Jgs#`_n@oIr}q@?!K4Fg)jQk3nl+HG0E+jp8JYFJyOQm zcYWuJNlXuI@u%lX{_ECldzi`LZT|E;v0t-(+=EOn*zQjceeCjoqH1hkrWd{)NH6Qs z$7FZ*I%?!&N!R!n`--E6T|@hvaTjn_G`{3q>Bf&&dK`R_Jm+$ko)>oQmh*udpMLw` zS+Aq#9Gp&BD6d1w>4k-oF7}anuK)eEZ`wz+D`?=#mzV173nl$zi^>z3UfAY(&O+e^ zEi6@r4}aq&OmOLW4PAO9#>Myi!S{KNB9(4%_7eZ$m2P~hb8`RLUcU4F?GrlW z@~={^?PE+Yn0=13Z|3sPo$2N~^4_cC*>5<{mmW%S?Q>0;-(O}z;aBJT(sS=}{u>_r z-HVUHG}pdi$v-d6rJwfp2`{6(M*j4iPHz3QxVD~m>LGm0pMOq6XaC;uyGGM-BqLyd zw@a@(a>w6H&#mlFkKE(ZH^wja?8ATf^AD%H^evA}@&?YFs($;t?r!@K&V6;6=l`hR zKDVoDpH+40b!U3P5B~JRyIlP?FS)xf({s!F^N(EQ>}%|~?Q*8)9QNDi^l<)vd@c7y zriVWBr$>%C`$}bMeaPf+DS!UqGoAfQWxo2H={fcN>3Q$D`bRpwcskSb+W6CRI=k}! zu!g@j5Bsu#^l2{rmt|`nVS3?7fBC}qy8K@{a&2QTy=K6^sY`DayVu*k<^JNgFO>3E zeqrT4&%UDHKD64|KfAHjZA=gS?Y9p%bLoFnKkopO!`1!vc|BeGymC+PRHhf!^QY%@ zarN6*>NQusmj3k6Jubb@@}8dmyxRWsLh+yT)r>E^{G0jHbFO#xq0BWEn4bH(r0e)L z*Y(fw_kF&L>5<|6I4jzIP`D>7kpP{Uy`)UrZjE?N5(XarWQO z=rx<^xiegP(f03VXCFJ}mnWEBc&6Wf&RMSg5_;y3VS41xt2it2Ur^QMzo$i8 zdnJF_Kh3$(Tdkp&kKWOe>7k>Ne!6Sd!dfo>ZUe6HDjwM$$p1E{Yn#7p7tISBU&~o2 zPweyRJNsdcF7HTQDE8XEp&ulD*Q3XoUhqtWv*PV{1DC$(jWIWP{4&4)@Km>cTDJJo zt7uLam#*!XEBQCre4iIzp~uBu)?Z#jmw(w88-C|G_TB`K_|)U0nXY}F%{aF_)59IT z-ISvC4=r=`U-agu%bA|r%%yAm7o@xVGgEH+gXsmg`uk6ABbVNy|4wiH7fuiKpXP4; zUG&iaZ~GOxO5(Gs^Bc)@_3wP-NS>Gfz5e(O4OmDVI#tyXir(I;e7l@HQL%rpq^5wep ze!Z7^mxc;@`qLvLT>M5i@mCb!fAIfe?>oS&sJ6Bzy%$R8W$2wWx}rnxz4r-82!TL= zKq!igB8mkI*bvL8DE8j#fP#v>U_}{J6ospxq8IV%zt>vtKFJw~@!s$I|L1S>Xx_8d ze%IP-uU%$OIfqefudkndlz*D^St1p9&1Z4B_HV=g^!zijxqPdX>-EEJBCFLRul+kHZ#%o+EmUp{3NJTjO8+0p{7}k^!pj|$ zPe0aXAepEn@azF_{!l0RPMd7ilActHkbIa-d)V=v-7-^yIn=^9hUxyczs?i zvhxqZKdztMe@J=Z(gF8Vx%DmL>n`@r_fp>agINzyxu?r}NV)xkl=ptPPd6&}zk@yQ z|5-<*yx$Ywb)<4rm$yWG4@mnic=BJ^{@G=oL|p4>y0O<+`9qSC&<5lf%xB^(}4TW zUK?I+Zj|yy(K+ME-aI~>Aas87ua@#xzMIY)Nc&QpAN2lgro?x2+phX#XKf5GHwKFR zyVrK$h1J9UUC$4Hme^b3*h~F9{@%^Lih9>O4smwope)duR`OW2>sN8ujyxbWq_A7@^ z%%yVkm2m&&5GjB5A5n2!4tsrm@KC;e@)eI$x!(-)U*8|HrTv}OUC!gzd>rN2zgin* ze&&Au@QY;cO+kF2$+mRBm4`_IiBSPs;qhZ|}65soZ=R<@)*}U*cQ& z=btjar-s+>B0n`!X7KoO?+lb9KW7#eCX;{X0r<}mzy5H^Z*uoczP|Ohh1YKv2(O;G zjpw&H4gS$T&IqwzS*v_F`M2*6uiqRh?Th;KOP(0k)MBEA=9lrM~l%)UKW1- zw^4r9nk|u3?z|!MOZUI0%kz&GQn~Ra$`PM8QsTQmGwu~C_U#b_74<(R<2UMH9p1k< zj}7E<7x^(pi~T*<{N%CSfss;<`D@gZ_PIS}eAr%i`|UKbZ{2aq05Wur$@-+@H@}ni zH@$g#1eM#hIgN&SrsUn8Blz_L{qLZ1cid8fP`QivCU$+0Ph9rMK>09<@6O#{e86@S z!^@qvGJn2Uy7+f0_r{|f^Vb?9@qfSX79Jl?tMGCM@n2K(D(*P5b$Ge|l;n5iBlJt* zD*x}w{+Sy~3U%mbj)e5>U($_fmH+#W-B0~={!Mka-S^wq&uWh58xfIF@d=4ZA$>ru zO0VsBFp)DHL0RiHR*si+g)0{2Ei5o|b2`mlxwO!nACy)7Y3dt{q5pL}8Y82Oh}gL3 zn8c*`gw(X;l%TANBUN#%Do#|zsX^IDtesJ(N!#`vI(F)unU$TBd-}jZqbE)+Sg^2k z(c&d#OJx-5=ugJX(nU)%=a!Z&Ei6#a+e`BE^5+(27L{hox56@4bn9}mO=V40&wn+? z{+x%47Ei*eo)2rH*E(N+JT+GHJl-Go*Y;ICU)GiRSBSkmMCM;r&xx&t6WGL_j`Bf|MIW1pQ&+&sijR{U;B+L;m~@ay@8t6x2LpvGB}3cS!@pMN>|b4@8X+l2G12C^PbUwJXF zm)7T{L^tfy0`X<<@b|j-n{Z9PM=SfY z?+NEQ;MFc{wuN|py3}W7gx71lA^tXX$(dQ%pWiN==YY5C^EHLUb5Ni8P-w_|T=1L7IqqQ39K>ov;7->*(w@4xg1 z-d%G$&mo?5Nc@cxEr=Rvu?{M~x!Oyapa;v@{@r@;-dl+0{4UqQE>QEF&!vB} z9$0vSc=i(U;{Y|!*eATH=Kj9K^X3W92Wp<3E9>~OS7vu3p0Qr)buJbR@s4*m{?`*RRqo8;Q_$)6REd;mlKOc|#)ZJNmA*-8_h zm5TQ0dRIxkb02&AL-J=_AoaQH!s9c}65gtM7i}V%?pKZWWb}tA`_A+3zHu4z`i~

    dDnn_p6*pM@YFbDx7D$CA{_7#%A*8UnJ$`hH#$UTVK~nRZ)4*{$B1X&Eako%&U2edd^e9e@j3A< z)aUjI=lN(yUjMB;5nY{+S>ZgltHgKrne(n?e;cLT+Z4{Ty9uxH`~Q>+vn^8Y+yLHG z87~gr<2dqK&i&-ids2pj`-Gqkp7Dju%bW`v6%o(fiSm~Ot%s!CpDpV~`@={1Jneil zn&^gkSkT9PBkxP;k0rZrzJki_Hqy;*J3-BJ@SM2DXFa(;yiQVXbriI5AIa`4dH!Wu z!UFPVd@_&01Ztjpi|`6E4kZ%7e3+-PVF7)tlfmb+HlEMw=djwJbF28<-)M6!_V)q& z0X5Ie6y7^c@2W{WCrP@+1?v5&wN-eX>P+p={_4vWg`Fm-dCoVI@0T8}yN`JGiE;vU zA5YN7{UbL^{Jr1fUXIVW7*{Blz#s0z1bOyRxt{cZ+Mk^*{+t$58&iE=q4@FUz@M&n zkc_|8AHH}M^YW$K1z-EK-WPx8f3jd3@yrt884KYL@dbI-XA++a)c))bWWAqpN2|BU zp9?=G?r(*7gC)LYQ8RfXVy=?<%(GB0+F=e6-q&;K7xC5nJrCt;1H2q*$FiXhzrgig zD&_8maGrZW#{EaHy&~)Vg;H*;59iryq#ZXWENe>soaIvPtO)11LnXfR`|Ou><7_E+ zSBLYguchACr*4vUXpNLx4tTgeG7ibOiv6rb4ApBL<F5){h@9AJv|C zZkCKY0~q2R7Jr%VZJRk2l=y~oO72f#515Xpr&6RQGXA9c;x-sxP*PGAjHmnjsyAbOs zp6eFAklKd)*;k?b>TsU%htzxiFW-I7ylbW0x;~ueY!Sar*S^jBE8_ww_kp2$;jhP{ z_*coFd$I70E5S#6{t+1mU-bDW@1MQz1`%DoUm@u0c0@?MR}A}w_xFDEV5V6yf_mR> z-7n)WqHW9fiQq0MWS&tfsCoWYY45DuRyPsBpM!EdH`6>bP3qnF*>x?6=i#}VTO97s zx?TLW8*_F);@POrS`^N6;qTqWcg7OWhaYENIL}O%dLK`nHG}=lmvW;doachKtR?;H zpejCH-{Jrd@tyt6`4;gU?Fad>@qEWRCjHTFQ($wdOUl-3a@5l`WoW- zR}3XE%qs;o&s{D3QGeSj+o{~W4CTPkcwTog6&q&^YH*y;Y?w!2*iC>quX>LO?}InL z@5Y1@nZ_Pa&&%NR1Os=%Y>k-b_BWE}iSO2WnfzHd%lhL0wLjyywD<0LAAU+a=LW1( zK+SW(Yx{dS4@`H9@QeV@`c3@3{`r%!-z4Q8Q1h&Zq(AnY{&h#@-3T5~_nULO#CPp4nS5Sw?g9^}c~)IH&-mA$ zww3+egShS$^a~^|bYY~1j;y!c}umvP_%2M2z)gvqD);WqnoE4AbQXb{UxF@V%{OpA?e{?= z7ZT4|Dm=3se8`&b)s_6dnO4XH*t%VKHqga9y+3fj259{$vgR9QV)yD#f3SbY5Wg%M!VE%T2G&piS@ouUqXmq}+cCxLZ)KZ^k;YtK0Vro{0YBpxnyh->a2bL}MURwrE7K-T%UI|~2h(>}L}@8SIm^9ec6T054L z+AwrH!S{V@NV$IR*Q*oG_vE!;W9F8bFR-6yrQ8G>+rdZvovWqYZJwWbI`N$Wc%D8` z&;#oB8n|v)-=cqW;=7|UKF0{UK+SjV68||XKe(RwcDD%x>V0QmcR|fJ9u@wQ`rq>e z^gKDA7~2IspyoS|3IEJrVmW^M=uGhs^nMgs^Nq)apM6d{-pDvVNVx~JkA(9b@V6d% z@HKL5nk(7A4K$jItk)m2zl@)=?`}DniMPo5Q^vh%)_v4$Vzsml{NVyI4 zfg%6RW&X~%elPD&j5~$z-i3OAdcE??#s626-fcquZAq)TE|c}m1BUYRqU5LZ;_<%{ z-x(wG(F59J!`BC6xA5!!uz5J~z1w9R8+QQl{)zVQye0hc*T3)$`~L{}2U;J8=ik0Y z;(s(Ft1a=(hxjr|eXmf^f~@_U8NwgC@|-!ux5ml1bb!VL$XMSz@H6%|Y)yOz<(|e# z!msN2xVhE zHVWET_5E%i_1nSvhlkf+mA$spenRyJ?5lddZ(Sw%cLVj?>%;4>%3j-PKe~QxZ|{@w zTIKh~FTnbBp`dY*pubn_g3tTCak#&X=lFH8?Xn7oqm77!g~ZZP}`XwOMTO_W<5*wIl3HZO%y-wNJ0BE&zrIK2aMJ>$PC=zR*@ zD`#pzDC%c^c?azIS+-NM?%)mC4JbP^c?Y7oX7Ay z(S)p@D~9X>&lN5B*UuMiEkA(skT2~s1JCDtJfE`$$a5Jl@Vw5)xDGytGtLGd&*Os6 z<$Tl^d@g5P3p+fYbA!+6_G7#Rp3_Mey0)7@%%54m%wv3 zAJ5%f;7QNnz7)IQb2tyr;T&M_xttHX;Bz@!U(WzfdQSJ1)E9jI=HmIA4YUH!<9yf! zpU2sF9%lj#png8*Pec2vd!F_gu1mfU)a!(S{rzW?Vrub(nl1YQ8|VS8HnMN`abM1U z_EM&=y7QYC>4QII8O!EWK@YMG+5TGM41QnB=!pF(zSm{c71?br=pR5n@jbF9qSx{| zVfTd{&;VLMy`Gtm$o?%ib95{PXgyHGak>u*+K?Tfk9Eny_fDGjDdC1X)8#&jIYZC^ znlnY#?Q@=x`ZlZ>dM{Pv9D!X*nbZq3Q$=RwDgIQozpy{$<<-!?<6@Uz7iR5$EBlnH z?9D3nH`%#{2leaUxiOcA=ij+W>aWUP?@RPPMc1$Wg!U-|89IAqetRDZ+K`QXBD;{ay`3%R z^~1D=at{efPxI{x7IWXMwlwY~Y7)F1KKIJrSGP0F2_g1*LCB71hYz0pqUZ*fTz8OZrk zZWIYR8s|bT4!5`3i~X<$g}nZlB~orK5_B~#hP)))-n~TZpE(pineykAOSy5DpaXQz z7TH@JZf|`q?SJt3=kFtXr=^s;tpttMz&3(DQ0LFyC-&!FE)S0Vj^Jks+8VP&wz8qe z{BwMCz%zlCppM_&FZJJ6 zP&R%qdXpbpq(JH57hSF7t;T2-f!^***j}d{{@Is!C;f{4X(nuZoW*d+TB;_bwGQHvlgaG%gp^^*dP-|AUL`@bgS(qm)}$3wj!_fqZSa zy>US5zj(l2UjNL^QtsX$Xxs?ANze!C`n_za|Gf^~o}l>6TZCucF6e5!1M)UOZExg? z{i3n^-sSe+E#=nzf}X|)AU_yx?_MePm;SPYH^}~@uzw1Cp#QYU#IAH2RhGBN!6#K!fK6^-kpN1*Qs`DUfpo{Vd4Z4}O>1 z@y|{q2j(Ct_XZ1ELm&gqp^$+(9{u~;mv3wN6Zvt*3(uS==mO12B0E5HvdG$x{+;cT zafi9UoGRtsG(l@RWS}_%GEn<*cS(Lud+CAs6puARcn;7U34cHv=x8jHJevb$e6L7; z>|XNY#*QQ~j5tB77BE53k4HJsTZ#V4m3Z{`&P+TfGOBoPWaIm2`uUN!7V&hK=ii$L zUB(+kD^s5H8`*+R7M}Y6*HhW%V3JZpoXeW{>v8RUzAkhLGP zh1}1%{3?_8<6Z&m76RuBdXQa=8>bX{^p}06#PiOi``U0kW2M|5FK7c@jAKvtx0dz% zvcyl*riFKrANLHgcPv2zX!Q}*S-vVXJ8 z_v*f%W_&x3+#A0Bz8Ylx{Z8$t+V8Ku%FCqTJt}DJhWw-@{t-`g-&-?}!R{kLN6P^} z)qStcZO4~ahKKLDd0K`a^IFM|KV152)xtI{I1f|hIiNL7&;)wW8<1@vH%|T8eS9o` zy!$u72`2=N-v#UaA-D_p&YvPbZpi)Z-4VF&tsMriVE;hY6ayCm%YZ9@tAXbMF9lu* z47d%6{WlHf&qIJCf#ZOafir-!fhE8qV8~(M!`2hLoEmol?*~2td=mH^a0l>p;LE^( z+mN^vzXP}qcq8y(;11y1z|Vn)fpr@!WM7fMkYjxK;F<;e=`b+uT9I>rgMl-FOMw>y z-vvGZ4EjHP-wIYO2M+K>-tnbi?fruDf!n?i`3GPx@KytTe7`67d+OfB@|?%NT+r1r z(7r_U=0$?udhp@TyI%GokAKwk9uD|2@PQ7{1$saqXrSIud~eG7y(6t?IQg?Sia#6Z z0ezsc3H1RjE#rGiCw(vbVwqPK(7aS+=Mu~}=!4(iHsLS${b*+f?10Wp$UqO@pALSH z+W7_R@p8%E$iZFt#*X*2tmo#lg3dF7KE4laJtwmJl%NH)|0({g4=>?v=-W7lugR?G zvhF!R`!lTXkj)uVZUen9q+I)R8(+%)-v8G!zQ5*A6}~wQcAsHghU@_i__w~1a_ukp zd(kfH^?^nW@oV9Cq#d9KwChOuf%`ce<4<7Y2Sh#%I0d*IxDj|C@D<=UKyGBEKZTdb z`ZW3?K`lQYkhOmF#lpKFfV#YrYySAlCgERlrQq#X34Q>*mNhR6<*Ndyc|reE&k}!6 zt`ckoc}^908hA5-LA#*;`sa$@oxrx|iTs2ksAbJt7vKl&g8rwj7e5)m&A=`JS@UK? zUmieh7xbTWnfRZ-LGWqFR|jOxGf_SufZ8tT|MN6CKle%(Tn%hrL*!S19cqf42kc!- zef|DudhI-iuKjh?LxfOuCG`}O<+~)tdDZ;^i%xl z(QPJcHLiqw4e+P#Qr@bE-~s4=0Oq3H295*js-jcG?pI)Z4Uq@b6#Okwa6yLPv(WDX z4yYyir-2P>i>&<*n`wkcA0ezq~ z8`mF?3C{#tKpUw2`|rrUq~pk%+sVKCu-JJ(A80&+{Z66yHz8X<8|VPFe{Zm?FX>sI z$P1m%ATFQiF$$;(zCxXP-s>?U`cl&On@yeaJ3k2eJ*c@=&klA$~hb{2!TcB98n!x_^Kk&r(qPm}TU^@sWIk$)fgGoFP#(9*bC{M(Qnpm&bwUC7$M7cKtVeO@?+ z{9DMM4Rmxqfo2)<0NDo`Paz&)$bT*Izc2c!YskOzobX(r2lRms#) znO}By8UKU2*L#`#8yj&xx?Io%dROCorSC(5=RogoLirVf>`VPQaIfrF{{+^*Pvl(S z7+@)I1MnW;%fN4de*iPEA2#s2;CAr)0S~O?5cKy149F*aU*LY>`S_hO1G1y}K;51o zZm=v?-3ojH_!jUh;PSr0(|Du`y)JLrNBBK~KE6Nq@2*!i)+?i$b<4oK3awuQWdGv* z&GBcPE#vy{jzc3b9?d~gpMOZk``cGf`i&ENNcM?7(ECbc^E*NN3qb>V=Sz_-=w00Z zaUffebw2G$GXC%AcJ+L!&w2s#3+Mw)PxKzp*e3p-(AmeJ~Oed z1yeAsXez5pf!6`ol!!irb49+tSnv?A>%0IjXcv$#n=gDF$L5viP5rC?Z#new!oT`| z@3Rdr|EvE$*gkvrU;V%1%IO?Rdtgx3`V*H6Z~Ya5^ERCtHD8x&e^sITxQv7U?tPYD zAmhZ&$GQO2`!5gsG+n>_lFY--eICxCgt%|X{4w4Zw15uKd`I*S&;uIpf)8|nzSh47 zJ787s=LFyX(eLZ%_l|<^>*)87f_fY83F+~s-xt#F^;GwM(%*gmM!zqk-}}i5yiZZx zdo(&e{l1QVuco^9gQ|MJCiwn~eqTkucN2VHrP}vc5Mbzi8U0>MHSgzC^?pn6{S*DZ zh<@)S_`ZmK|0Sr`@2Tkg>GxIidnNk)7-P}cgvqlEV>u=5y^ zHKqsrxB-9KZxDm=Jv2!CY8*XW_HP2dvH|&k{768q z3;8*ezYF{fdW}b**Zhts*Zy=pK{*)T`>Arh)htbLA@CVse7fi-0B;5U06e{hlwSn= z0NA3Y=obN>118oI{UqR4;89>OzDH{dKO#eLBybDxAh2s4DL)VR7VxJgqOS@Y)s^yM z;N!rkdZHfV0(=3O zjCM@{-T@58x9gY5tQz;L;K#sO{}lNEu-)L#|GoDkk7VEx}kz8To+ zUm`yO4954|ds05|eZlvD)Axvc09f{c$iD;EeJFCRj|7A9z4?jg6ZZ;U4Q%q6$lHLq zpNsq~@TB21QvL|A=hq^?037g*$nOEC z927Yi-=lwszSp0E+kt}&>9_ZQQzAs(2P}*f`6uA!7?J143igf@ER7dD20SZ4>Q|c`vZ=A0h|y*ZGL(=N%P120Z6Sk>h?6 z+yrd&v&g~t@|#QCMJ)ukbb#Da@TT_R^0ao4TLD`OKGP-~liG@``D5Wn`_uIV1L6OfZqYjgQ@MhpX;P=3P0Z-o{_Dg}E0z1Db`Z>Vcfu91u10Dwse@Xbk_|}dR{S%`F zf0lnn!H6Fxa?|mGITHluPZYd4ZS%Q;n!MS;Yx6c-QH(xNO zP%s$ZpJ$5xX-jZpTLaU#D521 zFutWXOZmmXTYygh-vE9IJPu5A#jX|bG~gIu5pXqd6YwtJ3&1_VL%?8sU7E~d)lgs_ za5-=T@HXI6z_)-0fG2=8nu@kKwn?bt}W=ouiHdq1A4zH_!+=DC~qw2!JmtId=uq}EBNntn%BY(Xk90= z541Lm>;TQ{MRtMK7T5!A{JWs`jiNVi0^TfW1AXAJWO?41k|NkDRWL72@FL)2!2Q5p zHKhFFnu4F!5^SF#cvc<3-E{@KG!$G9JOoT{F8VVY37+3rkO%#L@F(Iwu=%f;*i$hN z0?#SES#q6b*n;}Gr49W_&o7}5KF7464?fQ{q1VqfO+4Q;QJ)3$W}tq==`WCZaqPvI zx2WCztGHjeThImiKt8TktY?n1AhtGnRq=j&FH z_^a+YyRYk+i#T9sLDtXVb^O+SGVXhPbt08I#MRHmUc~qY`atU?(YrunC&o3<0eV1l zmy~-z^JVx2dO+h9_yIaVU+Xa+UEtcQEgnAyfCH`(`F3E;wIUY+cLG~oC;D~31Hb{B zVGoSCUgUYew}9=pi2k$x5X)gVBDU0^qY$_bI3rQ?w?jS<(ChMlR-vySC-zf-D}nC= zzX8^X7oPSP#BPD|i2=DBGB@HBf9@=o`S;Y{#NFWiUHlaM!@wJtOMM#uRfWC|cx`}v zfK!2G!1IBpXd0{fEga0a?Qi0vrNaNacxaLEH7;E&vc`5xMBaRsU>4*?Wg@376Ku9z zFk^+_7pnx9!LF+IWu(czsMX)Z_2B(oJP5wV7U@!-#ubon`ZsY6_}2#Pg6(`dZz!vV z&i;G2E?;b=ahGgChoc=;^~#@t0{K_tE0pTr zS+5Y(C;E5SD=YZlVXvfMxe`O<3I*hlLd#kalA)-OMNvs+MP->3VX{($%i^O_xJFPD z-a59gO#i>G{kn1gtM9AmdjEIB|JTMt=l|V0;D2pACk^|wz=Dw)P^1JD$pJ-DK#>?w zBm@-k0YzLu5gSm%1QgK$MN~i$8Bjz76y|)nZ(@&=?@1VIX7hc1|0>z<8m|gkkX=_~ zcekLAa_<(A&D#Wxs|D??g5K?d?lwX56_nov8TR(wkYR7!BeHc3_%{gpHw!u_H|~WV zb`E6gKG=b8q8$#tS8suDYPnSM5&T|_kN1q-m2yAI0lF)2KMS%4H1ItTOP4Pbo?8xk zpb4I{T=X8$2bw@D^t~L|!=Is1*8{Xx3D1U|hxn~(zW-wdz6WF=PD|${@O>b&1aU7C zbb%(&(eh#`xAgacptoV~EI>KX*1Uz#16`m8o&%l$}6 z4&F;Q_4jIYJ;;l1$^3cuoE9(A5@r|3eE<(=7K-cueV{c*^e)gS64?fNKyxnafj-bG zhCR@j2Ya9gH0Q$}=mV`1*aM9Pum^fTb0O@3KF}@|y$`e&iLA$q(@*kpV)BjrLb-V< z`~zK}541L*9-s#_FM}P>1^Phqa+CvIpbs>!KsnF_`dWXbl)FG5Xl{fZ(AXrh1$2Qv z(7XzKpbPYY<~3MfT1s9T?zwE@zcXHp?egBp|E=T3_oRK-{~`II>q|QBZM1rG~_Xj!^@wD7dal~(*xz30`j&1e`cWm$pQKL-=zK+_`fVr9+wba|FH~_6Tx2` zDYCx5FsZA^X(*rBPvjbq>qmw2?+>&ew3Fbv%!~V8*}wbZw@!GE-Tvug-v;GrJ0|u# zTI1-Ht>>M&anH;~_XOqZ?vDE?V%pl8&#%jF`Qqy22|;=3jOUm9@zCeaw%EN}mLA=* zJt%K4-tyH2gP#9k*NxlLUcV)|Wl%2d_-&`V&tE!p?_Cd0|788~@}N9+%o*1$*p+?f zD{Z14e0j~37lQInN&c=uS8m%gCVzKqQM-1vgYvq>C))IA*0A&M3p$RdmC|EeP##~F zSolohyzr1 zcV2o>uCsk>{rHmZO@=QY+~%=oAM6s8A4zW1bLib4jU2W6hG{>QcAguQzd!HtrKS0| zuc*D^mGk2xU%oUb|MuteR~#xCz4h1Ijz9n7ip9Hv^4qOs+$3XUJU3e8nvi>Di_8zr zl4Ls{H?dy>!5TcOIVoSNM7M>P#6gdOb)EoR=B~*o49I8wEdF)evoeIQ&x6GQx%4zC*YoG0Ks*neFXi=7--;F@>-FuAKzr^EoF`uh z_zM?iilaGt&+(EcTXeTEk({~@sN7*HoXKebzix9{P=KBFkG&zRCg z_>Dq#K0od2EwUbuKLq5(f%yLn zly?mH-y6usHGzCw_D{)=-q+qAke?3lUyGLb^giyLo{GXwrRwh_LbpV^~C*5}`Df&D<<@6vwVUkzi0uiMu=AlGju<$AoY zGDOzb4HFuOtk;`fmx!#_kJSNx{tzkG=j%fO`z6Q2`)7Ax{Eg}>_IkWb4wNHpA(&Q8 zd0sW;eFOOqImU;Qz<3FkFAt2LVELd#X^$Q+!SYGfl+UWByr`P;Gpi{dRZaPtdJ@0x z|6u%^swrRIRP6Qm3ffzN`5Y`i5m>*1rqYl8P$}J46HXn z|7!y4Ww8AGYRWIFrhI6X^~(-EYxx7o8<)mM_SwHZ?&}ZgeZ44e>D+{(;-zz!&F-9E zx*&7h+|otGb5>?9EnQK(Xi4dcm6_!^nfVI}GRq2=lou{ZTu@q29X+9KL1B4eNxOu^ zg2F|W$+HVfmn`g_xu|f-{IZ1d?9N%8vlHfK_nKHTd)TmrBj-%)F?;B$!o{U|UGhf_ zTRf`U>?uofClw8wx?)t1soC8+%q<%=qIb|`eqq_7yd{O1D^|?SE1RogO(@UloZUHx z{7xA=dG4?|eaJZE5^E|aFNC>SuX%hJiCr%oI;V)*j@JxV7m>^FXVX;zPdWfQtDUs0G}Frd6o z)t-yXR2?hHt#aIr+|FK{J8|B?1?8D#qvj1>S}3RMeE?SvtqF3Rf>v%3Iy0G%#=rVUv&w29)ub4Yx@chN| zm-NjYvLb69Z|F>XYqtd{YMuMFE8r1YE@3b zgs~kmCuN>Iv@1tnx?n-+Lh_s2T^#4<_nkesU(t}_@jaJ~D;+o`t9){g!MUr-Mvm=T zIDBb#_sp?lhEFJ8*kjS;lgD-?$LeGL9F^`YJr+mxU)*ErzyWzv3j5_v9W}IM>ePav zeRBHD9y7LQkAiW7$BoDyHYsyT>9Vd1N>57nlCsPd#RZhyE)wM8g6_*lkMBQ!WVc~s zR^&`vFrx49C5r~nFJ3ujdC|bhV;9aJH9RkWLUG=>kyB3PY*pbBHK>coVGgFsh~g#V zN^`nTTsgA1``DpVM(1XA@6o4Ec87i|R~6(8>f5c`;+46169$);P0}8DjCC$uQk1zO zvuq_dRSo1$IaxV5Sv|9QW_Qc!(zR=+yxDm@=j7+)^_VkY@dJGslNd1fIJ<3K58s2Tts>Qj3bs9=bi%JSR%lP8zRBA&@hYFup zx`M2cbC!=S8ohL3Y1h8llk&O^&*|T1P={f~<%{PREL%EaPWFVk1tV8vckim#j?zW* zi#iuCRLk*#*`3R?DHjrcc9-m|oG#h9UAtxHb}A_7mYdVFd+wa?BD z)Zn}ULzb*6%$d| z-ZTz6W%cZooi#o?r&m^Xuk4;vEBRORxp+=-VL|UXc_n3qiN|yLWnWOwTw_f!;2o;mEe^dOa_KQaf>4OR$GyTRgP6c zl9FrGs9n2$HuDnFYu2n4I{J%0)t{;o6$kamaMDRyBq>QrDO1>10;Yb7OGrwYqiwm3 zss~ko^H?VXi29wFOU0ia1*(G+lN{D@(CE7O_=_t1QI@G~(U*xWC4sU`N9?r~Iwq0s zX4WZ-&^s$NYCJ?bRR#5qN~%gkV$!puQ;nrwr2bL*#9hoIMaA(N`{QbvmYAHJ`YG#Z z>{3=~pe81NE4okzsZip7BpqdthYD%p6Hc&>bF6xZIw>wLl5SK=swlA>Q!L-SRLNJi z9E~zg6&|I7#wf>JpLI;3QLhGiN_q#@sfkI0fCf=&TH0ys579)&()>v151p!mhCCaO zC7lcbHEq<0Nls3&*&h!+#ZwN|++HNM9H2@=BI(vLkGo3^U-5S(c+#-QNEJ`wjilq8 zM8~M+b3^VFo=O%EeHBY;`ctf<#87xNT9T4pCS5f3t~!)Lg_pV~#EVn~2^4b5SEP%O zSh(ZV=s&_b9^hPQymEPhbt;(95glX5jYc9$2dSD8NvDFNF{Wy!)TGp7UW7!)Sx!rD zD>@pcikO^EM^CX;*7}HvJ(G0Q)ijxvQ_9z1wpDu0f~rWhat!MzSuzT!-BVac{YxE8 zBPcFDpZ!Uflah|&kU#dxH7z6^^_tYpPRrPqI$b%#fL^U_Y5uG6p{k0z06ZE5YRIb| zPfx!FJWM3c>rJHNDpc#J1{KRz?T8}MJ+pP|Hf`Fp{gHH)Do(CZ zr$H*+P>qU9NUK@9ZlmUHJ7%h_-T=}?M#riBL5eX+kb`u4pi-?d#N!5{>R-@)} z)lvg#Ncax4nk#S007x#|l(d0sud%|?Aj{cZ+T!rwI zk9{G3G+}sN$9~N^-I?6z=tJU<5}^+A5fy!ebdlOh1+0$au;pgaa8`+oqZ`zm71ey{ z%hbB0Q!AKCT&fxu8EO+(FN<|L$%4703mkt>7ZK4_Y;}V&ks=>oRjne|wMNr35_wX^FZ7HX!UA&aX$CojWmK-^# z16DFmMX${byOTzg!!XbBO*2ibxO@THF&5QsvCJV zzJdMGaHNxT5^V|7?qypVr8FQFR~0|4tMgg+a|#Gbtg#W*xSUoQSx% zBJszKK*;f>AssZz?edV0mI$e5E&HQu3bl<@n>aNi(l#98nM+tl@vDR9 zT}@x9BKh z(sSMSX&nbm^(Q1g$^IlVo`ov=&oNJVqw_s>!B{vhDGFGdVx@$rk z<8Gv*tpy!CjN;?ZIO&0HL{wkWsYX#GbaAexTiO`#IIYTDttm+}S;u)+=N+mwIb}ZS zbdtHNl9E@1bgFR@ddfQ1QQPQr%x8v-EyAM{a7ud3jJgffM*A7k$vIh_2i2LjUW0}o z2~W)`b=FR+QKMF!di9Qqju#CTHtoREqxfYC?noqG-6JBM-g8m=RNS?gr}UH^4lya& zWF9qyhlc9VxVW~^QOD_{eI;8OMl`OnDs+?zo}67pr_9(RcR^3^XmpT*X7Cvmw!|fM z>;Tfya;g|=D09?fLOdB;v<^-b9f!vL)QU8dbmU%r=CxDJ)rHKXev{Z}hLn>|Ep#*h zr8AR~*NRRBEIf*DJ!~;MxUNfBr|c_^h)Yk_8GotcTLav_xU0Bc?l+ySn9b19DA&gp zt^@6-z}0x$$~x`{IxSH5CO=qVOYu?*EsNjiHm5mqKAEgF|BJW}y z^=!ql8$3yYuwM_;QAtF^8x=Zg1`nBcE9s<`sHi>Au}twrCnSGEx+pd3Q|U6aLDS}K zI%L*MQ98ObRr95>*|K%}jyc`Nu}*cCY7?z}biSBQItrlDF++4*K!b#iS){APQ6D4o zv`&@NlCAv3&x0*D0f|@`@)ychXI|xsBO_O8o>nX3*#RAO z!dlYNDOxQgwA5v&osc8p>t;U z-hBtIC0$gk+5p$AU9Vx2W-Z&c@BAp~B4ZPhQ`P1&gDzp~)_qNEIX3D$b;Q5NIyL`P z#p=AE7W1_9uUN-xQ>Y~eNf+q2Z&^qB&=GOyWS#L>IlL`PlD^MN8foplnls)N#+JVf(k8R65^MAC6il~2(pBh$uY^&{M0AC3mHCP2hy!b7wqqUvmBUSuu>`&E5D?M!! z)p_;7kUwc-WMpE^S4bz9A9RgaOP%5~K4V*TvQXV2X^4sWf_YQ}k16h@@0dr!Ss(H7 zKZ&h`N7+)roFJXvEX!z%G5DoD8U@mI969UM^(tLa$nG|!mVUWU&tKL38Kfhb&PlkH z-WWV}SDJUw>P}v2M{O%?6?|-5F6-D>MWRkqDldK5A9W80Om!!ZU>(Ot12vwmb*I1| z)hh!bE>R(`;a;a)oI~Tfro$@;CxV_Xpw6rIF zz&f=9piLQHR-~qVE&ix!s&O>4;uC*@t(HhbrQ@ij*XJsZ;W#t4Pcsow8Gt zURROcnqU5;u9TTh*O@tNOO;BhXj|Bubll_WE&w)^BU#4-il?AjQ`2X$KdzbURk=zo zVSl{ZsH*86Z(91<%%h&9dxWw<-N3w%KVG%k-vLMr)CHBHVrnqEAtHVR4b@E zRaR(gy&F23HR?>DdMYvL1J?1};+Sc2ehD3AfaWxH$YIjaFb#EPZ0t|WQ~FR*M8q+z zBO-e0IBb>71AzvOphsZelCT8ZR3OiB`xT^&Q=nNJtnWwv;?xok%y9bvzJg&E_Ob5giY5${+0t^Tbxg zO_PB}Zd}}4(otV<{7rs(wRP(^Y}TSx zyN;c*v*}B55o$H8*+6O9cgoD|aoPgXMa3vn6-d2?jm#FUJKn%NH3O4VYSgYT}58hQ?t7DBIwI}v`EUFR$ZcQYUwZd$&{ltE2^f} zX`c#fL02gaQFSVKy4xb^hIo9z%j2yv>tx`o?o?-r8a1*>7okE`cM59PZP2J`i`H$Y zkuF+ApRR6oHc(yEx?P9$&?S?uakG}K+ji>o1pKjcJ`t#ME$b=;tUf}gVxzT~25?;b zE5u_BuU9mnk(7|E0 zucV`%qoWh+xC+%)n!s`KT}7uTRIePTlTP)n>Oy`*KvfTgKk>yQD`ph)Fd=DlsAC*> zGA<=y6SaXe zNEM%}d3>`~DO4Y9gN}CJ@%$7mHTAI&Pt}DZsH3VLKLszKQ`v}$dg>HB)>Vp^K0Y1b zk?nJ=W1<=aG|`h%Uk~so#Qz>$ML=(yqK^MeM?NE?-aduDztUAi5)tvvDQvZl7D_r) zZ$|GS9vjMhQT-eL8QZEM8)8Mre95}XHAF-lKpixq`LwDg=;4q*8q}iw5jqlS^`HyS ze`y}i4Egh?)=4!SP!xZ0Q6)pgDocdAaYs7hr~s)AbfoGpI8w*5eN z-oQE}k7`v{%GZ-l9n@<&F*ideCGz(_(MhW#BHWNa>Ni@=6B6%c9gh_nER@37heEMv z%ZP}FL$(#s1a&kX9wQ!`QI_bwLQ?W})~QoD9dwdW=dagAN4FUDu!?(+>!_%cKE2O6 z@u*Aour0;Rn{0LGA}#%E(#f8iwzYixDz=nUbZ2z*?`+Gt=LFDPh?5_;Q0~bgM--a^ z9rZ7*U^Hp!YaTUCWsCOrZAhmDy0TI?4|@xb6Ga1rvf5AEaxgshV~4PgDpm866B8dl zR&*Q+Pgj+#X_fr3Q}rjPqufjn<4J4sphE`e{1H2sbQFhdJk|a-DP=k9c$!lNDCF4H zq@$Tif=YtQLgIyD%emq-sLWnmStrvvZjgp7)Rj_lLnR#%Dcf5`M;TUw zg&()2K1@39a1}IPo~PD$k#w9sUQBqivYTzG9(_baympe#FoHUY=1umeE|aNN)mFMW z^2sS||7{(mKpnJBe$M_>`Y5R!aeVyOp*pA+RU|44KX5D*6!Bb8>y(69Eh{q@;v4+?(hf|{#vbwOP zF-oJF#&jdLg)_-vv>DQIE&QiB>3De38G+s|NlD3Ke-)#bh}mpQ^P698Qd7Tn#$eb| zr|DxPY{gpQ8815NUW|q5;!l0y28UWai&&>B<3&O(*yv~bS?Af zMlQ`}b!DI);N2y*bgJcG=sx+Qq>~kq)O|-5K&rD$@zJw7sW!KnqWI((!1fiiOul>*RDo%EVzIThyU!MzBu8 zQ)#AV#ElQxsta@+Q$n_sK;o(AILuQyrw&pVytK?N6n|<>j90ga)VI7EHEyy&+fsUX zIIDND#THYIo0f1R=~zP}n!Kf?+zZ=K#Ht7H7oDhR`=ercf^{k>YHm=TXdm$+>1ZOT z-4!QU&C7Q}I!U}5`f2-FC!>d(qFfwgf0R}keo7VhgYYoSqWQM(i3(dLQbn=+<6nwK zZKZRjN=*&9AkdCc6(`l>|XY5W@l0iC7sq#;qtd?mLJn0>(H#)kd z_Qy5Qa7#$aCLNx&(Xv72r;9(hmsMf_Z29#gn!>6>Mra)mU)2zGb80HDyR?2;x+Ipx8seVt)jjqI&#GxsI%VFJg$JJQuIgQRa6rd^=X)` zjF8V+Cx+VL7w|{pmij^+ao>_IRI7MB1Rk|bAC+`su140+!lNmz{Lxyc-nQi*15|CG z(}x-aYMDq(Bpo%2t5t^TsHuN6P*pyjDG>EK7_ ztDV>?nq+_$=p3=-0LhjD>;-?^5=^?@u;nwOG$Ve1=qQC`uX-&yW|+3+^AFV%7dI}X zqcx3&Qf%xr(y<|#@sNzMD|9MbTuDMP+j63G3L@r-j;tv<8qTqcSQn!3hs71P+|3l_ z(h6NDJLROKLVYNwE5QSagIvu#cFjzx+zIityQrwO&`|>=zSy{n#a7qA1NyQG9{fc| zZ)BYchDNERAn7L3QQAmFCslRaDgG$SDx1`k2?-BDM`@9i#>PIu{xB3MV3q7=SSNi( zDmtF8%u~^*{3pChIyxou+dlM7wE7JXfTuhvD~>VlFzaXpkcvV~O!TTL(het`ibSR3fO_~R_9 z_|}k)zqilLrD2q?o^*83W>0k`9aor2R^3M5Ti^#L>O6HT=|V~11jgOPI?A97HL`t> zblhCp{i)5p+IKz&o!X10)T*PlaE%)`{*-lSDg~_eSzm%D-9x>mzHdspP~*7oBag5y z)Hv1hh=`-2tHh0p{)Kd$VD;RZE=*NB;+qjg4N0}9Q@1SW)t>Z*q{B< zY9h;`*qL;ywVWoNgK25K#g=1GMKp9{`?F59iS1|tCnSs{9W_@m_)v`;&pfn)vltsY z75?a}hP1y_JLB4=Y|A-PT9p@d6K{>^Xz-{*M#lx>PgSI9qIW4&{x)iVD#0>>;^H<} z@YH;uHx^S;?qr?rO6tkjxCe!&h7V0>J`$c1e`?gJR!|~T^R{b$G|+fF$HeR+9ghQM za-6Se9z{r*RmbZUIyR<}{yyv269+wL8nRPN2RhP%cs!@I# z{IOFy9jT1Sx`Pya&BTCeWGznX-P=f#ykpvtKe~TKWsSzG*H$4Sy4xx&VKqsS=au5@9O!Mg6h2uB& zCjnCuh-b8*cFI&Bnby0M|3TV&z)5md_x^>#21&pY1Ofz`EeT_w@AiHk#=kb@yx#!G%o_Sq5y&Har(NAd(STU_t@L7GR8wlbnl;nWV%d2CZ?WCu}K=Yp6%U!E#CH7$}mc9+UIqqiuU$gz+k({8Sof85YG zDn=6tjT1?CTeoPWOtDe$(0@`i(nKA(Q+4S9|0Oj2C&{Azejv0msf0)x-tY0HSZR{` znkES-&4~KDNNBi`LMFvP)|DTwXl0MDs>hl~hx#P<&yNjF7c5E~qE8Ivl;?(~+(_u8 zSUyF|VU?Pz%F6?us%X;wOGxzJZeJfBkr?X_3yn+G8y?E&$o#dnoT>zpC{nN%eYYkV z0-C81T_tCelVZMh?TVqPq9;M2Q%Ohk-S7OL6PgUm%0H6r720iCl$H4!Bj*t>e7)5t z^-KS~LD7swj^g6)n}nuErzV%yuKjf_XAXBuwY>P^+Z9dMA;~py{82@d)`34=U@rKi z&{TOL(B#G%9&Pv|p`A~na#x{ze&_2#lVl++MIV1_|IyQ@Q|y8Z?@{_tXe1@EzNh4r zmr_+FEbA|L0{T=trASKQ#X=)ssuWNkj%oM_Cmrdemq~vmEH*C99Kn|^Ssj;u(BEn~l^b~d z0O^tLRW#}Tq?f{D_KENRBuP{Ar{aD7`5PR~JT7$q4Nnl-`DI4%yhq4k-N(mM$fSms~Qma?&EG)PB&*g|==3S@X#F@lSZd6Q1~_ zsj2rUIn#@se}N9T|9@@BJEu{t+gl#?=NrRDRMY>@4F-lPUnfos8r^2^)QM(y*oV>X z)zmwUo$f+U#D?S#aoIuM77S4S7FsxyEizygiW+9Hy69= zb8vDn?8}$=%N})J6hHdBs1Wn=^P)P)Kq24IGvR^wG1x%{3J^aQJIFvG=HsCK2sDtz z&_E38AcIzb_(!pW3=|;7O&z44zA%b-IH>-|7ewiiHBmIPCd$9NCaT}NCQ9FTVHE#3 zav*yDg;9oCfb?%JhzgK??ZPO99(@24#7{*QL?65`O8yo;X2jz~sXSoxVcf$@G3%FK z6lFX>kv({ARDbyTD8F=V6#oM5{u&wFCGTDzMR(xta`e3YlBj;;c~PDsj~PAhlBkgQ z-g$8pbD_L`n9K2>$2@XT6h9vN8`ej~6y`?40y2;jw*oWXg#W~^ju}0j`27a{@m+u5 zMNxqn^B`UQ8y7@5sG}!SK2NzWIO9@vWo!tp}F1fs7?8Ce@854t2u49uK)UfA{}^dc95dorVCHWl95rO1*EbNZF7fSA zE_fIszY!C90ph2?2ib2y6BGRfi2oPq_;u3kQ-tBUq}kJ;gZLm}&Iu1@`Vmazira`2 zk37WhLlyVe=lyHj-Bu9!Rw-&#{lZsGf;mB zb{-KZbj(Rs-K3voX|m_Z$S1`0sm8|CogeCa@{U2+h0nAv8^=v$C~E3zP4;rm|v{C(WZ_bK#aPd-S#@STA|?B64e_>NDb z`|qi14I!pI7*j@3-;tClp*A!|DtUHIY=*}oSZ@S{kVHBW$pXWKp`f6 zC;v@6LDVI0etL;ixJu6fHpFs+|@xwIg5CJua1rk6d?W?(gUR5!0k8TQFl|?wfrn;a2@&ah)bdjTKod? zmiit4AM)_wlv#n$uSM5oq!ngVCmk>gP=5q%)CJU`>yUXQvLJgDa+d>W(WeQIv=Mw4 zAjNHbJ+hBR7UZ`RpT|%RK1DfzUYCc98lX+K4CP z_cL$@qB&$Ai~oGbG5SFYtq}V&kpUSfK-450C!v816dqz#!puMcVrf?v2oG+eHu`>-e8o)uoqB$X zdOr(JgG*`m&R`y+pLzuGeh*=}AG(gyUh`N{{bBIGMmqf+em@nRGLD%=pY%o0auELn z{uR`5P=JWGIQa_nv!ofksLHsq`eT=#*Ca8;yU>|Lew2L?5 z?~tvMTaI-%Fi%F=2ljZk|n=|14qs0pX$zPW}S( zMdSgGD5jwP9KIL%2GQ?PMm~W2`zXJBN3_q$cko~IpGSEe5?1WdcfmUHRqU9_dcL7$ z*b5MSlk{1^4JhE{@bWr+|D)&+zePD%Lzw3%6O`Km#LvUzfvewIUR0P!{8DDiv-`NDTW8Obnn zlk)oV379FT~Gz!pCZ6te&+Wi3u|_o+*wo9B9bak;^~<;-AIDO&v4iQLXwm_n*0(C(E zExtc-cnbZ|A5ey0LRx?fM5m<=V7~%8C_pOdvYBt@HPLSork5i3K>F%0;`U|m30EC6 z`V(|w)*niKV8$=!8@cEVWf)!^dj<*+-;6ux5s&cJ`OZN74+$G){0hE7`ar@hCNc$P z^dZ`4^u@1)52CZ=KW2&<{TX=#;tj|`i!Y^&y$U&yLd!4<5Zy%lu*a{42Qm;}LEXTN z{v7&iFuz1yz|24ak_Vw%c(3LAJG5nY6K1~imy^$!8Tg&uDpOUvGd0GEjgV*_8N2 ztTCj*eOqqz+kj6KlZxMGAPx{B?F6!s=$s^VxqTfLWh`&jl*^P|! zpG|bk(^k-*Mt=hzM1PBkn*x5ycl=A3%{$xB~_4M!m*3LuCGgc8WSxe;8!|w*`oQ1wG;) zW(Eon|0*<)fda&D!VWS}fat6E`DXGMck#mrJ19W%aP&Y=;b)k2@-@GmygGu88NS!R z{~Tp%E%J{hESUAjz^BY-xQ#Buoji8;HRycjpg>RjztJVw3!X{(xAB9vF_rp{8NChp z&4f>IDRa!hB~fxW?KFt~g7yh|9W&m7J7jad>wIS*x{dII=l}1 zkby!>^0WYvjAh8bWF2@cx*7k+GTwRcMN#rq^5`!K6DWvFftmaj>AxLaAmckFp3(aN zW1u?7pcf#%5*d(z0>nG8gA5cPz6v`?|BZ6P*dzJM#ZmHN`Z69NtREs=^s^ae0pi2B zdq45SO#T@^Fw>m0;k$mn^I88npE>XOQGDL{Q5_^_pn>Qtc94Vkrt@jXkORr{;e+S} z@Iek@egGi_1xQ{5A4ER`ALJlT;e!GsFNP1IpM?){5dR!}kh}yL%nUPnDSVKF;?$Kl0wgbo4=oou?o*IKOJ0KsqSwL)If!2eALKueTg>DZ zWI%+y4&v9t2L(vp0PT&)g7_DZ!OWngd>0_$M;#h~5kz#QZ=+3hI0pn8~lf2Ta1FI>Pg(m2ZQ5^RzK8M! zQjmk_cI+SpIf&ki9i$)!(fhE2=v|l~1v!Y`jUA*Q2hrQHe-!frm>>l?h&~ALHvy>t zUHLnpy%QQpK`!5fFCm->yi~w zCGG-oCwd5LgdYiJD&K@V5n18!ok~1@hi?#l3_E5bkZ+KD924XM>=9=43FsgN(eLpM zQo-LN^JhT#pM)p)6!aXs@csn*A7f%qzXI)Bm>>tyx3T{|=BL3I`35P-LG*{%K?-sZ zeTi>$=b~S9i$2`u;{Hy)|CDc#$T!Hv{5B?t2uJi6@IVT35d9@~kb)dUe}!Fud?J2< zgm9-4b`TMd1f&ul@#_oN#Uu?P2?J@6fK<|gct)Sc4pI>PIo}`!If(AY4pNZIx1<-y z1(Ig?9o+@}v(P~<5Iy22NClsR1`^~_kb~%tu!9ujAo?>oe} zh;UN}G4ATnQ_ScNzCjM+k6;QNGed8InS7LQ5d9APHvRDfpo92>vXLh#vwT22IRIVuB15Abu2fkbwfkmtzMRC_wyZ>>vY$nCK`T3jI>( z0`z8r$AU+|1NF!7EqFL~5MKrjWS{`C$RJM?9b}*Y@s-#?1_}`Gzz#A{fcPrxAOi)6cVY(_ zC_qda)j;j3SfbRmt`=Egg6d;y75}o1) z$UsURtp6_cR4~Q-V~O!Ph+od!Vk7u2G`9+G5Rx!3*X7_VP8fc zW{Mg8KH|{Hy{Jz|0GTz{thN6(3yVBYHscId~xYJUozt0-5+}(E7Ol0(8t6 zGX*){$sa(2pMiV@JwxJ%SqJfeHX0NlfgYd2+(f)U^kmWxdmS?e@sC0KB6>t0W)9*% z#2-+AyDd+=H4L#7~KZ4J9eJg7=puP=LAby`Fd?3CTHz58VCW!wF zJvZYXcNyOq-|-cM?^Vo&U(FmA#NUSwQs~hcbo@7dY-in7zRwa*P=Mqnuo+npZ6S=v z*O7@{vxfa%=w-M}L6{a!`n_zeIKe;el6x zRO~Z+VAe z0Xc~O2RXGfR2s=BOOOY3kYSJSkBPfFvMJvM?sC54S0VoZ zXqXxPMwEksdX+(o9tdCZ9$uaA93+&9=*Nk#l&QZVEd`X(0wfPY2Z$bwJjg*zSxZ43 zH_5}{gXl6$DaW`?{+7ISKyofaHFdB#(yv82BIu8TRUa7ffOXS^NpM2C#d&) zNAE=!$Uz1zejjq60LlBIf#?IsfE>ghgb$+Mga&dDOZcHBA3`3)KZ*<}K=L?fAbLFV zAP4ai;DZ80e?}Pu$rF(S(UXv)oYgUN5KkcsqMsyeuc7RI7(U+xv}7aS*mDryfqUFV zn=plrnL;ZB(36iq2RZck$$Qc!^8E7TzneH9w~ zI%W=H>QM@^eS~d4>55s$%t3qrJ)i)|HKaF)mf?dO#5ck}1Rvznd}GhAhyDz{LGny^ zm>FjDEZl+kTI|QLAIA=IkU}d!aveMnp`#9x!+alshFQnVK|F&zC_wUbcpy3oALJmO zg$GiQ;7|P1e1if+2cbO;H=xdU4q^$rgzMSJf$TZRfP(MnxyXTB%m(}u(8QcWu8teb z9D5AC0131LTGE6M>hthH1mYI%Kmn2kXwQS!hJF${C_vJ|9jHUk;m0??19iS5Xc_Jb z>=9|5EMf=I5`2(@xQjd}K+=N`>LUAzi#R)aQIzK3V)l(b&7Q(%_};)i{bxB}^dQWK zT+Fx|d{ z_FT|W@Lk}hj(qev>d=J0_yxBr&Rx&f=Jm!*U#aa$TboliYcuW|x-oOZFYeX!)VROR znD-iU+4ysfF^kgOvy9$nYjfu>8@u60hJLGYcgy=V|C$#YxzcQEdurU(jhPNKJu>FZ z>$QFJN3=QhW^Lwk+DuPsGc#sx%*2>=V;08DjNbIs+Fkv*+MIfkvA{dWKCkKDHt}6H>2bT^-)8KEF(czo`V8$ZUee}_p-0A^ns5~+{yUAn4aUrj z`^?CtJ)>{Igy)yE8I|d~X!u4xG5Hif$I$1snVbAc4Zm*8$jD{Jj7lnGy+PvMQ&$o>|zE#t&H)i%4ZBL9@nDVmuwVGZx<}JotHgdNcxedmCmoXzFmzeZQ zOnI95AFVI@xHj`LeV?iAMQJznu3pwZV`j!ojhP$sc9X7&vBxI=izTi1jER42!c&yx z$fVmXU(s@@DHqGPX#2NK`KZ59+hbGiGE*Kl{H&(mYUGxUSr~ru8O=|OyIYO@+n?6- zdyIX9@h>UOPZ+*Qr(29YH+mxz&dkVfxI@dQZ_;MH45y*jjr?6k{(3`C4E;`1UcX(+ zFKazn%jh#^extT0eZzmAHlwn9E@=Bs6Ti&pDU6vKbL!``+!=I@-qDMnqItBo2f~U zJ4|}t@d{19r>yrTT-TfWeA4g}W3Ds(*Ji_CXUxLzFEeIbhRfLRFnTweaMq2PoABLY z%4uZivB{^x=-F)iO^tt&vC)bKMyubXx;H|;=T%*fRHq^$pj zo|Wx|G3y`G{@iZN4aUr#ZTvT8Va&v|TXkcm#*9sQDSq9=?>DqrH|0W>K0(E-&SNQ@hWMSr{|^Eu+_%nK6sfZuDejINo98jhPvf4d0lVF$-hHrv0y%>152zn7Jv}*StyVxi{73HKsqy>)L+X*R>fL^ZMV{ z_Pal;&HRKmcmAG{Gw$v%a&be`V?)2!$kmPg%$=H_8M#{x|87Gs4E-`=uN(W$FKTz| zzOT)DzNgLnOGe+fw7K&Sv^iti{m7KZWz&Dg9nDWoy}aiA+J49Tv>6$D_7-g~j9GuP zw%3jQR%4HTS<`cq{`vE?Ju~*pZqoLdv)U|-{T5@MH0I4`G{0`lyN!9fF(c!C-Sf5F z9md@mL!UC{J;uz8d8aWGBcGS?f2P)xWyW7)&b(UNV`JtfoeE+PvA=H<);2rroI*!pPra z(&2WKF1H!E*x2uSgO?y;Qr;Zr0|qN&m=%f5Xc)JvZ`& z3Fl5jzuB0#8#6L`zWp-ou5Rde8*}sXHN9L;x#x#J{2`Actoy)5O27D(X)JbbYDEEkx!-HH z27@EZ!%nX|2zj0EeCy2av%`v$`CbQQ716*_w#Ymo8sMT6G)`DR2!~@}T%xCcBfJ4>xAEUz)_Ep?i;sZGZr?c7*9 z*lWy3=aiZq_WG@Ji|y*(2VF<{=TNk5>wOAVDYmP5<4Wh8p%dx*5(_JLw6)l349*p4 z5#Q5WT5j}PM1J;kWBEQrE_86;J-UzT&z%br>id)pyXMc8p}aM6pK{B}-M8#g;`b%L zoZx*+M3lg<{RSG65;P37Xmm14d zF~8YsC~rn&4j^OW6okoy$oVoyYui|C(_GW^9z|dGX^sA}w8386Tnb&&7@V9P_9t-n z-MG?NJeTHCzEL{LXiB0UXmwltPIGlGVd`|-qcYNM)HX-WrRBNa{Mk{yDWzq;))3@H z9Z{wHp5%yNjnf6$1Z1hT)Vfi*HU+AtD3Ux?!iiIj{$i_(KGJ`@hbn7EJyc{Hb8$_k zt)fA4ZGskISxu%77j057{-1M!I?-$_F4m4VPS5Jk9c8RtCs_(rB_yFvQp$FgPD;WS ztHe^ajtG^BStc@>Da!T}oVkW;5NZqCwhG<)vCu%W;kwq^!jA2MK(lJ!vUO)5pek8N z8SJIcY!0Uv8co~B)w&(tb0UQUQK_l{q2W3OTXHtr(3WK>h<-~dUzkXWv~BB%JJ*m| zAWUH}E?>E@r>#H8J zO0Uhqw0@S-wXVF?R?1SNTn3g&^&6AC;B}{EP zDfW%EJ_Va_xI7i|pw;z5W+>M2!irZkf&>)Hb)Df!a^H@07;>C$bcQ!>tj$xYS}QJ8 zD|(<)CWp38cHZiS&LyOCD+@MQWymY(CXul+V$n^YCD9(9s*swCy+Jj-+6O72Qdzww zdTLX9g&LuTfCGj%WlW%J>DJQn(3Lz(UhcWNETNVlcqPG5Tq9Y^SPw$ICA$)F(P~|Y z4AYexn!TkZrmba22TXUG!|q%qku)(-V1_NF!>LWoY-jqth0bDYW6kdyx(!|vWb$eK z7!f_(>mKM$X74*gzh~J8jvU%`{mjuLdt6gG-lYdOtZhqY5o z|6O^oWZIs-%PFhsy1r>?U1pS7UL)I`-~HZl+uA4#hYt6y+ieL`o0i5F6a)_hf`P}@ zc|fg1EZ}XaFiFT}>p*Xo2F=B}z1W*08*ilFu|7~VpDuM%7x3NwxFqzzx(LWFbwY9_ zIPD(m9IdV^m3%*~b#|W`qq~wNP1ml$pw*YYYG1$KW3G9Wfh>he*=!i5HjNVvWm@81 zk0Zw`@dd^>mDZi5p>t{o<<6-{#BDs57aJWN(eXj__@UxCW+U?hMH}zZ7YLm;mX~P@ zr`7bp2Bb6Wxth1kq+{6Vx>`{Znkx)WmWF-@L&w=^o~E)`RZ>5_PF`CF`}>V0Z>V4f z)+1x#z8m@V>7I_We%EPtTl3y1vA^AV6^Qs_%gz}qV|?1Sb;K{j*|B|uBL(gnTK!&| zP#xZY`MlgJ(8?bMbO+KsgZW>?mk z@UD?r0nJoEq?}m$h>FGtb0Z6eUh{54BVqDGBcZEx2K&w|_xeMxZIEy*-h@Co@N!Jqy-ZeihV3%@E!zi8lVM#zn%?Td(NK-Y zSc+?@w9vj0XHc9F!_|Ic*gB!o#rn5GkKLe0B`+x!CwqPtEiMd(G@q4`f}zg%4XdFY zr(gD_fr|^>-hAs?>80@4dMP6-7c4zga&~#Y_cUX?6<7a+G+1nTQwX6973qW;##5=R zddC|>a%nH2kg*+WszIJCQQ3RVpxn^q$*6Z@jahX#s#kUSxC`mjriIQKrGQG&Z@D<* zazFMXuIGnxv_;2osnGZDSf>R z>_kef!AxzwbLyzHz+Plzq&-XR*t1Cavg+n~y~V90x+M@?nQUyV&3TK>GV^UN_7C^2 zA>qtiYq00!O4px@@aVGi=Ixb6f8MLO-PY;e-18XASudb4(Q5e3w;HXfl=h^~3}+il z%Zo1VvhdJ4vmCBHn8gS;gAl33UfY$yg~eWj<;Gy%vur1Jp|2HsWtdRmx{>kJCd%n_ zSCS_jb53ny1*6sItAYkAm_;(zQHzw4M5kJP!g<<8e`?d5;!R{QLL0-=3On6qzdMoJ zq>UK1j#Pb=0)m$(22w0-I1JU=MXT)5>}QJI>s#`i>V0NUb{1Sdi&Nbz?FzEHFC}wj zc_5ozW!s6zji&5$xir-(4>bnX_Hv8L?oI zpbT_xab9QD(zvYZTDEI+ykzXR78YA)SgY}q8Q+?0cDd3exfSHKB-C}izAG7J=G#PW z%%5s>o2`AiP%vCS#2nLdb$|`iD>3+Nis1=K1#bXQ)g&*@^}nGXF-)w zMyX0KV^*bGzqcq(m{~d!I#d;o3)LzNe+G$1UWh$ML5Mwi5MqyB2{DDt=7(kJAXix~ z%oUCoFrO2I%x45a^BK}A%+t#SOLeMnHixp{7|@mQKn8kEfBml1K~L!-raDdr&}FY_ zIaC7O(c(*IaZz;;VOP)8w<&9C^u_Eh_`?$8vh4c91;Dw+e04b#zohG*9nw7R?w#3K zV_abaBE$V7VGk_oX#7 z?Y4De7)ScMrORk|>mYM0i#M3%+L?Y!t=?L_9BfcaU%@(v)!8Yt!pe`)HQR3<=`Om4 z-xDE6D6Q79WV&S1ZWkcSbAB>!kqj8&%(jNdP%w#pU=IsfZjj4ikoK{1tvl!#=|(HE zgOxd1V;Q>sw4}Hx;S$B6uTPy+T&r=49=F=Cd9=!~NXEt$VMnUSQew<-SeJXNUdo&r zo7QAt(DX;CZX+x>EwW?###%TFEmfE0j`ddy74r!1prX#`W>;U?lXV zh{SC*KGS%aPfQG;G@aIOCXD^z9@%qPqW5(D9_uq>sO_fovC=K?I@Rbb$|TfkVjNsf zKf@(rhOt(al@{NmQn3&qD!mSRWX=ZRcz0zGiX5-lgISkM-Wn^5F7r#m*y)@N6H;b| z7s?&-8Uth~IK5^lp~L6V)I4)<@3hNg97>oy87SARv|BTcc4eB0f1a2O+{^+{rJ@~P zS=z(q7FEGUp(^Y~sa4LliEg$}WOZ)Y@W<=4Q5r}mdWY0WpaXTnVe!Fh-jdwZrpdlk8X-hc;)S@?9jv&sku~A!nAYYy z3kxmAhu-R`cCGmvYhk|;@|Ymnr1EsGbmdfPxyGP2X&LR({NChk0LbzrR5#4h>mvaP z71(dIs`yzk`lZS?G5NKBL_2GUbh$E0WShA+)c>p=pBwb~&QZ_X4D)?ZDedau2+NgK ze;HFMg73Rs-&8{;%V~#8rfo(yL3dsfDuD>dE&$6EC-zs=36I923=mrVeP_IY9N1%h zKA=|-t-Ui)qoTdNu3yZ9@lt0HaNEu6*wsH0PWao+WBpFM-RkqBbnZmUn1SVVmsx*! zg0$9dQWg5cO4&A48`1%*XW`M`nvB3(2lgn}zMNUawWLz+*mYIWAp>&?w~ISd!nTZw znDxj|)T;2q=t{-ZreLdxQx!~Ey_uFCvPtsk$kkk?Rau@-;=gs{nltBOlB^#vvWbFF zt=3w{u~vVHnk2idBPC2cukx#5sPeau#A`&N5@e5WIVP9(Zr)p{}T|VU?|za9yq}j9PM}erR2q=|yI-!$A*PfK!B?T^OlaC3j4E9%nLNP0*UJ zg0LD0>Ky5wdH89HyrKlq^NtGN`YrIb6_yrZ7dH?_H5%qbt_$|C5JKxtMrO4 zImFQ(P^(s4C0WAvKH;(|Ne>(Vge>n+_P}AXGRIE|tlO zjtgMBsS_Rz-m%rOnWQq+8~=_e7`i~8qf6V*RARKHHl5}n5=@7P_`3GK93eTj-@B4A zUMwm}8}R(5?mAk3qOD!J6mjXtAxBAKn|JNzj18Sf+`q_)%H8cf{norUR1MTvY0mI> zDI#72$GG(*+iKDrH*c72EZFvfYNRA*aRO6jSnBtVs|)K@AsWZ(GQH8H7w@T$EpEmH z!@EF0^H}?DvM1&pW@WN8m+_ z8M2)8pf&Z5bu&g2bqvhZ(GVLDQDru9Izu-^8Juj)yCT7a{%j>|R-e>wQNW^eSVT&O zbQy5 znBdt4?>+=jR?N@sWvjbL!!$Br9uqie4UVpK)vWx$o^dX!BNsUla6CK?;4RAg2fxRr z+Bgp@HF>N%HGDbf*A&$wT*IQ$n7*mH_9UfKM~*ahwP&nP<3@v3edSsfB}?7CUcIES zA6ynG32$W)Y)r0j_Dt3oR@YiN=q|&H14q0S5caq_-g2VmAKG{5;Pj#CW1i~ej;ne4 zaG7Ox2AnAOY=;}JWu$$Q3hEl4sZF6Km1EZN*raA$CxbO3d78Gp1jq(kwVN&2)>(DcNrc?;)Gs|dO2;3`7f zyri7y-S%?`t-_Xt$W_>~y15ElAH_f5A^54pE29ZTLJ|CB_m) z3Hx4#c={x_L|^K{9!_)xCwES)y@7XT$K|gHuJi*o98;V0hCBzj znK@6qcwg1;cBym<$z|TjI#us_C>RM=d{q+1xn}5Uf{UCzGGM0o6DGGRB(mG8;yF1q zdxCYBk>v5iQ0wVrsc{E!aExnCleOwN68^BhsJR0pPSZLu7@hGBP2qV(fMY$Y3(#;^ zMu1#l=UmM!r|p_2kNJm_8GuTose2ZgT#h;Q;4er88%d5)8!RsdBQnR@SR3iGgXJ&A zOg6=SHk?O^e)nsyE8?0gs=C+W-CWJTuA3l%xq}L_~llUS=L~hVa&$L&9N%C za%eMj%K9*qR9@(iRcGsgL`R*!Q2nr!N^ZvOQZKbw8JX>HuI+Gd)`Z1!Y{W`6l$@YR zvjVEA8auhMB5E^L^#Q(q6Fxa>t&VwG9v39%<~T}SDam?j#+C_}N}kzUn(KI1eK@SX z(j1cftgVJ~eKVNQrOJ9CBO)2~jNE7`$(8GCMi}bu>Pm4ip&jGFd}pxCh0igZxyGU# zZ}m8*2@;o1=}_dnPM5-3IU5`bgj^bq@q|kELL@>t2*IUWsua2c5)I!xEujr+d5DTE zl4K;zuELV-($we`u%TYau?_=f_3X3c_-t>fbzPt@pjP6dx5A`kSRXp-1pg7)`Sw>1 z5IM3SGXN_{P;}#1nd`bUW>tn3$4_q5`3;!SV;Fm6R59v{swWf3l~~!3DL0%R_n*lgv!}r=86Lu3QX|xkjkWBO`W;6iHg!70;`5h1U&6BAXBGbs~dt=tu)p$ zvQd6}F3V+?aAUi2-j(=TCj)#|n&jjq1HADm6r6*zfl%cs47rJQ$(a;s;ZMqq(yi*3 zT%Q;CIw8qbMzCfeJG;RdWgI(RM;5GH3NQ*Vy+DvCwB{pixz<{hMgbjiSxLcYuxY9|e)5E&g4py~sqw-T^tRw05j3(u7-*V5} zr4uJ|7Wq))?D6Uzj5jx^RAP@)DIOlDGNvJ^`h#OV<`VRVXSt#loJsZEscJLIcY}E) zKtyd6^?XEPZDtWwrnuGYRo#+7RhM?!CBuDA9CA2*mwzufmIPaI9x07*$__>-{5Ps#HaPG+w>fUCjsUQK&Q=Rp?;r1eUTK zIC5z(EH@_{$+T5m`MJUzyxr2J$RE78q+1DZYqDQ>!;H#y90h*Zyk%N89k!ZYGQd2* zQQ!$_D5cseRqO1#R`BaS!So48?(fT>b7|zinq?CQa-babLzj^pR8yowW~7%s|nzKwB0IQ!wh0n(v{Z9&RCCb^3dBz zbLpZrP%Wx|)kKoi@q<=rloi&<(AliqfOMHV>R4SZ7!}ZqE-DPGg?x+v{gJ-h=cSeI zEjQM93(uXJD2a29I2ba9mb?F@*qF5sZUnFeX|4sG^Keo{S}jflkAZL*PWi~hbm)ew ztsB*ys4^JlIFs5&wKRq$BS)DiB1*`cJL{8BiaI(dYAxxlOtqmBUbofmW_klXpIg;i znT=Zk?eLJwnz6)6Ludl%xB99U(&@P^t(qcnS(Qu7&Z`0IabslLa?Q+NykOYVbWd*hXyQ=pRm zl8ElaZa804wu-#kbP8UzQ?cLK!FN-RPI2XfkpN+XJslGuO0i{8`c} z#TnLB2B1Dm+PB%2rn|drnQ|CNb~@Z(I8-Vwcj3taYJi->t2}aJ_256>He_Xo%UfCD zVQ}U{vn^&Il^3XFo~7yD&K;A?`D5%0sJ^$dHW>26X8l&j-<`veW9xxaM#J85aLIvd zd|y4KCWxwY+a-NK<(&svN;8qD?uu1>tg^>w4$Im|j5yFK31dSiSzp_3tw)K1IkfNc z)hAX8qO@-8Uoy}h4uTa^3Ws^pj#SY%3Rs9${e!5p9*P2WbeU^d;f|Qc@ieR9P4yO_ z40(vRCcAKxu4e}(Hen(2?m6sjEy^B-8u;2!@nqMy@K+CBPY|n~yPhcKrGtG9G0bB1 zM55}TDyicbUZBl`imc}~{fn+n)(uCxOqV$?Z(ee(4$$G45opjH8Ap;cZh_elS1Jc# z3|VzSmAz=6WkYX>YFV+>cf)>$MTBN=Ye22(@PL_hAY}ETnY>o#9W1L^29J2~w!*xW zx4l4~$QX5Pgw);MRivcDq!=Fl2gAg?QEas}*A}wb+-fdyy$8JLFMq!3%75Z^zq@_+>`{}j7lJ1%C zJsy2)Ko)%%;I)Q_d2-OIQ{t5ueLPyFGO!lR+D|jQ5yfD)HxRN_%3~N}4<3+M3LVj4 zaG%#TAy`iFT9ChUC?YFo+yQtzFRxGrSJK%L>{zd*gnIi^goHN*h_n?z3!V3TZ%Ib? zmb%0$cHnR+u%Q4=R+?|wvh~$!37Thrp_$8DZtGQjvIW zoS5nPunmh!1i4r}%Ou27(q1_w2aTj#6fPk){b@R^`+sPfNz!*$#3 z)A9nf)un8HH?3R@TyawNt}7hMF0Z*+6^f$n-iIW{e5^-!&AJqEc`_vw8zG#mx>@ca zU#zx|})lMqf+n!FFk%X(u}iE@4%?0@2F;rl+KQzAO+Y z?y_WL!`SZe!mle^YI0Kaf~ z!=jsBvqZ7b?=77;z>H9?j`+8W;PJHUct*7eL)MTgr4Ggc9t+Zq*({#eSO{l7ejA>@ zG%4phPs*_jFQkOU5-WbF*1mMG8qfOeEA!4g2Z{o^^IP6upXGvyr;EO(^nHYD=0TEI zUJRKHnHEY-ZLBWU{jl6|?7H9rlB}Qfhps+pyX)?>eaRD$t3+1o5>MN?W|dz)2uhBr zPcv4Wv54(e_PhL|Vlp?fQrcQcZ8_cVMD(p+cEG*o${7eMf|KHi(BanUeIn&Lta;uG zcOpyF8);Q&L#+SOpoXef^xLi7-ifxA>J83zT8r~10wQ5>y2avBQkMWaUb$OYX~gBs z(HL_1a(VF1mlQDP2ZuvCUFxd~m-5FGV3=mZO#0s_UB7F0%-N-7E27HDQ5yYLfAo`)G9TLQ)}U+;AMHPj58|U z!kTJx3H^QPmmqQL@|zIIzc;mZKqi?1A%HeVtC~LU?t+#!d3!Fo$GGBCl7c zgfm~SmXuCcUaf7*jU4OVqg5)Pdi$1N8?mB_uuomk@mhU3o2O%E1?2$0uCOQEiii-s z@v?baciLafGPF@C^8#6%n3k$c{FIOwejlZ-T31PKN`A-R$vzKavMq~Eq-33%U4H_&S@ zR8Hr5KQ3WI-Cpo}1!YsdxnMe)^H5a#FAg3YHy_cb&BjbqbPF)Tm_TOit~u; zXo0M9$8kDcVawSQE5ZP*vaPAR27hf-Q`8BO(A_+_+3&gT*?WaU_T$D1SIUVLCE9!c z+=!`lT=fyAD=TGhXL?E1OIRat20Xnp8&2Du6YH1P$?<++-_qq- zGHWSw$*)xUl%(njXM&eZRr}$)Rs`RvjM97oIu<*mXKG`;HF5+0RdquPpKK9g)r0xq z?zxiadq1Wj1U0O(zRmZh{h2JqoQkkpoyTu<)h>`e_+TAq30>;woU%a^H~0VK&y(n}1_D z)!%&cUG;l1lQ`J&e#~H$eN=uvz^az@N}gqOMF0n#wk)s_iQp2cBTo{ab4AkE(i~5o zpFnndoW7F5c(Qk%FpzegmQUVkqwQ0#9!vG!TJ?puxcm#qt{4SmSLg!r_VHf2#d=@5 zGd?m4l{U!cPcRg))Zn&~rH;>dN(7aUM|}N_AumXBVk#Kvdprh2C;Hxkf0gCMMpl&w ziA@VSGvCVhv@9{QM%%lFdA~pPRlLq{y4_`o$BjH7S6+OCvMgs0dV?$YWZRk3*kYXE z|G?>dZ?@B((X&V!qSFn2LDSn@u?#;}_~0hMA;U`tyk*$JUXE+LAnkAQ2%BrL)NkpT zk?RD%n*Mm$tZ^OCajMKj^`JKVZ9oL2TT?`D8>%t?Jbr>~R;5fu3s0Vm)y_>UB~AwM zP|%DGEy6NA^fSv#lZD^~Ymb35dRaFT!yfLP(dLE(W#g#WF5g*6w82q?a5rhb(~@Om z9egXuz-iE8euBpo4@)+eTs!SUmEKLwgynHj^jK*e6AOP%;M`lGu9P(Vs3df!eYnT- zpCeQx^(2P=#Pz+SA;s^7)AM2R3Ks&*i7EtbSk%g{4vy;rJYpCcj}Z)h%?fc<4;~SC zRY0tV(1M@F)EUMYP3@%l$1CIjq#_36A4|0wLk<492F1}w1V^-2dHhVV|KlNYxgy-# zliy!B-Rd7%V3=zC9u1$0t-MUAmb5DbTq~|Ok;7wslNO&3@LT{bYsIbG zfc6KeZgZMDs7&yJ{&GLHfPTdr3P`;O4z>~vNJPRv_`>gCiXcm3gK2q+!5f2>^1=^J zsaiKE;jzC*im&Hxp!$@EjJlec|VeE?CKQj)4U%^6R(29 zJv&lm539yhN(6<{zq9J(oIjpp*D|n98 zTAX*ngi(rQ%yG3OZ;YuU{V4w;F4h0E<}2c~HDOR79O-JMHoU6q zCR=&bqUv58tAsv|9ydB2@VkX8m8Y$QHqVc=s1R7)v{4};Tu)Ogs*+`17Ae{cOUwJ| z->f1<-B0tUb|6AB3vRsQ6AW>bxH`NYiYk(9H3Th(lGa+na}FHsmZz}Pik>v)R+-PJ z6j0@YBgK_p<5XnToq8u^6mgf{O~Mn-aatb~>nORx>sI4f>N16uHsMkF&00{n=U zY-!cTI#(OqL4PvhmVu4(sp@{0z7!M={7ldkZ?`PJkyl|VEB%t=DD~P5kL+EEQdEwf z$TKrz0y5BO`ap@%d&}ou0x$7 z#F1-6ETyt)8PZ)l9nxK+?gA4=Q9>-gu*C5LMgx|o)Ud@w2F%a7PB} z!S-IVEmv&=B-}j?#Cg4djjyIxf@8VY=yRdgn<}H?jyIUqaPmOems*D^waB~)=}3<< zmMN(PWA^OQTrd0)nWilWGkaVSw7+s*8CzRADXLBs+JIS3b$G-mp|^OdB_kt$P-f18 zLK;XXVD)(PwQaet$F`K* zLe^P4Tj=dO=`EiLe?J||wUk!x@%)<5X*vfjT^3xHR~eNed1Bwe{U>IRojCT4nSC~{ zC2{xk;k}k9ih}D*!Mv6g0a*d$4kg`;jDC+wgD(pMS1|cn>NIP!a%j)o_zxMU?QeJo zbeSl#Sk2bltS4a#60eHMUXApy`t-3PaJrqXFpnVXPU=uN>s4162G9Ssl(bru@`TkA zlW*s`pzXA-P@8HshMu~~F>;*+8oqs7r^owZxn-F2q7^@>a(cW2k3Z_f{A#uFSr*J# zaIn$kTmQ=LC`J7sFI7I^sNb+1rHqqh1g?Ig+4}7N0B=PviOb4>oL_R%LesDQg*5dW z%OMG$I4k046El$L`uQgn(f(fU*c=ZeN*@%_TkJC)m$K@Yb4O_uOZm}E8%}*VoK;@^ zi|Y)(%35=U{^7wv&CCJJbBs*TUK*NdE2SQJD%uolPw7@S4u4vNW(|)12|HjFk2uzlF#MxFV)0B3L%CRi%@7&ZUhA zdoZ)&LEtYNXPTxCIa*nDPl07I8GFB*A5$vHBX6YRRWQ}V z+Im$TV;I5eh@nC@;{{tPOw#qmdw`NDwjrKR0tGfs*>54cBo#=%ZG(90=DCY8+_P7F?W zN~pDLy>f@MT*>dfTF#cu z{Bo(aZQZ=xbG3c*)tw&s4QFI1+p>eR0?`5tI6i>D21CG!3GiM<@u2vf5OdRYJ_GQ1IazB zQY>5CO*^rAzjq*3FC~<)_e-u~muxCyA$G|r->x#tC#d}L2`bBcg32|YutjB@Ptkej zQ*`$Elr7t~Y`!WC%+?)Sw`}+Jek8nGw{P9)&d{hRQlhTBDvZ|F%~xNw<;qao_AOU$ z-?lkaw{zRhojW#H^zFFns;jnEQ+eB!S8m^4P3x<+Y{q@4a?7^uTeqMfRJwJ?&h6W- z++I!nZ98^ewfX9iJh*DxRol1h^nUPHI#zX&z-E?ugM-aCW>&lP%^Az0$TO#wq_HHa z;MUTR3&7T<8iMeo9=8pL9sifLXqBW{@Z9tRyWxAuV<>*wNYlD&_K;Pg@4~yKa((N; zvZbw+!#|!tQym7aMwhpv<^HcB@44P;2pM}PF?LU4%uY{Gb=2i;=*Llaj>|T9*Sb<@ zX)_Wrf7w~ZbUJvF!;y~LU?|$GY$66PE`;Q<;v;7gv=+$Y#N7i7PPO;;gCmA7KUC=B zG;iBAJ|y0o51y7iHs}un~txw9#$Lf*+hAT4qexPNt zpgQb0S#@B@GL=nQ3QIwpGvL-bY~Mh~XqgSk~xR zxuI{D9a!noBPB0la+pp+6g*GUAD)0LKR@8zE0X3))(1xzh;pXLh7T))B5yOFrVd9T z4WY_Q8}!(R)DnaVyYVidi44bxytU*~Dx@y4eCPeV70XmI@GX;yy!MX`5T8ZP2l$)v zlDOW+xw-CX6{w2=C&;?S0{b%lFIVyg|KegLzdV{tcTF6+tX72Ju9hm2gp_NMdH~t& zowh-k+Qe&BY^$oV>Bbt5DR}3IE6k%hMMD|e(&+(pnKqUzwaNPC4RnHcxZM+9R@kG22i;dtT*Zrr`L^DE&!TKS=LiEBP~-b z?3hOm5!ukWI!~C#4Nu2KZ_Gd;+>)Kz)EPGB)Fz?KG1Yr>Pgz)sWYMWsYu#ARv}@`l z#wb}_k5ctX2{nKiQ8d>Xp5kCU#chP8&Z;=_vud^4bIN3@@R&F8yA<*BV|lzPmMbpX zwmvo1Pm~UneaH5v#E+j-)5Qv&q}?w1T?wjKuha z>Iz5QmT$_BI8YDzkIK(+4`zN4)==J|b=1)+9x#vkReZ!#N*hEC|Cd7$S8g3$gHh~{K6l*Lfk{) z*GhCl=&{^QFUuTBmzK1eENjqy3`P`;GB?&l*7IYWNHq_~$sAoZx8&?jhsSS5g6sd1 zofisT59sLfIa)}3-gsYCB_-2kyV?5q|BWb1I_3J|)TV3YJe7Hkc`Qfm;i#3I5l6B| zGoBOf;{-C|=s1OQnH6*2!_dh%39@xs8lb?L3Z6($qKiMU)&0|8J4gb;CcfDmJEzFj zRke&~s>J07+Qus9(aHupiQ}0o9DiuuuupcH#tU#EOUl8<+SBC7$yg86P84&Y&V&R| zpTG8bBkPcZjl}5 z7P<1=BHPa`vTeMG+CrB9R$(Dx@fu zP5f8^TV(8+gVn`MYrndXL`#(YE!nL*+2h%-3DRZgkEsfHA03(M zdU$0?YoDZC`6=~YYd@#F(K}-fG)xF`>HEY2X0wJOaQNI(`()2{tY5>P1bjTtdNS?p zAo>-4YLj%UI_B(6jrG7PkpsW0OC0ofDnozD1X)?yFK+~$LlL|HedT@vMvLc)648*-X!qW*t@|CYRAb>^Lil{l&A4x+XiY zo`7nJ;8J3gdTWIZbFnQmMF&t_>>G-r)5Ald2pmX;O(f@np!P1v5C;^@_os% zL9sb+FISBf)0$@e0}g&$q}dHsQ72VWEi*kh%z5##eoSqW&UbVUHCEWKr*1YeR#bVc zCrfIIG~j1G)Q9ex%c5m?(-WE_sXPpWjnwh(X<4;0wp|n4=qRgdXC&2P&=RNiu3&Lv zP-FLbpf2;UHzL#;SGUeA>(6O!vMiLJ^2_5&fJ?%>?IY(Fly%qKK!5D#cVl@#QM3kx z1+IZO;v(;Sm+DL9d*ogl4Xk#iF5)TGtcaAd2YGN)(d6P#V}WvOtYxTdv}*GEw^TCC z7mK*%bqF~zcm+RlxwE!c9Vldq*qTJ2?wUc<7wRu|I1>Yk-UtLN} zZQ>wihpg8p8EYjCOb=_@@s#A&>}QEc*zhNbu}O+_w+=ScG~gww-bqpat0{?STyxNv?`MOcMj zX7W}{QKmh@E_pS-RKijm2V!O8}$!E3Qp&?z6dHGTAT7s>v*c z=6DxD1WG%n=aAjoY5SE)J-{}5Qs!RV-m;=g!+qAm9+~}KSQ_s4ExUco_14lqyCPoi z@0@APd(m22S=@b=mUS!OVUW@{dGdbHVf4HEthyY2rRDf~NX^oLiHUAmEY%2)M21$1 z!vL+_YOUCpt|SG)U|D}l>*`UNFb=xIBB)**%BXGGEb+4%AP+fXM81ULI)j5MH=vc| z)R!rsS|F%_ESYtsxLKK9iV`T%DHAl8!Hs(a$DRgfLz*|J z*3c43o_Wzvy@=ZNlXh12uFQ zGPqKENTs{7X?H_Af1y~N=$qQal_7?U>O`QS$RPl=%P7yW>g}>Xmd#;K)T_l;27%iB z?mkyPc_fR(ljF)$o4P$263KdUdHm1O{DaL?n+`R2girl|oN=m-J%%m~DRd~8weW#{ z(;Rd(y4*swj8U}^*?netg&tSJ!|g=lmEjKLdV2Ie{{PB*oZA;Uz<#veX%)ZEXN0q* z{`aKXFreij>|rqXZJo2sySGxZdR=^?(eZ4Tar}V=>_%vU5D{pP0cDo z(s5zfI|TgHFGeao3Oh1{)mo_KMF4WQHDRz|2(QAVM?oMDj;x}*uq+MbISy#s&HWv($kWPoNO$d`yCt@W6nVkM z=R-gAJ>v&@A=SxkwY$Zwpdn$7ug#f?zoxWq)|KWAvpeaMcwLY;BwdOrWY)!8T8ipx zcSZ3po#eATnN(h7a!Dz@9iCjKDeqPV)6|>v3j|a26umO54I0Z*IC@UO%(N>_qZN97 zH78-7Rxs0Ybj=NpY}!(9AZ7cxYD|aqI9I~$M7!Vd=CezqPpHglD!0qin)PE&JEN0_ zSgPW0;cQiO4(%OCFRa!xm2^;%p`;jen*1iO8ikhvX8 zpICpritFTqT6R~}l`##4A4HtQ8-kw0c#G4O_TAX6tNPMDCo>J7PR-yCooy?82Jfl2 zD&Q$qEA@5ex9rXe?=*DenKiREpNN)|4bV`RYa4YHY+rPivz22GV%OdS1iS3g&SofL zsavErod&d`xcmp>xf~7B=}V$=FJ-rB+G3zw+-;4viX)cdou5|5<(4c9Yc8=rwvFNa z4@Y5lP2Eq=q1l`)C!fAtnuG3nqnW6y%~2+G%C-$)qq9{X->sBa6FVNyFcjaxGjdAM zNT&VHR+Vw0m9INn5XxpImDvsTE(9;FPK?u-ZvV)bbJ0rBXL0tC8&mQGCL5RDV)DVyp*r{!+6odsJhfn{TELPzFH9WJAT zvP+?UIs5#5uppT> z$Vdjs2rPp6^Fr<=n8c}8y38@D5?z9_;*6*hIwu@C_6UuuE90eE5e;qEdy=D*C%VwY zyc&aRK(Kik=8zH52foK5WgM+Ei?%MA*>+w9xxN-!fd@bSx0Mo)K3QTrzK#nQ?XVS@ z84CAQM&6AuapUKnZ8y*AcT^?Yb$M;$bUB6juKm(5s|JoFT<&A|aVE4GdsO3MwF(lRYlQo4*pDYShW zI>7yx#FX(f(HDL*J28(gEiZ^NDeD%jmDozi+X6y>Wv#Jj?Nn}JJK3b9?FR-ozpHdh zHf%P0e^1nmBTwoJcE4P5XM3l?Lx|Ms9&=9#2QxjcA2^F;(1Svh*x~i*w=8i}fUZEg}e> zBqSygc1X_FouiD7<|Wa$FP;Y6X>uNO7jxsVJ1>wdE0i*m;5!tc8BbeoX}Ic37d3;# zF17fqB!&)fe4y8veUywo9c@xX8ObQ))3f~}_6XRsj5Y>*(N^>j=VZ~i#Q{kgzy^{u zG|kepDAeb+0?{}pn~&fM?;w}QtW#nH{K`>simIhbJLC&k{8jf*0{OWDL3tQ zKDlM)Sx&3d`TQyZPjHZ}VAMXA9~1!0mIox*DDFcYO@o z`A;)9KADUyPCv|U`1tpC(cg%X@a0d)qu+L`D@rvzKPhOF;Gbpsef1J0;UR}jR%$c$Ybk=}2n?ZAKIl;x_O5!JMA@R8FGQG!)IPspO=M2bdtPJrf@lb!ix#b$pviDf^{ zp)qa-3pJCIDV>POBt>mD32AfVH1oG(#KDIA7R@Be|crq^YM6%6+ z8QZh*l!YCC(@V@Wn2RTAt{+5+!D>SfvmMAKgd#^LuDc{P#EGGbkQ)1z7~%#@n}#H* zzHjn^8`j&o*CjPZJ&e*rrAbCwZ<-ZVon}z&3wQJuA6;1~60f);gTLR1FIea(0gn1X zSg5TcERj|!{5otgx}m^T`atVAW{yzEUEofOt2P^WI?|J@XMFpqk-&G0_3Q(V?!U%l zmcDMmPudm$#CrC2@x0hkCT3bT-TiByltL(8AObbn3(jE7Cm*wuAj!+e2HqMEsBHIXL?K@5+0o^WOdu&5Nl(E(qgT&*{} zH{Z<67JZz=Ld9XAzAP?-tr5@>>}xD#<4?T4XLydJMPITl@|GN(B*_t4mh+Xax4m7{ z)=kijIbcrGvjQ;Maczr|8JIZB)2y(3T#q7&zC%op9Ipz4CIoj8JS>1u z9L#SVqig?kk&`Wh#USiBnwO9r9nQR8)jNDe_!-~V?qKKm{DwbBGqCtzxt)ubC1D0l zZ9Z`HEVz=F_@dO-7?LtpuIbxqoBIxK7f&L1qLr!9Cez0}bwi(h(Lo9ayjni<%m({8 zE-8lOw!Gf)C26K17Sv||&`b&)d9$l>L|jfv7n9!5XJGU(i9yPKa;JU2I;R^Bjywm;$iPssCVG5E`(Sdwv^S$THfA(o@hra@KCvhF}Da~Kq z5AeI94NmtPve?x0{Z1qcE1&g-*PmTUT2OzWLB%DI$S8pgrI?D3bgfLRc-uuGC`t?^ zsTw4DN?OZJr0K+)V#TQej8b=azYCV^0Yh3Scf;j;5xUkI8&8gT>TlP(rqJ7J(kwLO zi<*0_9bp6KLcTA;+S4Pxae^6@9mN}dJIHAB;{FK-RXsF*;^TAw^WlDltB)Ps1$|}a ze?ftCmr^h;V#McuOqBhV#vY&dY%YQJu$V5;-3C^R7xa}}_=W9fdKo)Vqh37niU`b? zp>MaNu7O({B1Sf8-5f=^sz^)xXs=5^U(2v>p7#9ys;}&3V`k)*TY7zK6Dj^K?gu!s zk@SNHYFgB|N8=;V2R!_?kOVgp`EC%kI+F!TWbS%S1Wk78f7;&Sf0HocKJomF;NJ-* z8MooTZcOuie#h@%{CJ_;mboHZ#;wE-`sjqckH3b*3f3n_?#rjOJy^)fomiREpF>FI z7;zrn4;S44~$Z|7q4 z6)oSXAE0cY7!u5(u{gQ9+rrV(<;~Q5{Q3=3wz*^2{z#f z_G*ud!U=Qxd9g8n-S2l>{zRA4p%>hC#DCJdXZ60h#>Fgfx$Z%_Fb-Nc^|!BIgL`&`N1sSq7ea#lYV)38x^1) zQP1%i1K^|Npf=q9O@jDJuZ2haP@J^GbH<#6vv*XHwG7iro^pFo@^w_ilz&Zka`6rT zlRvJ*-~9H3>)-F`-8(LVsCrxD6$<{r<4qX9czVVePQD0qy?Aeld#=zB^Y2rBQZ7m` z3vUd<1?*|-kO1R~io@vA1k5wyZjjia0laxni4jI*xm<#JsqbuW_UQLmq)3bxeUm(n z!SE$os`5GS7Wa+qe3tnr3-2hy;^4aSEJ&`9`i^^gUY6WJo_6cv2Ns^M5tAtTex9_k zw6{C`S}h;4#=K6%jB{s^z;5=qke}#p@OX!n_D6otol|dF(Q}&e#j2S5pU_yyyTWPI zK=$$WEc!*x2%qv39)r5>%RfSI@;~hjLrg$jn=&GDGj@42`uPrTnbod;!Sy+l|A@ywTA57r%lgh-8kZ6v*<5WGRcZ16e)Ik+E$q=l7CX;2 z?Jb?*FLM^Mn6Jz2n;Ywif?DXlKtoP`lNEiwS-XLh=~DaRq{y~#nUkxY)JT2kcm}`N zPK<|1tQPvh@gUw#zgRTeU9f?;z=O;BxW%UmEQ8%2-UITVS2Q6DIkDR{`EK0dUmx~Z zgtw&|{7r3bx5MxokSV^VWk?>_?EI8Lu!e?U`11Yn3^#=R3IYuB*8d z5zUxx{{@{@Z49ge4LqH5IwYzKNZFJLf^+F{ zl@!NQ71p0{SnuOlW{NwKiO{X+5)CGy$Iv<42A1=f(s4El}M*Mi@O@6(%GxozSO+xs6K-W||gF zEYxV%SZ7+SWIjF;adiYMrD5Ks`l!MuVCYZLvw=S@7{v&2atH}rY7%U^#4zWJQ(Cqb z{I4rUDRDr9dy~whD)c1R?f8y6)^FM!({$4(H*{SvzoY#f|A{ARsy|-t_7DDsoIH7J z`fZ+!K?67Vaq8dKi*YUjY6uZ%Am%*U*Dh4dd9;h&l?QdaIiB(ID%>mfrX5R6 zSvL*Fn=RIpvJ68;!AXHCsgG6hLq^^%@qJdpELyj?!TyeA$VQ=kCA^*IZHiFBB4mn$ zcma*W3Ow%1zpv|gJx}{v0@+!(%t3c?zo(NjlWg8+HIw?xntn=SG=y0#j>cuO#W~lx zz0a?hkL8;+#W&}dSGONpw7$Z;ld;8^YMG&;=38}R|C2Nto%XOep2z0vvTd0WPV*I8 zC8ZL?DXt9f6+lNmk&<=Wy8%n0|)DCRjtk zk-;4dF+;>rQ(xg%x^FN?rsmw#J7>~e`5(~Yp)$YGE>K4yOiW!4ow?1b$#Q$l$M4q^ z+hI3zdg!qMMw?M3YLhic+hMzG`#ZN7Rm69>eN`l7a^Glr5VmK|%!YBX86mr;o=eOV zi_~)rsLeWhcE@(PU`6-EE=kQVch*2ze_3GDxFi}F;3@UfuF)jQ?`ag-XbV16Z+lLm zRN~bx-}hmlGx1@?ycMAu>ScvGjP7u>h6jsQ6(m2R>S^9}L+x{m)#g{uhJ&F+jm|nK zv!@Q- z`fSG*YsuS-1!or@a0nrfGmV8ZHFVldj?5AC-Nxr?7_z>&T#rCT*q=SxRML&f>S>QT zrdo(JDWivuyb30|I8owVSd>&^C1m%&+5;^mdXqIs%LU3KEfD53p)Iu5Wc7jbF_$7K zqDXJ^`l-8_1370F>A#X|{E}6BgDqy7IeTlSga=AU1?S2Yk95L`8dVn^@QaMWX^)fpYoQ{esxa&nDzO>;)tEvfEBf*?Nv>Fx%^IrA z6f0I|&)B61*i@ra#93!BMT;m~KB@Nx56tBAIg^tiMa6sIuJ_Nm>obIuQKZA^bb39Z zz&oA;Dx^~Rb~|lqu?9OQD^QuP%$_UvPgoJy?y-TJ3OOby)@9bMvjGpw5@B7;?GWa` zS)uOLv%H{Pa`xMlDe%Rca7-`Fv3em{uIbf6^2TNoMT2%biB3;$^K@E!M^PJV(4V}p z80oE%EsQ6ml}-aXtFYuM^?p2i%bprILu^ z-}K5PSc;Pf=rzmJL1QwNQc)3}9|PIGa26*yIuk5JwR0Fib=4c#oOwSf%I5M})t>u-%(_p+p*duZ1Uq-7-LII{GhTy>2>ga-ly*ah(WBpI9E(Q@+p-*x+$9HO zb;{v_E$gcO>f{eexIfocEmv#oH5r~B*x8u1Fy;we8!wXLeue zMt>#iO(Dxl)=l`afQ(cAS@sWpNdE9_oeZ^>OFBZIfU3~%%sZXTByB{!VV{IgnCWm( zE7j~qwvwI8qKmTw1T~l-AS&8fHprAfqX^zi!e6u_XKHD9*%HU2+~Ory;!}y~tRU;k zq!~#zQO|{@VjoAvxYqCKFW!d3zi)XGhCiULC1Fqo^?i_1IeO5Nh6S@rPHl**b0`Gj zRquaf+H!@Lz5qdmUs-X_*{|#Ej#)tIr^4T%yV1#UyE}-oXAlOyb;Pz1)kFV6{PgE8 z{P}O}SkrzjC12u}d^^&>Bf>1OyAu2|?OtEd-cBLS32bR1`37Vw#eqYxgTIMr>S*Q@0V8xT$gdqWC|HZ4YUd?$dx z+`q$lShKVEz<(Z{*x_f58Vn~?B1yKxt4YWI?RM%l1qj$UjnX%;e)AKD6dvePwy(S( zmlm-jMWJAlgZ$$e{zq4j)zvDl2dOY~dT-c0!1RjW9j41I>8QVfb^wS+_|?%U)ooB@ zC2!*2u1uM!ZCn({H+SE%lz;dK70m&tes zBqcRjYCf`KE!iZx7J!~wN{FKt!#UYrbdwb#%{uA3GN)M?ciCM)$Kl}nCqAYURf$_! z=Qte1_dhvE;x9?(5g=}5JNL&fOs4&zH~0G}mo-c8sRh0{$$W-PiLe41KV6yKdi}Pd z>pCcpzxO~6E(W@@R?JECc}oC9@u+~YSZLeOMdj$#OE^iSM~U|Ee8En}kmm-Fh|t^MrXuvX6 zU4QmYmtgp}9rB5EwceSR`sl~PzS?In9hy0fV3wK8^$Hhz+^>)qqULku7}3IW^Helq zDPU&Y24`iA3C`*U(xafqc^+avazym=2A?wp_Ko0JEJ;73lDkX}ZuNqjO>s%YB$dY( zlAmo8=_kZ={{A9LAk{|Rg37EvM-GJ&?Bc5t6eSQ*Vwx^7tDM0RIl`~fv^E8R|A|sy z7N_)3eOiXEiwsG8vq^3V_|A*`6DK>@K>R>5bkZYuG+c7^-{y7hw~*5&t15MK5kN}? z{H@x&l}t~rc-sj);}v8-!r^c8p<#oFlrj0<4vB0Vzp_tsgCKE?r)5DJ z(U^p&n;6ro=3gq>UkGfNf^pBbDG_ZNauThN>p~<*$@ni#aJ?l>#YGXACh_}%AHCSR0aATkj_R|f08E0eoR zSLTg5XB)D~xX3T3LU5@(g=iP1?5H)aH2sSum~#1yXGdc^T}LJr%9@kXb!757Pn!)E zD(=B)=j2NLP;ZvFI}CEUBm3cfvzRK$^>}>GKgK$m=+ZGghvEwyowy_#L%idh3@jS}EMI5w)7e7e~+AF!?KD0ulJ>CT+O z^huf5D?A@>ZJ*l0Q&6nF`b0e7yS-oFePYbtFkJ7jL4{j1ECp=ohQAtc2|OPP`Q|5o zq3lZVhX?KlZe{aW&;}NP{7?4|vnzVLHjgj+-&l%&TR-d)aI&^!IBCaan1(M_B*TxW7i$+q<)RxA(C*3rLOKNVsGw; ziT`*A;)bhWaO0A!7ro)6c2#Cz`;H&4g5SW}5l{R0craB-ktaU1z)b`uvZe?5l5)SG z4-}|Pbq>IMTh@Vaxup!VHeuk=bASFR;)C%qp|lHb?LrX~39aG6vS*}{!#Zi%^av>} zA3@QDiNr1>n=## z8!n8*TMWcPp}yyrl$nsILK1(f#)A>PlKhwd`Cp#6y~1atb95zI+{aS#w+&D3u&{+o zU7pfRnmOXFr*_6A`pJ)l^caeu3q`K*5qwB%lKoows7&$!NUVK7TP)FGo$1t{fVn*aiJ@J%8ifX zS{jNn3$mm0@b$c#I?W#hXelkF$0p_cdcBR>f=?zB4*J@bffE?nbcDuTDaem@@60Fe zNm}SBA(?u`cN9h;9-hr1VC;3KUtZbWm;N&DJi|aK|CyC5cXWcJ-3xB+Kc4yh^I|4_ zBVNkDP*qGfj=w~4V@4R4MOQ!VJ`>S-0sbJUYSJj3GOoch(QxSwD4Weebi5PIlNHZMy6&WVTuwvI-5&&7T^dYwHU= z7Rwc9*ju*8#luU)Whk7&aJnzY-99L)*nQpZ>0q&Nq-?mTJyaG7#s+7di09Jhm3nv( zYi7bBBeu|3f2m}SPJ+x@c9&$PT_sRaJwCi}O>^14H7=pun2;0K;8O{Hy?wRC@sw&g z!`U=w+;q$tovKJPq68wq7EfNn_UVv}H+JF6@v1jAw=0bO#T=Z`i863H16RYFd-S5@ zh&MWk=Qx9tyQllnTPZD8us}uUCLE#lX^nY%{MEd^+duMwr(e!!ivurWcI8;)c0Mor z@&TDN&rG0bO^-5}9B+3f@M)1Olcxgo$cX8bm^RuOtzDLYS$vuChWXsCxuxJt|4-`a z9>J_fq{UJmY%9I(rDbuXgRc&97d520EC|egc9`UTSFf=5gg;*49!*>-#Yc9&qh~r^ zJ%DXY!1m8S|AZMQ{ZmNidF*$O>owNXW{>M-wR)Vbo5xpB{BDiy_g4r7%|g!{H+{m` zaQ6_^L(4r-Hv(XPLeW=>Py}`5jNx8~-LgJk(K8OS>peewiekE|t@tFw>^R2|)U?e= zi-H?oVMQMf=TY?Z_TY*D-~qD;tVIbZq)m+Hnq#VQCctYA-gL)MTA7A@pdKP`IBbJo zaky?~_7HL63f&9`SY^cM&U9|uoRZL!njS8rhwJcFGyNMa@89Zqe`hI3%{Lsxn4HO2 zx5RkHR!C?rrIXW{gG5-*fX5M5X?dMOOKYE7UA5RG#K&DS>Cz^gTtw&O>lJiVn@TuR zhXT(p6a=0c;Il1s)y-h%hCg27mUJ^X*&jI1i1p`hQ^{?7-lN67%KcSdQu;GICxY=5 zW8;gu1u=%Q88L*qE%Xqgx)DsQkjeuCwXkWV-FvM*)t7LSDduA@`lQtj%P#P?~)j_vW5)U|m zbUoQ%m{PQa5~A75tnp24jm0KuD@%wMI15fU?cmO8+-ZJIQ-p)y{u!9(m_Yv-xHol! zOIQ9BF|eZk44z4E?>BUnZf}S)+OmxGo*@?D>G&Z`D{Jdf=*atu^NYA4^hSY z74C}3>NyCoeY5D063*ECM2DH0FL(^?VA7!eVWuR1LWd^sLyDu&nLkn5;l*N3j%VUO zh?Q8!aY(VS!#E@$&SubZ4;DV~TA=|xOxt<5a}MLvTYFdcL9kO#aY$*f!#E_M?{kL) zH5PkF#DW!kqEHV3n>)0TB1|M=!SelSHRlAP02jA=#`YT{jMZcM&(}9ljsK*l8RB5uX_qPxfi9#rfHd; z6Vq0V!w2=}UGPOH#^dwCgyr)m&G2O<1+AlA@?qaM72e2ASSWDHCs#5A7ly1`V_Gi!Ek<~GHagkqXh)D3f(Pp(=&@zlCCK2NS$DT|4f%bNj0xjO3sREt2K8mk22P8}0#mVyF3jyUV0 zVQYBG@!Kz^U1f_~>+W}d`Jcb^On?@4vV}8!)#G!8ZzMjhKG!cbJ{-j?tXgjW^Dj1p z>O(2|bxZf3f1xi%w}08As=xi^f5Yb<2V&361@zouuNepV`JrPi$e+-vi9!cQW0dX> zEk7F%j89dtGH>g~7Y=@J_aJC$5IR3Qc#6tfa;Z^-0K=wh`M#su3d}V|=2}X#<&&q{ z9+@Z8oj!RQ-D;Gl`TKwK40A0`p2~L?<%zrIg)TrkeF4o9XP#P>P;M*Hd{L5P#n+bP zdGyIIUmtBUh!?)8#(w0HrIsti6+k&GS9uCymvcVQwUIdue|?-M^5?3pqF4BOwv|Zq z#VRSISYvc8TwZTe;q9XiyPL&*tz-Y9~vHmAM;XOl9Ui81r|y4JP}|z~1sH zGrbFj@*R(6p~L_%SCKsUH+^qqvXe_-Oj7X*7?b5MfH6OB-Q6R6X-Y`Te)@Y`ObLv` z_SP2jJH2`(pzxh2<|n@4LJjt5QrVU4atr56jcYk+ljEK`{|Ghvfjya$6Y%Yj=#$ zzmc&74hx;f(clC6&#gMxB}A^m6^@-EZ#nM6m5$&4jL$ylyNmdGU!TZqJ+5Ezb&LG* z9d79!GxQ<)*kX_I3|msmGrG`lG|^(qx;HlwNvQ@;eEZJK3?e!{Utt^=T7pWcqAU8$ zA?-2Cf}IdNHjQp)R5x|u@nZeB+Ex$tmbdX#QFZTdbCva{W4QHU0$;;G&(xBU@ik?* zhn>D@;V%zIvC@f!3n&(}U!*{>UnVFhqqc15awD}+*e74%>Wg#Sbh*J{<5M0^c zS(egne!0Eb<6}>{>tR}}^`iT@dWOWFs-;?H_yo&ZlA;YDKId=DdiP6xPtDEF($dEE z+y?OqCXP-#jtSv#fz<(E?1b_FNNU~KD;6=XS`DGXehnC@OY7WaM$uw1+M;xHTxBDZ%$IezeEV0>D$K}2sYD%f` zC6Q>Oqz{JW(EA0kfTv-hO2K~Y>r4Y+{OZsz^@_Lt&(^C4%yh%0hZK@u0|A#(Lqq7c zco+mp*;Sgj48f-K7~TLMbaQ9;?BH}T;!?nA1^1{h!XpZ}Fl3s% z$ih!wgd2Lfos-}LkXA;%_g(Fu2~BdqBIn3KOy-5Z7MjXU0GZ5>YZ&QFdj6x+q+(r$upEdT;OKERw(LYx&F>1+l5{ik% zB8rK7WyE(U&iIY0OFSLCz!hVE;Ewqo3pW(J944Y*I``nB82@I8BP2akUi|h3$q)7K zd)x>)$9=UpAJj)#ZV%Nr>=K7)`+bF>_FFl_O!}hsr2fn&OrbST3HHb~0c z>AymBki7pA(LVA^e#oN77W;^4Z%EHMs@C&ORrgc-eIHgI-&Sk(Usazn@G;`|4@0!z z%3R8fO$pq=jBBrPo7~6Si@#~DV|YumsGu)&>-GDGVQSB?b>o*SkS^v^SROnJ(8sZk z*lK5JX|mHK{M2crw!!5GKD1;|DF zup%7S5A1o14X&tP;(+~^8mFfp@sNAZIMi1u4#Q0#9UFB%VB(9X6c5Gpn82k|Ll+Cp zz2io^Oe-Ec4ejuN(#i6mXD?8m^O>iy-uYck&$AEO&>0@z98nA}(>%J%IcNN1w0G$w z9cyZBfN}k*O*g7*6vTg-!<10FLa$ednEKFoZ<+UN-NNZx4;tp7Z* zX`?y6JZO>)ZV}y$Hm|t!a6^m2=F{SXY!yU2+`S4!POSq=3Pnz1z3PWVLKz$nJL@0U z`AQ8}3{2eMYNJ#vQ7cE58<66|q5dZmjEu z=AFb7zEK?PJNb&m7?yLIW665c(Mb>aV5?Ji$S2=Z<;~1%wtdYQ#u%ahVUXwH$wZjd zx<{DoS^jf#h#FsJ4;@%9@WDyg(Xb4R@Yln9Krzi2&p(=-VZR}R>RkyRh8lFb!y@9d z=0o4P409s)ifl6s9F#sZ6b$n*5Rr`nIEa$n7}LLIKFp8%e746W4ujAqhCKkoR&ukd zHruCl@31tCV&XMAH8q>nzvJDt&ga((O-dc+sIj7e!b$yGy1pHAToM29ytBS}$TnMK z<{>j8!w5Y}{Aq=BsQq=m>Y?t^>46hCfvP8Oj`AEbmncCAL8Ef8TnDQdy~X#-&hMC7lL>ma_SKyekbkT z?RO0h)}0V`s2&gSfFt6h`5C|E2*1z&juM+kWVx=sbZxI=6j!zaTVb!%^_1%}wQK+3(L=1ohn@fuo+Q|Z|u@{}+v?q87 z!GXv~51yP~1QHvuC!f@vS}3|66~Wk(bZnaXM)?75B0njPGQ9DvqpqWGlZDX(_{QiV zrgvDK&+sCQFJhB+IPPa^mtm=OPSX-cZ+R%0r<)O#r1&8G?>FzSbkhsG)_FYBlA9Sg zReU_dqg4c>Y{PB+ZKr8K#sR@7Ie--L?fn*WeMR8LQUro=B-IiZ#D2xXj*=Bj*zm=2 z{{iY!0B4Qya_b#}nt|Wy>a&`7^qO5X>UrJ=mXdqg4a$LwdHabuc2PDOx_?tYRQsjY z{0>6xLpWtCa3cj>6Nj58IQE!~V!gW(hgzc~omR1KD6n)wr}u z^;GW`;})``UT6`N@sOqFhKNHEN4##HD{&{X#A?}lhpCPtA_VQ!BZANcBN4!afFwfE z1SJvqguo<1(FP|Ggf_Z}ASQ$dDaynUAp+Be2?>P%A@#JLkQ|OCTu1;kAwvS72pb}L zUFeVksKSQ`LLWjzAj&YJji3%CBB+VsL=j0jvPW2&up%O#&VVkwh*&tpFvl2|%C&C0 zO`skuJ-v3Q^Z+A11uaENo?fR5Pp;NPilEhlX}wwvj{I`9!G+8{=R!&%bj0uXy9v~Y zRd-EYJ!8sowp`RBZ+DC$R>wvJM6#7He>)(ZML24;K_mcLdpO0_&c`#&I*Osx?lT)| z{g!@AFSSEMtJ=~xq`EDATkY7F+e$siwtDOfUnPim`HQyLH7js2hSndKFa(E+K)&Tg zNZAGD-VNBOM-hSfvnJyM?6w!yKxO8;s=xA^Hri7#bSerT058R}?F&AH!}l*t zp!d?l{rAGfPKe5$Mv_U)Tzz>wtCq|4J%w`0rZc^b<)%RRuxtv5jRuqui53LC&UYWW z9+}P!BtTNNSXurlD9ZIHubYWX`Cx5=fJWZ7+;;K^u2da`UNzB;=hbF|+n98;u6xoz z0?(#D_JysO_414Rcuv_fEQq&*X)x1zspADb?M+Pr#!l0?@)Tu&0ptfPqXL#*f-qz=O*9!FO8bg|f(R9R@|ED&G>z z)dUIUP`+oXq-}RhJg7!SIfhC?M<;dzViGG}7!%cA!cjJ>J@RQ}?B=$Uq+foCp1fZ2ytmA^OgliuImyOgzp5zh`10=56w_&4*97R z&qFy~We>YiXg?+wn?Oxr1l2v`FJWc&6NvGyk&HAIn$G^>hEFoW7|5B@l;$`LojI1c zF-UUP9AjziyN*m`^aD)~@ag;=7rAE~Ih)Wu5_(1dNa)2K-tCn zF{zUzNY28gy`%`D>n1%=@_v$lX*ven+05HMIJj{eX=rJaBLY}*^Y;<}_=oP*+p&xz&qivdY`stc* z`l3BDm2sjyHkH8`ElIsv0;02#1mbWeqV>}WI}SwGgR(CzRS|LvLt(ltjNu2;O6J>w zxqDHZt`~$iq+Ufj-fLSyST42jX&(zmPclLWqBX&sUT1(D>FPX*BUKonBh?w8qt+?UQBP8y z1JNokr`IXZZy)Lu7?UfM7?bN186)VF86!+mXbhxPY6(N9Sa*I!H(SJ^>czcsHzm}p zQ)!^rDKyYeQfGkCDzlBCQ>EEa*L6@&tLUAcR;Nc#u2Z8YpQJ^PqE%uGK%>L!Wp!Ua zt(SOBkoL*d_u-XsWYdToLvffshtM3V&oO8Vd0Ip0u*!6l3HRsaO;R1h$wA~7gS8P9 zH{<0XsvGih5I5zSre|IqnFulJh1vE>VcsC;;iqwvEgDV(V{b{XPagp0QuW1PBqUPR zA)H-=qiz;sOmlV&G11vE#w0hz2$P+i5r_VZrd-QYogMRI7PqFU*d18qGf9VmGDk0_ zVNLIsETIX(P^K}K^`Sav3^qwl255RWH8=<8s|ILthcz$<>9tlw2kW{9?-2dh%1W_R zU$#x%1+U#$lgBd~z#O92q)_TU<6x%s7>6>kzc`ply~Tk{?kf)HFcG~&o7zttj`qgU z$hsYrS;n1gLS{j6GR$GdU)MH=HgO0Ja1(AOEr{N)*Bywz6z@>BW?L^j+g@reodlR{ zA-<8*p{7Sw&N3zhR`gxAOeoR&3j8(6sFzmS(^0xp;O$>05KFnH5R?b`^EtR4FUY)E21xvh#!q0rkNA&B-6a{LCn&1 zW|5!M@vgNW_b!UA)@fFQx~E)4Vq~WY7o*QzwJyZEY^B-*^%Tu}6pivdvCeg5NGQpUB ziWx>Y8dHqOb>`Rt(3oTdqVpwYgI}*rN3T+)C!V552cl7;qt$6JrPip=Axv@yb{kgO zl`WZG^&UW_`#?QK`5r~1eNU`Ye@3p+zlWG)02}*Zi=ON0OSt;@S6Q}Tj>BkEUyPa<2l!1kW^>w%KDh<;k^8{TWTF_ z9mrdH_Us=Ak^e-$>v`hI*g-ftU_YAdaeea+;%@`mfxK-BIMLU7un+Zwt<7>5aGS4W zZ3i(D2dLRCEweaze4)Ykcs6x#u_$h2nIbF$b$}q!0I3e{CbG6Tnk|-S9JeS3a;gT+ z+WvHDPjsh-o9Q0V;Lvk`)uVVxza{I*Zq%{U;H3uoTROikaI|}x4sswbY+FZY6J4-D zvNPG~#yIIXc%kP`c9CYY?*Jaj08NeeEXsjAi9ws_01U`<2Vig}cib3eV#l>m2kLVX z+QdF*kX$@5H9$$xCPya*?m+#H&)bN-N{!hvw}WCE@y(JEwc=9CqmzVQbA8%_zkf}| ze@w1wKnlPuzzy!}IbJS$b%#?|KmRnls=uDwr0?=PmofWov3t6%=0w+B=w{a}?su(x zI+kOqBpKkZdPI@iHK7%1YopES#)zDA(j8UR9M67h7Q0fFzQEaXy=@mbTQ|*qv*Tx` z&YNc4%=rI>nz&Km^>{X~sm_1wtJMw%h}t}bl6b!aB}cT;6zphYj@PQP+HULTyCw7- zWi3`!^D?_zJfcS}s@3dzzx#-_n z77n7Rmi5a%kNtXw=ZDgQ3v|e)j(uoRpiNV~WR#g1ZmTcG(E5w5 z@BU4-HTA<1|IV)0yrp!z_9^f19t%BEnzETycE4WXZql7GrT(HzBk3F5Z8soG780zh zZXWQ>c|U4J0vTD>G`Xwre)T))rN27ch%SuBdbf|jvgC=ue`u|0MhE^(U5-x)GK7xcb_(ECiSIo%8t1Zn4z_ zZW2a6cA3vb0k{D?Eo3h(NJX;PoZ=S>-XVFm-ExFUoV9W++V&SY2@hBY|nCg{D0LQZ?22%*sZRRhKD*6U@N z)5U66&e(V6JkYRYiA-#fca<#_Pt+c0;Mm zJf5pfZ|hq5MGGvKio!W|PhbUJzTDiJ+ee=3W{JCW0+-qRAr7t>bW6p1n@}iGYy?Rv z0t+l~J?#B^>jC|18Y0RK-0WQUDVtF%zl+Cf50r6;0W$99xAZTECBLPrx^d{^|vhN=)`(Fijhr>$6+8nQr0TUpw20qzB8sw zX-vB_-0<5cDX%W)=4)%ra9MBhj8s-Jwa{+*rf~B$9^u7oi!(E#4aSw4#F>&j;QE@2 z{pvnT4pkJ@dtc$%Ngi*Dd|=P2T3!J8!{YHN*H5**Uo6gDiLBo3;(4>Ijh?&8+^?TE zRVymAsbzMb>if?aIPii=+WMmtvz*g2#K({RrNq<^&151&eQ4^soO5(S0X9!R>h(iL z7G-YsTP!d@Vda1!fE32C7-qfcMA=ffaaunvRy?A%7k~0FsNv&r2BRH;cz;9mxz~WHRSPjN1~%Z5}!@8@J8ARQRHpSd~-r z$teS0RCq%-?V_B1RZJ{0akVcZvwO%;cxH6=ROM|vI(fs3Sy*8(e`It~{%-xbHofmP zUc&v_n*SDy(zKUh45B;v0ts$t5R=IC?6JhU$V1$ZqRj8W2~uh zJ={?HH+B6v1KU-PcE4pt3nbNIm8-O46^#wlFBI`Kqu?9Mp~rtbJcsWM(#C}lp3!Jn zOjqx0y?zdArYD7}5kiFE*2X+kaavz1Ky4SvrZJ^}BP(*&3NEq&zclNw86#PVWKo&h zoE0dpL2=t$4D|tK*Ix;hpyrG#l^aIJ5P@AZ>s-KvQXlrK5mgokl@?m5<0VoU0|O7a zx`(Unm&3;ub>v}rnR3I8%r*u}O6DTNHFB|$6^@Yy<6#*t?J9-oQoFMhW<%{lttm~r z$kB<7$IZp7DJMy0D_W0oIn3|yAyFWjHMB6bFEMB)@A&MYxIle$;_|UjS6HKVxgGi- zYv>7*eYV{!=xAeW`W4*nmfhoD{^u{LXrY?F_yvf+{LlaXXO_RLSCs#k|NV|W4|sLo z-2eE)Y*E+sC2nu9bAdumT)JxRpI(2d7Rw4dLzn00=XoYU<>?RI?3~m*qGoPrRmh zB~K(LjGoa-f3v_Wt(mvdPxlWGb%R(h2O{2!iR^Im(vkPivj~X2Z=Mm21bG(G@S;+Y zgSQKekU7cydP&P)h0a>}COJ~2tBC(?73b7MnMwIXWl2sZDwjv{C&sA{&h5E@2HPPs8yWY|B&3<HN7f-ZqN%RL|9b1Al)T-9I8?ZxR8 z98)xT?sQ;Advr1~yF)9E+MF!x1UErjE8Chi3H#XX74{d}J}n-0W)*as>!*HR?A!sT z3g?UIE!NX&X%`kZNGi>nU?=jrWUsl!g;-05?T{YOQdyHe9 zJ2>e_e4x@*)H{OXnH4imPt@jz#kYEN zVHVH@QD~UA!WttcjJowV9-dk@$9oJjtosy{YEsFT@=6TV+U$&EdNQdcs*-qF24&XB z+t2=*SKSH18l~YVr+8XGhmTG5oM*V+!YZ&{j7^=6hG(s6YMesc*4%C3ik@DfD{N;U zOzQVP=fypjao0Ip?`dM6A-9X-U^I3M9Vf3>9R_vxVtGEEZE;|47}vG8UGnbbqN#uH z#G&&d$i#9_#=B>M4`cLXVi~tHmzQx{xx`Qz)#j8SIje-%I)`mnRr z*Ss);95A%H{@)4>OoWDo?W)N2YJL9xVu<=4QOX-26w1X-W^tSOY+H=2f><0b%;!>Z zKjREFJG(Ys(mb+>o0pbr<#EuO)f*6CJiiQE2pMKa;X<2}s=ET*xV@#m`HY`J^r!S(0654WodfYv&gK2sY33%{c?xy-_&tb zkd;B^+%B_pRYFB<>{iqCmQGFHnJ=IqzTFZhRQV$)`T{DR3vo@x0SwZ`!9~U)i6Gcf zmYI2f&h^vQw+LL8EmHP#7_CxMwzw{{ELfMzp2#fWFlYQ(SlBEeT%IZiM^Jnr5xZBLoaKV8(Hl5=HmlvrzvCV zqDO^UZDueb-{GMYj8L3Eg+6Ks*M2;cx1<|Gs+Bggux%KZ3O> zl{q6YMiH3nS5Gs;@Nxj=4*((WAE6ayHGFi}f3BOy+I@-fj(!}9e?brEHw1y*_X7#6 zy&vdcHvaug2-WH;GHtcU+0ulXDuW2MR0a`hs0< zCHglt!0|~n7G4+kYA!x*>ofjdnpfvXiy$?K@wNM_kJM6VA=tB(A6K7O>#wWvtV9MP zjHeR)3u#lq35k>LAf%<{;#0c)MoTwdvPM3d%B*xWq%`_5T?om>b6gBRz7r{3Mi}c{Mj2H(Ue$4R@dU|!&)ONV`yxx2T5phJxD^! z>p>D4V2mUSRb04XV-2&7KYCnCTszasYERv}0>H8Vnu9f6Ba&f4!9z4MP8Q$zE>;lT zc;a@G$J6G`6%LSXlMwcx^%NKNji+$K zi;T+1MMh(#AtNH?5yjQ|Uv(qcB?}BnDP4`Y5KbpW5n9?XMCTgEeofarA!%r! zkT7bZkkU1h-Y~(}0(AM{_@)MaRphR2)rd)kE+mYkB&2klvV4TJK}Z_vh-VGCV?5H2 znteS6aY0WksH#>FTA?W@9j6*u8%0y48tRB=4Y^}nucW}f9)q~R(P5l}96e`rW2%tM za4RITG8R(#MoCA$b&NU1K_9JZxnTQ*qMeB@5{j&NU1K_9Jx*nTQ*qMvDzoby%OKoMocs)#O@sEE)vQ0Ur{CJJezMhYq8W(rAtL!(|bzIQ|{ ztLT00DtEwkB&3W*B_#FCvWSJmk)$-_G20q?&wHdMeGBv;#0Sl6Bre#9PD*7ZCM63D zN_}F?rj$0+D)Lfsl_J7KI3mixsnF5Hyb4JZZiTdg-^ggC4$c^n3Lw<4>TafHA!#Bn zA#LDS<7Qe)7S^6{u3;dsA8AX-MBE5H3UNX+1&OC~(SwxEa4e;=!j_VShDp6#%%+q! z)GBgUsYFGjF}EVZM6M#r&`6<|OPeVqjvFc@O`0mC4ULUDnbb2I<5dBK`c?kH)GQ=T zPB}!ba6Su57-z@9$=wfDEitxC?z3k%tMOCX@ zClQK#SR`5zT_#--Z7g6Bp_j4H>t)OesUr~yDdUC;NqtkJj;1mr6}_)r=OV}og_N#0sar}G(kGm2 z7zpe~+7dDmH$sm>oJb$DaXm~*XE>HpSz$}b;>sY|1zxMGKjM1*@trEESO*cLD|PZQ z`_pNsaxe1Ssd%QB^vn#?|T&yj*od7&ll-8gnhBjYMWhb~;v0vS9FV@Yw zYBN4KZ_`R|i0wcS+zs1-Ah@oq13`EntVnQHX-b;+58{hajgg_g%bnzz-~>H)0B*ec%(JDEH*5#0X2Ja5@eGWC)4#P>RGZ+Py)oPgZiW~GCl~>8 zxc#oeHiv!wM%cL?7WHz@7Cv5g+4vzG{_$q|*?RS*Zt!@~_&QhhSA5|5xL;O{rwi20?r_(yCp?~ApR(9wJut)gWj!6kK3sf#I-xBV;}^ko-7R^*Dkg9s zyDR+Y1RvY}_`_6f$V}KTlN;xeQm2SFFWU6VQ2sP89mn!D&Wmj*f>LmwJsU-(dX{7^1 zrj#5+sFR#rrjk|tmEP#^Dv?Z`>X=YD5zR1Es?0D{nk-|;6q#WN^_Wr1)Od9AY~JGb zid5>O4YSx@tykCfwe6;USl0Ku8IGvj_D<4m!B_kywxhC(3?mj_i{xKuKkNO&Bfm6^3gqq4M47@4uPVTAV929TK?JjYwS7w!#C;yIQv;Ydp@nuN6|Vq`-7Ds#x% zpt6NBhRhH$451Zd)G`w|Iw5lS0&fH(b&2JG=rQ{ej9MirH)^dEVdRQQVHCPa0W|9Q zU|ja`>}@T0(cb99)BaM6`ZT%G3z_Gq;l++db*KLp)rP94jCkDW5iEtSNW0@Lghz_ z5HcT)*UfHrx!Q>!&#^3Hx`J@L2!wCy?R~S@?A9Vj=o#15 z?)r$KmJU~0<#u8yF^>!ZVy_!oYLK0*$WgZ7WHA?e^)ig-X+pbhUpDnY^t-J7c)46H zc2akcH7$nWb2y??Y(rpzgO5iiwKKs~M#nSyEfIMqkVf#!`mwryq0V_#Jqy?{bZ^(y zoM@#@2(=RB@l5DTa&k?>F$eWc{|ytDP2C*N4hEzbi09>M|9mGodRA=Eb+g{BZ2&2; zv4U(=A=q1%u`?4A?|3dMG{31!8;3K{meIZ!9c|6L>t9kuxBF4?jYFAAKk-7e2TU-a5*qqDlbHEIaF)h$3~vMd_SX z%^ckfee7i-JO8y<%_l-&(S%&c0hE3qm|H|N2jB+nx`um$V-v(NMRftm7*DnQulnWd zx|u5S%dPi86P0(l{jIJ(PX;k}VoZj4E7}?>%KCEqPO|)3!~g>HG_f@R5l*CvyufzE zi%dnJgQ8HpaER7n*?m`GWM4hLU)Ae}i6ReZHZ+=uCyR=TQa=nM9Cpj*07Y&Xhv(%O zJjM%W>7#B6bvWwggFH0P`cPL0iN0H`UoF=A-C{YTgx5;}I(+PUi4SAmua+;f3yeop z$?3~AuHqigVhbcpy-r_bgFyoIp?-uWBBjPF4OoH7&1ShmlD3K8_BoA zPS}xuk}bHE0AwrZC4^trvH`M$5eAL%GR$x={%s{^NOE%B3R{kHh=xoO=Ol}uT_m%e zF+mNo58!hFBJ9@JE!>sQ>lPg)$caUV336ibiGUmc0UN388L$)Q`{t`y1B3LHNSB3%#^3}J&J~qmQ^%#T%nfO%4;IIhHYE( z_zuI;wN%2(w1Q%U)v;`)SEhy9RBYld1}T>y(J=`^90yiZr)e4D1<6}sEJmhLwT&s| zjbk!R>uBpt+&n|1YM&vMH_*^&S_sidZjg8S`}rqT`?xlF^O#K2I+BaHd4@>UK0_*R zprO;W@M6gyfD3!OrBb!g(#jiY3DvC>E0QZzTB@a0w({qnG_Abh&yj_yG(;**8d7-^ z4V|!s2t=beZhRxNc$Us0ycg{Yb^u5h6EhgP@C$O--|r?xv%=$2kpz!tvW1(Bf6X#Q z1|i#{$%y5VVzoKPvh544jmVZbaQZw@%7m7XYDAU*$OM*JV*pSpF#sr4 z7yzaya8ies9EyzfkAZHA@*KHRb&g!AI7hBjn~E!6s1wkOs~|M zr&p@Y(<}An>6MD}^h(W{Ek51gX=tZNKSEH-KSEGyAVN^;AVN@TK|D>5yO1SjJtzmh z7(yGvm>uvb)(~@{G=~^MX%8`k(ja08fkn_F1`ofo71D%^%mYhv(xYE_{mMC5%E!iDA}F{{BL(1TrTFYl-WH3p-Bypa z%z|?y@mfdP9N}6=N-SRMNXdn39VxMJts^B?taYRS@&j?X-ZTf|atsL2F1?NqN^%U% zfw&w)d?3yP*lh#9^fSrJm`Iod@3*a0`iQRa|Z zkD24>TxX7=^`SYA&Y9*YIP4mQd2=3tXta1JK+#Wo@m-)U^= zX0OfJRjm6r_F`rz?e%W_h!lW$8$hyw;7Iw@rRc1Qqx73t+wlzh(aVPBH@Ks!erLj6 z>0nds*3XOktHsjNA7c}HArRimp3KLAT6($~*SpC$0KJx!PRmGyX1{_ma`Gd790^ZH z6K@@rnKFlvBLcd zxy{I25bsNliszJCzPVbx#6d1OSDSLJmo`^Bf$J@XW0jRm_WFnfErzQ83B#5l)!K=n z){C5us4MN;kZKt>)YBMOnmARhw{b(QXPgc^UeMtZQQT`DT1Jd&ZWNUmX?n*p-JysD z;b+8<+udT^DNlR)Fb5Lf--Yl!x$pUS_HkRERXCnAzo8qBcXSANR{uU5y+-WsSXS_o z(?T+f?L966Q>^T@u~b)Cw_#knrif<0+w4X21^yh!)_gpB$6u<-8Tg`{7)3V>az7!X z7p{)@Sjz(N3ZlFP{%|7E>lR2mAdY9M8|R{vgDFeE^A|ta`K-i6baUxZdCTu0nBsf0 zdRlF<6t`#ffXWW^_W;T7T{#}6;8Z~E>7%+;svIISlA)Q z7};fVJuQ@84%GwY!miPQXb+aT)A%4_*IbX>#~IyYf;l_C#&#G636Z0%Lr6|~cXCft z>V9Cd%9x!!u z)`KYz&APyZaakvfCMfF$lSO3RI2gvqyVq_QX)M-*qzS~j;bc)*7tZ0#T^4_J@gohs zdT@l1S0|F$!kunQvY4xj9cjSTg(Hr(x`3piRzHsHisDWzU69oaCyTJUprqkd7mkmu zcH;HhbNBhL?Cb;ry{5Tb@e1R|+l#*)&(51h_FP#G5TT9lUTr?6-U?{e$N%F&w8v~? zN0Q<3jGpS7Lhsk0r-1Mmw{)Infkogy>iHBbUX3OIxp_TDFTpCvmspU&{+55rRtYhc z-X1hl)QBK;8$%i|E3+Qx~9k?lb_T zm^*bL%H~d8DDt^e7m{Y~)Pp4tCVRltbEh6m`P``sOgMMygwf2My1`^~r*0h4+^HKz zI(Of%Q_ck00r&Ye1uq;sb(Alclh6GixvK^KmA?$iY& zojdj8$mUL+Sh~4WFPv=d)CDD-J9Xhqm^+n17>PrQpXE8`cY?wZ2k8?(M<;DG&8tH> zj_$Rfqm%63cSLr}x@siSX(0sROo9=9E!1K|_x(!?2GQ1}X7H{Ny^lQ&MShyC)e^-g zPc005H#4anpy!iDlR&iJ@3mUPKyKbA*oSKYiNDutBgo!vDRf-n$*&d%x=*}XFw#+@ z1)%!~t_8E95mCO#l;Kcow2x^Qp`>pGwG?eQn$`~uhV-(Bco@Z62S=ORV|r^!^xk?A zMvRh%2`M|10>%hRGy;{IC4%T|)7x5bXKa}f5kw~=>@el$Aj&K$!RTysxX@VJIa3Vj z5>HAkK9P_&LD-wq+PNF=#2X4Rh+@H%BsO|0;sH-sGKZ)81wCUv<9|oR0G@PSZ!YKG zwlh(WqJ?$8YAI(o1lgxAymn-we`>o;khP%$&)Sa)a`YFjUXUG3gs5HM(1$=TWbdi= z!HFk05ty}|PA2L>qWd!iYe!Atc<8HZePvuz-qJD;LGsM9U6uYZGsK3 zZ~jDa!fePliok|H{}RCkhWk3A2$I@-FtDq^P^7@y(MhK=@Ey>~ei=mTmd?@oV93Iks81YXqAj9cI3tHB8dG-_i`;49Nck8**_jF(> zt)~NRg6(u5sw}4iOKmr0ys1`GMrH3XL5>)(oY9<-@YLQWMN!&Gi zBTco39PfaZ@b{a8n1Y3wZVMLZFveiPrdorAIfOYFr~}%A97dxt z;$d`Z5f7$SiwC_9Z7+;4xBy0{n{c7=VeACVy{R|#YEFa8!62{qcgw~7p8!lBpZp21 z)*^4^3nv}j4`QY9|Db?3b@OG>zX>n0BfqMAFtyuw>wR-ypJ5t3wD2uz`0#n2 zB3$qbwlC^N%odE&zqW9gE3I!WqiOwW3oRswjU$i-7pU^5C7{8R9OEp3y1P61ewYT< z+g&}s)%c@QGu6JR2@c0D&oBF=@Lb&m0Sbtlude1zK#-cvne5vP$YpX+4 z*|4`V=EwS5ZM4?`ru0W0Xp_8BAEwqfbzlZd7kA(eL^y?yD_lQUH=736u-TP9F?wky zMXT{LmQvwmuu1yvfz+zI3^_sDWk4uf)uFr54!7^do5sAyaUkPEV^u>_XJZNNu;SxB zIj=RdBrNR)^9V7A{k&`N3x(p)(%Etz`367gkzxLQyIvhun)<-LLzpbq9}R3JAN6g# z;5PrQl63KS8B6IC%V3jyVh^O&Czc_D(Tm+g8BpsJJJGaem@dUnvX&y0(pZXElWe6M zQEMti#0i#C#M2r|7nsgRccC5B>d;g-0nkk;y0~YHrZp`<5ZTq1?mCK;rY@RI_^=b#xtSh`J@OVHSQNOPnJu+>a+wQDi8;c;6-7jHd zQm1PpX}em2G@*kfIOtY?uf9}MwxYedEEf7e-JC6}?RGWrF1Q^ZMn`TwXtI4h@N85KVm#Tbxg}m9zWvRdu(lUpMut z|E_>h=JNjT-}l^+aqZE=;@fogwog^Fp^5EwGjI#RDE@A~E*^FV;th&DWK#imxOM^z zV|j%KE33nSe%Rl=9LgIUVtdRUc<`f%ZV@;~QI7vP%%l*Y2&Rn!a2HgMhMecB_jQY6H!a{^t?~HlYL0iB0>7{C?{T}6VpJ>OPw=4yw0HKSZn48FU>%}s z@TSwmj*((0yG05zsZ$i7v|S>F3I--tUkZfoa7Ok$9fsVjYIF}Dr|{PA-?xY1=WX?e z=7?y<&4fPJ67 zPt;ukp;TRhF-dc6B(35SqzQUUaG*Yc*-N>OPIFuafP{zc&DhIHr6la22 zr9hKys{l8}z*4x0R+fUn)F#?T3-1s{VwXQAnn;eKG>{x-l6e%tw8oKxO)!ldYMNmb z&<T;57}_0^B9zkH zidd73t{YKndPT$u23W*{8PZ~%*jl>4V1}#R;$cxYJdhm>_jiyvR`W!CPnz*qHS z^``*8S>vn3`moFzYd&M52WT0d<{b)|xw{sL_x6WZE_2?p)wln8o6Z&xug)aPd zjhz{Mge2~6Zi8{|zIxOuumGggVF7898oThcnk?W=P-X!Q`h2}wt#>+&23}ZdpVF^| zwCWu~RqA>Oc9P;pforW`2t4GA`(z+3YY_H`abz7qOJb88S%ca%$Kz{Ev@qxTM3Xl>ucN+DsUK5mko};O>~I9M*8KXR zCsD+sF=0^G z)lPm)v=8uRQ^_ZneSmN4YK}AAXY1!@EEvhpW%gm;Hq~PJXMtPB-{7PhUZTakS=oTr z#P3s>^l7_TKc=#u^@C38Y$KqxJ+2>mLbvM&*7m(YRAcXSl3P4T3}TA>*q6##SaR7rTbX5ulY*n+y{B9J{1^L z%@Jihe!79yQ2v%hgGy`y+g8p?6zf7`)ZcvpK^utZie>bpF^WA_- zop%EoZ7+6D`@7lw`uWx4dReU=U%6?H`Gcb&a~@}?Wb&+)QPU8~(TRJA(tZI%*Bl?u z-c=30c*Lz}L-dyFpFa#2?W(G7=qB-@iaMxo@O`nG*vo4e;mu-uk8i*}u0F5UUokNr zV%N&WFI5bcpC|Zc4m-mvRz@c+@8-%wwH%#%sDIz%ySn++dWTQ!&YNc4AWo-$hU@I0 zP9cY3(s%iWSazkybpuy=T#r0DxvjtLY#*s12>Y7ca2t+JcA)&NS>U39;~D=eCHhLl zbY0_W_ubvguHMdWHp|8CN{Yjkp8`Ni$PA2gNNIDKkY|rSzFy%ot|1jR#^$#F*yG_D zEC&yjFVtqc;S^f#Bct3~tXgiXt$lniYa!fV$$G!6+`&nO1Xy@;H*_fgtjpt71)UQ7 zaibCBi>(zJyo^d~p|S~z%Rol>;ezcs-FdL#_EU{{!~JKe8y&a!$HUw! z#FDrLzIxu^ZBsZs_v?7}dP_fsR}}_eXj8quU$5pPHhYGluBz2~I?&}7XK5EBjyw%8 z#LAg0A-;`ekRiU}dsQu8EuJ@cFZA1H-Rx#~58DpV>-FQZo|))!wr-*bbBDE|?W=*7 zj6B~mfZ|-xL}qyW@NWGOU_M5h2qu}tv}N^B+UM~7PruDEy(WzfkKON3a;NoShOTE2 zH2uMgedgLBATf$$f=`&#Veg72bz$#n!*zV}bwq#h#P3tiBvPO2-BZ2azPjhz&ptil zIhrMAi!&@IG>dx*TJ4&7;By?6>y)GDj!r^-t(WCSAq4u?>v5y#k4|{Q>AG4VdbVy! zPS|dAdE$+Id|dXkqga0|No!_6#PLAhqn4y`*R<8?-JHCQu``lW|M!3Y_ow3Icr5z_ zP*_6{k>~3I65@PWKtd~>>UXS6bi<5g#-0Mxm=8$p7eOPH|4X%h#LkX=ky(Gj7@nj<=;30efP4V|s`^wf;hiaeRnjy#>pl03D- zmOQP_ni6uUJ*C7Vi%LjEHkD8+t;%EQ?Fy9V-|!AG7DPrn#eeK8e0;hT`?f$QG|ND! zvdciOFw8)#v&@uUYML3f$Tm}2k#VM^O6v?DFf#W;VPs@uNLnx)5pUEN?EZi%NzG02WK%r-qzRMg@=@o_~H z-MQ4TJ(n zNtHGpKw#ze>DZBrnF*#vSKr&@xd(0YDn$mQA29Odkv|NmNdk^$G%I>8ugB4 zM#>j>PiiS%hDm8v{nu4Ip%*&{bzgP>Q+jlaq3hQPf}(fF^ol+nlTYgD4hX$3KPD+K zL{R@)FE_$o5YIMprWFkGDke~bQsiRG(?nor_<5}Ae z;JuJd)zq)PeS5-dU9Z0Ufa7#;7LSN73a5bEh4(-I^j*EWU(@vnukIErEEvyl=6AQO z@j>;XTFpM<1Q^OhM`YU|O&;NwiY$LjG}A5;_{Q)sT;*~Au30bt?-1L|?~~)VZJq$~ zJ)SEI(P6vDGx?Jbqa^Ud07Ls9huQhz$9{H*;{nO=3F6b``u_9wJ6y(Df7`s;zN~iD zw;7#F!H!mzdUS%*MwE^XSUy6O5~bPOT}HjBcK1(jv9vbhzp~tz*w)fhVzu7%Fo8wnCH7 zEK<%mi!SJN&L+)1I)S^{k}2>p)L-kx<5Qb?U#42#4;0z#@yK9T9naOv9hM(fCFQs} z8k}Eix6tLnnc-2xWoHem`s)Yo16c{Y0eZ1s&Oel-=dcTEaam2hsapnR65TQ2t~TS; za$j>{YIU>14Z0b__shCky>8iIq_6dIS#5em^?)O3`0A#MFW}QCVTYiBQbn0Awr6F!$I=DxHJvXRb4{co2*-UowA?%5;gbtQifseZPD+UJigF0tI_0;%d6+z z`Q7yy%I-N^NItdqqZ5;9-|sAEZa*(JSB0U6YCWD6GF*kY zxDi9?JZl3TG9|)yo&7$`$L08a5a$$y{kE9nPPml+%k6LLW?t;7riP-opYNYH)PM}^ z?rWAnd+5bRc77?;+nr$+L&1u1^yQ`fIgFByG&7E&Z zQt_DCy#ptG;gz~;JY@dPFywNA7UpYPB4jy%aj;#@Yp+x!48vjP0O<2n@Q+Gu8_$1V;D@n9pdX~y3QKCaXTW?&~ozcYWX1Tbpqn?x` z`YsfuMtujG{_KS9IEK9bv9I@$EHHW8yHc$llV&bfn78@HADyJRaFM$TMO;;RzM;OV zo#Ta#qyX{syOl{Jr9+O|l?u@=0A%LFfzE!Dr3QOTyHrSzbrDkEt|>0?yp-1*5U=`q z64da`b<*GxXU1m~+>P@ak0lQUzviW|SY48zi!k5qw-}-0C75hQX7)RMu%Lm?H>7Eg%jmHv*_*%Ushcb^ zG8>D`zO~4h&FSUKmI-X#@kIx}cCcxSm$-Db6`A~ixiYPh6vXGUdf9Y^0-x3eSs}Rm z5@Rl}B|fKhJ2lAl;<8O3$PH+l(|pa@?F>%t>WUpSm_#q}<~^Rv>>|udr2ZlpawumT zHw>5*9L6<(7q|hm-S$v>DAk47_%`?9^yPIS2QJdNU)0}QMTW74T1@#V3JuD*k<=P2 z2i@56sa(Q#Q{OLqh#fIkEthO3apdG|a#Ka2iA%hI^*hvH3Y2=8dX<=<%P@${BRzGCyzk}u1pV@ zk;RCD=-%ySQ&q@FEhlXdvU{p`xdRAYg0=OV>`@r~yhNrmgw`v5G|P!}B+dX|wl*#` zggC-Hh`*$m2y=kf1h|)DzL+Rjm5uFb{%;pDTB{InH0@H++D&JESnkM+Slh}b*E3w7 z)VzF`r*i0I`b;bD-|M^37C&u>XW*zhNe@$pB*V-e_V_IAxqkJ`pYU&Id`xZjUkma+ z#VotUTh6>#t}EIA?#&G+YeKWLs@%pmy&IQf9i1?b$Fr`=@&cj0PN-sgJ&tX1C%5K{ zn0Tjk6CGN`E&S`%E50kiY>2|=Kh55*AHV+*K>H z4@Pw6oW%BajpeUrTEv3y_E&OYd+}*@TK#|a-flUL97z+cN9jw7W+zorm1?SOuPExL zI4y~6CRH_O*4EmRnL#pJ$&9RwOi}E$eXhMfPj)_c$B*ML0+H0%xi~x4qhbc!9S(=X z;Q$;CtWpZKXdcaplMtk(KnZCiYZ9y5y=%AF4`$3|ZpDTlS92Kkm2;n>|f-|uMarSRSOFk$HpsUrgAc)OB{mb-QqQOJ^& zk6D@*u;II#hzNhoeOs-gukU6%ESy3%`CCkqKPKoGGaNWZ==?24=Z^`x9A!tf)A4q; zsStV&!G6x-m>r3*3i+6Y2eB-Q`<})6gL7m?a*&S-UUiig2k$r&gR~Jk-#%`3?F5@g zcl-~pmGwvCAqJl)t*rhK6FT{d_k{RJ*g$cW=I^6pstj53Vjx>U#hMNKUDaYgaUg3% zH(>bre7U*9T)J)^PG6rIrtQZC4!#B1enAxgd%NbZ*y0aM5iNB+cZJU;9Dk-*uvB8W zQRx=c>qx8JnUn5X)a)!-iEQ`;-;*1}Ma|I|Q28|$0^WqwzJ!ijLDh5W{_NHOl z`L?;jfwn2QOxrY13bMr0)n&ve8nc7R+croRw#t|N$NA;onn(0>GrNx<(9`cvKmLKq z;uC_9nv?b7YIe(=6vv2OFK@#DQ6qK3|F%JAbab@WMOEC+@8zxX^!o|UpF%Q6#{hpe zVP>+r!o}3Bcd*lWptC`ZTm_mnLu#uk*B z$5;pf9#6WQq6-0A94mTQsui6|@>(9^XlXg24ODb7zC5=Ta}W*WtnLdm?tC1W)01o>oO(gi~*Kb<6pt2hk&@U zA_Zf6b-Alue^k|S4<^%ER5Jrbl}GwC`Mic{p5G}SfCU&=m0^*G$Ume*{_&-G{Kt!z zzy1*X{_D$G{NXzI@bc9!Ap|~L>lSMjL2Go8){&^lDM|F5RJ-Z08@oglu{l9;e+QT(h{HAlBmdKagz- z4-~j>m@blUi{;lp{_r5{)xYeI9R;^>MDBk!TZCjeGMqIKtDfcUI{gUWhVOGE(9O>5 ziDgPW8N?k=Ivi{}Ao@V(`TmQko~M2XW_fCM;deq`W1*FxpIoOcLL6WU2cIFSWq+M~ z`-qt{hQqf@iV{o;UN6_}J)Kd-7&y#IzFjsc_khcNezW|Vpnq&t1F-!uOWO^!0LlpS z^nR02!?&E|qCQ`>57^O-8&~N6vo69m)t_|*1o*0$J25f3JxdsKneCH0p-bK<|+on6Dg|**efW7UN{7%vE*7!vHsO_{q?L{&VzZ25jiF{AdbVR-7PYC z_m+PO;e0IhSj>6syYlLo|lzTVN2)hhPZOH$6=0H`bwHRfwTp z;Lt9p9xm`FrCfx^pZ>tfZ2QotZgNE*Gd)X%F#j}=l$mq;G2yhpz=7T4FTr?2uU)hc zp4W~3LEyacO--RA&X*pL$`E9RnSv)H#SN99ZCab*$S!e`69M6CNDm*hy9+v)Hq;j? z|6TpwBA5s#8o1_^HXN`YLJynx!dIM|V)5uY=N8K?oEctW=I|d4=p{mrw;eV)$|X~Z zrgp@Pjl!AjH5PD>(KJR>!LBd*2>+znUe0j!+S5p&KJ4e(FXUyOs}W=M_uoA-ts>M< zDpm60HHHGdTmAl7|J>@IVv~N?-3W3pNxy57TtmfD1_AtTsxTWWt_{9Kc3NCPiWJWv z9#x3q^jvk8FJ;1EVMu(6do@#}<Yw=w(e}1!svf@V4%a=dDT{ZUzYk4*~hiv=6HvopyJ_Hs~ zl{+_mbR&etC|0Y1geD!=nx#ZN;=*u8a-REPK=m{Z&;{@40npRw-kW101Lm`?&5 zk}Z=O5GcXW`d7{KL)=}pBY>wYK(u?X(O2!Ta#?PNAtSvKweRJDFkb!Q>`cvYdiBew z;j{sLa(nv){OXrc{qgFTYQ=i>OO1>nho62OVQ&FkXKyvtDtoIDs(M@_)Y)5&QDJX2 zc!h!he3XJjqOY~LnyVq35LYpvjuH5for}Qh?5$>B%tikQ0sIgj8^F{K3xHPeNfd`< zOE81u8!%(WH^A%dE!AIVZ<*}yn4%UDx5JQ8&)3=8S1(^UdpqQ?Z2(+nXEfC+JEIY* zTB;H1?2N{!urnIG!p;DEtew#{)Y=)1Gc*>U4;p-ESVZ7M<2wSc7{4(F50id71O97m z2tbEeX8o=3>p*HqwoGcka1+cJI|J}~I|JZKJHup$$CTxE7&7X|3OmDF6@4xjNNUHg ziU*A_Xt~Jkt6PyO|Fb+|COFKxfZKl2Vg*xBVY6yx5Dq`Bh3jkmgxv3ocJ*k^Ci6mN zD880^zCPV=v2Rs?Be|PaAYP(p^%^$jx*C#cQn(Y6HFVhBtl@*HkHjgD*O2ot>MUA* zhM>KE5J0IXI2#RhZqE`mqKZw**%p?nPHk=}#$|>8Zm!8hrWS-~bn?ALsSD( z62L7HY;Z$#AFId?k7?hBRjL~>Bii1l=>d4JiUg2s=BgSvyMZ(s>q=CiFdKC?)Cq?f z8i~_y`AB!zJ-`jM8U-QvA-i(jw!6DOeyOH6+1sdwB?yWa~WYsANFo0y5RZ8ahVCo}r`fZJ;J!m{UXuqz* zApmHtL!hYEI0PO%oUi-mOrw)E4ne7csy?lB2vA4gL_*@Da_10~>ZWF4Q8P5uEXdGM z3*dTHo|Z@zLk&=sL(Ny+TQ3HXhvdOf5={WfG^>V9M13Sq|4{R^2Zx#m9UN)^tsQEL zYRypd;A4jxFl&Zdse-CLtsH8oqj#v8^1-3jvv6m>5%VI_%;5SJPBoUdr54b%4oE;; zwF2G;SxK;x+Q;@QZr&6Zp2Qj=iibcT%s!UO8&52yA#*aJ~d%LlJjt-c&CjS8edNigaA z1(v-@0phYq2N18g#O3x<@o&h#7PBcNUpaR-;DKDVJO;*hQb0Yzn?blLDRI4VWk<(c zj=XoXdnDeJ|0Z-Is7!B&$^O8|3%mE0>v)T@Jk_yMMkjJKr7VjR3y4s)KUxQ zuoA&VyGJ(XTAJw!r9?Mx{T(!dd**jdH>KQKH_Lgj^XGt$j%i?V*?*r*CjX##aV#1)XfytW0VxkfH@54_4b^i={llc zvJOo3SKLkMz{~eXtd#?u5`!0eCIa8qbCrY#wg;^i;kX_FG&Tlc*dZ9m7GNVApB3W0&QCEzT!8H+phYOSBPw@aC%7jUR^*HL?W2RUw^#FqA_2{KXkHQ;FjSn(#T|5K5g&_0a6v6-$bR$^;fLvdNAKD zo7Eyh5<%In%@xukKxJ-`hoAD2lmV`Oc~LGrJ9$+ueBHLIh@oX?>WjX2&F)QeGsEgp zUMLU6hP!{i&Av805R_w{h370K4>y}GBP8cwC~MRO?;l0%uuxgrT-?C?cM%9Kb0UK% zZB5NqSM<1SSO*<^yyd&VTTbj*E)}Q@de@Kdin9bdPG?Z25SC|2+|%{yGKHWxO8}i( zMpuPH$Wm@*bUsnyHzw$2P7@f~qvPES`4bnWR!NyT03xsvp(Pn(LnYIFL2;G<nPldyZq}-_ zcw%X}Xkhr|W_1(vKH=x*1S;vD5{ws?ol#7eJ+yeEn3BVVwMuCX^>^)l+e5;nTEorw zs0P-hcJY|`+-JNAtz@1>RE24Q3I}FqvL2frB_rVXv)G#m;8zZyz12 z(xS_KbQ}*uaLjN0g?!}TjQuQd4hMdLA`U$bt<5B6MC3|`_2L0$5bw4|_a*sW}egs#) z-Y@Z7DGV2OS5Ky&UKl5#s`W*5;~I@7GQ*DhXe7hZsBE9u%M+xjV&!RWr?wL4)wwN~I`W1x;_8d;R;sCGO-qvA%IU8MT@KCh8X^w1iW zpIcXB$Z(}tJQ8gWQm4d*^GV! z?x&DAM?_AGXrd8qknu9PXqqpCg{fpT^OTq6fSN-s)&!nvVn(-sEaJiAo>cxd-^m)Q z>?F8qUiC~%Mh!cqwe>kvgkY}Vr0kaK{fso_=@gzYRl^g-j-tFCFv7sQ#@wv--QDRO z{EzBp=*i)r>h%_TGhcKwx?hHHqvagoZ`PYN9-=Epf^OWfVgP})`}R4A;6_mnfK&gC z?s-wr9?pntc*rD`(+LwVeXU&zXx!lt>8ize4V!e+P{PAFB7x<_><2Vxx((6k3r|Eo zzqBy(JGOT5Fn55CEz82U9ujOI12X^GO4_U7W3IdZ1!tFrykA8HC{7zfE(0~ukqD_0 zMIi+#KpIMr!kBH~fVF^!Lik2XDRUUgK(3)dpi5MgYl}xLG{ghsTH#Cknh-;Mq(CmW zEPl&GejOc#><8Z_lLA z90ieUiz@DGNCKu?fw@m&l$*r^(*1WYU%h(qSENeA767cVF;n#Z#$t~|a;E8(Nb}it zi-dvgW_C+yfX5-LVO?1r?zqcyqT?!J!|F_KZC&}?3;jYQxg#a5Gr6^Ol@g`(*T!3q zBZVH!mzC@VlVK$eKWbIcP4~0z%P&7;`I2Uq>u)@ghPSKzXr;sbiSe3x)-f98)U0Td z8dQag68$YhYSWi5U%mWkY+bmHc1dpPNW5?iM@~RrZ{N_B`kKmannJ=AEeG-pDGd9W zNsHbm=!uDpSniPWo=*9DxtPq`&123d%QnvQF+FTl0Of<&T02G)OGyu@>( z2vWaz@$JIhm>6io%^~nEc&0?0xH-jpAI-vW)UT@$sa%B^hhx-XXqo_ZmJUfJ@H_gr zXBpzMWhN_5PV$a+81P?L!)Tn)l_*tW#8Y9=68Tq{r38m=ouRH?)drHdDSV9;@e%YQ z;qdGcqT!xji%U&2^9Vw(9awgk?6wRTfPgLLhmIgmSF`&KJ^IjFMMnwE2Xzon4lf1< z0fGEHRF^cTAIi4|f;w6J6ZwB}dxf4P>1~KdqxE95xWr2=-(I-OT6s02cmuiXLa|ce zf;W$WQ(M^-MIIPd(IKvk9uJw#NythqRlY?_+suP5F{Me8__p0+72|{HNJX zUv`|p_#{Y`jsAVMrDy^%Bl&ehzVD1B#XOVEJ*=5aXR$#P4Dhy}t z1SKOnTkrb4mIU?JF{m>6sETW6t%O~keh0cbZY5Z)L(8yPFCIa*6YOwb=&c&sv%>JA z`*_Zf>Tlt&=MqA9G1AZZ6C&a+K?rXM7&GJnowvfDunJvsTyRty-i60L5gm^5evzgU z7G?OkLtN0w?QFRwR79sH6rf_seg<k!6ce!ut<^kKPq>Y+j-WI?bis`Uy=fRxU9!&F=N1ADd@U6#S*Up1; zt)IxUbw-<>MjYW@PgdR`NWRZP7%fHHl8_fVvqO$XCNFJ^a89A{yfgVuhr2KKs^nLSX-jP)4G6&Ljxk-o0L~n9f&3!k! zz=NF}&#Q%R3POz|TBP^DATM(|^H*Z22pu+^%IO`htw)a^KPL!gemd0^g-8fFrboXh zzT6r~&wqmG)g#b)!;3RgxW&kjnq;WU1L(wd8QJJt832LboLNsp+~3~3z}vt2({epO zmA7B@R|FvGmtZq(!>cPu?5OsO2*&8Brer=L?&*}Sm*^tXg!7ZPE@K`M31(9K4uz(N z|NrlC7VZZm~G5!rY0`E~1ZEl|k@r$uN;Ld1MO10uFXO2v4%GE;~f zH~yv3TS>~;O!wDcn#WEv`lY*UcWMKT_}Q=V1c{RreSsM%Jd{eML0!ydETjMe!%p`t zQ83+|G%>)7G>-60=O%cV>#h*dx@z9MorZ6?3cnQYstPl&wHDwqydy|Grk3Hf_u0?8 z``H{)r2o(shI6=r@4>yQphQbMC`kGuC=KqoaS6mGuGqvmc=o&18T&hO+2%j@=*SkO zARTrDeME{5eqfi}F~n%vI>MsdTj2tswGwB~+by2JijTMmGOQREz+Qw`0-y6I=$g6w zSGwN!Vq(I|;W;7tz?f=A_65OBvllcr3{`haCAstW0vnp{#$QBOl@uul!ee$I?SMVc zh1Qj**@?D9<$(f5WlCwI683S*#o8SyLy;7Aaq)F@1yFi5Xg7nz*Z*EjyAtlZX=fIT_v zX}DvA&ejo?a0yR7uTOEsv&Dj5nysOY7`NfxbAqIdU@w09@fB?I$CJ}%W);|1Q4Wv)fLEEZLUt(>uFdwDv#he4}Es^{WQ z&nBN*+_2_3=BboueBDv}+EWQl8)VaaDv|RI?jwyM0zY}bnevit4BF9gD${Ok13JWc zHk2)I1FoMgz;M_ZDjA4Zz zcKE#Krw2F!c9&(8%*YKKg+Lyb#BhwmGuC>*a3)=oQ)^PI5h8Zo#m*u9qCLEmH)kfy zuCE;lKla0gnT19V@0b7^8ElV8`jJg@KY>H`0jc@?{Y3h>ZSc5c!%xR{*y_S*T=&B@ z#pKhqxE+pB@Ks$nCKPN^(EH^Ag(gq;$bIPdrR+wStNX6`#?G!?7kzv6<6oa|zAV2@ zF5i5zIWQ=H3Jpw$#dibE;>dp`TG&cK{a0;_;mdOH3%b8)oC(jt(eWodwT*K*JY`I$ zA&R3Em_W^%3~+8Y%u~aK+Oze^4lTLHw%iqxK|rLE$0DhjiCwkB6`E!y1TaSNcr|6r zgj4$gyN0}n{Px>si2%-&dA)-193LGk2C#)Bosg+Z#57bMw#Ql0TlClU{uUW;cRwT_ zp_bW^vTkb6aX90v2|H*V^9d|rB=EWXa*o7H1m zuIIGvUyo*)?r>=cI~L6Ncuv|O-?6A_tFXe??65ez=Y>!Zi?0R@X@i@ zfpMl)U4b8~f(jLSOsKlYiqO_+ zI{=Ot`8ky;Mzh;Uopb`j>ERN25G!kfpAk$MJwQY#3g_>N2PIz+wzMGKn!~%;(}5jmC)*eRb(z9DEPAoNGgr&xj|ml%Q-uFtZs@k$mR48rqW#Bfo2S%&T5i7n zGNr8|1;(xl5m4VYM z=?qUTLg8)@@Xi(X06M06VBW9V>m1jlLp{oHM!7-h25ijv*F?%^T@M|($*+j;RXFuq z0B8iMk9+hDG6PN!X{)}nOdrsFNRgM*s*^70g6rmDzoS_QyYrFwPdfd{0b(La0J8(& z6S6WXP{;0KaULkUEm(FOs~izW)4yh@;JhrP!tKs0X2?#!W(J}G+Y~l|8 zqjGM|JuK)QqQ5v1HI4SG?QFTis1|oHUy+GF@r6lM2?SMk(QbD<1w{Pwclt+t?=~wu zQe=?yckaXP1FXs!B=n8gRK*u|LWsy&O1N~Lv&PIpqBQ@+<-_0FZdamp!iN}%hA^?d zE+K&aZqXzXQLgMz4F<4uK}0%(OJh7h6q^$Fi}}j8aD6|Uuc;7S!4#^qYR)d=J`n)@ zb=zQ#f)wrDmq5=ACA;aYFj!yn#sRKJWaF$c!J)JwVThXpay?g?l1!JHlB8nuz0}cC zT<+!&J?SV486^QJ0tt*Ek?1Wua=z1Wg~yJHV87J4bRIMWRD!buJR=`h6iz7qvo@6e zYdlrhlEg2v1*sckOU{A`N_`Ez9ABUMALq)G_jfId{gF zrjCg(%X=ceJhqg!ByuzDXEPEKHI2%nS;&?~UV{BBI-b!)6lj0I!Y6|vEXYi(79jS2 z?RVz_`(a{>*yd!0QHE*x#Fvq^LGr^qJF+ZRWQILf#!ULcvo2$eb#dCkw!(5>Mi5DF z`tr!I`-(H>*B6=&%t+PF;fXTHq({Z2qI9B`E)>jkI@6_PQCNnaVHRUADiMZap7)%r#6|*kAYdx) zum)X>gEoA)zRWX^trSWvgyA*mAf?xjm+wx0`8Pa6nS7z;%yc{Fd3(}r=OkYFfm8f; zy+$5oT6J1YfbisN%S+11azjV5cw~VH2yhTVUu&97iMH>zzFLUyd6PYAm ztyP?yT};gCU?NU~ut>8q?nhD+5v-07B0MTjM6Msn2a?M>oFhH?=<16=WwDR?hyd;g z{YwaT%X?f+@I<+m`#l~_JbQD=Kjw5ug!WF6219Ug69#F1eM6_-pYWo^rzw*Qz9=G# zUAts}WyhLKMEUpqa*g=4f8lx?zg|LAkB;9UOol|cz~L*FY|@i(;V69OP4um6Q2j%@ zm63q{7rL??FFmrAzM;`WQ3PDC=`T1Z-_)qGKM_=?h$0X2=>+s{_$e%W@) z6H+~Nbd0!Whl;we;)E5&MXj(;Zt#)zvfeZ+qrgQ>rvA#{7pODL&lNB~RlvNcfO(mR znbO#jwqmys%ZUOQPhov!fk;W+8l2dzZlrZU8UUp9Zz0X~D$ZEyJW^@kho(Ch7*vK7#h1X@McWDlUhp&ItMW5k)g zV*)mByF2AOiIt}o>ZFou$7n^c9p$?nQ9s!PAM-(37j|!9*nVV@+5^xH?%Rk#g1jl6 zE-b0*21N2mhjFy`6)wLqE}b6z$@F0!y-M?&&iNm+~dZ+-o7h*JlZ>7LGIJC-Xn|h$5Rd_cEdO5D5l!OlpgG zaU@)EbY@=>A!jGUKp<-bl+XwkW#afA;_kK;U*hZn0eX!%RJ=t<`*U{d2gdu-wDFn3 zFwM^uoqjs`_?G>Xfc<_@rnlVu4iAn7e%#&Ubj)|W(;|H4xr(Z`w!Ob<=F*z@8qkTg z<5j?RVyFNfLH8x@f|8J+_LPG|)Q`VlVZlk*L{9%6ZMWi1Z@1qzmu*Y0K@bIO^C?Fz zpr`r|-_5&V2z|vZC(}b9@a_#Bd04f^Fi{X8f9me`yG8pTUHPz`ZKjVMmJ#xPUx-Z& z2*1EyE$o2|6wr{gUvZCTXS+62#2Zl|*2j(y)RK<{N&u&lh>%36~d6bqu+O19(?<~>`G&9tWJ2IlnHWbOt9!oDM)$*+XmkA7UuQIbP?(5kDDj&QJ7gVlMfJ%4W;@uvMQ&xJx=DVs3czfewm! z&Cj3EPqa-d%;JxCtJ$px25b1_q?Q);XIPi{Lu&b=wpisuup=v<;ANIhsSR0sWS&8G zTghsVSg?{UYx;cE%J~ldmM8`KXe=V_3UG7r$^8ve_wJqj3J(mzB>JRA5*3s<~s zc8w+Zdg1t{YCbhMO2d@GHx!tF`-&pB;B_BWgLrf}8QEW~luXEd;a?XtmdqeBCC=~Q zGPk=ze*`>I3*)7-UG^$|mYcWto1F@(U^${~*w->M68&IqXdyFua6hSe0!UVqrX#~? zTHs{l;mJ1hft{+54J`7~`|r|jG zto*rymTagCl^^e$OrUbF#*E zuXz%D3GAo$@MKR`W*t|Fc3ES9fXX)Nqk~%g< zv6XPT!yzsIX^OmT1yK~53uy!UGp=^?)f_>GL(7Xm>sESfc*mG*kQtFr02m)@OthhU zOVb#Cur*xbPUkjVi`ZhqVtHFn$Jdg8q>F$Q#CY^tO+GNIPW5!r!fqMSfV|kYyLR4U z!+``Dd{G)9Ra#ipRQt*IMA{Sv*9;hH=s;66=PhbHBK)~)PH$xo`Zw%WA`c-e;Y68b zdx&re<~=%WGTXP{i(Xrx3cy_AR-Nc|0GRr{0-kq!T^ZLHdA+WX_v_3+Ws>GlUxwe$tcQ6{+k`C)KwXXiGsI{tna?3DT@aA^ zy#BJr^751TBaExWmMhhSv*iJOUh`J5g7k&Ec#1a*4`fC~ZtZkvtJfIcL(WI+Fgo zN9d4Az$uCSp?HRuraXu*IAm{Ddh_mn_U#1MU&Qt?U-)7x>i?{3@lJ|c;=75@eVOmJ zt53nY1WluDDKWvAcCh_zWD}H-Lfvjn88!**4i{=g(j4hC|Jia+?amatHD+8+J)O0TJO52P?dACD-c2zLES1jLav^}D~JB(@2dQ~+FLOB)6aC*LM?P$!SS68#s>VYBXbWQ0KpN_xT zZ~2|V&(`sBC-Kpsbl<~4={~DLX}-~j3y93jFgN8H=8BWZL$DPSe=ZSYtP(YRkMQ(}RZ_vo zG!>f004^SH0I)4J0WdJW>|G_F(})*f6!qPeu`MM%RRjeqnTsgsCK@I9lHggT&lZpp z<&ap7pdVqG=t8K>jtPU3RKwrXdc0^e!yiO_x$_r^8~<4*tBAw6SaIWv^n4Z3^z%|! zkWNftxtf{60yj17!900aX5Y#VC?(_YllSf1oJN%C?yVt#;e-#;C*i1dpDjrx2GN*c z+;%MmWL~u}^jSbPv_M%1@R)O(ro@Q)?h)d#1~{&Q2AjcARr)RpCO(4nMcS#zlqe5e z1mrQ%iJ#XioU5F#wF>0Mx#crE>r$<*d)zr5ZQZI}e&brMc%BwFK42{@6V3wXy31sip zO^1!OgD0`26q*-o?$AKYP_a8h0UKn`ct6SCFsFKG%u!MJ)odCXR*hpFhIF`(%0#^MMO)jp~H0_6{brbv85o(lV=f`OH0^X7>WymbYTd==4{xb zQIXr}bN-mNp6;WPulp9u*A*!Fs&A2eT}dimU6jZ-E{r6ki&Oa~r6p{UuZ#hEXs88a zzbU!cPqA3+cO@17DH4h;NM)i*5|Kn@QJYk0Dv-FafUCtpgH=>m3&ej_BJm$%q4*Ld z7X2|2j4w(>6O<*wNlK$82IZ-M(&8e%2r004gl%1vaJ1U3a%0_aEXX${AXtuyCdcFd zy15T=E@+=z%%^B(`M8yE1tvPWjJS_W5u%gFL$x6@0Vd-FU*IsPYYI`3ttI?SRS3`N zA)jy01Fa&r=QxnnXL9~)a8MWQEkm|Dzhgbad_%jGFbU#i^8`foM$u{vO}S9>Fxjd-+bQne7{|R zCJ$tNP8xo9<2?Lq-6|+*RG^(QE_#cw){WQ;e*noPcn_T(TcYR@t|lt(kVRy*5OfkI z=Ns>Bp}qLa2Jo2{_`(a^R6`UO?~f#fUMsi= z=WkQoKalWG{=)Xr@yEZ+{g2O=e6fq6_$bUlb?kPNX`rOHr&k~BnVg3`!7Bn3u)PCA@_bU|CkpCrsFmd-LgJ;Tbfa zaQqQN;YibcV#(q5jI3Okeg1{;nouhZIT3?HXIN>d`(~!xK!m1sXB{4wcYx+2>r?#E z%v6_jyAe5z{pc`AAduUt9^aU~b>;_d@a>-{bhB@hGdF|Wko5{k4kTk7K{%fQY zzTmymQ2$k{pZ`kQZ1N=EFJAHeSpN(veeqBHKsQ2QUlewUq9?(&l(hv3m$KiHu}OXR zB;$@$K=a&dQN*h%2+4l(??Hua(y#V}CCQULVX-*JiYd>zdaNhJ;oD_VsXV{4fl0&z z#H)t>z$K3ccjd!xN5`w#zaFpmxWy|nHP@E`KLr+!$&f0hh$6E>xm@DRLv(s$I>Mlo zLeVGQQ8Z$peB96%%IAI2wkzJ+fd5@8MMA&D1>(!_pbcL{#UDX3@_^JFM2nPQf2q=9 zIb0_y=lcpJZVU~xg;<1Q7nq23bbxsA_G7V9aiulrXxf6{AEQeIjK@#@iPPA!*j8b- z_&}r*%&uF?v(m}*(+e|6>N14;p1jI_$L=G%4O}P9@MVOgCcC{Ey9?l zC!f+v@G+0XjO)^jLfFRjbJ~2vnYlED)bRZ5P09voo=K~Z*BF*_1UL7vMLjjxYG$qk znQ6>Y(v`_Bamb-O3Fa6IHJIyB{0FEPv}@2?$WPvyJ#mQ1Kcm2pF}R5(rAmmuDnz4N zjd^kzvk1tM!1X)HtdnF0aWsf4t90QnY|W}gbXuVdB&jK6E(3P9*loaO3!JDoxWPJy zaet(JZuDUQhKN7(8$hOy_jFbi8E5i#0(jA`)3k})2qjeG_vqD>9%t5xE0qV2Iv|_I ztkY^Au*8o|6!gGs#JdGcsX8UyY7i68t6Rm=LGqNBzrK9&5qSi!@l5S?@Q6sjIbMc` zg}_@8k`Cp=?7Bf*xF*Oqgx&&*ayl4;k^;az3z9oHiK?_HShL+`uuGHLK64S`D71@c$vo(?{MI$|``Ff9xCJYs7Xc;Wi8gV?Y+ILuL z(xY@ym0#^1%sQU+WgO6xfVlai8?eL0c;qplJC~BJMi(-cwKTnKi(D;eP(#4f*%}XK zmy0iEJ8Z><7L!L5w-u?R?3^2rpl8C7eg{`CR=2dRa(8bJP<3ORQ_>4XN|%u1NVU*q z0$fTk=Lt|(EKc`G(-4(5tJMXlIS@zpQ3k^bXPzq$eHKfZeD-b&_Cdxp#z zb1jXMMfMi$_hq}{FuxLLq@}6j8UdVAY7HkyYPoGp&Rm7i0c2-8BarsTWhWZVFD~m| zW^Hj52c+CruK>&La(Z&%-?uL^cY683p$9}iuaQq=f!i#!SBnsWm77S-7N};98iQD8 z_)oL@4%+P66p)NX2@A7pz(4?0SoN71Ksyh1!$dQ3bnIH=gyD9fLqNx43g~uJG)BRN z37E%5R8edNcD<2i6|IHJ_!v|X|I$6K=aX~nJpQ-8=*qtS3%k%Y>)1^MD(M z2eERGFsfgE=0vLp;j7U=!Yw?rGB_IU_p4Vg4r_tpARI_FPgxd6IiCO6_dinGgE~fA zCsWM6vn>hl$?ZSKrs-3Ak@oeUN@K*(um=ZKRZiGVqW$F!HYh6joP1+5Ue_qo8&t(m zkKBD(+)Us$4Vg)X!>fn@H`n@l+G>c>GYEEu-L1L_CA{24s{{X?r)~`nlZ)lzZyPl*dd!UW;2wj_EmE`LoV46-Z@^HCRN5u z9U($aq?(B}BsQibheWe*H9Hqh1Ik<64kqPpk2G4GjRH=t-_cBDC3H@go4aN^-6Nz% zS2FjXUqAZ2Qfj;uU7os?jsN)5o43=H%1QVU52a6kJ8?@O!j?}j{R)acB8@#~#OHUs zPu`y3(xiXVTXjYT&OO-O4~D!9w9AXTRq&oD3vNF+Kdjpi!jJa`Ab5{pxB($hp8F7{ zpY;$nU7DOkrUZhc*|az~tW1m5kt7wau_sO2m9zDZPG!h~ zXkE$_hkHdt1ONZxM?5#K5x3p!ZzuXgGhf^_Z%^M$Pcq-JG!DOFVJdeIk+zU>cOmf? z^5G-I1iLa=)_%kn&h8q>@pQGsvEpyou4vCVTn98bxo!yM4T}k|=>s+)jaYBva*H_- zkf|~x>frpzmdGAFa8M-TP5tp`rYIFF%fJOxeqh5rl@zX5mYqw)rqZJ%S!O6_Y`%n+ z^t}X`8@KNpvRj87SV`X$CrG!)7ZUg7%tA0Ob5!~mjc64(g7XwhwZNO3o3I5*r;!D) z`~41SWDQJS{@Bt}^IHTHYq6PJyE2ARF*WlQSTil?c#|-y))FBfnNn9uOi)ayg1Ky$ z)Z)dRRE_5k&W%D9hIzF#Id?IgAzZbClII9sSceboZ6sCC1rjGTvm0F;IYJpg5sWyduAZE5n;}sOesc&3xv)WQ^5KF2v0|SFrP3M=+b#m17^zm z*&5b7*y8F13HRSb31Tuf0JWEpzabQW;ps8H5YJ(aczWyxuh`?++^r9jk~%$HpQqEv zA_Om_Eij*jjrSB5p#O+Wor)2@DvvAj>Jt_!jyJq5JZ=6gl_JV7rq@vx4EXjE!J-i_ zn>nIcC0!kNL%7ZC>^Ag>PNoF>e0zF2)l{q=(%v<%Y$y}?stJ8|-GUA|x@oVyFtedH zI3)>hVU=DUbI!qiDr*9~kQu^};t}__R7R>SR6~#%CQ3X(K*cV{OCWnoL-KljMu3w$ z-PaB-qjl(l?#&RQOz9r`bZX6+2!YpbFv`Z|Y!;a{fh-ox{1k6x z*}k5O7i{$>sR&&cfs~o%=|NVJnvUR`g%BsY#wgYRmX{5do*2NHrXc%d$fsGjJFN=I zAtIP=;qay<9tK+CDg?X@+eUMdHLE<^v7HCfCq9$ zJi|U8Kbw{VwcbzmE8}k?7@)O7q2tt+utrPHFjdxl3muk78#C6wr}?L_mAWI-B2)k z%^HoA!{p%eEhWulFAMzxqZieUR;M!Quz`GH)%(6`3*be zqZwtPpJON@ZBG@iPv~Hh$gfXj7-}ezjR@7q+4ks&hNAmlL@N|yp5jil!~qYD8N&`^ z#5=qdwM1)|8jR7kL~E|WI(`~m!&q6-D^}yA3yje?W9t}S!;d3d@#EMw{B>Lfe;rMK zyjXu7$I`E3S^Bqe^#5%v{W^2*EWs~h>AxDs|473GQ#OwN$iY8;?2lt-{1_Xnp`#i+ z%5c?5p8PXBw}1=(*pAP8#ctY>hq^3i-NX-1@*VjJ#!u-Ne^7y$_InL)24P6!_G`QK zP}cy&+egk^=wey#@K84+rvAO?y!a(@R}O7%U_otb52P-QoxG*Tu0mCiy$)VoYLB=I zD5og}dd5&j18D$w63uIa;IR%4Ap{~uB2vE(pk-lspG0%cAoy5zqB&=Xel&#)f{$e< znsbKeM;3Jud@MVdbH<{KRJX+69BMFFpft)U<=;nrP=(&S}5T&N0t6k~Pmfemz|53aKIfF2GmykLEAWc9^;)O~U2;wIV7 zR`ZHo>-51`XC3EJ!SS|ZQfo=jN;>r1_xLwTASr07T?4d@s+EPV>L~E8Tts&`UjUUo z+e(?(xP|i2&q3rQ5WtmK^Ll0uFw6C-F3_;Ulo8BxAS|s zM1cGDHPq(**53J-Dg;XVff!c~H$iffHi#hK;;76&3+M?2uQ-v`Aq@r- zIeMmxTzmjbPPB)aS1~f}`BU&bJe{2fu`M+XA*6gIqRLjWAWYUrk?k;L)Ot@3Sj_ryrSh#QA9svgUn2%}ID z=F}JQeN^Pwr5o7s=R3Oi-fnw&I6CGls9H$R>ZFv#tPxco;^DmZ3Js2wpGl40;$i?? z6i!*FJAVL_{knLC-$y&^2qp+Pw!?e8xr_# z4db{&uf`FA}*+wvWL|Q?Np{DPXqZO>9Os+nX0b&H#qvhyGNuSSWb^@jiu>)a41Jct{sJ$OV}=V{ zVzp#vjJU=09=s02PcFdd;z^V{ASj!&m(~Z-v6s;YVa#~%6uEBS@;GBPDx?BvzTEf8 zBU7Aq8M%Y(B^aOGY$1hXB@4o|0<9>}62N#NT&5ZAhJ=8H)vpFJ)4^a%LbxH(80bR% zvUD(qQsQuhA`}2~(KQDk?^M#=OLbCk3ZFNWV!Dtd z872vjR%KEs)1bw`+4nQ{t+Y-sGw_dE>eUb49fRnOqLCc1)~M@sG#TLLa|p`w%kXL~ugJREkj zSi^W{KzRt~U+CR1sd7Sgo08c0PtT30_=ZeGEP?WOgy?o%$cQhy+9H8Lxfn0hCZ%d{ z(i50UKzPG~ADE?q%XcfY0o=@m&Oki+~1 zgma88J5C?{p`irMQOyW_h^J?4iAhaYqCn`N(l2oXL=BErGi2D0k4WU}7K*)G$c6Nfm-{_k z8%H{7O2SI1R8Cv$yhZrFn*Cxr;pNd(T~UZd)H$6>vabG$aib;*4I66~gQv6VCHL_jvhfv9V7FO>VHz{msZGDcoY%qL7Dd z7JJ$K{Q_N2*Tw(1L#~dFO?np8+ZM8O%+_{1%^_1T25$p-#_?xH-UOQ}2sw@le8m6QYKi6Bh@_w83aMKO zBymH&dgSw`@kE8}Wo?b~#^TkYGmSzO+^9l1T#qE)e zpMaQIFRF0eJb2;9`qo2Unz3m&d%Q|uq!mwugXqLq+>dCvnZVISX))Ay&AEbJxBK;C zhNmH;2Jxcv2XG%7@53N9H1Jz3}2eE{)SqFz0i=nz=q@!b;*+|FI6l^R^eWfH4xJA`M ziRzmzzRr+4`N>>gUVW(Np}!lgKCVgEu@TrH{a&+`OgPAp)4t>6Y{drmqazrmkR?7C z3tYFn{q&^j@E$dEX$%RaemDns1GoL&dG~c~Rum3FPb4mF_`L3BHx*VS-)lm{vQx-E zkoLgQ@sgge;#`xmfUgrlp$+GxNY#}qIob*Pbpr!jD+Gm)PQ0c?{Oj5L%L5$t@=)p5 zUJ>IIn*(@xv{n>Gg!6XuDEmmYh|$QC;ZQf1cm*GOzjTWfga z0cYG>aM9!P1&!21;KVJlPkR6r;(A1r37q#$DqHH{Kf#@<#7XQ1=fge41X4+W+hnb8 z?QEyS$!qUvb9;~dlFBOGSojASxoRZQI;1|{Z`WgH$3;u>9PQAMU{2rvyThyIGn$jc z5dfuX0(zj_EVo^)T$y8;Mi1!7W%qw0`n-}!k?HBU%8Wz}R%K1JXE+(-P%^?O3&nc?ijR(S;$_kywInD&C>guUR9RtyH&W@NS}XUS%+h3i^W{*UL&VWchv?(D#vu<*68Lqb z&hEKYO1rq}LK~9H#dA^#Xz!5n8JkTluyM3>*f!YuFRl*ABVY|{o$b_+`Y?;4xEA>XX=Xo`>D-Svv&YN3`AOI@#lZi>tB`ySKHOc)4tlUDY-5E~m)-A6 z9MI3|7@=urNFEzVjYoaI0A`CB-fQV?i`4dJd5iGTUch^#ckPEjT~wszbcPn!ed`7tpc$4C^I{X{kfsQTWYUJltF!=OLpw zroBJ^V_NLK5PI3w!>-zgW?ObTsh=a_I1uXPakBm*@Dv*auO;> zl3gJUKj!jYpCUwFJmQ^+<=h~`QsW-?lnz<@dc@alIDIzZs~OBg6{d_XuC=;0!TEi* zJuB=!SfN|?1mO(17)z;@V+@4MvCX0#FTPI6$W<+paljIoR5wZ2*UYx_JC;aQeYt*L zAvkShzfHNv-zY6Og!w#`4-`dF#gOzAG@qk&YMLPP22IW6y^N^Ds6%x{!rE^%GzTUe zJ+OY;-`wDdIMF6a9a+UA?Lg74XN?E1>pNSs8^nzpi>oyk(dS*WU$j-sYQzz;K{sZ%izB2j-VV7`SFOQ5t!-e=BV|*4zFHuWN|kJLG&=T-4@SpI zwPo8-MWK4>gkGV$*JkNdMcb&hb?<7{+}7UU96t8&EV_$etCDC9P$P;h;gLR~6=fAE zNSP6M-9NS#4ssleWaiHlEz91dPjLn?idvJ$>rt6J0)Nf)eIB|;SxN|bP02$S)FcmF z(vcqMf`as56ttrUqr$b~ePEofetVqI$a}l~y4<$wVhEMfG8$}x28R<^C+q&zvZ@ER zwO#Z3zDxiogP$++_W&}rvAxCV+P4F$+f%NRgD?mEF4a7DIU1=D`WK7}iB69y_v=OK zWc0GwYbi6scf$zQRfmXS>ebHM!}hX zyvmIT4p;{ElI2<{Y1%}bQ@UDfQhM-LhUO4gScn}(8$^_RnY-ERA;?X|M&>E5qu~k{ zf2R-z3^imoxq^=xO|po=5Ln~JFTGzhVGAXt;^31N^VG7A?1cBn6;d!ez^9iYmwU$= z#z}{lHFr1=lk$t%?#?$#(L~xW%INFMJVo%RxmQR;E#!l}c_ky3yux_HW75}Rr6k|^ zP@}*(xWL=5N#XhSkJ(m|UT|IX&r6Pzi4)aKxX1|C=cw^mh?>Dtgi|W|dh~XTtK5Hl znS=Z(_wnc4$5;L%bBCFdUSAQvh`sp;0JoNk0N8t=#v@mVA)qpta4Rza*K~7(ruBCe zyBpP*fyb$Z=O|Mix;aqGgeBa4lzPs$w4XosaRW{a^1o( zKt$wzx%{?0d6+%E!%0FJ2HwZIT)N>CCNVN)sKp*}QWOFu2U0`ecd#$!5S&IqnXUrl zAyI~WM_DGXXpc85%y+BVZAYoEq8?y0Vb@sF9)LV$s@PC?*kV`uO>@0hcH3x$s)&yK z*-AiOQEg;V6r?ZJRIpA*;BH>|7#RSo_O>4Y=KZpP2gnGqRB-4ggv?fMsC2Hh$R3E} z-0IRcCRjU&WpXsk35cs9YAAR3n+Cxrt72`g9uL8TgJx@P#s$TDN_r4N1X@76ghCmJ64;*XzU zU^!b)%**5he8Doku{KnVM$;#j8 zVDSEDRc*PRxPW*}1EQ|-9qwTIt0Ax=1T#yjoyzgOOoyaR&n9fALk0JYD9B<(thNG} zzF(V zSgwi1otwiz9<5-s8#Y2vhz_ER!|zQ+?pzl?722Qak202uv>M%G%iaWKP9Y~9o1F7o`i>hTSdAb z5Gj-LGX4m+MyvO;iFnWXIVy#|Y;a$BCb6WctxMsBI)`7>fU^T4I4QUl1&u+fiGL6H zasg~nW(edFp?pBj*U)o}2Bm`(zdW~EE3^4ik%55CidY8Tv+gOGXy6Vp)v^&^S7b}cZhRE`bJ(Wm_xz?~SyIMdx zq4(_;@2n$t2OL3OgYzDe$wg+HC$)vpF+sl-@o!P{**?-_5Ka8d<$S+uZ*G23n-ct) zV?1!@)urUb{Q;%vr#7pnNYrKqB~;;+qspZ);wDS^94Uf49BsQIwfaO9ypdw=yG4QhwS zIY=HklVi)K56H;jWRV~uCswHtnpQ5HqH3{sDa>ZMfnS?r%9X?;%J3!SmoVlDSH7qh zH!ovB<}$`kml!d`ivk1K--aG8cXzxaPyl)j+x=w-NHltY5(CkIpe*KkZ5s$IB-Pu( z3}~sTXknp!DCzBl>E2RQ93jVYF?}qQ zDUcnn)?{1kO3pVsTqVAqae~s|*oN6zHxIJQZLOE*N7qGl2qomAS>SbnJQxfQTps{q zvfLuM2h0JsoZ>d3PB-szD*m{GZ!mv7n^0W1D`93~h3z7Q2ksP(-~y=tQ*JsIJ#oz( z$y8W$+pIXjI~f{wC$fg#0y^o&{UcrMDt|3vr!ytrl)PN$ls+~CrdzUY{)ugOYE?o_ zgMGyo>rF3&IG?>Br)1RztBPhO(=^SDh~8X>>a7uDE7^6%y=C#wNKa(rv6n{Ja_$Yd zuhf(UwIy$%HM{7BMMxymCKosmyI2`m3;_m_co3R#Z|Uezd>lq3V78a+E|}-BX`KnLBy;qmIbcuE<9ebwwI&#_oj4{%Vc;<7@WdtXsaoHl5-;a9^%Xk1Uh6$2QH=&a@}% z7gxwZq5%3y!^?gHFZ*n0NWf%Q2n~@!b3A#+q9NV7#84WT^^+|De>40HOk&=5@BGw)7U#R zXp;&o3+4LAH;6Mhu2s z@%6S3OUgoTXypMEOKgkoNQ5iRn7mha6l??|;)923kLiADU$+Z&Y-p(4$BD>1Tk04x znz~^OH(sz2MAmw6Rk&Z*OpwUYV!+~_;<@6EXJuiN7RpyG9+=CVWovozWM#TvH-QOi zKw1HiJjmGAPUsq^mpD0B)uuEC&V&|h<-vC1*S=>F58D(ZmZ=#o0U))$w-S%(1oaSy%wjFWzDxy>{*#3-Uz_z8lv z)3sEMYQR^gENmlSi<%Nrm%bk)%w1dsYt(?dG)6Fb)y%&rdf|j6AQZ|SBRf?O8^Dz6 z_=oAvh0TQe^K8Pb4^k9Ew#{xh#}vs2@&vhw9J9>1q29GCHC(xn&(%CaW=>>BI3(K# zRZs?PI~_%V#Y4(Y*_fvrJXwH{E9sTDtA=j`g&;ho^V!>PS63G=%?u+LYBVr8%#lC; z_+v7mq-8Pd3~~2j%3jCcnr3sdLSBLn?_o)z6US0U9&#4++JFBA-JzhF@UNfX|-dRtcDyS-60@- zCxeee+#w8$$~R__u@PA#OT;f<2DFW6zm({=NQYzuVNDh#Qb z-2f-YZ?S?hPuxT2miYEnS>ru2lUSI`1nL6;JO&n8>EeD`?OGCS#U154oV`(}^$fq7iF)&>L9 z-7Rl|^%V2BG3!}Me8R6#AhwboABZQV5bj~N`a(|opaQhy8$kt0KoNK6fB0PhpA;O;Ef@FWPp+vG@s$6+}#yPml_9Esh8o$G1_$ zQ_@>fJ?>IfSAVkj=N_?lg^d@}$uZAacgza`yCZ=cXxOx^NvO4H@JtVEJpKl#LuxGI z#rc+wAvjS_Nl9bQB(+9}B37C*t?qTyx%tc#yztFe7LEVfv3Jg(TUl^I{;|K#yQmZa zlnXuz3PX*DID*np$JMdJ&z>Q}CWkXE5R%l_xat17)B7vBiKeVB3{l)?=9MET!#k3+ zIOR8;U0<1}p>3vq$Gyww@|;&1lXR&OLnMn1m_gbULd#QUaEaBmy!z~FoZx}xw|I$l z18rK%-Ezm}nzyOs?bi4s>!GJ&Kv@s2f_U@`{RX&AC*-KnE3JP*`S8pe?Q2B4S-vcD zOPI0^Le<5{L|m7;>@-M>~h|?)ceK(_5#jB?O7B z7ab!iHh~~0h6(Y(Wa{HsNnhPpGC$|rH#o7RcGa4~^{5Qop@1ckLsH&71XY(2y zK03+zalce_|iRvkYefuh3y>{X1TlqIcRYZEVOn zb`T4+oS*FVy>AW;&U{x`SXg8Lt_!qGWkCujyqooKg;9s?uw5G~8MY46opAKll0xV2 zTDAXSx(fI9eCzOF^99|{nenAQ(uU|{(KQ~gjJ^E4x!pp=J^Hmx=ohX06;tu-316Yu zmZRg3Gk#FLV|p1wg!nFYNkj_iwd}Y&vVh!O7tn?1k^hBbR`4lprASZu!qy9J)J4u#qo`)jq^Dfxn0nm#6MYow?<~45N+-;_PXVc~E*2 z?{^2KY=w1?*j?0TlN$VjI z6}^Vp5Zl4aWG2MSlKpPsWq^fSBs>D8fR?ge@hq`)REn)V#Z*bAmKsG1rnqsl9j+73 zU-RmG*}(_!q>-pd6=H4kZno-zArqBfZ9|iu=OD7!lE0NA3v|uYAGBYS@fnVeW#eCp z#TaG+6D*Jk%A|I4uZ42;#4sZZtz;`f>jtFYD0zO@`+M{D=jmm;{qWA0(7a;~DyI9* z28!PqPsPK83W^%e5Y>-R74EZ0)8NP$e9`hTD@wQ%W}b11D^&-APDhzHj4}GQSv7d| zeRqnCR^fueO2Pv`xR6_ODKtHH4knBT+E|Q<`#xQ?&Vx{{wlD7x@P*NF zOF>_{Kgh&Co6xO|*}`sDnyJu@ z4?S^u$g$w6Bt_{Si^t^(G~d36bhNw6XtM{A7fCq93haDSEyUi=wyR(n z>B%OC=3*__MJSXdo`s4Z1)?9jk?Bmpbygeey>2t58K(Og48k93vtlbDI9 z)RRQ4vlfH3Rl60vsJ!Uz5IELn(oEEF5Q??zK4ZI_O-!@6dK*;@%Jf9`)+p--xW?Uw z#K+- zk$4)nm#og$zv1bMb7h8&+ednJ*-(x^HCoL9G(E5(x14Bs?fHrXi8|krqvZiEn+0wh z<9P>X8t!)YE7=C~->B&VXX-Oos=~^67a+{oM*ANd+8DUNbfF|WbW+kq1~2V#-$?!|l$NF- zY~?GKvY5Cy9=wsPdQ*RmG1B_@RhGC#@Ukf95cX|O(XNE0u(;3%Ay9!40P#4;Rl%0c z@=&gX@yq1xy@Om0wv4fZeKBj!0*Dtsp#SflZ=oR*Tw2M>1<4%vX65bGK1_d@Zyz_i z_BrM;S})t4$yFFPhp^ocMZc~ad_iM^8>+Cfg}bs|cWAHrOJB_aKv}mKtRziWSjL|= zIFPYHPxgf-*Fw*4c)2kA<)K2w353-HROSvha&aAb=e!8B6W^6}OJ*hMkv(#EkS1am zv8aos8piYF_2TGwC$a5j=w@f<6sXy5+bww&Rg{>)U=$Q9Wzb+e^@9e3X8=^k^|>ao z6AS|xpI{qWwm4mDMF0$#k%lF}|4n-;qVnL^b+PSDIA)4dPAd|?gK1o|+KTlTHyh`Q8PPoQ_30K7JyPQ)jjZW<=EPP5G+6}Wr zk;Aah9bSxGJ$}H1(}iGA|A;(J+pcYJ)mYe!MH--<4xX4FG3VS|Qr?aLvTj(4V7WZ zuTF>jw^Xp#yv;_;dKyQ^{%Z+iOMAIdN}8@|K5ypO%ckADJsv1Jz0~`#mMozrJR z@#K__Z`l~+yb-jQPW>BU%h>qTZdf`>TbAA5C}Zf^`XkEup7S>h(2X8lzFXs71}|GXGJaD{QjD=3s1pVkX-kGKYUi#1Euf2Dc)2RbxO z8@Z6!6dsp!BJf6XMuhV`1@G|`nwxfc-pmx3sWVd|s*QYM;r&AU8U3K6Ozb;olpj`| zHTloM)kXgqW5`Ruf0m=_TnTq$u^^79GXaep*h@Z38k1%rDA75RV)7>rip5&tnPjoTEoOc?Wvo+P+2Da{CKfLtLXbRX>k%0NZgB)kRgW7r~T z^j?~OKhJv>w2yG$K^AESP(^Y%1A+>h+!Iv--5IqIWKMI)_u=6#upcu(0S~OZ3%&@D5(~?erJX?tvt^GM4>W$ zbF6=Q&p_7GRIMoVOF};CpQJqB<`k^Jq@88@8y!Iv9EAv~uEt@J1Y{#|1Z86t!iw9*4yRc)ViRN7U5ya< zC--JTTAD+We>PFcCv#kcpq8C0%F~(y=SmCL*Q?u5#P4YmB5V)|vb7l@YU)Z*ddPE; z_9tp8$RG_>VFi3L|59B;fYVa}-?{L^8>^&Yol0?fDu{H&Ej z7@0WuN_MfoOF0^iD07-E=7=%^l=J2VcuDY2P-+aAr5YyI%R$vobz8{M=`wW zl0)P6+_pG*K(qGq-CzFaUvQWp z)9QbtKY7yI{^ft!`T;utX<`NIh%)aLG#Sn{WPk%L4A#%>`Fe#wdlrZ<^hI$ANyEin z+ir8UI|HJCJXIZgoDQFqNbd5ArWOTaJj;h`933ZcQ}QXohz+z$#|^^maWE-k5kbvU zF7hK0uY^g8D)Ceh-ye%CgRy56>e|nk4MR2vnz3AHj3(x~?&vrZXLB;2H=E#ODF?Jz zrOa+&`*6TH{{oZzI*O0;hswTs7&F6B?4eo%zy_UL-_gq0(poUOYXk8 zC)?ZE-(;%v`(8qrgXRtGqhn)Nf=1Y{(%4&M*4tmh0lR+=ckLe80-AkCf6i|@7d-PE zZ>z1iYw7a&r*;ZHemEG@w6YHWhC`CyO`#*J+4^?UZf~D|d)_^E&-d%)x5@o}eUDeL z@`V^~>lXVBg<`xqSHdLO7OxY;4po`C3)6G5bppxsG3Z!X!vpc)|J0te$ z9lC!Qh)0Q=o_gt>8gA>LNw4DSalr-GeQ^(e@mxmxKk#GMV%Gcz!d9C#C2WD=x@J?w za{$6?miJiKEwo?+mkb=^${&-D$oz6QTP2TdU+j0EF*`&ZKZ+GGCD}0!ql@c|e%M_v zch`Gll-RMAdw4)YXLwk0-P}%Q?4|vqTP^1e=cUU_`*4a_9e!Vuyn=i(Nko@)jqx0x zObmDKl^A6O{a--zdx$b-by%91^T`xQ(#Wl>U?&`wTCyfaS+a<-?b|CHgZHVqMec06 z!#fK4Y&~D?DMX_Y)w__DIv0O{vLkV-FzBP7bUm0DtP|YZu`jBS zM6ut^?w6Drb*$uz*u5@G$o2#6Y^sWSDGm`goa|-+sdr0eG*V zN?LJ+?^bPbosp@l$3F|9RYsXAzC3)LwF&!;Z`IVOWr{YopT~CYK|RVTDCyB081E|a zakq}_OPmT;(H{1$%(Q{cm-QS0!)9i5JG*_3SqZg&R^>d4|M2$eUe?sKlzY8jt`e%6H2TkgbdBG3~_Vt zZa{IBG_U5MPaDca_|*d59D^jra!(t+%)EsE7sh!-<+wb+&rA&%%nC|yt)9?|KWM^u z0zPGyJX{L<%>u6E(5z7sf>)*Ao6#}=vW%$1a8E@IfZT7jOT6DBEe(1O1Dg{gAnnr@ z?lC;J-6Mz0j2Eis=ovkSC5w`%_ zA;~uDhTu3In?KF-Z{Lt>_wM=Em%O!q%UPLu;Py|;CEeqrE!GOoeO%B9*{!(8B)Xb7 zU|j8xyA=v4^donL$>eSZ0!^!ep?(&v{?*XOa5rU`W*XB7S} z9;_HS%dN51g8V-358r1&4u_DyQ}#&`Qg){VZ~4+}I{CD}f8XM06W3!#w-qzGnUq20 z>W*TAx*sfI`F)CyyXIos(oy|bS?V39=^il?2)G~F9h{rec@BKkbGcvP9ix$S$ZI~l zOHF17MZsi~veJ5vojN*(GBHf~ox##vaE&$C+Z!Yl-ckD3{pRxH*w(Sq(sKn^|F?Kz z1JPOISb&@ArSlYh4aits9m$MjA(_Heooz2a_Qe|YEfsWo3?qlRoRMrK?biMtnefI+ z8McXCU&@3szLP`jL)&sa(|Uqr+PrHvwk2faa&*2ISMlaWjr*JObkMq~K<2QPeWlzH zFrczycDCldkI}}Kj;bOht4t#Ej_i zV-V3!2G>v;tNIxp4%3aJV`z2I7Rne+iH8o_v;|*h(ocsB9*-@(JXR{X#t)Eo3p?_a)cSsb7tqvs1s;mK}8b@Q2X4UUxxCA%bnY;gt0ispOJU^6v( zMV8~{P=n{&^?AKDo&J=Tc`8qDTSRO03RuhODPuy@d5@^&L(aCnoP`2QXY`&>%E{BE ztoRu%VPm)to1pldYKn;J5YamheNo3HuhS#<#jg%y^J~H*rxL!2hc~8W%i>Un zm(JrojYIui(h*B#YzOeF8*oO5g8U>IS`r6|aMNz~E3Ci{ zYs5!HR`9B;H+He4g=+-#x|p1{yCWQ3xd=k*|8wgJ%cj)@!o`v*rwh_HNY>}cQ zeemi;(Ks-8K~Xq3S|sRaoD~brCx_K2)&inW>U0XY_+BdQXpP>HIXb@gDs*t~r!)?A ztQDmL^(dzB9XLU-5A4tD$KTLpPgW+yUk}~?Dz2ZVAX$bF41fqU&l2VVF`7r*JEu3k zac)7qW6bhlqgy|N6#%kD-c=_Z?0a z5l@1BN6z!KM~gHx2~XgU$L|yHGmMOGjOSrA>d`Sh60*TH6*IY04r4i&#B-hdZMXc| z;1$%7>&ip!7+?`#cXP&8=kFek-fHovqxTCv>Q7@CRu>`;_Nm;Jio;JI+_L$ZSvL>d zJTF@Q;K*ydFigbi!J<&{zK5-F;xpcZIf)6mzByE~7=kp7djm6Gx@I>~jqmUa=eQXg zMe+Yq_Z|R}9M$=FcTZ2)*>E{amrytz($4K(kPZO~CkaU?9484OBv{Sv&hCzGc4jp* zdqEfsSY!(c0|G=67_g0vF*uNgOwQ2;N5BdA8*KR5nB>6!`>MOTduFFY^~~P%?Oji& zdavGl_3G8DSJhSS0DxQtOVLEMjzV-bh|qa(MbZ^l@}04&i{FXw1%6BK7g^c0y9M6= zv-wB};zSs^^^Evn62ct&#;InSbXq(pk<HCGfyT(FkO^byOD*|mNZpa8hHrE{YI7)z>LVr4&#n&9h$A>MG zh9d(Wu9q-zA%+pS{<1^MOBTKnzN}s^Vj_~g%o+D$LlZ0>b|%LKIo`e; zfCulwVlx0oU<)tcFps+4@+GQ^I~@4R)|p){s7w2elXqc}4Id7#DEqw%%p2K4ibq=~ z^thP^!V0G0b(UME_PfBN5a^Z1Fn!R6WTza_Mu#N{aG_iQT^-R~YOOxLP%h#l#pBoB zbmI*^L|Qf@Ac4cESiIBizk5VgZro6=EExfC69g6nKz&Gaa=yG)^GOqkS%6{IALfl5 zlg_L!CRbi)0Xq{En3*qB3*tDf4lw(GwV;mGE&;b6TnqA8tpbqy!L=awYd73PYy@MJ zi9c8?Y9H|imN#+xz_lXxlW!ei9Bv?+4h5-mh#z(fa|q=!MhZM@1n1K*+WX z!s+nuB)O>Iz<1U^Hwm;o$dU0R4DedKse)V-H(jtl;+RnX78b!9P<{e)3Tv~oeod*9 zNbDWu<8(WT{4)zI)+d)*27ui5!$BP2;f&&)PZ3E5gIth6!Yn{;J{6L~mGhIO>7Z;- zZo;WR&^R=yB-`J?@T3SU5-XArTD(D?ipxCg`Acy#-I0sEH_4jDn&_sY0bKP(?}=NtBJyRKcyVl$8}42&GFTi1cUDY``W)FG9c&a+nGeY*2{DwIPQCeI+ToU{@(<7y{cA zHJ?*cEV6 z`S%6fVhwWZ9Yj{3Dw=a0EmahO`8(eZVMyXi2{83mNcP)L~9vF5RybeU1+Hkx!X+w@MN1Y*-P3)c zDOwgz^tebaj+P}6Jt>5bj-9yL_ge5I!IZH^Dae=KwOhPBZ}b*yl_$2jYTuE>D!8v<OV38NIbw_X`oYRKcrhT@V;AXh?sYe~OI8_Iy# z3_c=8kv0^g_^dFXkLz*+N<*<7Zr`n~qwGW~KkI3$(2`HpJ7Nm%g`&eD#oL&xEmr*c zZ{a=t1~=}3Lyvx7P=B#PK?=(2mrWNJVEwIqo`b3k`{Dj_B|>NFNPtNIr&iKHbG2*t zQVQixx1H_r()9Mu)t!?EWDq2SUAvp!NFEmL@eSqS3l}Gx6`W2MeTd0&btE9{=Ozkf zL*^N1nq6cO?Ii1{zlzvKJUm?F<{MnO?1lhKI0X#YaQ40!Mnp2sZ}O$jNfy|HYf0tj z9C-2!?hZTHLOi9mbQGcEgarjOJ%j{?I~@E$j;A+K1kS_95k1rewNg&Lf!%l~RY>&5 zO~-x10{S_v2?KfwtqFs=Cv7RC;0%hCIOsxrV^6ve@7PTl&=vM33g~otlSL6TIw4U6 zf@J=^W^bM$JsNM)2-=KnePg7tMSeRctF?xM@db(0Nj{TGv zmG|6w3(gCGwe+w?I~QoXrP0!9^d_3BEu0j|pj|B;jE;%$SvYnX49`%kff1hUrc(V_ z>FS$rJ{+DDK53*xf|u}=thiInn<`ioAwpsd*&eEtiY+~1uY6i0ZOuNOZr_f+b9#Pi z&q4|(qJ0_V&iJk_R-q&z*v=cZlC>DP4*1R+jmCt9t$nPhBSJgl2x+0VS7V{pwhzfV zAZ5Z@Yv8Lxsz`}|%38gp9)Uo$w8d#m#K-Dmt!+gILP-O*;HK;ya*A} z5@NL*r%8T|Yi(aUGgGPu%ivhC{-kYfiFu|glWbFBx>U0_F$NRDG zp;?G^6q_Rov*!n3ucs8G(stttI}))O4k;oBA6$whk?U4D9bvhjH!AGXjn&r0cRHp7 z%BW3iu*TUr17DXIOwH(!VQXl-$5YuFHNU?lRKtfRG?wtBJ#MQAqLQZF4C=_mwj zBq?fkxWfn|6{=836Ko@G{p~4J1_x@D2)Z0+Y?J)s_yCVf;e4V9-AxkMECKU zC7~b^i;ijse0WNSuS3|1FxOnsc`ktc&gv+4zzR73A$=RzPSD}2Tsy%v{NlC)@=|pQ zTS9kuv1|7=R|L;GAm+AIKKW0Vd@=!R{=%|LrUPvNJB-bAmlhaa*sI`le%a}hW0wu= zch(Zqu(be4JB=3Eg5_E(Fen}JYqt(Ix?Q_1O_$4nE#<-zs$ZVgTmNk3d$BZD2ePd9 zzS?HJ_EQ(@t$)eL_hP1sk2bWV=`bYi7D(qpw&0g~=Z<`-xISuS!FEyuxw6q50*~(0 z@Ofcd#D0=kqnE2Gu&2$lg^d{1ss%oVHn+g5>R}6Tw|Xc_LahM3YAnEQ0d`vZ zEkq&Vr%4;9M1u!T2B{U`J8)5L-D<(TJl`}|TYxuHXx2`Yv8eKilZ9jB1@t>g z#re@I%5^NPg)PfEbVq~WFhOFjShe!%FzGWosBpKUQfuW(?}n~7KC4BCyi~6*F0>4Q zhi5J^@EkSo_8wetE{{z~Q_vHvQ94}8JbigMVcq}jYxx<_nK^@nc znD#Py*$jjc%8rwdKz~znaq_&;XocVl87@N`bZPJQ|uO3ll$V<5(@ z+O}X-L4rM6FuxRW?zuu8f*yqi9oXB_(^tXPUN%9ng83GU9F!XKYs>THCYOz|*;mPH zDKuIe`U5SR6qLW9c09T^-B7D7#2{2;vp0G+Vlm^m`Rt3H&rKDK<<;$srsfu_EyL+S zg4?yb1y-fhgfLn@F$&A5c3f25xB_YUSSdI!#!wJkjgix?-L0@x#l3DXX*hOL+f2U4k5Uf+u9lM*MkaW8iq6^yAEE{TR10OX%%QNtf zsw^2!fxE|1q|#!e;I}PGVG8^2!UwF?8%w}DQsPO!YxiOLlNg`FltFtLf8c>b;ouC_ zRu4KTNJo4sI52LAU^k3a4~g=@=p{>0(BSk*HAhI@ArezC_{Cz6@SzCUyNQjBqL^zo z7vRd)ON|9=m}|wR>)fSbwg^R|Puw17jv~M)m}zU50;g^+apOdZM;tJ<;3N&uwB$wxu4;_e6Kc zd!oDJJ<;9qp6Kp)Pjq*@C%QY{6Qeuc6Wtx}iSCZ~M0fZ0M0fZ0M0Z=iHjH6kVmCzY zqBvvP6lO-DH_#}|-cw%Spw`l13MJC)v6riAb*%eRZD8MFjA0ZjTD8k>%4X?=WPogx04A+9k0*Si1}$_+S-ADRzkkAzdCRbRX>KOtU>A*k#-R ztLt+tgyJG5$uGc(w zUuoOvJa6u87P>E9A^W>1%8gGAgn~|^aqnrLy)f%x*kg)73mJ~5Lhge4r{B&)_Y`Y4UAJAkmvG*Les?FFOTJZ8 zDxZ#Yc3I{fadubi{wTXFd0)h~**Z0*^lE!fM#6dv;birvyAV#7Th~ra%M(tK6W%>l zeX4MhASBy(Bu7XNLCL9j(i$d4NG?Ii5t8Gmp9+U6T(#xG_DQO2ZBBZU1SK2Mq>1Yk z_8lVX)G6;ggwv(X_OaOPFek&APDrdzn(dI{Qqnj3=+Ke?N5r8e2`-33Oahz_hZc_? zlmv}&+xNcLB$t#V2&UgohO00RC5aJ>+l2RBY1$l}q==}$&P1#3B*BevC`y6@k^IPq zEiQjT6B7#wr8F_VT7WPG6G_+1q!`@*Il3hF+Yb8^nH*oxpT-3Fi2g*nUv~B_SQTn~ zoR3fY-)jvLq~qcB*PZewF##d2(6Vk@pEJQqnJ}N#zt}C2Cc>BXCsOEUf_z+mN@I_d zclzpCwzV-wp*x|J9q=Bav@Kh&F)jo1q*Q2nOj`L3$C7W;-H2Rou^vHI?TfxD4#jt* zwo480kwJG#5QMZ#JqSQ;8@*-qW6L$Mc7e5?fxp=}m6LZPl5|SDpAl(t>)Nt5{Sm1- zRq^kLo+k_`VHV!Qb5{+z#k|Q9OqU4Ba`Fj!( z&EYBSGeo3m+2fCXbl5%XQ#Gs}O2#P~QV*r0&kluCEd6#R976i;L^zbRcr$&mZw@J^ zC=42^t*0u~8A^z=M0j7?LZ@6#QOGi?INauV8DqSm#8^UcY3X;>ae^)h(3MjaLJTdW zemermjzriM+@Huq#3n+iJT=4OA-WbIM8QCkHPJO<{WGWm@^i`Sr;YU|Fe$#AKZS|$ z@%%|lhVSQ3UqXCBe*zQXEBcd{3?I^;zEe5m9lt3N@w(*O!$kO^{$-trkX5K#(>ISn ze!9XamaA)ha1C5SJaqKM2XHBYNStpS`z#WNj=qb;I|9{Tp?E3jyI91Nrc1TlGAt3z~8k>!UP*BD1Ryw5!VVQGa>F* zfE-=J)mKC6PhmpbHGcvE}$Afcha8g}Nhrk3nmmWFxac>d7NeKQ`#h>n^##3!A@F%>#QwL*-TJUt5 zX|-!ylM!$T)r+LeH}Gg~D9wrOMR=HKvvmg-lODy7+C zvsQQfu9$25w4;+lnms~ikMH#on{Guxf;qG=_T|!}(rQCt% z?h4uuVV7m?gVr{2%Q{NxY>&#KOWf|LVMLwM@PvY>q&_U`7rT+^acu9YTHrIR*v=be z3WhqCF=`N9Jd&8CR5WSz5+WX#oTLcInT?YO^>L_4lz0+mf`pJA!>FkkV(@!lA?QaQbBF z970Y}s5OGVo~j6H1X4~-U^D_DrzqYTfs#`h#*9GDDUD7>pyyNt9V3u(N@Ix;=;^AzRt(sGI>L`D{pU~tuuKqM8%%SxsG+B$JHs=z9omxUraHtW(m{2oOQ37&(3V7})FCdh?x;gy zavf2J#6-HF4t2?OJ{=Mh>2~^i$%&1)+5+{bJh?I0P}2K7J<;DC3lO*9>a^2t*Dp_) z;~OApm*&LvCH$#QVu(DnA||=-5hQ9kZS(ZeX-V;ErP1!x&eKQGF3qQvsGS+0r;nr^ zl21QDyDiLVCT^GT(@yC9{Cqo>!$PJRz7$yCR6}JndU!GGN9es-bwo%cqNN*b%eU0h1(bC`O zZ5uIti_^Bz(cg${8!>%u_k()u?z+<_N#&_@yIX|hPh)@MsS%0n*Cc?5{yiOOQkAUs;mlsM$O{hE^+N?6idQCDI~vmg#-$#Op( zvJ&QaI&>w^<#b3(ptI@FmNYlhAuMqYrbAi6TuXw(t(^u7N^QV=eaAy&m9)`lD z_q1v3oJjNOAz_Ey(@VgoTZ@;-;CX~*k8~#}oE}PXqWehxtx0kk5jmqZA=5-XB6BHA zod4*O)~^qZ{9G@Wvc7#y6i!;QylaohlI2FbgeA{kc4S^(aqERhj-m%L<#;9dF>7lU_6OQwVA(w96>(&NIpQTODA;iV}3$xdb*KAi5P z%?SyoII)htzj7qC1K>|_Vmk)@Bqy`O;7@PD=J149yySK;0)(8rhsUxPdxluVt zSA@eQmWs$&}^WCwQzKH zv|KGTYx9$5kC%>(jqcigGp^6W!*Vm|{T2A)Ht_w)a&K3-P#Ru~d$fqUI^1o91c@<(ZR^^ocUc;>5|qv2m>JTU)ri zUOV0>)f?BBr%^7)i*<1A7Oeu9WHto2S)MP|7Mlv$?b?0WLiwgr{aC3E7rwTzSSdD3 zhicWCG72~(w-(sz$_*Hjh;(*<^yW5Ot3v^bh55x3qc@a}9|21xlvF4=s3`UFR0HHU zi{&agDppTkZ#}%STAZwupw=<4)EBFiY!5IA?NG+!Eh4JdHPz|TiBL{NUblkXo1vCd zFbJWXd-6F_YLuEBg9+Ezmcl$t`VQ4g1T0mjYSXY3g}WNHDhu+85*|b-$-8RhD(Yq} zN|}3Tmg=j3(U{VFb$qd~Fel}inUx`)akxWBGkJsQSF0giL2IL``oXs%cl zUUg_q5pB~{gFsfXHWx#iu(pgi*d3wr(#e3mAt#~>T!*U>YI!^$SCs3esb;j|^nk%u z)tjRE*{hbH3pgGZ5MGE1hbX-$?U0AL<5(OZiXrxZTsA!|?$k(=P(qN3@@Roo6p3Xn zVi4>BjO=@Oq;#Y-UprP354r?blXH8%iaOg49;Kv~I!7=b>@9dHhvh;#wcf^6t?hIK z6r(rSZmt)rjiRXM#mbY4$g5O9qg8BB?=&{ zrEm|tBJv?jq>FCwyvZYLo(&YaZEZ=fn#)b-zo_tCTTsoRBDxIG^O&mC8d0pE≫a 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ℜ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î<6jv%UuK2I%^pUn-ZVr}K3_`v*(qUfx`p1E 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�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 z zfv2^4MsGh{Z2!9f!4~)UJ1l6jcAu|FeFKzH+$^VUa2Q(I4URem4o2UGA6UJd>4-Ihkhf3!f*rgZjN6Mj&_*iV;Wb>0I zYx%2)zedxVElhJ?zROnHVxN8&ojZYwo#N8Y*D07(2xz-}$quqT`GsF&mn6bWmpsX? zmSAmV!tRpaV1XEQ$&;;DHF?0=tq-5ggpv4I&%y6_t=Lshle;3P-z)VPbVW_{+b2bu zun}e-XQkVe(5 zkZZV5G}?R2Z%~ab4VC7@@T_UBzC{DH!}5bwZ;dOfn~SQO4b{z^@QN*|m1m0?<(UI# zWM}?C%xIX|JELyqv>BzDZ8I`6;~CvE&5T}_9+rVK>sic<{+VM_uj`Sr7xY?Ds+j|4 z`O=vghF1wSy1QXOZ+G2*SPdgASQ|mW;-TFHT<9HUntIwy>%canb2|^5W~TN}GjX9< z<7uCFs|@XAeHA{2>P^jSS>{u{2r(gvL0Jq$68eL{@37aabEgr2wT;+TaoCLsyO&5l zJ+5J9sK+*MAkeTTZ_Ct+dJ?c3BhTTpk_#L)n7Yc_sKh39Ek5pS9yJ>&U-?}*qc}4^ zqh;o~l9iYtUKYW`mc`Bzz4#qD<1#Vx5ARI<;$$?w zBmH5XY(1g)wfqS!CzCX9`S2N)P>QuJ>%>}dwGR4Q-qOxVMxSQ1#8<=ZQ9UlBXy(3C zhs`YfT#T4<&|`Am2FHU$q|GKvB$VbV_E<4FRL_B}qGdm7Tp=j$vq@zyKY9B8(|y zt?ri1<}hcZ>G!5V{?ckHl1P`R_m2wd

    ofhMZ>HvHmFZ@~Ag%U}SwIJ2fVC&`+hi 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©F{`EW*_#Ft&P0%%8Nwzk; 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
    |~GH4s&oX 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

    HqtqYe1MdR~6nNIvW47b9 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�<1DJ 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 PU3p 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

    s*18%`^+u6Zn2As&*b=lH+P-Zh#w->bz4 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 literal 0 HcmV?d00001 diff --git a/resilience-tests/pom.xml b/resilience-tests/pom.xml new file mode 100644 index 000000000..b9dc62299 --- /dev/null +++ b/resilience-tests/pom.xml @@ -0,0 +1,111 @@ + + + + arangodb-java-driver-parent + com.arangodb + 7.0.0-SNAPSHOT + + 4.0.0 + + resilience-tests + + + 19 + 19 + 19 + UTF-8 + + + + + org.mock-server + mockserver-netty + 5.13.2 + + + com.arangodb + arangodb-java-driver + ${version} + + + com.arangodb + jackson-dataformat-velocypack + 3.0.1 + + + eu.rekawek.toxiproxy + toxiproxy-java + 2.1.7 + + + ch.qos.logback + logback-classic + 1.2.11 + + + org.assertj + assertj-core + 3.23.1 + + + org.junit.platform + junit-platform-launcher + + + org.junit.jupiter + junit-jupiter-api + + + org.junit.jupiter + junit-jupiter-engine + + + org.junit.jupiter + junit-jupiter-params + + + org.awaitility + awaitility + 4.2.0 + + + + + + + io.netty + netty-bom + 4.1.84.Final + import + pom + + + com.fasterxml.jackson + jackson-bom + 2.13.4 + import + pom + + + org.junit + junit-bom + 5.9.1 + pom + import + + + + + + + + org.apache.maven.plugins + maven-surefire-plugin + 3.0.0-M5 + + + + + \ No newline at end of file diff --git a/resilience-tests/src/test/java/resilience/ActiveFailoverTest.java b/resilience-tests/src/test/java/resilience/ActiveFailoverTest.java new file mode 100644 index 000000000..4c639c55b --- /dev/null +++ b/resilience-tests/src/test/java/resilience/ActiveFailoverTest.java @@ -0,0 +1,75 @@ +package resilience; + +import ch.qos.logback.classic.Level; +import com.arangodb.ArangoDB; +import com.arangodb.async.ArangoDBAsync; +import resilience.utils.MemoryAppender; +import eu.rekawek.toxiproxy.Proxy; +import eu.rekawek.toxiproxy.ToxiproxyClient; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Tag; + +import java.io.IOException; +import java.util.List; + +@Tag("activeFailover") +public abstract class ActiveFailoverTest { + + protected static final String HOST = "127.0.0.1"; + protected static final String PASSWORD = "test"; + protected static final MemoryAppender logs = new MemoryAppender(Level.WARN); + private static final List endpoints = List.of( + new Endpoint("activeFailover1", HOST, 18529, "172.28.0.1:8529"), + new Endpoint("activeFailover2", HOST, 18539, "172.28.0.1:8539"), + new Endpoint("activeFailover3", HOST, 18549, "172.28.0.1:8549") + ); + + @BeforeAll + static void beforeAll() throws IOException { + ToxiproxyClient client = new ToxiproxyClient(HOST, 8474); + for (Endpoint ph : endpoints) { + Proxy p = client.getProxyOrNull(ph.getName()); + if (p != null) { + p.delete(); + } + ph.setProxy(client.createProxy(ph.getName(), ph.getHost() + ":" + ph.getPort(), ph.getUpstream())); + } + } + + @AfterAll + static void afterAll() throws IOException { + for (Endpoint ph : endpoints) { + ph.getProxy().delete(); + } + } + + @BeforeEach + void beforeEach() throws IOException { + for (Endpoint ph : endpoints) { + ph.getProxy().enable(); + } + } + + protected static List getEndpoints() { + return endpoints; + } + + protected static ArangoDB.Builder dbBuilder() { + ArangoDB.Builder builder = new ArangoDB.Builder().password(PASSWORD); + for (Endpoint ph : endpoints) { + builder.host(ph.getHost(), ph.getPort()); + } + return builder; + } + + protected static ArangoDBAsync.Builder dbBuilderAsync() { + ArangoDBAsync.Builder builder = new ArangoDBAsync.Builder().password(PASSWORD); + for (Endpoint ph : endpoints) { + builder.host(ph.getHost(), ph.getPort()); + } + return builder; + } + +} diff --git a/resilience-tests/src/test/java/resilience/ClusterTest.java b/resilience-tests/src/test/java/resilience/ClusterTest.java new file mode 100644 index 000000000..5b343bb28 --- /dev/null +++ b/resilience-tests/src/test/java/resilience/ClusterTest.java @@ -0,0 +1,75 @@ +package resilience; + +import ch.qos.logback.classic.Level; +import com.arangodb.ArangoDB; +import com.arangodb.async.ArangoDBAsync; +import resilience.utils.MemoryAppender; +import eu.rekawek.toxiproxy.Proxy; +import eu.rekawek.toxiproxy.ToxiproxyClient; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Tag; + +import java.io.IOException; +import java.util.List; + +@Tag("cluster") +public abstract class ClusterTest { + + protected static final String HOST = "127.0.0.1"; + protected static final String PASSWORD = "test"; + protected static final MemoryAppender logs = new MemoryAppender(Level.WARN); + private static final List endpoints = List.of( + new Endpoint("cluster1", HOST, 18529, "172.28.0.1:8529"), + new Endpoint("cluster2", HOST, 18539, "172.28.0.1:8539"), + new Endpoint("cluster3", HOST, 18549, "172.28.0.1:8549") + ); + + @BeforeAll + static void beforeAll() throws IOException { + ToxiproxyClient client = new ToxiproxyClient(HOST, 8474); + for (Endpoint ph : endpoints) { + Proxy p = client.getProxyOrNull(ph.getName()); + if (p != null) { + p.delete(); + } + ph.setProxy(client.createProxy(ph.getName(), ph.getHost() + ":" + ph.getPort(), ph.getUpstream())); + } + } + + @AfterAll + static void afterAll() throws IOException { + for (Endpoint ph : endpoints) { + ph.getProxy().delete(); + } + } + + @BeforeEach + void beforeEach() throws IOException { + for (Endpoint ph : endpoints) { + ph.getProxy().enable(); + } + } + + protected static List getEndpoints() { + return endpoints; + } + + protected static ArangoDB.Builder dbBuilder() { + ArangoDB.Builder builder = new ArangoDB.Builder().password(PASSWORD); + for (Endpoint ph : endpoints) { + builder.host(ph.getHost(), ph.getPort()); + } + return builder; + } + + protected static ArangoDBAsync.Builder dbBuilderAsync() { + ArangoDBAsync.Builder builder = new ArangoDBAsync.Builder().password(PASSWORD); + for (Endpoint ph : endpoints) { + builder.host(ph.getHost(), ph.getPort()); + } + return builder; + } + +} diff --git a/resilience-tests/src/test/java/resilience/Endpoint.java b/resilience-tests/src/test/java/resilience/Endpoint.java new file mode 100644 index 000000000..9e8c697d4 --- /dev/null +++ b/resilience-tests/src/test/java/resilience/Endpoint.java @@ -0,0 +1,45 @@ +package resilience; + +import eu.rekawek.toxiproxy.Proxy; + +/** + * class representing a proxied db endpoint + */ +public class Endpoint { + private final String name; + private final String host; + private final int port; + private final String upstream; + private Proxy proxy; + + public Endpoint(String name, String host, int port, String upstream) { + this.name = name; + this.host = host; + this.port = port; + this.upstream = upstream; + } + + public String getName() { + return name; + } + + public String getHost() { + return host; + } + + public int getPort() { + return port; + } + + public String getUpstream() { + return upstream; + } + + public Proxy getProxy() { + return proxy; + } + + public void setProxy(Proxy proxy) { + this.proxy = proxy; + } +} diff --git a/resilience-tests/src/test/java/resilience/SingleServerTest.java b/resilience-tests/src/test/java/resilience/SingleServerTest.java new file mode 100644 index 000000000..6ba01612e --- /dev/null +++ b/resilience-tests/src/test/java/resilience/SingleServerTest.java @@ -0,0 +1,60 @@ +package resilience; + +import ch.qos.logback.classic.Level; +import com.arangodb.ArangoDB; +import com.arangodb.async.ArangoDBAsync; +import resilience.utils.MemoryAppender; +import eu.rekawek.toxiproxy.Proxy; +import eu.rekawek.toxiproxy.ToxiproxyClient; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Tag; + +import java.io.IOException; + +@Tag("singleServer") +public abstract class SingleServerTest { + + protected static final String HOST = "127.0.0.1"; + protected static final String PASSWORD = "test"; + protected static final MemoryAppender logs = new MemoryAppender(Level.DEBUG); + private static final Endpoint endpoint = new Endpoint("singleServer", HOST, 18529, "172.28.0.1:8529"); + + @BeforeAll + static void beforeAll() throws IOException { + ToxiproxyClient client = new ToxiproxyClient(HOST, 8474); + Proxy p = client.getProxyOrNull(endpoint.getName()); + if (p != null) { + p.delete(); + } + endpoint.setProxy(client.createProxy(endpoint.getName(), HOST + ":" + endpoint.getPort(), endpoint.getUpstream())); + } + + @AfterAll + static void afterAll() throws IOException { + endpoint.getProxy().delete(); + } + + @BeforeEach + void beforeEach() throws IOException { + endpoint.getProxy().enable(); + } + + protected static Endpoint getEndpoint() { + return endpoint; + } + + protected static ArangoDB.Builder dbBuilder() { + return new ArangoDB.Builder() + .host(endpoint.getHost(), endpoint.getPort()) + .password(PASSWORD); + } + + protected static ArangoDBAsync.Builder dbBuilderAsync() { + return new ArangoDBAsync.Builder() + .host(endpoint.getHost(), endpoint.getPort()) + .password(PASSWORD); + } + +} diff --git a/resilience-tests/src/test/java/resilience/connection/ConnectionTest.java b/resilience-tests/src/test/java/resilience/connection/ConnectionTest.java new file mode 100644 index 000000000..6c2453acf --- /dev/null +++ b/resilience-tests/src/test/java/resilience/connection/ConnectionTest.java @@ -0,0 +1,79 @@ +package resilience.connection; + +import com.arangodb.ArangoDB; +import com.arangodb.ArangoDBException; +import com.arangodb.ArangoDBMultipleException; +import com.arangodb.Protocol; +import resilience.SingleServerTest; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + +import java.io.IOException; +import java.net.ConnectException; +import java.net.UnknownHostException; +import java.util.stream.Stream; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.catchThrowable; + +/** + * @author Michele Rastelli + */ +class ConnectionTest extends SingleServerTest { + + static Stream protocolProvider() { + return Stream.of( + Protocol.VST, + Protocol.HTTP_VPACK, + Protocol.HTTP2_VPACK + ); + } + + static Stream arangoProvider() { + return Stream.of( + dbBuilder().useProtocol(Protocol.VST).build(), + dbBuilder().useProtocol(Protocol.HTTP_VPACK).build(), + dbBuilder().useProtocol(Protocol.HTTP2_VPACK).build() + ); + } + + @ParameterizedTest + @MethodSource("protocolProvider") + void nameResolutionFailTest(Protocol protocol) { + ArangoDB arangoDB = new ArangoDB.Builder() + .host("wrongHost", 8529) + .useProtocol(protocol) + .build(); + + Throwable thrown = catchThrowable(arangoDB::getVersion); + assertThat(thrown).isInstanceOf(ArangoDBException.class); + assertThat(thrown.getMessage()).contains("Cannot contact any host!"); + assertThat(thrown.getCause()).isNotNull(); + assertThat(thrown.getCause()).isInstanceOf(ArangoDBMultipleException.class); + ((ArangoDBMultipleException) thrown.getCause()).getExceptions().forEach(e -> { + assertThat(e).isInstanceOf(UnknownHostException.class); + assertThat(e.getMessage()).contains("wrongHost"); + }); + arangoDB.shutdown(); + } + + @ParameterizedTest + @MethodSource("arangoProvider") + void connectionFailTest(ArangoDB arangoDB) throws IOException, InterruptedException { + getEndpoint().getProxy().disable(); + Thread.sleep(100); + + Throwable thrown = catchThrowable(arangoDB::getVersion); + assertThat(thrown).isInstanceOf(ArangoDBException.class); + assertThat(thrown.getMessage()).contains("Cannot contact any host"); + assertThat(thrown.getCause()).isNotNull(); + assertThat(thrown.getCause()).isInstanceOf(ArangoDBMultipleException.class); + ((ArangoDBMultipleException) thrown.getCause()).getExceptions().forEach(e -> { + assertThat(e).isInstanceOf(ConnectException.class); + }); + arangoDB.shutdown(); + getEndpoint().getProxy().enable(); + Thread.sleep(100); + } + +} diff --git a/resilience-tests/src/test/java/resilience/http/MockTest.java b/resilience-tests/src/test/java/resilience/http/MockTest.java new file mode 100644 index 000000000..e5eb6fab0 --- /dev/null +++ b/resilience-tests/src/test/java/resilience/http/MockTest.java @@ -0,0 +1,60 @@ +package resilience.http; + +import com.arangodb.ArangoDB; +import com.arangodb.ArangoDBException; +import com.arangodb.Protocol; +import resilience.SingleServerTest; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockserver.integration.ClientAndServer; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.catchThrowable; +import static org.mockserver.integration.ClientAndServer.startClientAndServer; +import static org.mockserver.model.HttpRequest.request; +import static org.mockserver.model.HttpResponse.response; + +class MockTest extends SingleServerTest { + + private ClientAndServer mockServer; + private ArangoDB arangoDB; + + @BeforeEach + void before() { + mockServer = startClientAndServer(getEndpoint().getHost(), getEndpoint().getPort()); + arangoDB = new ArangoDB.Builder() + .useProtocol(Protocol.HTTP_JSON) + .password(PASSWORD) + .host("127.0.0.1", mockServer.getPort()) + .build(); + } + + @AfterEach + void after() { + arangoDB.shutdown(); + mockServer.stop(); + } + + @Test + void doTest() { + arangoDB.getVersion(); + + mockServer + .when( + request() + .withMethod("GET") + .withPath("/.*/_api/version") + ) + .respond( + response() + .withStatusCode(503) + .withBody("{\"error\":true,\"errorNum\":503,\"errorMessage\":\"boom\",\"code\":503}") + ); + + Throwable thrown = catchThrowable(arangoDB::getVersion); + assertThat(thrown) + .isInstanceOf(ArangoDBException.class) + .hasMessageContaining("boom"); + } +} diff --git a/resilience-tests/src/test/java/resilience/reconnection/ReconnectionTest.java b/resilience-tests/src/test/java/resilience/reconnection/ReconnectionTest.java new file mode 100644 index 000000000..276e5236e --- /dev/null +++ b/resilience-tests/src/test/java/resilience/reconnection/ReconnectionTest.java @@ -0,0 +1,119 @@ +package resilience.reconnection; + +import ch.qos.logback.classic.Level; +import com.arangodb.ArangoDB; +import com.arangodb.ArangoDBException; +import com.arangodb.ArangoDBMultipleException; +import com.arangodb.Protocol; +import org.junit.jupiter.params.provider.EnumSource; +import resilience.SingleServerTest; +import eu.rekawek.toxiproxy.model.ToxicDirection; +import eu.rekawek.toxiproxy.model.toxic.Latency; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + +import java.io.IOException; +import java.net.ConnectException; +import java.util.concurrent.TimeoutException; +import java.util.stream.Stream; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.catchThrowable; +import static org.junit.jupiter.api.Assumptions.assumeTrue; + +/** + * @author Michele Rastelli + */ +class ReconnectionTest extends SingleServerTest { + + static Stream arangoProvider() { + return Stream.of( + dbBuilder().timeout(1_000).useProtocol(Protocol.VST).build(), + dbBuilder().timeout(1_000).useProtocol(Protocol.HTTP_VPACK).build(), + dbBuilder().timeout(1_000).useProtocol(Protocol.HTTP2_VPACK).build() + ); + } + + /** + * on reconnection failure: + * - 3x logs WARN Could not connect to host[addr=127.0.0.1,port=8529] + * - ArangoDBException("Cannot contact any host") + *

    + * once the proxy is re-enabled: + * - the subsequent requests should be successful + */ + @ParameterizedTest + @MethodSource("arangoProvider") + void unreachableHost(ArangoDB arangoDB) throws IOException, InterruptedException { + arangoDB.getVersion(); + + // close the driver connection + getEndpoint().getProxy().disable(); + Thread.sleep(100); + + for (int i = 0; i < 10; i++) { + Throwable thrown = catchThrowable(arangoDB::getVersion); + assertThat(thrown).isInstanceOf(ArangoDBException.class); + assertThat(thrown.getMessage()).contains("Cannot contact any host"); + assertThat(thrown.getCause()).isNotNull(); + assertThat(thrown.getCause()).isInstanceOf(ArangoDBMultipleException.class); + ((ArangoDBMultipleException) thrown.getCause()).getExceptions().forEach(e -> { + assertThat(e).isInstanceOf(ConnectException.class); + }); + } + + long warnsCount = logs.getLoggedEvents().stream() + .filter(e -> e.getLevel().equals(Level.WARN)) + .filter(e -> e.getMessage().contains("Could not connect to host[addr=127.0.0.1,port=18529]")) + .count(); + assertThat(warnsCount).isGreaterThanOrEqualTo(3); + + getEndpoint().getProxy().enable(); + Thread.sleep(100); + + arangoDB.getVersion(); + arangoDB.shutdown(); + } + + /** + * on reconnection failure: + * - 3x logs WARN Could not connect to host[addr=127.0.0.1,port=8529] + * - ArangoDBException("Cannot contact any host") + *

    + * once the proxy is re-enabled: + * - the subsequent requests should be successful + */ + @ParameterizedTest + @EnumSource(Protocol.class) + void connectionTimeout(Protocol protocol) throws IOException, InterruptedException { + // https://github.com/vert-x3/vertx-web/issues/2296 + // WebClient: HTTP/2 request timeout does not throw TimeoutException + assumeTrue(protocol != Protocol.HTTP2_VPACK); + assumeTrue(protocol != Protocol.HTTP2_JSON); + + ArangoDB arangoDB = dbBuilder() + .timeout(1_000) + .useProtocol(protocol) + .build(); + + arangoDB.getVersion(); + + // slow down the driver connection + Latency toxic = getEndpoint().getProxy().toxics().latency("latency", ToxicDirection.DOWNSTREAM, 10_000); + Thread.sleep(100); + + Throwable thrown = catchThrowable(arangoDB::getVersion); + thrown.printStackTrace(); + assertThat(thrown) + .isInstanceOf(ArangoDBException.class) + .extracting(Throwable::getCause) + .isInstanceOf(TimeoutException.class); + + toxic.remove(); + Thread.sleep(100); + + arangoDB.getVersion(); + arangoDB.shutdown(); + } + +} diff --git a/resilience-tests/src/test/java/resilience/timeout/TimeoutTest.java b/resilience-tests/src/test/java/resilience/timeout/TimeoutTest.java new file mode 100644 index 000000000..079c2e3fd --- /dev/null +++ b/resilience-tests/src/test/java/resilience/timeout/TimeoutTest.java @@ -0,0 +1,73 @@ +package resilience.timeout; + +import com.arangodb.ArangoCollection; +import com.arangodb.ArangoDB; +import com.arangodb.ArangoDBException; +import com.arangodb.Protocol; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.EnumSource; +import resilience.SingleServerTest; + +import java.util.Collections; +import java.util.Map; +import java.util.concurrent.TimeoutException; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assumptions.assumeTrue; + +/** + * @author Michele Rastelli + */ +class TimeoutTest extends SingleServerTest { + + /** + * on timeout failure: + * - throw exception + * - expect operation performed (at most) once + *

    + * after the exception: + * - the subsequent requests should be successful + */ + @ParameterizedTest + @EnumSource(Protocol.class) + void requestTimeout(Protocol protocol) throws InterruptedException { + // https://github.com/vert-x3/vertx-web/issues/2296 + // WebClient: HTTP/2 request timeout does not throw TimeoutException + assumeTrue(protocol != Protocol.HTTP2_VPACK); + assumeTrue(protocol != Protocol.HTTP2_JSON); + + ArangoDB arangoDB = dbBuilder() + .timeout(1_000) + .useProtocol(protocol) + .build(); + + arangoDB.getVersion(); + String colName = "timeoutTest"; + ArangoCollection col = arangoDB.db().collection(colName); + if (!col.exists()) col.create(); + col.truncate(); + + try { + arangoDB.db().query("" + + "INSERT {value:sleep(2)}\n" + + "INTO @@col\n" + + "RETURN NEW\n", + Collections.singletonMap("@col", colName), + Map.class); + } catch (Exception e) { + e.printStackTrace(); + assertThat(e) + .isInstanceOf(ArangoDBException.class) + .extracting(Throwable::getCause) + .isInstanceOf(TimeoutException.class); + } + + arangoDB.getVersion(); + + Thread.sleep(2_000); + assertThat(col.count().getCount()).isEqualTo(1); + + arangoDB.shutdown(); + } + +} diff --git a/resilience-tests/src/test/java/resilience/utils/MemoryAppender.java b/resilience-tests/src/test/java/resilience/utils/MemoryAppender.java new file mode 100644 index 000000000..018dd5415 --- /dev/null +++ b/resilience-tests/src/test/java/resilience/utils/MemoryAppender.java @@ -0,0 +1,30 @@ +package resilience.utils; + +import ch.qos.logback.classic.Level; +import ch.qos.logback.classic.Logger; +import ch.qos.logback.classic.LoggerContext; +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.core.read.ListAppender; +import org.slf4j.LoggerFactory; + +import java.util.Collections; +import java.util.List; + +public class MemoryAppender extends ListAppender { + + public MemoryAppender(Level level) { + setContext((LoggerContext) LoggerFactory.getILoggerFactory()); + start(); + Logger logger = (Logger) LoggerFactory.getLogger("root"); + logger.setLevel(level); + logger.addAppender(this); + } + + public void reset() { + this.list.clear(); + } + + public List getLoggedEvents() { + return Collections.unmodifiableList(this.list); + } +} \ No newline at end of file diff --git a/resilience-tests/src/test/java/resilience/vstKeepAlive/VstKeepAliveCloseAsyncTest.java b/resilience-tests/src/test/java/resilience/vstKeepAlive/VstKeepAliveCloseAsyncTest.java new file mode 100644 index 000000000..6a751da8d --- /dev/null +++ b/resilience-tests/src/test/java/resilience/vstKeepAlive/VstKeepAliveCloseAsyncTest.java @@ -0,0 +1,54 @@ +package resilience.vstKeepAlive; + +import ch.qos.logback.classic.Level; +import com.arangodb.async.ArangoDBAsync; +import resilience.SingleServerTest; +import eu.rekawek.toxiproxy.model.ToxicDirection; +import eu.rekawek.toxiproxy.model.toxic.Latency; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.Timeout; + +import java.io.IOException; +import java.util.concurrent.ExecutionException; + +import static org.awaitility.Awaitility.await; + +/** + * @author Michele Rastelli + */ +class VstKeepAliveCloseAsyncTest extends SingleServerTest { + + private ArangoDBAsync arangoDB; + + @BeforeEach + void init() { + arangoDB = dbBuilderAsync() + .timeout(1000) + .keepAliveInterval(1) + .build(); + } + + @AfterEach + void shutDown() { + arangoDB.shutdown(); + } + + /** + * after 3 consecutive VST keepAlive failures: + * - log ERROR Connection unresponsive + * - reconnect on next request + */ + @Test + @Timeout(10) + void keepAliveCloseAndReconnect() throws IOException, ExecutionException, InterruptedException { + arangoDB.getVersion().get(); + Latency toxic = getEndpoint().getProxy().toxics().latency("latency", ToxicDirection.DOWNSTREAM, 10_000); + await().until(() -> logs.getLoggedEvents().stream() + .filter(e -> e.getLevel().equals(Level.ERROR)) + .anyMatch(e -> e.getMessage().contains("Connection unresponsive!"))); + toxic.setLatency(0L); + arangoDB.getVersion().get(); + } +} diff --git a/resilience-tests/src/test/java/resilience/vstKeepAlive/VstKeepAliveCloseTest.java b/resilience-tests/src/test/java/resilience/vstKeepAlive/VstKeepAliveCloseTest.java new file mode 100644 index 000000000..f55c97862 --- /dev/null +++ b/resilience-tests/src/test/java/resilience/vstKeepAlive/VstKeepAliveCloseTest.java @@ -0,0 +1,55 @@ +package resilience.vstKeepAlive; + +import ch.qos.logback.classic.Level; +import com.arangodb.ArangoDB; +import com.arangodb.Protocol; +import resilience.SingleServerTest; +import eu.rekawek.toxiproxy.model.ToxicDirection; +import eu.rekawek.toxiproxy.model.toxic.Latency; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.Timeout; + +import java.io.IOException; + +import static org.awaitility.Awaitility.await; + +/** + * @author Michele Rastelli + */ +class VstKeepAliveCloseTest extends SingleServerTest { + + private ArangoDB arangoDB; + + @BeforeEach + void init() { + arangoDB = dbBuilder() + .useProtocol(Protocol.VST) + .timeout(1000) + .keepAliveInterval(1) + .build(); + } + + @AfterEach + void shutDown() { + arangoDB.shutdown(); + } + + /** + * after 3 consecutive VST keepAlive failures: + * - log ERROR Connection unresponsive + * - reconnect on next request + */ + @Test + @Timeout(10) + void keepAliveCloseAndReconnect() throws IOException { + arangoDB.getVersion(); + Latency toxic = getEndpoint().getProxy().toxics().latency("latency", ToxicDirection.DOWNSTREAM, 10_000); + await().until(() -> logs.getLoggedEvents().stream() + .filter(e -> e.getLevel().equals(Level.ERROR)) + .anyMatch(e -> e.getMessage().contains("Connection unresponsive!"))); + toxic.setLatency(0); + arangoDB.getVersion(); + } +} diff --git a/resilience-tests/src/test/resources/logback-test.xml b/resilience-tests/src/test/resources/logback-test.xml new file mode 100644 index 000000000..840d133d7 --- /dev/null +++ b/resilience-tests/src/test/resources/logback-test.xml @@ -0,0 +1,13 @@ + + + + + %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n + + + + + + + + From 5fe92e751650f925b2111f27da04bb7203ffa9a9 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Mon, 7 Nov 2022 19:55:46 +0100 Subject: [PATCH 177/254] CI integration --- .github/workflows/resilience.yml | 5 ++++- .gitignore | 2 ++ resilience-tests/bin/startProxy.sh | 5 +++++ .../bin/toxiproxy-server-linux-amd64 | Bin 8822784 -> 0 bytes 4 files changed, 11 insertions(+), 1 deletion(-) create mode 100755 resilience-tests/bin/startProxy.sh delete mode 100755 resilience-tests/bin/toxiproxy-server-linux-amd64 diff --git a/.github/workflows/resilience.yml b/.github/workflows/resilience.yml index b3c3edd04..f3115a2c9 100644 --- a/.github/workflows/resilience.yml +++ b/.github/workflows/resilience.yml @@ -10,6 +10,9 @@ jobs: timeout-minutes: 20 runs-on: ubuntu-latest + env: + TOXIPROXY_VERSION: v2.5.0 + strategy: fail-fast: false @@ -27,6 +30,6 @@ jobs: run: mvn -version - name: Start Toxiproxy working-directory: resilience-tests - run: ./bin/toxiproxy-server-linux-amd64 + run: ./bin/startProxy.sh - name: Test run: mvn --no-transfer-progress -am -pl resilience-tests test diff --git a/.gitignore b/.gitignore index 5f384eeab..8fcbc5c8a 100644 --- a/.gitignore +++ b/.gitignore @@ -12,3 +12,5 @@ target test-results-native .flattened-pom.xml +/resilience-tests/bin/toxiproxy-server-linux-amd64 + diff --git a/resilience-tests/bin/startProxy.sh b/resilience-tests/bin/startProxy.sh new file mode 100755 index 000000000..00c1802df --- /dev/null +++ b/resilience-tests/bin/startProxy.sh @@ -0,0 +1,5 @@ +#!/bin/bash + +wget -O bin/toxiproxy-server-linux-amd64 https://github.com/Shopify/toxiproxy/releases/download/${TOXIPROXY_VERSION}/toxiproxy-server-linux-amd64 +chmod a+x bin/toxiproxy-server-linux-amd64 +bin/toxiproxy-server-linux-amd64 & diff --git a/resilience-tests/bin/toxiproxy-server-linux-amd64 b/resilience-tests/bin/toxiproxy-server-linux-amd64 deleted file mode 100755 index 8b474e1a647af884b5c5f1b69efacc9bfc9c850e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8822784 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≦h2*qHm(ENJ8O?svZWU+i@ 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

  • 1TDxiw8C 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

    gu&E*aYw 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†Qg2tTjsDp;*aqs&gPin#*G_-&HgFEp z9YtaKOV&8_uZ^L9gyyGCwbML!u9Mz+e2$2rZ(tOTD2@Q>4!50=5*YQD%EPW1Nr6#s zj_;1`mfMfBWh*HPI zfBJ3zALD-*p)&k`_G}0KQ;}4Y09{=Cx0UV)|Icz1dj(0=2gS($r$piZ;LYU!Z4vx$ zyeuC6Z_KgbKkYLc{(l(Yz`t)jk!tY&`odWJPa1FGzeuvi;(s1W9TWdgPWk^B|EtzT z@c+Rb4n)=?srCW7xcIMOLCycpVp%NqJc^P3yGG%^tc3i(HG=<%%m0G^Nip)Dw;PL`ze-vsyS_40 zW7+6ue?t=b*(^X|$Fs3O%AEe2aM?MgteIhNLsAWmDoNof=Etw!u_*LsXR-TOtR0Gh zLcY#X6xuo&6nbHEghERh+B9Zf9)5w1Lgylj-i`T?hoJS|5p9n*2ndEekI2@%b9xwo zLqpm`lp|SV$#XqQ9g{rOH#^8P<5<&!?7z&I=(IgzZpO5%jl6YhEL@#hp~++PpY}+K z{sS;HeayZvZDV0$Blm~QmXP|c#12!aS|%wyKjCUh>hIVVmIMCaFtLhi z_<4ZPx&E-}HxvxwYOJDK{H1j4ZthN%bH2CdB2> z#o=OOO)zaC}r=O=Ho*RlNRLaAf&XT}Y7ME@83iOXm0vdzd><4J79<~Vw| z$Jy?!n`Cb+^io8%x5-ah%boHED_~>)c*~+|&NPSoJO@eIKhV>-lx<)^z5c40>X29^ zNUD84(iQSIIf}5);;I!@y&*!?%G`KV?cU!;)orhksxVn`CH40V2SszF17@ncRd(Z@ z)a-^0KRs1;l&rDT9E4KGq~=xE+Yuam&M9rQe2<6Ua*f}|{%PTNOQ{3DtB?eK>(F*w z{9ea`8o#HQl4isuA*p;QNBlOyS;isQM_vQ`p0z%L-?Sm|@LSi{hTjKp%~Tk_`DZ)u zyJICgVDOtfkH~Q1_YLfSY5cw@S!410apiIFd!+c+;rB)}|4W+`kHOm<_}z&l=YK#P z7r%)tsPX%{DQWP#6iIa^$`QYd;i}}o?>AQizwfM#;J2Pp(0JTV5xA)3ki3 z;feN$M$%0>VEDISZY+KeV}D8W@3(KTud(<&1*MLO-wUt#b@-j4@q34~N&Mzdap3nt zB!S<>Xge-`hq9o??@zbrk_NvDNi_-Oh~HhYezBP{&hD_LXl`#MS;6TdsJ{&o1BuJL=Sv`PGa{(A?0 zw;~Dr4u&s7T>O6idKkYCo00~<3y@STQI7bXMXxNoV!g2l_hlSt3tXTZ!U|Ub~Z$HTzi{A+-bxi!;G4a>o*T~;DmlHhV_vV`& z_`M2A;CC0=j*H)UEU5W+kSS^Kn}MWy0_BL`?sO@z$4ENUGr|NBq{&_0Nvqc2@wuU%nl|@1BA2@H^`) z8-D-u4DoC9v$i~+9pT?cm)Y?9-ppA1-kxXS_cqBIi{FP)>X`idX3?+1uaUn;{z34F z-);s=#=g`JN#M6TXd4&54J@efTQS*z-x4I%KEO=;PHYi{-)F}IztwL=@LS1%zA^mU zJ>7=i8Bg2r`}dv>{N_jpEd9447QfxF6R7#OqhyW6?;w;qCVsD)@PESZW3O8H&A-vX zzZW72{MMoExcI$}1vP$8F(r+BNJ3KiP>%R*!lduu-;v{h-?RQ1!EahtJp9(3VZ(3N zr)>Dm@8Q7jj#tn?eXv{WQl(?!?wOlm-XG6 zO4`R}(tmfR;l-Zk@z*90{r;CF{0M^H zRJ&x%^BWMHNd#xBKT;3F{TtPvA#*LgK{63}N}`eY4!4-m4j5|VuD%T)RR)S%^g|>h zclBjb|7@0+kmm7M;6TItmw^Zzhr^*59Eaoi?|g(gn7^1gaodKsH!iuEkZq1Z=byfL zWT10vUvBbC&@E-)9dbea<@0N!1ELH57_3g6K- zxX)0(viyzG;IS^(%`*lh_)5~S-})DDTzFb8AV&4M1e|{vP3sf(pVh7vkR&+&f(=QY ze`!?`zCR1rXzTv0<=FNL*NG}k?J#a{=0ywPG$UY~1Hq-fgdC|QcK{RCaR_x_jFAL9 zRF=Xnr`85%Axc;@Q`*wn{*b~++_&Gu@t?=>j|<3sxu?BA%E9aR{6Aky(fe{e`hb9E zffanf>-l)C9-D?%*Ht#+760K;=_l0i>GOv6l?Ti_Db9p7zM8nbkB$_stz6GMo`5u? z!)5p@iB!g1;wjHChBH((n1ct|afSm?H1ZJiXHZ zx{AkXG2+rf!x_=xC81BS8>sF*SK0w~;oY@?=*|PNJ*%Y!1n%Q#D`ZO;JaQ(N0X6`0 zsu#ELcysbn=e{^xAKI%t#4h-2>*c2%e4pijZPJ~%V*Zc|Q6zXT=~5ZJvfRY{^&#wX zzC-QGAK(QvhuW3F*ol2{`-Uk=$O@2-NohwgkKsCehtCq^(XrlAO=THav6Ty z)vrj4>v7b{TVv#7_cIvIq`b4ik)Q{N3f?U+^4?wl{q^#UU@8z=`qUT?G`1`2WIBZN zLH>$VL`X#l5@1@le-qkgpj2Gy$(z7hr3|e+lvdHDEQH^-WnbcNa@lUiS87+*hy&_p z5>9`Ybo_+m!i+RcEB1eZM$zbJ4T@?7MbOz+@IgHSUkA)07}kg=6~PEc7uL_0n?V)a z66IQNn?Ki}8t3>CmWE6x|H9#T?rcxu%OWSlmA+ITDbpN{SmW;bx1)yqnvLGx8}f5D zdflV96x3`g!2JXbhc7NTeaFZ^kB$Z4*;9FoI9U4tuMj_7*2;n}k!Xc!-kh!OyBLPv ziwo;95ZO5Y;e;jz3JyCV##`^5;j{0YzdZAfFvyTQAXh{{mZV`OzrYiykvK{iEg6_O zf4a6`f_nACe_ISVL55u#rjBrUziU%;Xg?q=Tg}JXi0FLhi13ur(K?gri;C} zho)tbE_VPi{ZKbpZCaYA<*-yw&e~~+G>Zp)QMQeykO<$aXCQNcL9y>Imgn_q8-8m= zqN=4{Lvrjd1iSw?^ZR&Be{_zL8}bvVc1+MM-Bpi~5Wd5$-PNz*NexF4)XzwT(}!GG zjvL=8w3_D$!>pUf$%uZw!39D;elvmGTHY^NzzC4cuE#ylRx4iBa|{D~NLA7$g@u1T5NF8Mj!Fywfq35rs*o0#bgeB8t;z&_Nj5eU>0x%``QATB` zqwqgQ)n}oRjJ)cf33;9eK0Z1pIDO<$1am`t7X)idtLR*|8^3MKcHnPv**5%bSN0y} zLlUCqkTqxMjTXBg(QhzZ!QJXrc=Q+syKJQC5c~@V+cxuT^Ro4*`^SLL=wCMZE0g?{ z$^PYWHY)_t$~y2MYLO&Er|Q*ECditN@zUg}!Q{w%IAn^fIOm!C&M(7s#89lCCcc3S z3o&?#JUQFSH?tn_E{8o-aYj5)7q%4v4_R&ERTXhSr-hyjpO?{1Ih%E8CQ_>!lW%$* zQBS0%VCr#Dp!+Whv2Q4S_dlEHH4sStu&=H>g_WmTmE(RsQ~SYp1>C6G-;&w~ zg==5V+B>247o>LTuZyLA*Rs{P1JL~7HQc%IW zco6y8{U*ZaDr5N%UXbz`k@9&`etEe3pRDqWtn#~L@0%3&ttncqI$VYW^j}AGTFoB} zDTVQoM*e{O;UBpU5y5#8n`2axyLt(8V9bE88E}C^a+|<6v9-jvuDX*MWP= z8hy`W-?Q2GY{t*9)_(=nU%0C)rSm-Z4K_w-xvMy>rVOq5?h@W*D$%Sc9(Us|37|!- zuc4~R+I(yBw1Z7#l_6tULVoZftlnzZ2s?BfBETHvgT(!S-iAEE2>_W9J3Nfm;jW&F zBqMeZKfxOu-Lb@8_*c_+5jzk?Ul57v!Kfrp&dKG!x6>9<><8sLCB*pJh_rXPg=>_s zNDBHw4FZ1)ar>y>A~&+0X|j$aX+U62EGRl7Gs@ej%vQ&t(sTzNf+I|~gg(EGf<4TK zZ*Zil#+J^;(XhaI4KPV%=JGT&{tsk2CX4(y+)jk(_zrSEF=!70kUu;z{BghGk7Dvi z3Hih8zaA>;?*YKrw7do9rIXf)2x+HnD+nmXYe#DKd252y+J2g(8O8&KDLfIwJUh$| zYkY>e)G$m@t>&0(ktW9kuP|tJ@W+gN;MX=cTJd9UC)YymbMo_#O}eC}VJOEvOh`~L zcSxl5&1%<88g^^GjGee_%>M1r6T|*{13QL4_)Eh--GZMV!?5$ADk1pBjw8-@_6+#` z=+5JR-|^}3zvrBw{O#&E1IT*Am<0WV{+o{juX`X z#{QU65e%aIiTeL&;|a>2fId5d$1mUQc;7AjF8U;XC4m3Yeepj@C)vL*j`Q8BfBZ3+ z#DV{Re;!kl$gls)_-X?0b29m_#@D?U{l7iF{?G8&-SI!b|9-|Sc7lDllWq2Iim~DtSOoi0OED-N znls4jZ?)RY|68UP;r=(=5heG(b>!7K9dZ9#!`zOz|7{iTf7{4dxIGZM3v=<7>8By+ z_y!3&?jPT^*pqVvU%A90j6U2C$MqJhGpp&Aq#swvBUGy`>IFP1b%W_^+GI1oWm)q> zM)dr^`vvRu1@GR)gw&(766uP>Ad=-)727#oti1XcerDDnEC;s7N(kw!NqL@}<7 z!dyYVi0? zr{}Gy2W%FiucChv71u3@FAnV9GszJFm(zc$`sl)#ff@WO4V*yWdQ_&T=~Z|mYQ`I3 zJA=rN;Zgcqcx}P>i=&blb8TjdCudd)wmD>FpJj{2idxdhi79MfWc|c!se)40lfiY`oHY~`Dpw45TCtq1$dFciAgyS2O1JSh zwDaYvGYp%T136D#yVAr=Z9OiqdsMSNv%KDe~+Pl2oe$mzl_>?%6?jS z=o=bu9=e?2u7>Md7F9H-WXN+BM6)KVw<0E9zGG$O!pg$9aYH_=EH7R~{(s&MK9UpcQrM@E5B;#dcf{bcVd<747N4xuh+gvGeVUrC>(aCZO{jm38c;g8 z0#1vAAY5zr&oI=FO27}q4=5cGdBj3qxfdaksJXM*n$KJ)kU=&`I(H=*Dyse|AKhPv z?dNXgfZd583jc=}MkylxjP2KEe-Ew!4ConWq^>UbGY5)bMGtLh>Pt9fs~S>w1S%4+ zjQcNx)di2sbFJ=w@NIQL4X?Di|Hj3#Oy9C^t*%M*EIk|Km~jSNZ0qhpW6b0`|BI2x z7rMUO99Nin@)rfHiw~HF$G_@bXr>wWWuetdz@>-k|(+ZJqV`;TZ5bp(?_YZQXQvr=&#?vO^zrf;vH> z@K-r#D-L&nKQL?%S{20dzwTYU+~z!Iz3w`!)&5Ox0y|QctnAKCEj!%mPm+DX!MzorO5Dq^(m~_J z+Ss=7Mqua#*ph~Q3{o=K(eyOBHcq~c-NbbrbJU*U(M{^H`Xr-g*rbI!u3~|tHCSvE z$gmxNf&Mq#MM<*3@UIrf$!3cS-o?CuowM4wxXlf?X1T=s8LLK`AIsQ+^ zHv#JmtTwqh?@;)^pvCvb+PhKw*Bq7SJp<_t%kg4D7{M=x*R`bwn!ZW7Jbf`2HXZydt54|lZ52K0x{|xY{evqzVLR9y)2+j;E9<%j`sB50OK(-cH~z*H`f7;}r6^ll-qc?D)e+I1&5I+9~mOr$@LA9WX!R zHSO(B6Q=as7^>ON(IWiy#!&ckYwx9y!tpM)3EG1)oRLxJn?9&LbQ=C|O~cP!nfRHI zJ3-sqqWf06bzcboV8_~L(VPj|L&YWyEfoAKcUtzswJ)RZ_uo3cFx6}RBajR&=v$&Vks78sebITJrSk|t<7QLO@H zF9Azl+gkwN7txSq1DiuM$al#JE<~xX`VC`JFy8{Htv8oLPsnK?H9}tK zY2j|*UoYjFy|*XoP)QuvD~@Gg{|A;GK9dG0R-u=NNFwnch{zx0^VPj4bATvfv2O4p z5LZz5_l5|+B`XDszNZbgw(R?+ElzrKz>@XNVJgf>=2eN3(b(%|j%H7ZE93Z!w4xc@ zhw^7!Ri0&Ipub}YvLT`CA^vGS7XAjqAL>Sg2gQ^@`zql_TJ3TO1>Gz^&Rw%qO2L$r zNNQy=_bp{{M&fE;LH{|#3C5etL#E8P*=4X9R`X$AmS+qs9*`8_@j zC-Jv(lJ+L{cuAO0b8PZ22^rMm{0T6M;D>Ka_lx8t*>kBM=$at2d9#^ zu@Y^o$)9@9|K{2$GC<3BP>eb(V^uAv{de1K}AELX`DyH&5gE+gS-#=IyY#l5q=C}D zcxd~c5&|zEh*l8{|Kg+tYZ9LWsm8Uh&nZja%h@!MRz>SU(~uqe5PGC20C{6?ZVUP; ztT{H}zN%kf17x(39XkGUt-cQD)m7bwATE#ZLMk+Ts{W0GPz&cuZ^iat_wWGROO1Q4 z%PCuO0b7FFh1>!AD}X5i?2`_#SExOW0PIi!HaR4|&(4XllfFt5SmPGR5nwtE3AE^MM*9vlzrr7Ylhs%?a0M|#v{;08- z>=AzWq_5-UGb*^teQxxX8)4ei$;g1_2U3fE4o%jTJPe15ZGdDTb2DW5rMb)aa-Ly9wV2YAC^yXLJ+&XDH-# z;@@m}ZGG@1r8R|QCq#@53T=5*x3eNfP8I<4Xf1mrmp88bGb80c@RQ5GTKQ+B|7vH0 z7_o`baj$=c=kPWUHgzoY?N0V2HX1gTyn%6WJ6-IBL%A(G(B+k*^}w)o*Hal7P|bla zLK?b%N*V@xd!%RoThA2JG>j3r_HgwJR4?7)Jhbn7b}7`qarb zsJv!*yw0?rvpins+SfmrDysmT3 z#+Jy=b*&yV9f~Ga?VYYMnK1!ri-XE2Fj%#^%1`(p#e-*AgZ5yIPxwpP;dY{qS z(%zR5KiG2c(#l=o?w;mmSP5->c&XPM6S4ojuJ^UtcTk}>=X+1v`(FRop2Ht|n!ZO? z^{3v%4}#&YxMk2+X277J>c$l7aWvF&1w;~zh%qdmzDebeDUady$0*3-9QH|*c8xM!H7vA0Omln3b( znMij}X~Qj9qk*{@LoNkCpTiAki2KEw`^sJftwv&#G`;|ODUIxi4BrlNcL=;qj|NaK zEuw?Z<6nhYQBg|67*p7gJ|aZp3LwDk6B>w9-7LzgQZ)+v)-zu-?VB^!uoEe478!%s zSZmO(Z`y+JyJL(~^dG)jUJN?dt4F#KXS}`?`=2~&i_ryY!)pJ{B}_AX3`UK*W2L)E z=Iv=4`LP3$>nHnJeQM<*#Y&OLg-o{cH>ry=)rIv0lAvH%b@XbB|55yB)(7XXnvM=` z@j`OmL2l^r{jn)JG4a>F%J^(V+uO%qX&|=9eQa|t$9F`+(%z$l)B{0E7e+`n>Ds$3 zdK+d>RO1fyfj-)t3pgm4$(L1+OlZq$!P!4A<*YfRg8Dbe-qF^Am(dMKxTIC*E2w{j z_=H^P|HDheQEX(Jh3{}_wJ?i9d|=40YX$A2z>4+-j*KgCXr#cA@dXZLfz#{)Lq1j5 z&)OGu=p_Xm)C55Hb(I6%Z~q(z-5gw67deGpp$gk^NxP>0$u10r0t)+Gq_Fd$1+b}V zer^ABT*AKH$&>{&HuN>IX(k8S7k7JHao0zR+xgcx*xtvbHP0zblJ&8Fd;7vt?ZQ$7 zwiDBwhW7q@Twy=J0JjS5!ou*ZCjWbIyH>7zQK3wgv?Nl}T6`MQq03p);Ss8h;cnP` zUNVmBvZ~o!h$@{PMDWqGiU0#|D0-_CI-C%MS9@IJat?WwIL-i%|*E>P`N-az2ScxE&!#$g|XoG zM1Jqw&~>Cu=FV@xG`E?!YrSz5`oO;{L@i_lmTYhM5sy;E0OifOGs=fRm-b35FH{juG&u%$nSVO5vX5v1Zwz?1JzG};>u=^pnBpc zoD)IN1VZ#{_Mv|l=WwxqAj`$_swP}Q1&Ua0%7uk00yFS*Pyko`-L|<7xhpjtn$ocq zFXnVW?ZeNX1hte(s;9jbL@is9C1NhF6@4h`-e-cr|DzQm^=+zcgMtVrqcmIwXs4}e z=8p50?B6z`XN6`DZk|vF8#gdt^@%FTP7T4SLmYja+vopRUL%a9yB47t z#h7m0DZ|Xoss>zSbjPL1Ex66(Te3UgbI>9OpL|8QkBr_#=2WAZD$JHbQAW=rqv!bw zc1G07__PqDcsc>s~ty+RB{u))bGQwWw21X@@|8sfB+ite)e7%;;*DQZt&>xC`f zwE6Zy7~n+(6TholBYPNM62;+-RnaOsz8_>*8XqANA0=AVtk4T6uRU@%{5Ozm?f6mT z5@QaA5r4g~19DgW_m3b~$xH{83m%T5@-&I*@3NW@t4DB{Iz}}>jbXCrV6cb}929TC zJWZ#el+Dn+s_{IuUS5iHODxgRe;Lr-LUrwN5dohZ8dYq1iyua6%7K!gkk=4Qon@ZGF6*y|!wXK>n`!{EN24fCl;x?I3ghF5 zuHrH}yEBsE_yeM$Q2NR8wP#%WI1X7`pLH77ZVZY_rZ*mPB-69t-*)oVPnI4c-7WG} zM61xNqX#%gJ`rIXks(hDt2!jGdBka2y%>uycz3hkxqthga3Zp!>KWS+Mazzg1lGsc z8tLEoq4#8xq-R!a|El&sm$};l-hR=P11{ z*m2aMDcMo-M=a&14KAb4@6d$wNE6z1VKR{@YQ(+=oG$$GcOANL6K+`#AqC?9F}U1@ z(KI?fcFMxnQ(uYn`Hi{G2jpMKA(6E3>MSC#V2g?5eZ}XK;Zm>*-x3j7c$J1@v_yX# z6(P&ZE(?Ys%CfxxASr%T=x;2P4enSlYqq9gzh~J|JZ6|W^S8rc;KP6RQG~vJn*8|l zpxDlFr#?PnzszdC&{ya3&k2DW6`R!p3;#5pl zTq9KolLb>Rcrr4b&!0MR6z2#&d_Tz#PN(EDT+58cu{g1QcNt-E0_fH{4T({H$vxl? zv#?LGJdC}5iHGFn+XLNx614^XfJ7REn(S?`efbHM50QYXlYcB6Mk4)pySMbMQ+5F$tu@AN&urDE2XU}cB_yFh8W3rN-hMjUHtr*zX z%~`Dx{}v(MM~L@XgCu$G0RV6dR&D@BGr942Hv2A@eV5OvlV$WG@nj-Td4#X0w zck-cBeucfh0Kkmq_{sG8@@y_HFdoV8zy$bJCo*ykuIVxdeKsNJaqU;WOi#{!!?nhv zjalP?9hb9(E9iIz?Z4g}kjRwat_;0DKLcQ(2dg(JbcITOz7x-1HrN8z&+cpO|a(RDSX6OBLnew zJjRK2IgUZ;dQ0zZcR1wVPg`H$S;c>#K=LuDISrVYK7gc)J_049lXOM7?h+ouaMc!+ zk09{F9>zgt?o)e?$blE&S7TpivI|iN*0cfP1l-y15*j&8+>M;^b={?>%1%(za)FND+%qIa=3vNmUzbbrAguab&i!9hBBqwSP72CcZxOu_=r>wu9c zEUe22qV9Z92WE4-^HB`sz;hGWr`-11%^Mi{(MN`VE!?rz_`z@s`!@!$v`gigMj&}8 z>k6a}!y(+GIIj`!h_#>qMzaiaK#GBleuo>bZPPA-uiOJa{^1>Z)3Iyx7_hcu6u<_~ zQQ!=St2ZG+d3;EYjqJ`Be*> zyp&aL^oaGuMZgSa#K1h>AB7CJ+BG5~AE_Ul-6IyCq4(RNQ{itIoH-bu;^ZT|Q>0(y zGTs@}_F2~;h5_(n>1=pAh{0i1Zf>tm{5+Q9tS_eoNfhOd_;CcWt2|e$e~CRAL695u zZ>qrlk`76~KaR-h?T|Faw+MPBtBNAnk>aUeh#QT*Hn5^L|0Qq&D#$<&pvSN{3YHjx zjYa_pL8zN!-Pr$FYEi-vmJ!@oTdm(@6Z^ZU1JC^mK+eoY?hhmYOUD>7d#wPDMcFWM zyBpq|reifPktLYe4up*XV`9q|{P_yHN%>&R(Qe*A%+|j(ZV?3@SS}pyJo}42dWM3m$7DJO~&{3>_cADX8nuQG67CI#ciV8uk zgsUMnS-+;~$-$Fh1awVFw#OWrru#8OORMt{j{{}hgaz$3PCXCto2!9kEcDQehaicNaG9Nx};s8s-HnH%v+xW2WDN%Zu=T z6T|9>GcUpE^xVYa{JoQhhlz@P`67=iz9s-?f?F@LM zlg}6;#GHY{NG5-AHQEFV?|!EuET?iaxUxeWGEL7+Jzk!<|`|QTUV~b@d!t zWVu$KgNjm1w50|f!ugwPFUb~>)Oz9u3Twl)LaS{Ch0?x(xE5j+3ohpvO?OAFI|j$h z>AJsn7Gyc4bqZ@tL)95p(LX!MxXt9~C;@zOOo<}DD}fnXG2X~!FBB1z|V9Y3uP_L0A%fR_R zwAVr@%ldvkLBo-@5RENOa&<)bbZMJ_^#_lp zR%RJcqe{Gi8?(Jk_ofx(XHaoYEg_uzHfy2A z?%Fs-Jn+6RBD5<99BCGfl5syI)2kj|SBs0{}1d8diN z+iNWh-ruG=x`cKA4|d0e?xCvA{E2NUd4C5xsb&v7g3O;-#G|Q>=o@%|IaRwF3-S0 zs~^OB=;$hTG$heuR#uUq8t;+PO0kw1sDxBrhQ!0O!1!3@$HT>EnfoK*MWSEOj*lnm z0lN!pR#Wmifk=E*CY;8`K=8t0kB)1DmD0BII&(xH2p-+FLz`Cvu!Fkm zs8;(i&ZyPr97WUbxFK-MdZ++vJ({tWD;?!DE9cZ!xDfJh2=rd>b#1SBBO)%~k-(y- zvL4bp%M=sH2Ec6tU~{xi(G2Go-VSjIESo-#P6i#WL*0BEW5in6+Zb|>={e#Q(+3^X z6Ibxl5_r-o`YUN`WkoB(a3-z}rjDVpr4%dWwx{ukb(|Sb{v*~w9D~G7igePdqj8;7 z+0Lw%zTpq~_Z7vzzo(I1vu7JA2K?K~Blwp`t3NCQ7Q1 zn_I|oRHusUoz8SSl?KMl(`vlO@I)hyB=8m-y+~fmX+?^hHcuv7pc&wkTd?jpMzwpC ziEJj9^dc2(wo0X!O$od z5>T^aC3s!FMPGo+?UsQTgvLZ(mos0N?7$SfY8*v=chB1t8VCvx5-6g9!$>axRdHG{ z)W~auaOFN2SFT}dvUz1r`yH@B0aFIExuqcbdwMcA5OM!4)>LV+J!pViSCX31ac&@aHk)G-V;>hm)npLC*rg)~O z$Y}6w3r2&6?l3?dS>bDh8{DA+ND~Lh_LzcR2j6u{5bDs2f(&RI6}_O}yji2t4$>O&j29S0 z91N-tc&%uLK*K^s`(gfW(dO@@Ja!OsQmh0+&6I;?@{(?XU$Ytb&F%*Ln#s?rTW4*- zt^T+b!`)x~Cyu*^ceL9b23PX;FsKvqH=p`>F7@+V5*b<}BPCZFZD*KTNnO>*y#K{er;(<9%9~h;5Vk^a8F2o-eKjo{OnCH~j z`Ad=4RSVEsYj#|vl$vN7Jfp6$xifR9C`5`>`$srcLs@$(wtlRjAGjNkrWS}M(*IH% zD*p>2-1=fQbqqJxC&bF;Y+l5p^~xAq&9}X4uwBQxMLVJGdU1cs^JdW)xzM$MCg^GJ zr7LS!PA`T<;7IvXIw?1{)le~<_@(tf2W`?}8`CI6GD2HVK7=d!5p}xV9Q`}#k)-fd zjyCW&9BmStnp_S^J{dfWbXy~EGvYuiu+(+bl9ufT2EcvUg3-MYorV}tKXz}fo{04| z0eU9-7i;kcQvY$jSgP;x5bFa=?ke#a+Q!Gupys;9dL2i_BGJ|&e{}hQj_v&!MrWHr z5FgFx)UdUmtM*e0f`78fKcIX50Hb#MeN|}*l@p}3ybF>fR=~eWF%i*Q9^sh91x1@j zXC$PdxaQHBJo*Y2dPxsJhgvIpOq%G!8?2^2q=cK>t**aZlw{&@8rN5XSL$-!0vI|RKcE;lzMcv+!rGKo z8>aICxwCafKgc6a*BO{}5eXwTnFr23Wr_>vXy$`_>prZ`nrQ?^r_uDKNxwy_U4<76 z*Ltm%1F;7xV$MDt^PG%9EpX%V(~2wXaIrz@2%S#ie_}8^MI8&Af+mTs2Y@(?WOFrz zCL?DI=;B0m#G4DA|tvMS#hCxbT*(+QM<@p$6aNw$^c6( z@`ze6)-~Ti&ZfO|z*>b6n)GO4sEc&2*kiy*S#c_jL(+Gnz;=~_W%8&DxxFzG)e?|{XBu$iI znFNd-6(A`;>I}WJEBDs7f+Cl|u=4r$HEj2H>UlA2bjShs$qXBXF)G zkwL3p$}^1o`D9k^^bXqWP26U|^NB&>TV?fC^KV0yDVs=NMlB@U)3&9F*Vv@Xy%b8iTePiOr-B-F2K% zMrtLrfA?GK&W^w>$l?muoxcuE8@a(yMZ;qRA$p6Lqpn`WH{^9F4J zg2leF9uuEHBNkyI(&iPaY9K04vnKAbo1}bKuIOkIPy4)5?JFTg#f=}1|Doo1HQKJ#9wG)9 zF@U3ZDi#;|w6r#pw zK#;GG+m6uh)VFAt%aXh3g0sLN$FW3#<0^5csfl2X zVaOSvWQ{#VP9M}ni@pp(rYBEI#lnF@PW;;tI`oQq{H;a)9b$Vx>OlH1;=(;G%Cf!w z54<^_(jh$WLLmZ5p8+CZYz4dwhEQbz#>vY3x=j^WSiBUZjChBcy!#bs*N+Vr?OJ`~#Zmb)HAen; zdy4!C--|Y&9i?bTS*DkM?fvKpNEgGk(a;Pe@W60ZZBtvAd@#oBeKDMsl#fvBHd^DL zjtPXsnrY`5#?dXOLT565lK*e@y1tw|9ymnJK=)_f z9GT%~4EoGS+{94rxg5FO;yGDkeRF!GV%ywv8;LsH<4K7Q`A&oYD2Mx62vOxKIJb6V z$!qJ6sSt2~z>nRQr*PU{z*+ZN9RyowUI#^5@xPk=ysDb?S4H|mFE}2;xppchc)y&y zUpbDJ@Is;?@{Z$;jF84ZU&@91uL!=4J1(NTl2!tEp$vRPCj?DrdjDwC(x_)?oa4x} z8Tk9d{S^aM<(rwEQ1M`K-p-Iy7;L;_Do3S)AFVD3W-}5;WqXkzME_J>U&w3aaR`)yFSbd-%26&4 z_KrfB|6JBt3N6Q1aJ(?eD9k%cu`cRP`eGLXZ5$sQv4jIl<_5m1I|R=WxpP6^lU8e{UQF%#mc|AKLu1;v!|8B3jbyckES|S zS3Sa20N`}mhP$iXRf)nP0sF0*Rs0BDeFTyj-CPcNwSGG6?W(c_tuCK~OP~ZM0Sp(K zGqtG58Q<}uHs?Op%$METlknc_2-)>f;pNyQHH4R$PlAybNosIt?xSgpUa2BqW>TR7 zf5Do%7_$n<@d!Y;h5yV~*_6Pr(sYI=lRa`!6H^hhD)ROUKY z3QRTxe~+Rs^c57q;j2tEx}8w^tn-(ul^8N<^Hh-jK}}*#Bg7)S%{$)y9qQ~HzjdsK^{?PvlO&MJ_ntbg3e34IW2~(QJeQi zLJ~;6q@Sewog;@^QQ2M6guBp$O=n9JR^ot(9h<_V4BO31K?R2>R8(oey?<}t0D@~b zK>316qovUX{LJv*fCi*U15ynCsENQ&U&FjXHDQDGYFB9j6eiT0=EaDDm*7X-FA78* zLW47sXk2<=bUXsn``rQ?6}M%Edw9%8GObHk0=2dNco96NNT_}vUFIY!^zXb{0aFKB z+-^lzdOlRPigd2dvC%SIt7qQp^)m$;@?Qupi4?)Cj)TcKK~{&W1zU`P8J*+~&!7X4 z4Sh%j{e-idtd$zYm?C)8QmS8EQi9xsQaBGv006+z-O%5Wlvb+MCs1Lbw+-YyZz<{h zT}TrCUBi0kzrb4?KZSk&uJ|^zA}n!e2Rf*xn#l_eUILHp?(^qQG6fSlV1 zpy>ztM$)a-wNn%2P_E%0>&CzCE4XlkE!0QnGwBpwJheO7m<0Ck1~?mljFi56+!HQJiUpbI^H!$g9>TnT0NNY;cpH-K+C6jbUDEb zmEj_&K!H67P{x3Z{+J=4EW|-Txty9s5U*3SSSH7Vl(fSIrfBZHJhD59V0C3p{<{Iz zo-1vz#!L)-ODn`gZ8R(oTYUw2&7mz~oH#u^Y>FnB8jnMJOrE(HIciauy3GLzn7W;JBbZY53lj~1t!o6V{r9N8X5&g^fVVrpNnzS zzSNEdQamn}zGm<_(7(%RB#L1NQ!(n#z$k;<4vfCm<%?yUzsoj@?f&z_w*>~wM&3Q- z*?0MDS})$gpfo0v8@-Onl>P_P+>%vgU2;OOy?XQ`iJgK+>uDmRUW5qr>X1p4g1)1!VJlFu;`qMC;k1j=g3bwMCv!F>xDx^=1#!5(>+@Ne{XSZTw z&}!Wra5}6(OlzRlH5aS(#E80SZkC6yu;HaP|8qPOzoUOzsf-71zKpNtUnF1A-PN|5 z^4E7_yf%+((T3_N20(@6e;yNYgnwJuZl84!N9%9)#aFy|9zQ`U3Mtmoown8#+5^=+ z)=Q!6lLE^3cKOw4uDb!TF{~hi72M%=JyZNA@SH*r9>PXJROjGmz)I6pP;}M=L3$@; zU6QkYt&x?66%aFeT1%emkdFnW2L46lrg=#_x{PGZS)`*M`wzfz!MvAVZIbuW$1pwU zAefeGm~TU`21ZY8AIgM3JJ&`5!bq8 zjp?#x!9_UX`jAWn!1@##_Gh~+zO2efSxcLwthOF3DmUoT!ZYe7}Qr1|Og)F;*8*pOXs7hLU z8cIsGOUhLxB`tMInyX5>KuY@8M8YK5tRs-#_-Q_{7nq~$5Z z`GQDEZ{S+m_h+0iesx%IHI!vNWS2Eum9=@BQ`VvPq(o5Y5)rlca`+kpWDQN*tte>fp7O|wA1*(0QsFJRD&ME0$ zRnq-Z(vnC?<5&{=?{=J^eLD|H`)*-b^X;;Fsj_bLIka%PD(f04Yht9V;Vg^oyA&tZ z6D$cbNx65e6!2e-TLT>kj;giyx&C;eRJUxv1Rancv` zKtkxqnv*_$U&$1_bg=VE_XDZa<^svW0z4uPFU`JEvx^?uv#RhD11rQJ;jIXFuF z8&Caw+vZb0uiAO)=RelIj8l~_?PDkZ`peF0kycOpy0b^pN_jrqI{EWx`Jv8UijE1y z)Pw(O|Bka)Nk18=?cN>R($PYCF}3;`y)HNp2gIIHqCss4YQI%AL2AEsX3ITVF4P{8!t-$H%J z;m?@%lKQNEo5{TlMMuWT@E?c)1;P>m;cu~3%Xy@J5HYYt-)dxk6wEY*?m;X772B*E zKUMXoKxavV&friX-Mx=h!!=|Brcz0wMtIBrm@3Z=p z?T-UO^n{<>{;Pq1sOSu^2*T|8VVNNq!}dd25(l}x--PwD-4&TY1@bH+s8E7{p*sl~ zGJf~i##rPCToS*d8jkpI=rO3KM3~wo#}tIkX@?)UZ})W4KSQJaV=Y*BlFm8a8e4z( z)oACyE&@|5kJi=Mne@+)>_S)~~n(toyh|EvEe(MR78PC+04 z6$i!tl|Ft_{WpDhiuynLAQlV%hx$9^46S}HHLwVGz)KlBE$%E_V_F=Bl+=IxP!8Wr z|95c+UyJC^Pniq1e`;ZMgDUCs7}VGYh!xYzYQYrA*d&vjnEu# z_D2)>car+!#z)q_;Ux8of^cAMEFx$}|DVQ3$a#uV$ixhXW^U~uf9?LUR_{`XIJxMx z#>IgX?U%3_mAlUg-8|hH-8lCIKW_9-C-9YafKSE;nSYpNOM_ED*t8}VVKEQ}1VR-* z_$lLqHoG7F`*AvktyMt3s6$X~S$RUwgkvWV_L}=8B}ZU!6>jK(Wz}*BHt>L*dJspz zz7%veMU|48wuI`0gtz&lYhy5_@4w{~zBvC;*oSA+)};Ghuc>7%3DxMDn%baq8hCx7 z6n=tVP4BDMtd=+YavT1gUV3va-+-`~r3YT0$d}D`RTXc`6#xKW+PoKWz{|V`2m$@0 zWqQtGy{0*lRr+ydzS}m7S$m;*@;sIx40-(1yfT?^BNDSVdJ!1KY;y@( zv|z&x-F1+&6R=DTU5;?RULmF{l{K_9Lr)B{5Q(Hyr=yMrhaX=|Wj2+Hu)DI4l)2qU1OwoENZNa&I<F8ae}tkz zUpjfzO&)cVKuYQVWJGKM9@hc43)zu|>tEC1pB0)i0*i#ukl;B-0tc>tO|CL>c6j{% zF>?OpiOk*g4BE_zkKvwpP|SHy9BMG*#_+!)MIz@0IXnpDdHu)o4k2J|ttuh~FylXP z6MCh#l|&o(-8MN8J|8APItgX!3ZF5-?pI-U(SGYZ96QC3sMgl`t2;-N$o0^d;v9_N zXN2OvGUBI{_L?oDm2T*9P)!&Xg#t$`5vBYdfZBZI5*ILebw9Qup|sS+)A01D?dqhI#)F z-uiE6KJBUbA(3B6-Wz+ML`)*iDbaOvnMHn+dAdDi&d7I#%lJCFl-_)pIy#LWX(M7b z;rki$KzrfS7tEkpq07ODhQEP`$Dv#bv|G8dD6n7-tGEFNz2)_hKR zGAc0XsfnZfe|e64YXorUncz+Qe3bvrrzXmN#`~tf7oLZ_q_+u@^*Hm6C^oiBeCxPe zZnxgx(M+E7p~N&k3SJ8gfrhP}o4@Ux46Wx^c20qzh8RW#SHg^(gcKf7U722Uq6=V{ zp8PHkWXWpj6q_5(-si}AL9;=wNFd8(a!S*&F1o8K#jD-0LvqSoTRi@MW0|T0hM9gY z_eWl<`L4(NTx%c=31r%wAtZJs9FfuH@qeV}?BI1~l%MrMJ5;j70o{B<$$Lgj$kGUa z;egGc8;Y{97$)vO-$O5DV-+izQRrcY#ZiMfsNfGTg7Nd1SIcKyM9Ad@489l8JU}!c zqd0$a<&{j|n^TWlo}3RzF>cS{PdrUOVAYThyovv0x{KTE`dFJY7O!|+-)nP5;sm)& z;Yoakxc2^v>uWw`Ul#@5X^?Kdcp1By^V<(kzW}S+Yvx$cPxvfCTuSBY3@*h^DkIu` zt0rOu*e3VGUq#M7mJ}njTw3FGeLf=#K##Z>D=iG|SCoGO%Wi;l?Wg`vy#CL<{ykg~ z|8v9j^^ChoKOW!rNwfNT{GaGK>-3uAjNZ@k82&Kx3v<><+}!K>aK`ywbMOeS>w_ux zpn}1$SrLYn0H1?pJ$#|z{~E@tEae)y2905%Y`(|;z2Vaxb(AV$bkf4C9acavx4Hee0OD%{kqH{ZmN%i~?C*zTykpcsg9}%IO|?x0QDX z$>|#FX&g_Io$ic3Pf&og({IFe0v5Mb6$FPMAaXhQ`qyEa@aGsam0rT#Wdn=V0I^U8 zi26g={+z)?XY`h#S_FnfnXCzUk&inYT{30JCz5T8COW$AdG91lOY!3~5Md&@eq+IZ-{Q>9Z8Z>=L^c^;nC{r)e94oWkUME!N$B%l|n$u0;eG z{7bkZ&o)^PC%&NeWrui(I$jD_^p{m<>j zwbB61`8-$gZ|kOAB+ce9R%%TgaTTAbD%P9l$e_>WA<}Hs=J3Q(RXRUg_zK|< zEL$cArKT(0J(|A;@J9f55Z>TqOd8*q2RYhmjU4E}?SF2uU|~K>LHt#EGlcNaEeLXasq(#yoUpkHQZHCyL@A`OYdx`S-VpZiqgmvuId*6IA| z!=K*x2?}RhgWj=OIdn$MfE&ZRJXQ2RA_V})jl?qc5{1yz%5gw$m^Y`zQ*)#n`f5fR zc|h&)ss<0%Snf5i{lV~8x8ij)nqNU~u?!|D&Rx+Rb>yta5HCgaXAu*ET3rT{%OEA{ zwkP4l)xghZPLC&Y2!JFR`G18%WVE~$C(NSH*~pD%JcHJZ4kRTOYAwb0H9A73ux2+E zp-};&dLq_ZDT9JZn5Z97EAr0`DuoCGCYsq*03PM%%Yo`f-a?y@KitrQbG=z^A&kyb z-r*lOnj+AMQ(YExb~Y+$da8XZoG;_E0!OPqihlL@jwESwx8f}Fz2TA?wfP*4?Ju=D zmB6)lu{55`?#41Y@XVS#z7;>fej=dQIH$1bv(rbL>FLGhuK|_YaBY}!ZxNKPBIuM0 z=VMZ@AJdE0Ti+I{X^iFI3dQa_(&O0u48s(@S1VP(em}mAe1c_tfPo?yR7Jo5x7!u% z2Dz1qP?ia2kw5*7&0auOQtzrK||OM@YY$ zXG6Nh8rcET+;~VKm|`HcZjOT!#l^#UE8xT)FNCxA8z4F%Ky)PZ*Xfr#o!A?cS&nzS zi7m{67K$BXCZ%{yH!`H<($m%ydKi>rB+6wl^bv*zr^mb7CzV?DvPCFI_^%Kh>y(Ss zaOV|haV_BDYP^P`DFB(OOkvQFg-T+39=coaM8map$}a_BWFT0R$;-?L)>7T= z`}bJiQ}^%LTO<8jS_BF|72W`E$F8Mq>c-G|r^hT$wD#;(11|{77Q~M@0LZ`_J{{e* z8?D8ti)2XfpVZ&1``+6|jA`|gfiFm9R>VKN$DVAHj?rtXvdP_A{c&*l>S`i6F|-%w zHo~mJ`b+%Uj z7!)=Kx+6$Bpb8Z2^ZK-S=;Hd^vII4eF0VX220GQF7Z3K84zv;``P(N^l{pIvLACB^mZCfn377YDeOrjR6A5dzo z7a=9)Pgh*i%2|$EhGeT*xqNCS-?vI!0H0N3pJwpKO2_`U7Qew>fl(2988fkzqM`JQ zXUQn->>ospsb32xpr?$j0jw0OojYbB>=WxaSWUIhN^=?% z8Wm}Qg1<%e59(yfB|I_NQTW?g8!{ryOp%6km;6el2dX?qP&igLL|fn#Xm5^KX>N`k z)8R-txhWFv&Bpe!O%eFl+ewbOOk?QKTvfTHMcbP7n%#M!vm$ME`YiUS+Mi6B?%U&L z`}5g;_ic*fOIu)hGbw3d48+KP#o`6`0|j}F@i6)^#a=D_tbn%qLh30(A%JM6!SDe+ z?%Q7NoDtZ*&~nF<9E;WHxx(*muaD1@N~4@uKtk`reI!b4)cVcUzi!V)ln*E_Rw=k>HX=}lJI-p=jA z91O09baZuL2}-U};5{wip>v&3SPOgFxq!5@mi^74wbMG#nreTZ*jKBn+5RfFA3WmB z&$Oq#0q14WiJ9+Y2`)I`vp+SMXmw zh&YfZr}SeBJxpc83NpArek?N+u>TW^T;5MXWi<~~aI)yLS@h|4(cBCmMczWuJo*Zb zrNkEv$CfJEDpVyO3!-GZz19OUB{!uHg?+TVpMpADpe6u>T8e(oDcT^^Tr`743O{6X%|8n%)aS3@ zhV*oE^~n~iU?a}MP$ic+FYDI2_lcTi z&KLRC+v$>|2ekOo)$AUAtnBS(G;75D@6GQwE-k6`U z2#r_r5tD7k(en2lIf11TVY=W9TlW1`itj&o_d}>9^%5Si0I)WDC*IZ4uFci@bjQK1 z^%CaT#QRr-_{3F1s2STcZ=2^-gYo5gGXi?*)K@UI8xemlM%*gg z!>*W1mtKhyuxgUo{~2|vhlfCamdC0sKE~(GNBBwuUa@||wwaG0*wcR^uYGcz{QWzZ zV1a?RSf#Z%&t_i$`l5e`v>)rYgxi{{GvL8fU{$BknTJ2nSekv;SMXsnA%yo{5f;O# zB*+H7=fAczd;z*l-NXx4ch>E+*~BC>==+-)tv8bgSLenc$c^>!36%4$(!y>0EQ{dh zR;eAnNwFkC#q6Y-W*QU7|3|r@%T>3vRd!$24IqU%1wySaib>YpwK;!Qoq6}aq%+HK zaQqXTnD6Vt&&{E3ZuDqibDcsh4O=tAMVvGQrfr(K9F641bacW^nOa&Gc6SiX`TcVA zHv`5Lk0rTrO<`BdBh}SB^%Vq?h{#@cS1bJ@wp;(w0yK$!LDd>y1F+=7GjrLAiEeaa z__DZ4B4%Lo9O8?wVE&&}0^=uQdCe!X>~)tsQpHwiY>l{yrqi5k!72Y%&soGX+@WE` zKTN?Z!?1$AWHxjq>{tUdb<`5l=NPCesa@46=rGlKL+xik)KowDKHE^Oa<5jIS{Of`rQ4|dun zs;Vj8TN|H88R<43|4H5HKHQyAJVsJFY_#fiaUGcq->ae=6it>)Fhy&M-N)CG{auGeFH`BT8@SXDomH2~y zu=^zBkL?NKf9fRQ9>R1Im<75!xW%^OboK&-K=RUhDAaj998Ht~d#aSW_zSEf2Vv4< zo?u@LQjrCSkdrJ+Orl2|L(IMv&-T{s4q#D^4^4>J83Nx$fDg<(31kcSKqbt`=VDLp z6s`@%g?V_}camIu>+tg(=usdKKdjAY9zZ=D32)|f>d`sv5^ABkCiIj092+4=g*v_>uB02Ab?^wcHPETc-A zm~dj&ba2TsQA#Vh5b-*gvN$}BgMpdfB3A6LJia4+W(=t5OqoSaV$>U(KC~!{keV;4e=bpZKn~L+k4Tf*!QpiEP>uCz71&hrQ3B~5Dnwu-P@Pz9T03z{3bwLJA~C>wU}c6_eG#isK7{T-N>~#RLw=8wvxj4GEs1daUSnD z_!$<+SB7hoR{IC&u|?qH67RU3Ue{)LYk31p081?BPHzsDw-(OxnOADHOlu;7*mnrsdvlQ4im)>hZ;&#moaF0nU=kRbvKURt z+Y}7VWs?$x=HOPP#YC6!FA;|(&FTTvj)QA8mdW+Mll2PTrk7=r9PLeB#eHY>6{E?1 z1e$B%D=>`IC)@1IdSHwFpxY}~b9IZS!R$r;0Rb$}%=o`+#f+&4)?hg|^PWWH7koYC zGY%M4MUcwlx#WWs2sL_gF8bsv>sS_6jyA`^-(^3F5VPb-s+JNfq->HT3PI+USkb!$ zMieg7q_Aj9Xg@FucRk@M6u3qNJZ=93={wZzb$z6nOYj|nb<+nX=;n>s(PQfrq&+A) zApM~Rdq-R|`S`=Rz}Ob+W`L=iHv`OgUSmw|PG(+}lTk_fMOgg0%poh%c?W=1;fg$kY=_mpU<9CZxNgu<27qfO{eW4B)OI5iDe-YAXh{#Cmun zXz~`;J09czmU18o%~!C=o($)oAH~-qd`&!!Cu*QHAVsGMLjgYT{aUfvJE<74p<**V zi5Mhx6uY)-2v*|69E=AKbcNW%aaJ!dIDsc6*!ii3>x5Rj3)kLp-+Em?XmeV4p0gJz zcAlL7Fp1C@6c)yQ2@e!w&y&yVP?6jLe?O$2fxk=DS&}xJabe^S`r4AU+1cuDH*Izw zb=F;*%@rlt{?Z`(n&Q_R06`hxGKy=gl2m-(E+zKDeVK|1kyVV9x3J>+Zago>N9?N6 z{t+LKHV0qCW{&nx`Z&qcv^OPKeBWO6>9_dwOMW^!aOa*RM9B6C&Wj=8?XUNstNIXw zqx}YUkFp;W`#&kpSy!C1qu9JI2|F+;DYO`2JL!l>enT&m#2vK9I#U56asOhbuWtN@hn#3lx)V7Ec|6X7F+y- zk>bZo@sJZot?g3KQNzE&`WsID>5ycN2>r?T9#`YcGNjISLzEh!{S8xgllK|~T(vth zhC#Bx<_9Rw)>{{6Qk-3%NLk+zjgH_F8Hlc8L19x@>ldSm?ZhiMvlToYWLFo~tVpZ| z-8fk`#mKTj21#oYm&M00<3`@_2IWcPd!f5v5F-b;wXm6(Mv_i?tJl0K$-cx#(mvZH^v|AX(R$-xa zW>E8mbBjL^zPZM@bx3nR0hnQ58LllelF{>FD47Qg{}#+UyGI|_6ro?8TUmubKIlF@ zX9d?9bat<5MU%0u+CHuJT|Vd9)bzs{IqPL?mC@fjXuFZPL3jO2o8!YXsA)Ijz~rwW zhfgB_!NW+B(C(h4$SI`wo#VNc@gg*16~6cK>4xlXUsoAV$_)!R?}1P zlZCYD4=X~^7ZMNZ<5ptkdBwSt@5S<}7$A+DMpmE?+NNXI6{N0AE<~w)U=c^Z0+}Oz z+%n@V6q|v((xm*t{ML$4V$3UMlFTJgV30%p@)pA6U*ks-mX0C*fpfCqW;wQSW=4zi zcm?7wkMTmme+JTH^07->dRqS4if{}ZaX?|wO#cq6C|cYjk>adN<#eMp0Y{a}ia1)c zXgWY!g3`Zgnkel2qKgG@~2JA5V~b zEB3oesF=Pf${*o>!V%k|xQb_R$tKxXZB2Hz&Ge6B-hVP`u5~z5{*5&tAaDYP#!0lN z`2#j9!IE`g4$K4B6ZgYSm7=>gV7e1VPlL(&`}7=a7RIG;;UzkxnLc1ZPdp(>7EIEy zSc>Vpnr2{?_*at~sq z`OH1}rcp6GpyM6LxlCr^bGOc3z-w<*gj$3=kcDPo8ez}t&7s)#18d8z06S|YheraA zrMAI8FgE^#8+a9O>(MGCJx+T_vPGcLZ$yUS#%T7VF$jAY4RA3P z;z{mO0x%`ivyXInl>;ti5g-LXk|!@PbDxs@(9faeU~RDsOlh+D!wp}7jy6ap$kC;w zb}8&ToU+iD)h*h!JLOiRwHZfi9)5!DM5p!i6AEFlpk?+fAP6NpJ{HygnX3P@+5ff= z!?&yzH|hNeES`unL~EPf8Mp(~MeO6Y)tD-rkx=30g6zmFJ%Y!YZxw!v8j5n!T6dbK z$x1Q&T&~@n;qe_wncCCiYdnHG8R15!#PCuE4W(>V#R z1zSmf7o@)>7jG_c&}tb$8=0XMfU;7T8Oe9T?LD&*qYLsD&;ZZo zPrX=tx|g1YhAjpPU*v*OGAR}0i zj_3zzxJe0c-Fza2L?xSJZ}eBBWa>@dWlq3J7CzXASEv6X7(wyaSQG+ z+M~Gn8^W>w_MDXD1I(U=(4T^I1h1e|6S?W`F$ZcsI zLTSsSb!KukZd<)1*&xCJk>+$Dc-`mDID$pq6o>RBFW4M1d2@&}y%g4&c})k1!##7h z^TGxk`RV1ZT)%M~-AW5Rc~+B=NF|&yrO|`65ap z$i;`aRFu&PMf}~0qX^9oJ)ZFBAJk4i7m z@8b3sm;wE}y(Z@@{Xx`0JTUDELzx=`wi(P2^tUcIfNSgNH(7%L!54Vq6(QEw7RlkQ z#d4s}9$uX}y;%u}FduXs?uYfzYrUqYOR@H5k5LW1yLq6qLsw5X0@tS)fqw9)O#T?{ z56RRPe3fgMNti^_jNMM54@dMzE{Z#6KJH*~Wj*HzbtccCCTw$e8ixuuYx0`uK4{LY zsc%t3dUw%gR?h5$wSTb`&Y6a*b@IodA{4=GRcGhoOU3NHxQeAJ|Ss^Zgs|LI3LAttfvT0zz%g;SZhXbx2=o#QSjSXuc-AcWuLfZg_XI zZU1_F$NFi$XZWD4?g`=*h|t?Mgy>5``*mMi*Xhvz@HM7~3uKrvT9W9L&+%8L2OH+t zABr1p$xUpl5p}`W*d-5&+lEjzJ}dIClV*fmkZLGwiY85rs&E(x;A62)gY5B|xBsWO z;Z7D*MsQG&k+T(W^wQ=&NTFEM_Be_xe4D?9W^847(^wu>GcJXVwPV^l;X9qy00K4$ zp1HZx?7Gj5qQH&fkM*0p2@_`C>WAVi6I^A(QY)ve1Z!IK?j$+g#=G}K@7{`2zzqZl z+@*1Fch%Mm=p(<{+N}kN@iB-OY*hcJqvd`WnR%7t+O$HbQUlb`wZ&~ zUG*dDx5e3KZxhL3*eYwe0mjVX%wijs_m77Xuo&)nJeb!Zm3zH5yA~KM3{(Wa$EXYX zoPf)~lEoxX%-w5*O4EWEXKRQ$QOED+ce+V zxal3YX^c6b&THO5PCVPIy^1YkHilOqapERq!W!eM*=^UELr3A1Bs|7Ua$_+7T#*hT zFWk6;of5FCO?5f$Fs&a4wLdSRSb@m~Glq-~WCe?{civtja6bUJ%Io?@^Kn4}@3=3p zP2N*p^8o_z0H(RTy2qOs4zs)lRbCJW2G_9aWm}{4p8@+Sw>XeqZMW$j6q#eVc260O z_ISn`^`M^8i&Tau=mZWwJbOSW+C(;xpwXbMx7VSmXv z2Kwz*5T_U%6esxPzSv_`IPEa;&$dLA{&XGSZa02M^rv2Y7S*4Mv^UpvqCaVG9?-ke zS`kGHD%4tH4D;D+6-xK51}oyBQlWJ7VW?1`@5r!=We?zC+^@}fi6?RT6Y~92GNH$2 zPT*M)1ZEWl3M?1+<3_x+ih&7(otVwj)7=U*wEE4+IP$d8Z(v(c6a=l zZ`*3C7Z-{dCs2c$fU&QywXoi1LG4Z4)853rP@SzpDg3{VK?C^52pNg7M(}SEA1F+8 zkP;50rPN&9Zfz-cl;5;G3D4iA&kcJKzePWoW&In{3PYZ**Q{)#|x0l+tOX1=EUfpN0AUx|CdBn6UmI8LYg1E?4(OWbx`#LjyHca3y+M8#o>hF^; zn6nCV80Mk+5@zYl;Wp!A>p|$aS3qd|XBlNj>Q_8KdG`Gty-*xT@?)T$_B`chs2X=r zE8b_QnST7BQW6$ZNr3&jQS;q^Gq@FyadE7Th^V8NHoh)6ueI3&a2q?goJ*AiX4cT( zYHyySy?H|y>yU&?sj+ZqTw0NJt}{MDex=z8qVGhXicz@ktJOcmaSU0`+R~bWGC!)W<;knWX&;`aT$MrA3fXA#I5>Dq{H*3PF&TDdsshUv17YMZP_CU#bZ6SK+^A3e!z}VQRSw$pa#RWu9 zj6nZ|uarXw418J+FUqH0yvi}!i`WwfX{;#&YDHEa_MuLLg3QS-6B!jFu!gH`#*Kx6 zTmF#%s0+P;YoV6+jKqhUHD6BvpmVrQdJFlK9BiS(y^2^k3Ng4jv}z|c{?hRCay$Gx zg1}*&Ajr6GgHRR&LRl;bH#i_%?G20s2)!u3XmR*vfhkW?e_4n6Uu6Ad;op-mt4NsT zAk4AM5?I8xq8}IH$V`Q596f+;8KCqaEY^slO0hve(YjaI!;Z-Xd@X!v{w4zlQ4kP? zdshjl&DQX<@C-<3M1e@pV0jp)r8pE{jl0&r|D(i78Qo|O()h$D`wa5|o+UpVhV2$5hGp)AJ#*f`D*!nh&+S6A!I5{ZvK zE3~LBohuw+twbOy3bUQQ0b(b?GGa+~qWyb^On7Whc&eTVQeFMiUq-^%jR^O>lO?jJ z@=*Ez3}U(?P4}l~(Xk0{9<&G>CBo8ZwXif=O_s*~(L_Ofli_Ee z+6 z&G$Si!j4Z%yyMQso-q%;#$o)DyLrGOUM$M>{j}%9Q{JT-5k8CccoP59Y552Lm$&zU zuX{ZI{}W9}5htZ3MoA|orAYm4Xha>&z%M678B6A6nf|H9BnGM~Y&jRa<_~*LA<&=T925&*$-d{PJke```Wdy03rt zbzk>&-*_zLi^3WbKM}!E{`6xrWnbsYo~%pN->!QIRUrPaRF{TdM%lmkcgibBx10Q% zxs9rOfAM3Px2@cMzOc$HXbHMC{yVd>C4dYQD6I-+BiWT%(2^0khWXP@mQ6oTIPhNb zVY`zLSBMMD-Krsyd}z}Z`C!+8s>S!k8nflYL1Yu6uI0VtLl;*`S#;iZ8~1dkY~iqs zRIEx?PjtfJ_CfuHgTt866U0tI!iT|lY(^$%f1p|oD{2xeLX`_o9ed1ii3c-GN7}@@ zw$(J)+Vk(3&QnCB7XiD5WHX)7eg1qC(!tr^p)69*KSvgoI$1PCtX#?LQTU5Ix|oB= zvFjAn=QF|EaKqVQr5wy5`F@e#s`buvOM;VIASx9kRwBsz?2;i-FkEw2YZTe&7B(Nj zfs3$Egs3MtQuyVj1c#q(0}9hb$5M}rCeB8mJ&!=f{F?-IW1cta{+g(}j#WSL2%%oH zP;aW{Q3&Ye5@WedK!3@7k)_Yr;)@2f%#^bJc)r{B{&PG}otUMv>9>DS zd+{XTg*S~J!OcY4ZsrX?<;aWfH+D0{a-+ZGr>-fUx(trF3}Ojn5KHKvVal!LEmbyg2ZSd#Xxe^35)4vkT_F32!4@=wsI7vIQAfM)+(N{39_lZtC>@>7p zwcV-xg+KMI|B*ftThA|!NcSp_y=Am!pL9!( zAt_&;atUuD;lXsyL2IdLEZS3|m~b>BmU`P%e=~J33Tims9J1kbN0YT!YgR=T{DHK% zh1~Sncs8~Fja05M2m1I%0rqKz;Kt(diD;)KdXGml?9Ld%4$GN0)b^+Yd3H{hbTb%b zn`00LDzpg!&LdzYmnR}5W#|Q8f8`Lp*Oslsye>=gLmTnLO=^Ufcx-8y!|$}Dwi+ep z{lv6jzo~N=`N0o^iOME_A-8q$E(~R?KimD}OP8~9mR=nqUZ z6rXXw_CO6gfeV^s8BPn41)9I>q|(R}d$QkQ=8=5=>^>zs@m*bHRzHj+iJ=SV&!~}D z!|1D@cc+?5|LI;++IPsfro?0$$cal$;9ezN-iaNm1s{3(dcC15vVb%!Nb7+bRs z`=1Vpug7nR@SbFk#2%!-q?i(>AT}4LbILBYKqf$8Hj5a%6~ZRRJ{WoA(8wbbc5@9{ zzEvWkxZ9dO>_INH?qEDDrZ;AK7g;dg2y)o>T@SCe9y>;5WP(JR$=|Ah8{*w}H=WboD z3;NG}25NV;9aj}z67L@`IcHm%JF~wYtH3rd$&bI}PPOBjydI|V43^ZJ*S?yyH+JHV z_vpXdTFJMcY&stQ9RIGD*~O&|y~@!OZjEjKZy5lGN}XAz5AhN&URd@+f>$4En`GT< z>GvytK&{E@0>1gTXeB=h5FWMCm_dn?`P=uV1jMlQXzprtaFzelYq#0>?PUCNBxde| z;}3hFCL=!)nA5N+(c2mgM^l zv>Wl)Q}1@8hX|%bY((Y9YT%q=0jqB#AElUFz>AEh$h>P%G+;IRi`CSaD}+|3h9FKl zOvJu4=ly;HJ;=G>E99*0Y0INOlmt|47ccz~GtY}G_zX$gqu7@E^zQ|P7hf;<-^F1y zFoJd>O^M3r#tP+IDXwF72>*LfN}x0R+ga{JE2;RDOi8A6qHP{vCjl_)mYy-nX1JmK z?{oCcAx_`q$ZBT8q2Z%0SJ6Dt+8bz@$NKvk|Fa%wt2?7HRb4^fwX0^js*(k zvDQ_8BgdZv00^{6xXyVjX@4q6MCM6MifAEAvsjBJn>0zGdA$W55n71D6}kC%B}+`g z6=Y{k!+~#&C)(uT3CXedH6-WAE^<069QWDk22K*psOmTVwPD0xqkBz7LFGRgCnU=c zjmDcO;Iqo>?jzo1efPVS`pDwUp)Ag+8|v zkK`YreFM=Eui>p+iG6>o?E6<%V&C7fjl?&wa{gRrY8>e@hW@Xa4AWvbYw+QMc($K} zk;&5a^fFd`&$__MZvp6Zkdb*3_-k(#NgxX~dU!B}fJ&3w9-}`_Jst2}hyTGcKyBoa zrNV8l9lLRbzpUhJqpZ=x^12R=VeS-;{&;#+L*!q}ol{lbhL5Zefrwqd!h>VrjU<5K zVUL8gVMv;J!jQ|{Lf(1TI6^KG4VMUiN^M>$YOY8<#C$lHv$!Y6Uu>^@u75_d@W+i} zp4N&@{?NaRdFnWqWZ~359-rq=-Wc#rB@o}_8mo@36-f6M^k`cN^3w$s;L*P|sRovS zZu_%-e$$lrp*WA-e-lE7Oo1@9XLsyMqya+X06M47~@58ZsbiZ9RcxSkNt~QB&>M7raUMhp* zDIoaTNA<-&1&^an|BqL*iT2mK^73f%-tz5iT5=+8AvmEazAV9-;_I3WuA1WWto4NC zIi#yg*5)@%?lPBzqm^&+200MK_UAsD+-zdb1zl$f7ws*DL72f+Xxa zF>7xgaEhPKLv-?Ub&2zb*2Z@ZnpIFA+ffpU=`1~%K>Xa~w0mpDM~2*xr=Nmx@s@jQ zh^c&U-I?(V?)ApSXWtu*#-GPry!*MyMSH73wLJxo!v6t5{*1Zfdg|_ts!yru{Cbl= zOpYC#oTK$(>iDzflQM4rFvrx8dX?J!AP~y-9_N3@D1#Apj?4|yT zdH~Jhx_1xP=`OSC$_vyHo}L%j>(}bfUdi z#;(gz;LHLckYKJ5NTADdZNxAzDJ%{WrYvA{6r%kX2h*^{HMM=~*c_$(4I0yt)W-t3 z^}JC-q%@7=lNa}?*^RZ@Z~QgOS6B6X%i*PkU#V9A!R$be^!3|WEac0cP#q~>Tn!j3mV=WCDZq3?0&%JuEmYW zf0oVXyq+3Cd2*sCA-8`&9!c>FI+*!%PwAZBcjF=6WZX;0SVbLu&qpWsj5~@Y$*N7) zZGt}?=*7A!A7$nUi~>r;dIPAil&n?MgiGY$6qenfhh*V`)}tY#;m@Cd!`Y|Tzf0X~ zUEN3XJ$x|w@(;2%zWcn7`z%ZApsbYs$B9ffKg9#~O3Q(NRraUnct~%I=+*;}g95t! zhb$AqwcEena>(~X`jP6V#eclsT3oCad$ice5oz{Wf&?O}@b~-{84!F$(wVa4h>4M- z`->4LKYmFw{;hpSGlf>ksi~u1V0~mTYGNS&Wsmu9I#HJxdfSG#rC_}&SBTf-{t#c) zFminZ7KnMLsRB^ERMcKE1*x}x!$^2A6Uk_NX&d<)II23{p-HVp*55M7?T1@ipTA9c zaPRV3W7Q9IOFnTrZB1)0@qC}}^e#I8cyL+2{c{_ZK`Ly422rW_1}&!{Nul;@7dQO_E0V5a@@YYX%?2N~xG?KA1C5 z-V96l0>(b&p?(}{*3sCPyl-#0d0_8(k$CAVAk(m4jSde&JzDI~<1Yqw2q5gpX+`^B9 zm9bBEo3qF0bty9;fXX!jcB6PV^XN_~Jqk*sOLA!^msoY*6Y3dgN^}Q`1QTBOA5ht)bKUBSV{j*Ll3i8WI-~+!L zvcinU{95!Si^3+q#NNT9*7=2Yi+u5Care2*NZ+p*7!T=B1^r9i_3!b|)Mb!iRR$$< z?!ZbE)y)1PGdb;?c{DxWPFJDNk7f?_l6!BPQZ*#9q)UWd0-Q>b4%~vYkn~XiR0!MZ@Kw}2S3vMqDI$ba7A5iwD)(HPqOQx@+MtlWAa*} zvFaZ@CT8;`ENx>vg>#EP{iwFBdGR%)yFT)M*?X*ZRVNFdtzz!?_Av?xx7g)Jo3!#U zEvtNO#AEvehp|6i-ep}(8|Xe1Dloyo19BZo!0w1aLI`8Ny|Ff$C|HGcYDQswe0wii zKwnEC6Q3Ik`QAIYp5sE|J&LznwZqf?rdS_3={vAludn?xRnq$qcHx#|L73jdkErac%SX(Gf-q5@cwL=u~9*GG~?1Z1v{SGs0w3xy_{B}&9w)5?Vb?`YU zDfzYCTZ-xiKgDOZzU*OJ)Yhc)??x%6fJhZ7Rje~F_S~NFmL)}W>w@o~ze+!QQ{7tZ zdX#w38l1SvI)<873Wh`${03-7lLd3E?PtfMYl`$!g3)13toj#^2+xbpju+VcHgzP# zZ_N+0TMC zXA!ErPB*pN>OXlIR1k`o>2FJcH<*>$om1Gt9eD)rio<{Mpn+)Y5vXsQ0nx#S)poxL zh+gM&{U;k526MNmdKFyifod}uGFc+AO9 zK(yWhb|fEF?iZoZNA>I%kc|nJ zn-+a?qaL>V5qrrAXG-w~FWu*t-Dmgk3=ae93;x7Q#9nrtxTIdj{*q>x{cfCo`d6dB z>=-*{>q0Yxqr_Uv22GFp=N)V#EW6gimzikBsxSMU>1T@J&9eyT7TqXM{CWSW@2gW5 zC7YLdEf0yY7oj_ptV(#Lk;nd$7x_WkdOq7!<;9{tJ=z z6KP%S)BG9d$EvqJq$&}_#j(dRc*i^PwC2eUS508~>-{oDOna9szMK@q|JO2pa)lBQ zHSArU{0ih-$|p7Y6Iy9x{_WiR`$~2g4Tb%iW0hfM9k73IsNhWhBJ=N{6fZdep0uRV zILzsmzl04=)}r_lHKKQfm%PV41E$ygOEc~BzZ(<@Dzszb>pja$u=5UtdvS?{+KZga zzAx9rTig)5`rBX#7TOT(uLxLx)Gut^)`x*l^WXi{tq}624*Ew-3NS_fIsaaNbofyW zLiU&8QncZ@H73nv=G-1A-@MblhvnO72rDN(7Y4vCX02sM+5Eo?R*B{61W62Q^!gcl z-Pxrqi9HqCSL z^7%Ms`r)Hq>uU$7D98K2 zmjFJw&-9`Gktnu`=JvMgZlz~!s}hZ+@fTxn92!l|(@IDE-0iZQ&$+5L{z3P9h3xu> z{f%!I<}*h=WX{R5WSSm;8c?SB@tE=PXXN2h7jVcAYrA{*tc|^izwtQ*vMklGrf?zA z+)Dgk-3FsDMfJ^k@rtko_OUblaZS$0+SprrOo*57tYi6#q6gJ!g-V>*=Dq7~I7gV; zl)6iX_r%gR09@NXs4me|3V%WRvw!IUv&kQQZ2L5v6lec8ll{K^uDeh0O||psoSuSS zV8zzEZtS7^-N3SJSd5+{v54hA{QcOpya|a>&tmZ1@4BZ=zNX%mn(30a5Au?Y3_N~# zp^Gk9;O}4uKzmoqa8xrwW-)z1xFp2$hl5IRFXt(iNEj%A(VdaWkX3N zG;pLFdmfV(BbD5f(&H;jia%<9jqc{i{1#&{^nZKF4OQ|h5jI2<3tA04+(qsDQ2av1 zDrIb6`f*OYU~L1-8roZr<)f?j=FS=8gt(JHm`M8;N*JIdJ9H%|GeGd28&aRC6t^Dj%a&Uf(WnXPI6R4&NxIh@*o_dpJ zGrCyh*3~60EFB-;SiA9^@gttDi(gpkjXbx^DgCt@-{2iVbo$1R*i@gt;oRgUAF+9K&iSbjFC#H?{}^xGMZ#ptuL#{!+VMlX`XzjsK^dlw5PjoFHiCeYU>?iA?3 z5g=cgo&m8~YVcnu1QdvxpVYIz8V5?%Pw30`JMB~G5wzTj*|i z^AbEolWmgo@M_@O^9TI(2BDdH-9&^M!7;)I?~fr?rHsMO%3%8wsS-RrCIf<7Rh5_c zK_10;RTC?2DDdJFD?(1?ct<8Ri2K|vA+QS0%mvDN|2o{S9<#prEy11S|7IQn)G*VS z#y5?v8u6-g%ObJ;G>Kwu_8JA^gn9jUHtRUE#Q$o#;>7suiW}kuPr)TLla-3R5>r|< zafhRU-2`8+T1~p{rAMu0`_LE^X!nqx{qXnc`r^C2d2idpTKDh@4;dPS5orwvN-awp zVQaLEKgRUbNbC|U^#0GJ719mDxrZDOw`W)0O)8HzpciRcn|rbW~74~>x7f-#Y!3*uRrqezC;_m?4V=A{Q!~VOSLx1+(6*p<-5@-0uULsR?CI;1_ExLKyeT6K)3vy)nUD$;!ELQJ1UiE?cGL$^n8<&5?VMP{~ zt9LZ?U#+paf$8{`LcUG@Gv63yW;?<9O|?Y%4Tp~IvLk85#}~ZD8{t8jttq6QU{AF8 z0Amda@3jaLP8QdV6B!8s2!BBLW7R|M3sg3z%3Cm7KKQ3h6IO&|>_(_OYiHyqj!vgL;n7t*1DcsImT* zTM;Mh-GC2fbH0p2aJi<`mo+A_?T6fOn3weaHYES{{I^ei-9)X;}^c2(__^w`a?WSZ;)s>PhNbOC~^ zl-ieOnbNIs7^AHRBZ*PVtc~zroRyJ4S{~71ux~o8KkSdbcVO6GI5ivgI!G`1W24#S zOQ{#P`VKDg4x9HXwd?!BXLQ3+(u!HNx_;y~&HfrjY-z}6!T8z8ydU$qA^z8fk$@D#GD96rJGo%#2t~^;!5v`b26$Xl^P$UK1 zBU#GgaMRRv4M_=&~~3D@cCb+Y)+=ZVd9bn%2I ztg~wPE4~HTk}LF*B#)8ApRZRO1j;K00`?a2Z!i9`zZR1BWBi~BX)D$WyY2Fqixm*W zajLG&CJU!G;{PCt9gSi+>s6<6U}#Z}Gv4Gb*M z33tDeXCLWohSXy6K|M=UtbxcmzNGK=Am6d^jZK;7Ix=X zVqZLH0kjUeOd=-33Soc<=1C+0c=9hXaf~NR>a<3!zyyQND&g20PQ4~<%{-+^44Zd@ zOdG?eb73+_@ij85Re~rks;Gb90kUwk9N;B}|43;Q#rN2S^6=k@sPY=sTIs5Y2NI|I z918z1^!M&o8_WlF35lpq zxpgv!BcjaGkmdcB%Nwg6Zpoy-FFGd!q%8e?2Cw}wN}h&?A2(uu#jmyN2mbfmRZ&ro z;g*Fs;xGA!+1u^@rCbC0tUO)iK&h!I=^bf~KF<*X?1w3w{<71QrG^&P}p_`Gi7%kL8b))fNKEm?&=WSORz450=M7Q!QTip#|K6H3s!)2y^;U* zWoVHs2f=DCr%MxNHfQK}cok1GP7$+#QngwiavZZSZjKn&fs+kyA|YJoaxU`NvW0!i zL=TAellEvaYf|4hvYcHe3+RC#M;_k3@$C_x4E{cL@o{BEp@lA3(=q11actPzk=g4A zu77(t{Q|9G8Vni!U!(pts?9Jxyb7Aj60N0j9r+YLN;ATyegdwNiw6 zQ4iPyQU9Ym`g5rzqK3c&q+9Fh@&GYWgo#Dpaw?1OsNLvWZ6lvkh28HIWR6X>26e7t z_EQQyvfb7%;p%8Z17G6w^Se$7@J4+pNj;m^92}v@ziAStD(By{O8jH))(V*;@oy^A zH5p!6Gkmm+@il)Xtp0m@J$0)!^0*0gdDWfV%-*^}m*5k*-6zda_@oO*Y$=yTKIudM z_o_?v@tqaA5Fb0MNH_k~s&e+*FozHBW_Xf#BwH(hoYCKe z~cI_Y&{w2h;QLFoE+FZswLnfZ5~WJQIHRfe8Y~c^v#MrKsLV`*D@bV}1Os z`ng*tF%ON*YeO}3aGWV6k)v*Gddi6%x&lYLvWddC_k{ZA8fBrcNLFzjVq;fgr`Y#J z<=gBkH7Z#+eV@ua|J+$%8g^&SKkbGMA)iyn0iI4HD>kq1!%_xn8s`hLXsFzsy@e|n zg}fQW=4vg<1HmH69U7Ko;ci!+VD{r5QKXpRN_~}Xk}T{w`{+D>-jnb3*}hO_9x}ot z=d4dlo%9XpmUcgzYhvLV%CM;oQ#vb=?V?ld20Di{q9|W1skp91S-|XRFJDHB7%XPA zE~LNiW7SQ!iF%G#-(X@a)JNkS$#_U&6qZlMatp?f z@senY{yz%jQ74w4EFN+ybeeqJ1&G28uUyPC&H^rOcpia1mJ2?Nk^m>?E{#$<=AMPE z07%1C!3!SSg2zf8BPC`lj|^!qALAaSFY3{Aj}pmx6sF+1_0MsqSW(S9a{ebcm^TA! z^Fvm-wdf=7|Mnh0M>cOdk=E?=l8fvc^N(JLJaM-*%S-&$DfcT?T{IEXyeFE(Fv0~; zd$H;-S=l2P$(4GmtJ3PKHhFO?p%?EvS>0f=HFAkVkF-K)!1qgzC)G3ldAkdQvt_r5 z5~gL)MdB-AGsvNFGM{xX8n|(7o6Dn=jV(#Wr-TTe*WC&_9j+i_{QP^7LR-D{OrIk z6T9piSxl_SuguFZvFJ%@yFw&ZeWKNYdUsZlbZ!dAXmR;@^d(vN$_#ov?9O-KsQXwl zPL#08^W0W?)XN@x8ICy7RQ)5{kuKYy%Z~;}S>Ii%oPSKJ6R22HDC4mzPJXZH&v6Z_Mku%d?A#8LQ4~5jR@~aP{ZKRvL%=VopIzZ)6*qlp>?e zxvRU#zsfO*X|T>LCc*l2rP?E=L1#)*d#7ivPRDWc3oWjrLsbY-%QU~>r*Q5R*(X=t z0oC@@6b)4ylf@ejJQd#ixOO_wFhWmTM5+$m zrjJb2J_^I75jUEVlZur2cH)%ItlNcv~gB?bQE+Hgn;vPH{q6vvnBOi2N&H zxXgbT=$vzX9m5evFAY6ygI5#?sl(*`g+~T$ay-8kMI}98{cdC*Sb7S2>1BJ5er8t!h1wOjMrIq2ThJgc`FOc)JmEEMx znu~QJc%mqmOS!HgHX{Y*$EweqFQ$uEwMzJT^zX%2BHp;^=N%2UzgdVl?% zo0hi<_Qd^q~`$X#-@Q`)hn8Pwr>Bl#0Lo8Ys3wH zD>z)T@Zww0QJEYXawT1p{JOt8fHVuq?F&db)r-$-!&(umuCo@f{_(>Oo~3p?rW^lP zf=0p;c?tU_HPGmE?rM=ObHP%OuKWxyd6SZ> zv(zwr?0L<3iE*vik@BBV!5ESJQVy-PqT}OQDS%AlSr0#gp*ij7qw_{@7El`f>mCq` z*KAa+VE!`tCziH?5vy*_QeloXwc=G2V1Hze4kV#0SAnaeMft-1Pe zE}^yGrLT(@tY8BmKD~}VR=sw^Wi+b&IQ1e5C~<_H{)#3%o+dn#>Hu^d42|QmXmE1W z(R7vlq1t0;^l{Ly-eV)&Iam|aYFbMB&AE&M6EBI+uU{w*Gy9rre&f|MJ4w zgMUVOfHx_5N9H0$)|2c9%bf67DnG@!TesL~JP=T5aD~O!Fu+E|z7jyf+w7Xd+YUL$ zQIMCI1j=|#qTn`5R(RVMnDu*CIxeoVF!R_aq=@kaC``{!YV)xTJ&V!OGcP%e^=M(y z8*;CO+LXENF{M3}^~rtP9-GT;V#eUM$L4WUMC8;&;WsbP@C~10m!J=GS8w4vF>N1= zajofSDL*;!SUb1cZaW$qZQ(`deAk$32{q`i{?WWoZoM9dzC0a*Nkn)V!6oj>xKd7> zFA70FhR4wEVTy>2hT(^Q*ZV?V*J|)rA#hKw`FKr1q+L-}y~HH|>TCcdj-4#L=5?U7 zcCw&k5pEr~k=K73CVu^w4InL7uzoWBQuJc8Gqw_nh!c*6_%&oM-$_kWE7A<|L$w_{^=`R@0(SXL|Y)pLD*cogzaWkif|=P@yQ&eup)Dy??HZaqQ&&Cf&R0V$Hw3 zs^W{eQU4wf0^4H;vDui+m-v@|81}EYjfC*5xm?sgr9<+G`3C9x_m5^(2z5~nP3a4U z*>E)A-?WeOJ;L_=m(D;A+V?az0Bhf)+_?6cvH~X8WVP?oO#8NwkoNsW#sh0#joRlj zt(6UZfcE*;dKcS11arUk?G|ZYqf}X>B(eSFSC5tbVpfwwr>VPQE(`|v9g?A@Pp}Mt zP(Bw&O&wOdY5O5HB|Zq@J-o#FQ#>T-Pq@J-le}MlI@JVmuf)XG(7$m?m2p9L%mqBY zXIv|FsxvhB>}KWB{sH7sE;Fo0N9BOIx;?w6iW# z{}%;m>q{j}`bK{&&oofgN<|)#K$-ep=xxZrF%gQ4hiLM@JKV{%rquW_ zs=VaaHYdOSDz$O$R)Q|iKyzq7P2?(LpEiP~4BYgWK z4@K%Cfq)lj zbV4LNlCYDP=S2eaq=D)0)=Gl??=0(#})58hN5e8eYI#=cUj0xcG5q%P#rlfxu!{z2mn6l%I7dl_-=zy7y{sMooDsC6qhC7? zw{{Fz(6G@|lAa~O&JN^R{xQ-p5RQygz{^bkT)8#P&uUyFYq>c83b4a8XNN6JW?ZYj z6}IZ8eyzGC@MRdFd)CyToP?F*B`o_ckO(~}`oT~O>L2hREk4c>Xn@JvMkltZq2^)73M}Inj2xG&`-jn2N*aK^`+W_p1XPeozkG9Ud_7P z{AvZrMH$HDX$U{cs8JhHL!?zddas!i(4JY%fMNK%Pl7g*#eIiLH&VQ4QjdXf zp1Sqqyp@Nkuq1C?7?k+G{OgN8f%HKw%~ohmjq`P}(p^28JS7Wnc?ZkH(>GE!Zz}|d zMgd}yX;A(|l?%C7gm$N}nA{2Ho?-tofK2WGxfUq#-{p?~9w}8~?$-6H2IJFO>qc;e z|8BAOi`?-^iN;nKW6OEsyrOGy4@6VHRIuZ1_Hn)6GE*cLB!=zydJlhPkb_K+s1h5H z%kaJSlD14fXG@le;|kD6GyFB^n*hm9^$2DtxOW&^hl4Jqm{|4P>x_RKF9=c|s38*; z%dlzMGWn6QKa8(+g|lR*9oWj1Ed0!8NDg>QtS|t@+|`0m|9QSc;+yvma4Q3Qhs3uJ zur!gu-=hY!Pe#F$MC(-lV(sk&Ysze?qaX432klyA_7a4{?^guvU2UMUzs^Mx!+&p? zuOy%yxNHiL&3|dalz4}xNk~5^VX3=qZbAr_+Ds2gXj_>PhiEz_;WQ-OT86mNOI!yE zk0X2 zd=T4!7(qkWhCgW7=M2R=IYZ&#GY)PIe46{&SEP$Mq;hjxVn2S|TU;C4jxFS#uDZc% zq(2k?aRC6rhET9y?cD8c+}}`0e8}G8HAOum&8__p9#e2ESE5wlGive1!@C!fZWR?M z=XlJ`gDHg}$-D6m@Nf3nfZ`E3zyXTGc?;V)_MR+Iocfsqg|lwdw13=kB-y_C6&Y3- zU;m)HWL63Kf!@%jGMsUxce;&gg5i`M4gU0zJRa8V>on@D!E}Xd>{{2vgabhTe8%() z#`L^Wj$zb0i=Jahkv*t^)up3g3@g?$qTok+^DnItvXB6^<3gzI9!;K`-;1P^osyAk zq%~R#TJfj=XO^K*Jt8a6tEbJHp9y+4PRZ*DbM(RVTg_-A2c1a{UoJdcj5;ve_)`Uv zlzMaSXa4(XS>oSy;nx44Q?wp0mV(nNo+l%P7WAr_)g-9R;|tyN0iGvM)> zn&y0TCXL9UiK4tIJ#DvgtMXe*@>*~V?OeoD?CF9IyWzE${kkaqx+wc~N$@%`33B$J z;KmABT>e`1U4l@0PlR?B;ZMBmAF@}RE_Ct06EaM%==36w{q1zluh{T6j*36Dens1y z-@H^zLpVZXck&PZP6ylT`@H-Qhn7XkW6HkQ_+QU5-L>@lB zvE#NM@Wl`^`CD~6#LGuziZayxNZLAs%eDjw2O|6|;}Wa>`m{hlyG73|o6BVNlD}{? zV}>6uyApV9#;YoE2!tG+xva!XOkg|RS!K3BHIlwqw5^$m2>|Z08Y_QY3)?rh`{$zua^_E`Cg$I z5AF12fu2Kc;U@!;Us)W$B(-~5pLPA$`P=lL#)Li|0qe}}{|O{Y_g@hMRO*;DZGuR? zf#IkS3{wJ{fY0>!pqp|Mpus5OLh)dH>r-=YWE}p|d3I z$`VW3$QEBB7M55d%#SY-EA$c!s^7u@1|uW z!9T@ZI?McrMhSMVGg+G@9Q-SQc%_Ymy9-Amc&~8}-C*2E{A{maBsx>Ga@48*)3acH z^=ow_XMYYl%8zU1-?aH!r`znWB+25_c6Yi>viORRP;BDG=Zuwq(?e4NP!^uSv-vlj z!VUJp&01?Gz9NPBw*+MczEY$AaS|n<^cU~%%8FQ7Q`2Sbp|a!#^)L8~f2*z9hb}4p zQ+vw3kUBMuYP}V$ zKimgaWr9_O8x7{tRE>t>@%CkaR;jI0T`l|Z29_4I%6UrJfKBeURVuUp>^w1hPlb`E z4Fg3hzL&pqkL=cxy)*^CN-roH{*L^-_Ca5Fjo%652&p1dzW>e5>!HPV+r_X{)$mx-G@kJf$s3#?Za)(Ph4Y3o&0`6qq; z;_+bv&ffp%JpT{Fa*kl|Z!gToveeJgLczgT3$nl$s7_N&`T>}LTjoi@*ED!uf$qFY zG?vh$QE4zQ`91dNed`^eD}L0dxu1Uc+}L$9ju4zHasN575J**RB(f+lZ^Dd?ip%^? z6~)*jA0#XMuX8H_9x43Q-aF>MCOZ2{2%|7@m@W6c!48(GNdV2WyCw(4WZ`4?XTfev z2s`L!=a+%rg>@nH_8tcG77opY-bDpD&|8~^UTB~E)bW4nP3t!RYm9(ZWAJ+>z)$ze zUqA_=eVe((Px;!}R(*Q3nFuQfni`jX2em+)C{p{V$Yqj=dn9Fce!H}=xs zgeQX32VG9sd1K;ddqz z^ep)O(7~_o>>T**;F0}5-^hXAR$dzX-sHx?@6N;iU&HUL8=UM4z!UNS;rkcB@7?_W z75wgY_y^WZ6S?UJ{A2ty!-s;db$5E_?}>90?`G5rJ4m9}OVQztBblQje7Gg+{lA4Ru2I6z&^zc8@-y#d{`GWqnWV-8X z|IUBbzh(3L_wPLdNobUI>7O0^k{0z}(8Y?p>_JRbWr_0;?bBD2zgNS1%QSYS8oN>f ziUE}VmmK!XYvee&aYiANaJF5sUk_O1wcu%Y;`V9!^wA6=KI|!#uu)K=^=zUhASkq;C;iF{Q`n>bQ zIV(%G)AC7v#k+!{d(*Z;tB!dsH>za9aITYE&2l;P1oT^VV(ss)&TBci6Nl{4{<|{c zfSgB%`CYcea^Fg4gR_@dvCZyhvoraH&Xlc+BpxVl)64X^*d3Oh2*11?y}9>5hmQSH z^{tY9cw;1K3!aG+Hnlx5m-Klpe|7r+wY}L+b*UdC)b@-zY7*x)0owRRdj-{?{+Z-y z_DfDfiX@BI?IUBR++M-@R_JKyP-M@6Y9EUh&7th^=kBuuox!YxCL{}&YmRiaxo}DC zk9$S2>Ps&c`?CET)Ro!4;ra6p0n1F~c-fbUIk$5IcbMa;KaJo+M^h39zld=+rViun zH)9VkHmfYJ<<)57oT`W8PUWU?9S+F`HeA* z`UIQSS@?d+RN~0|H_6m*?2N70$T4K8>!k;QCWz;Oz&qyiz}w{i2J{8IR~0+(G74Js zOcqw{mj&LYGP8K$@YXW2xS z`gz8`RP?pft?!9Ypf88%50q~aB$L6FwVTtt1dhXQogB~JEdl+&HMWUsZ1X?+ve?cw zWGYgxJC>=tQ-!h}K@-#*KerJD`oZvRUi@3Gc!+iT3>$#9o_z>_5ww259%W$ulTUMC ze%ru$h|@phcldd8p!%La01kXJWKyK~G8Q)v)e7e!^539!ErbwlEK)3gg80~ibm1DD zLrgo~=(0sIwu#f-3Fg}(zZnu) z+^zXX`#J&wvR=d|zxmn^oa=i9iKR1&%jo_rzUm&)uNT~nQ6o{XX|5ZAKayN^TH__< zp+5q^%iA}r9e%?ThB)cc<$Ofs6UuxyRa18~V$+shcZHeStkubF=+@MEKauHIiWR-u;_V@dG*J-N=)8k-&%}chwWd2fD;;e^FOoWi5(Q$6GsIXgPQoIe$;f2&S=Wd>PaLCROBUXFCT6CVNkD;Z zwvDvet+BJQ68@$~w19sIK~d14r$AMkl;*OGPg4|vI!11uQ+3y94xj2Fp|IyIqlntR z^;!~=v|=H+YmNo7^t{AGWSSGyX5X*`vTe-4&eS_W;K?^YsoG{Qv0LAIVFw|W1!DTz zx$2A4&~r^3iIGA3pz0{VNlXO)vMR1IIjV1!P)OuvwRzx_(BR89T}0qe9*>%1B{B*c z!puTwQUPCdq>LHT;$2oG%t?Z~W38UzFL#>QnxWnn`pcPB$n{ERZ~h0}QW9a1Oa=o( z2mQj|xx-OZ24-kxAw}u?KeA~mH7c|8XlQQqGZ9du4`}uPZnIT)ToKNTC9*U}9^O~N zxS%0XQ^cmthJ&tQm;MPGK&x?BFSQhstZuz`RGz;d7_4D)6A=Hcze8p}3GAbnQhuq* zFH!kWs@Mi_6>m9J0Zw6B6`hH_Vmo%5&SoopAk5;3)1~H_9pwy0G&Di^BMs2uW2Uoy zNlsUL+toowza#z)|8=9>k47Dvy=+{XKo_591o{$x5v$ToXKNn z79`hvl!G*nd_E7((%(OI`i0|)fwq_ou5e4^O?U`todN=Jk0`fjeP2oQuEeb`+h^xO z2;e5K^}7Eu$cwGpt#``jrUFuIoewu#-MT!d2&58Lq2VhJVJwML_MTW{wEQ6dif>~9 zdbkMEI@p`cc}{N(iv48|Z!lEPT1?11o^CG{esv@ta8*b3&Me3lbv-6XCuS?d~c-<)+ zaiyL=-XQ&PxWfUCk5Ktdks&oGOK3pcRBEA32a+3-6u$dCDw_JFQ0w1-Bk6tIwj+P$ z9^lW|eH6?FG+9$qlHYq|CL5l{Fi`cqZ^PI@*@;-0H?+!~5M*Ib#|Jssv#B4;$ri8A zX6dI3q{I!ZpQfd2;A;#zZKGu{$IHMaCQk9EMt7|Q|MF06E@m6>s`kw@hIq-^0{^b5 z;!BI2BU<9@iuQbFQ;!GUZNsZoCrD}RI@VnvkDv7v<0TilcRULtRTJvY*%gVw1Zj`7 z->x(~da>`}RKXb#=o;680uPlhvoGHRMHB`x!C-eXBee)7G(ya*h3wqOQ-Qj z^UWX)u$(g{Ry{18tkRP0Ls7)_0>AuIE#;XN<{h-K=!@H@V8yNVBR?bhas4N+)^~q) zdi{vcqId@`qv&&zCmc~flF+uVMC0#Ef0I*8`ya%40CN*F&O>V3cD7AFB%1tIU#0|3 zNXf6y|9dp~{l1j6Z4J3lTUuPFt{fvZdo;PHK|A2M3KK^>tI!^`B_`huHOoM_=6YtoCed0Jm ztE#qdBU;6bCY95yBWM@wj)>_Uzbo>u^o0DyY)v)fPn`xc$;JP@L;S~MB6X-fyVF{~ zjN_G&`U<)nC@>7So}y577gyxL_kYLa{%E^*do0rP`*Hu=PEjskmhh#`Ww^SMS^ihp zf1dUpi#Nik_p^4wsKYH>kbCjZU(ymb`q)~3@n>5p4gUxC-7m+NfuPH%Ip2qFX~_6X zXvmkT!?ri#H2lVrEcO5Fy#Dpyc2*!LvgQ-+lq&MOdjmF}x(IiO9Il;t_~QB3W8ch~e?9Zg|6=}iiyD``#x5ij#g~Z$;gcw0D z)xTF6lC7owW_MEo(`#mN-b;*fOZ6Ffr*_a7oO9F;s0=N^Z>O7*lb}Ip_B8(;EeQmH zpwjX4A`5PF{iBqOj%-@6=@qjB!+`bh7vnQMWah3OzU05CmL&^+{T$N&rbY!6idiy( z4{34|_mC|HtlEm+GP-4tV{HBLF6)#UAM2^`leTuht8Sg?qyLN4z&%TiMvuuLMsR2N z@pZ-yz=rd4n<+AVtxW9O$@ZOyKw0X4sDqw?7tI zMbptWaefU9O4D;#hkbaR`H7pXoaQq*xO1794S2T59hjSJ#?10KyN={vq)`p*gVpBg zihYoRI{2szT|#WR+1j&n&G)^FDKKEgN^H$ZOk`*YZ9xmnR6wKT_&_pED71puOM<|5 z(#M=Xw7+bMf7)?DIWd%(){iQ1)tXHIypo}Zm&1}YKc|XiY9>5>y*0N(8lP1UX3b^< z4_M14faByyLt5X`&@}_zoo3p@|LD)h1o z!HYoVH6mNnUo!CfONrPE;R_U&@ZKK9Zy=PVHRS_;@o!ZuK@(MLvheWNU3Hv4V)a2? zp)Yd{MZ5TD_}w>--i(DaF%&P0#pP=?2#nl%yAq2*`bnn#8-n^xTUHV@QQxj%#?m_pG7gajHRDYq?f&}iCkrp#%7jz{YmbX8nSbWx1kI(vzdv0K zX8YRW01-;CH%W_d&(g1Vn(x3v0XqK3&@u7-G6C;CSHq*P1gKeggTvr0?)`{)$Kii> zsr*lp!-nE3?GfjNF<+|BaflqiSP}F4Y9hBYvJcml&#D_tP_D07vw&kj;Bl`+V#On{A{H^)2gRz}t$19R&nQi;(SmJkRjDh@|HW>W zA@ys$2L7$1S)Y(^2~=Z*pDbReND9o&sn`KSQ}NMZix*q(ym%wf3dW5t>Ev4U2}Y(% zZM{;C3g{1E5`VgRE`-d^&905vY2{BW2}+gW(3)VZPtX;$Cyd9K@#wvm;m64el%|DeE1NVZ z7wQmZ1$oZYqI$CM`KzhtNLSAwW3|+Cpk-hrGt~$R*0lJzl3r}unJWEJS=GS`;ae~H zrLOdAuV*BlJAFNKw5cRw^9 z)Rsx9%xdh>*_Fk5%7~9`i}`_!p1WG2n+ZcG+yZ$A#}gv@$83@A6?_EwLOG|8sSi+~ za&!+pnEo}spZzs)9yp-Y8LcmEZUGkOmuWqL?X`AjZ>ayd6|nFrqYC-Ezn-lF_Wp2} zYSS;W?1PGK{<-V>TFFMKZ#KI#3UwvIt28jK(OTx%o|j;2(93-uho?JsD|^xEvMde8Yhcm1d!&wugPA2Qg1$KNC= zyJM7)*2r$Fg#L7;`!CY@_v`0geoTI2v)z}&um@kqal#nG3x7Eor;ow@l|>)fcYo!V zKB8!1!oQ~NLKNDhLMN$E6ma~1d#O6NQT`sPYaBH&KRZ>mo%E&>75AK|b-1Urpftuy z7TBtNjay_v%V0__S)XH;lYe*43pKIhJyw{K!)t$23;*Bw?$&J6uPOTeSN@zmzG`b} z>bL=oz|OwjF39HWUs7x!3kVN1)4P=n?~e20+qLStx#a}#j-zy5XgMmX@sb780A-Tq zWC4YNBy+6>aT-GsV+%&+wdGJOgshL63aCQ(O3tKA&8hS!yt+%bGLtf^wK8>7?kvXW z=WO~0Uzo-uDalVqwER%kMvAcdbz;z?C(QfLFH%pKa2=-*Nr!4Als-muN)}(!_ZcFh zlv2&VH)pp=c}sh5N|R5pe(?>-fn5L8#3j`4)@Vc>mHrEy@9P);>O+m@)3LuCY7pq; z{DYy_f5}T;`<~9YoOz0#TlP=AD7D4nGskx9Ka&~ljss>4^TKPKlaAp>ki>}kLg%|kJoziYaHsO4D33L%pYZBxWT{af!roo3ouXzEnpOB z!O)bBT@?TMkLv$`rhHNT<|EJekJ0!uTIQsm84AQ z1g+aD6QK8>{Uyo!)AUQ1LDLcR50P@67>)eiGIz;nXmV z6#_ZyhU|2pC&==HcZ@85@vGWA|C{e%l}Q#p5kVwAT0>zyHAVXY1O)uPPr6+VB1&XB zm@b-Ld@Gv4u`XAKa>a6Uz52vJxxS%XJ5nJB@Q>LPAY-aMFxrcMuXU5l9}lAbxg0aV zCH{a@+mi08ovs&2Z#N|uJ>IuOMBwMja$>2BB3S#*E|c;uX%$VJhoxk(DVR~i<@4wX z+vqkc#tw)qviPaqk%51W(bpeE4AeipfN5^T z+Av7&I7qt1PsKiD{3$=+vtt3PdlqG;sBxAz86CITp}5`oNw4SS8!R?@wIYxvzdG! zpj*<0+mxEQPzP7pu_yV{O$3ui8sUXzr0rKKRCvtWM#6934+;O|Z$`p9_ktKdmTOst zgeR;_6Ju+Jgf}E1#%V6sAIKGP^QYXbLkG-yhq8_)E2L2;=4Z>zX8N05UL)%CM1hTd z!=D_1S2$+HD8l?mBB*)lXk$wLySegbru+lSB>!OJ`bm@|&S|2%mmOTmSa0;NZx*`) z%*{op%EO$aw?E?hpYm4eW4Mck%+EcknMEe3{Y!!-Aj?44E zs+Y;)b8QxkR$o`CX$LE#W;JEvL_}?=@jUw9mYV@3(%*mu$Et@~dZfRFE^GuuCW9uG z^&U({9(nIKDr2%0iNHty3Z4dRcKvi3wE7fl(ASGZO*H7YP*ENtnkwOw90x~8*X580W33RDNs&;dkb&0m{=zpxFbV=}d`Z}r~@2dY- zIGH@*KdHVkr}`^$tN-wr0HOm_e|=DW4b|^;6@#{>%6fm9B#wIjJIjn8a{u0UW_N$R zycW{ke?w37$zxn!+ge3IsPRO29zQB_sya8vI%P8Ks*{A(8nn+ zXc+ZK=8{xz4td)8c@RJApOQ467e6ap7P1-Ab@Z`Cvm4ICV%=g45*op*4LQa9ZfQRg#^!0 zIR4A>XRysH8oEjwI)CzK;%*O^gg~xHD%)I35+n0${58JTdL>VwOt*~mTbbXL7^?sM zG_g{73WPE=S@@@8SU4zCUX;q#^upx*?|t0o7bu%)evfUz`|89kp$=zE)pUO+KQ4Vf z8-3J)(o|2zBO_~mZsy^E{qLhRN|IOD(kyXue%iRt7Za_h0Ftffcq|c{$Ad$qsf39* zV0>bd5aQVVD-r8#+u!8ZU6qYa^M9|x9TEj-(duF13ejROVH>B&Wx-EqF)57}YFvO8 z&7RQWc-nA*=GU9igJab#N2W2O*^BSiTcSa1*7v*K3z6djha5Kz13AVkDmCq)29V<< z%e|MPf;2^8z79F;(ck(0``9<1Lxph;H+3C*qrwDAE{#Biae*xb6;v39!g?r`3S+QC zg%Rw8-(9-K3Ac=~^?bGOAo(wYXKnhB-hWVBUZ_Q(>chE&e#$v1fDYo}^VEPd|Jxx& zg?I`GJ%AeUro)je{8-@liy=7rzg36+Z&&Qu>WQY=rwfBc4$=yj+BE<`;%w#tcxR&f zgCo!=ia&hEDBB?m4CwT_#1!GmprIm&opqeATsk!iS6Zfu>2U@)ddb&2yeaA)r;B7deXj(L&!!KG8O2d`e^#^7lWCFJF$2XB%M-borfL$Jiz ztrB{q!mt;4cy{@*{zM&Mk3I>3uWk*DD(*f&;576b)6mEMXW(!0H|}ZRUsUD5-z4x) zrMb-`v%sI(-BFhk_%**#K7;?n&A|WJS90JFcuM{4>$2f(CY;p0S@4~CHLx8c*kT^g zkJ)W7Z)%-Jj$t@rmw>TaDw_>k;ITrFEX!2u0<-|T>6+Sf$pBO&ir6tj9fb=6FNVBDYL+w^Fc^aYZv57^Qu_^ilPugy z)CRxj7{k>(r+upw#$RhtzdB41XEkJT02K6pt%lHA_r~AqOPsms&N7uX%a!#D-!}uzw-9c@05n5JF)- zrQyGLwDr~W!kpr|zx*GyZ|B>t!(%x0uaCi$9t)6ng?=zBA@l{LqKvX+Jk)<~O*SQ~ zZ_o#vGxgPs#*~e{!TQP=#AWuy|WN;>rdW{vBf)9%3|^H#*r#vEe<_MN-t)4mt) z$T4U!2f?ZaE(A8)qs*W+Bvqgm$d>gbvt{j>HW(kyGiKtqsNKwHSADJ-tx*kV65OY% z^R0sMBvd;j0aJm#4Sqs)s_gX=k|;6hn*8@R$fRW1REmAT_;o;|>^_`kLj4^>iNF%B z240|9Q;6Q;qCAL2s1XcPsBUR>#^mBf{Z%sHBbS;)KWWeTm!DQ*pg}$ybQJiTG3~V6 zpEm8#%g{Re@ht2!xBl^q?K8hx<*=YaeXCTb#|Qzl?KAJ>prY~j+2Efi{HqcE)wszW z&;{69YC?20nP!G^4m<)wt76M*{9_vb#o*_LbJbJO!)Z=rN-xKtA_?q`YSkovs`wIY ztOhR6k-Y;Dl3GyVl#$I(W#e^*q_UNflRsBHxb@3^`%~1bnvQ7s5hx}>e?F28bp1TK zvX{EDd(f2{L>(dfXO|!0?^oa&jmx%T9izdIgNCSF!PN94Zaukqi^bGY!uk8 zGO%_1X*>Qak>9WPde+bvx%0nB2*~8n7n0}U&Hv8sUjBN4w$dA%|vWfL;MdPlm zAimP)!zLp?mkXz3TN$uvj5j#Ipi8|;2SuG--l*YVQSHKJEx8}QSaU>E`eMYDf^mi6PG3ZN9Ea)EQB=87t^AyH3}EGxS4 z2^d_bwJBh5ZkiP^xMjhYQifnWYmWy1D5}i1w}3xuTl<8zSf_`m+9qevP7B9G@lU1x zC93b`(m#3e&)v8CcKrrQRR}21g&_&7E6e))-6y}0yG8pAr_o>k_(X|w00`Y%tM$_- z|_1fPzHPF-X+l3d#~hG)UBrb~GwV6lRQ~7!@G`K}Jx60i~mRfCwmVxK@k{r~@c7@||;Ez3%GjS6$s<(fRm;s!mr|)w}P$yPUhcxm@VQ z*+t7-3mv=J!U!ymG;3{I=)&uTlfmoOg|8)WI7L-%LVu?0Nsn_%4!c+0ASVY%Bm^FB%mn~-VLGyRCldxS|MHd(goJVuO67*PqzNB|M^@txeB>G)F|`%^@R|Jq;>m8(4Z1CsD|LG86#0xTlhn)2x;O7J zd{6NtY>MdFGjfxeHXx{Xsc4zUf$+uXCS~!%XZ8p9QL3WLcBOP;Cl(U)`kD%G7qTq& zr7&ZoVznoQ%CH4o$Uo)%o0cAbpKtvvO_X&QfiDQ&fwW=dFTcJD zODL){ohR~sSL6Lk`F@C{@IRu!9QzoqZ?Fv!JiK!m(Y?Z=$^D4|ZkAq8b=KGpuJ^|E zl&9hh%Njp{3aE^9E4NzNqX|Heplug!n&l}-__P8(ts)-x=SYTw@HW6PNTLh2kzsbkM;dPrAXZNu_zMjDEqaPN*5k(_^0z}iRZ$%8xHS9VS~V;6)aU{qsD*aZEVE`)3k{u-;}+UBudfcym$${Z z_xk#Ncd`xFa9ZnY)(hq_rMkYpCAa#nud~U4{i%4;S!C8e?H$v%%_|JDsK1D%vlEut zGa%mfTxNnF44j$HQk&skY7TtpIc5APp<)9TFn+2@dykMzv`PSkS4dqepf30m&^Z%BeWX5EQYi`z9@#Yp1xF_ z6PZ2r9d$m&iMqZqJBqq~{uaLnEJ1{|lm&xe<@68#?e;`-Zi=VU?&4eLpAu zDzEr9k_kYbwrC~5H!Z+TuR%b{I!E1<6KR9G_Dy@sO$Bk*H;qBMa?5L&pMZN60)V{^ zb46VOdM8eVJwrA}s!%5KlX1CQ$6F^qYnC_lt=uM*$j<_oe0Sonb1DG}Z5$65d_!-j z$|>iV6^wPvGtNhv@Yi*;o4xT@M@ZZQf7P+^O7v9$LqpOLhGj#{z4?-7;w5Wixx3}! ze-L>!ih*miOF?8@6r`0TkufX{At%^#m_^_1cg2$?uD-;qD}W*mzO ze{KstyX8u-Mvv>kzg>HAq$%LDSvJ&J2qo`}&-R|-kkH9 zG`_la3d=Lvb4!>>p1))iaO5?peEIoPn6NwK`R{z51XHS|+ zxtfUIIH4QyBcu52#5WYGTFoDZ6(AcZ2}3xmje0;5AhQc)etKF1zQ)_rl%+8b(kdqd zB(4NDMYy+z+|G7KalueP`ALx)!R|%>%z45|Y%_nf_aHtdL5*KZbX@qf!Z?7x?vg$6 z6QR!u*q5S)XBbLp5GIQ<163|fECXEqu$aBkkv<&mOEwE2a&+c5V6c|Y5NDm(Jc_fH zMse0s>*+T!7UHbx7WA#|5(4Yw^3_aE=2MHqrCm-67nTRYJ;fNTP-#8Ddgyg#DI^SM zlF(C)AMnpmnbFxO^T^Lm z228~RQBYy8$C7ZM6Dn+NV8eKPQ0i#X#Rq={gYH7x+JziOXPev5{Ib*q6IRgXCN=4A zL)86$0~2B_e@>Y2+5TX_G+@FCnhh=xaK^{7MxVmL115YzUGb#X6)W!S-YuMN=bXKyk@jL+&%#$&{V%2o#T#3cr@P9HyCBFn(aE%d} zCXki~u;u_V14b)4Qoy{;gam>2QpUk#qdBrjoYi^Vd&q!e%x)mHHPMYW^ z=)i@4YU^NT9#^)Vozb3SMSATS$k;-_0wc}k%asPUBHcogo$br%nDvyPMzGhr*^#@2 zMQJvNoBc)vrXmqvj z$d~nx#LQjdpOy;#?y2xkvFJljs>o`@K4Qhs#fVk52e(=b;x86y0Hcnwz&g9mHsB=9 z9gGDQlN2cO2nY+)kNve7Zfj3(^hd>Ah=NSVqeRlg z^3br9RKj{x-prQwk_Igw1*D=mxS7GXxLj2tkpWPzn1ay#FlLKjcg@@>a2;Dp)bf%a_Ke?w4q|CM5o{RIbYk2!yZD>|qv_A_6h@Wp&r z%q!+xA^-GVU-^7j5)+K;do=MKtRyWT`7|stFnN%WG^)w4sL@#yjh$fJ<*-vVW)a^= zu#eaFT6XQBWU`z&ZCk~-*F~f@>iH&mH}6QlEPiI6wc{77yO9#tDnZ7;??shbucCfV+BHt4In|M z7VSDz{uf4GU>!LSK+t6ev!7Qi%4QXO1j9Z1)y08D^YF4vo_mwD$tQTRwa(EJHv_cc z8)Zn8GdCD%wht*;t^_$aH;3tX_-U7D0|UtK>?wnASM1kolHn3qq#nst(Yv?qF^eA+ zy?ZAncx)m%ASOZ>vL!kjsN|M&#dt z9}?1Ysgz3VA^cq4-I-<-%Q1pMX5$JdK@gaMFxK#C^zfixzQ8=tdvnSHU6$kg8yOR; zFHzT!S-UtA2;RTTJndo)3C7?|AZQU|1L6x^z+OrP4Wh>}{<~6g0#s0d$B2Ezgp85D zqr(=Coc-xI_O1RE`9~Szs>D(boL5-0U$#{fyBcsbpt+p^0PR&RQ;y6mfwTAo$);9! zNBxV{YbAkuji%|$g(*Tj#KB$>%_t}2N@gz2#gUmyQzcVs<2=b+n#borRWaL0y2;s} zE9}qwG1GYF@`y~O&+O0gcYI!t&(@U(@+S74b@EJRBgqMEBss~^C;9rM04E&Xblie0 zEKWQ45_Fg%t>MU|U{{rC#j#3`6S6dTQ~r{lnX&X4?!aaP>*P2!?{nS}iqn##>b%S~ zwwa$pDr1TFV2DvNmiTh~AQ?-1L4H8-$Amn-BtI}?>ENQ@qWg!f&7SxT?uIO(;aDK{ zG(-cbY8tF_rZM(|7ZKg>(BRmqnHu~Q4oXQD)sz5=yl<#G-cf7u+y0`oxb9jIy%~E4 z!)#DL4@O%4T+?UB2C8Kg?lk)urHtId{9WrdhWLqJYTezJ7u8l}20{lwdCx>v0}X`X zHD5?KifRl=>+t|a4n0n;XIYjbMa%gOboCi;i8e3AL2Gl@6(#D5)4i^sqTveYLV;5d zg&QHvY;>i}+U<6;Lg!KrsN5AAyJhu#SxK$*-+i3!xc)_aNGTtpRbReC^`Yn->MYk* z|XO4?FtTqz~2j@DB81qCO-CSw&aW2#?fYActaxV`K z1M|G1emrjhdVum`naYqyVAzZzhn8+#W!?I3+(K7v$0_&$D~$>sKAAzmLwf`=Hc*x1 zh@vMQX|AGC=Z9?ac?*llM9*_9UY@RKbLyWh|45(|@2&FQu)nX*{(%ntzE;@WL%+vF z_goN4^gQL!GeR{jbCuAh+9_AwDjFkN$C7LybD>Cf2!Yaq+S(}b3!F-lgX)fSTv!o3 zKwtj&`t|FyLf9If7^qWOLw$UWQzfNvJi6C4W6WJD(iM^UZAoE zLzGfIiTwcHE`*~f6J4n$`q7`G6Ak@B$y9CMpn`%J>wz8%-bUR3>%w~BaW%*>(Z`gE zxRW1Z(bxuqb;Jr~E#MwOu0L@=$5^A~=S*u76G0g<3_(=P#-u=^58^n3dEKqxZMKQ9 z*$DXft2J|!*;bg7#Cd=XN&6u;YCrT=_JdNf zPpUlSh<${rpH2=$LgJ%17EPX-_lkT*5KE4rH;$Y*r6>^8lE2TitxTopV~kh#6HPF6 zm+IeOgiLM9+uPHoQye*sybYL5ZU<$`$61|dz_EWIQlpQSA8J!Xn|gRJG(^_p z-D!wOXERK~PcoKQl;MFyeHtuW&{_PQZHVw5QA31Jiy9&Y_6IRU_>#6E!uqb>To7wV zaf3GW$}0}7DGtH;Lb5as=rUXj)lG(*PYZ?QRC9G!j-D${y)sK|c?Nk?i`PYiC5V>c zHD8NCFjoekS~rO$Y7eLyN4SdE1J?b#U^w&m1>9wz)d@JzaF7gc_VbH>Fl zUWyqD8Xr)GgiEej--Z*!SA7piptxa0KPda?X-=jKAArGS3v=2Jqxfc;{094>;jhV! zhyLF?Miys0?E4l~0u2w62qHfa=~il+2fr&jEc6q|cKtt7GYYKwn-T~Rvk2;Uk0*sA zzmiQ5J@UU|d6c>j2E1~Lf$1b1mcNq7s-Fb?|GDz_&32A_PYzz20BCQQmI)w_z>?%6 zC^5J+8<0q1i~Gm`RPU^|x;;qx_6JXHooBEJU|xx_Am+gR@^WGt#>@dhKpnO~g>WR~ zOM_$LIEYGeMLA~-O5A=4aP}B6kgX>l;83HQ9HNtIynHrj>r~?t!@ohhfWO7vKZ+I~ zghDl6%TB4 z9!9`iIohm){(Rp$wK!50ZWU!rf`jj-<6;nhC}sF$(3p~0sc|q2KBNE86POSxaoH>Y zrXS`nrkTl1i*+YxwV45H&RvPS8%Ok$tf+)$%=Ukb}KNf&1(EzY4IzPYH=`y zrwSkYim32$I3!o$Bh-Z>lV2FsA<%e9Rd}a~>8S8?yi~YDzCXi-W6tm8^sA+yMY$I3 z%Jt&Arky{3|5d*E^9SFrGAfv9asFNEyd3AhPgCd6g{^-3r#i=MquqerwPa!_nsxE` zef%Dg?H!&!-=!7O8+QK|%|s)uiYN(HKaU)hFR|ehf=-`SWX;l7O2sW8#c`kw1UAx}lwa0X2nW_$;a`-WM^e z;)M6ik&O2o+Qxj4HQByp0d9F5-qUKYZmA?;^j^p}`R~VxW5%W#s>KTL1^H{=jOp`7 zVXBB^1*j`w0Mh7zFI_-gRH#fHmliZBIxFi2vr4Pac55#?zMm}rV(oX-y+c8rnz)Vy zR@3p$rzFk4D2MG>PVC8@e}P_c5K&0OfTfLCgKGZ@ztQgfis&cLaM8Va)u0wXU>k?^ z2wE03qe$Z&YwTVEZo@wohJ6qF=|bK@RHq$DRU|3dm;y6pQ{@Ei8MIsVshwJcX- z2*S7|HcRG`=@ixK-Ox$|(;bB zn3+{sl%MQAp>6j-^tH6@UTCeq!#ie&d=r@QhM3))>uI(iX4lqW#Os({HHM=Ndy_~r z;&2_WHBYSBaz7>(vx_cnoX~zRz?-QlmWH$AzaxUe_+2575&H-epc0>@fw>%!&4FXz z>di2^n~Azp6Y0JpnkO7uZ@v95+uD9staKRV964@HWk5Ft*0(aD1w-NU9nm}l^M=k= z!My2my|zYRn2V)N_K=gsI3aGvKPcR+6!)@mvzPf>C^G?n(1U%h{h26`j_eU9ePrC3C;9oUdd!HwVt<7KX`)b^a zl*r*{kcaoC?af>BdwwR2Ca(q%bhlqNNdGK&g4OaIAh6!-C}s|HI>jO))BWVcE3T`nsx$ zxPOrK>vKB2@7?o|-uGsAruUKhkVA4qw0tTG_bq3q7q02aEzyBa!wD!B;s+5CVD8rZ zFkPNbhXcYxBq9DNiyV?ez1l)xnc0Hx_MS#kBFXQ0{Hm5rR%yuaE24%3d!VRivP$#o zbeSv7Z^ZB4$EW#~%gt1dADxRbmFQQzoKgkNjsdkwmfv2IA%HADgz2oe?r_PMedTgH z#qS4vt3(Q?08K8De+QrE`F_fdM0CpFK+w&T_HSccry=M2Ur5t0m6#Qgyo$#-%!K zWWtEZSGX@ir^=71zuJ3*_WI?DaMh4vju2mzt%Yuo1;d1Znk^aQkVxCQ`nT$lEo8&@ zh9mLErsFzf&#KJ8Vy_#|4_q&hmXy()?SPBjaKs? z6INV+gJ#8Ch!7N;Vn^}YTVNi$uGOq;e-Uo=l={)ri9brtzoSR^^RL-H#r$K7myRwT zNMwPo9$V1L{3rBJRP#^&Yr=|A2O*u{5MhJtFb#ZmOU%SsJR8J+A`3bA+AY5)UFFXd z7YS1!O?Cn-w_SY)7-Q+UGZ|lB1AoKYn$RM9)}DmE6q9$oNi+E&I7@3hvnu_^Gs4K^ ziobUg{p9ZPRId5^U7NqL;2Oo>t8Y;w!^$RqkHfaSH77Kw>PN|ztMYXsnJfN+_SILe zsz-V3kfjvy(uNQ}vD*;lTeY`flq`>xUqRqYqEAm*5U?^G3!)2FN&yA>wGYcGx()}u zilX0*SKr-`_+9eFQas#uu{<1IEKIXThBY3(vEk6{S;u97k+#N~^KE91*49Ol1}70m{#~+$l+v7a>}JTzh2gGF578!*N^; z>|WRGSpF$r+fL8jXit*$sC@<#QmQ(jLU1pprsW2EEgJW_X3auS*|&bb!!Uo=Oj5s3 z{M+8&YrG0xDFft58%%4gMBM-9i{0Oxztpn)1aVs8PiP zLA@U+Qq;@P(9C=Ftyy<{aoy)FN-~!BeOZ+7vDVR0DYSm8 z`2&n)x*YjX+O%}idCTI^hpx+*7SOv%I*ZHx!OOc=88a>z^WLmY zig->5a&MUrtg9e?YpGZvljAa69ft4`m;1`bL*sm51ce|VvCHO?QO!k29tleUa?9TC9E6S zx(IoXr{MKY!uu8D{Yo+x2YPK9w}PEfkHSr{!CnVGE1%o}Q}VdItsMJVEI6^H@Vs$r z;~(Z@@Z4VEFNHTmm6pSTQS=$dwUB6|lMhfFlzG6^;n>lJUf`X`>0Dy4m7LRoU3_We z*RaiXq|fc&b#L+-f+bC?s}^kDYQ6OcTp8KU;)XGY%l>{>$8Bg4v+>Dw`RK2Esd;1q zpCf;^x6$m0j!=#74mG|+9ZI|(f(HQ~VS9Ejq4wmexuIHfK(BUxxeWy9NPfttT)q=2 zEWcS7;sQNMT2(IN!dEUC#(sB$9(xtqSy;;+)?=S^HEf{_uaWbO60$y@A7ZA1_&Es` zBAJ>hYW!cS@#m8NbIAYjL=fhK{5@&HitLFG$k))C@XExs*PU&ZS6~*QkOjKb%{xOk(zdXKBTstfOp9yW;sS` zLQpfAA8xfyzOZZ44}0ggIm}+9rDV1GS7=G{WeZP@ zw8bCD!bsnP_?FBCNtO}`rgHee{m9|NaxSeM-egoQ68~7N#&@k@)8t5>Z!OKP3+IAe zJ3ge@b@eE)>sh0cEmUi-i_QEg>$LuTFA6&HAFiSm;1%D}W|SSu0){pnG$&pQqU$h( zPLkNH^4cW6H*leY@a1m8(-07B3`iJnNH~%JcLO#ZBK@L^ebhK54KNQVFkGmJO`IE6 z{D<7K9fThoB|N5o6b%@eYR43SBRB=%gG!q>f_MmKvWz!`!GL^C&UV0RWhPR3O2TUxVz>F%&x&M+@m~p{6YktcZcM{8qX`i2zJ!{{- z)my4ZX1|1MvEkr{4QPMD{J)ytnvOddUta{%@;}uhJM^vj0^;w>7N!no{-(b;(e#OPpEP3KO=6 z^Bk=dcmr)jLvnc_l8op=!yw%C-*?D^H{#&&U@V2=&hrDE>qnNwT({+fV8=DA z94!xKtcl%@gX@B25)7^5`lbIhLBuPF1_?%k1hZWZeU!uRWzt%_#z|`kimKWlUzMxL z+EY(fNyZni$y{}|4!fQUnfKxdM!_LOg#3e|2+ZAKnC(N0` zNo$;Nrb@7(oSG^4Gsqp6ec~yEx%{#ZsKz@rfn3O*^gC8VLlJ)Y&h0{`cX2S1$u-f5 zb8Nj;<6)$m)ExA?HTG}mXu6U(+++v7>4E)=*&a3z5sXqJ%`b)AsXbhiJHd0`0Z?zV=bp;g}u zEShg?)ur)XLF(zo}O9#Yh{U$+c0 z%S~;+PScVyYO=2@WYeE-j(@9aq4x4 zkpnR2SgTxmV1ui0BJs)h#NfH$MsUCl^$!V2Hd&935;yE1acF4D+jqB>Z<%!?E+9LA z1;ruj!lxWf`e5LK*ofI-U!VBAA1C2?_c!d}8hxbCUHl@;mkLooagXMxtFC}j z{_b+_+TG`Z=!Ly;p>;>}q989?go|qVI$4~D)|`hNO66Rm=KlNnW)3uK?r?k@i~Kj5 z`}cL>+IPfnL=*!b>Xq3Bqpdn3FgQKGaLFf{6z9#t2xs1{$#D7Q7~xl!d5ln2mG$s> z<{>F#ligqRB2w!|IN5}uCiDMBC?yjWTl(fV1 zYxr1?ZtM#f-Kx9v=%!qT(Y5dzopJtNDl-q(Jb$kG5jFnhnL5ZdYlEoZ@AMO9Tj4lXUH964A$AJ+iZ8oW5EKUk-3Gtcuj7(zbT5UeQ<4>AT! zTF@FZKoJl^ffp+g!HbQ~-kWg(S<&xfMZaYF&u(*scQN~SeFB3w>|noc@(mC>cP09D ze_N}W@dp%5TE%y0X52ai%y`X^q)V;$xn}Ou`YVO{WjlYdl14;&{+)L1Y(LNB-;HH& zC~$%h9;REoW9{kRbyo5ni}{{mYMm$Z>?&*y>#uy1G4>=k%CkGveqN<*pR`+EP4|u) zGoP5MC3>)y{|Uay*}=k<_FFs~0>>@lxKA=AIVd78~a=HTcWQR`#B9p~RogLdHj z7Lev1{#{#e7X7<=F4LXn->sv9Nc8VS1bzjZ6C&_y99$yMwuB(Da?#Nt2jX)1b(Doj zkzFHR1S}S@T_CHp#pC7f{YyP%y6011m5Ff(V=m5@`9EWwX+`fxD35zFZ)KAiIJ;B=e(xWQL(+1h>_OfaIh9D>P@ z>nbb{?;s}--v6R&hc_u6yampB*CoiW5^9Ux2&5an+F!U1>8l+$S*EZP4(2J0pQS`! zP1d*7VRRY}oAq{S8mfx)sUPe1*tF%Nj%s~MT5D4Ot=sdCWfq8vQMdorH_m@EYBW#3 z4K<;*-v+In#BYO1`Px`$vgwU<*@myQ#iH2PTb_VuJogqY8e5h_G~RfDhiFvRW#A06 zEL7Iz<5Ag13M=|%`1)tIU#9&rosp;gw9R%U?hFX>sI;qyP6NH@RQ$7dE>%CT6k$m! zEB_3U#8mvV;NZIL;Fr-^f@hxGCHv^_nBiLxznLyFVUx8NUL7#_0fE72t|rc2)E(PA zgiGD!jvYfXVVud`F|O}knZx<8hYkK%(F(0WS3U+dIVz&r5sFp93MZ&ix;d8tlGAn52FSD+_C*C28U*2y82JfK!yue^be%|Oy zI0H~a)=->j*C(a?ye+3C87#y+M1p^Q-b-W>@BF;$gohfRpV$5hH9X8&G(WEsjA`sY znumi5ybp!Ku0eiY2y}6zBB?(jQopDA!CnbJAYZus6bc#@l(IfN)hzNUZB!_#ep8&t ziQ|B9R_(+kRl6XlZg#-^5;ZBmMxSo*@5AjUuBeJ47;37q*pOO`==hMqo3~;?=Fu5G zALnUtM18S8M_i&^c*)NT4BkQcd4a)>{JdK)(oB9M&e9sv-YE*qSGp8)4BmHfQpC4Lf&G<&&Zu!Otvb%tK+a(kMr=JuIKhTf~1ISXy@ z$wTp|Vurt;?7!Z+>-82VT=2n>pLccR^Ye}Xe@lK|Q(^SR=jUB1ibw~8b$;GWTpxb< zd1sZl^7Gcc?at48XSyRluc@R6hCM8yG`)#Qc~$>RNXnZ(n8MUADG&W&AaupFOkzUZd7`gW?B?Mn8uRlYCvQkWPGzdH@XKlFM%{Ljw7@CTmZF?=J8+UkTPQ|!*t6Z~e2YrAkKeTY8&!&m z-{e;b^3@p!7xER2-*mqm63{1plc8?Y)bln5Q_mQ`ncc@M-cpa>aQ{ijmoly&bADd8 z=@>s=2uo~7#czN@CeO?JtO8to7nbp-Jh>$?kaO+pno|$Do8e>P6Jy6|cI^rS$9gj8 z!LDkxUU{6EKNYm~ZXz!_^7F2x?Ur8rCWZXGIsbGJzC4C_kvZ72(IY=E7Qgwhzm@~u znR!)F(wCCM#@LhGsQAt0_Vc3go6eW&_zfgco_x4~AaZ)SdiTGo=e8IPIIM@R(bIZ9 z%oywaQ$42DD1~l3);!B*fN7t^S&s=JC4Y8cd}j_+4i_GL-#=M=C*wT6SwjAv#CI|) zMMO5o!6hOS<2$=vLRs0E_|EIY^ZKs@Glr9Pyo+0bJIN zi0|ApIJNlBiNl1r{c!LgZd}r(SA3^8^1F=oxlxsU-y;oGmU?{0KR>TO6h?HJ?dbRp z+I=UF?`*sf3T`^b2W_{39~zsVclm5BHuwAo#O9S%T5NVYS>@+VJIO`iTZh^2vg3&9~A%T;TQk;G zl0UYArxWU*pp6#VWbKAAcm#re3{oaI0zpG+8EnG#QYnOjBocHjpY?xWx^X zCsSaE{YP4DhE0fD{fa~UtvCpbDK3L878z3Z{hTgljo}Cntx00Q#m9$|a0=6*4Z$Me zkAVjMNE#nHxi}ghV!$BEG1d|IA{}l){ohgk>@pzAE-}N^K8wbW(jU6qLB?;2k4b-r zxcJeT0n;L}j>VtT8M3wHNdFN><6~-luyGjX2sX4aex&Lr*dD5J>thqu3YI^3RpLkE zO!1?ix?3^FS*>B6Ipa&m+VQ1gwAxz!jT*zE)PqfRreKqr z->?@x=FtP>Ysg)=?cYH|-2jb&Pedj2qMYn+WglWG3)1suQ>xYS*A=Vu2iacHVygTyL zf085eG+8nN8W(vQ3S%0&=1Lq)p$TZC%heTEcwUh#@-%}Mm|x_{DwlVt$HDXtzLBQ^ zlxBcwN>ghGG29(>l9-dKSg!T%2XP=&QKN!R2svd>xfLstVW+;YkPk{at}6+>UA(-$ zxb7?P!GBLE=~~Zj5f{XDi&)krJ|Ly+r)PbFQtAniyoSCJ(a_YR5KR)A8Vb9X^N)j( z_9*9JMrf>G#D_Hrp{aakGx&z4tiBNEV&Hn4FxcN<%OSpUb@P^3y@p$XC&Z_EG1W!I zr_z$M?76de+#3+bX|d|MdH0(*?@{fPWuRac{{1D| zD{IpO2FjG~9$uNk$4d?}k5S>{+y}(PplW>LyP9%9bo?qBx&q@cQ#tgmb>Q)uLwdFQ zx>OOM-B&oN!ZfNvqj=kSL!X!-sr9f#vXK3ZGC4%D{`!a>d**l@9~gLXbo?~XrgZZd zzX?c|`o=snMa+)r_vZQkR;?d+ZEWU%^#f1KQGX;k>f2U-)W097X~(ZB&KG3wG8|mU z9vnpUns}KaJJ4|%t=Z*Ppzd>caCDwQ%yxs$fczZ1IB8*0zPf*Bult+aIujZw@_+4t zX8C9iZp|>$_ZLOqGSb%^-|9aR^a0JW1kLfSQ(2!B+7wv+b)ar5i19llk{@PXk8pL1I40%2EfS%xU(e1)|_5wY@m%>o8K0nH1f=!ajntFhF zzRhB)d364j{N926Db_*~bKybod&akp1n04SX%}+fPOD$)NCo5(-#X|V5upd;;1Z!W zOp4W=%lah`=e<~jY4)iM#cW2VoOH5Cqq6CZ{_^~VIGCUB75QpOyUQ!`b%wfYsn=Z_ zANl%%0vI$2aF$^v+8ru}!2du~k#zb~gpcD2Pc81H`cts3NlimZ$N43p4~myJ6xXeT z8}chG%B84ynjDBl#GLg`)IU=5)QoGFHBU#LEo46m2M@CQ#Kf$_`+7J9W(C;9TH7HV z{pZo2B999vX?{n4sF3I~gyC+NiMs2XN-^v(b*QvN^4Ewy#ZHnRcbz1DfGH%UETK&W z?cbB30dJ-K%ah5Ctb4lPJ}pjLpcvb_=zJ|sa}I+zz3osBajNuX|9#E!Q|Ze)qVm#Z z{@V3Vhi$j`7ZgEsnku5xlyd#k(dy@wB5b)JRs3sI>h({dy5i-ZskO6sI~7Ag^d~Qd z`lbleego$pC)pFKupH~9UK8Q4EnUUGJDhb zzsBX|f&Y8sG#!qx-fZj75V82E#J9qYE{{_ErGX|S_IF|b^01>kYQzzm$t!S{){r*s zaAUCVrQEu|)RtT`b=9QJupmk4m{VYK4TWL_UrM|G@H1t^Nr*2?$tG zxY^4Bis|B~y$-YIz}nS5^N2;sHsUnWGzR9OO9Zrp|Juf%_fqRm{->ya5>4ZdPo-A> zbf7B=weBu=6zZKT98svIl6cU#C=~5j$a>nfrYHoo!I$cauRO0v7KJ*5W}aUZ>LT@o z!5&ZWjY93r`X}g!Muno1*FWXPhnui}o=>RBC&(15e>zE~Hwy>T^cw1)E=ve9&1aT_ zZ;%Q05rnE3j7dy{J6rimy_D;p@)2JOqx{K74ytg{DqNOUI4MEHDgE|J+VQ0?4C~N9A=1A9sg!js2v!!l#eoALVJ#tH{x& z-Th_o&t?}>(Z{F$X;DwOEQ}v5#7Wf=*lQrs)-y+pke?Ol)AUw2Hq9^v7W-#dolnyq z%ct1V!8*T#hsUBE=MElY6URB#{^Y*(Plou>=bbbM^lG=Thay0`H*jLtKZR6&-W*(} zCrfM0_^8n?wR-sPqS1zR=&5@6pY4m`58T&d_(mAE)ow{>qxC1|Ni9NuE6-|ebW((;bY>PN$1w%LhoQzZ9_!JxBMxi8<_ZRtl}m-G4v-t zKcX4+;ETbi<4@6y+A{}?`doVtMpf%{WD7HADu64M{^UET{^>GBcz{IQOhyBfG8ake zpHz%EwAxyGfD!}jRcbdT#~j8tCLc}5S^&sWa@ZJqjvY{BxuG#R9x;v`lH(hbUtvG5 z5+NYepCSHJe6*wfsYpItKtMV5`X|P&uMO+TEk^eZ>!FkMuSYW?j}sDFaS;9JTvi|IFa{HGA4h{k`68qX)Koc#As^rRr?!V-(pCLa8=gAqpD+ft zpnwi{^}$=;o+5#Wj2+@Zd?d~Kr~3}YvsnLhFHg+%Pe0e#EG79#bI|v~+WUCTR&VVA zZG6fe66<+WUufOIi#GJp7d^s@4#Y(w7_vAStvMMvN$Q{ei+#s2-YoWLZcV|5UY#sB zLJtl!NMcwBe=C6C#Q5tS^-tRv;1T@Nv_CECJ7NKz(R-8f(*F);+MP-zz+-LsPm+P9 z8sB+Y`9FX_jP*~~i{jaa`ltQW@Gw8I`ln+A6?1C3% z3t1ln+iKQ06KCnLhMm9rn?HZ});Bdi03`hHxqofI834L!FFn#rahA?Vt&P9>4>DPQ zJhiQ-XMNLKHvc!azN!5_YGhbn68{-&s&6_g143;Ea?}w2>2HqzK`*gr0BC{w?v2Fn46uPCS~_L3?_zq)xtN^wONR!+$JO}(pN-kSHs$zGKK8Fw z@u6V2*>42Ba&>&@=hmA0>g}_{_)tE#uT3*PG;otYYyR)Vhe||IH7Y(d;`hVQj?l4x zZQXV5_|Q{lI^sj0OI+R@A1V&DU7xH!-onF$^B3V@3Lqdpv_M_)hUXQ@;zKQH2KvQ^ zPE=3m=kbI;Q+()Z(J_tKx;ANiX#9T;gS+b3ymr~RM#YDMp_V_z_s9DN#wEgk77nKA zO^gqnb4EgZ=s~7Iq!1sP1EDKsW|H{O)j#_R#gyYi+`krba-N@@+^+lAzN+j$KzKu8 z9Hml!v|x9N%cSw4V7TRPX~l;saZh+A9b)kz5Mq^ep8cq}08x6|*RI;&FNA+`s;#II zr||7@iauRPA47f7jr+sdVSH#3PO1(~IXcAP(5|E44M}snXHf-hwd|^$oO!SZnBSA( z;pW)>^_KPKp=tj*rT%!n`_~d|0kk2dMKHEmUo>x5%>ljIP1;Wppxs2AREcMmZ{3dz zv=wKL47D1m$NmE9KCRYW^w<|Rfi2XxiO0x|nC#C#n(1J6@Lc=X?u7n#*;E;J{O4d5 z|G~k9j78%=eL6tGF#r_Z%oedA*M7Dc>NZV1Z)33JjG)=}TR2usKu|2Y<`W<%pQrS*;ee6bH$bQ;#^=REmGVmVNCrDn$bQ^AZiM`&j31;fRf z`QHXJ+MuF8Ro|PrPep%L8%2xA7)O0jBjP_P>|ZqJ3E;93LGu1Lr zRuLreABczTv3=1M_VZ%#pUyds_)ngENHhM!y=w0trl+?U4Ku8V4%5?nKFk#B{Vg8T zYm_xNHkfDIENlMY_z!z)V6rhip7lY0%>G6hyYbCD;y)c#{09e@h)j(CwAq`oQbm6P zq19Rth$Vs+P3z3$rh0MPc_->4>w>$(x~p9k84Xx!W= z82U8X{zfMrAjIv5g9mX_i~k_^%4mNZRoVC7q@l{TYy1Z~Bf8AI<3GoP6w&yPLF1(m z{lP*`9{u@sPbjztqx%DAZs6y}#(yrqOpDDu`$248d9W6noi-iTg!L2CHhM@-9sl{- zEGxBrx|8ES?4hKkVI$%{zi*PCSGwXq7pGYNll^MlHf~DGcuX&9+JI;#8_jm@N4u#t zO&lHn+rUqb_z%V){qJJYABKWZy<`3OUkuL~07}3A9iJur?|5R4|Fpl(KINANZc_Wh5Y2mc@S+W!^hJ;Gq62Y}2!^bb;y+)Q+0d-A4jP=+@gG;;JI{bn6LpIW!!42qgch$eD+xzH=qqip$Hjk=FoG8! z$oyZtE%BeKY#e1Lmv&9+6-H0L|>O|^)0*L=KV(h$wjNiMzU0nRg)a zXfH4ae{IsxO>)cjg9<6k=v%$HdSsiL&#y-}#TLPgd2>*p-K1ep>j+U~?)cC&l0Uw` zT?%dO`hMvO7}Z|v4j5hA(-AOwR^t4P3mDxF8yVW@4jfDo1q6(4Q&&v&ydqh^XcY}B zzkpF2^@Ke=p5PlW>c_bQPFtE-kyhTaI^1d(2 z1RrY!MIALFR3u&PxRIi4rWAThn%RAcE)xGi7m0OjW_M0pGrNADyP`+`xMbEPX*pS-`qwdj)R^XV3t4Q`2@mMHqPD@& zxDM)NRUBD3KU>zT7m155rPsJ_%xZs$z0yMmD*D;|SD|5z@ufp{fiuPU(!n^X>gi{T znM;uvY`XV6?NJq>Bw75gX?tt0>P#9SZ+-3IRVkc1vdTPEg>!rMuX|AON22~s(!cJa zA2o;cYIkr`MSyk(;iT#y`Vv@9&c;>UaJ6P1t!CrPkfxXEu?JAzX+79ZkNdo@G47RL zd5qf#08e_~Oa`+zx!GgxY5%DC|47j%m-BDvUw4muy-oE;Q-7fbQt_upcNb*tF&tdT zoE?8c;Awe%0DY1J=#w1iS{DdsKG_69GZu|_h~FKt(kuy$p(w%c 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 NN5CL8F|8;qou(pIa|KbVz!T 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 }Ln=_} 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%0AW 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�cD4QNTYXToR@wV}->f+` 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�j`ana{ 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%0Dqk>%m{H_zg#~0(c;u1uEFSBr}ij0co3*`%< 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

    ?B1#1)U|k?anNeJ>!ym6T?lgFZjY5+J`kirAo9 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 z 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

    Xk1BItvuE|wg+z-v~}6-Q)BYFK_Ic6kE1D>lOy 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®v31=`x;!kBssn9;ffGDIgZGxr3%mC`fx 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

    PGoC-r}S5vZR$al>r4|2*mY znwM_%B=b+v9-(i#C~+n3ql9hi05L=qJs=_~+7 zfyvPKBjStBn@RgS|1wTK={Dy3K(fLd>wo7nM|$9m5Y>PmHpb>v8v05OOftETUD}Bv z15_k=;pnmr!%rE%4C}haH%uQLx`q7*g1k7Vtw_rn z^OveOqZc->$q4JAYfeHvyp~8=U zlYt5imkX9%P+9(mt6?2qXiu0!avLcY&OO~`aI^buGw7*05JBIS?_vAqJp44ni~M)x z)BAFs%CCI#aMX8&GCXZ~^uS2+I%Z{g9G6=yFaO$v#bTzK`u^rNfd>mq}{s2;rj z%;YKY$cp#&iLChIw8-JlM|vP$UtqsFb)JejyXzNn77}vC*HtINI$Bl$9K*R|Y!q_d z=eLbQdZ$i=>AUi6r&EeyVR`6vmgSvecX4VIxqg1-(^n9&t`jWRy1r$IywJifAo*1-k1sLnRfTB9`B22{%%Rh;uDC}BF35N{|lp23e|E}Ts^*(>&;ovMrbpY5ynfxU$$ ze=i5Cy2+@ z(K`EP;tp;3C8kFzlf4F3q6TNWW%a6zkHH{vN1HXUCZq=7pXb-LNiCkv@VBeZuvG;R z`X$aOY~94IG3?%q`-oufRC;`6>FV#)kVAmood06zj?9Fw0t8dsV$87$R-Iq z0Va8VlfNb?m2Uw1k*o>ZrKI$tOJeG#h(E(?9XEYKu671xFWaohlMaWccZ>&zziIBy-qN!i z3KyVEMbEIBtW4rbmD%S>RnyYZL!o;zV&XH-;k(7orxVf-(;is)>`$TUEV%);b;nZE zRQGd9<9+>krc3=~sbx$mV?9Z2M$FJ&=Lr_C_+d>1daTq~hV2foq)PYb*y+=^^v`m5 zz0*GzYmM0aez|B76HSSp=%4n4pVwOY{e^j8s!TNzqgkKqD|ZQGCj|kJyc@>~YPUK& zkF2;ORXI}FmGWyt8@1Xjnw#Byif5D`BWWo9bE!ov63o2`oWzlHvZ%!S>rUm7Qze}`a z@?1=wEsgn#XQV0>Wu^n+9>77GfF9{LUppQ8n6l=fqL@Po5oE+sGcQDk6S zY{WmU)Qz&Bl23ALlJyXuvQ-fc@%+m2cUxuREmEeCnuiXPp&peSls~ZoZ+{ z=uzR;AM!hPL+=UU)?4|-062|EER+2wvm42Z|IZ|1Hq!| zr|l?DG_Mj8t`suGf zin{jG+dlEDy2!MwlP?#CtB|`xH>J)5{iJOP&CH_UcRrc_;W0EqM>(H;-m^Sw%B`0oQ~vxHBzr*nj^-VFXYNOhLQ+{7!%HR< zUW9A73r{AnE~hu@fY`E@t_J30sCB&j?Q_0!5qC^W75DnrX*H7TE+}j~tJA+h8~CGy z-U)0%6SE(qxvZzOujBQY^#W`ZVn0wLvj)~w)bb^(ovWDqlz2sLJGFLxXRR)M^RnUn zefvTmHSB*+$Zw$r7JqgGKhJVjtn*|DEdAJzA0Q%EUl^FAJ@w2wlI?}hv#BGQv()S_r`#V*XM@T-N|vREHsf~VzafcvrC9Jbh2;=$U#9?%DCe;G^!pE^B(kJex!JIliwtK5HAKCQWA zH&A}%6Bp2TZgPvAI-IU1uVLl*;q2Db8jj*cd@cs`Sa@xi&Jmzf=Iavi!5>%S6Jo2z zova#nMtZ#FmWru)Du!#t>Qx&%syLynt7#Wd|Je9*iphY{>J&VuSgz7&ML1WygDx!% z-V8z3@>b0hD39{a<*5NFmvXoH@5-n51w55s`7|JXN1HvKM+NKQaBGpDK^0iM5}s-P zP=(?azA=}ivB~p0sy=_MYQ>JzDq7y^F}8=rSK@mpI;}eHTtp<5rSnyr+wH)@fL)&V zJ-eS`Y8sJY2(_Xyl+`AoVjc|$>We6BOP;`Sq?(WSs>Xz0Gt}9}``F~z9^(IFOE-jX z{{tvt@C)FXn(?_(9xPmLV}hEj{(!%J{l=M-be+dhr_*dwhx1e5!e-{}cv^G$G*NGk z(D1XMSEkMxp|brKo47n))Fpp`SiYxcjZ?;O`N_nafk7!h@Db6 zJS_jWaBJAlrfRBzj;c>jUt3knm(1TzgV?M>Ch*Ow6&+0AdraVekiUH2PxI&Oka(^_}hX~U-o-HywK*a?*B4>PL~uEt!Cy^^HE`tKMKzgJygVoLul^`vgA@N!fUl(MSPy{ja&FKHhBrt z^Lo{aFPWZqn4Y(V-+bRUdbzY-K}}lmR(neR^eke2*ySZY_C%YXv%V(0+-g81W|cvV zZc0{E<9~JgYnqK$vCx`$hl z@L@4hfiGA0+_;QiW0N&|SS>$ zFNj)w9c!>ehHrmQAV29N$rN~?h5?#rc)M5VDoW*$S0ywrgo?#WR>>))F6{>#nU8*YBTSR4tK zFUg_xuRWQln5Db@leD?3`rpX;Mr<1xtG(o@8e_GN?#uxW6xYi4P*uzPSa}FzuId2- z5j~mE8lIu(!Og?9B#MS(GkRUaUTmUm0To!-OGs2gLUlB$OfrAo5y9N-NTT|*?CeW` zr^kmD7k}&0A6(TKDb0=cZEniG@~Y_Nx?YCRnR6!;o=o(tQ>3d}9gv)K-ZlU_hRR$N zg{i;G(4(?`;PfbE^FCIHdiw6#5A}+e0>1Nb6mTQayK3~k7Ko!RM{wQt$In@W@NFNe z^V+d1J2vlNcRbze`O;=vV#Ms*h1!pw=l5)0;c^nyv-#BTdiK}fx)n*b#?MSQ@%5?a zaZ2HDkZj@?Lz_A9j zSz+|;Z8@KDttnS(7Efsk*!U_{yQ|yU&8S=NUaRWvgx1Ta8?=4_K|Ljp2k-K6f|gu_ zidi8O96;6$t<+Kv08J^{F0NN+9Xa(uVFrE^^?4UhQXTWUXmaq<=HaprM87+^c?PzD z=(({Oy(dJ+QRu@5DRisc-56!9L2I6`Hr5oklwJLyhQtbjxQ1wgO_;Bdzux>M8cEjz z?cWwA)>{?#+s>W0_}8CtVu(1J$A=sk-Pd{k-lcr9K)8nmM20q3&t&M$*VyRZv2#6U z!jHG9^+VK>QHgDDv-zbq04@Qq-FCJ9k7>nmq zy=pD7-p(_9*I`J^n#9_~Ecj+B;y$($-(-#Vi$4iB2egEY^}uCEmG~!JuU3w3f2B z#8$vx&I$U?+3~jJsPL|79ip;p$_uiUm>lpSQj@B=-?qF64lATB=0WdnSCy_p z<0kR8jig(J`k@My?yX&{fg;BZWWmy6ktVIB>jLPPL(3A--9xu z)RecB6_nwX>vXBGF~=YOIE(4zMmG`v=yU#Xirxp`bc( zdJ(p*@SO4J*OH#rb#^1_gjkDIc{23NGnx6Hec>3xcG6nP?);Yqe{81`4$ZNz2v)VM z&d%^MJjDE2r)F`@hMZ?yctffjuPVQ7RtA6J2%D!(J4Mw}c7jz;V3Xj+4m(ZC{-&mD zn|kGc@y__8;1oJ?`#3Zx{HOaV3VBZd@8bk4Sus^o5p{Kel^I{4<@IJ8!Nw0Xf)lW` zrPW{TpPl}Z*O*t{R9af>)6g|}k@)z6_S0!@-XU~9Y-`~sT;0iWeBJINxRKRH`9W9+ zQy136>`(KRh;=@WEw5z;j?1;wcJzZ>FOZe1p1$h6n&;Nc>Sbijm^@2gGp0aK?Eltl z879nyXB;HO-uCm}DEuOD<w(bl$M1)IfGb@Uaq>bW@M2P z0a?Xu!n8ABT}!M0{x}mcGC|71+cQIub zj^u?k=Ko{KGtCCHl{D`bO9-{R%iap}Hv%upma<{i1Cuoi$doB-^zKDfh;gdczz9>M zZZ@xyvSEm(ZaWjLgbXHHovq_P-^mFbWg=^_&Ud=N|d^`G#{3blRCZ&xox1*E<;!e^3 zJD%2J*U8_i(idjOQXg!0s-vd?(ur#NtbJ;Z25plFO*Cb>dUXX0{(m|CHgkjHy+kLjGX-x|0Vxf%#wBhAODvTXGwL| zNm@6=_8IzRt+P#26Tm>uD+9c?}N7lCW3qizTw+{CiOhVpGe2^Rq%w*-;A(`W(|!$ zKs9n!?DhdZV}tKq5!+tS_zHjfG-4oO0kVC+#w-|F&Lp4?$2JS*{* zWq;kWzijQNE>oFgsQ*t4=YD%B`&)B=?5p%OnxI;*HmM<03Rt|Rsy@k3F0-wWl7t=R;04_ok+23M}vliA6C&2=>gT~NU$c|s5_9^8h&MP1ABT;#r zqfVxqQ-3Ye+R^c{s#Bd<_)X_b9N+P>cJ?BX76Nd1t!<*3;MMl()JCo?Pu#BJjkmf{ z!JG6!YZO_A3Q~iio4`HH{OA4ir#&PY_I&{4LeI;T$Ax544x~V}))U?Co}N{x z%VyE+`HQ`fCR}_DI>-Ifl!J5N@vI324raNV0MbE!F?EOj)vDVikEu0pq%q3@I}ZhM z$)f5ywRT_vkly_ZeBhhFgbpOsbZ5$~*{)lRoB@fD9-gF}D6 zv7^oVO`O95@3Ld-P{jNb&+qD=n4U=BfFc~b|CO9bTG)RFKYPYufJR<&YEf#?atRT-lh^OB71w7eDg-kHB|lVHVcZ z*luTUdSiH27evSAHXUx(aYskS%5g_n=x*SS(PcwN2`b@{p1M(|u5$;PC6N*tdqX5C zxy$EDX%U7|6-#N4_4!i5%R_uqb)uJWSc%Yw&xi!`KeC4p=ioXMI$I}Tf+3AU`$kZk z^OYZr16A|0OF(JhYxFrkq)4_#Q}Rp#ITz3zdW+@}y(RRTQF{IsdvyI8Y%O&y(KV0a zlO%JZAEJKbt~B+d&%GuJ9{8@E51)C@9_%}(-@H2_-kGL}H1p(#lMnBy%U$Ek1(=om zn=mUP(v2yXFwA^u?ZsIRy(P!_7-#6#s!yOx%$_cbaK%_a>$)4h$I4!_EAMyX!YCz? z^z}9Wx7!W-KWfvv+wF$0|ImOHy%40V`Qh%MGFhYfE%N%^v>VV&;0OhZQh!AbX9CXu z?cn!gjkHS)e8*-PSb-a20M1ii7dVd)81qa&oq4PS9a~6iqa1YhxpRTsr(|E4X+Sht zHNIYP+#3gIgTE2~sUWL&zU7&Mh;CU`tTT!4-fg3vJ&93IynFXidq=hIHrCY8Ot~5i z)s630ZhR$LO`#a*4-*IL6dw5sLTu@d_%8QL+=#(LL8#(LGfJ&d(<&hBG9 zDj2I9--Wcs{DF>B#PIn;r)o7uMq+A%@5D3vHI32v?z#C{hB_i<;QaS?S??%8iV4FS zw(jSM&xUV(Uf)pfLwHM?)smw_#iV74q-c-uouQl+EOTLB#q58I*z;H2XL^JXvBoJA z5s&NMtx548`A;0dwmLXkn>^+C(p_C#*!GEER~w$UqMb8QkXXX}<6O>x89CeJ?bbW~ zm{=>hiBXGZlmOAPsvHiM{*?^fc9+5W^9z7=&%018h%fAtUR2V*@3f?Pm(+tK^bgY7 zIt3-;%<~?)F>^-fT3)Jg&*bIebC2yRzvnpdkqck^u3$=?xoRN~yDEX<`f*!4-;m1E zp9bxE!FM(9BDK9EgFdw1AK?0)p2Cl7tGdy)bhX690@1G~v;akJ@lz5eWq;Bm38C6K zQ=K23KSq-k(5Bb7nd1(>?rh27-{lVfz&QE7fq$T#oIe>j<3CzoAFYM71Tb(euTGp%qPQAY>*xZKmra48%TtHYh)HFT z!dKHdesi<_y%EOq`{CSVjJ zM*e5W98Mu0#z$t0{ z^w#}YGa?wP$5kyWFsE#;!tyjWaY$9^dLqmKf*PG8LI>R}l&~ zd;)QGvbM+A(#^Afo02u)VoTd+6>(Eny=ptGg2RPSK_LZmlZB`&Z#HirpNks zt$@q=VY!}3|H=ActEJ!Xf@G)d!tTDXSW|6QbjUIl^}df6owT=&%FjGoxrASieM`^M zYqF~o`(g0R?iKA@(OfD&Lw_SJ)^q{<NRlGT|GBc zA*Ck6nQhp)Tt5Y`?yXHEZkL4`tbzE*I)BcBEe=+7Ysu-3eFgbqGbUznpI>5H4LEy$ zRm=8Er{~J*C*WZ9A>?QK^hoorXL;oSWb-Z=E%7n!n&aHyT`>{&cg04}SspFJ^tMcX zcivUMqL+TxF#dNfj`1+V-7DR28fFH-#56#ivug+&Y3}r3XvVQJhkfiFShAsG?uCWK z#S3Z~S?r%k&i@l$p56-$Kot<-?ib{6k>T4fm*3%u?2cl;@A|2&y{a=Q12~Y9Uv}_r zVCnpZJ=o=<*{GYD0!`p%1}D@Ls(Ft;k9i|#R@b4)%o40d5)+G`>ZRPt(49kU5AnoZ z81j!k+2RrO(E=-_<%l=$A)-i9>S1MucP_H03ue&Prbg{c`0=f$T~ic!VQXZCcUa`{ z*z7+L9gPw_u%x=MVUgwsEh`G-X%URj((UvwT?Io@<(O}iW!rzxZf-tr-moLozSMZA z9Dy5v(WdLSef)h-hOuF=o32Zb7cvJspy4@pN}NCnb#Ur`Fl6pytatif^w3z-#H{E* z4OT{DpX8fYt)=0W`qp@qHzDM@=%{M1RE=ohhzSO%BVAjcrS6dEiLc#L)k8N~<@;B} zUugM=DB$bZi6AOk`~~bWki}d!8r!11KpXg9B(Iu{@A$3?*~U33{c3gmuXs_kd4q0- z^C9;Uxm|e<^g#vfsI3lGt4B_PnKSRY!t+6#Q;veHKOD(SO6bjE6X;bk*O z1WrL!i9S_{>#}h!(57zU7QSXS3xt>V@veb>|N^c8HIjG*=GL?wnN(`+t@ZS7tUPX$q7}yE3~J?>-8u z0JS&NwUnhcs%9%N*A=KW-{)FYp%ky)F95G;C~qlSY6a{V4{BpW30@v-sjJ2&?Y~&& zZa6%--4SJ#br@EIV$&5R^kG^9TyhYO3lYF=(t z(6ezj^~+WTsW>-=r5AA0zx?}QZxx6BFZaV5jbiIo@Sd=(pU~*HNu%H9z5XLLIF)fp z%}$0^;QEgK%`QEfX%g$ZH_n_>Ch%3KM)Jg&8BBv6q&fq{8_4EA4`TJSe33otpsL5T zXE){YX~U~a!xd7``gJC8phx4^je!qX_C7%-?jz>fjYeH3XUjh9w#vmi=8Np`jq}xN z%Zlw)?0J9ws?No>{5?C;iDQ^d!MC%d$?8MgAO~uPuXWnUc*3V;tkr zQrM1qA8MsxL&DAY!CHdw%bTo9lA()UF?(|fUF9sGSNv~jhYQ_N40l5+=cmm+eC`(P z!`rwyXlXWM@g_smZHCp}h^u`xPMzI-?I0w!_3I_w)~^=qr;!e07HFAKly$?wBBDEH zziEOEJv3O=npVKV>sp)MAeEk9-fV`VH^u;fS7U(%$opM`-79HPMy)?}t2v|oX!rUFIg)m&^3e@8`u`bC|0ds%9{mXVroLyVt_GO9_0h&(PXCzLDQZW5 z9R43<_L)hVScVEuU6m($^DVBOBWXwTzw`Q_DN%i{w_&Q^o;Y1@Tl-ITYqCp%{A=sz zm|MdCus4l0zwhvUVWDyOq*2r+8PKOAF)l1#OOaBOSEG2hj05eiwZ4r7HGhH+?S8oSM)gyvp7E(pJtvhAxy6DWNC zKD*W{ehem;;+>4EgvS0IQ!TscazFaJ>2jQJq}S@x>T(uRd+B#un^{=s;3qgt3BPAH zXV_W}80mb0HF&Q_@dkuUGPG+1b{WluH!d^pTNN33U;2(S&8T4N6<KH|A-&?dnS9~ODV+xKXA$EtmrB`UiK<2cg)Di@@9Mp;{@zN@HC7P-_ZIy zbi+5mp8KS%lfks*42*U1C1d{Y=tSF?D(ghslT^>y+te}BVcec3UbpnDT-`@s^Sl2W zutmAbHHLb1$g~S7Y{vrp&JtSPEvK2P1Zo9x|D5b99mA6^5myS6k+r_G55y2=^%aaJ zSHn$U#t~~Ncm7F{(#_$UZTpt4)Q~B02m}J^+i2-Rlc^ovupv&NLTf^yvY3ktRtc}L z_SjB?NzL*|>3WP~avdho_}@e*mC%hsCm_f{_#7-fAV+4rE-zcjDO zP@jw*5EDi5$d*8y=O@Z|xD9q22^%`VyO!SnrU@~E zC4J=wnP}w>p=nCVKg%*6kvBl=+bu;7u*IE#9kWt^g*W(H-|_6!cVY1cR)53%^0`o~ z^qbTuz7YS?ieQ%X8Ee20;uXcIekzOM)tnMr))WVstUUG;R9->e)`h^N9h_a;L>nGVJsGQF#WOHCH|1231< z@XT;vU1XbHOupjzm$|npK?xr2;*1a{wVXLfu7}n;L@kSYZ9FnL%u3g-nyFpd)_j1s zIEA&}vs=q9!P-B55A6?Sh`TtgNvI#ZCBeYs4LSDGy7$TDnS-{5+kftlFMQJ&QFgce zfB7^pgt{Pfrq1b^oqdc(R-jc9n+RkOk=KifM9i$y=FISKbHq?kE>K$$t@CO%Qv768 zgfw_d4c6#$utx8=^x6X>%{v0?^A58<`lwJH3RNfXHATd=EalY9S!sH@8BvVx~bd&5~cpv!5*f^7+GuPRgu5tt${dBUx zoA`IB^J!Qy%53kZOZ@@1r6xiBd%*G+zdFd?v&&-NuW=B#%H(yx8n^}B)J+^-D)>99r+X_<|O+gV<}7q!CpwG~2} zy48J*SL7-Zr=K-BF4tdXtYo9!R((F$(xVDS1K8vSaOXxfVZx(zll6IQ?A?LP*?^yf<)L#P?7TXyxBb)Yl~O=(4}F`*l|UnVBxWt#X_^F48(PY)vVt7nX(&oL8+%icw*x?>w4-Z--^vdcTF?90 z0+T@#uXZv>U!;b4dJ;?JBI1WT_TqLU(lRJsLkMv)I*9ofHY4s0o10e&xe*R#61oue z1_$ldpIhDAynh|0ZP@Ufgx&*vxn)LimadSP=O$b+DU+BC4YRsj8Z*hf=BBE5qjR;) zz<@|Dul8NmD~DVD&~ZP6J6^HcamW5Pl$^4NP80!1iOhCP9#T%a^p=TJdvqBZ_NOE&3oUt%yhs0`61|w!=3Vt8!BXRbY&`#a z%*xhTT(Htyn4_0tentPW(*yf*u5Ud!-o{&QRBxBF5H|ZPDf?Q=T}t7tr@cLs@x8aD zeC&TG^v#v9OzJp%-wd4e4*H3K_gP;f+N#cVV&k!s0bGd>IDJcFltzu}}1X$<3#Z86Dj>c07(0P&sZMH8Q=13+rIwbDsA z{`#YH{dB1L*+D+6J|6bFWXO;Veb$%tQ$GSG5jw6rZ3Or;?H|G)j@TLguw0t2I$&@M zl#p;*J4+?BcHh9SYXqI*UQUlcnj*s4;O+O8Q{0_V_kP!JCTM|GH;aW#GBjEJIXvHK z?j@a?d-73nM$_D_IGX!~(!RAI@~r{CnFYJUr%OQUSdKk;#%suLy5!`5zfqP9jr!yu zTR)F@+Ri^&#diM5vD418wtDxX)GBZ2wY-c?^ur+C|R(h7nS-YtGp>aU!xH}gd9oUnfmhh1I`w|)oy z+EUhH?Q$PLO_7c;HWjJhT8)$ zoUUgU?MGAaV=g}wT){o>x3kTPi=mv=Nw-s|?+v_1k{1?E8M@A>@<}?FRk4&*lIK`< zZ$N@cXVZ0L+PnMG`;2E@W{)mBOHSFJ-eX@svq$%@&dD6yVqnfIg!urd?)c}}#Ka;S zh~$&~D4{F%BNF_mRhQ|yp4z6>2l=ZjXM~|S(dHkvWehHzO@nS;>)M~YrTfU@_gdd? zu}Am5hX%Qk9lDp1xt8UM4`po^2%-N)dZGepULy%Ct;tZ~lcuKT_hA9J^kr$N=Gf#r zPIRMT3x|;N!qe@J(vo2Z zByV`i_uB!v$vt%R2+sWb9qrP`4XMlIgxImd=YK6<>>Ey2!4LLO$E<%2++!UpQpfvs zAkn_)8BX@ubNP=p@45UlsjQ6hy~D|MtN`}Ve(BqLE5Atx1{s6e?-fqQ_gp^b^}Utv zt@42X3T7plfAF_hy?r!!FRM3i>3OgX@CQ{#t9e#EZqaV*vk`0^eZ~4l>-X?YuZwQF zoL_TWY%E1s75n!`zr7Gv*@$a>HJc=bU+$t!e%S$*R+Xm*WY*4Hg6*Cv%v+{^aPwsW zP}oQJ(vAZ4^9SEuljS{lilosL*&R8r7F)Uz9OF>f{zkx|-k%Wz^x`MTqD3i&mZ;LT z{d49Y#IJ4pr`B!%V8%nh=-j-&{Zs2*ajo%bK*2}vI(rKpe>#o@IjWOx)5o-{3Shec zF`GUSC58^`CnALHB#Z3sAcy~*`rCyw1o^4-z(3Z-`p0DsokVTk*{`C%MYSKeZ&XN-U)Lr)ymILZErBD>9=8dSQ(Q z;_HQ2#7r-Ak}Rzk)`M@aT_VY`!TabHrx$9rHAGRgv^rPBd@@33^<7oyd&; zp}XjBMR%qbTJf%Wp_072rullIi7y#3>_>L+BQN+-6#OuuPY2v=D>U%chLtL-SyfTz zUB=o$dhTLBIO06F!zol1}1qJAU3XkEYN6VX7ELKA~Wnbs?~&2QK7iLvtJ^ z)tw|4Fp{(eefaaa_`mF2;?Q@w$|iG;o86PDfR$~G=zfw{f1|lEgN_?ATkZb#nDYVg zw#(}v8M@=agR;DZsxFx`+ImFk`BoYL2kyTzumpB{-5e4)5k-($PUnWL7qnM8ZthBX zKeQIKpYPlETU~;ckyhn3x`cwD67NzHq@NEO_?HgY-GzaJ<-_WkPeW-<$bM`S1k#j$ zP9C^!aIZ4Tsb)@c#8e2)$<$pyZ# z9R-cA#dh>*d?~hLzs8NR9XX8~5S<;^=3;;Vwux_|W(XT?UWanOt=w-Y_p4Sur||{V zH(i3QNoq%l+KzxkZ}d3A*$KQQOBA_b`K%Kpxgt_B*w4&)GWgEjcP`w6H?_ruc;KWi z)|{d1+S<)Wvx&3kokiV!^0mOI4*Lqi)_!LGGKbJ&g>`5jhvBqwh?BbXt40#ss|5r) zLGuq!*Pq0IL+(KHNSwHz9{4K|sL0e0V1V)GLCvkOIcMl|1AR;}Q zI^Vvj@dBJkd(1xEWC=coxVhnB_GF{;ox3JddVJ%_@>e+?()iYmnE&b@fl}BU8KyRp zInz#anrU<{+s?j-Nj!?{WPs}siXUYsN; zh%cLvw~l&yd;~WrvJsG)Hh1+M!Lljce`U`0wx8ioRO+hk)8qE{biZCfhW`+y=)L@f zgyl5$^4|d4&_7sDzHc)Fm&NNx8gfh7!M_v-Hy12G0s9WaTyvG782$Et)c6$N)yO(z zIOJUt^vYHhscRU07tC=l#-DV4keao}0`6GXAYwV=C*(GXGRXQK7dMDS?$vKT*(Q7g zh$X7K+?r59+y__hR5x5gRWTncsg}yKbil`-=&^uQ-5a;pt&{)XfR*k zT8Es8Z|-=3kPn?LX71g&DY-mo^S}EST^8KWehPLIl;Z^k|AlU`pY)$dUDJcuGFfil z7n>v=W}P)qbB-oaUdTEm4{r7w*vyaJR1Wh=qJOKyUEQ8PF;dV{$8+ zw@-a_-NDf#5Mh&8IB@nW+&YP}m5JU<(X}!E0+8(!GQ0VIj@FPWINvok%=sDx3r`=ahz@9Dj*oLkZ$6I7 zjQ5)P@f#n(;o7LFdrXWpaRGvI_IGYJtZuAz^i{9s8;l@L40!Y1_X+;@Ch0*jx-6B+ zK<;bX-ZYo-Sj!k_Bfid*41N6Cz^rB2DwnM0VsI@R*uR$l!Q~=YK{*}1L=D3O{HYBB zXb`tX!IJ;Kq;|pk&YfBBmD6{lfX@Bc)OBCAf;0L!7W#k}Oo6PRPiRYSkkDrVZ(f@|E3Ey1p7Y;k`16|2YIw)h9v-)E{>ivi_Y# z|BBSV0`-p`$-x<(bc~~N(l8^|G&% zYT$-Ip4Gln9vFyy*_&&`tChQTI(2!_)&B;6^*?-*oi=WHzg{p#IO&fgBX>Qp?5(p3 zi|uc@{jEvl#y1-Mjc76Y8+M+fKZap!8wup_W4`-7?@af-T;HJ;9C^Y^7-n+7j*t3g zN$}!4HQ;wwj)lPb63tDLlBjU+X9&sSfa<&}E^$J#j_Is-)9L+nln;fj@ri7H6n};Z znS#J!Y;-~NNfS0oz@0HaHHky;HURuO&~tSzr;zgEFSvNdV~J^%#D!OgR8GtOZL_K^ zSGDDNfb^}XHU4Hjz zv;Skr81_dA=&W8k_h2$*XLRz{BR6Wn!|;MWw*M&I+-^VE@ypp`$NZeuzcae`&vdF; zP#;8EZVn6TsR1f+78i9b?|4DI1wgsp<4<(&Ecv($!qk&l8ZB|IR7a8b?+Vv-%K9$K zP*gVrhlN=9{DrUa{&`%KBPmJVxh~fMelE&ushbSN*TJBVQj4fXC251k>F;`m z^oXut<2SH6b?$a)Al92&`&(y!8wBuLO+L(7MnN#3LFiPAx1#sEU;c-BeV8<_5~%hr z&7J&NR`wOsr2E0YdVap1{It+_-RQ$eLjJ0N3iKae>~sL(j>cHh7FjbYn*k7$bX1<6 zt49@N3602%F_Lw0qt^G$JJ#|odhp|>awbn)`6POIDaL_0Dx>f7z?{g5_R zQ%bJ|*X@_m55=LFENh(24l`|DS6~|utbNa?pVD#Z z*|Zu3i;%IK5P7b?=)b5B$G0r+J64m+N8TB=TEArE-1-GMErLKOBWF1|IrID(cP#le zzO4)B`yv`zba&N6|&jlquo49gBiRcGI(_r*Q9*@Mr6e9 zv~_X|P=3E^C?%P{@<6wLGV{#mI=pM^cIOvf#faT7FZEn^UEJwkGV#LW=|I}P0>#HP zEGSxNE-Y#izg=K2i_`3&jrYpA^9p~((+*!Jl_3yWHe{dX?Kj#eX0${OuxQE}pBBB3wWI7)KT5`MNDY<2QP|jY zuIIYuno&eH=+x#hEt$Jm);qSxqlAU}J~Qv4L4kc5 z%6dc>(O(P&wy8@cP8;S(Hyb31I8(ZP`jp7vHQnhA&Aq4Wk!6n1(C5E*rFILp&nwVh=@(#OlHry$40GgCmj;`tI%|27mOnoV?qtr^a;hbVpwYx%s09 zQ?#zoALb8oGn4XSpTeFfi~%GO(|rak*n%idBx00xn^L<_mRk}9G8ItO8)X$Is$4)Z zq+d*hXa^t$lq|)P7e{(%IUwY%)})ZRM*0giakyIwG`elM*)0ug&-QM8+|fp0lFm>~ z>$P-o6^XR0VMt5dL!_nVyyq5oDgJdy>)Mlc1M*jq*3I4F-_PK`Dkk_h3I0toP&okH zYQ#@Z2+NullJMp|%10-+l4XxRIxx$kOF}~@t-|4WF^9s_KuuIZ7tT#eOK5|)_V+m7 zAq>XW$UVJ{hNS>s7F+vU55!L~+rr@g$J?90S5;ko{|OL?L%ab&gGvn;H8=*RCSo*U zkQ=y>s8mpF8|zSf#HXny7zQPH19H6_jaKX2M_XHM9jet@6k8cAgJZ-2MC;so;?;^n z6+zAW{jGh@&AmxbpZEQL{(L^<+;h%8dsus|wb!)QCg;`X>4oH(XznM%m%8XkG*d+i zQ>dQgy65Hw?9cH*<9@~mXBZze{dg{0X|#Sc!{1vFR@TaxeEex3b2jk(K}UAi%f5^J zi2g9_o8)(_>EEvZpv`9Mm!bYf7Xz&gh$gmVXl*5dzR{&(0-y}7%^!P2Z@OCQ$}H*E z$-hDVq`62q$iEVIwwFICoi+Jx=W`FJQ^+JVXG#vm5W22$0LKX0rXx=1xPchKQ~rby znJItNP|tqcsaCxqwdwWqKJ2h4opba^?CToYTW4CZWFxWz?Sk0Uc1n!2ItEyBIB}Y+TI^gc_B5@g zVsqrmv(T)xxE^A;EZJ`&|HzY<`~=?BFTZ-hmKHjHaep10of_i*dgHU5)rsXbq?Dn8 z8EU+|_RMy6)6Bnk-$?xXungMVi#8_^TD7ZEAPlLFFMq5$zGdh|zo7%W^ZKhFs7u;+ zFzjP~KFmis%0Qzny(Yg&zi#YDkrFt?vja$YVml?rf3yy&q(we_m=7^gs}rWSk(rHC zzNi3he6We0Ob#;S%0gBwR%Wud<&&Zz^>aZkDu&PuyoS`sZ#A*zkt`)?#ZFgEiE ze8`KAU{URkRN4HfOWpOG%f5m8cO3mq$M-t_l=goWi}ySGRc-Q|;@XApG>sr@4fs2; zNc-IV_4h!dFiOW!{4)>5FTEnhT2WeCaZpLq^EHW*lGM}P*vC_ni}Qu5g<52bT(6P& zNlRC-c^tk#vby$7_C?KK#d*9vZPC4c?-l&EO49u}NRIE>raiV$HFR&BdnaG~6Mn)N zSs1$HLuq~VYepa>lIAhy?ORK|v5GgSGOrSyu#XrA4FP@6L(6^ z1{=<(15S;DYZGsbPnML7ulVxfoyI4=7@v4I)nCsNU&NBb$5nhiE)x5CeDd~^ok4#J zjgQ2>4E4kDm|CuQn&-7=zFS-I&&U-&=QpSBE^i!Eoh&=2ZCu4O7w3;ltgTLblQGgf{y|izW!?y*q|>$8>Mk+ANNa#K)xe)nofz6#aZt zlv5R>!=KmFD91&{EBjifT%@0pQ|0?7(Gi)37b|>E23W>aj;!n**?jB>@-4#2)>)px z>Scfr;B4+v8x7!vfAklr@R19F5pj;F~{ZH5gZEBK8OU5V4mYBN4k@IqdH_ zkvRCooBr8cDfK;9YK=-=O{uot$OSG~>Q6bScOC&(EA7~@eHJ16S8#rSi@e#6f3)|^ zak7UkH(;|fQ&Y)Uu9rbV5Z0IBvS?DiTlVwH_!V3%}>l*tL2Go|?$M6Kv z;wO+ka;FYXLm*A=kjj(gE~k<0I8OSszs)9%NPbAHHU9m|xpdhpc;Oi4ivhw;v{HKo zt6rAdMEVQWL8I#;*RF^>#HRZp=hoFC%E*Zl3IpmIC|l}Z@n2Tigwd)jR7V1_#LKJA zC7AnAfs>J@eVqOmisWXoFqtUr&Fsl`{kj8s$AOOByYzwXEY$JOSJh~5@x>Z&lCz?) zhMl63!(mM-G2485)Z@l~cz?@xTP2NTT6B#pTWp{hvkpfxkb!q9@t-`;F`Ysg93(1(Ji$Uf^Fh_^@p>-kgv9SFFK-h7e2z z*(!TXa!yg=HTL`x|BHTaXPaL_xf-2zx6p#9HB8wU6u7A`NI}wiTfkDQ90Lc`pfrA! z8t=r;fJw&RDz5R4DU5ojh(CPIDbutP98TQ8QA1te8 zreczJ44&rs`IEiD`L*6jg_FI#xK3v+SQ6J-Fl^GAarv$!KMFN_dQzkxsqe`Uyf1SY zOKi~3J?!V}`WeyBTP8{=l-3K1;i+DZo(jd7*_GFR?#P53A1r|7S|E|26!6S~=g7L@)fF_&}1w&aEQ; z-->W{8a1w|iWz)t|+N>rRAYQq(B^cG% zsuYQ1=2rP5d7dhXSH59y2EaC&qdG>dnYcH9=b(PSuYNGikg4((b^Y@4)*flociWf4 zvA>NzGMqoLwnBfWeS--U$1Y_5d9Q3CJ&A7qo^br3LGou1pU27=+E*4E`eQ#fj?q}Q zI4~_INocjT^Eoo${zR0)O5&D;$U|X)ppIl6ez*0FW$|Xr=)05LC*N)V;vB|!b1`T5 zUb8&aw>q(L961^%pzKZDE5_!n)IKh5%2|PzhP2>rIcCK0qn3IP9bZ0iuf`9eYpRXr zQ}d(?!JJO13wsorim96x)R%q4idhZX$0b(zp93RuY_ILsMrQM1RuuvgG_<3+9x{g8 zt#UWmNb8M8yFZ7Eoj@qq&={xnpnqLBJ(LSZR29NhNR+(+4bOk!E~4A9x;a?uVD=T4 zfH-ZE^apS<`=@x_m7D>#Ti>lgmnvHmpr&F8wjO#re-f{3Q3Z$#iNT+ARHBaJ@bsT1 z!l0v!n{Z>V&Je<&^n)|QMdv1B`TgUcd7cu%0xxe;=M#cya|(Wrgj;sgL=|m?LK8U{znotVA9< zop}Nt!a;v3AZLD_`lk7j{P~4{K2+1DH79>D*so;>C4meS{-?tOvQW)1c)eh~FYeg3 zec4h(Vs&Aa=}mXjd(qFV3$l5izA1*+%{n2P9K0pw_1hAy_+-{m(d5pXquySd@v$HvcVPK6v$Y%I;{{US>awmRRalkM8*C?_`Az&~234XdU8pU@FQVLY5 zzhgL3V*p(v6~Ie7V$8kz9scXR=aEHn2dVdwhvtwQgdGYMp9E<(7=`!a+{i<(M5ZqP zIC8+M$kcToMmyUw^PFgAir1gG*xpZ)qrIO`H!S4(3Z^>eS>W{GX7&tS9vsfWxG{# z-CA9+JnRpb}d^BSMY* z84B6JRnti_>FYM~QmLOVeOf;ft~Ha)yu7^!uwCY~g&LqNwix|PNv=UYVH<_*SQ~Ba zz=R52rimqrS^&SR0xD-O^XjU-BCM6g)DJi$QNL>rnNWK;Rp6NNeZb)uitj&yz>SFg z`fNuAG+q@=XJAP z>_0G!fz!EsEvxi+aK~+uj2wQgb@(+y_{D_rCzOA*J>i#nOD7tr4E9(zOlYYAq>yr!jQ{~{HUz&@uKThDKVei_BSI5H?!7Zd|E-D1h+ zqBUbmZC(=X%-=})`c9I@+Jr+waT;FUo{hvWpQ0c;238eKPD08hP5gy0PvJlVE7A9x zHBVhQuvj4xd>%FazOHd-6xrN#-zWX|-&ai*qNnQCROMUquDgE{s*`{}Ho{RJ`(!7pWgCXqV|@lJt0vXq2;PgTG$x za-}9mPJ6A!8Dyh2C~GlssTxQ3_$Xd^j#bpZCeiOBmew2i5Dc12BztYp!WsojF#$z<~mtW5#2=o#}wF{W(cC*cY;-AI{MH}t@<{dOK!hkqog@%-MT9*B(rvVhN zpzdIYk#z!|CisgA6z1bpEf`ss#>ll5VB|j2`Nq`1mk$IZryTgSLvvSSo~!ZegSyrD zc1b!9MrMt(RO55{#%jDwHTI!K`Y@N@n6}UQ7+v5)&Khh}=kkU2j=q-dk%9Le1;Y8v ze-8hZJ&BcMJNSQX8vkP@C8B|<#f>HVR4txYBFR5Z4WkZ+8kRgD{3+~;Pf`BY6G3ON z6WSq|r{YKTk@#Jrf%xBU1$Ge5E!-u31Z%j$5X>b$O7qgF3c1;ciSkopYm>3HTR?@i zD3S2esZGX9Yu1cgyG3PFnCF-KeS}Y9p}!RN84I;@_!6!Wm_jMwdo>ppx_gT{tp~la z&@GMGREtVe(kNT0Y@%~ZPN{OGZ{V_?l zAIpA?YP7cq8s%+c<4%$|;31RBQv?`P*1&((HGVHz zv7+f?q-y#>zn=6TurJjP6_v@kF+%bso)L^|ld4jC`&Usy&#{Qn^TiX9OVYKn5r;}& zCGe<@iW@)F;8;_Tp4R%OcGYZ=1XQ1T#$P3(Ci7IOp?}kdp#SFmGtpmMUpQJMY#r)9 zush{5`G4dg-bEhbUB~C!mmwW}tTJ@{=J=dY-wHx=&?@tiQ}fB@=neVlK{EY4-_$QT zFqLPAGhp>2$G2_NkgCJ1z*N9(ID5a=9J!WEL76rUz<7BZ4u!G~yU!>~f=t9B0>r|A zWL=6~Z(P`%@!|gRF03RampFJWp~d8vvfqdmwU`L6{FmXAR1Fv`YZ&M=O;`x+k>JD| z183)hIy9Y?7n;FMOH9#7S$W{=#95;3toGmim1FJ9kTjhQKMx2*iq1|JDxhUsb&HQ{ zQ^yuzMV+-|tt2?mbj4eFHHp0j)_DEcE?Sje2HHp~3{F=nP zfrT}R#(_ntJ#C3tp z0_;#f3%d*5pLge)T^!Wm$6|psD}KxPm5ZA%$1}XYV_>1(*&EVo6fL!jnMS&q0`mdq zq2nnf`|DSID{Ou7eH24&_1N&>58N#JY2>vi%&1fVtrAwlxzYm{|Mwps91N)Av~C(h zSKsx^_5U!3-(`}2;EMb~{i0&*f?#D4cETb_yTvk!s&j?10VE%}lisEB9;1Qz#t>U` z$RasWXBU8we9 z*JCBcRf|WpRkePGuAjtq=M5`l6Ku3%4@^wSnnI)SmTTe_eQ1D z`fJdRAPt}j{f7nx&^GO~1X;J#ol?Z;%@<>V|F#eEHfm!Z8_8|6pHbD z(KcRzRn9yLID-9SW*@y>H6?(tID+-yLMl52X3#g5oK(ocB^OSlzB1}_)?Q2z)N1yF zS8jB?fWC_tJbAw68yRmvY6oXu7zJn~&@CsOm8;!O1se;&_d}Py(LO+yJ7zOBJ&A&A z{56LOoB~z0gIqjJ(4b zdC$#AeqmOJJI)Z{I{bNE6V%PWY_4Sq>f|11u?d`qgyk0F+s(ALo<3zkdm_vt49K~_;k#HvWhAb}s(RmqMeqV(IIKvgZUG+%Y zSn)6Rz6aaux=wmqY9F$_R7+YSJm;<1e-jVCX1R`8p2kWKG4;xuzliick6K_#J6_3{ z%xu;O(%VfES=ZF<{v;9&!7VCSb=?IIRRb zh8wSZ?Y{&P#JDM{p)gQ@x$zA?Ufz%XmsmGQhb-viyjn?n-OG99%*;?v>?ZAK5+1=^OsAYLm{;1DJttU2zoTmovjS?g;FUi2&VgGahEc2gN z&c`IEOHPnv0}IJoaVs#DE*1lt9^3l-6$L#2(s90MD)XO>zx(;3j2{G%5zvv-=lf)I z>GF46mx`T!HP`aTYuSuz>EWyVE-c1BF}i0jQkQr2z}naT%QC^g)Ye{oPy5JFatryh zImt<*?6n2|m7RNxGV^>>`Pc7s`%A8q8n@tm(}og3hBz;{;^m~p){-}blt>%s9y%bW zDo4HAtX^&QAGLM)d>$cOi3Z3|{V4nSAHG`o`BUXuf`jT7Jg!zSshNLT_9&sXhY7{s z=~~UBZlRj;XpmmMJQ}CboTjHu=2vd{-*9fd?00+q0xkqpXUINh-3xNdkDzVAS36U9 zU!U%FTKDYM|1WJ-q5sL?(7Rv|FE3*dpI)VInfekVvBmdPB~v2Tx^;VsMU&_meTV5| z=LZL-V9wYMJO?WS0=-&WgP7W4XTMF%23bD>M{6FeviA4FqG;>Du* zZLx}Vk@&xvhL|@vfgim+#zxY(4#_~D!ZtGcEX~!Z$;qADYjIa#G-0`x=bd}6Mh)af z1`e3)_2afGsD45rSy8~zW+(H5vP5}Fpy&LM@_~qeFZ+LgQ5a~{EzO0MxLC1IL}q<- zVeLe3ul4x9&ZOlwoec+0Oic7!Khf()g5|1w#Z0qzBqxZSuCjDNdB31$v6V9aT&r6# z`tir>WdVT8yZEBSM&&TCQK(U3EkA`nqwQ{^%9Qcbp;FhJ`pX9Nn9h!$b}fd6U*~mO zpWNIy`mXro!YZJD)5K)Il@pVvugupFM?}3N64B(&7(nKIobO+^ifB@zMsHr8xf-e8 z)+w@4>X>MW(xlECvV@=Kn&S;{ORX26XM8u1BWB- zgWISFc%1!}{o6aqFa5VJTC$ppSYOD6J`*E z3?gt<2D135fl_+40}KA|iIjuwjcZ&ekFnoqVk-K^^fQFtfs^%0`Oc+f1Wltz1;N`f zA~;1^RR3tO$n{v?UKJ)O|C*P#`p+;w&t+-S*{v^;#6`=Sne<#ZI9XqFFELszu){60}+5d_72_GKUTrmyd=;2RR8R zu7Z3tmMWNAp)Dx%_?q2_b4v!hHShTA6P+#PxatKcnm3is?T6?%p2>!fyTe@U$8y@U zA2PnG11-7&xTSWFX-PNBgBzH_HI|zsSb)M4CC!u(o+#HytLTre<%$g#AR@cwIaJrn zyYmQ0oxWag?U=4{?Gk3$JDD%^DGb{?;vwg2o%3T&a9K3zqU@uIoi`KQ#{U`^Nvm}$ zGB8&^)&0o8>cWmQA#VvYZC1Y=?o84&8a`AFGp!n!-^Y}ppcHVbS8u0v?5B_EoU8#+ z0)L_e{=_Rk{ZW8syUJDYx<9@ITtWUR#@YVzy>hm@@oA+6;D#pw&a(U&9W8iVWCcHa z5^~x1{9OY2U3M%1*S?JpQ7+J+b!bwr5_yfm?vCX~on7(9N|JMi~2`Qq~u z_r)N7r}$lM8%~VBYTLv}wd7j7+0qlzQlxbyj9Oh36;f5lE2`Q%F*inV^_Ba(yD$#gr+UFxEtI=Bucq_y)HIG?w_}9g^k4j)PKggd;Fu2G7T;d3Y6A!> zowJRA66AJv!>CUDy(WR>KR9pzte;kU<_DpDtS0`|{D@bi?!^DD9($ELFhX_aP|5e> zTR(^_Je}7a+vsSF*%AA!iT|Bwy%aeBuoV-YgBe_v8cFr6JzpU7ep z)zusF(0q=WpeL$8hi^>dikil=))LjF1#^ZKJ#u)9iazMlaZ|K8EDA$Yt)n_SF5nWv zIWS}a^rTdKk;i6|c zW8NgVbO5tpUd6Dn{YV0gf~sYB5(byWD<3;mOmi1u-+j~?OAIbc9R)F&7h$D!l*j(5 zd&7Pb&(`4LhVKO30aIFdDYSTltLo6~u?a?aBb;^l@oI&wc}#uBUwO9ubcDl6N2u(A z|4??pjmj?gyy3SJ60Rfin>>bc^%qeSJDB=fCc^jNFDm|)it}MXC=4I8y@^LPf-8Z0HxRkM*x2ahQ1+v$j%%iC(=Tl&qrx8r!)?V=ws zC9iV$a5e#H^UzlFhKKawNGhZco8R%Q5w%G>M<~)-Za2g)w+6^}v*R*42~7L_iBDBe zc)eL;NE0oM_Mlg<^5$YTSYf4sEq1&n_KBX=pux85V=wQ^dSjE&PC=O7X~ z=_gF{n#D9ZiO3H&C=vft+*2sFWy!2s?Ely%&JwPNU5k@h|H$8<_~zaO+u)hj$H<~T ziG;e@xMa#hAX8B5yr~KTJ&9jUN2~2Bjgkd5T|_P{`M>;vW$TD!(_!g)$4XhQWg6*( zk6_uum(mb`2(4z48N=Vo8At*!jHV;EMJqN%uDpe!=zlLo77gI5$U}P-65g0wUB0n# z$M}=QT$`R!{)F|H492U_r?X{SapR6H+YV~XYuUC#)BQ+CM{E78c&+is$Rarvwac!k zntYL1Br9G^4Kw`a{-CBj-52n4hsZ)w2X}IN!Nv69qVpv!fBt%OMJKyoHbip?KU$vJ z9Ra7~1d3($zNT||tYXzA2ebQZ=koF1iH}vcY#n-0zv}pkVjd07AMc&UqiyzRW%2m( z=Ng|*{iPc;Eau{6zsBeth5Tc!-^;!y>NowU!G5+&RXUrWZCz54CJF@znZ!?h(K|kL z41$DuB7(_B+JDA$N(e%KV&0gw2DSpQzBhKVXMT5}=YRZHDH>UVlKM9{Y%ld-&)SJE z%+}1#Tuwrr`4>kn{2oGH{jeC*x^u2vRq>B#1E@;%%rQqSk{mN5U#=Hqs zw&KD=te(}>^MkBgs51Z4P5X%%SvkgMyG?1g zqf}&o+MM`;P?75%b5kD-7tkW)TLcaB|9K|9bG-SYC@-eW{g@1Gi$IsE#E zrnQ?7Og4JRuFBTMJ8j-|2XG)Iz4Y>4zjsKEze(YG;7(a<|9It7Cu+&ZVT<|-QgYsM zd^NC4+mNTj?WJRrjh~7jX=dOfYPwc6HLP-4Gu%~-HDM!*S2kOn1R-1Vi#1N7CB3CK zU_JD&+fB8m{Q#UV(;u|+hQ0nIp8rjGJw5;aZ~v1ytE#%lB;5?kb3e1~BiAWHZ2R^R zNpD&kCAp>Zb0Ss5^jT;(3EoSxv+`cv_4hFNUs$|YAS?t13_)~Gogm6a;oa~s8AQEP zfT* zK8+i{2>ZXc`cFsOgmhls%SsAAWrZ7riR^(e=;A3`FL%ZMv@@GNYiT%MdAv0U#)KmN zm||@~38M48sl|>T8Go3*tJWXF<6X~4LR{RM%l=QR0!+lrQx++#MuU^(vKsBJsz^(u zEN;iC$w!u}XJJe2y+K-?=KO~f1O{y>m8XylyVm|TwVyl{?=gt75!qjeVbZ17WvR-5 z(oq)AcfJ5q{F^Q-m4Enb^TH4Xy(F+8Ik!t$)C-JKSIt#Nv9O9A)<*-+3p~%YlXz6{Vh6*ymh`)eJaEc@fKv#6C)Yi$;~x*Xzv*Zj^K>hM!ag&SaC zVDs`$p*sKP&FY_d44inG!t-tp?m({$2eNjKD;Vt(UIW*V^jg!b_zni*zLTOMB+quq zg#A-0Iyo|=g|%>%9=O!*1OLn(eSpQaHp$|8^3OCX29G8hn1q{dlb__~z$6xY3#zFu z$q%C~7*Fd@+E;T&Oo+f4mBI1ciGbm8_U|ww68GG}cbf$Tn4HS_zaRIb<&jt$dOQF3 z87UE*|C`aHzgqEf%-PXZ^7}CELP8O{FqxaaD4JCI|=+} z;yB4uXRs}$-U;p|k$8DO%aOG4vVU2VlW7nyf(|C8B0EiOh*utHIar%p20ftW}3Jk>8hdDs(HGCj!z`N486*cXsn!2jFo@)Hv ztdc+Ws6;QbD$xUV=kMlTPxs|kRdUq^_2j>LRHBzkxfssHm3rWYMgQljCfTQuKJU)9 zMAAvo1yL+4C@~4g0jK!sMUGRHic?@Xbw_~XkLk%NzWjRU9RDK0dpn$B?yn&2U)DP& zv0Tk%@HOPqF8*-3EiBA>PyTR}Dmk&yk^MA5S4_$Ahbqyz!7c3mouG*rNtFuP8?g5c zH7))y#?~wIAiB5T&L7OQfaKgP=5U`Xk~S#k?N?th{AN2eNIrWphp_$`yuRcX#~haH z8#-g(qANE0CHJb2Q)J%@UAS%0G+S_JU~GX(pOCbK6W7^2{0@sKK<=^ipRFO68UNZI zSJ>#d!Y4O(b;WT7$6s!`C(Rln)`1;@qrnwDFTd{5K>$MLX5o52tUmr1Py<<6o+4GyaVsB)|Z>?rrqDwJ@k{hdU>s1 zvi+U>FDsDnwrqQ=vqazEOLt-lbKlC z_6?$QT7I5&a5vimv4`}n|?&x$v2Up9Sv=JLFtgs;d`V zLjeQXNR)3|Tqfmn`b5d@^gvtep7)=7pF9P$Jk6;mprtE%L7|HRutG6xg<@50)(V=S z*>6Q}_QMbr)&Y-UvDf&gkAzUYA%nLn-9nHUitlf=UWDEw>hTYA1yf(Rf)3@Ku^4=v z^fR(ZAT}^0$92-VQg0mKx(z2#L_>O^y`cPIye&33PKUgZ9B21ofHN`i3u`=Fk=YOg zZ)#ACgI9Upxg3UB-F z?c#5?oxu2cx7gYYVou_fZ;utTvd}kb>d_+FiV(C?{k zP50=xYppisDcG{g`A!?vp17WC+J68)dB-a2#F9YRVkZLpxP@mLPGNdD(XV?B=ZNni z#T{y685fv2TnyhHT?1hTx&|`CKO^4;a^v4LkejWYtg$%$H2u!r2K4xt06Z2&(X}Yz2NcX^d4m`q!)kZcQe@*_D$tK&Eg2zH%7m`^Pf{^g}Eg!dbKD2`OUwA zhQ6KuL>3v`vn^f8#kbORj)6IC7c9UPPc)vV_}9bYmFucCbRvM;R6vK9F4Yfz5EE!= zYYpS|^T&(8#B|M&k4MlSx@u_uP0Y>;N%Is3@#k{PbLDmqO$dhE0B%` zl@<#xw36JsmYLj@+I;VJYBNn-;>W%zwS0>$i>DG{~r_AsWL0QdQ^`@UWF(LyAjX9e{@?!^7Gt%^^tKl z*>7M1rT+eBe%TqWC3Tn>iT+I%yth+u8r=>rGI6Xj={Fn0Hy^%`^@jXJdw@8nPIQQ) z#BTKWI#NSA#CZerPa1L3wOt<8c3XCB!VM<0&`-P_;)k}HcWh0^qGcgQaAWj$2)F?+ zn#r`WKHJ)G8;w6&uj1MQnM4QOSd4+;^TA9y@H#w=XoXWiS zFcasBbzyo#AVsO)KlvREJ{)uigzUll&yd_(UzVyzaIhI!jUw9LGwL(^t4j=%*pPF& z*_9|9Oa6p>-m#MW+T=m(f?L-(v4())BJ_)Dgqjb|2(rCORa4!PYi86WR@Nk58MQo? zNcn&Mtu%gYRMzn8C>F|75!@3uMN*#uO_d9d9Xt7i6Pk`ZXTc@?#*b|}xaE@mQ<~Tm zgoGHsq$;P09f_A9UC#nOowCo&(*Pc{7CCQCNd;EpA3MmO@bu}0i0MAcTqHvj3jzC+8nX6h9w zP%L10c{kh$2{ChT=oVb_x%wr;6@F6%YAjcn7?wDDi=~V!R^1orP8)QI;;a|mk)N!h zI~5;G34vCalgQ9tu=Klg9ret==WFq?ptp%AK?bMUSJ-+(HWV$lZ_2|b z{%n2Y6&$7kuwsIqIqD0`RGlRHGTkuChB}=6My#Tye`h;whE0{X{+NTU6fk!u1?|UD zesG2fzEkLH^f1Qa6@2=E#D1(pRyAV3)#`$N#MbNmL9XDFK|xibzAU$b+5^ZGsbh}; z3;>QY%}w=ESZz+NYz+mQe}iZd+ximX_{~|gDZ5M+g~=^&&w!wh^;T^_iL^h%zj`n0 z=%k>1D?s}*tYBvQY&Wp>Riawm4BEf%654<2i*IbdKkW-?iuf!d{au`f@Y*@`IgMw5 zi}wsd48L;>JrM;v3H%S;&iPSZ}&jm_X9{~!UhI-j*(PxGW0+RpzJq@&*Qw|5V3tD<|;O+DzoZ&18`#<0E zji6m5qcd18(27GgAxr|*|7Mg^2LjcTsvT76pY|q=ISQzf|IXl=&o{9Qxa!`2lgNth zaJ9M5g6of%b%SfrvX^&m!w@=x4WCNL-!(cHuyjL6g}K}>Q#GI}RDZ!h5PV4xj`wI6 ze)!ua>HBc83Dy^_YB7DEo=xT@S^4?^txs81J!n<=KiDACQFbi>{!!JdeN|Pf$t7ZV zM`l$r3ST`iqV>AB{QX_NJLTxK3?=U@!ppm@6F*wz(%F>hFrs!yyY4@mO(2Ehj&oDZvX)MPzUH;H?hCGjS=O*5(4C(@~k z0|Cf(xn8^cCl+-+XGBrOJAcHh-!3pfU)x^!4lA0?xi{oze-#{_Z{qML$HZA5f>o$q zs3KHrc|?LwPUBSnjDNj`SrFL`NyojjX-`#lM-=~}@6-oZhe1HPUVzR1rn=q{xK&Yi zT`gbG98F%`qDK{*o6dFlk7Tu4_IpJXHBL3aQ5ByAYd)Qh>Yi1_p0id>)4i9s=H5as zH``hbhzyHv8DRk9$DKzuD6q@i|3XS*E)&u;&gqjQ>0&Y<(A{)$-9 z0zFS5>LPi`$@xN^;nDbUIZdQz7!a>qb*L6~gytXTTRO#j|1b-=NLzi-hLO6pQDye? z&vte+ZpRE`{X=ce?w?Y5%B*`LM1?>K@A*-_I+Ct)U+PTBc5mNL=lfEPuUO*)bby2~ zZz8627V{+sD}b$K>-;{qx z3jI17l|hEiahqxtq}6_8QIKD=S$$|w9~!h=h*60b8CUQMrkotECu{n1N_BioXX7C8 z4=YyDKC7Uk)YwB{i=|zbdMqcd0{`kCeu{PYvql!mph|i%%~x2o#07->jK>;41H)c_BA`7pSdJ=^zxDP=F+?d^;!vBLZ#(?5GQ(>dhd^<3s85kJaMvq>WB&dpyx z0lu4!XPg{xGPUJKmaL|OE#=cA3;$}6Vl+aFDujf+ZW$h&QGQa6olzcHvQT9hHaQ@w zSPj}Em)TJjd;pFTR#GtHL=Zt^HYcV()O|Sb82gA1E&|jPj*Uc_c_~Q$P&1qr3B&$G z@0h-3^YTYr>!1Yj$mYZsRVon`^ z3q^JeCc~9~1^DGRofv&2I%P`Tp`#9A&uU@gLH6*N^utj+Y&v+UK_s!t9CaFm+tFf= zN4?VRX*$4&s`4UBUJ0h9N&}FDf8Hrb_<20_M_;M+H_~eMcxI)F!^ra^3$G8rU*6K( z|B$A6QLiq~jMt_XzyM$iXWXe6RZJ_js57ZMt>RVw_YGM3Qn%K)KQ?SPb#oR$b-Qu+@wF=G$)g>9^q;5mJND?_b}@~W z!hhl6@h|#ce3+Q{IB(2jSXhQ$)HlAe7~OsS)ZKCjPwq!}a+DWeSa|aC;&J6G8`q@n zh1>tSHzPk7VDl>L7xIlpKYDJ5rtSOU!*AKzG680(yohU}Bn< zQm6_U%s=YM%qf-r1(AgkT1WXe%&?=6U#ZubG)5z&aF<#<-GZZUQ4DKm0Wyi~v3Z08L*&bnGdIiasc(d7I(?bcN_> zob%}P2CLmiOvB`TUSiG|6k2)Jnty`*h_*T|()jyzeo0SS9 z9?hKRHULGvYl0xbAVh(C`<^y5JPj+?A7MMG2&z(Uuz2Ow`)DfJ$lWK!uI+8a;+g%% zUnYmRX4OhQqW0sJXIo)>%$G0cUOwhW^uxcx*TfKC6-!Jgj#nOQ#ZW>nDl#Rc$bXsw zc9!1_W~fx1Nivgh+ym>lyssqCDwy`(P~ww@IT@V8hUHdWK%j&GNBOJNR2VKAP2R6A ziOi9#I2$o}YOz1S^5>flin(r^MLm1?A?IIQpFG1RVK)zUHCnJX+F1GcCs*N`HvV3hqa(kAIw-!oFdxyE3EJFXjX;$a|>q-Qm+% z#TjglKQJlg%TXxs21BfO2cMxgx2tU9DcPAIntEcfp==e?UZ8F=@aWd`02H7v$-D967``CvF1BiHFKkt;uuvr;$_ zO-==n$N{?fv|8u_rrzr(tzM&izz)bvBpM9tmPWX;V8n*%;- z52v^e<7nK0`oX3_DNsogl3Gpt#kF*QvBpA6*I7%PM)F~cn%dI*Do{yJj-xl6k)J>%e=ecqNwh`6X=Ron4V9jNH%y%F4Io-L}yQ=wmPEZXk zc(mY0m65u~ihBRv8b21#Fo>!!SW(@*|M5GbU7K0wm&Cfj`AYtcr($2z^TlJB!qb7M zm-nwzWrB9AxIcS>Gr--c4gx@7XqWsi`={Y7oRRO@kkXvrx9N;?7F5)o)O1?Q>^?O* z`y*;eO-V$tgXI+@lI1uaf-VH+6SI-qRMs;3fF{s9%4*VFoZnO&U1loFVNzL!5*fUv zY8op6BcPepRn57^HPt1@#2K|%UtsUGu7u&B0TCpFC1JtiS|L`Y*?w=|ho5BC)9rgU z)htD@8bYgPvPgXG|M5?F7{cX5bDIgWtae~ewn_B6G!#~tRY5S&|3AKWT=~Qz#iL9k z0;O2eSDC@Tox$6WHw1exFNedim+i)Hzcm*eCC*^IbJ?h%0J2e6rjUAwfs}kZ-4z@h z6nrBn=5);-1rMad`o`Y>U15z0OSY@;0xCDuff{Lj7`Cm`XPs1^InoF& ztYvuP$xohRBR%=K-bYG3$l-pYD|K*C>J1GEcm%_oef)NYNqqc$|KE?Z*AX4^XgGIk zI|+jF3Kq2YKB5MVsLKDfD>XeR)ony~jNi_P{LBCNzZg*4cb&PANV?|Pkw0s6H^TQj zR>~r5q#fc!$SS&#IMP|Zzv*w{oBZl%`%h0(mXojV(sX9)*U5?bt!$ul8Dxsu;*|sU zaO;zjWU~_PgrYaHGe>ZRXQBgpiU(ds%R{U5Mz2CL;05-wjn$TGm73@QeS@AVL$Xf6iYq30F(9rs*?2 zV5;__Prb!ryYZbanYx>O&P-hmWMjja!6LbEHY+r4525m;Z!Pfi{}lJDQxF&&cMtk_hES;VH@uvIC1tVj~#k<&EDZ%Js1eqEZaf5xL4VrcG`1PHiLYJ28a-H*9Jd!C799QzUil2%p$ zx5nHDdK7=WFfbhL7*?CM-$xc*FBvZWeshNXJlGc=bq;?jz$ip+gpPo;p7*|J?M?oUVjO*oZPI8<%!suEH`4_YZrka6<;dmGqV6emfnzGKQ$cxzTBbMJeWIKA0Lqj z!oT^cdQDUnm~@k>_-q?hFrIoI9PlbJllu-AR++sY-D|hqguY~G)h9#`aITZK?&{Vb z{R*?ZMrlfKg#i@I{QdA8k`3^iE*8sPO@{W**Wmvqg8~j@osYM0J;$SL)$bYn_?VEX zAL*u;zRo`@ZAKe$snijyOM-Th|A~p4!O9yoY;yLS&!nHEt0m&qRZB(&*_Jf!X{IlJ zB=l_nk(yV@s?>LLMEK#4E@q?%qk{!ruV5(g7e+-dlLyG_reb1v64DXx}p`f&~ULz?mz99uW}99PyB#vrQ)n-5^gbydw{gg=OWg)J^eHa4|3_^0^0+vP9w@(rIpy}KCT(^|N6)kZv$8VYW8Qa|4-dgr>+Tx ze5pPoOD3JthyEn%Pw+PRCs*l%B`v&*CU3N9@E&y=5J-{QCXTdOTy3*|v$6d1!Lq#H zeTB8rTjI7t-cb2OC&z#)$HkLc?9Gd};Bg@V-X3RC@jq1>D>}7S?I`|ZkZ^&xly)AF zNX9b0!OT(pNuguxV~&=PW7HC|V++OnXSHt+Ji3z`m@E{m&^h=lyYr*oVD{vbcPU!2 z;X;cshl%7>u8|D&l0W1)*@g7h%8IO6J;It4&|UFd6}!rqVlnU@nW_wF5OP^ffTdCL$f2 zLe3|Fiuce<$OG;6B%l)BEVWT;?t{70q7CfKj&l~#t@R?!2GqzI!p?HPje|l39-Bni zH?Q=#;$v|bC0AXz4t@nI4eE}Jf4QsbP-``#IFK<~O(VUU9pN9U2B@joB+&G?3eyj} zeV-u|ZdxcNu+3$lQyOj4KQi#^7%l29KjHD)n01*Z0~9-IG$@8VP+REWm}pZo;-4L@ zup|GMF9N?gGPs5K)(TQ);oGoY@U659-|7hp5WYRNwabp~k?s126w;hv#bEUSF7|t!Wd8MrCH@tI1_#N=>zpd&J@9M?BUb!>_^{nbd7V7O0 z>4AD1GEr|d!4(~Uwc? zX0clwev18y#bJxl)!oiqz~Zpkz_IvNT`CIR-*f^p&q!Z`y>xb%Nhb#RNa-vH2hz zK@p~=4#Xc3CFL|#`$v_Cw?12t=B@TVajD+3rycsV2i|o?dQL`tOOAN>2T+0#i=vQ$ z%`;pzjs02sgO7PR#Q$_^h+|h_n6D^*qO)TmEp@S2gV}<|1xh$s$apiKnr{wfocRp& ze)?Tj|NJ6Q29e<*4_-c8A}YLG zqYrtx(H5Ye5ioSP7z74$Ef-n33A<4h(dg9A37Y=+=Ty#gJM!p3Xs~p#(~!AW@mc)} zM`-00j?kiF?xj5mt;&e(Rl_N%I577XHQbH4Kf%H1)Vib98q(M_f6jbIVALKY*a!%W zij<-C;hlsPX7_Wo?kamv{DOVlxIEAmV@4ps|}u{0##~Zg(>8 zPnX-kjX#Yp?``l_6@`(XS=U~&(SF0w!*y*Jt2jM&(Z^h~{|fZ1bVxvsxddbX>yByW z;>I57c-Gt=PMSCV^ep`45gx`Xue8zxhsHz^0Z0;;-%9V;0Ui?3f;DCM5<^=-+g&`#xXa7k11f$6Kb0-s#s@s>N*k0Uu);bs`$+ zY3$a(&oq@SqkJEePyIcWG|u%;lS3mQxGhiM(j}j29di!l=l#v+2$Kq(DIF0F;{sL% zr21mH`kntVeP?{uhM-w5@}Ivaa~uLsk*$B<;-CAr@d+Q5erLPm8@;u+@dar7t4}h= zSNQ)jzEAG{e;D8X#;&t+pfMn3qwQ9P7p)j_?F(8~6viY;23|6bX|f^!H)_-ApQt58 z=5%ei(v&ihTG5%(bWMoobqX7#mc|K8@L#b(c1>{P?2HM95lJUZ_VJr_S_#4+H-qeC zZ4lx)&3h^HUPkCrxNn!2p{iLfe=d@+I)H308?I_BlP3QP~Wc6k#m=3CB zgY7TB55Tsa^FIh&&9+ZfmHVr1ba@prO;bM$>q)H*N9g#+6>2m)h6*$)MIn(n>ZiwI z63SN*%u%UdnK`O)oG_jeE+!muAyGcYSbh*dYf6TTuUTgHkC{Ofga7_ADJ$VEY2NO7 zN2F13Hy4M-IHAJurJB0P6`JTCGIZK zWJJB-is-V|o`<^~N#&q>JJ3Z&qb4{9hC%E}1N!E6$xn!$Z`qup>sa~f!ezFVXT^){ zoq?4v9c5IFchWDN`AlcWy#{X!6$-WYsQXYYEaY2(*{gj1!r?B!)Z{yiNq)z9k{Hko zo&NFUCH=5q5hEiu=Vk_px`paZzSwq-taFq$K8U$*e?p2Qm#tE~z)0qi^SLapEIJ(J zKQQ8XM+}vH9oaYN8mgRfSZHkoOsd;lAb$8`OZX!n2-vG414Rgu6QTZgzwBRh#VZ(j zucV(Kw-42sh%3{AeKMxZ&v)f=gL0}otw(f~BR!efXZ~rGzHpDLR2@)Z?14<3>#Hs5 z{$Z}x)I+YIb&!I^K|wdyZr2c`DGLBOzM82{fjK|CaSv_&a(>H$MA- z@##wZSLaDiDG5}`ba04WZejbn-~5gn zk5!Q|o;R$@yc>>3Nc3C=Ie+FGMsBw}oH3g;W7rlTZD-TWmPaj3zU-^@YQ0Vq9RDJB zegRCBV$-uTI>~?nI^cgSSQ@ZXR{f4w*^O^Iiu;nWi6i5@4T~{`nSyKe^%ol zYQ8}woAOsc7cV~yWnQy@A0qCoOMEU!Pch)p7H!Bqvb|o?U`HaLz-pnNCNi9cBPpA z(_7{5cxAgJ+4I}8M)0jr&p*(8+cZ{m-2-&~l05`n+k%%(=b^!3sX7(Xe(xNiJBR3g z-}_hFd+Of+t+$!{nIRURb!#A2i1`RxNZG5VUFDFI&Y7?&|kYPDTQAWl75ys4dJ~aNAV&k-W4$Aq8jR4yAFS(3l z-55)Xu@Ag7|IevA1ofQMuMGLd^b7a`DL(&MJb%v8#YrdAxIRf6b9IF z?w7TZ8+pjm7A~eKYg0o79PI6kJj64}mFV<@`ub=8n(PwU&)nE&{wfqFN5Jxf{Z$8K z%g?pRbBb#hzSD%KXH337r$`+QeY}417ItQ>iva`E&uc3VDrwqKlPD=kJs09k=GEcP zS&$BGGz)$Wf?q?6vpleVAE0-z$QF$}83o7I`iq9>x0AM3+n8BZNqYgFAaWC>32>?u z(l?4l<25ORoiBlMAD$jDlq>cB{+hAjuP=oSSFCLsARt$z@*buQ8beBK8WdeH+Y%Ve z%csST%k+Zyz(01SJ}~_BrbR7y^S@ghZ z(9SA<-?rD>`5|%(>wFhdQjnQCIiKn*JB2)0Ufw@ich6Zi%0P!NI*_Bj_6IC^sk6IY z?>w|&(;{ei1Cz<9EmMQ-z3`ttPZMvdmsurb+9n5&@Gq>OvSNdlo+FRu(q&8t-U7OO zfALKLj*GtMVw%fD$Zo$Key$Qzj=w)c_*pOftQQS}uCi?-lnGjLO^S{Mu%^BJ_(a!J zKo`!Gz6fooDC07txS-B{O+yzP8y#Og4##C;t=TRZP(7qNV^vG@z?{Z;24N<8t$*Mq z!`zZzOAOZ@I{Gk8V4@*xYV0UHZ5og-X<UR#&9Ddmb!EW(Q4Bi?V7`8DgXoJT9{U@^LXu35m zVtd}Od3&(d;=%4EldSFbc9Y4DDT3LH+F&TEt zP--wS=63s>#S0`1GFtg{*9VZYL&jYHv*RB=l>_-(;vbUJz|SrZyTH0xVBPGGeoXaC z!9#yA)Xf_fB_6H(dzSi|O{sxz*K4)+rr+G8P!34UDG_T;2ISi={SyDoSQGR@Upr=J z?JwRfmOOzA$$;Wto+=8-8EoN?~VvoAQhwxY0_WjR&Q^=SO4SH>$Sdk$-&Z3WN~ zpHgC7##E=;xi*hbqp`%UAz+ssiereSz%35s$8zHoaDLwKZ>tumhZ^ zr)ClA`80Cr5?dr!u%qkA^j^07n%uRizIqbEMkh0H7}D$TfH#f@csET|`CK^(jL~(!D?YFPaVqa?2L2-j^FFEo>r|ywtwK*}b!z-7S2?M!rL% z$?O;ijdMBgB&(U>H<-n+HbBOH4p*i&Ng#yNL2HtPC_$mP?Uy(0L4HV$BkTZ=b=cIc zRGS_-j8BPgy*z(B=#u|jmvutRm5S}|_@0eziPKBtE9fl2 zg6*Pn82^KTx=N5mpi?H5r=O6DHZcyEp0gqNf4EBlXWBzaS1MuOjPAColAU=7RtW_>}#T~&O-7Hap=*j`9{`jXK zWR|*4>gG_s1oLbsbt~K>G39V1;bRUb{?k4~2n;s_4L+RxRKcA;<m+Y9#7mlgI>vGHv5GYpo&dN{ zxLwdAoO89m&t8I?$s$(@`ti!b4+S@riOcjgAwk}iR*g##ez-jPBna0XduWi#j|Y?% zJ>;ON#i;Ah^Hu*2kcc<6c5fB#Q{fd&}2w1??mf{+GXC>BxV_xnWvtFBeY0${p{ zA3=VB#{_{a{py@GEiF9E&24Ee#oMoRd464)r~yviW(HKD-w~|!Lx1leTdw9=!SeFg zvHhd(7cyGNuZVF7`x{)hpqK?jp72oeV$EeC zXQWfF|K|M;6jgvCIN01TxH=ei$3CWB*#5cuoN@W@h$}1}W^qZ}9jpMs6_@oJ^f9ef z-EAC2bYn&r2G$&!MA3YX!)C?2@PV`KwD5ybZ2k{o$bp5ZD_+4n^*fn;%+53&sFrn@ zsPI2|A@hXH6iv=$u3$7~9=bKGOLWT4W9^O-)6#Qpuchjc?W-e3&2)OHy$*^6JWd_V z6;o8#VR$vkQ^}22Q$!D+IRSIhxzDf5w2wjne-P(qjP;tZDlu$*+A^E->mmzx5ZCgC zd?Hnb1*wfU>cRE8vVZDNM1$`BIdjbf0VAS8^WWEu86)tmFlxa-7ZBnTf>Up)K|(w4DZsL0U#0<3n^XLGUW~ zqrZ~q6QG6{t&-S$1gXKpLM^jT%xOBjWp*j+U!*lxz*VLZEJp0cJ9F01&{~9r9E3E3 zQDouo)w(xi$%0tHYl^=XM^Y0p5lA`Wmf^8bVNoly1vF$ z_|pv@wvpsJfx`qp&c+6K^`hry4PG5loV#WroDE?~LB=#`3(`Sf1{E{kT&z zoYjV)S8C=cb6jAKIx(NEr%|t(o?~?)=kTu1|J7H`26iZ1@)$*k2KMrPbNe6|DE`Nf znKiFq=l{_}!(IOHuDHu!u^ZT@qIpm>qKWDvLR^BN^Fn{M1v|{+MSM+>ztmjt8hzTc z>A#Z<7m9D+Up`CubBhGOLcyVp1 zV7bcYw#+UL7VnnXSPhz1R~KW*LXB7QqcP0;DOG5H*h-WuH*Yg%)%ue@61<1pt{F`r z#~=N#KoGGei0x;eh>Pv7v++#_xc+V@KHX^@6z!J>8`5U7l*Cz?GhbjTl=KoT+2mKe z(THNVpFk8pzma1Y`~$BL6{L#@j{f&A4=3ws#-D|PhTq?4KfF;Rp+e_~_a`O(*Y?9% z-&p@93&={>pIZFCu0OIUkYA(1u`1zMmCd=S;1?9O(tokqSxox0fkBo9VqDr`n81hm zHpj1~A4010XDGasi73_j65pDOOv+u|>M@0K#{A(0XQX7B_`;tqu84xUx0Pv`Gd#yE z=%jm!Qn7Xu>Dv?*OfI9AW8o&0OznaBMB6Z(s^vwYqDq{zW=t_|(U3$=b0ork5G=Wc zM(Pw2?)g9YrxMv`PxJ`@Ph-gMcqf=>M<1U%{*nQo?a;^hu)Q>WyrHkYl|C8|U0ppq zn<|FQdR8XBAs5-Dve_=Pn3Lx^UrLSGK0a$$JH4%8G02uV#nOM@Gb2hCy^#Q{bA4tl zw(^CL@JA+lQoxayg@8$AQ^2?5|IvUX6aN?eU*M+&LuA>ggm|DE>{o}?266)ra$0lR zYyt{Fpa%Twqz)SfKiTIW_>(K1(`KeR#6)A>>;P;_^$$yk-?{8m`Ty&9QjW?fm+peNy7OtOPo+b>f9pazq z_2ZLH;mxpv{wB;TIG9VOGfK{+dbS}p9hz0cIc@3hAK?2gbF^cyf*<~;z8sZmX7-7Z zhZ+XbkI15ufL^CnEk0~DGI&<4)LEc4&GC2YHS2C@Hg;97t}4#W_$caOc93(-Rz&RQCMAycOG}8MRj{fU z@JP+1lO_a|`==TMwifilCoF!%E;;#j2`=F}G-}HvN zv(DJ(G#U~kb3jDN?!-W43|3=oA_uI=C)3~QRQ^r!e&m&1V~g3T)4|5ue*qDDdBfbJ zqx9%1dxXS-x{w!kA+=Nk=2@t@JEQUVcn@?nUAbdsH+O>3KdF2(?Z>n`eu%5i8dIcX=LACj1>|E5ccKc3~3?W~pA-DrQp^-lj@DI!|%zS9ZsHhnwl1y@wp&7x&A zge`W}vc~xg>nG>%O?Y>Yv*F&G&fuh*cA0C;(;-CPrlG{|*BcuhOcC0Z)fMtn}ciGP1p zJ+yNf7wf|W8>Hr9a|?F=bhZDaiMgELIh66Y-n}cZa!QFm)ohg_4xIGK0OSiE*G#Nx za|GiJIqV!H?26}Hl3-0jm>O3J+Vcgii1)fW;N|U4<^G6w(}=}8hgkpSkOKer1DPI(~>Nvc+t&3a({GXpmsU17_LZ6XELHu;HI@2Keu0f_HjUyT_&uLPm^8;69AnZB) zg|LBNZ%ws9Kf0zmz}Y)CY19LviCpp*L!Zz3FUhM;e11}!&OzL$5Le(}0*bp$z|p@8 zCxG==31ExmY+!den!JNB_Gky*W33^;tG)W+>9IsL^d3Jq$)Z~UFQ?66y0P^<@5|qV zDjOyVxWRzEVQc@$8jl6r%RBZN=zHjwV!(n)T=_)B4*l_$1W@f*mM!meXE9DbEbe7} z7Js*;dBGPs`M_%jSjR53M~XL|fOGcb7(MBu0BSkCDX&PJ5oD?+SBm<%V1FpQ~U@u%5Z7SSP6tK%V#Zl^OH-%YM#S3Xv8G}xy{o(CRB-Pp^Jlmu=erzmB9DUAXQMBi_gfcoy8mzkP*Fq&?4TSJU5n5ZY5C@;wxAH}daO)x^jMCk)Dq)WCqV$8Ia zES(cTs^i~1h|$sCS6Z3l??Z4iVchVysK}r`Syu!xE&RLQ0;p+{Z5jmq8TMN0tpvrE zIU{p8y6Uskk;w}VLdMn412E2-{JCuti=cv9^_3GLWvGVPHxQQv)=nb@VWjn40I_<^ zNL(uH#&F>Xo5w}&A5(^_6;3k-WMRD_bz9R&fAL37;w$S>X`}pX)a)u4mz;Rec%XEO zg&rI~4PfOYabORnE&uH+oc|lKk+_88r}>91CS5#?1WCR0vQt>EO+m7;ek>HD&)L_kT05An3)6Lrsq+sjvEoz}SV4VoN%Qn3uKL%zBnwV`6zzqvF` z)=-ND;VQuzZm?0dMke>lNtRb-?>1AXtUs5Xf;z9_Gzk6kjds^%JrI+K!kg=`f)CsI zLDNqPxH$bJctex;vIT3WRqUsmCUt|b*w+lk|+%?969JS|5+>tJbqKa45 zLS1avM+0%>LEBxa^7%Y>huoN;5_#mU<1Q?XKKE91#d~{4|JE}9{tX47N;LOliG(?- zWWnuL2^~64Ql2W%KP`?<)(KK3C2w}+>BJknZyUAFf}8vgZhOJFsnHkoWZ@}Y->57L z!nyiv@rS@Jo{xV1Uep_mXXk2rwPI^wbj7ygq9fVl+3%$E`WW9b zByw3E4nWFc*F7m!gUx8gRyO;uG)K-PuU}2ntNMz3z5m|^B_ zRRcAN&gcpzZsbzKcc z<|WSt&GXpxAUd)=?W9aYNNlp6ZpRXS4BD-C1M6F};wy&DM7x7cW8Oi)>Yr9Pc)S(_ zsY(1jyAyR?HPum*YH`rEnwIlPMoo3pREwyzXsaYLT3TxF53V_zgze;wEg(u`OKxP* zGrW$0-1qUC1k0xvDS?+~U(q#*HIX zcI>#tv63-JKhG^hB7*$XNG$POEb(ECoO-Wpd%82`%^jwsx&+*Z8M}f8@b0NX4gga{ zN|!k%91VB05KD$#a=oreJgtFPZ%`oG_&AnuX@)iE&D@V&JY`7EgvF;1$(^ux+>kzF zSC1Rg_aOcKKeW9IcvZ#K{~weiQH&=bksw8*MvZsy8dT~Df}UuQh*smJ8nx1>v_?!Y zC`w`yAwBFGtF2b)TY9I~w%F1Zg|Yv=+BXQD_3m7~$=9!Q^lR^P=T;T%qt}C} zcZroIk?Mu^!va4vxyjb2>;V?wYWopajY4W%YPT3=LI+`3aH!tzf4Uy8%c_s9hv56H z2SqA(fR*dYdW_vVOcooqSFCa)O7!=@bM<%RB>nxw#abN**8oXVE48nXi6Jyz++l^C znN9>!eY~{{hpB@l^^2UrBaqX|9cUB1pjN+K*5S8UEzPa zrVZ+kg@+wtw6J1$=Ishnam8$X8rr(YFvj8oAT(3%!slfPi?^$o`^(p0E=+}POhUQ~ z#j3B75Z=46g!awed(74`eH?Asd%6~pO)SzwlYmn1-gqFZvSpmDlyVyekXm7w0EJ}~ zMbscJD++bnXHu%NY*PE0+4tb)} z3Zm!p4B!GR(kotkOPX?f5~+t+hBXyX(89c`_~hl4!CX_aIwqIlw5=suYu&)k#;Zw0 zO75n{OBF(G=bAZp?W?%-dgcuF9h%Em^$+Rou18IJo2?5p%@!E_+h}hisuAKv%SxdM zGT-=WH{&~4rFN+x5tW2^Utf+fHr{?JS}K(8)J`n?_+57lXt+}LF_Gf-Ygj3^ojBfp ziGKR6!h7;Q-ae5BQ(I22o)T|AouAFO?@<|VA8n;NyVSAPC7SU8@%E8=efrVy_M!F` zxlplgerpmrn(JD}1#3d}>e5;%)3?>y%x!ZoeNjr*YhslT*;p@4CV$1M(7)Nqj_CkY zTdoV%yMOkvwcqUH^C#9|{uWY@8gs{g|G@n^|bZ6t?JT9)ZoUlce%c7jHlg1vV z7*W}GsP5ZH)smm<-vee3jkil5rOxO9o$+}>DuOuomffO#6E}(^ZC}q1=}+`;P-6+* zvmDXG>F7-5h~AH$?sc)?-?osF!rSd!ZKVeVN0Nh1c$=ri8;Yq)pa^K@9Xy1Kx6*q3 zjPs|m=>bsezR?F|c=YnNOtG$0w=N&hFs${D?}H|%i8$07aWJ27h>TgR%OhnjGK#65 zB;1O(f63||fF~iJBzP|l$_#>zda4w4Un6@@#e;&G3qEjUKRGBfGI#i{qk89t|5u|@ zq^Kt;Gtj2)D$ARF6Z;FMFVtEccdIU0^j49g96wW>_9Al5I}KU_r#VpeT4M|ZT|M?cV!>)ho#AXh&67Oa1S7fGy9w#cd;Ic zvp#_Ln;HjK1qCO6@q850-g2=6l%pt4&GyIo@Hi;qd`J{!^L^QU`T3vV{JbT!nx{C> zw|EV2inrB67RGdW{@RL0qV9OQVM)B*2=%_;TYoDGbB6!ocyHgd<&z>BSHt?#ktBeJ zI$6bzIa;QzeZT^XS(?2+wY6o9cME=uf z+4Vf`{uKi3;ptvrt)@dBI@Klm?dO45MDpLIK}>v{LJk6opi_Zjs^Q+SXNq$1)!bL~ zAT>Qn97Y0@C1Ej#+4l&5s4rHjF7>&ix~BKQWYARXzUvzRdj6IBlpd^32(jqw>rbh( zCi>c7J32Ktkw zRZ4w-x4uFA0hZ<2vgrhu((~<%(tV!@04W-3p>5A(>xu-RJh_H*w({~B{G(1z>`X&r zt+O&vN4aV1Xuw1sbvFLJkHr(S zY0Z60E2giD(=Ow|chPYe+rE21q$Fa!V6r42g>r7Z{dT|DIhje#{#t|m70x+LejoiwjR)n- z2Fyk#tcPW;NESubTZub=j(%aa_d$dfmj=Vd&l)D3Q53HlX=Ps*^7E!^h&TFbmPI!A zr{V(^c;$41r23Y(Hfz36PK8raPVL&-l+0_a)n0^#%bT03^K|AyO^x&m#Ow*8hvKi^ zs}RgWH6#n5@o$Z4i$=A@ok`?hD1RI=R2;kt`;I%qt%29~UX7|)yed%(4NX9{!_T&? zRBu+ajyw66qSz3@WU`kCil(Hyj<|>3XVXsFRHcVhGMGTlfvInTUjQ8-DIPKyxR2mj zu9FQ(U9?vIQ47R){}%Y(O!o{7(Ue=+?NSHgn+amALx#Zs*k47ozTVa)qj9CZuUh|E zkd)&ZHT4sa*A7L%I4?uRXf*O_*8Oy88>oi1417H&Zbin9}xJ$zPWG zJY6T^{go;7WT?^N+NU^rhF-#$nZ4DR)$5!6 zqVizs`MH{5eH!NR)w-VF;nE-^(tWRuf*qs>Pmmvlz_U&PJm1w{?d#|F>}9?Wtpxce z3K0tY5;)5*0n>|E0(G!1EdhUB7TRk*D1Xg0#@D@k4ZxQc8i-$ZBVG^ji*BrV!ase^ zgkIs-$QN-|wr($s&x!JJ)B>Bs?^b%33DDs)e&bQO7TnL*ehoE%{PUzHgV~n{BE2n# z8+V=pB336#D2C#aC}T(rLcZI7JP|FTVja2ERBYc@agX2WO`Dkr8@ilczbzKRM|?p{ zxXOB1<`sh6_>wEaQtq3lFtDgh$Lm=QeKT4peno|PMdm|yNAIx>N=Q=nkWQ|9&$<#x z^lBkhFlyD#qP!z@&3x+1O*VatL+e(09EYWw4`;Szr6!z^ ziKt3L*80nItJh*cwZ8k+>sbDzCdF+5{X5-0pC%ydI}w7}{#g*!6q-r4`LKtz- z1A#c_VX}E|z+GYXru|qjt+$UJ5dWI>s45k&WFvP~aPQN6yyJym0X+OKTV$~;EfG{6 zFmM}{9S>m~chB6(d2HpX0sp?0I3&-`*I;XDRzWq0q3>V+WBcQ`+GX4}E^hrzUcm4Z z2^k$P{^{YU#vsceKr+VLwz z;$J;oymSYI?b(XxcsJ#k&?F2$sWtljh%bC`SXhk~YT~2W(Lg z&sqf#sB+_w2%hh4EXwQofw&neSjW1a1@?1`r~jMo^z<2S?)O7~1hC6((9jTF;e}Ut z*bKX2_rP8tNC0f&Cw#%)I$y9qplfK)eepp9^qi~z3qU_#2cXZ`9iWq>Tm0_;jr}zO zbvdBkBLnJEfg1e&_|Q&m0NRgcp#60ZZ8v?Eqyy++5Suedw5?#w{-hV$j}f>73MD%g z`pmW;MAUW?^{0A`hT7`bae2JJn zaVS^!;=JtQ5HOIbn-`so_Pn8-&tt=Uj_kpPgRk-U+T;Azb`^7<8YuweQmNK)|MR#6 z3an}8CVQ3(i~)9ipB;Q;@WQR6m9NHhLOg)m`L`0kUR??*P zHvb#W->rc(E=$Yo=S@YJ{mt(sQ?-?DRs|}qv#Xcf*TfLH|FW89DX>v5vY1(#^hNwJ zL;vO*0*Jqdx?afLfW-_odEX}WH0&57(ziQ%j}#?r5Pe;-gmPti;kU&46>2%OsVbVe%kBv&l5l_e^}yq2cFK?fGbG&q$KHpU zYYFhl-1A>zN`iv5m+xjJ1+lNrWEG55QKns0(%Foj zxaFljH|&1l6Eb3K?RCI=;&tqm(+mPH6ns~7k?&)^XlY^3UhGEpdbW?xI~B%^Lf$NH zi&m&V)J;gRUBajG8m>cTsCdw1hVgb8cQzMW|JO-A@H@@3Cr`^#P)WF%R$|oMU$N?~ zb{W@Z7rnmRUWZ>>XJ4!3Yd`hH7yIHrZyvHQE-qaVzJWf;walA^;Tz4n>eT5? zy)<;RTz18ob?$9ZWSz(=S}Yy7Dpl~)FSBDmRkTTcO&l;%0BtR?W=HpjWCCOk| zWo7CU&sU}zo=1_M^?V_&W_P%aWYm7tW;amWF5?RAqJi!e4OG)@>S&3ZGF5{gwetb1 z@^8D0`;T2z<%MfP*l4kog?5Qs24E`PGd}MWX)IW6nlJ=4W1HwEKE)lv$}$|Qb3d>4 z=vCMASfp5lW*q4kwJZm(Ula@lN-b|$ICjTlrNu%!^b5PJHpyh zXwd#?Pri@Wpa_-_80;cGEO}<#e5-XZh zrgYJ9LmiefuBkvCDW(>?a*i%V~qh!#mk^d6Crxa=boYZ$}> z*{mm#X;P3^1iF-$~-qBed zCV%-}GO*bW1$y!TF_UyT>MD^bz)+-#0&LBVx3xz-y-7VKk~d^hgx>7aJ2Sei?3h`f zf&L!sFODsz;+Rb)Fp`$Yedi9uMJCtuFV@sTx^A+9uHiSM)^fUJV7iHvg5j6_J<$e7 zqxEb1ko-k;7P9>kcL3tyf9C+=%=`!thj3teTIkIN1Idxuzmr?-r*g(xhR-(#W~$}p zf7g-9t?%#CcvSLNH(h^y{c+b!yP-2V_Qb{!q_EAOaec-ix9aX@`j&^fq!pxYhC{Z_ zM?>4)xMNmgQtGmLMK>;>D#*}h!*BQ;Q_^^(?i&yBsB-Q6P9i$4n=y13EU93GEjx1n z^ZZ-U2=ht#MK;f~AxE3HNELp-TL>Xt^~{f;(0c@5fO1~zLq_&)+^JbN7qOPa+*S^FfHN}3?gcfbv5x`&~u{O3oD_V9QcfjQn;_dHJg|B_azQ&%NJYllZ zrB)bK+A=Zzc*U{eER{jUu@muVpD6tAQY|Q+kK`nH_D^>qW3hEEX!bK~5LOFuWEV}<0ir7OJc$#;h53Jbl_&%{yq|5|pg zTs-`>#$l7#$P=HG8h{V9`X~*2lg!%7Z70B(O**1}ED)jb&vS?*Oj+k4he7N3KV#$# zdb>j^#i*xlHv!|Pc3EaILg;z}0cNy^r0l#G$gR}|K!6jWVQro@oU*Z%P!_DETpID& zMDcIl6CLeRc-!?HX!cYrR32qySN(j?eQFFiZ?TN%ZVR%<57G3PSFy6KP54?t04 z3wM5Lt*&Z=&Rvq*xwqHQxq);={C^J-%ZB};bbbJ#ueVOEd)Wg8%9{Y&2DlS$^>L@H zM#R{sWEhdM+3~8vPdnDZA4l=XE!0V8^ki<>lTN$N^YOAYyg>C@xA#?cEGPfdaO>xl z^iz<1+urTW_q5Si_sGg8Z}`mhpKrLK0S4_8^;L~6jJI`B)a)|lv|vAy{BZlUn;N;| zQ(leKOLZn;pYcQqoUV7*wpqE6lYBYVRk`Y%a-reo&6eTJF|qtd>Gm z>S`FpVZ=W_x$=`)2FSEGqMIV zu!zBUaWONPDEngcePnwe(zA&16LJu5zl9%@Qs%B8JP>{{J9DBk`8Z{X$R^N+W$=J(W= zCUW1a|MB);aNpdt*JtAGKjc>y^j2Y>{4b%`+n63^8k6RHjOwRmeRlGHUk^r1Cfn@F zul@&mEL&qX`tBaKRXA`ar7lN++BsnMka+u%KvzOkUVPps_}TpHW}3-sm}wGjon*T~ zO8|0S?=%wbNugQ(HWZT+gZ~`KZPh!(KzDD&Rgn3+l>SdQrNs-}-4nx&kGt<)Z%h%2 z#4R?Qf+MZzdNxpY^%DQ)X|P+l!1E!kgUnj;IMTXhfY%pv%1C-XZu!%$tSVfDoBf6dU(`M_Sr*@0j zWMrbu>~y%>$Yu=)0U2vwlZ zV^YJyhQUjA(IgU-&y#z~-}i?cu5iz=1d#@=kl+A1pPtuvgnQ!03Lu^GRaut@KMzO_Ktg^&^4JmapQ9n=HSZ{Cc%^yA-VHA*Ds7$O)1F2#kZ-#gczXF= zbBx?pj0du$;m<1ls!G3X^$QxFS9`ZWYdhJW68_Bo)k-Gl z)M%0*=l4#=gMlj1@ZL)QuIEzJybK1|T5%O;WTSyClb(Y9xZvmiVw?Y!%^CZ?l!ir`KN~YkdV$>l z1<;>lMWepOX zjQD9&zU633Lqpk> zU$I2r)8S#qUiy+P%E%H9`9isYf{I9WK%|VqnEBr93+|Dz;Ven-2J0eXmf5G*Q`3La zvKFz$U!Kg`O=#{|75W2^tD)K0C=sF~VD5At(kjr(87uwJ#X9E-qTXnnS-t6fFzcJy zKkfU<58D6xW0=MFiLI{eSX0&UG|_J-0wFE7-G1FYP`(SY_I`^GDZaDQI|p9dlLlJe zGS<`am>EoxL3qVj<_$8@KKNyx;lQdS;0l{dgyS$Gv8uGi9cc<)wBaGk!BsDQWX)hI z{o-n-6#eg!jjSwG8{<=1p(hc2%lKbY*J=o|%XCKF(Ep${;sP=L{J%~h={{IN_mid&&&)l*2(g_)3|%Y62?f&$ybE&Ve2T zqkc2!5XcAic{lPLqNpPRQEhaj&i*!;;4@dl1#K4EHS#vEbKh<>^73glN9~Y?FnKjb zL0p@EKQ4R^<7+Ezwl;9Ub9H}ium*mArdPl1JCy0PGGWkB6cf}tF&(Oct1=1*3hB#D z>forA^)^qx;j)`~`rkzfB|jiaXt1J$h;?3T{3|O^Xx(BE|Hn`>ldINA{)vKx+)poy z;#@_(c1ti76kP6ZJb4#NVbWiQU@9*}dCybCj79RFbWms%6nGjDXLLKeiB`~D9R_aKxgdQm1|*LYGm=$>QX^jQSh^Y7PHIcI#K zk(>PMkLsOeLa~$g1~%rmoNhJ{SZ6hBaz|goCoM^T+dL~-gF)<8pK1IE^qZEQw&+Ll zLyH~@=h*7H=v3dZi_%GNCl48#as`50(ODHR%CQ$F8V}%n^;fhxF1Lawgy|s)A*11D z|7JOkI@^}xsRNb&aC{WA;HI7!f}^u%=Z7#y;AH%%Di=03_t_IZ{KaTS!wLUx!iy6n zq_Ir6hhPtx9va_te;E_@p!aK8v$5+>KR;&q$jMQoR*IRHYPbWZ{efgdf1<5jg9E7% zxH}{VtgfhLN|cZf`KUMe~quAGO_qVe=rqXl;;h72a z%b%&)#q+{u_0`ph8fzB*u4Y?T*No|MFPMv7DRf#_7JA{p>hByKVIEm$voX())!>T- zAv^z$jm_;Lk<^Bfwvzi(lXAY{9*Nrj;QZDzE~5R>TDxUhyQo)eMR4B~9ie>)zWfc9 zz$bS6R-DCarb9VdNyNF414t=|m*idl%qTbJAdN)zTXm{8jpW1MN2b63z^=0w(T^!& z);Thcg$$^TWXK#$up+phRu!E4ADHKW+pZw?Mxxj{_k-)S98DFG)QNJ! zTq#ygeoakCZSV1lv*(L&j&<&ik1U^T>Fc9#e9lAsbw9Wg8#MhY5g7$k>}Kfn)GGeu z=Cf`sNxR$wljt`Np zpBSnxl=akQEqTMg$;=H)BPVy5+D&Nq<*vL#pk&+4xYa)@^7d)@UK7SAG%;PS=w0IR z=xh?)AWxNWBhxXr?YLdK(|b<_|Ks<(40z}R%tBf`I10A%0sUbLOiL+vc&a>2u@sla zk#0gBK^Ck}CA{!-S4B;s@f)FnSjEgZ_Vb-Ldu+yWl%y@N8Q+F#z^Ub}a(pY=KQLO?AiN^nB;dY&0n$$H_&Fa=J*(m^Zi?Wp^ zOAHP&OZpmDlhkhg98oxJGcB<^h?L=^oafxm^Xano=1!)Wb7`is1pOcKKq`?0cs_2Q zi?PcE1-HIXK%b)Bp#IDAttW2#9_+-XdpA$9KPDtfPn{AM?}k5EdcW`nQGOjcH=lb$i;`*3d^ zuT6vDl(ekWOd-Zct~5V(cWw_>mMnnC%-1@u`X0>yP>x1=9`u!Lnb9-_m$IfdxEpOk zaLR?FG#UMrGL6zZ51`{yA0=36z-Rlp}7!{yo~VH zI&ON@LNvPZHNBIvTBr$INLdSOd&jtM9Jf1AW_GtLAvQb}18vmgI`uDdS_-J}r#mEV z0_!CL7izBJwWP*w(S20Yww9C2Xf_#N`qCL+R#yf~G=k*VyUH5yTZM;pbgZ+`Pz$hz z|FJjLG*)Y`f4kxLl%M5XTZ~FS9R@>pbR*xpJMOgoJ#BUb0sUEL?T`^gw*H~WpAsMa zu9bPq{Z9pA*qK?J-*EiUJXd@#ByM#gUr5Zg*kAQmw+w(QQ{`KpoWvK9NOn}S&F?&}oDi8bB29j-GYQQ6Uj^j_KVGJb^0jnh<0{YkVtc{dNE`DuQlgA{OMVo(8#6M8e2Dwi? z!z5b_pbueD=e_;l4s9iW3G%$lCztQ$VMIyXz=F{J`p9leo$~u@CWriM)Ea(rJZn1k z=BRDmmIv$@BRIRKNS(>xls_H-eJ5{0ynP6mu;gF-ag&In%;rq_h9e>CuoIX=3!n4_ z2$_hiamvlnk1f%UJj{*0(VFXQHC=d&H^r!^zTtGuVvYKid(4-;{$yWPt*PvGyOI%! zMp>Bm>@49iwn)2;ZTpklLf(Yw)_z80g5;s95)`z(iJ|#8rZ0)}QJ=0@LM7Rn{roIV z5Z!<3k-N^12dKN^Uw%Dxt2q{|@ektI4vFUf`6wS&1ZlQedMB`*%>f1KG9Xq$Qp3>Q zH}0e@3Pl2uhjQpSUK_r&{==}gtM7c+uLsN@w3z2xv?=f%!d`2zn7t+KT($8@qTV8j zdW-voIBRHMT}Pwg_^+|aS$vcSxV1vpiq%^G$%$WUWxG%GWlL0svSndeKhF7~{mr*K zKP)>sEL(0@Mx$#`^vm~3XySp=WY~oI<;r~3L&7dqhgECBG6onXSb%}Q`@$!O->D4? z*M)_1`ZU>>%@51ghh>{|4PuXP&cdQL4V900=oXwpVvApo(oBFwf>Fg1MRUkwar-Ah zpnsL_27%I(7V6hbzs-0MJBLrXL-Yy2S7?YjYM$IKY~1A&<5vF>J&PD?#M;>Y6~pr? zo=9+0*|DRt<6X3^Ikux*uGKMHaZ>2qXQs;9q09P)`^z{T0G(ie&u)6=&e_ew431^O z55w+0_!`}vF5rdDv#!qj-0-|#vttr(zwd&(g-@y|*_Pnzc;=i&`I8A0kvYkIi23#yM8)g3-``+wzdV(KyvEM)i7&r1=@Bfo?;EP}4 z*1c2ZnTX!G!zW0K54Xv&h#U`%VAv{-_>yGF4`D76Ez`V(qGa|?RU$sk58e0p>D64v zI?IkY&xfFj6-OQ2l7<(kuwCSB((ks(wi0i<+a|r}mqpS)*Rcg!$5X;qc^of1J3l^z z*jN9%SijftyLY5fS{1P$dT&4UQlf31U47832?=&jvL3GS!mvRadnmkDJvF{i*Y=YH zfA$;b4gpgq)W9|u=-tm3mwuZo{aebr#N5TDzZN`Ev2?%G0#1U0_1{)3%4@Fjm2Qo3 z_E`*C?_1tGcjCn*jYZANtl9|;*QH6+)XtXoWJ`^=|BQlRfs%&tJ>TUvU43%(#g&cw zgl{J|l(xKQ85g4`B@IJ)@+m%XYxIf68w7ccL|DB@*UaKu^Lw!Q+gIga^Ys^k%~gEV zo&O1r9;A}5j1$)yQ37mNc*riOEdO^FY4)+Kqx;s|ywp?Gel)8MRAxj!smx)zs`m9{ zj?df(T~$Lf*~C>l560)q{RIBw+|VmZ=UEZ<>xK88Eok@WpT0+K^urlLGFWCUMUjL~ zIs4s|l3jXF=ffQ{?d$I<*Nt!OLv*b4$#pZ5Y5gmR{ruC~A9=U*%`e<0*%(bR1WQN7 z=xiN!@@N?qzH6>^JT+PqGhb#+(B)<$$C=IPo<3yw*YI;9{uM!d=4fTwDz+~kBg(8M z(#X}n{)UOZe(%8$`+@XWS_)cY_w23GtOpH}4zMbfZohg~?os%vPd zKVi)Aqa*+2*c0PzBlSLdGlne<@wR+DN{vaTuBzs1Gme9`u%+u+C6hsg(WVw*yq3Jv zx=Yg;WAB^oQ7Dn~TM<=1eNzpxu_>JY>Tv!=R@6*QcrTFZzLtB15UDK*+I4y##P+?K z@RtC?47XlCyHs8B-C%!#0>*>{ljIwNm8-R&;DBPOdaJ8Cx=}S;{z1FJq<$v9fd>lM zG6SX^;XR{w4KFhPwDZQTZTeQrTMrpr9`l~MAiR;?5AAKZDx(fOJUeG-XS_y^XREd;iaK8fiZp^@P%d>?dd7pD{ae`cUjLl03VC$1CQG z`4C!^fcWnchwc7;Cjc~L!CVrut-)Ux+cG>Y(-5J9v#iE7e;40#d^bGkR{}2h- zgJ6`2Ib z;;dGwnq*+VNU5d%p%ityf86Hh%GN3~BO5$1JqgA1$nqu!sG&Vx;yrN+w~jmW7Qq>J z9zACk%IQm9FZeZ!+t$_P$ii2g@|=!79nKoF>|G%~k5-w4nqyKG?uN?++!Xj)SJunC zxyKP`F~O+w|5n2O$isE?>F5!nYa%7ShSjxJa_cg>e0Nw;G;fz>xl?v=fti2hL(eZg z@LmBka_YHbhJEbwA!j7O4RpcCHy_QqtiH|CsMLJuY7S!i9B$*j?yV9S0QN^zflf_W zzN_Zb8h?K8_tWF>>+hdxB*%ZJ8kqUywS(l|gp;9VhcV?h25av!bSn$p5A*^Q zQrKV+`_ugdP{Y<}hnY)n-`_FjrM@uhmbQ}Mw+Tl54E@S2-|!5Re#S*22||ds4}(HX zle*I0)%#WbdBEVJ_6voq#qRk1LkMMYwO2lD`a}9P%&%V%T?1kLg8W(VLmlwL|KbGB z%N|>u-!N5BtyIgu;V%86qQU@%c`2Kc;zmaC7OiWfki`CC}*X^#KSKgHFC)6a<&!lU$xPo*)q2j)u z0)tnuELb3l=pyMey>OqK%vXYfBT8hUN{d!O?8RrjZKqj<7FJUT;nvd}N~LMV=RsyI zrg~5)JPI$f`ZM9D?ud9cvS#o|T&Aq2J4=o+{AGdd5`Up~6LfXh>-aZ@(yd=T0Ft?R z)Kw4g|3pC+nI55* zWmj*cui||t-IN)o+@3EB&uQAu&KWoCkbglpH#N?*97&C}cG^JWWwwcd(rgeW_x^{D*! z+BMoF;^f8umAqBII^LBKr1h+;3{jC(oVO zIH>uqJuYq--pR9p@%G0l-113p$@vbyIg~4iJ%K^fNS?dx(A|Qgc0Ay?LeWNm!|8hv zlVV+if?#Aw^mac~nt$p~LoB}dx4Rqjz|5GfVMvRIrnl0$!z~aa+Rc2SQ5VB@K-)+Sh_#@pZEslg)N{(F839{$*eWGeRga;cwTG%KXA-u<({ zyZjfZEfA(w_@pnnSFYE9i`G0K>N%`b5`4b=o!%DA60j-|mRgL#U8y3B!4h&RJD#fS z;D{BZnWr(lxm%xq#-}^lu12pv52yr12aOaRj83`@Q|tw?)oVO8+^nJxb10qqYQqnF zWNbtb;onyrBa#@>h!(Tb!dn-6lqUS4i#9B(PP^w$`vOY{?7{xbMiR*f+K1b4yr5@m z0BLZ}p%h3S1=r?mtyeh8${$7M&6ZUIp6VSYqG8Q)Rjo07Iv;ddn4;?}J@I7!%cVE<^Hq7#nR#@lpp< z#=NOMN^0^mvLd`Jy4I~mA$xOmwGgTk?IlM2jXf2(DN&G3zPf_dS=skA+rnoJChvCX zh>GTapV0WX%HVv`-zD-Y$F7}TG^UF!0`BeKs`XbP8a-DaJymtA7ylkf{mzV>WpZqW zli5ZJcWM4EY{kSPV`mEW8r`#)Fo%Akk=+`9`y~9WT(S{jxc&e+xH-~>Y+d9gCV>R2 zZ=)B|6ecp&f+ke7l~AhP_0FvrwEI5w207jE@|iKTUF-wOuL)0zx2*@r&E+RFj0mSM ztq07W!^(N$X~E5c{je9f8`sE>Al;8lkN8KQkKePQp26`VbwYV2}SD~x^mE}fx?Pu2ugWIxS1Oa^pJtrEVddGuA}Bue;mG!x4BlW#Cu zN5rb(&ujPO;7?pVML0+THlpl;*spnSDtp#bzVXJ6Lvi_PB*<_|S$ zn#>;hL${euDZ)WPEuZj9ddSU?FgB5$oY9db-*>*t)2%uTKBGCSk=B)E*q1ZEcJr1` zFkrMR_hKxkhf~w05ba;-_QK0n$R5IrEys?>JTpdkS!657dmXi0ySSII;_1HMoGOB~ zndc^S=tTO$zNgyP-^sK@IrPK&LG`{eYipwJ?$If-;d|&~v|`ncR`5oyX5bSQw;v1i z20En&X%ZP=3UQaL5sG<>rR@8LP=RLv&@ju+GFP=)**Moh+UzQ=qDbIn4e2b5#UW9= z3Q83F%YkN5#{aooJ1QGb5IV7W?kOGkH0#Ie_+}a;zI2VHJmO69@N?^XibR0J0%N*- zMqN?pE-C<=%M1ISZr^n02y#1}AV6I9rFE9iick1PmFP%O@zNgWdkG{McXC^Zs_uqv zKiFo9_!WTsO~Q9qf1@~!y4g`p)KKl!l1t1};EQsaFo!ENu_(OQZ}jhuQelQ?+gKiJ zalzG*3cId#T#3~u{-wIsqHt>6&6Ew7Lx>kGD}^rLp~na9n9F%1|4j&H1HE-Ff;*C8 z658ca3JJDY8z`C}>&ez=Su(rju4%OfEO#subN&eNR``MYrSi>IG9;>q{V2)D_ho6(K*gG5?C zSc;I%5=#g{SYjq%v&6i-kJG@OhiHt$lB5tMFHrDw%jr7b%4hi@n-fP|c>$^Uc22o! z{{tneQfC)daxz(EDml6`)l^Q-`UG2H-AH=ImdLw=?#+~QYmY^f@UpvUNU;$o7v{N> z>x4UI7?-qM`f1?~y28bh@e4!!mK%4|p#WobqVPCF@&~L9xUMAtrZ#CrFv^K?~GVfO*=!LA%Eb+%)ebpKMrFx9Qz#t(rXGG>m|{%=ifUUQoA{6p9Ge@C zSKrVm>?9~kB`e1!6O9C}d8~GWyL@!ea4XOIU7L<1t!D-BYWK2ALMR{72r<{zBm=y} zy2;J_e%_HnL+#&-vWZ4I*ToVC!sGWsKr?(2;Eb>3S|@5P`?|^)Cx=w2eH-7>qdhv* zMxfnY;nAhB6*m+WRXJu;|| zpbb-{fW8Rrb0z@$h|POHYyy3o+<>s>kSp779jhKg&u_ZkBQgwDh7G+AgUEI6 zn+IogoUt_JV(|(#Z|{PJX*%KB-WT^0e}xtm_7r{a`u|L6v*)j$lUm*KR-VnoV?OSP z#lPLAeZI|1+UxLGs7gi?w=A?3EH>p4d;AHWC9b2g@y0HGR4k$CJe{|lD6Hs%{GneH zId~_?F)y?|_|GJ>*znFjY9Qfvn7m?jk5yoZ0#7ts1?*Vri+yP`-#}CPGo(z2rCTj7 zXOAQX=-him-GbDshZ5m%t?yVQf77{~j@dz=sTn1>UE*z8ZCcuN zjBqZ-O5Uj-*)!iUNi)7yBULA!NT3BKuM>Vje%?#uz%rY;H3 zhaB6Dnz+9AMsdy>0dxr;79+0~lL7VonPX|G3;+m~+@GKHa(a!B&EUg~F0xK%!AV#!N%Ru(}XZCv|hAjBmpaCc$8aRs}T!CXrYA-m5f@O8!{&zwbSS1 z_}8A^{%l|GnyLUlg79b3*kel@H&k|%mi9g$wV8eO`eh{;fsO>|r^#rmKg>j}2s`-k zV3!8l`fFh=Cu6?Jg=12^e&~+`CFCB1?v4So4~Vz_#0t+QNtNhdeBL*8pSpYoq*Y_^lHcs2!O{o?a8iamI=uyewkoa?v?l;_TY0E z;HQfoP?(`)IkGoh6!IU_I5GzK(Qc0sV&@tqXu&8iDx-%>JE^WcL;^wU$|UkLWTTEq z8ut?dWf7Pe$HuURy;y5)WL4R{y8pXvyPxr%J6I*z6VmUupP%bRL|fmYAJgbB^TX75 zDJIRarZEQKg|ry@6zDgzXf__7k{Z%Xp0W7vfJgR@Sy3dsRoWxOLp-3)McJ)+i&l3^fQYRUM?pEUOBX3;sP~?4ts%njj7I zGw7?tn`?E~@ff1!TWPHFT}_QIp*LXQd84rpkkN<%tKS`0gF%xyhv>8R;X&GJ z)|s={>|XiQJ2qJR6|$)iYr>SRN|X<<$x-`YqPh4r$E_>tv=1*BbBH-d93_)uyW{PvRE234+f4?S*dpw* zXQ9!3?1o#9@L?rE?4eS;>K$({sy941axQOx!>5xV4IkxM@gmDaU;7R&X%~($= zt_lVoG$}x+3-;w&$&sUrF3@^8Kt)hlCY)re1(-}Ysj#;M6S$HS(QKV7BaVVIgmhEm zMk=U6I^0Gjeq!As&MZ(*TUKf&j2b3#hZ6Y>LgP9^ISy=He^`1HM`{!y#3kDg_OmJvAqVi8g$((%Ls6JsQJ(Yg zThiYAw;87KPqox~k9CI`jpmUJM}8hpgeabQqQ=U6p2&PMR##>7C{iKZJ`si~U65ae zN{M+fGkC;M&7i4}HEskqlBf*Ih&H|hk!X`Un{FB;%pD0$Mjkc#Gm_t(A4oQ|tk_)& zuXgLVd4^DhJnt8$^*mp6(JNnd0Ec)KJ;K$9CU3!XTWg+M`$pyw2|u zIV*&C7VCV-rQm004oS+nG5R!-uZ-4Lu!-vrTr&Z?YrsnVKIX8Ey->?rw~PJjZL1vD zLF}7(MoMp5&dUSxq97yHEfg7`*Rx7Xupj?p_rvaOw|;p3K2#``BY$P_^>RVC8U`_3 z7+&fzT&aM}^FlD&;|stKW!NX0&3?9RB{MOVN*MpnsXmsiL|obDr(u+*tfY#ino_yZ z$)G{QZYV9+XE?Os2_ZpV<5`UJ$!`uO6PJ781p-RP%{x!Hg-z24Ws6E_pX@A24fh)2 z_+8cCks}{NZ_0}38^wMApkH}9D6?1qH92dAyZ;^WAFM5UIuHX7s}Gd_|G{53sWkA-Z;>){OfV9zp==9!t3Y(l}# z;1GLW_Y8tnf8tS)G&RAo7e{ZRh3#zAHNpc$Mw+xIH;pJ zoX8w*U0`zc(c}fKT+TVf%}DRLZa=)_hiD4UK8R z-2$-t%j|W1oie~@jUH4th;dAT)HZ#)%#HkvDu+W!ebtCqAj)Saw9=Dl(f+XcM%=OA z1+gPuE#N|I0{Oe}&-W&hgoBGpWnzCVW48!Wx@W0}ed96rhXVBH`H<~E29=kUiHVYR z@_1H?d7|Bdc!r* z*>lAQNnW1Jef0Xc-7sw$mb6w9ySUVwAA5Z~!;wM;~p9d+>mQM8f~%1>)bVP zdPxt>c8`q3q5x6sb+|ale{l}zu;FXAJhnWmE+>D^2>v)&tbyT?BxM}*}MPx zP_~@IU1ojMxCdYM>%-bh&F!)dSs-wyVT1zy$(J88p47mX-QkNAsw+0c(c7#nU(>2c zIUD=JtQXQJMLx8E_TVk)S}kaU^c} zTcJERi}Vg~`G-D8hdn}Xz0LL^U|wsY??b+U4K|mN1wAw*2hqI`;?dj==sj42$!T(3 zDAm=vTi(&mB;Ref5@eEmq5LOLg*Rtt*TQTyccCE<(q(S>HRYH8jFX6KECMOxEI%(ffRZDuKb!s2w z3=K;lLaBrn_GVpMRyr;=jm^4`T4Jv1b+eo1OauJz=G?Wt-Xb+uZGO-LXfT9m809quO^9UrO3oM%r$&k z#7SI{KGtYygSU?xhN8_>rCPdd8lPCF3mVZCkfqIc3`S2xgEG}_=;uLFFUjAlQmy0q z5~5Tvt~shK-}1fs5hk`dR3QggH)KlTfPt>?>-w0$Nk(I+N-kT6I*&? z?kJ)u(!}Mf3n*p8CFT}gtuai4{ zK;{1nVz0lLmLIOTaZR83eR}sNpx~fnAPT%{nm-~7rs3s+c$>6FD-cQ=@S^*g>07{SG*B_2O_7HX$2LWEu*b!M$l(6fG=Gl*LC{PQ* zCkFKHlg!*dxiddX-t~f%_LAh-SMTH$9d(!fLGItNeFeQkbDjxF(ROz3(a5O+WS_@p za-h-2XnWL@V)BO@4c?8AwBmOK5ODm5_lKb9`2*rR5EvzZL$R`?A$^vG*-sE^dHrdN z%h=_Oz>)9n{!^qEJoF(V(0@U{3~AEzD}_JqW7yAy-&?%=vtF=odCO>j$74S74f)5@ z=Z6;B%vfOi?9FNP>deBge_NEA;nxvLHWd&=h5q(g9mz%z%|Swd5{(@yDarR5Fi)5O zy{zH|npK(hv=P{+TPvsCZ3y}m`H<8ypVn$$l_vY#n#MuBKlH!lS)%FQ|50!jvtT`L zS*d}@{w-h^nU|7ZJ%e*erNLM6-+VDczeoLbKT%~J-?{0p2+J?cQCA_&oJhxZ-!uvK zjW5|8&SdZ7yAa_l``*Qf1i;q-349kAK*K9sS?oVD8fD3w5Air;)?uPBa2W;ml%e?- z0OO)7o-e_~V-z%UaWtNWarWrOF;ywfU!0vksPV{(mU7#qebCejPOg}IL1R$`M^;=! zJ3-Oyzb~PkQ;r!sh0jN3Mq}-Sw1zY%G^T{TB+FJI{?bMr64%S&jEP!;8BkaXUc5Sr zMQcx5EE)%SYliDZ&$=`|_`HpiRa`59w3~+&f+z${he~OYc8k^pvGH#VR{Z9siGZFt zY*HI44&8Bf`RW#3fJVHN1h6*^V#b1^i}z#`4u}T1k)|HR&bWnqL0?fLLBY)?DB{&` zKV6*1O!tWA)%gS@kR?dHXmV@&G@Ijk_X5126^4O=)9w*EpHkR3n6Tb1ji}tM_?ZG| z`95OTh3YYVOzO)3B6h@sgi{^DM_b1oXrD5Fv+q5Y4Qyw8t#uXo!?M=T*TePGdx+YC zR9Y~ERSIIi`wA`o_y>N)z<(u0cXSF6t>b>d)R|EO(-;p07J~DGB?cc#*14@j8<=R> zERd0_sFSPy0kIvrV2y0nRS?k4-0-GeH!7SA!V=s^C<)hzrd9kXXKp)I8&iQ^vS)Bg zv1PWy6H$8V)~5zE3~T+<`*SZYJxxSZjfDo4TvHuj?E4!VX-RngQ`xWn#%^AB+#e-0 z_A96rF31;(a_}kaR<869*(}}D351W5o||&TMO*)vaB|{fEy!p}ero8{PS6W-H7a#9 z8Hm+YVx6~gYO^cdU)_!(WL?qkp}IfaW%d8|x5^RVZ72CFcJn&ifA(boAt%POGgaLr z{ekaaCv+HXF^27ZPsUUzP3nrYZVv@OQL3TNN^IQnB^JSwN{#FW4nhL)3G_rifKd%B7ylU;b@UVn+K{-Xky` z5~m0SsnBxNCj);q^fNgWm0>h5JW+$Blw0X}mN3ssE%0MGq)hoCH&tl;`#|&7albuP zs9vCK8LAc^l7~vhLJ8*iX2=hAB9G-e@CtYXOa3ai*=9*Z=qNHXw| z9nv4){ zJ7r+zLzSHGks7z}08V;C0}BdnY&K$k*e%0MzT5d@ZTtx3(Ke z@LZWZaBv&XWi4{+PNlTE?b%LEAqEZ_vH7`z{FZ$Bfks?S&y8ax21VW0Lz?{6i6P^g z=WA*u?(aFde^Fa)ui4vm8o79@%<760@I`mEG?$V#}&lO=c>mE$(v z_DjBRD`rdd!)%I@E;KdIZ)RGbNSt3K0>7L*7Hc0q<4OHV#wR0H@dd3vWr`qs#ubn( zs~6=yvS0{r2y#tD0$aiJ_YP&AGL}n4nndG)#Z9__9bJL95k{G5o;ZT8xpFq$d7UljE-HiZ?l3-DE798Nw`NkYvxe9jOz5(kHTZx2 z0>}0J)g+7~eu#uICQ@5^p1}*3BLNl$uIB;$JvNEJ|t0N_StmX&f6-chF5PVUhqZqK z?X&u&gVG;Ph4cMC*txd$VQ$A`;o;%o6-lDrp10Y#p%$RPz4%P0J)h?f`=gxrj!5!cd%mo+nQO>9#kC+Y z?IXlHqu@%izSb6fj*_XR)C`x8X?H{~qpaIsOgp72)OH|rY? zSEtnqjO-sqCfAAUAu-qJLoF)>Ix@9u+oa_nNY&T-_zV=dR8x~oca?mk{ZC3^V|KgC zFPGiU^DW|onp(%5dz{Fw;)CieKIqaqAMfODep_UmvyCj&fmHrxs3Xnm^4AAqxj!jC z-=KRYqS2n#MggE+Q-=uKG3+D_u4oxIF8L14v^JIK8?8kDD$NZli3R}l4^S|Mz!t)1 zYrM_yf%w*M4-I!)krC+ZnyhZGKDUGlh$ZKi>DoH3?N|)~+3nn7eOD1%8{8s1{6>&B zTQ?(tYxb5bC2goURhXnvb17or=a#$zcF$g4uI}uw@1WqYQcXy1dky5}kHXJ7vzm@e zdJN<9J$)hfUF+?Tp?mhH#ny4p9ivVkEA+A!JL2S6VaYA_k|FDFi`L&3_ZyQkKbO~g zmdyQ&G#YTFOV=Rw=(ofMEVGtcahHD$RD!M9YvAlZ?W-yOJr0aE%8CC!mrtDHd8exU zyl@erOqW}?5Jw&e7Z~z$)J{irVeg@yBm1}RCWTQDq!tx%m)nC;-+H5jZY@_&>IA=U zkp;Iu-uA!8ze<9~ufF>%ak*WEWSr$JzDn}K=M(A%qgz0?wfvXZwHqGy>8Wfy6%x8{ zf3e&4zhZMZUf=Yi_I1=Xts$*bs~c1jIkR^5!#yid9;4DG0(bWOM2~VQziFTroRAeh za{sfMU1_RmZXjzoG?>tZtniV+S;4cALDARvJwE{=&{&wQ;tiPNMA||$P0|7)+*}i@ zFtNgE50=z?5a9d}$D@3XnB?UCerTdMJC|rrb*%}A>ZCtTtPF+bHhrGxiZYcSofB+< z>ACeu0WYudY_mBzpMD@1nbuJ5|HZf83kt4=~|Y$HwEelk~tX}?!PKS)EDdDh2iboQ+a zZNdUv>&hfHm8jL0Osg*`?^LGEI=VBaDEq$b--Q|Z zjqQH%F>B@|XJydJo3N6z+*^O~Qm7Z?G|BmMk#5~$x@F|ej`{0d7@@GWUrGB=DOt;) zU8AL?Lds^zkC>>1!!!(X!>)g$kLbS4CiHDp9jgStD{gti;EN3V0b9{Cl-3;|_2L7G zY|l+B?5J~T`uZEt=mYzR@&~FZzXPL1N;0c!Rch`QD#0IRf38Xu^lmY8{O{g^jim~{ zwq+8RDTEG+?QFZbK+gW4=ts5WKp4BOVGlOC`h(xjw(*y!ze%YG)!s!a`?#1wo!faG zfPtt;)uIsZrOU!OYQ;I~+!^&B13vq8XCtGjB>k9BPj3b{1t!mb?)CJcNpo1QIjomp zF;`H-E+t->#gFP(E@y?VORShmH!t}m+XkW<;?SLTjaq6eZPvXuQ)B4F2$p5&{N#nX zhR(CjD?$KFu)ZdEVn@3*^95(_B8rhvYWbEdi|{4wi4V?t3G6sdyd(4erJ4a{q2a~ z{I~j>$DbbxRJk<36r6A2z9pprN1QAaGq`Nfs_WnKD z`V=IKaP8BT?`02C6EgoLGTb7ipm~hC`JC{WRJWwff|(8u!Kh-)OPSUWw*8p{l4IYW zy{PxQ_Sy(t?|dU{hF_ajhS2Q!!1KZ4_q^-J2T>CvkbH(7!P#RVL7AamF+qj)qeMUK zvAafsG_zQaWc}jv90;@JXmPlngT>*@HwDeCt}#0qD;|Ny9Z#@_s*KicF}@yKNc?8t zoeOALE|#*nosa2jshS!xB?Pheevb$9fm(4n>|asqmieN%Gu)ZYoqL-oh-MtTc@6un zZk6Pfhqm3jkN*wToK0JQd#A+a!pl;k&r2~0^=!>Ws$J;o_tc-9Na*HqBMxMoo$S76 zJS8+evYuQS7?a8W^~Wvff8_0mH}n9TezcT(^S4e*rXF;3JDK{$7F~@0;10g&P2)cozh1&CSsCBOY9RUK zA=$T~RP*^y;)@c_qxOv%&lLo)|9(PWAV9$HbclSP!_vM_|J-ep_dkd&YOpZLHQync zF|?gvA3o9dzFWX#|JMX?>a$1cS?F^X92fxSKiSug(AWHQNzYvz>cRDe`rWKXI_eX> zY}=4O*_U*;+4rUM`r_`p{y`$DB_{CcWhYC$;*vYxRTVI}mBWm3dbSo(MKAh1y z^y`rt{u!E3D~9=7pY%ASU;*1a$G+oC&r0-rq3>l`FKke~^wr(t3S$U0bG2di6}Qws zr4d?l&-goQMuP=@{z+NXuv^OmclbTO^`;cVQ7_l{z{f?@3iGe$@ex}Mh0%`^!8$#h zd7%Swo(~@diOa(GegyOUCUd4zEhU5KdS&UAI(f>{D|@_lFaCpgRCzaE(b!wJvki1O z)J*}}1f_;)XCA*WX;E1f+9J$p!k*Q;nWsts_czwvb!sChxP}I_vh0?^8|`s)@6AEd zKTd63GjJ{!{+q|!5Gu@bCq(jj?iQ%FI%CH@Vuv4XW178LJSAKq4~zW!2(Grz>-430 zR?0m%VNGApQJDKaYCN5M#C`u1KOWuKcsA?PLBZR5`tjH;<8k&lvNd^AWjLNaGUE|d zNKIk-{RSKa9jbPzDiY!nT~h_K|AsU?HdfE2ac_52r?KN&O|*xF4^$N_mTnV3Fcn9E z1==pyF}a%a?}~-&MMj~l^>axdMSd1LXsdNK4AL8G+?%-KdluM-qxLVf?q%9X7zI1f`UK1t<-k1A0ScGK@-Yn?Z+rQMRbGTS1dG!T}==3RVOA>?iMfA z_P2slwkv9+=m@)5-!G-_2Uy>+Hcqa=2SjJxM8Xqfm^gLez=lz+n|F$y^55{I(^@7X z*B97B1^$y=;Gx_Cil^B8epGvby|e(_kO8%dmc6PC+*63m6G9v?FgdAYBKsLDN7!U?3>FCugZS3rG|}w7`^VJZ*;zXTmy_ zF|kVOLVnL3a8h#-a_=TEOE!Pk>#6X*d1h^1V?JlX)^%HVa0A;=IBG3*8BlIBkjr0h zi$v7q7O2upURR7psk*H~!nx{9N+n8?N3AA@T_pnIw%3x&`^aI3Ovpi?VKeLqVFw`c z3;FU5%sscl#Chrli=I(xi*>@EV&k?-2*>~Vw0VnMX9@c!c+@HW`YXxj{Xi`lqMvN; zzVxIT)(a>p#2NFC$tOKeY|GI|b0rMZpFh+-aQn$Q_JPzBAIm=Q(d{3Y+x{^hzy0_< z-w`l#;*YcR#ROu>k>Ha~wKxx$++IQ^4~}s}c80PjN@5m!>w71rM%}Za#G>mJX86j&ZW(a&1w-Q#eHP**8dx>?K{hS(_8Wiis+K@K z&dtbt1|Qik_!h1kjQ{gekC#|^IVt=uEgqh#@9tJRI8PJ zckZoUFg=fE=GfXNDQm8ML}8YUwAwUD3p}jP2memE6GEh2s&BiMJG}i`AI48;d5ncv zNg);#nHHpTMp_dp=8o4O!a;2C_e+38`uXlK)zQb@V(R1!T%r+R!70pGlcJ}YtHu|< zC#99#n!W!&YyN9wLzpWJftfbj)dUxake@eH_c9)fSwU)ZOpnu(elN}Vr0m&8nQr8| zkJpMYEh%h}nTMdMRfJxB%9?_dopPpnW@HUWR3`%wIBsQ17E(>G1{XPgdTZnK=G&o9 zMRtS? z=#%1S=X&Mp3IrUKtL=s%k9h(eMA!4@CtKcYMS_XX`J*9Q6H4L@%}up=4VU3WOyo68 zlVFm^JGbytka{Gn1=iB*SpwF=*93#lu|Oh!7`l>5DZpk=>Pjw_jPTc!i}HGpUX`fD zNK{it=nEXcI7Z7#^$#7i-@RcMOWHeCcDDl`j=V^X!&gmg>R4y?hco^O{Rj&Fxl#^U zl(?5T+@_~YoVss~A`ADkq!Q{Mc_kX&Op=MSch6+sTI8r%QQL5|ev-WudYV2WK0kiXPxYA(<8Q+OeAW(-w4%|8rg50Q zTq5!S^QeMjzd)A%DHUVPBAJKNb6 z?Rjy3`&l-(%Np`OAI}-`;Sr_(==Hthn4I-Jn1(*4|7pfmzz+I24Jg20ODq&)mKbQk zxc4+%?TTW!#pLh8nK4qoM<)Xg#f8K2rrRBGT$GkgnMW7}Rtw z-A~VgSn)KXD89Lh00c(fnX%EAfAW1p{nzUbs&mU{LRFT&H1&{cWA8!;qDKn~jf2Auh5> zWkORbv*)Wx%o^`0JdFx|U>I87*hg)%$H7O2V%E#I7(IIEpSZp38*0OX`hIQ|EVQti zCt0C|)o#;sbO$ihF@}=7LOQZKQD)avLHv)1M06#A$~M@3UkvLFMt!fVL}2W?i8O5^ zw?Ha@OsxecurWJ2Pf^@8fqnibQvAYcYFVk-^9U!fgH-bTKKP>$6VwpAf@eK@dai1y zk|}DT1KIMF?2CCUMvo$AdluNt90*04bOlB13Tn)?=WO4!tJl~iTrIGBpRPo4QKGO_ zl$Ty8liotEm94gSkAntd_B2f75yWo)2NtnU4U=j5g1t2{*xN$wxuazr!&Op_W!~x( z*v>wkAorPPG~`evKkcS%#&C_5c4VI*$LFU-){PAtR7K1;QqHYMIzsNne0{h~p)P78 zZA8RAnW_I^Sf7aSAhz=FsHi^5MKxRlaRZr#!@C^Kla`PKFT8LA5Sm?5i(3r0s%w<1__9mC}1KE zCJ1B#LBgR#a5Y}YDhk331W-tv1c}2)P(1Nk6;HfYMKSJ*fP_Q2yii;hkJTQBUGYK= zU-*5$)%`qkBwV}u{@(xo-=81MJV!s(Rn^ti)m7Eq;Z8+CiuN9ao#}NA_Su0qY84s4 zM5uajmIHc%@0!SBrfez{lM8BdujXNvgZwumwOkkZBJQ~^GCH!|oM{Byy+$K%A_s~pApeb?MO zKnHXzxMamgDDtHg{%q(lbcxC7n7X0!?!v4EkauM)jcb6Kw6 zy|O8og!S+As^oK*s_FT%aP(IdLIwoeA}|IDBVr^|TcG=8P)+A!TtF%a;3miQJr#bY zak@iiT0>%t2G{c&Zm|pcK+r@^BKQZe%V_^p?oU9co$aXO4>mf4nY7ZA_vy`@uvd9f z>Y$+K*Mf?@iPJ*3`dP02T2Qek!~02bz_IQ7VUR`VI{aX{719^L0uag275Ffj69One z)Pudu`$FcQeiar^I#B_MB_OeM6}P1EVADcy80ECK1`_}U(+&aT)%)9ch6NIF00?q7 z^V21T57{=@eSb3w^7L|?9D?mGXlxu@$+&cGQQqb`kA`oH)D*`|_1M!5_!!#Ma3&%4 z1famQ4uxo$xBqHsy1i&cSxjZxqt9(HW&qU~CVV;UcO2-yynht&EIruip-Q1P( z(E@)`@&;Fh$|fMK&ng8o@>bo0|D!k215OC+n{*-#nQwq+Dbqy&fDm^ zHc{>wS24(hn ze5G)hwAu;l0P7a;ljO@ox04hD4+R~zOG(ml`2Q1N8>-Urlt*tH$PHE)(E$oE%6&Z< zuWQ4-EaJ5T=x}#M!Tcl~f_d{C1SnE`&9KxE@o!A7JjZ!(io{LWDr))^;B|3$m@Gr= zzS)D_xQaWk@Fea5o<(?koUe{rA!9j-(Ef+ItEIERaSp^ZhCq&eI3s*Jc!quPrMCiM#b)W-F388_4$OB!@^=|-VS_V&i)FK_>pYpAQcZ}N11Upr?ZYbmK% zApz~U!jre{<{a0u*4TiP^ULIEZ7TM)@U{w0`4O|qlxfNSm0wrvJ8t@i7AuX=2OX>4 z1S##G<#(Z+o0i%3D|UNC)8K;PI{~2UO&v+lS$X5pjIP|j2vmNdjg&U2kn`dax zIn(3L!LPR?<;x?_a4-;qUqMHgStxvh`SSA!7jnxsf-~(; z-8?F6j_m*Lao@pf;J*;Rg59eTgs@!kT6|@Acc)e2zs|)&3;*Zb_Ko{)1M4oUWYb8c zK}X%CD9I@xcyW(a;+t)FXtny>t8gQ28j+8uQPQ=b6n{PLhvj+^Kt$dz#O#SLv1;QWwP zVl4>);SU=^XhTN?2_14abc%HtnM*^N=QQ z&Wh;SH{WB%UV+IIf(zVpf)I1oty+_xnCM!TI`2e`$M=2An6LAG{Jf4@ArXO&)%w|7 z{KP}FMjrjE?UQqu(h(CMAzqVNc{#6ObkJxIIFbydI20WFwzQg3FQZgEv#%`*5XANfRm1-x zuGHiwv@5lQFiTPEHDzrQ>Ux4SPY}T+%av;Ei{OWtZE4nV+%1Dii_it85;$I6@`teS zG}z~jPH72m&?@0}3x0Rf-Vu-rY%7{g=Wo5b>(7jbk0_s4l8;Zz5ZXoBWC0j3xdf|6 zfkQbgoK1W95hi>kp0Go8!6zt-so-n&^D_7%f|JWQ@vr$+Pyi}M-Tugrd>0-Em(m$sQ2v!r^e+X=Qqm#D z%aj~5Ds`KH5vP*&cv-N1CSCS;jetRTd%JnCRfs2WS-M(O%w^)o;T26a}*Dqus1G%6Ers)|W|_t~|C`+Y{C=+hdxws|5=J(Ri~yE^M-!67FpQ{4eyNDX|Bx8f!tCg08UC zE>tFk&=sUmAG=Vw-+ikTg8zCt*Y5$;1XIeTOVt7a%mfZ3&Tb|R6K)AduYV?X#D8$5 zNLJu%?kkhzOVMXaG6aj~yMcQ)x>HR(+#KlI_^Fta4fpSCv=!urBNyc6c&WWP9&p%C z2qRmM%kTEUWrKC7J((rJb>w3_BDJonIuv39Bg+?u89j%)%KleQ@ZF&8Ls#`;JQ-g( zJL$Ts^#)WGvzuP!s;=f&^@X|88)j8)h2;6?q+<0P)ZHAUGEy(do0>gx23kbfLQN;jK&4Klr=BJE$^m)S!ZqzDs$3zQ@}qJX-KcugsHejt28N zb~)+~d`5ZO!a3&Om+Z^-yiqc8c*)?R3vdEpE1h_puEw!`^lNyFW`M@KBDk-T(cC75 zJK0-gY1bj~Q+0P6j)z`q=-rCnAH~UWzVZE07~0{)N7l1JA^VG3kpHT~ENYfFwnN9Qgdr9Ft3Fw4KCmnbgufIA^f1j(*s+eJoX#DgJ2*O>TGLej0WXniL9`$*vJZ> zsHMwD4vw9MzoSf25sl?B^(<__Z~=h^o!4-(%9L2Qz!RMbF-4fh?4yLVICX_UqPCV8 z%?XjBWw9}uGIchJsvpO_d+_yymEji3^N`-76Gn+naKyMx647UL+OR^1n4z zvJD5?kU>(t1F&4|!b>i`mEYhZ{UPr6$nys>cknlejG36-G(ADR4KP&EAKu}n*i0HN z;dBqUB$H=|(wa$kF8`Ca%k47YydE_}fxW;I`6)R_T;AxBcWjv(--)1jx>0VLFN+AVFZLlOHalNo}}vnqj946zmRi6*v$?M-5rB1#_Oi5`M0}Y!hMJN87=;g}*k&xS2Z-#kfB( zVIb(-Hz%H|Liq&tQz6#RAo4`xe;@VlBu4yeK3;PxTO6k9Qk}qVZ2}Z@^!fv4R>6+1 z-I#&+{3BMSGCj0ARQVSm z4@33`$vD#fAg;Mf$=`DaTFHj&3aM@8ZZv5 zho(8W)%fp_YY*!P&gU%GvJ>>Ygh4+*&ZXkWpC|tEVuoERb^k%|M>(dU4uH3ws@8M( zzzS=zdSme{zTNOnV(X!vI&5RxIEb=(V6T*5cH}+96KID~9vdRItL#S;(${Ky>IkOfBHHCz@H|*T`^TLB1Rf&=(|;hz=dA2kGJMo%@9Ek<=|6Cs&p95? zE`%933pPy}N;!OKcv3L>{90d1#jGTcuc`42;EXBX2!?@yMzXKav;6m0U44W1_ud(v zyyiX_NdN|8sviz;Z%JU|YvId4rD53L_?yJPz801JXe0@`8Z7X}KYeXet}mEBP!68x z{DC4aWE=~cU*rj7Nk7+PD-~FV+&>`WTLp6Hu!+&u@FcLP4E^HrGqBks zJ;;!Y-EO!g77nIc0^(PmoWPTTra&f72;-n-&P6v%Xx!O94Ij~6t5z*MaL~UCoy1fV z(A7{y5e<%W8j&h2K)RdNF!Zwl6~B2MV9<{w_E*38$iLv`vpzFO3lYdsy97KgOYmL@ z^zLDj*BwlP!yv)h0p*p}W^y~hJ4bXXOLwhhxS9_TPCMj2!d>)sYw$ z9@xQszL7zMQMK~ongp1^HT80X{Bq<`Fh_$@gI(+}sc){+v})eAgbhH)BOD{*W$;6C zhvva-EQ-asWz~1^pYTuRUK~sFcBY#4lkaPb1Eqz@*Z=65r1~1g@>7Kk)-+7hg$;DUSaE-4oK1%UU z@b%IsYWnxLLPln=WAa!mAEwZ&8J@M$!xs>ejBv2ZOBhSd*IOqsSuXG6DKN<~9)`2g zK7;SWIInGY*+Z!f8%d6}vcH7=&E0N<4l$x-1r0%Qv!t3!a+0xLCCBgn^ec)MthA(@ z(3_ZHLeN#Sr(i_AfEzKQDu7p%`RVwMAthTs?yrZWLfzdG1!?O9YL^{ZNdx=%f6;H9b7IkX?i<8hp)3L8U159YlWN!J7%1M z1jmBnL-l-h>ReGMzQI<{L;j4b>i58iT@bc_tLhTm6bG7sI#*jzCmNCMM+YTP!a4xt zy?wA3uW zGryQ6h-yU(Qn%WxCzfXJkm6M`twr9iIoG!WPjS~v3&tb36A5_{7vN?$)KrY-<@4eo zit*+t+)y%fnX1eRzQjFeV#PsI823AH&x)||51c}Xh-?kr!=cxp#?(}zs%}ZYbFJBS9 zgdKkdb_u?L6*DF$`1&)?rwlFpaXTovJ8ql}d-&a42$0e3yqW_uxz!v1Nx!`fk-fs&LAGj=}-DZ7mchh>_M-I*E*V9q)bxsYL!m1%x zRXy&_PIBli%W+pwnI{%|H7CkYOfxWP)b#6Z6bs;JhRJ?A-hx(`Y%7r3!>z*MznOhN z_J74b2*ONhiEVl&^L!#KU=C`^HwOb2dU6FJm<}Hva0IF(x7E-M!4xGCM^zjjj^c~| zi8_xROO@&8LYBi5PZga^*-w=LTBXiuFgDkQW;H%8TSK+@U#7+SU-UB7vCsx1lPk_) zazkKLh9_`-7DKQYiz0cL#i$=^TBU1wv2(;txc8rzz$Gkj^j}lw6$uhME?ge=_Y7=(<;oY{BZnu?@pGV-hK(Q}|beyrx!) z$plYCAZ^pK3vB;iUdQFQ^O{It4tbhOxX_1^N34NtQKL#QymCG-lL)-hp6XmUsDQ7`VYv18lWcQiyrQ;WI1r zeZvThj&I$p6X~gi*1`3e$>)d`r25gMAzFuq2 zPX%?b97aK=Ml&JU@o*m3<8DyD{)t11AT*JIB<#=2R%~!Zc~rOEWJr+lB{VM1VPy%P z`K5ihLfePql0ih}&K0DkW~uRzn_o+jLWNLoLIrb!uppMJc!F~_M@<1Qk>TumXw383a4+uKJ}^KoHg)bwunpC zl7OQk5SgmL6$Vj6BJ?y%u3=@Dsqbmlagd#e3j#FBIt)6Br#0FdEJI4Qw#wBQ%!R~; zI9cpMCi>uGksl4gdo!t-?D3q#(an)^5Ri|qI8mfg#14|#lcRa&q8;358GOv@u%GE3IgZ`@D%bd=&OmB~^ zE^mbrc=IAl(oHqQfeUo6(#jdB%<}NTH-%({hR`_q+>e-Yi=}@FW`y_O?MBkn)qre4ezy1WI@oBv;iCl;R_cNy$2Q z!P|`wClm(m-IokmxOMh z1%~+630T#3%3q-q&<8wzciRuB=P^oH{VAFGGRSez_bT^3Xavj;eur7gPUac~on5bE zRhU<7f8W@rqH!bp+v8T+U+tHOzxG5Sg7vJF$BHcAXG)OHRL?1#FglvpJ3> zwV|;n?OMQIjkaJ5CHOM%;m^UC51)(rFgzK|`1+C)wSRZJ&PjXa5|#%;)^8<4B!o@8 zV?)?NN$4KtlFip-ctD18K{Y?NRu~$$1_co$b~uZo!qyWx#kmsqVv=yRuC>2a>*yoa zIu*6Dz4IyIP)itDf{v3xg=(i^-Ep;{AX#9^6f|GZw}a;S>huP^Ykc?=4?+E~9JD6$#n$s4Aa&=A zroKkN1Et}}qw)liXC(PG>W_kw^vXy0F?Jn_A%5huAbuG0yduOebi@!}W{4Li_}!hX znhHyW_)XHgvS7$Pm=!<$Gvu`3swuw1nVUY0ZUbs}af-NsdMqfg@%cF^%ym4qVC zEzZFD_bMwC8D%YhITcvOnp&Y78f;bL;WFt`44P4U%0`2w_2`6%8)jvxRoh)voxoXI6d2KA=;^7fjCeQ(CFq!ruK?&m3y>Pj z?eX>dDH#}366dsXRlmn7{4=u>UGrD+5`$wF{3F{D@Tl}VDKE@p-gs38@SX_M&W|KpEftO5St!Gv2{cu^ zUn0KF7j7ZG;tW#1;n?uQG~C#!$P=Y48mO8 zt`N=BvMkCRo@o?&DDW!eA zP21P~XVbxr10 zm9VEi2QCxMgMH?<>HgkBfw@g??sW`f&9csEs8;y3*p|G*F%uwrsBAQQsQAA~^dutX;sENa!43c^$HUGD$?*KB7wft5e^qz{DO49S z69SpuEEFBs|DY7!N&kj?@TGk4nUwvA&CE=P{YVUFC8l(X_ay^(dz@zYd+YQiXU{nKSVfG`1cV$_HebI%JqYH08ot+lB z9~i3w*upb-0T#S&nmWjyW@6FI%~Y$>1T`P29=~9#Nn|lpKx{FL!zORLmYN+I(apjR zHFQ38BlZQrtZ9!qASGF1ei#Zs?dY?TJwcw3@OqrU!;-4CKnnXvdM7aRfQm${ua9W1I%uVxZL*pSoMF%$w ztNE0(_PW6TRpPM3Plwff#qWoqmz@fo-=(19H<6#;M1FpY$j@&gKLmj}WYt9U z^g`FNtJ)v5#s_=``N3z9AAAN8#21@G=gUAL#8PN5*n47>p#ND>g6HmSR0$5e3rY~f ze?uj>VeFxmAogHPj#y9;w-vX`%~lJq<-CMNfQ&Q*BnqKHa!dL}W_IZM#`3>hb2mb~ z>u?h=Prc zIWoEr<3kjYGR%P!!!F4rqMf1Lan#$GwduJyjxuY5g&fCA8TjwU5YR9zEx86y`!OxD z96IexP~43Qu^$l7SsW)+MD@od`RtEq6ScUPK3^I0aI3zY72-&=Zdq?WWfvy`NFtFj z1M_9iKNvVc=iZivOa_~uUbi3d`pA9-!e39`M{|~imk8G3M~(vIqFt?ZrV>G3q(R~o zSG@&-fYkaAa9^@n#~lFBnz^BMkow3|dm91LbP)?5MWc#Y9qU|!Dl5SN2kLom_x@2s%R2kV{;D50*xvZn36GdMOoU^+?uAe`)2DsC-- zFyG5CZ+)#Z_4ONev0OOU(cx&mQ*j|z6Q)0j%Qc3V;9EvN=wu+r5P21U*t?2p$#a;2 z4ras`w`JI-1WU}M{ng^`G)URNTJL30(r%N=sNZDU5NYgr==3T$-n6hBlL7vR`Ze@f zN4K$V-*YD!*v>xALFX-3phGQ z##P+|*UXdgP7QH(g#ouEHqp0pWUTz(yi`~9K`_Il%ebn4#Enjw@#euk_zJi97V|5~ zv#E0xmsk!>kjYlh2|;9T$!^% zvTAm@UYgR=?3US+6NaHiOmv60qK=U$B)SLqKWjVk-!vOc9s-&U0;j8|p+j{cO;-ZH zUJ5aV#wa0hw543Z8X#_o6*K!Jc#ClA#WxShlG$(hW8upWfG!$K(}8NrV)yUyknd0< z5oT`2`SPfppJtJ(4Zn}xUlX5lZf$=r_RIG1Q5$8(mmpx>TtqBgMs&6Ais*(T%yb#Y zLnVzgA=_`-VfXKS<1;dNBI@z4PFkUwqiwjZ*(wj1wca3 zYoG*a$(r-HHQNGdJMKp_#db78{TA(#X48Lda#zeV@*fHFp7z|rkZ#Q8V9*`L3bBoBePXO zmw&S0cjr$81Ln{A+^ByxDx$0gW+y}Ye=|G-`3z0H4tjzTuvARe^dbAEFJZ8%TDb3UnN&0bYV1J#3jb zjY;0{vO`GTk?ez4*=TWl41*7{gALZjhzMgxAK{G_^bKm|sJ}oi(|&r4sVaTG<_~tr z$uB|#sQddxdE2IpDeArr+0mZv8$2-Ui#mT&oVXTAAhOOFyXV7hfdd37!z#BE9Y?r_ zRo0BNz}urt%xo|s7vn#fqOT!y{OT4c&RXe!YRqMZ?$GJ5>Z6B8$)Bsx{+n4zAhL3& z_={_n>UCa0^NTQ4GP?m%Ug{ul5RA3zi;*PIIplFt)^R9)uo4SxhF-+!3kaCt!P(K0 zQKP&ki}+VROmRgcLXEHxsKQ9Gzlm%91d(IpS`|qNlOGf)$WSw&7I@z89zno*F(N~B zCU=5`<&M85D2h=WMg}YmRdB;Tli#glSBne@I2AH565gW<(1EUlT*lt4lK5f|?aBjs z{r@b!4E8zcXAD<)Kf0>9D9Yo1i_V$^_&I|5*d|1WcSJ>p^JMh99>CyjG|uy&BfTY@ zvS)q0_F$+QK(PPia`r(?9&RPHkSx`%)DHUVnXRw{gt|-wxAK5q&&}OWfX;L6U@H=x zO5XeDlqYzLqjABcj+R&C`zYidkdZVVxmiviclTF7Za6^t-Os#EU3-8i z9AK0H@=tdq9 za9|nRN?hJ0U_;n1!6(?;sw)~x?8gu%{Gm~t%v*?ck3tOk8}hH$Kg3{H8iid}G=VLV4jV!#ko*6N1IiVId0q%1z)5 z92?%|_e~7rybXO9#?;=Cppi+`$k_Y52A!{s20kM%AwJf}eL#t93R|oXivty!pJu>^ zONI!Pv3p5NSFUEmuaYLAHGJODexdR%(H1IT3Dj7CTI~9iT4EQ7brl@h{yb-EjQu%u z%s*j&zQ)${@64yR&h^0l%(W#NqdKT{QI=bxjUmN#5VHi#MlSB@S_HjU(6eg0ubr{4 z2V!D${3b2NsbZH1!!npR%{s)SLi;1CFFP4xdPeBji>H9+r?ix+w1(l#kFolY)~IKif4^L0@$WSB=O_!~$o$*4Ifj2N0O=U_zjn)zjg2ZQ~c`< zr&|LSn)7p`_@$n?_z*mN=|YQ#-6A|ZGXLI?=8nvNM*kE1d*{gVC!%Lfgl{wx;R2Zm zBe)=wI|v^ItVG@VZZrqk?Mf^$>=O_%^wPME5ktQ_`$djsa3)-w3!6GPL)Q1J#lDT) zj~xl|GVbXOX)S@o{CZre-jQ8Ps7ND`NL5#W5mX@CajE6ZzihMPfV(J!A9_7y+%boKE$(&ch$I{4_8aHO>|p$(6qzSQZ0LgBOci(5dNn zhz~3KO6|kSC4_tu4O0ouFf~TMPc`p7d=F=eQP6=LoL zDbNcC(V!G>340ptLBt`U$`NzGemR&*dGhC-&0W@@Zk*@eMzKm8$RC-4MJ9+5=dU$k zw8)CcmO5obG=UMh3iXKTNLs#DU`PUe6DVJ0lrKmcoxPx|oX!a>J;c(G-Na%pGrG!ie6T*?6wWWa z65FHmAUv3Y0V`FkYJLC_A*g3GsKxlv9$A=D8i@M13t_mbBn1q76(>Y9><)nSO+b1x zNN`onLDSS$xX0dm0VaU($U82^mES${S!ykCd^BpQNh`*~a5~&4=i@>is^ycRG2rHq z0u)@3;h~M6FYS*bTM^V9+;$KaNc(qm8dkHi$n}P5RUn`^_VgL1ZV5qP+n zxe)jH`^7a|at=cOb=h)IG7QwhGq=Eqmh};Dv-_m9WXr4j**U<2Y&n{hQcwnY*V!+O z?OXRz!rg6nblZp04<+1?aNYjjY57LuM06Z`C$Ir8S9mW$x<=*R-{1P`Twf|0yV>~} zXw|jezKDMnRPLR>@`C$(ZSZ_SZ~gq_@M+dOwsP;e-+#RY3I9Q7j(+Qlgx4afFMs(3zaMB&Eh;x;j_ zBAmkbvwv6&uXe`qO7rJ=%^wK6OM^~srFp;mWQ+HA z=VXxgbAPK%J`cpDq_}x7PB9~z7`;6kBDzQ-9hHIw zM+pS}CxXexcTr$+2<9tI<0a8xxCTmHYrxQQ_q)g0xLhsLnu<(rWXNM_1a2wci#43q z(Qu?Eb}?{L1g@4=t(YV}d19=Y{J47+&&$w0VnW7MMoF5H@nIme10iqje0D&0(-i^H7 zC@{C;R{1rU--bkyL>W=d4HzQkckh41BIu4ynjphpKW@q2ej3gz(Qu9@oRwc_#O6*wTsK>qNr$6IDjbOq<(6N37AUO=A9vaf(y%wbT z8q%u*>GOw(JRv=2L3*5!nrTQCgjDym#;LQ0)czR@(f|#qP9QC^A-zmUSaIWi1{Y}m zI!5z@j?ow5ZDvZXhKA()kS_jflZ% zhV;qm7)a}Jt0oyp%>e1j29RzvkhEg_a&d&dx5SjRRoaWVRi_wO7}OnY z8^G#nU}>#(H(?2VNyr0?(j>niqfdQ;tOC*pH-_WA!SS5h{-&l+bE;S%aW*^YdqRRb z(V~t1P;fnZ7G`i59UUX^R^oSR9Ao!EcP3t1WmO@bsViuRqhl~oq%Jf!FX9HcAhSgG zlHP#TZV-COXoH3pqj&DN2)RMeop7r@25y8zhCSN=(kC?ifRkp}5F65SYhxfigj*FfkTL-2@&=F= z7)V;HB-oI4Z;gTUEpFBMfCL~n86bx5zT-0zlm}qQ^0)3KdxYgeH&~9mlX{97@3s7G zzXW{WO>-E0e*}*~=$RJZ&qNJx3;^GMS*~fM1?YE=7r<1)>d!HleS%x{^zQ_-FYz6% zScBPPyC5vj0}L_i8o`WJMhgS))nFoZxk2h)JONTU7E(Dtsw;q-{u6`QyZ2ZUaX~C* z=MgiP#>^9o+45%KS!;t?KmZ8OSZ_3DyjM%d0kit&G`ngwX4%+}OvWsDaU6jHuxrih znq6AB&bE=-606i#QmM}bt@!R`d>6&8oKa3N86BI zdnZOBp2DrV2ao_{vjJixqFvJr_~#Y_4(U5VAmDs3y(0mXFfXNOP1=ELpgJ=}cJ*sD zP(Zr>h8I>jm948;hiZ(40sCd~Qr%V+#GK9KT<*vK4UR`q4DUOb`tP{QlAM}L(oxbL zO=jX&eaN(hpyLKZfdGS_6BMXVmuUh<*Z@jn0TdCyA`Rg5SOB|$in`ALNVNfUiv^HQ z0HZX3o#*L>Fc_?B0sy53z@|kO3A@L|knk;T)d?EFv#|hD{*G?h)&RI&0KoW5`;!I$ z|1EQM@n9)IY`R#uFd-Jih$P_f!K<1JLv0+cjm2Rc0o<+ubc+R$O8|Eo0L^Ux?P38m zCxBrZz&HJ4xZv3dB1Rej>+ZC;uy$+=7nb8zrDy<4VgVGr4k>MA0L-%i)W-sNod7m4 zlOX80Di*-a$AN^+Fl8yqg#v&^KwkkMa|&s&8t1^PA<1S=kxqEy1fIJmo^xzuF;%GR zSaCh<_x%s*e%1yr0C5@41Vi7))h(SM#x>3jUd|~#xPwGZ@U$2cMMRJ+Ig~I z^`T(Z--h%av4Wy;uf~PCMnl>$5s*3UO!#9t%1z(y$&DSWnro?jbB4#3IZBJZ#rg9B3zmbh3SwZXI}9N0J~_??6v9HIC_ta$Rt>fQH6@@u{bJ}VGJq&i ze)k&-$SAnxof|u7A%%m!935xt<&+<*FTRAAY7qxZFtuSxgE z^u@2wvZQ`@2a)=>;26O9M^YpE;%jsuP`;kWg}RZE{Gj8z-vd%t1BqOttQ+4$(79AY zx=?SF@)-L<)Wd^^`aiM-- z#2fwBBalug|yax z5cdLU5iV3S4XJ{V>h94v8UN4RyDUfpG^A&5Af!b$q{nbC^xcmO&{tO?T<&M=|bOdf#tDb6%rQZqdzXxjT+K-;{mCwfy9lvA**XHv#?sKA$1i<2Lcv- z9W6+$38|Zg^avqszgyGSQA65`(X>xEgI4|f%L&`7NS+T&sms{cT7$Tb%Ne zQ`cxnJFWtx4hB*?4e8_o7EX_9NZTi}{eG^o=zAacLf?8^fW8hI)*`~%v`F*HSS15S zS+FkBu+9)zPuZ}#5fZ9; zAf$cet;$M(_BO~<-%iKlv)=PaDfrK z>N$>-i!xb~vC(||;vZjKzZaHlPu=NVOVz8Ca_^QmjVsQbCXOpdGnBPJv z$3#@ezG_8OAAsNckP%fuN+PO7RO_qvqp5Iy;3bHtrr#;e79UYfn8!B9Zo4rN)eRSe zKOJKts_DXR_e*%AQjki3(4}+!=wS?9hNfNs1^}%$67A4s+73K~|MymaucgiG{1^{J z4mRRKtz$L<@@uYWN&e5eL(7!$>Hi{T8^_lsturX;0n9-C?$HD$_O~DR(ta~>!S4~B zS9jCMg^@T}&p@Ak0jrJa&qg)lXe8dfbM3)3I1wf2C^kmlWYlmaLOgnL`ZW7}n! z;G5E08eC+*Pl29J3e~8-_WPa2=py{SI3ZLPJ*zhQz27~5F6ltFlWdIX{6{H> zX$4{Y8!qIbdKUBm&& z>vIA)`qMs(wCEV@^X87G}sw^(0SzJmXm%jH1mnIO>V+K;bhIIW9i%UH;q)}H9 z(oHs`p|}?w4Zww3q9L73NEaJO#_Gwq&%$X(s^C;4kj}Ir6vSAsioVLpqKer~cjtNbLU_*3Z8KtTSR^ zEwF9%WiH{=rYlHavJI;q_d?&FaiMYq(wmvDQ&D4Gn#@m`HMEOaL%UQpM?yKhBCY99 zTHQ-g=w^pE%aYQObfEJqDWvg(SDR62(AdFi++fO@`?ry3;o*azd9I~tjIp8& znn%(|X7qr*`CyY4XzhUiTLqy*W2NOiMUL2RgdVt6Spw2gfbZx(DAPG4cNhrTVf&a3 z;f)t#AUum(^$idKjR(715Wvg?Rbn8p3H|QN2|>qCe|b6v#5cHAk7*EZ+8`u(#A!ez z3y70#BtFAX6h+2+xK)>H2s3R6tXFN=s2QQj_-qatfqYzNM7nnU80W~E9csW19T+i>GB$aW%*vLsB z2aI=cq3%6jxYde~iVdVR;EJmIw6WC1`z-`gPl43chLmYR>Oe>r0FwGWEMmXA35%HV z>DCdZy4ko;-BAc8j^pW}V&V+G&X_pMBPNd1jfZ~spJ$UhM7R&`1>v5!P~Q#!!U4xT zXcd@BGx$^E{NttkBp{z)|7piFxQBm)R6dML^+$Z9-lH`O;Vjj|;wCto!~%h^+|e6i z`W}*cv?1fiEu|035uBg>WDSeY>Gyv3DN>INdw}Kq`*7e#L*r{)uzgC^0L|69(w4|i znWx*Qv*zk?w_04ixw&w4+3$$^rkgEtpU1smz62L)Pl2@0jfAw+K+4pR-hAAGbe4uR zQQD{4hIEzHKI7Ov&ud8aUpU1Emi~VgP(%Lh8Dg6!LkZd!V9JB1r9uoIkd?_Q^)eL2 z!C-xn3V*tk+5;@?3lzV7i9Q&D&(#-~O7Z3>&Q%0SI=6Yg-jyE)`!13I<5=+*1sI>c z{t1(2zXB~-0S}4az5FJ_6=ykJCv4A2xKLk$7O6Yk!a0i?Jm@HTN8`-ru+NAETD$~F zs0%WH3ifOZI^Nk~$KS5h^yh)HN%DTaS%)o45$9*7YN&Vih~h+3P1=|~!1io>*w=hW zy4m_A+--w%7gRM9hfLdtVSNsMqZaM;xgc(mNI_NMUAky&LrfZ^T!m+CTWrk9BP~`E+LagTd*9*;a-pb z~qaj_p5xXb2wY0WMx5mRYUs6STdlQ4e1-)3j_Xw3ze-QJxxeoSH(2Toz1OgxlTi>5=eiVVQGY$ zEJ#xc=^M9DcNrnwZy@#5IMwg4aO$ifog>suwIQ8J>ac#z-5nS3|7lRI32L|j)klN6 zwzY-SM-E}sK|w0Z2KB3j6zNtYG^F*T0Lft>8A+`a zq;4A0BZRd57EPa-?Ja9>@%#!6X&h#*@c-G6M&VxQ8-feax4j?e3#9Et3t+Jxz>zFZDlz3(kL0 zznT^V5m2%oJ*+W$*Th&8j_ZYt8 z`0IfZ81We3(S%l~8$jBOe8>iL@PQaWyKt+%AZLP(u~C55V21D(m5us(yT*uE`rQ`_ zAev#fJVZcZhJhI85)Y`&&}P^*c%>!^Px#w1_7! z{nb;m5nDkPBV}^Yje7BsUdE~h4Oj~s4lNEnjJ1F9YjEbaBPrI}Rx%2!TDU?-*5FLQ z8k}Mv;(`6avuj<|Q}LvzCNnd1ZQSx4z5X?BeX5231lBFnt+7;#0CQU+JO{7T(d za9CVFO+O5-wV_!C*=#vwH%KhQw?-DLaD7kw`q?Alw{}YOLN2v8|FHO-^RMHVAG`J_ z20zFJw_<_?*xD0FQ13RyaYk61qZj+Ie;*b*j2~?e!#?aEXYnuhF#N;0>Cx-2Ec|jH zA4Cj;euA3XTqBl@RY=%IYxQ{+(^NYPgYX|IRq0aEYH6rHYx&{&E_7nNqx`2^@CzwF z*>(*%$Lku>Q9}mSH`_HtL|i@BrUA9#2Uu&C)cU;C`cyjq2--xU#)Cq+#DVC!erpGEo1pnPUn@`;J1EPpJW%^>Jur(D8Zh(1fC3>&<+KvCGjG>xJsHYXTdv z*&CPNlfwn`*mD`nw^0`RDG^O>zy|s3XYohvI>EF`=v1TBOKM5KtNJ|LlLw)`xUgyG z1*pal*E7=-?3rn`%gJnw6J5)aJAab90Vy?}0N(poC$CbySQ)vSDt!G|__`$qVBC$2 zAJl(Q@)syc${UsBOT&O%n>Q-im$IDZj@q)N{vfk=NS*EjkpWn>wrHcxlp3~GP%LDN zg0Y_Zq)fnsS94${O$yPo{n0K11NoqLbY{vx4DPKlTw_$gou{UCCU#9rb}dWFMd+k_Bn=ntqd0n^>@V)9Cs`9(>`fL{!5Jh&yh_HVPuTXYz-t%;;t{P ziA5T*Xag+LmG^usZUrj3U#KN{cB}78HLV`LQ{-M+W{KeTu(dw-33A}j^8J8e&`p74 zD1)95>#qGptPiBYxSheBrnN*vn)NQH*)V>3O8)D(;dmQ#j_#uOhR9}{QIv0Q2T|5e z`Djsox7VRWS#8O+X*$)SsW#Nl5@jvP7g~~BtR=be_8;D`{r{z=kEpgMgt3p&P+lxr?8om*vt+#b5k@k%yL5VuTEdZ z8liy1e)PR0l|E}%8g(J^Rn)kA4LY)1AwFLaEm+dy)RQfZNWs7OP(-L+6f~ZRs@<$F zcQ?+3(@7!r$hagE+xi!0b^(Q%WP^G#U)QNgRk^4xyi6z-;aw~Btdx4H5<)X@T5L?6 z(Kr9o?f)kh1u$!!h1Z0w>gA21;UGIB#UCkhyCPH)YeZKjq4|&uS=|y zE|(elm+R|Aqc<4px});Q*6Zn$=ABvZ=8mNsdOAAdjTG+pke1ey+L4WM93OIv!~DC=G#F3hj;2}u=3_6|3k!wpfA~^h zV1hsyg*is6I{oIA_L?F2d;_18Xnhc3cJ6m^Z-m#%8Rp{E>NaiO{W`Oo3dns!-yrr; z{Gd}pxDcmMN zB!Wo7j!Wyf3sb-{WUtN!RUC1|kabnxU=hIWFrx{G?YUOZ`hWHXt(>E>FY0m|j&Frc zjUfFu*%yVTPGetea~#&bXm{@6#?L@P==Dj5E?`MScd?uzo(!3yQq#idE9ShSsLAfP zGhBDA5X&xEhQ)V9QLc#=w+7dZ%O6fEjGy1o!Px}IC~zoCfrdD?xedF5p4Heh2aQVO z^qu4Km}?1)5av5Q&*#4t+!dr-Sg_*E6dBe>2&<<}p&ePn!`3@YNR^cef1 zhWZE;!8VtJHAI2ll$lG4^2KP!G1=ZW*pLiv-m&oV4neD0mO6Az+tyI7!H%1^Bi|%& zV#BitBf_AHk29h#^Vo>zSay;NT>$MPb}*b5#{QA{`(>7TYN%g9|F(&TrvI4aGwGj@ zPxAjL>Ob{J{iC3Xe@9|e=fH_wnVHZJ^)b!e;6~ba7}~dy`E?$bfc>Zr#OO+#t_TDJ7qL-;?ZG_2olKl+aXM!qmC+YT?7p4cu>w(N&P=qQk!a#jN* z8&fyxyM)6@7^lsYuxyiGrLES($yah!VikJF+RzVu8xb>0zPcQyePM8~L9B<>YQ^`y zbmaHgn9_ddH?C#e#(q6HkQyk3BL+cnoM49IjBf3zSz$b-_h#89%HI#Zr)}r(6Qa_@ zKJmRK^}WEkeYX*uNMqW@Sl#lQ#^vwWUTldn(BeaPL4>x!qd(0MXL6PaofRu z92bLActM0Uaz*~Q=0493;@?@uIZP?%Fr}0$+x`{z75%RjD90`9z#;VKY@9@yO7d~~ z7(A?I=Tcb1_3#02gsoM{Y$vxW8NmY1i=^ z;XhVd;|S)!C{PQJW!}(K9%KH#TKeW;oTT6X7Tx~g$54&H=ll?IHj$1w{IU9MWPZpb zr<*YEy&e8tFs2!k(80JYG6s%oM;PhVNcq!@$+G;?;{V&Y@$%V^yJEsv)qw*UrB(f&W0B9jy$&Ov(tkL9 zL`f+tfjWa;hW_9GH=Z8j?L<=-mUEHpgPP^Z8<{ombnn`m-X?yv71(*OM*FMoAe4dt(J_p!*|40L}>9X9xFy#4=o z>BrJ;(c*M8`f<(A|4%Me(Wgv z(Nd2`ryaHZ^`pV{SoGuA#-b^Vi1++AMtzPxJ{~uISXzAAA+d~$^r(w6kJJMs+^;tN za7eiyi0MJ=(DlZK$J`^@|8nU3z5h?>=idQ~M&_4e0woACPe$;kycMQPM;-W4g)i#R zl%8v9o8it~M$W?XImywXo`+;&eXk|#jr{)0_VuhT4f|&^3zws^uk+Bu8^KIJ68tWV zZAB7{sSli+jDP$^`sb;fK7t=BV877o>0gzi!+0HDhz{c&B75bc?_)aYZ4q>0HG?Jj zjgDW^KL^f(b8_Ik(V02_#-4hF_^fMgHK%?JWXztQGrWhsnv1Y%9`HK{zO8c+R?R2I z1BtPR7#AU4I*@Y6Cz*V5!~kSI^5dV2mc_;fH|g4hnNFDPROs)A@8me`fn}M4)vh+w z!Sr|$XjgR~Yu4UV&)P*kjufAMNYmdSq8`^`aazkxhq$-XQE9Iz5}O_aiJ?48r)j?g z&!S_u4GkfMv664e-+$2jd)&zl^~1N}V;R5OLBm8kWZcye$L|iG{A=TPKMU9Y&Exmo zCmmG}P%XbZeAoUD9l!q-|I@e*jmW<`Ci#c@iIe)s?J%%JvB>8PD2IqZ#$7copVuC8=D;McY$kaj$&JAmJ3siJ%hRmY ziJIcq4u~l~~2o0HTu);`x7V_)A zKBTD1l!&Qr$amuhFnqH@JYSL%fQ(3f{o(SCh^>g#sIK(~J&%BN)YYfoXaR@cNNlXl4UWyfifc?JxDO;b4*$WY2>u6uio^fv1HfPJITnroYl$)VuWb>9e~14G{O5KN{LhQWe^Vg> zWO~hOH2%LP#NeMCjsLhW{|ETLrnBHb=f^nyf8GlCBhxWXe$I}?-_tyb|BJu)*YUq5 zR*ReDMMP7RYdr|Ho)ejHnwaXEm+R>??@XsqmM1U*fj~|=^G2m|yYQlP!~@e^i{8d+ ziFG(c58nL-Nu*!zFldWe8S))U%0<411HVT62ct~?>;Z&}8HJRHWH~(jn`=HVu307i zrw%X0#HCY?w|EEjl8XK}&O$`iZAkoF`wkvu2doV*ZrJCdp8zw&dSm1BIgFNPN#0OA53IJC;M161=7vOru5!H2KX^e#hNrDMqko0}gMkGc4h+&z zvs$yTe8Yc;fkq?3fA#erHQRMqN8Q!TV!Qh8bJOzS$4ItLTzOS6cpq$6iLLr?W+{*zsHRN3|2@3uq9BXL=d^$M&y1Xk|l%WQbFVi8xg60 z9O#d#AMt$zh(={$-x%8yvz)oR>iGxRFMP=73?n|S9WqGC(hiw)y^{Dgl(7-2jXFqA zZT?Gip9o7Lnbbc$zJ9QKGDtT4vp9l=>7S>ku_T~D4~6j`&Ns?M;%i;d*0rG zQxu#F9v_zA3A9cGM-tI%q+N83X}N>!I|DgQ>RN~C5IVmC`DI63Uvf0-SI>G^vppFd z59?QxSPS`j-O|onFb-Pu=i(;CHq^;EY zrOp<$MlYoOxjwUz{x^a?Kv{n+D|B-%jp=e-?D{2C$$SaWfJNYHf`yLg-bjvL_>M@2 zd|dj$LpndB2kJ*63(}+5|B|g%#_7ZZl2!X>v|(o$d)=o97Oo?pbn(Bj{SLDZPw1O) zc=>iWknh28xAqyu`TqKYwTBewD}iTZ6+_5-hyh6O zJ1qU@1Y_y{F4NaU(Ru&TIbo$7OE%qY4h(UR?mY^heDJi<{C ztD{_hd|3YO`)dq;TWmWf{vJj9#lnB~<70x~So_)ec^zXKY+*u7gB?SDUVd!}uANB{`PTJmreo`G+t0=mtrWy|-!S}#Uu^#2O9#>4*zu1!|M2MPd(OyV zguZ^PHJ-k?AN@Dbx8=Y;OCRmmDEq-`zu&P%vULU^`rj!?Bb}VYj<*Siq}BYS*Y|XY zX;D>7B;v`v=fj5N&SgtvY5VRl>&p+@zQ@PN@0S1iXX!6MEsczy!%08JHF!Lze{i6ocYiq$!m}L>~{w;>IzltvXgt}Dp z2jw%h;rJ*05ADi15Fo+~7=^pFJdv40CG8BXe<$d8^uKw(A^NgELAsa*@%s}TRzIGz zJw`u8R{$WpnD?{T8Pp{uQ6(!iU$zk3GC^jQ_TNY!xG4H`<_u z3IBfm$ZbsCt&LWYn1Aix*GT&e1{04?KZ<z&hV3>p3VIGF!}#NAM+<*r$y&S$M|RG zWAenRJZy^+Dx^|kHK=C&pqjUfYIb>Q4n#MKDqN(I1YO99jv&b|^&G)dgOykh;>=d~{mR#3=JEJl>ALgn@JW17>uWkQDQ8{S^`q<3 z4fua09=?sY+Uuuv9UWd+ATkoUO)|o7QH8ivxBOx#HY?Llw`3#}7xqv>`Ebn@0dHVK z*!dkoFL-)|xP0Il$@^*Q(BeSSr=H-spL+6sn0lrskhIXZ>(jYN6hTfF_qm}re^&}7=t3>_hH}6S)mH2}g4NH)56?kd%;F^sR;&=BLv2IG7Y!CNSTM;CwS1^j_uyng_y5e%V}7o{KE z5;2NI;ixay8w|pAWRtdh-V?cxT2m+bp?Bl(!7^+RKqi3&9$ai|PzztCs_9l$(mdg3 zrM`%MI@a}9y8mL$_V!5sedWhP_Fs$+=;cxS7iF^lw}Z#>ttRkT2AnJK6K#!7uwj|; z;TY|!_Jr>ue(*Ni8s-EWsx7^lHm{> z&ldLqCNRj4TD(|XH4}`hhHjd%aMyTIC~!eK{EvfEeM6N`ml|M7O+kagVM+g5-t-LL zX)rI~ah;y!gR6M}J{%5%V{9(r!+)7={Fga^aY%QMcWt!1hq_vwP~_{3#^nnR5iW5; zI3tkXhyZuCK!)Fl2ypzGX@TFrarhTS$*)Wz;GF|;sIO*Exg{WsRXKa{-(oCXiriASbuwbH0Dr#*`;4~5jdL`u8*pAn=U zH>gPcr48$kv2QHlf?N?H@Cw!t)~C`+DZ#+Uu8*aD#Wimi*K9fxl49CKazWJCHH|Y; zOdDoHWHZE^8yab}qfp_ho`_pg61vh7rH0JK6QS>V(1)2Jl$^vbtWnDH-w&W1fd6*K zQRDBGP6GiH|EASx#J>q=XWoERk@*&wzw|@VLrFdTKeOJ6CND&^qY?c#w|`7!Q9^n6 z_CNIgqW1hk+T3dC4W1fqG{-+n64%N_n(Z-Mln4Ix^ElUI^oaUftNy+FG9s58dj)n^Ei+bx_@=a zD)sxFmW9FZ>sA@`?figJ(cj0CA3*&RCw~a*9%2ROcefl`pw#IWHhLuegO=}Om><2{ zD|(Ynu>|xOeb&n8W;(X{(G88#H$am0}kW(FM>Mj1s# z2ZdL|A_?dy;D$2qxQ$wEP~*xrL%!!ZRk!8MKA<%$2nxUAXEaOxkc~b&JXU zql}YF0}Wd19oS{d|_@BnSbm0D% z(XssP$lpmuWkNfXzK;~Wdb-#G)DYVBlm?-S(}eqf-d=CV1E9FMn?9zshBk|i3izGa zEcFi4xqgNJ;?9SVmAgWemf7D3hq&#_12_dkhAO4c928+A_f>2G1NxU^Hcu0|7w1?ZjHgh zPtOm3y8iSw_O!aH)Af6Amjig(=ui`b!4N5sVytFSf4-{`cSI#&mHK?K;+!B1#$aTJ zX7Js}1~Z=VnV8vNo-;aKth*GMKTSYA9oct_SG$QNT#(4VqyNxH z{SaNhkFl@0m5dz#g)mRvgO zU)uk5|2p*V@BJ=DzBaEqaQWI{{SW*QQ-A2d>-XONaAN;~j$tDI%xS|vlS2;wTw!KG zPLzkZ4zBQN|BaPR%lMTm3wP?#p&v#%GjwBcxpT*)q3g#Pw07>dg`RQq5=3n z+B?wseDpJ_7Q#c?Aw!|R4)M3QhnBUD{`=bjkB|5E=QRFu$iq<|VZ{I0B>by=h2EO^ ze8Z%@c2h-i_O|Rz**`Xmro`E2BQt#Xs83T#+X&u6#`*QkZ_`gU_6bHX37=mAHz+yO z`}{miO#^#ze?6Ji%3A`LKM~Un!K_JDl|z#_YN;n^x;ha*h@(7M-3-r*6?`9e zp}=x7G^Tw}oF5PW-}Vq%y|NvII`b3y7d3s&a_B4Z{U?(Ef86}aAyCY-ytTq{(03LI zqKH$ZVtScMxd>O7a0PBumv4kBFmvu`1y0;lD(%_C9f^9V!aR1Ige`jqytOx&{viIU zGy3zF^Z&I2X>-T^pW?Rk5rg0VTmRoPKZV_&?f>ieehrWdoUBFQK`i6Y(~K3k8L+iD zZ=qU*e1mY7iMRUe(`|t5#Qho<#mWa~{&b65=@JOoZXk1nRg&(C5Z4cbaJP1>b^w&P zexqJh)vGOxGNE#j>oh~IIzH(q?;ko~|LJjoSR(+q<)VW&0%HBA`#NxUiF{e%#&{e5 z4%R-qS*>fWz@F~69BbMAo4kMPi-pElr{x}6;R{{Tgs|r!uUhu(?zxASzl)=lc^Pcd z`iOYc{CiEA=sfjYP(W2q$8WGuoj%#YEy|7`VF+UCGI=O%MUr9E&Ot}W+^ zW@x1;$~z;96GPViLX$%SKo%h4|GiSs~rB z8q2oqlw^~+jF_$Dsp2K8>6ZnX)XqykLl#f!LF4rLy4rX48@%R{cQn~4*JJe9DL#MO zYn(h6bFUYKeqBbD=@sJJhYt7_R*`)X9tZZ~V`xNQ{^Y(fD-YG*{u2AQnaV8qjw(JA zqY_N{=9@y?PIe)xmGx=QR=n%`QycN5W->&9m#nO}>`S{?!PFO!YOVbY2Tv|Eh`rx`JXUb2?EVl9bmp~93@Vxc<(Leyt zHz?lPDnrHM?4cDpot_ml@YNeg59`(UD>g%+#U{oHFOd_fdAXaPT*lvT{}a11q3KWP zyF>f>eGCuNRR0nR zVW3BR-*a42i+Al=ts859yamfVo)3_~1z0t#o*mX@gpf)td+1;xB$^2J(7zxj#V6>P z33#ex-K3&-aFr%Vr;$IkKjMZ~e9VE!IY}C)K&!MuU0b&h^Hl_-dIP~ zwvt}6hOe5mNZ+@gJWPJN|$9Z^!?R_Q&5Da|<$zvMU;H0LZQS)xDW!dm1mt4TX0$ z>;c;3iet_WY|qUf9+afYeb|tMRGf_MPu53xru^`Ox$BTKH(27u8i%&$^D1AGT6Yaf zAhQryqo3E{LOh)0p?El$*&%b1>%rEzqndAO9HSg;&ljZ_CrCWfDExP;v82FP0ozUq zpNJb6DeSU;9F^Sw<5a!4@hvj=xn1H!>O<@kXs3kKa4w%9Q0w%t*MAcLO zhNW(MN?j1B;j!&ko`m*!ol>OzVQ9Y%{gNPDX3z7>+6ayCc|s)QU#0nXs2)G*DEOEC zr+$)O@a$6QPn}UHxRzbs=b?Y-4N#9wQsk}zY>%S(gAutn8OLf@V3!SbiHx0agYCKF zYO;ckZKS+$Fuo?E3UH|B;GU*_S*16G zma#doHUW#MMWbPu3YhDR0`}~k#_`6wxY`1bz5~i}+2*EA3YD_FRUC4T_G=q7wgoHI z8;GoUBU8)iKR?s+b1JDaETdu-5fz450}|pb`0V3+yY1P)_1) z{HaF=zyEsy>Ki!cqW(!Q91J8v1#Eo~c85Lmpyv)tQd6IV)6Dj4KNI_@d&=jOi~q>a zBR*M)&yW5nj52KmJ}2wXXXwvw@$()03@|_2TJj_x?uOmtaTOqjvNbw$r_g&!zXHk2oAe4H=VFJ@WTR^?M(7s(&`> zdRZ^77hD}f_`SE^O4beRgl?TdHON2U*eYPgrFl!W(t{JL2p=>H6^qcys)v`WRrxLj zZP)Jb*5Wj8&pZl2%R+T46G*Ptm7^$~j!TqssU}H5hFT0-xB<{R^ zsTD10VG9*!CG+0h%49NNruu|o1rW$hyzHAh+dDZ#8lrvI4qQc$Hy2lr0gh z4M}^O^wa`O?TAjjr{opa` zTaiDKnE>f_shcBti5D$#RsNsdoF5(^!|zeb(@#IGpNCDL#EIBvV;(vn{jBL@h^7xv z#SEHE`~yu~Wrn#@&93CgZ}Qe?<4y35L6YIO=N{qdpdSyZ;$2Z!LBo_7Tds z=$Y!vikMXsbd{I_Tv22k(=9TG_B0vpO;gqfH`tN~$d($zev zl_=5q1U?LfD}#FEBZ2P<178l|108$b?&&(xc0h=Z>Z}K2M)hGcsv5sf zvr{oXF5Z(NaxGE=Nihxil9UA@JIZ@m>y(1fkioklmk7IT;ejJ(ch{TxR-6m>@I%`m zAw#Ku#!oXAD0d%Rffdn|89Mbkrk)DWw;eCR5=f*ZoetR;SKj>JjP` zc&J%7CYY(!e`4o1qVwCbe>9!f9(JG^2fasGmhH!buIB&AjT2UyCJH?2h9Ugn9UZc_ z_Ad-~%YW6YPg84P#6x=_m!{QMU{2zBc_)D9_2$pxL2Z%+b*%~N*Q>pM1jDb2mmAJ| zc=$2f66v+b_qiQ^7x@EvaPKdp;>`f7dPuCR_kliPL-oL9tU(A#SkDI(rt$oR2?Xy2 zr@1!2QvYPs4+Y@FM-uUAQaf6@9xbU$6EuQ04-L# zu!QHkzjEFO_q7NWiBm(Q0Ok*a;hYHU={oafR^(?>u!4$xF90MI5c~Oclz$fG)u}U} zKp_nL+Mj}MW~#kMf8VO!o+$!40Y;3TLm`MjGZD(lZUw~yHRdDkU8nu3?ncB>J;6wJ z%?%z{(uU5%8zV%``N1kZKX?Xpz<6vT+%O&+1b*`iZL%Hj5o=?)Ob?*1&%zb0+7iKM z+8k@d?$)T3zpz(QCk^CG?h?QYAz4XSiJ3BS4q*R{dIw2jqFh%7aq$hTD>*9*bL_NP!4hp5Ok6i>Qe*1!FfRC zc)tKk179AN;Xz%rL&R#&h9CKWoMI^GZmDs6|w!mPIbftFZ& zFU^cv*C$<$Ef!DiPyD_uxgVC$btVEtBRoC zh~EUb10^|LT|-_Z3oW&t+-Rg$8M}=?6FCbu+38Ic>4Tg2Zi2Q!h8HP>nsXt3hWtf~ zuQFp3VFdPw{kt!nE^mfWV-Y)27ksZ2PSfhW^IK5`TeGaz&DO5>t+jj44Sejg>;XPm zYcw$0o^8t@;0mv9a>Od?EY_BxW)GR&8&CrqyOJpx{}tE|V2!YZAZ{KEVDCUxl(i)~ zJ@|(DwSh8ApbWkMHrNMS2y6fK91nxEFyK%{cY$k&a4P47daN#4`$JF|yG-O> zmb8)j@G+Fo3p3;uyq$w&UUO=pYNka*^+^C;MD@DSZy`QJg!OwuA~hMJh9PQ_SSM(+ zNLomj7E-=VW@252yh1)@O0x4_m*MoL3spn0v%cwqzn_7>o-mc5wAh!?{(UC_Yu5qf zlpaBvhINvQvanQxaN2{1Npcxq(aB2uCM9)2i5khOo?P({5Q9v0bT8_galVK~t_zZ& z(-OwS$GXr|8h;_Z^gFJqG{aWCp#@(ck+(Bfi(pEo*rv(hXtD--6q|r;%JwR$2i`0E zW;YwqlIwUkL2$?yVi;Vd3I5%bxW;PWoc(kBJWffA#X- zv8X$~0}qPL+bMVam#>bbgVdQ?4w(5=ARcVzKmD)8|wS%B!mEJ+%TS-$YAZZc3JhPh-iK z*yyzBGo}js`MFs?QTzx~yd>NLzi7TRTsHHD$%Sb63^qJ<)~u-&C$QmJ700+5mipBW z;uT$|8Vo;)8lt@x`~Hqd5@BL*vZXgOZkSwg{4_lFzIIl{QLbuL(A2mLHP(kGu)Or? zhO(*Gvpc#xYBS}h#+A=E<*ATyes!c%v&yfOPD%M|flgC?&eYiUdr5gncY%Kg&7#Oa zhUv)EuQR94nm(dr)@waiZ+&q}(ijZI^4|H{T zrmP>E_Lrhi_z<=qt>O4c4HZ&@x8_!9BDNN_n`8yxXv>9PHGF7*_~A+ih|@I?ppdxY zFPP%1SiCN_cw?macSY<&MgJ&LgucR~4ZphkrKXuG8(3v7atO`_ZY%{bauC`hx;AgL zw(x%BjfV~MuOp=@Sk2*YkU`h8`v%n053ih`wXJDof|}Huq*EYi1wMu!jZ}3?C92}h zV5+aKsCN{k=Ii6(QMRdN3raLk*3i6Ag(~RwQE!YD9Hm67sBgyMgK_xIH+3|jNPY8B z(adIkqot&|-;nyH=H1u^8#SCI$#)kkG$2a)RY$9G#tJ5!opaz1sGar;6ud`c|;YXYDP$Z4l zm};=fp+16(8FQlt{zUs^q2y$F%Vd;#V5;P(RXXF1CZp7ZjK$1odoF$uvyH>qs9h(O zII|5c{}$g0^ECnPYET0Bcj50@30fom94)4?6Nf)p-To>3)nqhCHl3LFN1yJ_&0RE-%SX&o73JikV-GsXL(g zh4z1l?1;I4k*c~>{D=E`Rh($OSaJP~>DNs!pUR^)kF2Upo>Gx&HR8r?7;~}(oYX_vp_XT4@fY^D{DKPnB8$cGV6epX6)?Hv zTa#hQ?`df>zgLFfC$sulxqCjjwSR z8(kZ<+l&cNs&NP`6Mb8Liy7ES-vIj#<=UP#7zK5hNvo2YJ=SCWl2kWIgI)=Y*!5`< zmT^u*S1^~t`i<@CfeZfW61R38+|PPFrwgjV{+IE3T7`M2O!$0(5syiIh_0c-Cs?o0 zYI7gUUd0DVRG&#G16K`#^({yx2WLjyTjsDPMIInZkyMO)`@)|+L6)H>}tprgv;1~A2x|Be)32yizN$?NR9?#AG5Hk zaFRT0cZ9RB0R21s=C?TGO-KZ>`soCTl!N%f)IcbzdIJd!>mb~vo!jEQqky)MJ*SJ6 zyW2Z|h!{q6`!$1m^=uL63G?6&2u{Kn9Q!Yh zX%8znI=LAEcbCBA3q@w9xIsKjP@JV8*Chu zy#lCo^m~*)<~~Wj1%B+*jhlNxb{K~ms;w-r8Ff&jonp47n%2^=6#uYUt!)?nfC_s-elglnD_1S3sX{lmt-jO-eTT&%P%|+ z5DUPHP%_3knXka1PbY6Ty-$VibqSy)M!XOU=90dgt+5Rf$I^V$I&P=8{2ugwuy#H7CGs znUA1r`3P%{AF)4R$F3NAE@C*C2igxf(#+ToSFz&io!VYlo{`C+u+1-;NT-NJ6Pfsx z&Zc9)+0#t^Mv=4+F?z%_=g0f7%4~&tXAs_)>@bd#W9*Bq5;;o!VsfHH8UaEB>GHc$ z8j4saasIP=obu3?`n(!cBo)+dns<;n4Qo?#8Uk|zA9b;|eqr_6>ZE?_E#4#(J@!~< z-^K&7w#H}IsmP9_w0r}fEI2v|r((T{_pM&vI)^9(Z`B)!#`QRiizDq$QjOIJ_?a(u z9r3?C;y)dt?YCv@Erbun9`P@~8243@jybTTbA`gbZHo)AvD0G6d9yzl0_ zo!av{t^Se-C+LO3G)lJ%wU5!B1)aK54-mw%9^qL&re#V$jWgGtg%MjRx+pTuv}dI= z%`*9l1Rt|9nO1DlN_1Kl(@ITRnNG`LTBS*=(rJFCEih^IlJ+Z$?JeRnm$T$s5u%0` z>?nd&kWzp|4n#rFhbbU~H1)gM#9#$R45hsFCVWikf|HektGrc=xj>vA(A~B4X!<|) z`5@0^CIS3WWl^||hR5{IRfYI&f>u#5=P#8$*irqXP|~n5oZXZz}*x^{}A-~MMS)P z`G2_0ZPyNK?Y?sZpLEN&yMwadbj?%Wm}usyd(aGt0#sR-u@o;NZMQfNAL4-`pX5jW zB5kUR|3{{+2j9ghK%JP8)EU&aG4SNg&{LL>cf4$?Ek%D8A?QedP6py}oa}zCFO)TKtbYGGrw{qmSZo zDSKj2r(1AV1*7$kc}z<;T|fT*?D5l6@YvP`(+z^OI0S#QS`hqrokpFd9KUgH)oEe-n%vyYnm|H&L6r+T;9*eUngkgINg;GLWyZb_UiP6ha2(d2o!*) zBT6hHq97NQ?)LOQMqD0o#Pabqu5P=?GFb(l!u)+P!l3FY6`@TS{(J2l zR?k;RLSKD&F#_1)jULxK^=}TmNZNlgkbGLbQ|p!G+NBBo>nC+$sD(;_3vxKEk|Ozy zQNd?R7#=5qp6cShfNugL-2fgP9A5+9>OzxXA>oQUk&tT=5VM9J2{B#3^g&EVD^*O3 zvcYo_3&$2xCauwGSaN{Ji^=#4nB7k4_KN;SiN%?%R%TL_7AeF}5l2>!s0o}mTG>(P z4N{rb%1x#)#Sj+iAiGu?XE7E(by_;pgfaj~i%t`*EQSHnk_2P3pvG3lSh1)NTFtQr z^vo1#ex_v#_UrW0t~~}FsngZ~Ri1papq0OUv&hlP945C`=DRwBaTTJKzy16u1l#K$OBl6_CP&MZNYn z5fZfv$XViP6Gsi*h&uMh14}b)=&og&~`D9iU`T8A2OW*PAq> zAyx*j;b*Zo#Kl+6Bl#;6pEQ5HQui`^dsv0COS?RQt$2l4wMInz7&9= zp+4Wz8l^9|L&g0a;Y95RAeFCh`e9Knarp2XA%J-OTf0P$e?35YDBga<<4=aI>x1B3#1^IRYNNZM0?eJM7CH_o3ECe;Po+T*04CmpfWmlhK6yG4r=G zO#2W%8^`PT1?FMbxA50axuHtOFKp*4#)^If#xFFV8y$5$b>_gw_wSL#4t>kqS%{{3 z18E7Q4Lyv?)L-w`(Fm_2NV1-$kz!NmO$&bEWh^{fFLEU_nPf~$Gd2&8Z#oXyRNnHp z(bK@buJe|%4{1^pP5}%th{sbgs`{L(5Nc2{qUzS}Q!CEWJG_haB~Y^LfI~BgzXI5F zC@w=tVNwJHh8e4%`xn@Y_=kN!L-je+uP>ijj=NZy5|)(7<(1{$+W*CK!s;dd$JD=_ zB*OYzFq;g2h5FgQG72HMHMsjc4mOo%N>Y)sWbM6RKbneVFje6wU6N77hHXzyErr>8 zDr+y816^rg0pLwOgY}yDj^8bkUXJzx8~0ng{%Nh!)8|ady?My{|@4B=R*6OWanP zX-he6*=%bt*DzSBJO5UU%YRYVf7Ofv>T_n@Fb&kQ4$sr7Z|y!E$5;B3ytU8Zz3SE; zH+pMD(L+QD@l$Ave@3<{L7Y*_2S0O3mnsxQQbhW`>hK?#pPy`JW*y10%*jG>+8~QO z2&Z7rP=;ceWmq=SjH~`@P2upV+-4Zq+wB(Kvxf8DS`dse{JVZhFQB3%bz)XyYjlhg zA%@{dUoc|Z-BH;hkk$>@~j;toa%tQwsH&j=qN zuh22`1ha;+0bNW(3cJWA+UV!d14e!kIbVWOHGS@GtvH=!^&C-~KoRu7vW*~jj42;J zgna`a(nt%J!)4?RY@*}H?p(Osa3vDt zVFABDYHFF62jOvfn)>ERF>M~dO-~w_nNU=jyo*Q@aW)RT?D7@M3z8dgwEVR__dN<@ zXCO;pj>(!L_RbSmnDwZ3Y=A#eAJNAJ>n2789B_w(f7Fq>S8v_=3-s###psp3-ZQRO zZ~rDiuVnnA|@U#@?*^Pny}<=lC{!1(pYF7(xd+wI?QY~PDoUywsIy%LV! z;NSjY~N#=m%Aso zkqTg_rHe3*Y^hiy64)j9&0Ga0LaExfOonRZ&54Jqo>fBXQfdM!R4*2HG(ax=JaTv9@nKgjb`h<|C=KX9QL0fCUvEg*S*URj5W?`W{{V~2 ztjg{mwAOx1RoX9Zjb%av3V0s`!8m+Iei0YI-`pl|-L-H!S@w-x=)d1J>k%lt{-gRP zsj)3IpfUeqKB!J9r(K~KT~X(=F*{H_5ktjw;v(QOKhWUAOrjvTktG($2%=wtZ;B(ZUjAHOV`C(sTJemZ?m14ZJZq@|)&ClK94IB$g;lg0|jhF>g49K^O zWFJKpG7$c6y>+}eB)sTbS`AAwEVgHqtAI+Yho~56c^o0zY}z5wya@(hc{SRCSDKtq1mNAol06YiQrf!hFf5P zI(`x7SI58gplKYx$1!tHKYe#LcJgJ9XzPqTC`<*$}Tk= zrj|+ej~b9&@8A5JlmAKP@1^sTH z?DLu3><@j+ssE3x|1Y}01+duVYy_1i1;$0{U*KfFjoIhu>`SnLWA!1dKRkoIJ;qi4 zSf{`RERe4Y+<=o#R(n}sl@$2qWe5H&C;RcteuU0Gxi_+N^-TpO`#NSf@ZWZq>F{hk zs4y4QZO`OE4nW0H;GRhRE1c|)G5d=;`{}13yN~ssAla{S)j!E8a48D}b%7&>qJV^# z@4l8D&W_Y?IoZ!;_VGIV-Uu~plI&ew_4jlN?6*<)gM0<&3QlP+*^f51=2smhT8H%96&b+S)l_6KzK zgKt6o=P-LO$$p-z{+>>O{dFiXT^E>)6HYXKwqHa1^oi7;Tg6oLFh{?@E2X+@pDl>gWOe`6c`t&KgY>_8ne$~_RtKR0LUH7>WM268}J!scv?bW zm82W~PnLVPYS*GV@13jh7ioSj&yL}jCU5Oy^5sGEg)6mVu#1LYZ25AB`NBopF=_l# zanqa%){@SYbk<)nbOP(8I8)05il0y; za?jV#cM=SB9rCq%B=L$#qy%T_D*O=xM6`Y=fck)bfaiS%7n1k~e!Vj8-K%7OO1Z*R z0^No)pAa31{cZSpmGev3Z=Y~?OU0o$)aJH7!(a>ztdgIUYW!gTTPyb0pb9L%$O6Ym ztQ6TE&yxpf|D;;{3Qu~0R}dLCXYXh}l~wPPt&;>Ju%Q@x!(I<;s#?%H&070aPpcL0 z-$aJMs@_wDj^p;oz&_8+x0`X*{XWmEDa;J?l;Btucv%k>P{ponN|sj{zd zqn}+yQ@Bq(T*-lG=byyKPj92U2QN%9_?xf+W>2F(S-S;NvhHHQG$PAVJ|4x{L(0MT z@>IYfFF3-d8{T;i&4|6fW&DSla7&DMsQV4V>+g&LV|udP#Zu9ac+&K9j;0^b3isTD zen2|#+z{cp`@FaJ<7d17ZN}v7>h<;X_F>SweRfxvzdrL0%IlB!i_^WnuKZpi{Pmsp z_9j+j_nxi2PyM@??>^-3g8V2i`O}dH@A)X-h2<$zPz(MRU@I-e%}uk2b-xvuhtQsi z9#y#~)|U@r5@h2%*iaSykyPQOcMX)nUIciC4l;mFu<5c(g$EgQk#weHwo?Q&94Q`O z8!vEpPt{bBW_I)OW;`aO81AIO`3DmclZ_R^*ZT0>4u~f*J}2t&DdG4Ob9{<9uCo7u z<0D&`qvPX@M`nTD-B)P)eR*DA5)q1s=>9-@WPmK%?-(E1P-XYW_;5-y0P8**o+rH> z59Q+R)6=qtpww(s+au502O}x37$v^?eK^bn@*$mjp}{HSJ=-(2fTtp1opGNUpQ!`r zOUZ%Y7-S8Mm?HIOaC|epeY#ly)B>P<&p{LXwODsO1M5A9u{OH^$V`#S*nhp5L&jqF zt&y?#5|15>#r5Mm7>h9XDaSAeUbsH#!}Lb4PhLTnb@k3N4o7gg*>-Dw!7!D=Cn-G+ zIa)_|WdE42Ls-;vcQcC1Y)}QZihvwkA832d9)qL)c72F>AFxwo)ov^Ia=uEPfc4cM z>zk+J4nGv!O_G)qCLoX?&JlC5Rpj@P4?up%`BQl}LtXXu;QT2}EF?cC=%oHKIzz>Q zU%i2_gC)#zd0?#%>PaS#dpUU%PQ~OcOM194qd}U5!&-jfVL*C8s7nDR^Af*;DNg}l zu~P~Lqw%{}=w4#U4!~mXzRaR>@FowI^H7WjwQe&3uaTf|u(;=#V;L(6w>iH;qc{<( zs0Q`Fzr9~PPOrR+>u+$D->yUZ5!gm)4c2gWq4}_=m0XX~_qQnxy=?q~BcQqxcOOW3UYTXKMq;mWfm-fH6WQ2Z$UMFiE6~>7I3zT`MHMZJb;9gjO~Ief5u}gT^1gfn>;R= zq5~_OlGKBb9Aa;u3w-F`3~2_j!}u)#=2rl~$iXAFX8@tGvD%E!%A29r(3uyo{NW&t zxn%}(EE*obdN3Tt`K_DtcfFsF;~esEo&zKLKg9RKF7Fc|<%j3DZeq;&Qlw=!gtdlC z9V0b%21_-g+hFOQe@3v>%~cO~qr_mT^l4)0ewSi$baR#AL}@-+U^+#F&SY*O-U(6}_3+)NAgFF=i#Nwf;uUolWCoJ0HvNsGgYPoP0@T z0w%&VLH#(+J(O%QP2&3tY<)0`zJ=oVAQQRe#AS%+@%a_;9@q)JKZAsdKQZGok)Js} zgAV|+fRq(02xGpoSvewf=n^dr+@7%&Ww82ClgU>{<9s5BtMFg}#@y$=nH zcz8Ma0rnvbby#m_A8LkK+lTVXO0<1=8V#3pVj`0!G1Ql5)OoN-CH`pmQRFp#g3wN< zQJfYSF-oc*OfxXc+Xs55I~vgDq2HK?MKlj_e@}nZwkr=ZkY)(x3F?c1tdMvLY$&bA zWK)LeEi$McrcHQM-EU4XOk<1M4ioKj@=ci@qx+mOs>6e^&u5>4vB6053?<}DCJ)0B zrcI1HXb@~4Y-*Kr3o*&v-~&XQ!bgeYy|HatZC>Wsp)!9w9`&Py=5iKCV-smhcSFE9 z&(Fe_z=mX3&8jA*()Q2aYvs6*Bk(PkRpm7UJIukKEI$ z{`EaW)chd39XysCwikA~XJRb6?1Eb>lVxCYO4;fStP(aSHse}>hAddFqy;}aQYkYN zJ=KIi$mfOqSC8CyPUrJdsYu75zKj?KkfEp7G)QSXrTn9Qod3@4$>B!W6=*Dnu~(q5 zGTJXyQdGygQu(o3%H>5&wdf$H1Ggto;JRE!BG| za_R$vP0nM*G&cao{HX%QGw(nT(lw#J=|M<*R-iI@kW|y38q^**?^)C|h&k?-n!Gjh zSVOd?99`3Pcqm^^X1>QvO>|`i_IIyHsUB87wX(coba)L*;>a7EK!amUoGtICLu<~# zmiObsGI)Xgy>YqgOOtQ7uI$Rm<)>J=r=x~B$*jU#!*CyJsw$~T?_KC#QD9ma8Bu$I zHG(NmMRxVDvKd!SuQ;J?{oVLBDe<>DuJI-$I`W#j zslaepI0Y~`tR=ss|7Du~LtFu?-npGkfd04e7xb@x2cCv;HuRrI`p16tHuQfI>E8{C zl&#*tDnb8dzjX`?=rqFxOOemvf))B%xS#>gq?acAI$Y3gvXI~P|HNMRo4UvIz)EB1 zm@79x_M}>}0qZ3j2&I4x%HT?>eAQutLSGykl-=*J!M1}UYyc`TQ$^b|_bP$oi8mcK z_@Y~s4W`w*8DZ86hY@aN!K#^Cq}jGr>cqp0-SIDb<-ULH>&l6BOk3jWEH* z`a75)|3!xh_&v%5;x9!XmI4_x0*M@6;ZiZJdbn^J?wm8bv%v>Ml?M@lnh(wwJ{Tc< z0R2c#IGTIC>X9q2dYEv-p?SzOq{55&&3};Wd}G~(+`&OmH9GSqyZPW|O`%`1=amd8 z^lSD^3A)%bhJHcYAs2hbecQ`#4tvIZ`?AHwo^juvy%gn!3227b9DX6|!oO}gygM#Y z1UXmg+w*Ob!T+znYy0fq6di5PCy7kcpzdH>n=>`C5a2q@d-noRDe0#*(_8Z?`_I(c zOIZ_47JJ|WzfMhhfrwGXJvrFknqmBAd-7jTNm3aMO9O_Wa#M1|bCFCd3hIxW9Xx+7 zf_a8pBIJaMBA*;w4znGv>cUbW)b?~kEwa9$L&3_WU3VR8A3`1V`t2ljY@WUkhEcz-0v|>;YLF(6+MqxWP0^7~FK}#d` zv;?sIPYqzBx>xsf7nyYvAiDikKy;;sXcz}RW|T+AL*yFc87^?jT;MFMa!~a}wFA!5 zbKIyBbihKS6$;T`1(4Xk;iObplNU0iL{_n6VZ(FkM#!uTWa6wMdeZvIL$KWj(`)R0 z^J5N-@|SFO&)QiBYjR^ z1pdin13Ps+>tT6)=-i5@p0cBT*OwMSLXe%Ea`!N-o+19P_6l4z!>Y1SHB5lHzNCsG zu=r^htkp?AetS=SypfASYxGh~4B;K$!6C2+u1 zo$2hD9InI7h4j=Z>Qgi$SgmwWjbEwAPT7PoPU1~Ip_5h2V%M3I7xc-meAnNdy`eQS zyHPXF-rUObIRRF?BRWEAGC)9bm-E~N zU2ikwKPu(<3FU_r*m-*ka@WpE4$s9&llj3Wl8~6)fm@T4yfse}pioiP3*x{43)lmn z!i9>U83dK5@80`1 z@|ag_M@#^nJ@Cc1kdgPIw1q4DijZ5vV&7r*-(Io1P>cYZBX<&(|5X#plRFYLdy$mK zjzF%_1@?9G*1V03I2O9yP8|I)YGWv8g4&X#6P}7Gh0va$f3goH2jo42RScsX${HMc2P$gg%K=_yp81{0#_eWaiM>1Yj;T66*Cq2QP#Z*=g~bZYqn65>0HBZV8`1qN}Ulu zh%_4s^RPVo$1taI>JtcZ=I%_t)$<3EId}k>VSgP!ZguK`WbSexnco_I0O)w^Kr+uc zfXt$@Nw}~K&$}1K2!>T&A;=Al-!U09P9GChbPSDW9}gOLSyl1$u3Cn<`{pHS=*{9J$!0`|C&J~7wf6vwYbaX8*@E=IWw~$KxGOG5=iYp64 zH>Vf!%9KV>W?|^G!rCv(lX04m@7GDq-Mp7=%MaoFNL&boGCZm?8TDS0;gcIG^Ml_O z26;%A*SA^SfcW-!T@@aSI;G88o@j}t(xfRLR6t?qTs)WeWK)MpOR=rsvKSb12teRn zoG~qV61DWH?j1zo6DXwp6KJ_xMG0EXl2*t5tXA*touGd==vJ}k{1WJ1w3H(){SGaS z3aY};4L+WO=tr)?&}|SJ`uNLHG^%&-d^rpg3S~;6M%3Ucl+(6QxLJ@m9r?d3?^77M zE;)X%5~C0oFSf4gmz1{(EhOp2&7i#qO%Ok5?MgszZ82ui^pBI2@&K3m=WwyE&{f|%Y=;+bQf$*^dB5~K;YGEfD<(Q5pX1|Tn`}SVJRMD zrE{OUW|pY1V@K*eGR#6wUBq8IWyT(IJ)#r%YP!kyW%Ajx?oM!jI>03NvuI@B?HRmw zsEvk$f9Om%(>u)WFn=u5w+r+0GX>@w&QA#Qs@)yJd@{V^k&QfVn8m)FdrVun)djx< z&|NgpFP@hW=x!YY{rg~hh~7LX0l@bS{ROaGbfaLoS7LxK-qj(N7cT|C$0VYR!xI7g zuOUAlU>U!~Wdigic?q%nhaWoxdQJd9a}l=SR&Pe=!VeVe9-5c>xg~3n8hNisDfTQxk`Jw(96u5m57}^&p zj)~BGi0cK4TMqk0b>)2vLsK%KD*mPQ`hW~-+Z~Bjg=pIXJ2ht`WU^epi=#QczE@Q} zXTqJHiq`PvM4Zo{XjB5cmSD!r-4uJJ_>j}_02r*{p($W=Y4);#;m+vvi?k$ z2&KMHr2l_2h}84WAd)|2{6-=%GI+=3V=9__Afq>O!NiPNr*)n_M%7?8&rR6% zg`w#=^@3lRL0*_a;EONId+?#T+oqrHn*AokFK?jC-)-02~MtN-xhQAzCPU(w}G zca!aVYv-VwKVJZ_LkDiso%|HXtc^+cIYH{|V0mkA=a@%LI-Ily$pRu{|M>jhn{~^d zBYg2@osv6q;@}G(kArm7-%sg0HE93A;sYpwbsvP6s?3Y%17=kIt@j?Bqz<2&Ak=Nj z3C67-U7QNntF{XivVLbK7V!s!l z8uEwQhdCiGF^bC~kaGW#+QBRR&_)RYL?LEpBUtlnpTKz?+F`^IhbKQ!30YF}03J0W z;jAxaJ4>0881xd2PYpV{4$!-xN|url59Rx`?P}jo2RosQ`fk6j1Xb!h`Wf%qmVnY*W#fG!f9-A`G*P56V}J$1Tmw4se_f z<)^c#jD_GST5WCe#Z46T#*P946_*ce}F+>tRjKwJ#e_zFiO_hA5r zcd!;J=sZiK%UKi(ST+K33SbvnvgJUwXA~d{N`v508XNq|!hI6O_vrP}L!bhHpi=Tb z2#tRLOBsO_Nl=ARD*(sq(QB_VX6(%vTJkncVc}4=3saU{LK0`YWa6dxl|B`{bTS_EdCjPS8$_x9j-ybG6PF7ftguo&?{T34NJ)&7V$+YnB>o1KhXtbgPM z@`&ca5(`kwkOtXvE0^iAA$thOTu2=}51FA4j204QNRWsxma+%-co=?SNE9Q#AS$9o z!QWC^;`23u11N%o-NF|m{J}5!GkzsCf+8p*tVPONk9zY2bQ>T;j&<*fpmV}iaS>4t z@?cDi2m!z(lT0nV@C5~o@Dd47Qx2ml0sH6y<^deh(N6e8=I!9qQ9m#{Iu!4WP*sh5TiU4@wEy72OVQ1(qxqZYwT})(*ne1j}nK zgWFf%Li!LH2JE#f!yGP)$S^0NjU;kDwEWk@MZ$sY;q0)Gh#R6PlR_$sLJH>(K;`?@ zob)!9jqum>)B z5JL;Qg{zVrlG%>h=7gqRvbqccXGWuIfjf8er6{?~d{pPYnKhi;suDok3VQG04n=UaAyBRSDG+VX(CZLoleJi)Y{JdS zQU8*J+kAp@Bn!~t7$0`cpjKVS%U5#*8#iLyTk}@=@shnmZSrz9LaGf;f`}Q5?eNdt zRD`JvF8b=(>`~$2oW+co`Uk{nqi;B0Xv;ec|CxuF5Db6wmGZ*?G;Fl(YK5?$Y>uxW zw{g~40JPv#x&>ud?UfHRz(?9)8{^z<)Upjm^uR=1&uR*S=Ou6Ke#WUAN1o9oOEzA> z5=fKE5iE!X#0uboH^~Tn1s~A*w>?M9klEIoUtn1a3{j*`_&xh4)W&Q`gD!~JND=w9 z>W`3LoO+W*+kUn?{(Kp*<4C^*r7!EablnnDTI569#w!wkmpSj9HJI}bzBFdeE2IT+s(OzTBdq9 z+yuLcBl4mY@grD_l88^U`#lFEo(V{xfId=s#Qo~5`}K%t(k{nfL)~#miy(e@Itx7o zmjr;duP=$g8he(eh8^xk8Vjd|KZ6yfk)-h>yM5zgSX1A-xDXUKbTfbK5wrFm1!U|e z6K&ybd0QZ0$&~^;HvLufwW{YxklQ?d4U00x{_m4qA#rc~iRa^Sc7pizZ+U__*3WK( zyS>qG!sGlVJg$2=F^B+odMRRJ*VEMrf=_e<9}w*J-mFO0Or%JpTP5&=;C9x(FNd6n z6U04R`_f+#iKRUz?eB>H4)2Sg!bLUFN8)F81!xC#&miFP$20ixUMBuz!mWTGeM-yT z@j@Cgg7G^Mk-ne&kG6x4z0WxsCg^XMMro1L5Eg~8@w?- zw6f_&5(Mx%n)?gf!IfVRB`w4RS1y*!ZG$T}oQbTB=VuZ_w0^RrhYYTqE+r(mQt%jb z2UjvhEkIepYB38T;-VD4QjwiLNm{Oss1!5+WxJUdq*zG{bpgZM(N+G!@uVE!Z&05&VpVOl~$fVka?9+8<2qAnd%mlZjtE+|S@;2g-o zX%8b5`5Oi1EU82HE+#xtdaY5A{i8bWNWk2Q&K-^Zy-43Ax)BRjG#s%rU|lG6xL}Aw z_Z^r^bQ0Zf!zB4d(0!FuWC(#yOL!o3w0nTq^qIY z2Zw`dohZK;svXn%CKQ*^?WFS<@=b}t;E=6D#rlq0ftFn2pwSf7o@^IWPITm#JB1A zLT;5ZL4Oioco^YuR(^GybmBtykHUP#({c_f0p_OLH%^5{?igcJz3X}_`qQrY8@Xq7j?Qq{nC-k zi4Uv?96AgR_VawG1c0OC10O{Vu0m;T3x#=PBNmf8h!3=f{!pKA*|^Mv+PTq_Kn!|o zGcodX=X12%jRC~P>$o&l?t9&a3s{10;l|j!z`wfW_j-%T`Q8)X;x(|8127GYb%jc` z*)tD@uRV0e{R!5OH>*Zi51leU{IJdr<>u|Bz>2V389XXQ^s#4cVd--ucp&{Um%}7E3R@yB(Z2DB5=??aA~}N*m+2VIUT{^Flhn-kqFwy zFBE7e%T@JtIxIN~?eZ-hLYsaOpmh%Qj)8X8-nP(kemDGQ1H30+0Dk6(gy`M(Mu!03 zb7gzzUALz#z{*bfx#%6Eq3xa++QN>Z{aq!XJqGN{DMk!>`zL@_){l4e{<#qU-V*#? ze0W0qE`Gg3{8ml?#7+cY48&LMPJrK2em1ntqXpWB(-K1a<=;DmcJie5sA1)~x?d#nPo$S4wVdb&N17S^3hz}3!~P~ZLetTs4921mXT%t#zC??i z(7A4iNfSa#1Bh(h7-DnBY_aQcL|qXG^x}#AMHF+RaBugNs(8{c;Y2n56!z7)S$pX=Gl;g{gP_W_O$ z?qe`qg1|l`YqJ8~db|1X!r<5WTffW;eBPz7*Vo3Zcvs8{d+4bPUA_IL#_25v%k$*x z2>0`Crhc0X40NK`-rA|?u`yQuTXyd_$j=`7n>z?GY&`cah|Ov{TmI>R@z&B3cSH>A zvK;h}i3$M5~%Z5zMWFtJFlLPX;CPCG{2%nQcJ`oh|MICT$> zuQc`Utz2J-#P5|R#mDb$BM~NCKW8k?3Jj|w9Y_Zhb#xIglk}AtOYw^p9IWWdI!+1W z_8O2z(Xk4@&YC+GG9vMNT!o}HD|N)g?^Q_&?TTbew9S{|SBG#!;`a^~zL8Zja}rd@ zwOnt2#9BE4AWb&lS5}lt9LXl~OHB|!B<{t;?>#IeB%xG{ra{>%ly#h%1j%t~0=ZbN ziH5)+wgVn;Ii@CVm0nsdRo6rIu>j)SA`A68Xs{O>MN@+7z|H=o^4lnet&W%HWqk=y z07{84ajnn)NnmzRbFtqddbETmM%fLa&j}{`M>Z4pK`C@w|b^XKRinkTn{sjmGRKMDt7!BU%@im;<-U7Oozo(GM5}p5t zBmaQ7lnd5HW1n7!CU(b1Eyg?Z9J4-}=W3)m@ljmo^4>WVe@cT}(mm z9a}jJz&YB4vZ>VbEUfcdh)n4>Th_^6+lUYWu9IJb(##8NJ26oxk}x1@)fY4|IWUn3 zm4`2;ZD<0bwjavxGV6;AP$@I%OXKGUr&N1e`j`#B`-sjrr!F&O@6{`X|$ihi#rTY zGV!U3@ccx4Qr`0@R-lb$dSL6{4JKhr8p+zy7GR=&I91EDCXzD7ucTB75y;#p!tkM z-nEIulu^jZz~f>jmgt&5+rXh#GUIdHB>2Ew$E^YBHs^L`r#%?-s=`XYlIBIfCCF-uX6jW8|XvWd_}8!EbX{ z;CI?u!SAGFfZrF3HGU;u6u%D@M(`_}WGDhWXAX$s7pcVW>b`>C0r;Yx>O)R3q*uM+ zL$r+P$7X%<*fW%(coBkl1TV7xQ?35ywbt;N?Fs>z-=78E2TPnBa|^^7qW>^s1vJm}uXgYGNV@gjoeH6mYT4@3Pv#;+xl5|VlM0Q{~M z=ZOEMp*&SC_&5k*@7yE6Tmc+&uO2+yX+pSFebeG*)aFOnSei8UH)*Wx;eQBJV|?1G zNPJoahzap&O~NG0^?83_;Rd{`-+uabYt4>wMB8F0LcE8s7-nQy4tCf0aagC-oB_to z34n0zlx+DKcp`qpUHBq>hA)ZZ5VTQZX2x(hkn@WOezEL;f>c)%f{voEO^XH=`_EB9e zHPNpSMd+q;vkANiq~9ZTT?=FD>VCU(O!twdE=$)HlDg#NVW1KBcR5g% zsI6Xs>ea_^QKk;RPbpm1Kk4O@0Ft=v3xjJ5Y`yPWP4U4ELeT+L=;`^wQAxP75bUvE zg_?mS?CydKK};MTs%(4SJ}o6l`F^btREgtc10%W+64&{~$#UW@_y7@MYA|7usLu7+ zHBX)-4O!J2NLuTi+p3$et4fXEzX@*MAzy(FZ)nSg!hh$0KQdkMouZsVXv&ZO^V4V( zAi$G61`h~AI@RrO@svR)P?KMiHIMxL%NQPcQ1jmjs6UPMqd5N5B+1FF+uKF-Kenpp-BF*>XKlZp#?Hr{pNfh=43VuA*u_ys7N{&RZhTTNy)|^g)yuE5 zBZ>uK$CVJ%rL-K%XwX-xr*A_ea6z#YH_u5axZ3H}b;e)Kz!ksjgdckh&wGEMim?!Z|Av#@pT^r-D`9{k{`X*qQu0q`xa15d{eW}4s|=ci zNq6l0Q9m@h$CYq{9JpONb`w(6;S-(=p@(4t4W)NVr+i!4l;G-_wrMmSC ztJh}pVKWvWV7t60TRc+d^lP!aYb{VZ=~ENob}N)T&GKHq2|1haaO-9=Td)Z^pYDgN zUTZd$zwgR#dr}91e~ZS6rcF*~Z|s!WdHO2MP|63}I7F;Ky|x$JC{!+nvrjGl!eCZx zW?#5jIW{{<;4iKkp>M4=y>y7MLUEq-p%9tz3f z0H`DlU_vs}`1=P(Bvw9zeDwt(3rDUPg28&#Caza)&I85dZ~dZBlM9lCT*RJ+F1Gxn zi*=xjwPK&3d^s=53!GboyXLp@T!tdqW1K_P>#uL_p-WP+p*SaySn=^;eeb;9eV|_p za&dk`^U2sPr**ysonM(F6SRWh>-pT(|E4-jY0NvEyQKgWZKsr6j5)==V`Ht9G0M%U zor>@G-cD@~`~c<|uq;7eS@d#4HS;Nelea~r3B^KB$Q-w*2p)6z*S8AYLU3UtkoxLN z)Ps^Z!;{)MunuBy;N=H1W&okgThv!_n6y(V)zkzi4)pO=_3W+$1CRK^xt}K(`U@iN z3_ZSkwEQn6{3V3HgzGUPsIk^ULCuID3Tp15UMjyUBj+rvz&q7}EQLTFG|0QTAp~mz zTHrfZubFzF0G1*jWAv8cSKWIvU(CHE_}G9%1|l>`rgCm|hQ8-YOBGVo$YjF88JO+K znE~eLR|w`1rDdl+#_j|m(f^YdQ5zOyyvqcz)Gh%pFM1T4l1Ar$i<<;f$D>MBE2)*4 zXyQD+|61NXU+qL^dI5IK{|GVWe;`6KO)%M5V$_(&OZ^;Wy)FI#_WP@oKGpODz&p3c zKm7Z)R+A&0Y2QzA?w=a3jeAlN=jWs<%QnBD#sE!{bYDL3|x8W(@~(lIV(NIGq@s!?ZZ=eh{G02$f1ye0R5})dI4nxWPb_Kz~(IVz%laa-Y@j0GJdM0E$fd` zfVxkYzvxD0(kvR0AdmoLVl_@zbfHwFr#{RhQU!S$*u#(`HFS>|pRH^DzD(D=l(|rf zG6T%o`w-k7GfJMpnfe9Y3$iXLcd z8?Tx+SQb!$YJz(IXTb8s0;oYSV1y@3{1cmSUkucJ1jX*j9ra^NTjJ1Y&-<_qg$UZi zmJ8*A-`Q>PI}%_U{2I_tiC`HBCNT);|M(Q3-#>^rri=l4MYp7LitE6wvFnCgz4CPo z)at$u+^~kHMIaRTZUcP490N2!zi1^%{R>+*o$79yJUDNYFUiabZDTJ8L&8&Jf5cZPn40Dgex%zxGK=w8IY z(sPa&Tj;T`VzF~mOry)!$h9Y5Y_=veZ7 zWk!zt)@5W$`ofGNd0&!|F26MyY4VFJ9QbQ{vV2fI*N)^^J9&!Xs3^`QZV|+UJ9edj zi7GJvX#1)U>UB*JWfg+!Xp=S)3}6PZtZbW)GH`MTS-G~L1AJG2r4fK7FmH2 zpXIPcY(ZROx=@+Zd^B`YjvPj$`=zd8vv7$UQMYV=#H7N8I+@`(>}B)yN3@WD0j*E;Lx81L{(N2gI||U;sjL zjmBneD`%nbYw1twHAGIZm%6Qn0(`>26r*xhS+N|D&_aKEiSEEN{tPzYS|0*XBfLIr)EDZ9=z}I%%W+! z=!cX)QJs8tq_pRPJK>oF5eUK9by7fOUq#9Q8d(ec0;Smv;ExSJnLx_mWzGTaJQCUL zl=F9Lg{YHjOf~0z+$)w5Z4LrYZX;PkdVS@~LUZACmJdEP)S65)4N`ai9lT?tqaTd;Q!!cW!K<&b1 z=I8>Bqr?8{tITcPkX@A$0|Zj1?-yJn4I5Btft6_B*M8U?;B|$;b#~XlhzExPd-WB# z{Iqx1@F(y(s4aWpBYY1}^_1;6*DJUM`UQ@5E$XZH9hIbJ)Na8jaN9E&We_8#h$+rq z;bWGQk~l`B=kOxLL9N0Ah@npJ=Vczs(jsCfnb_edHOZpnK9zk9(bb@L@saVhd`C0H zv>p)YAO?c6fzk_%{5=*nB0bl+uw2!Qy?}07d3H#YR&a;2Lo4;_NOU?ev55Y#a%+T6 zytVfW9inRX02r+kkl=w^V~jbs-`sJa1CtS(whO`v$$j-WRN%S0tfc%^W1HVPe#Dc{ ztSjgOze((T6nXAJ9%~m4(9kCU>Zk&2Q=LuDBlfbnfB$F?x^H_H9s)i5#yJ?PMt?GP z!6PkYEUx{)#0gKAHo%OJ;A1R!=g(&te2k9p4o>TML%p_(=)e~71iWK*VQ;zyC)EJ| zni2Ehgp3T2<26;I(j2N8vjyvG ze;4!b!jg4eMgvpum8LlV@wr7mCe@38SwwN3(C{t1j^ew3DPKtPtfW9lx%hmqqi z&?(;`12imql;>*pap04wSm_O=JS9IPR`ADUQlCs?4o)@T0rEO1$lezIScIppiu2#; zG1w{=2}vlZXspob+>gv5UP_2<&&lulAm_n+>Y?9I%@`VP9G$7Vq{Gs!;AL>rT$b+a zj0}u;Gus)@bRMbjuIlz92GS+VU4%GGqW7o94Y6vxBB#gZgR+3d(}K|Q8*@PAqGXXAkrc-u4Xv;W81x4=hLT>l5jY7pWE zB^niL)M$gxMARl?G(ph2vXS633a#-`jEWi|XewBeZi1}Km93)EYX6O`T3W4QrHX}W z0w}>30j#3&r}(JOx~M^|2C(M;{hl*-bMpY(pFcjDdw1^4nKNh3oH=vm%o&KSqfa4Y zXh;B(&!Jf(QZho&hYq2K*0|iyl4(7{G7q{JYe4**f57Qjf23h!*_Cucz`KIMx@N&9gm07|ESkvI)fT=CoS1%!G5 ze)b?q=odqaKC6KIIl>#MmwthfI)4u3yH%C?&YnmwVlyHw=p2s|ZJJz?RG=fVo|!Nb z<9PBP*+SA7z>weYkgU<}2uM21?&W7~9E$?m_>aw2#csX3X6bQ|tow0xrOb&x)P5r^_;I6$J_|ib_b5-XfZbA!STVoEmLli(z zmDH3FnM+0e4$Ao*GS*LJ_=xUdQDAq-_e96n-5P754JgVyv`KL7GWTa;WZ``3yQ=8& zI|V^IpJ45%2FN8bw-zZrC&K_%mZPmVm>-$?oA#f`PBN$sCmNMAw9=a$1bhAw?uIh6%)UEmhMMs+z_y0fW;l=mA2MDh%dM6xc&sEh&lKfR;8pCPqE$9~P^TCd4GfMh598HJ(hW$3WEeyr&&d=Dl>$uQt1_2N=KvpiH;?CfL zFUY@KK!5=4iJQM1m}A?_XPLsWi{JhaIChohoo(~>;n@5+JKA-c19*H4uMT3$TkQ?Lp&E@e>i=_Mp zk}4*w^#ntTs~+-*7*4<=Tqu=A;qC-0tT%0|P#N!D_FLfh4Mx-~4iNV;G=aaa#V?P3 zXcU@5BNpCH4mR?V*Rse;jIZr7zM$O(7o37bthCxc?e3N-An`ojdW>S$@-~|`L2L8Z z2&Qs+#60~X$xgd4)_+j3#LULb7(l)Nrs6x0IQo;+(J!%baerl=8n;fR*4(g#${dYb zoqW3XiE)-Dz3Jo=n+mAVZeTNFdz;DUaDG~7KTijWOYMf<&B%&LMAxnru)8FW=LT(6 z2w|5nij;A7;5tlnOAiE;2uBee(t1ca#oL1J4X8RC8}r2e*xf){ zGKfEA5-+Z7Ij{!$vPB_#7_z^E9SL3m5@PP!A?2|{_@3MyyTaoOKj3akDK|T6WO^ZE z$V)R`!qH9G3pOY1DFgSjH+A4DFL_%N@Y^KiOHG#MT5EH$JSU{Ze7b?W3ivf)F`1fN zIN1=AsWTk1wcM+Oz6mi`;S{f%F3}?Eu+9dEdSp`(iv34|M}06#z-vMT+>h7?GPzUA z3M9_#Sp7kJv!!(^Kb}+h@sX1B!z(a{!8Vb8eBw%xUOOmvkEI_#^qs_clJo}rJ}ye$NZyln#9VgrIyn+2NDu^EX5Gj5WM9*d4G zf_7dC?c7oQMawL`KoQw&%NRc0z>^+2PT!nxjT`@iWY* zHai{(KXI?`FqY4*?7gyAv#@b7(s8E`3O;$tK2Bkm^XwC7zKplvV=&-+?i8<|^Ui?o z7cT{$e9od4zI0E5jo+bk!G!#O>A$u0B2)s2DFYjlG>$e< z8Cis9%75z-+#$ibOF`VKzhWnS)-hZv)*e~`ew28OrC71%$hK(?Wm&2Dm3Sy{D?R1E z1$3oZ@#F*ViF%BCxf%6%tuqLG z))V!(%|<p4rZM2~+7Yue;HS*stH{}h(&ztKMwY|kxU zj7`WVsKyTX9g}UWu0R~3mSH)GQ3Qu2O3$gQIMkRmf-Pe9HM$mp#Qb@cpDUBrKlGa3 z@Z-Gq>W6>_sXZGdaq=JszYyPb-1_eE!3(>u2**x1ybIkSUgb-_XL;v) zmaq7p<#FM~_iBID_bgxiJKOuY7$yWy$}Rgifqp^o{RPo_fmnsh|4I_bK1} zJ*a4#;nTe&Xl4gJ?1NH$JD>~~_~u-NGxAQrIgUxZ^B5;S z0LR>9VNfY2j4ORGZl3}eh#>(SO;BM>83!1gq5LpLTNs-yjKh2|zQh@tXRv`x7%$dK zd!9zv)@O5>N0?KhVNzv9N~v zU`@w~*=KOzf^>O8;f%TtaA+#^{5~-5 zv@n)f7!eg0wx&2P1>mG3=vweDrgn$&8Z$Bd-r0 zLoJME3uDK$p0?}*cyM_EH6Bz5cYlc98QBNI+76}0A`9VZAA~gvfQ9AwOBKd@xYG66 zWBb5pvM}Nn#!MfK=jNm+3j6ed3T4`AKq>AGMf!J)g*4AXI?4y>I=2U#jkgF*3TFV$ zQN7`quiw-b)ms=JUDHF8b+@FjF$)yNt*-&bX?0LvOL@uaPr zxz95IP}B!N=Nlvg?CAvX{?$D+coy%<7p@l1coD@<=~Mi1TfCCRAMh1V_mMEH0A9Qw z0FLhipvD5=v8018_W`KB0S&P7Yp4P!{~rJt+XujL7642Dfx%mO!vNNY2SK4nqe^8- zoH^UUlGqLWv(vkOV0k0g=dbQvfeqQFb7e<*q1pzqHb9{)SaIg8p+h@1Z?W1ps1xs4 zg=WvwWGrMB=55yG0wn)Tld;Uv%NCIv2xVWb$rVg)*W6V|o~+5$Om5TUIwXfBIbP2c zd})y{aSj)J{E>d-0OUuCB_|rERKUkW_2UxzQJ&Fwi+;@1k5UmzN|9)MlYVrbXEWoQ z`3oPL`HaRp`EavG>&GtpQR!>MXS%>-A%WmV8G)R?0_)1CPe5^~=lprN(}#!IygdvRuE+vtO$5Ws!dQqkd_& zU#jqBiGI09zbvy~U^j}l=@(bOwA(K*FvU0Pms$G7*e?#gbm^C?^a~Gu!@p)6t}diJ59(11rKJ1JM?z}Gi)ZD22H@4 zI(v6!xIuqA%)lO%{R1;uQ!9|mtVXU0`n!s`+6m@lO{hkOb4B5|-8D z9eJK$p4~Mm&Lm`O!P9*HDx0-T7{kq8h-@OCJ2Y814Oy2l>l#g4!s2fB4TQKKh=bJn&%J9bB-o0vU#danI<%A zo*45St4T|2o+{42nzT%FUCUe*1THm-2zF?V(wW{OdmhrHw3?_G{br>}DOw+%XLRxjUE zN@PCu5tOEb@a|I~0cg?%`=lAyX0EbVCS?A64M3Lk%Y6UCbdMMZj+ksqR7y}hOx^J( zQKG0{iMEUp=s%meLRzp0ndF5dL|&HR#c@~YM8kvnai3e)l-JRV*1NZj8L@A{l4jAZ z;@$fI(_-0Izdr$=;G2cBHB<4-*kAL(nEr^0?mJn1r_A9{k9s+z;JjdSU>=ZX4d(RqvI`9l4799QpQ)>h z+*T>(e{Lngjt8keKd+u(Wd|y?wX0D&h#+PW_))f#!-O*sp+Y#U=rM5E6aOBN!_+=~ zE5Y`+Pm9gccUs-teizTZPvJQPx)6=a%i__+I$tWR*EaPsUn*t=n;K4~MporYswtMF zUZ!ZNSovqxqwH00_cTFQA^!m3`q=2;Xb+$fxcrE1!Qh~T7+#Od2d&wCr9?llQ4g@GX72bC@oLOt881pE?}uF* zY)U8QeLk_xHRMO;H`xoH?~cdeikbcvJgaca@P;HfFe10RPCS>g1=~{szUwW>3)Td!>!+*7Wpv483Y$% zIyrP>I~IpM3p*0nCBY~ffpnfZjQy-C?4CY|j^Y)h4URmwINj^4ZF?Orq?VJv813AY z`uKi&Qo(am`LiRRt!;Idy>!mS_ckB5Y#c{o5k1zw{@7{VK9cTYtvgP0M!o4=wVnGl z&Zuv_9t7e%XN%a!Qt*VrXF;nN>ZbI6gCm$2Jn@n22Y`b;G_cFbvn7B(#hVgD(p6e53+k3 z^Xl1qaH``3$MI7;G}tsBf-Vu`bl4|DZ#I1;PWdG?#XLz|cychmKt*e2m9eoosfLBGT1)K98a8wDt^D$q@s1NH)ijL!VUC*x; zkZ4wr;&vk-);q#V*Rr+90BX`zWQR%g{`n?;szl0q`K4~^VUV(BHQsxjhZx|5D*(-`@)^*aY1xLG?3?49oBgMV`wFMc2b` zEgUr|=SX14kK^W@mv>$8$%+g-uMfv^S*S}2uMoc*aK|Zm_%j=hDH?=M#AGP?ML4>- zJenwvZZ}O=f1v*FR0#Iqr32R|1AJUZakdE1;OI-*lifqbuLc)fib0fU0iwW2Tq;+} z{Fc}qNj;-bT;0q^5BP^71!_)W#y7ncGpnR=d=_D->iEpx9~C!jad>12{ZPs$#-}_n z_9`VEr~4#5P<8iSuz%5M3zW&n6er`Nz>^cVQc-L~w zg9SfD7JEDh=fAoqV*Z$kKtb7`!Nf^bK1g>=f7f1uspJJKvn=$ddu8>aAfVkIO%Wxs z4vi8z$40z}V>pbSZa>id&sGT(q)&=pnS&#o6$PSqu*1bj-m< z?|NtkBr6*7MU{FhDpM8h&HwZD0nFHquwwmyjFR43u0d!93?^5rj zf?6mRf4p3aQQCw*ee1vRYe{7u>%ndo^8h&(Hj92H>%UW&hL#BqXzV5+3_bcFj)-<0 z5q&>HKQDeE=swP`?g@9mqqq~pG2EGz@_!6Pwhaz8-7dF!S}?I;P+4YoW`ts}vSJOI zgN_KrYCtsfJlbC#E6t}gl35B0K3j_ZoBlXh)U{_wrH8D=R%f#cghTlh43jn!nu`Jj z%f=I;34(2HnmKAE7JH+p9=d@`hGp_F723+qF%|jHzfo}(5MqAe6kK!7*xNXYC09c- zU3$_Twy!fd^R9QeSVqJ(K%2Cc(9E6|N`^queuodK8~Ej8Xu#2;{9_2Sqdi#Y<59$d ztOAks6&C?mLt!=n49s5iLL*X%l`uh&@7XoLijt*9Jw`EqF*6G>XBky^V5SB+N>G*U z2v&nS5MKxo+0Qt{oVXinaROy?>raK1{5Mh*4vFN*d?Jdupb}4WJ8qCCh3X{HJGbG@ zr`fl@O=@^CZBDF_pG)oGxxfui1?A}4dh^i{T`{C`vpbZ8tRN z#)niUvPjBVxx_Lemwrf$(j*fkvd!-XKFY>waJOj?pdf;LMn|J5PLcFDUP=-FkJZFy zA|9kYJu87+<|}7K9VdAxyafxquV$ZTDX;5bJ=QE{Hzwc*83Pb2`MylwdH!=78-XMA z_M$WdlanL(=pRinE1%KwWE+I1gXQOXDMNS0YKbq06EKJmD%tFu8m)k)mD+izM{SXk zVy`CcLX@tNnrfJnooea;BKYKx$ksvg=FJlfxz3#a2cB8AlVihb&Y7#oMu(7V7b6=q zQmhBDCHgDL9UQMFlHwHiA(WECWKrRl@}fXkQbf_5W3@;0*)cW zoRqZ8s0(O&Myn=uPKBV8M*))=TQUU`CaBxC%r9nE9yc6$FpCRtx@{{yv>o6#1Q}+A zCmnZWXQbrpugO%$5(TX~y%Qht|BW(4h(>Vu?lOzZ>luiz$*KG6B~9SU2X|E;!izdcsfI(t7>ImVWWqGU$ z0c&wiVub(>7eA0!N1#m$1j5q1da^O(VI8lP;atfc@05>?a!yrLY`D+AYt~)#d^h6@ z?8&dPEE0aurBR9{s_<31rTOuoumlsVC;zpF_HaWTxxqc*MmdG&j)cGS+5eLMX9o)r zh7ZQ~0(8GDO@tQO{Uk+j_!+#Pd>k3dNDW|EdD@eTZs1@d0KOnFvtg?8h2+IZmAs%z z4$DA(LUL*FC9)se&*8jCo=O*Z#beFEandD4v=fqN*}`737r{wC?-UrMj!+&oL*^-^ zL*1*w#T~%~-&^_u5QD$x)e`7`ru)Cp}I9wm0)^#RB;>>2icQ+&6 z*ufcQp(0W8gG6Uzjl`PLvX8zwk6@aRLnQPz4MA`fcB;(^N7p}a^Z2fZgR72Zn~ zUMLJpZ57PHQC`V5GZ$q#Sy_+Q0jp4PJI|CVYRO`tvI^my*yF@iR@pd+@S1t~V2?j7 z07B&vo>XlLf)v%U0^mIY%>A4Ud<-c^oWfD4vOWPu)T{tw6Uf2IlYq;Qhzt0XWz3OW z7+FkH)ut#6ba*Zgbxy|uwG?+5K&FX%yc?)^&_~_Kh2F7LB?Pr^#l1(2y}h-!7`y(d zfyEfrNfBc+WR~-E0tOY~BnP+^q#}@{g1~y_;kU^D#L9nBucE9o6@Q~e{XRLt8j7qc z;Ao0&4@KV;L&qALDxS-nqb$@1UO`4!SxtU@-okRS;PSb;KYY)vx)ejY0Sx{F{3xW!tPl( zED8%ydGQO=_ar4b=#y38pnrX!+^kXnXG~v5^iSQN9!b*?;t-({ZJ8p+AtK0w!>ib3 z#5BY+wJ)$ktJw~+F`g7N1WbGgg2(c}fFtfGck?zzN)~-)nf?L6x;&bVL8tWVG$qWcRgc7=rb8oh;zNAj-Bq=+@5jru|e}AGRC8i*5Mr^(1+ZwU9{Ue@-EWPxRp?rlT^g9J-{yxzAPxEnj{k1gVtA3KdVY z@d1uw1Ths%TG4@J|Hg(dwl6Q*Nc;AD`I7hp>X1fPp^&^(doOj~%RKL85nlYQXBmI% zS(LxM*4M~y+j@daF)>%1v>6FJh9L1EGX<(@uS#KlH) z_$prdW5odgN+!2vkOO7%7v;!FttU&mVyPZCN57_7CTZg{HHN(rWMvbFyGJ&UTxQ?H zSVB34gN2;p^IkBoJ+6!6B?7r`n^Gp2&wh)xee7@?FI8-Sx?nl#HSQ_mq@QjpvR^U) zD|EIlv~1JuQSkVNwyFfbS9}nXogwS;nT;vtFSfk)DqIGm6%~<^F+Jr3sc1#1lq+R9rkI;iF8Jhmc@yVV zrCb~@)j7>7@iNb8`~mO`P)deL zqPR2{D^MX@V8S-=y`2TEQoo2)lO>)7$bAdhi;yztYk?srbkj$N-SpArZYk^mmn2Bj zJ)pIYW@KW9gji!@f+Lg)Dmf@x!0LgiOh91jBK!_@w~&JjFe)!@4KDZtVrY<$HZh@T z0}hdiYJux8u?dbv*Vmqkg77DaJz(gO{WRsT@v!8Is*IgF_l6hEFMO#vsnlt{)ZA3+1(He| zUu+Uqi#OEJ>_3bql$^qr#4XafaAt^wD)<4%-sM9Qp{b@}Q52C|#HQdRV}$XH+9Y1y zIHe236zt)M^AkHKmlxPzmzGB&1xa^GUask=VUu{Qmiroj3yc1o$CD3o{f|he&*un0 zfyRW`*#LC`T6rq9-cphtlI%RJt^uu7;F@^@fqaaWR3}cLBjmx-hjvY;vykU#V-$$$!UZ0^g&w)nZ%}10cA>zA8G|URrw4NWA_oK8%oDZc3 zJs3^CMSfO<{hwgt{m4+*B2i&FgO5+j4=!BkxMlf`8)oiDL@UkHX?lAX=&wa}bQ8Xt zy+XF+JWp%g=5$=|H*_#tJ@oU7ikw&(`eRb5%yvama=p2^oCL54$0|@ujr1}+V?b6| zyswv0Y#ZFLn(bdzzl`k?{0H+h;*b7i?=79He0}1pSZrApT3Es&!#Xhgx_w z#?H)wd@5_`dSlX0j}10fQPehc&1}2uq+rwQ=u_P0bn7EOV1T$_)82#GrZHgzCPM^} z*~6^&Oe^eTeXpbt|191=AyX(T7Yz(gp2LQ>R%I(=A~oI%kf=Wd&#;+C5~y5@BDY)| z4I>b5xp3Bh79QgB^QwgNAM)>pE1FR_9-kV*4Jf<>Bslliz@Cbw);C|>A;@2V9BfQS zc5DO=npp@!up)72T9X_dif+Tz@1gaH(2#9jn}~XHe^36S80zDkg!<3`C=Mwy^k7UP z07_ZpJ=`NN*SL81a&Hk8Pf&l zr_XR_3^o-6=MLT(^G@;yinCTIXm`*n>kZV=fn_=1ZwfX&i2lPCDB2&q?N@l`1thaF z618|mAOFrga(}StRPEzy{$%_3Sp1fSEcpcrMjM`kpRhccaLx>rwaWJ`>W5{$}{d{)FhWhrHbk?2tAf0ur*q?fJ7_5`q zz!h=@N}nFfWKYdJ!}b!$&ae+dQj_-7qzIC@|1=A!#6kwSkRx#w z$T1TlgZnnIG31bU(0iM}&Od)66h+X6uFi1q@u8)`g=^xB$O~IbdvZAtn26(}=C%YH zv8FU5mjrY(m%xicA_-*fe+?CLXlZR`cSU8+ozjM7=K;Gf?vOT2)1<=%JMf3;(Dd^( z-DTD`O)Ar*?M(VBlc)i$H6K6pl3%~=z|Xije=fdbGt3YvJ4f_Pv*vqSfyXF$h9NW{6c(%f1oj85orUd;SWG%qB*vje&FOG8#LAjdNHY$_X-G z>>$q>apbvF@?^ond;y~2D#y_h0aA%I+Ef&J)kP; zx_W;%h>Du%=%es>g!A=JaPGgTEA)-uTDou1kQPNZ)0w;PrU_9i5@x|MKaR^~7Nx|qvkYD;B3?_u>Wbw;=ARhV>APysl zYX=4~#s?xg9lCfR&sThT8;T#y;>QkLT+KloU`5Vg6pzXcG>(Lwo{sZpf!F5u&}8&H zKqIkaels0%zjeP}{spFdI&K~wLIRk^3>jM#;4ug1LU95);mmh)Rqe#>@#8pT_jf+oS~xnRLA-8BJXk8CLO9t_iEA!ObTk!JWVpfn1g60>fw{6;j;PdOmAD^z zcr+)#0w*>L2Bg`%)n!61XXxB;?DQO-bAilSS=gffKOq$IkSR>0jVK>aMjc`mLQm_v| zvx$wRZJ;*aX?=gNY5hGLyi3r$pC}0n@G6F^E$+HyVmLMoab3^B*}aQPMLvg%H_o`W ze9*9tuBd%C%F)uJi)+vFggC$Eg8Q)Z3%&PjJW-HIr{gtF`_3%%e~+08EeFkEpp*W{ z!S|c|-6|BzNgR<0qxFIQ*fIUZuQxlMykDOBrLq2FQ9TS+~o998lov95wRY*SLD^>UHVBp6%Zelu9$0+C)3WrZ!|0`!dg!9 zVgnbP9*$iBi%@i9h)3hGnt^8k7FReN!u2b-qRO)arTm8_e(GutoY;t0$_K3{N6su~ z09EohIQX*saPb?#$Oo8h$-yID!nfH&gBQxG{7tcsY@}Tvv_4rrWTQ>*;A;Kz;6)qp zgqy#P1fEJL$8m(Yu7!2piy6TEpyE<75^N0KdJ6Ht=5yo{8MvLHVX z#AlrUYp2a#t|AZ^dKCeSIPii_=Fu@9yZ zJ3MBlC_)@&z zzC|2X&X4!rNs;h%;%&N?P}&J)s1Ux}Gz9G%^QMw!32W;iP5QA6;8BYC)qbbKqFe_6 zMDtKw)ByRi;|XpXcl2JF0!V`{O*pIY~Xjm z6bZl{GOSVsC>&+vN28c}xOx|nl8VKO@d5wA9d}c-Zl*}>#H$ROH_Sir8W;LZzLE0P zgWevG5~8W=Y34~@JK~vGF9`yxk@>CiKBqLG)r$~-~3P*J$T|QJiy zbHE&Qnh|4obdwps1YGH6o>~Xx3mazjEQ&gW;iz_+Jk4;B&A>{SK^WD|+#Tq$Tr-ow zhQy7(7xOow+ms-xFGDUlE)D>sLi*NJX-HooTf=HnF%BZ=ri3|u8wZNze_Cb#EWp)} z4VI)*QVJ~uE#U!nY#X6PP)T@hF`QRm&N=L5IET)BOlZUa1Y(Wk&HxMu1!m)8(&G8` zY_UiT=Nm_PDwJ)Vnn40VT zyq&lo5=ZurHYsy;kcbUigoa?QW~tLYL3-g7OxVkqUi{9?>>%y8+^T8(97))S;aF!c zv@i#%b(9G5cL1ir(T1}h5MG(cho4c<`dZF-U6AjO3f)HBsB{Ah$)<@Ob)$UyvwZ(@ z=D?f;>i01Sf2;t1|4oJ<+ncije;VUsovIY;ocI$ZcQc#Tu$nYVk=vg}(NU`RyMQMw z%Vd#Lip04?SOQD3xA_kEy^{WJe@>!+4gK1;1@eGGO(M@l{S%BWNdo!b(ImCe#rT}03{#hr@=dQVxQ5Y~a#;U7(V(%e*9NV0f_MP1DJXo00dcGi-{|M&-Mfc`F${0Y5_DOokKQ-!TYe*JR>0l zTg*fSFz$X}a8MrrGb{iZOnv~ztp9qUuUg* zUfi?JoW~Q0(^gXr#D0XQXHqA%^LEt9<$E(r<7REXt7LHs_^yJQN4!#sDW+pjcffhB zSx{01+7du8r_*o3trL*!Rdc*12wc`-4$%Yw&WcQyCP)peP4ved^8}7mMar0uH31Wg z)@|Nk0>)|`Q^@r^WpzNLq<)oEd7(fZ;Gs8#(ix6~ z(ZR_dvsy_pGX%?b%u#@sB#_(=S$IAj{DbA=0m={(O>)v4Y?E!PN1@pmNk|prt z8}yJ_3$bWe-G&D?_qK<=Z=v1XN$x62c+a5 zRD!NN3(drg6$dIC?gLRW*&1vg>zZv|6x&Y-gpUR zkdg)Ia_!mNqjYeV19;m z3e&MD1N&xNa^i=1T1b_-w}M7bT`5`RG6Vp2vIMZuB-hN>%>Q#e@vtfc7?O>3sYZsw zKo&Czl#JDmlG=1#VQHIqrQb}T^S5y2&f_z=7=?(^52vh8CJ;RJTNfrjRExH}XkPcF zg6KB2)t8DvWK$pZr3&H#;Vxe)hLYx0{!V>~ta9Xwsg@*cprVbrK6WyXc?~6s*u8`P znK%%OqyE!gDn-_3he1~W8s7dbR!L55PkMXdG?TY++rzcS=~Yc~MGDveFI=B(hN)Gj z$Xhcx47N1O;fP1_7V(KGQl6Ne7E8Li6=GXA16TkBYDoKn!NH~Qi$a$Ao5`rMCk*YX z8d?wyWwefxXFt9RJbU;HZK$YmyWhzTum{dM&aGD*U0_u z9c#(GuRg<4a`~g2$nahM$lvB)5wcjS9x(CmSOViij=*Y7;N)!71mY^z(!a}D(#;%p zEg2e8UvPr<&L@`T^ssbX_};UY>qF!|ORt92B;zV`^J)q{_y@^)jj)AA9L%tP1RJ-C z09y9&&w-QPD|>+G(z$XoqFMwEY7VkBxxQ3`dcBm95Q#{oCH$ zr2ad;@~4S|DJ%L*ys-CWB16whMqE9`6JkLc?P8PW%$!CSKr}Z zGoH>P-rvM?&>#{r(cL>*KP>=0Tw$ z?KW1*bQ0h%fNi>4xe*!2)qiR(nX_aQ~!M#jeVZsam7M%l;~dG={! zulSVjQ0L(ITwKH#m4o6g3&(bz)=44n1Rv|e2c(Y6D}sv`XI?5 zg7=b1`hMt({mZBOu^*P_xU-?sx&63sw8a(sSGW*eMszlZq-ARCR6CsI=wDnTLsjjI zWS~m+e$!Vo$8oaz_w5+mMXR(@wenFpJA7GcP)l}dXQ@e!Ddvh>KqH2;T&hP1;U94Y z#`h;HIle!9ip6Do&l6tjxh)H_k>GH#2YQe=xpp z9m@vk_)gC7-Z127a=^$24%%mHrPs_omHoRWWnV$pt>XasuCCkLS1D&+nJ!=)YbFKI z*dp|UdHETcY-`i8Z<=1%4JQK5y!-pQE*u-1s|t$vU1PsX%&DNW13)nU%yigs<6NDe z&8$}KJk7<4N{UP8$w!}X z=5KQr3bQ@7LUi8Of3+3j2$)pp?>wn+UzTw*ue{c;j92IwXZy>A7pK4Y@)&^t%!-ATXQwG#ctc~%C~hbbu;_sPdW)cZIyAfLm09JZ1_ zB|_g8H4j-h1@A7s?o+oKj}SZ&ZNuWL8krloFoscj$FraddaQ;YL4SVKDfp(PsSekY z{?W=5^CW#2+`wa1=;gBjCsJ~{l#yN*fWBVlZ*zrsJEUqsFAw)>nQ!s)_p;PdAhl#R zT=pOI@&~8FYytfwalBAL$0|lBOm2-5bp@QBatUvvmw9Vwy`kf8xn65UPjODDDVFFv zqpUn{KyKh{@(w1p#M?5v?V2gDejfuwNp4wN#LCooL7aQ}cVd0_g7|lS>;XkaTsD0&uq-kEnb?Y>=Z*l6u`u3(>}E27m+)0&*!umOPZd1h&kguAU%iiZ?49;36v;mI z!oDdLbAN{c5zou33l(peGoQRss`}xE+Cs5Y#SmfPW~`0J;sjaSO{1MrIGDN88P(+= zo~?5T&Qy)u7Z%=^4t%jYIZPuTyMg20+#4+?IoS}iu8y}~rWjjHU*^~6`ng*yU5Tlw z{?z_iL&PJ!?PpWCIT8kF+8-o>Myv)F31C>46?V^nGt`|vd6EPHGk8&u$(P59|5Vqeemko8+!;=FDncT&$tdtsXGFPvl9|@=6 zQ}F*B$nlT|A$)uW=GTDv*$g(Ym&uD5p*vyuGxwg;zxjLg*o4IXGZ}5qC2!`CH!=7) zz~D!ABJ}IXjzKfwREn0K2_pIFrumwVQ$mH zXpfAh29f;$?>?_|mG@HPz0~7{>PJ0wgue0jzYtG1>L)O)GXvnVq{&gZ)1+|V$akS6 z9R8Guif@N78~P4M_odMe7%1ZrvYIVEBhPmxynOjWQ1qocL zmUFXLez>QA;ZG_>1Q$m4r)f7$b1`c`;g#-Wp48@a;#7!gS_=3PLlI5$kP!qDS3$zS zBuI9|{3Mvv0uwLO?7T`u4NCo#GJo}zF{TU13k9@^@Ysids&op!<_0dvnQC)BEU;M6 zUUm|4@LClruBZ$)UIm$&yt$`dnEG#K!IM#t=#tybCyX{L#~}9W zUHT}LPW+uMP9d%UV&_1#GNgwa==`Y<(yF}(Nn(9uB|d?K@YDW`fBI40ixI0UVv2e=4=JfvnTj)1JG>=#w@p==DhZV`o7YOw)mfu?OP8K76unWW68&HqiGAVKhZw3 zEp?wrk@727wd z-N%_g*2jUVb|kXf$QdkUe%TK9xb;kd2$q2aGA$Dn5HJtVzSQ|{+Ccx{S>xwWxZ&ok zn{%Rf2Ac$;n|UsdHBx`Z`R%3$@!f2=-LiZxP!QfP5L|jJXZie{nhNa(1b%DJ+KmA> zu=dMLH0nOFZoxh`S7y?MV|7ui0%E}SaIXq2)|T&t)iJV&9!1T6h|L%uHs)AGW{>|H zWU$BA!+W{ly#<$JYJ1^xnH^lvjlDW%z4DSUM$?9wh(ruyEZYDs>1BVNE$(yFPXcFD z^+;;+2lJa7upyrevC1~-2!tJ!(*R)0pMw#7la3n*06>uYm!=~_M!o2-_tE125BR!gxFZ%5y~a=0=hYhT5n3p2mg-;@TYsh z^#7oKUXb#?y%Ta9`ngUbk60_3eL|zDLcja;@=~$^MuN;W_#6iTs0mgh9kSwJ{=uko z12_FE!|LSjk-!c`>XB9Ye2Mqc;=Q!vg*rLx6m#0+KKb?TG*5no>7@p)L{8Iz_;&!f zLP`Zb`3IC|^DruLGcRRhRC!j+s64;eY?Wt469zm`FXd#DlRO+!RZ`dp&JP_wrC?RZ zn|fCG0uoHqP|RA;YbnP0j{%3k0u(z;q8zEm6YIwVi`nvR><4BH{Kj9T{ZrKoi3l{Se5bHIp11;?E5S{O z6ML#N*jka*y|QV;E#S_IVKf6_55>&LCv|OSN*MdFn1ecg0-5sU7C^=_n$9Kh<$##V z3TTyC-7hwE+>&XsHt4Ap)?$8-AJW6kY^<9(1BvW3`3Z_E)4;ALpS_sS3q?sG^Wc=i zMVwD3qkfLhTyw*h>{c)85T`iE7axDDz)WuEx4A5Yz91zjzc%A(9)~AD^3t85A25^F zzsx8ixDuwtfnMkk;fB>53oxf6 zxrvxq8RW%(cfS9||3*H=3P~c*2!Zjz`gSg#1pk{M|BBetYP%#Qphc~%Mf@`BX`YXZ z3eZKgU`nV5u`n{25wc=1jK&E+5bz6g?Pp+J?BR^$06}26mDI>^Wz=hP@a7o}Y0NFn zFlCc^nOSAx5U*mh2XO8~f3CoC6K7*&_@yi37d?=-3@%`5|5&O1Gi|b;1=mtOU48oG zs_X|trnTcUc;`%!65ivOmPf*201q;tV) z2;eeS5NDy-aNXj-Nkg`Ry}>8AN$`O9X1Y0K{%lD>N8Cb@RUc z|JLQ&|Adk+R1f?=z%_5I#JcUi3^tfVB+R}eIbdpE(7AcBbRpy?{A-co1`hl*i240@ zq;cj%nrG>2``|s)l1^n;NnhZM9Oo~NQ75YAM&X5MWe%r14pE1pK(LON3ZixS$@6u6 zsu0Y=DL`ISD+ObIuL&rxG0x3jGyy;qplQ_v*^wkv)6N7?t(iXt?*(}=S z`UPq&h5y6dME?k)ujmkcD0zY=6~2WQ<%*o-2_BkK#V3fpyCj81v^4MfkCxebT+dB4W*Xd#dV<-FdbSU#XiM7G#|(cdmW=A zkOXl!3*ae?+UdP)_Fn1$L_WzVFi|EjS28NA|d zl@^XRW-DBa`J>}%&>7q1^M@lP*fa>mIOmea3j|Kb178Rtc!UN3YYCiBl6> z8Pk1RD=1rU*dI(dK)V`T7%p-0h%rDDk=U z6=~G8;pZnYuIW6~fEZ%6f$|vchQuvBJPKYUi5*NljENtV4|z1BP9IJrr&47p^uYYfdgLkH~r{mcGdJMHoaO%wyUOp81FThE5$#ecgtmP zC$VL1r<0{SsO%#?-o?0&{L0ZD&*M(qJ|ts9n=ZrMZgzgAf77|V>J9lSfSEb+&mZ82 zl`|OaevyWef}>)%`Ym~(L@67hrn8fh5c4o5uwh_gDlg=XdUpQ9g%E4|uuqMC@jP4}ViUbzK28WwD_L(&3rM9DtO?5~xEU zpbad+x&=~Sl^$kDH!xx%G#r!=*>>jJVu--Fqn=`xiF*g!bSV-+ftOi@s%@&SB*r1Y zGubK5dLqwf5o>85EYXq{+gB)s5uGND!NGe$u~CBxd%EIY2PloCte!d*a^cizvsY>2 zQ`q@T-jCF1*t?}(3q4ABE$_34;d0#UCQO32M2_F#ruXvCo-du7#&-4cPoUWjaG;F9 zm7kD(mY|Kl>tZ6Z@tb8KFHP5a6Wes6wJ@ zv*r+z8BJ&X^6stYO&H*lf9fFu&sW;>*ZZ(@2R?rthDDXZArRB!90cHjZwZ2Xxl^^^kouX%%>I5EXd_ z->Kn*L21p2qTVJ}F;RHNRTG}jF*R#IJ2Go8l^J99N!){{;|Gv|Ob$Us1iszt6F&x4 z{8Ga&b>0^TUrv`V_RP6GW^MK_K##nd@@VOy9p7j_s6r{VAH1sm6S<^h^bxz|ZlBbA zB>g_CVXC6Rj;x{C0w`kjFCm~~4v?=eo#Oz!4v*ePXuI@q`b3aIE; zToJ|)AP`Gmh+C{_Zp?t|FJv$e7gu3-GAmSElT(Wf8xk`_Y2&U2w-~pw{^g%Ohw&9` zbohx}hI|51&u0;Ax?T+#`F2onK^gGl{@$(F65w$ASIvBmZI?!Cdiz3_^}4 zodq#M#VUjmDmRLUc@h>&3_*Mo;LD5gUb?)O3=F$a4F6STn9wys<=t#6Sc*btGoNnu zgsr5q7l?=6NBGgnZz@zU<6&wx=?diUW0VxEh(OX%52d<8%9c_-bTFo|o4L?tBqGe1 z#ituEx$qV_QEJwG>QuyyRR;_}7wDgt!qxnTzXVK(UoP{;0I=DY2`Vc<9z^qxR$|TC z-9$APiUX7gky*PzSAdI;GlA+WTo#GnfoI_d?k7DNVAjP`U?!mq_E!YXQvwGUba-&a zX5iM}=o;DI*unAyA9lyW!(@$lA;eq0F#m=kb(9;oko1u{3b|r^ zX>ztZISj{`&j2E8(!h{uxc}4EE<6z}%Sv2D(h+@len1c5NpW*NDusJ%q8#7A0&Dy{iianV+$(7?3on5?h-%|34OH&9U$i;QBk*^c+bnJpw%${6B>Ha&Ji?Vqr1z z$;&eDrHv(l0&Lu)uat4RA}iJz$KWl2^gvulffd-@qFG_b7OZ&m!! zF5dzrhhls)PK4v?R_3$hBZjDXf8PN(4#TEGiGw<-WPBkWkJ9~q0Z*F6rsvA`e(dIa z&rvx9s{C>bapd&`X7|USf=Y)*C+0^=zG`4^BM#)5IZ4Dan22$mimz}WoD1Y`Tcp4{ z89Oj%!vb_xE_|fEh?K05lENow@~|(G=u))a{1c_r54f-9^=zwh_T6&pr9gB2(X7gIj1ywRmd(;Z zkEquWHs54^fHn(A9(8RDv94^um_pNfX?3xKoyHN5juwvUl3kz=r+-lRtP4 z?b8wzs|aamVPR|?9f#{ccF1+Mhl<;Rzi5GqfiRm1-nS0G=>mAP1^f*FzqJ^EDOOGT zF2Mro2tfU2YFyw}Dcs}~0No=6bP%xJ2A~fu1yCIQ#QE^|cZDl}?gOCP1Y|%##*>&c z+6vbqKqOZhjqh=!V?}}}NZ!_eU|RvCOLQG$+uy#K6BI%z2OEEdoFX4KU}Ok=Ksqi??RhbB@WCR%7b z)!r%}g#8*;Z$_R~k?rZV7=S=B@mu`fIfjx)_{&Vz`bT^huI6~nm^@w^)d$hzE(W5I zA|lAx;1r?<41lQAPf|3qgr9rIk!#D)L$yJ{53kTgzXH7>dvJjhVisNa=e^UOA@@6O zV_rR;X1@<<^n=Cz9gytfV>#LAfWY{eMOzXk0a2`6u2J!=8Ko$w3INVL2ynvl?f>+F z`MnQ}IZ1%bJb33QC(Z?m-$8KmS(Wtl;==xXL363Mpe;GyLrHKnMZn8Ep=GDpvVF*Z z%w-@yPA>N+|GioL`Q*FsJX7mR`z}0Re%R{?($d5~0G>m&>}qVLr6xV_zUAkpOLvCn z7s38`Vtlawv61NY{l$=c&rp^)=t|L_4@9M@zW?;-p1wB?Z#~cZgJ+KLCL;e(`7RQS zyF|L`--xivX84D2udZ7An1_&%zPwS^#lJLmvFZAOlh?L#9P72SSiSQ#qWZRXy{pPyE{JK^JgbyRg( z{~C6e8i-Z;%;6}2<%3`)`H%0P-$KX2{54`6nT4eX^z&eooDBmqm_@Ml3(YY-HiZ5U zn1zlOE~@iJ{ygtR4e^~Yykmc8iZIgBW0aAYnR;WrkUsO@@2TF%qBM}Jby_b(#AJRn z?4y&V{FmLF=^4QUN<*_UB1gQ_k7k)zC zhIv(;s2L;K@vdeI7k@N!irhHA5rLnn|8$6bt*J|JAcDKXp$BVef~^2m!*Z;5zY(E5 z3cC~UL&_9(%l$nEgd*SUHal}_S;H-9mt4YYebE2ik*^2wfeU_ujh|386s9~Dc{31b z`Pmz0UV2^aRnvYND!wHx*ti?i88kUL5`TKWB{O^dtQ}DvI~NypZ6HNXF2?}G`2}>- zhVd{q^7hM(Ci9h-XiaRo0Yh5GPoe^lcg2S2CXsv43QEm&7Yj4}@Th^9F}r3nnGsH+ zAs_UzA;aXRbP(PPQy3v;4) z$X%Nj561$Db!Vo9o}QR|^@k;o{$*wPpf(16#F|~Vc#xru8NS{`evPBnxR9fiNYk+b zPyQo|OBx#J@Ee}|MlO|fOel470(PCb@{jL9*E=YyasobQ4wpyC-h42Vapbe54+7sZ z<}EfL%#w>hT{#eWBO+az*5}q?{t>~kLTH(Igm`#_rNs)vtO_d2J^PdJFPdO8=Q7Vq z24uTI=oRoy*tR5UVM+@ z&Y&yK+hB_7a4dZ#*}wo9PEy0U7UNEP{gc#4*g5zx3GqWaEU;yJV<5!6%@S=s* zldaGS>{Mx_eyTNYV0$5q88Z>|fvcJr8YakB0x@~177YD^JbHl)^07bE!O5ItswzI+ z%-CBx<7l~_8K*`*2kx%G*gc1RiLuL~DLww2-TRMSpf?%lr4R;(R+?xFZ9JaRWeC^K zKZ0-_669r`_p*ptqMRliXM+X5OR>6ep2Cf-}CY@rN z#M-?%QtT(Q0s}M)Q%ENY$og?Dt;-?wUSFFLM{fbg2NgVN(PFPf%e)I+l-=pa!F`z z(2PggjDis|Ze~U|@X48=(gZ?9#}k>9rTL=t{uKJ|o*b;Tt;id&Cj+*5^90LXO*PBU z6*ARYIEz>SSlhmR>KI^ss>QmFSbO%f-w*DOb!zsHV)AT6DGc`FkAm(hyo|>k*(JDL zaeF;}+_HPvoihk(CH6flMB8|uE)?sYMs(QT>V>K{VoOUw$0&e$G=OeV7F`*_8dcON ze5V*2?~eT~bkzNWb1%UzEq*<#zb4@q`4j7(OM;Eu_re8T%$ME41w3@))d+Rv zJa|BewK{PYeIX!5bZtN;%`tcH?Oz~pBFRa-_XSr8Tpu_9rR#$#C_Pvo6bX?Z(S2a7 z4=4?(F~ds_K^du^*aZUglXOZkj8N{<%nJ$|b!@-JFZ55+!A- zbddK{=6!lII4A{qdMS2&i@5Fj13RCQ9I_t+2LLtbCWb<(VmFCGt94Att4N$DsHlS; zL=>0GgHHd!ItnvF9sT1ONE<3S&gjg6-yjw37Ey1=d8IPSD2U`G4e;e9 z%X`TsJ}NjDR>&|ZKSYNc3z6V5ZMxZazoycJAV>fuBMl3{_c9sUcZ^GK--^hjq{+}U9hU_J+OV3ehVHW6Tzp2x%yY=R z4mpZ?hD60^6Vo%in6{cQs}&t<@8fW-3gY`Lr+#CbM1e>t%aU~8#{P=#zoh!iZ~rf* zT$i0f^~G&LDIsvX_p%u;vXu|}|3o41mV>puE%K#Njry?v|APd!W_?HqC9pkO>SjLq zkZu78JbV^PBD*0JH}LCXPz!@WWN!v)tcjIJEQ@5JY)d+zJc@E@|j2!H>c_U|S zsJP1mhI^$u;o?iwig$(@?`c+E!9wn<(#EfXjlZKdh7KwPMk1d$?fbTj3R5iem2gT6 zS~L*LK*YVM@@+?0_-5%r1MoxMQzk-SF zHMkIQ-(WGC6NZu-bcO`9XlE)y2Xt1c5N!PTuJ zc|Xs+(>Y-6L2z&fwuyL-GIFI|d%&c@a=!Rw{B0gM8Z(v~IOsN3O>({WLMn>$!S&d1v;im-iMiu2*GPlridg-Ne#iVhtH(nD-Z3)B<*vpX@X*lUW= zRR1+aVK*Ju6umsvZj_~O1ye?Ma6fzdk*JrmdMy_#xIGOvh!9pK3mzsfar1BoapaIs z?1PhBedp%wd-k83r=~909Vn)he}hW=??%J_4z!qtIp5_UM(e=_6kN*U-Rnb~Aijm6 zyWxO+(O`a$;38f@gZ6Q+`s7kST<_gtyJ=^5Nd41MKlTi#(W{Vuz$Cd&@s1nMc48yC zK)Eib_=_76l4Mw?G&6=qj`Z(pqT|Ub8!C*(SO67 za4e~e>~EM+c#Zd=qMWOf9Y6D@A^qstv*DKrL)Y=z#^+8jznGW{|3EI{VBp@=dUi*g z*WKj$Gq&ewwkJ;cfbX)U%%iAr^aJLPSKBLwry<_J;n(b7!*C z?gp~<^saE5yFk^ede(*W*9XA)V*}mGz{m;%4sp=}?EhY_J&A!`?L-H0`xl;q=EEPN zoo-;xN*w$YoLg&@r8M8Q*xx^s!>PZH1I{H4Th zh{N03#C{Qd$9#c(_QXRJd6>bmhYgl*C;#1h1_{A~n}vtNC^r9bs%yQ;Exiuk14Ky6 zjg(v^z~PK=VU`4M$&z8e&iv&FjvdH*H8D31ij%76~Uh38t@fDH(90h1fuVJ?Aa}_vS~ctI$k2&Qwb3Cd)YivX|#bkhomW zOH=*@=T0S8M7ETY8;d9di%6|%ESIXnF{c{BBiM8-^MIP@bFfUMom2lmabE%+Rdv2k zAfpk%2?`oPYSgHpSc9S^A~h)L3``&@Y8248(Wt1=Bs9pD7(m8hBv!1b*kY@#w%Fo^ zD5znP)hbI1C@P3n&lr9R(y~_bf8Xz%bLY;M1(d(fBa>wAJyQ z`G*S8&Q7j%67M#s(T@pHy^}U_V48Nr*f==@+EuFEOh1FMxoi|f2mpRzf5&kXXG2cfxqt64zu@o(~5 za1DJB0I7Y>Mz%sm$P6b7;$bA^ETrJ&Xn$_wW|d3|nidZ-0V%h7VD?sd~0`$0)hy70|QXRL`9Dp0a?YD!k#IgBI-TmcIurd8aC%q zYotkd;kpg9O8chfr<;2b(dGv|cabhW-YEr@C5hC24jqehH=yBfGuq?)iV_Oc;^7pI zV?-KE;U8WDIw7itj#5U_P5~G6J(A*=sa*cS;s2FKYW^33*F|ysPyIJXCeR7VsNZc= zCe)0yCdDB#B!w6>WuG;FpC{pKwq^K&J#geV{+C;$V9)M_(D*Zb!7_X`5IQw=7|90Q zIR>UOxS8?YNgNzEnEC;JBjtO5-@t5K0~sEZt)7a0pHdjkasH8>Uv~zWHQQq37q&yhwZspH-XE;Q?EW@X zX6FxP)gKL)PTKE+{zU_UZl)L=D&?Kn2Xe*u6Po4Km(JAeX;V=FDf7Px3wi4ZExz6K zyXc9MefM_k*7f77n!XpaFZd6*)09V<1VKP;?@{fT8@Yp0OF_hUswkUNG~d=N1TcM| z`k(loD0`YQ%q0j`Qt7s8&vDOhCfBD#gYIyIsFzGaN%2w~V$ z`vwO7*W2{Kb7Kbn-)}JRT6|U0H+VgXB*Vr?+{4a_yuwcOuyfTj7@}*~fVvM<7%Tme zusmhJAnZAw-S#rw_KxZHhcWOdj+btamTpfbMSv;NtpEX-=X4V6mtBvmt%Yp8)k*9> zjIW8m+7D4@$(W2oR)Tzed^wZ=*cnyU z5-$FY^x5i!zK{qfqhntWd$xV=ZPgQ*k-h5XiSU>}7kN5#AKKMv#bb0@5w{u>OY{FfCcKmKeR=tD+Hn#4=_&+nB83?BzMY{&?_5SQY-r}-;G!Qdnkm8&% z@Ckzwduu$mBY8-zo?;@+I;LW`p5ywP*f?ly~}f)m`A<&Hgj}yZEOP zrp3$xa#*lG#0SU2u2~9^L7tD_$|-%jIdKfmj61S13`z?K8`hR9AmHL@PP0 zR>K4ZnK4kGPCK-_mdXeJgw{96^>up>Ri)~A0_EM)maqT&CQjDo^XLHK+UCjHg)>!a z3%BB!msdrs0-O+o&suUu(@#kyU$>D(@@QLo_GIfn^dhlp)<{>nV{D(XP6u`;p z!UL#)J;ca$Av3>I^SW?g#>LmYt8}&q{=%EUPFA=zMNX!J4APm7DQr3H>AfEuM5cpZ z7-~8&LvSWQ~zVa>n_C)`@stGS`Xpe>hY0I#>fJ75Wm(NxuP60CQ zkzQVvz#OgUrAtCr6~733Mn8yIb~LlB<=;T$eBYa`j<|cu4w!pi8WMcIZhVt(RDXuQ zT@>`?n*8PESe0g7|3C2^&Of_~WRSpAH-&A%_`(;wCL4jNLyl{+b?{;}TlG4gWI@6e zhskh~OsDul7cl>Tzf0Kfsoi6-^{@#LPm9Fi1*Skl&NOKx{+BAayF}EbkFd_;f&{ys z!y5XIanxxG*hpB=Evg@&on0mfj38lOB}NEDn<)LNyef?a)J1x>fK=97i1INxB@(Z{ zG$kfX6kJW030#sdU;#@g{KZs*LXydcE|~Au_!c^!VlWFG1VUcc9|*cL$qmx@m=j0A z+}g+tSU8pgOB)@^)M28llzZPfJbBCp`)NPF^Wrih>nppf{FTfE@!=x@~^dEY@=cCVh~ z-@xo*i?k&U(vr6tY3H%Qu;=~%YNXXnm(xX_8W%-cu-_uByZ}b)Cuv}`5-`2;t3px= z@j?2I+DL_<=w|h3M|gfE{H1RdI-772xu{i-2ebR&exEJxA-K@-z1H6`o#3DGjJ`PW zmQ{;vNTK|YiyzeLbHU1R`xX23&CmRjob4u`Q_X5{`>nW|mFU8iJ4`u^_iy)>=}(nH zAg5sDq%YtfOC*`7T+-?cu}it#tkN$rqFfrj69oj{qkw>?=;JpO5b(F#@f+IjSF<1W1HR&CjQS zDSyY3L_awKF7hmX6u%wvl<2&xE52K$Be@Lr4n2x-*&|mvYZh+*obltRQpAo>;gPU9 z$bIB%5Cj~;vEyPv3g!f4}jTI&C{yT@2xE$2UsIvf4xl70wW_)iGLXV}J*MoZD~ zYW1%y-Jm`ZmIMY5;ZGqy9NXgG-IK%5GQS>ZAI&)HH=&G)X}+3;+2+#IJ?pvkCAySh z8yEZ0ry1>M$F~pvyqz9!CitA?%1NmDZ`~BAt$#aiz;VCI_}P9Y$Dcv^fH0_!gv-P+ zyB51tt!=t~h0_Y-$LF?6vT(H&(x>|vrg4z&Ql6`H{k%I2yX`C{^Xv!uzrM-jeMal@Pjr5(iZ!= zufkuv)0VO`+D*C;v*ed@ht6_7WtKq~4pKiaHi2v8`wsLE`0w*C@32AA+l`K}xD zOqJc#G5F5f88O?{OGrt5Bz_%!f-tGO&k_ssE1c&`6Qch-(YoWOKMw5e&PU<7@jC~5 z*MAa=@9qv*xIGUK`)l6Kl(2EFKZvDkK%{0tAo#T}h?@;0RJLo!l58io5QPH4XAR<> zLpO{dEPw+>7K7w(JcSBJ?weeue*PB{o>~VXlQlK^CfHgRZVi@tYbL>O3WU@1En*K2 zbzB$#P9jWN=bf}24Rb5fIy~#dZi7R&F3cDl>W@Wt0Gf^B^j4tyJDj6MFc#FFK5L>4 zkLN!)1RoQeg(gi%cTPpr(Ew)hdB<+(P((%&2$@E>LW9JPGmCJqQGsAbtUL7IiTiER zcNT>65zB76oQy^+d+W}Odc@j4fD8q}l?B1i)HCfNWWn79aDc<5X_3!_Y}Qg?&fWX&UWwQ)XN+7tF zJK+(nP=$mohSmk)OVYUGfr>8kquHM}8g5zro#NBfaT@SxC`4kPQ6C^O|BCUd@U^9OdiL=e3|;R!#)>)$ zGlbw@{X60wF8w2u6^LKIm+{|)@#k~=cI^$OnREBCzJZ}k;<%e-rzO7mS#-eh=9=I4 zi5Y2RWSlR-@p&h|M&c#p&r3MQVuMVGuLN0WU9QacorzO2<;roS8o3BqJ{q1smSKA7 zP=qJugHZV>jKp(D=~5L+xiQCwsCKPy{;8*&Jn@T}->rhtsUIKp!bgIgTr!~_n$65v zH`2CPPMrX4^P2H$5@~iAQCI0B2i!Hn`gzNwjK({#XcRPkq21%<`5TKWA6SN zsaN8wS%g8Yrys64oJ%V8X4)GPO}W7=FqUH}UvSg4sKRyi+%uhf1q7zosI7l6wv?VM z*RCOIu%+9_6?$tbs4w9QA!V3CL8#pxvafeR-kOTOG@y@hmjrMK6Wzek z-|u^;{TqCbyoY~a0=Sn6Bfz||6c7B_FUJqJe^p!_$vT_lc-Zr=U&7zX=5WIJ!f|#Y z|BMBGHv{53fPb&sACjc~0gPo&PG~>aNc-?5)QXH4!B^LP;THGE88CK^`>f-K?!Y!z z{D8Zq!aktOM($~vzcP97pjyW?TR%72ru!%A&kU_UwG@i#ZHg0uf4)T~raxVWpVR52 z0QQzs^Chs2-dKP^>8o3iPIqoDcw-sor~fYWg%#}7pPfN|^C{a{Rgj-_mWU0*jlt2y zVZCu}3r!D7+whP2wUpB#35oR(DMA8g)vvi0PYGs03mh}`B~J$;Hgege2CcLz?`rd} zdeImKWxL8znN^;X&BGsLGSqyTo<45Tkf3@ADS}WLRSh`%5Q56f7U>uu|J0xOERx)l zZ55*aDnrUo@Iw}VDDj0^O9H$*dIcH9wN#2W&{F&x+^;j?*~n$E3##Xr%ke;5ujnB| zB29J9))+ClL}Q`Y=SJ@jc=H|}zh@&gHSjZB@Yu5Z1H6-Q^$+bUraclw03&i8iD0~p zLFR*k$F;)UDFaLYq16=ZYd>CuMVyNOSIRQsolK3ML@&~^_V3s~(zl%&b zPY4}Ef`4?k5PU(-EOs1j{}6|P7vxt&D9ib0{QkUrZ3ENk66vrZ%Yt+EVObu}SK&Ez z+Y~AgEeB5%XH+%u9-3FNIACKT6@3a@j? z!NTcPEY#_~$iHw)8=lF%`=f#|7F!nXyC`tdN~ZnqG2sUn z5U>JD0%5e|4CAM8$KR0N;Ay3O{NZ$bpT7k^_s0KY zvTExuk^H`bPY@Lt2ot)qR3lR27^vou$)^|1`*Nb zk%HAr>hQ5x#P%n6mX`JG){HRg)am#HBPD;fDGkBHrkzqRf9%FzvRj8t6pd~ajohgB9{G1n{MRTxKRGf6fBw4ZK=G&g0Px3H z>m+z1QV%;{30_@Ju(^z2bJrcQU^BdBV8gTX1@GVeFNK@7dw-2Z8fIJNXrb!_X;=*l z>iejpRgfI+_*;%of9Mi02q)KT|CFM?MZVVCeW;p*9Ch;vR9l-r`p|)x$p&JueW5>| zAim_d@x|-Hm(phAOBK5G#p6qnO}tQ+04);s6JNgE3I+S@W{oeRpAaI1cX&!-Oin^t zbdpH$clkE)MT%j8FB*Qiw3`fHYS0CABES|ls7@~=;LFATu`K94kzZ;|5pcm!HMqbr z)8N9vM8V~>^9U|jj@B7j6nZ2Dm-;>iTR2j6&OX7G`p+=+5f~1RFpNc(mv-6#o&Jzu z%4Niq%M&r>vLu*t8AbHRewLWB>HAfJDeLeFOi>|x)~ZP#YdlF9O5<>%?%LQCh(yka zxhSe>|K<9U82q?%Lksca*_=W+PTGa(r6Gi?l?(x7WiqTkT`r7WxRe!2Ku3{0zQEaa z$F+AFKnjiK3hvzV;TIyvnIjB>i1>!vcQFVeze1pNqsD55t(l!JOP_4aAPDYAM0+^Z zVv8#{xL%6hBsjQr2ZSlCQ-12&;S}(xdY}+G=>u?5C{XaK-c1M>rV33W8n~EDgk9B@ zYU&A=b~N*CsxT4*bp)$Av{uV=SZ6D;KNW=Fix-5t6ohhe0;o7EnDl=*+YU%u z5`cGI6o3IL#rDC-Lwq)<3i96dhVNwFh&Kvi{eC-dn*C691MREjqE}p`_s6MTF%&s?!!U^px)rADi9WF5LR6} zG66&_cGQF+Jdf8pmSUR)shJ}5NgMC4b~Pb|n=SAzt%z)&x4^7c&| zMfKc-O}r;E2HOrPtnV}r!$F^hHBNzR{9mwakNnusU8@@WHFa=o_u`i4%mSP+P>`2} zqXxpG)8N1R^7c*G;t$qEdPBQ#1vEyuqP}~8+bZ{p|2*^&4m6fKh>;9`>`>7{aQS>a zEYI#IKg`cVgpW61t%^8NR&@IXL@~Hk-5;nE&PQ3$tUzoCkiG?F{8^EZ^UEnlXVFE0Vg=O=LMP4M>JD~ z=PB3lO||ncCIkMPE;@H7^vHi)Lt5ZY=52e01TbL(Ch zv6K@!9uu0lqGCcV#ZKGZSIsWbcF55)$$|SQPG}~`tmyfU<-e@3Cg(V99MwTlX#qYkj7f@hXXljEW{2k!Ylr~ z569nB>z#ajYfv|Q!ce_#^j<}QKlq++;b-ZCLL)b43n2fD776z48qNC-^}D_S`iruAgr6JAu6Q-pPN3T=XB?Q5O33&KNk(h7nf%c2!UsFZT4jmCH&$l1aTL%DRtN0=*Ozcd zalh$5M$wG1x&dERq7L9PB(;{6UC5yzRqXl4KTXuOR4p1pNnv;w9E{?_mrv*HQG#-K zy+?gnPhx&5>8Cxu@c1-e5O>Xod(Fk74o;1pEYF@rNs&baKSDSmn-DIa*i%CMb3ykW5SdV|L!MW40Vp1O9)Blp36?-SA$}9(e77i6lRs{# z26W<_`RJONR{d~1fP#U`>e{#Ei(9AhX#PpRR*8sS36j=FKP!Nl)r-x zq?3csn1P*+p_G}CGm{9IK(oM8RSC(N=pIFa+0@r6`P%}ahsZZiIq?7&^iivLn#A#k z+htnd9{QmM?sbEqju_kw)2eQX+mf#2X-D3PVSa(cVF_gw8Dec`NC-BG)!v54Dvktg zXr-K~Q3Mal?|^fWlj_=E#}e2RbEBA=#s7`AD7n&{qmn`RFqZeQWPcfIi3% z(GT&q0gbTdy$>7!Tu6#TOlzehV&LCSc46SwFB`?c2ly=ZFA56E1maMT^DrpL`3edi zhw%=O5eN$MHPv~#3jix4x6)n23OyWGaa$KQnz1o=hpW~&;DS?G#HyFKxn8hRcQ*Iqac)6u`UQMp^d`CwYZD@ zrA?p4O+}brWE2dBTF)XLcxdm-=N_7j#rUxn@kyT*+Gxy?rmarI>q28jLuI{7uxrdz zM6OO{Aezpv?HdwfAC6qoBKyGhy_0#{3f51H84bf7;6KnHp{BDJ9m#MS14_Hyp+diY zme2(^gM~e{pSFdVU~?q%CTbBc1G0?uA#q*~JHZkUgs;%^)r_yfno1&m6&fLn*dtjd zoq(U@J6-8n_*6R}sFV&CT#m~rI|sSnDy{XQ{_Ekc3|pW51|GpP9DmJ{V%b#5oe%bR z^$i5Gmhh56-N+<{BJfPHq9XdChAwW3d9G!Zzd@*C?YyS1K2q9EUrWklbOv?kZSlG_ z+~4yFiHc$>5Os~ZO9}^|ExP=h_nVZD;570{Rv!b-5@!Jdz95NO1)7kknz*`rQhm`z z6Ei=Km_7(m~jDVIQO1T;a)XHXd1JZb}ZA0Z{N7TbuBb?Hn_^fu-TWdxTpMB;hY^&`a@nz$Cn zX@svp46|;+WA&4ze9HFBHuL>8b(vgSkwJrH95h)cGlQv_#Yx~naETp3GpH%lAU^5m zsuQ}ER1q@+`OIPv*;#$Vwggrf6LY^C!rpYV@p-~s^n z)%-g)G~f&$lZr5^MXlNBeh6B%9KS>QVg6x%OQUr_ss9_0I1>N}*H@_2&gb#rc6y2{NExl%GP4gmN+EjeiPF zh7N^F+*;8PsX~)dLx&UDu|c(AkWBgVdK?hj_t_YoNe`)gQMe-C9*&jWc!;1k+E!D&Cx2N?@ki-J(cKI9CHz30O_ zbh4X1*|%z-ToVj)il@Z?^JRD^{Xu3898}xJ=;K<6J6wC|#(7(%g=L1e{)O6lVG5$@ zoUM_6h>Pr7NGSscDQM+e<694ZS*d`bx*2uy3Wk`W=5vt4Jzf)7ss2-hp ze^&6(ijz>d*yr7@NSd#~O&r0E;GbgAD(#!y2({e(3mhSJ|C?sS^^e+4U7y$gQ%mwO)D9HLIwh1&y7>NLP%K)9QHI+q4@MH%1tw)+c;0xS~5 zhJNg8r%1~UXdh_&?t=H#`SSP&v5#l#1MB#BHZq552iDG2J9+Xsc`}>gjfQdfSg_O1 ztphRKPR~XL@FR?mdWf|2b}hb_BLBa0^*!8oIUZGilyUbh$Aju|{c{n24&i5q_&2OD z#0Mi5Jw$p?QLqoW62#ZnX}XC&?Rg=7#y2E>8pl{G)NlAdL;YR&LESFBc^<&FC)%H% zky8IW#&F7W3|< z{W0BHr z7#7E|maY`u{y_ZUstj43^Xkw^-4cAa0hS23=YImC9L)VH&;W;-<_*l`miTq* zj*3Pm{^Dyf6Msgxj|yFPeY)lI*>Y>FY-3PEP@PLsW`dMvKdRRM`LCK5>t7{PvxT8c zg`stJ{1?ZL-?o1tBK?J|$i+t7&3uR1 z`Cb(x@F-4??5Rtw0{ni)JB@q~sf6^kioEi6(uerf#>U>q_gPK!Kd+JRMStS<_gE=I z>KgvpdkMfPgi|Naanr1RZWKM2i|{TINocfv>dzR=+s!pHfizKz{@(2N&xCA2zk%Mg zugHaHJAWw~>aDJOOZSis=%~6wZl--WFHyJX=j6e~i8<)O z`xt9!q8j4R`kL6z|028;`ymr=%05wkGC6~JD%v&K5tE#RG>&UeujLDLxr#% zliN69G~2#|1I$i64{KAhT^<$k44S1Gq{(#RMK2RBP0uu)(RK;f0Ly{nc9A&r+L)cMX_|p=;CcZ{9|~FZN=;c!YTq zwl7(J&ZlNc33LlN)j&A?90rL#ksoZCDMP*%U*Q7Zr5OG|G()3u3tIxM3*$#`vfV6y z45ve?u@+rpl$Z=oX$vxw^K zQ#;SKBS#*6X?kY-$gM6!Q6ahuL!JLuHx@3W~7jUJHj8tc0t%YS@x@p)~~$pefUDGoqH$m z!@o@al;VV_eee%x%-?;@pm2{PneW0Oup0v17javY|D+8A!W}OPQ?0MB9dASUv=1}!GHFv`#K%hkgW}b&+32o(S+b3op6BH7he2? zYvCc4L#c+B_n&erix6Yvvm-}zwjR-8P0Oc@=yFKu*dqs{xMD6Ew31W-fo+|Of7;}7 znCa*(%L6RH(F>6o*fvJh1c>T&MIyS7N3?Wb!L7`@af0k#Y;0WN3#WUTtM1O-m+J9? z_Zs?s-vFtZR6^NA%;}wU1AhWE`ly|yScV*%#b2RUOiPDm=2U^vwUO8HulK>9GXdEh zXX)Spf4CQ1K(okC$@2#n1-dWyE!+d_S;XaHLc+lC39$ZH`Zvh0$IH|D1YXScq_Ahx z>ofzpHy-~`e-`mbe=XgS&>E5~evHkj1i}G)R|CI>qMlvP0AmBva1W$;9mnDv=F9u8 z>^zRPkQTjC0_qL0KDVMj*#`Pk{MOmNBh$SQYsOcR+Lar3K-3plb@a1pnCp;7qsxvdi!_t-KWby5#f*@gO2 zwGoH<7i!esL+kz@25}f?X)Kn9jD4(LLbC}1uI9tbmLrf`gn#fmO~&i^krg8NY8y8D z*T#i+$tnQUEq`pvq|3Tnq|ctDcHNqKIEC$zOzD&{xYd+)t$CSg&7ScSPQbs}V~=Kj zre@Eu@+0u?$==5n*8dB6nKg^;yZqGt;d`Pr+aNw8K>_%OrBMac$2)V$TZ}AAy(FB5 z?>LLhf{Q@f0LsL7#IjxtaBO-N?AUdNKp7;=v;s-vOTdJoay|xcb;4TkGBs7SR+oK< zeW}@(HvXpa8)b|8sD3)*(FWp zaN{|a!gH*IU+Z!^i)0F>nJygv`MMEtJB!dl?8{_S39q#(pbV_n07I3e8;Wv?-USH4 z0-#R-5PJdr10O}ASXRo=7tWt@Mm?Ly125}t52F&r;iKpxA079QCG+>yZJf1uuRNuO zzADa%npy_GKhhKbG%kSZt65FSUgQg%{xJ*N6$Inq zxZ?)Q&mAw^0=v-;@j|EG9&sDnwY?N&=3BYN1;N58a49X>%>;D|;|7n)(hfx2~G4)@%J_!Bi_|Mmk{J8p`Z=#o2{r@}l|I|4B&!_$u|9JX8 zvk@^NoaDyn|EMzL4sxmcI=@7D?@a_Nq#Z6|3Gpwf2tYL+%p~8224^9j8iD)aXi)JD z&b|AT&PQ)r*?h&bV3`Wid8nQZJ$I>ldlJ*^pHf1Y>fYGsWh)A7hG5=mB!x;@JUyF;dKCUc(^q;gZC;wU{>I+hbuL@KZ*`)jku^^o>LRf6m6( zzCBrBAR6D&yN>A-y$wKbkaQi_)Pfu%SM>71NzI_o8LnR7|JMbDCfEeUwJ`p?ySE9J++8dxuqAZ^?8?9D{fM1w94U4&68j%YgdcQ;Cu+OA!{n$H=eo^T3-)T^jL2vUb71gZCM3=d@s5u-tB zf{@7=5S(_}{J%jAPSKDRxR~HHz~FQkgVQ=3BN5q|G&qGD8R(9{;6vZ;O}>Tup{sBv z(@(^jruIMP=R2|Kb(AuRO$YNQfMGN?#bUGsX0F&&-jB=yWxNlzhpZ;Vr##(9N5sC9 zmfM;{oKgY(N{ma5u`v~$xWDm**tqnn6Nwx8YpTD^lfj|3&|%_IL_COl)FKpuHxZcX zGr@@Dl}=!~>Ur?!%b&5cW(1}EU~&y4g*)Z$2M)P|QF4}?xenFsw2%l!({bgA!SLvd zyZ31TOA>@ey5e1lKc|t<4~QT#{!B;w32gV{l(XHR`WF6xJ8QlZ5MD?SmXnfPAiUH8 z;rc&geuv5YVnA5lNSSo3kScJ=B1#NuNRIGRVk=wnsKZYmDyq~aEURMpxlr}Sk0wcd z*BecSpDHrFN$bDV2|8&%=jr_MbGp7$)G0Vy?1V3DJ|QEkg&F!vaF%j%GtY=xf6czb zywjNf#KDmjBWPHk$AesXpkxQ|;yirT(qzdO-Z!^iRMyG2W~*=E*RI=1kd(=ET`3a2 z@SL}??G*P9?q9^CsLe2{mvD58rPE0~D63y}-qnNrMczqA;g=Epsz;|6T;-jVMs31K zv<=n!d^nO>c-gU?9LR{;vd%dC!H(t)dshlZ)1kf%zqx&VtCdgo=~ul4QP)KUx6}pF z7Wpxu&VB3Ky!;G);VHlKHuajj;ek)P05UiDc7Kf|_R+qD4Hx;k?}LkkzsXG0IY}lW z^h14Qhy#0*Ga1xx&|rUF2k)f5gb+rNI#oqkrGrt7>s>&=gBdmUz+}phB!BeO!ld*) zLKkuCK^6Efxl#s24)&`WoiW%u>1hrbT9%qXcxD%jabYrKK@Gxzqd<6vI0nzNKhEy6T8Djh0W4p-G?|D; z{s?55eLTC<;VcsZdKoEJ{8PHloKG&ntGAr-ApG4_+Y}lQS$oTQ1CeiF0$t8Eek4BZ z(fGhi<>6mX5ysEXsp2Q_K|aBIt!!r3CGepR-)nrBFr0_VUZS;@`BFAxI6cjW9)XO8S_qn{%G8tU|%DQrZksQf{8V+8B@XTa#i z$3^8zYyiv}o1txoZ8mK|s@N6;VQ3(HJrYbGmZ7*?u6uz`g6QB=kQn^_q75i)WuqQxSj z7^MuIxxC`?8(8#?!*>>EnM7W3&rOk8LJ^(DJIUSTQ*3hXu_E=7#3L~{-)IsqRt9{$ zunby#8Wk6#BOO45tI!S-v`{=%BCTBoI^cn&>AA?}AvlX|g=P1pe$?s}1V5Lrg{D}| z<=%kOg3v9fGPo0`iS!ACZ)i=j_ZOUywMy3JW6|PP#=@refBjy12SL@>orDXR3p0f1 z2EjcRI9cqDb>Z9|OZ(@hog84V%MAVFm@ReV5!Lz^QBItmkN~?C9qRl)y0d_xSImLG zMdo0kV(u^UPW3WxxCGgu<|2oBZfXlqV`BnpL@`9?pZd@s*EBo-%y5ckMT90U|J+N2 zCz?qyl(g+mjyiYnKRVz{ zb>rW4d4sgIBFjU#nCU(r6075*Z<`cbwI|q=u*xl1QK5AGq~-IomdWSwz<&A?0(vRr z6h~gffc`5_k^dbUms8?C8>L(XLX_9zG)+4f1lJ`YYx>Fc?fH#E>4Mwqw7>ef_E*;x zq^-v7GTw=MF=RhZ4A71%{tD=lm}0%ZW^Y6J;l3yQyZ6?6e7iT|^nWJvHo}Y1(m(q3 zgO~o-p2X}|XC9pNm$H$NZsf<1{s9#HLJGdkY{p1`8oGo3fc|2{KcB!J6@Ngye(Z=Tn{NGucPg zd)1B2wEq-1$ZGkdMka}T5%c3Y;16L!&+jE@PYdi9Qw{OrP^)d@qIBCYOv#b?TS3Z;Uu$3C$h&2q{kL5 zpv2gukA90r{@YGeJB3!#IIyq`io-eJluNaQ+vcc9zJ{ebuFYFN?n!N^0D^P^{h_ft zoMqJo#skt}ntMg{diGy|{<#86n}~`(JXQZtGn^eVC11^}X+$1q=W<2ph5GrCug%J- zHX>R+!dgB`64p-_*t%M zqlH~-Ue(|3@7DAD)u`@5J)|#RK9$ zI#Sn49|y|+TJm4F&@BGTIGf@>Qu+SYe(yWY;Xem3{jiqvf83A8|Jr8if3xxZxoHmn zJ*oJAOAPyW{`ElE-xvL;BI)7)*}wl`v~a9$p*idyDC2C3{d2(nbpI_5_r<&?h4?Y- z|F`K0+;76XtIx+Y&3)F-HcS71bo>5X*x`ShRQ#9293A_bx7f89c}_%GvZl>g1Q@8j9|6Ri`N-;{m-a&%M7kG1bVI)C2{S^jQHYaV}JIUxQH zM?b1kx;Q}oc3}(W>lT{B-y?ra{{HSEbpA%G7W4P8%Abb6&Gz5^9kl%2->?GtR~>o8 z_~!^0VgP*YpAQ7U$D$+kxb$&=48DLZT&-JZ4uj8-aW<;J{k(I>=BCkeLwV(`@h0I1v7RQUe0**?SQDeTps2)h#rKzoBQE4El#lKK zk&)rS9wU6c43!asZW@F{Rl2T_u!sB9;#`XMhxh5)3e7GYH4u$r3)POY(-Rs!1&uO) z+$W*kGyQjC(^OXah}f3d@U9D_;pL+OY*_ZMBpvb6YK-`^-SHznD|ySlWlNE5#%ULO z-Wh@1pnCphve?cj&QyNK^CYvG4C^NAzx(e_U}?QpvSX?Ub=-w zG>~Hr1Xt;?o@&z9FS^wupj!h7;PpE7!ujI&Ye`W>%{ zipgKUCH}D}ZhQj!>2c_P-cA?mMS1h&I&FBIqM8q=HmW^<27DmxkFyV;R`q`4F`eZx+K_) zZX9Snihgbw%OYnK?5OhZG}z)REF#L4rTKcRr(WKb!v=fdSRX023vO4RKduRg6$815 z2j|?mhJp4mxx^!$)zsS?p?l=v1WhCTM-7SJUn5kLO*XQjMmEr3X>=#6eOLbJTM#7K zo|?ktnpE*;yKrw#Rvb2{&r2E^s4Qyf_2Hprp)&Kg@xP>jU-46fzfKrEccU+f>DIM2)PGjnFir+F#dZj>+VNAVRm zzK1<8jLyJy3F_u=D6!LZ6RzUFBHoNs-yLVH?ZT;3tY<5Nd%*fNSxT&4!T~P6YznS$ z;HG*Uy|U8#u%8N!_I=1Yq#wm)?#pl-*Z8aG*WuPHRWyBYp zkd6Ge8pC1;NKx3+^SexdDLdggR_YJ8uEPDukuh#o@4h$m;@v&zF z4vTu>5%SXZ%rEdtiP$q;o4SGHW@$s%^HzmZmAbZ`L)TTQMI1auPPei&{oLWTzUs=% zRwyN(fVvRw5rI7CYx^4NblO8W^)=je+IDbAj#N}jwlGHEBQ$^X_@LbzF+3gx8&~U^ z%!^cuZ%!_ekpVF_O#2Vp$-0^)Rg^&xj{l&9UL&P0*08&Xde-44m=)^Or-?^UAnKev z7rHXbaEw6Ou$Du{w>TIebZw?DbfUg0YLO-#&R+67P;N-Kf&7{NHF1MFOy^79B?(u8 zbmIcS%VDgq#RV#Ny+v8~_<|?ad(>wSaEA7bi2G1X$8#7v6T1fn!h`hrDFwJG#7IWi zOZrD=QNG7IJ}yt?!3c@!rz(b9#_L+fh>IW7)`F+$sZ; zsSbOG7L}Xmf;U2Rc=ygZ^Nr~6{;?4(9YC=f(9j3DFNCDUz`L4sV*)WE9g-oXp1+(q z)ad*RGXtRv&i}>$>e~Z(Ys&^x`5_wdM7ZN#N)dJ|qt+d&v0jb-%9>P%4wxEtwjs2Z z^I$YF`YlcGDb)B*jxu>4=?2+s2ZF3quf3E&kdxj7L29W?q{xu*jZ;M2Pj&YV31lIe zvm^hF0To9&Y<=Bk!Iy2A?MTQel`E~NTw>vNP^n8mwEPeK z(n^VKgUIX%N+m-R_Tk8iKU^xd2j|;!183N?_a14KzWGsTOw12VKLR#%qwsi};_zQi#k}0T!)4 zr>2q*!&56KP07d4?@o}9K3}w0KJ@WX`66HRQuJ|zpxOs_Ig;|l=kzC%NQsqbG1x$L zzcztpb^Zm$EsWek7 zX(0Tp>;Au&xGO5v{eLs%>elGRe)e|0PQGf`n$S7opR8(t2Ix(sbRo7=N+;nCipO!> zOQ-DqTOj= zf=>{E-$HV5kilD_^A)wdWso)0y>|B1rmo^{A9g=m}U) z0s85krnlUA{yIS%hS@K`VYqy~b{Kg3UL=g|a+t)rU2TQtdpIW$f}9ooo@w~^I{Ak~ znDNgh@1zy-m=zK00pR57UFDZpFIu=Uiw}l9<#z}-7!C)wSV!9K5CXV}FU|32Zty^} z@O|mr|GB%Yr(mueDTS8Kke1e{i`fkPDp*Ill!nxLM9b2Txw~TINM8^G6Kw1F3aN)* zvLa72O#pa%05u4Rj~?c)AS(ODEsP>o%$Z>#H_^*v^nC@zif%9EceQ*{&BLDG-A>M9 z_z<)A)tt=~GwpEd=Asv_@@-yd$BE)y81q~aI=qO;JOJUZlXk_a_GLlW^vNtGX*^N*EC#S#=BpiN-3-D%p~(u_8o_iT#`ml1Z)(|v+h&WUl-R4C+l1UXDpp6 zj8o_62Zuc)b!&vnYBVKof1DRqa`CeC*5&tA+*W@HUdNiE>-DpuuV38Q>mzO&S$6T# z{;kuoZN*|h=HCsijem2K6fxMl0VP7fyffA9R~hE^=LIQeJq1A z8xo!PHJS64+_&wych7kjQ|N7nlVb;(fxtmdN8L-PZ4CcQ@rp+*Az?db*AWw z`h=&CT@l06)0`RV`Muh#`9=9RLPx)Pf=}Gyp5R|UG!uN?iRK)K+daW|l1%V}2?-M% zI@>kDX6 zllyLb!sN#P)it@7?@2Z}ncIfJW^M$$NKF3!N6^0yZ*otte#3$3-!W!-F8%xcUtH5$ z$94V``nP+KnV%qf68$?UeA!#gu zg8TpMn&8>2MM!}!R|V`0e`I{Q{s#B-M*g!I_|lINX1sMcXKVuZe&(Lsm0WR8n4I9t zuLqjB{UrD@dboRnp>+p_FISDx({tg=MSpVfuIvtHdI|RZ@d0LjP2fvv`!0bUO1yY< z$A+?BpbUoYjj`}EhH-*OXRcQ-uC=ipY$K{*qg=R8V4n;mQ_c082}+llk$C-^-IRY8H$SQMa2&LGL!J5kV~uNmQtE-H?EK)K zF_T~p<7S?F?>qVES-rkd&&|cVnrB^ed!1|j3ARB7k*PlNnYl@KnUOOb--TYjwtt)T z{17aT1Y6*Lq9Is_skIUS%MSL3R5+e@Lz|Z`o=l^d#{}}xa=p;SZPggGNS-YogD^>82 z&h|`_Y=_RS=&0GOyj@^@#51k-KUpN&5eP0-e}CU%n@P*$Yvr(Fv0Vatuo6q0j8x$M zm#EI05)^;LGbG1hSh>LY0_q8_y~k?4Bp49_7a>1@lQL4S^B{ll)TM5U>1g?@Xh^5& z^JA{>JajFU2i6yWDC;{<{DV}{J4}qvjM=wreWxOkNd0DkNY46BIad4Qh!nHprPp^J z?w>#mtt?Hf?`%to%o~NnLzNa$0h1-8eRV>Oiyd2S29#wY@q{{*GUD@bdSVp&-!0hTaQ- zYf<_8&rJ>qUA{4~B{NDwb=1YlY1Y*GqB-9l62>!@VBa8cGlk!FCBYXegNYl1bl5Q# zq4LNvX0Y~L6$S96s_jY(QlsLal!vnfm7OP=7ri8*WAtNcP9f(FJ@Lus#GHIXhb?41 z*ueEe*Z3AljT^^zFQj5LRH=g%>r1UFy;$f{CB1&RG%DKCQLH*ipIA=fShQO8gFK9e zT2((`@uLIv>I1b#iVt)-A(tMW=P6*E_KYdV zopL&H)sN$(`gz>rRL3P5qtEJzp-Xg(Mh#hP;^O?HGhsvAr>GQjEypf(J~kM|ZFAnG z?Lu)IlVdEls zrE*KMlwyfTDVszDU$`S=9+B`uwNA7{^xcw`Rt-4E6b~>73A;BDP{4i>apwh8Y%~hg};GxRAFj2ZW6n+^w zH+dbBmhZ7#q>J0%Ffk{W@{Gns#t`plIp4>DQ*kKbZhZMzaGUb2*B$K%fRr)H8rFj# zWAA$>{~+xOEb7Klpx zc}~9x7uUZ$k22Lhv%$5Uc=5_)mn)!sqlPhxqNcRNazZzF!w`(;t1cQwcg1u z$lQkTa6hrY@PztR<&CK*!P#?Zm3cu-x3@(XVDpT0z=E9J^INQ2M#Znw4Bk`4zwEVyRmGjx~AFE|Ryt zy&$*7fc69Lf#`=i1^5AQtfEMQa8vjh_Ixter2%v9i)z4Ze^->pIS6jjO>G@Xx7muKKF5=P#F8MbP-TpiyOT^^vFyM!Q8L=&Xc21!$bga2r}} zzA|i(@Zwe2z8M2?Huv3R@1R?dteTU{-~66<7gwJ#F{hiL;8g8c1jVlrO?O97F6sW?b#`dx#sr9+q(XqWvmnlne}V1$$#zN0B_AZvHp!r1jd1VrS@-nKGK+fb1u47 zgV0%=f3uV3l?@Z?3)Qw-?GDJqfd<-|+D$07La98b#OyzE(XXpP2gYYba9)aW!0vK- zLi4Up!d22v?3i@{&gq%RW$WEKESt)5%+T_~bP&5eRcDM3Vr3WdfJQyrrm z!$9g2n@$ZP+sNURVfr^0L0pbNXI5N_O)O1lgR7}yCYW#`9k)EeV3%^U6TY*Rn35R6 z=2@@ae`iEWXaXXWMx+2~L$_R0Sl0?VQsw*rv2jex(?)-ZKV}OLrYr4XM6opQhtr{} z&;ug3h2F{k!4FJ|v<0=14!PK8w%@_q#Ht*qz3Z2>+3VC%ui2?vX|O3sst0F@D+t=k z8m8WD17%!|+x2{MBZ`_9YK*v#pc6IwRojEjfdqHT?Sbbm)T-AqI=SgH?iwwaQTib3 zpt_*$$>4M*e#8sOvk#67`p}t8>tEzK>w;?g{G;IWFsZUTl=$3mp&Oq&yz*1v^O#_q zOh8YfS&4BNftvAhR3=PTBGzg<`25XSEhM!NXd0av@|nbXI|}5|pW#v$tMjYYehWVD zL2*u#a^c|f9o?IjkCx)|?}?2G_h;l&=KvKNm&L!^!U?DF?@o{kKb^m#7LjVt^LZe# zAhShcUYuxB|GM!M{vDARL>ASD*2r+eo|PB4khxZEniGX)X?ZQT$yRU2E6{Acs~BT566!OSvt1CHUn(lTGy}cYwm?#i*4)6zv)0vsAEUh zt%f_w-jH>2IR)NaZD_{wWFE(|M!o!Z89O#_(X(a>IA$ckXPo_xf3Y_{aywG`=veNz z+EIoRy-iz#Oj{##TRMrcG#!`zfIq@(co7;wjb(s^(K4fxw2odRS%2s&HLzMg^g@oo z&5bAzYQBC9IITtcvEL%8EC(h0qw%$Ynh@u|SU<)3F`^&VUvcK?(*OTSg__n6(T7x? z$|R$A+CM_rm_k3SjkF`tp37f;5u+dTUyRd_19n|{PHap+&PBIs5IT$14+vXHAe?@z zxa7Pa`*ghoVkPQ-=i6vqb>PcnEhK7=h8J@E@ORFXUw90XeX&<ClSpDP1<;`^2g)R^+(n%ftEydezJVIVp{AbtuPuurhL)#*?er5n32yx#@J-x2 zTM6W#ABmd+LmSO@XF!a9U5$@(-i#d-?Z2=(*H1Bsp|Jb?zV`jpgX?S` zi62~)N)GbkhuHOnPpo{W;Qv=~bc=ugY5RWa@!fA9i65Wql@iFRGf205_D%J2QxQYa ziA^I;V25i-Q&XmDI&s`$?rhVO+%&TS-qtnCV z_7SjH=u^Ff@c0T*W!0wsaNlbp2UG zw{;a~5!nPULjy4L&bAko#|F;w;eKX5X z|J_<0ws2@+sDsmhHx56aw(mP5dsX}PQ4@Q=eFVyp&%swO;am|t#3nt|bDa}u99bQo ze1;$7_P@84P*sarKLw>V)eRWTY8iS=lCZWP+b5aK3JGLy1|NehdLEyw*OB>2(GHI% zouU`_b?uI%sfz9LDz;afvIyHLl7viKUDSilE9&TF7ylK1pr_4KETTmeh0!XWTy)}{ zt9x-a5;_@W%?|aCN^%1wI`#%%M8MH(#Rq4?$Nu`6sE>_r;VLr__0F9x6rZ@ZJP-A& z*wng)uC}PizCOcD}gU%hGdYJL`pb5!+c4UMz~fcvt+3+{lU>N4byH zR&q?wnMFzi`bcTYv1SlTF&x=)esF3t*c{MaE zQIbezeo6eB-;{rSYt9z!T>H~0u-j&F&_Q!?I-F|}8+1;)%}HtFD9*G%daQmPcTrUE zI0PbV*$Oqy|o5QP2v#vOABs0<&KTCP8BbQ4_06m78#xQ%{>Fx^k)SBPh zNY5ULWgbL0g=+3Plc$z80Ggaf>SRd&QBgs}=4e~Y8kNOM&^N}XhN4#;^4Vt)hT7t? zTGA40#S{0*)L8_#u&le2PH5;R5*Y|CRUKvUR31BcG{c~=1UVDjRcXdsmDj5La=mGL zM;Xp~=Alkn?CcRCj%V_{BYH+?tC!5e8#sE;b)hjJ)WE?5r#o=)_|q~35WigL zJ-ogOxhReQdF#f#ZTXJ`RR7~~F9Q#dT4Ro3v}HL?yJzTjvEnBFMIW@S>s>5IY+19; z2oZ33NTO!26rJ$wiAyKem0#<}5gTNXDVww-Uw#@Hy++2THqCT%+qMlSk3iMT=6)Ppy&K7q)2lpP7DJ7qI|*Eof5Zcu z=6BM$PaTtpU-8Sb*4u~-N^s(}eVjmSO1?f1d08%U6JsAsFNngF0Gy*Qb}im*A3L&n zrea*y@kUxl)^{u`8$|h_c_TgZDY@PF3(h}0)omYpJ{7f(@-(CkPumq9c}K7CIH#)Z zjVW=Rb8i%rPGPzeNunqqy_^H%_>U(k$-2Zfn#v!WQ>b_7AJq@R2F542gh6X;Z)X1f zX_z7HQ;c-h-|JvdRc{mxCDkb^hx6Mxbi$ofuJuSVn} z0T3SYrj{4FuUn|iaBCU=G8Xsm_d}zpa<3oqXqxhh~AO;^eS~_-wj+Fj$_^!sJVH)~V zfB9{kG|+VxJo3K1&u1^C{^CN76f$Wbg+>f>7AY{bj>KTNc>Uw()h- z_;4(m9{~r5TGk?f`1AxfKy3d_(*W^$696$1OPk^#*Z@1mhqxR4sUW(E@gcmgTYz{c z3J{BXw;Ujb8VySTh+StTkpNOm5Tf#kM2>qgQGR&{{f7&44>dk)?(D{g9ko9NJ`DX; zV*)W8BT$v-I7T2+;=|9U90We}b#y8YA2yzuL^`a0nSc)i4o{SpgT)6EUm)E?%ZB_L zqV7ihhs>Y11Roe*B*KG47>qBXoyGYN?_{~*Va>x$!ULkrM%{-&w>2gVh3HP*iC$ua z0iKa~54S|I;m^IAi48I9BYlm2C7{DbRQx2^2MZ2EJ&EkbG>Hw2zYifkoY3P?NHIX))~kTn0WU5eOrd@+Nr^g-qyOv=IHgD52GzdO3|;iZS7_#h9oH2;u$Q)8lV z4m!j6B*{d<$v-@tdl31Du13Fz54L_#@(=S)ZG`{og0$59KBV!*{~)G^Hoo}%(QbTr zY06K54_$6-Oenfy1gbYWZXP~-Q*#jb@V%o`QTfpI|ENexupcS$p=|>$lt#cKSwk#k ztrqpv7Ue+m4=v75u7*h4_~OUFhvfOm37Kwucx3WH;zQ=}#zf(0bf(TiABm#i;KNZr zKL~vI-so2XKFm0&5&o;r->2sHA;pJ}rEu<0)}K!}%8d_?O#CVEVgL1w3B~vAArx8Y zI8i8)ax!f>T0KQa215MNYw zO~QZBi!p@SzbBF1Ha*Gp^+UIQu|Ue)4kbR^*w&2?_g4KB_^|1k#w6mCBOnobCd5gE zFI9f>?gld{U>E`1D*DnqzKl#fHH$W7Q zZyF$)%1^#Gq%m=L|8R&yWL%s$*!-mT^(a6rIkn{gVHGR^Ag(<=i2yk1$q)aN$Z(sU zJe2F3Ga;sjHomy%FgHG2G4`jxhxu1FCJ=9VAP^gI$8C(oNQnToyuV3!XevMXx5CDRVNM$e!>ZA7 z!eH`~!3~fKT?O&{NzKFt*msxz@U+pd1bFD(DGC2=esccyM0WrG$xn`jm>ybuII*=G zA9_~)6!`GepvFYv=`@JMykEzOL`r=4=Kh1ghjETh#oUp(|pqQLw}_|W|P zWFbV_;=_-Te@LF6Y-l(f3TEqvJB*6r!vWAvJF`*cT5vUnu$%G^Z6t`AAsbyyNTC@^Ya0hw%siT2}ucMSWbquxHrB*GKUL4D3IX z^DkKcfSUmHjs<2QI_QHihWgAw7y%Mh%CS&ona^@cNig7iul<4$>c96|7U{2WkAOYh z(biAO>!_d1Z|sDOyL^pF!#(ItJ>+zS0!tQhqc5F1!L10`*R)gLhfrfgp(O=ULyd;T zco1rDyCm!va!CT>ewD~?nLfWgl<~!dQkZur@nQ2`H$LpR=cmAjp_er#5yLS8Rf&#$ z2}QNZ@ZqR~!H2$%PQ~HF#kH9Bm#%Q8r>bI45`g^8urjY7kf{Tma6A?Qlo zYcmC_fhc$Qp6!_5R;>N_HFGiq>&~fwd;hTz<3W!TSx;i=)hY#}(OClmE z@!^cEi2`$Q_%Ny~e1}YqG=sGd8S4LW_a)#_R@eIh35zTflxPI0QKH7W1qBTP8U%Hs z3C2AND2fYJv>*wlf;BV=5Qo9IV5vfjZEe-kp9rW3sKFqMD~kexDDK}hs34+=6;44 zo$zc`A6`T==;XHbA$(hmZ#-YtHwC>$!1Y}A0s+@~_R&HA_S&WNl-};7i+{fdn;QQE zTjc?z*(?v*a&&h7!=6&##SEgsnHwIe8Sct_IFgwUnN}5#XR1@SpfO{WP1?gpcevHU zq8l8wP)t1YSUqB2hWm0Js&Hqtm@wg?b;9Y%ltB*Kwa!Cx9%X>5mJUwiN#*nmd|<{P zqay(k&-XzBhFfpvE2SW`z>r8AGL%AGXJZEPWiDEFmXKJ^ucMGJrULiB7pOGzb6Pe- z7m&ZYz1wtk5c@oEm{jq{Dv~t*`6~=W2-|pm)OT7r{6U+6{2@XG{vd5^{y3kl?Th@F zcYfh!lzXmo7zOz3qw_i6^-abyKYR|B$w0$?miefou*}E!5SEE!ZHoL`i_dG~l;Yx^ zby^bLmWD*i+yZ3-lf-+{IMGa^+TXmn8T|8l0{*E;%s)_lD=84(W5#pA=1uocWeCGS zvR%91@z3uWJCi4GqN!JX=JrpG8A1L~=iB$nKefG2GFJF<8(5(u+VHRfdYsy-CnknS z`X6e}cGL$B&c1(9^O1jB%a|MaTAtx6`SIn%$Xj2(ofza;pE%QoJ&W%{{jh{HVN>$w z?lb*xRlQq3jJf(hp&vG%nv5y7{0mI6dw7s3(!V%iFf?Sx%4wP@;wp%|6zd`GpFyHU zlVWy})fkjAH7e~2C0sc7?9vbOZRzq^nuEVj!XP1qF*OA}nDss)f$iMw$ z?_``Z-vXz+ex;97{Bws@z~f*|VTWLTxLI2M+`3~Wbw@5Dq8gnwta)!W&Iqx%`M1aA z!?wV}VHB1SSYM=t`vcwbQmhy{-Vp)&S1d*TppD3PV|BVMC8fS|I2zVJAivUg4Xpm)TYq=^Yj%%nX@^%*c8{LOU%xhGY;8wo3E-!S%^%&-z5n zw(2=L`G@&jk|mRn+cXyWaPj9m-)a8D`UH0*sdUb+=iMbRl{R1MyT=Yrv6dc)%tctM z2oED$22GYJZRlPuXFX%!L@oBdLmaZZPc;ruh(0`T$ir$=Jg%3zh_^_Mi-74KQKYmDaX}$>P~M{d64QT?DdMBQF$t~D*02s`9}0iP#wVNo zUwsvli=H;=ez|uf((dMz_lpH)n1$ja z6v8ltLcnS`>8x_q@5iHtO)*4V9MnxqsM`XmwVvJ44E7;z+bP_@ZMS^hFNylB17B-8 zTXBd|35F<@V2CLgTI~N4tZ!f7xc^=M$P!MjOsp9FU=WO}(>8Ii^n!#Y!%P%*bks8-e-u$GG zlaCVQCyjI*x$E2%WW8)?m<$s*^@#cq@}pRbb6~8%{>u$Vx;N~{OSFdK_SHzo@8s`- ztQ-`5=ATHUd2a_vgjw1f_s`Km4xfBB9kB9O4*%lCoukgo&e-e2=k!b5m&grQr*{78+?1O7 zUt)k8Vj)a1Ls^4z%UWkWfWb%mf4&p$Ipo*MwHCyPx;G`NZ6_!=b1M38?ZKgSXNoA04zqzhlARJ_dUHyB7Xe5i zcK~0HPRHxeR#J83R%Bt-x5Y%ef7ud-YP93P!w07{tPe+fe{ggf_$Sh5-J41JWRSL4Ne&`w4+ZZ>ion?$ z!_n?vwUE)Dg^uAmnP~b)N2SU6@o=BjrMPE#BRiUb5oRLMZR&;{fE_t`aTT-c*Z29W z^8*@b%SO_yh09g1)!I@n7qHim(!UdY>s!2v?uwkIkNqqkweHWm>4J+`$oCLW<$?V( zsegdm3a{w@cR-v{inVm=;Ei1%0jZ~==k*7IpHJWrqN%6iXY0j}*=ucRTVK8Oazp(* zyW933Hhn?RQRp@3i+@s&+}H-`|DOE{d~Lm5z%|bx5}M< z^hR#A1~P5yaT((Z*$@={VfAG=gQ%H%4(crQ%>)eDb=EcL5%lNygiCW9|InlyC11tt zBeWF%L5GHu#^9_$S>Y)KSZzeokJ<)eSFg7IHV|=u(T<0)Mc#$F75s0KGDAI%4_EZR z2Al%$N`3oqbbMaVwbo-oxbbPY>KyV@(a_@7HVe^yNLO8rG~5ZHRoqaGnDP>^D-*>ua(E` zNjVJZyv%xRDUQ#Suhut+5ui(B^px|mmk-S4P>R`Q&DSbdlgby|;RNIh{(HkR8svt7 zL7WV0XPujg#X%zS_fX^V7n-E~`{)=`n}YtsZT*h?_?4G}4CQ6nZ9BN<(8{++KKd}g|C`S<#1kC|4-ammLIt=v@ea8^y}AsSSugm7CSC^U zA~#1{M=)>#g>lUXZ~n|y$zr3aH%jemtlvq+Or>`*QE^p#AhObr7n_&qRWUGVwELt3!I(_4z1r%Q2UZ2>cq-*K5=W?t;gFJ%bv_XA|1KEIX+qaXuq4Ow|;>=DAym- z|DotVgx9&dUgQ)859Awd;TkWo7=-j>E&#gRI`h3X;4hWB8;`9o$=VoRHh{^&EMos< z%b5&R;v>W-$?fbMYkX~B+%#q&*>FtCY#YOw$^_m?O`o%T^hck;f}8{+`{DMmhSg3# zv#oP=KV`P7k&fz#&+e%8$qVjI)j#MWnD0;e=W3OI^n7Ogow%)5M0}3+5vtGp6))je zEXw96V+V_~jZ#c6?_msaQ4M?X9MG@`xlQx(AXgK?G|Mcyg zHG4lGAH22|-kfk+LG(hbuyJ*3Hxx&*;fq@$4i%Rv;)a$BTNEOtD<+5uRG&=HsFlr- zHQJqzYkl9~HHtT$<68!;W>0}en7E8YqT&4NRkUWjQywYzD3u-aAnY5e+P3>9S)P~%TbTWPpfbw4_!8)GscVEePO*=Bj3*D z@}lFteGf=^p$FTB8P9hI$gEn3jK|Mxf~Y}Fa}f0hYip^1Usu(`=)xVh=s{?D?V~M9 zx>RiaaSA#|BX}+=i?js$M>IQ5Tvm(U7)ya`c9i`w1d&Q|<8yw+QcUSySPc~mc~J}| zZN_v!N=D~L(h4JCG<{(P^nFn_?_a3qb){g9LA)UPb?SRYxHP;dK_K~kR^R!DM776` zfLp=3uyzFo>Fua9M=K>cc!^ssMM=hPPnw`#^xH|$4;j>NunF-`VdVPE!m5u-j|fN3 z#E`GZz&J1#j}2-KTnvM7X#vV-7WO$Vt8`s{byimWYd-Op{Pp8tFU8THFkO`XM1FZ$ zpW^4Xj4aAjAgH8L9a9d#dmX@BI-&p%uZiQ$R&qyOWtE)-MvAGv~-OK-1iQ z3+gVxEGj0mw4kqSkER~*vTq_iJkOa(^9Tl}2-HX}VyDbR$`(Pya{T0(MGX(hTsr+A z9}k7ybLsC_frsXu;qZ`3jSY>0!9Xl!w!G&6mqvMMJ&CH%v_yNae;89xpD(e|NlvLx zU5L)4lneyAsr6g(Q><~lWxaU*Ai2b+v{c#b`W7GdUZ@<&hbG1QT+6d*{9P1|92Sm1 zXrUP(`_}P{)=>R2v-r22UHv+q{Zg7v418suDO+DH;Lgj$0`8L?%aDzIHSdahXj1~l zp_F8Uzn_lJKExs$>+44Dk5K#-Qv3yxaMsrpE{GH;%$2sioP+k^H3%!lo~fToIkm9+ zVg&`%oCj=iI{Aa~R$5MhsoKqu3Q;vw%J_n6+74XftxnT~O2ed&i@**S3@^$M`CrKi zcLF;?HGF;=>5g?J{99|r9;*~aH1*fgKGxr|KR&TP8HUSpsuOv+x=t-CFGB;gu!fl? z4}+FnBOwGNK*h4+z`QemL4eLp^3YIetiNDY(~38_!eUb<4SRn zUNMAi5k7ypSA@B~8q&{^VsNuav9=ZWMvz}Uz$eJyDJRGM>n}l&V|^V#);Dc<1bJmA z@&PXIYg6AE@gHkRcRh_(Z7%&4V3*rrdJ=W8l&C5_L)?P;HTo571$rFFYtw!-?uogj zbkrzJup0g=r6sszILY42hFqeFDq)eR$=P}fMi}KCLT{Gl&R<$mcYt4OeCCR?8nkYm z7hoVVWu^#f>`f~BIRA-#*BiPY>czz8(;Uy>n!W_SHu~iv?YRnsR+2BCxP9_Ln)UUQ z?zZb6cN&uVi%~zs%-D~7C!5lpqwKpA!&RG0GT9V5>y}6Pfp1A@4k#1&3-5r|G}KUC zhINalAKJc6Y`meHNLewM7il|foGXB?+xbwM<<;0)cWM1kWXO3Zh@KgA_Qh( zt|Kt+OCib_J;dQym$DM2;mox2yY`SG_%}6oFW|1b;%=?q0GIkpv+qf7CS~9GPqO*+=#R{&$&7(5)f!Eq>WX8&${$&Gjs zmhYyqR|Ijqa4B(o1#@Zvjr4b|t4}44L$rf1fFn1Fl^wG*A2C;uEgR3y;tGJ_veFna zn{l6uwYp<6DA(2k%Fj+|1WMDYHKKh0(kI%vEQt@f-<=51jkFxDhC)lMkHkAg|J^^6 z;HvynxrxASntU3Wqj7qajkDLGlVK3v8wo9Y!6%`Ud+#d=h5v&%xNkJ`$mb8w1Jn#O zCq=+R@#XXBpnQJN#v`9yUQGh$YQlN%>SSlh36m?_>GQ**_VS zC!u|-5N#%f(w5JJ_Ei(=DGGuc)w%de)--AuINEx4hz0-Eu$ChQ2d zowLrk9$m2}qGf}%^1RDNleO&&~CR z(C}Ah_6AMqk~V0{(6kn~Z7y8>rR+N(z9KYjBE|&Tb-|YMtu4>0UN@ljU#)QY+}eWZ zkuTreIR&R7yL1^)@nHym9NL3Jc#8JQ@Ig~9&N>GbW}R*Oyk;(B=hj#YPLRRimOU=% zFwqS6cMT3ezRd%ZEdw4`lc%2_R3ocDX=1_)!PaA>k>XLi)ypmqnxQl%9+}+p-?$fC5WM|cBbNs)oU5qAmARY(R(%4 z0z?Ki!c11qUm9hl*Zi!c_~#zQKQP@!aZSg6Aa77&6F5{}PD=KF68#`t${SWhicb^TVCsKFhgd?}YfrhAGX^2E%)zjXM=hd>HDKF%@XE$}xY8~p5e`GsJ|H$Pk^+qj1~p#r(WKYjb-e)K3Sh^C%+ zx?<2UI}h!F_)qI0^{Y zC_IV0u!Aa~KNlnVp+3#kE9)^NauLH;-;OTS=I!XbqZCtFY^Hp^f<5J5w1cz!*-f5k zC-F2nemAkBtzCai!coeKp66E`oPPBD^IRhRL8+udxEBS=%W_jfl~=K7B)xLgxnQ3> zupVv?K99eF?ZAVgbwsXCV)Rz^D~Q!(1rk9D2yks~&g9_v*$-FvAH_m&Tg-|E3?FceWV-P6_MgUn-5 zHo~9d`>}6AF%l3A1dWyc)@zi9)b;pK6DPJExEI-Rk5~01&^6Y_GXwk(>+IGm0zUpB zsah@1%WV-aILhXaHx++iE*XVBLjMTTWm^AN%JJ7E`?uA2J#UI}?ZeBgHgh?C+0cc1 zQf=s7MDBp{(jI-xT-<&xBhB@;i|p=B&Z14iGpj5Oyy2>tPp|5fKkcktF|$JsyTYuYB-9s0;3;ICHadh-q1Tm7XsYU}(o^q zPu{{}P1=AlTZ^~NV$B4Ht2z_9xvgh+JA4ErXX@pp!%7SP0c&>M;f9Y)0qiBK^GWxs z=BY`)LHlY0(tQv6ZKyz5wANHqqc$D&Ti|~0J?tF9fMoZuAA{PcO9rqx&OFEZNxo>$Pa1N%yaZ(Sm*d`ViDl zl*Q)(j%Pn*9b|yEZ%dc^*N?)&I>G(xJ06v4t#%1&l>67ElhAZ>qr2<=_17`^=#7}i zpqu=f$8XOZ`9MGiaVpJZ&$E?1^E0HhaP_|-Pmq1rXQ$P4Saa6$oGAr%q?#xP1E-ZyE7nx`yV>2h5kH&oE=#d_5 z59Y3;M8={yYZ{s`labpKudh#kqmCI!WX)%`$%brqvH#uN<5#nSvCxf8uV;mh&nCde zy6^t@h{SG>XI2>VLfe-=2mkCzer{@C0vlL0vI5dipFxA*|Uicwpg zw*UPv!7Y`$KX+kS$L;o{{`Ub;c8$mx*C+SJ$JHfijqi^QR`Lh?$P-^<DH)WZH z?g?O}EVFS5Wl-tIpM(6(`?F8}mS*f@`OEnt8Gt9DeX9^{dH@Woe0M?l+piN>S`)Hd zIELz7I1XgIKq4GBav`~Neh^3BJO}yfdv^d+|4jFj$lvu08Q~<@RQda0wom?c92Ahh zXPP5_V?Ij;-&izfO+ynN_(IQ!{JHM^eq~8O{w|BTaEmY=AQ5gNf9;@I{d$ws$+Yf{ z2CxcYh?%kf2KhVbPd@n@kiL)QZ*F}u0O$RY^IsPqfC=TVqC-Ib?*7z;W8FWJ;3)Dp zU~Uk{p!_Y41TbyB{Av5MIKlka6#Fxt_!S%T6B(wRuq`$HjhN*VzgrLViyyQXB)W;S z-_BSv@OI4vcxhAi~e5_GZDQmcLiX=@G^0} zHsRDKHt5f2{(HzLe@i>>WBJRml0kS9+P4bPrU$}=^0!}{_>YfVSPtaAej+SI{+1$Q z$FE0&^4E7t0NA~jKg`u!&)EAT#{O)I{5605_XnQ*-%2H(!&av=Bclh1#M42r8uJ@VIgVtibiC4Ys< z{Vx)IoW%dqa&P=EAKdGcza4EI`P&=+%b53)!8aDoS<}#j2R`w?xG!EFH8)^_7H@XJ zHuXk5B#vwAshOh^uM_8HQqKSAb%S-xM1tRz=T9WB{Io_N_v+=>agI{Qad>K>kAOT|f?Glt3aN)%p)HNq$8d zl)t{W2S9DU{N*Q~|9F2_vi(11b!x8v<->?i{Jw1A7r$otU&d}s23{#zvueq+L*H~kRx=|BWFmW=pj7>kiTh=GSpX%vUzp!4@!UrT%+F~4yUQnk15);} z{LNjT48nQUoc|hDdLc|GfBP{++Bg5Lb%9yO9rC2|H{hWlm_hklJT8E2^X2dV%ldDM zPXNdKxYCXa+Z+GOjyIFRw{tS*KQ!TyKn zAE*DG_1`3){4M>Sc|Cc~f6 z{8!*0(6CtS9e~4J}BN%7?`*i@! z=Ffl3Baic2iS{45H6nkhe9rhY=aShZ@;BNOhBjoPTmEkT#*sfY2YT_tV7ZKRB4FNHx za7o*lv0DSO_w%wp=iTX(zoonOvHa!W0Eqx&&eTC&I{}0zp?#|mZThhzRzdmuutA{+ zo;Gnzp_MKa2Trw7Of>)11W^piU*AyyK$|ar>i*|t<=p?np(Olc^2bS}xhxMO{qtt= zP)Y9r^1NGd{!B^90uyTvQZTeX*&59_UsnD7`VRQ9qDH_+U{?RGR^ zO-I!RH$0^nV-qKjoltS0k@P+HaCBW8*5TH*vuE=7NcuVWP{(H^-<=3Q4=5oFE^M{r zY6aoa(lZ<5W0w=-c1#)6PR^$c;l{htvt>|m<&yeM{e@%8$gcruR{Rn#SXfg0X_h)96W7%DR!2a3z6r2XKn4Ac(v!oRCL4K6pf(*z*{hCw~LJ^vIuni}CctPNLz5=U1ELD3B2Q;C6!i zD05f(aP-LEyz!j>b~rc+Z~*HM4+>Zh;scsg+NSZRZ(kk4Rf$NbjnU*~#0ZyKwZZxE zRO?yppeuyb`DLEeGbfp4COj2!O9~^}Z)xP344))g^G9m%c&H|gECT7k65nNq=Gdr8 zXodWv@U2q#0u@jEC)<$Jrj-&P>P6O-|K>D}?{IR1;zyluh!wa{PMZJbb|1c1Z};HK z02&=+EA%vxwhqL@B|a1fJrdx%dU-N@*Zv0he)dHW-)CnCzKigo@dYpWqJ5`}FnXd5 zAAS)i+xd;&(@65^08i!6~03izL2fB@fAn#agzO|4jNxbebeLX ze^=%hHWFWd&*#Kbo%-6F^?m1;lEHT%nzK$o6GqL7cw!z%J#tAQMwh;*+t~)cqA>C- zx8!yeBm{#p6XfT$t_kvpDjTt&nX?j041NBzIst6f;n&3nD>l*v(a%Tz){gVZ-}~G4 zvHTU)B?It6v~S&vHvIsmU%RLfvth??53vCZ3SgIa6`EjigJ$LnE;KLZ_IpzKTRS-c zkj`@78ayICq%I}vlRuuX+phAH*HelnZj*yNNJK7rGO9l@=W!OL{;ZYHnUZ*0^4otW|rHI7Rn>5)a=g7+0VWDew-H2c8Se} z!;xcJFh9gM%^;j`j>%N*QgFwp%-E5?>uE-A$_l$Ki)~#0<4_b7&5i) zqxiJiELDue_%LHDL#7>@t2G-s+-_*7x=D=6AY-8@gMS`u^HP|~U>CPu(2U9@VL0er zXb$^G<^kO3CkJWBCN3kAFsHoVVN_X@p*k8-g& zs@f?CNTT91VS9HCN5}$sNO)fxn$!yQ68ww?0l!~3IvVNOd45}6eZl)aai0Y4ce)kG zOtuUQusR!mK))Ys>u~jQ7xYxnu%<>^2fUC>dvsyFC))LbKz1&B*XqdnC(mesydOkTCBq%{+8w!pQl>nscvVq_=6ggM^UXHr@>UKzi0 z_4hkgqw|;R{BUcY2TpK)nCFFG7T(jRa`!6+vu?!siEei-YsjnoI#hWdA4k$7)3^-k zJry6c@F?$0bzjJg_r+<2(W@H@`@A2T6qU*(5yb@RICCf$xm=L6=-STU!|%tJl%hQH zEq*xmIx2A}MZwafT~2-P*PQa0vZ}PN`ZbQ+h|3?m7-imi07FNHCqml*H9~SU>jty4v5+CQ5xpmbQ=!8{@hRwW(rzUw# z3B|@)B0f_=q9DhT=@o}=w?2Ru4WO_|xL|UAW5sB_wOHvllGB+Xe|*Np`X_OBUggXV8`Y`Z=6$T6?qK{`qiU+dqqZ zd;qANIqO2SZ{3VG4IjkSU}n{0jo1;;WG6oDf^!7-wzlX zsuJ=!! z#)sHGz{YHOU;@JaggJM(-M{7Wn}t4Di`=k|M>Ey~sNKMdd}iuW({hZ=C>p{lBZmnl zBZmT#kwes#%)$^_Z=Jv+j-dWXM}|*Z-~#;?Zu2Y9gKL&rZi{S#lqa5=;eWzMhu{Vqt;j)R+Pn zg~C0fp~K4Y3x;9edO1_V*KUT)&Qv{*>RY6usbBvJd7kdsysV*Tt(t-%zN`@bJ-EC& zZg{IT65YMQ8!iXKGkP`@*XaX7i{8icv2F7kR^cv`TQdr9ZOH31p)j!u;U+F49eGDh zLG_E){NDhlXr;Q3>2F(Llw;!0vs+_lY0hJDpvvg}BMn%nauOaEMqoqXDgzkiTr>5h zs25YwQtgNy#8gBJegEsgryr9l$gRUv4X}AksTWnFP|M}=ma$L5OSiT{g)LEizm^sK z|MmnKwOv7VhnBH0n8O-};D^}h_>1>DDSZad`D)UC{QVdTmH^SziKU08Sfd(VYmnQU z7NP<9VaAhV#;F86XzXdZnbTAefPu4)B695amW8P?BkmcH98g zG`ztq-YYo1@7nW5RJ?UjQfC;e1OG zLcfjgtA#My{jS#Un5M$fCGz_7U?rr&*>2q~#h6g10q_yAKI=nwV~-DH#|*a;sm)?I zIe~A%#eldztl|rksEF7e$>ZUy2)ut$Kh(nJQ~DvjCs4r^ZDe!khlTuvevnVd;7a*@ zL6#+-OR~1&v*+6SR{7B)q?TD9npXEq2=%189FA;tcgeQxJn91V1>$lIKCZjvR2lmW-^T{<^p++bslo9xME-PfE;cTirs7d>+L)ooH> zOvrZBmV)YfeYsQY2{jFc)cSkJSY&>jnYEQ|xXjHDK@;K6jb=tNWh%3Zr0)x~o`yw& zca_yLQ%C}4|0^%rg?zCq*1?ovD4MFRM{^*$5b{OB|AS!-XVbhDgANw{-DktCxX?(o zQ;$4z^ioArFF=p@vTB`qx7fcS>>tD*3mwy;H}pjr+~11TW~Zb?E@Fbq0-fs(Mqlb# z!#O(m9}4=^g{tlaT(q>QK#Ds0Ks6@-wOoO~p0T0i@zW+(I`f za&1-t#y?=<_q#uxIVCh1x6|=U*+~cGhbEuhR&JTb`0&%QZdnB#g)y%=xP84b z!xX+i?*=qZzUNB?z>RGI6Xb0gQphY@!;WK0ONGx25Y*N0$KvK;9vem|H*ipnRbxkd*{`7E9)x&NQbELF?bE*!1Y^p~5ZHlVAgq7cg%7IbM zOC`suOKY#M!PmZ>J~=*AxefT>i-27v`4cr*7~qDhWq_e7-gr#KAwX5t;xZa7G*}1O z;s;1w==7(46Y!&{Z(Qj^XF2wV-=uy>FJTj=GPEFXR2xaGKPf+wn~43N-ydDKcHWNI zO5|T;J=JgIbMyQ~@OLcbNDwrd-bLzH>=%=rd}nyYukHnY`*BlVcJwCnPp?kp(Zed zO;aeD^|p85A5B;CEw=QNuEE1#EQN(* zWHAxj^dsBMV4cy_8AF}HVvWgAibvK8*ZdZ(*ma@b@`A%Py#_SGHS|9yzUjr94By0F zp@2uzuezX3O6+i~IWWq{YTwH(y~ZW=e_quZ_BG``uQ|f`$}5I%wEkC3eN}{}o`ya` zQzUQcrLLwn;Gqz5Ittj0gb-0YGnzd=}uZf+h+I(xp zt$6_u|I|waBUJU&UII8p0l49c0DvE@76ALR1;Y#&i@e|fn7ea8D6OqTZYCJ$3z=xb zdU^wh8cqM=)f4|M(3V{*U*1hc7QU!|&CY)&u`OM0}&^3s93Y z^!Ay8^q-`9rS$4AagFZm^M#>Gkp^4OSfS?|VJ7R|Qk#+HKn1grfkx_e@;L%r#RK^j-?j)% zd!##Nxd!+drph{@=c?Fd{DL0;(5X{OY(X1gjZead6@@Cl1LN3li+v(2Q}qUZck#zE zylBhkSX4mTDYIl1)wBU9(fo1>{S(Xq+xJo*O3SVAt3u7I(S%(Q{1l@>J-srh?}sg< zRo|Y)MO*5T4;H56NBS6^<23BC_`j9yne+o#ojt?+>QFWQj%-7lC39MPhWP#gp_Jy& zFaLPkJHMo;hVDm0vGdRX1hRkbyVqz3m!t6JUj~@z_;OFy*Vi;h-PIDJXlm@@07buk zStxow+c408=j8>5s3+x*XvE0tG)9zN8`R?{yI(-(fR(&#nieYd2mv`~W<>aWupt+deKhPKDy39Ap=)sJXQoemsrS3gWu z-;&@6t?rBMP}^=o@V|OSmu*3v({(i>97(VPJ#7A)_WoUH!%pxVoOgN4vtq<&3ki5GSVz3~kh zUh~%PBWyc9HtQg1;>jr>@g|HEGFjBBe01pu7nr?Z&rn00VQUE9L2@g+^@;sDV!w|^ zW@LqDthZ_>wxo4R{Vm%6jG`gJ@)TRnOCwtVGz+w=cG#0$2#S>kqE;v+vY7QWztY55WOfZ}UAYu?{L z;Ar}JtkuPz!@CHvdr4!OKR*b0##+2f;W^OYiPL2J*EG5+68qJ9$njI`I#8Ng_3N~h z*qz=creDpQzc-ZTnzy2Rq)ZLuKAz7 zJ@GctK$g`+Q|HIsl)7l@LDD<7;3w$Fj5C)!iCcJQyClE`<`Siy~@oc<*qtgwY298 z)aDE)axP|^0q*&uV(e{y@Tit4PpJ_%%O8KyJiFo7I>`_RfN(XjHit>y_!>=r{#Ve@CGAAROeyO7c4%@3EH^OoR$|l=-++$Yd)e4mLX+u(!IwiDu76%# z@?_7??K}0r9+=Pnn}r7K`FU^GA0n>s|DGMt36Crho$!2^qcT%8Hh9r#*DT#DKlDO! zs}cF_uMznwK~0W)z0yHA;IO`!TL!n4fs+azE^mp4;{Od*9g89^j1o>TYNsNfEoy{P zV#8Ha3r=(Ne{3^sC>K~|%l3kw2R>`~AofFh8O;S~B8CIHetai%9kD)$AL#LKkZW% zN;@-+f6q{VXY%hy@i(jBbFz62J~>UX4EAu@R?ADU&zykO0#Z*#G}u7 z?2^;Np1I(U;c(OXo?a`Tqb9 zwftwHh)ez()zOou8Yp1@siy8nZ3c_jo3L5T7j$D|9>(vslS9umW?@!cWpqrefyyMB zelo{0UKv9rC*QF>G-(pJh4$mtj!*3j;P=%R|GjRzOIDEs3NsY)n^hy>Xi z+o8&L(RHzu-S%sOEpD-2Ej89{X9Rfl+oxo#_p&Y5TqQ5aSmk0RHGkS}>tv?#N)7_? zY{90csiuzhH6<@dQ?{vGKMJ#y-CBZy4d8~yRyD8#1Ffm`WjEF2g73YflecUnX_(&z z%>q7*NI_+ta)17PR1bJQ{PyTrX|W5M9;e&(6<9#2%SdBvKW(VZ_H9*j6X-1Y4H_WN zmtO5^;2Jzp`?pt^`gQCM7rt2Z9zIMKy+`09ky6F}+jkEdS&mJo8i=O1^ZHF5{0@|f zrq6#CtR78&^(62|H2tjMiT$F)g$p%B-yyYj{k=uaq#tr2JG6hp8kwINfB6tf%b^bW zoS9XIPjw4wfgK!n(H4Y|zJ7}e0jm5ZSqR|-+4{{ezW1!{xw+>m>#pkyLDm$qIkw_u1_VXgH4n4Yj%l zquER}bwNLm+=Q!t)bWjr=RtbVyp+=%E7=NE735G=Ri!Et?UIAY1}h6e<>2tCs)rMQ zla`XwBIQn8Sex4N0+27-eZTQ?zpeGq-@!7N1f>#;Xsh&GRYv}-RsHL-vYk+Y+Jx1T z#H7D9{$@?mM@T1LEXs?FuQkGzI4-R>12NmOwP@zp+j$(h3@Ms^YajFhv&`9SmBX`d zN{&ByTJKM`IrAYIM*4}Y!qmvvam9+H7q?~;bniE|MHRb9N>!@(WUyxjx}n)}C$4lS zTZY*)7hC4?6*R!2)(N*Nwv<9%w(Jy#ErG9>GsAH>v#VI<_UxrN)5@B=S8N%*M6;#z z(6Hr!V9T2Z3tNsVOT+n7$rG0#UNd^+%2O4$C|1>?1hbGL63cmuB+xOh6PJ;FaWqHO zMRBx1FNCaCvJRe3`Idlf<(pr>iJ)bDp5O{r zIB)~zk7*-)^GBwBGY_q3K|S{>C8)W4YGaw%pZMkNH~A6t0u6LRImdpg$lhT8b#GUuD56OjF7AN2gi+bZ+wx$ z!;-c^CT=a)mDf1gFVEF6WW_~P-+bHJJy8@rmPfG}nB-jZ2ll(|`QxOM(Fe>QvP)4$ z7_hx17L~U;@&FsN9!9ll$%V_~v42m?$W-T@JQDW}_oF>yYN2Y#LB)m93xJ3^yn*|F z*WFQqJ@1kmaZN2wrhIcNZa`j&U?{MAF*->imdns_Btt$S!aSzZqnFs9R^P`-N63+k zNEISI`I2eTw07q5Rw>8TBbIY1Pnj<*M5GVy9}eB!?|U3jP(m9`{n!0)>p?j==ht&6 z$7QB*>W{yHme$h8sG@L22KE8oVI!*08)zqESh)I2+9#Q~@w=eff}LlLKI>(5hw2XN zI{XPU2$Eo3fj?^!9=?zhdDi;OBquP`b*lHh-q7GZdLiF<{%%}%oV`rrNhX}n!9Uig zVlwh;#j>}DnSc4H<{J8{xwf6^8ST*KacO{^8H+%h$-e-$|4*4Ryd z@#kp&!L!p+o(Huc#41zn|^@eVF?FO8@U4pD*=)A|I~$x2WIW_5Z$0 z{r_~LS|Mxc*JwYu+Zn9exm~^SC;bM#nKxJ-Y@qtZ@psd& z^ir>k(yySS?pK_l)W4&KvYjjyN$;o2W9b*a{9;}HpQ?NZT|PBY`G_umqbmQ-Ks9JM zOybu+M3+BWm7k-_Ba+NrzN;Csb*wJ`5eg`zh!D=bSx+`V`mi=C2}f(n@iZjohbHdf zX8*Vga29VuR<<=~2&Thm$47c#GJqP$ru;F4v*ov)Qx@m2&M1C;0iD6~AF=-K)?p1a z9r7U5Eo7e@4Zy{$^G#JR+@jP)ooZ;palVFr_z?~D^fzQJXrG`NY1P}-LK4&W6Y=o< zL`Z!?tiJzX}ppuyDn)OrE}+U$lRU^?5na zg-wWl1?bd^N#N}qX5lTB@HV9pGE=bZnjUUY7LkK~0GCK&i z^!s)xi2o)ZqkM1S@Zls1iWFqYUw8uvOHj7-LAd&(L$iik=Us~O@_zpDAb6Cim~b4~ z)r&5s7ieuX+bvrTa|eiF0>3|tF7_$iQ+5qmDXrB z2Mr@H6Q4@{tB{&ynLO2pexe<6*y}vHA!_9THa7U#=Vit|52Ag*yd;Q%M!^k|$cYBq zt*fv=iO!}Gz$ZA`jxtC}BdQoKL{`~nWoU9ob^*uvPz|OS*bw1kR_Eh1vvcaH=}TSg}MrJSiox*4RE; zgo%^7;ux5BzxyM)3QEzWX75l7c68*6uK!W_0@o+2?DKLsRPZuw^0xAIV@W&lKlP=h zXR}jD)@ax6%^;4{=B`--GMa6V_2 zB9jzYQ7I=xP!>x|#bhi+jh>6CrDUvP|B2u7*W21G;s-L2RoA^B#gOwWntCp4UuBIT z`Q<$(U=^Xcm<)v@?$)OR*-MRrG>k8hD&1#%LBacl$Lo76Pr>$XqH>LCnP%`Cc8z*bQ zLnJ2-kMpe+XXl_GKXXa(;z!JQ4TRW-xsakb(G}U=!w$=D`Xj9&6tU{d8$HJU@Df(ov^mmSOzR_ z0icSo*viYT=s!Yw)ViQLoQ)Kzr}Rb-Kz312ZjfqR^#A@e2OlX|y&U$TBVYYbH~6#< zSAQCgYHjBfIMfuV-URy+&52fw!u#Z^QQ4Bn`PJc^{OV#1 zWyUQeZtMK&ylfXy>rP^CG`7ekhgYBpec!?DZK;&ftTzu}aejqNq{Ut`at^6RiQ}@u zQU0$d3x|i@$73(S)zoTic@F2*baUQ`boJl@c1975KSsZ^*U!U zq?iDHdE^t-p}{Te8D;4wt@5i|<>W{EfgE?Xt>}O4DDq63{OX}OZNdNRd!lRh2%vUs zgkAj~hG{~q6PR^M|4{D<4}%B<#+sJKBEC5TfhY;hOPN2$9Ru2CvL$6-F6J^%pTD*i zb1N4uy39iBXlVw_iul6kckf zb&FHaWK&NQ`{%D8TH3CEu^bBWjsM@QUzQo_e7iLyPW>x7X*x8q|G)Cmml`F922U>Z zBWC3jogWsfrmc^$9-^j!orYr81Hb0d!3=V-o4$*sqsrZ7L^~wXWmK4fSgb?Dl6|{JC<&@@2+hU9i3n_RpG( zx`dCKNIy(<9^VlLnQ0wSXbkm@-C-_X)P059jc4^RZOFLmpRs%F{UdJw(Pj33>o3s% zAsCE9dZDkiqC>O#ADXm>6?$YCZlQHZ2m}Au9{9iH*iN+LiRaS)wZ*I#>oB^mJR<=$WEMZm8EJ-^b)Xm}70kMcYe zqD|o}I<37X91_oGrO`f*;nKv!+E3@#^vl2MLWuUEwU{QG-L}H#Xwys+`HS)i`)w5G zW&Y!=MVPTlXnrx9!IHjLd0BRwk`vfYMz|rbnB0{|sS1;!bFB`?8b1iXXW;zKxk_|1 zF{5Y4ce|GDuc_jQXgD$YcPu8$?v65WTFWxEHJZMD&3%E6d&}O|q87P7IFIm7jVmSu9b0YGuz% z(Sy~4=lW(d-a;`SW#2b6!?x}-2%(SKrYeo9KoK=^V;pCC@BLDehi zUha4`9v~e48h%u-pg5IDl*TLC&}#v&mi%fulOHL{Mu*^fLyj7zGzERs`RZSh=dmI! zml28chnc{*enbjOTx3#y+ISp{sra$QZ_h1=!t8{Z$+gt!htT_p?fv!EMR)6?>7X;K zA^S=;T9SbY7>Co9!rgH6b9t+iB`egIQ1Lj|U4K!q>JKyQs&`M@o2t)?_S&CAfY;`m zu_sHaab}K$%wJ5GRqF510QSJG2T?ouc{Dpt@G)qsZ+{m#b&yBV^5NYlpFjfby zHBlx{)4K=@o{L$mD6OLZ;H$|SIG94GS#?{iricr^SfxifJTaiWtT?44wPtx5CsxNDi*wFRiL}do z`?np`^rLr)D#|iaN|08)W41iU0sE2+*~*RNWrid98DuWA3nQkE^OYS<)Dp3g?VftLt0oS zEj+L2f3lZ9O#O({AdfJQE)qjVF3gC}86qme8rERbl+RMApTU-Mq~*t@<-aQSRPCP` zzkSHC!>Hm>){F`b`)#=To5s2$oN6s)I^UjqIpHv9qUw&vgO z;g3Ofe+Y7#SGui9DQ=qigt|T=Y^4030_pFiOZPZbbN&+fq5grwF}9K6uPaD_B1+H! z;Ry1h{!;Z&*(=tcvkk@K_3)zx+?7nRiKlkztJ%X`%3ovsL(jlwqcA(-jp3$ez1XQ^ z5Dc3omkro1_^!VsU2ewC$ROx?=#k;Dtwz>aUmuOWvdz)b9`2Na_%0?DXg{r1`%71F zlApM3E+=O=Z^amjs!!c+sOm~F1hfYTP9o*djO&`Jq=H0EcIOVo9H)1mLY1HL89Zm0 z8F5>JUFLGwM#=|-(TKCDkBDIb;;hq0$#SKT$f zEWVFuL>j`H14iNH1Q@bBQ5K! zvZFMo07=`vt@}YS$Vf8CXl3928f&=%kbEItGx=|!ZbMboctFfz<^I)PeE#@#JlEyS zESvr%XKCK4anXLu(dxM<0Oi!|1^%+Jc}_of_)6xdBR#A&Nm#4g7BKD)Sm?B3v95~6 z=wBv_$vy$b%TJrddT17FOLHCor|}bXr|aIc!QrR>5}7+?cQaJ^xG>KW?ay_y*w=;) zl@EP23p#_`Xg`I)@e1a@@gG3y(R_|H4_~_Ny7ad{%e-oLc7e|PXp``EQv@s`gP*vJ zw5YQ#$qKTF)NeiXU64=yuK9!{p+JYKkSszm$csJ(iOV0Ms%bK6?dArNw+gu?(C|&@ zUmkjd!$0T6;h$MY>gQl`m|_L6vEp#iZKjl?or-(7StwLB0`m#ki25^F(-fNU%x}Ttex1XZ46_;>* z?}$!6gy4z(Qzg`0N3Q3082N;JWC(GQ4%_v7n0XH25acES z46r6814kPf_=QUbT=5f+a3t~LCv4_;jAh^wvE*~A+9AVSd%a?1?8q5lw0?H=f0mIC zDi&;%`}M;e_H(Kh>j-!=I8_L-%~p9~rXFfrF)GA#wPt+dwk6aOFH3B$If9!S{#jaT zV*T)kOaES*HCqYC95w!}GPF5*hf96h<6k5XXUe!$|1tQ{GDq(w3Cfa<-$;)de_3Gs z_H(4|CJB(K9Q*H|DKZE*PF%*`)mdjB79@kR;HQ2apoLhXu>&r76A^1->npjp+(i9gnhNsg4-%b<`O)s-0u?0W zba9g@0=|^NPh3V?)LBn;HzMemFdTfjbPZA9__Vfv6_~2R5nTpb_bd~`$y70MNFrnZ zhN|Wm(fx}{bZ!0q6X7$VTT}6wPg9VVUR->p+fUv2AdH-Z&lA>&i_b9gUSfPsGe!LP zq#xP@e2RAdXYfI$X|MbU>p*_Q&Vzl&Pg{OYBn6;iY1dVYxQMuUXX5P$iX(-wzlZaO z&ymYO6*bwqb+B75x*PdYsIagne&UBi4Qj-t8pj)D|3gx{E>TCq7%Sn@aNhatIrBbx zqPo05A0)Hwy9Z4X;3I>dxQw)@vr4-L@yVN_WW!pxBY;cjY4xlo_K+4Bwy5+P5^!kq z2>pv8bBd$weaa1Asoz%n@e%z5eAFn^r;X3~8lOzjXE1yny|$2#)YM-I>iX#0FC&ip zP#xn)kypQsHIk-~Vi}iyyTpEK%MbGHF1N-&50DGO(hCuxJokIu&3h=Ldb&WBb@baF z3GmcQG**Kp8b0c*w=#nG`1Mp5D3H5eBBHyS_oNa6P<4}SOjZ19^P z0eQalQ(XM!Yw6Vb&xhZ1`>789e#6XriSawl6oGsR^BVlp4{ip2;m?0s{G9d4 zox*d;*C$L=M>fxpPtW>fQx}(n9k0thD$?U#;dU{Cn7|PK>R??>B=xC5g(=pI;~0Tz z94-j!iQr%sYsKU}gP(og7%SVHd05xn^v8A(I>fy)ScvQ6(m1XbUPmKwv3Ns;2~ilr zaIqjP;FwRlp@t48V+o1>87*{5SUfFor=HAcp^*#^00m@ZP|5B^Layn%O`*U#Bi$4M zle86r>vhETE`~|0v$km#hz-&5NpdUsywf9}V;Yyw=HdHWjawXi_ehYOmcYdL_A-K+ z0N*a=dG$u*ANpnE;GRZDHo=`X(*>@YA0HaqTzvCC_Tzi$*&ckSaKAnQzQqVPRf|X? z0Ren_n<9RE(+)KFijk`NKjdF-VUHEK;CAfKQ5y2t2tV4KKlk3g340A3+qAI%aQolB zm#8zJ{?#UrYkEAzC;`XJaXrnjpK9f6J@~kqHgkpVyarC5d;Z*VphJ3P83gQ`MW%?~ zzM0~ZM57Fh^y1gm;1!N`HAouDp7Hb;`4wJ;<)&f*-s5VT{|cTW25-= zH?LB31k3< z*a#B!hfDNknfHLtLXD47;pu-)$F}`B<>Q2SaT=Gh`_lgW ziTwB9OVpVUKk<%vysxJiF;w8G0`>|l!+uKeXrJ&tEFh9&P_uQf%nvU7wn(HW+DB-)Yixxbyoz| z*C|+{+3U9vEQ9s69Fd1>zntqg3`y;yc)a`G_3Z=+qto>NjP@Gd5`Tq<{!be*i=;kr zAR`LW=ki0L!Qw6g=egzM4)Y?D#33MT9p%UB%Y2eH#l6#$w}1W3`zXCtx`#M-8LW+d zS62}=-UX_t1K~Fkdx}v4LedQolALwc+WmtNGXCL%AbvM!BZ5sRn=xVxh~N1Ph@Wu% zy+k7BeDV`t{~1Y(um9|)Uj4UYY4Y{=Eb|`lNu>Wwk%0bd7bL#1AA@s$o#Tpf92oTuf7JI0Z~ra#&4eCz8)C5@@O< zgL8<9c(fL_34&wo_g(;m*c)0d*pz4gI%dR!rkck|Mfqr+e^;qw?SIF(=91K2@8LX& zi9;BK#6Kzj;m!~eUcMt#)#{^qxz|6x#mJA6imfQ?@gF{CKc`$EN4l!ddV8mm3sIFI zu-k*^(SPQByVC*x`xT}L@O@xS+O9fUweRE}O+w`~bvA>HG{81l#29(Sdzp4Vtl z|2D;cxXYx_+EVax6$&E0H5ymbK-+c?5aNN@~@kQ&lV$p ziSb!vium!F-YSTXjEE3e8#V{2S_bh+IKO0X3c&RroL_!2|NKk|nrjMv>m=qACF9x$PuWks z_^tUWIevGT_Y&iGg(>34uXl@P;5TyP|0I6z{K#Q71-}E0q{hW>mjrVXT`zu}^-3wx z`t~{VUSj+nG)4UQl{VC=km8Yv_mA!M?W61eC-FN}BL13!-$h1JXMMa(LU7z-oNIi}3Yna+uS}g?J zyEEgA7%Om90eb~oY@Q;vOnQbrm?E|e$By(2jveV4j_r?R4^d8fW`x-~SF^!z=_kxl z*AiooVL^Kw3)EeL&iZ(RDFPNC-LMKEIqR%>-!+{DNIxzDc+vK3`J5@cIo4}yo6H(a zekXNcgi=RD)e&o_4O#+${Cf<4JWgA*u^#v%u)g?-{KNgejiaB%qV@Ps#(l4gDg0Fd z2Y>si7H;b_nCs-EM*YLx&8sNnDp0>F6JfA(`iW8z0PFG~!MS3lfg-cO9r6{d(EpWeHJ_*}2! zudK2+0{DcU*@y8XdoMo;@kx^~zUJZ6-^iCEI39eu+t1zj3|Y}se6~nzshS@X$j>5E z#E;MPuY>p)c;0?301uRUIn*N7xBDW#XYcW8*8b#B3GegSFG2nGfEGQyc<|}BGW)5~ zZ<}}@T2u5}fAeZ$`RQtk`0?5GRS+Mu{7TH_1i4-eqwxXH%0vTT(UEWj~yR3UkU$I`b{}a1OCTNrU>wvt?UD8 zLd5^>2;yVp$N1;1?JEN~896e3`Mrw&{fYcr6TZ;$LI1mn&yKr)GG9wyeE-OF`>BnO z#4ld(w1Oz?K$Pdkb(nb%@{_>7b($#xd}N9;`^V|q8^_09Ux!yTiqn5%{Nj?&nu^~} z3E+ezDET7BF8O-Pe(J?3#IK)3+WF?UxcYOfk<_^O zU1C4=;&)FY`_J9Ydx_<5kA!`qi+=px`d2gXYy0B=Bz_YlOs^^U%{P)77r*KDQ!jpF z<~K6`nfDUocbX~U$1gqB4E(~iKOKH?&)=5DJ)iykC$|2Jdp^6rkuQY(;+$?TIUnnq zx4N6>5p(Vz>r3mqPeB>y=zqNP**}qeb*MAGM(nGLVww_h`K!16)XQH_Y7;n-e*eMn zcVhn9WQzFt>#0wg!C%&MKOKKHKYn7b*DpgqviZ}&k86{_`sF?eD1|0b__2(OPfP8m zHhwFt1r?31U;3N(fM0_3OIK3__<7bZyFO|hKPzWRqqzN?*Dp&XQmrZad#41D+W7eG zU;C+zkE~xhPfxDDXPNgB%h&Cuh+n=g`LJ<(?Dfl(MUCRL&(<%^(BJ*ux8~ORn zbF;YP`|r^5vwRRP%?cYO?h*`Jz-$GM_`|**G^)S%h5y2HZrP3y^Z18`O4yx`zv9ck z#Jt-4<(Gf^sm))I|Ek92-@KPZ{!Nj9{BLcXzpR{vjq=rA$^X8<|FiY8wV+X) z_L+YE_u{MBUV|6d-b10@%i*$T>S1ck{B1iQv0bFzbDrv$FIM6FEM^y zO%XqSyEZoizwG({E%?y|ozqnOX1?82`CIpnE*TfUr|hR*{5rpx9KSovdx`P8!W8l2 z*Lzbl@EiH$Pm3S(|Ec(!+hxySTU&l0zd(w3y49y0e`C%!r^!Rl`Q|+vTnJ^$a~#Ey z)q^{Nrk4>!*idX|DxjqbqJCfy0b2)3m)~lRFMuu8sLQb7|HBY?C#RpI3 zs*|qr7>YrPtCP$+Puvt%AcvS!D<9_}*H*4W%wyW~kZUK@nc1!o&v=#@89-AHz&C3; zx9EZUY}SAn@w_jQ!Sj{apGqd znIfRSCw^x7dPDzUe51ATpBfP-)t}iH`?>BfkA72O(VYF|Sw?ytU_A5Z9rklVW8!D} z>Rqv1p}6<-gm-_rzj+_>kpQ2rridS(U2g{QvEyfQ=LGQixyR3}UfXLcV5%{+h}~ofkx8e+V8to>v~McbV0R>&v-1k{r;SJ5BMb5AAZmj0X`yPCO)I| z^&mb*egf;~M;{5`W#q}k(fmx-&&^tY9V%gVKK&PW{d|#@&iL^ez3r!31#0}(XhSb- zED2wJh96$nxF^PMlPTiI@2OXtfuHr4|4ICYzO3ojsQle$BsH%5mD*3e`1PEZT>ko- z_Y&jR)fDmLx9jC*;Fta9|4IC2u52oP>t4|%P60SWT}vx z<$3H5GW}t5)LJ3@D;F){;%jylnJ!R3_ZweO@P29D&RH(SbpO~zPygU3EDO7-YwvKn z)<+ZSG<{TQeb=zFetOQxAK>CqJo@p2KOM52EWQ$~wa!M~u->_NiEP-G#nM z3|FzOm{3EC_z!9rt^^;|jO@9#em~r07VfhqG;IkA7erdE3r9xdIKbuJcGC%(e zrF?rS$fE@IQ&^IFE3E}`yCP9Baxd}f~@%heDlFtjB+>!&P2?*~#&DmkZk9lyu4Pqq>gzUl3y`03TQV z$fWW>Uo3;RcC$NZX_RT{5fs(>RhsK1%^hu;v*o15)$oa)hDW;^zKjj8y;e1h2hN2z zvX1~3CO54)bAPCI>&9Owg+7CQg2J4QPyR<%0SoC{5Yg$jBseHj%tfcFs06op)`HnE zzPxZlEnmS?{2K1FJrsS9wSXph;YbGv6>iHztBX6LZIA<2%?LF#yso!IA~RJ!BRB#dWvkSq*wF#=rv7Wd{^$jF zbR@snW*P2ORScAoVcYp>F{Th4%pn;N&jLRd4K&=;QiLZ`})o! zP17xBQc1sJrFU0Eoy%j|-Ibze6=Yvso!>e_6KAX^B_+5eAt-FlnAK?5rW$Hai* zHUqe*)4x{pH&ozOl)>R$$_nlmnvUMhkFNohe(J~Rs$v^@HHtfC{0C@2Nr`pBi$fws znZz0zadfuaOV+cYzK6(dxIylYM7Ajw2I43qZ!ncq4K7c-<79PHSfte+>*gW6O|xV< z%i->++cQ%_RXH3kaSum+TNG}1BQ`*OxF9nexjY*eRKC9o6GWf%wfHE7{#y<3tg~*Y zYd}4N*(lz-AdMFfQi9O9Xu!*$qZ+>Wf6RRec$7u*cYq8GN0`W=QA8p}4W24FQ z9{U(tX|2##8|v?rTR@Y30AdC1_a@BCtne6sTi}4ZBo{X`+IPtPx~d;Q;*7f>k&N^& z@0dc~(s@UrdK-xk$;~%GIrPodbvwlCp69d_ulW#ax-m_LvVs~s zFVNPi$r#>)9beYWwyB$gk@GAoasm2usW%uImCKWw1LQ`Y)$(O_ATp#l5E)+VwIY-A za6ct2oDgp$db|9eas02yjr|YoM=p&6?FVqdxQyM4-#9<5sI1>K@B;3)Dg(OoYg?Hdmd)4oFN&_z=Dp}{7 zd6Bei&PIcvZ>B6;>isbkH(!H3bJ?@{?jBj{32eEhDyQiI1A>!CPX-lO=Up?_va32gA)AL7lD!`sjBZ zhhnukjk{qB=w*Al*qn6a6h7XY_e08>_4l*oQO=+6C{mqggJ1xvpcD^ac; zGyv4?j}fXB12}F}1b-`=mU^Y0=Y^wlv()b2{UFsq1L`H)qgHj!QlDZ+wlO)lPRR;e zkomV_R2aB_bv$(+M>+3b#Shh&DHFEmg6n#q1D8?H3FW5ZM(V@HKs~Sa(;C8F`g8di zDh)ZHILS-8%Jta=?52Zz0EB4}0bWYs;@zn!6hwz0CyuMBeW>5vpEkZk7e`-6)$;NC z3(-YhiVEEh@z)xiv^aB~7lbwkZmN?k8d7wTr83;7tximDI5sbRR41PNT>H!By4(Nb z$e(Hdh5OPvzW??cE3RCTz$X1$W5rebeZR_I*W&-{wdpT`JX1~rEorVREDpU=2w@S_ey=Q5Ava!;Uu%tHHeBGAhzeo z>vOW2)L!hIrkZL7I9?SUDpiV7-rvHUOCTittG&?WT=j|#fMi_tS`JXzYuVbPQ4d~9 z-WWj8X6y{qY;macw*nB?QTvPKI_hF|-X95QQelvZF_BC2t;n54!IIUtT?DwtmG}S` zGnQ52e@*DiSqqMzWM{&oi$bNAfP>7B%*Xxmn7NG3XZ~IIZFLJ5;=`Nd7p5xEE>6FA ziNL5r%cg_ob?Rq-hx#5>BFp!N3%I2l4e6PQZhy9ssOaF#^A9(FKO~a-=Pw<*XQVIl zWQ##EzvF&ehWYI@NnhO$|IK@)zTFT19U$QUb;5t_%ueC|7wz(2d>M!T%ToAX(Juc5 zU=sg@(S!Ls>x@-2A7Q1;gh!{CDa*{AVo~tNG*# z6fe1>R$j;-8H6ICYR&xXULzmW`|vG-ygxhP%5eNA&cD8%e)RP1T9%XVujEqLVv!3> zspNCE-lc-)V&!1%wA?I|kQU{pT=axK!TNpIARk8$j3>QmO`!|K*YQs?Z#Di)cW7Y| zQ%Pmv62avBjGrW}6Hsl>7gy(Gsg|!(CFhTyQF4x?<{-F~^|Qa2`l3AwUX4o+i>mP# zB})%UptZ*(0@N)%USU|e^l-YkeTXAH>d1q%i7pXy4nie zU6@ttr{HNe`$DDHN|l~`)(o&vdtO8f?9q_#%@y1+3*JR>ZDMhAs5reB z)JXCS^p(-~+><7=;vR5%P#6s)q*venl(1i;wfsse?bt8MF==stdd?-ak4f5TTx!$o z+cfiDdH>nIeyebR*q&imQNQ*3N2-*1KWR_D^)r=4LT9`Zmr$BP_42r62~F6ySGI{@ zxa`}tk};7kp|o$KPH`ku_&23zs(z~yaGCVm{ao1pSvf6q>Kpxb32UY3H%RJ?v0xGm zs~G+;CH3pAM!-`fwc>XosZCl`hr;vkJe@IONa`}FB9f|^4oN*MSyK62{UDe-Qrf7c zlwy=Q2KYroW&w@fAyku{~E_PWc(CQst-cNN1_*8`fZl5EVKOFaAK1D%@T~g)85>T1s=N2yf|E&CYo%)Xdk6N&8b%lsE z|DLnpNHv0971dT`aXo*UwEN_R|_B?JwWZg2C?Rv!B*URSrKo;C z%`KhLx=ey;lwh)a{#WhiU&JX&65OQt#bf5ZD*UW{(XDfUK>t;U{=?4iWcyk8L3^@0 z)Ku2`?}cR9-56+3b~kNG(|_b=JNEO2LPvJBf1aHxzl{Pell;Co_dw*=a_T$!kG0yh zpG(J4qT3S{3CC;uIcbVpXk;R*V}}2R{p|7Iw4c+&k8NLmE;sL$+Sb1O6gxl=|G0?q zvzN&?$?>oE+LNEX;x;+)kLQx*=Rt{0W{iIcK)3EYPgs_&`y~E#Op^Re=$I-$mVnD7 zKes$`AoAmN>O1<6wNm5<^Mk9-qu{vb2XDV?v|GyjpqSYW2V^#T-jOC_(O37Qol^b# z|Eho1U(#;dm#?41>A5LOHU7PQ`TD>Vg0W~BNBNrjw^aFRe5XD6nrkYHe(Ly#WcfN} zM0@(_3<2ntuP-ErBC~w0Jt|4Q_O`7C_ucVTwUPK`k}uzH4@AD6aq1iS+Webz`T8pq zh4#<(o|`IWRZjgh|LkpP|3Lh+rzfWi+5z}y|6Thh4o~~?^_Y3D3O{aNzUmwxuzzF3 z{(Y1xUxgdmldqwsvbKM}OO~&V=d>qZo7T&?cl-as(#-O8!;wkyHTS1f`Dzq!ndIxm zIR_$NmQ&xcf2@_FzY_DurK1nj{?(+3%)f2_{;TpcO`N{=<>zwqUa1e;m!Dz>2<+cz zv45LWlmSvWo;|3(j&xF0H@?#0OO!9Nf zg9jo%UZ=ie|5&SC`I%CFfbw(7r2kZY66*sm>-bgX^#NyHK(Bfy;#Dc({fp)ikGPnm zye&3w)rt?akQA}Wltsec4hY-xuOQ}!n>MA&$jUe3G9myHYlNG`wJ|bs))R3VVKH^{ zS;;cOxs8tU-zEUvGBQxuk}e~hA9n8V$cP%cTg!)@CNauiD4<;O5nmr1-9-8Lx%EM{ zj(tOYBOiyd7UY8gX*JP^Lz8f7B{}5^VX70W-9o_puYQ?U4HFS4S^pk{+$zK%CL+(k zmOnZD*95VeV1@Uop=g!s?S)uxFLF1v{1$gpu|)}(?r+SGd`2%mzp0aFnA*+7XAul6 zK5GG)ZBiW@bZQtDn-t0gBmVp#oMUz!siuWNrivgJb#M@iUDbg$tgt!-okEgJ@|L)R z$W_qbg5eK?C2M{5MiPxVCR~Q7;d>SipRZK6bl;skX zh>ny5JW~ybODZ2WBh5Tc#89W|ltrw%vPgM#*~~RHN3g#YvJAtPusQ;WKzeX<^bB@I zLzi~2B7-8R>_z+cR3II;B)6vXuqAkiu)>=V0xatz$MBomMzEWWc+B;ga$I975sMZ` zbQaM^%elc4^T>}vG ztc+%}BbZH!&`e)RSwe=~;4P`oQh%%OA6U~C2rbVIhCe7{vYCDKIe>pH?q3-QGA#uh zkV$UH1XZed@5?jng?%w-_Wo^`^8%eFK7hvS0^4W^SzYH6eLy=C3gX?Y=kP&jB_TI%@}#>>sY~jE6Zbr}txm)y(Fa!%-wO z!wUx=<8^)Qp}Z*!Dl88wEZ-zl>hF|(J7?FsU9!}#e`j|1c$K=rU{C!y0fW}9&{Dqt zoA|%}py2<<``q|{aEsvoND}@}9_%|%{ELbIJ5R^)FZ{RhKb+bmv>n=DBE_43Fbtr1 zgbBe&V}c36NKTgSM3h;0NO!e!4v`L&`cK0H`?Rjpy*N_y10?=~erm3NBjwZA@RW%0 zWjb}Y2xF+jKp*2DZ!=x}`;`>_LdpkPMNXvG3a#>5b{))MJaOPI$=ZZzm(2BIlR#bp zP>bO6s|QY}aUafPU~Y{FH&TGG{w<)fL>Oe#(v#Rhmc3ZI#D{7zQcEcx7UZLxY0dZC zL5B3tIvbm#_SUU(OS)QD# z^uL;LJmOnOQYd7NBGqHi+mMAIJ)tqMP|zP6CXb_CD)KEFe^6Wfo|9_}tkB*LwH^Y6 zX4wqJeDH-Y>opA?>P2}867p0GdGb@97UTU=d7pS1UN81fZMio|ld2o9P40ic1JOSh z%J^Mb&;Hl3|8;av8l}U_3g+_@bU2*83QZ7q?9(K1?U^qJuZi{5R+KeE+v`_Yq2^pG z3Btx? zu%$TAwmew!{@sn(L?5jMt;`-q=mCovQH5&HQ7VPNn#>TG~<{3JmFjP=_4hy?qME$n(YB#@9Oda#yi=q|#Q4!jH)C&K$1GkB= z;ox7T#u5#Kla%CFKh2uddGHz#yG(jmu9i!``cC=QgMLXuFg3RAx%0Y%vX-7<`c)q9 zS8w)9<<8 zu>i80r*;F$;eXR7U3RB8OI=(*%>$vc!sSSVUi})C8CIjPHwW40 zyY{IgWYCn=YGm+sK~vseRewdd7qT>P`*{2Mpc%|8qgfKKM$1J%O6 zdvR2h;UDS4a;f~Q0RJl8{BsH>`1ikV{%Ku7ZgY#KF!8ceyi49i83gKgU%m|%ehW7@ zm>qkC)S5RFi6X1z6L1w22t<111|m~)Vbnce-h!lRAXW_hJ7wU?wg#B#ZMKgo5@m*zr$eD8*HPve`cJ!4fvYIUEh`I+#R|ToG(^zOX%brR;-n~`NZy*snC=olKZ75FZLJ|Y_UFltuDujCrICm8| zp!O7Qg?U)WcseN!%_=PPEt(^3H*6&5{!!!NT(b-ljgmU`kR;|EMjF;}|5tNOB+kAn zjP!EN7wO*gmF#VTeeQ?p#e!gPJ<10{uR};=3+RSm_$#XDYT2ZXcfm-vU}UTpHt5U( zF+{l-hHZm?#2Na5@OPLGtFH!99e{1P&OijY8XJd$k*f=;;0xS6H+D}7Bk#OCoss9o z87c9pwEfSrM@lyBScRC}Eqw^g+TS>};A{$rPJ-6KP=8}h!C9Q6F8~5+!6B$Uv&}d28ZJYF-F#|=_I0Z5xrFOY z@DzJ|?90Ob@X$USpk5mL)Q4z*=kNFk_=fLV;$az##B5l358O?*x6Eu~Z7?_SV(&BC zqm(wHKoi8~Mur=RRUovh!!*wb$N*IF97)^=*x9+3?T4Z1f9glREb)QWGyN!<8i;NN zy0|KiFc#yyfaX9Q#wdkuKGxlNh(?BE7?w7TXjoIzv&=4UD=S%ln>T88M-VE!JRU!R zd%PhU4`SG!6DM}YC|jqV{siF?xTt!l$bCM^qp5-52GzFRheVY4Q6WjwK9W3XhKZ^otg5iI%Cch4|B4SyaO z^if&(%fQZ$0xkbKJ9y-$Wp=@#!SJU+`znNxKK0G=N#(0Idduv~3fh8*D$V%Di<j)X#%BDW<*Exp!Zo+%$!?!u_$k4Ozy`&v(29NZSa)u*TK1kDIP$~u?d*ee(57m$ zFH4-G!9Nb;IVV}_oBKA<4*})`P9qm7Mqbt4j@&V4XlsEwg{%X*5ogJ-={E!F4h8c0!kJ$|!N6}{Yqdnr zwmNLEHXuqUI<$3ZH)49-thH^a)6vErm<+#lI47gd@hEU6pkkNF4cGFe8g0mzdcndp z3T!A~>Y#@q{C3XTDh{#P=3eZEf+|z?19k@k-BRkeQt)w8kWkrZohc|r0tG9ie@k`Y z8dF$WM&U*lwms7@g(o?3@$;`xo_MxUS{}9-(SAq@eE6J&ow3XDyPEZ!o0)CmDU?(f z>Q;K1R>}=Z6}pu}OeI+0Rv@8U|XJ*APbQ?r6 zRL8nC$sLN*P2KYwA+Y~C&54xWeD@)u0T^Ohd@<*=?Ag*A^);|}yy_>%ZbRJWqnC(6 z?;r%Kn&ZD1h@BtKUK{I6tca%CQ@f_kc}4MWXhV2a8}}x>PpAa(In0gjk?ft+jn9xm zpj16Su|hKAL{OI`yXOdeNw8}We93jz&dpZK?z62UVGp!*vFz+_>d}X!v*WJK*xBb- zW0pOT;7upv6Pg(#IHB2$nO+8DF@?P6*PxL#2nD!>9)rngejSV&0x$a1ASeU%@Le2& zghWG?OQJme?Z!6xgl9LbAp^05KvIPEbc!A4lz~Yc10Ax2oKUqW?=B{FYp-V6`K$>M ze}YY38h2B9($T#ah56XYOZ6=0H^%Y0;2Q9 zPJ_OyP>0${6jOGOPQqC@jR3Kk&cVn9P-^GpStYA|Ge!~tnBPII)}T#R%Puf$dB8p# zEmD#PjLC3^;EY-uva}$ISy*kY4m0GuqTC~|WZ+UoqtmEM3#^D8LvJ;9tgcz0+ z)2&2u*f&ISd_gIEkY3Kyr6=>%F~FawYh*XpoMuHvK^RU;L_B1dcHtj6W)Yq+g9ID3wUeQLtLty0!)rtmj)}Nn zjpcd#Jgc$%&`{|YFBru$M|UP%p3jhVT|TR^d+KO`!HHG4981oBPE-)|!sUfhp^z2$ zM13#W0ft=Ra@Mm#rPG{x3$-T}t}bTYa2+V7pCCTZis5nuG|DSOr9r2HRz-MNE)78{ z^b-|9dG_SY#_}pXLr->1G7R?c4)qZ7r4s5UWz?xN9uO6?%sU#U#vy-z_(x+OUav63%){c@$2dGbSuBcnC8RP zk!?P%f2z4osckA(zDnKKQ7Rb5>}$E&gRf1AIg?CiI2p<3fnY@gU&N{!iZ` zy!9=@+iRPm{k}VZ^@+EN6BGAS1shhGTE)nFEQ6{KryQLJY$ z@?^cd`!yY_`nsyDn)B(~RWZ(69Sm>P4%;hl8^x)r7E@vFYO8@Oj$&A%o7^q>mViLe zj8nyGS!Om7Y~%nyG+fioHCVKi8E08|TOhm<^G;RUhiakO_fRt@fpC2h!xs8d=hs|I zyn%3WFmeNq-8eL>rXLnoH2tU4^5~6^1L2iaVeEmm-v-OVU$MdL3=OK2;q@lkhd4mK zhGL|qvQN#rAdP9!N%1+adx??r)5Q5BH8hFSx95xQdS2|mg%Ae)0BXKM`P8TC!R7T+ zUDdNkwx`eHE-122o$wyhRpuB!c9I_&xtKZ<;eE<v#w4bq22y`a~O`rI8{7USC?o zm=fHMdc20)f(SnQH<9DZq#Zl)6Vm|dC9%$7TuUJQA&3Y7gSQ}XpkC=E+^apxjT!TD z7~lA@24@)=oSI`p$)#o@5Yd4V%ni{YLj!ZF2YobZy@0G@taqRWBHlox4n}hn0%>D) zd@V@-Ff4S#EM7XM12}a034_ZP)qzMK90-Nu`%J@I`DuFwT#exLqn?%UzW}w|9Tg#( zEG;U~h%4phjf14CHHd+k*bq)tgR-4Zh$Zj)?)M|g89ju-&p4MxRbZe&!)nCDqut2j zL<%<5SbatDpx;Q zYp2@XB_26zfP4HWsj*CtfY9B!ooWxk_*`#=zgvQ70?tpnn5Vd4qYOCCr)tT)+QLig zU{yUz#W$(bmk5dO;&cxy7`7)cp)*FzY&pZSES%jH6AT=$#6#(N{*HFNM<6`Bt2fq7 z>z|=qtY?5s+vY&YM&JD%zPd#SdKQUaXV z!IHMe+XVOf2>Cu+TsX%@s!qSyA19c26aGg0o12sLms%HatFET#1XnVLTXC81dVT8+ zVvw9)5UR`V1o*z0zvVkPSCv)--WlXjmb_=LNp-V(-A%`I%VY#jnF|vci_$2}MM(^5 z4pVq7=itSqRcaPsA}}?W4r?(YZD#?REYJqR&4KV{`XKP;w0+Ofi?w?3-&qCC{EG(u z_?wdHvD9+YBiaM3bCZGbXQkuM90Uw5N`K)L@e|5hKEbj1^4w8EIE+DlW2u14dXz^b zYJH=&<4}QEH*pP+nAQya2$3Evo;14(Iu=nI*R!%+I;9o;#>*_V@L!T9Fm)8ER}7Qu zyXP3Z2-^M*Boa7cbh+F)!Q zxjuk75cC}}w(LH6fwoq7w$1}!>>mMMZ{#>7p#vpr?mCoaLr?^Xu*i&13H+xA7{%6+ zDy+M}Z(NHF^P(yA_?;Voy1*Jrzx3L~FFHn|;6_oEyi+@XGgaWR0IhO-_3JEaA_GWG zVv-If+7lqO$U^q93a3UoD8T;q`MvbWR< z=p_i4+DrX}hkwE+^rW)}BW@@MUA|f}!aV|rVV)$e3w@${Q%`(ykB&F=`KFgZH&oO2 ztg>wWK`V7?ITQy74rYE@NjE4w+~naf417S5TJS`p&6T{@zDBd z1qCRy9WlF!@I8S8urY(kxHMdPAN=FsHb@Nv>|L!k7_m)3j1jJOAB_6LeT({dht=FEt^KsZ5QKIUTd0 zY)|v~FeH*>$n)}$Wcc z__EzzNkA=|xp8W5;1vA@hL}b#dNRJkz96$yy%7>~GIKo5Nsxh1xa7p87KY?-g0=C~ zu_BParKhfM!$La|WL^!>jgWkym345y{RmZTtQliqS8LdVQej`65w^OreaJM9;k}Sm zEMlKp;)!^ZF^4LPJWQSiA`7&R zoFma#W}P&Tw96K;2w=z^}CjW?+_<T9^onwCxj#_hrsgA^70!S%F; zse*qE*4EL4k{*oAHwJM+STM(w6IioayI4<$btA&!q{2{QYN}mab_K&|JQH1_7h#H( zh8GB+c{|%ooaPuFYn_cH>*G1>sMF9$)^rlY1l9+GS8hLnv3YL83o3Ri-s6Wa|KKIR-had5| zEQFZzUoI3qgXh8U^9A$y-u5(IPI{ESxyK3@#o$b?R-G!TK(x1SwXLGVQ69i4!S{a;RpN9J{sA-65#tDkqiX%H zXfmV9l1~Lg5B<0o8ATEU*{pU*a?u=-()v5|q<_AK`z5~`!bhtxEgP~li0z7)+t~-3 z)!W+FoYmW}ep()HAHms^*$YuXkx5=F(u-@$fU+i5XeDZ&5wHEct9H1>w+H}=TYL@O z1c}*Zv1nMX`V7O9^jBNT@dc6eli^PvB0&W>e-;;bO4EA&id0~XBko|A zzWx{Eal>QU)qyUynYM+m@P|r0kC50n%4(#<8%M)&#gS=mtCP4+&kZuW)USX5;kHUE zJP^|Mym(8uEVY(-Q?PBQ!!t2oeVCx+XaZeSuc&gk@VDARkgNTC+`AiH2(K8qdqJnJC%yIFd za2U_72A1*$g2j>nvA~y6-b3*@=3tgkC^_Qft(LYn<$5zt48ei$kKZDPvgs+rv<>_G* z(h9)MzyK3xRDD=NMCkWJx}o_U_ns@Mg_7VZ6Tl$tM)U=ktt1EEx5$6ailisWKR7@B zKs#Smoj{7|+n*64J4#)D*4O3oj5?l?Qd>f;Ai|7cAmpPhhkH>MH<2MQzM#T* z>(N}8efsXPUYtW2xYJj%nH7vLZmdBFZA^Zsw0e$FO1Bm=kL!*?k>9aOB$!e^Ag*Lw1-{4H*=Q?NoK+LB zRu9VuPFQ#T^4CP98y*z$L99EG8N5*y0TuKUp~k#m_!6kD*Q6j+*BBlkjuXFC4vU0J zvT6?wmCl#9uxK4Ph~HKlF6O&CyjhI1x}emhL0MfPCG(IUUwfWf@(1o97%Qa^?AKih zgoowfq%~;LW}t|vOdh6SP~GZAv=Rs-^Hwtn(LAFS%PpBk`*Qu|zJv4>1>YbDiCUc$hxRs#`zR> zJ=HKGA^wWEu~V6#ifIwda3FFnC_E}}Slb5Z9~|P|J81WRPs|2NQQ#}Ff1TbUp8o~U zgC!r<4!0tu8*aqG))CJ}eDF1nibquM>VgWSz4`9HSv)hx-E$!XYlEX^qm#q{>s@>Z zW91`^g{eW#Lj+dhnT3zq67{uLwip)0$-a7IK6(z3S@?hvnUPv#a*&2!ICu^9>qQym z7lRx^;pDZeA5NoaB@OcEm7KZ5oCA-FBFwTg4&zlgP&(raGt4D_Zy4s*Xzhdo%f|m` z6~e;Uj*Mq4#pH!bziTps&+^I{yp^bdBp-!xUHnDTQ7_O)1g@gccpbXRd zRyq3pD)Syb65?d=oHp;o^!)@jVIzR#gyR{1+Itk@z}#8^2dFSqdgJ|u5BiLii^2F^ z9MG4rEirV(f(kv+sa=uBbmqD|>_1{f&i!~U7IHL@@$9+I zk9Ct7-$R%oy1Vbwq6@IV!HdimG=m-?{fO(M{l>9jOpjVQ&)0F;6x*fFIMvM+F;USF z>>@xvrKH|8YVrD%w z2nCL=A9`}lC>`|R)194O9z~c8Ft6FsC<}j zQMF&=3tb-Gr0KuqUHHDp?mvnsm$Nd9;~oPr3syE58C^+d0aNGL*`{&=aauwo@7 zXgwllU@t(Sx&x2O+6tDenTBjylnF+9ti^&FM85*xE1;9_z)cXh`pY825F!K6&8pKn z?jS~dsk!DEcMCf9AQ3j?%UmpkI|X~k1s0^ik`>R$B)~lfuv*otYuUl(+Fux~bO%GF zSI&l9Hq~~;xUixplk;}`ilSLubPvBx|FkdP#Cr&GSlqddRy6i((TzRl_7+-S9TtB-vRnW|yGfbrbs3Qyeuy@Q%Kiz7{6-hvzHgQ}^dl_vcxW3B?kU zr~aM$Cd3c&lLtGOpK9k|zbB+O7JD{f>9qbDL;=cRUuf!lGdu7tMlU!|Wdt@U?2bXJ zqV=zU)~^j43Xd*={^{M|Au1An_Xa1NZmeUAUX;O_*CEx1|};j&`<)%D-cRz__89Z`Cg;g(TPw|AzZ6Pq`)F50kyl(O@U~)Bw}m*D*jUX z{&EXBC=ukIU~e_%j+eoLVqOVGjK@Opnpkhf8zw?hLfi!&;)d$oOjY29>XMzcr_s}a zEJ?HlU3-UmIY%w$Ug!ea<03k;`E-*C*=0CP1a9AfZE}0>elhmA%z9(<5pT;=^9yp~( z+K+Cgc*N~aP8FjeO!^Dm3DZRRk)5WINp{m0I_r zmYb@$+$^4vS#GwSCvqb;A;mcuJFNN#8lHar8A?wNTL6h5HS0W9zfP$2W^X zZ7%rBj_kvGV;J_v_N=QqaD&&Z2k=skX$Z7@mR%OfKD;avJlx9#{S8>n+4rPb%|Xyj ztx*_(;mvHz5%KaaZx7)l{cmd-Vq0;PWlxNJXn;7QhoI?^H z0+f=SYUDXwz<{#(z)V-(zcR^e%={lz!ui+xwHY1Xirb9e{vp+7G)y()DaF@#!B1(! zY!dT`_H0HpZ9;jvKr@pNkE#+N|BlHx{nq`PjQ6G(bhCTHV0a1NWiaML+$bIxdkE>o z4TqNh`gW{`>X@Hd7@}R>a-jK7sZX&Xkw$Tf?8Wji6Q_uTN>36rp$i}8L*0G^-_&n_ zadbL?z&pvKuFU1YfXvg)u{{^Ph=tv6W=f1q4hvyacI%z&G#nr-MRBc{Ur^1;1+gv7dEm#Sw`(R8$Gh?talF;eBiy8jdR-<-FL;{69MMfu(YX@gQ4O5Y23g*(HZg(~ zXM!t9Bi-qv+|}neh=+Gcbr1sr5UL9fqWEuj5K`oMy(Kp7{=T_~8}3IBa*r!V0J#3S zK(BxHVGw%yb{T8o=XK(PZ9Wn3-AV>T$_p{q($VPON;h?ikm{3zx7-(Zi+Nfv#Z7`s zWE6NDr0ec^?u5?Rl%NWpq!CYW;{z!^$)cUh!I@4-a>RdInqu(5cQ|>o>ShKruu*#E zH!kSG$P6lVWQGkBLs;e;(TZnO>^R2prTM-rJXy~ezTrOO#eOCou?Pnd6qmD2{hV^Z zsqM_g+Zax&Y>qem-5b($?NwaP({oPUIfjlA%ypn4GwSb7Lv*PD8+nb+4iX4lMG)Oy zEclPbbF4Zdae2hx&w}*uqnwS<>tU3POl@Vs=_|<;?o(~=d4`gh&&j@gH-yBor9=z~ z74rd?*$>1gsUv~#yMgdevg+Y<7no9?Aq(IgpS_J0Kst!Cz7w3At+1qtKAa!P{=gv{ z@-q=97nVt$J*Fa(G_D`Mx88x}#5qmY(q$90C#>Fw@j;y&sL zNRFIzDbpSTlKZz|u-sWmGoLL3ozc)pr zc-9_ac?du_3jg!q&kxi2`|6F0xV&N3QGsk7kjyK@9qWI(Te}E;=6HolpR8fCvI$d5 zSz;3=f2+^fzDz`A17(dAmz~1Tu;)n|DEUPF$yBJsJ3sD!PgIz%D-_E{$YLk!OwBMA z>QJF7RN5<1VS%ntDHST6+#EFq6`YjpRu(a0m&u<~!}E+;?GOHs7l2mJ~GD|avvZfh@fBxU6w+c zic7u#HJ|t*`OGu@n4Yj7{q6!^R{OnBZV;%PC+7J;T^LGWf8B)gN+1*ePM@L;cBpYu>im_WUfwD>WUhgj_hY>WwC4Ex}IRT>$gDl z^fKIIf9o`jsopM=6T2)|Ftz*d+IJYfwP@!(0Z|X|I282SORDB3!Z5^t?!oOa>MAh@ znm;`cfIp(4Lv`ig&m$s0nm_%z2!Cp)lB6I~0K*ZyX;sTt^L}p({o2u*Bf=Zo^Hl*x z%gm`9Et&_A=Gt46cu*X}E!*4#3?8UgPye^c`Q`Z_=Rh_A#v5|JI>905AAb4|$*D&7 zZHJbNGMQE}v6{ZqNU#(ij(H7ru%v5h$2$wGI8;FvRP~-hx_fe%knK5`9U3zwsYB6A zr9;?zVCTI5FLr6QmJnUbSy3`DC>`qlJ_i5jHI9p^@teM1{3;y$4#lpg{Pu91GzvJr zaHqy`00G)Lr(B)D@stC@G1l9`k%#D+{DoUZK3CRLe?a5%Po&OxA~^3T%+?}SB@zNE zvTFR)&oV|~=V5I;#RcMWy!0sDGh?SClPWkTtwxV3X@n~&jpZ1&Z85G2J{{<)=MQSj z9Z5acztIZDW}C2Csy%Nq7vblb8%wWwm^n4WPv|gz$0?x>*ciFx;m&dOb)BD_DlO#!}=iL@&W__{z?1 z27|ZA%!FPJKW@z=vim>c zPbS{LZ!^4sfJv;~@MiOoZr(hHUL^6RJkA?iFKb(ty_eZh$fk=ly; zA@T1(^(!V8=v#ZbYtabw?VDQNH)AkvywK^Joilmo0qNJ1<5(u?*U7(x9>}Ne%A@YW zOkQ?L(o2a)m};J-8?&YMSc!#Mk>5~Nz}e>L>Y&|_ zL_kfy-Rbgy`&ox~h5xjL8C@`=eObiLd9Q;|1>dgvku=GfaBcwcw1wA;09#?tIQ*vh zE**t0%>O$Pc-Wrt0H*FYu=;6OTTXLe9jsvu5Li`lScec6PC+T{i7)B_4XGO;jWCdM zHKadp(O#XM^TrQ?)#v9Bt0Ur&KE`i>^e(=rk%SbNZB>_pA@*G+?Pm4|4o|k-Wsz(1 z%VvItdjr5o@GuBR4rxGn7B>)|qIt@Ij5B!DE2lYUqqBx~&{RjX%BUH9QOARhJrIO^ zD4P*D41AY4#@`Tg94tY`YB`L|5-4@P4md@#U3rqZ?f9ACiGH}iGA=Ef;)D0wbj zkrf#lM5Za_3u}kt={92#hDIn48o;a_`XOsrs|>B;5aua1!AMW+)U8D)MS5$Pq}>Y3 zq267WSU7}XCOnv=V$KP$1q?tr;5pb|jy1k2HJelJ&iWeUet@|S~%T$1nC!f_J|sVo1)! zKWU%&r>^nuv_IOke>jdli09;}Zqx*j9U13ME7YBt5O}>?8i8VSh(MtT&+i0*`TtS- zqn=A{f6ply2r%N`Y2P=C8%#ih_T=+lj(oQ83(t7br{^JB0#WV7h|IB8Xz6;q&8qP& z_OO(lv*iJtFCXi(*v#x&@5AB;t^#T1k`ZQSkZQA_0fmbpibE~U`iCRct8!>{gnf2BwdkBphS9NlJo-vHT0L<6IbykYF&tJOHR%Lk0rl%;ROu(#EE zXx$HP!n@&?ITJ(ty9s=+S0zMTv4X-(+0WjhGaQ5#U{r+|7Xss=6>44QHEpr5Zrrr* zn{_v7lcZyy!(oJT9=jo!wJN&54axZc(?{Q;9ykZKZygFX;^1?X z3GK?C`U#P|{ylWyAa>x@S9J&a@Qk^;daC2z+0=#&5QF=^ba@aAF^X!1It7SD>Ac2q z;}^!4AJ*~Z&nU#xw=3creqP6uZRgW7F0XUeQoW?RS#`G2d(7e%6M;v-98Qykf}NXG z_)}60_oEA-APB>V@Jsx~9mLPz3wkh>Q@^C+lRuJ7x0~?t)ec9ExGwzMn_qLxms_vy z`{>n&Cyze`h8ZcrSUA_W63A*64(7rVk@|t`Fd5|Xs9X)a`D+XuJ^F3ttdB(Vb%#*4Lb;BUb7JNfp=6V>lnA@08QA!y@9DDj#FP?s?K{4J76F8`GiX z6K~h`zD0qKU0W%Ve(_r*1)|95ocP>WrbElWd=ew@Sm_q@xpSC+s{W3W?(}CyZ(Iz5 z^`}ng%;~9O9hY&j?-!$QevW?t=O3sm3(&Lp1-cS4TwC;3n=0p{NOl2G2eF42oB-W6 zgf8F-crt`fsO`$xfns#Pj{^*_f3zdU`y=u8Qop3MjQUmS&GShg;=wOkk)pBug!|g0 zJvQH~pPYSLUu(lBR?Aldtk>%AerXeybsz|bpJKh5)%E7aZ$JmD!-u}L7$|+fsXv|v zPK8SOfdmh7*|(@y<9KSVoJaXC(l;VScH?x)+46d92fRlhDd$f8{zm=2*=`)9 zeY{PLomWs)D%n4%IqVCI!+wrh7O){k5*K1AG*ASADn?uu{3qMNdyXH-*Az6#@?aSs zb6CahO<*AHUzQ?e=zlMF|L-yVclXwcV|1v&sK|Nk%<#34tKDrlQs}pdCX>FgecvpZ zz$EcNN4{#92v}1v1mcK8Lh;2aIqgvhOKta(zWnsfS&lPAH)4|`jdCu|Gf~~IUD38W z>*m^t6XgtC@XtX<^8n>q4?^d}2Lf}a%+j6nTXuN|>A?~`6?QR{`9Y^r7(hq=s;q&l z{Cx*H0Ft4r9_VcJ*n~O(Wx){66d_qKKr$@hRmS&cg!cCK&1$8hDQ&-DIsgChJc1Z2xZNJjRz=MlBxcb+Tzn%V_k=ni6^5M<(ZbVdVk*_(5 zx@+*ed!v_wUqWeIFk6xjB$Q(2jq_uR`^Q`EA1&@53*A3{@BZhe1bu)kTmLHqdmH5%5$M@5Gl%C_x`Eh7>pITl>&<_LC$1suIzv3-?pj-LSX-Htl z{42Dl&$Ls0i-usUtmoM)f?3!~Hl#?}_apzP_9N7Nhk+rx|KUk>>HkA0u*tTkvtD9= z+MXwLh1i=(jbVVob~`~FI_~+ZcrVYFNQ&f$*DmwB1IllHPWK;k7$<(iHrzTM4OP+G z%vWo%um(3XyY{5%#Z+TR3ykDEJwBKf>HB;9r5c2->KVQW*^|7O((#6<+ABfMj?>`& zdscogH51gK0@IAu>}Dnt)WXuBlUE+G(Z z{Ecp26o(3*(@G_#8uc z3Y6BFXS95YD)@o&0-%#XhrSqx7FZIac?v4w<@&D)1U1J2kb@!Giercx0z+d6{Ko-~ zgCXi9Fa%oT@ZP}?Fg1o~Y#jb~FhsEghA8jC5S<=}{~ZibDUKl&$vCJ92SfafV~83q z3{eO~br8g_At2#DJ9hoHF&7Tb;SgG|qC9SkPHPB?Ejkz;9<+CP+!*n}5q#iiuexp^ zYv{`XprvooCaTrj&LBc4*B|8)28d5^o94MNkCzo3uFp!p{*~n-i)N%cimVqBokX`N zFTOR=l%|c;`*yY?qqW%no-Ukt0zbp+Tiay4mbLSN+k0}D(ix8A%pPDNPiKXW@12)o z#c@CDWjvjGIF#+&%Mnw-(94&oQP_*@5bVXsmRZ~qF9F6CwEFr-ctS5E;o*B_c!BTQ zmS%4|F$kWZbC67ef(5-=wt2g@^01uVU7hXVdVDprozV6w>X%A-8kN8XOFls!LKQ6V z!+*lUA-)7laxN{`{u4hF{!<@OCfo=8cOnc$A~&$%F5}^-SI3$2kl_GzrcAnm@)w>d z=0A?tM>lmy+$qe)o+Y^5;A(IQ9cA_1UskuNw-6|2{DWue+MfE(SXhfUrZ)Tl*NI_Y zH-U8j7}-Go;14r(8~uaol-wku#-PA!XaaG?>3bHxS=Xg@1cDw%0XX#wjzpYDS-~86 z42sMjBE!)tyy_f&`sTF2t6swu0mrv+ zvn1&|`I8!d2WvmCaK^`!OVh^3QqGgi61sL>)O+7yWc(=!vi>3PPeU(?$@?Pm9)IA5 z$ALiXg1GD$Cljg{U(}kT2>dJ7{8Lj1c}WJy3HZKQvTl;phC1r&wzjZmcOaOh^8Nv_ z2>1WP8JO^fbDqTq^1nbQNjvl0i{BD|oQ^N*4KAmz&Msi|K}5kDpOdTVnm1EVAeHHW zXXGdyY14SC)^9Noex(NjdJZjjf}CvOtScPBAO`Z?A%t==gcZU25KggBC*kI$CPtfc zWtjkb+OSTsq212oh0vGhW9E^*P{XWi*1yJa{GcfbUF3tSzKe5kesP6is1-RV5&&|! z$eoUJBQ7!OiNl;Ix!U=S5!IL=rx(DUAaVz^{xx|L@N>=29sDL4{K~MtGaNUQQ%Rjk zB{iHe;{&KF08Z9HZ)c##OyfN4(59DI;z~Lep@u zFgQcncN`0?KSLaFN%1+-Fus2H8yS!E34s>&S<_1dRv;dqC5WpnKzvayLY@QBVN zD)8(M5WkB0!w<={R;W37jx-QxF2O_M=v{yKb($U%?>ain(Az8sPQXugH_Gz`odVvrIOdrJHKx;IQ_!hoE^#w4-srvYtr26uJdj1Nv z`4B^Mz4rE$(ENW41~PtNEi;XuOO1T~LQnf`&)efLer~uh!}w{>Wk7tAt&8qg3;yX0 zqp*m8@Q-WBzZH}oh!e&2Mer*JeubnG1~Em)jBjUs@_3FNEK$Nr_5oqAT!}AMIJ*Ep zyz0__YNMDBY7}C9;$R0K?f>+PBPHvTMH$v7eY3b>4LGEX;kf)wyE22Em~r z;TnW|Y|r6Yu0Yh=H6~V*+2?2yOlccTc!ifSQgxO%L!DLrv@tHUK;h=1R6Im+|OZa5p(Tss89Mhj8vIyxkRgpZ~yo5|0oUsW7CfO_jbr){@~O#GkkjUH3{gcMPqz{~?uX0- z3e)!Xh^|zNzcNjbMY*x(6TQ>++c)b|EkAzBk6EL@V76EtV-7j}(j@dy5Zqnu&*P#{ zylt2uw7rzi5H%tWtO|80njCRv?r&fQ1x6Hza?Fo7UQUXY?7IB| zt?kfM5!)}cA{R;Q8HluC^&aaxsEai{9AQ1;Lw+y9m$hs(pT8`t15YP2OC(K*YGF>Y zN6kUHQU3;#}7xN1;3%d4_Z%qdF&rdV-VyBR}_XyONP_a#36iEk(^vsq^cyLKU+VWy8UEzBs^?ig~5>5=Ktm)1y9C`DOcq=`_pPpV=! zY&-z|UGfa*yYSfk%Ex=3w<8}7SOyp1>dQF&|ES;oHfP<{WYTc)BT9C7;3`S*kaF}6Sc3H&S40uIF4jmJ86<(xEaK85lEpB#7(}y-X%RaWNEaySC+g~H4ePp&x>etQ;_g3Vco?0q zQVi$Ah+?gn@wsBTgkHqaH=rI^W&NCgCH?D<{-IfC{;s|hCBUDdq|2(+%}H3qmYezi z{|EGWciVr5J{UiD;IfzGLF4-MpUdAs2jl(9AKKrHP^hcL-3U%dddFq zm-;C5{STQN!K*vkc_oNsl%L;Yj~_>In*5x!)y<{m%8e1rTv@!M|7is3jTDjVDLT3Zej z5B9LbSyqFer-|eXkX}1aSifBQHv|JGJL)o7c<_t-^UYet)|29wY{AcoH1L)nBPVyb zAH5m}A*kVka*IKk8VD)i2KTik#J#_xA6@8w>}4hi(3i9uqTjYpqmPx}n&;xki|1-p zg-Y)hP}q4%UFgN2wEC{?+dA@&G+rt4W~`fk3zz00foh@AkU{Z%T+zOkSFiDuTQ zgRemg4g|V-rfz&Av)&b_?vu3cL~kCNk}WdhxOgQwe-0a!j2fb;Qj!_X#ARTOhs7t;728t= zsH*T8jwSONzF8fPv0)!^{;@QJ{aohek#G|`9qVJ+i>3GGxw=*|7O;4S2|LsYZdWET z(TtXSoPVr0^34s|P(^qoba7OawR~`_rf8_#9OeTEwdfLQW&D!i9n&KEmCuMYV zwSL;ljwb6TX3*iOq%2|`6<@f4MG_?<(pxLCAi+_ji+L#3S( zML`%VPl`emXlM$hXu5fqUhAOzh!4^jtb;0<*JsWC4?iWnnDY-{A@L{XK%%GRaz8iv zh`Gb0JiT#)S9Qb722PAAjpy2v=e}FJXQ{wh(*5O$?xO~~fAXpE?vo&{?iZ@@yL9&f zliklw6eXox-OpEpOi|JW@s-Vx6hqW6EMHQ+AYWTUZxa?q55W{HdMthR5)-E z9fUL?AgAiycN0raoQNALp1)HLNznFbF7~p(KFPI5uup{?m9S6p3H>7K7tMl0rH zm_&edccKfj^Y^g z?r3(NA;WBQkriUt(FV5Y-mZDMWztGqs*V>$<_w)V z#)Fj;(H=(KIOZmPdc(e_kcjGcZ) z*Kf8)mOib~gY@EtYT8dCtT!J6tccnBXUeNOrWn|xL8)C#*n@tRzE0<3Fc4WQYiN`z zG5PZ~NG=OD3^s^N;c+>)z~3cSi?c)QGF%h89k`z}x2v3AaH`nqspVtW?MMGtO#ls(YXD~y|Yefwp_?qZvr@CWCV z**PVAbR#gR1O{q?v_JmeZ@-CnCbeJ0_G6Fe_T{ymGZBqZAnG`J3VFVq?Rn-1wEJWZ z%h8x|p@?vnnPcx73hD*4tQghNa){qP2Gju@+H_3a%tO7#REGsWJcR2<5e3`k697tA z<9^ETAirQ)qde-yB7U)w4Z1mmF#x}q=P8)6GJRz;%DNnEnU|)b<-m6)Fuosx0d z8TY@>>^KQ`t$8lJ7u#K#-n+uLsMTuOmW`R=2$~3uU$ke&MHjRO(>4 zwq&j43xcWOI595yuBI2c2BFxYYQ?t7581XRi~ra=jP)Y5c>&Yoh8I*hCzLo#lg-Uj*@}|eVx$7Lx zjUI<4dKW3r#a%#oqKV#@Sx18&4AAY1IRc=+MO(li&@aQuP=WB;fN%5~648%r8iEw`bPE@dRAur*5!SI*r1!g&fcLqu}`tEDP41%XV zLa(mz-S*A^Vh)4W2Eqt5?EKJb*>kpa@`=~Q;!iK%-Nl|Q|^DIChk!@Cl?Qy1kBn9$F4Tn z0{+ZEfN|y*au9-07yP8D5OXqL;^s{xY%- zGLt2V=*LOTG@@@*lO$`Q|BZ-nAeVk3J{Xze2KnR{*h2Gt#3n@CY8EKaDvKqzsn1gi}zDcF2LO(X_R>(08w zbSp(WIqN@We;t@K5&9hQH~jIm?D69KkiEyjzF>ZND7$Otycs`9X~y#~f8m_HyDTWo zcL$IkI7QX-9e&e%lzxRT7~gxj%nn~=I}9k#b&|as;eG0;h1k6i_B=1uA9AYqe~Q(8 zs6H28B!2c8dqs>wJles{-7J(uW>Ij7B; zfg@o081wxJrma?F2!?F18$j%!Zxb;JULC!CxjPa5kCN8$Od9oge#KJ-O`xw<@mF*O zk*06oK~0bOtKuhAynMpL-6hWv6Y=ml{3Yr$`?QA-;l_aYB<#!ZaT5m_#@@Yxl$z}D!u(!Se3KN)_hsV^3zPRQK1 zbX*spFh_2?78VjU&MoD&=TCmL0}=z=Y$+2zD`Vx~IK1^i@8ZYA#ru8gGA@GBAp9Nj z8yOBDLI9sZP;Oc#f=T^*%&7?edZh~s3#4R%gLk@$SY*AuP!~-Ux!4pz%F)$yk0efs zVNu8)!Q-gHr<(O8oo*f3VYiF<65XzlLb%wQ1DMv&o~NI|vVHqB-CQTeX#zWg))UND zQV3vJ4RNgeU<8Xt4F#2e#(zTaR{W4JAK(k4^ZFA9u<$p?%hG(l9-nMC7oTZH8$m`q zRIn8O!mwzcQXeIr>5NMwXR>~KgWmezHdEZ z?cB>^TUorra%A^f;cw}Jk{(gsHj4a$m?o9b5ngE_+dz>jej0M9gI9ABhhVbMZA?Bq zbm?m&3dxs;r50wr@(JIBpEizZl}{Z-PV!ISB|ZL69Ka&|8-mF}^azMVQ&XaqONs_J z)BY@#^SK5lUJNTz*UF9^2cKbHb)h^kntJ+5D)1FeM1WGX6y~N44er1sgbm^XZ@d48 z`+QkTcod|1bi-X8yMw$F+L46AtQ)snZTM4iiPv}EpV5KE zS=)Z_sO_((Qi{P3m>eFMrCHJkxCXxHiQtbKjMk$^;ai$uY&U?*-PnY zFrsfrza;Bh&v8J2{uLZ6%G6kPYzGG#29ZVN9OhMP2Vj`C`pdj8=d%Lavqz^?*l2Z zVcT=f_e_6=epLPPSF|~n{+1``(yoS0@?YdL@8`m4rT?izx@sbtbKgI>IE$(xgJWnO zN&DO%Sx8HsPv08a4}w_%?-cDr_1-neIPvt_H++iojJkYb;r{7g={t9FtwF8YneWi@ zf4KV+@TiKc?SM2yFmw8zTN398{*INkiLEU)~Rz& zovluts_U7sMr^Ze;(ih>Sg>r`8BgWr~dftdaZ3 zO4S|9`9vYrQ||c&!OtP%qmutZ?J{}cQBc@U_HF=Uwz!{K4b5=AHB9 zi!M)T;J~<$R--oTx7RP|zot;OFl9$>0M08#Bux&&0=DWwXe8Ny`MliY^5Gcp_y%ws z{%Vg}`5{dzC;U`*S$?Zg<*T)w)fCbr(ar|XmltNtBC43e7J2;4po0s!p|-Urkk$ID zC$yIU)OoOHX9Eq?0IQul*%42h^A3S&`vbCVPaaO=*b$~Dv#Pd===(xM(&-3Rey*YZJ-*W9FBcpI{lhx~ARkHYzZm_SHN@y&&s2`Rt$({- z3f4c$_eWa3|Dxr4k&M|h)+)dC=^KR<*ZIkK-%F>*+o34>ZFj|G;^a&gd7-5TSO&=R zCFY&nu?{+_Z!$-cg;Pf%?_DYHMd*NHJ~N|Kgnf>5X!0p6w}PY>NtDcAAUUOB#5`Ah z{F#YgUV}u-VGDRQx4ZmmOWLy_?Sr^8Bw;A>u0wqzv9bDyp#z2@UZ4t@_yGw!KidOK zkBB!5G72cQOcXDC8NRwdwsljOJlfS#JD9Uaas|1)vYZ~tlt-td9rt&R?}g0TAgPRt zY@J#D(yb*IchEz!m089Ybvjz$wLC+;YlfEHl*m*7`a}F)*Pn>x^UrunoLC#nqKxPK zzWPCmqR2Sv8d$G#$i;~suhgh52ARmq<(+&e8FS~g^t}?{X(*I&)$@gbd|SY?ROO>u zzD;kcL~dBZFnj$X0JhY{0czXxVL%NG1$9ywP*fE$YZhpA+>RO?pkI@Rx2F1&veP;w zsCT|XM!}&%$G#Y(LZ?SiA@Ls}`~NVkkAG$S*I4Z6)(c>LAHi{`&=k}SqH15QeW3>R zhjptW`zHPp!9TwKrGdW>8?Vh&^3DZDKYv?b^m7JQyB+$OhhCljk?`G>yTNbxKq$o| zhyi@yc!mtKaF@e2ZeLdyh;@`q;iCF8B0*YKV=f4oFiklGMYr!H)a32(`wKxo7Toqn+D^myk1EvlqKdeQ| zx{;`klp7?eY<&@y!R#wLN2mHfA2ikqa%@IL_|NyZ!2#Iuf!{Ua3~Npd@fq+SxbDw6 zsbe12XK^@IfZNocolE05pJENk3Oe6~$-`0)c4dNJSul+>Zo<%9`6~*GKNlkN4rbzYsWWOZ}97graXf(#aB$O z`TBQxZ8mxk|F!uLn`3Y3&wwn;^Y-V64eNFy-;4^bt1e}DXlc#K2+_n``_ICN)=+P> zS7I~oUd3(Iv^|9!cIb#`obHdwVt6+lqp99}kgDPFpN_+6XpRxPVD;sPDIM5DVIAOE zm8S);L$AH$0(Tf3zH#lB`ldi)?IFbsihnv@IQ)NySUVTJyD7f|WhRKV zAT~yC;-$#Ivh}4bGFpHNbu|t9wTYu93ba}wC6@nn`bocw!fIs82?(j&*Fa!f)xMr6Y=p5`EJd-tO2BJgXz%73QKwn(K3P z84B|Uk6)K~F-BM|-}O<(VYIAJz4E@EyjRE}2*}1%u?1=p`jDwbdI?3(yP$59xOEE* zfPv*mW5|kDLO2uZrfCDGaTWvj@n4~t#=hzM(8co?YWrs0NK|La4T}$`@dhwhxzO*_ z{jxQ9JCW&?0)X{B&ww}FcWh-a>%UIoZ71z{@{owDFGv(HF%+uTE`3|cY zI$*E+_DgUN@-cM49`|j(=kE}se2H%;mL6LC+&m1&EZ_q%S@s;_oDqlXI475Mdpswi zs(^_JP7CB3Q~ZB=*6ii-ovk`;-Y(1O-hp8a-q4kZfyK+;hHRn4-MgG@#e4%}2ZOjw&zF6-Bzq=oRLEedx)*6Vxp;>c zMS?cDSWF^86AX+l&!u_cubgS?PsDs7;-l^JjGbD1$_qFMlm{&_Sf{f#Y;p;7{7_%J zde49w_wBOsYB^`J8$1WQDN?y$^RQ>ZX2l8~;VQu8I@oNnJQACixNJ7FBthf1b8`r< z1FYbwX;dhYSaFnk-($l=U2H1qpim_bt^EagAqS zBAzdCNFmJ_{#ZdBB0G4i&?)%*9nx{}aBbo=Bs~E}{XNq1#>iQ`!2I`qt&P?V2u%3!+_N*>hXvs(Hy<1-fVp&1|j3!Kn~ zd-eEOHxkuLa>F8K_IlDNPDqHezoX1RJ^h@PC*73tgu}$;SnnSLTXuko8l3nAa(v$gOy2&#V*W$LxGlr0}2}%#J_+%S3VXb&$045 zd5C>e8T%$P_Dz-uvC88+AJZsSw3Q+&56UIr&m`IE^Lt2i9v1a6-%~r}o0+%EFDckhta=S=AwRheyIHNzFb#1*^R_fL5q+YxC@(yJ= z_y2sp&c6)FqqKI z0XzTJojf$x-KXZpws=P}>QOnf_MMmN@#zgP``^}BA)uUvr}5^q{oCj@Ne))ANF_=r zt*N6xIy`;?T$xlyWo$y>+#po zD3n6_bm)4ry8B_LpgG@9G3_MCH>5iBd=P|CXJh^^UGq1d4Wgc21OeJ)9l?P2Yw>)w zDCa0re%+PBIlg7sL+0CrAECrb8-WYt+i8OvE@--cG{P_Yjz2 zn#U|1Om(g{)fh}+Kkm_qZZd22y5LJ)@V4f^ebO~|t2A056)v~`hN0%a&>Sq3;c1FNghnN=ms>er4WkSx6HyshWUPR)Q^@IL5iH;dw9B{eJwHKRaLQ(FaI+wlF3aHZdIElB zYYeC?9>FHEVH;0bPTEEoy^>?q83^*ra<*=FNPSffK_f@=tQp)slq`lz{1-^xEj}Cys9a9t7Xmud#m%nqdDDIKdCfpE-tZ zJZCqvpbVh>RPA80t6mYA_4oVN59jk$FWvXAt=KLH*KfoP)?BK#vq-FNDXIy(m-4KP ztJuYqyYQqH#PS9dbv%23Gfg}9bryAcAfecH;&+XH4hj4VAdQrem{4@H@!V`1jt}FUFVi&w;nRfr%+|aHxm!yC$8R z2&CRngFnzQ0_pa65hP6cp2CF^eK9Jd6YF|l)eybbW7UxBCRu7vH3(*<|Is*HDG{(1 z4aRnxf$swlg7Cu)FHp=Wk#HSC0j>b;;Av}C9??4pDpZ5?gP2y4d1ws9{Z#OSDLgH7 zVti%E)nw|l35?@G)$t+9skPf9my+X1+o{7Iv_!P_6Il@v`x4dvK6pZq{GI$j6Xb6* zxg2!9twa8@K@}!4SourGV+mEOwCLqr@gEVr{`)sne1CH?_??FvB6_#qT%%11g=acp zgNwZW4W8gN%!;*FLV!#BwiY6XIuN|fH9=0n!ei;WXD}X_Jc-Z5u+o~9;ZR(OkE<7I zc0yLoeYJ5uDpigVrx2TemmD9&zq+nCROX9E2MD)k{6nK;fC^zg^Bb?GZp!9jJ;=qRUy z{R2ol(lgft{Gs*_?Wpz*aFhcn&*%AO?uvidqoj3_IO+M-L|U*ZE8iA)_tL*YEW z%R$uHpmlhvyW(E?eR`&6z%7|>D_4694vii#J-cKkV)3(c@n<*!@--#bO~2N?eEMLC zKXS8g8C-HHw(oh+(1TaT`ljdOD!;^|9==%n=l{_Y;^^Hk9eTkqxS`|?A-`qkjM|u$AhIX^E*>#eY!CeSWRwl;HCH;%x?z< z^;5Tmk+D9?c8wHOS4VK{4*x!l>tkX1?@KocUI@{86PiAM)EP|_s+IR@N(<{=2z0() zI$ve&&w5<@pG?x2P8r4@*P1t^{(T?pC+gpiNovdiSTiJDu;U6ILgYv7da7r*a zrz|t%yf{dCqHV&^w5ksYoUQOK|}fm;Z9jj_1A_m z|HgNL^f4~fr(FK_yDlT7`4*&J8q&o78c0WLNTmYl1{+e5fpiTaJ*XjdC8XgNq%$?7 zTOUcb2J7!Lgu3AZ=>!|nxdu`WA?0gGn>GPbI|~x`a$~T^%{DmsG^D`->HV(^b!Qn! zrx8+n4e3@wdS$QXQ+Ew1=WYXOkcRYc#2RHe_t=m=!FLo^_;db=3)I(QL7k>O9VQ>g zXYab3`yT?u0@}X4N7z9+0^ZKyu+wk!!31_b{&tJ~xPt?yZ&%yJZ`22i%{_QUfFLKS}{rUKhT>QrClDMMHl5{me z9)E<7qrQ{jau3s>GaGD@)pDc5>c_i4aZ13V2ipt!8otE<``4f}4GZx!fBxMdz9fHc z=>-1vtjF-c8I8xC5&v=}sE)h=g}18zALygUYh!Mz3)n*zTu1T_`rDYBnW%5QnJKr@ zaVy)pwfRK31yjuV_{JgWSY1RAF@$CN81F}Sky}{T7?O&Ug#4pn-u6oU7nbv7`PB7q zdG%77e!o=GF8P-7rF``J3LiM6>TCH(+ASX`d*mbS8~L~frL-9tG&YI4+UrlPw*kONq0|m2AY>7FV*Z zAv#g$2k+j-)2UMo57>W4w<0!2kMf87A1o`6{R3rZHJFOpu zo{bP(R3hUovHwK&;L+NB7-^~7!kz*D#fV`Cpn^Mj=zwigQ4oA77YHO*=^9f+X6zFQ z*@$fgYH@eXl0q#c^J^VKvW1KFR0TZw0Ykb1T^GO(ym)O6dE#x?-{a^1T!_de(i+UT zw7<1_y9xYI?fx7CJ@{CS-Yb(s&^t63y}inTUhlBzd4&ET^tu7P3xHm=v<{&6o;nHW zRq@q4On@T))9WYjkxMDiuslBm$%idz&@#vqjzX6lpGLF`5Y0onjhePWU6m5V#8FNx zZ+}K)3dML%CgwT?YpAzf-=Y4q`f5E((O3@kUfP#>cDqn15;Y!fr)ZrjnG1>97H~VZ z5ynI@xuMmyf8K)Mqn>Xr@g=fa&iD?qg-pgp$IL2CPr$MP1}dGLKb#E9+)YmLn=Zqa?-t=kH_e|4eNo87bomQ0))>(B2p)34i7?*P|O9{CK4B6@0Jb4hxPljaU=TDf z`b%knj0tcKob3J=_Wa`;4SL4>4tqI;3#zBxbHwvqVw@kpau|A<*RU5IG3j1j@l7!cTn1I2yjSt;y{Uj(7;Uq4iCY&5REJ;aL^x+ z0@cOfC=x0HfcFE9jW+t$`1AZ_$mS%-8O8^c%*03m|9nEXB@(%*ba?AOfn7Ww;L6Q` zaRE8X6qf=QtJ0A+Hmh80*s1`<5RWVUvXZ{frgSf4?~5?;`(` zKtFgri78tAkz7=={7sd=Uu0q(gD`{u9&rt6c{C+oo< zoNMBD?RbUp2BDXkgZtFgw_DWLPIr_dqoAEsHj^!eTAs zyIA^b$$v!sXdM6Fx+O$Da;zIR|F_f``EF|yk&WI%<-5GRHRPjDD1NU=62)4Xq5kFV zGWcD&#xQxuOAYb+v@Cx7nj#!OYS^EUpsuQK@m_eITmC;o>v z9{&fm{VSyX!!j5CH1vVm{>fjDv4Rg-INDSUvu+r9NjfToiln-mG+6>8A7X#zd?WTt zUo&Klv&eETSN~Sl;}H1PdK?~8+rRH|lvemzMC0WDISV_5KqClGV$Z!E*tBr=&!FD&_U}0hCmZXVts6FfcLm1ZMsh_s`-dewnJ&hN@0w~q z+J$2J&a_}jNV?6sk!|9SJ#v;YL(?Iz82;vjvwt%Wfc+b6VP|u?YbgGol!VB~4YqvT zj>Flse7qLU{xu%|rrN(-EF5hrhFLd^yd)hJLPb(tu_nvIVG;ZHfD!wpD-2o3hqHe( zj6^x@U*qiCTUO^bzVBN%48E>sl(8Sj*w~~l0m>osm&c|XY@*L!nkwHJp_rZ)f@#tt zQ$ysV%V~y@*Wle!T0Z{#oJQU0A8T(q0P=mcg`Lgmsn!j{>7=%y_}^vY|0LdIW!b+l z_@CH#{F^G@4^7cLwyAj5x?xjsmUScBvNB1XtQ)p`|L*`KI=vp{^u{V`OmZ0pwUkLZ=V*K|4qgJatj$-ey+1_*rRY%DE@VmH9VthNE@$GmW-+KIf0fhh7ZTw+3f7q>#{4@D*9r8Rn=kuV2 zkWIr=)(xA60_%o71}B8jko5iany3N-Ekw{;vD6S%js53Z*Kc@Q56XDt0e(SU)gD8b@+jMXHIK~78LitF==Sa0m4B4>lkN7m==SMW`*gIwmhGR@?R)6EC0uN6IW^6mF^Ob^G_0Yx?<7 zwzs3Z@^NYZ^_zzNKDvFr)gEC`N>8@$qubxF+t1hSJGm>zO8X^t`|od){tK-3n6jq) zA8x6yP~E`s*X;{*`@`IoZfQT+Zof*mFSOc2BU7Gc`{#7~9=d(1ZlC0?d>u>opx6^%g__aNWMhYF~u*1KGZhZhyaSKVP?Z zyDLwX_Dk&c-F5p?t9>cjAHw!uq1J))>-Gh@J@ONuVd=gsXR@@XvVAa{{JVb^%pwKw z>sh$B8TZt)8bEgqpoa#~1)FXKKpz{x;~Kym0_f_Qy^$AyaR*^c&@i?y6DGXFkFvdo zyDQHV82^5QOdt{yGz{((5g5F{?F$IwI1S?t4dYG?qpQ2}C)A^qr2#jBf7A=LE);gn{}IV)DZ*VaFl^g%`N}5pJsm8cI72#igO7 zxGOIeC`Z|tRBITE4GdlY#$$vrTEkfVqHtslKE~PmGs^aMcUQUu*w)R4HPbY(r3M%; z0PGJ0)=>kSs(}^rqik;vcje1igD=bR*)Y!3Fjg2Cya0@231h>Z!kSYxj4TZ!)m?dw zz!+k~`1w|0%xVLJ7l82vZmZigjJg+us9pRh+k1q&@(6)(hz(<{hEYQp-61Nx0F0+` zTk4lJn8!4j$2FKE-IX;cxh%_hb(3L9nFh0sU?_3C0GLTc+`~!ZTu+Po93?M&epP=FKP@?Z{cC+p)xRd0T?e6#xWX(Ps5n2Vf;qN!l?hTVce}@ z>?REImluFB1GmZFoqplXU=8LR4d&=+XO!g>8W6700^;_1g9a}Uq~sEf8Cbbzs0cHG zQ(;ydjh|EpXy*!^UC8=Gh~tVh-rd8iqj>cNuXtE5e&5OKBYF32Uhx=UwUJk;`uA#H zvj$K-&ns5BsV8}rqJO9UtzZ?Mx{Fshza&B3&a1=q?=yIfGd2>`4ZKR`)iu0w>)*%n zT25ab$*Uy(K7?0?>E8$Px)bmA<&{*Joxm&BZvp?FyiVlrU3djY3i^2kmm>5-epj%v zOYPwmYoyc{yn;##{k(=sfPP*Lap3&YokCC-Zxr-;>S| z6@d=^u=vBXaSg&jv>bTB4l90qzH285>QgaN>FZQmfP{aDaefc?hp*846K4Q-><<_H z#74x`z|`ZnKCy!$6{vG#qCTk8I`_)&>iIBg-nzeyAQm-me>_*HLWM!)iq_L906xBDV6g6?RJ~J_(dW zS$#v(adzSbGI7S@xjv?3|8}X*<<<+-^XN^*bvJWXFrK4OC0)60?uK{K%->29t%Dpk z;s@DAi5K&s=8#`JKJ$E1?}QHEAoh3wjIRG3i??F({QLsQsM(Z>%>uF|#ozBW&Nm0_ zc31S`&pZ#$Vk6%F@ zI?e#RT&%k*D9b5YN3)9(#JQFXdkPJ+fzSB5V*p?7P{LIi%M<*igolSuQb7>%d;lIP(0lg{mhEE+akE|t#p;VclA-XEZb^;q5m()`VAp;Ujb;Bm*? zAdZR)L4w_|)Sw9MdX(U`gfF})pzE%rW`MyDuLU_(C7p@jBIyV3vPscA(sww2Q`J&v zz&bme*H)HuEnBf@lcy!=H!oOkB`Q@_)}xpvW9yQXE~Jg2{#r(0_WBz1gPAFd8m=N9 zp}+Xk@*d^HHtBJX*+0Ecj#SNq)M7_dcfE^Pi=&pm8Pl-;#9LEWOY-wcet{Y?jy{K9 zQC3n=TVS7-VNZMQ3!a}|kD?lF!u-%cn6Nn_gwJHm;wMa)d}25j$$cCsF1*EwJMta- znfd9PQh>TSDA%hQRrnq6s%g@$*e9xBegifiMZ;~pE9V`*#c7Bo@YPfB|~_hj<*Piv)5DD)&W{ucexVA0%9GkUJOu=0+htR;h!$pK z;;y3QBBq0~)yD4o_G23d72n)i)|LKHN(`;Dobjv3w@<$hk@WE0N#%0(dQ~;UAMkYE z;cm=NZqjcal(7VmT>S9+2k1bt|8EocjaI8Ugs>W5Ctp5z>?+z39MEi?AnkZT;9_#> zY8ENr{h0$8lPuKdy&I83RbsBX>R8xmj3XX~b2slD-13?Q7H3?rLvP^RXMR^-vaG=G zs_d00U`e1FgA*)>;R-geI5+F2?1W-h-|ba6$;Qd1-iY7KGdNKjgTz+l+chQRQSD!G z0|y8AU4^K?uTBPfs()!i{v11B^QUKx?tLkH2R#e`p(1yDZiPT$Xb0?y>`vhBV89;B zbFdrmVg0K%9|W+25B#n^;~Kx;^*_%KNx=EEcyF{n>4ihVYMj7SF$$3@1Od1KXxV0)dS$y1F`>Y?C*S9 zbqv=N&hL|`YM z2hahq6QU5-;BAlC!+=-7KP}w9613l#Qx4FV&F^;#l4TgHme; z{1EZ<1wH?BSLTyFAvL-zDgy7e?v@_>nWR_m{2?uV?5#^ zIM9i#oAf7@U1z-cm{W~6=U{*wxbl(W%J~W}xbprhXp9gu$_{mSaisA1?n->c`3zF% zz+SokfZJKaJMVArM&DntW)Q{>VH#vEY23HkNIIuisHRlc%n0(_Eb8Kc!$9qDqJo>Sw_hsy74L77_ z${8{5$cEH6?ZDW&5d4n~T^l+(5r>3)%$YF&>dcP%Edg!|*WO(zhBv4_78BMld*Tfi z%(AG_`QPERJAabD^O1T=)A#$K8&_NTiK=Z-#+}%t3Sq^mF?A_=gsc@+MEMZV)uJ8< zE%=QaAh09PyG``7=L)nh+t;onad!4K(8gg?Xl=muX? z*r3-J=MbNu92BT%v(c4Moi3REQ!V=t$IxtaeZ0_=IZ?B|BxW^FJ%2N$Yd7Tj&gKM}OlUTvW*^3DC_kRa+H^dZsc z53B~1UUv0Z`^&YC3WwAuqb-)yRa1*nMT_1PE!r4N|FjX|;om|)81YMKZKd*bW=2-- zoZ^h^JT1tu?i|r{4z1qc?m&R;v{#TJVmnMHu^~u#3}yi*A%o>!&PM<+tM-o|-^SWq zF%@5ldF{l|(QG<@)?OSBe+;j2>;yJ)5v4?7Uxf$m(Xj$%VaIL#Dz>bFn%>_a1Xz)e&!~Aj> z{W(?e>QW9{rO$qAAj7a<3obNbvW#78HQFFuuSRbkUqWqaP2>PaYXKg5G5kX@+oS1@ zjgjFuL;gn@!lKy+=lC~O{(*ih`8T+xw*nEdnnjWF`n*OLFkG05s2iwoL9 zs!yle!acwsqR-#Z66QRAV_I|Mcjrhm%n{|c;PuGzWy|lk;UA*>Mr}|12;Wq6RpgiN z7Y@U}6SZAn*pQpvKsQwzo3d8|nz=#`O$o*Gz9_>$!pe5bGoyVIfCPDanVl)k9aYRe^qTvmvyn|KQBD}lcUlPug;T( z!gU>%15-vs<3Mo`2P%aFv%rC7+vk15qsq6y=lQE)yT%h>jS4LUC~BSJ#q@5xPf!d zeoykjD_P9hh9nsHvolT3HG`p%919mmc#s$7w#W>mV}5&fYB49nhpOlCWW?jTzB|v! zIhjAmKni|Mnm;{aAV!@(8U8h6e(=DmSjwQf8(cyxOAE{o7Q7Z-KGh>bog8h}{Gd7U zOHYGFUD)_V#<%hFkH-%)^N$&SiZuTibb}qD-RH4*(dhXH^{>7%^(w^0dd7w&5^$a=Nc|VmcIiOUnCn;!t$VL@kK28 zh!TI!KF4q-mV6wL`16~=7CK?M6Dj_reif_;t9s%;jD2r*eDz}ZPK5t09$%e{&YBQk zE%|*E7B)S;%6>UAe}(?$#8*3)hxcDP(}ai&fr*`YeCzC31U4nU$_5I-QDfj+{PNRE z@zsoO@y1sp@nppKYTh6x=R)GErumma24u|n>jCgD%W|FcHFEym9RD)VbQ~qVIY9np z>F=WP;DGy=UIv|*@^L`?%iaGIjXTl&Oa1dLVIN}5-$%U=wv*QJFQ0>=Cis^TIZ;^H zbpNtrX;{(&^S|c!ml*&a_x%0(vtkk06#uegNo4wdasSe@bG-g#Pf`^Ba{53g=i>J- zlAuJ6G^;_1PJMi)1u~}nVEh%59}LQG`D78e;aVso3%wS~B$bC=1F4^(s9mjTfR3K% z;V~qVf`SssZ>iG_vf-lFfNIp{S?QlttA1AJfBt~GlH9r&7lGgdSFz%Iq+258*B>4b zFaHW-@K1_uk@^AYL2Joj_@}e(NS|dlmV@79J0&Q@gF85QUVwwBkBf_c&GGMJ4O&tB z`;{^HcW3v@XlRwT+S3DJ>)D8_d_8*6^Vn2O!BNMU`AoVF6zmj#b9PpY0tbJ+cr@jr3gxHq} zkYA*Ao%Ihv_VYeVem#Vi&zV^PjbI`5e>_d z8}={yLg>E?^ux9}>o0=npJ&k@19NND;2qTg9mX4TIF?6tpB9${>g5rh&r2nik`H&q zWrq3-oz(04hJq&})87>Nvu3(+$shUau6&3L3|(W8_FQPVQ7<%Lk%5a1Txj@X=t6@k zc1f6$=U8Sard$k%lwiGKz`3a`%k^{cC1=c6_Jr-UURNJ6Ff3fw68Ce$T zQT%&uuks;YDim$GAUG9C#bnkXmWKGEY`=W3(P7+z__dSrqe*QSa&bAS=Y)w zDfawfiW>b#>7$YL*S7Cn!RHX!jH^B1XGekGjQF$HsfM$$^2-MxKQymTcnNRy^@pCO z<0$fVfbv6Cy`%A<8Tlc;e-XaXtREZw7((H+^n1+|Y1QxNWx`Kyx|1V)xTex6&-R$*^cfxlf{B7~| zjdAEKI4BHtNgNPeZtMtIrxvGpSb4@Ks$(BGW=)4o54_kUs6H@-SC7J*I4 zKNSE4hsp$9#xFmuw7#)m-x|Ib520GD`jH#(WW=CtS*DY7@#mi~-;R_&xx#>qIe$F> z{_EWnob&}Ev{v_DV@=1uy#LyEd^8>$6#lDsLll2q{%g{4QFz=$|FvR%OW2nB|w z2-`{P_^&5GQ4{=^J0mXUHr9X5zdtPLV&|LfzXk$$ytxe3=h#>THpPFv=pG(SLo{%gMR;{TKYE_^&YQCl4EtG5yy;uzvDgx|9A8|K_ke2XOu53WHKi z{UN|~F4mK`-E%u{1>nA-8T2bPMgJk`r=r{3ku+i%$EjK@YGpzxN zal{uzG3Lk5%lsJc=*z=|eSF0Ev11AyGE;sh&->3t&Xi?G0Q>W(`lA{U6>(aZ$4&CJ z$77Z(S%E6Oe)T(im)!puxColxaQ>WK6>`(@gz+D(zWy>bJQAW`t-1cP@6OOrCB`a- zn$S}ZM~kh$)ZY=A|3ZIDufN=m4&#kk9O;FkBjcCD+D5Fu?C?jXzbW$fORT?qS0`ak z^!1mm`k~nCFHhjXh@lYo-W*}9|oP6@y~(Ce{_$=n`xFm(0gwi?9XgD|2wQ98gcmFgD5{eHzf)m9dUMJ^3yx! z#I|qE&QG7_4cm$Mj~35QZvaJ2nBSk;EiUFZc7DI&_OPV4%=~^VfXC}A)$p#d2yDvy zenn+u`iy^!EkCW4pWgRryz~3F@nl4&*6na7=UQZbzov@?GNye#2dR8W0uHFEu4T%D%B> z{gYLR5m)`cU7tKPJQA%QAMHbKuyOIxgtmG(S}Z=QFNw_mR*8>pM~Cs|bR6+fQJeVX zurcw`4s5P=EV%_;{#xRr@3zMgA8pkS#g31jz=ILvquTvANV!q#A5r2X?3$ALklY5_ zG1Y9-PfY(b9_z=^_SZgV?T^A9s%ZN|x#WuyY`iju@l8H4%foThZ&Oqg<#h6pa`12! z)`4|nu|KN%XD7EJ22PI2<%wpofaiC|T0a*3jKbe2@nhaE2leIOJ)FQu~1SW9(~v{zj4CXzPCl zvtLGjn_LMM;4bzzs|7!{K7U&<|F^dRwsFL_#WCu8Ub5^n_PX%pNf1Ho z6iXET;0%p(}k z6L$6jEt=_k#<&Hw$5>|C+97imzDkMDX}Ac45UlShnB=?@_>EU4z5wYl_g4o5hxnoV zU{G?EaWb@I>!SL<)_MY%ai2t|=fAy=@_+V6`?XS+m+j(Z;(LBC9iB0qX z1@E`+1UwoQ?~-Z=0bc8;CjX$N594D-oP(6jL2~T8<{%YtkP64?_cO2*%i4wA&kWNk zdYCvq^%EnHj~)L*lp^lGHt_{`Xm2R9cWni#(nyI_!UoPjz7UM48R$GX7Dgmd7ddY2@?wJG7bPC6zoLDK*;+&#(uAPl1y-rUbX^H0G+MS52Tl^z!OL>TGg8P zB0Zk?g8W%AAu@lOC%>sN<(K@|@BIz7Avgop?9X;r$m>O92VY>1w!7kPiXhl#Mr9ig zgjHMc-dAkrxyiAeM{mIf*Q|Zom#HW9Ll>HdG&8Z88|Fao(=N$Yx8b32Re;soJSK98 zM~3I(vD|SMe&=Reo4QA$LBybX-gi#JTI(`KMC7kY`?t?F5L`uxTAZ&!a~ksdkzb63)8LcZYyV5oS;aTfJT z^wXSwO_qANjeDeJ6gWeXdwfZY{qhUEA;gvWa)$(U$mxM|XT@H6v{~@t9bssyJ*9r* zje7aWhI_ze;IKb@-=6S8XPh8B=kdmh)PJ2|xX(FGjzk`>Gc)rb_VICL& z6wsYzX{;CuP)9us5Ax}PfT_IF%4`kCLHOgUw4O)CIP5;=4iTsjMh6NxBxfP(V>WT_ z3ZCyGaq#)#!bE?sh^+r6eu!N^6=Q$hi{U#F{4qwDjE-( zQ9s{u{wpa0ioY)ZHROvZjBdRDntw@4*q<2w>)Y_1w2uF(L}yL#UtfRL2)@Seze>kM z=5Mq8S5E*B&aXsv)v9w$0-NH$N(&;>_lx_l>gDnJuelc3z(dy)sHuA{yNB@6qA1kMSaiRAIHbRCe-&dCw|!Xk%d;2 z_~9U_FUvQmhMONdWU$foWi1z9Jo{nzL5?0@uzoz+{MhUdFXH?dNwjE-NQ~2wpS6~b z^1R#{&MZP!=uA18aFD-@nTA(8KF~xVB@t%|-s}(0ifey(>IJd=M`P-Dtw^MC^--h3 zBO(5|HTQ?_92pv_U{!>xKNuLKLd+ZSm>#jt=N4iq@4_`4NGW{lgX^i~+67}QnJ{w1U)Drzr?E0um zJQy()+VsE9VTh-GygB}9tm!R^e>y<<*=_%H5*`u*H77sY#Q4Xc6Eprf0Qvi6c*!=s zPGUIU9P9nPE$4rGM?fRG|2^39)7QKgg_(gsC*J(@3WSt_jAHPWv2V@JPj^K=JQ%cm zYn}Q16QHOG^LzI{8o}52=lAo6h9x~fe{=HF0|7i#8-RvBO zc;@#}{8O~`57SRf|8x+P!2kFG(7O^A>3*M(QE=Eg@WaB6c)#^=98eDvjBy&ks;Z)++nQ2cq-fSUK*( zHOimrxkB?K{>ht(KjPj$UV3t5{xna15B&b|xn7B*qwgQTMn4pN|M=N>s8RdJyP!eD zp!>q*PQx3rf4n*I$-b8?z)|9p15{sBWKaoPLvv8z78MW;u+Llksiw{k5NiqTofr$eVT? z3uGgnkBhmwE-e1~r5%XT!jLYvg#PB#FU{DOlXERnzx45Q7RZ?M%Y$Hj?sS7}IN#~8J9(BhM{;QvW?k0# zgMYwX+0=hAE`n4+FQ&zQ;dBiGP1h3&$sK{pr@i>X(3XNZb`>f0K21 z7-ss|{u1q^F>8|(<0;t|)6Dl@KGlGza50M`MQ!+>8Q1=%?6eT0;;=Br|1_rlq)F?0 zQ^O-6^3j_6oAwD<wDjo#<9M)RX-GaeeVf87%|mQ`?zx$nz_Cgt^UdM^J|E&-hIr; zl*qBc0gtZ+8pNXHZw`|B@Ty1S`@IVPuO{j#;|r`9}ZVHT6W2Xp<@z6V;Lzs<=Xjy3p2iEj_)`l$u; zTc5uzmtXwy{_xmFkAHt%^*x7LG{*4%EmPmq!uiKx_ca)wIO5~t82QI0y`Ljrujfkj zm3do3=+Z8VV&Z!tlPbPf6NZc?TcC^!nFE~K#N2yx-_NlkF?M{?>h)FMhDSo=<3QF| zT?;%K6)!vLtG3>w2PtmNiLbt@phM*GvF8u1RbREUeP}G*xcaKxB<}jE zRG{ccnFn2(__}HGd*JJ%ltyiJct4F7*n<~OgK-9Vb+ zh>w2-`OSH=G-0ig-`w$S?D(W<`JqO!!)?fzNN|jff+^d4hf@ zdVaGl9%|J7(YJ?33Cg?8bQ;!>{AQH+B}#q4ni&?zUv>PwZ@QB)2VeX>*5LOmjlUP% z)cX95BEM1c%WVv1G3EDQj=u+%wmyGbF8=o47#`dIpW^SQrfC{~jq&%FB@M>s|Bv{) zn?+b_#NP#~wc?jX#NYRXN8*6T-<^O*Q{(T+QyZx{@x|ZupGO`aJAdC=@%IdL9-PZ= zT>L$Disnfx#@{PGi_D*2Tl~G{_i@DEPwI!F$KSW%p+?2uBhesYQhZ*K)3C-Le|xO@ z-u(StWI)D@U;1Kx38`aqBpMUVnD%0{TWF3k8}IBveL8vL{<^h+ zyyUx*mwYQ^cD7}U=uedRE6V&~HoD-FS7Nj9&o}rN1mU0282p=)AFsaNP!V~5dj$B$ zS+k8U9^arukMF$HAPTMo;Bi%Ts{&)NO~znz&=|zxf3*15#ynR3Ihy?B8vc8Nuz&2j zM#xXg#h1O&t;keJwm*7&c`o!LWc?QVvP;HzyyY2lxOR)9-XO@ue6b|lD z)NprI=rMDJtau#HBkYRg{flbBB#jaDj6Xo*it7F(=jjCA&v?HK>|H?vYkiUNZMpMx zk}PZ>ZkJ}jrQ~I##u4A0*RXz+{25OE%#yY3g*Klwi@+<7&7{z(P|YJX`&uVw>h2{| zGG!6uN#V!CWC72|tN$Rjf9gnDK-C~?^OC@+6F8rRO33LV zs5R=__e0~5LOCC9-vkR6onJ^73^oV`t1bS|M^nSE&`;w_Z2misiHU>%#NS={UkXvs z83`U=vgn6rKv#FgcK+cN@u6R`>FK|}EHjnpPwPhgvzq|Y|(&R!` z5uc5iznC=@!_z&!OVT|9&P{b!+=}0Y{sq#YcnWo#597an7!5ATs>0KmB^Rj@{ZyWL zN~{4vLfkLO#Y5R8St?&YWG|n445)lOl#hoz#qIj8t~*qnfCnQ+3KPfc0Z9}Ut=;)^ z;x}G)nY%e`LFfZ0CK?<4aNx4T0FE{F5Kv(WzxQouzqu zk9S0R-QgbpXb@13M^%4TGI%$7ynCyv!H)gA-D{56|3<~mV!*6Xdp{yEJY2GDeX14v zoionjVm$IO?PSOXXfp91d6%jlfnbq#XvZLoJbw(tmY@C6f?u~PcsxSCiTw!+|7-_* z$YC)2ipIcqS5|5Hh5(xyE7Fj~^K*CpSCau{9F&Z~J$cNU{Z)Neld`OEqVe>J^LSUG{IT*k1e_DhUK_F!=4Q@xG&`f5-;>3UNmZVo@B1A4t+H+moz%U${ob+Hv5V8e@8>dm)tjM*m;e`r#peav9_2 zl8S<%8(#4t95$2@~Q^@v<{7ttHOr&GPu=3IP&9wt?7xyntd4^`w3E3~+72_mV5g zy+YOd46z~S(K6wGHM@{0AKLGUG?vOT`G`?qlz zaxn~^b<&d{=<$sPxId(OFp9kaa{_?Dey5DVCk*eVx^5otHuZErav1b@*GSXyO~t2r zyhEU!MXRXXVh_M5sAvzE0&oi|x|KZ_swJ!*fS&sPkl1&%YI6l7t$a231X%+ygA&#C z7p&PIglSa}s(x4RsqJ8h((XIshy?ZUl=b_o)Yx(BWyCFNFg8$n#v~Z8)N%OzN=v@P z9f-o#b_nbEM*Y;aS0FIoB$En`kGT8y#NEH$P`a%7-5&ry zRJJ(y<0(pztQ{Wj8!%oT?+TCY96`uUaYm+`ZB~0xINc*X!k?MIABY6m4)w@hE%*`aMA?o;+KCH9 zQ6kt0HLuW^iHSj|5aCAg>#96X{t!{-gnCbcXU_9-nlj z=LlRS&6qzVp)6-vHD&iukJmL7-|ISi{5cbG0r}Z^D?0YOE(9=jrv%Cf#6|fDlk#0 zN1MQcrbOa31|AnuPR>L0adxT|H+|hVN?`F@;1iINx=Jn0GX7J;_AeHm0g>Nz-^bw2 z4X=aK{-lXy4mb>@h7x)b%W_7)VjBj?v?saF?eUi;i-&=IBv&vO^t*1j1Oo#8IBd6Q zvYLOn6SLY0P65#4|0Me?+m%ZmWs^r@t_#>apWO0zd{YwTs8LKnft9f4COlLRV{%m6 z&Iv0!l96AJ`gXskY+vHczMfZxO`bks(xfX+^$bWZIfi@z3_|lK)m_{<;cwmX{Hl9k z$<-@)_516Nwp@@tQB3p`&x=``nNgr8aM`f8x!UasU1FhB&&!;|Y5R0SfI?gU8jin% z{}*4|F+uHFN6Rc+2h%@U0j7_$;xn>6ky2eMz%`Qnb657z{xxWPWN751dhoU{WPnz%?`Gh9Sq?Uq>usQZnXf#<(`WD#hDyq@M)jNyGK>BGe8^-h+}pFVg@1R17h7^j-7tE zn*JUbmyQzD{`DnL>tLalsXlrAC+N4q>yw)Sr6-|ubmCRjKpvhR+fW`}4*0839&7o( zQ1cf8KZzpBKX5N#cOEriunt_Z)SbJ5sLzwi`(STA##<}~A`6f2MJ1?L@8(Cv_a*Ks zk1ywD#e9q0Nl27D_@L8oMya7E&=IA3~l54uRQ-b=>-*|6uMrm12?J`g2>taI{dqp~&=k;r3Fw~=`iF!5ty9P30m6Jj0R8PO`rp#@e;7>v3lZpN;Q$k_ zKe8VIB`lC0yysc;C%p;7nCCsrNxuN>nCBe~`g!WM8cO35L=QDkYdoR|G2iuylY_ z?qweW#-b8(YRT9c`tN(l{AB?oM)NZ{KUGhI!MxY=pTraKkXa3 zC5byYe}x@Wk8FYagQV}!)K2|Vy99MTJHTW^Jd!`fSUES}gO-9UYMGIYkD zw&Qz%?Fa~}>(RX7+Oi3Fo*;Op6bhcnWjWo$;7OC7XfRh7X)KfIBom2{g(dKRBM8kc zUZA;grAAY`*_6xw9tlm*KTspu#YS}EZv@d}fvEUz!t$q_Zg8FW9ET#9r@^>B#VQ4V z+7%2EoVcp|U{ren)hgA~!qsBwhJQrDRo!)xuyo5$fXf-0*jH7ZCg>K|aQs&Yu89WM zRnIoWwZZtae!!oWxC>AZb#PWavN?#cQ|EB}*@0vHBP09iiGu8fX24Wejpvq)9Dj}H zM-VND55_+Xp20l5NMreIDx%C}2bLKBO+jdGxt-(xa`5=S6N#rBe~suoL%*7MlpcQ| zD&tRB{*+|~*NM+Ge>W1Y>aI*-=_fx1kAF`+ z{u?;{%LUgt2G>TFLQe2N-`b6#kSG|2HDCpPnGd zo@9_!T{WItUg!90JPQq;-NWD+%+rfBmKPxeS=l3a{5J-nxut^R|5EVyza0rpj=x6q z^>4t{j)1Ht9;wG4h|2gA7WCiXI`OX!c^ZuCQ>%CG`LGAT+m> zar|G@Xj(j-5_SAFqG#1xTvZcO_4or(8Gpip{u^8;E^f%vU|gSKje$Sys{2DZnjeg6 zFQAI?w{W#o>K~C!>RlPa(%XLs9{(PC{MT~)Ul3g97+hC9*$~$TrzFq4-R7(bWlo z?hz9)0s&Sjz)Fo-14R63|Aev8plZ4Yfl972iHfaf%aa#FEUiiNt1_qb_?F2WQ+@S- z%#5m=BBYmI&Dd=&642V? zTd1e9n1OIAEAy8Hf08k|a4Zu0h^g6t5bF8KnTpj;dY`PH&9t5sn0Pi(p3%Jmo&RCN z=6JTpoR;ubwZ)&I$n}iy68m|YW^cC)LpL*niCA|?K2vS!yk`G7?$P_N&hwpqTs>ps zvY8pF2{X^e8jnBi`mRSL=uplV%sEUQPkbXOVbDr;m4_~fcOK{!ykB;2*k5-VSBdl- zo-=Wo)BAHi-jtNE3eVzUO>7>1lSYqp-T+=QHG_G55kkWox?r#mTS|5%eRdiXG9JVR zKR!komQ@!_fjz05^_F5C2U9QMZ%?U}khLr3V&4cnUW6F9st)VD2xw7NqxP_pVP(QI z$Nr?_Tu(N>ecI_lk_5<^s%lcbWW~<)co$|Ymb-&lk~3FF&saZHy$3?VkSCS9d_?v9 zD|l`t=iYe?CUmw1B(Sx#U^+8CW3^7)yU`JOyOagd4v`f-%zBvD9{)^cnf6)>+#OjvvI%c>)#y)Y$3F0s%|SM9agSD52!Ooy5ca@o?@GiR zM!j(>S3}0l@72r{K1=yVWp<&@9HrrK$vIYd_lUwnI>Wu8$czIu|pCU zR3HbA0u(N_U~EeXLnPJrf|4iirjau#+muJH8v)!M08 zCpSvz_{{TPov}hI=WY(;>|He^2FkgbpHNQugp7W~?=Uty5EzN zNP0@uc#>XB`C)n+gS}1K0NEOKZ3V&d<+xBwqqEnOlNhzR7RyEgWt}yy-hyAaC}n;cnr?nV5*+HW85y+w+vz_jd*|u( z0uex1VSs^dse`Nwsov;Mbt%&_wHjY+?83>=;j&{nK} zJ7kBKl%F|Te(rUphiQO4=UP}8<{UpL5%ncc zXwDQ+)A6if%Ok5Jv*pWnnk`UgvgNV`4z}DS3+&QuJUlrj^9ah%zGKM^ON?i)r*uQ7 zr^CrjNjFSY7mp=HmQw@k$mu-a;S4~@#X;`n=ffDT%R>P3Mlsyr<9B}r$G`nT?f9Kau&Nl2 zf8}FDr(6d^0mnbPgXQ=a>OckzkfsoN>d&z$9Yufk{fyQP-2c@NSnhwW6=Nk@?q7db z6;jeL*HQ&-nTdQgqdRSxHC@^=i>6>Og+&s4z(hkTb6GzR3q6hA10#&71DS|%5o;Gd zK$!hUsDi)W#4GFo;fIodDS!HOZORdRXlQE8Lji04;o-36r=kz_`t~_X z&)4pE=;t0;dB+N!t`Ui4vu?`}{T!Q4hKJA@`aPVNTRSjmB@^lNW2{(|2QTo^OaJ&r%YIa%w&2F5jvm>LsL1 zS}^*+O0+aC7qL=BC4hwb#bY5j1K#5z>o-+(2&%qWg{KhoxFNtOrEr(G=LJxb*66p2 zP{4yiJBWpJEfb9Me3dj2dA>V{|1fwkcU7J*>HRB*Bw$Xx;c~9@tj_bkp++HqG(l{K z-%>^cdP(@|1yo{kQil0&+93-t(d>o0nEy+64)ELS{%++@wgzA|^ zaJszkUQ3V7Y$h4=YaPb3DeUu3Rs$gH|Bf`HAt;kTeFG<~Ab45EEIg=A2R4!s zp$f~z3S3ZAXYmtE65Tdt2;(TfL!(#ocfYIamx=h$CO~~YjiOHr`qM5T-Ty>dP^N@n z1`vn9OOwnUYza1fB%j(AtEbbn`Fu?9#nhcYR%|M6k9|nVb*_~%z0_04c~;9yglQb6 z{qIPqU>nxusK!w@jnIab3?TxT)VlsSxt$fCjQtByE!UAzz`7obqASc7$*l2#;X$nw z8rQfnt$K7X+BLANht0F?>Ky4VU|0EF^&Uf|vVvuwwyQ*({bXvp`jLFqcGdh;%1|bs zaW6*Dqit#l`B+4Payd*CPfw6Rb<6s_RVkBla-mq&ZkO6t_2Hs`#9nl&wyFTdR7-p2 z$*iQvxO&LyDS)na->6M$4ZE7Xej7ee9|T+CxDhr>qNeo^Z%a^LSiR3-O>DDbU(mkn z(DtR0ZhrQz#q8btOvWO9!oJ97s65(oTCb*a)ebCQ%IAGu7+66L*Zs{U?Og+h!?^g9 ziv9*kS@JcN3)1Alz(ZV_-{?7=-LbsR`=Q7C7UflIh9&usV?tKn9;xMao5-!yFX>3+ z6;9|dIRgNrOqR3(=_(=tB@)^6yE>n$!;o2o`0!MtL_hRF81l_=T8RpsM#_o`LXcA9 zfQ+tRVSLovQYDSIjzm_Y2gnf!%eS><&S&7k`FYe9X7og|{H`-6AqMHUkhm}k52#4O z{v_ZoDgt$u5R^4te%Io|pdV%5htrQ;Rn(8e$dB>JIbeT<&hO!?>U%MT#FSp>lmpSE zZWOYEENVfvmi|1Vmq`^UU>iNSXD1sATyct)=S;RMP-ony<+(d-@35aB&z$gyeyE;^ zEhxi_*wgIwlrE9!sNcbfL?QsMg(_~HS-AW3@G@RIpy9007H`ZCAIqpmU6vN{%OI2x z@i`nYi1;jiLd4}0{%Wz@hkuYy_!s${Yt?1dt2?>m2T_;bDeA^*+tNPle3ACsUd2eS z+2xRSopV#YZ)DFh`bOHN698Sr&gh)*sa&ZR|0rMg)A9RVdoG8R9`+ywMT@1lksai# z|5a_OnbI(kyOvMKoV7yg)~-V*B1@FhG3lgXH$gyI>iH=~b4(WR%cKDJ8Hu`=kIbGk zPo`{TIhA)%%23WX&x#e0vE(dynP6dKAo+v9ocSE79=$FB`vT~?tlWd&bp+|^mVhi8 zxFACylW9t@o=KN}jV#PNqOCd-0W-?q>jVMIO;G#hlgnVA5CNB6>nCzZh>HqfB5jqu zQU&^qf(-f7zVPW;v>2BEeP1TfFOG%%wkFWX@q!`Pu>ea2>9Zz?^X0CdJ-bfh?0GOo zY6knqh(b*yJ!)o&Ghc8-p=|1yJa7D7m%|k3D73#|Y)zi89Z4~lz5}yFEpV1V8d>pj z=KRwUm^r_fqHW{lGEt*+!C;X%#3utUeL_^;+SAwxA8vqhn=X+D<4y5Ur)v`MwyS>>Yj8x%bO!0oU=S9E(TN84mh!Y z%KtT@88G7VsqHJZMcda>+rDOg1g)z(H#i#MTE+h_9WA`0m&piT8^*IE)U z0kDK3*^W?T={aJYKU)ql$@l`J8VE(QF~87*0#I5>;JN7;3)D@AYwcQY4I4C_fhD4Q zJC7<}k|8B-Iy0!O|CZS~ovS!hu}VQ%{ z9f7fZaUWc-N*8 zbguk_a4(WiI9d7BlQ4Q6Q8~1>LLqp zfdDpE#4=TQAT$)bd1sR4KL(y15)YnqC5+W^cN3N1cyRZ3wxtS=2j{ninVQOIqk)BS>5!pH?6O`PK4VucoZh^1Fz?>)?=RJM2%^AQ9m|A~H~q zec}+|a&ZYN`8qyMyJJs z6=Q1VcV&K#c&coo7ItU>{9btm8>s7{1|fPB7K3rXK*yK#&reb4{jR>RxzHsN5bDWP ztvQ&2Sc{hMMHa^pnK(hJo&ZH4vV{feuYc5>sWTr#Fw4*?LpNwOccbDpGY)i(m!* zmfnbHfN}(^!Lz6vZ07`rVP;-Vmk$4+ciN=XjS$6o_k3gh)fI&S#Ys8Zp*V$V!<>N9 z{PVw18cE46y+$jI$iVFN6l9%0aNH0riuyf_7OCzhgjXWw7s9XW8W+)W`gM3USODZ; zvyD}k8Q2_<=}@vaazx1zme9cFVthYrsAx}4&|)4#(WL#1j#@rX7bTNgi@Sw?2#05} zYrm_2T~hFo=Xn3Qqy$NQsI?yib6hbE{)KM$udQ)Wfdn3d;fPoojl zo@OaI7fxf~X{>NAg2vbi^Gcp5%%igPRyt z{!2dLziP;G_^)m9X%>SQW~`R)_3DL}wSK{in3XQkuSN2^o#D9lOwq4JPh0x6b7zp4 z^Jz6?9J`YA_lH(aZ#AI+uwVf`(u<1x^+e$y?f*PWzY0A*Tff8=W1)a3=lRaf#U`W- zPo8f$7B8$g(eK(hKr0{Sc}aypN-N(vf>ko-taGI2BIJ{J{*>Q!(ubC|TJ!g-h`)1E z#`HewA*GpKNL0&j)&yaS5se^)T&EE8vi68aFV`NiK;7F#E4VnUEXufeM2RKP`D*D* zb4ML&0lCsraQ&n9h-9Dkh~sUK*cauy>bw5`kG(ICkFvV@pCK6tNSvUcL5N0;8u!FC zLDMD>;2D@e*d!p;1PCOuBxHersKEqe93G8I-N2T%wo;c@tQ6U-VG#mY4PXJGR&c#B z*cY`Tf;GSI_uS{1c_svq{$BrUKA$}EEO$NkoO91P_uO-}+AGbrCdK_DF)8kQfb^~B zcgMW=yU#-;j#`}#axYbXm=m5K)nR*n ztiyy#`drG!&DppNKYD(2yb#(y>2q83d-#GA((mmjpC7e;8%^Y|ISA~S41k!t*h2;h zb3WT^V|-{??TE(TW3Otm&EzO*f_X#<^aF?ZGgtdY#RmHme%&hi5PsqoMH~z?V$-$y zb|e6UehKMUOJ-4?ff-|xGHpx#w3|RU*gO3k(Cw4m4yuQmqK1!U8zVF@X?6&;ED7@} zFe#EdZHm-NFq>QCPLr4E>C8%4D{6WKHED95F4ci#K*qAHh7`#}r!=()k*Gol9CDA+ zozS3DD*;{B`JnV{fyEK1!)q-xq{iEy^x_an$*Ig!mCq!~f(uZrMMH9Jdw69xjemGc zd-$dIh4F6|ryEhqv?uE3&qm-iY7@;YexuU6wOb4dpl($3dWOlZ&lfujpJNasOn4SFL zY(1PPf;cvkz7E!M-Lb!6IIl#1Rn{0ioG0EYPW@tEkG4mzX{;Dlj36*N50g{FhVY;{ z?)3OA68^BUn&Srzju-F+&Fd|y2VYpiQNV(;urIUQfvD~-#P8W%3Cr?V;dOd)7R^y2 zOYqjNXMV2VuabghlM4x?bM18>dO$yTmWE9!VN;}TnH`4Bg1Z5m3z1n}0=CERNW>*~ za0srqTdQ7az@d#jXh6?|d_ISqM0gPw+^?KYbP#uT)E?oVK7!L2YyTWdA zmH+N=ckfGrDK(wly=gSNYtN#3swOXr+a#Slf+!rx!@Ptg>G9@5xrdTz=EMWt2) z5=flyn5Mt~Ff>hrm;|0!qC<{n4^e#u{O;b{7FB&*5u&PmCspOED|>C0cvZBQqQDf@ z>wu=HOvc+lL^z5#7GtDb#BQiv9geiD1V}-M#J!q>)f>2*!M&+3{f6v_nxn%3a7XIlRK|b3kiE<|THwxN z*&MA-8G&8g4UZ`!eVg~815&D}9>dAti4wvhgIya)1wiDdHNEXo#zX>wDa_m8s!OMZ z^xb707)hy0#|OzI6EX;vB8=6Oaab0?j0K|o616I02_S9`LsrgnEXWtAm(9UUkLDVP zM&R)U#-zmg0{)cv9J6yuj@cFeLqQ=O%Q>`Xb2+IrC(t>?7syVD(a!XN@BHA1D6mx3 zrfqKV2X@2%l&%4RcbdKdyMcimgaG$VNR7?fJE<#wNiVwcg1FZ`a18tIgml9N~8@myJDmy7|@tqg21Hm zU7!L#W)IWz!F_P9>Gcdo3#lQOdH$IV@7;j7Nr?!R8^bvUt0O~AIp0XD z$!IBMg`urKnX=Legz{r|dXg03d3|FPBQ~CMv|jSVLg9IEFm}Sdc{f8i{zVEnTgzeC zrw+^kJo+UgoDr2ENN4ary^*MZ4~UeJ3~EtZWgULD7J$+a&cjO*NFnIcSa&iZ3N5W) z4Eslbn||TOSjqRBKEz=_nw<28d;1|xVooqOJ|~!&=u5Bn&fAZ4Il=6sh_K!DsJ1U6 zp?BWvc<&1i-wK!_4yft*Yy-^my}zp`ePeakvm4LoWeVO1&86T>tE0y~Mf< zUVgC|Ib*C>d3f>nf5LYD+AKn2SqZ_3pwg5?0|<_T8*qYLbWOZV03WfUV@bI;*1P3< zzS>7{m{pP}PyLlo7VPx=u|~cFQ5e#)0u$!vlH@B5(;(cg2E~w;<9+E{yfxb}`~%Hf z8)`BxVrvk;spG&vbVJiqAU>6QJ$B7JOgc6_N$5!GKCbT`(VZq-yipLdKA*|Xd^DAv z!O#jH0^qnL#voAGZ6N!-4CR)V!4-#?HyoP};_w1K1=u}i#*Udhz=iZc>!+k7!7?C6 zR*H_;3Hf|*iWRYQ<#p^d=J$rye8rCq7rnrM@aqq(Q`gGvI(3=+)(ifVKhVPBk~{r@>(aeffqf%!r6kmX7Bc<+bo(;&Zk&Dsz9 zz#d7zJfvkUlV{tmA8GGr`f7Y94p)(dlp4WYKn2i49~vcs&|MuVFlc8>?~1at%<3Q7 zm3gyPp2>V>>@w`FL?lHWZsv!>@j!TR_aJyUOjB>cdMHr_z{mXzaN|<9Lur-xMA$@| zki$KmaVSV_9HJ$TC3v83M)lElWgvwchoJb?tcrDf7>ztnqYfi@1F8IMjJ5DBZ3%IW zfz+{P2HB>NE#5!JvdTw$}#(+?|L`j#ZRxur5S%h^}7MhI2K&@PGxP(yR6iJ+-7BI2t`F$R} zuetttjINMo?7Q^r;Z};zC$R(AN@1@!0_Uy$$NG)x$Rajp#$&poBS0d5Ycl>M`4Ej( z(>RFTMu9x?LkU=iPpUbE4X8pR^>=lYFJLgza!F}QO~yni3KSy}bXA)0@16H6n({a~1#f`IWd-tK7mgx+I6NHA6N`Sji1ny*=SuVT=i)S zv7cNyI4cqJd@}HS+!LS;U;*|Qzz!TDnP>8$lW^m{dSnnYQ9v-e_3hbR;}2mq_Xn#j z)kubUL=D$f8qO-q+ooc124j^h1>iD2w#lLu$3)Yj(TpTN?;^(i{cm z?>5pu@YYO~Nv<;>M+*byuSGF3e^m&6i+Pmz-Km(s7ChzTgmIC{DL1a^Q%KUlOnH;1 z`q1gZ!dgS!h^HoOug5Eo?=P70HqxESjOENKWbfziC;4lnWx3mvT9{`Okm$m`OcevQ`YkPsOppF5kLQ@Gg zPGR%Z02DtIdjLiQM2K&@S_qDLYc}R?P{B@!Z~I5ax0UsIiEsOw#J7Fr_}Z=bu-Bme zc-9}s`s3{S&)4;%j@u?OA_2cM1h=}3b-c+sbh!Le#n0`H@-ta}8p}_!%fIeK{gZz6 zCN`i>9sg0i+7WfW!a5D<(+2hl^5dGedKG@B?Jw7pOll71vkjn4TqsFUvfxUDmN+

    5(W2BA6CfAof?0Xyeg$?H*a@KsGkxmezNz&&l#gP!$xN6=Ll!C% znGHH(9Z|-xZH*n>5HQSy^B%F74-qI$mDA*{6-s1N&%%MC4*bV9TaBdTAkpO?^l3Jj z7B+bd1v=s%ai0Ow-YF~wEoR%X1%w?@HzprN>AAopY^(K-tpCdJUV&L#>#TG4d256G2=;b}zjMCh_Zb~l^QZYLE`>`5_|hXjUw1_8-=cOsOdF3? z0(Uvss;Q+Zqw++yWRNI(3$1_%3w4Xo8L0@euXM^*ukp;*HDA2Rb$9FLqp-;4176}A z<@8YI{O*9>_rll#y-?ca7K}px?nTj!0M;QWrNl7!d)i-3PxkMy%?u0WXk7A4Ty{H(30c58JC0hj!=+o(xyu z?B6|he%*MciYWgV_IK0s@q^YbIgS*ul!QpERST>-((F1M0PJZOfDsauMJQ+=_F6!{ zjd5{+B{c#UdzVerPg#lze|M|OJs51m1l$}2IQ#dEm0#S_lYs${ zv+h~e5lI#%$)nXQKBvfM&)IWP53$`a7f6~n1aSgCsHBS-1YH7+O17i-mot>-$1JuzMJs1tx0o3p2LrV7x2D;|F#ikJtO~g+K4B9Kn3#O~QpWC-&Ap zN3aBYgH2nE38)|p38+8@rG9gf&6Bm?y@M^c>}a0E6#~UF!1&_Ompa45vO8|pr7&J_X%M@>d!)UlVXIT^=xKmC2gyMr8l_I2c=K9V4Eq*G- zJy{1pSB*j_L>LfLemDZ@LyCiD=Q(4!*aDMS5)v*!Lb3dP{VFVfXIgJXVuO8mFEpXm z6KF4c^>(Te*N_sK1)3Ew$KLcw6QJeo6^NsN4%-jR3Im~+NGj$~I}!mwF$C&tY8_wD z*rv0pSMcmNjTqYKX@bY%BgUJZs8{^e-)0Be065Q5(@0IYb6s@_vo*Y>wnMR+~NZ)bKt&;ve&F-_vmt3mkT67BQtnHc;*yT*h zpb$i}aM+7_>?@)MH%&0&gZ9R=jCV9@1R=Q+9oXD2z}#tV$sG`!z3E78hnkGPjk1)) zd_ja$Fj%nFB~lpx1&{d}1jv9CLxByjUbmZhk-3;T?Un1G z|0}4|md}Ohc@#ZTSL@zPkaVzi^pxK8WDlIZnXh}s{f!qp`=hRQ^oEIG|7Ul0t>4(v zw1AmFjJi)DoWa3jz?oY4cdIp}7tJiVyh;q+GD4Jr<-K%K!$d$J0y32s-%h?w~OT7Jd; zphCA8zkPU6yLj1-iKP5cALq7(Ie03M-%=JkKI=n<%j4EhLUl zz>gm1h3T6qR42SpZ@!^VP13GN>T%#R*J>WZuLEzye)(Ml>MUrbhW|MHxot!Q{#7 zSa~Ua)s!UmaiKnWgE9#ljc4fu1sCgCXIdz&3mG_^%|~I8&4MH{T4y`7wxx|edFJl z6dZ*!S%m%JefzuV89N8X1F29>?9yMuzQK6vD$c3^Ah#=UHvSnqKj0~tiP&ARILBLR zJadI`FLdMR{4ebMrss)!P(MU{7wr#Et<(KlN-6Xt_J;&Jf4Kfch6=OlXZBFFp&Lj2 z?^F8H_Kyn|q5e)*{oSqljZ@VBjGaGRKPXa67?L$SkmYtt_;LLPH3@Ww?$_NkNX+b} z(66I?8CEWlw5tTyx+VNt+gIcf^$I5d9#_j}&#UDq9VmtZ7bG!_J!`3rT|)L1sW9BQ zT{fE9_LYCtp%CJl^1{+ec5-)pc>95n&sTKYu5~YM8 z3~oV;9$b!Q8erm(uhvTNWdZS%`~s-y--YtQ4?O(@&F1?$d^b!TmZG)1WtedG#CO=A zF0?1^OUdP9mWd)NV(h;BgbYU8yq37MW>{93FXH@&O77*XL`!ADUb z|ICH}I*Ar^gbahj--bG|FsX$bgcVHNEF`r)^>Fj33w$7Ye%2%2Cf}U@sFAn+@xE z8Gbpoe9!olV%*bq4m~Y0Tn3Ruqdt!&OQz$ZQKH5UCqgv zE+4C0UwN)T4z#jS-ROq^4$BIbhs0mrLNeN){^5Y{6`ujVHzAK2fA#k*Yz1LLr$Z8D z(<1twMUVqj7f0RcQa4rM1!AzZwc&H2?Lr%dYovY;!c0;3|6Sv33VX%FU#H=PT@{Yc zg;$D3SQvjE-_Nv>qa7wNjYsgK;MmH5{vJ~`Mz9fvtQ@RrdUAqiHAnSL-GK-1LrJU< zk|)8*KRJ~ym~N!+^3E&Z93Skwn_+t~DomofOXXqkPmcrv3{MUa^pFBtgMY;U0l&Al zKZi162-JD+1CzNY^h$m+6aMgtH3l+2seM;|-_jH(7~teXk$_)9UM)5VZ85h1PyKCC zQyBKi8q_JO{XPwQ>qU(EX7BL;_627*!g`j2v8l;;tRJbry+6=D2A){3oT=WOIbF^K z$xnk0+Z`^@-uq)^&gcz?mQCLKkDxXzC59c8i5aFgMlxe@ ze~XPDG)Fy9z|X)+UG`#Gi}VE={g-d`p%n&N;lFUb;ofVsaMkp)VPaIwZNJ8;IgrBzs>u}OCtdABe z{_2Q7*as8HKsbTj2`8}kyz`bYmD%%lU(mlN#ux0lNAk|)TbpYK{jj~ETe&RR^pwni zso?X$!oszw4I}qnc5A+kwp&@~utUBrZ;IH~gK(3u897T;`|v_N{<8L-5k=JEwyGc& zNdtS-DEzA7^3X^x&yHvE{g=uuzi*bo_pyon?zUho8Fe(mDLnEw||3 zc6FGzhTnh6?-BJWe$@e7Xta2b5AWjQuw2j>7f%QNL^WDD6>wTi0A_q>nsW%M_>Z$+ zJf0n4znJ*hY1uEPU)Q#O4ESMhkdOHOVFWr+XbAbpM6r%_VIP^D;)C;7r|p3E-W5h# z^>^_7Tt%l(IDqE7)yr9A5wB&_xPIC_a-PemyjJ`0ULi~DH0(5a(};LcCo()0|GF_;VY?`+((ot%3n zkf#*MHDN)R03OrEt7Sv`W{G{X%)Y6&ZyIrfdg8z{Z-VzACu1feajfL8>AB!ixVrE4 z3q5?@$RwbLEm@=oaS&y76mG%}qI{!Ndte(#jf5{Y|3MJO4LB(P2|xh5#haSuVst>haTx+I=CFOI zUVRL!y;y|+)1ZfH%X((Z!~U*a_x*{?m#*z|E3t)FlZYRJB1oixlRQYI zp1-E`iy2GFd#t0#F9PYxFR(&>mnR*&7@AwETP1YoNs*dmW#d7KlRW#!bL zm$!y4=MsmZOj3nmzry|s1$-hDaEzf0m<%=uj)Sj0`5=i@;vC62+Xv zqNKXaDqh4&nxY)7e=Ssi_GzOPLDGfmSm;QSC?l|3dy<8dOtX^IWc0d~?D%TdEvS#; zn8()795rWHd9eEn22eNm)L9;FP_vjvz4H=Ty=Q)%D8(1P37MAI&QCWC)#T-p_IQ4O zMrTxk`AMzmhY!SU0zfvrEWIT(L1+SYP7r*fHoJ%*Fn#MhiID%oc{CG%Ld;zU5H;Yy z#XOH$d4%T04?0uw^k)izK8{%8z08LJBbWEm+Q9s3YmkH|1m?@Ugs%dx!2Bin+I$Bp zlk6-?UCPSLDk(#{-%Vbuv?le^}^pFS8kzP8PEAoe4$U_f9;*OmsAtsWA1=oCVQ68*5#pl7idT(3M9of z3zK|mrg!0{%-X}1fMtU!8m_^Z$DZd4ECIS3UtuK>3R4J6czVlSMN%dU#a`KRz=#^s z%y=VxT4F`aN+fsHH3P2ji}+HVy|`YVoWpfmmJ5SJ8giu|7YJi!GIFIgAZ8Jdpd`n~DE$o5_ureM#}^-S0UpqfpZ{w4b|x z3YeyjiLil)ydYVDc#(1_K#1VJoWvQ$^^a}pcc*K{l- z$~mYid@J(ZN%8MIAsSnxQ&;Z&5Abg>$*ksJ8fOEb3N8-(BapnnoRd-RH$$A18xP7I zXHhQj#}6oha&ZUpWnrXTH5LP*O9oT{Z%aK(0gG+ z)bKevEP_7IKq041pXr)D4ZCZz?8uA8hP~sFgX9)@q9a|aS z=rBR)6#%}dMYcN|=zcD{j~9*TI83ZQVf6eCs0*XNU-yQ>HbmnA z@6d8RhF^hr>R6hibN6EF<|_Ddy41(#G8HST*_dMCSKV&Ai4!95%RBE0-9C&}c>Lj| zB1pi+eMh$eRKRc(mMg%vJDb^(dKezHSVn<2gu01=~^OXDu9{p@~RQx-cx`$M%>uC9it z3*}17JTL0~@}~X`QTvNpys)G?kmq3N*HF)BK%M&%pI{0j~NUS$EVhQ>3h4XEu- z$mO(fXtB!jrbWHdhMMh_7z+S|L?O{iQW#9sO!&1vGU~D4EbVuksdwrm6 z5isD(eDDT!u>&RNa*v~|pbqIql(efHkPPDlc(Lc3kx(PZT2$SI;3;Tq?W0nsol+VH z%M+~_S8rm|?BnZxeCw~urIpxF`TU;tkgGjLxwCKkKjwm|cz`6vTI4feI(&s!E-%~!Q8mFKDl2I|?S z%FafF&-DlIXA(b>*5en2ni<)X5hXqbPd+XRY{NR0>hvU)bP2;^dhTiRVDxl=I90ch zs)}_m8qbCQ;Tq!N8M3q3AIP*q-Rq6Uzxx-7O^?CxHKRRf9Jzp*F|-P8=!7+yFCRSY|Ri8W5zsE4w=>z*RG#4gi~C|Qjs zH8Q86#ZKc3KB944Tk&#&b4XeQ+A{odBpglmOtQeI-hEt~HkKk0$1NY2nfY*g0UjHz z9y?nzge6P>h&J%o^o&`HRo@x>hIg!i2qcAI4$G&3o*C>;`LJIPJiW9pXB{2HP#x{X zOd&vPXy|YL;DfsHdM|6M#_yeO!~NVg8ej8}ZamwmcAcdgFO5b+Wf)A)uVEcftNHCj zjb{eI2Wh#ERi7otL5JGk3+->ZA6w`+MPQz=43p>{+pg9Wleyc`mPW5o5+tn?rw#C*q6X3-9K4xtJ_|YLI*X$){^no52S@3N*J6J=7WaLN@Nt%Q2ycy` z$gh!{QB}N4c`NdzOf70wqdhAwYh$ad$X}=QKV5;n44kvHaZo+*4rH*?@NYe-{M&1i zE?b*4)s-y!boH-&giD0}B{&|M7BSlbhL-{J*QeIE=24<}T`9sXhq%Zh58+#|zxC6+ z3X_G1xlWDj*Q{1FGV@Q>)_tU6b{Q12N9B|0+5Rzj756rPlkHSd;2641C^r-S`J8xc zokjhAhZdi;W)hYW*uZ%8+}ln;fqW{y>1(G{b~^gU-lhonzwp=p0RHc@^EC${_RC8^2HTWhHR*ZxCzq}qIz(B4)UxT{7;Auofd9nl$P1r7J|tuOXS-)HEo@i zq+5ftIciciqMILX7o_{cj&+X+6J_S7wRF#i4BPD-V)!WqB8_>kI81 zQ5}R_)JuIxEqV%;LCA#Rf>tt;3GPE=V$gn($>nTLDr_()<>_kN8zz+_7^S6tV$>mG z)FJi#SA@QpX6GFMDVdm_u|ET0I$&f6>s!gp*xZF5jH8%2V1dg5ZVZTr>S0nw&lwJE z!WqQ5uFAjL?F_MJG?U`tmh}$tuE#<^C=MS~*%`u!Zw7K$dv${C5WlXmb=9irZOw`! z+9UY$zgunmxx}W{AAvugM&QpGDC4yG<5L`gi1?Nvj3LWGO2hb*Li|~Cn}t8X zl-Pe-_>*Z3njhl={K+K#x3 z6UNWMi51ZZyLJv1hPl7v0djqOgvvnRfI2;sNgY-us=AfaZftF~$+MOPv|uoMT9 zUb5+UB;DSYCG^zzc^(kNfuC2td0P1Cu#e0G^kYj`OSEo}Bfl zzkLFDnF)g)YX@$mtto0w>EB=_0>`_Sz{Q*lXGy8g^ISRO_o0?eE-+Nf_<}RXQ};Ek zXNq9#CI18yLZ_C^M5X2Ke2_jeRF3c@U6&a`#vHjSi6EH+SzS!Vs(U= zYi8W@BDf^x<|8b_w&JvGFw%E=%{tVJs9AnY(f;%e-kO(S!tobxpgb@r=x-k<^FPlo zugw7n`6>lZ6*mkDE@;0Li3XUrV(tG8-r{}b(wdAjrG1?T1ZpKg^DjaFx1fE^3qZHp zE!i;pxYg!%fQcDfzm>bHvHr-$0d|M@i_O-5g29GvY|Pf8zQT(?gMbRy?R>nY%){mB|Xt0l3W$;QvydY>3DznMqC ztWA=f0-G}vEd1ma@7@PAV00_m0L+0u9uF9-WdXDl7fjEA^Ui>02q|Ht!I~_e3(7Tg z&0^J!Xf!EjrTjwVr1isq`|`f#8yN*4*9Tn3I&7&w_^dD!KWKrOe1W5|IQRm4{DJ?4 zHi-2Uf8awuNGAPDuUQ3j_Xp4O2gk->fBOM%&3wL)R)LLY5>=O>3`!rlM)7ui4^hb% z9CJ4IrVl?mE+;ttY=kzcI2-Xpv(HY(w)C?x1z>0TXMS|Y_&X&^yE_Bm?tPYSECT)3 zbVXgPfn+6uoG-ZWEIxQwbfVK1dfR{}_0hL2Ef_!0fp@Ox!RRKYcpdN;yEJ!~K{C^J zo#sB|ZS^b==${YJ&g;$tCT)MTFB$ZA7-1|yf9>NQL_dJKEc150-|YHjO~zF{IKo~0 zXg%BH4|M&q=`pcg{(xw{@K|NP_(hG|zX{%taJBwcBJ)zo`;gRIS`%_|~bJxUCD%kD{WBYo)f|{Do-9$rIJZu^A$(BsTRHYm7s` z`#mB5qx3tD4+lX{=$j$c;K5~ijIGO!Ygs>c$35{-^g46>flA$cA*t?Q=TY2C(>#W1nZJsfU~kb`z$;BvNlFo-*$CDo*8ZU*7OvbfSw)7ITW`+pqz z+pU}fMSmmSnjSaG0)Nhi{?i6j}RLaGbbh2-_f zFEZBZqSvi~ZAv?#bZ+_Ioz(vI^nghDXYFapKa{V$^O8A|5%Je3@Rd4+^hjLMa%?M% zxrQAplAJ{1DklO}EYZD%;L0z6e`yGhG+S?lM`3{;NQC&64MZH<__e7D$P>g24`IHd zJ*KNIh>IBX%=iS82$mCwX?>ohekJ}QBELfEJWhTMD|4cf+OoHr_(o{tBuT{AR+Oqn zud&84OrTAF2#x5e<=4GN#Q05G{U3~9-{Z#5Ids;rw5edJ+kFjM*9Aq#ULzDutsJ9- zkvxHZh4^}#NJJDWkg!zUBtdRttijmFmA8b?Kf-|$TQCx;#|bnE(G^6U zum^#aC(}=0^aq@6*c>qp@GU10uVAtK_`=oP*H5LU z2pfj{clWB}hxdWd@csz@pjiO0Lq7?wJgxC{@b^(1oYUv;8Z5PtANxB-S~lqb#2D!X zdacGW*bzJ&_L$?ia)>=+-U`{*7JooUiG6LtMhuGyHjVY!pMgIc96<15IDUXrst4ZZ zkXrRx1|N)S$l!Asvj@JE`L73K*PFDxZD*VqZF^f5G1d{BI6T;qOjkX+CUVFlKMPf> zhhDP=yQ$V1;#1S_(*Ubud|y~`TH~wv@AsO1Az)yo!GL`vlkL%`-_YJ~dTxk?O6UC< zWE^}*Q*VmYOM)>yqpm`frQr#BI!(rl20xU{K73(z`~KHtgCLb|pL?lHz;!Z*hYXhCek4rRuqTE%4Y_nyFvRox2 z(^60RG|~^<(}B%TZtfRiy&!j4V`O7#BK65Oi$?YE6&OHtP*)mi12C@9Y72Z48PWh7 zniKs9)Y8pwcFr7(BSHoTvm0W3HAmd{z1lpNtN7V)C#s|Vx8^mHwOx|{l2C}V`S+Sv zEucE4=jTp`f3Lneg1)!?=|7b*4z1^UhCOc+!)#|#Q~-Ha$;o8x>n-?_c_*RxU} zL!#00j`8gW2-t? zVFYcV!791=31%^xuym!*;emqkTaYqobuaipof`gUJ$qyl*L2%j;hGxq%5j*6^IQMF z{X2VI8G(NTmz@^=QGRI9>wkr`m(4jyTLU-Oh}v)J-w-#!7GU|TU1%^i{bkQb9bWPe zh_u#n#X8;_6eQOG|8*rN++eEd%F40*L>^(=AzB)y{j7CvR!6_EqTAbx;p9Ei zcaNL3?WCR=EDSB8g(S75If};)rGI(Pbzz=?Gd{9OY(R}XFb^M@2T`O-I0&&XpV$Yq zw@xd9C08swpt&WeLU-9R0$3Osc@{a63j2s)Ya!5RaIoiAw4av6 z&VKXiu203oX!CvZdwz4G+n@eX`7emQxeN|jO5y+${|-TB{DDvP&bINR+rzw-iSwt> zf4?~n)QP?CQZ49}=xY#t^NGGdWOR@w7!1yhWw)z7tIf2bN*lYS%cu(X6jx=41w_>T-qW10({Qnd2-|l&9 zh(tm{2t)P$AA2^dYRj&8|V3iqPVlnP-D!MPrC4h;<>L*9XrxwE)xEzqdOwTYu01YyWc zH5{C~b@)bgr&j~WNf?V6+v!o3&69232xpbHGKvLO`t_zAz9D_@gFgc*?>Yp%c$ltM zW~{MDT33^CuU&w(;}p`XoPPlERKJ0Kwnp+Nbj|dDBDMKfO&s|**cPi%gSIbblKEI4 zv7!$#b5xod`~BNIpQGkj47^QORhE`llob|CG16lyQ^8*9n{U?hU(K;jm|$0pFPSlw zDfqq1ggI3)1yd?JrfyjY0JyN25sdx%gMKcFyTv6B4#WI@+324*m&!@AHTTB5^xCzI z{vjlh8yB$)Cp8(tJCfBGpJV+HXMn=tlQ_Xd1nm+2qR%qC5*< z76APq1!i{-^8uGw&Km#%3j0A_zJ(Tdo9*3+vt`a{&oPGJ+dmG=p5|cSE1k%N|J*{K z1IYJS3&8qj&Y2Quq2flnmuNLoYu*V1TReGLCQaHjDdk{sRpR`m);GN>-Sn*8*)L2s z=;>m?7JXU}d%6dW)U<`}3IS?S(pqN&%LDVXT}v&>owJbyP2Zc_T9y8@|I5;25A8tP zF)DQgB!l(q`21*fy?|DGMGkl#Wb~$&>X;?gp}jhby(&?Exnos=dCA4|^{Uw!Q#s$Q zO{&Igy<$@p&C#&}&%P+D`!*kD-0}W#6cLM%oWt&agtTM1^I~rM|AA*q{RFHZG~AQV zL&Om1JQ1-Iy*0hzi|jXhLM$J@H)e3~s=b4u4?+I>9`fIL_(tw;_*%9i0tKT_WYv5a zljHu}4p5t8j!D9NBhhJP{`m#a5JZsvi3{>FhsKO!x<&#Ct&aO&=~e_ zselJeW^|N=yLk+p0aq@yg&;zVb!fp{zhgmW>~PcKDOX5(S!>ly$+_0bH>z0jCtTF5 z*IHSV>NX5#TQZ19GwTh;e$uE>VZJ;%)=%sC0^Q3;3o@4i6V}8M6L8)Rd!v)vXt3(C z6Qe=&WTL@r&gfjVt7zxIfu*u|Zk@&{vF9UkzUFGER4dzgejL>{yc5Y2=0C*t|KIQg2xW-%VWvO?$q6QH&4Kg|1p>}}zVv@r9-x>A z8EiZQPGfbeNnKqi8pJK44p5THWzUyzP%XC3K?yN9p<6B{EkgTdEZcur(W6Ctz!D zA1z<)JwHOeYX046%2(r)R%+pjJGCKPk%naRK7S!x)yuP9J$DFKE9JG#sBCd(t>%=N zP{_FG-p8pcBy8p5!Ks8mBhC`2(xb2)yb0_3Vq0Pg#jSBYv?8(}IXHDT%CA)}#**cd z&(`5raF}$CxN-yOMG#^z*2tQg;qX1%E#jCc#2Ax2$O=$I>Y*Ipa~BL3(3FQJh76>B zoPSkwm$1yPV3}jKgJmXd9~|^=*Zv8 zMvgfQY!izjaE))8COp%t<9~oDx$vxcjOm$_4yMzuBe|!aOs6&L1k1ea2OlOBSZ(rf z{+#BSzudrCUe8w$7PB%bDZ(t~ncW|9*|#y88533z8*4H?`8P`tCMs~GU?#g02x-1i zNi5JzNcdDU(Q3YH%(0m0hb$);yJQ=gs4NFLIH<0K-tDI6hu@+zGg&(T4GNL8Hv61) zk%N6Q7pW1W!S#SQCusHw+X~s|jnZCg3N2oz38xBiJVNtlKJs(^?EIkSon&_O)n9_& z5N8vdwdD~>0s6})J7h8{g!TNLvyn6ad1OISHEsycI1*_ofZ8XMT2v!mD>r;Z^dJES z`GSKivsG;tAN>)vdFF4`d^8`Wpf9nR0nJAxF9vrBUbiY;%yhOkcapxq4H(kL; zfxz#D`KUj=sS;Q^2Kp%YXsN|VKe3|bHCir75LAU(`6uD#aBl}# zVOFrz&q+(zWkYCR2H(lm<; z@>%PicD99b#8W7~inAXmHnJatt$^UZ{SM&X1kBc}Z1(5nR*0Gqa4X=VD@k;O5-B9S zOn008)%4t(4jr*0>osF9zY}4IWglXoSjSe8=o>H*=R0ceZfDj-OOkNW$3!sYzcBEZD<0p@@s%#|QvQv%%ocZ5} zXR1ANrIL1elH>^kaJ3`JG8y~jNs=_2+DTIw(SYPP;kg z0L&3O_zQ%o^N z-#bQEgtcN#wAm-YPe_F<%4uvV`kx}dSc~RI>tvzhs+z&7SQCsh2`e_DCcV8c8`bqd zb+CLaSdY2ijLn&&r+g`vj1tA4pbd82i?v-3!i%#FM#~1_pMLoCnLHa1M~3eSufF`F z5(nPs@Ke<6<4_IOUBiCX+8i{D5@Xx8Q%nFaQ zCVNv3WwIxC{GNJ#pVcK|eh)r=+VguI!7qMVvq+3{4jw|+sbUGbL&f5+V}9Q+pDn2l zq#I9W17tWN@AaI_QA;5ufe^T0FT^3~u$36U+4ILF-3wvyKIEj9wHA3@)UqyumbI~O z?Z=h5;2P9lW3`?op~5h*QV9lD3#?Y<;Lbv}9AH+40hUUUo{hk6tXyRuA73I#=@CZ=gXPG zdq%zH&rRaO8cY~MvjmX5nr#Ti4v+=6Co~mr$&TKG%-uG|`$+lG52%)iy(=`!-wi05eP`>;|A_nEFIi!CZuSTZ;OhrpP z$QfCZ+KHWc-1jozf2o=xIIO*v9s_SQo)V^8q9(x~K;tzE6-u%9Lkl&{*+}BrpvFHz zCSsA8^^!`c!vYi55M)uChVC?~=$WJ)L-l^_B#b1q^qfXLCsW{SG z69NqF&${x_)8a4Mzl3OX+WVhFUL}`WewN}gNYf|8iH|#yEr{3NaC+=Hw>@iOfU5`d z!RtisD)bg>taIXUdec+;D~xf--}9W2C)@12@|PT|$yh_J!3oQ)MoF!HgL&`aFPJxfy(@-g8x(LL=s@D}&g(;B zFgp*mR;~MBu@_&&1dp%hvm}s~Le}}illqfOQ9T(Lte{BLwP9dzc0-)syu&@%Olt6_ ze^7oGu~RhkB3T0mgg;F3fW>0#0M5Jnhw9p$3J*3P$f~k0;BSPX=!a&~QhQ$@x)Cnc z!P(dvc@^9be2g{s4)Aeo^FI;4ss6+_~EW&-uhKd#%jBao?pSK>T3E( zz<+-|)-iu`n0(K&jI$UR`7!i#DwW;4)p&(&hWVd3=TW<$8OZb$EEfOob8P?bD)n+a zEJg4Tta5p4_cJq?K(+jKlqRMPNvr&u*nGuupgqQBU5N2DJ+GbxQ`4DNlVE#_l|?%m zyN-N*Dr48p01Ap|yp;RTzd^6e*o~}~xmQbWMDC+AI^FMR*T4-dLfFBIoA~ByxNIQ_ z)E6(aB*ytiDzRVe({C{NNUr{hCsi~8r>%7oxd_lx-7g}7S_m~~<9^h<0Tg%<7#)6k z;HNH36Y7PBoa9i~bo)sb=WYJ;pTt-Goe4TQb$n%^znS1YX&h+`KQ19rX0kZjpNnxE z5QFKJ@dM3ncL`*N;~qw*M8lLj@E9=lbKwxUO>J4wLJrSt!g?YDiv=Ii%pwKM!U`-V zMs@Yo0w-Xa#%UIDYW~nGF@it5fMQN#e>M4o(){5AOg!KZA~=CR)Ulu75ArKVgByw7 z73JC7;xq4grZsPv?hi(P1vdK?&}SGn&44%5@(Xyw5&@GwA`+C?Sd)>WENbrA2ul1N z{3w94-y=GXI`?Z$iQv<=DN|D-#v{V`unNeeRam-mnx20=>2ax5Shd$XFjCaj-82QJ zgeZ{CpFxn{5d16`IWFzC>`E{YKR2?#Z%|X=zY>HBUpf!Xna`sr!5A>Ov16n=prf+S z*!pwzmM10vQ)X?cjOV9_`B>1P)4kmG~bMe{%ZW zr=-8pfTx27CkOzA^27m`V~GLPG^iRLJ{bXaddNY5R{Szm8L*(yglH~K8R*pXx4LHp z{auNYPK*AYO=^S%SCe3LCn3RQ@SETiy_CNoLHWfTTQBdi1|+|W^@;0{>ajNk>DMMT z%I_XBp=g}trR}4JymZ<}-wjdGT7BX>1a_S&G}paiCjmiL$!s51olE7}+A3^%dMygu zNB`;7_EAX!`zW*WkM_}O+}rk1itn&e!F~{7AC*b?I{Sg*BKraLWj?EqWKrjk z-eebo{TaX&h=qVV94@?CkrG`-3JHrDH`!lJ&mA=Lb!5F}Y{vn%eYAMEHZdl{(joRf zhm7)__<&LelAKh;>765{R&p6O{itr6|3BBv~0F3mqGgsxFkovAi*9Z{hfO{l)c-uSrE+g z>7OAixanU9MwXA()WHBW=lQ`J^`1gx%V>{#xj{>vAItSKqmMj z^MvTL;6>~sSXBu5aRdBt;P05{L-;@MVF1sBt%;cc!P{g#U#~eef-l^i(i`2FK zQSH@o?3bcL(>b4ye*>RR4@KJX!fwv+*Fxry`7VE-2!sHm3-t*|mMp2~Zpf0>f!F#g<}dDiw&Y2s zQFqA;z1&0=qgZ~J#eDlhXcRLUk8I6n(s`MAsSiH?cME^9R46%}t`mHtntsC)7FyCp zF7)u}k_Q|5Yem#RFi0$i=&|qzj6^wN2ygUP)ls)N(N3b`^^4@1jH{)fL}@mVA(Fpm zSS@e9jKED1uzAM(20QH$0UTqZh-z=;XjJ28t)KSe(M1~fn#MwktuwGNMWEOVQ>$hm zT%nmTKL+a-03eVhqdjH@(yR>Udz-OBWv`>mx*w^|MJm;shhd^%8Q2>+u;{Xk(&j7! zLL#0m$qWZ3pafFr1Lc*FD1s@p!&DjK5)RCI=8qb)vbf=#Wz`(4uG^q`-3x*DNk7EY`2d^9 z`_IW)M!#VbSig7PQv`cNe0~n`GQI`dT8UqW&Ta3L<`%!9TJMJ0{6+~nOMeJj?V$Wo zx2F9Lsy4!QF;YSUgCmGVNzI)nD!^qJWt#Zx=!AMZoa%7DRsr-QRlOqW;H3n1l`6hR z!?{R&W(eo1rW+%*f-s0rtsguc7oi`VfznSyKhW@dn9QT*Ae5ZR*ja`##Klu^ZwJI5 z*!K}oZF6P}@KYK{;9gTqJl|S^OtGJo56gTRl#ptE!>4`$r z6IL1L=rR`L;E;$iriaRy%Q8@T#%$bZ{Zg0n?mZ}HuvHG1@zItT1V6FLStxC}CR9$2 z-Ii>&Wuz{nj%A!-m7xRJ#EvKqmBAozH5s4pW`7XM!{bKQI_c22zegcw=|TpwkWC+I zprq-Bd{cX--4G3w-%B9`%CpESWh`PDZ!Z#{bYL0xTV-$+8=d*pZJ~zfG74Bmoj`V? zUC13QB%ljfKf8nY|60XZ{duo-f6favCCe@)jivO_rOZYt>e~alI~H6Y!3-Gz*Im2p zG4`+wj?eecTH|xM>!jH1wfzF(vike|42e6spCRsGcc zAD?lu`uqLl^=Bh`{7J@t#!ub9MGXYo>J;U#ayOj3{VgYN->RsS=O5)d z`Skfrh3oO>Oi;3mrjM)3D#RsbnFZYg5%@ZGMtk z_&xrKlYI}>|D|fH{&4$VX>Rkot0`^aiOU!L#0UI`Lg%#rQ`%)S`-G;OH%oBVKDvJ`j-O-PBBcW|4IG!SfqtVJ{a@u zI@(bxJgN0{&F2TU)@*_PjU|5^1a}4ksv|XHYrh>^ebu7laWn| zc#`&A-*)>(gxd$yRIk+OAvkfH^mdLvPHDSgf|1P+gMqY(CM*p=kdzZvUyckUC;A_CH~t748^@z=-o+vkpk=T~vSJItIt) zp_OgS@zIl=gVa=cBKwc<_uLbAz{cfn4jc`l>3K2Wt`6eZFJry8&Hj7mO{9T8B0i$H zqv*IvRbmFG@l9@?6y@F%^+G4wSJj&BG({q2R~@ZH9ku4)siW5XgRu)2(r-JVvYeiu z89fhmcKrorR@&hwe-(@45-wo|%eaQ~*^j&pvZG7I=B#+8Gt8N=58t+l_J>$F#{~b0 zV_O45;%GJKb}t^(BJnfuT&3%YWj%;AVrIAh z!$z2CcvpY;^YSEPJC>6^zreS;`o33o$FdMN;!?ve&6qPjDHB-m^X5+BkKFm5%LYji zvRh1-6Xy%OYZW!f?0Hsm6rO#>J6&6!z9nnU$1Emi+`A~+x7y`8FQYl?PrqS30@(l# ztTK6MmFLK#(zC!c85;#?+GDfmFC3dhR*cPNdEZ*2vMH+<;5DQd@~+i+|5hq_w_Jm* zinJa9B*sjFHNWCXgD^8vGQ#nvEdgx@-ISuj6m$RW$0|M+gka_coRQ*eF|}%%I-j!&5z(a zqBs`qcrP>p zve&WhSHiGJPyQ6RjMb@5MF^ob*Y<>^f7E{MoY4`<;2*U_8vmj$!?b@r*JGoKb|nh< zHO0ZJ7A|83%xg0cdV{#e`||7ceXd~w1LZgp7{1iIIcPuPvmb$(F6M0%V8*VKim+t! z?Rp}=92o<=Mf?-5b`J692cF$Ugvq^vXi9$00bsc3liXg zVNftt7bM5`B7TqKT@~*VdDJ}_3LjEb6&n(?dOBz05*t3J@PA_8l%sd4}~yl*DV^ z(x_3TYT>pI|1W8QjBJ$=$ck^qnQ7vG%J76%{FAvD-`gbh|JH}_fTIF%keO&s)X6%~|rDuZ$zUp>nnl72Vk_pGD zgepm{YsNxpD3{&%%XH(p%&Y77+&By?u8mtYbW3Y8HoienIofN)$p&%A0XmQRh-JY4 zuonBvpOB2&K_B*S$%__lwo$@?Jx_}J>J%3s$}JOmkk7Su%o?W9$%|fcXYDv~jqZQipWN z39O_1bo+f|Pm#5%PYWY-y$dneAQ+NTRS{}$o~KzP`Kx!H$+X9x zABX8!g4AtAw9tDm@vgYx?9A#PuC4s1art(cHs3bBea}Fw2cu=Zap6|Oy%T{X0&i1G zNn_J9v4p(_9*H=g@FA*Ol>5vK?*UBbfIU29>T#+iZDdHQc5-Vp+SukM2yG`=mJj5? zP(%FXN)E~c(sKbDYaJ)j0LcGwf}q9!5t)blzm(Ge_?`dn|&+C}l%Tx(5y=%}-Qi|6V7k$J~pfVi|yBEfzu`Z=KWa2nx4 zGSHmgrTq^0ye>YlQ-E{}lj6mr2x2e2I^ytP@7nNB3we9${vZ1U{uii`iRk9Zoc!Z` zBJQ=z=NPc9x%(>0Ip`3jzvJ5(9ai%P5q<+3-jHO#J=61fsd#useMY|y=A(NjbAdu~ z$+D`{0}I$w#2n<-JgFEDNMN-a4@d|HRa75x<#e_WwMMoNkP$)Qr2bL2Vt&>Bfp%&* z--uUFNVb>-Va!evBgm*_3I~)&I+Dz{M?>&ARLTu@lA!0C9!b>fdOd;?`WvfT3q!9|MNIbT)cPEVOzk-3SXnk@h!54 zLmf$yrB{Fxl7?ij(2WCf33eucLL77Du#Uw^MHVQ;lQ(^LIh;j2zmFvp2m-bGVy{07zL@4;P58wO%0p#!49(dyXu*d?2-BWfa z)cOee{Dn=QfQw{fU`&D~cyg2T~ZmC3Tv$ZVz#q222ie$Ph~JW01!JJX>Jk}sU{F)L;BM8gC? zkyzc}M>VKf$Kw*ohSLIZEKfc0G-u;(xsx~>FBHv!s8~lbM1mr4%95wyca^{wXeP5; zQ_LYX>nZJftC_oY@CyOh$^ZUMkw!dctr=m?Motuv((IX`Rc6A++5Z#dS4T!+wl8nv z@L5a0@y>gl4L`ve6IYnLb03zz-i_ULRq@`rbL6Qind?t?Cs$Sya>*RC6l?wIlI~)_ z8bdCZg0t2zThj9>*bg^@;#GV7Im7;(Xn)4dpk(z~yyV9I3>I5cj}lmP&4!d!baYgk z@%@CWTby4*!Bcd^TT zm&-lL<(}+vPjR`Yy4)o$cd5%g&E+n0xyxPd3YUAj%RR&8u5!6&y4=OK!;(waEUBB_}cKxgHKhxdLD0a8=W#c~=|9J14ihtzsr{F&o z|JUIkc?S=}Kk^SQbGOUw<7!usivR2IU*T#uwiN$m_@CiwH*Ny{i|~*4IoN7@N|#`}pW_(%RClvjlEijbxVWfT?Te=`1&t{Cr%k*^r(iupX<)oxM& z{_#8s&y!KcWaOWW{FAT8{|)#bhyO|V2P`I|zA0$a6qGrI_m!@8Q_-%eD1T}dV1@Ea zkhTQnmEd~`+Et4DrFdV8wv^(1De9SqdZwYCGXA5kGL%tPI?Iv29Pi8Vz5;nGkhcQwEBFi;RiF*iZ@~Xeu68q!X9miefp*Nm_o`x7)PyM& zuBfSn74E34vE{goACJpaUdkroQhtLws&_HI_O6`Zj_T8=4=(+ExD=G)G6k3Hf|Jo7_%s!IP10@YF(FD)BBCm>QK^fOolURc;9i%`HLGa`|;gB^op| z70noW{dKqu8-_~(${RYa5|=`hHN7b3@a5JS{>U~JTQpjXuRN+d3vGzFKbNK(jp3rmo$ko6W;A<2ZwsjjGr zpv|a>g?KDtZAIhpbyDF>T&Cl3av_pT28l*Zp2|xJike)4)=w^(5fe3K@Gw`@lmfh) zQh)|c0cl1}DaY3-Y~Pg1$wXE>PGzg6mY|}km1t1O*t>9Qh?q?quWKU=<*V9 zi|F#17_I1v;wgo$=qrjrQ_)%Y!*%@lGF&H5EWx#GVmYqmK=9}+B;^%Y8{NC0ys)EO zabH}4G`&m4&*ZgavOBs@!DLH`k-m?VnO#s(;Eu)> zDYFYfYPe3t*X+Vll$>2yJ`UGn;5n}2P-b=ss53gd5^M(7GNkD{8I%^?7h{fVnY^hg zMLYWyPe#gq#b7ki{Qw7COUjU@UnRInbpNuF8SZHCnIc?EN+$7Ij`EEXaHnYBc;@v@ zod7uarh?buT3*pnuDq{Elj~Huq7AT69NOJUVmZ11b4K*upICG#ca91 zn6>yz*i(PWIMkbi(c!h6_X4q;k}{+OyF%U^fzlvy-snLEQ}BLJ0T^NQAkY@B#pCz} zh}JQB@KoLpE(JG?&h0-m7gzGH=v<6Du7!mtKevz&$Sp2K%3NRqu4Q1((YY0bTW%$x zF{F4Z-V6l`!F4>p4wZ2kS~!mPmF&f^aRsPlSRuz{SYaVj;)?QzfdSxJJdt0EXECMJ zGOSe6Ph*Y4DhlKZW{P{(3qF{F>kRPh=wZN2cl2=S-EiP1?n{V)!)LP1BZfj&h#nyr zJ7Q{a74FLmF<#(-ct5g$BQ>&MGFmdSpbTvoSxiWdEG7g-6@pPlk1i|&^hN`VT+sz% zK`7B+n4pvb^byxG$OgQY<623284GO3wYUQBamD+wz;;~89iqWR{~uXz7b97=<#(N! zn;#Jw`E@-5Vg@kfd4TECOjg%N*R4B@rK-yM=)6;3H#57dnM+SsW<+FW+{}!KjuTOt z*~a5SGQxmhz%XdU3-yRbLSkeAG9C|wY%C)fBOwHq45*NdWW)>bfClqme*gd4`^3p~ zNtJu8wf8x3&i+_?t^ZzoAIYa!82Wq0--`+5JB$MUG79+H*Zn)Rtp1`P_4mMk2Tjq8 zP5!>+?*x50hr(sdb{QA`%T--JTbB_bnwfsC%ZSiltRDWpea&CLQI~N6%|{-Jxt`Sg zT#wPg-&6GdTyLP~?@2q(p`W==Pnu({$9U0ST5IlLs`@z`s{Rj$*hBoq0-8Hy zR2Fkbn!fm3QvXMqdghK?1N`OMquz=B_79cIXyPv;x0vfQTJ=|N+Gn)#SL%L_F2FPN zCqwG9?_dAvkco1R>4#R}ujqc)fAza3d+Hk}d%DBP-gmV138R?5j9>pf)?eo`ilG_B z`g=&3)4gNLobHYK`dcDD)l@fkI_%O${8g^zB>oO~+5sb)znY8Z2AxAmG-u8Y7}xyO z6vkg&H5f8E@mDoG(8R)DwIFjF@*!hif0>x(hJNcIdO)<=bhM`@M10eKZ|Uz?lFo_d zg%0-O+=%hZUo-=MPo}yGeXhUi!=tf&k-zlP(U|F3f2q}x+jNB9DCWj)HU4s+apx^> z&38tqA1>vpu?zzK>bJ&2X6m`IX2v<@O@5KT&?Q>Me<@#f^yDQPMt{{C`OBTl-U)S8 z_D*TdQs%}Slc}yk+wk`on|+R%mHSgYy2GR=$waj`+3Rz+iQ8z>!Qh#jxV9(#0j)e4 zp3*<3rGAUQJnhtdh9SZ)@|U~4-5YbCw>_-xxihql{;I{#&^i9g{m=FWlDkdM{MKhj zYKt?!?|0~*V(vSQ)_IEHI?YREl*N31cmoS){`$V^eO|NjJ(8((-Mr@IlH_25wwr%& zA_YrA*CQD)>yeB`Cl@5+F~;}&L-k4$?!|Qvr+p0D`G@+U#{A|UuSas!?Q`Ac5#3S= zAATXB->V2+UU_jB5|q9;UpMR>9JJ;)r{lK>ANBU9he}51*!f2n{Q=zL!DP%sXiny4 zkH4KVPt5a_L+<(bd@|l^%s)ZDA$-#B>B%%dQ}W5lkhy_G6Vdz=REUJ7CJYkI4D(Mn zWh>7=o%WbV=Re=WbR=QYMz}TT;xdq6v?-Y|aVWWcGm=|Q?%s~%j+62pNhv=^iRx^t ze6+LcMAfrZ%9S8_(dTiuN?Gson&J-{^UwD7ac}0I_1-$^qh#TRDF4R%^Sw!jcX-|# zA5u%thl9ycYySC^4%e7}VRK|&(>XtjAF?fBZ?dZdHN!)^n4Uh}bb^CC|8juNXw1Lb zLoX;{=qPbBGJ#`D%)c6IvQ(n}@@hPs3|mUhX@?(Aduont9*tWwv+I$zdl;o8j71(| zdpKq0R)QfmuSx#X#{7;a;Q5`-5i>jqI)$X?cBdY;zJxoG1v0-gI?=l`wd)s1nCO-0 zW;+v^2_&*==4rhHZnpdCDYnVHet=3=!b9v1AML(Wa;!$(9q;MZU&KRb&ZnuAQ1Xib zI+mo|)2n=GQ)B+iy%RhmB~uCer5@>ZzpIY3lM8k<>^7!SGNOm=D8BQ9v7<@`-tQf_kV!pFSZIK+w=2n73L()S7llZ!h zMx3}Qs&c-g5vPO^r-U&^g3kXY66Mi26B28^dF+ERKiio~_s+{s;AgwN6Fq0Q$K0TV z(MZxCPb6gY@+w`8&0@Z1%VJ)30k`g*j#LE8K=^Z)HY0(vlAQ0om9;UCt?=T7 zlh?16Fqn(^0~G543HAc_Jm?Q}mxKP8NpfB$gM=E>B&U;y;z-V&{Fo<$+Y!e^tvniq z68SOAa0-{eQ5?I zzCeb7N|v{7-BH4@R|0CFWP9g<68gE4azcys%jty2?Y{+aDCSQz`jyCjoIjBgAdwPK zGSIWog;WzH;!gJt`&@o1&7kCb>yZ--pLvGCAq|Ib`)t#Rh5Z2&@%*W0;`!4FqXbSm zq?jK()8slouuV!LvvYocW6lM#A*h}~bZ^-Y652+XA9%u@*Er{?u>!{-{ zg+u&=_mdUyC5dNo5>yG?WW39iHIA1acR@qocogz9(SI8W56D!nsvGyvQY7lT&3XEx zhMJy%>onih>&y@yo6+q=`7cS)jpuo*CL;ZR6Q#^sAhwn=O-&cC(YGJm%J5EGDO zdT=w6TO>z)b(FKQEBP!m7*+(PPf^_G8yNa`|H-z~;HYsce)q$F zoziDr=U>C+(Z4r;9O?akHh%y9pO5q%+E4%P1MKSGHR@mg-u)!f;-8Q7<3BzK`9Bru zn?D)p{XZ3Hk>2}Vet();|33VmJ5E3T-;uuG_`>|PA4dA&mm__1BhvT37U}(eB;NDg zH!q_6n@B&T^y6;^|L!0BIp@FmJAc+`@jpd+?ZbEGKm65{{z0V0--z`7|Mi>Bf7g!d zul%NKf z<6fj6_LKaNe(c|S^LOL9xO*meN&-eb@ zsMl-9k$(J*NQ>W20BM@WszX`u=~}@_j%4eB%Gd7)Kvc`sQy3|Gp9FwZ9sA?%IDI>Bp45|0}`2`4DN5 z%64*O(()&LXU#S?|n@A_uBs+_j&UR@w@M?NBLr*Grky2hQ)%d@{;s?geg%h zV7)>X3)4ZlchD;qt_O0kaQ!D=W8lL3g2ux2gL31^4m?tf6Q{RtManA0f+2=`jfDrD z4sHYKpsNKj(h~TBbOe;tB`xiVEj;Xj^Yt1F5Bn3Xye$}NC|e6yFb69C@WMDXsgY+= zyJriV;Z81WhDW!cl>(LD+#77+vns{dcG|(8UNGFyZAGebrz6~Sc+k`SAw2eepXb<= zcT_eOSZ~DAReFNUqEvWKYeB0A`W+S^pM!KPJQ{A|l_}M_h|(#hUt{6%KqjElxX


    _9*}knoG2A?qEyhyf}sqa!ytxIusVQ?g(sNU`u(Ti@J@S^$GR`8 zojs8Dg{Sgq_+3^cz-=1~pYyAFj?edGX_8`H_r|T1!uNkFFMDC@)dM^aQd}I>AC-9f zCeJ~7_jaVf;^wu6BYDX>rPI52l!9aFx}lIP((=yMK;=rWQINjw?df+)W9FnKI6`CL z8OSKu1nC7{1Zi(@h>N|z`o^L2aoE%^Sdk5$c4FCg;rZTApPW!0JO#g5X?YB;KzjZF zFJ7rukQbi!CP%7Q7H*?FUXa?8mD`D)pT%3@3Z!S7yW38mZa!Cf?&rcA_kBoT>iJ0b z^;|Faf7)XOY2oF;0iFrzfQ3rx`{iiwTL6Ov3JW({Fv>zZ1GDS_UnzC{8g}8iUJb!K zcz%GF16CkNjb11nOmrRHso!almTvD?w%i*FEEj7{cww9Ne8BH0Rl7!Nz8q3-6dHo8 zk>XVFdpmeC>JNfpfOr;Ibr}OKk+N!_{2qvaK)#N!l@RzLuqQITJ>|P^&fbz zD=%~}2D>0p3j_dYrGm7(3))Uv(l1HJ<4rw(FC1shUsNglIckFRfQDhMnpAq0RFE*w z1&qY_Pdz$y?or$>LD;0op{YhEqZ_NIia)s(%&>{Q;Vq_Xffd zWJRixt+Yejhf~+TUQ6}CdX?)@D^|~^;!!{R9&1Kvyb#@6_!B&-`TG<8GARd(_c`BS$}Jd;pNqMU@U&>Ls0wQ3a%d*eraT z>gn6*aH9KZooq-y8q+(#*_`Tq;L-m|yHjv2Qhw)TjwrGJ?{_gh;bXj!(i6mwdK&it zZOn|M!|2yQ|E_1u39TzF2yAVxinS6PUd~ZJ)@FWQ~paL@9{d)0A4S`9u8V z8Bq9wpg29hA-OM=4yVB23tE4(oVB;tJMgR+njdPwi`RTYN`(RiE*OlvnbKR40&^no zcaCZAa&pWRt&|#}o=Al}I|aaAAVy}Bz#pa7-?~it)|eglnJ~?2+!?$x4{WD&e1XX& zds*nLQ`g6o4yJmU4%8x~o`*=w-tH!P5%_LPJXG_}CpMc$QSZ%r_{mJkTQJ-C$K`k@5Cm=fzDEo3b$_d8El* z1pT#yC}Zhpkv?YsVDaI}vB1#Aq82R)NC`qF?BYXDsa&<0j7W&E4i`6Hg*&l``=Fas zW^W)90|L$ch&8-Lt!54|K^HfNxE$Cj5T~ay>O{~j`B4!kEY3kNZ((PNP%lfh#~qk_qf|w z3~!{{f>5(_X9#(MBD&bx-0(3ot6ZK%Too2Gcntd}Cj$sngRH{EC-lY#1SBomEx`^8 z;_jUmL|CYc3=4;FiQv_^972}N#TH8+V|=?s`zkDYE^aZ|xwCDR z7(p!eEovP^F{q2rhWH;W3PWfDDKykAjE+3qdFbKe}^-?W{W786Hd&0lY|vSadB2 zyK#&39Vy1f;x2w97A*v$)#^em!sLf!3<98M-W^{shtUKOj$;$yV6{c!Y909}B5Feq z%3?}W5+*0_Zf1hHDI~WcFf)B;xi6kUq|RhmG9h+>uuPzYH4oy_5Pr)ui@`=qhysTnWyojU*?8z!?TVY!wcI3l|urs?D&J@q1 zNIp0Bq3lEav_*OixE8$yM@o@MCgO%j?87O`p_w9%(A_R$vlq$Rp8T)HquzPCoZ-n7 zhy+(fuKS|Y#twngi~WHoWD#<T;VFJ8zKPH!A z5#LF3y$MD1nutdwOB%@%0c6GENq;{~HDY0UW4&?=IIN~1crYTV>}4-1Qcy4i#E9T? z6P}4AAwWRg7>`S)5k$;HCNPG1=F|QlWyJ)91W;Cf;vxY8Udvt_(8#i+O}Lc@`1p!p zl?kdTNyM3Ed=cjprb&pCtr80ZVib<@A|q*}7?nlE6v`EZ@cacaoqQqZXb~lbxkX!y z_9nbMHxy{>fiJ=@$ZJM#8O4l7nd3vsGj>KXqlp;FLNKwbaJ@y`D+Q^Tkf|o3f4WDw ziio!!!U|6CD8Tn35Lv$t;i`kMTePSk#RoE^MRcS<&@fLF<+;e9ib14^BXmb|alDtR z1&tDKA;O(a1W=`{cTbT)Xo=nu=7S(m2SHei0@h>Fy3Dt-wUkv30T@hR`Z)`uQbTV{ zW0kln@(UafYJxhP(-wul@(JGHVrf*6pHSF?>lvjZARP&WJR=iw%^=1OI$11vJ%M2m zJ;!c9q-L`Frzhl>Wi^=yEsBHyHhMUOrbrXJW2s6cuZQeOT4aF|#0W z3}1ik}iS>TLOYn zAD2TgdhME>3qo8(#mLAp5qbkjXbCl~YyPd`()328F44SxplD8CVaiv? z=j1JT_9wPOzqG%)Xx~{cy;n>Y?v$;RD`R>ruKssC4ak z@6e8L^9d38Nrp`jPxTaApm)d`Srckg{oa%x(Nsk5D);H$6qiX<1jU+iT&yT5c3o(^|B!ugmQL(gtiQ|_Y7>Q*z>zf>=>+vCkYr_a9}uu9k5dX?5? znksGItSNld9uE{9(ya=0_s)!xz279r*O;;>d1mSnP-So0rT(D2vLlM;Llucqr&B%a z{!xEFVlJ~I(fsw^g(Fm3O(DWPY>P(I`h{%>K}9`>!^)0Wa^<={|0+{2b{fs+a<1hm zH_@hBc8oQYql(D8_I*3DA8L8bP9qCGUWpwj)cp7sjW zi)=WF$nz$nBZ9g`<-3Ri$!#=W68mUhs`*k&oqpz*D83^`0l82od-&zeS6CC6AIR+O zVr@VTM^oA3qRNT-s;IMDw?4ad8w#kbH-1VhU^WlYg}ev8^kmqv(ExR6 z{#dT5#}@lCpE)$UiCK&oa7L7!GAN!+V?C(&UCExXdJwW0Z<5LAm8^@Qt-i6%;GkWp z@t}NXoQS@4$#zWe&Mil{`&`RfUT;T!W7E;p-vD4VyriOMHd7A}i&avAldb4UR z#+}|M`PsV5blZ`B5@dV%8OS3^C>ahcv zMU8Dnn34t|_vFNV7i!dZO+vAj=ZIY>0=?ySHR+r<0nEOlFlLy3n=)!KLd&8lZ(4VU z>Vs|Jc|xHKj=3Wgjb?MR>BRzib^*l?D=OF&E%Q`V%p_3qp`)BAc{s>$%UN_5MU1$N zgr-;j9F`LSB_WB+aZlhNEM0Fi*Dyp2sZ=@MaxuXlsSc#%X zLye}p4ti}eRnf!y%AI2Ml$fPZV{40|sdxPr^9qVu(M%_*>}=xfK{30k2Z-uAoI@1r z01AMHdW)yYijk;iv_!Aj)MK(o@j0?#%+#V7^Rf-02EDkmmyl%DHAQJ=f@0$C3Jj5r zw8MU;?wt3N{pA(xWn^7(P|7S6?ZnZ#VTsZQp?C_jeal6K2=i`n)Gb}^|tq=9FwMWvmGr_ zqo+fR-{z4cO!StZrhx)L(Q#bk{lU{%Ic?(4Nr!M3tzp_%F!fTnQ?p-g#>zF6^)mN! zSpBP=9Z@?p9mtNTSX*df!t0T_pLXA=+Jchq4Jv9wyYh@pQ0}`6uYNX}fXbKS$KO&e z+;GMW8m}iCU)11O@g|~TCWb;oJ@7~tWzQ7Zp?*wHFg#5CCDub(1VI+FbEaPK9;az` zhElf{uoVSv{GOJw9676^$#!-gioF%0Ja?O#^mo|B z*p%KhWMaze%%%*!G_~cy2n2pWuj`#=P-pIc@(s=&zoqk=^4x98V6v$5$rG(7n|iL@ zE2d-t1m#_9O|}sjM??k+FxIY&<^bE#kONfM2a<(VP&8SmwbcSO_`L76-DUs?>TAPf zDL_rLK4p1xd>~w@={bWrAW`yak%jdD)lt9JxYX`NLsHFzB=A&nCgQ1p5NtglqxYwB z(kTL9kcCA7RUU)qed z$&N@A{Vgc%^fnbe(ZT2VJeeTP4z8K>llqE1UxEE9+B0%A0Y0E)3TVIkzoQ$pArmZD@fFZ_q;(dKgn(iDl`qHB7UdII)PA8!JI%@y5UADD^lkYG+GbjOgJpB6=Aw8Mj-8WQxL33ja3$_ zGI@*VO;Qknmd^B`6C9mFqQfsvhs5-?9+Wm5Sigd_-)EAO55mc6J$Or>@_J^=#@Yk2 z8Z9O*COSoZwjBK{!vK=Cg;>;YJsh)i$+i1-N%Hu#{rO4-RJwESX z-Sr94Y~lBwSW}1`bi+AsN%{Ldk!E!O$t0P|f^`^F`uKg9Y%$TMjwbQZ6K~+3x}YWb)O+M(fv6_YY3o78z`z8$FX1 z6hlv>8s1V_Z#&yxs({GduXY=)=bPHFD>u01SxgfcWFROn4_c6Dht8KA-_!z4ne_KO zq)noODf>bjD`N!EwNi9^i$=?>35gGl>(FSudRR5qtG#X>L)chl&(K2)^SlE<3?>K( zJXx}OX>t-#;*y@*O1AX;Vu#>!NF!5JL2E`fT0fo=8s*T87Jx^J-)?D8rH&}_iPi!e zmNG2>LYYisbK9|Ibc0rF2Xi0|Jr>TvuwCm0FJi=+RJUrhc7OrVsOq$kFC(y8B(JBK zX^{*kikOti9<3HiQh#5Sqz~_O&a$J zsoc9%;FX)u1!CZs+#RYLnbcb~S^{gH`y_-G0S{BDl5Vp_!1ZRtIJcM$h8?>?kZ1?m zzE`vqzo5;!CFH2@{xue<6-CZOn~_Y|;0N*Ykeaj9wG(M4ptX;7m+5v~m^>rOiu)2S zffK-$ko=Zm1IPsJs6d|TAbG}P4RlDB@WMoFVL|D)@Ipl5XHX>~J?r5IXOht7AZbk9 zSD*j`38NuM`8zG6MqUAjBrB01{Iq@u)4?rCMy#%^Z*67wRzc23Uf0bg}6Z4NOMhKr01b5IfQm zDrCDLNNX5K%;!V(D3O|vk3$LDNzP}k@V@dbq= zi!?sOQ8uk^p2mw7;WQ_PwdUfC1EWAKI!=sr3RM1U%f}u((J65)fS}knWO6u;Itu{k z0jI>Y4(O`tO8l_l9xPe!$PE2fg$$;$j zxRR~?BEOATV@P7yZ=S!pS+ov2&xtExq7sSQ?bX)Sp&T;%79!)mb8(8q@BMq6m)+7C zOX+67KcRn%7UWTSNI8nVv3!FT)m88B!z-^D2QY27-pTLMX>>1U7WK}`cEos0p#FgGD(mv{`FQYB*eH339PDTquhH0ZtE>rAavL4l$$ zWm*17n#-iO6H3ajF&(-j>Ycf_htsfy#R*xOO(;6z`KL(^iRj@wQ z5eZGnZvl+k4{RDKq@8z2B2bO4n#BCn)S<(%B9NvqZ)5OWS{m@*onx& zM9nX9D4*`=J4l_Cv3tY`vaM0J&x#histESh&Id@Q92uu3r%4mAeiT+)(V`i;5jkcu zwWg#=>5B9OA7xo{c53OsoLWIN!ffrL01lIPQ;Eb}_Phz18x}H*NXll*QRH_$kFy{H^RzS$-DxQ@#l9W| zvXvQRQWcV>uIxicb~rPH0(72y2RV(;-0~QDons6~TGM1{T@5)7&`HwqL`b*`j3?^M zCfQyW^~?DrJMwNN1sVLDcNRJBj~su~5=@Z#1NfGpUa6}@N?p0b#vl{e#m!W|+7aQH zT}Z=Nwt{R7(cGvN$goHu@kNs&oo3UrXkoBr>*}rCupOGeXh{p$$_tY4PT4!L|G`7# z%&?OX?pBbBd`hIy{UA4)J1UZ$Kp~Av^<~d>T3twEs?vrZp*5 zbh%g2r`^vgdfd4)qibb!(CU)L{f*AJ0}!-y{U@Jh015i$r-qyENq+OwgfWS}RiiVI zC3!}&L}w^Vv;nZVKlBt$68HQ;0?bqd9om%;Lged=6?Rh@?!R&pbN}|l&TA91Gy1HAd zpS!hd@7A8-2ese5cZpV=fbCH~Q9OPtXmCg5KdjyVhqe0$#2DqFt2X*N1E5?Rblk@! zQ2&jkKn%6+$Nh~H?#tYR_Bt(Lxs*8|dqZVJ6Cf2jAm}*O2wKP`FYpOv)G0SU=MVQe zI_@59=#OaPU^nzfw07{wP06$jc&_aaH;l6B*`PJo;ij8@t%VyV(It;m>>5XkIu|mgIsSVXE4f60G1zcqs zzg@I8DaY^X=IpW5<{0F(W9nC%QOp@R0kPX54`QL)%Lfw6Wxy1S}JD;4+yO zFtbDt@AM+DXbE7}ucmPXEohZaV>;kKeiwP(03=$NuJ!&!olKWPh(bqk*tKv09T>T^rCWN#ifC}vk(^`En2C=SX(8H2Hn@EiVn=jWy7nb| zXxTnb{Rs3;K~m5=)cr{h5DA(p26F`pUy1`K3}r0^f@_R7(GEOIw1PexOAee1+2@msVRTTxKi6ie*CW7$8<2plAGC{Rs$M1Ikn3d-ncAH-dGCS zSgh$3pa`u)f}*apHPiZzcEMZg908>b51=*wJ0sIt-c59X#Ze~K34*4xu!a=$?$GTe z{PLlOIQH{5m@KhMR4frSi4NGrYpG~?A4_}P0L*aKm&i0OCA%GZ*a`nF(V8@pJVN5srzgj<()3=2;AmvrG3b-d=doEF+PjvS(j*7+d1WwU ziAWw*6k{K`u+{+0f_57vIqLK!b?7plqZ7>{1P8k=bquh}7lbB`gt!_V#|o`R(&TSC z&EwE9j|+2$J_YV5*{mU&s()ZFKj>uhD8!F(!rx-av^BSAht$gYt_q0bYs&MvTuwGjAVzWdmCHh=Lf4rNc^Bm{yk&1R#0R8*}Mk4#Bu{3n)uw9YeZH zhYr89*9@&bYs?EeW<{bJD*E|XGn#NUJzf>b;7usc2J4P2iX%oEy%Ky~ECntZ18l5$yWe$0Zyk^=k~)EEds zmpcPS+*~^Ji z#LAXr$+f06xp99Xs=5DgxG)NoNMQ6NfqECQ z6$d(Y`zdrb)BL_4MSwr50p!MsaI*b9OM<*G@)c^gge!Rn zDt^FrJ?OJ!lRz^7!*2@O_@BxkPf)4p+;)<0V^*nOiOzjnbZoc}xvW>sS(5k0T7V7u zZ6)W~-uAjIn^8uPw-lUc*-DsF)I$mYq=$;uZdfCHqLck&IgqbbVMJ&9NA$P5Y2z9+ z=6KSppeny)Ayv&5;6#lG2c0| z9^*3&JikMNmq2aD}00( zv_<_GnRNgFG}{}h-?F_gKM1*8yENaK_JnNtIANHSp^L^##v+V% znTE58zgjHC!8u_UMF^=w8Idc{P;)$GSlNFWLGVjx_DbI-EsqmkNIt~@vn|A=#2acuk0scq%9VR5|)@5SR1)5=(`jY7=-%j|m0l3Tvx+*fmjBvAJ z&OiI~heccP)Qxn4TpJMg(~MY(so+{M6&5QdFj2rpF#%d8=7;qgRJf&zRlubgVVEG4 zy1}gq!WHvb##_x~KvYadHFeEr70fNBo^$t81K06537Abxy_mu_14rcs_bTwzOzqhM zP)-l}_4OQkO0lo=&QLuLH;WOQ7~KK5RykFirWhfZp3pO64corXn!yI9+Jo}6(dI|G zeLzypU+utbd)^HT<5_c~v)@rpVqA%d;U3Bfi<0&eGn#HhxI4E-zoYp#m=$1TibHB1 zg8}!Y18c<+MquwJ4k=BHP~%U?Ibvmbqwh^7FoZ%KZ}|H_?d!ZTaWfkjITQog&8JYb zum6-$v|&SbJgCzxA#9-PHMJH$c@? z%O#N=R>vy|df6&|YTi>qV`gZ-+cj~vkQ-6g!^;fu4uc|xsC%998f;;sm_^kc} zpVgn>v-%UY`BJWOpmZEM?6pGi|7QagI&jy@m(qX`OcT)QlT!6sC|a9bUk|M5Fwl4ax^`V?yw zK(g&kolE1#(2o+*%*3Wn+GwXRS`9NXfrK-aw(5*?FePF~d0T_G`q8}6+A6(&oCv0MK{Y->#e=p{-(*pE`sM_Z0kh5 zZQ-J(#RqaqM-4kH9%hFC?jyEZbd)m-8f`14xoWv*ynb?;8trEU)j#OiwGHMa`!KOt z#VE39^TmVbk2Ay496)M2;+q3yY_pJVuT+QgWyTxhGqdZlU^jf*9*c@$)92Ps4tmrm zMtZ7YYUlah#eOdx<=ggq(zD(DXV5ssgolF*N6WoneK4=mwDBUmkkaK81To1K)is0w z0e^UBbTB?9jGULRc7?`xV?_HUwj_`b8?xvWWXy7CYE8)i;0!YZ6|s3BG3mhY$Vp&p zJ9hnhE}+3QKFW396qxwO=yV zwV7PkW^!GBVQVe@sF=L$)Q%D^+-NIixf&Q^2%$$aql8||%8y;Ci3uMtF=-(oioJ|z z^kAZTQZZh)A3nEBCOXSm-7VN_09 zwN)|T?SNr|$^DufgVa6)J~QEND2Me~t3h(o)*OYMwFzF{B+^mq3r!gIQoACsP>5P4 zxERa^AH6M1TK?r3j*J<4qYf{Dnay)zK+3pZ%7KyZqc@F{tCOX=F9!-mA_%LE_s^zI zYYH(O^TQEO3{;reLvd){%5XIicMsu((&`BdNv?wGa?83urvj8D*&av))1+Ld}L+74K@Z%2(f zP8kG+EtX<{F!S&57#)rh)5su4pIl2I5e!S3+9`n-+ZOKY<_6Mib7nTDU3cv3wtKAp zj-+nHe$@XhMdO8;uLj`@x*kONpjKvx;Hy zscSU1Xxkr1o-_=Lck#Uj<(!;gad^ul%%FQfrzWsWIYfCLg*V+cqTcHY;w1+J!g9GU zD$nZyv~tZMx{5caUr`4z9OdJsa+m~HqpD{NN^i!XONurZY6;y?k{M>O;~s(PFf1%{ z;D|o^CME%0!5m@t$wwy#cp8;tyu6(Ql+nsXTSv%h9Z*4&FaWAvE#L-1lB+rpgEd7k zAw538>sW1QJ6KufoO8<0Z+$VMdBEV>iZN!Q*y2){-e5K`(&2E?VOgQ*?w}CdLjp_o zB+fOS(UU%iXyJgC+X-6swpo~SO+nF-U}B7bfRe+6jJiZ~z=YBXKPxdY7EY^$ZeE*H zbn0j8IG1GN`5Z5SPxPO=i6AUn9Y~F4UYG832<8P+<$e0yV zh-Z!(Z_`zV2YF<%JUsvj1|mYK(qhcu5v|#lM!zm$oB^%cE#HZQ@SWdeI&S&TI^>Ex1p= z#p!kA*eIdJKv@%G3ndsum7Z!esu*t??y{J)SROeUHg>Td2MufO6~>#dckZ*8v(e1R__No#_P;Xww}!RPy}AWOt$RI%=&0R&$fifF%In` zYhX|dd8M$Owyw)iBS(<)g9yG3=8z9+bn#D}V+IcyhQ%-@Vs%SCGf6*xIgZDXZJ*~7 z24c3-R7|=)^~7MTxyYGWX)s}>8KKUMgRk3~{gNqF!0_d7TI5tc5%8LxK+q7YOl>2| z37T#TQaLVIr+2y#x}6Lc#l)5)B1JO4AF*)pb1%9WfKQ@d3;cE3hmnFe$-c z%<ORtk#_)1Cub&xF$@`%*43} zM8>y6#TG7&XCe(wfxi^Vc`(q6Tb8+=K=#sT>i%h!MHS1@}9*BtM;4F39Q z6^Scu21UYYoBWiU0a?~KP*Zaeh#Gk*I#+-wc^QR`JVC0_8I*U=zo2d}?(3gaalPg$ z^ffpymB;UWT}6fZI+RMpVVdLi5m{+YS|DO2br*AvmNcim>&)Ae#`1M)XM?6@p|j*V z0kWL<(^p)VwA*9*I-jHQVhKF(?jvWazk8xP+wI;9eG#I_Yg3$r$9G z!Fid4l0sH@&>%W~4Xy;&96vTJXikAk(yoyw&JiT!1qhqkFL8QO{etqa!G_~cGDpVU zI~AvL_demChu?vGCT}Eh+YB&2i}PMb)a`Oa?56$viL0)2G_SS}_&Rg4C9$?r$YPgA!-8XT9@bWkQ?E;TIL5U+xYQ$cmqCeD#@WYlmkj*|r`{wZ4Ng(S-}*=-IACE} zt2-JtT2qTH8#{&r$TKHp=66UF%Esx-9rCatZ)W5hPNy$e(duo@#Yaha2ROwB zZ*gwcjC(ak11%d=Mtz@-HqOa2ketq&4vuvK^(EzLDUXn0{&Jmx<#Kw;cZVCx5BOJk z%*)i3(8?`uh!*#fcoQ$@QnJgQJHoz%kcs>0lntu^vMi&dnQmh@5qa|V_srZbJ>I>kvHUr9f?`i&!>`%5ig6Q{;=&iUtn3jM2|x& zWrV=l^+*do%Ly~ofTMN|0B*DMhG0`TpG%!E-eqr2$B-ZhR(ZIQ{TWAJWeU*mpeKls zO#$Q5A+n)oPo~IN#zP#KxcqW_h;{#6fWXV@MuPahK)W`UXR)s@_`PI=1&Rb0$4SOm zVZ2U;4+!$)ttlxkRa?cyrye42JHE@}yz>iQQhO`md=O|jCyixkaruhFC_u@a0w_^{cP?>vgPXm(t^-ey>*c#B+9Z$ST$f(f;GR*l>h0Vm;yIFr zW}ZL`gf4F^(@j|R=yx2!FAhz^Jf`zH%)uCmFgH70V_6teRxspgh*mXd3_5j5<;hU> zkMq=wF9ovD6}RZEoRXl%b_2jMUZwds1)E;*g$_i*s{(ANq_h^Ln1HZtifsQ zFk7VSv@_YY>+6D}c3;oTI-bm2@^~7{U%lMs8Dm5=mst)DMa6<}vAlOO8u*b3j)b$u zj3oj%YfS5o7jTXuWe^j~TPzbMbJEMvL(4TlOnDU|_UoJC(2)<)*Bye3&Zd$zjS1%? z^|qPlK=zgyYSdjE0a|e&GDO~zM>oK4^VbfRyEsyLj1|jW4h#+dq0d6Vv)j36wZ=y7}FI3f^ka4Zwd4mh0V zhZr3N9OZOg67DG+&aQX83p9e$LR8EhnR8d7rS-`J+3Qp%ZJS^$t5b2B8FF6&$a04< zY(n0-TPxl{AQwJ&s$Dn_@|34DMv`9Qp5m%{i3m%*k80517Dp;-3ye6;PI16*u{@~F zN5SQJCphZ@_kw`}fl|bGu}mPXfW|nE&m4LZ>>jjd*|=76nCCc1vf~3M9h@@&9*w~@IF8qp5uAnSki z3pl=aVC$1dE0)=A?sJs@LC@eAllFOd1ab0y5`LYytQ8a5V~a&4>!Yze>K~*H@BDf` zoG`|NIGvoVxI*&iWEzW(d0f^;aN0Kc7G-UYqofW<2LF~x40loLJCXujf+H@FX3?h% zmo=is+rS~#D43)Qf;O%~9!HqT74#t?%hld%ftt%xf0E8hgL@KV=ULmp-LfDS>~GGB z0dQG9(=CX=B#wxZ=F%*hxTUE|OP4C1tUaXYd>H zY+>!O--sEkVo|Ad_&N)WQLI$Riq6=pu|HJ|;0k>^kQSZlS*$R<-_R66=jGGbEA%(; zfE(ef!G-~J!wWdYiqIC-{D#2^*jt~)zGk5)X75&T2y6ybQm#;y43CiOEyW1~FTup*Mhy28x`VkFR`kni1Bja zxUt-aicOJODje0N04nF&;f)X~<(dstcqO(kyJ@h|U~S-R$o{@JW5Z%xxsHucfePdX z`&vCx*Y0b4Y((FzSZQ6fP|lUYVH@sB27=t>Vcn9%Zz)Kg!d?7Q!8)3klq)+#QFS1X zuu^U+vGEd%5LRJ!Y7wm6V1bI_cPlm?k~>qF-2DqJ&nVZsv84?CkYf3-o6*~yt0$H} zq{8Kf!eDIrDpwfMC)eVu>=kPRXO>Gv0^U`*u%K`iYZNK7alcP8D;+dAtXLJjed`hn z9K}<)2d3ES%zhqgYMITre=2-5Ipv%ibzonsaTcu6Bv4{6Myv$5G~#Oqv@eC7N+)UK zbz%o8z7ck~f$Li}H!Qn8w?CkaYcD>zq61OoV0 zJj7n_og8aMfz?Rh{Cqb`VxQTXabe|3t=k2O!dmvX-#ueJjRlKGHrDn0uCC3e*2bMd z`m~;cm$xFE>KQgv?hH~}8wUU#)F!!Uy4?760ErrF1bvpPp34vA!g2)7O4)(xF=Ncw zzP=tjV{NDF&YVV?kKGg-nsLL^?TiHjL0wn5L@?J`ovl>M&5x08B^!ubJc-E$rz zn04-y_tu!r#U+igKzOiDZ#%vlPL@U`Xi%)Eu;?Ob1}06&L4!fuE8 z8+XPdeKd`j9e|sau)k7|%`8q@{4V_klBJQ*Ij{kv%Jpfim_6;`TQhgUmap{bO_t6) zj`;e_z)Ow?ItOzl0VG)kIa+YgO%Ycs3CD}R*vKrKq=W~q$oJ?2uEv*FV11fbI#qWC z^vL}|9e~Ght-kg*s@R*plD#9NAdMAmLl?Z9repSu4-`uwpM}D&#>0Jv!3APsJjG5x zYj|mv(Hbk5@Rb8cVInAM5cG;>4*_X`?p$K;QkYy+ZrI^sZMrA84wmna6P=s786!#_ zME8Zjwblxbr=oOXdTPJ|9}EWqP=U8$?LuVJ1y*{Wpne{lTy5{JPE1~55cJ{;YTTr; zvOC;n7z#JhUi_8nxK4*%&e&bFnsT*EJGrc|Hv2usoy)E|?F4kRM`PtnLX9}@@HxA{ z)Pgo)vU_%!rE;80oyYe5U?Y%Gt>9c6Okb)C`|SUW`^H(1r9Mvm<)V zejnU}30FFlV*t{UGHgu)E7ux0EuCdH6l1Xh?sg))AY4VUC|3tBb4aIHIZV5FjsR+~ z`i_e~FN`k-D=XJw7&5mwEOUmb&9%nVlc8^)b17%4eyg5PwXECmt*l7E2T-8Y;J9 zbE9MnAY!dnK$MJ=c-AOZv|*QPz&{5L*497rQ<0*1hJPBBfx z+V8>%WLb&LroFCPuqhUU&*#|!Z^K%d=V6sGpMbwsN*xz?@+xYZ!qmA?X7sg;e1SmT z`58l_)Vc>H9MVGWq&F&=>H_szDW@a7QW?i!u6WJYS&u=JR}AyWbx=T?S#7>di04WQ zp^4e5$ZQ^T6&j?2k(67H0i3aX`jj6^U=f~$Frbwx1V<1StlaS`{wdfzYoy%7()vbs zs_xA`^4Y(4x9^)-N}|jcb0Nt5+!elgg+IA+{rxNXgDd&PuUx+W?_Mdte5L&P75;Bt zDgW+DzCISEfBE@~;%6@Lzcg>Q%Kw*wt@za|{J(jHU%SHp?iK#ypAJF({r6Y$|HKvk zXRq)-cZL6Ziy_GOE1H-2zkQ|rKX!%x<175f*5&K}!Ik`iLx=S*|K2|lY{mbRSNQK; z;fvIO`TA>D^8eHo{@s<|`=u-S#d-+x{noGWpI#~d$EkvI`DUu%%-_6HK6Quc{Ze?pae=WLKRsP;#vrD`LC|zr|wfd|C=lMdx?MltM^Ui{!^@0;4-iXki%+1mwR2dEZ_WL zv3iO_al`96@?(nC9AuXkqu_7f`a#-|4CV&^Ssi1AzgLHEgP-BI!Os9(^EJrUJg!dO zgbV+5eTT03z*ddih_3~>>3QI*5I6IF(-hXG{NO#YME)$8E%S0;jnApPo;C$;IUh?v z!F<*4Cul{%P0p`}FzI^#5`c)pmc-Wrm*80?=kqjarMv;JkK^D}gyRQ41B>|r%_Sa? zv*J^z)oR9kuiqF6Z`8u++`nqr8anvIe zDDlKh#TQgFFE{@A^qlAM^|9jx^g8hjfyb%8J0HU`7HCs`sdIDaVmy!GZMAJ0KM_2c zzrsxZa6_I;7_cfI$EQ~PDe>uey2xi`VB4Mx{fq48nrZIOGFq5BbJ>_Zm0m})eMWc{!j9Y(%+3@@hz>KE>1%(fgta|^< z6EA^9Jj-VX6@KW9pJ-s!ctVH!6W`B3cyjAh-n@N5>4(HeM7zpg(FYY6?#}{{pAhYD zG*EPX=JWF;o=?VFU*`P7;XW?uto)JUzH7YCaH{iK1gP$7UGMW|YJBzn>G!>g zT+5e*|81S$my5irAXgSzQ;3`M)9jom;qquRmObdtgJF%|8ouRgN~?j@=dJ0Pf0lN9b3eT&b#poz?Qf{Q zG&^Zoy{B+8%6m3au&IynO*~l<$dvf}u?Na$1V1p{8SjvnT7DdLxXMs8rjJ7BsJKSv zzu4WB>j-~xLJ{xo<7gVZja`V$qv$q@kIlJrf`~$3CI}_o1^9FgET7CT0U;LF{Y^+*UD?}?6 zkXE+{%Oc2{I4LdEHde#;S958~YODg22DoK7%)FKpz;^_=!V8kuVF7AGp3mW~`J@B! zDa4g0*5M_qnrEJGJ%1cG74P`FAt(xwUE=exVAAK}W5X7!NwlGOhB1)1F?j9|-xp4l z0A}%?Id_Mjvpu6#@p(Sn?!8T8H^#?ys4D;=htIBJ>TrBm4s>d)YV)37-RGK$_eS=7 z8in}n9{oF2(kSM{=b z|E~~m+h>hcFw7W2U9bAA0s?XpNH1-fZUld!KtipMHdg(x+dI4bjCozPb#n#en?Q;5+n(Uc!=WS z_yCGmb!6rakyib4^(^v-GUh--WAogq0Bqx=5n8hv2zKtmP4V%yC4hE5g|o_evH>J} ziAp>*dVs!gEr{oo2YOEm7hUzSmBgvUnn1A{IJVXewfUgAs`Yfn@-h97cqQ^3n(2pE z_}Qw%G3D~8<5QpFqiooJ>=6a()(?celQ74mlU3e_iKO{P{5g9+Jy?WMi?8W7^EjGJ z*MW|&D(LcIkMV~YqV_PBzQs$r7sH=Css}Bv4!v>7LlAvhta1#WuuL@|^**QL>FQyX zs|bnb9USs7e5tfpRhVVyAO~8m+HTn-K(+*Nr+=GgXDLU?D!gZPgsDNmddB)!LDgyN zO)vk*UrVrhLYgZ+-dWcN?2eieWDL(9l21y?X$X0|m*`im17Tt5>;}raJ5eQyoPkFRRnsxg zFFrLk?*PwS=I#(%fmd-Y_EqBs!?_=C8OIo={MqJF)PnN050pviWRJHn&j2MW^sw^T z*opBOXWA622@-!b87oRgJO;h+bH#^KAAxi8ML5>u)P77AHT_(yzEwC_O`pEiLGoyf ztY3(fsOj%w^-R6Vu^ImEPViQbw{?u`TE?4BPWTQ1JJQ#Bc`xWbt$>HT);IdYcF-V- zwbW!clIK^ffl1xI`RNbhC_S8P1h;=!N1+gaLfI0h9dXkvsN+Hw)PWfb>c|WNkS96Q zv71o$_}bu%pP06m!03agz$CD{o5Q(O!f%lRx_n7?*rYI$z#doiq+i#=ja=eV#Eot` zsRh}%M7GKuSF;u%lJ$tKCImASNfDWqfI)LOP_18&>Ic>`upj|DO!u(~G*9~FKt(qlBe(=9>5@v|m7u!7kqUKzqcC`|3U;#HlLd0?!w_-_hdeUkc{1Gt zr0HpL1YALyD;2A#AU=1?y1*xNuQ^uobIpxwDBGc=J9kR-4j<0&`^ z@KH*Rh+zwF60o2?JgAq56Ih8);$0F-mDG9&w)xRZ0?(YbEBv#=4ddo9Ubw^|l__Az z4`zY>_|bU|A_RXz<>me6A&9OZy}><_&f5r|OoAL@v>`9@vH(Zvl7M04d*mZ2ZT0DA z5p*=i`JlNZm>pq~1OfcmYg{vG7CRd?ZSX6C$vh9|cacE5mvC@+MD8JhXM?ek5DP%c z+HEA0-0KQEUirmf6J(vP9?w`AVQc>IGIQxm<-PV&o+`i z1vu$$j5%N-4m4Y<05hiiqhXg{$qJYa^*V(?0xMuX`E-Qg$xV%M?d-@=R;X4I0E{!y z3N=BHP^56HbdMzXhJ9de>`LIxC$$n9YFPTSOAh0ky>)>%M9l;z2R@#3COD0QlxKpH z!(%Wn)~-Xa5>L2hd@=_?!l%-{Vgyz-QJwZ6zfF^&)_=VE8wBE3a(10wax^c$+?@7{%ChBAEmffAxvRH zHrA^6sN^%R+2584i?OMFmTQ~5de0|_xj!IakVG(CxV;jT6HZ{3ovp3P5=^LEYR5BB z2pEv*i`<>Y+GA>zuM%;`2ytDj#sU6_ut5pNdzBP{r@ORkn{inQH0wQ~+ezTP+iWQH zidF~$pRz*{g6JAG!H)Y(5&-$6NW?TXB9Ozb(-*a<*jPg#@BXsjXynOv#87t$6oruz zNgHch<l8czru_tB1PY%^Bq4%O@}PmML1waJo})^4m>ojq0;eBJL7xw>YoXN1zr zU0XY(A8xW%qBSt}!Vq9NRD$#!rO)$t$)0z3C>SI^&L0wuI%ur9_UpB-UqiX7 z$-+)gD?tK@>{QcGxB|K=N01<}w$kuQDrYCcU;svR7=kXz0(bUH0DrN)}nKpnqZ)7Y@BA2Tu~9QuNPtX)s){P9_GPp)dp zVhy<`1$FTrn-tfC(R5}thQOfiGxkw>C>3k_oV2$IKn&z5=NtisCu=f!h~YQrj6Ax= zNpkGg9E|AU<_I-P7>Q9sMqCvFpcu!43$&B(A%XUw*g* zZ3tL)1LLsqX^X8BagK^$($~;cLLX}je^M?a0>-}UFg}&B24=&X@hm*7f+N?u{ZnvJ zwp6AA@YXPKpV#+tO7P-^5U=z}3kgs#TDHPtBx+6qLjW<&p)INU2uQS6s0$L7vv$Bw z2zAkK`&|yu4(<&3ITD%!IO4Z1*0KNvf|bTi!FLq9rdIPlQweq+yr^2+B~nLpW6#x( zx$|dP>Su6iFXvqSSg^mpPH4wkOlRop=&)I!F_i2Nm2kUD;j(X>OUld7fuP=#DZ$mf zv2iM6hj^a2$yj&-SoOKpwSI}d+#}c&xKOKoYetJ6s5^&yzLs|J&bmY3Lyp~7$Y!x7 zKxi|%CZ5btg7}mT9Y(-|1w1*Mh0-=jN^n@L?4&0gZ>Wx28GWJHiZ!D=?)-6v-kMe! z@#WZT>BleDhCVT1OTM&sIIeM~WC~5z9E8C-`|wB-pgB2vnIQ~T2A)%_S>SJcVd<$S z+pkqqr;temaX>^;eUupML)H9f3dxgz+i0yJzN3J^duppN;w;Edhrds|T&gh%fIP4c zUye67cT~cWg}cMyGktYN0`ERjof&4!f~0|YmsDbhDaT>b2rw~KpK<464df?2rJS`x zKtDBwf`z3EvexF38n|N*M}lOGct5yH*jCG9&Y#)PsAV4vHUsw%AXM*CGT3@Ln?CzM z7!K?xkVkCY%O#$TU(kTbYfLedd9t9y<;em8i(6oDS_(ON2+p%cFf!-=@VI$Ip>KT( zq!zk4iii?kB&?>LVr@DAJI4)6-ADqI&JCr*0SAyIv18&lM$j?ay+e64& zOd8jMN_}t-3;g;IWQQgJVY|tZDAp6EB-`(XJceTZaLCujH~NDcz#jV>Z*LasxKpw9 z6|Y@2T$AX{*^^YPE7r;7GF)THCGZ6a0O;4XZKRT1#)T}odLMu0IL0D7`}AA)*g@*; z-r>1eatYT#^7Z9Co0i0zr1gJGr0y+QQuzx*RO+kp;ej=o_)$yms;Z4&3{O8t1gM@{jvmn z_R>|t3Z7lMD$IoXRrW(l>c>zRz3lFt+@?sppEpO6Qzk=Qp^J1?mL%lriUjCtCdt^< z70Hz{y3xJbRTXm&!;& zFJN`dU|N#s6GK(cq#|OfikGL?846>ZrU{z+SYqfW0O%wEo}7(b;bqa`0zX|hf~J1L z=X;E(&Lrt$=KPl6F8hip1}h|v8N*X!3Zsm=0JC0Ai+b?yon?v2U}J5tlmSBMO&>{; zEIztFZ{adLB5T!JcH$}l<^hi6I&_4WzHHU$y#n>5OhUD|cSq)HNKV14Sh?TOx@wZR zr31-8lJzVo&4BQ+n&dgV%bD(Yo?Hg3%j>h3Bs=W9sFfLDVPK}zBvigpwb@k@7A-A>N~mjCj><5vktQ<*dqNL%y=Cs!mGB{d0Vsu8={RVV#@?3emg zwP#LuPN&D#?o)f_ROT$cbHx)zZ>n}xbCt2KbVSn&cIza`fL)IV7wQeV>Jr*Ds7Ye# zkwlXP?MkGu+g%bZj9^K#!X~{T2{T+Rx`*E~!ZkaqDoOCm9B!aPTcXTt`_YB&!*US6 zb$+4l$%kau0ml5PO?~hEuy^zBRSA*Al+j1m4Kn5D$*V}SIW9{Af99Fdld(seX7}2X zBq@9=ynx2Km!7o-jVXzR$-Hb3LoP8}$=JbJHr5k@q{-W}Ok@4=dFNybqOkQU;alqh ztCE6vc)_90jrAuwUhwXn+2MfeKutfMvIg19dx0eZ@t6hSG}bE!sxPjC`e9VUT;=V~gQvkejH4F&VV;fkwDabIxutH zXIa(Ww6V_0e^vPcUXbWJigjGCk|8?~b`wjUmOL!GU4wMf%$C6YB?Rau3*7x>t2GYhgH8&D}kpiXGIhJO{BHHWXBuclX zSp(YGPC+v8LnbL&v@`2XdTD;WBM`p! z>60X>L3frg&Lf6j2(l#X)vb*|BnBZADCOy?Y_5Bvt+f|rA{vQ4Z_HW0p5QH=u_Sy; zR|P7^(uiX`RVKT$PiS1f>2w?(eEKcQOvgTXw_BIIb=XDH3B`K-cs)g}AnEN-*>TF2 zbboA(xrtahHgE$+x%I;iD|5$M zXX%Z7R53o|#GSL3cgwER`hh8_c~IvC62g*H0mC@|p}9V@sS+@Wr-||bA&+9J4eS$q z&)Ckc83akGrm6RqerO~bfbdG-pJH8y&iUJlFUN)lLK43cm57933l5R1v{tchxJlKM zaX?E@8v2r`)&OYJ8UkfVUlM*&dQ^uu3JOGWUK>lSS4nb7A4H=40L(8Om+H#$7JrqASeKWB+q-6P@1V6W>Xglc`vsSE;Rh2iVbi*-KJY5*^* z4kQlmq3<#ZqDST3vS|}A&m;UOwu2`~1&Ml8ZG);LuCJ_nb=71#(stcj-w2!PHP>gB zVFGT~OID7+AG@1^-U+|qs*LYYYu-b>K1q5tYtaJ91us^EXCz^X@9ZJ4SLyG|tXKF< z(gMXyQrT=(nY_wI85VJlH)rVl`WZ(BsdEr{8E8C`LAdC~u6* z8+?bb__(sh4^9l5273WfkY|v?%rIb!byM$LD5>iy( zye84t*#dUG=t3fu;z<&u6C$}E+4qQ2mjN4>vOiGaGZrxhG}1Q$d_lx+Jn3Ydhz;X9 z7Ufd0NhFDEy~jkSU;H|+i^tZFBuW&bn76GCbi6{nn^t;7>UoDrFH15(zSusOBqDy)K16p#h$PDMEyASc`nng_na6 zT(h^lJLtg8Iq5Sk#$ zWYQp%M`)Q4C&?tl2rHYA0s|xrDc~AOW-={fCi8}QlSa{4P*!CHac!(RVlOOKELh@N zkhQF=Yg^lht|E(~Vp)~-|NotK+jrmhvh13fIrp5~zI#u*=bn3h=aLZ1ZZ&E;E+SMA zFJAcH0+6!T7$nKE11w(RF(JtWdI>DRqIO_rh9G2Cp@0Vk(bnwf9~kTE-(M#XY;khX z;ERbrPeJ51F&7_$;Nl~l1ribtav=n$A9<+VViHFnpB-?B4q?%KORk*+0Ivz>3bc?k zV3~K&oOme+zCRDLK(q)%{Y5leh$TbtAbZ7mMF4V1DIFml1o8tI9?N;^B9I@p^qx2P zX5sfdAaXgiS9x6-APiezv$8qMQf&q*9C0SZBAJh*Ulk{EF4L6CuQI zCYX@V(PI#g(JcVRqJKJB%F$x-AXal?5FdFZAi3|MgwTL+sJoWkCIW&!2zLjh0B-GQ z^#TGXql-MP;+PDr8wHI(16O^Ruxb#ql(QKo9xY!1#hI*H#W@*pUtqDna?7aBE3bP7 z(cyl-=8#b=xIFS8xf9xIae#PS#;u7!e2L##u%w($sdy_8mh1}wpmbmM131v#rQ!dAMK6wsDvG4C0-~*fs{;0g;I5h&=wr^x zS|e3&p!1ifATZk$1ZK-1s$K}kz@_=DJ^+C*1%Z%3XpyD%#vpGPKxEkVcIZ18V+RNe z-U9WsUedbjGqcKWLbsYW`K#+8JpBfJ& z0gIv{`)Xqc*x$+hVo>l99#t<|E_ZkA5l^9E>f8mxG z?iGXqZLQ*}pi6e@0BC7lyB|CUi^AEVEv=C+njFCbvOr1+jckSQdDRf6kHXuk;xZvH{ICzNPbIL-LaFJKoTfO3yII133LsP+Jf|+ ztt8hu6pAc#8g5G~-pS^LPh(;?U<4A0+|nwXf0f>?h3~ed74AaWtyD%;U1T)90nwH_lfnAn7aZ1qdSoiTlURHi68qt{rP> zg_|dGe`CYAs2BCGpcA1h8|xkc?5#Xz?FBn@6%=`aTCq_@ddi1|Q>+y`y~aV`2#XRA zTx;*BJ&|LsvsQH}VC?u&sEIm()n-$bp0j-sr^vSMP3s^lYAvYOcf}srn)Rime`S zw_5f>asi3w2q3)yiq+3HRizdEjaT%st*l+j=dP{SDu@E2vD=w79NS8=1#_n^U&JN?3sMRZc7gLBAf7qe2b5NioLvxm z`iPG14g&FklG_~kXi=6wuv-H0K?qhXJv_+1PXZmNQ(*A$sD#85R&8t(UViAus}I~P zK#7kMbz$3J4Fq|N0iv`>%qp3u(@Z#rql<_Hh^%%*>d9L;h>2|7M;a)*FxJR3&e5UIGtR9 zCiT^~#jpu{4SqZU%LAuM42%6k1Y1UKH_<7@IR_YJ)H3G+`|t#o!-MF-S%>-56fg4G z2~4#T-@g^&LjyNcw;JOGRtOY8>fefMvA9Cd7sHCYvG)SEaA3=_Mu&prA~QTP?r?lZ_5`&dk*Rol zlLCNYQ4$_j39gjR$F#~lOAo_(F#npv1I!$31sFVR9!4=y8=)i7_s}+QHeoiGhv7Mu zp$?pq_Io_<;qowY6yWL?rQmh6fa!HV4`Uuk*BEws7=@wm^zoe1c!PI#+YOIgZ41TK z=3tleX{CRxpjmxj&~S|n zk8!ku(h7`^dEw)l9y!OL=&@3?nnE59%p|H?_eqNCwD?y|4lz7<+}4 zcM2X+nX+oM@GwLDkJ?pbL?RETi+7E4xp79)+ibU@pQ?W;TY&m&g2>;NgYK?~ee6yd@(V-`P#yfM^+p_~PL{ z_l*QL2o=?`z!}~ky^tz+)CTrw^o|ABx4%Oen#H0Bo(PT@R)^A$Oc(OxFlcFc>-mn} znh{tH>F8tw3f~1Dt1@ye7g`|tB8Ou9b=hL2H6$>eP6xv}qpncgA{*JnPXpL`me&IF z&NI?!Qkc#uXgwa;peY_%qZk|G(VB1x45mxwJQ!MZXF)E&0j9bYltF&VjrNwo5XyKp zyh1qp@G#av$Os5vBfST}IWaE*jF+3Pd##U{dxz<8AxtvSQ5&qQai%@K8b$Smx*A;< z3t;FUg5|Y;iZ_JyJGzTJbDnnhCR{nDxe8ziU+fwMJ0h84Z6KwQJcSU#ppx)c4q){9 zjNAzFv^W#4?bGqr!Jc^t(bNcf6^xtgSucI zYgzMJrmv=`Ea#yja=_Rjqp^G(w=(T0n4G-_l(wIK2Q6UmM~v5CTQ+t% z7;=S3v(8oqFaekqbSg+g{I73BV^^RbVBUHG*Wjdu?g6%m#F^_Nw zA@UHgI$|Stu`y0II#yiE^bPtt%0PcNF)l=NwM-8mU*`MGz+*jiy`^%%ps^0zN%*P} zxIkcc0!C{XURON$Zm}%{>l?u6`+0py);GW`&dH2$;0cQmmb(#NIebef6wYk}-`j8v zV*?CcKKV+b%QMWm#MB`@-7VXoe;Nad&bbVZ(+w76ah$FfK;de@l(Jj5WjgPt&9!K3 zbeA~Jz*w2?GrqYjWz)fA=&Cfr2RYQUA6}g4<{N|2==2SNv0>?81t%BeejgMHxsZos zKO^MCs7%K(F$ovw8g+<6sC@Nfr<2On38ujhz~CbyBi;1G$3*u40aK5Xn^uNVUN}s_Op;bR9Z%HG9S2B+6{z=YWw#nnxhZCekI8>h4QB`+VitLZclgZ^EhEB0VfR;B}n zh--vLgZ;@eKX$r`qtI(Oozw+#-m-s#KTc(O8q-EPHTN!xdIpT5`zSitt&Pfbxj%^S zO>9o(n{(}8C5W0?nZA!4IqJg^g;`2#rM zQT@7+MUu_B(gvptVzErpi&Q2co7AEC3?PnSimuR zPa^<&r-lHbL4{ro0rC`k7X|}U9|i+cCk6w(ogp3z2AU#ZE(QPt7Y!H(d4L&6s%UUw zMu4d|f-yTj=OXLQ$(@!Q>j~=E~4iy>5YEHm)0pvh3a5Ts|GmjJqch1m&-IHu-b1`A7*_pl$ zmN^00DMR{k^g)7EEtL;UPyTd;rSh1Gv26JUs-Y zaPvApOCSkeh}?34Q5r(rbHKCc07_gJ{}6ubflz^Pm&!Cfvq4}hCg+)hsxL832IMLsi+2qVv>T>+dej%AnCgFvfy`>h zYLM9jxM``F_=`M4WWqy?d7yJwI!xIecHvVo4am#P$fYuKEh#1eVUf8mi7%*MPAN9C z^QKK5M4?9qi$O+B=W>>m#DLJyScKY2X3TEYF&T(1F_1)``bU_DFi>PRuP_fJ`w50D zi+cJ-gej~W>J=LpXq~6hNo$o{45ZbDhSUY5n6$JDz!BJ@A&{Lmm`_;Xo&_;*&!{|| zZfibp$LNPfmq-|`AMS@P1rEV^jnH|=e9vFLR^FZlT)%+sGNH7vp3;4O7f!v%-{o4B;*=*C$3~*G73_0FngNW*>y5C_BY-N-f(s(i`~vrO{9wXK&>Ub^Xncs_ZD0YKc&;@eT!tn1hp z*V5*~YXX0c2L=wEHdaSSvIo&QZNwpHmO>M~P22@i1Wv^feX(S^OsN8xecF7kWT1l*s7AOR>(U#qz*7Iho$U~-;3 zv<5ayr!i<~RO7M6aXhQ5qS98|F}MeTftVq=FuV$}u5E03YCc5_O863(0(lIgFs3%< z6qtCjOf5vI4GRwOSEO!WE%M;dI+D0?c;)6AB>~)om^LtKdd70^fOb~H4q~8*o^gN4 zkF9*%+^e*S`z@K|dUAITAzHwsS)kjhLoir1%YPe~A}K!{6-TaOs6CZ7sLte$jRK`S zP=-oNf-n;&4+#_p+(6HlipDYns-L78QkhJL0F@d1sG4XtV=%nfn5@iz`=Jxg0+Zh2 zlyFd$s&cC;h05bL1YJsQjRLN`F$QL4?lx+zGYH*K6BAJOc4!3}G9l13paIa(wIO?u z>IIagn-^pTO?&~2TW|(2lPc5lu0aOh6($mv~vvxwcz&{*TugxE^34Jfp>c> z_?V$8)LEQUJgwBg5;$PF3>7Cv5N^QG;vqHF>jwd$&PUQQ6uh1-e1nP#v0INB2^wha z(sOQ&C*2l1>v@D5LHRI`pthpZ+qFbSJ{8ph+u>@>hGhrb&&kl&u?qNBfNVG4j!aHqHXX`P`4hGG$j2c11B z3U%kPWKSRnMsVR*N2Xf01QiOm`%VfSz%;OhAhlLm6w*;wIye6qNfig86y#rU` zj?FP)Ux-zpv0Z)jCGJceqhRRxU|;8o&L!(%Xz!@)M-Aq2V9Q=O*OO)tPv8%0`wjQT zTV_z2ka5zeu@1n@C=%M1&J(2VL5_`pz4tj>fPu<=*-T|zHp(VO*>iMEBI{M`es zjiL0Ap9BfuRF-UWhISt))_^SL!{Ze4B65UScFT+)K!Iza5QS++Uq;D@#!ryAl;`pv z^QIk5;X(tW3MGH-!05b|8M=(r(}3s+tU`j~{iacbL*P1-o+#I+9i#TJ2CeXxK@A(Q z)Gd8-7c5lTL(`7D3it90!6!5P)f~ZF2Q{T-2E>;OSun$sp=tIjWIzWUG&>zdo&Uht zc)`>aO6#bvKCd#vJPEASJ8rLD1Nk;7l!M4fBNiDTPAUp_V4=(2;K~fPDM`X(j?e`T z93beP(Ou%ranA_=O0IsHdf4sadN}gLG)>FLPrw`AGZ5BaSbdclgYa2(lW&TGg0R8y zOT983@WhoAYtP)2V+>F) zLD3E=18kb}b&wgm#UHhbT{9X31)G=d*-%=YFyMiq>DmFV+@skHZv+nbHo+F$h1Sy4 zK^z`21CbNrB?~$Bmx#%G?ukv_|g2V;FqrlcNC>lz=N%v&5z|9gpDHupq`-2anS+l==M7Lz z=|c>C4|0?7@#qZaQqavLBX-bD7^GX1^pF>FQA1awub^(L8I*RXekpXyFwxEor`C}- z&$PCgaY`Izgq4{Xu(&Wnk9PnLd2VGU#ZVNkaSE7}LSflv90Ge;U|*Ug2{1C{xDy<^ z=M8Y|a1i@D0h<9XU{*xwAG5$2?4ei!Y|=8gXs0rmMYCxdtauc`w83eVNaAe16VfKw zR0a4M%W-ccPAx*%0NW^CJOIGBE(Eq1g-{aqwenOuhX4mt6~;r@!8&0(bIwUGuEc}Q zv}ADR5REF~qcR*%@l=Z@MPNN5!v1upK@8Thiz-BGk?Xc8!L~*`5gpXD%+v%ntfApx zdqno4f(OaI4b+pFV!-ofqg5`N6DrX&X_!`Gl4Cd20S-JutAH!PzB7Ha07nXN{dIJZ zcnrNg*Wor6EM0)*SuvE1Z=2@;q8)eJ8+~V zS>2S`mU?QZ--_)tDn6KKci2`3zZ31i9UYoHMo-JN5@*0m@2wKBCbiXBzX-r|9m66C z3@m;KI*X9l0QV^gLSMNX0T*!yR}i4eCSK zTmzVG>b@ERj`1b^`X=U$^#J$vj^X}cSWfh0#Z0!fZE=%@NqJEeETe(3t+sd!Mk$O( z%FQp8km1z}ADDZcO~5pE!~&++Y+N9-Abh->h#H%Fw}tnz{VVzg)$PF0IMn)Ma1>$3 z2h0GI4*;JUSecQ54&T%ggX3 z4boyW@Q{RCLOny6fCs~3Mk-QDtQujDa0a1qW^DoX*f92pYK{QQ`m5`snwnX}gQb|v zNgj@2%TKXPF(;N4gmQb3?+2mh`vLYY1^;+CnxsW6UhhqNpn&3lY{^ms2QQLwjF(_T ztCeFiKi^czevZTQBAS{M`(Jn$rSznz0taSK#o(S11Jf-(_196%fQkRWRQJJuGw~3@ zFkaYk_7m3OaDU58WcNUDION$5+^WJ8OBCP*F-j-NuzXe_Zv|dC*@$2pgg~{-qmmafd?kaxB*FCG|#A5JBS7_8pa&`n-CU~|G% z=9XxJrUpg=z{m|&u$uv<@Rv&{1tz|j-5{vUjNd-j{sT;>rud7S!dJr0AH0k`Q({&y zVVtVG3r{CujtC5XPH`Lj$Icc#^uXbX5vLYa5=0_ zngsJl5EyBdEa;!uuFN+$7@efE$!d9p(d4*hUVujF<3a!yby}FQubYDK;d_Gbg&okE zV|ivBqrj<<9=30^88k2+a>lpOIj+pC!%cy|adIcQrzLz~W}POp_~l6%qO{2TwDa2D zak!`GTXM1n9PH3`gMlkLXk{iVCF}zU?aNuBtS`bQ6?;-lpUSMj?xc$@BO|?wV2xB} z(P?(4Gmutw(VQjGg9-QZT<0*j~+n{#+ zp*^?}-6JFsDR8rheBc_xi(yrapF5K$e6+xvG2ji1pE*MkIGrMqyp@D|u0LKW)wPXN zAgZ6WJIB|=&LcRf8_C%LSNa4b4rFA{bg!g;x9Jaq_H6@X>DhkLt=lRCS8 zYJ3I1*m>oc$B%6(54Ubg;vs{>Vq}h@$Ifn^oylmHnzjqA&k}OV39o~LFZuVJTs;Bj zpl#&fE=8!>yIK$6vd|K^p9M826<-zu1((ZjHm<<_go%b&VZ|4NBd~4*I7gX#e#l>M z#~!2r=2rowTd2o#0cO%_iiB{<#LlG=K6WG=>bAdpJ@iHqDc*Ey6xI_a3yt8c1VG7v zY8%4YCWclCi!Xu)F<=oKQ-=PqZW+P71d8inxTcxcc2Pk;STz zJ&@oCknQKouyTSe_!Fcp>3JPhHvqmw^CNJMw;YueZ6W-U8ab0k*?gF#7CGnd!b>xz za4VesI0_5#*?0}lxD{WGT2!yby29x&r+Wfk&jh|(e0&ACbBd{IjCl_BTa`WFV1hSc zybPz;rbT1Xq!zQt2JhIh2a$CX;p^rRT-H7t=M3L!l7#l0Jmn;CMU*Qs>nKrW3@1OP zBr=(`fP?tc^!ey#c=p{z+<>w@Fg&n}A-It&3l=cpJ2)Sl@%oS9A{F?&obmn1I4KY` z2*LO8b$doe*lRq?__%sg*Xy(6faAF&XjjCsU_r?7HpwYdTHJRa;S|7qkp0Cq(xVI? z%3a^CL0mMYH4wvnnnLt5wJE#6yOuS8F9)1h73$tSHnyWPfH-mo;d9oji!By9LY-HasRxQS$6S$EiU4ZkedfP7H;ENYGtPOq`|?n!P?k9 z*)lP>g7M)cpyiFDeXJ|l*wc>DGkR^8;>U1ek9MITIn~eyI!`;M8>|p^fa25C;V5|eWR4@Ex}V?^FqQPiFT1tKSekYW%^nOht)C_vf6beA0$mEP z1B3JBx^Vx>EHQnZ!tVH0pAST}x7^Xu$}F}-VK6bDC)Ur)t}=_R=OC5b0rG;7aVUvP z03SxU^mspcusCp7y|lB)MS^?W1N))@R%WSvsXQB_RDBpHq20X)@NyL!;jo)nFcbcM z_T(n<)3Y$MWHgfQ&#~$f6jCv`Gqh;lNp6xvi{_tiXjEqH83QN5QV@BM{^E8a%>xU? zO(;Mfg>m<#E3=htc!N#eCalb+GrpWf!UY*spD32{&FaJkpn_$M3ZCAmAUp(gUz@6m z3Y>i=1tw1*Kg>Xrf{Z1`1v%473Np4;Qs9j%F34F|T#z%bxWIagz3U>FP=J>~Ag(%C z72w6hiU1c755rRy%)8V}K~sWIY{%TVi~?o20ILc{Z|nr-0+SYzCzPtPg2?GPTdcC6 zHWB`)O2cc1`jF-oc9vbkn;jm{VF7{zi9nsb01O8{hS8yp&CtZvD~uIATaUU(5E9da zuTNf@vI0E=L%1(*C8qGU86Oepffp#WKokjQZTSMypO4LN^SuiU-4*B!URmup#Bc@9 zEOMt~+J+V^v;=C7g00kQczIYU=%oji$2_;VOKZKt1X_wZ9!9Z%=9jP{3L6V)OIBcC z$*d!y@J|}__Vo>nO>C$5Yod@XyOY@xme2`Lh+MGBnVfEga2(0$Ik--oICeI68S zvEwz~I9#BXIyqYPaBa5N)!9U|*ACDtRt!jq*8;br_}opu5s5|cCJY4>fqE~WOZ4@q zfHsxA$yzATr&*<{t#PhYHVK%5YzH_FDI>W{Oeh7maQKa*pmBQ}mfe(KjmRuZZNNg1 zH3Fr5U_TpiJXcf@B(*U8VRoqhW3Sh7Sc;+dp{juE4b}Wn8W-SJulp2Q6+SH}ya|9j z*1SyXC`fJtL2qVZKHE8eh^Nrb;J2@qp>Z2^RImb7X#t0{GOJ?tN)+mh#OTLpYo?dGh5Ewh1(Xl7jbUq$Ctcv8SC*Oge*D5YSv3gb+~N zkaU}ReJwlE(|y7vUMPhwH=>C+lyg#0iLsA*e-JLGHoxA?yn!s<{Q43RYk{+9{N%+Tlyo8|Jh+SF(WeV=P~W zx9~*u^tH*?^Y4}iCBa9c@dPEtlvN+|C82*WeBoo3?{J*FkD0R-Q!>2aQw2tpuk4$fg&TFv|vW z9)&tZ+{M$Vy{&3}SmGX!pyTj}MwqBB)To5zfK_QFIFz#Y3pTH{@$iR+0Ve?@ya-rR zpCi13UcPto&%QR(=v)We1oOrUw$mBuGgv!;hRv(Nj*8}FbZ@!%m@8pYj3=m#)N-7$ z2PIpT9g*`3P98#7AvC5<1L7}va&1-;Zexsx7M_|_8wMtjICB?|2PMJ@2KGWD?+-+< zmBf#`kYR)#1U#3OaOf;>upNj?#&?Tuu2LqFWdzfFA6%Q)!^w#xr@+*MkhM|?6k>|b zO-e}8c5#GmS|YiHDb)e`W}7Nf(w8i6RDwiQ4QOyh5GAU>2iMZbs0&KQ5W>QSBPX=t(HvII$z*fh zT;7cJX-9PRBQh$?gS!w(?=Dz8uVoHA(p$#JM=M@lXx`BJan{%}2O1_WwW|Ke&lzwm z9aadh6u036SNU;d((I|zw{n+}2rzHjv71Ts4Nn|+s%YH2h43dzwv6G^p+zm(qkqn; z%pvgweO;`nVE4B(ddXg(9@dIZ@FjBmtU%26(1_cC8O!-))z z8Q`x%G7zGn5*cb#0wudPvUfoFR}ix_#~l}H8G6Hfv2qf0<;6~ijC_bFTINb(?Gi=M zqdlh=u1!LKD%3|xsJJuKW4Q>u_gma4vM3_ob;zpBjY35Ye3n#{_kXmUWEx~qWj#qF zR^&UvS4N+6HQoF|=V_9wQM3}2U<93L5t3hE0A^SSS3_IJ5v8*;%Yf9i1Np2K5qo)_9GKUyMh*3Yi4vbzE@a)Qoq8y3VGzk>owNw% zp!u`YA_S@xi~I^^jb}V)ixq-E69|g*a*)py;@fgX`g~@F%4HHMQn_>@t_UlQGWp2M z8*Co9qG%)0+VE{fMI}@$!}AsL8Mqb&w?CY|uSL*0pn#g=obQrYH{v1*x(=yK24fRZ z0$X21`n0^HG9ali!Xk5Olb;%5*%vwG$Mke7s&&Ar!k7Bsh!=HSi%4(2rgvo5IxMe* ziq@yOev_hTa#>=zC2B(wXw(*%4cxN2r1cm-tJRao+IU*f&Clo35F;!|I`zo%g=Cxv>mOtPurxgt`W zp|f$(Rv9BQoaYamh-N6(3Bk8#=lUI(29 z9V1^~Z3q??idY+WDwdDLq#}7AxA1r)#uZ2>+}@^ud=XM{5!`cw&M~e<-0LyCY%<^- zdE8bYuUF%s9hnQ@!#zF@{k;&l-E-#Ww5k1tcVZo^psI$C3m#62%{&ZD=cKqNkpd29di92?9G`Q-+2zX+Fohy}(pB_pj$2v>z0&C%k&iAGUQi>loB}B^rrPg>H-e%dpI9 z#3JTc24A+Y$`zvq>5-ckgJ?%t`La1f*@}XqXLZIJmUz0fEc!z5h+_-7_C#7Hx}MTm z8R=n^va}aIOzVr3X)kGqpmSE1=u*)bXet|xfy&68D?i4$7G5^fJ&<8TXT)feV!-E<=C;#V+EcnU0F#XW{w8 zyhQzH-YP7)o|bi!#8bsc+9Op;({YiZ4i^@iXD2)ThEq_G4~{+&y#Ne4(|tG$r_01U zV$8#`19h6|x_b>BWik=CRn3WFI7m^}Jo;&xk$E5~Yz^tmdCe!9j0SL$=5cbMd0=q+ z52(n2st}d2(=949E{3}$%o<(r+409(GHg8)Ux*k=1Oy|I@4S|iHHdZn0N+8t15mr* z6JtYq+Hu|ySnx=mOi=_l+~35uS{z7lGQ5=yA_Jx!NnZJ!k_3O%e3S8poPh>dZSt*y_w`Rjv=$W>FBi|Ca8+W4ZO+6Y{i z9kubHMf(?F4K3;$+f$jlKo4JO#i2WqBhD4(Tyb;h@ z7dFzjxG>tnaka#Z`2J*SykeYu-mlh}bMpzCoh#}X^AqOLJAx}aQV5r0eunfIKQluu zb7M^o9~LeaGp6R6`b16^J;QWzNd@| zB@v-7Bo^X@BFg|P%(;f!qe9e-D?rRch%LFo(0k=iO0~D{>^X8c#f6Ec(V&nthZWW# zQtNPPtr2vlyD8-Wd$m%pS%X6Hn`t3WyL^z~W?ERtYlxJ=y6P}mh|WRL($S_Ln+y5F zgb@lMWvHLCAIBFiSzgeod?C5=67QfdGAgPZGR~<4etW(@8HLUVI zs+JYZpjX90JHJP$EtnJyMIvgifzAV!mG6A;S^ZqmG1XDHQQm_!1yl<|1r!!88-R6G zJ6zk26|`Fvxb1!HC+WDPcMo22nk(w5MnS~P*b2A!m;$cSI5o6HyDz6&t4mQcH>24) zH8fXf=O36MQa+R0tfs(9VZj$E7LOGA)xf(xro_f}ZgDDMhu2NorY!W}PCe@rNg*bY z&mT778W~=Nmo}9$dDafoCoW5iP9#PFC4%RW3Tq=H9cy4<;LIBFhkeNBpjQk~t^Zyf z6!{f6fa5~Ai$-8@)yA=F(6P91x9WRRR@XwAq2cF3n1#wZx9NS9PA#Nfqqls?@AB1~ zmh4?}J`yNU9y4=ypite4JVM;|!dtI3P1EcPnMY9U4V~4pMu`p?ewxE$M zcBAY7Z(bCdoPi}Fk(bVt!1P(+$N=7r5stX3zjq9qr)92QfRhW8a022K$K8>e>mq;s z%Pkh~&@vai4j$6<0v!(wg?NfHin7^^V^1*G-DBWjTSi6W?zhU^>O|qyz2k(triKS= z2Jq%Je2qxNGe9oe%3SrJnmNw?c&GPCA$A9p!PGXGo4sBqEVVKh#=({2tD&V&s3GM- zHn7XoU5W()Ek1FW#)TC28+cRa!eLyuH$~kILotXdr=*5O_|jnIl)$CxdB-CBil@LT zr{wGou-rw%{iD5=Q^<81Mj>1d5lXg#u*Y?IfbY25{~*l#UH{4 zr}}0{p;S-QHMWsxoTlbWvBNDQu~^E(N)mTryjpWK=%n4k*}5d-Q(7(c$LqOLf5IM@ zI;R0V4cnoHit?m2OP+{8OB99Imy*gJKO@&}BXY{ShKI-sOiC?y6z)q7($t!v9`QjF zF%VecNw1Ppi$pM5;#{>37a0D81#$<|0tzBn@1f|#jZn&~WtE3zJD{x4JWX=}S~%gzimXc(65G} zu;4sOPR{A9gng&uaVer*cZu3b7;ufB5?VLlS{&ACb_`YyGcx<`-+br2Fzq;sXpmcE#cO3Pr@-A!IT9sn#>Bu{WDOmu!1u@3`Cvyi?<56w+a9YnA46M@PQ1#n7VZOlE? zx4A~nXbPAWw?X9;8D}ogVxS+ToQMzo92_3PbX>Z5b9X1gb@}|?O8H(IMS{}JTXsh9 z+5Rc+Fe}&RQ^~0ueMIi9DOf1Jw!|e(#f?3=6)GkVfoH{$olnJ$t!}19&rFJ@)-zLw zny|Ao*a|*1R)y2AajNN+^O+B9UfoTLz^Ns^xF0z~2gW6aF;mQ3SMSSYifw1GEn=FO ztK6pv53`5+Vxx`%gIsYitK{?&S%F#0Da^DpX<8Z-yHIAOPMMQwn65bHPHC}=LqKjv zdJR(b7o~QZZ=#~a#m>{I=+<+wtZ-Gp-f@pBXW5d`L$q=gJq0C3i)l*5rw0WWLRoIf zw_Drz*zFWT?L9C2U4vrnwSBm>m^+r<4%D`TrEUr%>-@ghH%sboJnpDh@M^F>tnPX) zVkMYU0a(vTa*&FZ`q)nuM<#3xxsF6j$nPXj2g|?ORi7`a8EatGo04L(`;lx1dA(>@ zh2kxv`*8e=QmzA`Y^Xe^mFR=mjf(XOPov^3qZ1fHKe`quHTJb=baK@{DmIZkh?9v9 zVqh_~75n2Erp{^*`axr!2$2?Q2}12Rx7tEoYl5yx-U4MiNKkrUv=2@xJnAA{3)32? zUMLJqi?z$t4gFPqXtC-MfsTw~xJOVNEK-PNJQXR&thUaBV)~k6@Hgp^IFbztH4hB6 zLAju7+V0vlzF4$|V_l-27ANP&X>oFdoEFE*Mjc&~2|!LTbQzv0c6mB~A&NDsGVmAr z@PSjAU1qK$Nm8*>MU@FI)u;!bbs4nH?2_M-g2xrndo={9ZrrpAEDou@PQ~}fsW;u( z&p70!&7fe#G?vx}ES{<=N%XAHcDq|qITcR3Vs73pwInL1(OvWs`Of7f5*+0#$`k-D zkH31zX{i0+DVL(5M&%KCtYR{KR33kKl=rD8r9bD|Z#ga2A!teRN;k9Ww5(Iip`m_r zi|NJ1VTw8RT81xojF&is(<6L2`0T8z6ub-;jFDK3wIC-o* zik?y-2uxRhQD0#pWaV)4p@W6tx%qJ)PiC1;w^^VXz3!lpd6E!y^t?z40SoP}yjY}e zNF5)uRJA8CdM}8=azg4fJnAF*IK8EI606+ME1=xnqfXfdP(O!OjC zDTfNO`z0#JAktJvQMrBKAmdR~F0+ih97uVDNEJ$a#O2ZLZjKhh1{Q@t%7gP^^*)$G zM9R@Ix-U*y=$r{>>nl)EGHKX_UOQ$!5A0JMu2POp%pdLBaC@-G<*foaFXdjVPIQWT zTE0Fxd`im`rK67du}-<10o~&@Iuf__fxgQ{j&&S?0psJs>ez5UxvQZ9pQf6FyQgsV zFoMzidF^Q;-JQVksyUj0%i*-$@*Dx)A;7hEI`-nQehghw^Pkq}Ztr$+ESw%3RBhT> z8$*tpMeY=H(caF=>AABiJ^R|ZtADU^IwW*{k&ExK1Oc;6hvZZPeMR-97qw1BX!seq zhB6fk2*jZ!?1tGSsi&-MNDN8K>9HOVYZ>6FDS|nkkS0hUay;E>0^Suz)i_b@5HMCh z6#qfd$wqel2Du#37(p&JSq&0Ig6v!Hd8ykRrXLoZLl{MtDcq;!ciQBty7FUfg0+DT zQzDgVZidESHK_b+uj<*>#UqG<=c`LvgOivJ(?n*9fPRrYrT-I|st77mgOwrcrQQ0# zvqdCypu;AoNj_h&>^*k}`vmhlH6u z5HR(o6jV1uwARMK4V@nXo0k#j?k4B7Uo{AHzEUqUO9(kngo~?hgy61wq7Q+fRu2|A zqk~l)AgDkKx_whzgCc0O$z}>V5rnN~&tP}=A)(ngNm@Nm;XZ5?T{3zho|i6y{uBXv zV)D#~iR%4rva( zAU>rU$ZiQ?rvQ_Q8ZJr8FO}+0tp;C5M-bqiViXPs5*4XZCHdYTCXn!h>1G{-Fv_j; zYASvQlNipHYTN{OLT&KvtJ$qxHR(7%IP1cBEqJ%`Y>(mj1~&X%uYy^G zzmD!OcqUDy4sIS}#&U9;hoo}45r(^m+@KCUvkB*e=UydKB7w9Ox7O{xNqg0fXB8v4 z9k?m5{~QK45y&t;t_3r;p7MM-3pM=9Fu?2}AHX_XCb9IpFh(@3r1yrS1%`%t6r`p0 zG-Ro)^O#(?$@+l?Ox1LL4Ap+Lj;ITEa3TtnV%TS=zU5n?`Jt61hp{4$)uylJI^x@c7zd1nrdSR#B!ZX&lL!Z{d|YG1j>?KO(V=us1BoPk>O+qMUJXw}5L66h zmiPc3jGWks7TErbFfjKp^Wszj=xI=gvVC42aAHUXf(Rp~rZ$j9gE6)m&*md<%CV64 z)Lh-ceJ+-q<##y>3{~G3#h0T3!X=RF_t$4!u)H_go-Yd?moZL>8<{ut7UoX@D_YhoX%cSb?*d zpbqya(S=p~Djr7Ird6>`8%KLiJ8o0&h-OI5-7o8$2MN?LG*iV~we0YkJnEG*NJfb^BScwIHbPG@{G@_0ZO2lo*hH{*w4iwrYk~2=zE%{Fel8IW1 z5=pzuHqquRq7*UASXF_&MaI(QQ!#VZAky5K2Jr-rm!0$K~H9_FPyF(x;ArgHc9A& zmo*MUp*{%PNUw>s8w&Ou1Qz0=>K#bw&uq^LKkZ9^LUSL5*LoBu&A2P>FV_%p6R&0#6r^k;%#s9BJx1J%FZs77+dXbMvw+m z=NEwm+a>DS8KL-LY?8|SHO*v+P@-{>iOFIvLa~w1J_TQrFWn z_H^)h;L01V_x8zg;U$o|NPRSph5{7XkS^R^d1{0*S_|q)YT*fq{o4MxmTU2{EaQWe zz67Gmg%QvlaB*6l(NI<`;9Ue!lt(dPwPblyl%<_bQ7CuLv}3NOM3=SElalm}`f?*u zI9AS}>jGB{4E6RQ{|i4FvKaw$1Ef;fLjQ5I7`}~kaMB~SB2K1X zCQ@8IF%I{ufD`RWcYwe;tk&bt2kp1ujL>ifO@ZYZ5>w0=pW*OPcW{nR(W40tM2~Fw zoVQEs32=hVx?cRu5RBUWx~Tu%74uO|q@j&=2*9yh9j!_n81!x6@>I8k?r`S>;M##O+fMUi~32#1E9 zsV5q2dUsd*V;|kFfU#*|S3V;gJ$(1h)@WRj%rlR!8g4d+0S-L(iC|3HGF)=X(NzYH zKuU1P>}gaFduHuGG(8{HdWfE`;!Es;bLop3q&PMdde+Y0FHu+ZyvRk16cggrgMZO` zX@Qe-!pg2$*SmXoI$t7NZo&{rbEygj| z#SqDp3#+4&9+Yt8d^cmeZKr7_|7PXPz|ZSve34`lT!a))uu&>!=FVxs5*E?o?p(x& z0+lnNaWu8C2+23ok=HO4sZ{lAIWshtH_D}C+0D-Ir~|1#GMDY^vwT)nAVoqYnLDCq zn*I{kD9EN%c%&?|;cNJqC!M80I}e;n-F#oeA?eB-q?_NIUD+>OUsHq>OCdut)kUSS z@@%`#rp-mthhDu{SY@XLaprbc6P+8OMI;>IzM4Q1eyug-brcQ0wVKp5Jm0tlYXeS8 z(VCn*nD2*RzqvknCc6(Q*9TPKnXJ~DSWHDzrJI`>mq&7}*b5qypo&C>Fh7-w`^fcm zoIy7Tn^GhanRY)2N7))FnA8+?hx8CJY*f%{O%YO}fx9V)kP;O!RjF(S=vXotnu7J4O=S%f?TM%dfRR zls~azrP((oV2WHhIGC?VdyIDCXd%7gBh6`Ng70WfF3QL;t!-oBEtGnijBVNpbV3at zhN;TC_Zo0s!d> zT9eilRTJngD!#R@1S?i%+pYHzR@fyuiq^WEX;GtBNRev>m}KY)h6OF!BPdp za2m9T_DH#Cjz!ujxu#+)T6T^ z$Ihxcc_@R0Ln{Pk?pcwVVQUaWH4TFBVl1z`tc`EaMRj>BAF5WYE9_HrmoBP{vE-#- zjTh7_brF_)AHMUXzsire_cHTg>U3by1v{>5Yar5D#8Pla7Rrn~LCp}UMA=W6Bb zoXbMbR^-PHyd088qbQd}8a%jY$8i7fVW3gabLH%e=79s7MD@v_CBl~Zv7lug3F7Ba zuO&6w+^N!XcA|Ae`h>sIceW`O^Jx}%d33DrTEA9wM<q*FkbAP3y)(i31~fkA39SOG+O%)Z6X~_1=wwJ6jlO{@BYvT`TcbHNvS&=? z%GFlTvR!S$4ZU`d3Pr8Wqvibt1vE@eM&RYpGVXvJT1MpM&@wWwfJWTDDE_l(MI9$W zFUUjDT}Y~QcBG(OQtOszI`XOE=t%|+$#!=q67I8N8-LInsLP4?k=35Z6$9oa&qHEJWd8PLKPyB%}58} zl#WKxqD{}P42G}~#m)@wTkP@Ra2S8OMeHlAEik|eXJA2X5gOZZgA_8sIS9|TV;*&; z+hG9p$a5|XP=GnXc&BMgHM9QQ0I{2B`?GyEraozs~J>Z;(QTf&`)qT zM=72Yt0VNe+5O)Hk32c*DcMdxcf;AlH^a`6G>v1Ooy+Ko`w+s=#t*Ei?M8xBRuJs{ zL&HNl$HT%yV#j89lDe|Nc+9PXb`>wH(b=6{%%9j$BvMHW?W#4YJ zcMEd8Aztiez&e$2cq0O#9f&s@9O&q-@m^7&Q4whbZ5^DIf)Tbyn>r20a&{{ ziNejKp)~G7>x*4INxGW#c*Q=87tK-BKMXBN@e}*xTzv(+*pn9E>4}}oA%aKL#|N%6 z{mJ^L4kWnS%p--sba?7>csb3!i09Z@GN5$44v#zP{))dZsS20kuF^g{4n_)bpjwEt zPsb6>th4+?VPw-gho?&>WWhFnvIHl-u6T)#Xg zR3S@lVa9kEK!eMe4e-39OV$s@5%iCCaf7Rw5gza2P!&UEtWiN93hR?LuFYK36ueRm zk;VF9;IZM~7>^}DZFHbENJ^sOnd~9P1Nln1CFmxp+znPd8&fsNy#U9TOY?=PB>k^} zHpvb$yZ+M;*?1^udEEqAkmb#APXBwiB6*-mw$M%6fQl+Ul;ti?N` z7%QFJz(rO^qyxQ++wKwb3WvMT>=9E{Fj4M2Vt*K=!(BBcPwr>BK4w)NQDNf2M1rKC z#?*b&5n^F39U{+BgiC^*+Eo3*YGe+>oFjM)M3{o!?9jo4sz*M*jUg6vh2&#e(?#VY zae4)ad97m9*qk+OQE3aSq>k!-6{i&oK&!DZGc1$+_jao%Mhs1`r0EDTKEPGgLi-pY zsw!ZcMsyWLjDT6CMiFJ06x&h=brPv>qZUMRM>#o_h|#D$l%nxz~lpyBPGZ>=ZE*!bFWbtB>jP#(Sc%17TcaBj9+Fg~B z*6E%mw?XJ?IX9Fq=Eulg>WmO|VF%xv1F-pSXM`wI6NWIlXhZao_DHlG?S3!CKRL}f zhnRRj#AXH}I@ZV)!8~RNZYh=uImG={mxh`jmIdPcz#V~}?v}JTbfX_{M=auA!kx1S z??}uqx!&*ah=&~>Ci;gui^3~^4ACWI>%~FgFt-9UBpt6}S-RLJ|l`EsW{$vtOsT5@?WdH222 z9`MiPIdjiFcOz701gMSkqc{f2NwO;K1-_W!3*DsF1GPE3Q;y?M8*wpz6VRbXnko?CZJ*$CA?(9;yvzt&TNI!bp<`Z}l! z?6N!@)bp1gE-HF^xTxrD6I5ow%>1{ki6ullSup8{|0q%-B2rW*RnlMDZ4K})f(;ua zt~5`Z#@)rJtg$!`1DZE43L6wwD+W`LJj~4e(rS!aFyIW8#tqF9$#a8~J;J8T0;8}t zk?dS&fKV-P-_F48XR=;}U1B6=TWn%|jX9=?G_6%oNvH&jJ+T%NRNm>%)=_5W|J$PQD`C4G&)4 zRtYoFJ9NR~g*6;uQM&GhCTHeV76cL|dtlh-a)bc)FhmTSto6ggmFTR>g4`ivA$V#L z$;y@mv8G_9b$I6CVZ=s|jvrb6gy7_*H~iN9an!dKDMD1Xo2Ny7Bf@87}WY z-Jl{i8}wH#&EE0x-UHr(%#TfR**$xhxOD`34K%~;L)J;X(Mjsu`09!M4aWw=y`mFf zzax()Jb?{y$LO+nya!`keyin5WM{pwx>s|k1vl5AYMcnpt&f1E z`fN~hik3(OtvQsq$@!O)xa~GTG@eLh$A$fuG2~zdG~pUOA7PVXvFX|k6Qr@wHPMD0 z%Mv<4Mt7X+vUsMSAhW&abD$*hT#-#ila}N}sr$tgoAW|p8ggQO9Ri&V?|DSX=yBm}h98g);bZY|o`1ijf7fqO^$P({Xo>n-q zDRX>f&@-B!_kBIhcz(*4MOJt&D~#Ephh6L-MbxAU{dA%7iXJJLdV&k4q%XKReFc4I zp5mTRA*BTUN;5Rt4t40f>rM5u?OeDfAEU$fK~eHfLrs72ol&0R*ab5q>KcaNUr?jHt7sKzB)V*o?z2!tPT6VJAMvN zwc>{8a!0E!-W_*$t06kZ$&wOjr$_6E{1g=v=pBK(0P9-~szvfdz;^FI(1J=wfk`Hu zD>3Z}pZDHjs(~HGCdJ{HZf?`*oU-QdV|BeDqjdNw8>X)bCs8sQjF)@gUQPIL@d~&^ z-YUK+!Pw)f4ij@IYRgu?n26jITXo8gimH{??{Ww-&nfDq>HI{jOZZu0pG%ab^(Vq7 z?vYsP76fPb4Ox_NI8|Fye6oKU+#!)8f{unf&AJfB;Wfrjc%X<~^angMe2tzSnqfBO zHOoPQA)u;`%aDRE!)@f)RWxUfnopy>7^@R4_+;fp}Z)kWpfKPrpp^5Oqw$AcibU6|~_?amyPY!QoW zOQu`C(Vlb!X+v^9Yc(R{$vN#4COCrTn_dDIm7pvtM%IIAR7QY>1a~{xUHHKdjHSAo z8Zt`YEUnxxk(!heL_4~htbG+RNta?5Uha4zAwb0{96HQ17v_0Y>-y?}J}eDh7qWT4 zxS}p;Z)oc|<`ogJ2Qpz6DR)tVqH(xZQonPd*#$7$A{AY*Z_SEdyNizjDWOkyUlQJaQTxwaT5u{|kjkpvB<_Mmn~WNebVFTZ>APW14Do7OYYwiKeJKVw+~trmd8%Mk_OQXh~sl*#}Da zkN@(APhy|H(uBmC4A*dxBwS`Wv4B=`%Y~h$S>GwvOF+_C8^K*Qi$geEl691pou5yp zm#aEU*4PBLMt#w)(b~RIe=a(tK!}3zJElca(pw+T7zE;ZrD!0^TP>_mR%|# zI=!w=UDkNNm^Wr%AJ`lAn{nXQO;IW<`ljw)4AN}aL|sY-pbN>!L! zo9^8*pp9~E*PifDsz|4mfVi^IVWq+}m#wArOv+O=IHgOpBk@k=sOTdn$nnOu@5Kut z;7JKlx-`zWuMDx++zxX4(UGN}Ips9*$*+=?s-r&nbJ|+8#+`LZJ0`m|E81E_mYK%} zQ__qqIhaLj*tQl19_-#Go{5M|wa(@rB5v*Q{S@bCIRX5&7_BXA{7UZ;yW5oD1$nag zn5vwNeG_8fU07WYZLiiRl79KJ3#;qK2jFp)QQ++A$#}>NCnj>me}36Dprs4#Nv|dI zDuw@!Rfzq3==RIIjy?9+gpFNh5Rr&`}u}V>(9y2S56cB zsV4N#f9+n?NC-u~tvUw&nd{zj#rYC`|gb3gFi9R0)X(*Ma@%G^b$%x%U6%KcxMG-!7lO-@f&q{w+s8aIMn+u$=z&1K+tkM?Z6c&>w0--*@lZ zpOmA&&f5QZdHcV5=)_;<=x<8MNL z@%n0({{Q`4=^ra^|Mty)Julb(6CEv5!LQ5dcb~KP`#Jh;y8aJ6UQYklcb#%{j((@o zSAJJcKhnMMhdKJkE|dNr`fEA;-cRrRW{&>pT{8U25#{@5%h&F_F-PAsG>t1b*o6Mk zgKeM4(f5B-zu&a-_J8ux%|FP|uh;$`JgS`jyia{|L5}`eN`I&c{pt7p+v*(sIKJQH z+#@QLqs!Z$^Q?J~<>)VeSm*zka{Ajo@sdi8{uigo_dj@SIsMn3`mHB&^!J}2?N81t zr@ws0BRAyeKlKKopK3xs{@@eW=ji{wF7!R^v` z;9r&OSuZW6f5pa6zAs0A>VIqho6sNghPS;dNB@t1FZ9*#>o3}ibpC$y@#C`l_qeC( z_`g#A{lELPxBMa3{+w?~gHzuxpZ~XB^nD5Q&=+}QvzTadM`lUbk zZFc`|Q~K)hT!#Vofb^JZgDWAWdcV0H0 zqksR~pnKuJgWJpLAG-JNvg`k0rLXps(+_Mu?&@6o)wfIghnmn|zWLAR=jflM^gX@h z?SFR1zyC2u|B&+ksVmCo|H3cMc|1q|?~ls*=~-V+|NGb6volBko?R-x|F)d}cOL)G zS^v*R+l0QlvYh^eJG<`6wLj|{LcelVIsFxXIkqE5f05EpHld&Yg=a3y(GMzp<>K=8 zfB4moto=0OO*;S2F5mx;eEsR)&b5EV_k_N(qkR25|EK?SZH~U@Mw!3L+snWI$=~@= zcK_Y5M(8Ium&=bI|Mkl6=i0yYDxsfhvi{z&?3S?{eXr6_zVYQc5%MGDpTGLz6)(!s z-@Q}XuP%5|DSgLJ&dvHyAM6scLl>0K|Etbemt8;iog?k{Y$%`q51(<@+Fbu{)nOlO z^8If8#uIi7@7qkR0g?i_nf zuK$10_NSW6-?m@9=Sx}o-^%!>n&^K&Ke{#R|C{$_p|0eVYS8e-Cj((H2-*b7n{ruY>Jo9Hc`cFR~?H_z+`TG0TY{|91d8>|pTY39G zeCx_zlFHIsbY5+1s9y>;H(_ zpOa1K@4WZ1tp5D@9-Y6Zl(+wv5C83Na_zrQ{rA=L%Jrugj33DI?|-~j*H07r?|l1@ z+4c8nYyYd|?Js!lt=aR3gX%x2{Ir~ZynS!pf4*72e@}P${JrHP4`ua-n)&Z8FXz9H zf90~Q|K}X_pY&`i@Bih`pO^i9mwi#@zuH>f|NB0>_HDWEKmS)kKiP!-SFbqpOF8<7 z|4HeuE9YMuuRZ%8bM(F1e&rqI`>($LEAPqCzoA9e|H|?5_V+(>UoA&JXF~gbp#1wy z{NlFk`Rli|{i!DHA2{WQ|B!2czuM0|O~zko8_4?KKeA1~e{VVeeC`MCIWyP(i5fpr zonF3v&b#FH?EZVJ`X48o(Es!Mj=ewEe(gm0ev?i3$IUyx`Q;q_$Cdv~Z7<(H&-=%f zXXohOul=98s(k#Pnt0&$9Q{G%{|DbwPXEpO$5-a)Z`1SRsi&3mziV$@lRf`>gVI+! z%IUAGAJLU-f70YvTY3Ly4qyDwIr;^5e%6HkHy?e$V>$Zw+x*qb_wQSOa{t9S`q}!~ zt24^`KXm8E-;ksKg2}HRmeVgk|10<9=r`&4<7AWeYgetwp1EHb59ohL?Y5i}~{`QYAUzcltrTQPL zra*qCS{cKbF%IE(FH#~MANB>oo9|!lB)6d>=LRSB|PM7V}-R1K8b^HGN zxw-aVc7)9Tp=-wBa`fL=CiGKV%E$k}ir=1^qp!}; z_1C2Ry-VkRFGv5&vxI)K$^8HEs0*_C o`K#PhuD>0%^2AGW?O!xa=Wky5`0u#9 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

    ?zc^D!kAP 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≫a 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ℜ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î<6jv%UuK2I%^pUn-ZVr}K3_`v*(qUfx`p1E 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�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 z zfv2^4MsGh{Z2!9f!4~)UJ1l6jcAu|FeFKzH+$^VUa2Q(I4URem4o2UGA6UJd>4-Ihkhf3!f*rgZjN6Mj&_*iV;Wb>0I zYx%2)zedxVElhJ?zROnHVxN8&ojZYwo#N8Y*D07(2xz-}$quqT`GsF&mn6bWmpsX? zmSAmV!tRpaV1XEQ$&;;DHF?0=tq-5ggpv4I&%y6_t=Lshle;3P-z)VPbVW_{+b2bu zun}e-XQkVe(5 zkZZV5G}?R2Z%~ab4VC7@@T_UBzC{DH!}5bwZ;dOfn~SQO4b{z^@QN*|m1m0?<(UI# zWM}?C%xIX|JELyqv>BzDZ8I`6;~CvE&5T}_9+rVK>sic<{+VM_uj`Sr7xY?Ds+j|4 z`O=vghF1wSy1QXOZ+G2*SPdgASQ|mW;-TFHT<9HUntIwy>%canb2|^5W~TN}GjX9< z<7uCFs|@XAeHA{2>P^jSS>{u{2r(gvL0Jq$68eL{@37aabEgr2wT;+TaoCLsyO&5l zJ+5J9sK+*MAkeTTZ_Ct+dJ?c3BhTTpk_#L)n7Yc_sKh39Ek5pS9yJ>&U-?}*qc}4^ zqh;o~l9iYtUKYW`mc`Bzz4#qD<1#Vx5ARI<;$$?w zBmH5XY(1g)wfqS!CzCX9`S2N)P>QuJ>%>}dwGR4Q-qOxVMxSQ1#8<=ZQ9UlBXy(3C zhs`YfT#T4<&|`Am2FHU$q|GKvB$VbV_E<4FRL_B}qGdm7Tp=j$vq@zyKY9B8(|y zt?ri1<}hcZ>G!5V{?ckHl1P`R_m2wd

    ofhMZ>HvHmFZ@~Ag%U}SwIJ2fVC&`+hi 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©F{`EW*_#Ft&P0%%8Nwzk; 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
    |~GH4s&oX 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

    HqtqYe1MdR~6nNIvW47b9 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�<1DJ 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 PU3p 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

    s*18%`^+u6Zn2As&*b=lH+P-Zh#w->bz4 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 From 8419f6450f9d8df1ecd69c3aaa3afd218521b7f3 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Mon, 7 Nov 2022 20:03:35 +0100 Subject: [PATCH 178/254] fixed ssl tests --- driver/src/test/java/com/arangodb/ArangoSslTest.java | 1 + .../test/java/com/arangodb/async/example/ssl/SslExampleTest.java | 1 + 2 files changed, 2 insertions(+) diff --git a/driver/src/test/java/com/arangodb/ArangoSslTest.java b/driver/src/test/java/com/arangodb/ArangoSslTest.java index 068e812eb..1c9c2bd3a 100644 --- a/driver/src/test/java/com/arangodb/ArangoSslTest.java +++ b/driver/src/test/java/com/arangodb/ArangoSslTest.java @@ -75,6 +75,7 @@ void connect(Protocol protocol) throws Exception { final ArangoDB arangoDB = new ArangoDB.Builder() .useProtocol(protocol) .host("localhost", 8529) + .password("test") .useSsl(true) .sslContext(sc).build(); final ArangoDBVersion version = arangoDB.getVersion(); diff --git a/driver/src/test/java/com/arangodb/async/example/ssl/SslExampleTest.java b/driver/src/test/java/com/arangodb/async/example/ssl/SslExampleTest.java index 33df7cf88..c90175310 100644 --- a/driver/src/test/java/com/arangodb/async/example/ssl/SslExampleTest.java +++ b/driver/src/test/java/com/arangodb/async/example/ssl/SslExampleTest.java @@ -69,6 +69,7 @@ void connect() throws Exception { final ArangoDBAsync arangoDB = new ArangoDBAsync.Builder() .host("localhost", 8529) + .password("test") .useSsl(true) .sslContext(sc).build(); final ArangoDBVersion version = arangoDB.getVersion().get(); From 588edbd9e56b5b46dea5b31576f6cae747aa2a5f Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Mon, 7 Nov 2022 20:09:15 +0100 Subject: [PATCH 179/254] fixed CodeQL CI --- resilience-tests/pom.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/resilience-tests/pom.xml b/resilience-tests/pom.xml index b9dc62299..22f252779 100644 --- a/resilience-tests/pom.xml +++ b/resilience-tests/pom.xml @@ -12,9 +12,9 @@ resilience-tests - 19 - 19 - 19 + 17 + 17 + 17 UTF-8 From e688c843d9a7b402df507595c512cb0399df7af2 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Tue, 8 Nov 2022 12:07:05 +0100 Subject: [PATCH 180/254] [DE-411] http retries (#468) * CodeQL fixes * added http retries for safe methods --- .github/workflows/codeql.yml | 5 + .../internal/http/HttpCommunication.java | 16 +- .../internal/http/HttpConnection.java | 7 +- .../java/resilience/SingleServerTest.java | 22 +- .../resilience/connection/ConnectionTest.java | 14 +- .../reconnection/ReconnectionTest.java | 119 ----------- .../test/java/resilience/retry/RetryTest.java | 197 ++++++++++++++++++ .../src/test/resources/logback-test.xml | 2 +- 8 files changed, 243 insertions(+), 139 deletions(-) delete mode 100644 resilience-tests/src/test/java/resilience/reconnection/ReconnectionTest.java create mode 100644 resilience-tests/src/test/java/resilience/retry/RetryTest.java diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index a50a410d9..14392e1ac 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -28,6 +28,11 @@ jobs: analyze: name: Analyze runs-on: ubuntu-latest + + defaults: + run: + working-directory: driver + permissions: actions: read contents: read diff --git a/driver/src/main/java/com/arangodb/internal/http/HttpCommunication.java b/driver/src/main/java/com/arangodb/internal/http/HttpCommunication.java index 82229676c..0ce212159 100644 --- a/driver/src/main/java/com/arangodb/internal/http/HttpCommunication.java +++ b/driver/src/main/java/com/arangodb/internal/http/HttpCommunication.java @@ -22,6 +22,7 @@ import com.arangodb.ArangoDBException; import com.arangodb.Request; +import com.arangodb.RequestType; import com.arangodb.Response; import com.arangodb.internal.net.*; import com.arangodb.internal.serde.InternalSerde; @@ -84,8 +85,6 @@ private Response execute(final Request request, final HostHandle hostHandle, fin return response; } catch (final SocketTimeoutException e) { // SocketTimeoutException exceptions are wrapped and rethrown. - // Differently from other IOException exceptions they must not be retried, - // since the requests could not be idempotent. TimeoutException te = new TimeoutException(e.getMessage()); te.initCause(e); throw new ArangoDBException(te, reqId); @@ -96,7 +95,7 @@ private Response execute(final Request request, final HostHandle hostHandle, fin } final Host failedHost = host; host = hostHandler.get(hostHandle, accessType); - if (host != null) { + if (host != null && isSafe(request)) { LOGGER.warn("Could not connect to {} while executing request [id={}]", failedHost.getDescription(), reqId, e); LOGGER.debug("Try connecting to {}", host.getDescription()); @@ -106,9 +105,9 @@ private Response execute(final Request request, final HostHandle hostHandle, fin } } } - } catch (final ArangoDBException e) { - if (e instanceof ArangoDBRedirectException && attemptCount < 3) { - final String location = ((ArangoDBRedirectException) e).getLocation(); + } catch (final ArangoDBRedirectException e) { + if (attemptCount < 3) { + final String location = e.getLocation(); final HostDescription redirectHost = HostUtils.createFromLocation(location); hostHandler.failIfNotMatch(redirectHost, e); return execute(request, new HostHandle().setHost(redirectHost), attemptCount + 1); @@ -118,6 +117,11 @@ private Response execute(final Request request, final HostHandle hostHandle, fin } } + private boolean isSafe(final Request request) { + RequestType type = request.getRequestType(); + return type == RequestType.GET || type == RequestType.HEAD || type == RequestType.OPTIONS; + } + public static class Builder { private HostHandler hostHandler; private InternalSerde serde; diff --git a/driver/src/main/java/com/arangodb/internal/http/HttpConnection.java b/driver/src/main/java/com/arangodb/internal/http/HttpConnection.java index 3bd43813a..65fef09af 100644 --- a/driver/src/main/java/com/arangodb/internal/http/HttpConnection.java +++ b/driver/src/main/java/com/arangodb/internal/http/HttpConnection.java @@ -61,6 +61,7 @@ import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; import java.util.concurrent.atomic.AtomicInteger; @@ -227,10 +228,12 @@ public Response execute(final Request request) throws IOException { throw ArangoDBException.wrap(e); } catch (ExecutionException e) { Throwable cause = e.getCause(); - if (cause instanceof IOException) { + if (cause instanceof TimeoutException) { + throw ArangoDBException.wrap(cause); + } else if (cause instanceof IOException) { throw (IOException) cause; } else { - throw ArangoDBException.wrap(e.getCause()); + throw new IOException(cause); } } checkError(resp); diff --git a/resilience-tests/src/test/java/resilience/SingleServerTest.java b/resilience-tests/src/test/java/resilience/SingleServerTest.java index 6ba01612e..7e9bc32b6 100644 --- a/resilience-tests/src/test/java/resilience/SingleServerTest.java +++ b/resilience-tests/src/test/java/resilience/SingleServerTest.java @@ -37,8 +37,8 @@ static void afterAll() throws IOException { } @BeforeEach - void beforeEach() throws IOException { - endpoint.getProxy().enable(); + void beforeEach() { + enableEndpoint(); } protected static Endpoint getEndpoint() { @@ -57,4 +57,22 @@ protected static ArangoDBAsync.Builder dbBuilderAsync() { .password(PASSWORD); } + protected void enableEndpoint(){ + try { + getEndpoint().getProxy().enable(); + Thread.sleep(100); + } catch (IOException | InterruptedException e) { + throw new RuntimeException(e); + } + } + + protected void disableEndpoint(){ + try { + getEndpoint().getProxy().disable(); + Thread.sleep(100); + } catch (IOException | InterruptedException e) { + throw new RuntimeException(e); + } + } + } diff --git a/resilience-tests/src/test/java/resilience/connection/ConnectionTest.java b/resilience-tests/src/test/java/resilience/connection/ConnectionTest.java index 6c2453acf..24e484282 100644 --- a/resilience-tests/src/test/java/resilience/connection/ConnectionTest.java +++ b/resilience-tests/src/test/java/resilience/connection/ConnectionTest.java @@ -8,7 +8,6 @@ import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.MethodSource; -import java.io.IOException; import java.net.ConnectException; import java.net.UnknownHostException; import java.util.stream.Stream; @@ -59,21 +58,18 @@ void nameResolutionFailTest(Protocol protocol) { @ParameterizedTest @MethodSource("arangoProvider") - void connectionFailTest(ArangoDB arangoDB) throws IOException, InterruptedException { - getEndpoint().getProxy().disable(); - Thread.sleep(100); + void connectionFailTest(ArangoDB arangoDB) { + disableEndpoint(); Throwable thrown = catchThrowable(arangoDB::getVersion); assertThat(thrown).isInstanceOf(ArangoDBException.class); assertThat(thrown.getMessage()).contains("Cannot contact any host"); assertThat(thrown.getCause()).isNotNull(); assertThat(thrown.getCause()).isInstanceOf(ArangoDBMultipleException.class); - ((ArangoDBMultipleException) thrown.getCause()).getExceptions().forEach(e -> { - assertThat(e).isInstanceOf(ConnectException.class); - }); + ((ArangoDBMultipleException) thrown.getCause()).getExceptions().forEach(e -> + assertThat(e).isInstanceOf(ConnectException.class)); arangoDB.shutdown(); - getEndpoint().getProxy().enable(); - Thread.sleep(100); + enableEndpoint(); } } diff --git a/resilience-tests/src/test/java/resilience/reconnection/ReconnectionTest.java b/resilience-tests/src/test/java/resilience/reconnection/ReconnectionTest.java deleted file mode 100644 index 276e5236e..000000000 --- a/resilience-tests/src/test/java/resilience/reconnection/ReconnectionTest.java +++ /dev/null @@ -1,119 +0,0 @@ -package resilience.reconnection; - -import ch.qos.logback.classic.Level; -import com.arangodb.ArangoDB; -import com.arangodb.ArangoDBException; -import com.arangodb.ArangoDBMultipleException; -import com.arangodb.Protocol; -import org.junit.jupiter.params.provider.EnumSource; -import resilience.SingleServerTest; -import eu.rekawek.toxiproxy.model.ToxicDirection; -import eu.rekawek.toxiproxy.model.toxic.Latency; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.MethodSource; - -import java.io.IOException; -import java.net.ConnectException; -import java.util.concurrent.TimeoutException; -import java.util.stream.Stream; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.catchThrowable; -import static org.junit.jupiter.api.Assumptions.assumeTrue; - -/** - * @author Michele Rastelli - */ -class ReconnectionTest extends SingleServerTest { - - static Stream arangoProvider() { - return Stream.of( - dbBuilder().timeout(1_000).useProtocol(Protocol.VST).build(), - dbBuilder().timeout(1_000).useProtocol(Protocol.HTTP_VPACK).build(), - dbBuilder().timeout(1_000).useProtocol(Protocol.HTTP2_VPACK).build() - ); - } - - /** - * on reconnection failure: - * - 3x logs WARN Could not connect to host[addr=127.0.0.1,port=8529] - * - ArangoDBException("Cannot contact any host") - *

    - * once the proxy is re-enabled: - * - the subsequent requests should be successful - */ - @ParameterizedTest - @MethodSource("arangoProvider") - void unreachableHost(ArangoDB arangoDB) throws IOException, InterruptedException { - arangoDB.getVersion(); - - // close the driver connection - getEndpoint().getProxy().disable(); - Thread.sleep(100); - - for (int i = 0; i < 10; i++) { - Throwable thrown = catchThrowable(arangoDB::getVersion); - assertThat(thrown).isInstanceOf(ArangoDBException.class); - assertThat(thrown.getMessage()).contains("Cannot contact any host"); - assertThat(thrown.getCause()).isNotNull(); - assertThat(thrown.getCause()).isInstanceOf(ArangoDBMultipleException.class); - ((ArangoDBMultipleException) thrown.getCause()).getExceptions().forEach(e -> { - assertThat(e).isInstanceOf(ConnectException.class); - }); - } - - long warnsCount = logs.getLoggedEvents().stream() - .filter(e -> e.getLevel().equals(Level.WARN)) - .filter(e -> e.getMessage().contains("Could not connect to host[addr=127.0.0.1,port=18529]")) - .count(); - assertThat(warnsCount).isGreaterThanOrEqualTo(3); - - getEndpoint().getProxy().enable(); - Thread.sleep(100); - - arangoDB.getVersion(); - arangoDB.shutdown(); - } - - /** - * on reconnection failure: - * - 3x logs WARN Could not connect to host[addr=127.0.0.1,port=8529] - * - ArangoDBException("Cannot contact any host") - *

    - * once the proxy is re-enabled: - * - the subsequent requests should be successful - */ - @ParameterizedTest - @EnumSource(Protocol.class) - void connectionTimeout(Protocol protocol) throws IOException, InterruptedException { - // https://github.com/vert-x3/vertx-web/issues/2296 - // WebClient: HTTP/2 request timeout does not throw TimeoutException - assumeTrue(protocol != Protocol.HTTP2_VPACK); - assumeTrue(protocol != Protocol.HTTP2_JSON); - - ArangoDB arangoDB = dbBuilder() - .timeout(1_000) - .useProtocol(protocol) - .build(); - - arangoDB.getVersion(); - - // slow down the driver connection - Latency toxic = getEndpoint().getProxy().toxics().latency("latency", ToxicDirection.DOWNSTREAM, 10_000); - Thread.sleep(100); - - Throwable thrown = catchThrowable(arangoDB::getVersion); - thrown.printStackTrace(); - assertThat(thrown) - .isInstanceOf(ArangoDBException.class) - .extracting(Throwable::getCause) - .isInstanceOf(TimeoutException.class); - - toxic.remove(); - Thread.sleep(100); - - arangoDB.getVersion(); - arangoDB.shutdown(); - } - -} diff --git a/resilience-tests/src/test/java/resilience/retry/RetryTest.java b/resilience-tests/src/test/java/resilience/retry/RetryTest.java new file mode 100644 index 000000000..6eb074928 --- /dev/null +++ b/resilience-tests/src/test/java/resilience/retry/RetryTest.java @@ -0,0 +1,197 @@ +package resilience.retry; + +import ch.qos.logback.classic.Level; +import com.arangodb.ArangoDB; +import com.arangodb.ArangoDBException; +import com.arangodb.ArangoDBMultipleException; +import com.arangodb.Protocol; +import io.vertx.core.http.HttpClosedException; +import org.junit.jupiter.params.provider.EnumSource; +import resilience.SingleServerTest; +import eu.rekawek.toxiproxy.model.ToxicDirection; +import eu.rekawek.toxiproxy.model.toxic.Latency; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + +import java.io.IOException; +import java.net.ConnectException; +import java.util.List; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; +import java.util.stream.Stream; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.catchThrowable; +import static org.junit.jupiter.api.Assumptions.assumeTrue; + +/** + * @author Michele Rastelli + */ +class RetryTest extends SingleServerTest { + + static Stream arangoProvider() { + return Stream.of( + dbBuilder().timeout(1_000).useProtocol(Protocol.VST).build(), + dbBuilder().timeout(1_000).useProtocol(Protocol.HTTP_VPACK).build(), + dbBuilder().timeout(1_000).useProtocol(Protocol.HTTP2_VPACK).build() + ); + } + + /** + * on reconnection failure: - 3x logs WARN Could not connect to host[addr=127.0.0.1,port=8529] - + * ArangoDBException("Cannot contact any host") + *

    + * once the proxy is re-enabled: - the subsequent requests should be successful + */ + @ParameterizedTest + @MethodSource("arangoProvider") + void unreachableHost(ArangoDB arangoDB) { + arangoDB.getVersion(); + disableEndpoint(); + + for (int i = 0; i < 10; i++) { + Throwable thrown = catchThrowable(arangoDB::getVersion); + assertThat(thrown).isInstanceOf(ArangoDBException.class); + assertThat(thrown.getMessage()).contains("Cannot contact any host"); + assertThat(thrown.getCause()).isNotNull(); + assertThat(thrown.getCause()).isInstanceOf(ArangoDBMultipleException.class); + ((ArangoDBMultipleException) thrown.getCause()).getExceptions().forEach(e -> { + assertThat(e).isInstanceOf(ConnectException.class); + }); + } + + long warnsCount = logs.getLoggedEvents().stream() + .filter(e -> e.getLevel().equals(Level.WARN)) + .filter(e -> e.getMessage().contains("Could not connect to host[addr=127.0.0.1,port=18529]")) + .count(); + assertThat(warnsCount).isGreaterThanOrEqualTo(3); + + enableEndpoint(); + arangoDB.getVersion(); + arangoDB.shutdown(); + } + + /** + * on delayed response: + * - ArangoDBException with cause TimeoutException + *

    + * once the delay is removed: + * - the subsequent requests should be successful + */ + @ParameterizedTest + @EnumSource(Protocol.class) + void connectionTimeout(Protocol protocol) throws IOException, InterruptedException { + // https://github.com/vert-x3/vertx-web/issues/2296 + // WebClient: HTTP/2 request timeout does not throw TimeoutException + assumeTrue(protocol != Protocol.HTTP2_VPACK); + assumeTrue(protocol != Protocol.HTTP2_JSON); + + ArangoDB arangoDB = dbBuilder() + .timeout(1_000) + .useProtocol(protocol) + .build(); + + arangoDB.getVersion(); + + // slow down the driver connection + Latency toxic = getEndpoint().getProxy().toxics().latency("latency", ToxicDirection.DOWNSTREAM, 10_000); + Thread.sleep(100); + + Throwable thrown = catchThrowable(arangoDB::getVersion); + thrown.printStackTrace(); + assertThat(thrown) + .isInstanceOf(ArangoDBException.class) + .extracting(Throwable::getCause) + .isInstanceOf(TimeoutException.class); + + toxic.remove(); + Thread.sleep(100); + + arangoDB.getVersion(); + arangoDB.shutdown(); + } + + + /** + * on closed pending requests of safe HTTP methods: - retry 3 times - ArangoDBMultipleException with 3 exceptions + *

    + * once restored: - the subsequent requests should be successful + */ + @ParameterizedTest + @EnumSource(Protocol.class) + void retryGetOnClosedConnection(Protocol protocol) throws IOException, InterruptedException { + assumeTrue(protocol != Protocol.VST); + ArangoDB arangoDB = dbBuilder() + .useProtocol(protocol) + .build(); + + arangoDB.getVersion(); + + // slow down the driver connection + Latency toxic = getEndpoint().getProxy().toxics().latency("latency", ToxicDirection.DOWNSTREAM, 10_000); + Thread.sleep(100); + + ScheduledExecutorService es = Executors.newSingleThreadScheduledExecutor(); + es.schedule(this::disableEndpoint, 300, TimeUnit.MILLISECONDS); + + Throwable thrown = catchThrowable(arangoDB::getVersion); + thrown.printStackTrace(); + assertThat(thrown).isInstanceOf(ArangoDBException.class); + assertThat(thrown.getCause()).isInstanceOf(ArangoDBMultipleException.class); + List exceptions = ((ArangoDBMultipleException) thrown.getCause()).getExceptions(); + assertThat(exceptions).hasSize(3); + assertThat(exceptions.get(0)).isInstanceOf(IOException.class); + assertThat(exceptions.get(0).getCause()).isInstanceOf(HttpClosedException.class); + assertThat(exceptions.get(1)).isInstanceOf(ConnectException.class); + assertThat(exceptions.get(2)).isInstanceOf(ConnectException.class); + + toxic.remove(); + Thread.sleep(100); + enableEndpoint(); + + arangoDB.getVersion(); + arangoDB.shutdown(); + es.shutdown(); + } + + + /** + * on closed pending requests of unsafe HTTP methods: - no retry should happen + *

    + * once restored: - the subsequent requests should be successful + */ + @ParameterizedTest + @EnumSource(Protocol.class) + void notRetryPostOnClosedConnection(Protocol protocol) throws IOException, InterruptedException { + assumeTrue(protocol != Protocol.VST); + ArangoDB arangoDB = dbBuilder() + .useProtocol(protocol) + .build(); + + arangoDB.db().query("return null", Void.class); + + // slow down the driver connection + Latency toxic = getEndpoint().getProxy().toxics().latency("latency", ToxicDirection.DOWNSTREAM, 10_000); + Thread.sleep(100); + + ScheduledExecutorService es = Executors.newSingleThreadScheduledExecutor(); + es.schedule(this::disableEndpoint, 300, TimeUnit.MILLISECONDS); + + Throwable thrown = catchThrowable(() -> arangoDB.db().query("return null", Void.class)); + thrown.printStackTrace(); + assertThat(thrown).isInstanceOf(ArangoDBException.class); + assertThat(thrown.getCause()).isInstanceOf(IOException.class); + assertThat(thrown.getCause().getCause()).isInstanceOf(HttpClosedException.class); + + toxic.remove(); + Thread.sleep(100); + enableEndpoint(); + + arangoDB.db().query("return null", Void.class); + arangoDB.shutdown(); + es.shutdown(); + } + +} diff --git a/resilience-tests/src/test/resources/logback-test.xml b/resilience-tests/src/test/resources/logback-test.xml index 840d133d7..343f4dfdd 100644 --- a/resilience-tests/src/test/resources/logback-test.xml +++ b/resilience-tests/src/test/resources/logback-test.xml @@ -6,7 +6,7 @@ - + From 39b1b40b0de2c7d201fb5815131b1a44c4835d80 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Tue, 8 Nov 2022 14:13:27 +0100 Subject: [PATCH 181/254] [DE-424] Bugfix HTTP shutdown (#469) * CodeQL fixes * fixed http shutdown --- .github/workflows/codeql.yml | 6 +- .../internal/net/ConnectionPoolImpl.java | 6 ++ .../test/java/resilience/retry/RetryTest.java | 11 ++-- .../resilience/shutdown/ShutdownTest.java | 58 +++++++++++++++++++ 4 files changed, 71 insertions(+), 10 deletions(-) create mode 100644 resilience-tests/src/test/java/resilience/shutdown/ShutdownTest.java diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 14392e1ac..048635939 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -29,10 +29,6 @@ jobs: name: Analyze runs-on: ubuntu-latest - defaults: - run: - working-directory: driver - permissions: actions: read contents: read @@ -66,6 +62,7 @@ jobs: # If this step fails, then you should remove it and run the build manually (see below) - name: Autobuild uses: github/codeql-action/autobuild@v2 + working-directory: driver # ℹ️ Command-line programs to run using the OS shell. # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun @@ -79,3 +76,4 @@ jobs: - name: Perform CodeQL Analysis uses: github/codeql-action/analyze@v2 + working-directory: driver diff --git a/driver/src/main/java/com/arangodb/internal/net/ConnectionPoolImpl.java b/driver/src/main/java/com/arangodb/internal/net/ConnectionPoolImpl.java index 05cd39b4a..c86f07a47 100644 --- a/driver/src/main/java/com/arangodb/internal/net/ConnectionPoolImpl.java +++ b/driver/src/main/java/com/arangodb/internal/net/ConnectionPoolImpl.java @@ -20,6 +20,7 @@ package com.arangodb.internal.net; +import com.arangodb.ArangoDBException; import com.arangodb.internal.velocystream.internal.VstConnection; import com.arangodb.internal.velocystream.internal.VstConnectionSync; import org.slf4j.Logger; @@ -42,6 +43,7 @@ public class ConnectionPoolImpl implements ConnectionPool { private final ConnectionFactory factory; private int current; private volatile String jwt = null; + private boolean closed = false; public ConnectionPoolImpl(final HostDescription host, final Integer maxConnections, final ConnectionFactory factory) { @@ -62,6 +64,9 @@ public Connection createConnection(final HostDescription host) { @Override public synchronized Connection connection() { + if (closed) { + throw new ArangoDBException("Connection pool already closed!"); + } final Connection connection; @@ -91,6 +96,7 @@ public void setJwt(String jwt) { @Override public synchronized void close() throws IOException { + closed = true; for (final Connection connection : connections) { connection.close(); } diff --git a/resilience-tests/src/test/java/resilience/retry/RetryTest.java b/resilience-tests/src/test/java/resilience/retry/RetryTest.java index 6eb074928..e83f8565d 100644 --- a/resilience-tests/src/test/java/resilience/retry/RetryTest.java +++ b/resilience-tests/src/test/java/resilience/retry/RetryTest.java @@ -33,9 +33,9 @@ class RetryTest extends SingleServerTest { static Stream arangoProvider() { return Stream.of( - dbBuilder().timeout(1_000).useProtocol(Protocol.VST).build(), - dbBuilder().timeout(1_000).useProtocol(Protocol.HTTP_VPACK).build(), - dbBuilder().timeout(1_000).useProtocol(Protocol.HTTP2_VPACK).build() + dbBuilder().useProtocol(Protocol.VST).build(), + dbBuilder().useProtocol(Protocol.HTTP_VPACK).build(), + dbBuilder().useProtocol(Protocol.HTTP2_VPACK).build() ); } @@ -57,9 +57,8 @@ void unreachableHost(ArangoDB arangoDB) { assertThat(thrown.getMessage()).contains("Cannot contact any host"); assertThat(thrown.getCause()).isNotNull(); assertThat(thrown.getCause()).isInstanceOf(ArangoDBMultipleException.class); - ((ArangoDBMultipleException) thrown.getCause()).getExceptions().forEach(e -> { - assertThat(e).isInstanceOf(ConnectException.class); - }); + ((ArangoDBMultipleException) thrown.getCause()).getExceptions().forEach(e -> + assertThat(e).isInstanceOf(ConnectException.class)); } long warnsCount = logs.getLoggedEvents().stream() diff --git a/resilience-tests/src/test/java/resilience/shutdown/ShutdownTest.java b/resilience-tests/src/test/java/resilience/shutdown/ShutdownTest.java new file mode 100644 index 000000000..1a8924196 --- /dev/null +++ b/resilience-tests/src/test/java/resilience/shutdown/ShutdownTest.java @@ -0,0 +1,58 @@ +package resilience.shutdown; + +import com.arangodb.ArangoDB; +import com.arangodb.ArangoDBException; +import com.arangodb.Protocol; +import io.vertx.core.http.HttpClosedException; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.EnumSource; +import resilience.SingleServerTest; + +import java.io.IOException; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.catchThrowable; +import static org.junit.jupiter.api.Assumptions.assumeTrue; + +/** + * @author Michele Rastelli + */ +class ShutdownTest extends SingleServerTest { + + @ParameterizedTest + @EnumSource(Protocol.class) + void shutdown(Protocol protocol) throws InterruptedException { + ArangoDB arangoDB = dbBuilder() + .useProtocol(protocol) + .build(); + + arangoDB.getVersion(); + arangoDB.shutdown(); + Thread.sleep(1_000); + Throwable thrown = catchThrowable(arangoDB::getVersion); + assertThat(thrown).isInstanceOf(ArangoDBException.class); + assertThat(thrown.getMessage()).contains("closed"); + } + + @ParameterizedTest + @EnumSource(Protocol.class) + void shutdownWithPendingRequests(Protocol protocol) { + assumeTrue(protocol != Protocol.VST); + ArangoDB arangoDB = dbBuilder() + .useProtocol(protocol) + .build(); + + ScheduledExecutorService es = Executors.newSingleThreadScheduledExecutor(); + es.schedule(arangoDB::shutdown, 200, TimeUnit.MILLISECONDS); + Throwable thrown = catchThrowable(() -> arangoDB.db().query("return sleep(1)", Void.class)); + thrown.printStackTrace(); + assertThat(thrown).isInstanceOf(ArangoDBException.class); + assertThat(thrown.getCause()).isInstanceOf(IOException.class); + assertThat(thrown.getCause().getCause()).isInstanceOf(HttpClosedException.class); + es.shutdown(); + } + +} From 4ffadab336cf7c49a680b75608827fe812a4b1b5 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Tue, 8 Nov 2022 20:52:13 +0100 Subject: [PATCH 182/254] codeql fixes --- .github/workflows/codeql.yml | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 048635939..9c1de6db7 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -42,6 +42,13 @@ jobs: # Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support steps: + - name: Set up JDK + uses: actions/setup-java@v2 + with: + java-version: 17 + distribution: 'adopt' + cache: maven + - name: Checkout repository uses: actions/checkout@v3 @@ -62,7 +69,6 @@ jobs: # If this step fails, then you should remove it and run the build manually (see below) - name: Autobuild uses: github/codeql-action/autobuild@v2 - working-directory: driver # ℹ️ Command-line programs to run using the OS shell. # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun @@ -76,4 +82,3 @@ jobs: - name: Perform CodeQL Analysis uses: github/codeql-action/analyze@v2 - working-directory: driver From 4b1bfc044ca22aa8430c1e7c7533ca9ef6d30b82 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Tue, 8 Nov 2022 21:11:37 +0100 Subject: [PATCH 183/254] tests fixes --- driver/src/test/java/com/arangodb/BaseJunit5.java | 1 - 1 file changed, 1 deletion(-) diff --git a/driver/src/test/java/com/arangodb/BaseJunit5.java b/driver/src/test/java/com/arangodb/BaseJunit5.java index 7e2ecc2a6..8ab731579 100644 --- a/driver/src/test/java/com/arangodb/BaseJunit5.java +++ b/driver/src/test/java/com/arangodb/BaseJunit5.java @@ -88,7 +88,6 @@ static void init() { @AfterAll static void shutdown() { dropDB(TEST_DB); - adbs.forEach(ArangoDB::shutdown); } static String rnd() { From 9c9a808fd128dc1aae8236a57f15a53bbc168472 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Tue, 8 Nov 2022 21:47:20 +0100 Subject: [PATCH 184/254] codeql fixes --- .github/workflows/codeql.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 9c1de6db7..1c453d168 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -42,6 +42,9 @@ jobs: # Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support steps: + - name: Checkout repository + uses: actions/checkout@v3 + - name: Set up JDK uses: actions/setup-java@v2 with: @@ -49,9 +52,6 @@ jobs: distribution: 'adopt' cache: maven - - name: Checkout repository - uses: actions/checkout@v3 - # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL uses: github/codeql-action/init@v2 From 3f8f94f89cbb4e41e9da9d221f4d496aefd3c753 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Wed, 9 Nov 2022 14:09:34 +0100 Subject: [PATCH 185/254] [DE-426] execute generic parameterized request (#470) * removed execute with hostHandle * removed ArangoRoute * execute custom request with POJO body --- .../src/main/java/com/arangodb/ArangoDB.java | 26 +-- .../java/com/arangodb/ArangoDatabase.java | 9 - .../main/java/com/arangodb/ArangoRoute.java | 112 ---------- .../src/main/java/com/arangodb/Request.java | 193 +++++++++--------- .../src/main/java/com/arangodb/Response.java | 100 +-------- .../com/arangodb/async/ArangoDBAsync.java | 15 +- .../com/arangodb/async/ArangoRouteAsync.java | 14 +- .../async/internal/ArangoDBAsyncImpl.java | 11 +- .../internal/ArangoDatabaseAsyncImpl.java | 4 +- .../async/internal/ArangoExecutorAsync.java | 10 +- .../async/internal/ArangoRouteAsyncImpl.java | 18 +- .../velocystream/VstCommunicationAsync.java | 20 +- .../com/arangodb/internal/ArangoDBImpl.java | 12 +- .../arangodb/internal/ArangoDatabaseImpl.java | 9 +- .../arangodb/internal/ArangoExecuteable.java | 6 +- .../com/arangodb/internal/ArangoExecutor.java | 10 +- .../arangodb/internal/ArangoExecutorSync.java | 12 +- .../arangodb/internal/ArangoRouteImpl.java | 99 --------- .../internal/InternalArangoCollection.java | 156 +++++++------- .../arangodb/internal/InternalArangoDB.java | 62 +++--- .../internal/InternalArangoDatabase.java | 116 ++++++----- .../InternalArangoEdgeCollection.java | 22 +- .../internal/InternalArangoGraph.java | 28 ++- .../internal/InternalArangoRoute.java | 7 +- .../internal/InternalArangoSearch.java | 12 +- .../InternalArangoVertexCollection.java | 24 +-- .../arangodb/internal/InternalArangoView.java | 10 +- .../arangodb/internal/InternalRequest.java | 148 ++++++++++++++ .../arangodb/internal/InternalResponse.java | 105 ++++++++++ .../internal/InternalSearchAlias.java | 12 +- .../arangodb/{ => internal}/RequestType.java | 28 ++- .../internal/http/HttpCommunication.java | 14 +- .../internal/http/HttpConnection.java | 24 +-- .../arangodb/internal/http/HttpProtocol.java | 6 +- .../internal/net/CommunicationProtocol.java | 6 +- .../internal/net/ExtendedHostResolver.java | 6 +- .../internal/serde/InternalDeserializers.java | 8 +- .../internal/serde/InternalModule.java | 8 +- .../internal/serde/InternalSerializers.java | 6 +- .../arangodb/internal/util/RequestUtils.java | 8 +- .../arangodb/internal/util/ResponseUtils.java | 4 +- .../velocystream/VstCommunication.java | 20 +- .../velocystream/VstCommunicationSync.java | 18 +- .../internal/velocystream/VstProtocol.java | 10 +- .../internal/AuthenticationRequest.java | 4 +- .../internal/JwtAuthenticationRequest.java | 4 +- .../test/java/com/arangodb/ArangoDBTest.java | 20 +- .../java/com/arangodb/ArangoRouteTest.java | 80 -------- .../test/java/com/arangodb/JwtAuthTest.java | 16 +- .../java/com/arangodb/async/ArangoDBTest.java | 20 +- .../java/com/arangodb/async/JwtAuthTest.java | 22 +- .../src/test/java/perf/SyncBenchmarkTest.java | 11 +- 52 files changed, 804 insertions(+), 921 deletions(-) delete mode 100644 driver/src/main/java/com/arangodb/ArangoRoute.java delete mode 100644 driver/src/main/java/com/arangodb/internal/ArangoRouteImpl.java create mode 100644 driver/src/main/java/com/arangodb/internal/InternalRequest.java create mode 100644 driver/src/main/java/com/arangodb/internal/InternalResponse.java rename driver/src/main/java/com/arangodb/{ => internal}/RequestType.java (64%) delete mode 100644 driver/src/test/java/com/arangodb/ArangoRouteTest.java diff --git a/driver/src/main/java/com/arangodb/ArangoDB.java b/driver/src/main/java/com/arangodb/ArangoDB.java index 661d77b30..118bd755c 100644 --- a/driver/src/main/java/com/arangodb/ArangoDB.java +++ b/driver/src/main/java/com/arangodb/ArangoDB.java @@ -23,9 +23,7 @@ import com.arangodb.config.ConfigPropertiesProvider; import com.arangodb.config.ConfigPropertyKey; import com.arangodb.entity.*; -import com.arangodb.internal.ArangoDBImpl; -import com.arangodb.internal.ArangoDefaults; -import com.arangodb.internal.InternalArangoDBBuilder; +import com.arangodb.internal.*; import com.arangodb.internal.http.HttpCommunication; import com.arangodb.internal.http.HttpConnectionFactory; import com.arangodb.internal.net.*; @@ -276,21 +274,19 @@ public interface ArangoDB extends ArangoSerdeAccessor { void grantDefaultCollectionAccess(String user, Permissions permissions); /** - * Generic Execute. Use this method to execute custom FOXX services. + * Execute custom requests. Requests can be programmatically built by setting low level detail such as method, path, + * query parameters, headers and body payload. + * This method can be used to call FOXX services, API endpoints not (yet) implemented in this driver or trigger + * async jobs, see + * Fire and Forget + * and + * Async Execution and later Result Retrieval * * @param request request - * @return VelocyStream response + * @param type Deserialization target type for the response body (POJO or {@link com.arangodb.util.RawData}) + * @return response */ - Response execute(Request request); - - /** - * Generic Execute. Use this method to execute custom FOXX services. - * - * @param request request - * @param hostHandle Used to stick to a specific host when using {@link LoadBalancingStrategy#ROUND_ROBIN} - * @return VelocyStream response - */ - Response execute(Request request, HostHandle hostHandle); + Response execute(Request request, Class type); /** * Returns the server logs diff --git a/driver/src/main/java/com/arangodb/ArangoDatabase.java b/driver/src/main/java/com/arangodb/ArangoDatabase.java index 8224f27c0..1ef5e1de1 100644 --- a/driver/src/main/java/com/arangodb/ArangoDatabase.java +++ b/driver/src/main/java/com/arangodb/ArangoDatabase.java @@ -612,15 +612,6 @@ public interface ArangoDatabase extends ArangoSerdeAccessor { */ void reloadRouting(); - /** - * Returns a new {@link ArangoRoute} instance for the given path (relative to the database) that can be used to - * perform arbitrary requests. - * - * @param path The database-relative URL of the route - * @return {@link ArangoRoute} - */ - ArangoRoute route(String... path); - /** * Fetches all views from the database and returns an list of view descriptions. * diff --git a/driver/src/main/java/com/arangodb/ArangoRoute.java b/driver/src/main/java/com/arangodb/ArangoRoute.java deleted file mode 100644 index 4e4bab95b..000000000 --- a/driver/src/main/java/com/arangodb/ArangoRoute.java +++ /dev/null @@ -1,112 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2018 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb; - -/** - * Interface for a specific path to be used to perform arbitrary requests. - * - * @author Mark Vollmary - */ -public interface ArangoRoute extends ArangoSerdeAccessor { - - /** - * Returns a new {@link ArangoRoute} instance for the given path (relative to the current route) that can be used to - * perform arbitrary requests. - * - * @param path The relative URL of the route - * @return {@link ArangoRoute} - */ - ArangoRoute route(String... path); - - /** - * Header that should be sent with each request to the route. - * - * @param key Header key - * @param value Header value (the {@code toString()} method will be called for the value} - * @return {@link ArangoRoute} - */ - ArangoRoute withHeader(String key, Object value); - - /** - * Query parameter that should be sent with each request to the route. - * - * @param key Query parameter key - * @param value Query parameter value (the {@code toString()} method will be called for the value} - * @return {@link ArangoRoute} - */ - ArangoRoute withQueryParam(String key, Object value); - - /** - * The response body. - * - * @param body The request body - * @return {@link ArangoRoute} - */ - ArangoRoute withBody(Object body); - - /** - * Performs a DELETE request to the given URL and returns the server response. - * - * @return server response - */ - Response delete(); - - /** - * Performs a GET request to the given URL and returns the server response. - * - * @return server response - */ - - Response get(); - - /** - * Performs a HEAD request to the given URL and returns the server response. - * - * @return server response - */ - - Response head(); - - /** - * Performs a PATCH request to the given URL and returns the server response. - * - * @return server response - */ - - Response patch(); - - /** - * Performs a POST request to the given URL and returns the server response. - * - * @return server response - */ - - Response post(); - - /** - * Performs a PUT request to the given URL and returns the server response. - * - * @return server response - */ - - Response put(); - -} diff --git a/driver/src/main/java/com/arangodb/Request.java b/driver/src/main/java/com/arangodb/Request.java index f3c8e9429..dbc708632 100644 --- a/driver/src/main/java/com/arangodb/Request.java +++ b/driver/src/main/java/com/arangodb/Request.java @@ -1,137 +1,130 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - package com.arangodb; -import java.util.Collections; import java.util.HashMap; -import java.util.Locale; import java.util.Map; -/** - * @author Mark Vollmary - */ -public class Request { - - private final DbName dbName; - private final RequestType requestType; +public final class Request { + private final DbName db; + private final Method method; private final String path; - private final Map queryParam; - private final Map headerParam; - private int version = 1; - private int type = 1; - private byte[] body; - - public Request(final DbName dbName, final RequestType requestType, final String path) { - super(); - this.dbName = dbName; - this.requestType = requestType; - this.path = path; - body = null; - queryParam = new HashMap<>(); - headerParam = new HashMap<>(); - } + private final Map queryParams; + private final Map headers; + private final T body; - public int getVersion() { - return version; + public enum Method { + DELETE, + GET, + POST, + PUT, + HEAD, + PATCH, + OPTIONS } - public Request setVersion(final int version) { - this.version = version; - return this; + public static Builder builder() { + return new Builder<>(); } - public int getType() { - return type; - } - - public Request setType(final int type) { - this.type = type; - return this; + private Request(DbName db, Method method, String path, Map queryParams, Map headers, T body) { + this.db = db; + this.method = method; + this.path = path; + this.queryParams = queryParams; + this.headers = headers; + this.body = body; } - public DbName getDbName() { - return dbName; + public DbName getDb() { + return db; } - public RequestType getRequestType() { - return requestType; + public Method getMethod() { + return method; } public String getPath() { return path; } - public Map getQueryParam() { - return queryParam; + public Map getQueryParams() { + return queryParams; } - public Request putQueryParam(final String key, final Object value) { - if (value != null) { - queryParam.put(key, value.toString()); - } - return this; + public Map getHeaders() { + return headers; } - public Map getHeaderParam() { - return Collections.unmodifiableMap(headerParam); + public T getBody() { + return body; } - public boolean containsHeaderParam(final String key) { - return headerParam.containsKey(key.toLowerCase(Locale.ROOT)); - } + public static final class Builder { + private DbName db; + private Request.Method method; + private String path; + private final Map queryParams; + private final Map headers; + private T body; - public Request putHeaderParam(final String key, final String value) { - if (value != null) { - headerParam.put(key.toLowerCase(Locale.ROOT), value); + public Builder() { + queryParams = new HashMap<>(); + headers = new HashMap<>(); + } + + public Builder db(DbName db) { + this.db = db; + return this; + } + + public Builder method(Request.Method method) { + this.method = method; + return this; + } + + public Builder path(String path) { + this.path = path; + return this; } - return this; - } - public Request putHeaderParams(final Map params) { - if (params != null) { - for (Map.Entry it : params.entrySet()) { - putHeaderParam(it.getKey(), it.getValue()); + public Builder queryParam(final String key, final String value) { + if (value != null) { + queryParams.put(key, value); } + return this; } - return this; - } - public byte[] getBody() { - return body; - } + public Builder queryParams(Map queryParams) { + if (queryParams != null) { + for (Map.Entry it : queryParams.entrySet()) { + queryParam(it.getKey(), it.getValue()); + } + } + return this; + } - public Request setBody(final byte[] body) { - this.body = body; - return this; - } + public Builder header(final String key, final String value) { + if (value != null) { + headers.put(key, value); + } + return this; + } - @Override - public String toString() { - return "{" + - "requestType=" + requestType + - ", database='" + dbName + '\'' + - ", url='" + path + '\'' + - ", parameters=" + queryParam + - ", headers=" + headerParam + - '}'; - } + public Builder headers(Map headers) { + if (headers != null) { + for (Map.Entry it : headers.entrySet()) { + header(it.getKey(), it.getValue()); + } + } + return this; + } + public Builder body(T body) { + this.body = body; + return this; + } + + public Request build() { + return new Request<>(db, method, path, queryParams, headers, body); + } + } } diff --git a/driver/src/main/java/com/arangodb/Response.java b/driver/src/main/java/com/arangodb/Response.java index a7fffa552..49c37698b 100644 --- a/driver/src/main/java/com/arangodb/Response.java +++ b/driver/src/main/java/com/arangodb/Response.java @@ -1,105 +1,27 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - package com.arangodb; -import java.util.Collections; -import java.util.HashMap; -import java.util.Locale; import java.util.Map; -/** - * @author Mark Vollmary - */ -public class Response { - - private int version = 1; - private int type = 2; - private int responseCode; - private final Map meta; - private byte[] body = null; - - public Response() { - super(); - meta = new HashMap<>(); - } - - public int getVersion() { - return version; - } - - public void setVersion(final int version) { - this.version = version; - } - - public int getType() { - return type; - } +public final class Response { + private final int responseCode; + private final Map headers; + private final T body; - public void setType(final int type) { - this.type = type; + public Response(int responseCode, Map headers, T body) { + this.responseCode = responseCode; + this.headers = headers; + this.body = body; } public int getResponseCode() { return responseCode; } - public void setResponseCode(final int responseCode) { - this.responseCode = responseCode; - } - - public Map getMeta() { - return Collections.unmodifiableMap(meta); - } - - public String getMeta(final String key) { - return meta.get(key.toLowerCase(Locale.ROOT)); - } - - public boolean containsMeta(final String key) { - return meta.containsKey(key.toLowerCase(Locale.ROOT)); - } - - public void putMeta(final String key, final String value) { - this.meta.put(key.toLowerCase(Locale.ROOT), value); + public Map getHeaders() { + return headers; } - public void putMetas(final Map meta) { - for (Map.Entry it : meta.entrySet()) { - putMeta(it.getKey(), it.getValue()); - } - } - - public byte[] getBody() { + public T getBody() { return body; } - - public void setBody(final byte[] body) { - this.body = body; - } - - @Override - public String toString() { - return "{" + - "statusCode=" + responseCode + - ", headers=" + meta + - '}'; - } } diff --git a/driver/src/main/java/com/arangodb/async/ArangoDBAsync.java b/driver/src/main/java/com/arangodb/async/ArangoDBAsync.java index 949dedd02..28e1701f3 100644 --- a/driver/src/main/java/com/arangodb/async/ArangoDBAsync.java +++ b/driver/src/main/java/com/arangodb/async/ArangoDBAsync.java @@ -257,12 +257,19 @@ public interface ArangoDBAsync extends ArangoSerdeAccessor { CompletableFuture grantDefaultCollectionAccess(final String user, final Permissions permissions); /** - * Generic Execute. Use this method to execute custom FOXX services. + * Execute custom requests. Requests can be programmatically built by setting low level detail such as method, path, + * query parameters, headers and body payload. + * This method can be used to call FOXX services, API endpoints not (yet) implemented in this driver or trigger + * async jobs, see + * Fire and Forget + * and + * Async Execution and later Result Retrieval * - * @param request VelocyStream request - * @return VelocyStream response + * @param request request + * @param type Deserialization target type for the response body (POJO or {@link com.arangodb.util.RawData}) + * @return response */ - CompletableFuture execute(final Request request); + CompletableFuture> execute(final Request request, final Class type); /** * Returns the server logs diff --git a/driver/src/main/java/com/arangodb/async/ArangoRouteAsync.java b/driver/src/main/java/com/arangodb/async/ArangoRouteAsync.java index ed66aff87..c2ab2d221 100644 --- a/driver/src/main/java/com/arangodb/async/ArangoRouteAsync.java +++ b/driver/src/main/java/com/arangodb/async/ArangoRouteAsync.java @@ -21,7 +21,7 @@ package com.arangodb.async; import com.arangodb.ArangoSerdeAccessor; -import com.arangodb.Response; +import com.arangodb.internal.InternalResponse; import java.util.concurrent.CompletableFuture; @@ -72,7 +72,7 @@ public interface ArangoRouteAsync extends ArangoSerdeAccessor { * * @return server response */ - CompletableFuture delete(); + CompletableFuture delete(); /** * Performs a GET request to the given URL and returns the server response. @@ -80,7 +80,7 @@ public interface ArangoRouteAsync extends ArangoSerdeAccessor { * @return server response */ - CompletableFuture get(); + CompletableFuture get(); /** * Performs a HEAD request to the given URL and returns the server response. @@ -88,7 +88,7 @@ public interface ArangoRouteAsync extends ArangoSerdeAccessor { * @return server response */ - CompletableFuture head(); + CompletableFuture head(); /** * Performs a PATCH request to the given URL and returns the server response. @@ -96,7 +96,7 @@ public interface ArangoRouteAsync extends ArangoSerdeAccessor { * @return server response */ - CompletableFuture patch(); + CompletableFuture patch(); /** * Performs a POST request to the given URL and returns the server response. @@ -104,7 +104,7 @@ public interface ArangoRouteAsync extends ArangoSerdeAccessor { * @return server response */ - CompletableFuture post(); + CompletableFuture post(); /** * Performs a PUT request to the given URL and returns the server response. @@ -112,6 +112,6 @@ public interface ArangoRouteAsync extends ArangoSerdeAccessor { * @return server response */ - CompletableFuture put(); + CompletableFuture put(); } diff --git a/driver/src/main/java/com/arangodb/async/internal/ArangoDBAsyncImpl.java b/driver/src/main/java/com/arangodb/async/internal/ArangoDBAsyncImpl.java index 5e52ffdf5..2ad1b2b0d 100644 --- a/driver/src/main/java/com/arangodb/async/internal/ArangoDBAsyncImpl.java +++ b/driver/src/main/java/com/arangodb/async/internal/ArangoDBAsyncImpl.java @@ -22,6 +22,8 @@ import com.arangodb.ArangoMetrics; import com.arangodb.DbName; +import com.arangodb.Request; +import com.arangodb.Response; import com.arangodb.async.ArangoDBAsync; import com.arangodb.async.ArangoDatabaseAsync; import com.arangodb.async.internal.velocystream.VstCommunicationAsync; @@ -40,8 +42,7 @@ import com.arangodb.model.LogOptions; import com.arangodb.model.UserCreateOptions; import com.arangodb.model.UserUpdateOptions; -import com.arangodb.Request; -import com.arangodb.Response; +import com.arangodb.internal.InternalResponse; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -75,7 +76,7 @@ public ArangoDBAsyncImpl( super(new ArangoExecutorAsync(asyncCommBuilder.build(util), util, new QueueTimeMetricsImpl(responseQueueTimeSamples), timeoutMs), util); - final VstCommunication cacheCom = syncCommBuilder.build(util); + final VstCommunication cacheCom = syncCommBuilder.build(util); cp = new VstProtocol(cacheCom); this.asyncHostHandler = asyncHostHandler; @@ -215,8 +216,8 @@ public CompletableFuture grantDefaultCollectionAccess(final String user, f } @Override - public CompletableFuture execute(final Request request) { - return executor.execute(request, response -> response); + public CompletableFuture> execute(Request request, Class type) { + return executor.execute(executeRequest(request), responseDeserializer(type)); } @Override diff --git a/driver/src/main/java/com/arangodb/async/internal/ArangoDatabaseAsyncImpl.java b/driver/src/main/java/com/arangodb/async/internal/ArangoDatabaseAsyncImpl.java index 180f2671c..b8ab7b0aa 100644 --- a/driver/src/main/java/com/arangodb/async/internal/ArangoDatabaseAsyncImpl.java +++ b/driver/src/main/java/com/arangodb/async/internal/ArangoDatabaseAsyncImpl.java @@ -35,7 +35,7 @@ import com.arangodb.model.arangosearch.AnalyzerDeleteOptions; import com.arangodb.model.arangosearch.ArangoSearchCreateOptions; import com.arangodb.model.arangosearch.SearchAliasCreateOptions; -import com.arangodb.Request; +import com.arangodb.internal.InternalRequest; import java.util.Collection; import java.util.Collections; @@ -179,7 +179,7 @@ public CompletableFuture> query( final Map bindVars, final AqlQueryOptions options, final Class type) { - final Request request = queryRequest(query, bindVars, options); + final InternalRequest request = queryRequest(query, bindVars, options); final HostHandle hostHandle = new HostHandle(); final CompletableFuture execution = executor.execute(request, InternalCursorEntity.class, hostHandle); diff --git a/driver/src/main/java/com/arangodb/async/internal/ArangoExecutorAsync.java b/driver/src/main/java/com/arangodb/async/internal/ArangoExecutorAsync.java index 1510cbf2a..831b64e40 100644 --- a/driver/src/main/java/com/arangodb/async/internal/ArangoExecutorAsync.java +++ b/driver/src/main/java/com/arangodb/async/internal/ArangoExecutorAsync.java @@ -26,7 +26,7 @@ import com.arangodb.internal.QueueTimeMetricsImpl; import com.arangodb.internal.net.HostHandle; import com.arangodb.internal.serde.InternalSerde; -import com.arangodb.Request; +import com.arangodb.internal.InternalRequest; import java.io.IOException; import java.lang.reflect.Type; @@ -49,20 +49,20 @@ public ArangoExecutorAsync(final VstCommunicationAsync communication, final Inte this.communication = communication; } - public CompletableFuture execute(final Request request, final Type type) { + public CompletableFuture execute(final InternalRequest request, final Type type) { return execute(request, response -> createResult(type, response)); } - public CompletableFuture execute(final Request request, final Type type, final HostHandle hostHandle) { + public CompletableFuture execute(final InternalRequest request, final Type type, final HostHandle hostHandle) { return execute(request, response -> createResult(type, response), hostHandle); } - public CompletableFuture execute(final Request request, final ResponseDeserializer responseDeserializer) { + public CompletableFuture execute(final InternalRequest request, final ResponseDeserializer responseDeserializer) { return execute(request, responseDeserializer, null); } private CompletableFuture execute( - final Request request, + final InternalRequest request, final ResponseDeserializer responseDeserializer, final HostHandle hostHandle) { diff --git a/driver/src/main/java/com/arangodb/async/internal/ArangoRouteAsyncImpl.java b/driver/src/main/java/com/arangodb/async/internal/ArangoRouteAsyncImpl.java index e00688dcc..57270220d 100644 --- a/driver/src/main/java/com/arangodb/async/internal/ArangoRouteAsyncImpl.java +++ b/driver/src/main/java/com/arangodb/async/internal/ArangoRouteAsyncImpl.java @@ -22,8 +22,8 @@ import com.arangodb.async.ArangoRouteAsync; import com.arangodb.internal.InternalArangoRoute; -import com.arangodb.RequestType; -import com.arangodb.Response; +import com.arangodb.internal.RequestType; +import com.arangodb.internal.InternalResponse; import java.util.Map; import java.util.concurrent.CompletableFuture; @@ -66,37 +66,37 @@ public ArangoRouteAsync withBody(final Object body) { return this; } - private CompletableFuture request(final RequestType requestType) { + private CompletableFuture request(final RequestType requestType) { return executor.execute(createRequest(requestType), response -> response); } @Override - public CompletableFuture delete() { + public CompletableFuture delete() { return request(RequestType.DELETE); } @Override - public CompletableFuture get() { + public CompletableFuture get() { return request(RequestType.GET); } @Override - public CompletableFuture head() { + public CompletableFuture head() { return request(RequestType.HEAD); } @Override - public CompletableFuture patch() { + public CompletableFuture patch() { return request(RequestType.PATCH); } @Override - public CompletableFuture post() { + public CompletableFuture post() { return request(RequestType.POST); } @Override - public CompletableFuture put() { + public CompletableFuture put() { return request(RequestType.PUT); } diff --git a/driver/src/main/java/com/arangodb/async/internal/velocystream/VstCommunicationAsync.java b/driver/src/main/java/com/arangodb/async/internal/velocystream/VstCommunicationAsync.java index e0eab0092..98edbc61b 100644 --- a/driver/src/main/java/com/arangodb/async/internal/velocystream/VstCommunicationAsync.java +++ b/driver/src/main/java/com/arangodb/async/internal/velocystream/VstCommunicationAsync.java @@ -33,8 +33,8 @@ import com.arangodb.internal.velocystream.internal.Message; import com.arangodb.velocypack.exception.VPackException; import com.arangodb.velocypack.exception.VPackParserException; -import com.arangodb.Request; -import com.arangodb.Response; +import com.arangodb.internal.InternalRequest; +import com.arangodb.internal.InternalResponse; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -45,7 +45,7 @@ /** * @author Mark Vollmary */ -public class VstCommunicationAsync extends VstCommunication, VstConnectionAsync> { +public class VstCommunicationAsync extends VstCommunication, VstConnectionAsync> { private static final Logger LOGGER = LoggerFactory.getLogger(VstCommunicationAsync.class); @@ -57,19 +57,19 @@ private VstCommunicationAsync(final HostHandler hostHandler, final Integer timeo } @Override - protected CompletableFuture execute(final Request request, final VstConnectionAsync connection) { + protected CompletableFuture execute(final InternalRequest request, final VstConnectionAsync connection) { return execute(request, connection, 0); } @Override - protected CompletableFuture execute(final Request request, final VstConnectionAsync connection, - final int attemptCount) { - final CompletableFuture rfuture = new CompletableFuture<>(); + protected CompletableFuture execute(final InternalRequest request, final VstConnectionAsync connection, + final int attemptCount) { + final CompletableFuture rfuture = new CompletableFuture<>(); try { final Message message = createMessage(request); send(message, connection).whenComplete((m, ex) -> { if (m != null) { - final Response response; + final InternalResponse response; try { response = createResponse(m); } catch (final VPackParserException e) { @@ -127,14 +127,14 @@ private CompletableFuture send(final Message message, final VstConnecti @Override protected void authenticate(final VstConnectionAsync connection) { - Request authRequest; + InternalRequest authRequest; if (jwt != null) { authRequest = new JwtAuthenticationRequest(jwt, ENCRYPTION_JWT); } else { authRequest = new AuthenticationRequest(user, password != null ? password : "", ENCRYPTION_PLAIN); } - Response response; + InternalResponse response; try { response = execute(authRequest, connection).get(); } catch (final InterruptedException e) { diff --git a/driver/src/main/java/com/arangodb/internal/ArangoDBImpl.java b/driver/src/main/java/com/arangodb/internal/ArangoDBImpl.java index 04d631369..22a0e95a1 100644 --- a/driver/src/main/java/com/arangodb/internal/ArangoDBImpl.java +++ b/driver/src/main/java/com/arangodb/internal/ArangoDBImpl.java @@ -25,7 +25,6 @@ import com.arangodb.internal.http.HttpCommunication; import com.arangodb.internal.http.HttpProtocol; import com.arangodb.internal.net.CommunicationProtocol; -import com.arangodb.internal.net.HostHandle; import com.arangodb.internal.net.HostHandler; import com.arangodb.internal.net.HostResolver; import com.arangodb.internal.serde.InternalSerde; @@ -36,8 +35,6 @@ import com.arangodb.model.LogOptions; import com.arangodb.model.UserCreateOptions; import com.arangodb.model.UserUpdateOptions; -import com.arangodb.Request; -import com.arangodb.Response; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -214,13 +211,8 @@ public void grantDefaultCollectionAccess(final String user, final Permissions pe } @Override - public Response execute(final Request request) { - return executor.execute(request, response -> response); - } - - @Override - public Response execute(final Request request, final HostHandle hostHandle) { - return executor.execute(request, response -> response, hostHandle); + public Response execute(Request request, Class type) { + return executor.execute(executeRequest(request), responseDeserializer(type)); } @Override diff --git a/driver/src/main/java/com/arangodb/internal/ArangoDatabaseImpl.java b/driver/src/main/java/com/arangodb/internal/ArangoDatabaseImpl.java index c3ed750d9..e2c1eca2d 100644 --- a/driver/src/main/java/com/arangodb/internal/ArangoDatabaseImpl.java +++ b/driver/src/main/java/com/arangodb/internal/ArangoDatabaseImpl.java @@ -31,10 +31,8 @@ import com.arangodb.model.arangosearch.AnalyzerDeleteOptions; import com.arangodb.model.arangosearch.ArangoSearchCreateOptions; import com.arangodb.model.arangosearch.SearchAliasCreateOptions; -import com.arangodb.Request; import java.util.Collection; -import java.util.Collections; import java.util.Map; import static com.arangodb.internal.serde.SerdeUtils.constructListType; @@ -163,7 +161,7 @@ public ArangoCursor query( final String query, final Map bindVars, final AqlQueryOptions options, final Class type) { - final Request request = queryRequest(query, bindVars, options); + final InternalRequest request = queryRequest(query, bindVars, options); final HostHandle hostHandle = new HostHandle(); final InternalCursorEntity result = executor.execute(request, InternalCursorEntity.class, hostHandle); @@ -366,11 +364,6 @@ public void reloadRouting() { executor.execute(reloadRoutingRequest(), Void.class); } - @Override - public ArangoRoute route(final String... path) { - return new ArangoRouteImpl(this, String.join("/", path), Collections.emptyMap()); - } - @Override public Collection getViews() { return executor.execute(getViewsRequest(), getViewsResponseDeserializer()); diff --git a/driver/src/main/java/com/arangodb/internal/ArangoExecuteable.java b/driver/src/main/java/com/arangodb/internal/ArangoExecuteable.java index c1bb79eed..10fc7c87a 100644 --- a/driver/src/main/java/com/arangodb/internal/ArangoExecuteable.java +++ b/driver/src/main/java/com/arangodb/internal/ArangoExecuteable.java @@ -24,8 +24,6 @@ import com.arangodb.DbName; import com.arangodb.internal.serde.InternalSerde; import com.arangodb.internal.util.EncodeUtils; -import com.arangodb.Request; -import com.arangodb.RequestType; /** * @author Mark Vollmary @@ -69,8 +67,8 @@ public InternalSerde getSerde() { return serde; } - protected Request request(final DbName dbName, final RequestType requestType, final String... path) { - return new Request(dbName, requestType, createPath(path)); + protected InternalRequest request(final DbName dbName, final RequestType requestType, final String... path) { + return new InternalRequest(dbName, requestType, createPath(path)); } } diff --git a/driver/src/main/java/com/arangodb/internal/ArangoExecutor.java b/driver/src/main/java/com/arangodb/internal/ArangoExecutor.java index 359a0f952..ad9e0acda 100644 --- a/driver/src/main/java/com/arangodb/internal/ArangoExecutor.java +++ b/driver/src/main/java/com/arangodb/internal/ArangoExecutor.java @@ -22,8 +22,6 @@ import com.arangodb.QueueTimeMetrics; import com.arangodb.internal.serde.InternalSerde; -import com.arangodb.Request; -import com.arangodb.Response; import java.lang.reflect.Type; @@ -43,18 +41,18 @@ protected ArangoExecutor(final InternalSerde serde, final QueueTimeMetricsImpl q timeoutS = timeoutMs >= 1000 ? Integer.toString(timeoutMs / 1000) : null; } - protected T createResult(final Type type, final Response response) { + protected T createResult(final Type type, final InternalResponse response) { return serde.deserialize(response.getBody(), type); } - protected final void interceptResponse(Response response) { + protected final void interceptResponse(InternalResponse response) { String queueTime = response.getMeta("X-Arango-Queue-Time-Seconds"); if (queueTime != null) { qtMetrics.add(Double.parseDouble(queueTime)); } } - protected final Request interceptRequest(Request request) { + protected final InternalRequest interceptRequest(InternalRequest request) { request.putHeaderParam("x-arango-queue-time-seconds", timeoutS); return request; } @@ -64,6 +62,6 @@ public QueueTimeMetrics getQueueTimeMetrics() { } public interface ResponseDeserializer { - T deserialize(Response response); + T deserialize(InternalResponse response); } } diff --git a/driver/src/main/java/com/arangodb/internal/ArangoExecutorSync.java b/driver/src/main/java/com/arangodb/internal/ArangoExecutorSync.java index 8588c26b0..88b2f6f0f 100644 --- a/driver/src/main/java/com/arangodb/internal/ArangoExecutorSync.java +++ b/driver/src/main/java/com/arangodb/internal/ArangoExecutorSync.java @@ -25,8 +25,6 @@ import com.arangodb.internal.net.CommunicationProtocol; import com.arangodb.internal.net.HostHandle; import com.arangodb.internal.serde.InternalSerde; -import com.arangodb.Request; -import com.arangodb.Response; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -48,24 +46,24 @@ public ArangoExecutorSync(final CommunicationProtocol protocol, final InternalSe this.protocol = protocol; } - public T execute(final Request request, final Type type) { + public T execute(final InternalRequest request, final Type type) { return execute(request, type, null); } - public T execute(final Request request, final Type type, final HostHandle hostHandle) { + public T execute(final InternalRequest request, final Type type, final HostHandle hostHandle) { return execute(request, response -> createResult(type, response), hostHandle); } - public T execute(final Request request, final ResponseDeserializer responseDeserializer) { + public T execute(final InternalRequest request, final ResponseDeserializer responseDeserializer) { return execute(request, responseDeserializer, null); } public T execute( - final Request request, + final InternalRequest request, final ResponseDeserializer responseDeserializer, final HostHandle hostHandle) { - final Response response = protocol.execute(interceptRequest(request), hostHandle); + final InternalResponse response = protocol.execute(interceptRequest(request), hostHandle); interceptResponse(response); T deserialize = responseDeserializer.deserialize(response); diff --git a/driver/src/main/java/com/arangodb/internal/ArangoRouteImpl.java b/driver/src/main/java/com/arangodb/internal/ArangoRouteImpl.java deleted file mode 100644 index b73753ddc..000000000 --- a/driver/src/main/java/com/arangodb/internal/ArangoRouteImpl.java +++ /dev/null @@ -1,99 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2018 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.internal; - -import com.arangodb.ArangoRoute; -import com.arangodb.RequestType; -import com.arangodb.Response; - -import java.util.Map; - -/** - * @author Mark Vollmary - */ -public class ArangoRouteImpl extends InternalArangoRoute - implements ArangoRoute { - - protected ArangoRouteImpl(final ArangoDatabaseImpl db, final String path, final Map headerParam) { - super(db, path, headerParam); - } - - @Override - public ArangoRoute route(final String... path) { - final String[] fullPath = new String[path.length + 1]; - fullPath[0] = this.path; - System.arraycopy(path, 0, fullPath, 1, path.length); - return new ArangoRouteImpl(db, String.join("/", fullPath), headerParam); - } - - @Override - public ArangoRoute withHeader(final String key, final Object value) { - _withHeader(key, value); - return this; - } - - @Override - public ArangoRoute withQueryParam(final String key, final Object value) { - _withQueryParam(key, value); - return this; - } - - @Override - public ArangoRoute withBody(final Object body) { - _withBody(body); - return this; - } - - private Response request(final RequestType requestType) { - return executor.execute(createRequest(requestType), response -> response); - } - - @Override - public Response delete() { - return request(RequestType.DELETE); - } - - @Override - public Response get() { - return request(RequestType.GET); - } - - @Override - public Response head() { - return request(RequestType.HEAD); - } - - @Override - public Response patch() { - return request(RequestType.PATCH); - } - - @Override - public Response post() { - return request(RequestType.POST); - } - - @Override - public Response put() { - return request(RequestType.PUT); - } - -} diff --git a/driver/src/main/java/com/arangodb/internal/InternalArangoCollection.java b/driver/src/main/java/com/arangodb/internal/InternalArangoCollection.java index 2b8e625c0..90389ed3b 100644 --- a/driver/src/main/java/com/arangodb/internal/InternalArangoCollection.java +++ b/driver/src/main/java/com/arangodb/internal/InternalArangoCollection.java @@ -28,8 +28,6 @@ import com.arangodb.internal.util.RequestUtils; import com.arangodb.model.*; import com.arangodb.util.RawData; -import com.arangodb.Request; -import com.arangodb.RequestType; import com.fasterxml.jackson.databind.JsonNode; import java.lang.reflect.Type; @@ -80,27 +78,27 @@ public String name() { return name; } - protected Request insertDocumentRequest(final T value, final DocumentCreateOptions options) { - final Request request = createInsertDocumentRequest(options); + protected InternalRequest insertDocumentRequest(final T value, final DocumentCreateOptions options) { + final InternalRequest request = createInsertDocumentRequest(options); request.setBody(getSerde().serializeUserData(value)); return request; } - protected Request insertDocumentsRequest(final RawData values, final DocumentCreateOptions options) { - Request request = createInsertDocumentRequest(options); + protected InternalRequest insertDocumentsRequest(final RawData values, final DocumentCreateOptions options) { + InternalRequest request = createInsertDocumentRequest(options); request.setBody(getSerde().serialize(values)); return request; } - protected Request insertDocumentsRequest(final Collection values, final DocumentCreateOptions options) { - Request request = createInsertDocumentRequest(options); + protected InternalRequest insertDocumentsRequest(final Collection values, final DocumentCreateOptions options) { + InternalRequest request = createInsertDocumentRequest(options); request.setBody(getSerde().serializeCollectionUserData(values)); return request; } - private Request createInsertDocumentRequest(final DocumentCreateOptions options) { + private InternalRequest createInsertDocumentRequest(final DocumentCreateOptions options) { final DocumentCreateOptions params = (options != null ? options : new DocumentCreateOptions()); - final Request request = request(db.dbName(), RequestType.POST, PATH_API_DOCUMENT, name); + final InternalRequest request = request(db.dbName(), RequestType.POST, PATH_API_DOCUMENT, name); request.putQueryParam(ArangoRequestParam.WAIT_FOR_SYNC, params.getWaitForSync()); request.putQueryParam(RETURN_NEW, params.getReturnNew()); request.putQueryParam(RETURN_OLD, params.getReturnOld()); @@ -140,16 +138,16 @@ protected ResponseDeserializer>> }; } - protected Request importDocumentsRequest(final RawData values, final DocumentImportOptions options) { + protected InternalRequest importDocumentsRequest(final RawData values, final DocumentImportOptions options) { return importDocumentsRequest(options).putQueryParam("type", ImportType.auto).setBody(getSerde().serialize(values)); } - protected Request importDocumentsRequest(final Collection values, final DocumentImportOptions options) { + protected InternalRequest importDocumentsRequest(final Collection values, final DocumentImportOptions options) { return importDocumentsRequest(options).putQueryParam("type", ImportType.list) .setBody(getSerde().serializeCollectionUserData(values)); } - protected Request importDocumentsRequest(final DocumentImportOptions options) { + protected InternalRequest importDocumentsRequest(final DocumentImportOptions options) { final DocumentImportOptions params = options != null ? options : new DocumentImportOptions(); return request(db.dbName(), RequestType.POST, PATH_API_IMPORT).putQueryParam(COLLECTION, name) .putQueryParam(ArangoRequestParam.WAIT_FOR_SYNC, params.getWaitForSync()) @@ -158,8 +156,8 @@ protected Request importDocumentsRequest(final DocumentImportOptions options) { .putQueryParam("complete", params.getComplete()).putQueryParam("details", params.getDetails()); } - protected Request getDocumentRequest(final String key, final DocumentReadOptions options) { - final Request request = request(db.dbName(), RequestType.GET, PATH_API_DOCUMENT, + protected InternalRequest getDocumentRequest(final String key, final DocumentReadOptions options) { + final InternalRequest request = request(db.dbName(), RequestType.GET, PATH_API_DOCUMENT, DocumentUtil.createDocumentHandle(name, key)); final DocumentReadOptions params = (options != null ? options : new DocumentReadOptions()); request.putHeaderParam(ArangoRequestParam.IF_NONE_MATCH, params.getIfNoneMatch()); @@ -175,9 +173,9 @@ protected ResponseDeserializer getDocumentResponseDeserializer(final Clas return response -> getSerde().deserializeUserData(response.getBody(), type); } - protected Request getDocumentsRequest(final Collection keys, final DocumentReadOptions options) { + protected InternalRequest getDocumentsRequest(final Collection keys, final DocumentReadOptions options) { final DocumentReadOptions params = (options != null ? options : new DocumentReadOptions()); - final Request request = request(db.dbName(), RequestType.PUT, PATH_API_DOCUMENT, name) + final InternalRequest request = request(db.dbName(), RequestType.PUT, PATH_API_DOCUMENT, name) .putQueryParam("onlyget", true) .putHeaderParam(ArangoRequestParam.IF_NONE_MATCH, params.getIfNoneMatch()) .putHeaderParam(ArangoRequestParam.IF_MATCH, params.getIfMatch()).setBody(getSerde().serialize(keys)) @@ -217,28 +215,28 @@ protected ResponseDeserializer> getDocumentsResponseD }; } - protected Request replaceDocumentRequest( + protected InternalRequest replaceDocumentRequest( final String key, final T value, final DocumentReplaceOptions options) { - final Request request = createReplaceDocumentRequest(options, DocumentUtil.createDocumentHandle(name, key)); + final InternalRequest request = createReplaceDocumentRequest(options, DocumentUtil.createDocumentHandle(name, key)); request.setBody(getSerde().serializeUserData(value)); return request; } - protected Request replaceDocumentsRequest(final Collection values, final DocumentReplaceOptions options) { - final Request request = createReplaceDocumentRequest(options, name); + protected InternalRequest replaceDocumentsRequest(final Collection values, final DocumentReplaceOptions options) { + final InternalRequest request = createReplaceDocumentRequest(options, name); request.setBody(getSerde().serializeCollectionUserData(values)); return request; } - protected Request replaceDocumentsRequest(final RawData values, final DocumentReplaceOptions options) { - final Request request = createReplaceDocumentRequest(options, name); + protected InternalRequest replaceDocumentsRequest(final RawData values, final DocumentReplaceOptions options) { + final InternalRequest request = createReplaceDocumentRequest(options, name); request.setBody(getSerde().serialize(values)); return request; } - private Request createReplaceDocumentRequest(final DocumentReplaceOptions options, String path) { + private InternalRequest createReplaceDocumentRequest(final DocumentReplaceOptions options, String path) { final DocumentReplaceOptions params = (options != null ? options : new DocumentReplaceOptions()); - final Request request = request(db.dbName(), RequestType.PUT, PATH_API_DOCUMENT, path); + final InternalRequest request = request(db.dbName(), RequestType.PUT, PATH_API_DOCUMENT, path); request.putHeaderParam(ArangoRequestParam.IF_MATCH, params.getIfMatch()); request.putHeaderParam(TRANSACTION_ID, params.getStreamTransactionId()); request.putQueryParam(ArangoRequestParam.WAIT_FOR_SYNC, params.getWaitForSync()); @@ -277,27 +275,27 @@ protected ResponseDeserializer>> }; } - protected Request updateDocumentRequest(final String key, final T value, final DocumentUpdateOptions options) { - final Request request = createUpdateDocumentRequest(options, DocumentUtil.createDocumentHandle(name, key)); + protected InternalRequest updateDocumentRequest(final String key, final T value, final DocumentUpdateOptions options) { + final InternalRequest request = createUpdateDocumentRequest(options, DocumentUtil.createDocumentHandle(name, key)); request.setBody(getSerde().serializeUserData(value)); return request; } - protected Request updateDocumentsRequest(final Collection values, final DocumentUpdateOptions options) { - final Request request = createUpdateDocumentRequest(options, name); + protected InternalRequest updateDocumentsRequest(final Collection values, final DocumentUpdateOptions options) { + final InternalRequest request = createUpdateDocumentRequest(options, name); request.setBody(getSerde().serializeCollectionUserData(values)); return request; } - protected Request updateDocumentsRequest(final RawData values, final DocumentUpdateOptions options) { - final Request request = createUpdateDocumentRequest(options, name); + protected InternalRequest updateDocumentsRequest(final RawData values, final DocumentUpdateOptions options) { + final InternalRequest request = createUpdateDocumentRequest(options, name); request.setBody(getSerde().serialize(values)); return request; } - private Request createUpdateDocumentRequest(final DocumentUpdateOptions options, String path) { + private InternalRequest createUpdateDocumentRequest(final DocumentUpdateOptions options, String path) { final DocumentUpdateOptions params = (options != null ? options : new DocumentUpdateOptions()); - final Request request = request(db.dbName(), RequestType.PATCH, PATH_API_DOCUMENT, path); + final InternalRequest request = request(db.dbName(), RequestType.PATCH, PATH_API_DOCUMENT, path); request.putHeaderParam(ArangoRequestParam.IF_MATCH, params.getIfMatch()); request.putHeaderParam(TRANSACTION_ID, params.getStreamTransactionId()); request.putQueryParam(ArangoRequestParam.KEEP_NULL, params.getKeepNull()); @@ -338,25 +336,25 @@ protected ResponseDeserializer>> }; } - protected Request deleteDocumentRequest(final String key, final DocumentDeleteOptions options) { + protected InternalRequest deleteDocumentRequest(final String key, final DocumentDeleteOptions options) { return createDeleteDocumentRequest(options, DocumentUtil.createDocumentHandle(name, key)); } - protected Request deleteDocumentsRequest(final Collection docs, final DocumentDeleteOptions options) { - final Request request = createDeleteDocumentRequest(options, name); + protected InternalRequest deleteDocumentsRequest(final Collection docs, final DocumentDeleteOptions options) { + final InternalRequest request = createDeleteDocumentRequest(options, name); request.setBody(getSerde().serializeCollectionUserData(docs)); return request; } - protected Request deleteDocumentsRequest(final RawData docs, final DocumentDeleteOptions options) { - final Request request = createDeleteDocumentRequest(options, name); + protected InternalRequest deleteDocumentsRequest(final RawData docs, final DocumentDeleteOptions options) { + final InternalRequest request = createDeleteDocumentRequest(options, name); request.setBody(getSerde().serialize(docs)); return request; } - private Request createDeleteDocumentRequest(final DocumentDeleteOptions options, String path) { + private InternalRequest createDeleteDocumentRequest(final DocumentDeleteOptions options, String path) { final DocumentDeleteOptions params = (options != null ? options : new DocumentDeleteOptions()); - final Request request = request(db.dbName(), RequestType.DELETE, PATH_API_DOCUMENT, path); + final InternalRequest request = request(db.dbName(), RequestType.DELETE, PATH_API_DOCUMENT, path); request.putHeaderParam(ArangoRequestParam.IF_MATCH, params.getIfMatch()); request.putHeaderParam(TRANSACTION_ID, params.getStreamTransactionId()); request.putQueryParam(ArangoRequestParam.WAIT_FOR_SYNC, params.getWaitForSync()); @@ -393,8 +391,8 @@ protected ResponseDeserializer>> }; } - protected Request documentExistsRequest(final String key, final DocumentExistsOptions options) { - final Request request = request(db.dbName(), RequestType.HEAD, PATH_API_DOCUMENT, + protected InternalRequest documentExistsRequest(final String key, final DocumentExistsOptions options) { + final InternalRequest request = request(db.dbName(), RequestType.HEAD, PATH_API_DOCUMENT, DocumentUtil.createDocumentHandle(name, key)); final DocumentExistsOptions params = (options != null ? options : new DocumentExistsOptions()); request.putHeaderParam(TRANSACTION_ID, params.getStreamTransactionId()); @@ -403,11 +401,11 @@ protected Request documentExistsRequest(final String key, final DocumentExistsOp return request; } - protected Request getIndexRequest(final String id) { + protected InternalRequest getIndexRequest(final String id) { return request(db.dbName(), RequestType.GET, PATH_API_INDEX, createIndexId(id)); } - protected Request deleteIndexRequest(final String id) { + protected InternalRequest deleteIndexRequest(final String id) { return request(db.dbName(), RequestType.DELETE, PATH_API_INDEX, createIndexId(id)); } @@ -428,8 +426,8 @@ private String createIndexId(final String id) { } @Deprecated - protected Request createHashIndexRequest(final Iterable fields, final HashIndexOptions options) { - final Request request = request(db.dbName(), RequestType.POST, PATH_API_INDEX); + protected InternalRequest createHashIndexRequest(final Iterable fields, final HashIndexOptions options) { + final InternalRequest request = request(db.dbName(), RequestType.POST, PATH_API_INDEX); request.putQueryParam(COLLECTION, name); request.setBody( getSerde().serialize(OptionsBuilder.build(options != null ? options : new HashIndexOptions(), fields))); @@ -437,8 +435,8 @@ protected Request createHashIndexRequest(final Iterable fields, final Ha } @Deprecated - protected Request createSkiplistIndexRequest(final Iterable fields, final SkiplistIndexOptions options) { - final Request request = request(db.dbName(), RequestType.POST, PATH_API_INDEX); + protected InternalRequest createSkiplistIndexRequest(final Iterable fields, final SkiplistIndexOptions options) { + final InternalRequest request = request(db.dbName(), RequestType.POST, PATH_API_INDEX); request.putQueryParam(COLLECTION, name); request.setBody( getSerde().serialize(OptionsBuilder.build(options != null ? options : new SkiplistIndexOptions(), @@ -446,24 +444,24 @@ protected Request createSkiplistIndexRequest(final Iterable fields, fina return request; } - protected Request createPersistentIndexRequest( + protected InternalRequest createPersistentIndexRequest( final Iterable fields, final PersistentIndexOptions options) { - final Request request = request(db.dbName(), RequestType.POST, PATH_API_INDEX); + final InternalRequest request = request(db.dbName(), RequestType.POST, PATH_API_INDEX); request.putQueryParam(COLLECTION, name); request.setBody(getSerde().serialize( OptionsBuilder.build(options != null ? options : new PersistentIndexOptions(), fields))); return request; } - protected Request createInvertedIndexRequest(final InvertedIndexOptions options) { - final Request request = request(db.dbName(), RequestType.POST, PATH_API_INDEX); + protected InternalRequest createInvertedIndexRequest(final InvertedIndexOptions options) { + final InternalRequest request = request(db.dbName(), RequestType.POST, PATH_API_INDEX); request.putQueryParam(COLLECTION, name); request.setBody(getSerde().serialize(options)); return request; } - protected Request createGeoIndexRequest(final Iterable fields, final GeoIndexOptions options) { - final Request request = request(db.dbName(), RequestType.POST, PATH_API_INDEX); + protected InternalRequest createGeoIndexRequest(final Iterable fields, final GeoIndexOptions options) { + final InternalRequest request = request(db.dbName(), RequestType.POST, PATH_API_INDEX); request.putQueryParam(COLLECTION, name); request.setBody( getSerde().serialize(OptionsBuilder.build(options != null ? options : new GeoIndexOptions(), fields))); @@ -471,8 +469,8 @@ protected Request createGeoIndexRequest(final Iterable fields, final Geo } @Deprecated - protected Request createFulltextIndexRequest(final Iterable fields, final FulltextIndexOptions options) { - final Request request = request(db.dbName(), RequestType.POST, PATH_API_INDEX); + protected InternalRequest createFulltextIndexRequest(final Iterable fields, final FulltextIndexOptions options) { + final InternalRequest request = request(db.dbName(), RequestType.POST, PATH_API_INDEX); request.putQueryParam(COLLECTION, name); request.setBody( getSerde().serialize(OptionsBuilder.build(options != null ? options : new FulltextIndexOptions(), @@ -480,25 +478,25 @@ protected Request createFulltextIndexRequest(final Iterable fields, fina return request; } - protected Request createTtlIndexRequest(final Iterable fields, final TtlIndexOptions options) { - final Request request = request(db.dbName(), RequestType.POST, PATH_API_INDEX); + protected InternalRequest createTtlIndexRequest(final Iterable fields, final TtlIndexOptions options) { + final InternalRequest request = request(db.dbName(), RequestType.POST, PATH_API_INDEX); request.putQueryParam(COLLECTION, name); request.setBody( getSerde().serialize(OptionsBuilder.build(options != null ? options : new TtlIndexOptions(), fields))); return request; } - protected Request createZKDIndexRequest( + protected InternalRequest createZKDIndexRequest( final Iterable fields, final ZKDIndexOptions options) { - final Request request = request(db.dbName(), RequestType.POST, PATH_API_INDEX); + final InternalRequest request = request(db.dbName(), RequestType.POST, PATH_API_INDEX); request.putQueryParam(COLLECTION, name); request.setBody(getSerde().serialize(OptionsBuilder.build(options != null ? options : new ZKDIndexOptions().fieldValueTypes(ZKDIndexOptions.FieldValueTypes.DOUBLE), fields))); return request; } - protected Request getIndexesRequest() { - final Request request = request(db.dbName(), RequestType.GET, PATH_API_INDEX); + protected InternalRequest getIndexesRequest() { + final InternalRequest request = request(db.dbName(), RequestType.GET, PATH_API_INDEX); request.putQueryParam(COLLECTION, name); return request; } @@ -527,66 +525,66 @@ protected ResponseDeserializer> getInvertedIndex }; } - protected Request truncateRequest(final CollectionTruncateOptions options) { - final Request request = request(db.dbName(), RequestType.PUT, PATH_API_COLLECTION, name, "truncate"); + protected InternalRequest truncateRequest(final CollectionTruncateOptions options) { + final InternalRequest request = request(db.dbName(), RequestType.PUT, PATH_API_COLLECTION, name, "truncate"); final CollectionTruncateOptions params = (options != null ? options : new CollectionTruncateOptions()); request.putHeaderParam(TRANSACTION_ID, params.getStreamTransactionId()); return request; } - protected Request countRequest(final CollectionCountOptions options) { - final Request request = request(db.dbName(), RequestType.GET, PATH_API_COLLECTION, name, "count"); + protected InternalRequest countRequest(final CollectionCountOptions options) { + final InternalRequest request = request(db.dbName(), RequestType.GET, PATH_API_COLLECTION, name, "count"); final CollectionCountOptions params = (options != null ? options : new CollectionCountOptions()); request.putHeaderParam(TRANSACTION_ID, params.getStreamTransactionId()); return request; } - protected Request dropRequest(final Boolean isSystem) { + protected InternalRequest dropRequest(final Boolean isSystem) { return request(db.dbName(), RequestType.DELETE, PATH_API_COLLECTION, name).putQueryParam("isSystem", isSystem); } - protected Request getInfoRequest() { + protected InternalRequest getInfoRequest() { return request(db.dbName(), RequestType.GET, PATH_API_COLLECTION, name); } - protected Request getPropertiesRequest() { + protected InternalRequest getPropertiesRequest() { return request(db.dbName(), RequestType.GET, PATH_API_COLLECTION, name, "properties"); } - protected Request changePropertiesRequest(final CollectionPropertiesOptions options) { - final Request request = request(db.dbName(), RequestType.PUT, PATH_API_COLLECTION, name, "properties"); + protected InternalRequest changePropertiesRequest(final CollectionPropertiesOptions options) { + final InternalRequest request = request(db.dbName(), RequestType.PUT, PATH_API_COLLECTION, name, "properties"); request.setBody(getSerde().serialize(options != null ? options : new CollectionPropertiesOptions())); return request; } - protected Request renameRequest(final String newName) { - final Request request = request(db.dbName(), RequestType.PUT, PATH_API_COLLECTION, name, "rename"); + protected InternalRequest renameRequest(final String newName) { + final InternalRequest request = request(db.dbName(), RequestType.PUT, PATH_API_COLLECTION, name, "rename"); request.setBody(getSerde().serialize(OptionsBuilder.build(new CollectionRenameOptions(), newName))); return request; } - protected Request responsibleShardRequest(final T value) { - final Request request = request(db.dbName(), RequestType.PUT, PATH_API_COLLECTION, name, "responsibleShard"); + protected InternalRequest responsibleShardRequest(final T value) { + final InternalRequest request = request(db.dbName(), RequestType.PUT, PATH_API_COLLECTION, name, "responsibleShard"); request.setBody(getSerde().serializeUserData(value)); return request; } - protected Request getRevisionRequest() { + protected InternalRequest getRevisionRequest() { return request(db.dbName(), RequestType.GET, PATH_API_COLLECTION, name, "revision"); } - protected Request grantAccessRequest(final String user, final Permissions permissions) { + protected InternalRequest grantAccessRequest(final String user, final Permissions permissions) { return request(DbName.SYSTEM, RequestType.PUT, PATH_API_USER, user, ArangoRequestParam.DATABASE, db.dbName().get(), name).setBody(getSerde().serialize(OptionsBuilder.build(new UserAccessOptions(), permissions))); } - protected Request resetAccessRequest(final String user) { + protected InternalRequest resetAccessRequest(final String user) { return request(DbName.SYSTEM, RequestType.DELETE, PATH_API_USER, user, ArangoRequestParam.DATABASE, db.dbName().get(), name); } - protected Request getPermissionsRequest(final String user) { + protected InternalRequest getPermissionsRequest(final String user) { return request(DbName.SYSTEM, RequestType.GET, PATH_API_USER, user, ArangoRequestParam.DATABASE, db.dbName().get(), name); } diff --git a/driver/src/main/java/com/arangodb/internal/InternalArangoDB.java b/driver/src/main/java/com/arangodb/internal/InternalArangoDB.java index 25376bade..1243fd53e 100644 --- a/driver/src/main/java/com/arangodb/internal/InternalArangoDB.java +++ b/driver/src/main/java/com/arangodb/internal/InternalArangoDB.java @@ -21,6 +21,8 @@ package com.arangodb.internal; import com.arangodb.DbName; +import com.arangodb.Request; +import com.arangodb.Response; import com.arangodb.entity.LogLevelEntity; import com.arangodb.entity.Permissions; import com.arangodb.entity.ServerRole; @@ -28,8 +30,6 @@ import com.arangodb.internal.ArangoExecutor.ResponseDeserializer; import com.arangodb.internal.serde.InternalSerde; import com.arangodb.model.*; -import com.arangodb.Request; -import com.arangodb.RequestType; import java.util.ArrayList; import java.util.Collection; @@ -53,11 +53,11 @@ protected InternalArangoDB(final E executor, final InternalSerde util) { super(executor, util); } - protected Request getRoleRequest() { + protected InternalRequest getRoleRequest() { return request(DbName.SYSTEM, RequestType.GET, PATH_API_ROLE); } - protected Request getServerIdRequest() { + protected InternalRequest getServerIdRequest() { return request(DbName.SYSTEM, RequestType.GET, PATH_API_SERVER_ID); } @@ -69,8 +69,8 @@ protected ResponseDeserializer getServerIdResponseDeserializer() { return response -> getSerde().deserialize(response.getBody(), "/id", String.class); } - protected Request createDatabaseRequest(final DBCreateOptions options) { - final Request request = request(DbName.SYSTEM, RequestType.POST, + protected InternalRequest createDatabaseRequest(final DBCreateOptions options) { + final InternalRequest request = request(DbName.SYSTEM, RequestType.POST, InternalArangoDatabase.PATH_API_DATABASE); request.setBody(getSerde().serialize(options)); return request; @@ -81,7 +81,7 @@ protected ResponseDeserializer createDatabaseResponseDeserializer() { Boolean.class); } - protected Request getDatabasesRequest(final DbName dbName) { + protected InternalRequest getDatabasesRequest(final DbName dbName) { return request(dbName, RequestType.GET, InternalArangoDatabase.PATH_API_DATABASE); } @@ -90,7 +90,7 @@ protected ResponseDeserializer> getDatabaseResponseDeserializ constructListType(String.class)); } - protected Request getAccessibleDatabasesForRequest(final DbName dbName, final String user) { + protected InternalRequest getAccessibleDatabasesForRequest(final DbName dbName, final String user) { return request(dbName, RequestType.GET, PATH_API_USER, user, ArangoRequestParam.DATABASE); } @@ -106,12 +106,12 @@ protected ResponseDeserializer> getAccessibleDatabasesForResp }; } - protected Request createUserRequest( + protected InternalRequest createUserRequest( final DbName dbName, final String user, final String passwd, final UserCreateOptions options) { - final Request request; + final InternalRequest request; request = request(dbName, RequestType.POST, PATH_API_USER); request.setBody( getSerde().serialize(OptionsBuilder.build(options != null ? options : new UserCreateOptions(), user, @@ -119,15 +119,15 @@ protected Request createUserRequest( return request; } - protected Request deleteUserRequest(final DbName dbName, final String user) { + protected InternalRequest deleteUserRequest(final DbName dbName, final String user) { return request(dbName, RequestType.DELETE, PATH_API_USER, user); } - protected Request getUsersRequest(final DbName dbName) { + protected InternalRequest getUsersRequest(final DbName dbName) { return request(dbName, RequestType.GET, PATH_API_USER); } - protected Request getUserRequest(final DbName dbName, final String user) { + protected InternalRequest getUserRequest(final DbName dbName, final String user) { return request(dbName, RequestType.GET, PATH_API_USER, user); } @@ -136,31 +136,47 @@ protected ResponseDeserializer> getUsersResponseDeseriali constructListType(UserEntity.class)); } - protected Request updateUserRequest(final DbName dbName, final String user, final UserUpdateOptions options) { - final Request request; + protected InternalRequest updateUserRequest(final DbName dbName, final String user, final UserUpdateOptions options) { + final InternalRequest request; request = request(dbName, RequestType.PATCH, PATH_API_USER, user); request.setBody(getSerde().serialize(options != null ? options : new UserUpdateOptions())); return request; } - protected Request replaceUserRequest(final DbName dbName, final String user, final UserUpdateOptions options) { - final Request request; + protected InternalRequest replaceUserRequest(final DbName dbName, final String user, final UserUpdateOptions options) { + final InternalRequest request; request = request(dbName, RequestType.PUT, PATH_API_USER, user); request.setBody(getSerde().serialize(options != null ? options : new UserUpdateOptions())); return request; } - protected Request updateUserDefaultDatabaseAccessRequest(final String user, final Permissions permissions) { + protected InternalRequest updateUserDefaultDatabaseAccessRequest(final String user, final Permissions permissions) { return request(DbName.SYSTEM, RequestType.PUT, PATH_API_USER, user, ArangoRequestParam.DATABASE, "*").setBody(getSerde().serialize(OptionsBuilder.build(new UserAccessOptions(), permissions))); } - protected Request updateUserDefaultCollectionAccessRequest(final String user, final Permissions permissions) { + protected InternalRequest updateUserDefaultCollectionAccessRequest(final String user, final Permissions permissions) { return request(DbName.SYSTEM, RequestType.PUT, PATH_API_USER, user, ArangoRequestParam.DATABASE, "*", "*").setBody(getSerde().serialize(OptionsBuilder.build(new UserAccessOptions(), permissions))); } - protected Request getLogEntriesRequest(final LogOptions options) { + protected InternalRequest executeRequest(final Request request) { + InternalRequest ireq = new InternalRequest(request.getDb(), RequestType.from(request.getMethod()), request.getPath()); + ireq.putHeaderParams(request.getHeaders()); + ireq.putQueryParams(request.getQueryParams()); + ireq.setBody(serde.serializeUserData(request.getBody())); + return ireq; + } + + protected ResponseDeserializer> responseDeserializer(Class type) { + return response -> new Response<>( + response.getResponseCode(), + response.getMeta(), + serde.deserializeUserData(response.getBody(), type) + ); + } + + protected InternalRequest getLogEntriesRequest(final LogOptions options) { final LogOptions params = options != null ? options : new LogOptions(); return request(DbName.SYSTEM, RequestType.GET, PATH_API_ADMIN_LOG_ENTRIES) .putQueryParam(LogOptions.PROPERTY_UPTO, params.getUpto()) @@ -172,16 +188,16 @@ protected Request getLogEntriesRequest(final LogOptions options) { .putQueryParam(LogOptions.PROPERTY_SORT, params.getSort()); } - protected Request getLogLevelRequest() { + protected InternalRequest getLogLevelRequest() { return request(DbName.SYSTEM, RequestType.GET, PATH_API_ADMIN_LOG_LEVEL); } - protected Request setLogLevelRequest(final LogLevelEntity entity) { + protected InternalRequest setLogLevelRequest(final LogLevelEntity entity) { return request(DbName.SYSTEM, RequestType.PUT, PATH_API_ADMIN_LOG_LEVEL) .setBody(getSerde().serialize(entity)); } - protected Request getQueryOptimizerRulesRequest() { + protected InternalRequest getQueryOptimizerRulesRequest() { return request(DbName.SYSTEM, RequestType.GET, PATH_API_QUERY_RULES); } diff --git a/driver/src/main/java/com/arangodb/internal/InternalArangoDatabase.java b/driver/src/main/java/com/arangodb/internal/InternalArangoDatabase.java index 8841570ef..fcde6ad9b 100644 --- a/driver/src/main/java/com/arangodb/internal/InternalArangoDatabase.java +++ b/driver/src/main/java/com/arangodb/internal/InternalArangoDatabase.java @@ -27,8 +27,6 @@ import com.arangodb.internal.util.RequestUtils; import com.arangodb.model.*; import com.arangodb.model.arangosearch.*; -import com.arangodb.Request; -import com.arangodb.RequestType; import java.util.Collection; import java.util.Map; @@ -81,19 +79,19 @@ protected ResponseDeserializer> getDatabaseResponseDeserializ return arango.getDatabaseResponseDeserializer(); } - protected Request getAccessibleDatabasesRequest() { + protected InternalRequest getAccessibleDatabasesRequest() { return request(dbName, RequestType.GET, PATH_API_DATABASE, "user"); } - protected Request getVersionRequest() { + protected InternalRequest getVersionRequest() { return request(dbName, RequestType.GET, PATH_API_VERSION); } - protected Request getEngineRequest() { + protected InternalRequest getEngineRequest() { return request(dbName, RequestType.GET, PATH_API_ENGINE); } - protected Request createCollectionRequest(final String name, final CollectionCreateOptions options) { + protected InternalRequest createCollectionRequest(final String name, final CollectionCreateOptions options) { byte[] body = getSerde().serialize(OptionsBuilder.build(options != null ? options : new CollectionCreateOptions(), name)); @@ -101,8 +99,8 @@ protected Request createCollectionRequest(final String name, final CollectionCre return request(dbName, RequestType.POST, InternalArangoCollection.PATH_API_COLLECTION).setBody(body); } - protected Request getCollectionsRequest(final CollectionsReadOptions options) { - final Request request; + protected InternalRequest getCollectionsRequest(final CollectionsReadOptions options) { + final InternalRequest request; request = request(dbName, RequestType.GET, InternalArangoCollection.PATH_API_COLLECTION); final CollectionsReadOptions params = (options != null ? options : new CollectionsReadOptions()); request.putQueryParam("excludeSystem", params.getExcludeSystem()); @@ -114,7 +112,7 @@ protected ResponseDeserializer> getCollectionsRespo constructListType(CollectionEntity.class)); } - protected Request dropRequest() { + protected InternalRequest dropRequest() { return request(DbName.SYSTEM, RequestType.DELETE, PATH_API_DATABASE, dbName.get()); } @@ -123,22 +121,22 @@ protected ResponseDeserializer createDropResponseDeserializer() { Boolean.class); } - protected Request grantAccessRequest(final String user, final Permissions permissions) { + protected InternalRequest grantAccessRequest(final String user, final Permissions permissions) { return request(DbName.SYSTEM, RequestType.PUT, PATH_API_USER, user, ArangoRequestParam.DATABASE, dbName.get()).setBody(getSerde().serialize(OptionsBuilder.build(new UserAccessOptions(), permissions))); } - protected Request resetAccessRequest(final String user) { + protected InternalRequest resetAccessRequest(final String user) { return request(DbName.SYSTEM, RequestType.DELETE, PATH_API_USER, user, ArangoRequestParam.DATABASE, dbName.get()); } - protected Request updateUserDefaultCollectionAccessRequest(final String user, final Permissions permissions) { + protected InternalRequest updateUserDefaultCollectionAccessRequest(final String user, final Permissions permissions) { return request(DbName.SYSTEM, RequestType.PUT, PATH_API_USER, user, ArangoRequestParam.DATABASE, dbName.get() , "*").setBody(getSerde().serialize(OptionsBuilder.build(new UserAccessOptions(), permissions))); } - protected Request getPermissionsRequest(final String user) { + protected InternalRequest getPermissionsRequest(final String user) { return request(DbName.SYSTEM, RequestType.GET, PATH_API_USER, user, ArangoRequestParam.DATABASE, dbName.get()); } @@ -147,10 +145,10 @@ protected ResponseDeserializer getPermissionsResponseDeserialzer() Permissions.class); } - protected Request queryRequest(final String query, final Map bindVars, - final AqlQueryOptions options) { + protected InternalRequest queryRequest(final String query, final Map bindVars, + final AqlQueryOptions options) { final AqlQueryOptions opt = options != null ? options : new AqlQueryOptions(); - final Request request = request(dbName, RequestType.POST, PATH_API_CURSOR) + final InternalRequest request = request(dbName, RequestType.POST, PATH_API_CURSOR) .setBody(getSerde().serialize(OptionsBuilder.build(opt, query, bindVars))); if (Boolean.TRUE.equals(opt.getAllowDirtyRead())) { RequestUtils.allowDirtyRead(request); @@ -159,9 +157,9 @@ protected Request queryRequest(final String query, final Map bin return request; } - protected Request queryNextRequest(final String id, final AqlQueryOptions options, Map meta) { + protected InternalRequest queryNextRequest(final String id, final AqlQueryOptions options, Map meta) { - final Request request = request(dbName, RequestType.POST, PATH_API_CURSOR, id); + final InternalRequest request = request(dbName, RequestType.POST, PATH_API_CURSOR, id); request.putHeaderParams(meta); final AqlQueryOptions opt = options != null ? options : new AqlQueryOptions(); @@ -173,9 +171,9 @@ protected Request queryNextRequest(final String id, final AqlQueryOptions option return request; } - protected Request queryCloseRequest(final String id, final AqlQueryOptions options, Map meta) { + protected InternalRequest queryCloseRequest(final String id, final AqlQueryOptions options, Map meta) { - final Request request = request(dbName, RequestType.DELETE, PATH_API_CURSOR, id); + final InternalRequest request = request(dbName, RequestType.DELETE, PATH_API_CURSOR, id); request.putHeaderParams(meta); final AqlQueryOptions opt = options != null ? options : new AqlQueryOptions(); @@ -187,60 +185,60 @@ protected Request queryCloseRequest(final String id, final AqlQueryOptions optio return request; } - protected Request explainQueryRequest(final String query, final Map bindVars, - final AqlQueryExplainOptions options) { + protected InternalRequest explainQueryRequest(final String query, final Map bindVars, + final AqlQueryExplainOptions options) { final AqlQueryExplainOptions opt = options != null ? options : new AqlQueryExplainOptions(); return request(dbName, RequestType.POST, PATH_API_EXPLAIN) .setBody(getSerde().serialize(OptionsBuilder.build(opt, query, bindVars))); } - protected Request parseQueryRequest(final String query) { + protected InternalRequest parseQueryRequest(final String query) { return request(dbName, RequestType.POST, PATH_API_QUERY).setBody(getSerde().serialize(OptionsBuilder.build(new AqlQueryParseOptions(), query))); } - protected Request clearQueryCacheRequest() { + protected InternalRequest clearQueryCacheRequest() { return request(dbName, RequestType.DELETE, PATH_API_QUERY_CACHE); } - protected Request getQueryCachePropertiesRequest() { + protected InternalRequest getQueryCachePropertiesRequest() { return request(dbName, RequestType.GET, PATH_API_QUERY_CACHE_PROPERTIES); } - protected Request setQueryCachePropertiesRequest(final QueryCachePropertiesEntity properties) { + protected InternalRequest setQueryCachePropertiesRequest(final QueryCachePropertiesEntity properties) { return request(dbName, RequestType.PUT, PATH_API_QUERY_CACHE_PROPERTIES).setBody(getSerde().serialize(properties)); } - protected Request getQueryTrackingPropertiesRequest() { + protected InternalRequest getQueryTrackingPropertiesRequest() { return request(dbName, RequestType.GET, PATH_API_QUERY_PROPERTIES); } - protected Request setQueryTrackingPropertiesRequest(final QueryTrackingPropertiesEntity properties) { + protected InternalRequest setQueryTrackingPropertiesRequest(final QueryTrackingPropertiesEntity properties) { return request(dbName, RequestType.PUT, PATH_API_QUERY_PROPERTIES).setBody(getSerde().serialize(properties)); } - protected Request getCurrentlyRunningQueriesRequest() { + protected InternalRequest getCurrentlyRunningQueriesRequest() { return request(dbName, RequestType.GET, PATH_API_QUERY_CURRENT); } - protected Request getSlowQueriesRequest() { + protected InternalRequest getSlowQueriesRequest() { return request(dbName, RequestType.GET, PATH_API_QUERY_SLOW); } - protected Request clearSlowQueriesRequest() { + protected InternalRequest clearSlowQueriesRequest() { return request(dbName, RequestType.DELETE, PATH_API_QUERY_SLOW); } - protected Request killQueryRequest(final String id) { + protected InternalRequest killQueryRequest(final String id) { return request(dbName, RequestType.DELETE, PATH_API_QUERY, id); } - protected Request createAqlFunctionRequest(final String name, final String code, - final AqlFunctionCreateOptions options) { + protected InternalRequest createAqlFunctionRequest(final String name, final String code, + final AqlFunctionCreateOptions options) { return request(dbName, RequestType.POST, PATH_API_AQLFUNCTION).setBody(getSerde().serialize(OptionsBuilder.build(options != null ? options : new AqlFunctionCreateOptions(), name, code))); } - protected Request deleteAqlFunctionRequest(final String name, final AqlFunctionDeleteOptions options) { - final Request request = request(dbName, RequestType.DELETE, PATH_API_AQLFUNCTION, name); + protected InternalRequest deleteAqlFunctionRequest(final String name, final AqlFunctionDeleteOptions options) { + final InternalRequest request = request(dbName, RequestType.DELETE, PATH_API_AQLFUNCTION, name); final AqlFunctionDeleteOptions params = options != null ? options : new AqlFunctionDeleteOptions(); request.putQueryParam("group", params.getGroup()); return request; @@ -250,8 +248,8 @@ protected ResponseDeserializer deleteAqlFunctionResponseDeserializer() return response -> getSerde().deserialize(response.getBody(), "/deletedCount", Integer.class); } - protected Request getAqlFunctionsRequest(final AqlFunctionGetOptions options) { - final Request request = request(dbName, RequestType.GET, PATH_API_AQLFUNCTION); + protected InternalRequest getAqlFunctionsRequest(final AqlFunctionGetOptions options) { + final InternalRequest request = request(dbName, RequestType.GET, PATH_API_AQLFUNCTION); final AqlFunctionGetOptions params = options != null ? options : new AqlFunctionGetOptions(); request.putQueryParam("namespace", params.getNamespace()); return request; @@ -262,8 +260,8 @@ protected ResponseDeserializer> getAqlFunctionsRes constructListType(AqlFunctionEntity.class)); } - protected Request createGraphRequest(final String name, final Collection edgeDefinitions, - final GraphCreateOptions options) { + protected InternalRequest createGraphRequest(final String name, final Collection edgeDefinitions, + final GraphCreateOptions options) { return request(dbName, RequestType.POST, InternalArangoGraph.PATH_API_GHARIAL).setBody(getSerde().serialize(OptionsBuilder.build(options != null ? options : new GraphCreateOptions(), name, edgeDefinitions))); } @@ -271,7 +269,7 @@ protected ResponseDeserializer createGraphResponseDeserializer() { return response -> getSerde().deserialize(response.getBody(), "/graph", GraphEntity.class); } - protected Request getGraphsRequest() { + protected InternalRequest getGraphsRequest() { return request(dbName, RequestType.GET, InternalArangoGraph.PATH_API_GHARIAL); } @@ -280,7 +278,7 @@ protected ResponseDeserializer> getGraphsResponseDeseria constructListType(GraphEntity.class)); } - protected Request transactionRequest(final String action, final TransactionOptions options) { + protected InternalRequest transactionRequest(final String action, final TransactionOptions options) { return request(dbName, RequestType.POST, PATH_API_TRANSACTION).setBody(getSerde().serialize(OptionsBuilder.build(options != null ? options : new TransactionOptions(), action))); } @@ -291,24 +289,24 @@ protected ResponseDeserializer transactionResponseDeserializer(final Clas }; } - protected Request beginStreamTransactionRequest(final StreamTransactionOptions options) { + protected InternalRequest beginStreamTransactionRequest(final StreamTransactionOptions options) { StreamTransactionOptions opts = options != null ? options : new StreamTransactionOptions(); - Request r = request(dbName, RequestType.POST, PATH_API_BEGIN_STREAM_TRANSACTION).setBody(getSerde().serialize(opts)); + InternalRequest r = request(dbName, RequestType.POST, PATH_API_BEGIN_STREAM_TRANSACTION).setBody(getSerde().serialize(opts)); if(Boolean.TRUE.equals(opts.getAllowDirtyRead())) { RequestUtils.allowDirtyRead(r); } return r; } - protected Request abortStreamTransactionRequest(String id) { + protected InternalRequest abortStreamTransactionRequest(String id) { return request(dbName, RequestType.DELETE, PATH_API_TRANSACTION, id); } - protected Request getStreamTransactionsRequest() { + protected InternalRequest getStreamTransactionsRequest() { return request(dbName, RequestType.GET, PATH_API_TRANSACTION); } - protected Request getStreamTransactionRequest(String id) { + protected InternalRequest getStreamTransactionRequest(String id) { return request(dbName, RequestType.GET, PATH_API_TRANSACTION, id); } @@ -317,7 +315,7 @@ protected ResponseDeserializer> transactionsRespon constructListType(TransactionEntity.class)); } - protected Request commitStreamTransactionRequest(String id) { + protected InternalRequest commitStreamTransactionRequest(String id) { return request(dbName, RequestType.PUT, PATH_API_TRANSACTION, id); } @@ -326,7 +324,7 @@ protected ResponseDeserializer streamTransactionRespons StreamTransactionEntity.class); } - protected Request getInfoRequest() { + protected InternalRequest getInfoRequest() { return request(dbName, RequestType.GET, PATH_API_DATABASE, "current"); } @@ -335,11 +333,11 @@ protected ResponseDeserializer getInfoResponseDeserializer() { DatabaseEntity.class); } - protected Request reloadRoutingRequest() { + protected InternalRequest reloadRoutingRequest() { return request(dbName, RequestType.POST, PATH_API_ADMIN_ROUTING_RELOAD); } - protected Request getViewsRequest() { + protected InternalRequest getViewsRequest() { return request(dbName, RequestType.GET, InternalArangoView.PATH_API_VIEW); } @@ -348,24 +346,24 @@ protected ResponseDeserializer> getViewsResponseDeseriali constructListType(ViewEntity.class)); } - protected Request createViewRequest(final String name, final ViewType type) { + protected InternalRequest createViewRequest(final String name, final ViewType type) { return request(dbName, RequestType.POST, InternalArangoView.PATH_API_VIEW).setBody(getSerde().serialize(OptionsBuilder.build(new ViewCreateOptions(), name, type))); } - protected Request createArangoSearchRequest(final String name, final ArangoSearchCreateOptions options) { + protected InternalRequest createArangoSearchRequest(final String name, final ArangoSearchCreateOptions options) { return request(dbName, RequestType.POST, InternalArangoView.PATH_API_VIEW).setBody(getSerde().serialize(ArangoSearchOptionsBuilder.build(options != null ? options : new ArangoSearchCreateOptions(), name))); } - protected Request createSearchAliasRequest(final String name, final SearchAliasCreateOptions options) { + protected InternalRequest createSearchAliasRequest(final String name, final SearchAliasCreateOptions options) { return request(dbName, RequestType.POST, InternalArangoView.PATH_API_VIEW).setBody(getSerde().serialize( SearchAliasOptionsBuilder.build(options != null ? options : new SearchAliasCreateOptions(), name))); } - protected Request getAnalyzerRequest(final String name) { + protected InternalRequest getAnalyzerRequest(final String name) { return request(dbName, RequestType.GET, InternalArangoView.PATH_API_ANALYZER, name); } - protected Request getAnalyzersRequest() { + protected InternalRequest getAnalyzersRequest() { return request(dbName, RequestType.GET, InternalArangoView.PATH_API_ANALYZER); } @@ -374,12 +372,12 @@ protected ResponseDeserializer> getSearchAnalyzersRes constructListType(SearchAnalyzer.class)); } - protected Request createAnalyzerRequest(final SearchAnalyzer options) { + protected InternalRequest createAnalyzerRequest(final SearchAnalyzer options) { return request(dbName, RequestType.POST, InternalArangoView.PATH_API_ANALYZER).setBody(getSerde().serialize(options)); } - protected Request deleteAnalyzerRequest(final String name, final AnalyzerDeleteOptions options) { - Request request = request(dbName, RequestType.DELETE, InternalArangoView.PATH_API_ANALYZER, name); + protected InternalRequest deleteAnalyzerRequest(final String name, final AnalyzerDeleteOptions options) { + InternalRequest request = request(dbName, RequestType.DELETE, InternalArangoView.PATH_API_ANALYZER, name); request.putQueryParam("force", options != null ? options.getForce() : null); return request; } diff --git a/driver/src/main/java/com/arangodb/internal/InternalArangoEdgeCollection.java b/driver/src/main/java/com/arangodb/internal/InternalArangoEdgeCollection.java index 89bb70423..37ee04fc1 100644 --- a/driver/src/main/java/com/arangodb/internal/InternalArangoEdgeCollection.java +++ b/driver/src/main/java/com/arangodb/internal/InternalArangoEdgeCollection.java @@ -26,8 +26,6 @@ import com.arangodb.internal.util.DocumentUtil; import com.arangodb.internal.util.RequestUtils; import com.arangodb.model.*; -import com.arangodb.Request; -import com.arangodb.RequestType; /** * @author Mark Vollmary @@ -58,8 +56,8 @@ public String name() { return name; } - protected Request insertEdgeRequest(final T value, final EdgeCreateOptions options) { - final Request request = request(graph.db().dbName(), RequestType.POST, PATH_API_GHARIAL, graph.name(), EDGE_PATH, + protected InternalRequest insertEdgeRequest(final T value, final EdgeCreateOptions options) { + final InternalRequest request = request(graph.db().dbName(), RequestType.POST, PATH_API_GHARIAL, graph.name(), EDGE_PATH, name); final EdgeCreateOptions params = (options != null ? options : new EdgeCreateOptions()); request.putHeaderParam(TRANSACTION_ID, params.getStreamTransactionId()); @@ -72,8 +70,8 @@ protected ResponseDeserializer insertEdgeResponseDeserializer() { return response -> getSerde().deserialize(response.getBody(), EDGE_JSON_POINTER, EdgeEntity.class); } - protected Request getEdgeRequest(final String key, final GraphDocumentReadOptions options) { - final Request request = request(graph.db().dbName(), RequestType.GET, PATH_API_GHARIAL, graph.name(), EDGE_PATH, + protected InternalRequest getEdgeRequest(final String key, final GraphDocumentReadOptions options) { + final InternalRequest request = request(graph.db().dbName(), RequestType.GET, PATH_API_GHARIAL, graph.name(), EDGE_PATH, DocumentUtil.createDocumentHandle(name, key)); final GraphDocumentReadOptions params = (options != null ? options : new GraphDocumentReadOptions()); request.putHeaderParam(TRANSACTION_ID, params.getStreamTransactionId()); @@ -89,8 +87,8 @@ protected ResponseDeserializer getEdgeResponseDeserializer(final Class return response -> getSerde().deserializeUserData(getSerde().extract(response.getBody(), EDGE_JSON_POINTER), type); } - protected Request replaceEdgeRequest(final String key, final T value, final EdgeReplaceOptions options) { - final Request request = request(graph.db().dbName(), RequestType.PUT, PATH_API_GHARIAL, graph.name(), EDGE_PATH, + protected InternalRequest replaceEdgeRequest(final String key, final T value, final EdgeReplaceOptions options) { + final InternalRequest request = request(graph.db().dbName(), RequestType.PUT, PATH_API_GHARIAL, graph.name(), EDGE_PATH, DocumentUtil.createDocumentHandle(name, key)); final EdgeReplaceOptions params = (options != null ? options : new EdgeReplaceOptions()); request.putHeaderParam(TRANSACTION_ID, params.getStreamTransactionId()); @@ -104,8 +102,8 @@ protected ResponseDeserializer replaceEdgeResponseDeserializer return response -> getSerde().deserialize(response.getBody(), EDGE_JSON_POINTER, EdgeUpdateEntity.class); } - protected Request updateEdgeRequest(final String key, final T value, final EdgeUpdateOptions options) { - final Request request; + protected InternalRequest updateEdgeRequest(final String key, final T value, final EdgeUpdateOptions options) { + final InternalRequest request; request = request(graph.db().dbName(), RequestType.PATCH, PATH_API_GHARIAL, graph.name(), EDGE_PATH, DocumentUtil.createDocumentHandle(name, key)); final EdgeUpdateOptions params = (options != null ? options : new EdgeUpdateOptions()); @@ -121,8 +119,8 @@ protected ResponseDeserializer updateEdgeResponseDeserializer( return response -> getSerde().deserialize(response.getBody(), EDGE_JSON_POINTER, EdgeUpdateEntity.class); } - protected Request deleteEdgeRequest(final String key, final EdgeDeleteOptions options) { - final Request request = request(graph.db().dbName(), RequestType.DELETE, PATH_API_GHARIAL, graph.name(), EDGE_PATH, + protected InternalRequest deleteEdgeRequest(final String key, final EdgeDeleteOptions options) { + final InternalRequest request = request(graph.db().dbName(), RequestType.DELETE, PATH_API_GHARIAL, graph.name(), EDGE_PATH, DocumentUtil.createDocumentHandle(name, key)); final EdgeDeleteOptions params = (options != null ? options : new EdgeDeleteOptions()); request.putHeaderParam(TRANSACTION_ID, params.getStreamTransactionId()); diff --git a/driver/src/main/java/com/arangodb/internal/InternalArangoGraph.java b/driver/src/main/java/com/arangodb/internal/InternalArangoGraph.java index 8c874c041..975902459 100644 --- a/driver/src/main/java/com/arangodb/internal/InternalArangoGraph.java +++ b/driver/src/main/java/com/arangodb/internal/InternalArangoGraph.java @@ -25,8 +25,6 @@ import com.arangodb.internal.ArangoExecutor.ResponseDeserializer; import com.arangodb.model.OptionsBuilder; import com.arangodb.model.VertexCollectionCreateOptions; -import com.arangodb.Request; -import com.arangodb.RequestType; import java.util.Collection; @@ -61,19 +59,19 @@ public String name() { return name; } - protected Request dropRequest() { + protected InternalRequest dropRequest() { return dropRequest(false); } - protected Request dropRequest(final boolean dropCollections) { - final Request request = request(db.dbName(), RequestType.DELETE, PATH_API_GHARIAL, name); + protected InternalRequest dropRequest(final boolean dropCollections) { + final InternalRequest request = request(db.dbName(), RequestType.DELETE, PATH_API_GHARIAL, name); if (dropCollections) { request.putQueryParam("dropCollections", true); } return request; } - protected Request getInfoRequest() { + protected InternalRequest getInfoRequest() { return request(db.dbName(), RequestType.GET, PATH_API_GHARIAL, name); } @@ -81,7 +79,7 @@ protected ResponseDeserializer getInfoResponseDeserializer() { return addVertexCollectionResponseDeserializer(); } - protected Request getVertexCollectionsRequest() { + protected InternalRequest getVertexCollectionsRequest() { return request(db.dbName(), RequestType.GET, PATH_API_GHARIAL, name, VERTEX); } @@ -90,8 +88,8 @@ protected ResponseDeserializer> getVertexCollectionsResponseD constructListType(String.class)); } - protected Request addVertexCollectionRequest(final String name, final VertexCollectionCreateOptions options) { - final Request request = request(db.dbName(), RequestType.POST, PATH_API_GHARIAL, name(), VERTEX); + protected InternalRequest addVertexCollectionRequest(final String name, final VertexCollectionCreateOptions options) { + final InternalRequest request = request(db.dbName(), RequestType.POST, PATH_API_GHARIAL, name(), VERTEX); request.setBody(getSerde().serialize(OptionsBuilder.build(options, name))); return request; } @@ -100,7 +98,7 @@ protected ResponseDeserializer addVertexCollectionResponseDeseriali return addEdgeDefinitionResponseDeserializer(); } - protected Request getEdgeDefinitionsRequest() { + protected InternalRequest getEdgeDefinitionsRequest() { return request(db.dbName(), RequestType.GET, PATH_API_GHARIAL, name, EDGE); } @@ -109,8 +107,8 @@ protected ResponseDeserializer> getEdgeDefinitionsDeserialize constructListType(String.class)); } - protected Request addEdgeDefinitionRequest(final EdgeDefinition definition) { - final Request request = request(db.dbName(), RequestType.POST, PATH_API_GHARIAL, name, EDGE); + protected InternalRequest addEdgeDefinitionRequest(final EdgeDefinition definition) { + final InternalRequest request = request(db.dbName(), RequestType.POST, PATH_API_GHARIAL, name, EDGE); request.setBody(getSerde().serialize(definition)); return request; } @@ -119,8 +117,8 @@ protected ResponseDeserializer addEdgeDefinitionResponseDeserialize return response -> getSerde().deserialize(response.getBody(), GRAPH, GraphEntity.class); } - protected Request replaceEdgeDefinitionRequest(final EdgeDefinition definition) { - final Request request = request(db.dbName(), RequestType.PUT, PATH_API_GHARIAL, name, EDGE, + protected InternalRequest replaceEdgeDefinitionRequest(final EdgeDefinition definition) { + final InternalRequest request = request(db.dbName(), RequestType.PUT, PATH_API_GHARIAL, name, EDGE, definition.getCollection()); request.setBody(getSerde().serialize(definition)); return request; @@ -130,7 +128,7 @@ protected ResponseDeserializer replaceEdgeDefinitionResponseDeseria return response -> getSerde().deserialize(response.getBody(), GRAPH, GraphEntity.class); } - protected Request removeEdgeDefinitionRequest(final String definitionName) { + protected InternalRequest removeEdgeDefinitionRequest(final String definitionName) { return request(db.dbName(), RequestType.DELETE, PATH_API_GHARIAL, name, EDGE, definitionName); } diff --git a/driver/src/main/java/com/arangodb/internal/InternalArangoRoute.java b/driver/src/main/java/com/arangodb/internal/InternalArangoRoute.java index 78e782d68..86ac9d047 100644 --- a/driver/src/main/java/com/arangodb/internal/InternalArangoRoute.java +++ b/driver/src/main/java/com/arangodb/internal/InternalArangoRoute.java @@ -20,9 +20,6 @@ package com.arangodb.internal; -import com.arangodb.Request; -import com.arangodb.RequestType; - import java.util.HashMap; import java.util.Map; import java.util.Map.Entry; @@ -66,8 +63,8 @@ public void _withBody(final Object body) { this.body = body; } - protected Request createRequest(final RequestType requestType) { - final Request request = request(db.dbName(), requestType, path); + protected InternalRequest createRequest(final RequestType requestType) { + final InternalRequest request = request(db.dbName(), requestType, path); for (final Entry param : headerParam.entrySet()) { request.putHeaderParam(param.getKey(), param.getValue()); } diff --git a/driver/src/main/java/com/arangodb/internal/InternalArangoSearch.java b/driver/src/main/java/com/arangodb/internal/InternalArangoSearch.java index e4c3d5fc9..fc33ccfe4 100644 --- a/driver/src/main/java/com/arangodb/internal/InternalArangoSearch.java +++ b/driver/src/main/java/com/arangodb/internal/InternalArangoSearch.java @@ -21,8 +21,6 @@ package com.arangodb.internal; import com.arangodb.model.arangosearch.ArangoSearchPropertiesOptions; -import com.arangodb.Request; -import com.arangodb.RequestType; /** * @author Mark Vollmary @@ -37,18 +35,18 @@ protected InternalArangoSearch(final D db, final String name) { super(db, name); } - protected Request getPropertiesRequest() { + protected InternalRequest getPropertiesRequest() { return request(db.dbName(), RequestType.GET, PATH_API_VIEW, name, PROPERTIES_PATH); } - protected Request replacePropertiesRequest(final ArangoSearchPropertiesOptions options) { - final Request request = request(db.dbName(), RequestType.PUT, PATH_API_VIEW, name, PROPERTIES_PATH); + protected InternalRequest replacePropertiesRequest(final ArangoSearchPropertiesOptions options) { + final InternalRequest request = request(db.dbName(), RequestType.PUT, PATH_API_VIEW, name, PROPERTIES_PATH); request.setBody(getSerde().serialize(options != null ? options : new ArangoSearchPropertiesOptions())); return request; } - protected Request updatePropertiesRequest(final ArangoSearchPropertiesOptions options) { - final Request request = request(db.dbName(), RequestType.PATCH, PATH_API_VIEW, name, PROPERTIES_PATH); + protected InternalRequest updatePropertiesRequest(final ArangoSearchPropertiesOptions options) { + final InternalRequest request = request(db.dbName(), RequestType.PATCH, PATH_API_VIEW, name, PROPERTIES_PATH); request.setBody(getSerde().serialize(options != null ? options : new ArangoSearchPropertiesOptions())); return request; } diff --git a/driver/src/main/java/com/arangodb/internal/InternalArangoVertexCollection.java b/driver/src/main/java/com/arangodb/internal/InternalArangoVertexCollection.java index 58a3d6d9f..204aaf532 100644 --- a/driver/src/main/java/com/arangodb/internal/InternalArangoVertexCollection.java +++ b/driver/src/main/java/com/arangodb/internal/InternalArangoVertexCollection.java @@ -26,8 +26,6 @@ import com.arangodb.internal.util.DocumentUtil; import com.arangodb.internal.util.RequestUtils; import com.arangodb.model.*; -import com.arangodb.Request; -import com.arangodb.RequestType; /** * @author Mark Vollmary @@ -58,12 +56,12 @@ public String name() { return name; } - protected Request dropRequest() { + protected InternalRequest dropRequest() { return request(graph.db().dbName(), RequestType.DELETE, PATH_API_GHARIAL, graph.name(), VERTEX_PATH, name); } - protected Request insertVertexRequest(final T value, final VertexCreateOptions options) { - final Request request = request(graph.db().dbName(), RequestType.POST, PATH_API_GHARIAL, graph.name(), VERTEX_PATH, + protected InternalRequest insertVertexRequest(final T value, final VertexCreateOptions options) { + final InternalRequest request = request(graph.db().dbName(), RequestType.POST, PATH_API_GHARIAL, graph.name(), VERTEX_PATH, name); final VertexCreateOptions params = (options != null ? options : new VertexCreateOptions()); request.putHeaderParam(TRANSACTION_ID, params.getStreamTransactionId()); @@ -76,8 +74,8 @@ protected ResponseDeserializer insertVertexResponseDeserializer() return response -> getSerde().deserialize(response.getBody(), VERTEX_JSON_POINTER, VertexEntity.class); } - protected Request getVertexRequest(final String key, final GraphDocumentReadOptions options) { - final Request request = request(graph.db().dbName(), RequestType.GET, PATH_API_GHARIAL, graph.name(), VERTEX_PATH, + protected InternalRequest getVertexRequest(final String key, final GraphDocumentReadOptions options) { + final InternalRequest request = request(graph.db().dbName(), RequestType.GET, PATH_API_GHARIAL, graph.name(), VERTEX_PATH, DocumentUtil.createDocumentHandle(name, key)); final GraphDocumentReadOptions params = (options != null ? options : new GraphDocumentReadOptions()); request.putHeaderParam(TRANSACTION_ID, params.getStreamTransactionId()); @@ -93,8 +91,8 @@ protected ResponseDeserializer getVertexResponseDeserializer(final Class< return response -> getSerde().deserializeUserData(getSerde().extract(response.getBody(), VERTEX_JSON_POINTER), type); } - protected Request replaceVertexRequest(final String key, final T value, final VertexReplaceOptions options) { - final Request request = request(graph.db().dbName(), RequestType.PUT, PATH_API_GHARIAL, graph.name(), VERTEX_PATH, + protected InternalRequest replaceVertexRequest(final String key, final T value, final VertexReplaceOptions options) { + final InternalRequest request = request(graph.db().dbName(), RequestType.PUT, PATH_API_GHARIAL, graph.name(), VERTEX_PATH, DocumentUtil.createDocumentHandle(name, key)); final VertexReplaceOptions params = (options != null ? options : new VertexReplaceOptions()); request.putHeaderParam(TRANSACTION_ID, params.getStreamTransactionId()); @@ -108,8 +106,8 @@ protected ResponseDeserializer replaceVertexResponseDeserial return response -> getSerde().deserialize(response.getBody(), VERTEX_JSON_POINTER, VertexUpdateEntity.class); } - protected Request updateVertexRequest(final String key, final T value, final VertexUpdateOptions options) { - final Request request; + protected InternalRequest updateVertexRequest(final String key, final T value, final VertexUpdateOptions options) { + final InternalRequest request; request = request(graph.db().dbName(), RequestType.PATCH, PATH_API_GHARIAL, graph.name(), VERTEX_PATH, DocumentUtil.createDocumentHandle(name, key)); final VertexUpdateOptions params = (options != null ? options : new VertexUpdateOptions()); @@ -125,8 +123,8 @@ protected ResponseDeserializer updateVertexResponseDeseriali return response -> getSerde().deserialize(response.getBody(), VERTEX_JSON_POINTER, VertexUpdateEntity.class); } - protected Request deleteVertexRequest(final String key, final VertexDeleteOptions options) { - final Request request = request(graph.db().dbName(), RequestType.DELETE, PATH_API_GHARIAL, graph.name(), + protected InternalRequest deleteVertexRequest(final String key, final VertexDeleteOptions options) { + final InternalRequest request = request(graph.db().dbName(), RequestType.DELETE, PATH_API_GHARIAL, graph.name(), VERTEX_PATH, DocumentUtil.createDocumentHandle(name, key)); final VertexDeleteOptions params = (options != null ? options : new VertexDeleteOptions()); diff --git a/driver/src/main/java/com/arangodb/internal/InternalArangoView.java b/driver/src/main/java/com/arangodb/internal/InternalArangoView.java index 150a297d9..38b042695 100644 --- a/driver/src/main/java/com/arangodb/internal/InternalArangoView.java +++ b/driver/src/main/java/com/arangodb/internal/InternalArangoView.java @@ -22,8 +22,6 @@ import com.arangodb.model.OptionsBuilder; import com.arangodb.model.ViewRenameOptions; -import com.arangodb.Request; -import com.arangodb.RequestType; /** * @author Mark Vollmary @@ -53,17 +51,17 @@ public String name() { return name; } - protected Request dropRequest() { + protected InternalRequest dropRequest() { return request(db.dbName(), RequestType.DELETE, PATH_API_VIEW, name); } - protected Request renameRequest(final String newName) { - final Request request = request(db.dbName(), RequestType.PUT, PATH_API_VIEW, name, "rename"); + protected InternalRequest renameRequest(final String newName) { + final InternalRequest request = request(db.dbName(), RequestType.PUT, PATH_API_VIEW, name, "rename"); request.setBody(getSerde().serialize(OptionsBuilder.build(new ViewRenameOptions(), newName))); return request; } - protected Request getInfoRequest() { + protected InternalRequest getInfoRequest() { return request(db.dbName(), RequestType.GET, PATH_API_VIEW, name); } diff --git a/driver/src/main/java/com/arangodb/internal/InternalRequest.java b/driver/src/main/java/com/arangodb/internal/InternalRequest.java new file mode 100644 index 000000000..912062cf0 --- /dev/null +++ b/driver/src/main/java/com/arangodb/internal/InternalRequest.java @@ -0,0 +1,148 @@ +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed 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. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.internal; + +import com.arangodb.DbName; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Locale; +import java.util.Map; + +/** + * @author Mark Vollmary + */ +public class InternalRequest { + + private final DbName dbName; + private final RequestType requestType; + private final String path; + private final Map queryParam; + private final Map headerParam; + private int version = 1; + private int type = 1; + private byte[] body; + + public InternalRequest(final DbName dbName, final RequestType requestType, final String path) { + super(); + this.dbName = dbName; + this.requestType = requestType; + this.path = path; + body = null; + queryParam = new HashMap<>(); + headerParam = new HashMap<>(); + } + + public int getVersion() { + return version; + } + + public InternalRequest setVersion(final int version) { + this.version = version; + return this; + } + + public int getType() { + return type; + } + + public InternalRequest setType(final int type) { + this.type = type; + return this; + } + + public DbName getDbName() { + return dbName; + } + + public RequestType getRequestType() { + return requestType; + } + + public String getPath() { + return path; + } + + public Map getQueryParam() { + return queryParam; + } + + public InternalRequest putQueryParam(final String key, final Object value) { + if (value != null) { + queryParam.put(key, value.toString()); + } + return this; + } + + public InternalRequest putQueryParams(final Map params) { + if (params != null) { + for (Map.Entry it : params.entrySet()) { + putQueryParam(it.getKey(), it.getValue()); + } + } + return this; + } + + public Map getHeaderParam() { + return Collections.unmodifiableMap(headerParam); + } + + public boolean containsHeaderParam(final String key) { + return headerParam.containsKey(key.toLowerCase(Locale.ROOT)); + } + + public InternalRequest putHeaderParam(final String key, final String value) { + if (value != null) { + headerParam.put(key.toLowerCase(Locale.ROOT), value); + } + return this; + } + + public InternalRequest putHeaderParams(final Map params) { + if (params != null) { + for (Map.Entry it : params.entrySet()) { + putHeaderParam(it.getKey(), it.getValue()); + } + } + return this; + } + + public byte[] getBody() { + return body; + } + + public InternalRequest setBody(final byte[] body) { + this.body = body; + return this; + } + + @Override + public String toString() { + return "{" + + "requestType=" + requestType + + ", database='" + dbName + '\'' + + ", url='" + path + '\'' + + ", parameters=" + queryParam + + ", headers=" + headerParam + + '}'; + } + +} diff --git a/driver/src/main/java/com/arangodb/internal/InternalResponse.java b/driver/src/main/java/com/arangodb/internal/InternalResponse.java new file mode 100644 index 000000000..3e0ba6bbb --- /dev/null +++ b/driver/src/main/java/com/arangodb/internal/InternalResponse.java @@ -0,0 +1,105 @@ +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed 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. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.internal; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Locale; +import java.util.Map; + +/** + * @author Mark Vollmary + */ +public class InternalResponse { + + private int version = 1; + private int type = 2; + private int responseCode; + private final Map meta; + private byte[] body = null; + + public InternalResponse() { + super(); + meta = new HashMap<>(); + } + + public int getVersion() { + return version; + } + + public void setVersion(final int version) { + this.version = version; + } + + public int getType() { + return type; + } + + public void setType(final int type) { + this.type = type; + } + + public int getResponseCode() { + return responseCode; + } + + public void setResponseCode(final int responseCode) { + this.responseCode = responseCode; + } + + public Map getMeta() { + return Collections.unmodifiableMap(meta); + } + + public String getMeta(final String key) { + return meta.get(key.toLowerCase(Locale.ROOT)); + } + + public boolean containsMeta(final String key) { + return meta.containsKey(key.toLowerCase(Locale.ROOT)); + } + + public void putMeta(final String key, final String value) { + this.meta.put(key.toLowerCase(Locale.ROOT), value); + } + + public void putMetas(final Map meta) { + for (Map.Entry it : meta.entrySet()) { + putMeta(it.getKey(), it.getValue()); + } + } + + public byte[] getBody() { + return body; + } + + public void setBody(final byte[] body) { + this.body = body; + } + + @Override + public String toString() { + return "{" + + "statusCode=" + responseCode + + ", headers=" + meta + + '}'; + } +} diff --git a/driver/src/main/java/com/arangodb/internal/InternalSearchAlias.java b/driver/src/main/java/com/arangodb/internal/InternalSearchAlias.java index 410918742..97abc1745 100644 --- a/driver/src/main/java/com/arangodb/internal/InternalSearchAlias.java +++ b/driver/src/main/java/com/arangodb/internal/InternalSearchAlias.java @@ -21,8 +21,6 @@ package com.arangodb.internal; import com.arangodb.model.arangosearch.SearchAliasPropertiesOptions; -import com.arangodb.Request; -import com.arangodb.RequestType; public class InternalSearchAlias, D extends InternalArangoDatabase, E extends ArangoExecutor> extends InternalArangoView { @@ -33,18 +31,18 @@ protected InternalSearchAlias(final D db, final String name) { super(db, name); } - protected Request getPropertiesRequest() { + protected InternalRequest getPropertiesRequest() { return request(db.dbName(), RequestType.GET, PATH_API_VIEW, name, PROPERTIES_PATH); } - protected Request replacePropertiesRequest(final SearchAliasPropertiesOptions options) { - final Request request = request(db.dbName(), RequestType.PUT, PATH_API_VIEW, name, PROPERTIES_PATH); + protected InternalRequest replacePropertiesRequest(final SearchAliasPropertiesOptions options) { + final InternalRequest request = request(db.dbName(), RequestType.PUT, PATH_API_VIEW, name, PROPERTIES_PATH); request.setBody(getSerde().serialize(options != null ? options : new SearchAliasPropertiesOptions())); return request; } - protected Request updatePropertiesRequest(final SearchAliasPropertiesOptions options) { - final Request request = request(db.dbName(), RequestType.PATCH, PATH_API_VIEW, name, PROPERTIES_PATH); + protected InternalRequest updatePropertiesRequest(final SearchAliasPropertiesOptions options) { + final InternalRequest request = request(db.dbName(), RequestType.PATCH, PATH_API_VIEW, name, PROPERTIES_PATH); request.setBody(getSerde().serialize(options != null ? options : new SearchAliasPropertiesOptions())); return request; } diff --git a/driver/src/main/java/com/arangodb/RequestType.java b/driver/src/main/java/com/arangodb/internal/RequestType.java similarity index 64% rename from driver/src/main/java/com/arangodb/RequestType.java rename to driver/src/main/java/com/arangodb/internal/RequestType.java index 009f08c35..5b9d27aae 100644 --- a/driver/src/main/java/com/arangodb/RequestType.java +++ b/driver/src/main/java/com/arangodb/internal/RequestType.java @@ -18,7 +18,9 @@ * Copyright holder is ArangoDB GmbH, Cologne, Germany */ -package com.arangodb; +package com.arangodb.internal; + +import com.arangodb.Request; /** * @author Mark Vollmary @@ -43,13 +45,25 @@ public enum RequestType { this.type = type; } - public static RequestType fromType(final int type) { - for (final RequestType rType : RequestType.values()) { - if (rType.type == type) { - return rType; - } + public static RequestType from(final Request.Method method) { + switch (method) { + case DELETE: + return DELETE; + case GET: + return GET; + case POST: + return POST; + case PUT: + return PUT; + case HEAD: + return HEAD; + case PATCH: + return PATCH; + case OPTIONS: + return OPTIONS; + default: + throw new IllegalArgumentException(); } - return null; } public int getType() { diff --git a/driver/src/main/java/com/arangodb/internal/http/HttpCommunication.java b/driver/src/main/java/com/arangodb/internal/http/HttpCommunication.java index 0ce212159..f68f86f01 100644 --- a/driver/src/main/java/com/arangodb/internal/http/HttpCommunication.java +++ b/driver/src/main/java/com/arangodb/internal/http/HttpCommunication.java @@ -21,9 +21,9 @@ package com.arangodb.internal.http; import com.arangodb.ArangoDBException; -import com.arangodb.Request; -import com.arangodb.RequestType; -import com.arangodb.Response; +import com.arangodb.internal.InternalRequest; +import com.arangodb.internal.RequestType; +import com.arangodb.internal.InternalResponse; import com.arangodb.internal.net.*; import com.arangodb.internal.serde.InternalSerde; import com.arangodb.internal.util.HostUtils; @@ -59,11 +59,11 @@ public void close() throws IOException { hostHandler.close(); } - public Response execute(final Request request, final HostHandle hostHandle) { + public InternalResponse execute(final InternalRequest request, final HostHandle hostHandle) { return execute(request, hostHandle, 0); } - private Response execute(final Request request, final HostHandle hostHandle, final int attemptCount) { + private InternalResponse execute(final InternalRequest request, final HostHandle hostHandle, final int attemptCount) { final AccessType accessType = RequestUtils.determineAccessType(request); Host host = hostHandler.get(hostHandle, accessType); try { @@ -75,7 +75,7 @@ private Response execute(final Request request, final HostHandle hostHandle, fin String body = request.getBody() == null ? "" : serde.toJsonString(request.getBody()); LOGGER.debug("Send Request [id={}]: {} {}", reqId, request, body); } - final Response response = connection.execute(request); + final InternalResponse response = connection.execute(request); if (LOGGER.isDebugEnabled()) { String body = response.getBody() == null ? "" : serde.toJsonString(response.getBody()); LOGGER.debug("Received Response [id={}]: {} {}", reqId, response, body); @@ -117,7 +117,7 @@ private Response execute(final Request request, final HostHandle hostHandle, fin } } - private boolean isSafe(final Request request) { + private boolean isSafe(final InternalRequest request) { RequestType type = request.getRequestType(); return type == RequestType.GET || type == RequestType.HEAD || type == RequestType.OPTIONS; } diff --git a/driver/src/main/java/com/arangodb/internal/http/HttpConnection.java b/driver/src/main/java/com/arangodb/internal/http/HttpConnection.java index 65fef09af..0a8eefac9 100644 --- a/driver/src/main/java/com/arangodb/internal/http/HttpConnection.java +++ b/driver/src/main/java/com/arangodb/internal/http/HttpConnection.java @@ -29,9 +29,9 @@ import com.arangodb.internal.serde.InternalSerde; import com.arangodb.internal.util.EncodeUtils; import com.arangodb.internal.util.ResponseUtils; -import com.arangodb.Request; -import com.arangodb.RequestType; -import com.arangodb.Response; +import com.arangodb.internal.InternalRequest; +import com.arangodb.internal.RequestType; +import com.arangodb.internal.InternalResponse; import io.netty.handler.ssl.ApplicationProtocolConfig; import io.netty.handler.ssl.ClientAuth; import io.netty.handler.ssl.IdentityCipherSuiteFilter; @@ -163,7 +163,7 @@ public SslContextFactory sslContextFactory() { client = WebClient.create(vertx, webClientOptions); } - private static String buildUrl(final Request request) { + private static String buildUrl(final InternalRequest request) { StringBuilder sb = new StringBuilder(); DbName dbName = request.getDbName(); if (dbName != null && !dbName.get().isEmpty()) { @@ -187,7 +187,7 @@ private static String buildUrl(final Request request) { return sb.toString(); } - private static void addHeader(final Request request, final HttpRequest httpRequest) { + private static void addHeader(final InternalRequest request, final HttpRequest httpRequest) { for (final Entry header : request.getHeaderParam().entrySet()) { httpRequest.putHeader(header.getKey(), header.getValue()); } @@ -217,10 +217,10 @@ private HttpMethod requestTypeToHttpMethod(RequestType requestType) { } } - public Response execute(final Request request) throws IOException { - CompletableFuture rfuture = new CompletableFuture<>(); + public InternalResponse execute(final InternalRequest request) throws IOException { + CompletableFuture rfuture = new CompletableFuture<>(); vertx.runOnContext(e -> doExecute(request, rfuture)); - Response resp; + InternalResponse resp; try { resp = rfuture.get(); } catch (InterruptedException e) { @@ -240,7 +240,7 @@ public Response execute(final Request request) throws IOException { return resp; } - public void doExecute(final Request request, final CompletableFuture rfuture) { + public void doExecute(final InternalRequest request, final CompletableFuture rfuture) { String path = buildUrl(request); HttpRequest httpRequest = client .request(requestTypeToHttpMethod(request.getRequestType()), path) @@ -270,8 +270,8 @@ public void doExecute(final Request request, final CompletableFuture r .onFailure(rfuture::completeExceptionally); } - private Response buildResponse(final HttpResponse httpResponse) { - final Response response = new Response(); + private InternalResponse buildResponse(final HttpResponse httpResponse) { + final InternalResponse response = new InternalResponse(); response.setResponseCode(httpResponse.statusCode()); Buffer body = httpResponse.body(); if (body != null) { @@ -286,7 +286,7 @@ private Response buildResponse(final HttpResponse httpResponse) { return response; } - protected void checkError(final Response response) { + protected void checkError(final InternalResponse response) { ResponseUtils.checkError(util, response); } diff --git a/driver/src/main/java/com/arangodb/internal/http/HttpProtocol.java b/driver/src/main/java/com/arangodb/internal/http/HttpProtocol.java index 3bdc01d74..15d35c2d4 100644 --- a/driver/src/main/java/com/arangodb/internal/http/HttpProtocol.java +++ b/driver/src/main/java/com/arangodb/internal/http/HttpProtocol.java @@ -22,8 +22,8 @@ import com.arangodb.internal.net.CommunicationProtocol; import com.arangodb.internal.net.HostHandle; -import com.arangodb.Request; -import com.arangodb.Response; +import com.arangodb.internal.InternalRequest; +import com.arangodb.internal.InternalResponse; import java.io.IOException; @@ -40,7 +40,7 @@ public HttpProtocol(final HttpCommunication httpCommunitaction) { } @Override - public Response execute(final Request request, final HostHandle hostHandle) { + public InternalResponse execute(final InternalRequest request, final HostHandle hostHandle) { return httpCommunitaction.execute(request, hostHandle); } diff --git a/driver/src/main/java/com/arangodb/internal/net/CommunicationProtocol.java b/driver/src/main/java/com/arangodb/internal/net/CommunicationProtocol.java index 799fd03d3..a7f5d2b75 100644 --- a/driver/src/main/java/com/arangodb/internal/net/CommunicationProtocol.java +++ b/driver/src/main/java/com/arangodb/internal/net/CommunicationProtocol.java @@ -20,8 +20,8 @@ package com.arangodb.internal.net; -import com.arangodb.Request; -import com.arangodb.Response; +import com.arangodb.internal.InternalRequest; +import com.arangodb.internal.InternalResponse; import java.io.Closeable; @@ -30,7 +30,7 @@ */ public interface CommunicationProtocol extends Closeable { - Response execute(final Request request, HostHandle hostHandle); + InternalResponse execute(final InternalRequest request, HostHandle hostHandle); void setJwt(String jwt); diff --git a/driver/src/main/java/com/arangodb/internal/net/ExtendedHostResolver.java b/driver/src/main/java/com/arangodb/internal/net/ExtendedHostResolver.java index d5a535249..4d111af37 100644 --- a/driver/src/main/java/com/arangodb/internal/net/ExtendedHostResolver.java +++ b/driver/src/main/java/com/arangodb/internal/net/ExtendedHostResolver.java @@ -25,8 +25,8 @@ import com.arangodb.internal.ArangoExecutorSync; import com.arangodb.internal.serde.InternalSerde; import com.arangodb.internal.util.HostUtils; -import com.arangodb.Request; -import com.arangodb.RequestType; +import com.arangodb.internal.InternalRequest; +import com.arangodb.internal.RequestType; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -120,7 +120,7 @@ private Collection resolveFromServer() { try { response = executor.execute( - new Request(DbName.SYSTEM, RequestType.GET, "/_api/cluster/endpoints"), + new InternalRequest(DbName.SYSTEM, RequestType.GET, "/_api/cluster/endpoints"), response1 -> { final List> tmp = arangoSerialization.deserialize(response1.getBody(), "/endpoints", diff --git a/driver/src/main/java/com/arangodb/internal/serde/InternalDeserializers.java b/driver/src/main/java/com/arangodb/internal/serde/InternalDeserializers.java index 2cd22326a..6062a86a1 100644 --- a/driver/src/main/java/com/arangodb/internal/serde/InternalDeserializers.java +++ b/driver/src/main/java/com/arangodb/internal/serde/InternalDeserializers.java @@ -8,7 +8,7 @@ import com.arangodb.entity.arangosearch.FieldLink; import com.arangodb.util.RawBytes; import com.arangodb.util.RawJson; -import com.arangodb.Response; +import com.arangodb.internal.InternalResponse; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.TreeNode; @@ -73,10 +73,10 @@ public ReplicationFactor deserialize(final JsonParser p, final DeserializationCo }; @SuppressWarnings("unchecked") - static final JsonDeserializer RESPONSE = new JsonDeserializer() { + static final JsonDeserializer RESPONSE = new JsonDeserializer() { @Override - public Response deserialize(final JsonParser p, final DeserializationContext ctxt) throws IOException { - final Response response = new Response(); + public InternalResponse deserialize(final JsonParser p, final DeserializationContext ctxt) throws IOException { + final InternalResponse response = new InternalResponse(); Iterator it = ((ArrayNode) p.readValueAsTree()).iterator(); response.setVersion(it.next().intValue()); response.setType(it.next().intValue()); diff --git a/driver/src/main/java/com/arangodb/internal/serde/InternalModule.java b/driver/src/main/java/com/arangodb/internal/serde/InternalModule.java index 5f7d465ac..40943086f 100644 --- a/driver/src/main/java/com/arangodb/internal/serde/InternalModule.java +++ b/driver/src/main/java/com/arangodb/internal/serde/InternalModule.java @@ -8,8 +8,8 @@ import com.arangodb.internal.velocystream.internal.JwtAuthenticationRequest; import com.arangodb.util.RawBytes; import com.arangodb.util.RawJson; -import com.arangodb.Request; -import com.arangodb.Response; +import com.arangodb.internal.InternalRequest; +import com.arangodb.internal.InternalResponse; import com.fasterxml.jackson.databind.Module; import com.fasterxml.jackson.databind.module.SimpleModule; @@ -27,7 +27,7 @@ enum InternalModule implements Supplier { module.addSerializer(RawBytes.class, InternalSerializers.RAW_BYTES_SERIALIZER); module.addSerializer(AuthenticationRequest.class, InternalSerializers.AUTHENTICATION_REQUEST); module.addSerializer(JwtAuthenticationRequest.class, InternalSerializers.JWT_AUTHENTICATION_REQUEST); - module.addSerializer(Request.class, InternalSerializers.REQUEST); + module.addSerializer(InternalRequest.class, InternalSerializers.REQUEST); module.addSerializer(CollectionType.class, InternalSerializers.COLLECTION_TYPE); module.addDeserializer(RawJson.class, InternalDeserializers.RAW_JSON_DESERIALIZER); @@ -35,7 +35,7 @@ enum InternalModule implements Supplier { module.addDeserializer(CollectionStatus.class, InternalDeserializers.COLLECTION_STATUS); module.addDeserializer(CollectionType.class, InternalDeserializers.COLLECTION_TYPE); module.addDeserializer(ReplicationFactor.class, InternalDeserializers.REPLICATION_FACTOR); - module.addDeserializer(Response.class, InternalDeserializers.RESPONSE); + module.addDeserializer(InternalResponse.class, InternalDeserializers.RESPONSE); module.addDeserializer(InvertedIndexPrimarySort.Field.class, InternalDeserializers.INVERTED_INDEX_PRIMARY_SORT_FIELD); } diff --git a/driver/src/main/java/com/arangodb/internal/serde/InternalSerializers.java b/driver/src/main/java/com/arangodb/internal/serde/InternalSerializers.java index 7e9688aad..7012f67fc 100644 --- a/driver/src/main/java/com/arangodb/internal/serde/InternalSerializers.java +++ b/driver/src/main/java/com/arangodb/internal/serde/InternalSerializers.java @@ -7,7 +7,7 @@ import com.arangodb.internal.velocystream.internal.JwtAuthenticationRequest; import com.arangodb.util.RawBytes; import com.arangodb.util.RawJson; -import com.arangodb.Request; +import com.arangodb.internal.InternalRequest; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.databind.JsonSerializer; @@ -62,9 +62,9 @@ public void serialize(JwtAuthenticationRequest value, JsonGenerator gen, gen.writeEndArray(); } }; - static final JsonSerializer REQUEST = new JsonSerializer() { + static final JsonSerializer REQUEST = new JsonSerializer() { @Override - public void serialize(Request value, JsonGenerator gen, SerializerProvider serializers) throws IOException { + public void serialize(InternalRequest value, JsonGenerator gen, SerializerProvider serializers) throws IOException { gen.writeStartArray(); gen.writeNumber(value.getVersion()); gen.writeNumber(value.getType()); diff --git a/driver/src/main/java/com/arangodb/internal/util/RequestUtils.java b/driver/src/main/java/com/arangodb/internal/util/RequestUtils.java index 710fd8d0f..7074cfc3b 100644 --- a/driver/src/main/java/com/arangodb/internal/util/RequestUtils.java +++ b/driver/src/main/java/com/arangodb/internal/util/RequestUtils.java @@ -21,8 +21,8 @@ package com.arangodb.internal.util; import com.arangodb.internal.net.AccessType; -import com.arangodb.Request; -import com.arangodb.RequestType; +import com.arangodb.internal.InternalRequest; +import com.arangodb.internal.RequestType; /** * @author Mark Vollmary @@ -35,11 +35,11 @@ private RequestUtils() { super(); } - public static Request allowDirtyRead(final Request request) { + public static InternalRequest allowDirtyRead(final InternalRequest request) { return request.putHeaderParam(HEADER_ALLOW_DIRTY_READ, "true"); } - public static AccessType determineAccessType(final Request request) { + public static AccessType determineAccessType(final InternalRequest request) { if (request.containsHeaderParam(HEADER_ALLOW_DIRTY_READ)) { return AccessType.DIRTY_READ; } diff --git a/driver/src/main/java/com/arangodb/internal/util/ResponseUtils.java b/driver/src/main/java/com/arangodb/internal/util/ResponseUtils.java index 8ff292b4f..73030fc8c 100644 --- a/driver/src/main/java/com/arangodb/internal/util/ResponseUtils.java +++ b/driver/src/main/java/com/arangodb/internal/util/ResponseUtils.java @@ -25,7 +25,7 @@ import com.arangodb.internal.ArangoErrors; import com.arangodb.internal.net.ArangoDBRedirectException; import com.arangodb.internal.serde.InternalSerde; -import com.arangodb.Response; +import com.arangodb.internal.InternalResponse; import java.util.concurrent.TimeoutException; @@ -42,7 +42,7 @@ private ResponseUtils() { super(); } - public static void checkError(final InternalSerde util, final Response response) { + public static void checkError(final InternalSerde util, final InternalResponse response) { final int responseCode = response.getResponseCode(); if (responseCode >= ERROR_STATUS) { if (responseCode == ERROR_INTERNAL && response.containsMeta(HEADER_ENDPOINT)) { diff --git a/driver/src/main/java/com/arangodb/internal/velocystream/VstCommunication.java b/driver/src/main/java/com/arangodb/internal/velocystream/VstCommunication.java index 7b3a1d917..430af425f 100644 --- a/driver/src/main/java/com/arangodb/internal/velocystream/VstCommunication.java +++ b/driver/src/main/java/com/arangodb/internal/velocystream/VstCommunication.java @@ -34,8 +34,8 @@ import com.arangodb.internal.velocystream.internal.VstConnection; import com.arangodb.velocypack.VPackSlice; import com.arangodb.velocypack.exception.VPackParserException; -import com.arangodb.Request; -import com.arangodb.Response; +import com.arangodb.internal.InternalRequest; +import com.arangodb.internal.InternalResponse; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -138,32 +138,32 @@ public void close() throws IOException { hostHandler.close(); } - public R execute(final Request request, final HostHandle hostHandle) { + public R execute(final InternalRequest request, final HostHandle hostHandle) { return execute(request, hostHandle, 0); } - protected R execute(final Request request, final HostHandle hostHandle, final int attemptCount) { + protected R execute(final InternalRequest request, final HostHandle hostHandle, final int attemptCount) { final C connection = connect(hostHandle, RequestUtils.determineAccessType(request)); return execute(request, connection, attemptCount); } - protected abstract R execute(final Request request, C connection); + protected abstract R execute(final InternalRequest request, C connection); - protected abstract R execute(final Request request, C connection, final int attemptCount); + protected abstract R execute(final InternalRequest request, C connection, final int attemptCount); - protected void checkError(final Response response) { + protected void checkError(final InternalResponse response) { ResponseUtils.checkError(util, response); } - protected Response createResponse(final Message message) throws VPackParserException { - final Response response = util.deserialize(message.getHead().toByteArray(), Response.class); + protected InternalResponse createResponse(final Message message) throws VPackParserException { + final InternalResponse response = util.deserialize(message.getHead().toByteArray(), InternalResponse.class); if (message.getBody() != null) { response.setBody(message.getBody().toByteArray()); } return response; } - protected final Message createMessage(final Request request) throws VPackParserException { + protected final Message createMessage(final InternalRequest request) throws VPackParserException { request.putHeaderParam("accept", "application/x-velocypack"); request.putHeaderParam("content-type", "application/x-velocypack"); final long id = mId.incrementAndGet(); diff --git a/driver/src/main/java/com/arangodb/internal/velocystream/VstCommunicationSync.java b/driver/src/main/java/com/arangodb/internal/velocystream/VstCommunicationSync.java index d1acdbc60..837e12d50 100644 --- a/driver/src/main/java/com/arangodb/internal/velocystream/VstCommunicationSync.java +++ b/driver/src/main/java/com/arangodb/internal/velocystream/VstCommunicationSync.java @@ -32,8 +32,8 @@ import com.arangodb.internal.velocystream.internal.Message; import com.arangodb.internal.velocystream.internal.VstConnectionSync; import com.arangodb.velocypack.exception.VPackParserException; -import com.arangodb.Request; -import com.arangodb.Response; +import com.arangodb.internal.InternalRequest; +import com.arangodb.internal.InternalResponse; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -42,7 +42,7 @@ /** * @author Mark Vollmary */ -public class VstCommunicationSync extends VstCommunication { +public class VstCommunicationSync extends VstCommunication { private static final Logger LOGGER = LoggerFactory.getLogger(VstCommunicationSync.class); @@ -54,16 +54,16 @@ protected VstCommunicationSync(final HostHandler hostHandler, final Integer time } @Override - protected Response execute(final Request request, final VstConnectionSync connection) { + protected InternalResponse execute(final InternalRequest request, final VstConnectionSync connection) { return execute(request, connection, 0); } @Override - protected Response execute(final Request request, final VstConnectionSync connection, final int attemptCount) { + protected InternalResponse execute(final InternalRequest request, final VstConnectionSync connection, final int attemptCount) { try { final Message requestMessage = createMessage(request); final Message responseMessage = send(requestMessage, connection); - final Response response = createResponse(responseMessage); + final InternalResponse response = createResponse(responseMessage); checkError(response); return response; } catch (final VPackParserException e) { @@ -89,13 +89,13 @@ private Message send(final Message message, final VstConnectionSync connection) @Override protected void authenticate(final VstConnectionSync connection) { - Request authRequest; + InternalRequest authRequest; if (jwt != null) { authRequest = new JwtAuthenticationRequest(jwt, ENCRYPTION_JWT); } else { authRequest = new AuthenticationRequest(user, password != null ? password : "", ENCRYPTION_PLAIN); } - final Response response = execute(authRequest, connection); + final InternalResponse response = execute(authRequest, connection); checkError(response); } @@ -169,7 +169,7 @@ public Builder connectionTtl(final Long connectionTtl) { return this; } - public VstCommunication build(final InternalSerde util) { + public VstCommunication build(final InternalSerde util) { return new VstCommunicationSync(hostHandler, timeout, user, password, jwt, useSsl, sslContext, util, chunksize, maxConnections, connectionTtl); diff --git a/driver/src/main/java/com/arangodb/internal/velocystream/VstProtocol.java b/driver/src/main/java/com/arangodb/internal/velocystream/VstProtocol.java index 729c3028b..4782cea74 100644 --- a/driver/src/main/java/com/arangodb/internal/velocystream/VstProtocol.java +++ b/driver/src/main/java/com/arangodb/internal/velocystream/VstProtocol.java @@ -23,8 +23,8 @@ import com.arangodb.internal.net.CommunicationProtocol; import com.arangodb.internal.net.HostHandle; import com.arangodb.internal.velocystream.internal.VstConnectionSync; -import com.arangodb.Request; -import com.arangodb.Response; +import com.arangodb.internal.InternalRequest; +import com.arangodb.internal.InternalResponse; import java.io.IOException; @@ -33,15 +33,15 @@ */ public class VstProtocol implements CommunicationProtocol { - private final VstCommunication communication; + private final VstCommunication communication; - public VstProtocol(final VstCommunication communication) { + public VstProtocol(final VstCommunication communication) { super(); this.communication = communication; } @Override - public Response execute(final Request request, final HostHandle hostHandle) { + public InternalResponse execute(final InternalRequest request, final HostHandle hostHandle) { return communication.execute(request, hostHandle); } diff --git a/driver/src/main/java/com/arangodb/internal/velocystream/internal/AuthenticationRequest.java b/driver/src/main/java/com/arangodb/internal/velocystream/internal/AuthenticationRequest.java index dd48dbc4b..a7498e4ce 100644 --- a/driver/src/main/java/com/arangodb/internal/velocystream/internal/AuthenticationRequest.java +++ b/driver/src/main/java/com/arangodb/internal/velocystream/internal/AuthenticationRequest.java @@ -21,12 +21,12 @@ package com.arangodb.internal.velocystream.internal; import com.arangodb.DbName; -import com.arangodb.Request; +import com.arangodb.internal.InternalRequest; /** * @author Mark Vollmary */ -public class AuthenticationRequest extends Request { +public class AuthenticationRequest extends InternalRequest { private final String user; private final String password; diff --git a/driver/src/main/java/com/arangodb/internal/velocystream/internal/JwtAuthenticationRequest.java b/driver/src/main/java/com/arangodb/internal/velocystream/internal/JwtAuthenticationRequest.java index f2667b125..3d9fe56f9 100644 --- a/driver/src/main/java/com/arangodb/internal/velocystream/internal/JwtAuthenticationRequest.java +++ b/driver/src/main/java/com/arangodb/internal/velocystream/internal/JwtAuthenticationRequest.java @@ -1,9 +1,9 @@ package com.arangodb.internal.velocystream.internal; import com.arangodb.DbName; -import com.arangodb.Request; +import com.arangodb.internal.InternalRequest; -public class JwtAuthenticationRequest extends Request { +public class JwtAuthenticationRequest extends InternalRequest { private final String token; private final String encryption; // "jwt" diff --git a/driver/src/test/java/com/arangodb/ArangoDBTest.java b/driver/src/test/java/com/arangodb/ArangoDBTest.java index d54647b58..9f87115ce 100644 --- a/driver/src/test/java/com/arangodb/ArangoDBTest.java +++ b/driver/src/test/java/com/arangodb/ArangoDBTest.java @@ -22,9 +22,12 @@ import com.arangodb.entity.*; import com.arangodb.internal.config.FileConfigPropertiesProvider; +import com.arangodb.internal.serde.SerdeUtils; import com.arangodb.model.*; import com.arangodb.model.LogOptions.SortOrder; +import com.arangodb.util.RawJson; import com.arangodb.util.TestUtils; +import com.fasterxml.jackson.databind.JsonNode; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Disabled; @@ -390,9 +393,20 @@ void authenticationFailUser() { @ParameterizedTest(name = "{index}") @MethodSource("arangos") - void execute(ArangoDB arangoDB) { - final Response response = arangoDB.execute(new Request(DbName.SYSTEM, RequestType.GET, "/_api/version")); - assertThat(arangoDB.getSerde().parse(response.getBody(), "/version").isTextual()).isTrue(); + void executeGetVersion(ArangoDB arangoDB) { + Request request = Request.builder() + .db(DbName.SYSTEM) + .method(Request.Method.GET) + .path("/_api/version") + .queryParam("details", "true") + .build(); + final Response response = arangoDB.execute(request, RawJson.class); + JsonNode body = SerdeUtils.INSTANCE.parseJson(response.getBody().getValue()); + assertThat(body.get("version").isTextual()).isTrue(); + assertThat(body.get("details").isObject()).isTrue(); + String header = response.getHeaders().get("x-arango-queue-time-seconds"); + assertThat(header).isNotNull(); + assertThat(response.getResponseCode()).isEqualTo(200); } @ParameterizedTest(name = "{index}") diff --git a/driver/src/test/java/com/arangodb/ArangoRouteTest.java b/driver/src/test/java/com/arangodb/ArangoRouteTest.java deleted file mode 100644 index 768175fc6..000000000 --- a/driver/src/test/java/com/arangodb/ArangoRouteTest.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2018 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb; - -import com.arangodb.entity.BaseDocument; -import com.arangodb.internal.ArangoRequestParam; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.MethodSource; - -import java.util.UUID; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.catchThrowable; - -/** - * @author Mark Vollmary - * @author Michele Rastelli - */ -class ArangoRouteTest extends BaseJunit5 { - - private static final String COLLECTION_NAME = "ArangoRouteTest_collection"; - - @BeforeAll - static void init() { - initCollections(COLLECTION_NAME); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void get(ArangoDatabase db) { - final Response res = db.route("/_api/version").get(); - assertThat(db.arango().getSerde().parse(res.getBody(), "/version").isTextual()).isTrue(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void withHeader(ArangoDatabase db) { - final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); - String rev = db.collection(COLLECTION_NAME).insertDocument(doc).getRev(); - Throwable thrown = catchThrowable(() -> - db.route("/_api/document", COLLECTION_NAME, doc.getKey()).withHeader(ArangoRequestParam.IF_NONE_MATCH - , rev).get()); - assertThat(thrown).isInstanceOf(ArangoDBException.class); - ArangoDBException e = (ArangoDBException) thrown; - assertThat(e.getResponseCode()).isEqualTo(304); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void withParentHeader(ArangoDatabase db) { - final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); - String rev = db.collection(COLLECTION_NAME).insertDocument(doc).getRev(); - Throwable thrown = catchThrowable(() -> - db.route("/_api/document").withHeader(ArangoRequestParam.IF_NONE_MATCH, rev).route(COLLECTION_NAME, - doc.getKey()).get()); - assertThat(thrown).isInstanceOf(ArangoDBException.class); - ArangoDBException e = (ArangoDBException) thrown; - assertThat(e.getResponseCode()).isEqualTo(304); - } - -} diff --git a/driver/src/test/java/com/arangodb/JwtAuthTest.java b/driver/src/test/java/com/arangodb/JwtAuthTest.java index c56a5fb57..34d41a751 100644 --- a/driver/src/test/java/com/arangodb/JwtAuthTest.java +++ b/driver/src/test/java/com/arangodb/JwtAuthTest.java @@ -1,9 +1,7 @@ package com.arangodb; import com.arangodb.internal.config.FileConfigPropertiesProvider; -import com.arangodb.serde.ArangoSerde; import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.Disabled; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.EnumSource; @@ -32,17 +30,19 @@ static void init() { } private static String getJwt(ArangoDB arangoDB) { - ArangoSerde serde = arangoDB.getSerde(); Map reqBody = new HashMap<>(); reqBody.put("username", "root"); reqBody.put("password", "test"); - Request req = new Request(DbName.SYSTEM, RequestType.POST, "/_open/auth"); - req.setBody(serde.serialize(reqBody)); + Request req = Request.builder() + .db(DbName.SYSTEM) + .method(Request.Method.POST) + .path("/_open/auth") + .body(reqBody) + .build(); - Response resp = arangoDB.execute(req); - Map respBody = serde.deserialize(resp.getBody(), Map.class); - return respBody.get("jwt"); + Response resp = arangoDB.execute(req, Map.class); + return (String) resp.getBody().get("jwt"); } @ParameterizedTest diff --git a/driver/src/test/java/com/arangodb/async/ArangoDBTest.java b/driver/src/test/java/com/arangodb/async/ArangoDBTest.java index 5aa0cfbeb..34d645582 100644 --- a/driver/src/test/java/com/arangodb/async/ArangoDBTest.java +++ b/driver/src/test/java/com/arangodb/async/ArangoDBTest.java @@ -23,10 +23,10 @@ import com.arangodb.*; import com.arangodb.entity.*; import com.arangodb.internal.config.FileConfigPropertiesProvider; +import com.arangodb.internal.serde.SerdeUtils; import com.arangodb.model.*; +import com.arangodb.util.RawJson; import com.arangodb.util.TestUtils; -import com.arangodb.Request; -import com.arangodb.RequestType; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Timeout; @@ -444,10 +444,14 @@ void authenticationFailUser() throws InterruptedException { @Test void execute() throws InterruptedException, ExecutionException { arangoDB - .execute(new Request(DbName.SYSTEM, RequestType.GET, "/_api/version")) + .execute(Request.builder() + .db(DbName.SYSTEM) + .method(Request.Method.GET) + .path("/_api/version") + .build(), RawJson.class) .whenComplete((response, ex) -> { assertThat(response.getBody()).isNotNull(); - assertThat(arangoDB.getSerde().parse(response.getBody(), "/version").isTextual()).isTrue(); + assertThat(SerdeUtils.INSTANCE.parseJson(response.getBody().getValue()).get("version").isTextual()).isTrue(); }) .get(); } @@ -458,10 +462,14 @@ void execute_acquireHostList_enabled() throws InterruptedException, ExecutionExc .loadProperties(new FileConfigPropertiesProvider()) .acquireHostList(true).build(); arangoDB - .execute(new Request(DbName.SYSTEM, RequestType.GET, "/_api/version")) + .execute(Request.builder() + .db(DbName.SYSTEM) + .method(Request.Method.GET) + .path("/_api/version") + .build(), RawJson.class) .whenComplete((response, ex) -> { assertThat(response.getBody()).isNotNull(); - assertThat(arangoDB.getSerde().parse(response.getBody(), "/version").isTextual()).isTrue(); + assertThat(SerdeUtils.INSTANCE.parseJson(response.getBody().getValue()).get("version").isTextual()).isTrue(); }) .get(); } diff --git a/driver/src/test/java/com/arangodb/async/JwtAuthTest.java b/driver/src/test/java/com/arangodb/async/JwtAuthTest.java index e0c8717cc..f821f3ea9 100644 --- a/driver/src/test/java/com/arangodb/async/JwtAuthTest.java +++ b/driver/src/test/java/com/arangodb/async/JwtAuthTest.java @@ -1,13 +1,7 @@ package com.arangodb.async; -import com.arangodb.ArangoDB; -import com.arangodb.ArangoDBException; -import com.arangodb.DbName; +import com.arangodb.*; import com.arangodb.internal.config.FileConfigPropertiesProvider; -import com.arangodb.serde.ArangoSerde; -import com.arangodb.Request; -import com.arangodb.RequestType; -import com.arangodb.Response; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Disabled; @@ -35,17 +29,19 @@ static void init() { } private static String getJwt(ArangoDB arangoDB) { - ArangoSerde serde = arangoDB.getSerde(); Map reqBody = new HashMap<>(); reqBody.put("username", "root"); reqBody.put("password", "test"); - Request req = new Request(DbName.SYSTEM, RequestType.POST, "/_open/auth"); - req.setBody(serde.serialize(reqBody)); + Request req = Request.builder() + .db(DbName.SYSTEM) + .method(Request.Method.POST) + .path("/_open/auth") + .body(reqBody) + .build(); - Response resp = arangoDB.execute(req); - Map respBody = serde.deserialize(resp.getBody(), Map.class); - return respBody.get("jwt"); + Response resp = arangoDB.execute(req, Map.class); + return (String) resp.getBody().get("jwt"); } @AfterEach diff --git a/driver/src/test/java/perf/SyncBenchmarkTest.java b/driver/src/test/java/perf/SyncBenchmarkTest.java index fceb46685..f30ef331a 100644 --- a/driver/src/test/java/perf/SyncBenchmarkTest.java +++ b/driver/src/test/java/perf/SyncBenchmarkTest.java @@ -4,7 +4,6 @@ import com.arangodb.DbName; import com.arangodb.Protocol; import com.arangodb.Request; -import com.arangodb.RequestType; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.EnumSource; @@ -47,12 +46,16 @@ void getVersionWithDetails(Protocol protocol) { ArangoDB adb = new ArangoDB.Builder().useProtocol(protocol).build(); Benchmark benchmark = new Benchmark(warmupDurationSeconds, numberOfRequests) { - private final Request request = new Request(DbName.SYSTEM, RequestType.GET, - "/_api/version").putQueryParam("details", true); + private final Request request = Request.builder() + .db(DbName.SYSTEM) + .method(Request.Method.GET) + .path("/_api/version") + .queryParam("details", "true") + .build(); @Override protected void sendRequest() { - adb.execute(request); + adb.execute(request, Void.class); } @Override From 3af6662a7037f706e628586f4ec98202d70a3587 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Wed, 9 Nov 2022 14:11:19 +0100 Subject: [PATCH 186/254] removed com.arangodb.Function --- .../src/main/java/com/arangodb/Function.java | 38 ------------------- 1 file changed, 38 deletions(-) delete mode 100644 driver/src/main/java/com/arangodb/Function.java diff --git a/driver/src/main/java/com/arangodb/Function.java b/driver/src/main/java/com/arangodb/Function.java deleted file mode 100644 index b0af90c5b..000000000 --- a/driver/src/main/java/com/arangodb/Function.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2018 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb; - -/** - * @param the type of the input to the function - * @param the type of the result of the function - * @author Mark Vollmary - */ -public interface Function { - - /** - * Applies this function to the given argument. - * - * @param t the function argument - * @return the function result - */ - R apply(T t); - -} From 04db3b50b9fde6637eed54fa74e15c93e1fc8b95 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Thu, 10 Nov 2022 09:13:59 +0100 Subject: [PATCH 187/254] fixed 3.8 tests --- driver/src/test/java/com/arangodb/ArangoDBTest.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/driver/src/test/java/com/arangodb/ArangoDBTest.java b/driver/src/test/java/com/arangodb/ArangoDBTest.java index 9f87115ce..eb92489b0 100644 --- a/driver/src/test/java/com/arangodb/ArangoDBTest.java +++ b/driver/src/test/java/com/arangodb/ArangoDBTest.java @@ -404,9 +404,11 @@ void executeGetVersion(ArangoDB arangoDB) { JsonNode body = SerdeUtils.INSTANCE.parseJson(response.getBody().getValue()); assertThat(body.get("version").isTextual()).isTrue(); assertThat(body.get("details").isObject()).isTrue(); - String header = response.getHeaders().get("x-arango-queue-time-seconds"); - assertThat(header).isNotNull(); assertThat(response.getResponseCode()).isEqualTo(200); + if (isAtLeastVersion(3, 9)) { + String header = response.getHeaders().get("x-arango-queue-time-seconds"); + assertThat(header).isNotNull(); + } } @ParameterizedTest(name = "{index}") From e8218e41546e5a584c1ff846bbcc531d11b43d04 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Thu, 10 Nov 2022 10:41:36 +0100 Subject: [PATCH 188/254] PackageVersion --- driver/pom.xml | 48 +++++++++++++++++++ .../java/com/arangodb/PackageVersion.java.in | 8 ++++ .../java/com/arangodb/PackageVersionTest.java | 27 +++++++++++ 3 files changed, 83 insertions(+) create mode 100644 driver/src/main/java/com/arangodb/PackageVersion.java.in create mode 100644 driver/src/test/java/com/arangodb/PackageVersionTest.java diff --git a/driver/pom.xml b/driver/pom.xml index d3a035714..bff84ed51 100644 --- a/driver/pom.xml +++ b/driver/pom.xml @@ -104,6 +104,48 @@ + + com.google.code.maven-replacer-plugin + replacer + 1.5.3 + + + generate-sources + + replace + + + + + ${project.basedir}/src/main/java/com/arangodb/PackageVersion.java.in + ${project.build.directory}/generated-sources/replacer/com/arangodb/PackageVersion.java + + + + @project.version@ + ${project.version} + + + + + + org.codehaus.mojo + build-helper-maven-plugin + 3.3.0 + + + generate-sources + + add-source + + + + ${project.build.directory}/generated-sources/replacer + + + + + org.sonatype.plugins nexus-staging-maven-plugin @@ -375,6 +417,12 @@ 2.0.4 test + + ru.lanwen.verbalregex + java-verbal-expressions + 1.8 + test + diff --git a/driver/src/main/java/com/arangodb/PackageVersion.java.in b/driver/src/main/java/com/arangodb/PackageVersion.java.in new file mode 100644 index 000000000..e801e4d89 --- /dev/null +++ b/driver/src/main/java/com/arangodb/PackageVersion.java.in @@ -0,0 +1,8 @@ +package com.arangodb; + +/** + * Automatically generated from PackageVersion.java.in by replacer plugin. + */ +public final class PackageVersion { + public final static String VERSION = "@project.version@"; +} diff --git a/driver/src/test/java/com/arangodb/PackageVersionTest.java b/driver/src/test/java/com/arangodb/PackageVersionTest.java new file mode 100644 index 000000000..0bea32f66 --- /dev/null +++ b/driver/src/test/java/com/arangodb/PackageVersionTest.java @@ -0,0 +1,27 @@ +package com.arangodb; + +import org.junit.jupiter.api.Test; +import ru.lanwen.verbalregex.VerbalExpression; + +import static org.assertj.core.api.Assertions.assertThat; + +class PackageVersionTest { + + @Test + void packageVersion() { + VerbalExpression testRegex = VerbalExpression.regex() + .startOfLine() + // major + .digit().atLeast(1) + .then(".") + // minor + .digit().atLeast(1) + .then(".") + // patch + .digit().atLeast(1) + .maybe("-SNAPSHOT") + .endOfLine() + .build(); + assertThat(PackageVersion.VERSION).matches(testRegex.toString()); + } +} From 3944b0e529faa2a47f532e5678ed6c6508fcde91 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Thu, 10 Nov 2022 12:14:35 +0100 Subject: [PATCH 189/254] [DE-427] user agent --- .../internal/http/HttpConnection.java | 7 +++--- .../java/com/arangodb/PackageVersionTest.java | 24 ++++++++++++++++++- 2 files changed, 26 insertions(+), 5 deletions(-) diff --git a/driver/src/main/java/com/arangodb/internal/http/HttpConnection.java b/driver/src/main/java/com/arangodb/internal/http/HttpConnection.java index 0a8eefac9..f4f53445c 100644 --- a/driver/src/main/java/com/arangodb/internal/http/HttpConnection.java +++ b/driver/src/main/java/com/arangodb/internal/http/HttpConnection.java @@ -20,10 +20,7 @@ package com.arangodb.internal.http; -import com.arangodb.ArangoDBException; -import com.arangodb.ContentType; -import com.arangodb.DbName; -import com.arangodb.Protocol; +import com.arangodb.*; import com.arangodb.internal.net.Connection; import com.arangodb.internal.net.HostDescription; import com.arangodb.internal.serde.InternalSerde; @@ -73,6 +70,7 @@ public class HttpConnection implements Connection { private static final Logger LOGGER = LoggerFactory.getLogger(HttpConnection.class); private static final String CONTENT_TYPE_APPLICATION_JSON_UTF8 = "application/json; charset=utf-8"; private static final String CONTENT_TYPE_VPACK = "application/x-velocypack"; + private static final String USER_AGENT = "ArangoDB-JavaDriver/" + PackageVersion.VERSION; private static final AtomicInteger THREAD_COUNT = new AtomicInteger(); private final InternalSerde util; private final ContentType contentType; @@ -250,6 +248,7 @@ public void doExecute(final InternalRequest request, final CompletableFuture resp = adb.execute(Request.builder() + .method(Request.Method.GET) + .path("/_admin/echo") + .build(), JsonNode.class); + assertThat(resp.getBody().get("headers").get("user-agent").textValue()).endsWith(PackageVersion.VERSION); + adb.shutdown(); + } } From 6a9a3adc3d3613cb82d5f396c41e12d025d54800 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Thu, 10 Nov 2022 14:43:18 +0100 Subject: [PATCH 190/254] [DE-322] v7 documentation (#471) * http client * ArangoDB.execute * ConfigPropertiesProvider * docs upd --- driver/ChangeLog.md => ChangeLog.md | 42 ++++++---- README.md | 2 +- docs/v7_detailed_changes.md | 123 +++++++++++++++++----------- 3 files changed, 100 insertions(+), 67 deletions(-) rename driver/ChangeLog.md => ChangeLog.md (96%) diff --git a/driver/ChangeLog.md b/ChangeLog.md similarity index 96% rename from driver/ChangeLog.md rename to ChangeLog.md index 0b27cc0df..2bcbc63d2 100644 --- a/driver/ChangeLog.md +++ b/ChangeLog.md @@ -10,18 +10,21 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) a ### Changed -- changed default communication protocol from VST to HTTP/1.1 -- changed default content-type encoding format from VPACK to JSON -- transitive dependency on `org.apache.httpcomponents:httpclient:4.5.x` is not optional anymore, but it can be excluded - if using VST only +- configuration properties from local files are not read automatically anymore +- `ArangoDB.execute()` accepts now target deserialization type +- `Request` and `Response` support now generic body type +- removed default host configuration to `127.0.0.1:8529` +- changed http client library to Vert.x WebClient +- changed default communication protocol from `VST` to `HTTP/2` +- changed default content-type encoding format from `VPACK` to `JSON` - VPACK support is now provided by the optional dependency `com.arangodb:jackson-dataformat-velocypack` as dataformat backend for Jackson - changed serialization module, which is now based on Jackson API - data objects passed as arguments to API methods are now treated as immutable and the related metadata fields are not updated anymore (updated metadata can be found anyway in the object returned by the API method) - changed some API signatures which were using unnecessary generics -- changed `com.arangodb.ArangoCursor#getStats()` to return untyped map -- modeled replication factor with a new interface (`com.arangodb.entity.ReplicationFactor`) with +- changed `ArangoCursor#getStats()` to return untyped map +- modeled replication factor with a new interface (`ReplicationFactor`) with implementations: `NumericReplicationFactor` and `SatelliteReplicationFactor` - all data definition classes are now `final` - `BaseDocument` and `BaseEdgeDocument` are now `final` @@ -31,12 +34,10 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) a ### Removed -- removed user data custom serializer API based on `com.arangodb.util.ArangoSerialization` (in favor - of `com.arangodb.serde.ArangoSerde`) -- removed user data custom serializer implementation `com.arangodb.mapping.ArangoJack` (in favor - of `com.arangodb.serde.JacksonSerde`) -- removed support for interpreting raw strings as JSON (in favor of `com.arangodb.util.RawJson`) -- removed support of data type `com.arangodb.velocypack.VPackSlice` (in favor of Jackson types: `JsonNode`, `ArrayNode`, `ObjectNode`, ...) +- removed user data custom serializer API based on `ArangoSerialization` (in favor of `ArangoSerde`) +- removed user data custom serializer implementation `ArangoJack` (in favor of `JacksonSerde`) +- removed support for interpreting raw strings as JSON (in favor of `RawJson`) +- removed support of data type `VPackSlice` (in favor of Jackson types: `JsonNode`, `ArrayNode`, `ObjectNode`, ...) - removed client APIs already deprecated in Java Driver version `6.19.0` - removed deprecated server APIs: - `MMFiles` related APIs @@ -44,27 +45,34 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) a - `ArangoDB.getLogs()` - `minReplicationFactor` in collections and graphs - `overwrite` flag in `DocumentCreateOptions` +- removed `ArangoCursorInitializer` ### Added +- added `ArangoDB.Builder.loadProperties(ConfigPropertiesProvider)` to register custom configuration providers +- added `FileConfigPropertiesProvider` to load properties from local files +- added support to `HTTP/2` communication protocol +- added transitive dependency on `io.vertx:vertx-web-client`, which can be excluded if using VST only - added transitive dependency on Jackson Core, Databind and Annotations -- added wrapper class for raw JSON content (`com.arangodb.util.RawJson`) -- added wrapper class for content already encoded as byte array (`com.arangodb.util.RawBytes`) +- added wrapper class for raw JSON content (`RawJson`) +- added wrapper class for content already encoded as byte array (`RawBytes`) - added support for Jackson types (`JsonNode`, `ArrayNode`, `ObjectNode`, ...) - added support for Jackson annotations in data types -- added new user data custom serializer API based on `com.arangodb.serde.ArangoSerde` -- added new user data custom serializer implementation based on Jackson (`com.arangodb.serde.JacksonSerde`) +- added new user data custom serializer API based on `ArangoSerde` +- added new user data custom serializer implementation based on Jackson (`JacksonSerde`) - added methods and parameters targets to meta binding annotations - added overloaded methods for CRUD operations allowing specifying the return type - added API to support CRUD operations from raw data (`RawBytes` and `RawJson`) containing multiple documents - added `BaseDocument#removeAttribute(String)` and `BaseEdgeDocument#removeAttribute(String)` +- added request id to `ArangoDBException` ### Fixed - removed `--allow-incomplete-classpath` from native image configuration (#397) - ability to control whether `null` values are included in the serialization (#389) -- added support to `com.arangodb.model.DocumentCreateOptions#keepNull` (#374) +- added support to `DocumentCreateOptions#keepNull` (#374) - allow specifying the return type on insertDocuments (#373) +- removed credentials logging (#410) ## [6.19.0] diff --git a/README.md b/README.md index d50d4ec1d..843d4e3e1 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ The official [ArangoDB](https://www.arangodb.com/) Java Driver. ## Learn more -- [ChangeLog](driver/ChangeLog.md) +- [ChangeLog](ChangeLog.md) - [Examples](driver/src/test/java/com/arangodb/example) - [Examples Async](driver/src/test/java/com/arangodb/async/example) - [Tutorial](https://www.arangodb.com/docs/stable/drivers/java-tutorial.html) diff --git a/docs/v7_detailed_changes.md b/docs/v7_detailed_changes.md index 65769cd83..f63fc6578 100644 --- a/docs/v7_detailed_changes.md +++ b/docs/v7_detailed_changes.md @@ -1,34 +1,48 @@ # Version 7.0: detailed changes +## HTTP client -## Default protocol +The HTTP client has been changed to Vert.x WebClient. `HTTP/2` is now supported. `HTTP/2` supports multiplexing and uses +`1` connection per host by default. -The default communication protocol is now `HTTP_JSON` (`HTTP/1.1` with `JSON` content type). +## Configuration changes +The default communication protocol is now `HTTP2_JSON` (`HTTP/2` with `JSON` content type). + +The default host configuration to `127.0.0.1:8529` has been removed. + +Configuration properties are not read automatically from properties files anymore. + +A new configuration option for loading properties has been +introduced: `ArangoDB.Builder.loadProperties(ConfigPropertiesProvider)`. Implementations could supply configuration +properties coming from different sources, eg. system properties, remote stores, frameworks facilities, etc. An +implementation for loading properties from local files is provided by `FileConfigPropertiesProvider`. ## Transitive dependencies -A transitive dependency on `org.apache.httpcomponents:httpclient:4.5.x` has been added and the dependency -on `com.arangodb:velocypack` has been removed. -The dependency on `org.apache.httpcomponents:httpclient` can be excluded when using `VST` communication protocol only. -When using `VST` or `HTTP_VPACK`, the optional dependency on `com.arangodb:jackson-dataformat-velocypack` must be -provided. -When using `HTTP_JSON` (default), no dependencies on `VPACK` libraries are required. +A transitive dependency on `io.vertx:vertx-web-client` has been added. In can be excluded when using `VST` protocol +only. + +The dependency on `com.arangodb:velocypack` has been removed. + +When using protocol `VST`, `HTTP_VPACK` or `HTTP2_VPACK`, the optional dependency +on `com.arangodb:jackson-dataformat-velocypack` must be provided. + +When using protocol `HTTP_JSON` or `HTTP2_JSON` (default), no dependencies on `VPACK` libraries are required. + Transitive dependencies on Jackson Core, Databind and Annotations have been added, using by default version `2.13`. The versions of such libraries can be overridden, the driver is compatible with Jackson versions: `2.10`, `2.11`, `2.12` , `2.13`. - ## User Data Types Before version `7.0` the driver always parsed raw strings as JSON, but unfortunately this does not allow distinguishing the case when the intent is to use the raw string as such, without parsing it. Since version `7.0`, strings are not -interpreted as JSON anymore. To represent user data as raw JSON, the wrapper class `com.arangodb.util.RawJson` has been -added. +interpreted as JSON anymore. To represent user data as raw JSON, the wrapper class `RawJson` has been added. -To represent user data already encoded as byte array, the wrapper class `com.arangodb.util.RawBytes` has been added. -The byte array can either represent a `JSON` string (UTF-8 encoded) or a `VPACK` value, but the encoding must be the -same used for the driver protocol configuration (`JSON` for `HTTP_JSON`, `VPACK` otherwise). +To represent user data already encoded as byte array, the wrapper class `RawBytes` has been added. +The byte array can either represent a `JSON` string (UTF-8 encoded) or a `VPACK` value, but the encoding must be the +same used for the driver protocol configuration (`JSON` for `HTTP_JSON` and `HTTP2_JSON`, `VPACK` otherwise). `BaseDocument` and `BaseEdgeDocument` are now `final`, they have a new method `removeAttribute(String)` and `getProperties()` returns now an unmodifiable map. @@ -38,75 +52,86 @@ metadata received in the response. Since version `7.0`, the input data objects p treated as immutable and the related metadata fields are not updated anymore. The updated metadata can still be found in the object returned by the API method. - ## Serialization The serialization module has been changed and is now based on the Jackson API. -Up to version 6, the (de)serialization was always performed to/from `VPACK`. In case the JSON representation was required, -the raw `VPACK` was then converted to `JSON`. Since version 7, the serialization module is a dataformat agnostic API, based -on the Jackson API. By default, it reads and writes `JSON` format. `VPACK` support is provided by the optional -dependency `com.arangodb:jackson-dataformat-velocypack`, which is a dataformat backend implementation for Jackson. - -The (de)serialization of user data can be customized by registering an implementation -of `com.arangodb.serde.ArangoSerde` via `com.arangodb.ArangoDB.Builder#serializer()`. -The default user data serializer is `com.arangodb.serde.JacksonSerde`, which is based on Jackson API and is available -for both `JSON` and `VPACK`. It (de)serializes user data using Jackson Databind and can handle Jackson Annotations. -It can be customized through `com.arangodb.serde.JacksonSerde#configure(Consumer)`, -i.e. registering Kotlin or Scala modules. Furthermore, meta binding annotations (`@Id`, `@Key`, `@Rev`, `@From`, `@To`) -are supported for mapping documents and edges metadata fields (`_id`, `_key`, `_rev`, `_from`, `_to`). - -`com.arangodb.serde.ArangoSerde` interface is not constrained to Jackson. It is instead an abstract API that can be -implemented using any custom serialization library, e.g. an example of `JSON-B` implementation can be found in +Up to version 6, the (de)serialization was always performed to/from `VPACK`. In case the JSON representation was +required, the raw `VPACK` was then converted to `JSON`. Since version 7, the serialization module is a dataformat +agnostic API, based on the Jackson API. By default, it reads and writes `JSON` format. `VPACK` support is provided by +the optional dependency `com.arangodb:jackson-dataformat-velocypack`, which is a dataformat backend implementation for +Jackson. + +The (de)serialization of user data can be customized by registering an implementation of `ArangoSerde` +via `ArangoDB.Builder#serializer()`. The default user data serializer is `JacksonSerde`, which is based on Jackson API +and is available for both `JSON` and `VPACK`. It (de)serializes user data using Jackson Databind and can handle Jackson +Annotations. It can be customized through `JacksonSerde#configure(Consumer)`, i.e. registering Kotlin or +Scala modules. Furthermore, meta binding annotations (`@Id`, `@Key`, `@Rev`, `@From`, `@To`) are supported for mapping +documents and edges metadata fields (`_id`, `_key`, `_rev`, `_from`, `_to`). + +`ArangoSerde` interface is not constrained to Jackson. It is instead an abstract API that can be implemented using any +custom serialization library, e.g. an example of `JSON-B` implementation can be found in the [tests](../src/test/java/com/arangodb/serde/JsonbSerdeImpl.java). Independently of the user data serializer, the following data types are (de)serialized with specific handlers (not customizable): + - `JsonNode` and its children (`ArrayNode`, `ObjectNode`, ...) - `RawJson` - `RawBytes` - `BaseDocument` - `BaseEdgeDocument` - ## Removed APIs The following client APIs have been removed: + - client APIs already deprecated in Java Driver version `6.19.0` - client API to interact with deprecated server APIs: - - `MMFiles` related APIs - - `ArangoDatabase.executeTraversal()` - - `ArangoDB.getLogs()` - - `minReplicationFactor` in collections and graphs - - `overwrite` flag in `DocumentCreateOptions` - -The deprecation notes in the related javadoc contain information about the reason of the deprecation and suggest -migration alternatives to use. + - `MMFiles` related APIs + - `ArangoDatabase.executeTraversal()` + - `ArangoDB.getLogs()` + - `minReplicationFactor` in collections and graphs + - `overwrite` flag in `DocumentCreateOptions` -To migrate your existing project to Java Driver version `7.0`, it is recommended updating to version `6.19` first and -make sure that your code does not use any deprecated API. This can be done by checking the presence of deprecation -warnings in the Java compiler output. +The user data custom serializer implementation `ArangoJack` has been removed in favor of `JacksonSerde`. -The user data custom serializer implementation `com.arangodb.mapping.ArangoJack` has been removed in favor of `com.arangodb.serde.JacksonSerde`. +Support for interpreting raw strings as JSON has been removed (in favor of `RawJson`). -Support for interpreting raw strings as JSON has been removed (in favor of `com.arangodb.util.RawJson`). - -Support of data type `com.arangodb.velocypack.VPackSlice` has been removed (in favor of Jackson types: `JsonNode`, `ArrayNode`, `ObjectNode`, ...). +Support of data type `VPackSlice` has been removed (in favor of Jackson types: `JsonNode`, `ArrayNode`, `ObjectNode`, +...). +Support for custom initialization of +cursors (`ArangoDB._setCursorInitializer(ArangoCursorInitializer cursorInitializer)`) has been removed. ## API methods changes -Before version `7.0` some CRUD API methods inferred the return type from the type of the data object passed as input. Now the return type can be explicitly set for each CRUD API method. +Before version `7.0` some CRUD API methods inferred the return type from the type of the data object passed as input. +Now the return type can be explicitly set for each CRUD API method. CRUD operations operating with multiple documents have now an overloaded variant which accepts raw data (`RawBytes` and `RawJson`) containing multiple documents. -`com.arangodb.ArangoCursor#getStats()` returns now an untyped map. +`ArangoCursor#getStats()` returns now an untyped map. + +`Request` and `Response` classes have been refactored to support generic body +type. `ArangoDB.execute(Request, Class): Response` accepts now the target deserialization type for the response +body. +`ArangoDBException` has been enhanced with the id of the request causing it. ## API entities All entities and options classes are now `final`. -The replication factor is now modeled with a new interface (`com.arangodb.entity.ReplicationFactor`) with +The replication factor is now modeled with a new interface (`ReplicationFactor`) with implementations: `NumericReplicationFactor` and `SatelliteReplicationFactor`. + +## Migration + +To migrate your existing project to Java Driver version `7.0`, it is recommended updating to version `6.19` first and +make sure that your code does not use any deprecated API. This can be done by checking the presence of deprecation +warnings in the Java compiler output. + +The deprecation notes in the related javadoc contain information about the reason of the deprecation and suggest +migration alternatives to use. From 81e5fec11c16014d895e21b92bd1722c203f40c3 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Fri, 11 Nov 2022 10:19:51 +0100 Subject: [PATCH 191/254] [DE-322] tutorial --- tutorial/.gitignore | 32 ++ tutorial/README.md | 3 + tutorial/Tutorial.md | 307 ++++++++++++++++++ tutorial/gradle/build.gradle | 17 + tutorial/gradle/settings.gradle | 1 + tutorial/gradle/src | 1 + tutorial/maven/pom.xml | 26 ++ .../maven/src/main/java/FirstProject.java | 134 ++++++++ 8 files changed, 521 insertions(+) create mode 100644 tutorial/.gitignore create mode 100644 tutorial/README.md create mode 100644 tutorial/Tutorial.md create mode 100644 tutorial/gradle/build.gradle create mode 100644 tutorial/gradle/settings.gradle create mode 120000 tutorial/gradle/src create mode 100644 tutorial/maven/pom.xml create mode 100644 tutorial/maven/src/main/java/FirstProject.java diff --git a/tutorial/.gitignore b/tutorial/.gitignore new file mode 100644 index 000000000..f631b0010 --- /dev/null +++ b/tutorial/.gitignore @@ -0,0 +1,32 @@ +# Compiled class file +*.class + +# Log file +*.log + +# BlueJ files +*.ctxt + +# Mobile Tools for Java (J2ME) +.mtj.tmp/ + +# Package Files # +*.jar +*.war +*.nar +*.ear +*.zip +*.tar.gz +*.rar + +# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml +hs_err_pid* +target +**/.idea +*.iml +**/.directory +/gradle/.gradle/ +/gradle/build/ +/gradle/gradle/ +/gradle/gradlew +/gradle/gradlew.bat diff --git a/tutorial/README.md b/tutorial/README.md new file mode 100644 index 000000000..3983069b0 --- /dev/null +++ b/tutorial/README.md @@ -0,0 +1,3 @@ +# ArangoDB Java driver tutorial + +Code for ArangoDB [Java driver tutorial](https://www.arangodb.com/docs/stable/drivers/java-tutorial.html). diff --git a/tutorial/Tutorial.md b/tutorial/Tutorial.md new file mode 100644 index 000000000..9f2bcc3cc --- /dev/null +++ b/tutorial/Tutorial.md @@ -0,0 +1,307 @@ +# Tutorial: Java in 10 Minutes + +This is a short tutorial with the [Java Driver](https://github.com/arangodb/arangodb-java-driver) and ArangoDB. In less +than 10 minutes you can learn how to use ArangoDB Java driver in Maven and Gradle projects. + + +## Project configuration + +To use the ArangoDB Java driver, you need to import +[arangodb-java-driver](https://github.com/arangodb/arangodb-java-driver) +as a library into your project. + +In a Maven project, you need to add the following dependency to `pom.xml`: + +```xml + + + com.arangodb + arangodb-java-driver + ... + + +``` + +In a Gradle project, you need to add the following to `build.gradle`: + +```groovy +dependencies { + implementation 'com.arangodb:arangodb-java-driver:...' +} +``` + + +## Connection + +Let's configure and open a connection to start ArangoDB. + +```java +ArangoDB arangoDB = new ArangoDB.Builder() + .host("localhost", 8529) + .build(); +``` + +> **Hint:** The default connection is to 127.0.0.1:8529. + + +## Creating a database + +Let’s create a new database: + +```java +ArangoDatabase db = arangoDB.db(DbName.of("mydb")); +System.out.println("Creating database..."); +db.create(); +``` + + +## Creating a collection + +Now let’s create our first collection: + +```java +ArangoCollection collection = db.collection("firstCollection"); +System.out.println("Creating collection..."); +collection.create(); +``` + + +## Creating a document + +Now we create a document in the collection. Any object can be added as a document to the database and be retrieved from +the database as an object. + +For this example we use the class BaseDocument, provided with the driver. The attributes of the document are stored in a +map as key/value pair: + +```java +String key = "myKey"; +BaseDocument doc = new BaseDocument(key); +doc.addAttribute("a", "Foo"); +doc.addAttribute("b", 42); +System.out.println("Inserting document..."); +collection.insertDocument(doc); +``` + +Some details you should know about the code: + +- the document key is passed to the `BaseDocument` constructor +- `addAttribute()` puts a new key/value pair into the document +- each attribute is stored as a single key value pair in the document root + + +## Read a document + +To read the created document: + +```java +System.out.println("Reading document..."); +BaseDocument readDocument = collection.getDocument(key, BaseDocument.class); +System.out.println("Key: " + readDocument.getKey()); +System.out.println("Attribute a: " + readDocument.getAttribute("a")); +System.out.println("Attribute b: " + readDocument.getAttribute("b")); +``` + +After executing this program the console output should be: + +```text +Key: myKey +Attribute a: Foo +Attribute b: 42 +``` + +Some details you should know about the code: + +- `getDocument()` reads the stored document data and deserilizes it into the given class (`BaseDocument`) + + +## Creating a document from Jackson JsonNode + +We can also create a document from a Jackson [JsonNode](https://fasterxml.github.io/jackson-databind/javadoc/2.13/com/fasterxml/jackson/databind/JsonNode.html) object: + +```java +System.out.println("Creating a document from Jackson JsonNode..."); +String keyJackson = "myJacksonKey"; +JsonNode jsonNode = JsonNodeFactory.instance.objectNode() + .put("_key", keyJackson) + .put("a", "Bar") + .put("b", 53); +System.out.println("Inserting document from Jackson JsonNode..."); +collection.insertDocument(jsonNode); +``` + + +## Read a document as Jackson JsonNode + +Documents can also be read as Jackson [JsonNode](https://fasterxml.github.io/jackson-databind/javadoc/2.13/com/fasterxml/jackson/databind/JsonNode.html): + +```java +System.out.println("Reading document as Jackson JsonNode..."); +JsonNode readJsonNode = collection.getDocument(keyJackson, JsonNode.class); +System.out.println("Key: " + readJsonNode.get("_key").textValue()); +System.out.println("Attribute a: " + readJsonNode.get("a").textValue()); +System.out.println("Attribute b: " + readJsonNode.get("b").intValue()); +``` + +After executing this program the console output should be: + +```text +Key: myKey +Attribute a: Bar +Attribute b: 53 +``` + +Some details you should know about the code: + +- `getDocument()` returns the stored document as instance of `com.fasterxml.jackson.databind.JsonNode`. + + +## Creating a document from JSON String + +Documents can also be created from raw JSON strings: + +```java +System.out.println("Creating a document from JSON String..."); +String keyJson = "myJsonKey"; +RawJson json = RawJson.of("{\"_key\":\"" + keyJson + "\",\"a\":\"Baz\",\"b\":64}"); +System.out.println("Inserting document from JSON String..."); +collection.insertDocument(json); +``` + +## Read a document as JSON String + +Documents can also be read as raw JSON strings: + +```java +System.out.println("Reading document as JSON String..."); +RawJson readJson = collection.getDocument(keyJson, RawJson.class); +System.out.println(readJson.getValue()); +``` + +After executing this program the console output should be: + +```text +{"_key":"myJsonKey","_id":"firstCollection/myJsonKey","_rev":"_e0nEe2y---","a":"Baz","b":64} +``` + + +## Update a document + +Let's update the document: + +```java +doc.addAttribute("c", "Bar"); +System.out.println("Updating document ..."); +collection.updateDocument(key, doc); +``` + + +## Read the document again + +Let’s read the document again: + +```java +System.out.println("Reading updated document ..."); +BaseDocument updatedDocument = collection.getDocument(key, BaseDocument.class); +System.out.println("Key: " + updatedDocument.getKey()); +System.out.println("Attribute a: " + updatedDocument.getAttribute("a")); +System.out.println("Attribute b: " + updatedDocument.getAttribute("b")); +System.out.println("Attribute c: " + updatedDocument.getAttribute("c")); +``` + +After executing this program the console output should look like this: + +```text +Key: myKey +Attribute a: Foo +Attribute b: 42 +Attribute c: Bar +``` + + +## Delete a document + +Let’s delete a document: + +```java +System.out.println("Deleting document ..."); +collection.deleteDocument(key); +``` + + +## Execute AQL queries + +First we need to create some documents with the name Homer in collection firstCollection: + +```java +for (int i = 0; i < 10; i++) { + BaseDocument value = new BaseDocument(String.valueOf(i)); + value.addAttribute("name", "Homer"); + collection.insertDocument(value); +} +``` + +Get all documents with the name Homer from collection firstCollection and iterate over the result: + +```java +String query = "FOR t IN firstCollection FILTER t.name == @name RETURN t"; +Map bindVars = Collections.singletonMap("name", "Homer"); +System.out.println("Executing read query ..."); +ArangoCursor cursor = db.query(query, bindVars, null, BaseDocument.class); +cursor.forEach(aDocument -> System.out.println("Key: " + aDocument.getKey())); +``` + +After executing this program the console output should look something like this: + +```text +Key: 1 +Key: 0 +Key: 5 +Key: 3 +Key: 4 +Key: 9 +Key: 2 +Key: 7 +Key: 8 +Key: 6 +``` + +Some details you should know about the code: + +- the AQL query uses the placeholder `@name` which has to be bind to a value +- `query()` executes the defined query and returns a `ArangoCursor` with the given class (here: `BaseDocument`) +- the order is not guaranteed + + +## Delete a document with AQL + +Now we will delete the document created before: + +```java +String query = "FOR t IN firstCollection FILTER t.name == @name " + + "REMOVE t IN firstCollection LET removed = OLD RETURN removed"; +Map bindVars = Collections.singletonMap("name", "Homer"); +System.out.println("Executing delete query ..."); +ArangoCursor cursor = db.query(query, bindVars, null, BaseDocument.class); +cursor.forEach(aDocument -> System.out.println("Removed document " + aDocument.getKey())); +``` + +After executing this program the console output should look something like this: + +```text +Removed document: 1 +Removed document: 0 +Removed document: 5 +Removed document: 3 +Removed document: 4 +Removed document: 9 +Removed document: 2 +Removed document: 7 +Removed document: 8 +Removed document: 6 +``` + +## Learn more + +- Have a look at the [AQL documentation](https://www.arangodb.com/docs/stable/aql/) to learn more about the query language. +- Also check out the documentation about ArangoDB's [Data Model & Concepts](https://www.arangodb.com/docs/stable/data-model-and-concepts.html) diff --git a/tutorial/gradle/build.gradle b/tutorial/gradle/build.gradle new file mode 100644 index 000000000..7071475df --- /dev/null +++ b/tutorial/gradle/build.gradle @@ -0,0 +1,17 @@ +plugins { + id 'java' +} + +group 'com.arangodb' +version '1.0-SNAPSHOT' + +repositories { + mavenCentral() + maven { + url "https://oss.sonatype.org/content/repositories/snapshots" + } +} + +dependencies { + implementation 'com.arangodb:arangodb-java-driver:7.0.0-SNAPSHOT' +} diff --git a/tutorial/gradle/settings.gradle b/tutorial/gradle/settings.gradle new file mode 100644 index 000000000..28160edab --- /dev/null +++ b/tutorial/gradle/settings.gradle @@ -0,0 +1 @@ +rootProject.name = 'arangodb-java-driver-tutorial-gradle' diff --git a/tutorial/gradle/src b/tutorial/gradle/src new file mode 120000 index 000000000..c927ed2aa --- /dev/null +++ b/tutorial/gradle/src @@ -0,0 +1 @@ +../maven/src \ No newline at end of file diff --git a/tutorial/maven/pom.xml b/tutorial/maven/pom.xml new file mode 100644 index 000000000..51600f8e7 --- /dev/null +++ b/tutorial/maven/pom.xml @@ -0,0 +1,26 @@ + + + 4.0.0 + + com.arangodb + arangodb-java-driver-tutorial-maven + 1.0-SNAPSHOT + + + 17 + 17 + 17 + UTF-8 + + + + + com.arangodb + arangodb-java-driver + 7.0.0-SNAPSHOT + + + + diff --git a/tutorial/maven/src/main/java/FirstProject.java b/tutorial/maven/src/main/java/FirstProject.java new file mode 100644 index 000000000..2950387db --- /dev/null +++ b/tutorial/maven/src/main/java/FirstProject.java @@ -0,0 +1,134 @@ +import com.arangodb.*; +import com.arangodb.entity.BaseDocument; +import com.arangodb.util.RawJson; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.node.JsonNodeFactory; + +import java.util.Collections; +import java.util.Map; + +public class FirstProject { + private static final ArangoDB arangoDB = new ArangoDB.Builder() + .host("localhost", 8529) + .password("test") + .build(); + + private static void cleanup() { + ArangoDatabase db = arangoDB.db(DbName.of("mydb")); + if (db.exists()) db.drop(); + } + + public static void main(String[] args) { + cleanup(); + + // Creating a database + ArangoDatabase db = arangoDB.db(DbName.of("mydb")); + System.out.println("Creating database..."); + db.create(); + + // Creating a collection + ArangoCollection collection = db.collection("firstCollection"); + System.out.println("Creating collection..."); + collection.create(); + + // Creating a document + String key = "myKey"; + BaseDocument doc = new BaseDocument(key); + doc.addAttribute("a", "Foo"); + doc.addAttribute("b", 42); + System.out.println("Inserting document..."); + collection.insertDocument(doc); + + // Read a document + { + System.out.println("Reading document..."); + BaseDocument readDocument = collection.getDocument(key, BaseDocument.class); + System.out.println("Key: " + readDocument.getKey()); + System.out.println("Attribute a: " + readDocument.getAttribute("a")); + System.out.println("Attribute b: " + readDocument.getAttribute("b")); + } + + // Creating a document from Jackson JsonNode + String keyJackson = "myJacksonKey"; + JsonNode jsonNode = JsonNodeFactory.instance.objectNode() + .put("_key", keyJackson) + .put("a", "Bar") + .put("b", 53); + System.out.println("Inserting document from Jackson JsonNode..."); + collection.insertDocument(jsonNode); + + // Read a document as Jackson JsonNode + { + System.out.println("Reading document as Jackson JsonNode..."); + JsonNode readJsonNode = collection.getDocument(keyJackson, JsonNode.class); + System.out.println("Key: " + readJsonNode.get("_key").textValue()); + System.out.println("Attribute a: " + readJsonNode.get("a").textValue()); + System.out.println("Attribute b: " + readJsonNode.get("b").intValue()); + } + + // Creating a document from JSON String + String keyJson = "myJsonKey"; + RawJson json = RawJson.of(""" + {"_key":"%s","a":"Baz","b":64} + """.formatted(keyJson)); + System.out.println("Inserting document from JSON String..."); + collection.insertDocument(json); + + // Read a document as JSON String + { + System.out.println("Reading document as JSON String..."); + RawJson readJson = collection.getDocument(keyJson, RawJson.class); + System.out.println(readJson.getValue()); + } + + // Update a document + { + doc.addAttribute("c", "Bar"); + System.out.println("Updating document ..."); + collection.updateDocument(key, doc); + } + + // Read the document again + { + System.out.println("Reading updated document ..."); + BaseDocument updatedDocument = collection.getDocument(key, BaseDocument.class); + System.out.println("Key: " + updatedDocument.getKey()); + System.out.println("Attribute a: " + updatedDocument.getAttribute("a")); + System.out.println("Attribute b: " + updatedDocument.getAttribute("b")); + System.out.println("Attribute c: " + updatedDocument.getAttribute("c")); + } + + // Delete a document + { + System.out.println("Deleting document ..."); + collection.deleteDocument(key); + } + + // Execute AQL queries + { + for (int i = 0; i < 10; i++) { + BaseDocument value = new BaseDocument(String.valueOf(i)); + value.addAttribute("name", "Homer"); + collection.insertDocument(value); + } + + String query = "FOR t IN firstCollection FILTER t.name == @name RETURN t"; + Map bindVars = Collections.singletonMap("name", "Homer"); + System.out.println("Executing read query ..."); + ArangoCursor cursor = db.query(query, bindVars, null, BaseDocument.class); + cursor.forEach(aDocument -> System.out.println("Key: " + aDocument.getKey())); + } + + // Delete a document with AQL + { + String query = "FOR t IN firstCollection FILTER t.name == @name " + + "REMOVE t IN firstCollection LET removed = OLD RETURN removed"; + Map bindVars = Collections.singletonMap("name", "Homer"); + System.out.println("Executing delete query ..."); + ArangoCursor cursor = db.query(query, bindVars, null, BaseDocument.class); + cursor.forEach(aDocument -> System.out.println("Removed document " + aDocument.getKey())); + } + + arangoDB.shutdown(); + } +} From 19c4d97a25d9c7c1ef4f45cdb30bc8f2c54a8be6 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Mon, 28 Nov 2022 20:18:50 +0100 Subject: [PATCH 192/254] renamed ArangoDB.Builder.serializer to ArangoDB.Builder.serde --- docker/start_db.sh | 2 +- .../src/main/java/com/arangodb/ArangoDB.java | 22 +++++++++++++------ .../com/arangodb/async/ArangoDBAsync.java | 4 ++-- .../internal/InternalArangoDBBuilder.java | 6 ++--- .../test/java/com/arangodb/BaseJunit5.java | 2 +- .../com/arangodb/serde/CustomSerdeTest.java | 2 +- 6 files changed, 23 insertions(+), 15 deletions(-) diff --git a/docker/start_db.sh b/docker/start_db.sh index f5a946dbf..ee231d427 100755 --- a/docker/start_db.sh +++ b/docker/start_db.sh @@ -70,7 +70,7 @@ docker run -d \ --auth.jwt-secret=/jwtSecret \ --starter.address="${GW}" \ --docker.image="${DOCKER_IMAGE}" \ - --starter.local --starter.mode=${STARTER_MODE} --all.log.level=debug --all.log.output=+ --log.verbose + --starter.local --starter.mode=${STARTER_MODE} --all.log.level=debug --all.log.output=+ --log.verbose --all.server.descriptors-minimum=1024 wait_server() { diff --git a/driver/src/main/java/com/arangodb/ArangoDB.java b/driver/src/main/java/com/arangodb/ArangoDB.java index 118bd755c..cc371bbe8 100644 --- a/driver/src/main/java/com/arangodb/ArangoDB.java +++ b/driver/src/main/java/com/arangodb/ArangoDB.java @@ -549,16 +549,24 @@ public Builder responseQueueTimeSamples(final Integer responseQueueTimeSamples) } /** - * Replace the built-in serializer/deserializer with the given one. + * Sets the serde for the user data. + * This is used to serialize and deserialize all the data payload such as: + * - documents, vertexes, edges + * - AQL bind vars + * - body payload of requests and responses in {@link ArangoDB#execute(Request, Class)} *

    - *
    - * ATTENTION!: Any registered custom serializer/deserializer or module will be ignored. + * However, note that the following types will always be serialized and deserialized using the internal serde: + * - {@link com.fasterxml.jackson.databind.JsonNode} + * - {@link com.arangodb.util.RawJson} + * - {@link com.arangodb.util.RawBytes} + * - {@link com.arangodb.entity.BaseDocument} + * - {@link com.arangodb.entity.BaseEdgeDocument} * - * @param serialization custom serializer/deserializer + * @param serde custom serde for the user data * @return {@link ArangoDB.Builder} */ - public Builder serializer(final ArangoSerde serialization) { - setSerializer(serialization); + public Builder serde(final ArangoSerde serde) { + setUserDataSerde(serde); return this; } @@ -572,7 +580,7 @@ public ArangoDB build() { throw new ArangoDBException("No host has been set!"); } - final ArangoSerde userSerde = customSerializer != null ? customSerializer : + final ArangoSerde userSerde = this.userDataSerde != null ? this.userDataSerde : JacksonSerde.of(ContentType.of(protocol)); final InternalSerde serde = InternalSerde.of(ContentType.of(protocol), userSerde); diff --git a/driver/src/main/java/com/arangodb/async/ArangoDBAsync.java b/driver/src/main/java/com/arangodb/async/ArangoDBAsync.java index 28e1701f3..be0209d8c 100644 --- a/driver/src/main/java/com/arangodb/async/ArangoDBAsync.java +++ b/driver/src/main/java/com/arangodb/async/ArangoDBAsync.java @@ -502,7 +502,7 @@ public Builder loadBalancingStrategy(final LoadBalancingStrategy loadBalancingSt * @return {@link ArangoDBAsync.Builder} */ public Builder serializer(final ArangoSerde serialization) { - setSerializer(serialization); + setUserDataSerde(serialization); return this; } @@ -516,7 +516,7 @@ public ArangoDBAsync build() { throw new ArangoDBException("No host has been set!"); } - final ArangoSerde userSerde = customSerializer != null ? customSerializer : JacksonSerde.of(ContentType.VPACK); + final ArangoSerde userSerde = this.userDataSerde != null ? this.userDataSerde : JacksonSerde.of(ContentType.VPACK); final InternalSerde serde = InternalSerde.of(ContentType.VPACK, userSerde); final int max = maxConnections != null ? Math.max(1, maxConnections) diff --git a/driver/src/main/java/com/arangodb/internal/InternalArangoDBBuilder.java b/driver/src/main/java/com/arangodb/internal/InternalArangoDBBuilder.java index 88264b25b..df0d49496 100644 --- a/driver/src/main/java/com/arangodb/internal/InternalArangoDBBuilder.java +++ b/driver/src/main/java/com/arangodb/internal/InternalArangoDBBuilder.java @@ -58,7 +58,7 @@ public abstract class InternalArangoDBBuilder { protected Boolean acquireHostList = ArangoDefaults.DEFAULT_ACQUIRE_HOST_LIST; protected Integer acquireHostListInterval = ArangoDefaults.DEFAULT_ACQUIRE_HOST_LIST_INTERVAL; protected LoadBalancingStrategy loadBalancingStrategy = ArangoDefaults.DEFAULT_LOAD_BALANCING_STRATEGY; - protected ArangoSerde customSerializer; + protected ArangoSerde userDataSerde; protected Integer responseQueueTimeSamples = ArangoDefaults.DEFAULT_RESPONSE_QUEUE_TIME_SAMPLES; private static void loadHosts(final ConfigPropertiesProvider properties, final Collection hosts) { @@ -226,8 +226,8 @@ protected void setResponseQueueTimeSamples(final Integer responseQueueTimeSample this.responseQueueTimeSamples = responseQueueTimeSamples; } - protected void setSerializer(final ArangoSerde serializer) { - this.customSerializer = serializer; + protected void setUserDataSerde(final ArangoSerde serde) { + this.userDataSerde = serde; } protected HostHandler createHostHandler(final HostResolver hostResolver) { diff --git a/driver/src/test/java/com/arangodb/BaseJunit5.java b/driver/src/test/java/com/arangodb/BaseJunit5.java index 8ab731579..f88cac877 100644 --- a/driver/src/test/java/com/arangodb/BaseJunit5.java +++ b/driver/src/test/java/com/arangodb/BaseJunit5.java @@ -25,7 +25,7 @@ class BaseJunit5 { new ArangoDB.Builder().loadProperties(new FileConfigPropertiesProvider()).useProtocol(Protocol.HTTP_JSON).build(), new ArangoDB.Builder().loadProperties(new FileConfigPropertiesProvider()).useProtocol(Protocol.HTTP2_VPACK).build(), new ArangoDB.Builder().loadProperties(new FileConfigPropertiesProvider()).useProtocol(Protocol.HTTP2_JSON).build(), - new ArangoDB.Builder().loadProperties(new FileConfigPropertiesProvider()).useProtocol(Protocol.HTTP2_JSON).serializer(JsonbSerde.create()).build() + new ArangoDB.Builder().loadProperties(new FileConfigPropertiesProvider()).useProtocol(Protocol.HTTP2_JSON).serde(JsonbSerde.create()).build() ); protected static Stream dbsStream() { diff --git a/driver/src/test/java/com/arangodb/serde/CustomSerdeTest.java b/driver/src/test/java/com/arangodb/serde/CustomSerdeTest.java index 249d7fcca..a1d75fc39 100644 --- a/driver/src/test/java/com/arangodb/serde/CustomSerdeTest.java +++ b/driver/src/test/java/com/arangodb/serde/CustomSerdeTest.java @@ -72,7 +72,7 @@ static void init() { arangoDB = new ArangoDB.Builder() .loadProperties(new FileConfigPropertiesProvider()) .useProtocol(Protocol.VST) - .serializer(serde).build(); + .serde(serde).build(); db = arangoDB.db(DbName.of("custom-serde-test")); if (!db.exists()) { From ee4a40449004bac39e08dd8b72732761302c9636 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Tue, 29 Nov 2022 11:07:38 +0100 Subject: [PATCH 193/254] [DE-434] ArangoSearch cache --- .../entity/arangosearch/CollectionLink.java | 19 +++++++++++++++++++ .../entity/arangosearch/StoredValue.java | 18 +++++++++++++++--- .../java/com/arangodb/ArangoSearchTest.java | 14 +++++++++++++- 3 files changed, 47 insertions(+), 4 deletions(-) diff --git a/driver/src/main/java/com/arangodb/entity/arangosearch/CollectionLink.java b/driver/src/main/java/com/arangodb/entity/arangosearch/CollectionLink.java index 63b6a1a38..c5901abcc 100644 --- a/driver/src/main/java/com/arangodb/entity/arangosearch/CollectionLink.java +++ b/driver/src/main/java/com/arangodb/entity/arangosearch/CollectionLink.java @@ -44,6 +44,7 @@ public final class CollectionLink { private Collection fields; private Collection nested; private Boolean inBackground; + private Boolean cache; private CollectionLink(final String name) { super(); @@ -135,6 +136,19 @@ public CollectionLink inBackground(final Boolean inBackground) { return this; } + /** + * @param cache If you enable this option, then field normalization values are always cached in memory. This can + * improve the performance of scoring and ranking queries. Otherwise, these values are memory-mapped + * and it is up to the operating system to load them from disk into memory and to evict them from + * memory. + * @return link + * @since ArangoDB 3.9.5, Enterprise Edition only + */ + public CollectionLink cache(final Boolean cache) { + this.cache = cache; + return this; + } + @JsonIgnore public String getName() { return name; @@ -169,4 +183,9 @@ public Collection getNested() { public Boolean getInBackground() { return inBackground; } + + public Boolean getCache() { + return cache; + } + } \ No newline at end of file diff --git a/driver/src/main/java/com/arangodb/entity/arangosearch/StoredValue.java b/driver/src/main/java/com/arangodb/entity/arangosearch/StoredValue.java index 66448a4d4..66c261f77 100644 --- a/driver/src/main/java/com/arangodb/entity/arangosearch/StoredValue.java +++ b/driver/src/main/java/com/arangodb/entity/arangosearch/StoredValue.java @@ -36,16 +36,24 @@ public final class StoredValue { private final List fields; private final ArangoSearchCompression compression; + private final Boolean cache; /** * @param fields A list of attribute paths. The . character denotes sub-attributes. * @param compression Defines how to compress the attribute values. + * @param cache Whether to cache stored values in memory. (Since ArangoDB 3.9.5, Enterprise Edition only) */ @JsonCreator public StoredValue(@JsonProperty("fields") List fields, - @JsonProperty("compression") ArangoSearchCompression compression) { + @JsonProperty("compression") ArangoSearchCompression compression, + @JsonProperty("cache") Boolean cache) { this.fields = fields; this.compression = compression; + this.cache = cache; + } + + public StoredValue(List fields, ArangoSearchCompression compression) { + this(fields, compression, null); } public StoredValue(List fields) { @@ -60,16 +68,20 @@ public ArangoSearchCompression getCompression() { return compression; } + public Boolean getCache() { + return cache; + } + @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; StoredValue that = (StoredValue) o; - return Objects.equals(fields, that.fields) && compression == that.compression; + return Objects.equals(fields, that.fields) && compression == that.compression && Objects.equals(cache, that.cache); } @Override public int hashCode() { - return Objects.hash(fields, compression); + return Objects.hash(fields, compression, cache); } } diff --git a/driver/src/test/java/com/arangodb/ArangoSearchTest.java b/driver/src/test/java/com/arangodb/ArangoSearchTest.java index 280a60f48..deaecc588 100644 --- a/driver/src/test/java/com/arangodb/ArangoSearchTest.java +++ b/driver/src/test/java/com/arangodb/ArangoSearchTest.java @@ -657,11 +657,15 @@ void arangoSearchOptions(ArangoDatabase db) { .includeAllFields(true) .storeValues(StoreValuesType.ID) .trackListPositions(false) - .inBackground(true); + .inBackground(true) + .cache(true); + if (isEnterprise()) { link.nested(FieldLink.on("f3")); } ArangoSearchCreateOptions options = new ArangoSearchCreateOptions().link(link); + StoredValue storedValue = new StoredValue(Arrays.asList("a", "b"), ArangoSearchCompression.none, true); + options.storedValues(storedValue); final ArangoSearch view = db.arangoSearch(viewName); view.create(options); @@ -679,6 +683,14 @@ void arangoSearchOptions(ArangoDatabase db) { assertThat(createdLink.getIncludeAllFields()).isTrue(); assertThat(createdLink.getStoreValues()).isEqualTo(StoreValuesType.ID); assertThat(createdLink.getTrackListPositions()).isFalse(); + + if (isEnterprise() && isAtLeastVersion(3, 9, 5) && isLessThanVersion(3, 10)) { + assertThat(createdLink.getCache()).isTrue(); + assertThat(properties.getStoredValues()) + .isNotEmpty() + .allSatisfy(it -> assertThat(it.getCache()).isTrue()); + } + if (isEnterprise() && isAtLeastVersion(3, 10)) { assertThat(createdLink.getNested()).isNotEmpty(); FieldLink nested = createdLink.getNested().iterator().next(); From 6bf4a7099939024280d60f957e06398e085a402d Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Tue, 29 Nov 2022 11:14:26 +0100 Subject: [PATCH 194/254] updated test docker images --- .github/workflows/maven.yml | 24 ++++++++++++------------ .github/workflows/native.yml | 4 ++-- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index 03874be61..b8aceadb2 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -21,12 +21,12 @@ jobs: fail-fast: false matrix: docker-img: - - docker.io/arangodb/arangodb:3.8.7 - - docker.io/arangodb/arangodb:3.9.3 - - docker.io/arangodb/arangodb:3.10.0 - - docker.io/arangodb/enterprise:3.8.7 - - docker.io/arangodb/enterprise:3.9.3 - - docker.io/arangodb/enterprise:3.10.0 + - docker.io/arangodb/arangodb:3.8.8 + - docker.io/arangodb/arangodb:3.9.5 + - docker.io/arangodb/arangodb:3.10.1 + - docker.io/arangodb/enterprise:3.8.8 + - docker.io/arangodb/enterprise:3.9.5 + - docker.io/arangodb/enterprise:3.10.1 topology: - single - cluster @@ -38,12 +38,12 @@ jobs: user-language: - en include: - - docker-img: docker.io/arangodb/arangodb:3.10.0 + - docker-img: docker.io/arangodb/arangodb:3.10.1 topology: single db-ext-names: true java-version: 11 user-language: tr - - docker-img: docker.io/arangodb/enterprise:3.10.0 + - docker-img: docker.io/arangodb/enterprise:3.10.1 topology: cluster db-ext-names: true java-version: 17 @@ -78,7 +78,7 @@ jobs: fail-fast: false matrix: docker-img: - - docker.io/arangodb/arangodb:3.10.0 + - docker.io/arangodb/arangodb:3.10.1 topology: - single java-version: @@ -130,7 +130,7 @@ jobs: fail-fast: false matrix: docker-img: - - docker.io/arangodb/enterprise:3.10.0 + - docker.io/arangodb/enterprise:3.10.1 topology: - single - cluster @@ -183,7 +183,7 @@ jobs: - 2.11.4 - 2.10.5 docker-img: - - docker.io/arangodb/arangodb:3.10.0 + - docker.io/arangodb/arangodb:3.10.1 topology: - single db-ext-names: @@ -222,7 +222,7 @@ jobs: fail-fast: false matrix: docker-img: - - docker.io/arangodb/enterprise:3.10.0 + - docker.io/arangodb/enterprise:3.10.1 topology: - cluster db-ext-names: diff --git a/.github/workflows/native.yml b/.github/workflows/native.yml index d847b8861..f3edda3f7 100644 --- a/.github/workflows/native.yml +++ b/.github/workflows/native.yml @@ -14,7 +14,7 @@ jobs: fail-fast: false matrix: docker-img: - - docker.io/arangodb/enterprise:3.10.0 + - docker.io/arangodb/enterprise:3.10.1 topology: - cluster db-ext-names: @@ -51,7 +51,7 @@ jobs: fail-fast: false matrix: docker-img: - - docker.io/arangodb/enterprise:3.10.0 + - docker.io/arangodb/enterprise:3.10.1 topology: - single java-version: From 5d8dca67baca4162a098d60053b71d72b4cee4ef Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Thu, 1 Dec 2022 11:25:56 +0100 Subject: [PATCH 195/254] deps upd --- driver/pom.xml | 4 ++-- pom.xml | 2 ++ resilience-tests/pom.xml | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/driver/pom.xml b/driver/pom.xml index bff84ed51..c372e221d 100644 --- a/driver/pom.xml +++ b/driver/pom.xml @@ -16,7 +16,7 @@ https://github.com/arangodb/arangodb-java-driver - 2.13.3 + 2.14.1 arangodb-1 https://sonarcloud.io false @@ -358,7 +358,7 @@ com.arangodb jackson-dataformat-velocypack - 3.0.1 + 3.1.0 true diff --git a/pom.xml b/pom.xml index e4625ef8e..fb96cbcb0 100644 --- a/pom.xml +++ b/pom.xml @@ -24,6 +24,8 @@ + 1.8 + 1.8 UTF-8 diff --git a/resilience-tests/pom.xml b/resilience-tests/pom.xml index 22f252779..d22ebc321 100644 --- a/resilience-tests/pom.xml +++ b/resilience-tests/pom.xml @@ -84,7 +84,7 @@ com.fasterxml.jackson jackson-bom - 2.13.4 + 2.14.1 import pom From 9de421af94c7f49530113c128f999b3e0152beb5 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Thu, 1 Dec 2022 11:37:06 +0100 Subject: [PATCH 196/254] fixed SerdeUtils logs --- .../java/com/arangodb/internal/serde/SerdeUtils.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/driver/src/main/java/com/arangodb/internal/serde/SerdeUtils.java b/driver/src/main/java/com/arangodb/internal/serde/SerdeUtils.java index 0a4d83374..088e0b6d2 100644 --- a/driver/src/main/java/com/arangodb/internal/serde/SerdeUtils.java +++ b/driver/src/main/java/com/arangodb/internal/serde/SerdeUtils.java @@ -1,23 +1,24 @@ package com.arangodb.internal.serde; import com.arangodb.ArangoDBException; -import com.arangodb.jackson.dataformat.velocypack.VPackMapper; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.JavaType; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.type.TypeFactory; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.lang.reflect.Type; import java.util.ArrayList; import java.util.Arrays; import java.util.List; -import java.util.logging.Level; -import java.util.logging.Logger; public enum SerdeUtils { INSTANCE; + private static final Logger LOGGER = LoggerFactory.getLogger(SerdeUtils.class); + private final ObjectMapper jsonMapper = new ObjectMapper(); public static Type constructListType(Class clazz) { @@ -48,9 +49,8 @@ static void checkSupportedJacksonVersion() { ).forEach(version -> { int major = version.getMajorVersion(); int minor = version.getMinorVersion(); - if (major != 2 || minor < 10 || minor > 13) { - Logger.getLogger(VPackMapper.class.getName()) - .log(Level.WARNING, "Unsupported Jackson version: {0}", version); + if (major != 2 || minor < 10 || minor > 14) { + LOGGER.warn("Unsupported Jackson version: {}", version); } }); } From 3d50654dd774665d8588efa4f0bdb80e7f995fbc Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Thu, 1 Dec 2022 11:56:50 +0100 Subject: [PATCH 197/254] fixed VST error handling --- .../velocystream/internal/VstConnectionSync.java | 8 +++++++- .../src/test/java/resilience/retry/RetryTest.java | 14 ++++++++++---- .../java/resilience/shutdown/ShutdownTest.java | 1 - 3 files changed, 17 insertions(+), 6 deletions(-) diff --git a/driver/src/main/java/com/arangodb/internal/velocystream/internal/VstConnectionSync.java b/driver/src/main/java/com/arangodb/internal/velocystream/internal/VstConnectionSync.java index ecac6bd33..6530a0656 100644 --- a/driver/src/main/java/com/arangodb/internal/velocystream/internal/VstConnectionSync.java +++ b/driver/src/main/java/com/arangodb/internal/velocystream/internal/VstConnectionSync.java @@ -25,6 +25,7 @@ import javax.net.ssl.SSLContext; import java.util.Collection; +import java.util.concurrent.ExecutionException; import java.util.concurrent.FutureTask; import java.util.concurrent.TimeUnit; @@ -46,8 +47,13 @@ public Message write(final Message message, final Collection chunks) { super.writeIntern(message, chunks); try { return timeout == null || timeout == 0L ? task.get() : task.get(timeout, TimeUnit.MILLISECONDS); - } catch (final Exception e) { + } catch (final ExecutionException e) { + throw ArangoDBException.wrap(e.getCause()); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); throw new ArangoDBException(e); + } catch (final Exception e) { + throw ArangoDBException.wrap(e); } } diff --git a/resilience-tests/src/test/java/resilience/retry/RetryTest.java b/resilience-tests/src/test/java/resilience/retry/RetryTest.java index e83f8565d..1f2817b6c 100644 --- a/resilience-tests/src/test/java/resilience/retry/RetryTest.java +++ b/resilience-tests/src/test/java/resilience/retry/RetryTest.java @@ -114,9 +114,14 @@ void connectionTimeout(Protocol protocol) throws IOException, InterruptedExcepti /** - * on closed pending requests of safe HTTP methods: - retry 3 times - ArangoDBMultipleException with 3 exceptions + * on closed pending requests of safe HTTP methods: *

    - * once restored: - the subsequent requests should be successful + * - retry 3 times + * - ArangoDBMultipleException with 3 exceptions + *

    + * once restored: + *

    + * - the subsequent requests should be successful */ @ParameterizedTest @EnumSource(Protocol.class) @@ -164,7 +169,6 @@ void retryGetOnClosedConnection(Protocol protocol) throws IOException, Interrupt @ParameterizedTest @EnumSource(Protocol.class) void notRetryPostOnClosedConnection(Protocol protocol) throws IOException, InterruptedException { - assumeTrue(protocol != Protocol.VST); ArangoDB arangoDB = dbBuilder() .useProtocol(protocol) .build(); @@ -182,7 +186,9 @@ void notRetryPostOnClosedConnection(Protocol protocol) throws IOException, Inter thrown.printStackTrace(); assertThat(thrown).isInstanceOf(ArangoDBException.class); assertThat(thrown.getCause()).isInstanceOf(IOException.class); - assertThat(thrown.getCause().getCause()).isInstanceOf(HttpClosedException.class); + if (protocol != Protocol.VST) { + assertThat(thrown.getCause().getCause()).isInstanceOf(HttpClosedException.class); + } toxic.remove(); Thread.sleep(100); diff --git a/resilience-tests/src/test/java/resilience/shutdown/ShutdownTest.java b/resilience-tests/src/test/java/resilience/shutdown/ShutdownTest.java index 1a8924196..a53e3c331 100644 --- a/resilience-tests/src/test/java/resilience/shutdown/ShutdownTest.java +++ b/resilience-tests/src/test/java/resilience/shutdown/ShutdownTest.java @@ -48,7 +48,6 @@ void shutdownWithPendingRequests(Protocol protocol) { ScheduledExecutorService es = Executors.newSingleThreadScheduledExecutor(); es.schedule(arangoDB::shutdown, 200, TimeUnit.MILLISECONDS); Throwable thrown = catchThrowable(() -> arangoDB.db().query("return sleep(1)", Void.class)); - thrown.printStackTrace(); assertThat(thrown).isInstanceOf(ArangoDBException.class); assertThat(thrown.getCause()).isInstanceOf(IOException.class); assertThat(thrown.getCause().getCause()).isInstanceOf(HttpClosedException.class); From 872aa02e06f72e4ddeac994ff41b64d2574d6b43 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Thu, 1 Dec 2022 14:38:53 +0100 Subject: [PATCH 198/254] added Jackson 2.14 to test matrix --- .github/workflows/maven.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index b8aceadb2..cce5dd8aa 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -178,6 +178,7 @@ jobs: fail-fast: false matrix: jackson-version: + - 2.14.1 - 2.13.3 - 2.12.7 - 2.11.4 From 275abf7e13f3d5c80bde4ff43786bb6fd9bbf2e6 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Fri, 2 Dec 2022 11:41:10 +0100 Subject: [PATCH 199/254] [DE-435] renamed user agent header --- .../main/java/com/arangodb/internal/http/HttpConnection.java | 4 ++-- driver/src/test/java/com/arangodb/PackageVersionTest.java | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/driver/src/main/java/com/arangodb/internal/http/HttpConnection.java b/driver/src/main/java/com/arangodb/internal/http/HttpConnection.java index f4f53445c..a62ef669e 100644 --- a/driver/src/main/java/com/arangodb/internal/http/HttpConnection.java +++ b/driver/src/main/java/com/arangodb/internal/http/HttpConnection.java @@ -70,7 +70,7 @@ public class HttpConnection implements Connection { private static final Logger LOGGER = LoggerFactory.getLogger(HttpConnection.class); private static final String CONTENT_TYPE_APPLICATION_JSON_UTF8 = "application/json; charset=utf-8"; private static final String CONTENT_TYPE_VPACK = "application/x-velocypack"; - private static final String USER_AGENT = "ArangoDB-JavaDriver/" + PackageVersion.VERSION; + private static final String USER_AGENT = "JavaDriver/" + PackageVersion.VERSION; private static final AtomicInteger THREAD_COUNT = new AtomicInteger(); private final InternalSerde util; private final ContentType contentType; @@ -248,7 +248,7 @@ public void doExecute(final InternalRequest request, final CompletableFuture Date: Thu, 8 Dec 2022 21:08:34 +0100 Subject: [PATCH 200/254] [DE-415] [DE-416] shaded package (#473) * transitive deps relocation * split classes that do not must be shaded * serde modules * pom files reorganization * deps upd * pom files reorganization * pom files reorganization * shaded integration tests * repackaged serde modules * archunit tests for shaded pkg * moved test files * fixed jackson serde annotations in shaded pkg * fixed TransactionOptions serialization * shaded tests * archunit tests for shaded pkg * rm deactivateDefaultTyping from jackson-serde * deploy config upd * deploy config upd * fixed shaded serde-api * shaded-integration-tests CI --- .github/workflows/maven.yml | 40 +- .gitignore | 1 + driver/pom.xml | 268 +- .../src/main/java/com/arangodb/ArangoDB.java | 15 +- .../com/arangodb/async/ArangoDBAsync.java | 3 +- .../com/arangodb/entity/DocumentEntity.java | 14 +- .../internal/InternalArangoDBBuilder.java | 19 +- .../internal/http/HttpConnection.java | 3 +- .../internal/serde/ContentTypeFactory.java | 24 + ...r.java => InternalJsonMapperProvider.java} | 2 +- ...vider.java => InternalMapperProvider.java} | 6 +- .../internal/serde/InternalSerde.java | 5 +- .../internal/serde/InternalSerdeImpl.java | 25 +- ....java => InternalVPackMapperProvider.java} | 2 +- .../arangodb/model/TransactionOptions.java | 3 + .../java/com/arangodb/serde/JacksonSerde.java | 42 - .../{ => META-INF}/vertx/vertx-version.txt | 0 .../com/arangodb/ArangoCollectionTest.java | 5 +- .../test/java/com/arangodb/BaseJunit5.java | 4 +- .../arangodb/async/ArangoCollectionTest.java | 3 +- .../arangodb/async/example/graph/Circle.java | 6 +- .../async/example/graph/CircleEdge.java | 2 +- .../arangodb/async/serde/CustomSerdeTest.java | 5 +- .../com/arangodb/example/graph/Circle.java | 6 +- .../arangodb/example/graph/CircleEdge.java | 2 +- .../mapping/annotations/AnnotatedEntity.java | 2 +- .../annotations/ArangoAnnotationsTest.java | 6 +- .../com/arangodb/serde/CustomSerdeTest.java | 4 +- .../arangodb/serde/CustomTypeHintTest.java | 2 +- .../java/com/arangodb/serde/JsonbSerde.java | 29 - jackson-serde/pom.xml | 44 + .../com/arangodb/serde/jackson}/From.java | 9 +- .../java/com/arangodb/serde/jackson}/Id.java | 9 +- .../arangodb/serde/jackson/JacksonSerde.java | 20 + .../serde/jackson/JacksonSerdeProvider.java | 32 + .../java/com/arangodb/serde/jackson}/Key.java | 9 +- .../java/com/arangodb/serde/jackson}/Rev.java | 9 +- .../java/com/arangodb/serde/jackson}/To.java | 9 +- .../internal/JacksonMapperProvider.java | 21 + .../jackson/internal}/JacksonSerdeImpl.java | 24 +- .../internal/JsonJacksonMapperProvider.java | 15 + .../internal/VPackJacksonMapperProvider.java | 16 + .../com.arangodb.serde.ArangoSerdeProvider | 1 + jsonb-serde/pom.xml | 34 + .../java/com/arangodb/serde/jsonb/From.java | 19 + .../java/com/arangodb/serde/jsonb/Id.java | 19 + .../com/arangodb/serde/jsonb/JsonbSerde.java | 12 +- .../serde/jsonb/JsonbSerdeProvider.java | 33 + .../java/com/arangodb/serde/jsonb/Key.java | 19 + .../java/com/arangodb/serde/jsonb/Rev.java | 19 + .../java/com/arangodb/serde/jsonb/To.java | 19 + .../com.arangodb.serde.ArangoSerdeProvider | 1 + pom.xml | 289 ++ resilience-tests/pom.xml | 71 - .../java/resilience/SingleServerTest.java | 2 +- .../src/test/resources/logback-test.xml | 2 +- serde-api/pom.xml | 14 + .../main/java/com/arangodb/ContentType.java | 16 +- .../java/com/arangodb/serde/ArangoSerde.java | 6 - .../arangodb/serde/ArangoSerdeProvider.java | 15 + shaded-integration-tests/pom.xml | 196 + .../src/test/jackson/java/arch/AdbTest.java | 18 + .../src/test/jackson/java/arch/BaseTest.java | 54 + .../src/test/jackson/java/arch/Person.java | 13 + .../jackson/java/arch/RelocationsTest.java | 56 + .../src/test/jackson/java/arch/SerdeTest.java | 81 + .../com/arangodb/ArangoCollectionTest.java | 3220 +++++++++++++++++ .../java/com/arangodb/ArangoCursorTest.java | 133 + .../java/com/arangodb/ArangoDBTest.java | 656 ++++ .../java/com/arangodb/ArangoDatabaseTest.java | 1413 ++++++++ .../com/arangodb/ArangoDocumentUtilTest.java | 84 + .../arangodb/ArangoEdgeCollectionTest.java | 445 +++ .../java/com/arangodb/ArangoGraphTest.java | 438 +++ .../java/com/arangodb/ArangoSearchTest.java | 1010 ++++++ .../java/com/arangodb/ArangoSslTest.java | 101 + .../arangodb/ArangoVertexCollectionTest.java | 480 +++ .../java/com/arangodb/ArangoViewTest.java | 114 + .../jackson/java/com/arangodb/BaseJunit5.java | 128 + .../java/com/arangodb/ConcurrencyTests.java | 34 + .../java/com/arangodb/DocumentTest.java | 138 + .../java/com/arangodb/InvertedIndexTest.java | 194 + .../java/com/arangodb/JwtAuthTest.java | 97 + .../java/com/arangodb/ParallelTest.java | 42 + .../java/com/arangodb/SerializableTest.java | 57 + .../StreamTransactionConflictsTest.java | 119 + .../arangodb/StreamTransactionGraphTest.java | 407 +++ .../com/arangodb/StreamTransactionTest.java | 820 +++++ .../arangodb/annotations/AnnotatedEntity.java | 81 + .../annotations/ArangoAnnotationsTest.java | 64 + .../arangodb/async/ArangoCollectionTest.java | 2514 +++++++++++++ .../java/com/arangodb/async/ArangoDBTest.java | 566 +++ .../arangodb/async/ArangoDatabaseTest.java | 1024 ++++++ .../async/ArangoEdgeCollectionTest.java | 367 ++ .../com/arangodb/async/ArangoGraphTest.java | 387 ++ .../com/arangodb/async/ArangoRouteTest.java | 81 + .../com/arangodb/async/ArangoSearchTest.java | 551 +++ .../async/ArangoVertexCollectionTest.java | 356 ++ .../com/arangodb/async/ArangoViewTest.java | 86 + .../java/com/arangodb/async/BaseTest.java | 118 + .../com/arangodb/async/CommunicationTest.java | 46 + .../com/arangodb/async/ConcurrencyTest.java | 94 + .../com/arangodb/async/ConcurrencyTests.java | 29 + .../com/arangodb/async/InvertedIndexTest.java | 199 + .../java/com/arangodb/async/JwtAuthTest.java | 103 + .../async/StreamTransactionConflictsTest.java | 120 + .../async/StreamTransactionGraphTest.java | 398 ++ .../arangodb/async/StreamTransactionTest.java | 362 ++ .../debug/ConsolidationIntervalMsecTest.java | 83 + .../arangodb/async/example/ExampleBase.java | 64 + ...ueryWithSpecialReturnTypesExampleTest.java | 128 + .../document/GetDocumentExampleTest.java | 94 + .../document/ImportDocumentExampleTest.java | 87 + .../document/InsertDocumentExampleTest.java | 74 + .../async/example/document/TestEntity.java | 47 + .../graph/AQLActorsAndMoviesExampleTest.java | 605 ++++ .../async/example/graph/BaseGraphTest.java | 116 + .../arangodb/async/example/graph/Circle.java | 80 + .../async/example/graph/CircleEdge.java | 122 + .../GraphTraversalsInAQLExampleTest.java | 122 + .../graph/ShortestPathInAQLExampleTest.java | 106 + .../async/example/ssl/SslExampleTest.java | 79 + .../arangodb/async/serde/CustomSerdeTest.java | 177 + .../com/arangodb/example/ExampleBase.java | 62 + .../com/arangodb/example/FirstProject.java | 134 + ...ueryWithSpecialReturnTypesExampleTest.java | 132 + .../document/GetDocumentExampleTest.java | 98 + .../document/InsertDocumentExampleTest.java | 70 + .../arangodb/example/document/TestEntity.java | 47 + .../graph/AQLActorsAndMoviesExampleTest.java | 581 +++ .../arangodb/example/graph/BaseGraphTest.java | 114 + .../com/arangodb/example/graph/Circle.java | 80 + .../arangodb/example/graph/CircleEdge.java | 122 + .../GraphTraversalsInAQLExampleTest.java | 113 + .../graph/ShortestPathInAQLExampleTest.java | 105 + .../arangodb/example/ssl/SslExampleTest.java | 131 + .../arangodb/internal/HostHandlerTest.java | 189 + .../internal/QueueTimeMetricsImplTest.java | 61 + .../velocystream/CommunicationTest.java | 122 + .../com/arangodb/serde/CustomSerdeTest.java | 242 ++ .../arangodb/serde/CustomTypeHintTest.java | 145 + .../java/com/arangodb/serde/SerdeTest.java | 71 + .../java/com/arangodb/util/MapBuilder.java | 46 + .../com/arangodb/util/MapBuilderTest.java | 43 + .../java/com/arangodb/util/TestUtils.java | 112 + .../src/test/jsonb/java/arch/AdbTest.java | 18 + .../src/test/jsonb/java/arch/BaseTest.java | 74 + .../src/test/jsonb/java/arch/Person.java | 61 + .../test/jsonb/java/arch/RelocationsTest.java | 54 + .../src/test/jsonb/java/arch/SerdeTest.java | 66 + .../test/resources/arangodb-bad.properties | 1 + .../src/test/resources/arangodb.properties | 5 + .../src/test/resources/logback-test.xml | 18 + shaded/pom.xml | 133 + 153 files changed, 24198 insertions(+), 486 deletions(-) create mode 100644 driver/src/main/java/com/arangodb/internal/serde/ContentTypeFactory.java rename driver/src/main/java/com/arangodb/internal/serde/{JsonMapperProvider.java => InternalJsonMapperProvider.java} (74%) rename driver/src/main/java/com/arangodb/internal/serde/{MapperProvider.java => InternalMapperProvider.java} (69%) rename driver/src/main/java/com/arangodb/internal/serde/{VPackMapperProvider.java => InternalVPackMapperProvider.java} (78%) delete mode 100644 driver/src/main/java/com/arangodb/serde/JacksonSerde.java rename driver/src/main/resources/{ => META-INF}/vertx/vertx-version.txt (100%) delete mode 100644 driver/src/test/java/com/arangodb/serde/JsonbSerde.java create mode 100644 jackson-serde/pom.xml rename {driver/src/main/java/com/arangodb/entity => jackson-serde/src/main/java/com/arangodb/serde/jackson}/From.java (68%) rename {driver/src/main/java/com/arangodb/entity => jackson-serde/src/main/java/com/arangodb/serde/jackson}/Id.java (68%) create mode 100644 jackson-serde/src/main/java/com/arangodb/serde/jackson/JacksonSerde.java create mode 100644 jackson-serde/src/main/java/com/arangodb/serde/jackson/JacksonSerdeProvider.java rename {driver/src/main/java/com/arangodb/entity => jackson-serde/src/main/java/com/arangodb/serde/jackson}/Key.java (68%) rename {driver/src/main/java/com/arangodb/entity => jackson-serde/src/main/java/com/arangodb/serde/jackson}/Rev.java (68%) rename {driver/src/main/java/com/arangodb/entity => jackson-serde/src/main/java/com/arangodb/serde/jackson}/To.java (68%) create mode 100644 jackson-serde/src/main/java/com/arangodb/serde/jackson/internal/JacksonMapperProvider.java rename {driver/src/main/java/com/arangodb/internal/serde => jackson-serde/src/main/java/com/arangodb/serde/jackson/internal}/JacksonSerdeImpl.java (60%) create mode 100644 jackson-serde/src/main/java/com/arangodb/serde/jackson/internal/JsonJacksonMapperProvider.java create mode 100644 jackson-serde/src/main/java/com/arangodb/serde/jackson/internal/VPackJacksonMapperProvider.java create mode 100644 jackson-serde/src/main/resources/META-INF/services/com.arangodb.serde.ArangoSerdeProvider create mode 100644 jsonb-serde/pom.xml create mode 100644 jsonb-serde/src/main/java/com/arangodb/serde/jsonb/From.java create mode 100644 jsonb-serde/src/main/java/com/arangodb/serde/jsonb/Id.java rename driver/src/test/java/com/arangodb/serde/JsonbSerdeImpl.java => jsonb-serde/src/main/java/com/arangodb/serde/jsonb/JsonbSerde.java (69%) create mode 100644 jsonb-serde/src/main/java/com/arangodb/serde/jsonb/JsonbSerdeProvider.java create mode 100644 jsonb-serde/src/main/java/com/arangodb/serde/jsonb/Key.java create mode 100644 jsonb-serde/src/main/java/com/arangodb/serde/jsonb/Rev.java create mode 100644 jsonb-serde/src/main/java/com/arangodb/serde/jsonb/To.java create mode 100644 jsonb-serde/src/main/resources/META-INF/services/com.arangodb.serde.ArangoSerdeProvider create mode 100644 serde-api/pom.xml rename {driver => serde-api}/src/main/java/com/arangodb/ContentType.java (62%) rename {driver => serde-api}/src/main/java/com/arangodb/serde/ArangoSerde.java (84%) create mode 100644 serde-api/src/main/java/com/arangodb/serde/ArangoSerdeProvider.java create mode 100644 shaded-integration-tests/pom.xml create mode 100644 shaded-integration-tests/src/test/jackson/java/arch/AdbTest.java create mode 100644 shaded-integration-tests/src/test/jackson/java/arch/BaseTest.java create mode 100644 shaded-integration-tests/src/test/jackson/java/arch/Person.java create mode 100644 shaded-integration-tests/src/test/jackson/java/arch/RelocationsTest.java create mode 100644 shaded-integration-tests/src/test/jackson/java/arch/SerdeTest.java create mode 100644 shaded-integration-tests/src/test/jackson/java/com/arangodb/ArangoCollectionTest.java create mode 100644 shaded-integration-tests/src/test/jackson/java/com/arangodb/ArangoCursorTest.java create mode 100644 shaded-integration-tests/src/test/jackson/java/com/arangodb/ArangoDBTest.java create mode 100644 shaded-integration-tests/src/test/jackson/java/com/arangodb/ArangoDatabaseTest.java create mode 100644 shaded-integration-tests/src/test/jackson/java/com/arangodb/ArangoDocumentUtilTest.java create mode 100644 shaded-integration-tests/src/test/jackson/java/com/arangodb/ArangoEdgeCollectionTest.java create mode 100644 shaded-integration-tests/src/test/jackson/java/com/arangodb/ArangoGraphTest.java create mode 100644 shaded-integration-tests/src/test/jackson/java/com/arangodb/ArangoSearchTest.java create mode 100644 shaded-integration-tests/src/test/jackson/java/com/arangodb/ArangoSslTest.java create mode 100644 shaded-integration-tests/src/test/jackson/java/com/arangodb/ArangoVertexCollectionTest.java create mode 100644 shaded-integration-tests/src/test/jackson/java/com/arangodb/ArangoViewTest.java create mode 100644 shaded-integration-tests/src/test/jackson/java/com/arangodb/BaseJunit5.java create mode 100644 shaded-integration-tests/src/test/jackson/java/com/arangodb/ConcurrencyTests.java create mode 100644 shaded-integration-tests/src/test/jackson/java/com/arangodb/DocumentTest.java create mode 100644 shaded-integration-tests/src/test/jackson/java/com/arangodb/InvertedIndexTest.java create mode 100644 shaded-integration-tests/src/test/jackson/java/com/arangodb/JwtAuthTest.java create mode 100644 shaded-integration-tests/src/test/jackson/java/com/arangodb/ParallelTest.java create mode 100644 shaded-integration-tests/src/test/jackson/java/com/arangodb/SerializableTest.java create mode 100644 shaded-integration-tests/src/test/jackson/java/com/arangodb/StreamTransactionConflictsTest.java create mode 100644 shaded-integration-tests/src/test/jackson/java/com/arangodb/StreamTransactionGraphTest.java create mode 100644 shaded-integration-tests/src/test/jackson/java/com/arangodb/StreamTransactionTest.java create mode 100644 shaded-integration-tests/src/test/jackson/java/com/arangodb/annotations/AnnotatedEntity.java create mode 100644 shaded-integration-tests/src/test/jackson/java/com/arangodb/annotations/ArangoAnnotationsTest.java create mode 100644 shaded-integration-tests/src/test/jackson/java/com/arangodb/async/ArangoCollectionTest.java create mode 100644 shaded-integration-tests/src/test/jackson/java/com/arangodb/async/ArangoDBTest.java create mode 100644 shaded-integration-tests/src/test/jackson/java/com/arangodb/async/ArangoDatabaseTest.java create mode 100644 shaded-integration-tests/src/test/jackson/java/com/arangodb/async/ArangoEdgeCollectionTest.java create mode 100644 shaded-integration-tests/src/test/jackson/java/com/arangodb/async/ArangoGraphTest.java create mode 100644 shaded-integration-tests/src/test/jackson/java/com/arangodb/async/ArangoRouteTest.java create mode 100644 shaded-integration-tests/src/test/jackson/java/com/arangodb/async/ArangoSearchTest.java create mode 100644 shaded-integration-tests/src/test/jackson/java/com/arangodb/async/ArangoVertexCollectionTest.java create mode 100644 shaded-integration-tests/src/test/jackson/java/com/arangodb/async/ArangoViewTest.java create mode 100644 shaded-integration-tests/src/test/jackson/java/com/arangodb/async/BaseTest.java create mode 100644 shaded-integration-tests/src/test/jackson/java/com/arangodb/async/CommunicationTest.java create mode 100644 shaded-integration-tests/src/test/jackson/java/com/arangodb/async/ConcurrencyTest.java create mode 100644 shaded-integration-tests/src/test/jackson/java/com/arangodb/async/ConcurrencyTests.java create mode 100644 shaded-integration-tests/src/test/jackson/java/com/arangodb/async/InvertedIndexTest.java create mode 100644 shaded-integration-tests/src/test/jackson/java/com/arangodb/async/JwtAuthTest.java create mode 100644 shaded-integration-tests/src/test/jackson/java/com/arangodb/async/StreamTransactionConflictsTest.java create mode 100644 shaded-integration-tests/src/test/jackson/java/com/arangodb/async/StreamTransactionGraphTest.java create mode 100644 shaded-integration-tests/src/test/jackson/java/com/arangodb/async/StreamTransactionTest.java create mode 100644 shaded-integration-tests/src/test/jackson/java/com/arangodb/async/debug/ConsolidationIntervalMsecTest.java create mode 100644 shaded-integration-tests/src/test/jackson/java/com/arangodb/async/example/ExampleBase.java create mode 100644 shaded-integration-tests/src/test/jackson/java/com/arangodb/async/example/document/AqlQueryWithSpecialReturnTypesExampleTest.java create mode 100644 shaded-integration-tests/src/test/jackson/java/com/arangodb/async/example/document/GetDocumentExampleTest.java create mode 100644 shaded-integration-tests/src/test/jackson/java/com/arangodb/async/example/document/ImportDocumentExampleTest.java create mode 100644 shaded-integration-tests/src/test/jackson/java/com/arangodb/async/example/document/InsertDocumentExampleTest.java create mode 100644 shaded-integration-tests/src/test/jackson/java/com/arangodb/async/example/document/TestEntity.java create mode 100644 shaded-integration-tests/src/test/jackson/java/com/arangodb/async/example/graph/AQLActorsAndMoviesExampleTest.java create mode 100644 shaded-integration-tests/src/test/jackson/java/com/arangodb/async/example/graph/BaseGraphTest.java create mode 100644 shaded-integration-tests/src/test/jackson/java/com/arangodb/async/example/graph/Circle.java create mode 100644 shaded-integration-tests/src/test/jackson/java/com/arangodb/async/example/graph/CircleEdge.java create mode 100644 shaded-integration-tests/src/test/jackson/java/com/arangodb/async/example/graph/GraphTraversalsInAQLExampleTest.java create mode 100644 shaded-integration-tests/src/test/jackson/java/com/arangodb/async/example/graph/ShortestPathInAQLExampleTest.java create mode 100644 shaded-integration-tests/src/test/jackson/java/com/arangodb/async/example/ssl/SslExampleTest.java create mode 100644 shaded-integration-tests/src/test/jackson/java/com/arangodb/async/serde/CustomSerdeTest.java create mode 100644 shaded-integration-tests/src/test/jackson/java/com/arangodb/example/ExampleBase.java create mode 100644 shaded-integration-tests/src/test/jackson/java/com/arangodb/example/FirstProject.java create mode 100644 shaded-integration-tests/src/test/jackson/java/com/arangodb/example/document/AqlQueryWithSpecialReturnTypesExampleTest.java create mode 100644 shaded-integration-tests/src/test/jackson/java/com/arangodb/example/document/GetDocumentExampleTest.java create mode 100644 shaded-integration-tests/src/test/jackson/java/com/arangodb/example/document/InsertDocumentExampleTest.java create mode 100644 shaded-integration-tests/src/test/jackson/java/com/arangodb/example/document/TestEntity.java create mode 100644 shaded-integration-tests/src/test/jackson/java/com/arangodb/example/graph/AQLActorsAndMoviesExampleTest.java create mode 100644 shaded-integration-tests/src/test/jackson/java/com/arangodb/example/graph/BaseGraphTest.java create mode 100644 shaded-integration-tests/src/test/jackson/java/com/arangodb/example/graph/Circle.java create mode 100644 shaded-integration-tests/src/test/jackson/java/com/arangodb/example/graph/CircleEdge.java create mode 100644 shaded-integration-tests/src/test/jackson/java/com/arangodb/example/graph/GraphTraversalsInAQLExampleTest.java create mode 100644 shaded-integration-tests/src/test/jackson/java/com/arangodb/example/graph/ShortestPathInAQLExampleTest.java create mode 100644 shaded-integration-tests/src/test/jackson/java/com/arangodb/example/ssl/SslExampleTest.java create mode 100644 shaded-integration-tests/src/test/jackson/java/com/arangodb/internal/HostHandlerTest.java create mode 100644 shaded-integration-tests/src/test/jackson/java/com/arangodb/internal/QueueTimeMetricsImplTest.java create mode 100644 shaded-integration-tests/src/test/jackson/java/com/arangodb/internal/velocystream/CommunicationTest.java create mode 100644 shaded-integration-tests/src/test/jackson/java/com/arangodb/serde/CustomSerdeTest.java create mode 100644 shaded-integration-tests/src/test/jackson/java/com/arangodb/serde/CustomTypeHintTest.java create mode 100644 shaded-integration-tests/src/test/jackson/java/com/arangodb/serde/SerdeTest.java create mode 100644 shaded-integration-tests/src/test/jackson/java/com/arangodb/util/MapBuilder.java create mode 100644 shaded-integration-tests/src/test/jackson/java/com/arangodb/util/MapBuilderTest.java create mode 100644 shaded-integration-tests/src/test/jackson/java/com/arangodb/util/TestUtils.java create mode 100644 shaded-integration-tests/src/test/jsonb/java/arch/AdbTest.java create mode 100644 shaded-integration-tests/src/test/jsonb/java/arch/BaseTest.java create mode 100644 shaded-integration-tests/src/test/jsonb/java/arch/Person.java create mode 100644 shaded-integration-tests/src/test/jsonb/java/arch/RelocationsTest.java create mode 100644 shaded-integration-tests/src/test/jsonb/java/arch/SerdeTest.java create mode 100644 shaded-integration-tests/src/test/resources/arangodb-bad.properties create mode 100644 shaded-integration-tests/src/test/resources/arangodb.properties create mode 100644 shaded-integration-tests/src/test/resources/logback-test.xml create mode 100644 shaded/pom.xml diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index cce5dd8aa..7d9b0eb40 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -213,7 +213,7 @@ jobs: run: mvn -version - name: Test working-directory: driver - run: mvn --no-transfer-progress test -Dadb.jackson.version=${{matrix.jackson-version}} + run: mvn --no-transfer-progress test -Djackson.version=${{matrix.jackson-version}} sonar: timeout-minutes: 10 @@ -263,3 +263,41 @@ jobs: working-directory: driver run: mvn -B --no-transfer-progress -Dgpg.skip=true verify org.sonarsource.scanner.maven:sonar-maven-plugin:sonar -Dsonar.projectKey=arangodb_arangodb-java-driver + shaded-integration-tests: + timeout-minutes: 20 + runs-on: ubuntu-latest + + strategy: + fail-fast: false + matrix: + docker-img: + - docker.io/arangodb/arangodb:3.10.1 + topology: + - single + - cluster + java-version: + - 17 + + steps: + - uses: actions/checkout@v2 + - name: Set up JDK + uses: actions/setup-java@v2 + with: + java-version: ${{matrix.java-version}} + distribution: 'adopt' + cache: maven + - name: Start Database + run: ./docker/start_db.sh + env: + STARTER_MODE: ${{matrix.topology}} + DOCKER_IMAGE: ${{matrix.docker-img}} + - name: Info + run: mvn -version + - name: Install + run: mvn --no-transfer-progress install -DskipTests=true -Dgpg.skip=true -Dmaven.javadoc.skip=true + - name: Test jackson-serde + working-directory: shaded-integration-tests + run: mvn --no-transfer-progress -P jackson-serde test + - name: Test jsonb-serde + working-directory: shaded-integration-tests + run: mvn --no-transfer-progress -P jsonb-serde test diff --git a/.gitignore b/.gitignore index 8fcbc5c8a..11ee1822e 100644 --- a/.gitignore +++ b/.gitignore @@ -14,3 +14,4 @@ test-results-native .flattened-pom.xml /resilience-tests/bin/toxiproxy-server-linux-amd64 +dependency-reduced-pom.xml diff --git a/driver/pom.xml b/driver/pom.xml index c372e221d..11c48edb8 100644 --- a/driver/pom.xml +++ b/driver/pom.xml @@ -13,12 +13,11 @@ arangodb-java-driver arangodb-java-driver ArangoDB Java Driver - https://github.com/arangodb/arangodb-java-driver - 2.14.1 arangodb-1 https://sonarcloud.io + false false @@ -55,15 +54,10 @@ native - - org.apache.maven.plugins - maven-surefire-plugin - 3.0.0-M5 - org.graalvm.buildtools native-maven-plugin - 0.9.16 + 0.9.19 true @@ -91,17 +85,6 @@ - - - ossrh - https://oss.sonatype.org/content/repositories/snapshots - - - ossrh - https://oss.sonatype.org/service/local/staging/deploy/maven2/ - - - @@ -118,10 +101,10 @@ ${project.basedir}/src/main/java/com/arangodb/PackageVersion.java.in - ${project.build.directory}/generated-sources/replacer/com/arangodb/PackageVersion.java + ${project.build.directory}/generated-sources/replacer/com/arangodb/PackageVersion.java + - @project.version@ ${project.version} @@ -146,127 +129,6 @@ - - org.sonatype.plugins - nexus-staging-maven-plugin - 1.6.13 - true - - ossrh - https://oss.sonatype.org/ - 84aff6e87e214c - false - - - - org.apache.maven.plugins - maven-compiler-plugin - 3.10.1 - - - -Xlint:unchecked - -Xlint:deprecation - - true - 1.8 - 1.8 - - - - org.apache.maven.plugins - maven-resources-plugin - 3.3.0 - - UTF-8 - - - - org.apache.maven.plugins - maven-source-plugin - 3.2.1 - - - - jar - - - - - - org.apache.maven.plugins - maven-javadoc-plugin - 3.4.0 - - - attach-javadocs - - jar - - - com.arangodb.internal - - - - - - org.apache.maven.plugins - maven-surefire-plugin - 3.0.0-M7 - - - **/*Test.java - **/*Example.java - - - - - org.apache.maven.plugins - maven-deploy-plugin - 3.0.0 - - 10 - - - - org.apache.maven.plugins - maven-gpg-plugin - 3.0.1 - - - sign-artifacts - verify - - sign - - - - - - org.codehaus.mojo - flatten-maven-plugin - 1.2.7 - - oss - - - - - flatten - process-resources - - flatten - - - - - flatten.clean - clean - - clean - - - - org.jacoco jacoco-maven-plugin @@ -289,7 +151,7 @@ com.github.spotbugs spotbugs-maven-plugin - 4.7.1.1 + 4.7.3.0 spotbugs/spotbugs-exclude.xml @@ -305,7 +167,7 @@ com.github.spotbugs spotbugs - 4.7.1 + 4.7.3 @@ -330,14 +192,50 @@ + + maven-shade-plugin + 3.4.1 + + + package + + shade + + + true + true + + + com.arangodb:serde-api + + + + + com.arangodb:serde-api + + META-INF/MANIFEST.MF + + + + + + + + + com.arangodb + serde-api + + + com.arangodb + jackson-serde + org.slf4j slf4j-api - 1.7.36 com.fasterxml.jackson.core @@ -358,47 +256,14 @@ com.arangodb jackson-dataformat-velocypack - 3.1.0 true - - jakarta.json.bind - jakarta.json.bind-api - 2.0.0 - com.google.code.findbugs jsr305 3.0.2 provided - - ch.qos.logback - logback-classic - 1.2.11 - test - - - org.junit.platform - junit-platform-launcher - test - - - org.junit.jupiter - junit-jupiter-engine - test - - - org.junit.jupiter - junit-jupiter-params - test - - - org.assertj - assertj-core - 3.23.1 - test - org.reflections reflections @@ -408,13 +273,7 @@ org.graalvm.sdk graal-sdk - 22.2.0 - test - - - org.eclipse - yasson - 2.0.4 + 22.3.0 test @@ -425,43 +284,4 @@ - - - - com.fasterxml.jackson - jackson-bom - ${adb.jackson.version} - import - pom - - - io.vertx - vertx-stack-depchain - 4.3.4 - pom - import - - - io.netty - netty-bom - 4.1.82.Final - pom - import - - - org.junit - junit-bom - 5.9.1 - pom - import - - - - - - https://github.com/arangodb/arangodb-java-driver - scm:git:git://github.com/arangodb/arangodb-java-driver.git - scm:git:git://github.com/arangodb/arangodb-java-driver.git - - diff --git a/driver/src/main/java/com/arangodb/ArangoDB.java b/driver/src/main/java/com/arangodb/ArangoDB.java index cc371bbe8..956583e0a 100644 --- a/driver/src/main/java/com/arangodb/ArangoDB.java +++ b/driver/src/main/java/com/arangodb/ArangoDB.java @@ -23,10 +23,16 @@ import com.arangodb.config.ConfigPropertiesProvider; import com.arangodb.config.ConfigPropertyKey; import com.arangodb.entity.*; -import com.arangodb.internal.*; +import com.arangodb.internal.ArangoDBImpl; +import com.arangodb.internal.ArangoDefaults; +import com.arangodb.internal.InternalArangoDBBuilder; import com.arangodb.internal.http.HttpCommunication; import com.arangodb.internal.http.HttpConnectionFactory; -import com.arangodb.internal.net.*; +import com.arangodb.internal.net.ConnectionFactory; +import com.arangodb.internal.net.Host; +import com.arangodb.internal.net.HostHandler; +import com.arangodb.internal.net.HostResolver; +import com.arangodb.internal.serde.ContentTypeFactory; import com.arangodb.internal.serde.InternalSerde; import com.arangodb.internal.velocystream.VstCommunicationSync; import com.arangodb.internal.velocystream.VstConnectionFactorySync; @@ -35,7 +41,6 @@ import com.arangodb.model.UserCreateOptions; import com.arangodb.model.UserUpdateOptions; import com.arangodb.serde.ArangoSerde; -import com.arangodb.serde.JacksonSerde; import javax.annotation.concurrent.ThreadSafe; import javax.net.ssl.SSLContext; @@ -581,8 +586,8 @@ public ArangoDB build() { } final ArangoSerde userSerde = this.userDataSerde != null ? this.userDataSerde : - JacksonSerde.of(ContentType.of(protocol)); - final InternalSerde serde = InternalSerde.of(ContentType.of(protocol), userSerde); + serdeProvider().of(ContentTypeFactory.of(protocol)); + final InternalSerde serde = InternalSerde.of(ContentTypeFactory.of(protocol), userSerde); int protocolMaxConnections; switch (protocol) { diff --git a/driver/src/main/java/com/arangodb/async/ArangoDBAsync.java b/driver/src/main/java/com/arangodb/async/ArangoDBAsync.java index be0209d8c..c6eaf5db4 100644 --- a/driver/src/main/java/com/arangodb/async/ArangoDBAsync.java +++ b/driver/src/main/java/com/arangodb/async/ArangoDBAsync.java @@ -39,7 +39,6 @@ import com.arangodb.model.UserCreateOptions; import com.arangodb.model.UserUpdateOptions; import com.arangodb.serde.ArangoSerde; -import com.arangodb.serde.JacksonSerde; import javax.annotation.concurrent.ThreadSafe; import javax.net.ssl.SSLContext; @@ -516,7 +515,7 @@ public ArangoDBAsync build() { throw new ArangoDBException("No host has been set!"); } - final ArangoSerde userSerde = this.userDataSerde != null ? this.userDataSerde : JacksonSerde.of(ContentType.VPACK); + final ArangoSerde userSerde = this.userDataSerde != null ? this.userDataSerde : serdeProvider().of(ContentType.VPACK); final InternalSerde serde = InternalSerde.of(ContentType.VPACK, userSerde); final int max = maxConnections != null ? Math.max(1, maxConnections) diff --git a/driver/src/main/java/com/arangodb/entity/DocumentEntity.java b/driver/src/main/java/com/arangodb/entity/DocumentEntity.java index fe3ddda5b..56cc8545b 100644 --- a/driver/src/main/java/com/arangodb/entity/DocumentEntity.java +++ b/driver/src/main/java/com/arangodb/entity/DocumentEntity.java @@ -20,16 +20,24 @@ package com.arangodb.entity; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + /** * @author Mark Vollmary */ public class DocumentEntity { - @Key + @JsonProperty("_key") + @JsonInclude(JsonInclude.Include.NON_NULL) private String key; - @Id + + @JsonProperty("_id") + @JsonInclude(JsonInclude.Include.NON_NULL) private String id; - @Rev + + @JsonProperty("_rev") + @JsonInclude(JsonInclude.Include.NON_NULL) private String rev; public DocumentEntity() { diff --git a/driver/src/main/java/com/arangodb/internal/InternalArangoDBBuilder.java b/driver/src/main/java/com/arangodb/internal/InternalArangoDBBuilder.java index df0d49496..e493a6207 100644 --- a/driver/src/main/java/com/arangodb/internal/InternalArangoDBBuilder.java +++ b/driver/src/main/java/com/arangodb/internal/InternalArangoDBBuilder.java @@ -27,14 +27,12 @@ import com.arangodb.internal.net.*; import com.arangodb.internal.util.HostUtils; import com.arangodb.serde.ArangoSerde; +import com.arangodb.serde.ArangoSerdeProvider; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.net.ssl.SSLContext; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; -import java.util.Locale; +import java.util.*; /** @@ -144,6 +142,19 @@ protected static String getProperty(ConfigPropertiesProvider props, ConfigProper return props.getProperty(key, defaultValue); } + protected static ArangoSerdeProvider serdeProvider() { + ServiceLoader loader = ServiceLoader.load(ArangoSerdeProvider.class); + Iterator it = loader.iterator(); + if (!it.hasNext()) { + throw new ArangoDBException("No ArangoSerdeProvider found!"); + } + ArangoSerdeProvider serdeProvider = it.next(); + if (it.hasNext()) { + throw new ArangoDBException("Found multiple serde providers! Please set explicitly the one to use."); + } + return serdeProvider; + } + protected void doLoadProperties(final ConfigPropertiesProvider properties) { loadHosts(properties, hosts); timeout = loadTimeout(properties, timeout); diff --git a/driver/src/main/java/com/arangodb/internal/http/HttpConnection.java b/driver/src/main/java/com/arangodb/internal/http/HttpConnection.java index a62ef669e..e031c636d 100644 --- a/driver/src/main/java/com/arangodb/internal/http/HttpConnection.java +++ b/driver/src/main/java/com/arangodb/internal/http/HttpConnection.java @@ -23,6 +23,7 @@ import com.arangodb.*; import com.arangodb.internal.net.Connection; import com.arangodb.internal.net.HostDescription; +import com.arangodb.internal.serde.ContentTypeFactory; import com.arangodb.internal.serde.InternalSerde; import com.arangodb.internal.util.EncodeUtils; import com.arangodb.internal.util.ResponseUtils; @@ -84,7 +85,7 @@ private HttpConnection(final HostDescription host, final Integer timeout, final final InternalSerde util, final Protocol protocol, final Long ttl) { super(); this.util = util; - this.contentType = ContentType.of(protocol); + this.contentType = ContentTypeFactory.of(protocol); this.timeout = timeout; vertx = Vertx.vertx(new VertxOptions().setPreferNativeTransport(true).setEventLoopPoolSize(1)); vertx.runOnContext(e -> { diff --git a/driver/src/main/java/com/arangodb/internal/serde/ContentTypeFactory.java b/driver/src/main/java/com/arangodb/internal/serde/ContentTypeFactory.java new file mode 100644 index 000000000..453cc2a0f --- /dev/null +++ b/driver/src/main/java/com/arangodb/internal/serde/ContentTypeFactory.java @@ -0,0 +1,24 @@ +package com.arangodb.internal.serde; + +import com.arangodb.ContentType; +import com.arangodb.Protocol; + +public final class ContentTypeFactory { + private ContentTypeFactory() { + } + + public static ContentType of(Protocol protocol) { + switch (protocol) { + case HTTP_JSON: + case HTTP2_JSON: + return ContentType.JSON; + case VST: + case HTTP_VPACK: + case HTTP2_VPACK: + return ContentType.VPACK; + default: + throw new IllegalArgumentException("Unexpected value: " + protocol); + } + } + +} diff --git a/driver/src/main/java/com/arangodb/internal/serde/JsonMapperProvider.java b/driver/src/main/java/com/arangodb/internal/serde/InternalJsonMapperProvider.java similarity index 74% rename from driver/src/main/java/com/arangodb/internal/serde/JsonMapperProvider.java rename to driver/src/main/java/com/arangodb/internal/serde/InternalJsonMapperProvider.java index e3ba08eb5..343c387d6 100644 --- a/driver/src/main/java/com/arangodb/internal/serde/JsonMapperProvider.java +++ b/driver/src/main/java/com/arangodb/internal/serde/InternalJsonMapperProvider.java @@ -2,7 +2,7 @@ import com.fasterxml.jackson.databind.ObjectMapper; -enum JsonMapperProvider implements MapperProvider { +enum InternalJsonMapperProvider implements InternalMapperProvider { INSTANCE; @Override diff --git a/driver/src/main/java/com/arangodb/internal/serde/MapperProvider.java b/driver/src/main/java/com/arangodb/internal/serde/InternalMapperProvider.java similarity index 69% rename from driver/src/main/java/com/arangodb/internal/serde/MapperProvider.java rename to driver/src/main/java/com/arangodb/internal/serde/InternalMapperProvider.java index a4431a6cd..fca65bd24 100644 --- a/driver/src/main/java/com/arangodb/internal/serde/MapperProvider.java +++ b/driver/src/main/java/com/arangodb/internal/serde/InternalMapperProvider.java @@ -5,12 +5,12 @@ import java.util.function.Supplier; -public interface MapperProvider extends Supplier { +public interface InternalMapperProvider extends Supplier { static ObjectMapper of(final ContentType contentType) { if (contentType == ContentType.JSON) { - return JsonMapperProvider.INSTANCE.get(); + return InternalJsonMapperProvider.INSTANCE.get(); } else if (contentType == ContentType.VPACK) { - return VPackMapperProvider.INSTANCE.get(); + return InternalVPackMapperProvider.INSTANCE.get(); } else { throw new IllegalArgumentException("Unexpected value: " + contentType); } diff --git a/driver/src/main/java/com/arangodb/internal/serde/InternalSerde.java b/driver/src/main/java/com/arangodb/internal/serde/InternalSerde.java index 4a6087981..aeca0e880 100644 --- a/driver/src/main/java/com/arangodb/internal/serde/InternalSerde.java +++ b/driver/src/main/java/com/arangodb/internal/serde/InternalSerde.java @@ -2,13 +2,12 @@ import com.arangodb.serde.ArangoSerde; import com.arangodb.ContentType; -import com.arangodb.serde.JacksonSerde; import com.fasterxml.jackson.databind.JsonNode; import java.lang.reflect.Type; import java.util.Collection; -public interface InternalSerde extends JacksonSerde { +public interface InternalSerde extends ArangoSerde { /** * Creates a new InternalSerde with default settings for the specified data type. @@ -17,7 +16,7 @@ public interface InternalSerde extends JacksonSerde { * @return the created InternalSerde */ static InternalSerde of(final ContentType contentType, ArangoSerde userSerde) { - return new InternalSerdeImpl(MapperProvider.of(contentType), userSerde); + return new InternalSerdeImpl(InternalMapperProvider.of(contentType), userSerde); } /** diff --git a/driver/src/main/java/com/arangodb/internal/serde/InternalSerdeImpl.java b/driver/src/main/java/com/arangodb/internal/serde/InternalSerdeImpl.java index 9ade5dbbf..6e3e4c349 100644 --- a/driver/src/main/java/com/arangodb/internal/serde/InternalSerdeImpl.java +++ b/driver/src/main/java/com/arangodb/internal/serde/InternalSerdeImpl.java @@ -7,6 +7,8 @@ import com.arangodb.util.RawBytes; import com.arangodb.util.RawJson; import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; @@ -18,26 +20,37 @@ import static com.arangodb.internal.serde.SerdeUtils.checkSupportedJacksonVersion; -final class InternalSerdeImpl extends JacksonSerdeImpl implements InternalSerde { +final class InternalSerdeImpl implements InternalSerde { static { checkSupportedJacksonVersion(); } private final ArangoSerde userSerde; + private final ObjectMapper mapper; InternalSerdeImpl(final ObjectMapper mapper, final ArangoSerde userSerde) { - super(mapper); + this.mapper = mapper; this.userSerde = userSerde; + mapper.deactivateDefaultTyping(); + mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); mapper.registerModule(InternalModule.INSTANCE.get()); mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); - mapper.deactivateDefaultTyping(); mapper.setAnnotationIntrospector(new InternalAnnotationIntrospector( new UserDataSerializer(this), new UserDataDeserializer(this) )); } + @Override + public byte[] serialize(final Object value) { + try { + return mapper.writeValueAsBytes(value); + } catch (JsonProcessingException e) { + throw new ArangoDBException(e); + } + } + @Override public String toJsonString(final byte[] content) { try { @@ -140,7 +153,11 @@ public T deserialize(final byte[] content, final Type type) { if (content == null) { return null; } - return super.deserialize(content, type); + try { + return mapper.readerFor(mapper.constructType(type)).readValue(content); + } catch (IOException e) { + throw new ArangoDBException(e); + } } private boolean isManagedClass(Class clazz) { diff --git a/driver/src/main/java/com/arangodb/internal/serde/VPackMapperProvider.java b/driver/src/main/java/com/arangodb/internal/serde/InternalVPackMapperProvider.java similarity index 78% rename from driver/src/main/java/com/arangodb/internal/serde/VPackMapperProvider.java rename to driver/src/main/java/com/arangodb/internal/serde/InternalVPackMapperProvider.java index 0762414fc..e157b3dc2 100644 --- a/driver/src/main/java/com/arangodb/internal/serde/VPackMapperProvider.java +++ b/driver/src/main/java/com/arangodb/internal/serde/InternalVPackMapperProvider.java @@ -3,7 +3,7 @@ import com.arangodb.jackson.dataformat.velocypack.VPackMapper; import com.fasterxml.jackson.databind.ObjectMapper; -enum VPackMapperProvider implements MapperProvider { +enum InternalVPackMapperProvider implements InternalMapperProvider { INSTANCE; @Override diff --git a/driver/src/main/java/com/arangodb/model/TransactionOptions.java b/driver/src/main/java/com/arangodb/model/TransactionOptions.java index 95d0b5378..28d314d18 100644 --- a/driver/src/main/java/com/arangodb/model/TransactionOptions.java +++ b/driver/src/main/java/com/arangodb/model/TransactionOptions.java @@ -20,6 +20,8 @@ package com.arangodb.model; +import com.arangodb.internal.serde.UserData; + /** * @author Mark Vollmary * @author Michele Rastelli @@ -57,6 +59,7 @@ TransactionOptions action(final String action) { return this; } + @UserData public Object getParams() { return params; } diff --git a/driver/src/main/java/com/arangodb/serde/JacksonSerde.java b/driver/src/main/java/com/arangodb/serde/JacksonSerde.java deleted file mode 100644 index 2a642c2ac..000000000 --- a/driver/src/main/java/com/arangodb/serde/JacksonSerde.java +++ /dev/null @@ -1,42 +0,0 @@ -package com.arangodb.serde; - -import com.arangodb.ContentType; -import com.arangodb.internal.serde.JacksonSerdeImpl; -import com.arangodb.internal.serde.MapperProvider; -import com.fasterxml.jackson.databind.ObjectMapper; - -import java.util.function.Consumer; - -/** - * User data serde based on Jackson Databind. - */ -public interface JacksonSerde extends ArangoSerde { - - /** - * Creates a new JacksonSerde with default settings for the specified data type. - * - * @param contentType serialization target data type - * @return the created JacksonSerde - */ - static JacksonSerde of(final ContentType contentType) { - return create(MapperProvider.of(contentType)); - } - - /** - * Creates a new JacksonSerde using the provided ObjectMapper. - * - * @param mapper Jackson ObjectMapper to use - * @return the created JacksonSerde - */ - static JacksonSerde create(final ObjectMapper mapper) { - return new JacksonSerdeImpl(mapper); - } - - /** - * Allows configuring the underlying Jackson ObjectMapper - * - * @param configureFunction function to configure the Jackson ObjectMapper - */ - void configure(final Consumer configureFunction); - -} diff --git a/driver/src/main/resources/vertx/vertx-version.txt b/driver/src/main/resources/META-INF/vertx/vertx-version.txt similarity index 100% rename from driver/src/main/resources/vertx/vertx-version.txt rename to driver/src/main/resources/META-INF/vertx/vertx-version.txt diff --git a/driver/src/test/java/com/arangodb/ArangoCollectionTest.java b/driver/src/test/java/com/arangodb/ArangoCollectionTest.java index 66c34ba34..d32cf4992 100644 --- a/driver/src/test/java/com/arangodb/ArangoCollectionTest.java +++ b/driver/src/test/java/com/arangodb/ArangoCollectionTest.java @@ -24,7 +24,10 @@ import com.arangodb.internal.serde.SerdeUtils; import com.arangodb.model.*; import com.arangodb.model.DocumentImportOptions.OnDuplicate; -import com.arangodb.serde.JacksonSerde; +import com.arangodb.serde.jackson.Id; +import com.arangodb.serde.jackson.JacksonSerde; +import com.arangodb.serde.jackson.Key; +import com.arangodb.serde.jackson.Rev; import com.arangodb.util.MapBuilder; import com.arangodb.util.RawBytes; import com.arangodb.util.RawData; diff --git a/driver/src/test/java/com/arangodb/BaseJunit5.java b/driver/src/test/java/com/arangodb/BaseJunit5.java index f88cac877..ed1813514 100644 --- a/driver/src/test/java/com/arangodb/BaseJunit5.java +++ b/driver/src/test/java/com/arangodb/BaseJunit5.java @@ -4,7 +4,6 @@ import com.arangodb.internal.config.FileConfigPropertiesProvider; import com.arangodb.model.CollectionCreateOptions; import com.arangodb.model.GraphCreateOptions; -import com.arangodb.serde.JsonbSerde; import com.arangodb.util.TestUtils; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; @@ -24,8 +23,7 @@ class BaseJunit5 { new ArangoDB.Builder().loadProperties(new FileConfigPropertiesProvider()).useProtocol(Protocol.HTTP_VPACK).build(), new ArangoDB.Builder().loadProperties(new FileConfigPropertiesProvider()).useProtocol(Protocol.HTTP_JSON).build(), new ArangoDB.Builder().loadProperties(new FileConfigPropertiesProvider()).useProtocol(Protocol.HTTP2_VPACK).build(), - new ArangoDB.Builder().loadProperties(new FileConfigPropertiesProvider()).useProtocol(Protocol.HTTP2_JSON).build(), - new ArangoDB.Builder().loadProperties(new FileConfigPropertiesProvider()).useProtocol(Protocol.HTTP2_JSON).serde(JsonbSerde.create()).build() + new ArangoDB.Builder().loadProperties(new FileConfigPropertiesProvider()).useProtocol(Protocol.HTTP2_JSON).build() ); protected static Stream dbsStream() { diff --git a/driver/src/test/java/com/arangodb/async/ArangoCollectionTest.java b/driver/src/test/java/com/arangodb/async/ArangoCollectionTest.java index 69090d7c8..1e7bfd36a 100644 --- a/driver/src/test/java/com/arangodb/async/ArangoCollectionTest.java +++ b/driver/src/test/java/com/arangodb/async/ArangoCollectionTest.java @@ -25,7 +25,8 @@ import com.arangodb.internal.serde.SerdeUtils; import com.arangodb.model.*; import com.arangodb.model.DocumentImportOptions.OnDuplicate; -import com.arangodb.serde.JacksonSerde; +import com.arangodb.serde.jackson.JacksonSerde; +import com.arangodb.serde.jackson.Key; import com.arangodb.util.RawData; import com.arangodb.util.RawJson; import com.fasterxml.jackson.annotation.JsonTypeInfo; diff --git a/driver/src/test/java/com/arangodb/async/example/graph/Circle.java b/driver/src/test/java/com/arangodb/async/example/graph/Circle.java index 4df7cfcc1..e828aaeb3 100644 --- a/driver/src/test/java/com/arangodb/async/example/graph/Circle.java +++ b/driver/src/test/java/com/arangodb/async/example/graph/Circle.java @@ -20,9 +20,9 @@ package com.arangodb.async.example.graph; -import com.arangodb.entity.Id; -import com.arangodb.entity.Key; -import com.arangodb.entity.Rev; +import com.arangodb.serde.jackson.Id; +import com.arangodb.serde.jackson.Key; +import com.arangodb.serde.jackson.Rev; /** * @author a-brandt diff --git a/driver/src/test/java/com/arangodb/async/example/graph/CircleEdge.java b/driver/src/test/java/com/arangodb/async/example/graph/CircleEdge.java index aa89d8d35..bfaa65210 100644 --- a/driver/src/test/java/com/arangodb/async/example/graph/CircleEdge.java +++ b/driver/src/test/java/com/arangodb/async/example/graph/CircleEdge.java @@ -20,7 +20,7 @@ package com.arangodb.async.example.graph; -import com.arangodb.entity.*; +import com.arangodb.serde.jackson.*; /** * @author a-brandt diff --git a/driver/src/test/java/com/arangodb/async/serde/CustomSerdeTest.java b/driver/src/test/java/com/arangodb/async/serde/CustomSerdeTest.java index 1b8e71a97..982381db9 100644 --- a/driver/src/test/java/com/arangodb/async/serde/CustomSerdeTest.java +++ b/driver/src/test/java/com/arangodb/async/serde/CustomSerdeTest.java @@ -28,7 +28,8 @@ import com.arangodb.internal.config.FileConfigPropertiesProvider; import com.arangodb.model.DocumentCreateOptions; import com.arangodb.ContentType; -import com.arangodb.serde.JacksonSerde; +import com.arangodb.serde.jackson.JacksonSerde; +import com.arangodb.serde.jackson.JacksonSerdeProvider; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -57,7 +58,7 @@ class CustomSerdeTest { @BeforeEach void init() throws ExecutionException, InterruptedException { - JacksonSerde serde = JacksonSerde.of(ContentType.VPACK); + JacksonSerde serde = new JacksonSerdeProvider().of(ContentType.VPACK); serde.configure((mapper) -> { mapper.configure(WRITE_SINGLE_ELEM_ARRAYS_UNWRAPPED, true); mapper.configure(USE_BIG_INTEGER_FOR_INTS, true); diff --git a/driver/src/test/java/com/arangodb/example/graph/Circle.java b/driver/src/test/java/com/arangodb/example/graph/Circle.java index 8e1a00431..f40783bdd 100644 --- a/driver/src/test/java/com/arangodb/example/graph/Circle.java +++ b/driver/src/test/java/com/arangodb/example/graph/Circle.java @@ -20,9 +20,9 @@ package com.arangodb.example.graph; -import com.arangodb.entity.Id; -import com.arangodb.entity.Key; -import com.arangodb.entity.Rev; +import com.arangodb.serde.jackson.Id; +import com.arangodb.serde.jackson.Key; +import com.arangodb.serde.jackson.Rev; /** * @author a-brandt diff --git a/driver/src/test/java/com/arangodb/example/graph/CircleEdge.java b/driver/src/test/java/com/arangodb/example/graph/CircleEdge.java index e55e3bc1b..96afa9f00 100644 --- a/driver/src/test/java/com/arangodb/example/graph/CircleEdge.java +++ b/driver/src/test/java/com/arangodb/example/graph/CircleEdge.java @@ -20,7 +20,7 @@ package com.arangodb.example.graph; -import com.arangodb.entity.*; +import com.arangodb.serde.jackson.*; /** * @author a-brandt diff --git a/driver/src/test/java/com/arangodb/mapping/annotations/AnnotatedEntity.java b/driver/src/test/java/com/arangodb/mapping/annotations/AnnotatedEntity.java index e3ce6ea78..f26fb6f25 100644 --- a/driver/src/test/java/com/arangodb/mapping/annotations/AnnotatedEntity.java +++ b/driver/src/test/java/com/arangodb/mapping/annotations/AnnotatedEntity.java @@ -1,6 +1,6 @@ package com.arangodb.mapping.annotations; -import com.arangodb.entity.*; +import com.arangodb.serde.jackson.*; import java.util.Objects; diff --git a/driver/src/test/java/com/arangodb/mapping/annotations/ArangoAnnotationsTest.java b/driver/src/test/java/com/arangodb/mapping/annotations/ArangoAnnotationsTest.java index a2ca82f22..084f67ba9 100644 --- a/driver/src/test/java/com/arangodb/mapping/annotations/ArangoAnnotationsTest.java +++ b/driver/src/test/java/com/arangodb/mapping/annotations/ArangoAnnotationsTest.java @@ -20,9 +20,9 @@ package com.arangodb.mapping.annotations; -import com.arangodb.serde.ArangoSerde; import com.arangodb.ContentType; -import com.arangodb.serde.JacksonSerde; +import com.arangodb.serde.ArangoSerde; +import com.arangodb.serde.jackson.JacksonSerdeProvider; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.EnumSource; @@ -38,7 +38,7 @@ class ArangoAnnotationsTest { @ParameterizedTest @EnumSource(ContentType.class) void documentFieldAnnotations(ContentType contentType) { - ArangoSerde mapper = JacksonSerde.of(contentType); + ArangoSerde mapper = new JacksonSerdeProvider().of(contentType); AnnotatedEntity e = new AnnotatedEntity(); e.setId("Id"); diff --git a/driver/src/test/java/com/arangodb/serde/CustomSerdeTest.java b/driver/src/test/java/com/arangodb/serde/CustomSerdeTest.java index a1d75fc39..428363da6 100644 --- a/driver/src/test/java/com/arangodb/serde/CustomSerdeTest.java +++ b/driver/src/test/java/com/arangodb/serde/CustomSerdeTest.java @@ -25,6 +25,8 @@ import com.arangodb.internal.config.FileConfigPropertiesProvider; import com.arangodb.internal.serde.InternalSerde; import com.arangodb.model.DocumentCreateOptions; +import com.arangodb.serde.jackson.JacksonSerde; +import com.arangodb.serde.jackson.JacksonSerdeProvider; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.databind.*; @@ -61,7 +63,7 @@ class CustomSerdeTest { @BeforeAll static void init() { - JacksonSerde serde = JacksonSerde.of(ContentType.VPACK); + JacksonSerde serde = new JacksonSerdeProvider().of(ContentType.VPACK); serde.configure((mapper) -> { mapper.configure(WRITE_SINGLE_ELEM_ARRAYS_UNWRAPPED, true); mapper.configure(USE_BIG_INTEGER_FOR_INTS, true); diff --git a/driver/src/test/java/com/arangodb/serde/CustomTypeHintTest.java b/driver/src/test/java/com/arangodb/serde/CustomTypeHintTest.java index 2de790a5e..fed63354e 100644 --- a/driver/src/test/java/com/arangodb/serde/CustomTypeHintTest.java +++ b/driver/src/test/java/com/arangodb/serde/CustomTypeHintTest.java @@ -25,9 +25,9 @@ import com.arangodb.ArangoDB; import com.arangodb.ArangoDatabase; import com.arangodb.DbName; -import com.arangodb.entity.Key; import com.arangodb.internal.config.FileConfigPropertiesProvider; import com.arangodb.model.DocumentCreateOptions; +import com.arangodb.serde.jackson.Key; import com.fasterxml.jackson.annotation.JsonTypeInfo; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; diff --git a/driver/src/test/java/com/arangodb/serde/JsonbSerde.java b/driver/src/test/java/com/arangodb/serde/JsonbSerde.java deleted file mode 100644 index c6dac0dcc..000000000 --- a/driver/src/test/java/com/arangodb/serde/JsonbSerde.java +++ /dev/null @@ -1,29 +0,0 @@ -package com.arangodb.serde; - -import jakarta.json.bind.JsonbConfig; - -/** - * User data serde based on Jakarta JSON Binding (JSON-B). - */ -public interface JsonbSerde extends ArangoSerde { - - /** - * Creates a new JsonbSerde with default settings. - * - * @return the created JsonbSerde - */ - static JsonbSerde create() { - return new JsonbSerdeImpl(); - } - - /** - * Creates a new JsonbSerde using the provided . - * - * @param config JsonbConfig to use - * @return the created JsonbSerde - */ - static JsonbSerde of(final JsonbConfig config) { - return new JsonbSerdeImpl(config); - } - -} diff --git a/jackson-serde/pom.xml b/jackson-serde/pom.xml new file mode 100644 index 000000000..7ce85c92e --- /dev/null +++ b/jackson-serde/pom.xml @@ -0,0 +1,44 @@ + + + 4.0.0 + + com.arangodb + arangodb-java-driver-parent + 7.0.0-SNAPSHOT + + + jackson-serde + jackson-serde + Jackson Serde module for ArangoDB Java Driver + + + false + + + + + com.fasterxml.jackson.core + jackson-databind + + + com.fasterxml.jackson.core + jackson-core + + + com.fasterxml.jackson.core + jackson-annotations + + + com.arangodb + jackson-dataformat-velocypack + true + + + com.arangodb + serde-api + provided + + + \ No newline at end of file diff --git a/driver/src/main/java/com/arangodb/entity/From.java b/jackson-serde/src/main/java/com/arangodb/serde/jackson/From.java similarity index 68% rename from driver/src/main/java/com/arangodb/entity/From.java rename to jackson-serde/src/main/java/com/arangodb/serde/jackson/From.java index 1e82ae341..b84ee1fb0 100644 --- a/driver/src/main/java/com/arangodb/entity/From.java +++ b/jackson-serde/src/main/java/com/arangodb/serde/jackson/From.java @@ -1,11 +1,8 @@ -package com.arangodb.entity; +package com.arangodb.serde.jackson; -import com.arangodb.internal.DocumentFields; import com.fasterxml.jackson.annotation.JacksonAnnotationsInside; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; -import jakarta.json.bind.annotation.JsonbAnnotation; -import jakarta.json.bind.annotation.JsonbProperty; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; @@ -18,9 +15,7 @@ @Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER}) @Retention(RetentionPolicy.RUNTIME) @JacksonAnnotationsInside -@JsonProperty(DocumentFields.FROM) +@JsonProperty("_from") @JsonInclude(JsonInclude.Include.NON_NULL) -@JsonbAnnotation -@JsonbProperty(DocumentFields.FROM) public @interface From { } diff --git a/driver/src/main/java/com/arangodb/entity/Id.java b/jackson-serde/src/main/java/com/arangodb/serde/jackson/Id.java similarity index 68% rename from driver/src/main/java/com/arangodb/entity/Id.java rename to jackson-serde/src/main/java/com/arangodb/serde/jackson/Id.java index f0e55dcb6..ee1033993 100644 --- a/driver/src/main/java/com/arangodb/entity/Id.java +++ b/jackson-serde/src/main/java/com/arangodb/serde/jackson/Id.java @@ -1,11 +1,8 @@ -package com.arangodb.entity; +package com.arangodb.serde.jackson; -import com.arangodb.internal.DocumentFields; import com.fasterxml.jackson.annotation.JacksonAnnotationsInside; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; -import jakarta.json.bind.annotation.JsonbAnnotation; -import jakarta.json.bind.annotation.JsonbProperty; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; @@ -18,9 +15,7 @@ @Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER}) @Retention(RetentionPolicy.RUNTIME) @JacksonAnnotationsInside -@JsonProperty(DocumentFields.ID) +@JsonProperty("_id") @JsonInclude(JsonInclude.Include.NON_NULL) -@JsonbAnnotation -@JsonbProperty(DocumentFields.ID) public @interface Id { } diff --git a/jackson-serde/src/main/java/com/arangodb/serde/jackson/JacksonSerde.java b/jackson-serde/src/main/java/com/arangodb/serde/jackson/JacksonSerde.java new file mode 100644 index 000000000..35e1555ab --- /dev/null +++ b/jackson-serde/src/main/java/com/arangodb/serde/jackson/JacksonSerde.java @@ -0,0 +1,20 @@ +package com.arangodb.serde.jackson; + +import com.arangodb.serde.ArangoSerde; +import com.fasterxml.jackson.databind.ObjectMapper; + +import java.util.function.Consumer; + +/** + * User data serde based on Jackson Databind. Not shaded in arangodb-java-driver-shaded. + */ +public interface JacksonSerde extends ArangoSerde { + + /** + * Allows configuring the underlying Jackson ObjectMapper + * + * @param configureFunction function to configure the Jackson ObjectMapper + */ + void configure(final Consumer configureFunction); + +} diff --git a/jackson-serde/src/main/java/com/arangodb/serde/jackson/JacksonSerdeProvider.java b/jackson-serde/src/main/java/com/arangodb/serde/jackson/JacksonSerdeProvider.java new file mode 100644 index 000000000..4fcbf2fcf --- /dev/null +++ b/jackson-serde/src/main/java/com/arangodb/serde/jackson/JacksonSerdeProvider.java @@ -0,0 +1,32 @@ +package com.arangodb.serde.jackson; + +import com.arangodb.ContentType; +import com.arangodb.serde.jackson.internal.JacksonSerdeImpl; +import com.arangodb.serde.jackson.internal.JacksonMapperProvider; +import com.arangodb.serde.ArangoSerdeProvider; +import com.fasterxml.jackson.databind.ObjectMapper; + +public class JacksonSerdeProvider implements ArangoSerdeProvider { + + /** + * Creates a new JacksonSerde with default settings for the specified data type. + * + * @param contentType serialization target data type + * @return the created JacksonSerde + */ + @Override + public JacksonSerde of(final ContentType contentType) { + return create(JacksonMapperProvider.of(contentType)); + } + + /** + * Creates a new JacksonSerde using the provided ObjectMapper. + * + * @param mapper Jackson ObjectMapper to use + * @return the created JacksonSerde + */ + static JacksonSerde create(final ObjectMapper mapper) { + return new JacksonSerdeImpl(mapper); + } + +} diff --git a/driver/src/main/java/com/arangodb/entity/Key.java b/jackson-serde/src/main/java/com/arangodb/serde/jackson/Key.java similarity index 68% rename from driver/src/main/java/com/arangodb/entity/Key.java rename to jackson-serde/src/main/java/com/arangodb/serde/jackson/Key.java index fd146d011..94177c44d 100644 --- a/driver/src/main/java/com/arangodb/entity/Key.java +++ b/jackson-serde/src/main/java/com/arangodb/serde/jackson/Key.java @@ -1,11 +1,8 @@ -package com.arangodb.entity; +package com.arangodb.serde.jackson; -import com.arangodb.internal.DocumentFields; import com.fasterxml.jackson.annotation.JacksonAnnotationsInside; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; -import jakarta.json.bind.annotation.JsonbAnnotation; -import jakarta.json.bind.annotation.JsonbProperty; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; @@ -18,9 +15,7 @@ @Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER}) @Retention(RetentionPolicy.RUNTIME) @JacksonAnnotationsInside -@JsonProperty(DocumentFields.KEY) +@JsonProperty("_key") @JsonInclude(JsonInclude.Include.NON_NULL) -@JsonbAnnotation -@JsonbProperty(DocumentFields.KEY) public @interface Key { } diff --git a/driver/src/main/java/com/arangodb/entity/Rev.java b/jackson-serde/src/main/java/com/arangodb/serde/jackson/Rev.java similarity index 68% rename from driver/src/main/java/com/arangodb/entity/Rev.java rename to jackson-serde/src/main/java/com/arangodb/serde/jackson/Rev.java index 63189e565..764927d6f 100644 --- a/driver/src/main/java/com/arangodb/entity/Rev.java +++ b/jackson-serde/src/main/java/com/arangodb/serde/jackson/Rev.java @@ -1,11 +1,8 @@ -package com.arangodb.entity; +package com.arangodb.serde.jackson; -import com.arangodb.internal.DocumentFields; import com.fasterxml.jackson.annotation.JacksonAnnotationsInside; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; -import jakarta.json.bind.annotation.JsonbAnnotation; -import jakarta.json.bind.annotation.JsonbProperty; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; @@ -18,9 +15,7 @@ @Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER}) @Retention(RetentionPolicy.RUNTIME) @JacksonAnnotationsInside -@JsonProperty(DocumentFields.REV) +@JsonProperty("_rev") @JsonInclude(JsonInclude.Include.NON_NULL) -@JsonbAnnotation -@JsonbProperty(DocumentFields.REV) public @interface Rev { } diff --git a/driver/src/main/java/com/arangodb/entity/To.java b/jackson-serde/src/main/java/com/arangodb/serde/jackson/To.java similarity index 68% rename from driver/src/main/java/com/arangodb/entity/To.java rename to jackson-serde/src/main/java/com/arangodb/serde/jackson/To.java index 113496d86..7510e2e53 100644 --- a/driver/src/main/java/com/arangodb/entity/To.java +++ b/jackson-serde/src/main/java/com/arangodb/serde/jackson/To.java @@ -1,11 +1,8 @@ -package com.arangodb.entity; +package com.arangodb.serde.jackson; -import com.arangodb.internal.DocumentFields; import com.fasterxml.jackson.annotation.JacksonAnnotationsInside; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; -import jakarta.json.bind.annotation.JsonbAnnotation; -import jakarta.json.bind.annotation.JsonbProperty; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; @@ -18,9 +15,7 @@ @Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER}) @Retention(RetentionPolicy.RUNTIME) @JacksonAnnotationsInside -@JsonProperty(DocumentFields.TO) +@JsonProperty("_to") @JsonInclude(JsonInclude.Include.NON_NULL) -@JsonbAnnotation -@JsonbProperty(DocumentFields.TO) public @interface To { } diff --git a/jackson-serde/src/main/java/com/arangodb/serde/jackson/internal/JacksonMapperProvider.java b/jackson-serde/src/main/java/com/arangodb/serde/jackson/internal/JacksonMapperProvider.java new file mode 100644 index 000000000..b961b009d --- /dev/null +++ b/jackson-serde/src/main/java/com/arangodb/serde/jackson/internal/JacksonMapperProvider.java @@ -0,0 +1,21 @@ +package com.arangodb.serde.jackson.internal; + +import com.arangodb.ContentType; +import com.fasterxml.jackson.databind.ObjectMapper; + +import java.util.function.Supplier; + +/** + * Not shaded in arangodb-java-driver-shaded. + */ +public interface JacksonMapperProvider extends Supplier { + static ObjectMapper of(final ContentType contentType) { + if (contentType == ContentType.JSON) { + return JsonJacksonMapperProvider.INSTANCE.get(); + } else if (contentType == ContentType.VPACK) { + return VPackJacksonMapperProvider.INSTANCE.get(); + } else { + throw new IllegalArgumentException("Unexpected value: " + contentType); + } + } +} diff --git a/driver/src/main/java/com/arangodb/internal/serde/JacksonSerdeImpl.java b/jackson-serde/src/main/java/com/arangodb/serde/jackson/internal/JacksonSerdeImpl.java similarity index 60% rename from driver/src/main/java/com/arangodb/internal/serde/JacksonSerdeImpl.java rename to jackson-serde/src/main/java/com/arangodb/serde/jackson/internal/JacksonSerdeImpl.java index cf24b9f01..f439d7c3e 100644 --- a/driver/src/main/java/com/arangodb/internal/serde/JacksonSerdeImpl.java +++ b/jackson-serde/src/main/java/com/arangodb/serde/jackson/internal/JacksonSerdeImpl.java @@ -1,7 +1,6 @@ -package com.arangodb.internal.serde; +package com.arangodb.serde.jackson.internal; -import com.arangodb.ArangoDBException; -import com.arangodb.serde.JacksonSerde; +import com.arangodb.serde.jackson.JacksonSerde; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; @@ -10,14 +9,21 @@ import java.lang.reflect.Type; import java.util.function.Consumer; -public class JacksonSerdeImpl implements JacksonSerde { +/** + * Not shaded in arangodb-java-driver-shaded. + */ +public final class JacksonSerdeImpl implements JacksonSerde { - protected final ObjectMapper mapper; + private final ObjectMapper mapper; public JacksonSerdeImpl(final ObjectMapper mapper) { this.mapper = mapper; - mapper.deactivateDefaultTyping(); - mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + try { + mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + } catch (Exception e) { + // to be safe in case the provided Jackson version does not support the methods above + e.printStackTrace(); + } } @Override @@ -25,7 +31,7 @@ public byte[] serialize(final Object value) { try { return mapper.writeValueAsBytes(value); } catch (JsonProcessingException e) { - throw new ArangoDBException(e); + throw new RuntimeException(e); } } @@ -34,7 +40,7 @@ public T deserialize(final byte[] content, final Type type) { try { return mapper.readerFor(mapper.constructType(type)).readValue(content); } catch (IOException e) { - throw new ArangoDBException(e); + throw new RuntimeException(e); } } diff --git a/jackson-serde/src/main/java/com/arangodb/serde/jackson/internal/JsonJacksonMapperProvider.java b/jackson-serde/src/main/java/com/arangodb/serde/jackson/internal/JsonJacksonMapperProvider.java new file mode 100644 index 000000000..c2e1c4afd --- /dev/null +++ b/jackson-serde/src/main/java/com/arangodb/serde/jackson/internal/JsonJacksonMapperProvider.java @@ -0,0 +1,15 @@ +package com.arangodb.serde.jackson.internal; + +import com.fasterxml.jackson.databind.ObjectMapper; + +/** + * Not shaded in arangodb-java-driver-shaded. + */ +enum JsonJacksonMapperProvider implements JacksonMapperProvider { + INSTANCE; + + @Override + public ObjectMapper get() { + return new ObjectMapper(); + } +} diff --git a/jackson-serde/src/main/java/com/arangodb/serde/jackson/internal/VPackJacksonMapperProvider.java b/jackson-serde/src/main/java/com/arangodb/serde/jackson/internal/VPackJacksonMapperProvider.java new file mode 100644 index 000000000..d44ed0a2d --- /dev/null +++ b/jackson-serde/src/main/java/com/arangodb/serde/jackson/internal/VPackJacksonMapperProvider.java @@ -0,0 +1,16 @@ +package com.arangodb.serde.jackson.internal; + +import com.arangodb.jackson.dataformat.velocypack.VPackMapper; +import com.fasterxml.jackson.databind.ObjectMapper; + +/** + * Not shaded in arangodb-java-driver-shaded. + */ +enum VPackJacksonMapperProvider implements JacksonMapperProvider { + INSTANCE; + + @Override + public ObjectMapper get() { + return new VPackMapper(); + } +} diff --git a/jackson-serde/src/main/resources/META-INF/services/com.arangodb.serde.ArangoSerdeProvider b/jackson-serde/src/main/resources/META-INF/services/com.arangodb.serde.ArangoSerdeProvider new file mode 100644 index 000000000..198620d5b --- /dev/null +++ b/jackson-serde/src/main/resources/META-INF/services/com.arangodb.serde.ArangoSerdeProvider @@ -0,0 +1 @@ +com.arangodb.serde.jackson.JacksonSerdeProvider diff --git a/jsonb-serde/pom.xml b/jsonb-serde/pom.xml new file mode 100644 index 000000000..3776e7e3a --- /dev/null +++ b/jsonb-serde/pom.xml @@ -0,0 +1,34 @@ + + + 4.0.0 + + com.arangodb + arangodb-java-driver-parent + 7.0.0-SNAPSHOT + + + jsonb-serde + jsonb-serde + JsonB Serde module for ArangoDB Java Driver + + + + true + + + + + com.arangodb + serde-api + provided + + + jakarta.json.bind + jakarta.json.bind-api + 3.0.0 + + + + \ No newline at end of file diff --git a/jsonb-serde/src/main/java/com/arangodb/serde/jsonb/From.java b/jsonb-serde/src/main/java/com/arangodb/serde/jsonb/From.java new file mode 100644 index 000000000..057be2105 --- /dev/null +++ b/jsonb-serde/src/main/java/com/arangodb/serde/jsonb/From.java @@ -0,0 +1,19 @@ +package com.arangodb.serde.jsonb; + +import jakarta.json.bind.annotation.JsonbAnnotation; +import jakarta.json.bind.annotation.JsonbProperty; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * @author Michele Rastelli + */ +@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER}) +@Retention(RetentionPolicy.RUNTIME) +@JsonbAnnotation +@JsonbProperty("_from") +public @interface From { +} diff --git a/jsonb-serde/src/main/java/com/arangodb/serde/jsonb/Id.java b/jsonb-serde/src/main/java/com/arangodb/serde/jsonb/Id.java new file mode 100644 index 000000000..f2c4f8462 --- /dev/null +++ b/jsonb-serde/src/main/java/com/arangodb/serde/jsonb/Id.java @@ -0,0 +1,19 @@ +package com.arangodb.serde.jsonb; + +import jakarta.json.bind.annotation.JsonbAnnotation; +import jakarta.json.bind.annotation.JsonbProperty; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * @author Michele Rastelli + */ +@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER}) +@Retention(RetentionPolicy.RUNTIME) +@JsonbAnnotation +@JsonbProperty("_id") +public @interface Id { +} diff --git a/driver/src/test/java/com/arangodb/serde/JsonbSerdeImpl.java b/jsonb-serde/src/main/java/com/arangodb/serde/jsonb/JsonbSerde.java similarity index 69% rename from driver/src/test/java/com/arangodb/serde/JsonbSerdeImpl.java rename to jsonb-serde/src/main/java/com/arangodb/serde/jsonb/JsonbSerde.java index a19dacbbf..45c98c0bd 100644 --- a/driver/src/test/java/com/arangodb/serde/JsonbSerdeImpl.java +++ b/jsonb-serde/src/main/java/com/arangodb/serde/jsonb/JsonbSerde.java @@ -1,5 +1,6 @@ -package com.arangodb.serde; +package com.arangodb.serde.jsonb; +import com.arangodb.serde.ArangoSerde; import jakarta.json.bind.Jsonb; import jakarta.json.bind.JsonbBuilder; import jakarta.json.bind.JsonbConfig; @@ -7,15 +8,18 @@ import java.lang.reflect.Type; import java.nio.charset.StandardCharsets; -public class JsonbSerdeImpl implements JsonbSerde { +/** + * User data serde based on Jakarta JSON Binding (JSON-B). + */ +public class JsonbSerde implements ArangoSerde { private final Jsonb jsonb; - public JsonbSerdeImpl() { + public JsonbSerde() { jsonb = JsonbBuilder.create(); } - public JsonbSerdeImpl(final JsonbConfig config) { + public JsonbSerde(final JsonbConfig config) { jsonb = JsonbBuilder.create(config); } diff --git a/jsonb-serde/src/main/java/com/arangodb/serde/jsonb/JsonbSerdeProvider.java b/jsonb-serde/src/main/java/com/arangodb/serde/jsonb/JsonbSerdeProvider.java new file mode 100644 index 000000000..149aa1427 --- /dev/null +++ b/jsonb-serde/src/main/java/com/arangodb/serde/jsonb/JsonbSerdeProvider.java @@ -0,0 +1,33 @@ +package com.arangodb.serde.jsonb; + +import com.arangodb.ContentType; +import com.arangodb.serde.ArangoSerdeProvider; +import jakarta.json.bind.JsonbConfig; + +import java.util.Objects; + +public class JsonbSerdeProvider implements ArangoSerdeProvider { + + /** + * Creates a new JsonbSerde with default settings. + * + * @return the created JsonbSerde + */ + @Override + public JsonbSerde of(final ContentType contentType) { + if (Objects.requireNonNull(contentType) == ContentType.JSON) { + return new JsonbSerde(); + } + throw new IllegalArgumentException(contentType.toString()); + } + + /** + * Creates a new JsonbSerde using the provided . + * + * @param config JsonbConfig to use + * @return the created JsonbSerde + */ + static JsonbSerde create(final JsonbConfig config) { + return new JsonbSerde(config); + } +} diff --git a/jsonb-serde/src/main/java/com/arangodb/serde/jsonb/Key.java b/jsonb-serde/src/main/java/com/arangodb/serde/jsonb/Key.java new file mode 100644 index 000000000..e5ff89558 --- /dev/null +++ b/jsonb-serde/src/main/java/com/arangodb/serde/jsonb/Key.java @@ -0,0 +1,19 @@ +package com.arangodb.serde.jsonb; + +import jakarta.json.bind.annotation.JsonbAnnotation; +import jakarta.json.bind.annotation.JsonbProperty; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * @author Michele Rastelli + */ +@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER}) +@Retention(RetentionPolicy.RUNTIME) +@JsonbAnnotation +@JsonbProperty("_key") +public @interface Key { +} diff --git a/jsonb-serde/src/main/java/com/arangodb/serde/jsonb/Rev.java b/jsonb-serde/src/main/java/com/arangodb/serde/jsonb/Rev.java new file mode 100644 index 000000000..86a7a5ee1 --- /dev/null +++ b/jsonb-serde/src/main/java/com/arangodb/serde/jsonb/Rev.java @@ -0,0 +1,19 @@ +package com.arangodb.serde.jsonb; + +import jakarta.json.bind.annotation.JsonbAnnotation; +import jakarta.json.bind.annotation.JsonbProperty; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * @author Michele Rastelli + */ +@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER}) +@Retention(RetentionPolicy.RUNTIME) +@JsonbAnnotation +@JsonbProperty("_rev") +public @interface Rev { +} diff --git a/jsonb-serde/src/main/java/com/arangodb/serde/jsonb/To.java b/jsonb-serde/src/main/java/com/arangodb/serde/jsonb/To.java new file mode 100644 index 000000000..89b4ef7d2 --- /dev/null +++ b/jsonb-serde/src/main/java/com/arangodb/serde/jsonb/To.java @@ -0,0 +1,19 @@ +package com.arangodb.serde.jsonb; + +import jakarta.json.bind.annotation.JsonbAnnotation; +import jakarta.json.bind.annotation.JsonbProperty; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * @author Michele Rastelli + */ +@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER}) +@Retention(RetentionPolicy.RUNTIME) +@JsonbAnnotation +@JsonbProperty("_to") +public @interface To { +} diff --git a/jsonb-serde/src/main/resources/META-INF/services/com.arangodb.serde.ArangoSerdeProvider b/jsonb-serde/src/main/resources/META-INF/services/com.arangodb.serde.ArangoSerdeProvider new file mode 100644 index 000000000..7a37a64b1 --- /dev/null +++ b/jsonb-serde/src/main/resources/META-INF/services/com.arangodb.serde.ArangoSerdeProvider @@ -0,0 +1 @@ +com.arangodb.serde.jsonb.JsonbSerdeProvider diff --git a/pom.xml b/pom.xml index fb96cbcb0..008081829 100644 --- a/pom.xml +++ b/pom.xml @@ -10,10 +10,14 @@ driver resilience-tests + shaded + jackson-serde + serde-api pom arangodb-java-driver-parent + https://github.com/arangodb/arangodb-java-driver @@ -27,6 +31,8 @@ 1.8 1.8 UTF-8 + true + 2.14.1 @@ -46,4 +52,287 @@ https://www.arangodb.com + + + ch.qos.logback + logback-classic + test + + + org.junit.platform + junit-platform-launcher + test + + + org.junit.jupiter + junit-jupiter-api + test + + + org.junit.jupiter + junit-jupiter-engine + test + + + org.junit.jupiter + junit-jupiter-params + test + + + org.assertj + assertj-core + test + + + + + + + com.fasterxml.jackson + jackson-bom + ${jackson.version} + import + pom + + + io.vertx + vertx-stack-depchain + 4.3.5 + pom + import + + + io.netty + netty-bom + 4.1.85.Final + pom + import + + + org.junit + junit-bom + 5.9.1 + pom + import + + + com.arangodb + arangodb-java-driver + ${project.version} + + + com.arangodb + serde-api + ${project.version} + + + com.arangodb + jackson-serde + ${project.version} + + + com.arangodb + arangodb-java-driver-shaded + ${project.version} + + + com.arangodb + jackson-dataformat-velocypack + 3.1.0 + + + org.slf4j + slf4j-api + 2.0.5 + + + ch.qos.logback + logback-classic + 1.4.5 + + + org.assertj + assertj-core + 3.23.1 + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.10.1 + + + -Xlint:unchecked + -Xlint:deprecation + + true + 1.8 + 1.8 + + + + org.apache.maven.plugins + maven-resources-plugin + 3.3.0 + + UTF-8 + + + + org.apache.maven.plugins + maven-source-plugin + 3.2.1 + + + + jar + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + 3.4.1 + + + attach-javadocs + + jar + + + **.internal** + + + + + + org.apache.maven.plugins + maven-surefire-plugin + 3.0.0-M7 + + + **/*Test.java + **/*Example.java + + + + + org.apache.maven.plugins + maven-gpg-plugin + 3.0.1 + + + sign-artifacts + verify + + sign + + + + + + org.codehaus.mojo + flatten-maven-plugin + 1.3.0 + + oss + + + + + flatten + process-resources + + flatten + + + + + flatten.clean + clean + + clean + + + + + + org.apache.maven.plugins + maven-enforcer-plugin + 3.1.0 + + + enforce + + enforce + + + + + 3.6 + + + + + + + + org.apache.maven.plugins + maven-deploy-plugin + 3.0.0 + + 10 + + + + org.sonatype.plugins + nexus-staging-maven-plugin + 1.6.13 + true + + ossrh + https://oss.sonatype.org/ + 84aff6e87e214c + false + + + + + + + + ossrh + https://oss.sonatype.org/content/repositories/snapshots + + + ossrh + https://oss.sonatype.org/service/local/staging/deploy/maven2/ + + + + + https://github.com/arangodb/arangodb-java-driver + scm:git:git://github.com/arangodb/arangodb-java-driver.git + scm:git:git://github.com/arangodb/arangodb-java-driver.git + + + + + no-deploy + + + !deploy + + + + jsonb-serde + + + + diff --git a/resilience-tests/pom.xml b/resilience-tests/pom.xml index d22ebc321..341474a48 100644 --- a/resilience-tests/pom.xml +++ b/resilience-tests/pom.xml @@ -11,13 +11,6 @@ resilience-tests - - 17 - 17 - 17 - UTF-8 - - org.mock-server @@ -27,44 +20,16 @@ com.arangodb arangodb-java-driver - ${version} com.arangodb jackson-dataformat-velocypack - 3.0.1 eu.rekawek.toxiproxy toxiproxy-java 2.1.7 - - ch.qos.logback - logback-classic - 1.2.11 - - - org.assertj - assertj-core - 3.23.1 - - - org.junit.platform - junit-platform-launcher - - - org.junit.jupiter - junit-jupiter-api - - - org.junit.jupiter - junit-jupiter-engine - - - org.junit.jupiter - junit-jupiter-params - org.awaitility awaitility @@ -72,40 +37,4 @@ - - - - io.netty - netty-bom - 4.1.84.Final - import - pom - - - com.fasterxml.jackson - jackson-bom - 2.14.1 - import - pom - - - org.junit - junit-bom - 5.9.1 - pom - import - - - - - - - - org.apache.maven.plugins - maven-surefire-plugin - 3.0.0-M5 - - - - \ No newline at end of file diff --git a/resilience-tests/src/test/java/resilience/SingleServerTest.java b/resilience-tests/src/test/java/resilience/SingleServerTest.java index 7e9bc32b6..05c87d7e2 100644 --- a/resilience-tests/src/test/java/resilience/SingleServerTest.java +++ b/resilience-tests/src/test/java/resilience/SingleServerTest.java @@ -18,7 +18,7 @@ public abstract class SingleServerTest { protected static final String HOST = "127.0.0.1"; protected static final String PASSWORD = "test"; - protected static final MemoryAppender logs = new MemoryAppender(Level.DEBUG); + protected static final MemoryAppender logs = new MemoryAppender(Level.INFO); private static final Endpoint endpoint = new Endpoint("singleServer", HOST, 18529, "172.28.0.1:8529"); @BeforeAll diff --git a/resilience-tests/src/test/resources/logback-test.xml b/resilience-tests/src/test/resources/logback-test.xml index 343f4dfdd..840d133d7 100644 --- a/resilience-tests/src/test/resources/logback-test.xml +++ b/resilience-tests/src/test/resources/logback-test.xml @@ -6,7 +6,7 @@ - + diff --git a/serde-api/pom.xml b/serde-api/pom.xml new file mode 100644 index 000000000..c567b1159 --- /dev/null +++ b/serde-api/pom.xml @@ -0,0 +1,14 @@ + + + 4.0.0 + + com.arangodb + arangodb-java-driver-parent + 7.0.0-SNAPSHOT + + + serde-api + + \ No newline at end of file diff --git a/driver/src/main/java/com/arangodb/ContentType.java b/serde-api/src/main/java/com/arangodb/ContentType.java similarity index 62% rename from driver/src/main/java/com/arangodb/ContentType.java rename to serde-api/src/main/java/com/arangodb/ContentType.java index ed9077ac3..ec63aaf8d 100644 --- a/driver/src/main/java/com/arangodb/ContentType.java +++ b/serde-api/src/main/java/com/arangodb/ContentType.java @@ -20,19 +20,5 @@ package com.arangodb; public enum ContentType { - JSON, VPACK; - - public static ContentType of(Protocol protocol) { - switch (protocol) { - case HTTP_JSON: - case HTTP2_JSON: - return ContentType.JSON; - case VST: - case HTTP_VPACK: - case HTTP2_VPACK: - return ContentType.VPACK; - default: - throw new IllegalArgumentException("Unexpected value: " + protocol); - } - } + JSON, VPACK } diff --git a/driver/src/main/java/com/arangodb/serde/ArangoSerde.java b/serde-api/src/main/java/com/arangodb/serde/ArangoSerde.java similarity index 84% rename from driver/src/main/java/com/arangodb/serde/ArangoSerde.java rename to serde-api/src/main/java/com/arangodb/serde/ArangoSerde.java index b8071be04..4218bbc12 100644 --- a/driver/src/main/java/com/arangodb/serde/ArangoSerde.java +++ b/serde-api/src/main/java/com/arangodb/serde/ArangoSerde.java @@ -3,7 +3,6 @@ import com.arangodb.ContentType; import java.lang.reflect.Type; -import java.util.function.Consumer; /** * Contract for serialization/deserialization of user data. @@ -13,11 +12,6 @@ * - serialization libraries already in use in frameworks (e.g. JSON-B, Micronaut Serialization, ...) * - high performance serialization libraries (e.g. supporting compile-time data binding code generation) * - low-level libraries without support to data binding - *

    - * To create a custom serde based on Jackson, existing {@link JacksonSerde} can be reused and instantiated providing a - * custom configured ObjectMapper ({@link JacksonSerde#create(com.fasterxml.jackson.databind.ObjectMapper)}) or - * configured - * after creation through {@link JacksonSerde#configure(Consumer)}. */ public interface ArangoSerde { diff --git a/serde-api/src/main/java/com/arangodb/serde/ArangoSerdeProvider.java b/serde-api/src/main/java/com/arangodb/serde/ArangoSerdeProvider.java new file mode 100644 index 000000000..460e1f2fd --- /dev/null +++ b/serde-api/src/main/java/com/arangodb/serde/ArangoSerdeProvider.java @@ -0,0 +1,15 @@ +package com.arangodb.serde; + +import com.arangodb.ContentType; + +public interface ArangoSerdeProvider { + + /** + * Returns a serde instance for the given content type + * + * @param contentType content type + * @return serde instance + */ + ArangoSerde of(final ContentType contentType); + +} diff --git a/shaded-integration-tests/pom.xml b/shaded-integration-tests/pom.xml new file mode 100644 index 000000000..b2f8c0331 --- /dev/null +++ b/shaded-integration-tests/pom.xml @@ -0,0 +1,196 @@ + + + 4.0.0 + + com.arangodb + integration-tests + 7.0.0-SNAPSHOT + + + 17 + 17 + UTF-8 + 2.14.1 + + + + + ch.qos.logback + logback-classic + 1.4.5 + test + + + org.junit.platform + junit-platform-launcher + test + + + org.junit.jupiter + junit-jupiter-api + test + + + org.junit.jupiter + junit-jupiter-engine + test + + + org.junit.jupiter + junit-jupiter-params + test + + + org.assertj + assertj-core + 3.23.1 + test + + + com.tngtech.archunit + archunit-junit5 + 1.0.1 + test + + + + + + + com.fasterxml.jackson + jackson-bom + ${jackson.version} + import + pom + + + io.vertx + vertx-stack-depchain + 4.3.5 + pom + import + + + io.netty + netty-bom + 4.1.85.Final + pom + import + + + org.junit + junit-bom + 5.9.1 + pom + import + + + + + + ${testSourceDirectory} + + + org.apache.maven.plugins + maven-surefire-plugin + 3.0.0-M7 + + + ${serde} + + + + + + + + + jackson-serde + + true + + + src/test/jackson/java + jackson + + + + com.arangodb + arangodb-java-driver-shaded + 7.0.0-SNAPSHOT + test + + + com.arangodb + jackson-dataformat-velocypack + 3.1.0 + test + + + + + jsonb-serde + + src/test/jsonb/java + jsonb + + + + com.arangodb + arangodb-java-driver-shaded + 7.0.0-SNAPSHOT + test + + + com.arangodb + jackson-serde + + + + + com.arangodb + jsonb-serde + 7.0.0-SNAPSHOT + test + + + org.eclipse + yasson + 3.0.2 + + + + + native + + + + org.graalvm.buildtools + native-maven-plugin + 0.9.19 + true + + + test-native + + generateTestResourceConfig + test + + test + + + + true + false + + --no-fallback + + + + + + + + \ No newline at end of file diff --git a/shaded-integration-tests/src/test/jackson/java/arch/AdbTest.java b/shaded-integration-tests/src/test/jackson/java/arch/AdbTest.java new file mode 100644 index 000000000..fc320db4e --- /dev/null +++ b/shaded-integration-tests/src/test/jackson/java/arch/AdbTest.java @@ -0,0 +1,18 @@ +package arch; + +import com.arangodb.ArangoDB; +import com.arangodb.entity.ArangoDBVersion; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + +import static org.assertj.core.api.Assertions.assertThat; + +class AdbTest extends BaseTest { + @ParameterizedTest + @MethodSource("adbByProtocol") + void getVersion(ArangoDB adb) { + final ArangoDBVersion version = adb.getVersion(); + assertThat(version.getServer()).isNotNull(); + assertThat(version.getVersion()).isNotNull(); + } +} diff --git a/shaded-integration-tests/src/test/jackson/java/arch/BaseTest.java b/shaded-integration-tests/src/test/jackson/java/arch/BaseTest.java new file mode 100644 index 000000000..3927d7fff --- /dev/null +++ b/shaded-integration-tests/src/test/jackson/java/arch/BaseTest.java @@ -0,0 +1,54 @@ +package arch; + +import com.arangodb.ArangoDB; +import com.arangodb.ContentType; +import com.arangodb.DbName; +import com.arangodb.Protocol; +import org.junit.jupiter.params.provider.Arguments; + +import java.util.Arrays; +import java.util.stream.Stream; + +public class BaseTest { + protected static final DbName TEST_DB = DbName.of("java_driver_integration_tests"); + protected static final String HOST = "172.28.0.1"; + protected static final int PORT = 8529; + protected static final String PASSWD = "test"; + + protected static ArangoDB createAdb() { + return new ArangoDB.Builder() + .host(HOST, PORT) + .password(PASSWD) + .build(); + } + + protected static ArangoDB createAdb(ContentType contentType) { + Protocol protocol = contentType == ContentType.VPACK ? Protocol.HTTP2_VPACK : Protocol.HTTP2_JSON; + return new ArangoDB.Builder() + .host(HOST, PORT) + .password(PASSWD) + .useProtocol(protocol) + .build(); + } + + protected static ArangoDB createAdb(Protocol protocol) { + return new ArangoDB.Builder() + .host(HOST, PORT) + .password(PASSWD) + .useProtocol(protocol) + .build(); + } + + protected static Stream adbByProtocol() { + return Arrays.stream(Protocol.values()) + .map(BaseTest::createAdb) + .map(Arguments::of); + } + + protected static Stream adbByContentType() { + return Arrays.stream(ContentType.values()) + .map(BaseTest::createAdb) + .map(Arguments::of); + } + +} diff --git a/shaded-integration-tests/src/test/jackson/java/arch/Person.java b/shaded-integration-tests/src/test/jackson/java/arch/Person.java new file mode 100644 index 000000000..a168c9d0c --- /dev/null +++ b/shaded-integration-tests/src/test/jackson/java/arch/Person.java @@ -0,0 +1,13 @@ +package arch; + +import com.arangodb.serde.jackson.Key; +import com.fasterxml.jackson.annotation.JsonProperty; + +public record Person( + @Key + String key, + @JsonProperty("firstName") + String name, + int age +) { +} diff --git a/shaded-integration-tests/src/test/jackson/java/arch/RelocationsTest.java b/shaded-integration-tests/src/test/jackson/java/arch/RelocationsTest.java new file mode 100644 index 000000000..761556d78 --- /dev/null +++ b/shaded-integration-tests/src/test/jackson/java/arch/RelocationsTest.java @@ -0,0 +1,56 @@ +package arch; + +import com.tngtech.archunit.core.importer.ImportOption.DoNotIncludeTests; +import com.tngtech.archunit.junit.AnalyzeClasses; +import com.tngtech.archunit.junit.ArchTest; +import com.tngtech.archunit.lang.ArchRule; + +import static com.tngtech.archunit.lang.syntax.ArchRuleDefinition.noClasses; + + +@AnalyzeClasses(packages = "com.arangodb..", importOptions = {DoNotIncludeTests.class}) +public class RelocationsTest { + + @ArchTest + public static final ArchRule nettyRelocation = noClasses().that() + .resideInAPackage("com.arangodb..") + .should().dependOnClassesThat() + .resideInAPackage("io.netty.."); + + @ArchTest + public static final ArchRule vertxRelocation = noClasses().that() + .resideInAPackage("com.arangodb..") + .should().dependOnClassesThat() + .resideInAPackage("io.vertx.."); + + @ArchTest + public static final ArchRule jacksonRelocation = noClasses().that() + .resideInAPackage("com.arangodb..").and() + .resideOutsideOfPackage("com.arangodb.jackson.dataformat.velocypack..").and() + .resideOutsideOfPackage("com.arangodb.serde.jackson..") + .should().dependOnClassesThat() + .resideInAPackage("com.fasterxml.jackson.."); + + @ArchTest + public static final ArchRule jacksonDataformatVelocypackRelocation = noClasses().that() + .resideInAPackage("com.arangodb..").and() + .resideOutsideOfPackage("com.arangodb.jackson.dataformat.velocypack..").and() + .resideOutsideOfPackage("com.arangodb.serde.jackson..") + .should().dependOnClassesThat() + .resideInAPackage("com.arangodb.jackson.dataformat.velocypack.."); + + @ArchTest + public static final ArchRule noJsonbDependency = noClasses().that() + .resideInAPackage("com.arangodb..") + .should().dependOnClassesThat() + .resideInAPackage("com.arangodb.serde.jsonb.."); + + @ArchTest + // jackson-serde is accessed via SPI + public static final ArchRule noExplicitDependencyOnJacksonSerde = noClasses().that() + .resideInAPackage("com.arangodb..").and() + .resideOutsideOfPackage("com.arangodb.serde.jackson..") + .should().dependOnClassesThat() + .resideInAPackage("com.arangodb.serde.jackson.."); + +} diff --git a/shaded-integration-tests/src/test/jackson/java/arch/SerdeTest.java b/shaded-integration-tests/src/test/jackson/java/arch/SerdeTest.java new file mode 100644 index 000000000..91b2e0831 --- /dev/null +++ b/shaded-integration-tests/src/test/jackson/java/arch/SerdeTest.java @@ -0,0 +1,81 @@ +package arch; + +import com.arangodb.ArangoDB; +import com.arangodb.shaded.fasterxml.jackson.databind.JsonNode; +import com.arangodb.shaded.fasterxml.jackson.databind.node.JsonNodeFactory; +import com.arangodb.util.RawJson; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + +import java.util.Collections; +import java.util.Map; + +import static org.assertj.core.api.Assertions.assertThat; + +class SerdeTest extends BaseTest { + + @ParameterizedTest + @MethodSource("adbByContentType") + void shadedJsonNode(ArangoDB adb) { + // uses the internal serde + JsonNode doc = JsonNodeFactory.instance + .objectNode() + .put("foo", "bar"); + JsonNode res = adb.db().query("return @d", Collections.singletonMap("d", doc), JsonNode.class).next(); + assertThat(res.size()).isEqualTo(1); + assertThat(res.get("foo").asText()).isEqualTo("bar"); + JsonNode value = adb.db().query("return @d.foo", Collections.singletonMap("d", doc), JsonNode.class).next(); + assertThat(value.textValue()).isEqualTo("bar"); + } + + @ParameterizedTest + @MethodSource("adbByContentType") + void jsonNode(ArangoDB adb) { + // uses the user serde + com.fasterxml.jackson.databind.JsonNode doc = com.fasterxml.jackson.databind.node.JsonNodeFactory.instance + .objectNode() + .put("foo", "bar"); + com.fasterxml.jackson.databind.JsonNode res = adb.db().query("return @d", Collections.singletonMap("d", doc), + com.fasterxml.jackson.databind.JsonNode.class).next(); + assertThat(res.size()).isEqualTo(1); + assertThat(res.get("foo").asText()).isEqualTo("bar"); + com.fasterxml.jackson.databind.JsonNode value = adb.db().query("return @d.foo", Collections.singletonMap("d", doc), + com.fasterxml.jackson.databind.JsonNode.class).next(); + assertThat(value.textValue()).isEqualTo("bar"); + } + + @ParameterizedTest + @MethodSource("adbByContentType") + void map(ArangoDB adb) { + Map doc = Collections.singletonMap("foo", "bar"); + Map res = adb.db().query("return @d", Collections.singletonMap("d", doc), Map.class).next(); + assertThat(res).hasSize(1); + assertThat(res.get("foo")).isEqualTo("bar"); + String value = adb.db().query("return @d.foo", Collections.singletonMap("d", doc), String.class).next(); + assertThat(value).isEqualTo("bar"); + } + + @ParameterizedTest + @MethodSource("adbByContentType") + void rawJson(ArangoDB adb) { + RawJson doc = RawJson.of(""" + {"foo":"bar"}"""); + RawJson res = adb.db().query("return @d", Collections.singletonMap("d", doc), RawJson.class).next(); + assertThat(res.getValue()).isEqualTo(doc.getValue()); + RawJson value = adb.db().query("return @d.foo", Collections.singletonMap("d", doc), RawJson.class).next(); + assertThat(value.getValue()).isEqualTo("\"bar\""); + } + + @ParameterizedTest + @MethodSource("adbByContentType") + void person(ArangoDB adb) { + Person doc = new Person("key", "Jim", 22); + Person res = adb.db().query("return @d", Collections.singletonMap("d", doc), Person.class).next(); + assertThat(res).isEqualTo(doc); + String key = adb.db().query("return @d._key", Collections.singletonMap("d", doc), String.class).next(); + assertThat(key).isEqualTo("key"); + String name = adb.db().query("return @d.firstName", Collections.singletonMap("d", doc), String.class).next(); + assertThat(name).isEqualTo("Jim"); + } + +} diff --git a/shaded-integration-tests/src/test/jackson/java/com/arangodb/ArangoCollectionTest.java b/shaded-integration-tests/src/test/jackson/java/com/arangodb/ArangoCollectionTest.java new file mode 100644 index 000000000..acff3ae3b --- /dev/null +++ b/shaded-integration-tests/src/test/jackson/java/com/arangodb/ArangoCollectionTest.java @@ -0,0 +1,3220 @@ +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed 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. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb; + +import com.arangodb.entity.*; +import com.arangodb.internal.serde.SerdeUtils; +import com.arangodb.model.*; +import com.arangodb.model.DocumentImportOptions.OnDuplicate; +import com.arangodb.serde.jackson.Id; +import com.arangodb.serde.jackson.JacksonSerde; +import com.arangodb.serde.jackson.Key; +import com.arangodb.serde.jackson.Rev; +import com.arangodb.shaded.fasterxml.jackson.databind.JsonNode; +import com.arangodb.util.MapBuilder; +import com.arangodb.util.RawBytes; +import com.arangodb.util.RawData; +import com.arangodb.util.RawJson; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonTypeInfo; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +import java.util.*; +import java.util.stream.Collectors; +import java.util.stream.IntStream; +import java.util.stream.Stream; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.catchThrowable; +import static org.junit.jupiter.api.Assumptions.assumeTrue; + +/** + * @author Mark Vollmary + * @author Michele Rastelli + */ +class ArangoCollectionTest extends BaseJunit5 { + + private static final String COLLECTION_NAME = "ArangoCollectionTest_collection"; + private static final String EDGE_COLLECTION_NAME = "ArangoCollectionTest_edge_collection"; + + private final ObjectMapper mapper = new ObjectMapper(); + + private static Stream cols() { + return dbsStream().map(db -> db.collection(COLLECTION_NAME)).map(Arguments::of); + } + + private static Stream edges() { + return dbsStream().map(db -> db.collection(EDGE_COLLECTION_NAME)).map(Arguments::of); + } + + @BeforeAll + static void init() { + initCollections(COLLECTION_NAME); + initEdgeCollections(EDGE_COLLECTION_NAME); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void insertDocument(ArangoCollection collection) { + final DocumentCreateEntity doc = collection.insertDocument(new BaseDocument(), null); + assertThat(doc).isNotNull(); + assertThat(doc.getId()).isNotNull(); + assertThat(doc.getKey()).isNotNull(); + assertThat(doc.getRev()).isNotNull(); + assertThat(doc.getNew()).isNull(); + assertThat(doc.getId()).isEqualTo(COLLECTION_NAME + "/" + doc.getKey()); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void insertDocumentWithArrayWithNullValues(ArangoCollection collection) { + List arr = Arrays.asList("a", null); + BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); + doc.addAttribute("arr", arr); + + final DocumentCreateEntity insertedDoc = collection.insertDocument(doc, + new DocumentCreateOptions().returnNew(true)); + assertThat(insertedDoc).isNotNull(); + assertThat(insertedDoc.getId()).isNotNull(); + assertThat(insertedDoc.getKey()).isNotNull(); + assertThat(insertedDoc.getRev()).isNotNull(); + assertThat(insertedDoc.getId()).isEqualTo(COLLECTION_NAME + "/" + insertedDoc.getKey()); + //noinspection unchecked + assertThat((List) insertedDoc.getNew().getAttribute("arr")).containsAll(Arrays.asList("a", null)); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void insertDocumentWithNullValues(ArangoCollection collection) { + BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); + doc.addAttribute("null", null); + + final DocumentCreateEntity insertedDoc = collection.insertDocument(doc, + new DocumentCreateOptions().returnNew(true)); + assertThat(insertedDoc).isNotNull(); + assertThat(insertedDoc.getId()).isNotNull(); + assertThat(insertedDoc.getKey()).isNotNull(); + assertThat(insertedDoc.getRev()).isNotNull(); + assertThat(insertedDoc.getId()).isEqualTo(COLLECTION_NAME + "/" + insertedDoc.getKey()); + assertThat(insertedDoc.getNew().getProperties()).containsKey("null"); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void insertDocumentUpdateRev(ArangoCollection collection) { + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); + final DocumentCreateEntity createResult = collection.insertDocument(doc, null); + assertThat(doc.getRevision()).isNull(); + assertThat(createResult.getRev()).isNotNull(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void insertDocumentReturnNew(ArangoCollection collection) { + final DocumentCreateOptions options = new DocumentCreateOptions().returnNew(true); + final DocumentCreateEntity doc = collection.insertDocument(new BaseDocument(), options); + assertThat(doc).isNotNull(); + assertThat(doc.getId()).isNotNull(); + assertThat(doc.getKey()).isNotNull(); + assertThat(doc.getRev()).isNotNull(); + assertThat(doc.getNew()).isNotNull(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void insertDocumentWithTypeOverwriteModeReplace(ArangoCollection collection) { + assumeTrue(isAtLeastVersion(3, 7)); + assumeTrue(collection.getSerde().getUserSerde() instanceof JacksonSerde, "polymorphic deserialization support" + + " required"); + + String key = UUID.randomUUID().toString(); + Dog dog = new Dog(key, "Teddy"); + Cat cat = new Cat(key, "Luna"); + + final DocumentCreateOptions options = new DocumentCreateOptions() + .returnNew(true) + .returnOld(true) + .overwriteMode(OverwriteMode.replace); + collection.insertDocument(dog, options); + final DocumentCreateEntity doc = collection.insertDocument(cat, options, Animal.class); + assertThat(doc).isNotNull(); + assertThat(doc.getId()).isNotNull(); + assertThat(doc.getKey()).isNotNull().isEqualTo(key); + assertThat(doc.getRev()).isNotNull(); + + assertThat(doc.getOld()) + .isNotNull() + .isInstanceOf(Dog.class); + assertThat(doc.getOld().getKey()).isEqualTo(key); + assertThat(doc.getOld().getName()).isEqualTo("Teddy"); + + assertThat(doc.getNew()) + .isNotNull() + .isInstanceOf(Cat.class); + assertThat(doc.getNew().getKey()).isEqualTo(key); + assertThat(doc.getNew().getName()).isEqualTo("Luna"); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void insertDocumentOverwriteModeIgnore(ArangoCollection collection) { + assumeTrue(isAtLeastVersion(3, 7)); + + String key = "key-" + UUID.randomUUID(); + final BaseDocument doc = new BaseDocument(key); + doc.addAttribute("foo", "a"); + final DocumentCreateEntity meta = collection.insertDocument(doc); + + final BaseDocument doc2 = new BaseDocument(key); + doc2.addAttribute("bar", "b"); + final DocumentCreateEntity insertIgnore = collection.insertDocument(doc2, + new DocumentCreateOptions().overwriteMode(OverwriteMode.ignore)); + + assertThat(insertIgnore).isNotNull(); + assertThat(insertIgnore.getRev()).isEqualTo(meta.getRev()); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void insertDocumentOverwriteModeConflict(ArangoCollection collection) { + assumeTrue(isAtLeastVersion(3, 7)); + + String key = "key-" + UUID.randomUUID(); + final BaseDocument doc = new BaseDocument(key); + doc.addAttribute("foo", "a"); + collection.insertDocument(doc); + + final BaseDocument doc2 = new BaseDocument(key); + Throwable thrown = catchThrowable(() -> collection.insertDocument(doc2, + new DocumentCreateOptions().overwriteMode(OverwriteMode.conflict))); + assertThat(thrown).isInstanceOf(ArangoDBException.class); + ArangoDBException e = (ArangoDBException) thrown; + assertThat(e.getResponseCode()).isEqualTo(409); + assertThat(e.getErrorNum()).isEqualTo(1210); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void insertDocumentOverwriteModeReplace(ArangoCollection collection) { + assumeTrue(isAtLeastVersion(3, 7)); + + String key = "key-" + UUID.randomUUID(); + final BaseDocument doc = new BaseDocument(key); + doc.addAttribute("foo", "a"); + final DocumentCreateEntity meta = collection.insertDocument(doc); + + final BaseDocument doc2 = new BaseDocument(key); + doc2.addAttribute("bar", "b"); + final DocumentCreateEntity repsert = collection.insertDocument(doc2, +new DocumentCreateOptions().overwriteMode(OverwriteMode.replace).returnNew(true)); + + assertThat(repsert).isNotNull(); + assertThat(repsert.getRev()).isNotEqualTo(meta.getRev()); + assertThat(repsert.getNew().getProperties().containsKey("foo")).isFalse(); + assertThat(repsert.getNew().getAttribute("bar")).isEqualTo("b"); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void insertDocumentOverwriteModeUpdate(ArangoCollection collection) { + assumeTrue(isAtLeastVersion(3, 7)); + + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); + doc.addAttribute("foo", "a"); + final DocumentCreateEntity meta = collection.insertDocument(doc); + + doc.addAttribute("bar", "b"); + final DocumentCreateEntity updated = collection.insertDocument(doc, + new DocumentCreateOptions().overwriteMode(OverwriteMode.update).returnNew(true)); + + assertThat(updated).isNotNull(); + assertThat(updated.getRev()).isNotEqualTo(meta.getRev()); + assertThat(updated.getNew().getAttribute("foo")).isEqualTo("a"); + assertThat(updated.getNew().getAttribute("bar")).isEqualTo("b"); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void insertDocumentOverwriteModeUpdateMergeObjectsFalse(ArangoCollection collection) { + assumeTrue(isAtLeastVersion(3, 7)); + + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); + Map fieldA = Collections.singletonMap("a", "a"); + doc.addAttribute("foo", fieldA); + final DocumentCreateEntity meta = collection.insertDocument(doc); + + Map fieldB = Collections.singletonMap("b", "b"); + doc.addAttribute("foo", fieldB); + final DocumentCreateEntity updated = collection.insertDocument(doc, + new DocumentCreateOptions().overwriteMode(OverwriteMode.update).mergeObjects(false).returnNew(true)); + + assertThat(updated).isNotNull(); + assertThat(updated.getRev()).isNotEqualTo(meta.getRev()); + assertThat(updated.getNew().getAttribute("foo")).isEqualTo(fieldB); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void insertDocumentOverwriteModeUpdateKeepNullTrue(ArangoCollection collection) { + assumeTrue(isAtLeastVersion(3, 7)); + + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); + doc.addAttribute("foo", "bar"); + collection.insertDocument(doc); + + doc.updateAttribute("foo", null); + final BaseDocument updated = collection.insertDocument(doc, new DocumentCreateOptions() + .overwriteMode(OverwriteMode.update) + .keepNull(true) + .returnNew(true)).getNew(); + + assertThat(updated.getProperties()).containsEntry("foo", null); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void insertDocumentOverwriteModeUpdateKeepNullFalse(ArangoCollection collection) { + assumeTrue(isAtLeastVersion(3, 7)); + + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); + doc.addAttribute("foo", "bar"); + collection.insertDocument(doc); + + doc.updateAttribute("foo", null); + final BaseDocument updated = collection.insertDocument(doc, new DocumentCreateOptions() + .overwriteMode(OverwriteMode.update) + .keepNull(false) + .returnNew(true)).getNew(); + + assertThat(updated.getProperties()).doesNotContainKey("foo"); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void insertDocumentWaitForSync(ArangoCollection collection) { + final DocumentCreateOptions options = new DocumentCreateOptions().waitForSync(true); + final DocumentCreateEntity doc = collection.insertDocument(new BaseDocument(), options); + assertThat(doc).isNotNull(); + assertThat(doc.getId()).isNotNull(); + assertThat(doc.getKey()).isNotNull(); + assertThat(doc.getRev()).isNotNull(); + assertThat(doc.getNew()).isNull(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void insertDocumentAsJson(ArangoCollection collection) { + String key = "doc-" + UUID.randomUUID(); + RawJson rawJson = RawJson.of("{\"_key\":\"" + key + "\",\"a\":\"test\"}"); + final DocumentCreateEntity doc = collection.insertDocument(rawJson); + assertThat(doc).isNotNull(); + assertThat(doc.getId()).isEqualTo(collection.name() + "/" + key); + assertThat(doc.getKey()).isEqualTo(key); + assertThat(doc.getRev()).isNotNull(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void insertDocumentAsBytes(ArangoCollection collection) { + String key = "doc-" + UUID.randomUUID(); + Map doc = new HashMap<>(); + doc.put("_key", key); + doc.put("a", "test"); + byte[] bytes = collection.getSerde().serializeUserData(doc); + RawBytes rawJson = RawBytes.of(bytes); + final DocumentCreateEntity createEntity = collection.insertDocument(rawJson, +new DocumentCreateOptions().returnNew(true)); + assertThat(createEntity).isNotNull(); + assertThat(createEntity.getId()).isEqualTo(collection.name() + "/" + key); + assertThat(createEntity.getKey()).isEqualTo(key); + assertThat(createEntity.getRev()).isNotNull(); + assertThat(createEntity.getNew()).isNotNull().isInstanceOf(RawBytes.class); + Map newDoc = collection.getSerde().deserializeUserData(createEntity.getNew().getValue(), + Map.class); + assertThat(newDoc).containsAllEntriesOf(doc); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void insertDocumentSilent(ArangoCollection collection) { + assumeTrue(isSingleServer()); + final DocumentCreateEntity meta = collection.insertDocument(new BaseDocument(), + new DocumentCreateOptions().silent(true)); + assertThat(meta).isNotNull(); + assertThat(meta.getId()).isNull(); + assertThat(meta.getKey()).isNull(); + assertThat(meta.getRev()).isNull(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void insertDocumentSilentDontTouchInstance(ArangoCollection collection) { + assumeTrue(isSingleServer()); + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); + final String key = "testkey-" + UUID.randomUUID(); + doc.setKey(key); + final DocumentCreateEntity meta = collection.insertDocument(doc, + new DocumentCreateOptions().silent(true)); + assertThat(meta).isNotNull(); + assertThat(meta.getKey()).isNull(); + assertThat(doc.getKey()).isEqualTo(key); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void insertDocumentsSilent(ArangoCollection collection) { + assumeTrue(isSingleServer()); + final MultiDocumentEntity> info = + collection.insertDocuments(Arrays.asList(new BaseDocument(), new BaseDocument()), +new DocumentCreateOptions().silent(true)); + assertThat(info).isNotNull(); + assertThat(info.getDocuments()).isEmpty(); + assertThat(info.getDocumentsAndErrors()).isEmpty(); + assertThat(info.getErrors()).isEmpty(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void getDocument(ArangoCollection collection) { + final DocumentCreateEntity createResult = collection.insertDocument(new BaseDocument(), null); + assertThat(createResult.getKey()).isNotNull(); + final BaseDocument readResult = collection.getDocument(createResult.getKey(), BaseDocument.class, null); + assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); + assertThat(readResult.getId()).isEqualTo(COLLECTION_NAME + "/" + createResult.getKey()); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void getDocumentIfMatch(ArangoCollection collection) { + final DocumentCreateEntity createResult = collection.insertDocument(new BaseDocument(), null); + assertThat(createResult.getKey()).isNotNull(); + final DocumentReadOptions options = new DocumentReadOptions().ifMatch(createResult.getRev()); + final BaseDocument readResult = collection.getDocument(createResult.getKey(), BaseDocument.class, options); + assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); + assertThat(readResult.getId()).isEqualTo(COLLECTION_NAME + "/" + createResult.getKey()); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void getDocumentIfMatchFail(ArangoCollection collection) { + final DocumentCreateEntity createResult = collection.insertDocument(new BaseDocument(), null); + assertThat(createResult.getKey()).isNotNull(); + final DocumentReadOptions options = new DocumentReadOptions().ifMatch("no"); + final BaseDocument document = collection.getDocument(createResult.getKey(), BaseDocument.class, options); + assertThat(document).isNull(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void getDocumentIfNoneMatch(ArangoCollection collection) { + final DocumentCreateEntity createResult = collection.insertDocument(new BaseDocument(), null); + assertThat(createResult.getKey()).isNotNull(); + final DocumentReadOptions options = new DocumentReadOptions().ifNoneMatch("no"); + final BaseDocument readResult = collection.getDocument(createResult.getKey(), BaseDocument.class, options); + assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); + assertThat(readResult.getId()).isEqualTo(COLLECTION_NAME + "/" + createResult.getKey()); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void getDocumentIfNoneMatchFail(ArangoCollection collection) { + final DocumentCreateEntity createResult = collection.insertDocument(new BaseDocument(), null); + assertThat(createResult.getKey()).isNotNull(); + final DocumentReadOptions options = new DocumentReadOptions().ifNoneMatch(createResult.getRev()); + final BaseDocument document = collection.getDocument(createResult.getKey(), BaseDocument.class, options); + assertThat(document).isNull(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void getDocumentAsJson(ArangoCollection collection) { + String key = rnd(); + RawJson rawJson = RawJson.of("{\"_key\":\"" + key + "\",\"a\":\"test\"}"); + collection.insertDocument(rawJson); + final RawJson readResult = collection.getDocument(key, RawJson.class); + assertThat(readResult.getValue()).contains("\"_key\":\"" + key + "\"").contains("\"_id\":\"" + COLLECTION_NAME + "/" + key + "\""); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void getDocumentNotFound(ArangoCollection collection) { + final BaseDocument document = collection.getDocument("no", BaseDocument.class); + assertThat(document).isNull(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void getDocumentNotFoundOptionsDefault(ArangoCollection collection) { + final BaseDocument document = collection.getDocument("no", BaseDocument.class, new DocumentReadOptions()); + assertThat(document).isNull(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void getDocumentNotFoundOptionsNull(ArangoCollection collection) { + final BaseDocument document = collection.getDocument("no", BaseDocument.class, null); + assertThat(document).isNull(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void getDocumentWrongKey(ArangoCollection collection) { + Throwable thrown = catchThrowable(() -> collection.getDocument("no/no", BaseDocument.class)); + assertThat(thrown).isInstanceOf(ArangoDBException.class); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void getDocumentDirtyRead(ArangoCollection collection) throws InterruptedException { + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); + collection.insertDocument(doc, new DocumentCreateOptions()); + Thread.sleep(2000); + final RawJson document = collection.getDocument(doc.getKey(), RawJson.class, + new DocumentReadOptions().allowDirtyRead(true)); + assertThat(document).isNotNull(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void getDocuments(ArangoCollection collection) { + final Collection values = new ArrayList<>(); + values.add(new BaseDocument("1")); + values.add(new BaseDocument("2")); + values.add(new BaseDocument("3")); + collection.insertDocuments(values); + final MultiDocumentEntity documents = collection.getDocuments(Arrays.asList("1", "2", "3"), +BaseDocument.class); + assertThat(documents).isNotNull(); + assertThat(documents.getDocuments()).hasSize(3); + for (final BaseDocument document : documents.getDocuments()) { + assertThat(document.getId()).isIn(COLLECTION_NAME + "/" + "1", COLLECTION_NAME + "/" + "2", + COLLECTION_NAME + "/" + "3"); + } + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void getDocumentsWithCustomShardingKey(ArangoCollection c) { + ArangoCollection collection = c.db().collection("customShardingKeyCollection"); + if (collection.exists()) collection.drop(); + + collection.create(new CollectionCreateOptions().shardKeys("customField").numberOfShards(10)); + + List values = + IntStream.range(0, 10).mapToObj(String::valueOf).map(key -> new BaseDocument()).peek(it -> it.addAttribute( + "customField", rnd())).collect(Collectors.toList()); + + MultiDocumentEntity> inserted = collection.insertDocuments(values); + List insertedKeys = + inserted.getDocuments().stream().map(DocumentEntity::getKey).collect(Collectors.toList()); + + final Collection documents = +collection.getDocuments(insertedKeys, BaseDocument.class).getDocuments(); + + assertThat(documents).hasSize(10); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void getDocumentsDirtyRead(ArangoCollection collection) { + final Collection values = new ArrayList<>(); + values.add(new BaseDocument("1")); + values.add(new BaseDocument("2")); + values.add(new BaseDocument("3")); + collection.insertDocuments(values); + final MultiDocumentEntity documents = collection.getDocuments(Arrays.asList("1", "2", "3"), + BaseDocument.class, new DocumentReadOptions().allowDirtyRead(true)); + assertThat(documents).isNotNull(); + if (isAtLeastVersion(3, 10)) { + assertThat(documents.isPotentialDirtyRead()).isTrue(); + } + assertThat(documents.getDocuments()).hasSize(3); + for (final BaseDocument document : documents.getDocuments()) { + assertThat(document.getId()).isIn(COLLECTION_NAME + "/" + "1", COLLECTION_NAME + "/" + "2", + COLLECTION_NAME + "/" + "3"); + } + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void getDocumentsNotFound(ArangoCollection collection) { + final MultiDocumentEntity readResult = collection.getDocuments(Collections.singleton("no"), + BaseDocument.class); + assertThat(readResult).isNotNull(); + assertThat(readResult.getDocuments()).isEmpty(); + assertThat(readResult.getErrors()).hasSize(1); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void getDocumentsWrongKey(ArangoCollection collection) { + final MultiDocumentEntity readResult = collection.getDocuments(Collections.singleton("no/no"), + BaseDocument.class); + assertThat(readResult).isNotNull(); + assertThat(readResult.getDocuments()).isEmpty(); + assertThat(readResult.getErrors()).hasSize(1); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void updateDocument(ArangoCollection collection) { + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); + doc.addAttribute("a", "test"); + doc.addAttribute("c", "test"); + final DocumentCreateEntity createResult = collection.insertDocument(doc, null); + doc.updateAttribute("a", "test1"); + doc.addAttribute("b", "test"); + doc.updateAttribute("c", null); + final DocumentUpdateEntity updateResult = collection.updateDocument(createResult.getKey(), doc, +null); + assertThat(updateResult).isNotNull(); + assertThat(updateResult.getId()).isEqualTo(createResult.getId()); + assertThat(updateResult.getNew()).isNull(); + assertThat(updateResult.getOld()).isNull(); + assertThat(updateResult.getRev()).isNotEqualTo(updateResult.getOldRev()); + assertThat(updateResult.getOldRev()).isEqualTo(createResult.getRev()); + + final BaseDocument readResult = collection.getDocument(createResult.getKey(), BaseDocument.class, null); + assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); + assertThat(readResult.getAttribute("a")).isNotNull(); + assertThat(String.valueOf(readResult.getAttribute("a"))).isEqualTo("test1"); + assertThat(readResult.getAttribute("b")).isNotNull(); + assertThat(String.valueOf(readResult.getAttribute("b"))).isEqualTo("test"); + assertThat(readResult.getRevision()).isEqualTo(updateResult.getRev()); + assertThat(readResult.getProperties()).containsKey("c"); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void updateDocumentWithDifferentReturnType(ArangoCollection collection) { + final String key = "key-" + UUID.randomUUID(); + final BaseDocument doc = new BaseDocument(key); + doc.addAttribute("a", "test"); + collection.insertDocument(doc); + + final DocumentUpdateEntity updateResult = collection.updateDocument(key, +Collections.singletonMap("b", "test"), new DocumentUpdateOptions().returnNew(true), BaseDocument.class); + assertThat(updateResult).isNotNull(); + assertThat(updateResult.getKey()).isEqualTo(key); + BaseDocument updated = updateResult.getNew(); + assertThat(updated).isNotNull(); + assertThat(updated.getAttribute("a")).isEqualTo("test"); + assertThat(updated.getAttribute("b")).isEqualTo("test"); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void updateDocumentUpdateRev(ArangoCollection collection) { + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); + final DocumentCreateEntity createResult = collection.insertDocument(doc, null); + doc.addAttribute("foo", "bar"); + final DocumentUpdateEntity updateResult = collection.updateDocument(createResult.getKey(), doc, + null); + assertThat(doc.getRevision()).isNull(); + assertThat(createResult.getRev()).isNotNull(); + assertThat(updateResult.getRev()) + .isNotNull() + .isNotEqualTo(createResult.getRev()); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void updateDocumentIfMatch(ArangoCollection collection) { + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); + doc.addAttribute("a", "test"); + doc.addAttribute("c", "test"); + final DocumentCreateEntity createResult = collection.insertDocument(doc, null); + doc.updateAttribute("a", "test1"); + doc.addAttribute("b", "test"); + doc.updateAttribute("c", null); + final DocumentUpdateOptions options = new DocumentUpdateOptions().ifMatch(createResult.getRev()); + final DocumentUpdateEntity updateResult = collection.updateDocument(createResult.getKey(), doc, + options); + assertThat(updateResult).isNotNull(); + assertThat(updateResult.getId()).isEqualTo(createResult.getId()); + assertThat(updateResult.getRev()).isNotEqualTo(updateResult.getOldRev()); + assertThat(updateResult.getOldRev()).isEqualTo(createResult.getRev()); + + final BaseDocument readResult = collection.getDocument(createResult.getKey(), BaseDocument.class, null); + assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); + assertThat(readResult.getAttribute("a")).isNotNull(); + assertThat(String.valueOf(readResult.getAttribute("a"))).isEqualTo("test1"); + assertThat(readResult.getAttribute("b")).isNotNull(); + assertThat(String.valueOf(readResult.getAttribute("b"))).isEqualTo("test"); + assertThat(readResult.getRevision()).isEqualTo(updateResult.getRev()); + assertThat(readResult.getProperties()).containsKey("c"); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void updateDocumentIfMatchFail(ArangoCollection collection) { + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); + doc.addAttribute("a", "test"); + doc.addAttribute("c", "test"); + final DocumentCreateEntity createResult = collection.insertDocument(doc, null); + doc.updateAttribute("a", "test1"); + doc.addAttribute("b", "test"); + doc.updateAttribute("c", null); + + final DocumentUpdateOptions options = new DocumentUpdateOptions().ifMatch("no"); + Throwable thrown = catchThrowable(() -> collection.updateDocument(createResult.getKey(), doc, options)); + assertThat(thrown).isInstanceOf(ArangoDBException.class); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void updateDocumentReturnNew(ArangoCollection collection) { + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); + doc.addAttribute("a", "test"); + final DocumentCreateEntity createResult = collection.insertDocument(doc, null); + doc.updateAttribute("a", "test1"); + doc.addAttribute("b", "test"); + final DocumentUpdateOptions options = new DocumentUpdateOptions().returnNew(true); + final DocumentUpdateEntity updateResult = collection.updateDocument(createResult.getKey(), doc, + options); + assertThat(updateResult).isNotNull(); + assertThat(updateResult.getId()).isEqualTo(createResult.getId()); + assertThat(updateResult.getOldRev()).isEqualTo(createResult.getRev()); + assertThat(updateResult.getNew()).isNotNull(); + assertThat(updateResult.getNew().getKey()).isEqualTo(createResult.getKey()); + assertThat(updateResult.getNew().getRevision()).isNotEqualTo(createResult.getRev()); + assertThat(updateResult.getNew().getAttribute("a")).isNotNull(); + assertThat(String.valueOf(updateResult.getNew().getAttribute("a"))).isEqualTo("test1"); + assertThat(updateResult.getNew().getAttribute("b")).isNotNull(); + assertThat(String.valueOf(updateResult.getNew().getAttribute("b"))).isEqualTo("test"); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void updateDocumentReturnOld(ArangoCollection collection) { + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); + doc.addAttribute("a", "test"); + final DocumentCreateEntity createResult = collection.insertDocument(doc, null); + doc.updateAttribute("a", "test1"); + doc.addAttribute("b", "test"); + final DocumentUpdateOptions options = new DocumentUpdateOptions().returnOld(true); + final DocumentUpdateEntity updateResult = collection.updateDocument(createResult.getKey(), doc, + options); + assertThat(updateResult).isNotNull(); + assertThat(updateResult.getId()).isEqualTo(createResult.getId()); + assertThat(updateResult.getOldRev()).isEqualTo(createResult.getRev()); + assertThat(updateResult.getOld()).isNotNull(); + assertThat(updateResult.getOld().getKey()).isEqualTo(createResult.getKey()); + assertThat(updateResult.getOld().getRevision()).isEqualTo(createResult.getRev()); + assertThat(updateResult.getOld().getAttribute("a")).isNotNull(); + assertThat(String.valueOf(updateResult.getOld().getAttribute("a"))).isEqualTo("test"); + assertThat(updateResult.getOld().getProperties().keySet()).doesNotContain("b"); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void updateDocumentKeepNullTrue(ArangoCollection collection) { + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); + doc.addAttribute("a", "test"); + final DocumentCreateEntity createResult = collection.insertDocument(doc, null); + doc.updateAttribute("a", null); + final DocumentUpdateOptions options = new DocumentUpdateOptions().keepNull(true); + final DocumentUpdateEntity updateResult = collection.updateDocument(createResult.getKey(), doc, + options); + assertThat(updateResult).isNotNull(); + assertThat(updateResult.getId()).isEqualTo(createResult.getId()); + assertThat(updateResult.getRev()).isNotEqualTo(updateResult.getOldRev()); + assertThat(updateResult.getOldRev()).isEqualTo(createResult.getRev()); + + final BaseDocument readResult = collection.getDocument(createResult.getKey(), BaseDocument.class, null); + assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); + assertThat(readResult.getProperties()).containsKey("a"); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void updateDocumentKeepNullFalse(ArangoCollection collection) { + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); + doc.addAttribute("a", "test"); + final DocumentCreateEntity createResult = collection.insertDocument(doc, null); + doc.updateAttribute("a", null); + final DocumentUpdateOptions options = new DocumentUpdateOptions().keepNull(false); + final DocumentUpdateEntity updateResult = collection.updateDocument(createResult.getKey(), doc, + options); + assertThat(updateResult).isNotNull(); + assertThat(updateResult.getId()).isEqualTo(createResult.getId()); + assertThat(updateResult.getRev()).isNotEqualTo(updateResult.getOldRev()); + assertThat(updateResult.getOldRev()).isEqualTo(createResult.getRev()); + + final BaseDocument readResult = collection.getDocument(createResult.getKey(), BaseDocument.class, null); + assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); + assertThat(readResult.getId()).isEqualTo(createResult.getId()); + assertThat(readResult.getRevision()).isNotNull(); + assertThat(readResult.getProperties().keySet()).doesNotContain("a"); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void updateDocumentSerializeNullTrue(ArangoCollection collection) { + final TestUpdateEntity doc = new TestUpdateEntity(); + doc.a = "foo"; + doc.b = "foo"; + final DocumentCreateEntity createResult = collection.insertDocument(doc); + final TestUpdateEntity patchDoc = new TestUpdateEntity(); + patchDoc.a = "bar"; + final DocumentUpdateEntity updateResult = collection.updateDocument(createResult.getKey(), patchDoc); + assertThat(updateResult).isNotNull(); + assertThat(updateResult.getKey()).isEqualTo(createResult.getKey()); + + final BaseDocument readResult = collection.getDocument(createResult.getKey(), BaseDocument.class); + assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); + assertThat(readResult.getProperties()).containsKey("a"); + assertThat(readResult.getAttribute("a")).isEqualTo("bar"); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void updateDocumentSerializeNullFalse(ArangoCollection collection) { + final TestUpdateEntitySerializeNullFalse doc = new TestUpdateEntitySerializeNullFalse(); + doc.a = "foo"; + doc.b = "foo"; + final DocumentCreateEntity createResult = collection.insertDocument(doc); + final TestUpdateEntitySerializeNullFalse patchDoc = new TestUpdateEntitySerializeNullFalse(); + patchDoc.a = "bar"; + final DocumentUpdateEntity updateResult = collection.updateDocument(createResult.getKey(), patchDoc); + assertThat(updateResult).isNotNull(); + assertThat(updateResult.getKey()).isEqualTo(createResult.getKey()); + + final BaseDocument readResult = collection.getDocument(createResult.getKey(), BaseDocument.class); + assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); + assertThat(readResult.getProperties()).containsKeys("a", "b"); + assertThat(readResult.getAttribute("a")).isEqualTo("bar"); + assertThat(readResult.getAttribute("b")).isEqualTo("foo"); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void updateDocumentMergeObjectsTrue(ArangoCollection collection) { + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); + final Map a = new HashMap<>(); + a.put("a", "test"); + doc.addAttribute("a", a); + final DocumentCreateEntity createResult = collection.insertDocument(doc, null); + a.clear(); + a.put("b", "test"); + doc.updateAttribute("a", a); + final DocumentUpdateOptions options = new DocumentUpdateOptions().mergeObjects(true); + final DocumentUpdateEntity updateResult = collection.updateDocument(createResult.getKey(), doc, +options); + assertThat(updateResult).isNotNull(); + assertThat(updateResult.getId()).isEqualTo(createResult.getId()); + assertThat(updateResult.getRev()).isNotEqualTo(updateResult.getOldRev()); + assertThat(updateResult.getOldRev()).isEqualTo(createResult.getRev()); + + final BaseDocument readResult = collection.getDocument(createResult.getKey(), BaseDocument.class, null); + assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); + final Object aResult = readResult.getAttribute("a"); + assertThat(aResult).isInstanceOf(Map.class); + final Map aMap = (Map) aResult; + assertThat(aMap).containsKeys("a", "b"); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void updateDocumentMergeObjectsFalse(ArangoCollection collection) { + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); + final Map a = new HashMap<>(); + a.put("a", "test"); + doc.addAttribute("a", a); + final DocumentCreateEntity createResult = collection.insertDocument(doc, null); + a.clear(); + a.put("b", "test"); + doc.updateAttribute("a", a); + final DocumentUpdateOptions options = new DocumentUpdateOptions().mergeObjects(false); + final DocumentUpdateEntity updateResult = collection.updateDocument(createResult.getKey(), doc, + options); + assertThat(updateResult).isNotNull(); + assertThat(updateResult.getId()).isEqualTo(createResult.getId()); + assertThat(updateResult.getRev()).isNotEqualTo(updateResult.getOldRev()); + assertThat(updateResult.getOldRev()).isEqualTo(createResult.getRev()); + + final BaseDocument readResult = collection.getDocument(createResult.getKey(), BaseDocument.class, null); + assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); + final Object aResult = readResult.getAttribute("a"); + assertThat(aResult).isInstanceOf(Map.class); + final Map aMap = (Map) aResult; + assertThat(aMap.keySet()).doesNotContain("a"); + assertThat(aMap).containsKey("b"); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void updateDocumentIgnoreRevsFalse(ArangoCollection collection) { + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); + doc.addAttribute("a", "test"); + final DocumentCreateEntity createResult = collection.insertDocument(doc, null); + doc.updateAttribute("a", "test1"); + doc.setRevision("no"); + + final DocumentUpdateOptions options = new DocumentUpdateOptions().ignoreRevs(false); + Throwable thrown = catchThrowable(() -> collection.updateDocument(createResult.getKey(), doc, options)); + assertThat(thrown).isInstanceOf(ArangoDBException.class); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void updateDocumentSilent(ArangoCollection collection) { + assumeTrue(isSingleServer()); + final DocumentCreateEntity createResult = collection.insertDocument(new BaseDocument()); + final DocumentUpdateEntity meta = collection.updateDocument(createResult.getKey(), + new BaseDocument(), new DocumentUpdateOptions().silent(true)); + assertThat(meta).isNotNull(); + assertThat(meta.getId()).isNull(); + assertThat(meta.getKey()).isNull(); + assertThat(meta.getRev()).isNull(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void updateDocumentsSilent(ArangoCollection collection) { + assumeTrue(isSingleServer()); + final DocumentCreateEntity createResult = collection.insertDocument(new BaseDocument()); + final MultiDocumentEntity> info = +collection.updateDocuments(Collections.singletonList(new BaseDocument(createResult.getKey())), + new DocumentUpdateOptions().silent(true)); + assertThat(info).isNotNull(); + assertThat(info.getDocuments()).isEmpty(); + assertThat(info.getDocumentsAndErrors()).isEmpty(); + assertThat(info.getErrors()).isEmpty(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void updateNonExistingDocument(ArangoCollection collection) { + final BaseDocument doc = new BaseDocument("test-" + rnd()); + doc.addAttribute("a", "test"); + doc.addAttribute("c", "test"); + + Throwable thrown = catchThrowable(() -> collection.updateDocument(doc.getKey(), doc, null)); + assertThat(thrown).isInstanceOf(ArangoDBException.class); + ArangoDBException e = (ArangoDBException) thrown; + assertThat(e.getResponseCode()).isEqualTo(404); + assertThat(e.getErrorNum()).isEqualTo(1202); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void updateDocumentPreconditionFailed(ArangoCollection collection) { + final BaseDocument doc = new BaseDocument("test-" + rnd()); + doc.addAttribute("foo", "a"); + final DocumentCreateEntity createResult = collection.insertDocument(doc, null); + + doc.updateAttribute("foo", "b"); + collection.updateDocument(doc.getKey(), doc, null); + + doc.updateAttribute("foo", "c"); + Throwable thrown = catchThrowable(() -> collection.updateDocument(doc.getKey(), doc, + new DocumentUpdateOptions().ifMatch(createResult.getRev()))); + assertThat(thrown).isInstanceOf(ArangoDBException.class); + ArangoDBException e = (ArangoDBException) thrown; + assertThat(e.getResponseCode()).isEqualTo(412); + assertThat(e.getErrorNum()).isEqualTo(1200); + BaseDocument readDocument = collection.getDocument(doc.getKey(), BaseDocument.class); + assertThat(readDocument.getAttribute("foo")).isEqualTo("b"); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void replaceDocument(ArangoCollection collection) { + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); + doc.addAttribute("a", "test"); + final DocumentCreateEntity createResult = collection.insertDocument(doc, null); + doc.removeAttribute("a"); + doc.addAttribute("b", "test"); + final DocumentUpdateEntity replaceResult = collection.replaceDocument(createResult.getKey(), +doc, null); + assertThat(replaceResult).isNotNull(); + assertThat(replaceResult.getId()).isEqualTo(createResult.getId()); + assertThat(replaceResult.getNew()).isNull(); + assertThat(replaceResult.getOld()).isNull(); + assertThat(replaceResult.getRev()).isNotEqualTo(replaceResult.getOldRev()); + assertThat(replaceResult.getOldRev()).isEqualTo(createResult.getRev()); + + final BaseDocument readResult = collection.getDocument(createResult.getKey(), BaseDocument.class, null); + assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); + assertThat(readResult.getRevision()).isEqualTo(replaceResult.getRev()); + assertThat(readResult.getProperties().keySet()).doesNotContain("a"); + assertThat(readResult.getAttribute("b")).isNotNull(); + assertThat(String.valueOf(readResult.getAttribute("b"))).isEqualTo("test"); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void replaceDocumentUpdateRev(ArangoCollection collection) { + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); + final DocumentCreateEntity createResult = collection.insertDocument(doc, null); + final DocumentUpdateEntity replaceResult = collection.replaceDocument(createResult.getKey(), + doc, null); + assertThat(doc.getRevision()).isNull(); + assertThat(createResult.getRev()).isNotNull(); + assertThat(replaceResult.getRev()) + .isNotNull() + .isNotEqualTo(createResult.getRev()); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void replaceDocumentIfMatch(ArangoCollection collection) { + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); + doc.addAttribute("a", "test"); + final DocumentCreateEntity createResult = collection.insertDocument(doc, null); + doc.removeAttribute("a"); + doc.addAttribute("b", "test"); + final DocumentReplaceOptions options = new DocumentReplaceOptions().ifMatch(createResult.getRev()); + final DocumentUpdateEntity replaceResult = collection.replaceDocument(createResult.getKey(), + doc, options); + assertThat(replaceResult).isNotNull(); + assertThat(replaceResult.getId()).isEqualTo(createResult.getId()); + assertThat(replaceResult.getRev()).isNotEqualTo(replaceResult.getOldRev()); + assertThat(replaceResult.getOldRev()).isEqualTo(createResult.getRev()); + + final BaseDocument readResult = collection.getDocument(createResult.getKey(), BaseDocument.class, null); + assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); + assertThat(readResult.getRevision()).isEqualTo(replaceResult.getRev()); + assertThat(readResult.getProperties().keySet()).doesNotContain("a"); + assertThat(readResult.getAttribute("b")).isNotNull(); + assertThat(String.valueOf(readResult.getAttribute("b"))).isEqualTo("test"); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void replaceDocumentIfMatchFail(ArangoCollection collection) { + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); + doc.addAttribute("a", "test"); + final DocumentCreateEntity createResult = collection.insertDocument(doc, null); + doc.removeAttribute("a"); + doc.addAttribute("b", "test"); + + final DocumentReplaceOptions options = new DocumentReplaceOptions().ifMatch("no"); + Throwable thrown = catchThrowable(() -> collection.replaceDocument(createResult.getKey(), doc, options)); + assertThat(thrown).isInstanceOf(ArangoDBException.class); + + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void replaceDocumentIgnoreRevsFalse(ArangoCollection collection) { + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); + doc.addAttribute("a", "test"); + final DocumentCreateEntity createResult = collection.insertDocument(doc, null); + doc.removeAttribute("a"); + doc.addAttribute("b", "test"); + doc.setRevision("no"); + + final DocumentReplaceOptions options = new DocumentReplaceOptions().ignoreRevs(false); + Throwable thrown = catchThrowable(() -> collection.replaceDocument(createResult.getKey(), doc, options)); + assertThat(thrown).isInstanceOf(ArangoDBException.class); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void replaceDocumentReturnNew(ArangoCollection collection) { + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); + doc.addAttribute("a", "test"); + final DocumentCreateEntity createResult = collection.insertDocument(doc, null); + doc.removeAttribute("a"); + doc.addAttribute("b", "test"); + final DocumentReplaceOptions options = new DocumentReplaceOptions().returnNew(true); + final DocumentUpdateEntity replaceResult = collection.replaceDocument(createResult.getKey(), +doc, options); + assertThat(replaceResult).isNotNull(); + assertThat(replaceResult.getId()).isEqualTo(createResult.getId()); + assertThat(replaceResult.getOldRev()).isEqualTo(createResult.getRev()); + assertThat(replaceResult.getNew()).isNotNull(); + assertThat(replaceResult.getNew().getKey()).isEqualTo(createResult.getKey()); + assertThat(replaceResult.getNew().getRevision()).isNotEqualTo(createResult.getRev()); + assertThat(replaceResult.getNew().getProperties().keySet()).doesNotContain("a"); + assertThat(replaceResult.getNew().getAttribute("b")).isNotNull(); + assertThat(String.valueOf(replaceResult.getNew().getAttribute("b"))).isEqualTo("test"); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void replaceDocumentReturnOld(ArangoCollection collection) { + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); + doc.addAttribute("a", "test"); + final DocumentCreateEntity createResult = collection.insertDocument(doc, null); + doc.removeAttribute("a"); + doc.addAttribute("b", "test"); + final DocumentReplaceOptions options = new DocumentReplaceOptions().returnOld(true); + final DocumentUpdateEntity replaceResult = collection.replaceDocument(createResult.getKey(), + doc, options); + assertThat(replaceResult).isNotNull(); + assertThat(replaceResult.getId()).isEqualTo(createResult.getId()); + assertThat(replaceResult.getOldRev()).isEqualTo(createResult.getRev()); + assertThat(replaceResult.getOld()).isNotNull(); + assertThat(replaceResult.getOld().getKey()).isEqualTo(createResult.getKey()); + assertThat(replaceResult.getOld().getRevision()).isEqualTo(createResult.getRev()); + assertThat(replaceResult.getOld().getAttribute("a")).isNotNull(); + assertThat(String.valueOf(replaceResult.getOld().getAttribute("a"))).isEqualTo("test"); + assertThat(replaceResult.getOld().getProperties().keySet()).doesNotContain("b"); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void replaceDocumentSilent(ArangoCollection collection) { + assumeTrue(isSingleServer()); + final DocumentCreateEntity createResult = collection.insertDocument(new BaseDocument()); + final DocumentUpdateEntity meta = collection.replaceDocument(createResult.getKey(), +new BaseDocument(), new DocumentReplaceOptions().silent(true)); + assertThat(meta).isNotNull(); + assertThat(meta.getId()).isNull(); + assertThat(meta.getKey()).isNull(); + assertThat(meta.getRev()).isNull(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void replaceDocumentSilentDontTouchInstance(ArangoCollection collection) { + assumeTrue(isSingleServer()); + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); + final DocumentCreateEntity createResult = collection.insertDocument(doc); + final DocumentUpdateEntity meta = collection.replaceDocument(createResult.getKey(), doc, + new DocumentReplaceOptions().silent(true)); + assertThat(meta.getRev()).isNull(); + assertThat(doc.getRevision()).isNull(); + assertThat(createResult.getRev()).isNotNull(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void replaceDocumentsSilent(ArangoCollection collection) { + assumeTrue(isSingleServer()); + final DocumentCreateEntity createResult = collection.insertDocument(new BaseDocument()); + final MultiDocumentEntity> info = + collection.replaceDocuments(Collections.singletonList(new BaseDocument(createResult.getKey())), + new DocumentReplaceOptions().silent(true)); + assertThat(info).isNotNull(); + assertThat(info.getDocuments()).isEmpty(); + assertThat(info.getDocumentsAndErrors()).isEmpty(); + assertThat(info.getErrors()).isEmpty(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void deleteDocument(ArangoCollection collection) { + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); + final DocumentCreateEntity createResult = collection.insertDocument(doc, null); + collection.deleteDocument(createResult.getKey()); + final BaseDocument document = collection.getDocument(createResult.getKey(), BaseDocument.class, null); + assertThat(document).isNull(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void deleteDocumentReturnOld(ArangoCollection collection) { + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); + doc.addAttribute("a", "test"); + final DocumentCreateEntity createResult = collection.insertDocument(doc, null); + final DocumentDeleteOptions options = new DocumentDeleteOptions().returnOld(true); + final DocumentDeleteEntity deleteResult = collection.deleteDocument(createResult.getKey(), + options, BaseDocument.class); + assertThat(deleteResult.getOld()).isNotNull(); + assertThat(deleteResult.getOld()).isInstanceOf(BaseDocument.class); + assertThat(deleteResult.getOld().getAttribute("a")).isNotNull(); + assertThat(String.valueOf(deleteResult.getOld().getAttribute("a"))).isEqualTo("test"); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void deleteDocumentIfMatch(ArangoCollection collection) { + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); + final DocumentCreateEntity createResult = collection.insertDocument(doc, null); + final DocumentDeleteOptions options = new DocumentDeleteOptions().ifMatch(createResult.getRev()); + collection.deleteDocument(createResult.getKey(), options); + final BaseDocument document = collection.getDocument(createResult.getKey(), BaseDocument.class, null); + assertThat(document).isNull(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void deleteDocumentIfMatchFail(ArangoCollection collection) { + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); + final DocumentCreateEntity createResult = collection.insertDocument(doc); + final DocumentDeleteOptions options = new DocumentDeleteOptions().ifMatch("no"); + Throwable thrown = catchThrowable(() -> collection.deleteDocument(createResult.getKey(), options)); + assertThat(thrown).isInstanceOf(ArangoDBException.class); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void deleteDocumentSilent(ArangoCollection collection) { + assumeTrue(isSingleServer()); + final DocumentCreateEntity createResult = collection.insertDocument(new BaseDocument()); + final DocumentDeleteEntity meta = collection.deleteDocument(createResult.getKey(), + new DocumentDeleteOptions().silent(true), BaseDocument.class); + assertThat(meta).isNotNull(); + assertThat(meta.getId()).isNull(); + assertThat(meta.getKey()).isNull(); + assertThat(meta.getRev()).isNull(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void deleteDocumentsSilent(ArangoCollection collection) { + assumeTrue(isSingleServer()); + final DocumentCreateEntity createResult = collection.insertDocument(new BaseDocument()); + final MultiDocumentEntity> info = collection.deleteDocuments( + Collections.singletonList(createResult.getKey()), + new DocumentDeleteOptions().silent(true), + BaseDocument.class); + assertThat(info).isNotNull(); + assertThat(info.getDocuments()).isEmpty(); + assertThat(info.getDocumentsAndErrors()).isEmpty(); + assertThat(info.getErrors()).isEmpty(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void getIndex(ArangoCollection collection) { + final Collection fields = new ArrayList<>(); + fields.add("a"); + final IndexEntity createResult = collection.ensureHashIndex(fields, null); + final IndexEntity readResult = collection.getIndex(createResult.getId()); + assertThat(readResult.getId()).isEqualTo(createResult.getId()); + assertThat(readResult.getType()).isEqualTo(createResult.getType()); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void getIndexByKey(ArangoCollection collection) { + final Collection fields = new ArrayList<>(); + fields.add("a"); + final IndexEntity createResult = collection.ensureHashIndex(fields, null); + final IndexEntity readResult = collection.getIndex(createResult.getId().split("/")[1]); + assertThat(readResult.getId()).isEqualTo(createResult.getId()); + assertThat(readResult.getType()).isEqualTo(createResult.getType()); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void deleteIndex(ArangoCollection collection) { + final Collection fields = new ArrayList<>(); + fields.add("a"); + final IndexEntity createResult = collection.ensureHashIndex(fields, null); + final String id = collection.deleteIndex(createResult.getId()); + assertThat(id).isEqualTo(createResult.getId()); + Throwable thrown = catchThrowable(() -> collection.db().getIndex(id)); + assertThat(thrown).isInstanceOf(ArangoDBException.class); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void deleteIndexByKey(ArangoCollection collection) { + final Collection fields = new ArrayList<>(); + fields.add("a"); + final IndexEntity createResult = collection.ensureHashIndex(fields, null); + final String id = collection.deleteIndex(createResult.getId().split("/")[1]); + assertThat(id).isEqualTo(createResult.getId()); + Throwable thrown = catchThrowable(() -> collection.db().getIndex(id)); + assertThat(thrown).isInstanceOf(ArangoDBException.class); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void createHashIndex(ArangoCollection collection) { + String f1 = "field-" + rnd(); + String f2 = "field-" + rnd(); + final Collection fields = Arrays.asList(f1, f2); + final IndexEntity indexResult = collection.ensureHashIndex(fields, null); + assertThat(indexResult).isNotNull(); + assertThat(indexResult.getConstraint()).isNull(); + assertThat(indexResult.getFields()).contains(f1); + assertThat(indexResult.getFields()).contains(f2); + assertThat(indexResult.getId()).startsWith(COLLECTION_NAME); + assertThat(indexResult.getIsNewlyCreated()).isTrue(); + assertThat(indexResult.getMinLength()).isNull(); + if (isSingleServer()) { + assertThat(indexResult.getSelectivityEstimate()).isPositive(); + } + assertThat(indexResult.getSparse()).isFalse(); + assertThat(indexResult.getType()).isEqualTo(IndexType.hash); + assertThat(indexResult.getUnique()).isFalse(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void createHashIndexWithOptions(ArangoCollection collection) { + assumeTrue(isAtLeastVersion(3, 5)); + + String name = "hashIndex-" + rnd(); + final HashIndexOptions options = new HashIndexOptions(); + options.name(name); + + String f1 = "field-" + rnd(); + String f2 = "field-" + rnd(); + final Collection fields = Arrays.asList(f1, f2); + + final IndexEntity indexResult = collection.ensureHashIndex(fields, options); + assertThat(indexResult).isNotNull(); + assertThat(indexResult.getConstraint()).isNull(); + assertThat(indexResult.getFields()).contains(f1); + assertThat(indexResult.getFields()).contains(f2); + assertThat(indexResult.getId()).startsWith(COLLECTION_NAME); + assertThat(indexResult.getIsNewlyCreated()).isTrue(); + assertThat(indexResult.getMinLength()).isNull(); + if (isSingleServer()) { + assertThat(indexResult.getSelectivityEstimate()).isPositive(); + } + assertThat(indexResult.getSparse()).isFalse(); + assertThat(indexResult.getType()).isEqualTo(IndexType.hash); + assertThat(indexResult.getUnique()).isFalse(); + assertThat(indexResult.getName()).isEqualTo(name); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void createGeoIndex(ArangoCollection collection) { + String f1 = "field-" + rnd(); + final Collection fields = Collections.singletonList(f1); + final IndexEntity indexResult = collection.ensureGeoIndex(fields, null); + assertThat(indexResult).isNotNull(); + assertThat(indexResult.getFields()).contains(f1); + assertThat(indexResult.getId()).startsWith(COLLECTION_NAME); + assertThat(indexResult.getIsNewlyCreated()).isTrue(); + assertThat(indexResult.getMinLength()).isNull(); + assertThat(indexResult.getSparse()).isTrue(); + assertThat(indexResult.getUnique()).isFalse(); + if (isAtLeastVersion(3, 4)) { + assertThat(indexResult.getType()).isEqualTo(IndexType.geo); + } else { + assertThat(indexResult.getType()).isEqualTo(IndexType.geo1); + } + if (isAtLeastVersion(3, 10)) { + assertThat(indexResult.getLegacyPolygons()).isFalse(); + } + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void createGeoIndexWithOptions(ArangoCollection collection) { + assumeTrue(isAtLeastVersion(3, 5)); + + String name = "geoIndex-" + rnd(); + final GeoIndexOptions options = new GeoIndexOptions(); + options.name(name); + + String f1 = "field-" + rnd(); + final Collection fields = Collections.singletonList(f1); + final IndexEntity indexResult = collection.ensureGeoIndex(fields, options); + assertThat(indexResult).isNotNull(); + assertThat(indexResult.getFields()).contains(f1); + assertThat(indexResult.getId()).startsWith(COLLECTION_NAME); + assertThat(indexResult.getIsNewlyCreated()).isTrue(); + assertThat(indexResult.getMinLength()).isNull(); + assertThat(indexResult.getSparse()).isTrue(); + assertThat(indexResult.getUnique()).isFalse(); + if (isAtLeastVersion(3, 4)) { + assertThat(indexResult.getType()).isEqualTo(IndexType.geo); + } else { + assertThat(indexResult.getType()).isEqualTo(IndexType.geo1); + } + assertThat(indexResult.getName()).isEqualTo(name); + if (isAtLeastVersion(3, 10)) { + assertThat(indexResult.getLegacyPolygons()).isFalse(); + } + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void createGeoIndexLegacyPolygons(ArangoCollection collection) { + assumeTrue(isAtLeastVersion(3, 10)); + + String name = "geoIndex-" + rnd(); + final GeoIndexOptions options = new GeoIndexOptions(); + options.name(name); + options.legacyPolygons(true); + + String f1 = "field-" + rnd(); + final Collection fields = Collections.singletonList(f1); + final IndexEntity indexResult = collection.ensureGeoIndex(fields, options); + assertThat(indexResult).isNotNull(); + assertThat(indexResult.getFields()).contains(f1); + assertThat(indexResult.getId()).startsWith(COLLECTION_NAME); + assertThat(indexResult.getIsNewlyCreated()).isTrue(); + assertThat(indexResult.getMinLength()).isNull(); + assertThat(indexResult.getSparse()).isTrue(); + assertThat(indexResult.getUnique()).isFalse(); + if (isAtLeastVersion(3, 4)) { + assertThat(indexResult.getType()).isEqualTo(IndexType.geo); + } else { + assertThat(indexResult.getType()).isEqualTo(IndexType.geo1); + } + assertThat(indexResult.getName()).isEqualTo(name); + if (isAtLeastVersion(3, 10)) { + assertThat(indexResult.getLegacyPolygons()).isTrue(); + } + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void createGeo2Index(ArangoCollection collection) { + String f1 = "field-" + rnd(); + String f2 = "field-" + rnd(); + final Collection fields = Arrays.asList(f1, f2); + + final IndexEntity indexResult = collection.ensureGeoIndex(fields, null); + assertThat(indexResult).isNotNull(); + assertThat(indexResult.getFields()).contains(f1); + assertThat(indexResult.getFields()).contains(f2); + assertThat(indexResult.getId()).startsWith(COLLECTION_NAME); + assertThat(indexResult.getIsNewlyCreated()).isTrue(); + assertThat(indexResult.getMinLength()).isNull(); + assertThat(indexResult.getSparse()).isTrue(); + assertThat(indexResult.getUnique()).isFalse(); + if (isAtLeastVersion(3, 4)) { + assertThat(indexResult.getType()).isEqualTo(IndexType.geo); + } else { + assertThat(indexResult.getType()).isEqualTo(IndexType.geo2); + } + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void createGeo2IndexWithOptions(ArangoCollection collection) { + assumeTrue(isAtLeastVersion(3, 5)); + + String name = "geoIndex-" + rnd(); + final GeoIndexOptions options = new GeoIndexOptions(); + options.name(name); + + String f1 = "field-" + rnd(); + String f2 = "field-" + rnd(); + final Collection fields = Arrays.asList(f1, f2); + + final IndexEntity indexResult = collection.ensureGeoIndex(fields, options); + assertThat(indexResult).isNotNull(); + assertThat(indexResult.getFields()).contains(f1); + assertThat(indexResult.getFields()).contains(f2); + assertThat(indexResult.getId()).startsWith(COLLECTION_NAME); + assertThat(indexResult.getIsNewlyCreated()).isTrue(); + assertThat(indexResult.getMinLength()).isNull(); + assertThat(indexResult.getSparse()).isTrue(); + assertThat(indexResult.getUnique()).isFalse(); + if (isAtLeastVersion(3, 4)) { + assertThat(indexResult.getType()).isEqualTo(IndexType.geo); + } else { + assertThat(indexResult.getType()).isEqualTo(IndexType.geo2); + } + assertThat(indexResult.getName()).isEqualTo(name); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void createSkiplistIndex(ArangoCollection collection) { + String f1 = "field-" + rnd(); + String f2 = "field-" + rnd(); + final Collection fields = Arrays.asList(f1, f2); + final IndexEntity indexResult = collection.ensureSkiplistIndex(fields, null); + assertThat(indexResult).isNotNull(); + assertThat(indexResult.getConstraint()).isNull(); + assertThat(indexResult.getFields()).contains(f1); + assertThat(indexResult.getFields()).contains(f2); + assertThat(indexResult.getId()).startsWith(COLLECTION_NAME); + assertThat(indexResult.getIsNewlyCreated()).isTrue(); + assertThat(indexResult.getMinLength()).isNull(); + assertThat(indexResult.getSparse()).isFalse(); + assertThat(indexResult.getType()).isEqualTo(IndexType.skiplist); + assertThat(indexResult.getUnique()).isFalse(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void createSkiplistIndexWithOptions(ArangoCollection collection) { + assumeTrue(isAtLeastVersion(3, 5)); + + String name = "skiplistIndex-" + rnd(); + final SkiplistIndexOptions options = new SkiplistIndexOptions(); + options.name(name); + + String f1 = "field-" + rnd(); + String f2 = "field-" + rnd(); + final Collection fields = Arrays.asList(f1, f2); + final IndexEntity indexResult = collection.ensureSkiplistIndex(fields, options); + assertThat(indexResult).isNotNull(); + assertThat(indexResult.getConstraint()).isNull(); + assertThat(indexResult.getFields()).contains(f1); + assertThat(indexResult.getFields()).contains(f2); + assertThat(indexResult.getId()).startsWith(COLLECTION_NAME); + assertThat(indexResult.getIsNewlyCreated()).isTrue(); + assertThat(indexResult.getMinLength()).isNull(); + assertThat(indexResult.getSparse()).isFalse(); + assertThat(indexResult.getType()).isEqualTo(IndexType.skiplist); + assertThat(indexResult.getUnique()).isFalse(); + assertThat(indexResult.getName()).isEqualTo(name); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void createPersistentIndex(ArangoCollection collection) { + String f1 = "field-" + rnd(); + String f2 = "field-" + rnd(); + final Collection fields = Arrays.asList(f1, f2); + + final IndexEntity indexResult = collection.ensurePersistentIndex(fields, null); + assertThat(indexResult).isNotNull(); + assertThat(indexResult.getConstraint()).isNull(); + assertThat(indexResult.getFields()).contains(f1); + assertThat(indexResult.getFields()).contains(f2); + assertThat(indexResult.getId()).startsWith(COLLECTION_NAME); + assertThat(indexResult.getIsNewlyCreated()).isTrue(); + assertThat(indexResult.getMinLength()).isNull(); + assertThat(indexResult.getSparse()).isFalse(); + assertThat(indexResult.getType()).isEqualTo(IndexType.persistent); + assertThat(indexResult.getUnique()).isFalse(); + assertThat(indexResult.getDeduplicate()).isTrue(); + if (isAtLeastVersion(3, 10)) { + assertThat(indexResult.getCacheEnabled()).isFalse(); + } + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void createPersistentIndexCacheEnabled(ArangoCollection collection) { + assumeTrue(isAtLeastVersion(3, 10)); + + String f1 = "field-" + rnd(); + String f2 = "field-" + rnd(); + final Collection fields = Arrays.asList(f1, f2); + + final IndexEntity indexResult = collection.ensurePersistentIndex(fields, new PersistentIndexOptions().cacheEnabled(true)); + assertThat(indexResult).isNotNull(); + assertThat(indexResult.getConstraint()).isNull(); + assertThat(indexResult.getFields()).contains(f1); + assertThat(indexResult.getFields()).contains(f2); + assertThat(indexResult.getId()).startsWith(COLLECTION_NAME); + assertThat(indexResult.getIsNewlyCreated()).isTrue(); + assertThat(indexResult.getMinLength()).isNull(); + assertThat(indexResult.getSparse()).isFalse(); + assertThat(indexResult.getType()).isEqualTo(IndexType.persistent); + assertThat(indexResult.getUnique()).isFalse(); + assertThat(indexResult.getDeduplicate()).isTrue(); + assertThat(indexResult.getCacheEnabled()).isTrue(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void createPersistentIndexStoredValues(ArangoCollection collection) { + assumeTrue(isAtLeastVersion(3, 10)); + + String f1 = "field-" + rnd(); + String f2 = "field-" + rnd(); + final Collection fields = Arrays.asList(f1, f2); + + final IndexEntity indexResult = collection.ensurePersistentIndex(fields, new PersistentIndexOptions().storedValues("v1", "v2")); + assertThat(indexResult).isNotNull(); + assertThat(indexResult.getConstraint()).isNull(); + assertThat(indexResult.getFields()).contains(f1); + assertThat(indexResult.getFields()).contains(f2); + assertThat(indexResult.getId()).startsWith(COLLECTION_NAME); + assertThat(indexResult.getIsNewlyCreated()).isTrue(); + assertThat(indexResult.getMinLength()).isNull(); + assertThat(indexResult.getSparse()).isFalse(); + assertThat(indexResult.getType()).isEqualTo(IndexType.persistent); + assertThat(indexResult.getUnique()).isFalse(); + assertThat(indexResult.getDeduplicate()).isTrue(); + assertThat(indexResult.getCacheEnabled()).isFalse(); + assertThat(indexResult.getStoredValues()) + .hasSize(2) + .contains("v1", "v2"); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void createPersistentIndexWithOptions(ArangoCollection collection) { + assumeTrue(isAtLeastVersion(3, 5)); + + String name = "persistentIndex-" + rnd(); + final PersistentIndexOptions options = new PersistentIndexOptions(); + options.name(name); + + String f1 = "field-" + rnd(); + String f2 = "field-" + rnd(); + + final Collection fields = Arrays.asList(f1, f2); + final IndexEntity indexResult = collection.ensurePersistentIndex(fields, options); + assertThat(indexResult).isNotNull(); + assertThat(indexResult.getConstraint()).isNull(); + assertThat(indexResult.getFields()).contains(f1); + assertThat(indexResult.getFields()).contains(f2); + assertThat(indexResult.getId()).startsWith(COLLECTION_NAME); + assertThat(indexResult.getIsNewlyCreated()).isTrue(); + assertThat(indexResult.getMinLength()).isNull(); + assertThat(indexResult.getSparse()).isFalse(); + assertThat(indexResult.getType()).isEqualTo(IndexType.persistent); + assertThat(indexResult.getUnique()).isFalse(); + assertThat(indexResult.getName()).isEqualTo(name); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void createZKDIndex(ArangoCollection collection) { + assumeTrue(isAtLeastVersion(3, 9)); + collection.truncate(); + String f1 = "field-" + rnd(); + String f2 = "field-" + rnd(); + final Collection fields = Arrays.asList(f1, f2); + + final IndexEntity indexResult = collection.ensureZKDIndex(fields, null); + assertThat(indexResult).isNotNull(); + assertThat(indexResult.getConstraint()).isNull(); + assertThat(indexResult.getFields()).contains(f1); + assertThat(indexResult.getFields()).contains(f2); + assertThat(indexResult.getId()).startsWith(COLLECTION_NAME); + assertThat(indexResult.getIsNewlyCreated()).isTrue(); + assertThat(indexResult.getMinLength()).isNull(); + assertThat(indexResult.getType()).isEqualTo(IndexType.zkd); + assertThat(indexResult.getUnique()).isFalse(); + collection.deleteIndex(indexResult.getId()); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void createZKDIndexWithOptions(ArangoCollection collection) { + assumeTrue(isAtLeastVersion(3, 9)); + collection.truncate(); + + String name = "ZKDIndex-" + rnd(); + final ZKDIndexOptions options = + new ZKDIndexOptions().name(name).fieldValueTypes(ZKDIndexOptions.FieldValueTypes.DOUBLE); + + String f1 = "field-" + rnd(); + String f2 = "field-" + rnd(); + + final Collection fields = Arrays.asList(f1, f2); + final IndexEntity indexResult = collection.ensureZKDIndex(fields, options); + assertThat(indexResult).isNotNull(); + assertThat(indexResult.getConstraint()).isNull(); + assertThat(indexResult.getFields()).contains(f1); + assertThat(indexResult.getFields()).contains(f2); + assertThat(indexResult.getId()).startsWith(COLLECTION_NAME); + assertThat(indexResult.getIsNewlyCreated()).isTrue(); + assertThat(indexResult.getMinLength()).isNull(); + assertThat(indexResult.getType()).isEqualTo(IndexType.zkd); + assertThat(indexResult.getUnique()).isFalse(); + assertThat(indexResult.getName()).isEqualTo(name); + collection.deleteIndex(indexResult.getId()); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void indexEstimates(ArangoCollection collection) { + assumeTrue(isAtLeastVersion(3, 8)); + assumeTrue(isSingleServer()); + + String name = "persistentIndex-" + rnd(); + final PersistentIndexOptions options = new PersistentIndexOptions(); + options.name(name); + options.estimates(true); + + String f1 = "field-" + rnd(); + String f2 = "field-" + rnd(); + + final Collection fields = Arrays.asList(f1, f2); + final IndexEntity indexResult = collection.ensurePersistentIndex(fields, options); + assertThat(indexResult).isNotNull(); + assertThat(indexResult.getEstimates()).isTrue(); + assertThat(indexResult.getSelectivityEstimate()).isNotNull(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void indexEstimatesFalse(ArangoCollection collection) { + assumeTrue(isAtLeastVersion(3, 8)); + assumeTrue(isSingleServer()); + + String name = "persistentIndex-" + rnd(); + final PersistentIndexOptions options = new PersistentIndexOptions(); + options.name(name); + options.estimates(false); + + String f1 = "field-" + rnd(); + String f2 = "field-" + rnd(); + + final Collection fields = Arrays.asList(f1, f2); + final IndexEntity indexResult = collection.ensurePersistentIndex(fields, options); + assertThat(indexResult).isNotNull(); + assertThat(indexResult.getEstimates()).isFalse(); + assertThat(indexResult.getSelectivityEstimate()).isNull(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void indexDeduplicate(ArangoCollection collection) { + assumeTrue(isAtLeastVersion(3, 8)); + + String name = "persistentIndex-" + rnd(); + final PersistentIndexOptions options = new PersistentIndexOptions(); + options.name(name); + options.deduplicate(true); + + String f1 = "field-" + rnd(); + String f2 = "field-" + rnd(); + + final Collection fields = Arrays.asList(f1, f2); + final IndexEntity indexResult = collection.ensurePersistentIndex(fields, options); + assertThat(indexResult).isNotNull(); + assertThat(indexResult.getDeduplicate()).isTrue(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void indexDeduplicateFalse(ArangoCollection collection) { + assumeTrue(isAtLeastVersion(3, 8)); + + String name = "persistentIndex-" + rnd(); + final PersistentIndexOptions options = new PersistentIndexOptions(); + options.name(name); + options.deduplicate(false); + + String f1 = "field-" + rnd(); + String f2 = "field-" + rnd(); + + final Collection fields = Arrays.asList(f1, f2); + final IndexEntity indexResult = collection.ensurePersistentIndex(fields, options); + assertThat(indexResult).isNotNull(); + assertThat(indexResult.getDeduplicate()).isFalse(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void createFulltextIndex(ArangoCollection collection) { + String f1 = "field-" + rnd(); + final Collection fields = Collections.singletonList(f1); + final IndexEntity indexResult = collection.ensureFulltextIndex(fields, null); + assertThat(indexResult).isNotNull(); + assertThat(indexResult.getConstraint()).isNull(); + assertThat(indexResult.getFields()).contains(f1); + assertThat(indexResult.getId()).startsWith(COLLECTION_NAME); + assertThat(indexResult.getIsNewlyCreated()).isTrue(); + assertThat(indexResult.getSparse()).isTrue(); + assertThat(indexResult.getType()).isEqualTo(IndexType.fulltext); + assertThat(indexResult.getUnique()).isFalse(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void createFulltextIndexWithOptions(ArangoCollection collection) { + assumeTrue(isAtLeastVersion(3, 5)); + + String name = "fulltextIndex-" + rnd(); + final FulltextIndexOptions options = new FulltextIndexOptions(); + options.name(name); + + String f = "field-" + rnd(); + final Collection fields = Collections.singletonList(f); + final IndexEntity indexResult = collection.ensureFulltextIndex(fields, options); + assertThat(indexResult).isNotNull(); + assertThat(indexResult.getConstraint()).isNull(); + assertThat(indexResult.getFields()).contains(f); + assertThat(indexResult.getId()).startsWith(COLLECTION_NAME); + assertThat(indexResult.getIsNewlyCreated()).isTrue(); + assertThat(indexResult.getSparse()).isTrue(); + assertThat(indexResult.getType()).isEqualTo(IndexType.fulltext); + assertThat(indexResult.getUnique()).isFalse(); + assertThat(indexResult.getName()).isEqualTo(name); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void createTtlIndexWithoutOptions(ArangoCollection collection) { + assumeTrue(isAtLeastVersion(3, 5)); + final Collection fields = new ArrayList<>(); + fields.add("a"); + + Throwable thrown = catchThrowable(() -> collection.ensureTtlIndex(fields, null)); + assertThat(thrown).isInstanceOf(ArangoDBException.class); + ArangoDBException e = (ArangoDBException) thrown; + assertThat(e.getResponseCode()).isEqualTo(400); + assertThat(e.getErrorNum()).isEqualTo(10); + assertThat(e.getMessage()).contains("expireAfter attribute must be a number"); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void createTtlIndexWithOptions(ArangoCollection collection) { + assumeTrue(isAtLeastVersion(3, 5)); + + String f1 = "field-" + rnd(); + final Collection fields = Collections.singletonList(f1); + + String name = "ttlIndex-" + rnd(); + final TtlIndexOptions options = new TtlIndexOptions(); + options.name(name); + options.expireAfter(3600); + + final IndexEntity indexResult = collection.ensureTtlIndex(fields, options); + assertThat(indexResult).isNotNull(); + assertThat(indexResult.getFields()).contains(f1); + assertThat(indexResult.getId()).startsWith(COLLECTION_NAME); + assertThat(indexResult.getIsNewlyCreated()).isTrue(); + assertThat(indexResult.getType()).isEqualTo(IndexType.ttl); + assertThat(indexResult.getExpireAfter()).isEqualTo(3600); + assertThat(indexResult.getName()).isEqualTo(name); + + // revert changes + collection.deleteIndex(indexResult.getId()); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void getIndexes(ArangoCollection collection) { + String f1 = "field-" + rnd(); + final Collection fields = Collections.singletonList(f1); + collection.ensureHashIndex(fields, null); + long matchingIndexes = + collection.getIndexes().stream().filter(i -> i.getType() == IndexType.hash).filter(i -> i.getFields().contains(f1)).count(); + assertThat(matchingIndexes).isEqualTo(1L); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("edges") + void getEdgeIndex(ArangoCollection edgeCollection) { + Collection indexes = edgeCollection.getIndexes(); + long primaryIndexes = indexes.stream().filter(i -> i.getType() == IndexType.primary).count(); + long edgeIndexes = indexes.stream().filter(i -> i.getType() == IndexType.primary).count(); + assertThat(primaryIndexes).isEqualTo(1L); + assertThat(edgeIndexes).isEqualTo(1L); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void exists(ArangoCollection collection) { + assertThat(collection.exists()).isTrue(); + assertThat(collection.db().collection(COLLECTION_NAME + "no").exists()).isFalse(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void truncate(ArangoCollection collection) { + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); + collection.insertDocument(doc, null); + final BaseDocument readResult = collection.getDocument(doc.getKey(), BaseDocument.class, null); + assertThat(readResult.getKey()).isEqualTo(doc.getKey()); + final CollectionEntity truncateResult = collection.truncate(); + assertThat(truncateResult).isNotNull(); + assertThat(truncateResult.getId()).isNotNull(); + final BaseDocument document = collection.getDocument(doc.getKey(), BaseDocument.class, null); + assertThat(document).isNull(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void getCount(ArangoCollection collection) { + Long initialCount = collection.count().getCount(); + collection.insertDocument(RawJson.of("{}")); + final CollectionPropertiesEntity count = collection.count(); + assertThat(count.getCount()).isEqualTo(initialCount + 1L); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void documentExists(ArangoCollection collection) { + final Boolean existsNot = collection.documentExists(rnd(), null); + assertThat(existsNot).isFalse(); + + String key = rnd(); + RawJson rawJson = RawJson.of("{\"_key\":\"" + key + "\"}"); + collection.insertDocument(rawJson); + final Boolean exists = collection.documentExists(key, null); + assertThat(exists).isTrue(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void documentExistsIfMatch(ArangoCollection collection) { + String key = rnd(); + RawJson rawJson = RawJson.of("{\"_key\":\"" + key + "\"}"); + final DocumentCreateEntity createResult = collection.insertDocument(rawJson); + final DocumentExistsOptions options = new DocumentExistsOptions().ifMatch(createResult.getRev()); + final Boolean exists = collection.documentExists(key, options); + assertThat(exists).isTrue(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void documentExistsIfMatchFail(ArangoCollection collection) { + String key = rnd(); + RawJson rawJson = RawJson.of("{\"_key\":\"" + key + "\"}"); + collection.insertDocument(rawJson); + final DocumentExistsOptions options = new DocumentExistsOptions().ifMatch("no"); + final Boolean exists = collection.documentExists(key, options); + assertThat(exists).isFalse(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void documentExistsIfNoneMatch(ArangoCollection collection) { + String key = rnd(); + RawJson rawJson = RawJson.of("{\"_key\":\"" + key + "\"}"); + collection.insertDocument(rawJson); + final DocumentExistsOptions options = new DocumentExistsOptions().ifNoneMatch("no"); + final Boolean exists = collection.documentExists(key, options); + assertThat(exists).isTrue(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void documentExistsIfNoneMatchFail(ArangoCollection collection) { + String key = rnd(); + RawJson rawJson = RawJson.of("{\"_key\":\"" + key + "\"}"); + final DocumentCreateEntity createResult = collection.insertDocument(rawJson); + final DocumentExistsOptions options = new DocumentExistsOptions().ifNoneMatch(createResult.getRev()); + final Boolean exists = collection.documentExists(key, options); + assertThat(exists).isFalse(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void insertDocuments(ArangoCollection collection) { + final Collection values = Arrays.asList(new BaseDocument(), new BaseDocument(), + new BaseDocument()); + + final MultiDocumentEntity docs = collection.insertDocuments(values); + assertThat(docs).isNotNull(); + assertThat(docs.getDocuments()).isNotNull(); + assertThat(docs.getDocuments()).hasSize(3); + assertThat(docs.getErrors()).isNotNull(); + assertThat(docs.getErrors()).isEmpty(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void insertDocumentsOverwriteModeUpdate(ArangoCollection collection) { + assumeTrue(isAtLeastVersion(3, 7)); + + final BaseDocument doc1 = new BaseDocument(UUID.randomUUID().toString()); + doc1.addAttribute("foo", "a"); + final DocumentCreateEntity meta1 = collection.insertDocument(doc1); + + final BaseDocument doc2 = new BaseDocument(UUID.randomUUID().toString()); + doc2.addAttribute("foo", "a"); + final DocumentCreateEntity meta2 = collection.insertDocument(doc2); + + doc1.addAttribute("bar", "b"); + doc2.addAttribute("bar", "b"); + + final MultiDocumentEntity> repsert = + collection.insertDocuments(Arrays.asList(doc1, doc2), + new DocumentCreateOptions().overwriteMode(OverwriteMode.update).returnNew(true)); + assertThat(repsert).isNotNull(); + assertThat(repsert.getDocuments()).hasSize(2); + assertThat(repsert.getErrors()).isEmpty(); + for (final DocumentCreateEntity documentCreateEntity : repsert.getDocuments()) { + assertThat(documentCreateEntity.getRev()).isNotEqualTo(meta1.getRev()); + assertThat(documentCreateEntity.getRev()).isNotEqualTo(meta2.getRev()); + assertThat(documentCreateEntity.getNew().getAttribute("foo")).isEqualTo("a"); + assertThat(documentCreateEntity.getNew().getAttribute("bar")).isEqualTo("b"); + } + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void insertDocumentsJson(ArangoCollection collection) { + final Collection values = new ArrayList<>(); + values.add(RawJson.of("{}")); + values.add(RawJson.of("{}")); + values.add(RawJson.of("{}")); + final MultiDocumentEntity docs = collection.insertDocuments(values); + assertThat(docs).isNotNull(); + assertThat(docs.getDocuments()).isNotNull(); + assertThat(docs.getDocuments()).hasSize(3); + assertThat(docs.getErrors()).isNotNull(); + assertThat(docs.getErrors()).isEmpty(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void insertDocumentsRawData(ArangoCollection collection) { + final RawData values = RawData.of("[{},{},{}]"); + final MultiDocumentEntity docs = collection.insertDocuments(values); + assertThat(docs).isNotNull(); + assertThat(docs.getDocuments()).isNotNull(); + assertThat(docs.getDocuments()).hasSize(3); + assertThat(docs.getErrors()).isNotNull(); + assertThat(docs.getErrors()).isEmpty(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void insertDocumentsRawDataReturnNew(ArangoCollection collection) { + final RawData values = RawData.of("[{\"aaa\":33},{\"aaa\":33},{\"aaa\":33}]"); + final MultiDocumentEntity> docs = + collection.insertDocuments(values, new DocumentCreateOptions().returnNew(true)); + assertThat(docs).isNotNull(); + assertThat(docs.getDocuments()).isNotNull(); + assertThat(docs.getDocuments()).hasSize(3); + assertThat(docs.getErrors()).isNotNull(); + assertThat(docs.getErrors()).isEmpty(); + + for (final DocumentCreateEntity doc : docs.getDocuments()) { + RawData d = doc.getNew(); + assertThat(d) + .isNotNull() + .isInstanceOf(RawJson.class); + + JsonNode jn = SerdeUtils.INSTANCE.parseJson(((RawJson) d).getValue()); + assertThat(jn.has("aaa")).isTrue(); + assertThat(jn.get("aaa").intValue()).isEqualTo(33); + } + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void insertDocumentsOne(ArangoCollection collection) { + final Collection values = new ArrayList<>(); + values.add(new BaseDocument()); + final MultiDocumentEntity docs = collection.insertDocuments(values); + assertThat(docs).isNotNull(); + assertThat(docs.getDocuments()).isNotNull(); + assertThat(docs.getDocuments()).hasSize(1); + assertThat(docs.getErrors()).isNotNull(); + assertThat(docs.getErrors()).isEmpty(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void insertDocumentsEmpty(ArangoCollection collection) { + final Collection values = new ArrayList<>(); + final MultiDocumentEntity docs = collection.insertDocuments(values); + assertThat(docs).isNotNull(); + assertThat(docs.getDocuments()).isNotNull(); + assertThat(docs.getDocuments()).isEmpty(); + assertThat(docs.getErrors()).isNotNull(); + assertThat(docs.getErrors()).isEmpty(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void insertDocumentsReturnNew(ArangoCollection collection) { + final Collection values = new ArrayList<>(); + values.add(new BaseDocument()); + values.add(new BaseDocument()); + values.add(new BaseDocument()); + final DocumentCreateOptions options = new DocumentCreateOptions().returnNew(true); + final MultiDocumentEntity> docs = collection.insertDocuments(values, + options); + assertThat(docs).isNotNull(); + assertThat(docs.getDocuments()).isNotNull(); + assertThat(docs.getDocuments()).hasSize(3); + assertThat(docs.getErrors()).isNotNull(); + assertThat(docs.getErrors()).isEmpty(); + for (final DocumentCreateEntity doc : docs.getDocuments()) { + assertThat(doc.getNew()).isNotNull(); + final BaseDocument baseDocument = doc.getNew(); + assertThat(baseDocument.getKey()).isNotNull(); + } + + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void insertDocumentsFail(ArangoCollection collection) { + String k1 = rnd(); + String k2 = rnd(); + final Collection values = Arrays.asList(new BaseDocument(k1), new BaseDocument(k2), + new BaseDocument(k2)); + + final MultiDocumentEntity docs = collection.insertDocuments(values); + assertThat(docs).isNotNull(); + assertThat(docs.getDocuments()).isNotNull(); + assertThat(docs.getDocuments()).hasSize(2); + assertThat(docs.getErrors()).isNotNull(); + assertThat(docs.getErrors()).hasSize(1); + assertThat(docs.getErrors().iterator().next().getErrorNum()).isEqualTo(1210); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void importDocuments(ArangoCollection collection) { + final Collection values = Arrays.asList(new BaseDocument(), new BaseDocument(), + new BaseDocument()); + + final DocumentImportEntity docs = collection.importDocuments(values); + assertThat(docs).isNotNull(); + assertThat(docs.getCreated()).isEqualTo(values.size()); + assertThat(docs.getEmpty()).isZero(); + assertThat(docs.getErrors()).isZero(); + assertThat(docs.getIgnored()).isZero(); + assertThat(docs.getUpdated()).isZero(); + assertThat(docs.getDetails()).isEmpty(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void importDocumentsJsonList(ArangoCollection collection) { + final Collection values = Arrays.asList( + RawJson.of("{}"), + RawJson.of("{}"), + RawJson.of("{}") + ); + + final DocumentImportEntity docs = collection.importDocuments(values); + assertThat(docs).isNotNull(); + assertThat(docs.getCreated()).isEqualTo(values.size()); + assertThat(docs.getEmpty()).isZero(); + assertThat(docs.getErrors()).isZero(); + assertThat(docs.getIgnored()).isZero(); + assertThat(docs.getUpdated()).isZero(); + assertThat(docs.getDetails()).isEmpty(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void importDocumentsDuplicateDefaultError(ArangoCollection collection) { + String k1 = rnd(); + String k2 = rnd(); + + final Collection values = Arrays.asList(new BaseDocument(k1), new BaseDocument(k2), +new BaseDocument(k2)); + + final DocumentImportEntity docs = collection.importDocuments(values); + assertThat(docs).isNotNull(); + assertThat(docs.getCreated()).isEqualTo(2); + assertThat(docs.getEmpty()).isZero(); + assertThat(docs.getErrors()).isEqualTo(1); + assertThat(docs.getIgnored()).isZero(); + assertThat(docs.getUpdated()).isZero(); + assertThat(docs.getDetails()).isEmpty(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void importDocumentsDuplicateError(ArangoCollection collection) { + String k1 = rnd(); + String k2 = rnd(); + + final Collection values = Arrays.asList(new BaseDocument(k1), new BaseDocument(k2), + new BaseDocument(k2)); + + final DocumentImportEntity docs = collection.importDocuments(values, + new DocumentImportOptions().onDuplicate(OnDuplicate.error)); + assertThat(docs).isNotNull(); + assertThat(docs.getCreated()).isEqualTo(2); + assertThat(docs.getEmpty()).isZero(); + assertThat(docs.getErrors()).isEqualTo(1); + assertThat(docs.getIgnored()).isZero(); + assertThat(docs.getUpdated()).isZero(); + assertThat(docs.getDetails()).isEmpty(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void importDocumentsDuplicateIgnore(ArangoCollection collection) { + String k1 = rnd(); + String k2 = rnd(); + + final Collection values = Arrays.asList(new BaseDocument(k1), new BaseDocument(k2), + new BaseDocument(k2)); + + final DocumentImportEntity docs = collection.importDocuments(values, + new DocumentImportOptions().onDuplicate(OnDuplicate.ignore)); + assertThat(docs).isNotNull(); + assertThat(docs.getCreated()).isEqualTo(2); + assertThat(docs.getEmpty()).isZero(); + assertThat(docs.getErrors()).isZero(); + assertThat(docs.getIgnored()).isEqualTo(1); + assertThat(docs.getUpdated()).isZero(); + assertThat(docs.getDetails()).isEmpty(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void importDocumentsDuplicateReplace(ArangoCollection collection) { + String k1 = rnd(); + String k2 = rnd(); + + final Collection values = Arrays.asList(new BaseDocument(k1), new BaseDocument(k2), + new BaseDocument(k2)); + + final DocumentImportEntity docs = collection.importDocuments(values, +new DocumentImportOptions().onDuplicate(OnDuplicate.replace)); + assertThat(docs).isNotNull(); + assertThat(docs.getCreated()).isEqualTo(2); + assertThat(docs.getEmpty()).isZero(); + assertThat(docs.getErrors()).isZero(); + assertThat(docs.getIgnored()).isZero(); + assertThat(docs.getUpdated()).isEqualTo(1); + assertThat(docs.getDetails()).isEmpty(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void importDocumentsDuplicateUpdate(ArangoCollection collection) { + String k1 = rnd(); + String k2 = rnd(); + + final Collection values = Arrays.asList(new BaseDocument(k1), new BaseDocument(k2), + new BaseDocument(k2)); + + final DocumentImportEntity docs = collection.importDocuments(values, + new DocumentImportOptions().onDuplicate(OnDuplicate.update)); + assertThat(docs).isNotNull(); + assertThat(docs.getCreated()).isEqualTo(2); + assertThat(docs.getEmpty()).isZero(); + assertThat(docs.getErrors()).isZero(); + assertThat(docs.getIgnored()).isZero(); + assertThat(docs.getUpdated()).isEqualTo(1); + assertThat(docs.getDetails()).isEmpty(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void importDocumentsCompleteFail(ArangoCollection collection) { + String k1 = rnd(); + String k2 = rnd(); + + final Collection values = Arrays.asList(new BaseDocument(k1), new BaseDocument(k2), + new BaseDocument(k2)); + + Throwable thrown = catchThrowable(() -> collection.importDocuments(values, + new DocumentImportOptions().complete(true))); + assertThat(thrown).isInstanceOf(ArangoDBException.class); + ArangoDBException e = (ArangoDBException) thrown; + assertThat(e.getErrorNum()).isEqualTo(1210); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void importDocumentsDetails(ArangoCollection collection) { + String k1 = rnd(); + String k2 = rnd(); + + final Collection values = Arrays.asList(new BaseDocument(k1), new BaseDocument(k2), + new BaseDocument(k2)); + + final DocumentImportEntity docs = collection.importDocuments(values, new DocumentImportOptions().details(true)); + assertThat(docs).isNotNull(); + assertThat(docs.getCreated()).isEqualTo(2); + assertThat(docs.getEmpty()).isZero(); + assertThat(docs.getErrors()).isEqualTo(1); + assertThat(docs.getIgnored()).isZero(); + assertThat(docs.getUpdated()).isZero(); + assertThat(docs.getDetails()).hasSize(1); + assertThat(docs.getDetails().iterator().next()).contains("unique constraint violated"); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void importDocumentsOverwriteFalse(ArangoCollection collection) { + collection.insertDocument(new BaseDocument()); + Long initialCount = collection.count().getCount(); + + final Collection values = new ArrayList<>(); + values.add(new BaseDocument()); + values.add(new BaseDocument()); + collection.importDocuments(values, new DocumentImportOptions().overwrite(false)); + assertThat(collection.count().getCount()).isEqualTo(initialCount + 2L); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void importDocumentsOverwriteTrue(ArangoCollection collection) { + collection.insertDocument(new BaseDocument()); + + final Collection values = new ArrayList<>(); + values.add(new BaseDocument()); + values.add(new BaseDocument()); + collection.importDocuments(values, new DocumentImportOptions().overwrite(true)); + assertThat(collection.count().getCount()).isEqualTo(2L); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("edges") + void importDocumentsFromToPrefix(ArangoCollection edgeCollection) { + final Collection values = new ArrayList<>(); + final String[] keys = {rnd(), rnd()}; + for (String s : keys) { + values.add(new BaseEdgeDocument(s, "from", "to")); + } + assertThat(values).hasSize(keys.length); + + final DocumentImportEntity importResult = edgeCollection.importDocuments(values, + new DocumentImportOptions().fromPrefix("foo").toPrefix("bar")); + assertThat(importResult).isNotNull(); + assertThat(importResult.getCreated()).isEqualTo(values.size()); + for (String key : keys) { + final BaseEdgeDocument doc = edgeCollection.getDocument(key, BaseEdgeDocument.class); + assertThat(doc).isNotNull(); + assertThat(doc.getFrom()).isEqualTo("foo/from"); + assertThat(doc.getTo()).isEqualTo("bar/to"); + } + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void importDocumentsJson(ArangoCollection collection) throws JsonProcessingException { + final String values = mapper.writeValueAsString(Arrays.asList(Collections.singletonMap("_key", rnd()), + Collections.singletonMap("_key", rnd()))); + + final DocumentImportEntity docs = collection.importDocuments(RawData.of(values)); + assertThat(docs).isNotNull(); + assertThat(docs.getCreated()).isEqualTo(2); + assertThat(docs.getEmpty()).isZero(); + assertThat(docs.getErrors()).isZero(); + assertThat(docs.getIgnored()).isZero(); + assertThat(docs.getUpdated()).isZero(); + assertThat(docs.getDetails()).isEmpty(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void importDocumentsJsonDuplicateDefaultError(ArangoCollection collection) throws JsonProcessingException { + String k1 = rnd(); + String k2 = rnd(); + + final String values = mapper.writeValueAsString(Arrays.asList(Collections.singletonMap("_key", k1), + Collections.singletonMap("_key", k2), Collections.singletonMap("_key", k2))); + + final DocumentImportEntity docs = collection.importDocuments(RawData.of(values)); + assertThat(docs).isNotNull(); + assertThat(docs.getCreated()).isEqualTo(2); + assertThat(docs.getEmpty()).isZero(); + assertThat(docs.getErrors()).isEqualTo(1); + assertThat(docs.getIgnored()).isZero(); + assertThat(docs.getUpdated()).isZero(); + assertThat(docs.getDetails()).isEmpty(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void importDocumentsJsonDuplicateError(ArangoCollection collection) throws JsonProcessingException { + String k1 = rnd(); + String k2 = rnd(); + + final String values = mapper.writeValueAsString(Arrays.asList(Collections.singletonMap("_key", k1), + Collections.singletonMap("_key", k2), Collections.singletonMap("_key", k2))); + + final DocumentImportEntity docs = collection.importDocuments(RawData.of(values), + new DocumentImportOptions().onDuplicate(OnDuplicate.error)); + assertThat(docs).isNotNull(); + assertThat(docs.getCreated()).isEqualTo(2); + assertThat(docs.getEmpty()).isZero(); + assertThat(docs.getErrors()).isEqualTo(1); + assertThat(docs.getIgnored()).isZero(); + assertThat(docs.getUpdated()).isZero(); + assertThat(docs.getDetails()).isEmpty(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void importDocumentsJsonDuplicateIgnore(ArangoCollection collection) throws JsonProcessingException { + String k1 = rnd(); + String k2 = rnd(); + + final String values = mapper.writeValueAsString(Arrays.asList(Collections.singletonMap("_key", k1), + Collections.singletonMap("_key", k2), Collections.singletonMap("_key", k2))); + final DocumentImportEntity docs = collection.importDocuments(RawData.of(values), + new DocumentImportOptions().onDuplicate(OnDuplicate.ignore)); + assertThat(docs).isNotNull(); + assertThat(docs.getCreated()).isEqualTo(2); + assertThat(docs.getEmpty()).isZero(); + assertThat(docs.getErrors()).isZero(); + assertThat(docs.getIgnored()).isEqualTo(1); + assertThat(docs.getUpdated()).isZero(); + assertThat(docs.getDetails()).isEmpty(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void importDocumentsJsonDuplicateReplace(ArangoCollection collection) throws JsonProcessingException { + String k1 = rnd(); + String k2 = rnd(); + + final String values = mapper.writeValueAsString(Arrays.asList(Collections.singletonMap("_key", k1), + Collections.singletonMap("_key", k2), Collections.singletonMap("_key", k2))); + + final DocumentImportEntity docs = collection.importDocuments(RawData.of(values), + new DocumentImportOptions().onDuplicate(OnDuplicate.replace)); + assertThat(docs).isNotNull(); + assertThat(docs.getCreated()).isEqualTo(2); + assertThat(docs.getEmpty()).isZero(); + assertThat(docs.getErrors()).isZero(); + assertThat(docs.getIgnored()).isZero(); + assertThat(docs.getUpdated()).isEqualTo(1); + assertThat(docs.getDetails()).isEmpty(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void importDocumentsJsonDuplicateUpdate(ArangoCollection collection) throws JsonProcessingException { + String k1 = rnd(); + String k2 = rnd(); + + final String values = mapper.writeValueAsString(Arrays.asList(Collections.singletonMap("_key", k1), +Collections.singletonMap("_key", k2), Collections.singletonMap("_key", k2))); + + final DocumentImportEntity docs = collection.importDocuments(RawData.of(values), + new DocumentImportOptions().onDuplicate(OnDuplicate.update)); + assertThat(docs).isNotNull(); + assertThat(docs.getCreated()).isEqualTo(2); + assertThat(docs.getEmpty()).isZero(); + assertThat(docs.getErrors()).isZero(); + assertThat(docs.getIgnored()).isZero(); + assertThat(docs.getUpdated()).isEqualTo(1); + assertThat(docs.getDetails()).isEmpty(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void importDocumentsJsonCompleteFail(ArangoCollection collection) { + final String values = "[{\"_key\":\"1\"},{\"_key\":\"2\"},{\"_key\":\"2\"}]"; + Throwable thrown = catchThrowable(() -> collection.importDocuments(RawData.of(values), + new DocumentImportOptions().complete(true))); + assertThat(thrown).isInstanceOf(ArangoDBException.class); + ArangoDBException e = (ArangoDBException) thrown; + assertThat(e.getErrorNum()).isEqualTo(1210); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void importDocumentsJsonDetails(ArangoCollection collection) throws JsonProcessingException { + String k1 = rnd(); + String k2 = rnd(); + + final String values = mapper.writeValueAsString(Arrays.asList(Collections.singletonMap("_key", k1), + Collections.singletonMap("_key", k2), Collections.singletonMap("_key", k2))); + + final DocumentImportEntity docs = collection.importDocuments(RawData.of(values), +new DocumentImportOptions().details(true)); + assertThat(docs).isNotNull(); + assertThat(docs.getCreated()).isEqualTo(2); + assertThat(docs.getEmpty()).isZero(); + assertThat(docs.getErrors()).isEqualTo(1); + assertThat(docs.getIgnored()).isZero(); + assertThat(docs.getUpdated()).isZero(); + assertThat(docs.getDetails()).hasSize(1); + assertThat(docs.getDetails().iterator().next()).contains("unique constraint violated"); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void importDocumentsJsonOverwriteFalse(ArangoCollection collection) throws JsonProcessingException { + collection.insertDocument(new BaseDocument()); + Long initialCount = collection.count().getCount(); + + final String values = mapper.writeValueAsString(Arrays.asList(Collections.singletonMap("_key", rnd()), + Collections.singletonMap("_key", rnd()))); + collection.importDocuments(RawData.of(values), new DocumentImportOptions().overwrite(false)); + assertThat(collection.count().getCount()).isEqualTo(initialCount + 2L); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void importDocumentsJsonOverwriteTrue(ArangoCollection collection) throws JsonProcessingException { + collection.insertDocument(new BaseDocument()); + + final String values = mapper.writeValueAsString(Arrays.asList(Collections.singletonMap("_key", rnd()), + Collections.singletonMap("_key", rnd()))); + collection.importDocuments(RawData.of(values), new DocumentImportOptions().overwrite(true)); + assertThat(collection.count().getCount()).isEqualTo(2L); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("edges") + void importDocumentsJsonFromToPrefix(ArangoCollection edgeCollection) throws JsonProcessingException { + String k1 = UUID.randomUUID().toString(); + String k2 = UUID.randomUUID().toString(); + + final String[] keys = {k1, k2}; + + final String values = mapper.writeValueAsString(Arrays.asList(new MapBuilder().put("_key", k1).put("_from", + "from").put("_to", "to").get(), new MapBuilder().put("_key", k2).put("_from", "from").put("_to", "to").get())); + + final DocumentImportEntity importResult = edgeCollection.importDocuments(RawData.of(values), +new DocumentImportOptions().fromPrefix("foo").toPrefix("bar")); + assertThat(importResult).isNotNull(); + assertThat(importResult.getCreated()).isEqualTo(2); + for (String key : keys) { + final BaseEdgeDocument doc = edgeCollection.getDocument(key, BaseEdgeDocument.class); + assertThat(doc).isNotNull(); + assertThat(doc.getFrom()).isEqualTo("foo/from"); + assertThat(doc.getTo()).isEqualTo("bar/to"); + } + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void deleteDocumentsByKey(ArangoCollection collection) { + final Collection values = new ArrayList<>(); + { + final BaseDocument e = new BaseDocument(UUID.randomUUID().toString()); + e.setKey("1"); + values.add(e); + } + { + final BaseDocument e = new BaseDocument(UUID.randomUUID().toString()); + e.setKey("2"); + values.add(e); + } + collection.insertDocuments(values); + final Collection keys = new ArrayList<>(); + keys.add("1"); + keys.add("2"); + final MultiDocumentEntity> deleteResult = collection.deleteDocuments(keys); + assertThat(deleteResult).isNotNull(); + assertThat(deleteResult.getDocuments()).hasSize(2); + for (final DocumentDeleteEntity i : deleteResult.getDocuments()) { + assertThat(i.getKey()).isIn("1", "2"); + } + assertThat(deleteResult.getErrors()).isEmpty(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void deleteDocumentsRawDataByKeyReturnOld(ArangoCollection collection) { + final RawData values = RawData.of("[{\"_key\":\"1\"},{\"_key\":\"2\"}]"); + collection.insertDocuments(values); + final RawData keys = RawData.of("[\"1\",\"2\"]"); + MultiDocumentEntity> deleteResult = collection.deleteDocuments(keys, + new DocumentDeleteOptions().returnOld(true)); + assertThat(deleteResult).isNotNull(); + assertThat(deleteResult.getDocuments()).hasSize(2); + for (final DocumentDeleteEntity i : deleteResult.getDocuments()) { + assertThat(i.getKey()).isIn("1", "2"); + assertThat(i.getOld()).isNotNull().isInstanceOf(RawJson.class); + JsonNode jn = SerdeUtils.INSTANCE.parseJson(((RawJson) i.getOld()).getValue()); + assertThat(jn.get("_key").asText()).isEqualTo(i.getKey()); + } + assertThat(deleteResult.getErrors()).isEmpty(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void deleteDocumentsByDocuments(ArangoCollection collection) { + final Collection values = new ArrayList<>(); + { + final BaseDocument e = new BaseDocument(UUID.randomUUID().toString()); + e.setKey("1"); + values.add(e); + } + { + final BaseDocument e = new BaseDocument(UUID.randomUUID().toString()); + e.setKey("2"); + values.add(e); + } + collection.insertDocuments(values); + MultiDocumentEntity> deleteResult = collection.deleteDocuments(values); + assertThat(deleteResult).isNotNull(); + assertThat(deleteResult.getDocuments()).hasSize(2); + for (final DocumentDeleteEntity i : deleteResult.getDocuments()) { + assertThat(i.getKey()).isIn("1", "2"); + } + assertThat(deleteResult.getErrors()).isEmpty(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void deleteDocumentsByKeyOne(ArangoCollection collection) { + final Collection values = new ArrayList<>(); + { + final BaseDocument e = new BaseDocument(UUID.randomUUID().toString()); + e.setKey("1"); + values.add(e); + } + collection.insertDocuments(values); + final Collection keys = new ArrayList<>(); + keys.add("1"); + final MultiDocumentEntity> deleteResult = collection.deleteDocuments(keys); + assertThat(deleteResult).isNotNull(); + assertThat(deleteResult.getDocuments()).hasSize(1); + for (final DocumentDeleteEntity i : deleteResult.getDocuments()) { + assertThat(i.getKey()).isEqualTo("1"); + } + assertThat(deleteResult.getErrors()).isEmpty(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void deleteDocumentsByDocumentOne(ArangoCollection collection) { + final Collection values = new ArrayList<>(); + { + final BaseDocument e = new BaseDocument(UUID.randomUUID().toString()); + e.setKey("1"); + values.add(e); + } + collection.insertDocuments(values); + final MultiDocumentEntity> deleteResult = collection.deleteDocuments(values); + assertThat(deleteResult).isNotNull(); + assertThat(deleteResult.getDocuments()).hasSize(1); + for (final DocumentDeleteEntity i : deleteResult.getDocuments()) { + assertThat(i.getKey()).isEqualTo("1"); + } + assertThat(deleteResult.getErrors()).isEmpty(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void deleteDocumentsEmpty(ArangoCollection collection) { + final Collection values = new ArrayList<>(); + collection.insertDocuments(values); + final Collection keys = new ArrayList<>(); + final MultiDocumentEntity deleteResult = collection.deleteDocuments(keys); + assertThat(deleteResult).isNotNull(); + assertThat(deleteResult.getDocuments()).isEmpty(); + assertThat(deleteResult.getErrors()).isEmpty(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void deleteDocumentsByKeyNotExisting(ArangoCollection collection) { + final Collection values = new ArrayList<>(); + collection.insertDocuments(values); + final Collection keys = Arrays.asList(rnd(), rnd()); + + final MultiDocumentEntity deleteResult = collection.deleteDocuments(keys); + assertThat(deleteResult).isNotNull(); + assertThat(deleteResult.getDocuments()).isEmpty(); + assertThat(deleteResult.getErrors()).hasSize(2); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void deleteDocumentsByDocumentsNotExisting(ArangoCollection collection) { + final Collection values = new ArrayList<>(); + { + final BaseDocument e = new BaseDocument(UUID.randomUUID().toString()); + e.setKey("1"); + values.add(e); + } + { + final BaseDocument e = new BaseDocument(UUID.randomUUID().toString()); + e.setKey("2"); + values.add(e); + } + final MultiDocumentEntity deleteResult = collection.deleteDocuments(values); + assertThat(deleteResult).isNotNull(); + assertThat(deleteResult.getDocuments()).isEmpty(); + assertThat(deleteResult.getErrors()).hasSize(2); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void updateDocuments(ArangoCollection collection) { + final Collection values = Arrays.asList(new BaseDocument(rnd()), new BaseDocument(rnd())); + collection.insertDocuments(values); + values.forEach(it -> it.addAttribute("a", "test")); + + final MultiDocumentEntity updateResult = collection.updateDocuments(values); + assertThat(updateResult.getDocuments()).hasSize(2); + assertThat(updateResult.getErrors()).isEmpty(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void updateDocumentsWithDifferentReturnType(ArangoCollection collection) { + List keys = + IntStream.range(0, 3).mapToObj(it -> "key-" + UUID.randomUUID()).collect(Collectors.toList()); + List docs = + keys.stream().map(BaseDocument::new).peek(it -> it.addAttribute("a", "test")).collect(Collectors.toList()); + + collection.insertDocuments(docs); + + List> modifiedDocs = docs.stream().peek(it -> it.addAttribute("b", "test")).map(it -> { + Map map = new HashMap<>(); + map.put("_key", it.getKey()); + map.put("a", it.getAttribute("a")); + map.put("b", it.getAttribute("b")); + return map; + }).collect(Collectors.toList()); + + final MultiDocumentEntity> updateResult = + collection.updateDocuments(modifiedDocs, new DocumentUpdateOptions().returnNew(true), BaseDocument.class); + assertThat(updateResult.getDocuments()).hasSize(3); + assertThat(updateResult.getErrors()).isEmpty(); + assertThat(updateResult.getDocuments().stream()).map(DocumentUpdateEntity::getNew).allMatch(it -> it.getAttribute("a").equals("test")).allMatch(it -> it.getAttribute("b").equals("test")); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void updateDocumentsOne(ArangoCollection collection) { + final Collection values = new ArrayList<>(); + { + final BaseDocument e = new BaseDocument(UUID.randomUUID().toString()); + e.setKey("1"); + values.add(e); + } + collection.insertDocuments(values); + final Collection updatedValues = new ArrayList<>(); + final BaseDocument first = values.iterator().next(); + first.addAttribute("a", "test"); + updatedValues.add(first); + final MultiDocumentEntity updateResult = collection.updateDocuments(updatedValues); + assertThat(updateResult.getDocuments()).hasSize(1); + assertThat(updateResult.getErrors()).isEmpty(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void updateDocumentsEmpty(ArangoCollection collection) { + final Collection values = new ArrayList<>(); + final MultiDocumentEntity updateResult = collection.updateDocuments(values); + assertThat(updateResult.getDocuments()).isEmpty(); + assertThat(updateResult.getErrors()).isEmpty(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void updateDocumentsWithoutKey(ArangoCollection collection) { + final Collection values = new ArrayList<>(); + { + values.add(new BaseDocument("1")); + } + collection.insertDocuments(values); + final Collection updatedValues = new ArrayList<>(); + for (final BaseDocument i : values) { + i.addAttribute("a", "test"); + updatedValues.add(i); + } + updatedValues.add(new BaseDocument()); + final MultiDocumentEntity updateResult = collection.updateDocuments(updatedValues); + assertThat(updateResult.getDocuments()).hasSize(1); + assertThat(updateResult.getErrors()).hasSize(1); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void updateDocumentsJson(ArangoCollection collection) { + final Collection values = new ArrayList<>(); + values.add(RawJson.of("{\"_key\":\"1\"}")); + values.add(RawJson.of("{\"_key\":\"2\"}")); + collection.insertDocuments(values); + + final Collection updatedValues = new ArrayList<>(); + updatedValues.add(RawJson.of("{\"_key\":\"1\", \"foo\":\"bar\"}")); + updatedValues.add(RawJson.of("{\"_key\":\"2\", \"foo\":\"bar\"}")); + final MultiDocumentEntity updateResult = collection.updateDocuments(updatedValues); + assertThat(updateResult.getDocuments()).hasSize(2); + assertThat(updateResult.getErrors()).isEmpty(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void updateDocumentsRawData(ArangoCollection collection) { + final RawData values = RawData.of("[{\"_key\":\"1\"}, {\"_key\":\"2\"}]"); + collection.insertDocuments(values); + + final RawData updatedValues = RawData.of("[{\"_key\":\"1\", \"foo\":\"bar\"}, {\"_key\":\"2\", " + + "\"foo\":\"bar\"}]"); + final MultiDocumentEntity updateResult = collection.updateDocuments(updatedValues); + assertThat(updateResult.getDocuments()).hasSize(2); + assertThat(updateResult.getErrors()).isEmpty(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void updateDocumentsRawDataReturnNew(ArangoCollection collection) { + final RawData values = RawData.of("[{\"_key\":\"1\"}, {\"_key\":\"2\"}]"); + collection.insertDocuments(values); + + final RawData updatedValues = RawData.of("[{\"_key\":\"1\", \"foo\":\"bar\"}, {\"_key\":\"2\", " + + "\"foo\":\"bar\"}]"); + MultiDocumentEntity> updateResult = + collection.updateDocuments(updatedValues, new DocumentUpdateOptions().returnNew(true)); + assertThat(updateResult.getDocuments()).hasSize(2); + assertThat(updateResult.getErrors()).isEmpty(); + for (DocumentUpdateEntity doc : updateResult.getDocuments()) { + RawData d = doc.getNew(); + assertThat(d) + .isNotNull() + .isInstanceOf(RawJson.class); + + JsonNode jn = SerdeUtils.INSTANCE.parseJson(((RawJson) d).getValue()); + assertThat(jn.has("foo")).isTrue(); + assertThat(jn.get("foo").textValue()).isEqualTo("bar"); + } + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void replaceDocuments(ArangoCollection collection) { + final Collection values = new ArrayList<>(); + { + values.add(new BaseDocument("1")); + values.add(new BaseDocument("2")); + } + collection.insertDocuments(values); + final Collection updatedValues = new ArrayList<>(); + for (final BaseDocument i : values) { + i.addAttribute("a", "test"); + updatedValues.add(i); + } + final MultiDocumentEntity updateResult = collection.replaceDocuments(updatedValues); + assertThat(updateResult.getDocuments()).hasSize(2); + assertThat(updateResult.getErrors()).isEmpty(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void replaceDocumentsOne(ArangoCollection collection) { + final Collection values = new ArrayList<>(); + { + final BaseDocument e = new BaseDocument(UUID.randomUUID().toString()); + e.setKey("1"); + values.add(e); + } + collection.insertDocuments(values); + final Collection updatedValues = new ArrayList<>(); + final BaseDocument first = values.iterator().next(); + first.addAttribute("a", "test"); + updatedValues.add(first); + final MultiDocumentEntity updateResult = collection.updateDocuments(updatedValues); + assertThat(updateResult.getDocuments()).hasSize(1); + assertThat(updateResult.getErrors()).isEmpty(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void replaceDocumentsEmpty(ArangoCollection collection) { + final Collection values = new ArrayList<>(); + final MultiDocumentEntity updateResult = collection.updateDocuments(values); + assertThat(updateResult.getDocuments()).isEmpty(); + assertThat(updateResult.getErrors()).isEmpty(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void replaceDocumentsWithoutKey(ArangoCollection collection) { + final Collection values = new ArrayList<>(); + { + values.add(new BaseDocument("1")); + } + collection.insertDocuments(values); + final Collection updatedValues = new ArrayList<>(); + for (final BaseDocument i : values) { + i.addAttribute("a", "test"); + updatedValues.add(i); + } + updatedValues.add(new BaseDocument()); + final MultiDocumentEntity updateResult = collection.updateDocuments(updatedValues); + assertThat(updateResult.getDocuments()).hasSize(1); + assertThat(updateResult.getErrors()).hasSize(1); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void replaceDocumentsJson(ArangoCollection collection) { + final Collection values = new ArrayList<>(); + values.add(RawJson.of("{\"_key\":\"1\"}")); + values.add(RawJson.of("{\"_key\":\"2\"}")); + collection.insertDocuments(values); + + final Collection updatedValues = new ArrayList<>(); + updatedValues.add(RawJson.of("{\"_key\":\"1\", \"foo\":\"bar\"}")); + updatedValues.add(RawJson.of("{\"_key\":\"2\", \"foo\":\"bar\"}")); + final MultiDocumentEntity updateResult = collection.replaceDocuments(updatedValues); + assertThat(updateResult.getDocuments()).hasSize(2); + assertThat(updateResult.getErrors()).isEmpty(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void replaceDocumentsRawData(ArangoCollection collection) { + final RawData values = RawData.of("[{\"_key\":\"1\"}, {\"_key\":\"2\"}]"); + collection.insertDocuments(values); + + final RawData updatedValues = RawData.of("[{\"_key\":\"1\", \"foo\":\"bar\"}, {\"_key\":\"2\", " + + "\"foo\":\"bar\"}]"); + final MultiDocumentEntity updateResult = collection.replaceDocuments(updatedValues); + assertThat(updateResult.getDocuments()).hasSize(2); + assertThat(updateResult.getErrors()).isEmpty(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void replaceDocumentsRawDataReturnNew(ArangoCollection collection) { + final RawData values = RawData.of("[{\"_key\":\"1\"}, {\"_key\":\"2\"}]"); + collection.insertDocuments(values); + + final RawData updatedValues = RawData.of("[{\"_key\":\"1\", \"foo\":\"bar\"}, {\"_key\":\"2\", " + + "\"foo\":\"bar\"}]"); + MultiDocumentEntity> updateResult = + collection.replaceDocuments(updatedValues, new DocumentReplaceOptions().returnNew(true)); + assertThat(updateResult.getDocuments()).hasSize(2); + assertThat(updateResult.getErrors()).isEmpty(); + for (DocumentUpdateEntity doc : updateResult.getDocuments()) { + RawData d = doc.getNew(); + assertThat(d) + .isNotNull() + .isInstanceOf(RawJson.class); + + JsonNode jn = SerdeUtils.INSTANCE.parseJson(((RawJson) d).getValue()); + assertThat(jn.has("foo")).isTrue(); + assertThat(jn.get("foo").textValue()).isEqualTo("bar"); + } + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void getInfo(ArangoCollection collection) { + final CollectionEntity result = collection.getInfo(); + assertThat(result.getName()).isEqualTo(COLLECTION_NAME); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void getPropeties(ArangoCollection collection) { + final CollectionPropertiesEntity result = collection.getProperties(); + assertThat(result.getName()).isEqualTo(COLLECTION_NAME); + assertThat(result.getCount()).isNull(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void changeProperties(ArangoCollection collection) { + final CollectionPropertiesEntity properties = collection.getProperties(); + assertThat(properties.getWaitForSync()).isNotNull(); + if (isAtLeastVersion(3, 7)) { + assertThat(properties.getSchema()).isNull(); + } + + String schemaRule = ("{ " + " \"properties\": {" + " \"number\": {" + " " + +" \"type\": \"number\"" + " }" + " }" + " }").replaceAll("\\s", ""); + String schemaMessage = "The document has problems!"; + + CollectionPropertiesOptions updatedOptions = +new CollectionPropertiesOptions().waitForSync(!properties.getWaitForSync()).schema(new CollectionSchema().setLevel(CollectionSchema.Level.NEW).setMessage(schemaMessage).setRule(schemaRule)); + + final CollectionPropertiesEntity changedProperties = collection.changeProperties(updatedOptions); + assertThat(changedProperties.getWaitForSync()).isNotNull(); + assertThat(changedProperties.getWaitForSync()).isEqualTo(!properties.getWaitForSync()); + if (isAtLeastVersion(3, 7)) { + assertThat(changedProperties.getSchema()).isNotNull(); + assertThat(changedProperties.getSchema().getLevel()).isEqualTo(CollectionSchema.Level.NEW); + assertThat(changedProperties.getSchema().getMessage()).isEqualTo(schemaMessage); + assertThat(changedProperties.getSchema().getRule()).isEqualTo(schemaRule); + } + + // revert changes + CollectionPropertiesEntity revertedProperties = collection.changeProperties(new CollectionPropertiesOptions() + .waitForSync(properties.getWaitForSync()).schema(new CollectionSchema())); + if (isAtLeastVersion(3, 7)) { + assertThat(revertedProperties.getSchema()).isNull(); + } + + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void rename(ArangoCollection collection) { + assumeTrue(isSingleServer()); + ArangoDatabase db = collection.db(); + final CollectionEntity result = collection.rename(COLLECTION_NAME + "1"); + assertThat(result).isNotNull(); + assertThat(result.getName()).isEqualTo(COLLECTION_NAME + "1"); + final CollectionEntity info = db.collection(COLLECTION_NAME + "1").getInfo(); + assertThat(info.getName()).isEqualTo(COLLECTION_NAME + "1"); + Throwable thrown = catchThrowable(() -> db.collection(COLLECTION_NAME).getInfo()); + assertThat(thrown).isInstanceOf(ArangoDBException.class); + ArangoDBException e = (ArangoDBException) thrown; + assertThat(e.getResponseCode()).isEqualTo(404); + db.collection(COLLECTION_NAME + "1").rename(COLLECTION_NAME); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void responsibleShard(ArangoCollection collection) { + assumeTrue(isCluster()); + assumeTrue(isAtLeastVersion(3, 5)); + ShardEntity shard = collection.getResponsibleShard(new BaseDocument("testKey")); + assertThat(shard).isNotNull(); + assertThat(shard.getShardId()).isNotNull(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void renameDontBreaksCollectionHandler(ArangoCollection collection) { + assumeTrue(isSingleServer()); + collection.rename(COLLECTION_NAME + "1"); + assertThat(collection.getInfo()).isNotNull(); + collection.db().collection(COLLECTION_NAME + "1").rename(COLLECTION_NAME); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void getRevision(ArangoCollection collection) { + final CollectionRevisionEntity result = collection.getRevision(); + assertThat(result).isNotNull(); + assertThat(result.getName()).isEqualTo(COLLECTION_NAME); + assertThat(result.getRevision()).isNotNull(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void keyWithSpecialCharacter(ArangoCollection collection) { + final String key = "myKey_-:.@()+,=;$!*'%-" + UUID.randomUUID(); + collection.insertDocument(new BaseDocument(key)); + final BaseDocument doc = collection.getDocument(key, BaseDocument.class); + assertThat(doc).isNotNull(); + assertThat(doc.getKey()).isEqualTo(key); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void alreadyUrlEncodedkey(ArangoCollection collection) { + final String key = "http%3A%2F%2Fexample.com%2F-" + UUID.randomUUID(); + collection.insertDocument(new BaseDocument(key)); + final BaseDocument doc = collection.getDocument(key, BaseDocument.class); + assertThat(doc).isNotNull(); + assertThat(doc.getKey()).isEqualTo(key); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void grantAccessRW(ArangoCollection collection) { + ArangoDB arangoDB = collection.db().arango(); + try { + arangoDB.createUser("user1", "1234", null); + collection.grantAccess("user1", Permissions.RW); + } finally { + arangoDB.deleteUser("user1"); + } + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void grantAccessRO(ArangoCollection collection) { + ArangoDB arangoDB = collection.db().arango(); + try { + arangoDB.createUser("user1", "1234", null); + collection.grantAccess("user1", Permissions.RO); + } finally { + arangoDB.deleteUser("user1"); + } + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void grantAccessNONE(ArangoCollection collection) { + ArangoDB arangoDB = collection.db().arango(); + try { + arangoDB.createUser("user1", "1234", null); + collection.grantAccess("user1", Permissions.NONE); + } finally { + arangoDB.deleteUser("user1"); + } + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void grantAccessUserNotFound(ArangoCollection collection) { + Throwable thrown = catchThrowable(() -> collection.grantAccess("user1", Permissions.RW)); + assertThat(thrown).isInstanceOf(ArangoDBException.class); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void revokeAccess(ArangoCollection collection) { + ArangoDB arangoDB = collection.db().arango(); + try { + arangoDB.createUser("user1", "1234", null); + collection.grantAccess("user1", Permissions.NONE); + } finally { + arangoDB.deleteUser("user1"); + } + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void revokeAccessUserNotFound(ArangoCollection collection) { + Throwable thrown = catchThrowable(() -> collection.grantAccess("user1", Permissions.NONE)); + assertThat(thrown).isInstanceOf(ArangoDBException.class); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void resetAccess(ArangoCollection collection) { + ArangoDB arangoDB = collection.db().arango(); + try { + arangoDB.createUser("user1", "1234", null); + collection.resetAccess("user1"); + } finally { + arangoDB.deleteUser("user1"); + } + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void resetAccessUserNotFound(ArangoCollection collection) { + Throwable thrown = catchThrowable(() -> collection.resetAccess("user1")); + assertThat(thrown).isInstanceOf(ArangoDBException.class); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void getPermissions(ArangoCollection collection) { + assertThat(collection.getPermissions("root")).isEqualTo(Permissions.RW); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void annotationsInParamsAndMethods(ArangoCollection collection) { + assumeTrue(collection.getSerde().getUserSerde() instanceof JacksonSerde, "JacksonSerde only"); + AnnotatedEntity entity = new AnnotatedEntity(UUID.randomUUID().toString()); + AnnotatedEntity doc = collection.insertDocument(entity, new DocumentCreateOptions().returnNew(true)).getNew(); + assertThat(doc).isNotNull(); + assertThat(doc.getKey()).isEqualTo(entity.getKey()); + assertThat(doc.getId()).isNotNull(); + assertThat(doc.getRev()).isNotNull(); + } + + @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, property = "type") + public interface Animal { + String getKey(); + + String getName(); + } + + public static class Dog implements Animal { + + @Key + private String key; + private String name; + + public Dog() { + } + + public Dog(String key, String name) { + this.key = key; + this.name = name; + } + + @Override + public String getKey() { + return key; + } + + public void setKey(String key) { + this.key = key; + } + + @Override + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + } + + public static class Cat implements Animal { + @Key + private String key; + private String name; + + public Cat() { + } + + public Cat(String key, String name) { + this.key = key; + this.name = name; + } + + @Override + public String getKey() { + return key; + } + + public void setKey(String key) { + this.key = key; + } + + @Override + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + } + + public static class TestUpdateEntity { + private String a, b; + + public String getA() { + return a; + } + + public String getB() { + return b; + } + } + + public static class TestUpdateEntitySerializeNullFalse { + private String a, b; + + @JsonInclude(JsonInclude.Include.NON_NULL) + public String getA() { + return a; + } + + @JsonInclude(JsonInclude.Include.NON_NULL) + public String getB() { + return b; + } + } + + public static class AnnotatedEntity { + + private final String key; + private String id; + private String rev; + + public AnnotatedEntity(@Key String key) { + this.key = key; + } + + public String getKey() { + return key; + } + + public String getId() { + return id; + } + + @Id + public void setId(String id) { + this.id = id; + } + + public String getRev() { + return rev; + } + + @Rev + public void setRev(String rev) { + this.rev = rev; + } + } + +} diff --git a/shaded-integration-tests/src/test/jackson/java/com/arangodb/ArangoCursorTest.java b/shaded-integration-tests/src/test/jackson/java/com/arangodb/ArangoCursorTest.java new file mode 100644 index 000000000..cfbd98775 --- /dev/null +++ b/shaded-integration-tests/src/test/jackson/java/com/arangodb/ArangoCursorTest.java @@ -0,0 +1,133 @@ +/* + * DISCLAIMER + * + * Copyright 2018 ArangoDB GmbH, Cologne, Germany + * + * Licensed 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. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb; + +import com.arangodb.model.AqlQueryOptions; +import com.fasterxml.jackson.databind.JsonNode; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + +import java.util.Optional; +import java.util.Set; +import java.util.concurrent.atomic.AtomicLong; +import java.util.stream.Collectors; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * @author Mark Vollmary + * @author Michele Rastelli + */ +class ArangoCursorTest extends BaseJunit5 { + + @BeforeAll + static void init() { + initDB(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void firstStream(ArangoDatabase db) { + final ArangoCursor cursor = db.query("FOR i IN 0..99 RETURN i", JsonNode.class); + final Optional first = cursor.stream().findFirst(); + assertThat(first).isPresent(); + assertThat(first.get().isInt()).isTrue(); + assertThat(first.get().asLong()).isZero(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void next(ArangoDatabase db) { + final ArangoCursor cursor = db.query("FOR i IN 0..99 RETURN i", new AqlQueryOptions().batchSize(5), + JsonNode.class); + while (cursor.hasNext()) { + cursor.next(); + } + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void mapFilterCountStream(ArangoDatabase db) { + final ArangoCursor cursor = db.query("FOR i IN 0..99 RETURN i", JsonNode.class); + final long count = cursor.stream().map(JsonNode::asLong).filter(t -> t < 50).count(); + assertThat(count).isEqualTo(50L); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void mapFilterCollectIntoSetStream(ArangoDatabase db) { + final ArangoCursor cursor = db.query("FOR i IN 0..99 RETURN i", JsonNode.class); + final Set target = cursor.stream().map(JsonNode::asLong).filter(t -> t < 50).collect(Collectors.toSet()); + assertThat(target) + .isNotNull() + .hasSize(50); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void forEach(ArangoDatabase db) { + final AtomicLong i = new AtomicLong(0L); + final ArangoCursor cursor = db.query("FOR i IN 0..99 RETURN i", JsonNode.class); + cursor.forEach(t -> assertThat(t.asLong()).isEqualTo(i.getAndIncrement())); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void mapForeachStream(ArangoDatabase db) { + final AtomicLong i = new AtomicLong(0L); + final ArangoCursor cursor = db.query("FOR i IN 0..99 RETURN i", JsonNode.class); + cursor.stream().map(JsonNode::asLong).forEach(t -> assertThat(t).isEqualTo(i.getAndIncrement())); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void mapFilterForEachStream(ArangoDatabase db) { + final AtomicLong i = new AtomicLong(0L); + final ArangoCursor cursor = db.query("FOR i IN 0..99 RETURN i", JsonNode.class); + cursor.stream().map(JsonNode::asLong).filter(t -> t < 50).forEach(t -> assertThat(t).isEqualTo(i.getAndIncrement())); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void anyMatchStream(ArangoDatabase db) { + final ArangoCursor cursor = db.query("FOR i IN 0..99 RETURN i", JsonNode.class); + final boolean match = cursor.stream().anyMatch(t -> t.asLong() == 50L); + assertThat(match).isTrue(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void noneMatchStream(ArangoDatabase db) { + final ArangoCursor cursor = db.query("FOR i IN 0..99 RETURN i", JsonNode.class); + final boolean match = cursor.stream().noneMatch(t -> t.asLong() == 100L); + assertThat(match).isTrue(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void allMatchStream(ArangoDatabase db) { + final ArangoCursor cursor = db.query("FOR i IN 0..99 RETURN i", JsonNode.class); + final boolean match = cursor.stream().allMatch(t -> t.asLong() < 100L); + assertThat(match).isTrue(); + } + +} diff --git a/shaded-integration-tests/src/test/jackson/java/com/arangodb/ArangoDBTest.java b/shaded-integration-tests/src/test/jackson/java/com/arangodb/ArangoDBTest.java new file mode 100644 index 000000000..0bf363642 --- /dev/null +++ b/shaded-integration-tests/src/test/jackson/java/com/arangodb/ArangoDBTest.java @@ -0,0 +1,656 @@ +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed 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. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb; + +import com.arangodb.entity.*; +import com.arangodb.internal.config.FileConfigPropertiesProvider; +import com.arangodb.internal.serde.SerdeUtils; +import com.arangodb.model.*; +import com.arangodb.model.LogOptions.SortOrder; +import com.arangodb.shaded.fasterxml.jackson.databind.JsonNode; +import com.arangodb.util.RawJson; +import com.arangodb.util.TestUtils; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + +import java.util.*; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Executors; +import java.util.stream.Collectors; +import java.util.stream.IntStream; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.catchThrowable; +import static org.junit.jupiter.api.Assumptions.assumeTrue; + +/** + * @author Mark Vollmary + * @author Reşat SABIQ + * @author Michele Rastelli + */ +class ArangoDBTest extends BaseJunit5 { + + private static final DbName DB1 = DbName.of("ArangoDBTest_db1"); + private static final DbName DB2 = DbName.of("ArangoDBTest_db2"); + + private static final String ROOT = "root"; + private static final String PW = "machts der hund"; + + private static Boolean extendedNames; + + @BeforeAll + static void initDBs() { + initDB(DB1); + initDB(DB2); + } + + @AfterAll + static void shutdown() { + dropDB(DB1); + dropDB(DB2); + } + + private boolean supportsExtendedNames(ArangoDB arangoDB) { + if (extendedNames == null) { + try { + ArangoDatabase testDb = arangoDB.db(DbName.of("test-" + TestUtils.generateRandomDbName(20, true))); + testDb.create(); + extendedNames = true; + testDb.drop(); + } catch (ArangoDBException e) { + extendedNames = false; + } + } + return extendedNames; + } + + @ParameterizedTest(name = "{index}") + @MethodSource("arangos") + void getVersion(ArangoDB arangoDB) { + final ArangoDBVersion version = arangoDB.getVersion(); + assertThat(version.getServer()).isNotNull(); + assertThat(version.getVersion()).isNotNull(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("arangos") + void createAndDeleteDatabase(ArangoDB arangoDB) { + final DbName dbName = DbName.of("testDB-" + TestUtils.generateRandomDbName(20, + supportsExtendedNames(arangoDB))); + final Boolean resultCreate; + resultCreate = arangoDB.createDatabase(dbName); + assertThat(resultCreate).isTrue(); + final Boolean resultDelete = arangoDB.db(dbName).drop(); + assertThat(resultDelete).isTrue(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("arangos") + void createWithNotNormalizedName(ArangoDB arangoDB) { + assumeTrue(supportsExtendedNames(arangoDB)); + + final String dbName = "testDB-\u006E\u0303\u00f1"; + DbName normalized = DbName.normalize(dbName); + arangoDB.createDatabase(normalized); + arangoDB.db(normalized).drop(); + + Throwable thrown = catchThrowable(() -> DbName.of(dbName)); + assertThat(thrown) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("not normalized"); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("arangos") + void createDatabaseWithOptions(ArangoDB arangoDB) { + assumeTrue(isCluster()); + assumeTrue(isAtLeastVersion(3, 6)); + final DbName dbName = DbName.of("testDB-" + TestUtils.generateRandomDbName(20, + supportsExtendedNames(arangoDB))); + final Boolean resultCreate = arangoDB.createDatabase(new DBCreateOptions() + .name(dbName) + .options(new DatabaseOptions() + .writeConcern(2) + .replicationFactor(2) + .sharding("") + ) + ); + assertThat(resultCreate).isTrue(); + + DatabaseEntity info = arangoDB.db(dbName).getInfo(); + assertThat(info.getReplicationFactor().getValue()).isEqualTo(2); + assertThat(info.getWriteConcern()).isEqualTo(2); + assertThat(info.getSharding()).isEmpty(); + + final Boolean resultDelete = arangoDB.db(dbName).drop(); + assertThat(resultDelete).isTrue(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("arangos") + void createDatabaseWithOptionsSatellite(ArangoDB arangoDB) { + assumeTrue(isCluster()); + assumeTrue(isEnterprise()); + assumeTrue(isAtLeastVersion(3, 6)); + + final DbName dbName = DbName.of("testDB-" + TestUtils.generateRandomDbName(20, + supportsExtendedNames(arangoDB))); + final Boolean resultCreate = arangoDB.createDatabase(new DBCreateOptions() + .name(dbName) + .options(new DatabaseOptions() + .writeConcern(2) + .replicationFactor(ReplicationFactor.ofSatellite()) + .sharding("") + ) + ); + assertThat(resultCreate).isTrue(); + + DatabaseEntity info = arangoDB.db(dbName).getInfo(); + assertThat(info.getReplicationFactor()).isEqualTo(ReplicationFactor.ofSatellite()); + assertThat(info.getWriteConcern()).isEqualTo(2); + assertThat(info.getSharding()).isEmpty(); + + final Boolean resultDelete = arangoDB.db(dbName).drop(); + assertThat(resultDelete).isTrue(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("arangos") + void createDatabaseWithUsers(ArangoDB arangoDB) throws InterruptedException { + final DbName dbName = DbName.of("testDB-" + TestUtils.generateRandomDbName(20, + supportsExtendedNames(arangoDB))); + final Map extra = Collections.singletonMap("key", "value"); + final Boolean resultCreate = arangoDB.createDatabase(new DBCreateOptions() + .name(dbName) + .users(Collections.singletonList(new DatabaseUsersOptions() + .active(true) + .username("testUser") + .passwd("testPasswd") + .extra(extra) + )) + ); + assertThat(resultCreate).isTrue(); + + DatabaseEntity info = arangoDB.db(dbName).getInfo(); + assertThat(info.getName()).isEqualTo(dbName.get()); + + Optional retrievedUserOptional = arangoDB.getUsers().stream() + .filter(it -> it.getUser().equals("testUser")) + .findFirst(); + assertThat(retrievedUserOptional).isPresent(); + + UserEntity retrievedUser = retrievedUserOptional.get(); + assertThat(retrievedUser.getActive()).isTrue(); + assertThat(retrievedUser.getExtra()).isEqualTo(extra); + + // needed for active-failover tests only + Thread.sleep(2_000); + + ArangoDB arangoDBTestUser = new ArangoDB.Builder() + .loadProperties(new FileConfigPropertiesProvider()) + .user("testUser") + .password("testPasswd") + .build(); + + // check if testUser has been created and can access the created db + ArangoCollection collection = arangoDBTestUser.db(dbName).collection("col-" + UUID.randomUUID()); + collection.create(); + arangoDBTestUser.shutdown(); + + final Boolean resultDelete = arangoDB.db(dbName).drop(); + assertThat(resultDelete).isTrue(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("arangos") + void getDatabases(ArangoDB arangoDB) { + Collection dbs = arangoDB.getDatabases(); + assertThat(dbs).contains("_system", DB1.get()); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("arangos") + void getAccessibleDatabases(ArangoDB arangoDB) { + final Collection dbs = arangoDB.getAccessibleDatabases(); + assertThat(dbs).contains("_system"); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("arangos") + void getAccessibleDatabasesFor(ArangoDB arangoDB) { + final Collection dbs = arangoDB.getAccessibleDatabasesFor("root"); + assertThat(dbs).contains("_system"); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("arangos") + void createUser(ArangoDB arangoDB) { + String username = "user-" + UUID.randomUUID(); + final UserEntity result = arangoDB.createUser(username, PW, null); + assertThat(result.getUser()).isEqualTo(username); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("arangos") + void deleteUser(ArangoDB arangoDB) { + String username = "user-" + UUID.randomUUID(); + arangoDB.createUser(username, PW, null); + arangoDB.deleteUser(username); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("arangos") + void getUserRoot(ArangoDB arangoDB) { + final UserEntity user = arangoDB.getUser(ROOT); + assertThat(user.getUser()).isEqualTo(ROOT); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("arangos") + void getUser(ArangoDB arangoDB) { + String username = "user-" + UUID.randomUUID(); + arangoDB.createUser(username, PW, null); + final UserEntity user = arangoDB.getUser(username); + assertThat(user.getUser()).isEqualTo(username); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("arangos") + void getUsersOnlyRoot(ArangoDB arangoDB) { + final Collection users = arangoDB.getUsers(); + assertThat(users).isNotEmpty(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("arangos") + void getUsers(ArangoDB arangoDB) { + String username = "user-" + UUID.randomUUID(); + // Allow & account for pre-existing users other than ROOT: + final Collection initialUsers = arangoDB.getUsers(); + + arangoDB.createUser(username, PW, null); + final Collection users = arangoDB.getUsers(); + assertThat(users).hasSize(initialUsers.size() + 1); + + final List expected = new ArrayList<>(users.size()); + // Add initial users, including root: + for (final UserEntity userEntity : initialUsers) { + expected.add(userEntity.getUser()); + } + // Add username: + expected.add(username); + + for (final UserEntity user : users) { + assertThat(user.getUser()).isIn(expected); + } + } + + @ParameterizedTest(name = "{index}") + @MethodSource("arangos") + void updateUserNoOptions(ArangoDB arangoDB) { + String username = "user-" + UUID.randomUUID(); + arangoDB.createUser(username, PW, null); + arangoDB.updateUser(username, null); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("arangos") + void updateUser(ArangoDB arangoDB) { + String username = "user-" + UUID.randomUUID(); + final Map extra = new HashMap<>(); + extra.put("hund", false); + arangoDB.createUser(username, PW, new UserCreateOptions().extra(extra)); + extra.put("hund", true); + extra.put("mund", true); + final UserEntity user = arangoDB.updateUser(username, new UserUpdateOptions().extra(extra)); + assertThat(user.getExtra()).hasSize(2); + assertThat(user.getExtra()).containsKey("hund"); + assertThat(Boolean.valueOf(String.valueOf(user.getExtra().get("hund")))).isTrue(); + final UserEntity user2 = arangoDB.getUser(username); + assertThat(user2.getExtra()).hasSize(2); + assertThat(user2.getExtra()).containsKey("hund"); + assertThat(Boolean.valueOf(String.valueOf(user2.getExtra().get("hund")))).isTrue(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("arangos") + void replaceUser(ArangoDB arangoDB) { + String username = "user-" + UUID.randomUUID(); + final Map extra = new HashMap<>(); + extra.put("hund", false); + arangoDB.createUser(username, PW, new UserCreateOptions().extra(extra)); + extra.remove("hund"); + extra.put("mund", true); + final UserEntity user = arangoDB.replaceUser(username, new UserUpdateOptions().extra(extra)); + assertThat(user.getExtra()).hasSize(1); + assertThat(user.getExtra()).containsKey("mund"); + assertThat(Boolean.valueOf(String.valueOf(user.getExtra().get("mund")))).isTrue(); + final UserEntity user2 = arangoDB.getUser(username); + assertThat(user2.getExtra()).hasSize(1); + assertThat(user2.getExtra()).containsKey("mund"); + assertThat(Boolean.valueOf(String.valueOf(user2.getExtra().get("mund")))).isTrue(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("arangos") + void updateUserDefaultDatabaseAccess(ArangoDB arangoDB) { + String username = "user-" + UUID.randomUUID(); + arangoDB.createUser(username, PW); + arangoDB.grantDefaultDatabaseAccess(username, Permissions.RW); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("arangos") + void updateUserDefaultCollectionAccess(ArangoDB arangoDB) { + String username = "user-" + UUID.randomUUID(); + arangoDB.createUser(username, PW); + arangoDB.grantDefaultCollectionAccess(username, Permissions.RW); + } + + @Test + void authenticationFailPassword() { + final ArangoDB arangoDB = new ArangoDB.Builder() + .loadProperties(new FileConfigPropertiesProvider()) + .password("no").jwt(null).build(); + Throwable thrown = catchThrowable(arangoDB::getVersion); + assertThat(thrown).isInstanceOf(ArangoDBException.class); + assertThat(((ArangoDBException) thrown).getResponseCode()).isEqualTo(401); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("arangos") + void authenticationFailUser() { + final ArangoDB arangoDB = new ArangoDB.Builder() + .loadProperties(new FileConfigPropertiesProvider()) + .user("no").jwt(null).build(); + Throwable thrown = catchThrowable(arangoDB::getVersion); + assertThat(thrown).isInstanceOf(ArangoDBException.class); + assertThat(((ArangoDBException) thrown).getResponseCode()).isEqualTo(401); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("arangos") + void executeGetVersion(ArangoDB arangoDB) { + Request request = Request.builder() + .db(DbName.SYSTEM) + .method(Request.Method.GET) + .path("/_api/version") + .queryParam("details", "true") + .build(); + final Response response = arangoDB.execute(request, RawJson.class); + JsonNode body = SerdeUtils.INSTANCE.parseJson(response.getBody().getValue()); + assertThat(body.get("version").isTextual()).isTrue(); + assertThat(body.get("details").isObject()).isTrue(); + assertThat(response.getResponseCode()).isEqualTo(200); + if (isAtLeastVersion(3, 9)) { + String header = response.getHeaders().get("x-arango-queue-time-seconds"); + assertThat(header).isNotNull(); + } + } + + @ParameterizedTest(name = "{index}") + @MethodSource("arangos") + void getLogEntries(ArangoDB arangoDB) { + assumeTrue(isAtLeastVersion(3, 8)); + final LogEntriesEntity logs = arangoDB.getLogEntries(null); + assertThat(logs.getTotal()).isPositive(); + assertThat(logs.getMessages()).hasSize(logs.getTotal().intValue()); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("arangos") + void getLogEntriesUpto(ArangoDB arangoDB) { + assumeTrue(isAtLeastVersion(3, 8)); + final LogEntriesEntity logsUpto = arangoDB.getLogEntries(new LogOptions().upto(LogLevel.WARNING)); + assertThat(logsUpto.getMessages()) + .map(LogEntriesEntity.Message::getLevel) + .doesNotContain("INFO"); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("arangos") + void getLogEntriesLevel(ArangoDB arangoDB) { + assumeTrue(isAtLeastVersion(3, 8)); + final LogEntriesEntity logsInfo = arangoDB.getLogEntries(new LogOptions().level(LogLevel.INFO)); + assertThat(logsInfo.getMessages()) + .map(LogEntriesEntity.Message::getLevel) + .containsOnly("INFO"); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("arangos") + void getLogEntriesStart(ArangoDB arangoDB) { + assumeTrue(isAtLeastVersion(3, 8)); + final LogEntriesEntity logs = arangoDB.getLogEntries(null); + final Long firstId = logs.getMessages().get(0).getId(); + final LogEntriesEntity logsStart = arangoDB.getLogEntries(new LogOptions().start(firstId + 1)); + assertThat(logsStart.getMessages()) + .map(LogEntriesEntity.Message::getId) + .doesNotContain(firstId); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("arangos") + void getLogEntriesSize(ArangoDB arangoDB) { + assumeTrue(isAtLeastVersion(3, 8)); + final LogEntriesEntity logs = arangoDB.getLogEntries(null); + int count = logs.getMessages().size(); + assertThat(count).isPositive(); + final LogEntriesEntity logsSize = arangoDB.getLogEntries(new LogOptions().size(count - 1)); + assertThat(logsSize.getMessages()).hasSize(count - 1); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("arangos") + void getLogEntriesOffset(ArangoDB arangoDB) { + assumeTrue(isAtLeastVersion(3, 8)); + final LogEntriesEntity logs = arangoDB.getLogEntries(null); + assertThat(logs.getTotal()).isPositive(); + Long firstId = logs.getMessages().get(0).getId(); + final LogEntriesEntity logsOffset = arangoDB.getLogEntries(new LogOptions().offset(1)); + assertThat(logsOffset.getMessages()) + .map(LogEntriesEntity.Message::getId) + .doesNotContain(firstId); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("arangos") + void getLogEntriesSearch(ArangoDB arangoDB) { + assumeTrue(isAtLeastVersion(3, 8)); + final LogEntriesEntity logs = arangoDB.getLogEntries(null); + final LogEntriesEntity logsSearch = arangoDB.getLogEntries(new LogOptions().search(TEST_DB.get())); + assertThat(logs.getTotal()).isGreaterThan(logsSearch.getTotal()); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("arangos") + void getLogEntriesSortAsc(ArangoDB arangoDB) { + assumeTrue(isAtLeastVersion(3, 8)); + final LogEntriesEntity logs = arangoDB.getLogEntries(new LogOptions().sort(SortOrder.asc)); + long lastId = -1; + List ids = logs.getMessages().stream() + .map(LogEntriesEntity.Message::getId) + .collect(Collectors.toList()); + for (final Long id : ids) { + assertThat(id).isGreaterThan(lastId); + lastId = id; + } + } + + @ParameterizedTest(name = "{index}") + @MethodSource("arangos") + void getLogEntriesSortDesc(ArangoDB arangoDB) { + assumeTrue(isAtLeastVersion(3, 8)); + final LogEntriesEntity logs = arangoDB.getLogEntries(new LogOptions().sort(SortOrder.desc)); + long lastId = Long.MAX_VALUE; + List ids = logs.getMessages().stream() + .map(LogEntriesEntity.Message::getId) + .collect(Collectors.toList()); + for (final Long id : ids) { + assertThat(lastId).isGreaterThan(id); + lastId = id; + } + } + + @ParameterizedTest(name = "{index}") + @MethodSource("arangos") + void getLogLevel(ArangoDB arangoDB) { + assumeTrue(isAtLeastVersion(3, 7)); // it fails in 3.6 active-failover (BTS-362) + final LogLevelEntity logLevel = arangoDB.getLogLevel(); + assertThat(logLevel.getAgency()).isEqualTo(LogLevelEntity.LogLevel.INFO); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("arangos") + void setLogLevel(ArangoDB arangoDB) { + assumeTrue(isAtLeastVersion(3, 7)); // it fails in 3.6 active-failover (BTS-362) + final LogLevelEntity entity = new LogLevelEntity(); + try { + entity.setAgency(LogLevelEntity.LogLevel.ERROR); + final LogLevelEntity logLevel = arangoDB.setLogLevel(entity); + assertThat(logLevel.getAgency()).isEqualTo(LogLevelEntity.LogLevel.ERROR); + } finally { + entity.setAgency(LogLevelEntity.LogLevel.INFO); + arangoDB.setLogLevel(entity); + } + } + + @ParameterizedTest(name = "{index}") + @MethodSource("arangos") + void setAllLogLevel(ArangoDB arangoDB) { + assumeTrue(isAtLeastVersion(3, 9)); + final LogLevelEntity entity = new LogLevelEntity(); + try { + entity.setAll(LogLevelEntity.LogLevel.ERROR); + final LogLevelEntity logLevel = arangoDB.setLogLevel(entity); + assertThat(logLevel.getAgency()).isEqualTo(LogLevelEntity.LogLevel.ERROR); + assertThat(logLevel.getQueries()).isEqualTo(LogLevelEntity.LogLevel.ERROR); + LogLevelEntity retrievedLevels = arangoDB.getLogLevel(); + assertThat(retrievedLevels.getAgency()).isEqualTo(LogLevelEntity.LogLevel.ERROR); + } finally { + entity.setAll(LogLevelEntity.LogLevel.INFO); + arangoDB.setLogLevel(entity); + } + } + + @ParameterizedTest(name = "{index}") + @MethodSource("arangos") + void getQueryOptimizerRules(ArangoDB arangoDB) { + assumeTrue(isAtLeastVersion(3, 10)); + final Collection rules = arangoDB.getQueryOptimizerRules(); + assertThat(rules).isNotEmpty(); + for (QueryOptimizerRule rule : rules) { + assertThat(rule).isNotNull(); + assertThat(rule.getName()).isNotNull(); + QueryOptimizerRule.Flags flags = rule.getFlags(); + assertThat(flags.getHidden()).isNotNull(); + assertThat(flags.getClusterOnly()).isNotNull(); + assertThat(flags.getCanBeDisabled()).isNotNull(); + assertThat(flags.getCanCreateAdditionalPlans()).isNotNull(); + assertThat(flags.getDisabledByDefault()).isNotNull(); + assertThat(flags.getEnterpriseOnly()).isNotNull(); + } + } + + @ParameterizedTest(name = "{index}") + @MethodSource("arangos") + void arangoDBException(ArangoDB arangoDB) { + Throwable thrown = catchThrowable(() -> arangoDB.db(DbName.of("no")).getInfo()); + assertThat(thrown).isInstanceOf(ArangoDBException.class); + ArangoDBException e = (ArangoDBException) thrown; + assertThat(e.getResponseCode()).isEqualTo(404); + assertThat(e.getErrorNum()).isEqualTo(1228); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("arangos") + void fallbackHost() { + final ArangoDB arangoDB = new ArangoDB.Builder() + .loadProperties(new FileConfigPropertiesProvider()) + .host("not-accessible", 8529).host("127.0.0.1", 8529).build(); + final ArangoDBVersion version = arangoDB.getVersion(); + assertThat(version).isNotNull(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("arangos") + void loadproperties() { + Throwable thrown = catchThrowable(() -> new ArangoDB.Builder() + .loadProperties(new FileConfigPropertiesProvider("arangodb", "/arangodb-bad.properties")) + ); + assertThat(thrown).isInstanceOf(ArangoDBException.class); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("arangos") + void accessMultipleDatabases(ArangoDB arangoDB) { + final ArangoDBVersion version1 = arangoDB.db(DB1).getVersion(); + assertThat(version1).isNotNull(); + final ArangoDBVersion version2 = arangoDB.db(DB2).getVersion(); + assertThat(version2).isNotNull(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("arangos") + @Disabled("Manual execution only") + void queueTime(ArangoDB arangoDB) throws InterruptedException, ExecutionException { + List> futures = IntStream.range(0, 80) + .mapToObj(i -> CompletableFuture.runAsync( + () -> arangoDB.db().query("RETURN SLEEP(1)", Void.class), + Executors.newFixedThreadPool(80)) + ) + .collect(Collectors.toList()); + for (CompletableFuture f : futures) { + f.get(); + } + + QueueTimeMetrics qt = arangoDB.metrics().getQueueTime(); + double avg = qt.getAvg(); + QueueTimeSample[] values = qt.getValues(); + if (isAtLeastVersion(3, 9)) { + assertThat(values).hasSize(20); + for (int i = 0; i < values.length; i++) { + assertThat(values[i].value).isNotNegative(); + if (i > 0) { + assertThat(values[i].timestamp).isGreaterThanOrEqualTo(values[i - 1].timestamp); + } + } + + if (avg < 0.0) { + System.err.println("avg < 0: " + avg); + System.err.println("got values:"); + for (QueueTimeSample v : values) { + System.err.println(v.value); + } + } + assertThat(avg).isPositive(); + } else { + assertThat(avg).isEqualTo(0.0); + assertThat(values).isEmpty(); + } + + } +} diff --git a/shaded-integration-tests/src/test/jackson/java/com/arangodb/ArangoDatabaseTest.java b/shaded-integration-tests/src/test/jackson/java/com/arangodb/ArangoDatabaseTest.java new file mode 100644 index 000000000..bfd9924cd --- /dev/null +++ b/shaded-integration-tests/src/test/jackson/java/com/arangodb/ArangoDatabaseTest.java @@ -0,0 +1,1413 @@ +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed 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. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb; + +import com.arangodb.entity.*; +import com.arangodb.entity.AqlExecutionExplainEntity.ExecutionPlan; +import com.arangodb.entity.QueryCachePropertiesEntity.CacheMode; +import com.arangodb.model.*; +import com.arangodb.util.MapBuilder; +import com.arangodb.util.RawBytes; +import com.arangodb.util.RawJson; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.fasterxml.jackson.databind.node.JsonNodeFactory; +import com.fasterxml.jackson.databind.node.ObjectNode; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + +import java.io.IOException; +import java.util.*; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; +import java.util.concurrent.atomic.AtomicInteger; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.catchThrowable; +import static org.junit.jupiter.api.Assertions.fail; +import static org.junit.jupiter.api.Assumptions.assumeTrue; + + +/** + * @author Mark Vollmary + * @author Michele Rastelli + */ +class ArangoDatabaseTest extends BaseJunit5 { + + private static final String CNAME1 = "ArangoDatabaseTest_collection_1"; + private static final String CNAME2 = "ArangoDatabaseTest_collection_2"; + private static final String ENAMES = "ArangoDatabaseTest_edge_collection"; + + @BeforeAll + static void init() { + BaseJunit5.initDB(); + BaseJunit5.initCollections(CNAME1, CNAME2); + BaseJunit5.initEdgeCollections(ENAMES); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void getVersion(ArangoDatabase db) { + final ArangoDBVersion version = db.getVersion(); + assertThat(version).isNotNull(); + assertThat(version.getServer()).isNotNull(); + assertThat(version.getVersion()).isNotNull(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void getEngine(ArangoDatabase db) { + final ArangoDBEngine engine = db.getEngine(); + assertThat(engine).isNotNull(); + assertThat(engine.getName()).isNotNull(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("arangos") + void exists(ArangoDB arangoDB) { + assertThat(arangoDB.db(TEST_DB).exists()).isTrue(); + assertThat(arangoDB.db(DbName.of("no")).exists()).isFalse(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void getAccessibleDatabases(ArangoDatabase db) { + final Collection dbs = db.getAccessibleDatabases(); + assertThat(dbs).contains("_system"); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void createCollection(ArangoDatabase db) { + String name = "collection-" + rnd(); + final CollectionEntity result = db.createCollection(name, null); + assertThat(result).isNotNull(); + assertThat(result.getId()).isNotNull(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void createCollectionWithReplicationFactor(ArangoDatabase db) { + assumeTrue(isCluster()); + String name = "collection-" + rnd(); + final CollectionEntity result = db + .createCollection(name, new CollectionCreateOptions().replicationFactor(2)); + assertThat(result).isNotNull(); + assertThat(result.getId()).isNotNull(); + CollectionPropertiesEntity props = db.collection(name).getProperties(); + assertThat(props.getReplicationFactor().getValue()).isEqualTo(2); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void createCollectionWithWriteConcern(ArangoDatabase db) { + assumeTrue(isAtLeastVersion(3, 5)); + assumeTrue(isCluster()); + + String name = "collection-" + rnd(); + final CollectionEntity result = db.createCollection(name, + new CollectionCreateOptions().replicationFactor(2).writeConcern(2)); + assertThat(result).isNotNull(); + assertThat(result.getId()).isNotNull(); + CollectionPropertiesEntity props = db.collection(name).getProperties(); + assertThat(props.getReplicationFactor().getValue()).isEqualTo(2); + assertThat(props.getWriteConcern()).isEqualTo(2); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void createSatelliteCollection(ArangoDatabase db) { + assumeTrue(isEnterprise()); + assumeTrue(isCluster()); + + String name = "collection-" + rnd(); + final CollectionEntity result = db + .createCollection(name, new CollectionCreateOptions().replicationFactor(ReplicationFactor.ofSatellite())); + + assertThat(result).isNotNull(); + assertThat(result.getId()).isNotNull(); + CollectionPropertiesEntity props = db.collection(name).getProperties(); + assertThat(props.getReplicationFactor()).isEqualTo(ReplicationFactor.ofSatellite()); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void createCollectionWithNumberOfShards(ArangoDatabase db) { + assumeTrue(isCluster()); + String name = "collection-" + rnd(); + final CollectionEntity result = db + .createCollection(name, new CollectionCreateOptions().numberOfShards(2)); + + assertThat(result).isNotNull(); + assertThat(result.getId()).isNotNull(); + CollectionPropertiesEntity props = db.collection(name).getProperties(); + assertThat(props.getNumberOfShards()).isEqualTo(2); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void createCollectionWithShardingStrategys(ArangoDatabase db) { + assumeTrue(isAtLeastVersion(3, 4)); + assumeTrue(isCluster()); + + String name = "collection-" + rnd(); + final CollectionEntity result = db.createCollection(name, new CollectionCreateOptions() + .shardingStrategy(ShardingStrategy.COMMUNITY_COMPAT.getInternalName())); + + assertThat(result).isNotNull(); + assertThat(result.getId()).isNotNull(); + CollectionPropertiesEntity props = db.collection(name).getProperties(); + assertThat(props.getShardingStrategy()).isEqualTo(ShardingStrategy.COMMUNITY_COMPAT.getInternalName()); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void createCollectionWithSmartJoinAttribute(ArangoDatabase db) { + assumeTrue(isAtLeastVersion(3, 5)); + assumeTrue(isEnterprise()); + assumeTrue(isCluster()); + + String name = "collection-" + rnd(); + final CollectionEntity result = db.createCollection(name, + new CollectionCreateOptions().smartJoinAttribute("test123").shardKeys("_key:")); + assertThat(result).isNotNull(); + assertThat(result.getId()).isNotNull(); + assertThat(db.collection(name).getProperties().getSmartJoinAttribute()).isEqualTo("test123"); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void createCollectionWithSmartJoinAttributeWrong(ArangoDatabase db) { + assumeTrue(isAtLeastVersion(3, 5)); + assumeTrue(isEnterprise()); + assumeTrue(isCluster()); + + String name = "collection-" + rnd(); + + try { + db.createCollection(name, new CollectionCreateOptions().smartJoinAttribute("test123")); + } catch (ArangoDBException e) { + assertThat(e.getErrorNum()).isEqualTo(4006); + assertThat(e.getResponseCode()).isEqualTo(400); + } + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void createCollectionWithNumberOfShardsAndShardKey(ArangoDatabase db) { + assumeTrue(isCluster()); + + String name = "collection-" + rnd(); + final CollectionEntity result = db + .createCollection(name, new CollectionCreateOptions().numberOfShards(2).shardKeys("a")); + assertThat(result).isNotNull(); + assertThat(result.getId()).isNotNull(); + final CollectionPropertiesEntity properties = db.collection(name).getProperties(); + assertThat(properties.getNumberOfShards()).isEqualTo(2); + assertThat(properties.getShardKeys()).hasSize(1); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void createCollectionWithNumberOfShardsAndShardKeys(ArangoDatabase db) { + assumeTrue(isCluster()); + String name = "collection-" + rnd(); + final CollectionEntity result = db.createCollection(name, + new CollectionCreateOptions().numberOfShards(2).shardKeys("a", "b")); + assertThat(result).isNotNull(); + assertThat(result.getId()).isNotNull(); + final CollectionPropertiesEntity properties = db.collection(name).getProperties(); + assertThat(properties.getNumberOfShards()).isEqualTo(2); + assertThat(properties.getShardKeys()).hasSize(2); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void createCollectionWithDistributeShardsLike(ArangoDatabase db) { + assumeTrue(isEnterprise()); + assumeTrue(isCluster()); + + final Integer numberOfShards = 3; + + String name1 = "collection-" + rnd(); + String name2 = "collection-" + rnd(); + db.createCollection(name1, new CollectionCreateOptions().numberOfShards(numberOfShards)); + db.createCollection(name2, new CollectionCreateOptions().distributeShardsLike(name1)); + + assertThat(db.collection(name1).getProperties().getNumberOfShards()).isEqualTo(numberOfShards); + assertThat(db.collection(name2).getProperties().getNumberOfShards()).isEqualTo(numberOfShards); + } + + private void createCollectionWithKeyType(ArangoDatabase db, KeyType keyType) { + String name = "collection-" + rnd(); + db.createCollection(name, new CollectionCreateOptions().keyOptions( + false, + keyType, + null, + null + )); + assertThat(db.collection(name).getProperties().getKeyOptions().getType()).isEqualTo(keyType); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void createCollectionWithKeyTypeAutoincrement(ArangoDatabase db) { + assumeTrue(isSingleServer()); + createCollectionWithKeyType(db, KeyType.autoincrement); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void createCollectionWithKeyTypePadded(ArangoDatabase db) { + assumeTrue(isAtLeastVersion(3, 4)); + createCollectionWithKeyType(db, KeyType.padded); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void createCollectionWithKeyTypeTraditional(ArangoDatabase db) { + createCollectionWithKeyType(db, KeyType.traditional); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void createCollectionWithKeyTypeUuid(ArangoDatabase db) { + assumeTrue(isAtLeastVersion(3, 4)); + createCollectionWithKeyType(db, KeyType.uuid); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void createCollectionWithJsonSchema(ArangoDatabase db) { + assumeTrue(isAtLeastVersion(3, 7)); + String name = "collection-" + rnd(); + String rule = ("{ " + + " \"properties\": {" + + " \"number\": {" + + " \"type\": \"number\"" + + " }" + + " }" + + " }") + .replaceAll("\\s", ""); + String message = "The document has problems!"; + + final CollectionEntity result = db + .createCollection(name, new CollectionCreateOptions() + .schema( + new CollectionSchema() + .setLevel(CollectionSchema.Level.NEW) + .setMessage(message) + .setRule(rule) + ) + ); + assertThat(result.getSchema().getLevel()).isEqualTo(CollectionSchema.Level.NEW); + assertThat(result.getSchema().getRule()).isEqualTo(rule); + assertThat(result.getSchema().getMessage()).isEqualTo(message); + + CollectionPropertiesEntity props = db.collection(name).getProperties(); + assertThat(props.getSchema().getLevel()).isEqualTo(CollectionSchema.Level.NEW); + assertThat(props.getSchema().getRule()).isEqualTo(rule); + assertThat(props.getSchema().getMessage()).isEqualTo(message); + + BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); + doc.addAttribute("number", 33); + db.collection(name).insertDocument(doc); + + BaseDocument wrongDoc = new BaseDocument(UUID.randomUUID().toString()); + wrongDoc.addAttribute("number", "notANumber"); + Throwable thrown = catchThrowable(() -> db.collection(name).insertDocument(wrongDoc)); + assertThat(thrown).isInstanceOf(ArangoDBException.class); + ArangoDBException e = (ArangoDBException) thrown; + + assertThat(e).hasMessageContaining(message); + assertThat(e.getResponseCode()).isEqualTo(400); + assertThat(e.getErrorNum()).isEqualTo(1620); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void createCollectionWithComputedFields(ArangoDatabase db) { + assumeTrue(isAtLeastVersion(3, 10)); + String cName = "collection-" + rnd(); + ComputedValue cv = new ComputedValue() + .name("foo") + .expression("RETURN 11") + .overwrite(false) + .computeOn(ComputedValue.ComputeOn.insert) + .keepNull(false) + .failOnWarning(true); + + final CollectionEntity result = db.createCollection(cName, new CollectionCreateOptions().computedValues(cv)); + + assertThat(result).isNotNull(); + assertThat(result.getComputedValues()) + .hasSize(1) + .contains(cv); + + ComputedValue cv2 = new ComputedValue() + .name("bar") + .expression("RETURN 22") + .overwrite(true) + .computeOn(ComputedValue.ComputeOn.update, ComputedValue.ComputeOn.replace) + .keepNull(true) + .failOnWarning(false); + + db.collection(cName).changeProperties(new CollectionPropertiesOptions().computedValues(cv2)); + + CollectionPropertiesEntity props = db.collection(cName).getProperties(); + assertThat(props.getComputedValues()) + .hasSize(1) + .contains(cv2); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void deleteCollection(ArangoDatabase db) { + String name = "collection-" + rnd(); + db.createCollection(name, null); + db.collection(name).drop(); + Throwable thrown = catchThrowable(() -> db.collection(name).getInfo()); + assertThat(thrown).isInstanceOf(ArangoDBException.class); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void deleteSystemCollection(ArangoDatabase db) { + final String name = "_system_test"; + db.createCollection(name, new CollectionCreateOptions().isSystem(true)); + db.collection(name).drop(true); + Throwable thrown = catchThrowable(() -> db.collection(name).getInfo()); + assertThat(thrown) + .isInstanceOf(ArangoDBException.class) + .extracting(it -> ((ArangoDBException) it).getResponseCode()) + .isEqualTo(404); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void deleteSystemCollectionFail(ArangoDatabase db) { + final String name = "_system_test"; + ArangoCollection collection = db.collection(name); + if (collection.exists()) + collection.drop(true); + + db.createCollection(name, new CollectionCreateOptions().isSystem(true)); + try { + collection.drop(); + fail(); + } catch (final ArangoDBException e) { + assertThat(e.getResponseCode()).isEqualTo(403); + } + collection.drop(true); + try { + collection.getInfo(); + fail(); + } catch (final ArangoDBException e) { + assertThat(e.getResponseCode()).isEqualTo(404); + } + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void getIndex(ArangoDatabase db) { + final Collection fields = Collections.singletonList("field-" + rnd()); + final IndexEntity createResult = db.collection(CNAME1).ensureHashIndex(fields, null); + final IndexEntity readResult = db.getIndex(createResult.getId()); + assertThat(readResult.getId()).isEqualTo(createResult.getId()); + assertThat(readResult.getType()).isEqualTo(createResult.getType()); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void deleteIndex(ArangoDatabase db) { + final Collection fields = Collections.singletonList("field-" + rnd()); + final IndexEntity createResult = db.collection(CNAME1).ensureHashIndex(fields, null); + final String id = db.deleteIndex(createResult.getId()); + assertThat(id).isEqualTo(createResult.getId()); + try { + db.getIndex(id); + fail(); + } catch (final ArangoDBException e) { + assertThat(e.getResponseCode()).isEqualTo(404); + } + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void getCollections(ArangoDatabase db) { + final Collection collections = db.getCollections(null); + long count = collections.stream().map(CollectionEntity::getName).filter(it -> it.equals(CNAME1)).count(); + assertThat(count).isEqualTo(1L); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void getCollectionsExcludeSystem(ArangoDatabase db) { + final CollectionsReadOptions options = new CollectionsReadOptions().excludeSystem(true); + final Collection nonSystemCollections = db.getCollections(options); + final Collection allCollections = db.getCollections(null); + assertThat(allCollections).hasSizeGreaterThan(nonSystemCollections.size()); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("arangos") + void grantAccess(ArangoDB arangoDB) { + String user = "user-" + rnd(); + arangoDB.createUser(user, "1234", null); + arangoDB.db(TEST_DB).grantAccess(user); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("arangos") + void grantAccessRW(ArangoDB arangoDB) { + String user = "user-" + rnd(); + arangoDB.createUser(user, "1234", null); + arangoDB.db(TEST_DB).grantAccess(user, Permissions.RW); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("arangos") + void grantAccessRO(ArangoDB arangoDB) { + String user = "user-" + rnd(); + arangoDB.createUser(user, "1234", null); + arangoDB.db(TEST_DB).grantAccess(user, Permissions.RO); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("arangos") + void grantAccessNONE(ArangoDB arangoDB) { + String user = "user-" + rnd(); + arangoDB.createUser(user, "1234", null); + arangoDB.db(TEST_DB).grantAccess(user, Permissions.NONE); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void grantAccessUserNotFound(ArangoDatabase db) { + String user = "user-" + rnd(); + Throwable thrown = catchThrowable(() -> db.grantAccess(user, Permissions.RW)); + assertThat(thrown).isInstanceOf(ArangoDBException.class); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("arangos") + void revokeAccess(ArangoDB arangoDB) { + String user = "user-" + rnd(); + arangoDB.createUser(user, "1234", null); + arangoDB.db(TEST_DB).revokeAccess(user); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void revokeAccessUserNotFound(ArangoDatabase db) { + String user = "user-" + rnd(); + Throwable thrown = catchThrowable(() -> db.revokeAccess(user)); + assertThat(thrown).isInstanceOf(ArangoDBException.class); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("arangos") + void resetAccess(ArangoDB arangoDB) { + String user = "user-" + rnd(); + arangoDB.createUser(user, "1234", null); + arangoDB.db(TEST_DB).resetAccess(user); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void resetAccessUserNotFound(ArangoDatabase db) { + String user = "user-" + rnd(); + Throwable thrown = catchThrowable(() -> db.resetAccess(user)); + assertThat(thrown).isInstanceOf(ArangoDBException.class); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("arangos") + void grantDefaultCollectionAccess(ArangoDB arangoDB) { + String user = "user-" + rnd(); + arangoDB.createUser(user, "1234"); + arangoDB.db(TEST_DB).grantDefaultCollectionAccess(user, Permissions.RW); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void getPermissions(ArangoDatabase db) { + assertThat(db.getPermissions("root")).isEqualTo(Permissions.RW); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void query(ArangoDatabase db) { + for (int i = 0; i < 10; i++) { + db.collection(CNAME1).insertDocument(new BaseDocument(), null); + } + final ArangoCursor cursor = db.query("for i in " + CNAME1 + " return i._id", null, null, String.class); + assertThat((Object) cursor).isNotNull(); + for (int i = 0; i < 10; i++, cursor.next()) { + assertThat((Iterator) cursor).hasNext(); + } + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void queryWithNullBindVar(ArangoDatabase db) { + final ArangoCursor cursor = db.query("return @foo", Collections.singletonMap("foo", null), null, + Object.class); + assertThat(cursor.hasNext()).isTrue(); + assertThat(cursor.next()).isNull(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void queryForEach(ArangoDatabase db) { + for (int i = 0; i < 10; i++) { + db.collection(CNAME1).insertDocument(new BaseDocument(), null); + } + final ArangoCursor cursor = db.query("for i in " + CNAME1 + " return i._id", null, null, String.class); + assertThat((Object) cursor).isNotNull(); + + int i = 0; + while (cursor.hasNext()) { + cursor.next(); + i++; + } + assertThat(i).isGreaterThanOrEqualTo(10); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void queryWithCount(ArangoDatabase db) { + for (int i = 0; i < 10; i++) { + db.collection(CNAME1).insertDocument(new BaseDocument(), null); + } + + final ArangoCursor cursor = db + .query("for i in " + CNAME1 + " Limit 6 return i._id", null, new AqlQueryOptions().count(true), + String.class); + assertThat((Object) cursor).isNotNull(); + for (int i = 1; i <= 6; i++, cursor.next()) { + assertThat(cursor.hasNext()).isTrue(); + } + assertThat(cursor.getCount()).isEqualTo(6); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void queryWithLimitAndFullCount(ArangoDatabase db) { + for (int i = 0; i < 10; i++) { + db.collection(CNAME1).insertDocument(new BaseDocument(), null); + } + + final ArangoCursor cursor = db + .query("for i in " + CNAME1 + " Limit 5 return i._id", null, new AqlQueryOptions().fullCount(true), + String.class); + assertThat((Object) cursor).isNotNull(); + for (int i = 0; i < 5; i++, cursor.next()) { + assertThat((Iterator) cursor).hasNext(); + } + assertThat(cursor.getStats()).isNotNull(); + assertThat(((Number) cursor.getStats().get("fullCount")).intValue()) + .isGreaterThanOrEqualTo(10); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void queryWithBatchSize(ArangoDatabase db) { + for (int i = 0; i < 10; i++) { + db.collection(CNAME1).insertDocument(new BaseDocument(), null); + } + + final ArangoCursor cursor = db + .query("for i in " + CNAME1 + " return i._id", null, new AqlQueryOptions().batchSize(5).count(true), + String.class); + + assertThat((Object) cursor).isNotNull(); + for (int i = 0; i < 10; i++, cursor.next()) { + assertThat((Iterator) cursor).hasNext(); + } + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void queryIterateWithBatchSize(ArangoDatabase db) { + for (int i = 0; i < 10; i++) { + db.collection(CNAME1).insertDocument(new BaseDocument(), null); + } + + final ArangoCursor cursor = db + .query("for i in " + CNAME1 + " return i._id", null, new AqlQueryOptions().batchSize(5).count(true), + String.class); + + assertThat((Object) cursor).isNotNull(); + final AtomicInteger i = new AtomicInteger(0); + for (; cursor.hasNext(); cursor.next()) { + i.incrementAndGet(); + } + assertThat(i.get()).isGreaterThanOrEqualTo(10); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void queryWithTTL(ArangoDatabase db) throws InterruptedException { + // set TTL to 1 seconds and get the second batch after 2 seconds! + final int ttl = 1; + final int wait = 2; + for (int i = 0; i < 10; i++) { + db.collection(CNAME1).insertDocument(new BaseDocument(), null); + } + + final ArangoCursor cursor = db + .query("for i in " + CNAME1 + " return i._id", null, new AqlQueryOptions().batchSize(5).ttl(ttl), + String.class); + + assertThat((Iterable) cursor).isNotNull(); + + try { + for (int i = 0; i < 10; i++, cursor.next()) { + assertThat(cursor.hasNext()).isTrue(); + if (i == 1) { + Thread.sleep(wait * 1000); + } + } + fail("this should fail"); + } catch (final ArangoDBException ex) { + assertThat(ex.getMessage()).isEqualTo("Response: 404, Error: 1600 - cursor not found"); + } + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void changeQueryCache(ArangoDatabase db) { + QueryCachePropertiesEntity properties = db.getQueryCacheProperties(); + assertThat(properties).isNotNull(); + assertThat(properties.getMode()).isEqualTo(CacheMode.off); + assertThat(properties.getMaxResults()).isPositive(); + + properties.setMode(CacheMode.on); + properties = db.setQueryCacheProperties(properties); + assertThat(properties).isNotNull(); + assertThat(properties.getMode()).isEqualTo(CacheMode.on); + + properties = db.getQueryCacheProperties(); + assertThat(properties.getMode()).isEqualTo(CacheMode.on); + + final QueryCachePropertiesEntity properties2 = new QueryCachePropertiesEntity(); + properties2.setMode(CacheMode.off); + db.setQueryCacheProperties(properties2); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void queryWithCache(ArangoDatabase db) { + assumeTrue(isSingleServer()); + for (int i = 0; i < 10; i++) { + db.collection(CNAME1).insertDocument(new BaseDocument(), null); + } + + final QueryCachePropertiesEntity properties = new QueryCachePropertiesEntity(); + properties.setMode(CacheMode.on); + db.setQueryCacheProperties(properties); + + final ArangoCursor cursor = db + .query("FOR t IN " + CNAME1 + " FILTER t.age >= 10 SORT t.age RETURN t._id", null, + new AqlQueryOptions().cache(true), String.class); + + assertThat((Object) cursor).isNotNull(); + assertThat(cursor.isCached()).isFalse(); + + final ArangoCursor cachedCursor = db + .query("FOR t IN " + CNAME1 + " FILTER t.age >= 10 SORT t.age RETURN t._id", null, + new AqlQueryOptions().cache(true), String.class); + + assertThat((Object) cachedCursor).isNotNull(); + assertThat(cachedCursor.isCached()).isTrue(); + + final QueryCachePropertiesEntity properties2 = new QueryCachePropertiesEntity(); + properties2.setMode(CacheMode.off); + db.setQueryCacheProperties(properties2); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void queryWithMemoryLimit(ArangoDatabase db) { + Throwable thrown = catchThrowable(() -> db.query("RETURN 1..100000", null, + new AqlQueryOptions().memoryLimit(32 * 1024L), String.class)); + assertThat(thrown).isInstanceOf(ArangoDBException.class); + assertThat(((ArangoDBException) thrown).getErrorNum()).isEqualTo(32); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void queryWithFailOnWarningTrue(ArangoDatabase db) { + Throwable thrown = catchThrowable(() -> db.query("RETURN 1 / 0", null, + new AqlQueryOptions().failOnWarning(true), String.class)); + assertThat(thrown).isInstanceOf(ArangoDBException.class); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void queryWithFailOnWarningFalse(ArangoDatabase db) { + final ArangoCursor cursor = db + .query("RETURN 1 / 0", null, new AqlQueryOptions().failOnWarning(false), String.class); + assertThat(cursor.next()).isNull(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void queryWithTimeout(ArangoDatabase db) { + assumeTrue(isAtLeastVersion(3, 6)); + Throwable thrown = catchThrowable(() -> db.query("RETURN SLEEP(1)", null, + new AqlQueryOptions().maxRuntime(0.1), String.class).next()); + assertThat(thrown).isInstanceOf(ArangoDBException.class); + assertThat(((ArangoDBException) thrown).getResponseCode()).isEqualTo(410); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void queryWithMaxWarningCount(ArangoDatabase db) { + final ArangoCursor cursorWithWarnings = db + .query("RETURN 1 / 0", null, new AqlQueryOptions(), String.class); + assertThat(cursorWithWarnings.getWarnings()).hasSize(1); + final ArangoCursor cursorWithLimitedWarnings = db + .query("RETURN 1 / 0", null, new AqlQueryOptions().maxWarningCount(0L), String.class); + final Collection warnings = cursorWithLimitedWarnings.getWarnings(); + assertThat(warnings).isNullOrEmpty(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void queryCursor(ArangoDatabase db) { + final int numbDocs = 10; + for (int i = 0; i < numbDocs; i++) { + db.collection(CNAME1).insertDocument(new BaseDocument(), null); + } + + final int batchSize = 5; + final ArangoCursor cursor = db.query("for i in " + CNAME1 + " return i._id", null, + new AqlQueryOptions().batchSize(batchSize).count(true), String.class); + assertThat((Object) cursor).isNotNull(); + assertThat(cursor.getCount()).isGreaterThanOrEqualTo(numbDocs); + + final ArangoCursor cursor2 = db.cursor(cursor.getId(), String.class); + assertThat((Object) cursor2).isNotNull(); + assertThat(cursor2.getCount()).isGreaterThanOrEqualTo(numbDocs); + assertThat((Iterator) cursor2).hasNext(); + + for (int i = 0; i < batchSize; i++, cursor.next()) { + assertThat((Iterator) cursor).hasNext(); + } + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void changeQueryTrackingProperties(ArangoDatabase db) { + try { + QueryTrackingPropertiesEntity properties = db.getQueryTrackingProperties(); + assertThat(properties).isNotNull(); + assertThat(properties.getEnabled()).isTrue(); + assertThat(properties.getTrackSlowQueries()).isTrue(); + assertThat(properties.getMaxQueryStringLength()).isPositive(); + assertThat(properties.getMaxSlowQueries()).isPositive(); + assertThat(properties.getSlowQueryThreshold()).isPositive(); + properties.setEnabled(false); + properties = db.setQueryTrackingProperties(properties); + assertThat(properties).isNotNull(); + assertThat(properties.getEnabled()).isFalse(); + properties = db.getQueryTrackingProperties(); + assertThat(properties.getEnabled()).isFalse(); + } finally { + final QueryTrackingPropertiesEntity properties = new QueryTrackingPropertiesEntity(); + properties.setEnabled(true); + db.setQueryTrackingProperties(properties); + } + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void queryWithBindVars(ArangoDatabase db) { + for (int i = 0; i < 10; i++) { + final BaseDocument baseDocument = new BaseDocument(UUID.randomUUID().toString()); + baseDocument.addAttribute("age", 20 + i); + db.collection(CNAME1).insertDocument(baseDocument, null); + } + final Map bindVars = new HashMap<>(); + bindVars.put("@coll", CNAME1); + bindVars.put("age", 25); + + final ArangoCursor cursor = db + .query("FOR t IN @@coll FILTER t.age >= @age SORT t.age RETURN t._id", bindVars, null, + String.class); + + assertThat((Object) cursor).isNotNull(); + + for (int i = 0; i < 5; i++, cursor.next()) { + assertThat((Iterator) cursor).hasNext(); + } + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void queryWithRawBindVars(ArangoDatabase db) { + final Map bindVars = new HashMap<>(); + bindVars.put("foo", RawJson.of("\"fooValue\"")); + bindVars.put("bar", RawBytes.of(db.getSerde().serializeUserData(11))); + + final JsonNode res = db.query("RETURN {foo: @foo, bar: @bar}", bindVars, null, JsonNode.class).next(); + + assertThat(res.get("foo").textValue()).isEqualTo("fooValue"); + assertThat(res.get("bar").intValue()).isEqualTo(11); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("arangos") + void queryWithWarning(ArangoDB arangoDB) { + final ArangoCursor cursor = arangoDB.db().query("return 1/0", null, null, String.class); + + assertThat((Object) cursor).isNotNull(); + assertThat(cursor.getWarnings()).isNotNull(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void queryStream(ArangoDatabase db) { + if (isAtLeastVersion(3, 4)) { + final ArangoCursor cursor = db + .query("FOR i IN 1..2 RETURN i", null, new AqlQueryOptions().stream(true).count(true), + Void.class); + assertThat((Object) cursor).isNotNull(); + assertThat(cursor.getCount()).isNull(); + } + } + + @ParameterizedTest(name = "{index}") + @MethodSource("arangos") + void queryClose(ArangoDB arangoDB) throws IOException { + final ArangoCursor cursor = arangoDB.db() + .query("for i in 1..2 return i", null, new AqlQueryOptions().batchSize(1), String.class); + cursor.close(); + AtomicInteger count = new AtomicInteger(); + Throwable thrown = catchThrowable(() -> { + while (cursor.hasNext()) { + cursor.next(); + count.incrementAndGet(); + } + }); + + assertThat(thrown).isInstanceOf(ArangoDBException.class); + assertThat(count).hasValue(1); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void queryNoResults(ArangoDatabase db) throws IOException { + final ArangoCursor cursor = db + .query("FOR i IN @@col RETURN i", new MapBuilder().put("@col", CNAME1).get(), null, + BaseDocument.class); + cursor.close(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void queryWithNullBindParam(ArangoDatabase db) throws IOException { + final ArangoCursor cursor = db.query("FOR i IN @@col FILTER i.test == @test RETURN i", + new MapBuilder().put("@col", CNAME1).put("test", null).get(), null, BaseDocument.class); + cursor.close(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void queryAllowDirtyRead(ArangoDatabase db) throws IOException { + final ArangoCursor cursor = db.query("FOR i IN @@col FILTER i.test == @test RETURN i", + new MapBuilder().put("@col", CNAME1).put("test", null).get(), + new AqlQueryOptions().allowDirtyRead(true), BaseDocument.class); + if (isAtLeastVersion(3, 10)) { + assertThat(cursor.isPotentialDirtyRead()).isTrue(); + } + cursor.close(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void explainQuery(ArangoDatabase db) { + final AqlExecutionExplainEntity explain = db.explainQuery("for i in 1..1 return i", null, null); + assertThat(explain).isNotNull(); + assertThat(explain.getPlan()).isNotNull(); + assertThat(explain.getPlans()).isNull(); + final ExecutionPlan plan = explain.getPlan(); + assertThat(plan.getCollections()).isEmpty(); + assertThat(plan.getEstimatedCost()).isPositive(); + assertThat(plan.getEstimatedNrItems()).isPositive(); + assertThat(plan.getVariables()).hasSize(2); + assertThat(plan.getNodes()).isNotEmpty(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void explainQueryWithBindVars(ArangoDatabase db) { + final AqlExecutionExplainEntity explain = db.explainQuery("for i in 1..1 return @value", + Collections.singletonMap("value", 11), null); + assertThat(explain).isNotNull(); + assertThat(explain.getPlan()).isNotNull(); + assertThat(explain.getPlans()).isNull(); + final ExecutionPlan plan = explain.getPlan(); + assertThat(plan.getCollections()).isEmpty(); + assertThat(plan.getEstimatedCost()).isPositive(); + assertThat(plan.getEstimatedNrItems()).isPositive(); + assertThat(plan.getVariables()).hasSize(3); + assertThat(plan.getNodes()).isNotEmpty(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void explainQueryWithIndexNode(ArangoDatabase db) { + ArangoCollection character = db.collection("got_characters"); + ArangoCollection actor = db.collection("got_actors"); + + if (!character.exists()) + character.create(); + + if (!actor.exists()) + actor.create(); + + String query = "" + + "FOR `character` IN `got_characters` " + + " FOR `actor` IN `got_actors` " + + " FILTER `character`.`actor` == `actor`.`_id` " + + " RETURN `character`"; + + final ExecutionPlan plan = db.explainQuery(query, null, null).getPlan(); + plan.getNodes().stream() + .filter(it -> "IndexNode".equals(it.getType())) + .flatMap(it -> it.getIndexes().stream()) + .forEach(it -> { + assertThat(it.getType()).isEqualTo(IndexType.primary); + assertThat(it.getFields()).contains("_key"); + }); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void parseQuery(ArangoDatabase db) { + final AqlParseEntity parse = db.parseQuery("for i in 1..1 return i"); + assertThat(parse).isNotNull(); + assertThat(parse.getBindVars()).isEmpty(); + assertThat(parse.getCollections()).isEmpty(); + assertThat(parse.getAst()).hasSize(1); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void getCurrentlyRunningQueries(ArangoDatabase db) throws InterruptedException { + String query = "return sleep(1)"; + Thread t = new Thread(() -> db.query(query, null, null, Void.class)); + t.start(); + Thread.sleep(300); + final Collection currentlyRunningQueries = db.getCurrentlyRunningQueries(); + assertThat(currentlyRunningQueries).hasSize(1); + final QueryEntity queryEntity = currentlyRunningQueries.iterator().next(); + assertThat(queryEntity.getQuery()).isEqualTo(query); + assertThat(queryEntity.getState()).isEqualTo(QueryExecutionState.EXECUTING); + t.join(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void killQuery(ArangoDatabase db) throws InterruptedException, ExecutionException { + ExecutorService es = Executors.newSingleThreadExecutor(); + Future future = es.submit(() -> { + try { + db.query("return sleep(5)", null, null, Void.class); + fail(); + } catch (ArangoDBException e) { + assertThat(e.getResponseCode()).isEqualTo(410); + assertThat(e.getErrorNum()).isEqualTo(1500); + assertThat(e.getErrorMessage()).contains("query killed"); + } + }); + Thread.sleep(500); + + Collection currentlyRunningQueries = db.getCurrentlyRunningQueries(); + assertThat(currentlyRunningQueries).hasSize(1); + QueryEntity queryEntity = currentlyRunningQueries.iterator().next(); + assertThat(queryEntity.getState()).isEqualTo(QueryExecutionState.EXECUTING); + db.killQuery(queryEntity.getId()); + + db.getCurrentlyRunningQueries().forEach(q -> + assertThat(q.getState()).isEqualTo(QueryExecutionState.KILLED) + ); + + future.get(); + es.shutdown(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void getAndClearSlowQueries(ArangoDatabase db) { + db.clearSlowQueries(); + + final QueryTrackingPropertiesEntity properties = db.getQueryTrackingProperties(); + final Long slowQueryThreshold = properties.getSlowQueryThreshold(); + properties.setSlowQueryThreshold(1L); + db.setQueryTrackingProperties(properties); + + db.query("return sleep(1.1)", null, null, Void.class); + final Collection slowQueries = db.getSlowQueries(); + assertThat(slowQueries).hasSize(1); + final QueryEntity queryEntity = slowQueries.iterator().next(); + assertThat(queryEntity.getQuery()).isEqualTo("return sleep(1.1)"); + + db.clearSlowQueries(); + assertThat(db.getSlowQueries()).isEmpty(); + properties.setSlowQueryThreshold(slowQueryThreshold); + db.setQueryTrackingProperties(properties); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void createGetDeleteAqlFunction(ArangoDatabase db) { + final Collection aqlFunctionsInitial = db.getAqlFunctions(null); + assertThat(aqlFunctionsInitial).isEmpty(); + try { + db.createAqlFunction("myfunctions::temperature::celsiustofahrenheit", + "function (celsius) { return celsius * 1.8 + 32; }", null); + + final Collection aqlFunctions = db.getAqlFunctions(null); + assertThat(aqlFunctions).hasSizeGreaterThan(aqlFunctionsInitial.size()); + } finally { + final Integer deleteCount = db.deleteAqlFunction("myfunctions::temperature::celsiustofahrenheit", null); + // compatibility with ArangoDB < 3.4 + if (isAtLeastVersion(3, 4)) { + assertThat(deleteCount).isEqualTo(1); + } else { + assertThat(deleteCount).isNull(); + } + final Collection aqlFunctions = db.getAqlFunctions(null); + assertThat(aqlFunctions).hasSize(aqlFunctionsInitial.size()); + } + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void createGetDeleteAqlFunctionWithNamespace(ArangoDatabase db) { + final Collection aqlFunctionsInitial = db.getAqlFunctions(null); + assertThat(aqlFunctionsInitial).isEmpty(); + try { + db.createAqlFunction("myfunctions::temperature::celsiustofahrenheit1", + "function (celsius) { return celsius * 1.8 + 32; }", null); + db.createAqlFunction("myfunctions::temperature::celsiustofahrenheit2", + "function (celsius) { return celsius * 1.8 + 32; }", null); + + } finally { + final Integer deleteCount = db + .deleteAqlFunction("myfunctions::temperature", new AqlFunctionDeleteOptions().group(true)); + // compatibility with ArangoDB < 3.4 + if (isAtLeastVersion(3, 4)) { + assertThat(deleteCount).isEqualTo(2); + } else { + assertThat(deleteCount).isNull(); + } + final Collection aqlFunctions = db.getAqlFunctions(null); + assertThat(aqlFunctions).hasSize(aqlFunctionsInitial.size()); + } + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void createGraph(ArangoDatabase db) { + String name = "graph-" + rnd(); + final GraphEntity result = db.createGraph(name, null, null); + assertThat(result.getName()).isEqualTo(name); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void createGraphSatellite(ArangoDatabase db) { + assumeTrue(isAtLeastVersion(3, 7)); + assumeTrue(isCluster()); + assumeTrue(isEnterprise()); + + String name = "graph-" + rnd(); + final GraphEntity result = db.createGraph(name, null, new GraphCreateOptions().replicationFactor(ReplicationFactor.ofSatellite())); + assertThat(result.getReplicationFactor()).isEqualTo(ReplicationFactor.ofSatellite()); + + GraphEntity info = db.graph(name).getInfo(); + assertThat(info.getReplicationFactor()).isEqualTo(ReplicationFactor.ofSatellite()); + + GraphEntity graph = db.getGraphs().stream().filter(g -> name.equals(g.getName())).findFirst().get(); + assertThat(graph.getReplicationFactor()).isEqualTo(ReplicationFactor.ofSatellite()); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void createGraphReplicationFaktor(ArangoDatabase db) { + assumeTrue(isCluster()); + String name = "graph-" + rnd(); + final String edgeCollection = "edge-" + rnd(); + final String fromCollection = "from-" + rnd(); + final String toCollection = "to-" + rnd(); + final Collection edgeDefinitions = + Collections.singletonList(new EdgeDefinition().collection(edgeCollection).from(fromCollection).to(toCollection)); + final GraphEntity result = db.createGraph(name, edgeDefinitions, new GraphCreateOptions().replicationFactor(2)); + assertThat(result).isNotNull(); + for (final String collection : Arrays.asList(edgeCollection, fromCollection, toCollection)) { + final CollectionPropertiesEntity properties = db.collection(collection).getProperties(); + assertThat(properties.getReplicationFactor().getValue()).isEqualTo(2); + } + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void createGraphNumberOfShards(ArangoDatabase db) { + assumeTrue(isCluster()); + String name = "graph-" + rnd(); + final String edgeCollection = "edge-" + rnd(); + final String fromCollection = "from-" + rnd(); + final String toCollection = "to-" + rnd(); + final Collection edgeDefinitions = + Collections.singletonList(new EdgeDefinition().collection(edgeCollection).from(fromCollection).to(toCollection)); + final GraphEntity result = db + .createGraph(name, edgeDefinitions, new GraphCreateOptions().numberOfShards(2)); + assertThat(result).isNotNull(); + for (final String collection : Arrays.asList(edgeCollection, fromCollection, toCollection)) { + final CollectionPropertiesEntity properties = db.collection(collection).getProperties(); + assertThat(properties.getNumberOfShards()).isEqualTo(2); + } + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void getGraphs(ArangoDatabase db) { + String name = "graph-" + rnd(); + db.createGraph(name, null, null); + final Collection graphs = db.getGraphs(); + assertThat(graphs).hasSizeGreaterThanOrEqualTo(1); + long count = graphs.stream().map(GraphEntity::getName).filter(name::equals).count(); + assertThat(count).isEqualTo(1L); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void transactionString(ArangoDatabase db) { + final TransactionOptions options = new TransactionOptions().params("test"); + final RawJson result = db.transaction("function (params) {return params;}", RawJson.class, options); + assertThat(result.getValue()).isEqualTo("\"test\""); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void transactionNumber(ArangoDatabase db) { + final TransactionOptions options = new TransactionOptions().params(5); + final Integer result = db.transaction("function (params) {return params;}", Integer.class, options); + assertThat(result).isEqualTo(5); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void transactionVPack(ArangoDatabase db) { + final TransactionOptions options = new TransactionOptions().params(JsonNodeFactory.instance.textNode("test")); + final JsonNode result = db.transaction("function (params) {return params;}", JsonNode.class, options); + assertThat(result.isTextual()).isTrue(); + assertThat(result.asText()).isEqualTo("test"); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void transactionJsonObject(ArangoDatabase db) { + ObjectNode params = JsonNodeFactory.instance.objectNode().put("foo", "hello").put("bar", "world"); + final TransactionOptions options = new TransactionOptions().params(params); + final RawJson result = db + .transaction("function (params) { return params['foo'] + ' ' + params['bar'];}", RawJson.class, + options); + assertThat(result.getValue()).isEqualTo("\"hello world\""); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void transactionJsonArray(ArangoDatabase db) { + ArrayNode params = JsonNodeFactory.instance.arrayNode().add("hello").add("world"); + final TransactionOptions options = new TransactionOptions().params(params); + final RawJson result = db + .transaction("function (params) { return params[0] + ' ' + params[1];}", RawJson.class, options); + assertThat(result.getValue()).isEqualTo("\"hello world\""); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void transactionMap(ArangoDatabase db) { + final Map params = new MapBuilder().put("foo", "hello").put("bar", "world").get(); + final TransactionOptions options = new TransactionOptions().params(params); + final RawJson result = db + .transaction("function (params) { return params['foo'] + ' ' + params['bar'];}", RawJson.class, + options); + assertThat(result.getValue()).isEqualTo("\"hello world\""); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void transactionArray(ArangoDatabase db) { + final String[] params = new String[]{"hello", "world"}; + final TransactionOptions options = new TransactionOptions().params(params); + final RawJson result = db + .transaction("function (params) { return params[0] + ' ' + params[1];}", RawJson.class, options); + assertThat(result.getValue()).isEqualTo("\"hello world\""); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void transactionCollection(ArangoDatabase db) { + final Collection params = new ArrayList<>(); + params.add("hello"); + params.add("world"); + final TransactionOptions options = new TransactionOptions().params(params); + final RawJson result = db + .transaction("function (params) { return params[0] + ' ' + params[1];}", RawJson.class, options); + assertThat(result.getValue()).isEqualTo("\"hello world\""); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void transactionInsertJson(ArangoDatabase db) { + String key = "key-" + rnd(); + final TransactionOptions options = new TransactionOptions().params("{\"_key\":\"" + key + "\"}") + .writeCollections(CNAME1); + db.transaction("function (params) { " + + "var db = require('internal').db;" + + "db." + CNAME1 + ".save(JSON.parse(params));" + + "}", Void.class, options); + assertThat(db.collection(CNAME1).getDocument(key, RawJson.class)).isNotNull(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void transactionExclusiveWrite(ArangoDatabase db) { + assumeTrue(isAtLeastVersion(3, 4)); + String key = "key-" + rnd(); + final TransactionOptions options = new TransactionOptions().params("{\"_key\":\"" + key + "\"}") + .exclusiveCollections(CNAME1); + db.transaction("function (params) { " + + "var db = require('internal').db;" + + "db." + CNAME1 + ".save(JSON.parse(params));" + + "}", Void.class, options); + assertThat(db.collection(CNAME1).getDocument(key, RawJson.class)).isNotNull(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void transactionEmpty(ArangoDatabase db) { + db.transaction("function () {}", Void.class, null); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void transactionAllowImplicit(ArangoDatabase db) { + final String action = "function (params) {" + "var db = require('internal').db;" + + "return {'a':db." + CNAME1 + ".all().toArray()[0], 'b':db." + CNAME2 + ".all().toArray()[0]};" + + "}"; + final TransactionOptions options = new TransactionOptions().readCollections(CNAME1); + db.transaction(action, JsonNode.class, options); + options.allowImplicit(false); + Throwable thrown = catchThrowable(() -> db.transaction(action, JsonNode.class, options)); + assertThat(thrown) + .isInstanceOf(ArangoDBException.class) + .extracting(it -> ((ArangoDBException) it).getResponseCode()) + .isEqualTo(400); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void transactionPojoReturn(ArangoDatabase db) { + final String action = "function() { return {'value':'hello world'}; }"; + final TransactionTestEntity res = db.transaction(action, TransactionTestEntity.class, new TransactionOptions()); + assertThat(res).isNotNull(); + assertThat(res.value).isEqualTo("hello world"); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void getInfo(ArangoDatabase db) { + final DatabaseEntity info = db.getInfo(); + assertThat(info).isNotNull(); + assertThat(info.getId()).isNotNull(); + assertThat(info.getName()).isEqualTo(TEST_DB.get()); + assertThat(info.getPath()).isNotNull(); + assertThat(info.getIsSystem()).isFalse(); + + if (isAtLeastVersion(3, 6) && isCluster()) { + assertThat(info.getSharding()).isNotNull(); + assertThat(info.getWriteConcern()).isNotNull(); + assertThat(info.getReplicationFactor()).isNotNull(); + } + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void getDocument(ArangoDatabase db) { + String key = "key-" + rnd(); + final BaseDocument value = new BaseDocument(key); + db.collection(CNAME1).insertDocument(value); + final BaseDocument document = db.getDocument(CNAME1 + "/" + key, BaseDocument.class); + assertThat(document).isNotNull(); + assertThat(document.getKey()).isEqualTo(key); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void shouldIncludeExceptionMessage(ArangoDatabase db) { + assumeTrue(isAtLeastVersion(3, 4)); + + final String exceptionMessage = "My error context"; + final String action = "function (params) {" + "throw '" + exceptionMessage + "';" + "}"; + try { + db.transaction(action, Void.class, null); + fail(); + } catch (final ArangoDBException e) { + assertThat(e.getErrorMessage()).isEqualTo(exceptionMessage); + } + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void getDocumentWrongId(ArangoDatabase db) { + Throwable thrown = catchThrowable(() -> db.getDocument("123", BaseDocument.class)); + assertThat(thrown).isInstanceOf(ArangoDBException.class); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void reloadRouting(ArangoDatabase db) { + db.reloadRouting(); + } + + public static class TransactionTestEntity { + private String value; + + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } + } +} diff --git a/shaded-integration-tests/src/test/jackson/java/com/arangodb/ArangoDocumentUtilTest.java b/shaded-integration-tests/src/test/jackson/java/com/arangodb/ArangoDocumentUtilTest.java new file mode 100644 index 000000000..224aea3cc --- /dev/null +++ b/shaded-integration-tests/src/test/jackson/java/com/arangodb/ArangoDocumentUtilTest.java @@ -0,0 +1,84 @@ +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed 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. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb; + +import com.arangodb.internal.util.DocumentUtil; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.catchThrowable; + +/** + * @author Mark Vollmary + * @author Michele Rastelli + */ +class ArangoDocumentUtilTest { + + @Test + void validateDocumentKeyValid() { + checkDocumentKey("1test"); + checkDocumentKey("test1"); + checkDocumentKey("test-1"); + checkDocumentKey("test_1"); + checkDocumentKey("_test"); + } + + @Test + void validateDocumentKeyInvalidSlash() { + Throwable thrown = catchThrowable(() -> checkDocumentKey("test/test")); + assertThat(thrown).isInstanceOf(ArangoDBException.class); + } + + @Test + void validateDocumentKeyEmpty() { + Throwable thrown = catchThrowable(() -> checkDocumentKey("")); + assertThat(thrown).isInstanceOf(ArangoDBException.class); + } + + private void checkDocumentKey(final String key) throws ArangoDBException { + DocumentUtil.validateDocumentKey(key); + } + + @Test + void validateDocumentIdValid() { + checkDocumentId("1test/1test"); + checkDocumentId("test1/test1"); + checkDocumentId("test-1/test-1"); + checkDocumentId("test_1/test_1"); + checkDocumentId("_test/_test"); + } + + @Test + void validateDocumentIdInvalidWithoutSlash() { + Throwable thrown = catchThrowable(() -> checkDocumentId("test")); + assertThat(thrown).isInstanceOf(ArangoDBException.class); + } + + @Test + void validateDocumentIdEmpty() { + Throwable thrown = catchThrowable(() -> checkDocumentId("")); + assertThat(thrown).isInstanceOf(ArangoDBException.class); + } + + private void checkDocumentId(final String id) throws ArangoDBException { + DocumentUtil.validateDocumentId(id); + } +} diff --git a/shaded-integration-tests/src/test/jackson/java/com/arangodb/ArangoEdgeCollectionTest.java b/shaded-integration-tests/src/test/jackson/java/com/arangodb/ArangoEdgeCollectionTest.java new file mode 100644 index 000000000..d25ed0e69 --- /dev/null +++ b/shaded-integration-tests/src/test/jackson/java/com/arangodb/ArangoEdgeCollectionTest.java @@ -0,0 +1,445 @@ +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed 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. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb; + +import com.arangodb.entity.*; +import com.arangodb.model.*; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +import java.util.Arrays; +import java.util.Collections; +import java.util.UUID; +import java.util.stream.Stream; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.catchThrowable; + + +/** + * @author Mark Vollmary + * @author Michele Rastelli + */ +class ArangoEdgeCollectionTest extends BaseJunit5 { + + private static final String GRAPH_NAME = "EdgeCollectionTest_graph"; + private static final String VERTEX_COLLECTION_NAME = "EdgeCollectionTest_vertex_collection"; + private static final String EDGE_COLLECTION_NAME = "EdgeCollectionTest_edge_collection"; + + private static Stream args() { + return dbsStream() + .map(db -> new Object[]{ + db.graph(GRAPH_NAME).vertexCollection(VERTEX_COLLECTION_NAME), + db.graph(GRAPH_NAME).edgeCollection(EDGE_COLLECTION_NAME) + }) + .map(Arguments::of); + } + + @BeforeAll + static void init() { + initCollections(VERTEX_COLLECTION_NAME); + initEdgeCollections(EDGE_COLLECTION_NAME); + initGraph( + GRAPH_NAME, + Collections.singletonList(new EdgeDefinition() + .collection(EDGE_COLLECTION_NAME) + .from(VERTEX_COLLECTION_NAME) + .to(VERTEX_COLLECTION_NAME) + ), + null + ); + } + + private BaseEdgeDocument createEdgeValue(ArangoVertexCollection vertices) { + final VertexEntity v1 = vertices.insertVertex(new BaseDocument()); + final VertexEntity v2 = vertices.insertVertex(new BaseDocument()); + + final BaseEdgeDocument value = new BaseEdgeDocument(); + value.setFrom(v1.getId()); + value.setTo(v2.getId()); + return value; + } + + @ParameterizedTest(name = "{index}") + @MethodSource("args") + void insertEdge(ArangoVertexCollection vertices, ArangoEdgeCollection edges) { + final BaseEdgeDocument value = createEdgeValue(vertices); + final EdgeEntity edge = edges.insertEdge(value); + assertThat(edge).isNotNull(); + final BaseEdgeDocument document = edges.getEdge(edge.getKey(), BaseEdgeDocument.class); + assertThat(document).isNotNull(); + assertThat(document.getKey()).isEqualTo(edge.getKey()); + assertThat(document.getFrom()).isNotNull(); + assertThat(document.getTo()).isNotNull(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("args") + void insertEdgeUpdateRev(ArangoVertexCollection vertices, ArangoEdgeCollection edges) { + final BaseEdgeDocument value = createEdgeValue(vertices); + final EdgeEntity edge = edges.insertEdge(value); + assertThat(value.getRevision()).isNull(); + assertThat(edge.getRev()).isNotNull(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("args") + void insertEdgeViolatingUniqueConstraint(ArangoVertexCollection vertices, ArangoEdgeCollection edges) { + edges.graph().db().collection(EDGE_COLLECTION_NAME) + .ensurePersistentIndex(Arrays.asList("_from", "_to"), new PersistentIndexOptions().unique(true)); + + BaseEdgeDocument edge = createEdgeValue(vertices); + edges.insertEdge(edge); + + try { + edges.insertEdge(edge); + } catch (ArangoDBException e) { + assertThat(e.getResponseCode()).isEqualTo(409); + assertThat(e.getErrorNum()).isEqualTo(1210); + } + } + + @ParameterizedTest(name = "{index}") + @MethodSource("args") + void getEdge(ArangoVertexCollection vertices, ArangoEdgeCollection edges) { + final BaseEdgeDocument value = createEdgeValue(vertices); + final EdgeEntity edge = edges.insertEdge(value); + final BaseEdgeDocument document = edges + .getEdge(edge.getKey(), BaseEdgeDocument.class); + assertThat(document).isNotNull(); + assertThat(document.getKey()).isEqualTo(edge.getKey()); + assertThat(document.getFrom()).isNotNull(); + assertThat(document.getTo()).isNotNull(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("args") + void getEdgeIfMatch(ArangoVertexCollection vertices, ArangoEdgeCollection edges) { + final BaseEdgeDocument value = createEdgeValue(vertices); + final EdgeEntity edge = edges.insertEdge(value); + final GraphDocumentReadOptions options = new GraphDocumentReadOptions().ifMatch(edge.getRev()); + final BaseDocument document = edges.getEdge(edge.getKey(), + BaseDocument.class, options); + assertThat(document).isNotNull(); + assertThat(document.getKey()).isEqualTo(edge.getKey()); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("args") + void getEdgeIfMatchFail(ArangoVertexCollection vertices, ArangoEdgeCollection edges) { + final BaseEdgeDocument value = createEdgeValue(vertices); + final EdgeEntity edge = edges.insertEdge(value); + final GraphDocumentReadOptions options = new GraphDocumentReadOptions().ifMatch("no"); + final BaseEdgeDocument edge2 = edges.getEdge(edge.getKey(), + BaseEdgeDocument.class, options); + assertThat(edge2).isNull(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("args") + void getEdgeIfNoneMatch(ArangoVertexCollection vertices, ArangoEdgeCollection edges) { + final BaseEdgeDocument value = createEdgeValue(vertices); + final EdgeEntity edge = edges.insertEdge(value); + final GraphDocumentReadOptions options = new GraphDocumentReadOptions().ifNoneMatch("no"); + final BaseDocument document = edges.getEdge(edge.getKey(), + BaseDocument.class, options); + assertThat(document).isNotNull(); + assertThat(document.getKey()).isEqualTo(edge.getKey()); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("args") + void getEdgeIfNoneMatchFail(ArangoVertexCollection vertices, ArangoEdgeCollection edges) { + final BaseEdgeDocument value = createEdgeValue(vertices); + final EdgeEntity edge = edges.insertEdge(value); + final GraphDocumentReadOptions options = new GraphDocumentReadOptions().ifNoneMatch(edge.getRev()); + final BaseEdgeDocument edge2 = edges.getEdge(edge.getKey(), + BaseEdgeDocument.class, options); + assertThat(edge2).isNull(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("args") + void replaceEdge(ArangoVertexCollection vertices, ArangoEdgeCollection edges) { + final BaseEdgeDocument doc = createEdgeValue(vertices); + doc.addAttribute("a", "test"); + final EdgeEntity createResult = edges.insertEdge(doc); + doc.removeAttribute("a"); + doc.addAttribute("b", "test"); + final EdgeUpdateEntity replaceResult = edges + .replaceEdge(createResult.getKey(), doc); + assertThat(replaceResult).isNotNull(); + assertThat(replaceResult.getId()).isEqualTo(createResult.getId()); + assertThat(replaceResult.getRev()).isNotEqualTo(replaceResult.getOldRev()); + assertThat(replaceResult.getOldRev()).isEqualTo(createResult.getRev()); + + final BaseEdgeDocument readResult = edges + .getEdge(createResult.getKey(), BaseEdgeDocument.class); + assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); + assertThat(readResult.getRevision()).isEqualTo(replaceResult.getRev()); + assertThat(readResult.getProperties().keySet()).doesNotContain("a"); + assertThat(readResult.getAttribute("b")).isNotNull(); + assertThat(String.valueOf(readResult.getAttribute("b"))).isEqualTo("test"); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("args") + void replaceEdgeUpdateRev(ArangoVertexCollection vertices, ArangoEdgeCollection edges) { + final BaseEdgeDocument doc = createEdgeValue(vertices); + final EdgeEntity createResult = edges.insertEdge(doc); + final EdgeUpdateEntity replaceResult = edges + .replaceEdge(createResult.getKey(), doc); + assertThat(doc.getRevision()).isNull(); + assertThat(createResult.getRev()).isNotNull(); + assertThat(replaceResult.getRev()) + .isNotNull() + .isNotEqualTo(createResult.getRev()); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("args") + void replaceEdgeIfMatch(ArangoVertexCollection vertices, ArangoEdgeCollection edges) { + final BaseEdgeDocument doc = createEdgeValue(vertices); + doc.addAttribute("a", "test"); + final EdgeEntity createResult = edges.insertEdge(doc); + doc.removeAttribute("a"); + doc.addAttribute("b", "test"); + final EdgeReplaceOptions options = new EdgeReplaceOptions().ifMatch(createResult.getRev()); + final EdgeUpdateEntity replaceResult = edges + .replaceEdge(createResult.getKey(), doc, options); + assertThat(replaceResult).isNotNull(); + assertThat(replaceResult.getId()).isEqualTo(createResult.getId()); + assertThat(replaceResult.getRev()).isNotEqualTo(replaceResult.getOldRev()); + assertThat(replaceResult.getOldRev()).isEqualTo(createResult.getRev()); + + final BaseEdgeDocument readResult = edges + .getEdge(createResult.getKey(), BaseEdgeDocument.class); + assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); + assertThat(readResult.getRevision()).isEqualTo(replaceResult.getRev()); + assertThat(readResult.getProperties().keySet()).doesNotContain("a"); + assertThat(readResult.getAttribute("b")).isNotNull(); + assertThat(String.valueOf(readResult.getAttribute("b"))).isEqualTo("test"); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("args") + void replaceEdgeIfMatchFail(ArangoVertexCollection vertices, ArangoEdgeCollection edges) { + final BaseEdgeDocument doc = createEdgeValue(vertices); + doc.addAttribute("a", "test"); + final EdgeEntity createResult = edges.insertEdge(doc); + doc.removeAttribute("a"); + doc.addAttribute("b", "test"); + final EdgeReplaceOptions options = new EdgeReplaceOptions().ifMatch("no"); + Throwable thrown = catchThrowable(() -> edges.replaceEdge(createResult.getKey(), doc, options)); + assertThat(thrown).isInstanceOf(ArangoDBException.class); + ArangoDBException e = (ArangoDBException) thrown; + assertThat(e.getResponseCode()).isEqualTo(412); + assertThat(e.getErrorNum()).isEqualTo(1200); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("args") + void updateEdge(ArangoVertexCollection vertices, ArangoEdgeCollection edges) { + final BaseEdgeDocument doc = createEdgeValue(vertices); + doc.addAttribute("a", "test"); + doc.addAttribute("c", "test"); + final EdgeEntity createResult = edges.insertEdge(doc); + doc.updateAttribute("a", "test1"); + doc.addAttribute("b", "test"); + doc.updateAttribute("c", null); + final EdgeUpdateEntity updateResult = edges + .updateEdge(createResult.getKey(), doc); + assertThat(updateResult).isNotNull(); + assertThat(updateResult.getId()).isEqualTo(createResult.getId()); + assertThat(updateResult.getRev()).isNotEqualTo(updateResult.getOldRev()); + assertThat(updateResult.getOldRev()).isEqualTo(createResult.getRev()); + + final BaseEdgeDocument readResult = edges + .getEdge(createResult.getKey(), BaseEdgeDocument.class); + assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); + assertThat(readResult.getAttribute("a")).isNotNull(); + assertThat(String.valueOf(readResult.getAttribute("a"))).isEqualTo("test1"); + assertThat(readResult.getAttribute("b")).isNotNull(); + assertThat(String.valueOf(readResult.getAttribute("b"))).isEqualTo("test"); + assertThat(readResult.getRevision()).isEqualTo(updateResult.getRev()); + assertThat(readResult.getProperties()).containsKey("c"); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("args") + void updateEdgeUpdateRev(ArangoVertexCollection vertices, ArangoEdgeCollection edges) { + final BaseEdgeDocument doc = createEdgeValue(vertices); + final EdgeEntity createResult = edges.insertEdge(doc); + final EdgeUpdateEntity updateResult = edges + .updateEdge(createResult.getKey(), doc); + assertThat(doc.getRevision()).isNull(); + assertThat(createResult.getRev()).isNotNull(); + assertThat(updateResult.getRev()) + .isNotNull() + .isNotEqualTo(createResult.getRev()); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("args") + void updateEdgeIfMatch(ArangoVertexCollection vertices, ArangoEdgeCollection edges) { + final BaseEdgeDocument doc = createEdgeValue(vertices); + doc.addAttribute("a", "test"); + doc.addAttribute("c", "test"); + final EdgeEntity createResult = edges.insertEdge(doc); + doc.updateAttribute("a", "test1"); + doc.addAttribute("b", "test"); + doc.updateAttribute("c", null); + final EdgeUpdateOptions options = new EdgeUpdateOptions().ifMatch(createResult.getRev()); + final EdgeUpdateEntity updateResult = edges + .updateEdge(createResult.getKey(), doc, options); + assertThat(updateResult).isNotNull(); + assertThat(updateResult.getId()).isEqualTo(createResult.getId()); + assertThat(updateResult.getRev()).isNotEqualTo(updateResult.getOldRev()); + assertThat(updateResult.getOldRev()).isEqualTo(createResult.getRev()); + + final BaseEdgeDocument readResult = edges + .getEdge(createResult.getKey(), BaseEdgeDocument.class); + assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); + assertThat(readResult.getAttribute("a")).isNotNull(); + assertThat(String.valueOf(readResult.getAttribute("a"))).isEqualTo("test1"); + assertThat(readResult.getAttribute("b")).isNotNull(); + assertThat(String.valueOf(readResult.getAttribute("b"))).isEqualTo("test"); + assertThat(readResult.getRevision()).isEqualTo(updateResult.getRev()); + assertThat(readResult.getProperties()).containsKey("c"); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("args") + void updateEdgeIfMatchFail(ArangoVertexCollection vertices, ArangoEdgeCollection edges) { + final BaseEdgeDocument doc = createEdgeValue(vertices); + doc.addAttribute("a", "test"); + doc.addAttribute("c", "test"); + final EdgeEntity createResult = edges.insertEdge(doc); + doc.updateAttribute("a", "test1"); + doc.addAttribute("b", "test"); + doc.updateAttribute("c", null); + final EdgeUpdateOptions options = new EdgeUpdateOptions().ifMatch("no"); + Throwable thrown = catchThrowable(() -> edges.updateEdge(createResult.getKey(), doc, options)); + assertThat(thrown).isInstanceOf(ArangoDBException.class); + ArangoDBException e = (ArangoDBException) thrown; + assertThat(e.getResponseCode()).isEqualTo(412); + assertThat(e.getErrorNum()).isEqualTo(1200); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("args") + void updateEdgeKeepNullTrue(ArangoVertexCollection vertices, ArangoEdgeCollection edges) { + final BaseEdgeDocument doc = createEdgeValue(vertices); + doc.addAttribute("a", "test"); + final EdgeEntity createResult = edges.insertEdge(doc); + doc.updateAttribute("a", null); + final EdgeUpdateOptions options = new EdgeUpdateOptions().keepNull(true); + final EdgeUpdateEntity updateResult = edges + .updateEdge(createResult.getKey(), doc, options); + assertThat(updateResult).isNotNull(); + assertThat(updateResult.getId()).isEqualTo(createResult.getId()); + assertThat(updateResult.getRev()).isNotEqualTo(updateResult.getOldRev()); + assertThat(updateResult.getOldRev()).isEqualTo(createResult.getRev()); + + final BaseEdgeDocument readResult = edges + .getEdge(createResult.getKey(), BaseEdgeDocument.class); + assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); + assertThat(readResult.getProperties().keySet()).hasSize(6); + assertThat(readResult.getProperties()).containsKey("a"); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("args") + void updateEdgeKeepNullFalse(ArangoVertexCollection vertices, ArangoEdgeCollection edges) { + final BaseEdgeDocument doc = createEdgeValue(vertices); + doc.addAttribute("a", "test"); + final EdgeEntity createResult = edges.insertEdge(doc); + doc.updateAttribute("a", null); + final EdgeUpdateOptions options = new EdgeUpdateOptions().keepNull(false); + final EdgeUpdateEntity updateResult = edges + .updateEdge(createResult.getKey(), doc, options); + assertThat(updateResult).isNotNull(); + assertThat(updateResult.getId()).isEqualTo(createResult.getId()); + assertThat(updateResult.getRev()).isNotEqualTo(updateResult.getOldRev()); + assertThat(updateResult.getOldRev()).isEqualTo(createResult.getRev()); + + final BaseEdgeDocument readResult = edges + .getEdge(createResult.getKey(), BaseEdgeDocument.class); + assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); + assertThat(readResult.getId()).isEqualTo(createResult.getId()); + assertThat(readResult.getRevision()).isNotNull(); + assertThat(readResult.getProperties().keySet()).doesNotContain("a"); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("args") + void deleteEdge(ArangoVertexCollection vertices, ArangoEdgeCollection edges) { + final BaseEdgeDocument doc = createEdgeValue(vertices); + final EdgeEntity createResult = edges.insertEdge(doc); + edges.deleteEdge(createResult.getKey()); + final BaseEdgeDocument edge = edges + .getEdge(createResult.getKey(), BaseEdgeDocument.class); + assertThat(edge).isNull(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("args") + void deleteEdgeIfMatch(ArangoVertexCollection vertices, ArangoEdgeCollection edges) { + final BaseEdgeDocument doc = createEdgeValue(vertices); + final EdgeEntity createResult = edges.insertEdge(doc); + final EdgeDeleteOptions options = new EdgeDeleteOptions().ifMatch(createResult.getRev()); + edges.deleteEdge(createResult.getKey(), options); + final BaseEdgeDocument edge = edges + .getEdge(createResult.getKey(), BaseEdgeDocument.class); + assertThat(edge).isNull(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("args") + void deleteEdgeIfMatchFail(ArangoVertexCollection vertices, ArangoEdgeCollection edges) { + final BaseEdgeDocument doc = createEdgeValue(vertices); + final EdgeEntity createResult = edges.insertEdge(doc); + final EdgeDeleteOptions options = new EdgeDeleteOptions().ifMatch("no"); + Throwable thrown = catchThrowable(() -> edges.deleteEdge(createResult.getKey(), options)); + assertThat(thrown).isInstanceOf(ArangoDBException.class); + ArangoDBException e = (ArangoDBException) thrown; + assertThat(e.getResponseCode()).isEqualTo(412); + assertThat(e.getErrorNum()).isEqualTo(1200); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("args") + void edgeKeyWithSpecialChars(ArangoVertexCollection vertices, ArangoEdgeCollection edges) { + final BaseEdgeDocument value = createEdgeValue(vertices); + final String key = "_-:.@()+,=;$!*'%" + UUID.randomUUID(); + value.setKey(key); + final EdgeEntity edge = edges.insertEdge(value); + assertThat(edge).isNotNull(); + final BaseEdgeDocument document = edges.getEdge(edge.getKey(), BaseEdgeDocument.class); + assertThat(document).isNotNull(); + assertThat(document.getKey()).isEqualTo(key); + assertThat(document.getFrom()).isNotNull(); + assertThat(document.getTo()).isNotNull(); + } + +} diff --git a/shaded-integration-tests/src/test/jackson/java/com/arangodb/ArangoGraphTest.java b/shaded-integration-tests/src/test/jackson/java/com/arangodb/ArangoGraphTest.java new file mode 100644 index 000000000..73e56711c --- /dev/null +++ b/shaded-integration-tests/src/test/jackson/java/com/arangodb/ArangoGraphTest.java @@ -0,0 +1,438 @@ +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed 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. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb; + +import com.arangodb.entity.CollectionPropertiesEntity; +import com.arangodb.entity.EdgeDefinition; +import com.arangodb.entity.GraphEntity; +import com.arangodb.entity.ReplicationFactor; +import com.arangodb.model.GraphCreateOptions; +import com.arangodb.model.VertexCollectionCreateOptions; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +import java.util.*; +import java.util.stream.Stream; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assumptions.assumeTrue; + + +/** + * @author Mark Vollmary + * @author Michele Rastelli + */ +class ArangoGraphTest extends BaseJunit5 { + + private static final String GRAPH_NAME = "ArangoGraphTest_graph"; + + private static final String VERTEX_COL_1 = "ArangoGraphTest_vertex_collection_1"; + private static final String VERTEX_COL_2 = "ArangoGraphTest_vertex_collection_2"; + private static final String VERTEX_COL_3 = "ArangoGraphTest_vertex_collection_3"; + private static final String VERTEX_COL_4 = "ArangoGraphTest_vertex_collection_4"; + + private static final String EDGE_COL_1 = "ArangoGraphTest_edge_collection_1"; + private static final String EDGE_COL_2 = "ArangoGraphTest_edge_collection_2"; + private static final String EDGE_COL_3 = "ArangoGraphTest_edge_collection_3"; + + private static final Integer REPLICATION_FACTOR = 2; + private static final Integer NUMBER_OF_SHARDS = 2; + + private static final EdgeDefinition ed1 = + new EdgeDefinition().collection(EDGE_COL_1).from(VERTEX_COL_1).to(VERTEX_COL_2); + private static final EdgeDefinition ed2 = + new EdgeDefinition().collection(EDGE_COL_2).from(VERTEX_COL_2).to(VERTEX_COL_1, VERTEX_COL_3); + + private static Stream graphs() { + return dbsStream() + .map(db -> db.graph(GRAPH_NAME)) + .map(Arguments::of); + } + + @BeforeAll + static void init() { + final Collection edgeDefinitions = Arrays.asList(ed1, ed2); + + final GraphCreateOptions options = new GraphCreateOptions() + .replicationFactor(REPLICATION_FACTOR) + .numberOfShards(NUMBER_OF_SHARDS); + + initGraph(GRAPH_NAME, edgeDefinitions, options); + } + + + @ParameterizedTest(name = "{index}") + @MethodSource("graphs") + void exists(ArangoGraph graph) { + assertThat(graph.exists()).isTrue(); + assertThat(graph.db().graph(GRAPH_NAME + "no").exists()).isFalse(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void createWithReplicationAndWriteConcern(ArangoDatabase db) { + assumeTrue(isAtLeastVersion(3, 5)); + assumeTrue(isCluster()); + + final Collection edgeDefinitions = new ArrayList<>(); + final GraphEntity graph = db.createGraph(GRAPH_NAME + "_1", edgeDefinitions, + new GraphCreateOptions().isSmart(true).replicationFactor(2).writeConcern(2)); + assertThat(graph).isNotNull(); + assertThat(graph.getName()).isEqualTo(GRAPH_NAME + "_1"); + assertThat(graph.getWriteConcern()).isEqualTo(2); + assertThat(graph.getReplicationFactor().getValue()).isEqualTo(2); + db.graph(GRAPH_NAME + "_1").drop(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void getGraphs(ArangoDatabase db) { + final Collection graphs = db.getGraphs(); + assertThat(graphs.stream().anyMatch(it -> it.getName().equals(GRAPH_NAME))).isTrue(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("graphs") + void getInfo(ArangoGraph graph) { + final GraphEntity info = graph.getInfo(); + assertThat(info).isNotNull(); + assertThat(info.getName()).isEqualTo(GRAPH_NAME); + assertThat(info.getEdgeDefinitions()).hasSize(2); + final Iterator iterator = info.getEdgeDefinitions().iterator(); + final EdgeDefinition e1 = iterator.next(); + assertThat(e1.getCollection()).isEqualTo(EDGE_COL_1); + assertThat(e1.getFrom()).contains(VERTEX_COL_1); + assertThat(e1.getTo()).contains(VERTEX_COL_2); + final EdgeDefinition e2 = iterator.next(); + assertThat(e2.getCollection()).isEqualTo(EDGE_COL_2); + assertThat(e2.getFrom()).contains(VERTEX_COL_2); + assertThat(e2.getTo()).contains(VERTEX_COL_1, VERTEX_COL_3); + assertThat(info.getOrphanCollections()).isEmpty(); + + if (isCluster()) { + for (final String collection : new String[]{EDGE_COL_1, EDGE_COL_2, VERTEX_COL_1, VERTEX_COL_2}) { + final CollectionPropertiesEntity properties = graph.db().collection(collection).getProperties(); + assertThat(properties.getReplicationFactor().getValue()).isEqualTo(REPLICATION_FACTOR); + assertThat(properties.getNumberOfShards()).isEqualTo(NUMBER_OF_SHARDS); + } + } + } + + @ParameterizedTest(name = "{index}") + @MethodSource("graphs") + void getVertexCollections(ArangoGraph graph) { + final Collection vertexCollections = graph.getVertexCollections(); + assertThat(vertexCollections) + .hasSize(3) + .contains(VERTEX_COL_1, VERTEX_COL_2, VERTEX_COL_3); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("graphs") + void addVertexCollection(ArangoGraph graph) { + final GraphEntity g = graph.addVertexCollection(VERTEX_COL_4); + assertThat(g).isNotNull(); + final Collection vertexCollections = graph.getVertexCollections(); + assertThat(vertexCollections).contains(VERTEX_COL_1, VERTEX_COL_2, VERTEX_COL_3, VERTEX_COL_4); + + // revert + graph.vertexCollection(VERTEX_COL_4).drop(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void addSatelliteVertexCollection(ArangoDatabase db) { + assumeTrue(isCluster() || isAtLeastVersion(3, 10)); + assumeTrue(isEnterprise()); + assumeTrue(isAtLeastVersion(3, 9)); + + String v1Name = "vertex-" + rnd(); + + ArangoGraph g = db.graph(GRAPH_NAME + rnd()); + g.create(null, new GraphCreateOptions().isSmart(true).smartGraphAttribute("test")); + g.addVertexCollection(v1Name, new VertexCollectionCreateOptions().satellites(v1Name)); + + Collection vertexCollections = g.getVertexCollections(); + assertThat(vertexCollections).contains(v1Name); + assertThat(db.collection(v1Name).getProperties().getReplicationFactor()).isEqualTo(ReplicationFactor.ofSatellite()); + + // revert + g.drop(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("graphs") + void getEdgeCollections(ArangoGraph graph) { + final Collection edgeCollections = graph.getEdgeDefinitions(); + assertThat(edgeCollections) + .hasSize(2) + .contains(EDGE_COL_1, EDGE_COL_2); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("graphs") + void addEdgeDefinition(ArangoGraph graph) { + EdgeDefinition ed = new EdgeDefinition().collection(EDGE_COL_3).from(VERTEX_COL_1).to(VERTEX_COL_2); + final GraphEntity g = graph.addEdgeDefinition(ed); + assertThat(g).isNotNull(); + final Collection edgeDefinitions = g.getEdgeDefinitions(); + assertThat(edgeDefinitions).hasSize(3); + int count = 0; + for (final EdgeDefinition e : edgeDefinitions) { + if (e.getCollection().equals(EDGE_COL_3)) { + count++; + } + } + assertThat(count).isEqualTo(1); + for (final EdgeDefinition e : edgeDefinitions) { + if (e.getCollection().equals(EDGE_COL_3)) { + assertThat(e.getFrom()).contains(VERTEX_COL_1); + assertThat(e.getTo()).contains(VERTEX_COL_2); + } + } + if (isCluster()) { + final CollectionPropertiesEntity properties = graph.db().collection(EDGE_COL_3).getProperties(); + assertThat(properties.getReplicationFactor().getValue()).isEqualTo(REPLICATION_FACTOR); + assertThat(properties.getNumberOfShards()).isEqualTo(NUMBER_OF_SHARDS); + } + + // revert + graph.removeEdgeDefinition(EDGE_COL_3); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void addSatelliteEdgeDefinition(ArangoDatabase db) { + assumeTrue(isCluster() || isAtLeastVersion(3, 10)); + 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(null, new GraphCreateOptions().isSmart(true).smartGraphAttribute("test")); + g.addEdgeDefinition(ed); + final GraphEntity ge = g.getInfo(); + assertThat(ge).isNotNull(); + final Collection edgeDefinitions = ge.getEdgeDefinitions(); + assertThat(edgeDefinitions).hasSize(1); + EdgeDefinition e = edgeDefinitions.iterator().next(); + assertThat(e.getCollection()).isEqualTo(eName); + assertThat(e.getFrom()).contains(v1Name); + assertThat(e.getTo()).contains(v2Name); + + assertThat(db.collection(v1Name).getProperties().getReplicationFactor()).isEqualTo(ReplicationFactor.ofSatellite()); + + // revert + g.drop(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("graphs") + void replaceEdgeDefinition(ArangoGraph graph) { + final GraphEntity g = graph + .replaceEdgeDefinition(new EdgeDefinition().collection(EDGE_COL_1).from(VERTEX_COL_3).to(VERTEX_COL_4)); + final Collection edgeDefinitions = g.getEdgeDefinitions(); + assertThat(edgeDefinitions).hasSize(2); + int count = 0; + for (final EdgeDefinition e : edgeDefinitions) { + if (e.getCollection().equals(EDGE_COL_1)) { + count++; + } + } + assertThat(count).isEqualTo(1); + for (final EdgeDefinition e : edgeDefinitions) { + if (e.getCollection().equals(EDGE_COL_1)) { + assertThat(e.getFrom()).contains(VERTEX_COL_3); + assertThat(e.getTo()).contains(VERTEX_COL_4); + } + } + + // revert + graph.removeEdgeDefinition(EDGE_COL_1); + graph.vertexCollection(VERTEX_COL_4).drop(); + graph.addEdgeDefinition(ed1); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("graphs") + void removeEdgeDefinition(ArangoGraph graph) { + final GraphEntity g = graph.removeEdgeDefinition(EDGE_COL_1); + final Collection edgeDefinitions = g.getEdgeDefinitions(); + assertThat(edgeDefinitions).hasSize(1); + assertThat(edgeDefinitions.iterator().next().getCollection()).isEqualTo(EDGE_COL_2); + + //revert + graph.addEdgeDefinition(ed1); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void smartGraph(ArangoDatabase db) { + assumeTrue(isEnterprise()); + assumeTrue(isCluster() || isAtLeastVersion(3, 10)); + + final Collection edgeDefinitions = new ArrayList<>(); + edgeDefinitions.add(new EdgeDefinition().collection("smartGraph-edge-" + rnd()).from("smartGraph-vertex-" + rnd()).to("smartGraph-vertex-" + rnd())); + + String graphId = GRAPH_NAME + rnd(); + final GraphEntity g = db.createGraph(graphId, edgeDefinitions, + new GraphCreateOptions().isSmart(true).smartGraphAttribute("test").numberOfShards(2)); + + assertThat(g).isNotNull(); + assertThat(g.getIsSmart()).isTrue(); + assertThat(g.getSmartGraphAttribute()).isEqualTo("test"); + assertThat(g.getNumberOfShards()).isEqualTo(2); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void hybridSmartGraph(ArangoDatabase db) { + assumeTrue(isEnterprise()); + assumeTrue(isCluster() || isAtLeastVersion(3, 10)); + 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).isNotNull(); + assertThat(g.getIsSmart()).isTrue(); + assertThat(g.getSmartGraphAttribute()).isEqualTo("test"); + assertThat(g.getNumberOfShards()).isEqualTo(2); + + assertThat(db.collection(eName).getProperties().getReplicationFactor()).isEqualTo(ReplicationFactor.ofSatellite()); + assertThat(db.collection(v1Name).getProperties().getReplicationFactor()).isEqualTo(ReplicationFactor.ofSatellite()); + assertThat(db.collection(v2Name).getProperties().getReplicationFactor().getValue()).isEqualTo(2); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void disjointSmartGraph(ArangoDatabase db) { + assumeTrue(isEnterprise()); + assumeTrue(isCluster() || isAtLeastVersion(3, 10)); + assumeTrue((isAtLeastVersion(3, 7))); + + final Collection edgeDefinitions = new ArrayList<>(); + edgeDefinitions.add(new EdgeDefinition().collection("smartGraph-edge-" + rnd()).from("smartGraph-vertex-" + rnd()).to("smartGraph-vertex-" + rnd())); + + String graphId = GRAPH_NAME + rnd(); + final GraphEntity g = db.createGraph(graphId, edgeDefinitions, new GraphCreateOptions() + .isSmart(true).isDisjoint(true).smartGraphAttribute("test").numberOfShards(2)); + + assertThat(g).isNotNull(); + assertThat(g.getIsSmart()).isTrue(); + assertThat(g.getIsDisjoint()).isTrue(); + assertThat(g.getSmartGraphAttribute()).isEqualTo("test"); + assertThat(g.getNumberOfShards()).isEqualTo(2); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void hybridDisjointSmartGraph(ArangoDatabase db) { + assumeTrue(isEnterprise()); + assumeTrue(isCluster() || isAtLeastVersion(3, 10)); + 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).isNotNull(); + assertThat(g.getIsSmart()).isTrue(); + assertThat(g.getIsDisjoint()).isTrue(); + assertThat(g.getSmartGraphAttribute()).isEqualTo("test"); + assertThat(g.getNumberOfShards()).isEqualTo(2); + + assertThat(db.collection(v1Name).getProperties().getReplicationFactor()).isEqualTo(ReplicationFactor.ofSatellite()); + assertThat(db.collection(v2Name).getProperties().getReplicationFactor().getValue()).isEqualTo(2); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void enterpriseGraph(ArangoDatabase db) { + assumeTrue(isEnterprise()); + assumeTrue(isCluster() || isAtLeastVersion(3, 10)); + + final Collection edgeDefinitions = new ArrayList<>(); + edgeDefinitions.add(new EdgeDefinition().collection("enterpriseGraph-edge-" + rnd()).from("enterpriseGraph-vertex-" + rnd()).to("enterpriseGraph-vertex-" + rnd())); + + String graphId = GRAPH_NAME + rnd(); + final GraphEntity g = db.createGraph(graphId, edgeDefinitions, new GraphCreateOptions().isSmart(true).numberOfShards(2)); + + assertThat(g).isNotNull(); + assertThat(g.getSmartGraphAttribute()).isNull(); + assertThat(g.getNumberOfShards()).isEqualTo(2); + if (isAtLeastVersion(3, 10)) { + assertThat(g.getIsSmart()).isTrue(); + } else { + assertThat(g.getIsSmart()).isFalse(); + } + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void drop(ArangoDatabase db) { + final String edgeCollection = "edge_" + rnd(); + final String vertexCollection = "vertex_" + rnd(); + final String graphId = GRAPH_NAME + rnd(); + final GraphEntity result = db.graph(graphId).create(Collections + .singleton(new EdgeDefinition().collection(edgeCollection).from(vertexCollection).to(vertexCollection))); + assertThat(result).isNotNull(); + db.graph(graphId).drop(); + assertThat(db.collection(edgeCollection).exists()).isTrue(); + assertThat(db.collection(vertexCollection).exists()).isTrue(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void dropPlusDropCollections(ArangoDatabase db) { + final String edgeCollection = "edge_dropC" + rnd(); + final String vertexCollection = "vertex_dropC" + rnd(); + final String graphId = GRAPH_NAME + "_dropC" + rnd(); + final GraphEntity result = db.graph(graphId).create(Collections + .singleton(new EdgeDefinition().collection(edgeCollection).from(vertexCollection).to(vertexCollection))); + assertThat(result).isNotNull(); + db.graph(graphId).drop(true); + assertThat(db.collection(edgeCollection).exists()).isFalse(); + assertThat(db.collection(vertexCollection).exists()).isFalse(); + } + +} diff --git a/shaded-integration-tests/src/test/jackson/java/com/arangodb/ArangoSearchTest.java b/shaded-integration-tests/src/test/jackson/java/com/arangodb/ArangoSearchTest.java new file mode 100644 index 000000000..deaecc588 --- /dev/null +++ b/shaded-integration-tests/src/test/jackson/java/com/arangodb/ArangoSearchTest.java @@ -0,0 +1,1010 @@ +/* + * DISCLAIMER + * + * Copyright 2018 ArangoDB GmbH, Cologne, Germany + * + * Licensed 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. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb; + +import com.arangodb.entity.InvertedIndexField; +import com.arangodb.entity.ViewEntity; +import com.arangodb.entity.ViewType; +import com.arangodb.entity.arangosearch.*; +import com.arangodb.entity.arangosearch.analyzer.*; +import com.arangodb.model.InvertedIndexOptions; +import com.arangodb.model.arangosearch.*; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + +import java.util.*; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.catchThrowable; +import static org.junit.jupiter.api.Assumptions.assumeTrue; + +/** + * @author Mark Vollmary + * @author Michele Rastelli + */ +class ArangoSearchTest extends BaseJunit5 { + + private static final String COLL_1 = "ArangoSearchTest_view_replace_prop"; + private static final String COLL_2 = "ArangoSearchTest_view_update_prop"; + + @BeforeAll + static void init() { + initCollections(COLL_1, COLL_2); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void exists(ArangoDatabase db) { + assumeTrue(isAtLeastVersion(3, 4)); + String viewName = "view-" + rnd(); + db.createArangoSearch(viewName, new ArangoSearchCreateOptions()); + assertThat(db.arangoSearch(viewName).exists()).isTrue(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void createAndExistsSearchAlias(ArangoDatabase db) { + assumeTrue(isAtLeastVersion(3, 10)); + String viewName = "view-" + rnd(); + db.createSearchAlias(viewName, new SearchAliasCreateOptions()); + assertThat(db.arangoSearch(viewName).exists()).isTrue(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void getInfo(ArangoDatabase db) { + assumeTrue(isAtLeastVersion(3, 4)); + String viewName = "view-" + rnd(); + db.createArangoSearch(viewName, new ArangoSearchCreateOptions()); + final ViewEntity info = db.arangoSearch(viewName).getInfo(); + assertThat(info).isNotNull(); + assertThat(info.getId()).isNotNull(); + assertThat(info.getName()).isEqualTo(viewName); + assertThat(info.getType()).isEqualTo(ViewType.ARANGO_SEARCH); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void drop(ArangoDatabase db) { + assumeTrue(isAtLeastVersion(3, 4)); + String viewName = "view-" + rnd(); + db.createArangoSearch(viewName, new ArangoSearchCreateOptions()); + final ArangoView view = db.arangoSearch(viewName); + view.drop(); + assertThat(view.exists()).isFalse(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void rename(ArangoDatabase db) { + assumeTrue(isSingleServer()); + assumeTrue(isAtLeastVersion(3, 4)); + String viewName = "view-" + rnd(); + final String name = viewName + "_new"; + db.createArangoSearch(name, new ArangoSearchCreateOptions()); + db.arangoSearch(name).rename(viewName); + assertThat(db.arangoSearch(name).exists()).isFalse(); + assertThat(db.arangoSearch(viewName).exists()).isTrue(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void createArangoSearchView(ArangoDatabase db) { + assumeTrue(isAtLeastVersion(3, 4)); + String viewName = "view-" + rnd(); + final ViewEntity info = db.arangoSearch(viewName).create(); + assertThat(info).isNotNull(); + assertThat(info.getId()).isNotNull(); + assertThat(info.getName()).isEqualTo(viewName); + assertThat(info.getType()).isEqualTo(ViewType.ARANGO_SEARCH); + assertThat(db.arangoSearch(viewName).exists()).isTrue(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void createSearchAliasView(ArangoDatabase db) { + assumeTrue(isAtLeastVersion(3, 10)); + String viewName = "view-" + rnd(); + final ViewEntity info = db.searchAlias(viewName).create(); + assertThat(info).isNotNull(); + assertThat(info.getId()).isNotNull(); + assertThat(info.getName()).isEqualTo(viewName); + assertThat(info.getType()).isEqualTo(ViewType.SEARCH_ALIAS); + assertThat(db.searchAlias(viewName).exists()).isTrue(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void createArangoSearchViewWithOptions(ArangoDatabase db) { + assumeTrue(isAtLeastVersion(3, 4)); + String viewName = "view-" + rnd(); + final ArangoSearchCreateOptions options = new ArangoSearchCreateOptions(); + final ViewEntity info = db.arangoSearch(viewName).create(options); + assertThat(info).isNotNull(); + assertThat(info.getId()).isNotNull(); + assertThat(info.getName()).isEqualTo(viewName); + assertThat(info.getType()).isEqualTo(ViewType.ARANGO_SEARCH); + assertThat(db.arangoSearch(viewName).exists()).isTrue(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void createArangoSearchViewWithPrimarySort(ArangoDatabase db) { + assumeTrue(isAtLeastVersion(3, 5)); + String viewName = "view-" + rnd(); + final ArangoSearchCreateOptions options = new ArangoSearchCreateOptions(); + + final PrimarySort primarySort = PrimarySort.on("myFieldName"); + primarySort.ascending(true); + options.primarySort(primarySort); + options.primarySortCompression(ArangoSearchCompression.none); + options.consolidationIntervalMsec(666666L); + StoredValue storedValue = new StoredValue(Arrays.asList("a", "b"), ArangoSearchCompression.none); + options.storedValues(storedValue); + + final ArangoSearch view = db.arangoSearch(viewName); + final ViewEntity info = view.create(options); + assertThat(info).isNotNull(); + assertThat(info.getId()).isNotNull(); + assertThat(info.getName()).isEqualTo(viewName); + assertThat(info.getType()).isEqualTo(ViewType.ARANGO_SEARCH); + assertThat(db.arangoSearch(viewName).exists()).isTrue(); + + if (isAtLeastVersion(3, 7)) { + final ArangoSearchPropertiesEntity properties = view.getProperties(); + assertThat(properties.getPrimarySortCompression()).isEqualTo(ArangoSearchCompression.none); + Collection retrievedStoredValues = properties.getStoredValues(); + assertThat(retrievedStoredValues).isNotNull(); + assertThat(retrievedStoredValues).hasSize(1); + StoredValue retrievedStoredValue = retrievedStoredValues.iterator().next(); + assertThat(retrievedStoredValue).isNotNull(); + assertThat(retrievedStoredValue.getFields()).isEqualTo(storedValue.getFields()); + assertThat(retrievedStoredValue.getCompression()).isEqualTo(storedValue.getCompression()); + } + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void createArangoSearchViewWithCommitIntervalMsec(ArangoDatabase db) { + assumeTrue(isAtLeastVersion(3, 5)); + String viewName = "view-" + rnd(); + final ArangoSearchCreateOptions options = new ArangoSearchCreateOptions(); + options.commitIntervalMsec(666666L); + + final ViewEntity info = db.arangoSearch(viewName).create(options); + assertThat(info).isNotNull(); + assertThat(info.getId()).isNotNull(); + assertThat(info.getName()).isEqualTo(viewName); + assertThat(info.getType()).isEqualTo(ViewType.ARANGO_SEARCH); + assertThat(db.arangoSearch(viewName).exists()).isTrue(); + + // check commit interval msec property + final ArangoSearch view = db.arangoSearch(viewName); + final ArangoSearchPropertiesEntity properties = view.getProperties(); + assertThat(properties.getCommitIntervalMsec()).isEqualTo(666666L); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void createSearchAliasViewWithOptions(ArangoDatabase db) { + assumeTrue(isAtLeastVersion(3, 10)); + String viewName = "view-" + rnd(); + final SearchAliasCreateOptions options = new SearchAliasCreateOptions(); + final ViewEntity info = db.searchAlias(viewName).create(options); + assertThat(info).isNotNull(); + assertThat(info.getId()).isNotNull(); + assertThat(info.getName()).isEqualTo(viewName); + assertThat(info.getType()).isEqualTo(ViewType.SEARCH_ALIAS); + assertThat(db.searchAlias(viewName).exists()).isTrue(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void createSearchAliasViewWithIndexesAndGetProperties(ArangoDatabase db) { + assumeTrue(isAtLeastVersion(3, 10)); + ArangoCollection col = db.collection(COLL_1); + String idxName1 = "idx-" + rnd(); + col.ensureInvertedIndex(new InvertedIndexOptions() + .name(idxName1) + .fields(new InvertedIndexField().name("a" + rnd()))); + + String idxName2 = "idx-" + rnd(); + col.ensureInvertedIndex(new InvertedIndexOptions() + .name(idxName2) + .fields(new InvertedIndexField().name("a" + rnd()))); + + String viewName = "view-" + rnd(); + final SearchAliasCreateOptions options = new SearchAliasCreateOptions() + .indexes( + new SearchAliasIndex(COLL_1, idxName1, SearchAliasIndex.OperationType.add), + new SearchAliasIndex(COLL_1, idxName2, SearchAliasIndex.OperationType.add), + new SearchAliasIndex(COLL_1, idxName2, SearchAliasIndex.OperationType.del) + ); + final ViewEntity info = db.searchAlias(viewName).create(options); + assertThat(info).isNotNull(); + assertThat(info.getId()).isNotNull(); + assertThat(info.getName()).isEqualTo(viewName); + assertThat(info.getType()).isEqualTo(ViewType.SEARCH_ALIAS); + + final SearchAliasPropertiesEntity properties = db.searchAlias(viewName).getProperties(); + assertThat(properties).isNotNull(); + assertThat(properties.getId()).isNotNull(); + assertThat(properties.getName()).isEqualTo(viewName); + assertThat(properties.getType()).isEqualTo(ViewType.SEARCH_ALIAS); + assertThat(properties.getIndexes()) + .isNotNull() + .isNotEmpty() + .anyMatch(i -> i.getCollection().equals(COLL_1) && i.getIndex().equals(idxName1)); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void getArangoSearchViewProperties(ArangoDatabase db) { + assumeTrue(isAtLeastVersion(3, 4)); + String viewName = "view-" + rnd(); + final ArangoSearch view = db.arangoSearch(viewName); + view.create(new ArangoSearchCreateOptions()); + final ArangoSearchPropertiesEntity properties = view.getProperties(); + assertThat(properties).isNotNull(); + assertThat(properties.getId()).isNotNull(); + assertThat(properties.getName()).isEqualTo(viewName); + assertThat(properties.getType()).isEqualTo(ViewType.ARANGO_SEARCH); + assertThat(properties.getConsolidationIntervalMsec()).isNotNull(); + assertThat(properties.getCleanupIntervalStep()).isNotNull(); + final ConsolidationPolicy consolidate = properties.getConsolidationPolicy(); + assertThat(consolidate).isNotNull(); + final Collection links = properties.getLinks(); + assertThat(links).isEmpty(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void updateArangoSearchViewProperties(ArangoDatabase db) { + assumeTrue(isAtLeastVersion(3, 4)); + String viewName = "view-" + rnd(); + final ArangoSearch view = db.arangoSearch(viewName); + view.create(new ArangoSearchCreateOptions()); + final ArangoSearchPropertiesOptions options = new ArangoSearchPropertiesOptions(); + options.cleanupIntervalStep(15L); + options.consolidationIntervalMsec(65000L); + options.consolidationPolicy(ConsolidationPolicy.of(ConsolidationType.BYTES_ACCUM).threshold(1.)); + options.link(CollectionLink.on(COLL_2) + .fields(FieldLink.on("value").analyzers("identity").trackListPositions(true).includeAllFields(true) + .storeValues(StoreValuesType.ID))); + final ArangoSearchPropertiesEntity properties = view.updateProperties(options); + assertThat(properties).isNotNull(); + assertThat(properties.getCleanupIntervalStep()).isEqualTo(15L); + assertThat(properties.getConsolidationIntervalMsec()).isEqualTo(65000L); + final ConsolidationPolicy consolidate = properties.getConsolidationPolicy(); + assertThat(consolidate).isNotNull(); + assertThat(consolidate.getType()).isEqualTo(ConsolidationType.BYTES_ACCUM); + assertThat(consolidate.getThreshold()).isEqualTo(1.); + assertThat(properties.getLinks()).hasSize(1); + final CollectionLink link = properties.getLinks().iterator().next(); + assertThat(link.getName()).isEqualTo(COLL_2); + assertThat(link.getFields()).hasSize(1); + final FieldLink next = link.getFields().iterator().next(); + assertThat(next.getName()).isEqualTo("value"); + assertThat(next.getIncludeAllFields()).isTrue(); + assertThat(next.getTrackListPositions()).isTrue(); + assertThat(next.getStoreValues()).isEqualTo(StoreValuesType.ID); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void updateSearchAliasViewWithIndexesAndGetProperties(ArangoDatabase db) { + assumeTrue(isAtLeastVersion(3, 10)); + ArangoCollection col = db.collection(COLL_1); + String idxName = "idx-" + rnd(); + col.ensureInvertedIndex(new InvertedIndexOptions() + .name(idxName) + .fields(new InvertedIndexField().name("a" + rnd()))); + ArangoCollection col2 = db.collection(COLL_2); + String idxName2 = "idx-" + rnd(); + col2.ensureInvertedIndex(new InvertedIndexOptions() + .name(idxName2) + .fields(new InvertedIndexField().name("a" + rnd()))); + + String viewName = "view-" + rnd(); + final SearchAliasCreateOptions options = new SearchAliasCreateOptions() + .indexes(new SearchAliasIndex(COLL_1, idxName)); + final ViewEntity info = db.searchAlias(viewName).create(options); + db.searchAlias(viewName).updateProperties(new SearchAliasPropertiesOptions() + .indexes(new SearchAliasIndex(COLL_2, idxName2))); + + assertThat(info).isNotNull(); + assertThat(info.getId()).isNotNull(); + assertThat(info.getName()).isEqualTo(viewName); + assertThat(info.getType()).isEqualTo(ViewType.SEARCH_ALIAS); + + final SearchAliasPropertiesEntity properties = db.searchAlias(viewName).getProperties(); + assertThat(properties).isNotNull(); + assertThat(properties.getId()).isNotNull(); + assertThat(properties.getName()).isEqualTo(viewName); + assertThat(properties.getType()).isEqualTo(ViewType.SEARCH_ALIAS); + assertThat(properties.getIndexes()) + .isNotNull() + .isNotEmpty() + .hasSize(2) + .anyMatch(i -> i.getCollection().equals(COLL_1) && i.getIndex().equals(idxName)) + .anyMatch(i -> i.getCollection().equals(COLL_2) && i.getIndex().equals(idxName2)); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void replaceArangoSearchViewProperties(ArangoDatabase db) { + assumeTrue(isAtLeastVersion(3, 4)); + String viewName = "view-" + rnd(); + final ArangoSearch view = db.arangoSearch(viewName); + view.create(new ArangoSearchCreateOptions()); + final ArangoSearchPropertiesOptions options = new ArangoSearchPropertiesOptions(); + options.link(CollectionLink.on(COLL_1) + .fields(FieldLink.on("value").analyzers("identity"))); + final ArangoSearchPropertiesEntity properties = view.replaceProperties(options); + assertThat(properties).isNotNull(); + assertThat(properties.getLinks()).hasSize(1); + final CollectionLink link = properties.getLinks().iterator().next(); + assertThat(link.getName()).isEqualTo(COLL_1); + assertThat(link.getFields()).hasSize(1); + assertThat(link.getFields().iterator().next().getName()).isEqualTo("value"); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void replaceSearchAliasViewWithIndexesAndGetProperties(ArangoDatabase db) { + assumeTrue(isAtLeastVersion(3, 10)); + ArangoCollection col = db.collection(COLL_1); + String idxName = "idx-" + rnd(); + col.ensureInvertedIndex(new InvertedIndexOptions() + .name(idxName) + .fields(new InvertedIndexField().name("a" + rnd()))); + ArangoCollection col2 = db.collection(COLL_2); + String idxName2 = "idx-" + rnd(); + col2.ensureInvertedIndex(new InvertedIndexOptions() + .name(idxName2) + .fields(new InvertedIndexField().name("a" + rnd()))); + + String viewName = "view-" + rnd(); + final SearchAliasCreateOptions options = new SearchAliasCreateOptions() + .indexes(new SearchAliasIndex(COLL_1, idxName)); + final ViewEntity info = db.searchAlias(viewName).create(options); + db.searchAlias(viewName).replaceProperties(new SearchAliasPropertiesOptions() + .indexes(new SearchAliasIndex(COLL_2, idxName2))); + + assertThat(info).isNotNull(); + assertThat(info.getId()).isNotNull(); + assertThat(info.getName()).isEqualTo(viewName); + assertThat(info.getType()).isEqualTo(ViewType.SEARCH_ALIAS); + + final SearchAliasPropertiesEntity properties = db.searchAlias(viewName).getProperties(); + assertThat(properties).isNotNull(); + assertThat(properties.getId()).isNotNull(); + assertThat(properties.getName()).isEqualTo(viewName); + assertThat(properties.getType()).isEqualTo(ViewType.SEARCH_ALIAS); + assertThat(properties.getIndexes()) + .isNotNull() + .isNotEmpty() + .hasSize(1) + .anyMatch(i -> i.getCollection().equals(COLL_2) && i.getIndex().equals(idxName2)); + } + + private void createGetAndDeleteTypedAnalyzer(ArangoDatabase db, SearchAnalyzer analyzer) { + + String fullyQualifiedName = db.dbName().get() + "::" + analyzer.getName(); + analyzer.setName(fullyQualifiedName); + + // createAnalyzer + SearchAnalyzer createdAnalyzer = db.createSearchAnalyzer(analyzer); + assertThat(createdAnalyzer).isEqualTo(analyzer); + + // getAnalyzer + SearchAnalyzer gotAnalyzer = db.getSearchAnalyzer(analyzer.getName()); + assertThat(gotAnalyzer).isEqualTo(analyzer); + + // getAnalyzers + SearchAnalyzer foundAnalyzer = + db.getSearchAnalyzers().stream().filter(it -> it.getName().equals(fullyQualifiedName)) + .findFirst().get(); + assertThat(foundAnalyzer).isEqualTo(analyzer); + + // deleteAnalyzer + AnalyzerDeleteOptions deleteOptions = new AnalyzerDeleteOptions(); + deleteOptions.setForce(true); + + db.deleteSearchAnalyzer(analyzer.getName(), deleteOptions); + + Throwable thrown = catchThrowable(() -> db.getSearchAnalyzer(analyzer.getName())); + assertThat(thrown).isInstanceOf(ArangoDBException.class); + ArangoDBException e = (ArangoDBException) thrown; + assertThat(e.getResponseCode()).isEqualTo(404); + assertThat(e.getErrorNum()).isEqualTo(1202); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void identityAnalyzerTyped(ArangoDatabase db) { + assumeTrue(isAtLeastVersion(3, 5)); + + String name = "test-" + UUID.randomUUID(); + + Set features = new HashSet<>(); + features.add(AnalyzerFeature.frequency); + features.add(AnalyzerFeature.norm); + features.add(AnalyzerFeature.position); + + IdentityAnalyzer analyzer = new IdentityAnalyzer(); + analyzer.setFeatures(features); + analyzer.setName(name); + + createGetAndDeleteTypedAnalyzer(db, analyzer); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void delimiterAnalyzerTyped(ArangoDatabase db) { + assumeTrue(isAtLeastVersion(3, 5)); + + String name = "test-" + UUID.randomUUID(); + + Set features = new HashSet<>(); + features.add(AnalyzerFeature.frequency); + features.add(AnalyzerFeature.norm); + features.add(AnalyzerFeature.position); + + DelimiterAnalyzerProperties properties = new DelimiterAnalyzerProperties(); + properties.setDelimiter("-"); + + DelimiterAnalyzer analyzer = new DelimiterAnalyzer(); + analyzer.setFeatures(features); + analyzer.setName(name); + analyzer.setProperties(properties); + + createGetAndDeleteTypedAnalyzer(db, analyzer); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void stemAnalyzerTyped(ArangoDatabase db) { + assumeTrue(isAtLeastVersion(3, 5)); + + String name = "test-" + UUID.randomUUID(); + + Set features = new HashSet<>(); + features.add(AnalyzerFeature.frequency); + features.add(AnalyzerFeature.norm); + features.add(AnalyzerFeature.position); + + StemAnalyzerProperties properties = new StemAnalyzerProperties(); + properties.setLocale("ru"); + + StemAnalyzer options = new StemAnalyzer(); + options.setFeatures(features); + options.setName(name); + options.setProperties(properties); + + createGetAndDeleteTypedAnalyzer(db, options); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void normAnalyzerTyped(ArangoDatabase db) { + assumeTrue(isAtLeastVersion(3, 5)); + + String name = "test-" + UUID.randomUUID(); + + Set features = new HashSet<>(); + features.add(AnalyzerFeature.frequency); + features.add(AnalyzerFeature.norm); + features.add(AnalyzerFeature.position); + + NormAnalyzerProperties properties = new NormAnalyzerProperties(); + properties.setLocale("ru"); + properties.setAnalyzerCase(SearchAnalyzerCase.lower); + properties.setAccent(true); + + NormAnalyzer options = new NormAnalyzer(); + options.setFeatures(features); + options.setName(name); + options.setProperties(properties); + + createGetAndDeleteTypedAnalyzer(db, options); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void ngramAnalyzerTyped(ArangoDatabase db) { + assumeTrue(isAtLeastVersion(3, 5)); + + String name = "test-" + UUID.randomUUID(); + + Set features = new HashSet<>(); + features.add(AnalyzerFeature.frequency); + features.add(AnalyzerFeature.norm); + features.add(AnalyzerFeature.position); + + NGramAnalyzerProperties properties = new NGramAnalyzerProperties(); + properties.setMax(6L); + properties.setMin(3L); + properties.setPreserveOriginal(true); + + NGramAnalyzer analyzer = new NGramAnalyzer(); + analyzer.setFeatures(features); + analyzer.setName(name); + analyzer.setType(AnalyzerType.ngram); + analyzer.setProperties(properties); + + createGetAndDeleteTypedAnalyzer(db, analyzer); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void enhancedNgramAnalyzerTyped(ArangoDatabase db) { + assumeTrue(isAtLeastVersion(3, 6)); + + String name = "test-" + UUID.randomUUID(); + + Set features = new HashSet<>(); + features.add(AnalyzerFeature.frequency); + features.add(AnalyzerFeature.norm); + features.add(AnalyzerFeature.position); + + NGramAnalyzerProperties properties = new NGramAnalyzerProperties(); + properties.setMax(6L); + properties.setMin(3L); + properties.setPreserveOriginal(true); + properties.setStartMarker("^"); + properties.setEndMarker("^"); + properties.setStreamType(StreamType.utf8); + + NGramAnalyzer analyzer = new NGramAnalyzer(); + analyzer.setFeatures(features); + analyzer.setName(name); + analyzer.setProperties(properties); + + createGetAndDeleteTypedAnalyzer(db, analyzer); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void textAnalyzerTyped(ArangoDatabase db) { + assumeTrue(isAtLeastVersion(3, 5)); + + String name = "test-" + UUID.randomUUID(); + + Set features = new HashSet<>(); + features.add(AnalyzerFeature.frequency); + features.add(AnalyzerFeature.norm); + features.add(AnalyzerFeature.position); + + TextAnalyzerProperties properties = new TextAnalyzerProperties(); + properties.setLocale("ru"); + properties.setAnalyzerCase(SearchAnalyzerCase.lower); + properties.setAccent(true); + properties.setStemming(true); + + TextAnalyzer analyzer = new TextAnalyzer(); + analyzer.setFeatures(features); + analyzer.setName(name); + analyzer.setType(AnalyzerType.text); + analyzer.setProperties(properties); + + createGetAndDeleteTypedAnalyzer(db, analyzer); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void enhancedTextAnalyzerTyped(ArangoDatabase db) { + assumeTrue(isAtLeastVersion(3, 6)); + + String name = "test-" + UUID.randomUUID(); + + Set features = new HashSet<>(); + features.add(AnalyzerFeature.frequency); + features.add(AnalyzerFeature.norm); + features.add(AnalyzerFeature.position); + + EdgeNgram edgeNgram = new EdgeNgram(); + edgeNgram.setMin(2L); + edgeNgram.setMax(100000L); + edgeNgram.setPreserveOriginal(true); + + TextAnalyzerProperties properties = new TextAnalyzerProperties(); + properties.setLocale("ru"); + properties.setAnalyzerCase(SearchAnalyzerCase.lower); + properties.setAccent(true); + properties.setStemming(true); + properties.setEdgeNgram(edgeNgram); + + TextAnalyzer analyzer = new TextAnalyzer(); + analyzer.setFeatures(features); + analyzer.setName(name); + analyzer.setProperties(properties); + + createGetAndDeleteTypedAnalyzer(db, analyzer); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void arangoSearchOptions(ArangoDatabase db) { + assumeTrue(isAtLeastVersion(3, 4)); + String viewName = "view-" + rnd(); + FieldLink field = FieldLink.on("f1").inBackground(true); + if (isEnterprise()) { + field.nested(FieldLink.on("f2")); + } + CollectionLink link = CollectionLink.on(COLL_1) + .analyzers("identity") + .fields(field) + .includeAllFields(true) + .storeValues(StoreValuesType.ID) + .trackListPositions(false) + .inBackground(true) + .cache(true); + + if (isEnterprise()) { + link.nested(FieldLink.on("f3")); + } + ArangoSearchCreateOptions options = new ArangoSearchCreateOptions().link(link); + StoredValue storedValue = new StoredValue(Arrays.asList("a", "b"), ArangoSearchCompression.none, true); + options.storedValues(storedValue); + + final ArangoSearch view = db.arangoSearch(viewName); + view.create(options); + + final ArangoSearchPropertiesEntity properties = view.getProperties(); + assertThat(properties).isNotNull(); + assertThat(properties.getId()).isNotNull(); + assertThat(properties.getName()).isEqualTo(viewName); + assertThat(properties.getType()).isEqualTo(ViewType.ARANGO_SEARCH); + assertThat(properties.getLinks()).isNotEmpty(); + + CollectionLink createdLink = properties.getLinks().iterator().next(); + assertThat(createdLink.getName()).isEqualTo(COLL_1); + assertThat(createdLink.getAnalyzers()).contains("identity"); + assertThat(createdLink.getIncludeAllFields()).isTrue(); + assertThat(createdLink.getStoreValues()).isEqualTo(StoreValuesType.ID); + assertThat(createdLink.getTrackListPositions()).isFalse(); + + if (isEnterprise() && isAtLeastVersion(3, 9, 5) && isLessThanVersion(3, 10)) { + assertThat(createdLink.getCache()).isTrue(); + assertThat(properties.getStoredValues()) + .isNotEmpty() + .allSatisfy(it -> assertThat(it.getCache()).isTrue()); + } + + if (isEnterprise() && isAtLeastVersion(3, 10)) { + assertThat(createdLink.getNested()).isNotEmpty(); + FieldLink nested = createdLink.getNested().iterator().next(); + assertThat(nested.getName()).isEqualTo("f3"); + } + + FieldLink fieldLink = createdLink.getFields().iterator().next(); + assertThat(fieldLink.getName()).isEqualTo("f1"); + if (isEnterprise() && isAtLeastVersion(3, 10)) { + assertThat(fieldLink.getNested()).isNotEmpty(); + FieldLink nested = fieldLink.getNested().iterator().next(); + assertThat(nested.getName()).isEqualTo("f2"); + } + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void pipelineAnalyzer(ArangoDatabase db) { + assumeTrue(isAtLeastVersion(3, 8)); + + // comma delimiter + DelimiterAnalyzerProperties commaDelimiterProperties = new DelimiterAnalyzerProperties(); + commaDelimiterProperties.setDelimiter(","); + + DelimiterAnalyzer commaDelimiter = new DelimiterAnalyzer(); + commaDelimiter.setProperties(commaDelimiterProperties); + + // semicolon delimiter + DelimiterAnalyzerProperties semicolonDelimiterProperties = new DelimiterAnalyzerProperties(); + semicolonDelimiterProperties.setDelimiter(","); + + DelimiterAnalyzer semicolonDelimiter = new DelimiterAnalyzer(); + semicolonDelimiter.setProperties(semicolonDelimiterProperties); + + // stem + StemAnalyzerProperties stemAnalyzerProperties = new StemAnalyzerProperties(); + stemAnalyzerProperties.setLocale("en"); + + StemAnalyzer stemAnalyzer = new StemAnalyzer(); + stemAnalyzer.setProperties(stemAnalyzerProperties); + + // pipeline analyzer + Set features = new HashSet<>(); + features.add(AnalyzerFeature.frequency); + features.add(AnalyzerFeature.norm); + features.add(AnalyzerFeature.position); + + PipelineAnalyzerProperties properties = new PipelineAnalyzerProperties() + .addAnalyzer(commaDelimiter) + .addAnalyzer(semicolonDelimiter) + .addAnalyzer(stemAnalyzer); + + PipelineAnalyzer pipelineAnalyzer = new PipelineAnalyzer(); + pipelineAnalyzer.setName("test-" + UUID.randomUUID()); + pipelineAnalyzer.setProperties(properties); + pipelineAnalyzer.setFeatures(features); + + createGetAndDeleteTypedAnalyzer(db, pipelineAnalyzer); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void stopwordsAnalyzer(ArangoDatabase db) { + assumeTrue(isAtLeastVersion(3, 8)); + + Set features = new HashSet<>(); + features.add(AnalyzerFeature.frequency); + features.add(AnalyzerFeature.norm); + features.add(AnalyzerFeature.position); + + StopwordsAnalyzerProperties properties = new StopwordsAnalyzerProperties() + .addStopwordAsHex("616e64") + .addStopwordAsString("the"); + + assertThat(properties.getStopwordsAsStringList()).contains("and"); + assertThat(properties.getStopwordsAsHexList()).contains("746865"); + + StopwordsAnalyzer analyzer = new StopwordsAnalyzer(); + String name = "test-" + UUID.randomUUID(); + analyzer.setName(name); + analyzer.setProperties(properties); + analyzer.setFeatures(features); + + createGetAndDeleteTypedAnalyzer(db, analyzer); + db.createSearchAnalyzer(analyzer); + Collection res = db.query("RETURN FLATTEN(TOKENS(SPLIT('the fox and the dog and a theater', ' '), " + + "@aName))", + Collections.singletonMap("aName", name), Collection.class).next(); + assertThat(res).containsExactly("fox", "dog", "a", "theater"); + db.deleteSearchAnalyzer(name); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void aqlAnalyzer(ArangoDatabase db) { + assumeTrue(isAtLeastVersion(3, 8)); + + AQLAnalyzerProperties properties = new AQLAnalyzerProperties(); + properties.setBatchSize(2); + properties.setCollapsePositions(true); + properties.setKeepNull(false); + properties.setMemoryLimit(2200L); + properties.setQueryString("RETURN SOUNDEX(@param)"); + properties.setReturnType(AQLAnalyzerProperties.ReturnType.string); + + Set features = new HashSet<>(); + features.add(AnalyzerFeature.frequency); + features.add(AnalyzerFeature.norm); + features.add(AnalyzerFeature.position); + + AQLAnalyzer aqlAnalyzer = new AQLAnalyzer(); + aqlAnalyzer.setName("test-" + UUID.randomUUID()); + aqlAnalyzer.setProperties(properties); + aqlAnalyzer.setFeatures(features); + + createGetAndDeleteTypedAnalyzer(db, aqlAnalyzer); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void geoJsonAnalyzer(ArangoDatabase db) { + assumeTrue(isAtLeastVersion(3, 8)); + + GeoAnalyzerOptions options = new GeoAnalyzerOptions(); + options.setMaxLevel(10); + options.setMaxCells(11); + options.setMinLevel(8); + + GeoJSONAnalyzerProperties properties = new GeoJSONAnalyzerProperties(); + properties.setOptions(options); + properties.setType(GeoJSONAnalyzerProperties.GeoJSONAnalyzerType.point); + + Set features = new HashSet<>(); + features.add(AnalyzerFeature.frequency); + features.add(AnalyzerFeature.norm); + features.add(AnalyzerFeature.position); + + GeoJSONAnalyzer geoJSONAnalyzer = new GeoJSONAnalyzer(); + geoJSONAnalyzer.setName("test-" + UUID.randomUUID()); + geoJSONAnalyzer.setProperties(properties); + geoJSONAnalyzer.setFeatures(features); + + createGetAndDeleteTypedAnalyzer(db, geoJSONAnalyzer); + } + + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void geoPointAnalyzer(ArangoDatabase db) { + assumeTrue(isAtLeastVersion(3, 8)); + + GeoAnalyzerOptions options = new GeoAnalyzerOptions(); + options.setMaxLevel(10); + options.setMaxCells(11); + options.setMinLevel(8); + + GeoPointAnalyzerProperties properties = new GeoPointAnalyzerProperties(); + properties.setLatitude(new String[]{"a", "b", "c"}); + properties.setLongitude(new String[]{"d", "e", "f"}); + properties.setOptions(options); + + Set features = new HashSet<>(); + features.add(AnalyzerFeature.frequency); + features.add(AnalyzerFeature.norm); + features.add(AnalyzerFeature.position); + + GeoPointAnalyzer geoPointAnalyzer = new GeoPointAnalyzer(); + geoPointAnalyzer.setName("test-" + UUID.randomUUID()); + geoPointAnalyzer.setProperties(properties); + geoPointAnalyzer.setFeatures(features); + + createGetAndDeleteTypedAnalyzer(db, geoPointAnalyzer); + } + + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void segmentationAnalyzer(ArangoDatabase db) { + assumeTrue(isAtLeastVersion(3, 9)); + + SegmentationAnalyzerProperties properties = new SegmentationAnalyzerProperties(); + properties.setBreakMode(SegmentationAnalyzerProperties.BreakMode.graphic); + properties.setAnalyzerCase(SearchAnalyzerCase.upper); + + Set features = new HashSet<>(); + features.add(AnalyzerFeature.frequency); + features.add(AnalyzerFeature.norm); + features.add(AnalyzerFeature.position); + + SegmentationAnalyzer segmentationAnalyzer = new SegmentationAnalyzer(); + segmentationAnalyzer.setName("test-" + UUID.randomUUID()); + segmentationAnalyzer.setProperties(properties); + segmentationAnalyzer.setFeatures(features); + + createGetAndDeleteTypedAnalyzer(db, segmentationAnalyzer); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void collationAnalyzer(ArangoDatabase db) { + assumeTrue(isAtLeastVersion(3, 9)); + + CollationAnalyzerProperties properties = new CollationAnalyzerProperties(); + properties.setLocale("ru"); + + Set features = new HashSet<>(); + features.add(AnalyzerFeature.frequency); + features.add(AnalyzerFeature.norm); + features.add(AnalyzerFeature.position); + + CollationAnalyzer collationAnalyzer = new CollationAnalyzer(); + collationAnalyzer.setName("test-" + UUID.randomUUID()); + collationAnalyzer.setProperties(properties); + collationAnalyzer.setFeatures(features); + + createGetAndDeleteTypedAnalyzer(db, collationAnalyzer); + } + + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void classificationAnalyzer(ArangoDatabase db) { + assumeTrue(isAtLeastVersion(3, 10)); + assumeTrue(isEnterprise()); + + ClassificationAnalyzerProperties properties = new ClassificationAnalyzerProperties(); + properties.setModelLocation("/tmp/foo.bin"); + properties.setTopK(2); + properties.setThreshold(.5); + + Set features = new HashSet<>(); + features.add(AnalyzerFeature.frequency); + features.add(AnalyzerFeature.norm); + features.add(AnalyzerFeature.position); + + ClassificationAnalyzer analyzer = new ClassificationAnalyzer(); + analyzer.setName("test-" + UUID.randomUUID()); + analyzer.setProperties(properties); + analyzer.setFeatures(features); + + createGetAndDeleteTypedAnalyzer(db, analyzer); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void nearestNeighborsAnalyzer(ArangoDatabase db) { + assumeTrue(isAtLeastVersion(3, 10)); + assumeTrue(isEnterprise()); + + NearestNeighborsAnalyzerProperties properties = new NearestNeighborsAnalyzerProperties(); + properties.setModelLocation("/tmp/foo.bin"); + properties.setTopK(2); + + Set features = new HashSet<>(); + features.add(AnalyzerFeature.frequency); + features.add(AnalyzerFeature.norm); + features.add(AnalyzerFeature.position); + + NearestNeighborsAnalyzer analyzer = new NearestNeighborsAnalyzer(); + analyzer.setName("test-" + UUID.randomUUID()); + analyzer.setProperties(properties); + analyzer.setFeatures(features); + + createGetAndDeleteTypedAnalyzer(db, analyzer); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void MinHashAnalyzer(ArangoDatabase db) { + assumeTrue(isAtLeastVersion(3, 10)); + assumeTrue(isEnterprise()); + + SegmentationAnalyzerProperties segProperties = new SegmentationAnalyzerProperties(); + segProperties.setBreakMode(SegmentationAnalyzerProperties.BreakMode.alpha); + segProperties.setAnalyzerCase(SearchAnalyzerCase.lower); + + SegmentationAnalyzer segAnalyzer = new SegmentationAnalyzer(); + segAnalyzer.setProperties(segProperties); + + MinHashAnalyzerProperties properties = new MinHashAnalyzerProperties(); + properties.setAnalyzer(segAnalyzer); + properties.setNumHashes(2); + + Set features = new HashSet<>(); + features.add(AnalyzerFeature.frequency); + features.add(AnalyzerFeature.norm); + features.add(AnalyzerFeature.position); + + MinHashAnalyzer analyzer = new MinHashAnalyzer(); + analyzer.setName("test-" + UUID.randomUUID()); + analyzer.setProperties(properties); + analyzer.setFeatures(features); + + createGetAndDeleteTypedAnalyzer(db, analyzer); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void offsetFeature(ArangoDatabase db) { + assumeTrue(isAtLeastVersion(3, 10)); + + String name = "test-" + UUID.randomUUID(); + + Set features = new HashSet<>(); + features.add(AnalyzerFeature.frequency); + features.add(AnalyzerFeature.norm); + features.add(AnalyzerFeature.position); + features.add(AnalyzerFeature.offset); + + IdentityAnalyzer analyzer = new IdentityAnalyzer(); + analyzer.setFeatures(features); + analyzer.setName(name); + + createGetAndDeleteTypedAnalyzer(db, analyzer); + } + +} diff --git a/shaded-integration-tests/src/test/jackson/java/com/arangodb/ArangoSslTest.java b/shaded-integration-tests/src/test/jackson/java/com/arangodb/ArangoSslTest.java new file mode 100644 index 000000000..1c9c2bd3a --- /dev/null +++ b/shaded-integration-tests/src/test/jackson/java/com/arangodb/ArangoSslTest.java @@ -0,0 +1,101 @@ +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed 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. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb; + +import com.arangodb.entity.ArangoDBVersion; +import org.junit.jupiter.api.Tag; +import org.junit.jupiter.api.condition.EnabledIfSystemProperty; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.EnumSource; + +import javax.net.ssl.KeyManagerFactory; +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLHandshakeException; +import javax.net.ssl.TrustManagerFactory; +import java.security.KeyStore; +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.catchThrowable; + + +/** + * @author Mark Vollmary + * @author Michele Rastelli + */ +@Tag("ssl") +@EnabledIfSystemProperty(named = "SslTest", matches = "true") +class ArangoSslTest { + + /* + * a SSL trust store + * + * create the trust store for the self signed certificate: + * keytool -import -alias "my arangodb server cert" -file UnitTests/server.pem -keystore example.truststore + * + * Documentation: + * https://hc.apache.org/httpcomponents-client-ga/httpclient/apidocs/org/apache/http/conn/ssl/SSLSocketFactory.html + */ + private static final String SSL_TRUSTSTORE = "/example.truststore"; + private static final String SSL_TRUSTSTORE_PASSWORD = "12345678"; + + @ParameterizedTest + @EnumSource(Protocol.class) + void connect(Protocol protocol) throws Exception { + final KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType()); + ks.load(this.getClass().getResourceAsStream(SSL_TRUSTSTORE), SSL_TRUSTSTORE_PASSWORD.toCharArray()); + + final KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); + kmf.init(ks, SSL_TRUSTSTORE_PASSWORD.toCharArray()); + + final TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); + tmf.init(ks); + + final SSLContext sc = SSLContext.getInstance("TLS"); + sc.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null); + + final ArangoDB arangoDB = new ArangoDB.Builder() + .useProtocol(protocol) + .host("localhost", 8529) + .password("test") + .useSsl(true) + .sslContext(sc).build(); + final ArangoDBVersion version = arangoDB.getVersion(); + assertThat(version).isNotNull(); + } + + @ParameterizedTest + @EnumSource(Protocol.class) + void connectWithoutValidSslContext(Protocol protocol) { + final ArangoDB arangoDB = new ArangoDB.Builder() + .useProtocol(protocol) + .host("localhost", 8529) + .useSsl(true) + .build(); + Throwable thrown = catchThrowable(arangoDB::getVersion); + assertThat(thrown).isInstanceOf(ArangoDBException.class); + ArangoDBException ex = (ArangoDBException) thrown; + assertThat(ex.getCause()).isInstanceOf(ArangoDBMultipleException.class); + List exceptions = ((ArangoDBMultipleException) ex.getCause()).getExceptions(); + exceptions.forEach(e -> assertThat(e).isInstanceOf(SSLHandshakeException.class)); + } + +} diff --git a/shaded-integration-tests/src/test/jackson/java/com/arangodb/ArangoVertexCollectionTest.java b/shaded-integration-tests/src/test/jackson/java/com/arangodb/ArangoVertexCollectionTest.java new file mode 100644 index 000000000..5b5504d80 --- /dev/null +++ b/shaded-integration-tests/src/test/jackson/java/com/arangodb/ArangoVertexCollectionTest.java @@ -0,0 +1,480 @@ +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed 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. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb; + +import com.arangodb.entity.BaseDocument; +import com.arangodb.entity.VertexEntity; +import com.arangodb.entity.VertexUpdateEntity; +import com.arangodb.model.*; +import com.arangodb.util.RawJson; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +import java.util.Collection; +import java.util.Collections; +import java.util.UUID; +import java.util.stream.Stream; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.catchThrowable; + + +/** + * @author Mark Vollmary + * @author Michele Rastelli + */ +class ArangoVertexCollectionTest extends BaseJunit5 { + + private static final String GRAPH_NAME = "ArangoVertexCollectionTest_graph"; + private static final String COLLECTION_NAME = "ArangoVertexCollectionTest_vertex_collection"; + + private static Stream vertices() { + return dbsStream() + .map(db -> db.graph(GRAPH_NAME).vertexCollection(COLLECTION_NAME)) + .map(Arguments::of); + } + + @BeforeAll + static void init() { + initCollections(COLLECTION_NAME); + initGraph( + GRAPH_NAME, + null, + new GraphCreateOptions().orphanCollections(COLLECTION_NAME) + ); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("vertices") + void dropVertexCollection(ArangoVertexCollection vertices) { + ArangoGraph graph = vertices.graph(); + vertices.drop(); + final Collection vertexCollections = graph.getVertexCollections(); + assertThat(vertexCollections).isEmpty(); + + // revert + graph.addVertexCollection(COLLECTION_NAME); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("vertices") + void insertVertex(ArangoVertexCollection vertices) { + final VertexEntity vertex = vertices + .insertVertex(new BaseDocument(), null); + assertThat(vertex).isNotNull(); + ArangoCollection collection = vertices.graph().db().collection(vertices.name()); + final BaseDocument document = collection + .getDocument(vertex.getKey(), BaseDocument.class, null); + assertThat(document).isNotNull(); + assertThat(document.getKey()).isEqualTo(vertex.getKey()); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("vertices") + void insertVertexViolatingUniqueConstraint(ArangoVertexCollection vertices) { + ArangoCollection collection = vertices.graph().db().collection(vertices.name()); + collection + .ensureSkiplistIndex(Collections.singletonList("field"), + new SkiplistIndexOptions().unique(true).sparse(true)); + + VertexEntity inserted = vertices.insertVertex(RawJson.of("{\"field\": 99}")); + + try { + vertices.insertVertex(RawJson.of("{\"field\": 99}")); + } catch (ArangoDBException e) { + assertThat(e.getResponseCode()).isEqualTo(409); + assertThat(e.getErrorNum()).isEqualTo(1210); + } + + // revert + vertices.deleteVertex(inserted.getKey()); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("vertices") + void duplicateInsertSameObjectVertex(ArangoVertexCollection vertices) { + + // ######################################################### + // Create a new BaseDocument + // ######################################################### + + UUID uuid = UUID.randomUUID(); + BaseDocument bd = new BaseDocument(UUID.randomUUID().toString()); + bd.setKey(uuid.toString()); + bd.addAttribute("name", "Paul"); + + vertices.insertVertex(bd); + + UUID uuid2 = UUID.randomUUID(); + BaseDocument bd2 = new BaseDocument(UUID.randomUUID().toString()); + bd2.setKey(uuid2.toString()); + bd2.addAttribute("name", "Paul"); + + vertices.insertVertex(bd2); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("vertices") + void insertVertexUpdateRev(ArangoVertexCollection vertices) { + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); + final VertexEntity vertex = vertices.insertVertex(doc, null); + assertThat(doc.getRevision()).isNull(); + assertThat(vertex.getRev()).isNotNull(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("vertices") + void getVertex(ArangoVertexCollection vertices) { + final VertexEntity vertex = vertices + .insertVertex(new BaseDocument(), null); + final BaseDocument document = vertices + .getVertex(vertex.getKey(), BaseDocument.class, null); + assertThat(document).isNotNull(); + assertThat(document.getKey()).isEqualTo(vertex.getKey()); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("vertices") + void getVertexIfMatch(ArangoVertexCollection vertices) { + final VertexEntity vertex = vertices + .insertVertex(new BaseDocument(), null); + final GraphDocumentReadOptions options = new GraphDocumentReadOptions().ifMatch(vertex.getRev()); + final BaseDocument document = vertices + .getVertex(vertex.getKey(), BaseDocument.class, options); + assertThat(document).isNotNull(); + assertThat(document.getKey()).isEqualTo(vertex.getKey()); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("vertices") + void getVertexIfMatchFail(ArangoVertexCollection vertices) { + final VertexEntity vertex = vertices + .insertVertex(new BaseDocument(), null); + final GraphDocumentReadOptions options = new GraphDocumentReadOptions().ifMatch("no"); + final BaseDocument vertex2 = vertices + .getVertex(vertex.getKey(), BaseDocument.class, options); + assertThat(vertex2).isNull(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("vertices") + void getVertexIfNoneMatch(ArangoVertexCollection vertices) { + final VertexEntity vertex = vertices + .insertVertex(new BaseDocument(), null); + final GraphDocumentReadOptions options = new GraphDocumentReadOptions().ifNoneMatch("no"); + final BaseDocument document = vertices + .getVertex(vertex.getKey(), BaseDocument.class, options); + assertThat(document).isNotNull(); + assertThat(document.getKey()).isEqualTo(vertex.getKey()); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("vertices") + void getVertexIfNoneMatchFail(ArangoVertexCollection vertices) { + final VertexEntity vertex = vertices + .insertVertex(new BaseDocument(), null); + final GraphDocumentReadOptions options = new GraphDocumentReadOptions().ifNoneMatch(vertex.getRev()); + final BaseDocument vertex2 = vertices + .getVertex(vertex.getKey(), BaseDocument.class, options); + assertThat(vertex2).isNull(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("vertices") + void replaceVertex(ArangoVertexCollection vertices) { + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); + doc.addAttribute("a", "test"); + final VertexEntity createResult = vertices + .insertVertex(doc, null); + doc.removeAttribute("a"); + doc.addAttribute("b", "test"); + final VertexUpdateEntity replaceResult = vertices + .replaceVertex(createResult.getKey(), doc, null); + assertThat(replaceResult).isNotNull(); + assertThat(replaceResult.getId()).isEqualTo(createResult.getId()); + assertThat(replaceResult.getRev()).isNotEqualTo(replaceResult.getOldRev()); + assertThat(replaceResult.getOldRev()).isEqualTo(createResult.getRev()); + + final BaseDocument readResult = vertices + .getVertex(createResult.getKey(), BaseDocument.class, null); + assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); + assertThat(readResult.getRevision()).isEqualTo(replaceResult.getRev()); + assertThat(readResult.getProperties().keySet()).doesNotContain("a"); + assertThat(readResult.getAttribute("b")).isNotNull(); + assertThat(String.valueOf(readResult.getAttribute("b"))).isEqualTo("test"); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("vertices") + void replaceVertexUpdateRev(ArangoVertexCollection vertices) { + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); + final VertexEntity createResult = vertices + .insertVertex(doc, null); + final VertexUpdateEntity replaceResult = vertices + .replaceVertex(createResult.getKey(), doc, null); + assertThat(doc.getRevision()).isNull(); + assertThat(createResult.getRev()).isNotNull(); + assertThat(replaceResult.getRev()) + .isNotNull() + .isNotEqualTo(createResult.getRev()); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("vertices") + void replaceVertexIfMatch(ArangoVertexCollection vertices) { + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); + doc.addAttribute("a", "test"); + final VertexEntity createResult = vertices + .insertVertex(doc, null); + doc.removeAttribute("a"); + doc.addAttribute("b", "test"); + final VertexReplaceOptions options = new VertexReplaceOptions().ifMatch(createResult.getRev()); + final VertexUpdateEntity replaceResult = vertices + .replaceVertex(createResult.getKey(), doc, options); + assertThat(replaceResult).isNotNull(); + assertThat(replaceResult.getId()).isEqualTo(createResult.getId()); + assertThat(replaceResult.getRev()).isNotEqualTo(replaceResult.getOldRev()); + assertThat(replaceResult.getOldRev()).isEqualTo(createResult.getRev()); + + final BaseDocument readResult = vertices + .getVertex(createResult.getKey(), BaseDocument.class, null); + assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); + assertThat(readResult.getRevision()).isEqualTo(replaceResult.getRev()); + assertThat(readResult.getProperties().keySet()).doesNotContain("a"); + assertThat(readResult.getAttribute("b")).isNotNull(); + assertThat(String.valueOf(readResult.getAttribute("b"))).isEqualTo("test"); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("vertices") + void replaceVertexIfMatchFail(ArangoVertexCollection vertices) { + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); + doc.addAttribute("a", "test"); + final VertexEntity createResult = vertices + .insertVertex(doc, null); + doc.removeAttribute("a"); + doc.addAttribute("b", "test"); + final VertexReplaceOptions options = new VertexReplaceOptions().ifMatch("no"); + Throwable thrown = catchThrowable(() -> vertices.replaceVertex(createResult.getKey(), doc, options)); + assertThat(thrown).isInstanceOf(ArangoDBException.class); + ArangoDBException e = (ArangoDBException) thrown; + assertThat(e.getResponseCode()).isEqualTo(412); + assertThat(e.getErrorNum()).isEqualTo(1200); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("vertices") + void updateVertex(ArangoVertexCollection vertices) { + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); + doc.addAttribute("a", "test"); + doc.addAttribute("c", "test"); + final VertexEntity createResult = vertices + .insertVertex(doc, null); + doc.updateAttribute("a", "test1"); + doc.addAttribute("b", "test"); + doc.updateAttribute("c", null); + final VertexUpdateEntity updateResult = vertices + .updateVertex(createResult.getKey(), doc, null); + assertThat(updateResult).isNotNull(); + assertThat(updateResult.getId()).isEqualTo(createResult.getId()); + assertThat(updateResult.getRev()).isNotEqualTo(updateResult.getOldRev()); + assertThat(updateResult.getOldRev()).isEqualTo(createResult.getRev()); + + final BaseDocument readResult = vertices + .getVertex(createResult.getKey(), BaseDocument.class, null); + assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); + assertThat(readResult.getAttribute("a")).isNotNull(); + assertThat(String.valueOf(readResult.getAttribute("a"))).isEqualTo("test1"); + assertThat(readResult.getAttribute("b")).isNotNull(); + assertThat(String.valueOf(readResult.getAttribute("b"))).isEqualTo("test"); + assertThat(readResult.getRevision()).isEqualTo(updateResult.getRev()); + assertThat(readResult.getProperties()).containsKey("c"); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("vertices") + void updateVertexUpdateRev(ArangoVertexCollection vertices) { + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); + final VertexEntity createResult = vertices + .insertVertex(doc, null); + doc.addAttribute("foo", "bar"); + final VertexUpdateEntity updateResult = vertices + .updateVertex(createResult.getKey(), doc, null); + assertThat(doc.getRevision()).isNull(); + assertThat(createResult.getRev()).isNotNull(); + assertThat(updateResult.getRev()) + .isNotNull() + .isNotEqualTo(createResult.getRev()); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("vertices") + void updateVertexIfMatch(ArangoVertexCollection vertices) { + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); + doc.addAttribute("a", "test"); + doc.addAttribute("c", "test"); + final VertexEntity createResult = vertices + .insertVertex(doc, null); + doc.updateAttribute("a", "test1"); + doc.addAttribute("b", "test"); + doc.updateAttribute("c", null); + final VertexUpdateOptions options = new VertexUpdateOptions().ifMatch(createResult.getRev()); + final VertexUpdateEntity updateResult = vertices + .updateVertex(createResult.getKey(), doc, options); + assertThat(updateResult).isNotNull(); + assertThat(updateResult.getId()).isEqualTo(createResult.getId()); + assertThat(updateResult.getRev()).isNotEqualTo(updateResult.getOldRev()); + assertThat(updateResult.getOldRev()).isEqualTo(createResult.getRev()); + + final BaseDocument readResult = vertices + .getVertex(createResult.getKey(), BaseDocument.class, null); + assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); + assertThat(readResult.getAttribute("a")).isNotNull(); + assertThat(String.valueOf(readResult.getAttribute("a"))).isEqualTo("test1"); + assertThat(readResult.getAttribute("b")).isNotNull(); + assertThat(String.valueOf(readResult.getAttribute("b"))).isEqualTo("test"); + assertThat(readResult.getRevision()).isEqualTo(updateResult.getRev()); + assertThat(readResult.getProperties()).containsKey("c"); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("vertices") + void updateVertexIfMatchFail(ArangoVertexCollection vertices) { + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); + doc.addAttribute("a", "test"); + doc.addAttribute("c", "test"); + final VertexEntity createResult = vertices + .insertVertex(doc, null); + doc.updateAttribute("a", "test1"); + doc.addAttribute("b", "test"); + doc.updateAttribute("c", null); + final VertexUpdateOptions options = new VertexUpdateOptions().ifMatch("no"); + + Throwable thrown = catchThrowable(() -> vertices.updateVertex(createResult.getKey(), doc, options)); + assertThat(thrown).isInstanceOf(ArangoDBException.class); + ArangoDBException e = (ArangoDBException) thrown; + assertThat(e.getResponseCode()).isEqualTo(412); + assertThat(e.getErrorNum()).isEqualTo(1200); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("vertices") + void updateVertexKeepNullTrue(ArangoVertexCollection vertices) { + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); + doc.addAttribute("a", "test"); + final VertexEntity createResult = vertices + .insertVertex(doc, null); + doc.updateAttribute("a", null); + final VertexUpdateOptions options = new VertexUpdateOptions().keepNull(true); + final VertexUpdateEntity updateResult = vertices + .updateVertex(createResult.getKey(), doc, options); + assertThat(updateResult).isNotNull(); + assertThat(updateResult.getId()).isEqualTo(createResult.getId()); + assertThat(updateResult.getRev()).isNotEqualTo(updateResult.getOldRev()); + assertThat(updateResult.getOldRev()).isEqualTo(createResult.getRev()); + + final BaseDocument readResult = vertices + .getVertex(createResult.getKey(), BaseDocument.class, null); + assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); + assertThat(readResult.getProperties().keySet()).hasSize(4); + assertThat(readResult.getProperties()).containsKey("a"); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("vertices") + void updateVertexKeepNullFalse(ArangoVertexCollection vertices) { + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); + doc.addAttribute("a", "test"); + final VertexEntity createResult = vertices + .insertVertex(doc, null); + doc.updateAttribute("a", null); + final VertexUpdateOptions options = new VertexUpdateOptions().keepNull(false); + final VertexUpdateEntity updateResult = vertices + .updateVertex(createResult.getKey(), doc, options); + assertThat(updateResult).isNotNull(); + assertThat(updateResult.getId()).isEqualTo(createResult.getId()); + assertThat(updateResult.getRev()).isNotEqualTo(updateResult.getOldRev()); + assertThat(updateResult.getOldRev()).isEqualTo(createResult.getRev()); + + final BaseDocument readResult = vertices + .getVertex(createResult.getKey(), BaseDocument.class, null); + assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); + assertThat(readResult.getId()).isEqualTo(createResult.getId()); + assertThat(readResult.getRevision()).isNotNull(); + assertThat(readResult.getProperties().keySet()).doesNotContain("a"); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("vertices") + void deleteVertex(ArangoVertexCollection vertices) { + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); + final VertexEntity createResult = vertices + .insertVertex(doc, null); + vertices.deleteVertex(createResult.getKey(), null); + final BaseDocument vertex = vertices + .getVertex(createResult.getKey(), BaseDocument.class, null); + assertThat(vertex).isNull(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("vertices") + void deleteVertexIfMatch(ArangoVertexCollection vertices) { + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); + final VertexEntity createResult = vertices + .insertVertex(doc, null); + final VertexDeleteOptions options = new VertexDeleteOptions().ifMatch(createResult.getRev()); + vertices.deleteVertex(createResult.getKey(), options); + final BaseDocument vertex = vertices + .getVertex(createResult.getKey(), BaseDocument.class, null); + assertThat(vertex).isNull(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("vertices") + void deleteVertexIfMatchFail(ArangoVertexCollection vertices) { + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); + final VertexEntity createResult = vertices + .insertVertex(doc, null); + final VertexDeleteOptions options = new VertexDeleteOptions().ifMatch("no"); + Throwable thrown = catchThrowable(() -> vertices.deleteVertex(createResult.getKey(), options)); + assertThat(thrown).isInstanceOf(ArangoDBException.class); + ArangoDBException e = (ArangoDBException) thrown; + assertThat(e.getResponseCode()).isEqualTo(412); + assertThat(e.getErrorNum()).isEqualTo(1200); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("vertices") + void vertexKeyWithSpecialChars(ArangoVertexCollection vertices) { + final String key = "_-:.@()+,=;$!*'%" + UUID.randomUUID(); + final VertexEntity vertex = vertices + .insertVertex(new BaseDocument(key), null); + assertThat(vertex).isNotNull(); + ArangoCollection collection = vertices.graph().db().collection(vertices.name()); + final BaseDocument document = collection + .getDocument(vertex.getKey(), BaseDocument.class, null); + assertThat(document).isNotNull(); + assertThat(document.getKey()).isEqualTo(key); + } + +} diff --git a/shaded-integration-tests/src/test/jackson/java/com/arangodb/ArangoViewTest.java b/shaded-integration-tests/src/test/jackson/java/com/arangodb/ArangoViewTest.java new file mode 100644 index 000000000..09121b7ff --- /dev/null +++ b/shaded-integration-tests/src/test/jackson/java/com/arangodb/ArangoViewTest.java @@ -0,0 +1,114 @@ +/* + * DISCLAIMER + * + * Copyright 2018 ArangoDB GmbH, Cologne, Germany + * + * Licensed 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. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb; + +import com.arangodb.entity.ViewEntity; +import com.arangodb.entity.ViewType; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + +import java.util.Collection; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assumptions.assumeTrue; + + +/** + * @author Mark Vollmary + * @author Michele Rastelli + */ +class ArangoViewTest extends BaseJunit5 { + + @BeforeAll + static void init() { + initDB(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void exists(ArangoDatabase db) { + String name = "view-" + rnd(); + db.createView(name, ViewType.ARANGO_SEARCH); + assertThat(db.view(name).exists()).isTrue(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void getInfo(ArangoDatabase db) { + String name = "view-" + rnd(); + db.createView(name, ViewType.ARANGO_SEARCH); + final ViewEntity info = db.view(name).getInfo(); + assertThat(info).isNotNull(); + assertThat(info.getId()).isNotNull(); + assertThat(info.getName()).isEqualTo(name); + assertThat(info.getType()).isEqualTo(ViewType.ARANGO_SEARCH); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void getInfoSearchAlias(ArangoDatabase db) { + assumeTrue(isAtLeastVersion(3, 10)); + String name = "view-" + rnd(); + db.createView(name, ViewType.SEARCH_ALIAS); + final ViewEntity info = db.view(name).getInfo(); + assertThat(info).isNotNull(); + assertThat(info.getId()).isNotNull(); + assertThat(info.getName()).isEqualTo(name); + assertThat(info.getType()).isEqualTo(ViewType.SEARCH_ALIAS); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void getViews(ArangoDatabase db) { + assumeTrue(isAtLeastVersion(3, 10)); + String name1 = "view-" + rnd(); + String name2 = "view-" + rnd(); + db.createView(name1, ViewType.ARANGO_SEARCH); + db.createView(name2, ViewType.SEARCH_ALIAS); + Collection views = db.getViews(); + assertThat(views).extracting(ViewEntity::getName).contains(name1, name2); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void drop(ArangoDatabase db) { + String name = "view-" + rnd(); + db.createView(name, ViewType.ARANGO_SEARCH); + final ArangoView view = db.view(name); + view.drop(); + assertThat(view.exists()).isFalse(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void rename(ArangoDatabase db) { + assumeTrue(isSingleServer()); + String oldName = "view-" + rnd(); + String newName = "view-" + rnd(); + + db.createView(oldName, ViewType.ARANGO_SEARCH); + db.view(oldName).rename(newName); + assertThat(db.view(oldName).exists()).isFalse(); + assertThat(db.view(newName).exists()).isTrue(); + } + +} diff --git a/shaded-integration-tests/src/test/jackson/java/com/arangodb/BaseJunit5.java b/shaded-integration-tests/src/test/jackson/java/com/arangodb/BaseJunit5.java new file mode 100644 index 000000000..fd2aa8415 --- /dev/null +++ b/shaded-integration-tests/src/test/jackson/java/com/arangodb/BaseJunit5.java @@ -0,0 +1,128 @@ +package com.arangodb; + +import com.arangodb.entity.*; +import com.arangodb.internal.config.FileConfigPropertiesProvider; +import com.arangodb.model.CollectionCreateOptions; +import com.arangodb.model.GraphCreateOptions; +import com.arangodb.util.TestUtils; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.params.provider.Arguments; + +import java.util.Arrays; +import java.util.Collection; +import java.util.List; +import java.util.UUID; +import java.util.stream.Stream; + +class BaseJunit5 { + protected static final DbName TEST_DB = DbName.of("java_driver_shaded_test_db"); + + private static final List adbs = Arrays.asList( + new ArangoDB.Builder().loadProperties(new FileConfigPropertiesProvider()).useProtocol(Protocol.VST).build(), + new ArangoDB.Builder().loadProperties(new FileConfigPropertiesProvider()).useProtocol(Protocol.HTTP_VPACK).build(), + new ArangoDB.Builder().loadProperties(new FileConfigPropertiesProvider()).useProtocol(Protocol.HTTP_JSON).build(), + new ArangoDB.Builder().loadProperties(new FileConfigPropertiesProvider()).useProtocol(Protocol.HTTP2_VPACK).build(), + new ArangoDB.Builder().loadProperties(new FileConfigPropertiesProvider()).useProtocol(Protocol.HTTP2_JSON).build() + ); + + protected static Stream dbsStream() { + return adbs.stream().map(adb -> adb.db(TEST_DB)); + } + + protected static Stream arangos() { + return adbs.stream().map(Arguments::of); + } + + protected static Stream dbs() { + return dbsStream().map(Arguments::of); + } + + static ArangoDatabase initDB(DbName name) { + ArangoDatabase database = adbs.get(0).db(name); + if (!database.exists()) + database.create(); + return database; + } + + static ArangoDatabase initDB() { + return initDB(TEST_DB); + } + + static void dropDB(DbName name) { + ArangoDatabase database = adbs.get(0).db(name); + if (database.exists()) + database.drop(); + } + + static void initGraph(String name, Collection edgeDefinitions, GraphCreateOptions options) { + ArangoDatabase db = initDB(); + db.createGraph(name, edgeDefinitions, options); + } + + static void initCollections(String... collections) { + ArangoDatabase db = initDB(); + for (String collection : collections) { + if (db.collection(collection).exists()) + db.collection(collection).drop(); + db.createCollection(collection, null); + } + } + + static void initEdgeCollections(String... collections) { + ArangoDatabase db = initDB(); + for (String collection : collections) { + if (db.collection(collection).exists()) + db.collection(collection).drop(); + db.createCollection(collection, new CollectionCreateOptions().type(CollectionType.EDGES)); + } + } + + @BeforeAll + static void init() { + dropDB(TEST_DB); + } + + @AfterAll + static void shutdown() { + dropDB(TEST_DB); + } + + static String rnd() { + return UUID.randomUUID().toString(); + } + + boolean isAtLeastVersion(final int major, final int minor) { + return isAtLeastVersion(major, minor, 0); + } + + boolean isAtLeastVersion(final int major, final int minor, final int patch) { + return TestUtils.isAtLeastVersion(adbs.get(0).getVersion().getVersion(), major, minor, patch); + } + + boolean isLessThanVersion(final int major, final int minor) { + return isLessThanVersion(major, minor, 0); + } + + boolean isLessThanVersion(final int major, final int minor, final int patch) { + return TestUtils.isLessThanVersion(adbs.get(0).getVersion().getVersion(), major, minor, patch); + } + + boolean isStorageEngine(ArangoDBEngine.StorageEngineName name) { + return name.equals(adbs.get(0).getEngine().getName()); + } + + boolean isSingleServer() { + return adbs.get(0).getRole() == ServerRole.SINGLE; + } + + boolean isCluster() { + return adbs.get(0).getRole() == ServerRole.COORDINATOR; + } + + boolean isEnterprise() { + return adbs.get(0).getVersion().getLicense() == License.ENTERPRISE; + } + + +} diff --git a/shaded-integration-tests/src/test/jackson/java/com/arangodb/ConcurrencyTests.java b/shaded-integration-tests/src/test/jackson/java/com/arangodb/ConcurrencyTests.java new file mode 100644 index 000000000..1103cb6df --- /dev/null +++ b/shaded-integration-tests/src/test/jackson/java/com/arangodb/ConcurrencyTests.java @@ -0,0 +1,34 @@ +package com.arangodb; + +import com.arangodb.internal.config.FileConfigPropertiesProvider; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.EnumSource; + +import java.util.List; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.stream.Collectors; +import java.util.stream.IntStream; + +class ConcurrencyTests { + + @ParameterizedTest + @EnumSource(Protocol.class) + void concurrentPendingRequests(Protocol protocol) throws ExecutionException, InterruptedException { + ExecutorService es = Executors.newFixedThreadPool(10); + ArangoDB adb = new ArangoDB.Builder() + .loadProperties(new FileConfigPropertiesProvider()) + .useProtocol(protocol).build(); + List> futures = IntStream.range(0, 10) + .mapToObj(__ -> CompletableFuture.runAsync(() -> adb.db().query("RETURN SLEEP(1)", Void.class), es)) + .collect(Collectors.toList()); + for (CompletableFuture f : futures) { + f.get(); + } + adb.shutdown(); + es.shutdown(); + } + +} diff --git a/shaded-integration-tests/src/test/jackson/java/com/arangodb/DocumentTest.java b/shaded-integration-tests/src/test/jackson/java/com/arangodb/DocumentTest.java new file mode 100644 index 000000000..0ce14ff53 --- /dev/null +++ b/shaded-integration-tests/src/test/jackson/java/com/arangodb/DocumentTest.java @@ -0,0 +1,138 @@ +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed 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. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb; + +import com.arangodb.entity.BaseDocument; +import com.arangodb.entity.DocumentCreateEntity; +import com.arangodb.util.RawJson; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +import java.util.Map; +import java.util.UUID; +import java.util.stream.Stream; + +import static org.assertj.core.api.Assertions.assertThat; + + +/** + * @author Mark Vollmary + * @author Michele Rastelli + */ +class DocumentTest extends BaseJunit5 { + + private static final String COLLECTION_NAME = "DocumentTest_collection"; + + private static Stream cols() { + return dbsStream() + .map(db -> db.collection(COLLECTION_NAME)) + .map(Arguments::of); + } + + + @BeforeAll + static void init() { + initCollections(COLLECTION_NAME); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void insertAsJson(ArangoCollection collection) { + //@formatter:off + final RawJson json = RawJson.of( + "{" + + "\"article\": {" + + "\"artist\": \"PREGARDIEN/RHEINISCHE KANTOREI/DAS\"," + + "\"releaseDate\": \"1970-01-01\"," + + "\"composer\": \"BACH\"," + + "\"format\": \"CD\"," + + "\"vat\": \"H\"," + + "\"carriers\": 1," + + "\"label\": \"CAPRICCIO\"," + + "\"title\": \"BACH ST MATTHEW PASSION BWV244\"," + + "\"barcode\": [" + + "\"4006408600466\"" + + "]," + + "\"conductor\": \"MAX, H.\"" + + "}," + + "\"stock\": {" + + "\"status\": \"RMV\"," + + "\"lastUpdate\": \"2016-11-01 00:00\"" + + "}" + + "}" + ); + //@formatter:on + final DocumentCreateEntity createResult = collection.insertDocument(json); + final BaseDocument doc = collection.getDocument(createResult.getKey(), BaseDocument.class); + assertThat(doc).isNotNull(); + final Object article = doc.getAttribute("article"); + assertThat(article).isNotNull(); + final Object artist = ((Map) article).get("artist"); + assertThat(artist).isNotNull(); + assertThat(artist.toString()).isEqualTo("PREGARDIEN/RHEINISCHE KANTOREI/DAS"); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void insertAsBaseDocument(ArangoCollection collection) { + final BaseDocument document = new BaseDocument(UUID.randomUUID().toString()); + { + final BaseDocument article = new BaseDocument(UUID.randomUUID().toString()); + document.addAttribute("article", article); + article.addAttribute("artist", "PREGARDIEN/RHEINISCHE KANTOREI/DAS"); + article.addAttribute("releaseDate", "1970-01-01"); + article.addAttribute("composer", "BACH"); + article.addAttribute("format", "CD"); + article.addAttribute("vat", "H"); + article.addAttribute("carriers", 1); + article.addAttribute("label", "CAPRICCIO"); + article.addAttribute("title", "BACH ST MATTHEW PASSION BWV244"); + article.addAttribute("barcode", new String[]{"4006408600466"}); + article.addAttribute("conductor", "MAX, H."); + final BaseDocument stock = new BaseDocument(UUID.randomUUID().toString()); + document.addAttribute("stock", stock); + stock.addAttribute("status", "RMV"); + stock.addAttribute("lastUpdate", "2016-11-01 00:00"); + } + final DocumentCreateEntity createResult = collection.insertDocument(document); + final BaseDocument doc = collection.getDocument(createResult.getKey(), BaseDocument.class); + assertThat(doc).isNotNull(); + final Object article = doc.getAttribute("article"); + assertThat(article).isNotNull(); + final Object artist = ((Map) article).get("artist"); + assertThat(artist).isNotNull(); + assertThat(artist.toString()).isEqualTo("PREGARDIEN/RHEINISCHE KANTOREI/DAS"); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void documentKeyWithSpecialChars(ArangoCollection collection) { + final String key = "_-:.@()+,=;$!*'%" + UUID.randomUUID(); + final BaseDocument document = new BaseDocument(key); + final DocumentCreateEntity createResult = collection.insertDocument(document); + final BaseDocument doc = collection.getDocument(createResult.getKey(), BaseDocument.class); + assertThat(doc).isNotNull(); + assertThat(doc.getKey()).isEqualTo(key); + } + +} diff --git a/shaded-integration-tests/src/test/jackson/java/com/arangodb/InvertedIndexTest.java b/shaded-integration-tests/src/test/jackson/java/com/arangodb/InvertedIndexTest.java new file mode 100644 index 000000000..e96bc70ef --- /dev/null +++ b/shaded-integration-tests/src/test/jackson/java/com/arangodb/InvertedIndexTest.java @@ -0,0 +1,194 @@ +package com.arangodb; + +import com.arangodb.entity.*; +import com.arangodb.entity.arangosearch.*; +import com.arangodb.entity.arangosearch.analyzer.DelimiterAnalyzer; +import com.arangodb.entity.arangosearch.analyzer.DelimiterAnalyzerProperties; +import com.arangodb.model.InvertedIndexOptions; +import com.arangodb.model.PersistentIndexOptions; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +import java.util.*; +import java.util.stream.Stream; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assumptions.assumeTrue; + +public class InvertedIndexTest extends BaseJunit5 { + + private static final String COLLECTION_NAME = "InvertedIndexTest_collection"; + + private static Stream cols() { + return dbsStream().map(db -> db.collection(COLLECTION_NAME)).map(Arguments::of); + } + + @BeforeAll + static void init() { + initCollections(COLLECTION_NAME); + } + + private void createAnalyzer(String analyzerName, ArangoDatabase db) { + Set features = new HashSet<>(); + features.add(AnalyzerFeature.frequency); + features.add(AnalyzerFeature.norm); + features.add(AnalyzerFeature.position); + + DelimiterAnalyzer da = new DelimiterAnalyzer(); + da.setName(analyzerName); + da.setFeatures(features); + DelimiterAnalyzerProperties props = new DelimiterAnalyzerProperties(); + props.setDelimiter("-"); + da.setProperties(props); + + db.createSearchAnalyzer(da); + } + + private InvertedIndexOptions createOptions(String analyzerName) { + InvertedIndexField field = new InvertedIndexField() + .name("foo") + .analyzer(AnalyzerType.identity.toString()) + .includeAllFields(true) + .searchField(false) + .trackListPositions(false) + .features( + AnalyzerFeature.position, + AnalyzerFeature.frequency, + AnalyzerFeature.norm, + AnalyzerFeature.offset + ); + + if (isEnterprise()) { + field.nested( + new InvertedIndexField() + .name("bar") + .analyzer(analyzerName) + .searchField(true) + .features(AnalyzerFeature.position, AnalyzerFeature.frequency) + .nested( + new InvertedIndexField() + .name("baz") + .analyzer(AnalyzerType.identity.toString()) + .searchField(false) + .features(AnalyzerFeature.frequency) + ) + ); + } + + return new InvertedIndexOptions() + .name("invertedIndex-" + UUID.randomUUID()) + .inBackground(true) + .parallelism(5) + .primarySort(new InvertedIndexPrimarySort() + .fields( + new InvertedIndexPrimarySort.Field("f1", InvertedIndexPrimarySort.Field.Direction.asc), + new InvertedIndexPrimarySort.Field("f2", InvertedIndexPrimarySort.Field.Direction.desc) + ) + .compression(ArangoSearchCompression.lz4) + ) + .storedValues(new StoredValue(Arrays.asList("f3", "f4"), ArangoSearchCompression.none)) + .analyzer(analyzerName) + .features(AnalyzerFeature.position, AnalyzerFeature.frequency) + .includeAllFields(false) + .trackListPositions(true) + .searchField(true) + .fields(field) + .consolidationIntervalMsec(11L) + .commitIntervalMsec(22L) + .cleanupIntervalStep(33L) + .consolidationPolicy(ConsolidationPolicy.of(ConsolidationType.TIER) + .segmentsMin(3L) + .segmentsMax(44L) + .segmentsBytesMax(55555L) + .segmentsBytesFloor(666L) + .minScore(77L) + ) + .writebufferIdle(44L) + .writebufferActive(55L) + .writebufferSizeMax(66L); + } + + private void assertCorrectIndexEntity(InvertedIndexEntity indexResult, InvertedIndexOptions options) { + assertThat(indexResult).isNotNull(); + assertThat(indexResult.getId()).isNotNull().isNotEmpty(); + // FIXME: in single server this is null + // assertThat(indexResult.getIsNewlyCreated()).isTrue(); + assertThat(indexResult.getUnique()).isFalse(); + assertThat(indexResult.getSparse()).isTrue(); + assertThat(indexResult.getVersion()).isNotNull(); + assertThat(indexResult.getCode()).isNotNull(); + assertThat(indexResult.getType()).isEqualTo(IndexType.inverted); + assertThat(indexResult.getName()).isEqualTo(options.getName()); + assertThat(indexResult.getFields()).containsExactlyElementsOf(options.getFields()); + assertThat(indexResult.getSearchField()).isEqualTo(options.getSearchField()); + assertThat(indexResult.getStoredValues()).containsExactlyElementsOf(options.getStoredValues()); + assertThat(indexResult.getPrimarySort()).isEqualTo(options.getPrimarySort()); + assertThat(indexResult.getAnalyzer()).isEqualTo(options.getAnalyzer()); + assertThat(indexResult.getFeatures()).hasSameElementsAs(options.getFeatures()); + assertThat(indexResult.getIncludeAllFields()).isEqualTo(options.getIncludeAllFields()); + assertThat(indexResult.getTrackListPositions()).isEqualTo(options.getTrackListPositions()); + assertThat(indexResult.getCleanupIntervalStep()).isEqualTo(options.getCleanupIntervalStep()); + assertThat(indexResult.getCommitIntervalMsec()).isEqualTo(options.getCommitIntervalMsec()); + assertThat(indexResult.getConsolidationIntervalMsec()).isEqualTo(options.getConsolidationIntervalMsec()); + assertThat(indexResult.getConsolidationPolicy()).isEqualTo(options.getConsolidationPolicy()); + assertThat(indexResult.getWritebufferIdle()).isEqualTo(options.getWritebufferIdle()); + assertThat(indexResult.getWritebufferActive()).isEqualTo(options.getWritebufferActive()); + assertThat(indexResult.getWritebufferSizeMax()).isEqualTo(options.getWritebufferSizeMax()); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void createAndGetInvertedIndex(ArangoCollection collection) { + assumeTrue(isAtLeastVersion(3, 10)); + String analyzerName = "delimiter-" + UUID.randomUUID(); + createAnalyzer(analyzerName, collection.db()); + InvertedIndexOptions options = createOptions(analyzerName); + InvertedIndexEntity created = collection.ensureInvertedIndex(options); + assertCorrectIndexEntity(created, options); + InvertedIndexEntity loadedIndex = collection.getInvertedIndex(created.getName()); + assertCorrectIndexEntity(loadedIndex, options); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void getInvertedIndexesShouldNotReturnOtherIndexTypes(ArangoCollection collection) { + assumeTrue(isAtLeastVersion(3, 10)); + + // create persistent index + collection.ensurePersistentIndex(Collections.singletonList("foo"), new PersistentIndexOptions().name("persistentIndex")); + + // create inverted index + String analyzerName = "delimiter-" + UUID.randomUUID(); + createAnalyzer(analyzerName, collection.db()); + InvertedIndexOptions options = createOptions(analyzerName); + InvertedIndexEntity created = collection.ensureInvertedIndex(options); + + Collection loadedIndexes = collection.getInvertedIndexes(); + assertThat(loadedIndexes).map(InvertedIndexEntity::getName) + .doesNotContain("persistentIndex") + .contains(created.getName()); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void getIndexesShouldNotReturnInvertedIndexes(ArangoCollection collection) { + assumeTrue(isAtLeastVersion(3, 10)); + + // create persistent index + collection.ensurePersistentIndex(Collections.singletonList("foo"), new PersistentIndexOptions().name("persistentIndex")); + + // create inverted index + String analyzerName = "delimiter-" + UUID.randomUUID(); + createAnalyzer(analyzerName, collection.db()); + InvertedIndexOptions options = createOptions(analyzerName); + InvertedIndexEntity created = collection.ensureInvertedIndex(options); + + Collection loadedIndexes = collection.getIndexes(); + assertThat(loadedIndexes).map(IndexEntity::getName) + .doesNotContain(created.getName()) + .contains("persistentIndex"); + } + +} diff --git a/shaded-integration-tests/src/test/jackson/java/com/arangodb/JwtAuthTest.java b/shaded-integration-tests/src/test/jackson/java/com/arangodb/JwtAuthTest.java new file mode 100644 index 000000000..34d41a751 --- /dev/null +++ b/shaded-integration-tests/src/test/jackson/java/com/arangodb/JwtAuthTest.java @@ -0,0 +1,97 @@ +package com.arangodb; + +import com.arangodb.internal.config.FileConfigPropertiesProvider; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.EnumSource; + +import java.util.HashMap; +import java.util.Map; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.catchThrowable; +import static org.junit.jupiter.api.Assumptions.assumeTrue; + + +/** + * @author Michele Rastelli + */ +class JwtAuthTest { + + private volatile static String jwt; + + @BeforeAll + static void init() { + ArangoDB arangoDB = new ArangoDB.Builder() + .loadProperties(new FileConfigPropertiesProvider()) + .build(); + jwt = getJwt(arangoDB); + arangoDB.shutdown(); + } + + private static String getJwt(ArangoDB arangoDB) { + Map reqBody = new HashMap<>(); + reqBody.put("username", "root"); + reqBody.put("password", "test"); + + Request req = Request.builder() + .db(DbName.SYSTEM) + .method(Request.Method.POST) + .path("/_open/auth") + .body(reqBody) + .build(); + + Response resp = arangoDB.execute(req, Map.class); + return (String) resp.getBody().get("jwt"); + } + + @ParameterizedTest + @EnumSource(Protocol.class) + void notAuthenticated(Protocol protocol) { + ArangoDB arangoDB = getBuilder(protocol).build(); + Throwable thrown = catchThrowable(arangoDB::getVersion); + assertThat(thrown).isInstanceOf(ArangoDBException.class); + ArangoDBException e = (ArangoDBException) thrown; + assertThat(e.getResponseCode()).isEqualTo(401); + arangoDB.shutdown(); + } + + @ParameterizedTest + @EnumSource(Protocol.class) + void authenticated(Protocol protocol) { + ArangoDB arangoDB = getBuilder(protocol) + .jwt(jwt) + .build(); + arangoDB.getVersion(); + arangoDB.shutdown(); + } + + @ParameterizedTest + @EnumSource(Protocol.class) + void updateJwt(Protocol protocol) { + assumeTrue(protocol != Protocol.VST, "DE-423"); + ArangoDB arangoDB = getBuilder(protocol) + .jwt(jwt) + .build(); + arangoDB.getVersion(); + arangoDB.updateJwt("bla"); + + Throwable thrown = catchThrowable(arangoDB::getVersion); + assertThat(thrown).isInstanceOf(ArangoDBException.class); + ArangoDBException e = (ArangoDBException) thrown; + assertThat(e.getResponseCode()).isEqualTo(401); + + arangoDB.updateJwt(jwt); + arangoDB.getVersion(); + arangoDB.shutdown(); + } + + private ArangoDB.Builder getBuilder(Protocol protocol) { + return new ArangoDB.Builder() + .loadProperties(new FileConfigPropertiesProvider()) + .useProtocol(protocol) + .jwt(null) // unset credentials from properties file + .user(null) // unset credentials from properties file + .password(null); // unset credentials from properties file + } +} diff --git a/shaded-integration-tests/src/test/jackson/java/com/arangodb/ParallelTest.java b/shaded-integration-tests/src/test/jackson/java/com/arangodb/ParallelTest.java new file mode 100644 index 000000000..2df8079bb --- /dev/null +++ b/shaded-integration-tests/src/test/jackson/java/com/arangodb/ParallelTest.java @@ -0,0 +1,42 @@ +package com.arangodb; + +import com.arangodb.internal.config.FileConfigPropertiesProvider; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.EnumSource; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assumptions.assumeTrue; + +class ParallelTest { + + @ParameterizedTest(name = "{index}") + @EnumSource(Protocol.class) + void connectionParallelism(Protocol protocol) throws InterruptedException { + // test that connections are internally async and can have multiple pending requests + // BTS-1102: the server does not run pipelined HTTP/1.1 requests in parallel + assumeTrue(protocol != Protocol.HTTP_JSON && protocol != Protocol.HTTP_VPACK); + ArangoDB adb = new ArangoDB.Builder() + .loadProperties(new FileConfigPropertiesProvider()) + .useProtocol(protocol) + .maxConnections(1) + .build(); + + ExecutorService es = Executors.newFixedThreadPool(3); + List> tasks = new ArrayList<>(); + for (int i = 0; i < 3; i++) { + tasks.add(es.submit(() -> adb.db().query("return sleep(1)", Void.class))); + } + + Thread.sleep(2_000); + assertThat(tasks).allMatch(Future::isDone); + adb.shutdown(); + es.shutdown(); + } + +} diff --git a/shaded-integration-tests/src/test/jackson/java/com/arangodb/SerializableTest.java b/shaded-integration-tests/src/test/jackson/java/com/arangodb/SerializableTest.java new file mode 100644 index 000000000..c1e770530 --- /dev/null +++ b/shaded-integration-tests/src/test/jackson/java/com/arangodb/SerializableTest.java @@ -0,0 +1,57 @@ +package com.arangodb; + +import com.arangodb.entity.BaseDocument; +import com.arangodb.entity.ErrorEntity; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.JsonNodeFactory; +import org.junit.jupiter.api.Test; + +import java.io.*; + +import static org.assertj.core.api.Assertions.assertThat; + +public class SerializableTest { + + @Test + public void serializeBaseDocument() throws IOException, ClassNotFoundException { + BaseDocument bd = new BaseDocument("poaids"); + bd.setId("apdso/02193"); + bd.setRevision("poip"); + bd.addAttribute("aaa", "bbb"); + + BaseDocument bd2 = roundTrip(bd); + assertThat(bd).isEqualTo(bd2); + } + + @Test + public void serializeArangoDBException() throws IOException, ClassNotFoundException { + ObjectMapper mapper = new ObjectMapper(); + JsonNode jn = JsonNodeFactory.instance.objectNode() + .put("errorMessage", "boomError") + .put("exception", "boomException") + .put("code", 11) + .put("errorNum", 22); + ErrorEntity ee = mapper.readerFor(ErrorEntity.class).readValue(jn); + ArangoDBException e = new ArangoDBException(ee); + + ArangoDBException e2 = roundTrip(e); + assertThat(e2.getException()).isEqualTo(e.getException()); + assertThat(e2.getResponseCode()).isEqualTo(e.getResponseCode()); + assertThat(e2.getErrorNum()).isEqualTo(e.getErrorNum()); + assertThat(e2.getRequestId()).isEqualTo(e.getRequestId()); + } + + private T roundTrip(T input) throws IOException, ClassNotFoundException { + ByteArrayOutputStream os = new ByteArrayOutputStream(); + ObjectOutputStream objectOutputStream = new ObjectOutputStream(os); + objectOutputStream.writeObject(input); + + InputStream is = new ByteArrayInputStream(os.toByteArray()); + ObjectInputStream objectInputStream = new ObjectInputStream(is); + T output = (T) objectInputStream.readObject(); + objectInputStream.close(); + + return output; + } +} diff --git a/shaded-integration-tests/src/test/jackson/java/com/arangodb/StreamTransactionConflictsTest.java b/shaded-integration-tests/src/test/jackson/java/com/arangodb/StreamTransactionConflictsTest.java new file mode 100644 index 000000000..1e5ed62df --- /dev/null +++ b/shaded-integration-tests/src/test/jackson/java/com/arangodb/StreamTransactionConflictsTest.java @@ -0,0 +1,119 @@ +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed 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. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb; + +import com.arangodb.entity.ArangoDBEngine; +import com.arangodb.entity.BaseDocument; +import com.arangodb.entity.StreamTransactionEntity; +import com.arangodb.model.DocumentCreateOptions; +import com.arangodb.model.StreamTransactionOptions; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + +import java.util.UUID; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.catchThrowable; +import static org.junit.jupiter.api.Assumptions.assumeTrue; + + +/** + * @author Michele Rastelli + */ +class StreamTransactionConflictsTest extends BaseJunit5 { + + private static final String COLLECTION_NAME = "db_concurrent_stream_transactions_test-" + UUID.randomUUID(); + + @BeforeAll + static void init() { + initCollections(COLLECTION_NAME); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void conflictOnInsertDocumentWithNotYetCommittedTx(ArangoDatabase db) { + assumeTrue(isSingleServer()); + assumeTrue(isAtLeastVersion(3, 5)); + assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); + + StreamTransactionEntity tx1 = db.beginStreamTransaction( + new StreamTransactionOptions().readCollections(COLLECTION_NAME).writeCollections(COLLECTION_NAME)); + + StreamTransactionEntity tx2 = db.beginStreamTransaction( + new StreamTransactionOptions().readCollections(COLLECTION_NAME).writeCollections(COLLECTION_NAME)); + + String key = UUID.randomUUID().toString(); + + // insert a document from within tx1 + db.collection(COLLECTION_NAME) + .insertDocument(new BaseDocument(key), new DocumentCreateOptions().streamTransactionId(tx1.getId())); + + // insert conflicting document from within tx2 + Throwable thrown = catchThrowable(() -> db.collection(COLLECTION_NAME).insertDocument(new BaseDocument(key), + new DocumentCreateOptions().streamTransactionId(tx2.getId()))); + assertThat(thrown).isInstanceOf(ArangoDBException.class); + ArangoDBException e = (ArangoDBException) thrown; + + if (isAtLeastVersion(3, 8)) { + assertThat(e.getResponseCode()).isEqualTo(409); + assertThat(e.getErrorNum()).isEqualTo(1200); + } + + db.abortStreamTransaction(tx1.getId()); + db.abortStreamTransaction(tx2.getId()); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void conflictOnInsertDocumentWithAlreadyCommittedTx(ArangoDatabase db) { + assumeTrue(isSingleServer()); + assumeTrue(isAtLeastVersion(3, 5)); + assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); + + StreamTransactionEntity tx1 = db.beginStreamTransaction( + new StreamTransactionOptions().readCollections(COLLECTION_NAME).writeCollections(COLLECTION_NAME)); + + StreamTransactionEntity tx2 = db.beginStreamTransaction( + new StreamTransactionOptions().readCollections(COLLECTION_NAME).writeCollections(COLLECTION_NAME)); + + String key = UUID.randomUUID().toString(); + + // insert a document from within tx1 + db.collection(COLLECTION_NAME) + .insertDocument(new BaseDocument(key), new DocumentCreateOptions().streamTransactionId(tx1.getId())); + + // commit tx1 + db.commitStreamTransaction(tx1.getId()); + + // insert conflicting document from within tx2 + Throwable thrown = catchThrowable(() -> db.collection(COLLECTION_NAME).insertDocument(new BaseDocument(key), + new DocumentCreateOptions().streamTransactionId(tx2.getId()))); + assertThat(thrown).isInstanceOf(ArangoDBException.class); + ArangoDBException e = (ArangoDBException) thrown; + if (isAtLeastVersion(3, 8)) { + assertThat(e.getResponseCode()).isEqualTo(409); + assertThat(e.getErrorNum()).isEqualTo(1200); + } + + db.abortStreamTransaction(tx2.getId()); + } +} diff --git a/shaded-integration-tests/src/test/jackson/java/com/arangodb/StreamTransactionGraphTest.java b/shaded-integration-tests/src/test/jackson/java/com/arangodb/StreamTransactionGraphTest.java new file mode 100644 index 000000000..e4d73fa33 --- /dev/null +++ b/shaded-integration-tests/src/test/jackson/java/com/arangodb/StreamTransactionGraphTest.java @@ -0,0 +1,407 @@ +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed 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. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb; + +import com.arangodb.entity.*; +import com.arangodb.model.*; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +import java.util.Collections; +import java.util.UUID; +import java.util.stream.Stream; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assumptions.assumeTrue; + + +/** + * @author Michele Rastelli + */ +class StreamTransactionGraphTest extends BaseJunit5 { + + private static final String GRAPH_NAME = "graph_stream_transaction_graph_test"; + private static final String EDGE_COLLECTION = "edge_collection_stream_transaction_graph_test"; + private static final String VERTEX_COLLECTION_1 = "vertex_collection_1_stream_transaction_graph_test"; + private static final String VERTEX_COLLECTION_2 = "vertex_collection_2_stream_transaction_graph_test"; + + private static Stream vertices() { + return dbsStream() + .map(db -> db.graph(GRAPH_NAME).vertexCollection(VERTEX_COLLECTION_1)) + .map(Arguments::of); + } + + private static Stream edges() { + return dbsStream() + .map(db -> db.graph(GRAPH_NAME).edgeCollection(EDGE_COLLECTION)) + .map(Arguments::of); + } + + @BeforeAll + static void init() { + initDB(); + initGraph(GRAPH_NAME, Collections.singletonList(new EdgeDefinition() + .collection(EDGE_COLLECTION).from(VERTEX_COLLECTION_1).to(VERTEX_COLLECTION_2) + ), null); + } + + private BaseEdgeDocument createEdgeValue(String streamTransactionId, ArangoGraph graph) { + ArangoVertexCollection vertexCollection1 = graph.vertexCollection(VERTEX_COLLECTION_1); + ArangoVertexCollection vertexCollection2 = graph.vertexCollection(VERTEX_COLLECTION_2); + VertexEntity v1 = vertexCollection1.insertVertex(new BaseDocument(), + new VertexCreateOptions().streamTransactionId(streamTransactionId)); + VertexEntity v2 = vertexCollection2.insertVertex(new BaseDocument(), + new VertexCreateOptions().streamTransactionId(streamTransactionId)); + BaseEdgeDocument value = new BaseEdgeDocument(); + value.setFrom(v1.getId()); + value.setTo(v2.getId()); + return value; + } + + @ParameterizedTest(name = "{index}") + @MethodSource("vertices") + void getVertex(ArangoVertexCollection vertexCollection1) { + assumeTrue(isSingleServer()); + assumeTrue(isAtLeastVersion(3, 5)); + assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); + + ArangoDatabase db = vertexCollection1.graph().db(); + StreamTransactionEntity tx = db + .beginStreamTransaction(new StreamTransactionOptions() + .readCollections(VERTEX_COLLECTION_1, VERTEX_COLLECTION_2, EDGE_COLLECTION) + .writeCollections(VERTEX_COLLECTION_1, VERTEX_COLLECTION_2, EDGE_COLLECTION)); + + // insert a vertex from outside the tx + VertexEntity createdVertex = vertexCollection1.insertVertex(new BaseDocument()); + + // assert that the vertex is not found from within the tx + assertThat(vertexCollection1.getVertex(createdVertex.getKey(), BaseDocument.class, + new GraphDocumentReadOptions().streamTransactionId(tx.getId()))).isNull(); + + db.abortStreamTransaction(tx.getId()); + } + + + @ParameterizedTest(name = "{index}") + @MethodSource("vertices") + void createVertex(ArangoVertexCollection vertexCollection1) { + assumeTrue(isSingleServer()); + assumeTrue(isAtLeastVersion(3, 5)); + assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); + + ArangoDatabase db = vertexCollection1.graph().db(); + StreamTransactionEntity tx = db.beginStreamTransaction( + new StreamTransactionOptions() + .readCollections(VERTEX_COLLECTION_1, VERTEX_COLLECTION_2, EDGE_COLLECTION) + .writeCollections(VERTEX_COLLECTION_1, VERTEX_COLLECTION_2, EDGE_COLLECTION)); + + // insert a vertex from within the tx + VertexEntity createdVertex = vertexCollection1.insertVertex(new BaseDocument(), + new VertexCreateOptions().streamTransactionId(tx.getId())); + + // assert that the vertex is not found from outside the tx + assertThat(vertexCollection1.getVertex(createdVertex.getKey(), BaseDocument.class, null)).isNull(); + + // assert that the vertex is found from within the tx + assertThat(vertexCollection1.getVertex(createdVertex.getKey(), BaseDocument.class, + new GraphDocumentReadOptions().streamTransactionId(tx.getId()))).isNotNull(); + + db.commitStreamTransaction(tx.getId()); + + // assert that the vertex is found after commit + assertThat(vertexCollection1.getVertex(createdVertex.getKey(), BaseDocument.class, null)).isNotNull(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("vertices") + void replaceVertex(ArangoVertexCollection vertexCollection1) { + assumeTrue(isSingleServer()); + assumeTrue(isAtLeastVersion(3, 5)); + assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); + + BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); + doc.addAttribute("test", "foo"); + + VertexEntity createdVertex = vertexCollection1.insertVertex(doc, null); + + ArangoDatabase db = vertexCollection1.graph().db(); + StreamTransactionEntity tx = db.beginStreamTransaction( + new StreamTransactionOptions() + .readCollections(VERTEX_COLLECTION_1, VERTEX_COLLECTION_2, EDGE_COLLECTION) + .writeCollections(VERTEX_COLLECTION_1, VERTEX_COLLECTION_2, EDGE_COLLECTION)); + + // replace vertex from within the tx + doc.updateAttribute("test", "bar"); + vertexCollection1.replaceVertex(createdVertex.getKey(), doc, + new VertexReplaceOptions().streamTransactionId(tx.getId())); + + // assert that the vertex has not been replaced from outside the tx + assertThat(vertexCollection1.getVertex(createdVertex.getKey(), BaseDocument.class, null) + .getProperties()).containsEntry("test", "foo"); + + // assert that the vertex has been replaced from within the tx + assertThat(vertexCollection1.getVertex(createdVertex.getKey(), BaseDocument.class, + new GraphDocumentReadOptions().streamTransactionId(tx.getId())).getProperties()).containsEntry("test" + , "bar"); + + db.commitStreamTransaction(tx.getId()); + + // assert that the vertex has been replaced after commit + assertThat(vertexCollection1.getVertex(createdVertex.getKey(), BaseDocument.class, null) + .getProperties()).containsEntry("test", "bar"); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("vertices") + void updateVertex(ArangoVertexCollection vertexCollection1) { + assumeTrue(isSingleServer()); + assumeTrue(isAtLeastVersion(3, 5)); + assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); + + BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); + doc.addAttribute("test", "foo"); + + VertexEntity createdDoc = vertexCollection1.insertVertex(doc, null); + + ArangoDatabase db = vertexCollection1.graph().db(); + StreamTransactionEntity tx = db.beginStreamTransaction( + new StreamTransactionOptions() + .readCollections(VERTEX_COLLECTION_1, VERTEX_COLLECTION_2, EDGE_COLLECTION) + .writeCollections(VERTEX_COLLECTION_1, VERTEX_COLLECTION_2, EDGE_COLLECTION)); + + // update vertex from within the tx + doc.updateAttribute("test", "bar"); + vertexCollection1.updateVertex(createdDoc.getKey(), doc, + new VertexUpdateOptions().streamTransactionId(tx.getId())); + + // assert that the vertex has not been updated from outside the tx + assertThat(vertexCollection1.getVertex(createdDoc.getKey(), BaseDocument.class, null) + .getProperties()).containsEntry("test", "foo"); + + // assert that the vertex has been updated from within the tx + assertThat(vertexCollection1.getVertex(createdDoc.getKey(), BaseDocument.class, + new GraphDocumentReadOptions().streamTransactionId(tx.getId())).getProperties()).containsEntry("test" + , "bar"); + + db.commitStreamTransaction(tx.getId()); + + // assert that the vertex has been updated after commit + assertThat(vertexCollection1.getVertex(createdDoc.getKey(), BaseDocument.class, null) + .getProperties()).containsEntry("test", "bar"); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("vertices") + void deleteVertex(ArangoVertexCollection vertexCollection1) { + assumeTrue(isSingleServer()); + assumeTrue(isAtLeastVersion(3, 5)); + assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); + + VertexEntity createdDoc = vertexCollection1.insertVertex(new BaseDocument(), null); + + ArangoDatabase db = vertexCollection1.graph().db(); + StreamTransactionEntity tx = db.beginStreamTransaction( + new StreamTransactionOptions() + .readCollections(VERTEX_COLLECTION_1, VERTEX_COLLECTION_2, EDGE_COLLECTION) + .writeCollections(VERTEX_COLLECTION_1, VERTEX_COLLECTION_2, EDGE_COLLECTION)); + + // delete vertex from within the tx + vertexCollection1.deleteVertex(createdDoc.getKey(), new VertexDeleteOptions().streamTransactionId(tx.getId())); + + // assert that the vertex has not been deleted from outside the tx + assertThat(vertexCollection1.getVertex(createdDoc.getKey(), BaseDocument.class, null)).isNotNull(); + + // assert that the vertex has been deleted from within the tx + assertThat(vertexCollection1.getVertex(createdDoc.getKey(), BaseDocument.class, + new GraphDocumentReadOptions().streamTransactionId(tx.getId()))).isNull(); + + db.commitStreamTransaction(tx.getId()); + + // assert that the vertex has been deleted after commit + assertThat(vertexCollection1.getVertex(createdDoc.getKey(), BaseDocument.class, null)).isNull(); + } + + + @ParameterizedTest(name = "{index}") + @MethodSource("edges") + void getEdge(ArangoEdgeCollection edgeCollection) { + assumeTrue(isSingleServer()); + assumeTrue(isAtLeastVersion(3, 5)); + assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); + + ArangoDatabase db = edgeCollection.graph().db(); + StreamTransactionEntity tx = db + .beginStreamTransaction(new StreamTransactionOptions() + .readCollections(VERTEX_COLLECTION_1, VERTEX_COLLECTION_2, EDGE_COLLECTION) + .writeCollections(VERTEX_COLLECTION_1, VERTEX_COLLECTION_2, EDGE_COLLECTION)); + + // insert an edge from outside the tx + EdgeEntity createdEdge = edgeCollection.insertEdge(createEdgeValue(null, edgeCollection.graph())); + + // assert that the edge is not found from within the tx + assertThat(edgeCollection.getEdge(createdEdge.getKey(), BaseEdgeDocument.class, + new GraphDocumentReadOptions().streamTransactionId(tx.getId()))).isNull(); + + db.abortStreamTransaction(tx.getId()); + } + + + @ParameterizedTest(name = "{index}") + @MethodSource("edges") + void createEdge(ArangoEdgeCollection edgeCollection) { + assumeTrue(isSingleServer()); + assumeTrue(isAtLeastVersion(3, 5)); + assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); + + ArangoDatabase db = edgeCollection.graph().db(); + StreamTransactionEntity tx = db.beginStreamTransaction( + new StreamTransactionOptions() + .readCollections(VERTEX_COLLECTION_1, VERTEX_COLLECTION_2, EDGE_COLLECTION) + .writeCollections(VERTEX_COLLECTION_1, VERTEX_COLLECTION_2, EDGE_COLLECTION)); + + // insert an edge from within the tx + EdgeEntity createdEdge = edgeCollection.insertEdge(createEdgeValue(tx.getId(), edgeCollection.graph()), + new EdgeCreateOptions().streamTransactionId(tx.getId())); + + // assert that the edge is not found from outside the tx + assertThat(edgeCollection.getEdge(createdEdge.getKey(), BaseEdgeDocument.class, null)).isNull(); + + // assert that the edge is found from within the tx + assertThat(edgeCollection.getEdge(createdEdge.getKey(), BaseEdgeDocument.class, + new GraphDocumentReadOptions().streamTransactionId(tx.getId()))).isNotNull(); + + db.commitStreamTransaction(tx.getId()); + + // assert that the edge is found after commit + assertThat(edgeCollection.getEdge(createdEdge.getKey(), BaseEdgeDocument.class, null)).isNotNull(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("edges") + void replaceEdge(ArangoEdgeCollection edgeCollection) { + assumeTrue(isSingleServer()); + assumeTrue(isAtLeastVersion(3, 5)); + assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); + + BaseEdgeDocument doc = createEdgeValue(null, edgeCollection.graph()); + doc.addAttribute("test", "foo"); + + EdgeEntity createdEdge = edgeCollection.insertEdge(doc, null); + + ArangoDatabase db = edgeCollection.graph().db(); + StreamTransactionEntity tx = db.beginStreamTransaction( + new StreamTransactionOptions() + .readCollections(VERTEX_COLLECTION_1, VERTEX_COLLECTION_2, EDGE_COLLECTION) + .writeCollections(VERTEX_COLLECTION_1, VERTEX_COLLECTION_2, EDGE_COLLECTION)); + + // replace edge from within the tx + doc.updateAttribute("test", "bar"); + edgeCollection.replaceEdge(createdEdge.getKey(), doc, + new EdgeReplaceOptions().streamTransactionId(tx.getId())); + + // assert that the edge has not been replaced from outside the tx + assertThat(edgeCollection.getEdge(createdEdge.getKey(), BaseEdgeDocument.class, null) + .getProperties()).containsEntry("test", "foo"); + + // assert that the edge has been replaced from within the tx + assertThat(edgeCollection.getEdge(createdEdge.getKey(), BaseEdgeDocument.class, + new GraphDocumentReadOptions().streamTransactionId(tx.getId())).getProperties()).containsEntry("test" + , "bar"); + + db.commitStreamTransaction(tx.getId()); + + // assert that the edge has been replaced after commit + assertThat(edgeCollection.getEdge(createdEdge.getKey(), BaseEdgeDocument.class, null) + .getProperties()).containsEntry("test", "bar"); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("edges") + void updateEdge(ArangoEdgeCollection edgeCollection) { + assumeTrue(isSingleServer()); + assumeTrue(isAtLeastVersion(3, 5)); + assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); + + BaseEdgeDocument doc = createEdgeValue(null, edgeCollection.graph()); + doc.addAttribute("test", "foo"); + + EdgeEntity createdDoc = edgeCollection.insertEdge(doc, null); + + ArangoDatabase db = edgeCollection.graph().db(); + StreamTransactionEntity tx = db.beginStreamTransaction( + new StreamTransactionOptions() + .readCollections(VERTEX_COLLECTION_1, VERTEX_COLLECTION_2, EDGE_COLLECTION) + .writeCollections(VERTEX_COLLECTION_1, VERTEX_COLLECTION_2, EDGE_COLLECTION)); + + // update edge from within the tx + doc.updateAttribute("test", "bar"); + edgeCollection.updateEdge(createdDoc.getKey(), doc, new EdgeUpdateOptions().streamTransactionId(tx.getId())); + + // assert that the edge has not been updated from outside the tx + assertThat(edgeCollection.getEdge(createdDoc.getKey(), BaseEdgeDocument.class, null) + .getProperties()).containsEntry("test", "foo"); + + // assert that the edge has been updated from within the tx + assertThat(edgeCollection.getEdge(createdDoc.getKey(), BaseEdgeDocument.class, + new GraphDocumentReadOptions().streamTransactionId(tx.getId())).getProperties()).containsEntry("test" + , "bar"); + + db.commitStreamTransaction(tx.getId()); + + // assert that the edge has been updated after commit + assertThat(edgeCollection.getEdge(createdDoc.getKey(), BaseEdgeDocument.class, null) + .getProperties()).containsEntry("test", "bar"); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("edges") + void deleteEdge(ArangoEdgeCollection edgeCollection) { + assumeTrue(isSingleServer()); + assumeTrue(isAtLeastVersion(3, 5)); + assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); + + EdgeEntity createdDoc = edgeCollection.insertEdge(createEdgeValue(null, edgeCollection.graph()), null); + + ArangoDatabase db = edgeCollection.graph().db(); + StreamTransactionEntity tx = db.beginStreamTransaction( + new StreamTransactionOptions() + .readCollections(VERTEX_COLLECTION_1, VERTEX_COLLECTION_2, EDGE_COLLECTION) + .writeCollections(VERTEX_COLLECTION_1, VERTEX_COLLECTION_2, EDGE_COLLECTION)); + + // delete edge from within the tx + edgeCollection.deleteEdge(createdDoc.getKey(), new EdgeDeleteOptions().streamTransactionId(tx.getId())); + + // assert that the edge has not been deleted from outside the tx + assertThat(edgeCollection.getEdge(createdDoc.getKey(), BaseEdgeDocument.class, null)).isNotNull(); + + // assert that the edge has been deleted from within the tx + assertThat(edgeCollection.getEdge(createdDoc.getKey(), BaseEdgeDocument.class, + new GraphDocumentReadOptions().streamTransactionId(tx.getId()))).isNull(); + + db.commitStreamTransaction(tx.getId()); + + // assert that the edge has been deleted after commit + assertThat(edgeCollection.getEdge(createdDoc.getKey(), BaseEdgeDocument.class, null)).isNull(); + } + +} diff --git a/shaded-integration-tests/src/test/jackson/java/com/arangodb/StreamTransactionTest.java b/shaded-integration-tests/src/test/jackson/java/com/arangodb/StreamTransactionTest.java new file mode 100644 index 000000000..3b47d9222 --- /dev/null +++ b/shaded-integration-tests/src/test/jackson/java/com/arangodb/StreamTransactionTest.java @@ -0,0 +1,820 @@ +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed 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. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb; + +import com.arangodb.entity.*; +import com.arangodb.model.*; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + +import java.io.IOException; +import java.util.*; +import java.util.stream.Collectors; +import java.util.stream.IntStream; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.catchThrowable; +import static org.junit.jupiter.api.Assumptions.assumeTrue; + +/** + * @author Michele Rastelli + */ +class StreamTransactionTest extends BaseJunit5 { + + private static final String COLLECTION_NAME = "StreamTransactionTest_collection"; + + @BeforeAll + static void init() { + initCollections(COLLECTION_NAME); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void beginStreamTransaction(ArangoDatabase db) { + assumeTrue(isSingleServer()); + assumeTrue(isAtLeastVersion(3, 5)); + assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); + + StreamTransactionEntity tx = db.beginStreamTransaction(null); + assertThat(tx.getId()).isNotNull(); + assertThat(tx.getStatus()).isEqualTo(StreamTransactionStatus.running); + db.abortStreamTransaction(tx.getId()); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void beginStreamTransactionWithNonExistingCollectionsShouldThrow(ArangoDatabase db) { + assumeTrue(isSingleServer()); + assumeTrue(isAtLeastVersion(3, 5)); + assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); + Throwable thrown = catchThrowable(() -> + db.beginStreamTransaction(new StreamTransactionOptions().writeCollections("notExistingCollection"))); + assertThat(thrown).isInstanceOf(ArangoDBException.class); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void abortStreamTransaction(ArangoDatabase db) { + assumeTrue(isSingleServer()); + assumeTrue(isAtLeastVersion(3, 5)); + assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); + + StreamTransactionEntity begunTx = db.beginStreamTransaction(null); + StreamTransactionEntity abortedTx = db.abortStreamTransaction(begunTx.getId()); + + assertThat(abortedTx.getId()).isNotNull(); + assertThat(abortedTx.getId()).isEqualTo(begunTx.getId()); + assertThat(abortedTx.getStatus()).isEqualTo(StreamTransactionStatus.aborted); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void abortStreamTransactionTwice(ArangoDatabase db) { + assumeTrue(isSingleServer()); + assumeTrue(isAtLeastVersion(3, 5)); + assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); + + StreamTransactionEntity begunTx = db.beginStreamTransaction(null); + db.abortStreamTransaction(begunTx.getId()); + db.abortStreamTransaction(begunTx.getId()); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void abortStreamTransactionWhenTransactionIdDoesNotExistsShouldThrow(ArangoDatabase db) { + assumeTrue(isSingleServer()); + assumeTrue(isAtLeastVersion(3, 5)); + assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); + Throwable thrown = catchThrowable(() -> db.abortStreamTransaction("000000")); + assertThat(thrown).isInstanceOf(ArangoDBException.class); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void abortStreamTransactionWithInvalidTransactionIdShouldThrow(ArangoDatabase db) { + assumeTrue(isSingleServer()); + assumeTrue(isAtLeastVersion(3, 5)); + assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); + Throwable thrown = catchThrowable(() -> db.abortStreamTransaction("invalidTransactionId")); + assertThat(thrown).isInstanceOf(ArangoDBException.class); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void abortCommittedStreamTransactionShouldThrow(ArangoDatabase db) { + assumeTrue(isSingleServer()); + assumeTrue(isAtLeastVersion(3, 5)); + assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); + + StreamTransactionEntity createdTx = db.beginStreamTransaction(null); + db.commitStreamTransaction(createdTx.getId()); + Throwable thrown = catchThrowable(() -> db.abortStreamTransaction(createdTx.getId())); + assertThat(thrown).isInstanceOf(ArangoDBException.class); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void getStreamTransaction(ArangoDatabase db) { + assumeTrue(isSingleServer()); + assumeTrue(isAtLeastVersion(3, 5)); + assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); + + StreamTransactionEntity createdTx = db.beginStreamTransaction(null); + StreamTransactionEntity gotTx = db.getStreamTransaction(createdTx.getId()); + + assertThat(gotTx.getId()).isNotNull(); + assertThat(gotTx.getId()).isEqualTo(createdTx.getId()); + assertThat(gotTx.getStatus()).isEqualTo(StreamTransactionStatus.running); + + db.abortStreamTransaction(createdTx.getId()); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void getStreamTransactionWhenTransactionIdDoesNotExistsShouldThrow(ArangoDatabase db) { + assumeTrue(isSingleServer()); + assumeTrue(isAtLeastVersion(3, 5)); + assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); + + Throwable thrown = catchThrowable(() -> db.getStreamTransaction("000000")); + assertThat(thrown).isInstanceOf(ArangoDBException.class); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void getStreamTransactionWithInvalidTransactionIdShouldThrow(ArangoDatabase db) { + assumeTrue(isSingleServer()); + assumeTrue(isAtLeastVersion(3, 5)); + assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); + + Throwable thrown = catchThrowable(() -> db.getStreamTransaction("invalidTransactionId")); + assertThat(thrown).isInstanceOf(ArangoDBException.class); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void commitStreamTransaction(ArangoDatabase db) { + assumeTrue(isSingleServer()); + assumeTrue(isAtLeastVersion(3, 5)); + assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); + + StreamTransactionEntity createdTx = db.beginStreamTransaction(null); + StreamTransactionEntity committedTx = db.commitStreamTransaction(createdTx.getId()); + + assertThat(committedTx.getId()).isNotNull(); + assertThat(committedTx.getId()).isEqualTo(createdTx.getId()); + assertThat(committedTx.getStatus()).isEqualTo(StreamTransactionStatus.committed); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void commitStreamTransactionTwice(ArangoDatabase db) { + assumeTrue(isSingleServer()); + assumeTrue(isAtLeastVersion(3, 5)); + assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); + + StreamTransactionEntity createdTx = db.beginStreamTransaction(null); + db.commitStreamTransaction(createdTx.getId()); + db.commitStreamTransaction(createdTx.getId()); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void commitStreamTransactionWhenTransactionIdDoesNotExistsShouldThrow(ArangoDatabase db) { + assumeTrue(isSingleServer()); + assumeTrue(isAtLeastVersion(3, 5)); + assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); + + Throwable thrown = catchThrowable(() -> db.commitStreamTransaction("000000")); + assertThat(thrown).isInstanceOf(ArangoDBException.class); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void commitStreamTransactionWithInvalidTransactionIdShouldThrow(ArangoDatabase db) { + assumeTrue(isSingleServer()); + assumeTrue(isAtLeastVersion(3, 5)); + assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); + + Throwable thrown = catchThrowable(() -> db.commitStreamTransaction("invalidTransactionId")); + assertThat(thrown).isInstanceOf(ArangoDBException.class); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void commitAbortedStreamTransactionShouldThrow(ArangoDatabase db) { + assumeTrue(isSingleServer()); + assumeTrue(isAtLeastVersion(3, 5)); + assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); + + StreamTransactionEntity createdTx = db.beginStreamTransaction(null); + db.abortStreamTransaction(createdTx.getId()); + Throwable thrown = catchThrowable(() -> db.commitStreamTransaction(createdTx.getId())); + assertThat(thrown).isInstanceOf(ArangoDBException.class); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void getDocument(ArangoDatabase db) { + assumeTrue(isSingleServer()); + assumeTrue(isAtLeastVersion(3, 5)); + assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); + + StreamTransactionEntity tx = db + .beginStreamTransaction(new StreamTransactionOptions().readCollections(COLLECTION_NAME)); + ArangoCollection collection = db.collection(COLLECTION_NAME); + + // insert a document from outside the tx + DocumentCreateEntity externalDoc = collection + .insertDocument(new BaseDocument(), null); + + // assert that the document is not found from within the tx + assertThat(collection.getDocument(externalDoc.getKey(), BaseDocument.class, + new DocumentReadOptions().streamTransactionId(tx.getId()))).isNull(); + + db.abortStreamTransaction(tx.getId()); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void getDocumentWithNonExistingTransactionIdShouldThrow(ArangoDatabase db) { + assumeTrue(isSingleServer()); + assumeTrue(isAtLeastVersion(3, 5)); + assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); + + ArangoCollection collection = db.collection(COLLECTION_NAME); + + Throwable thrown = catchThrowable(() -> collection + .getDocument("docId", BaseDocument.class, new DocumentReadOptions().streamTransactionId("123456"))); + assertThat(thrown).isInstanceOf(ArangoDBException.class); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void getDocumentWithInvalidTransactionIdShouldThrow(ArangoDatabase db) { + assumeTrue(isSingleServer()); + assumeTrue(isAtLeastVersion(3, 5)); + assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); + + ArangoCollection collection = db.collection(COLLECTION_NAME); + Throwable thrown = catchThrowable(() -> collection + .getDocument("docId", BaseDocument.class, new DocumentReadOptions().streamTransactionId("abcde"))); + assertThat(thrown).isInstanceOf(ArangoDBException.class); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void getDocuments(ArangoDatabase db) { + assumeTrue(isSingleServer()); + assumeTrue(isAtLeastVersion(3, 5)); + assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); + + StreamTransactionEntity tx = db + .beginStreamTransaction(new StreamTransactionOptions().readCollections(COLLECTION_NAME)); + ArangoCollection collection = db.collection(COLLECTION_NAME); + + // insert documents from outside the tx + DocumentCreateEntity externalDoc1 = collection + .insertDocument(new BaseDocument(), null); + + DocumentCreateEntity externalDoc2 = collection + .insertDocument(new BaseDocument(), null); + + // assert that the documents are not found from within the tx + MultiDocumentEntity documents = collection + .getDocuments(Arrays.asList(externalDoc1.getId(), externalDoc2.getId()), BaseDocument.class, + new DocumentReadOptions().streamTransactionId(tx.getId())); + + assertThat(documents.getDocuments()).isEmpty(); + + db.abortStreamTransaction(tx.getId()); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void insertDocument(ArangoDatabase db) { + assumeTrue(isSingleServer()); + assumeTrue(isAtLeastVersion(3, 5)); + assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); + + StreamTransactionEntity tx = db.beginStreamTransaction( + new StreamTransactionOptions().readCollections(COLLECTION_NAME).writeCollections(COLLECTION_NAME)); + ArangoCollection collection = db.collection(COLLECTION_NAME); + + // insert a document from within the tx + DocumentCreateEntity txDoc = collection + .insertDocument(new BaseDocument(), new DocumentCreateOptions().streamTransactionId(tx.getId())); + + // assert that the document is not found from outside the tx + assertThat(collection.getDocument(txDoc.getKey(), BaseDocument.class, null)).isNull(); + + // assert that the document is found from within the tx + assertThat(collection.getDocument(txDoc.getKey(), BaseDocument.class, + new DocumentReadOptions().streamTransactionId(tx.getId()))).isNotNull(); + + db.commitStreamTransaction(tx.getId()); + + // assert that the document is found after commit + assertThat(collection.getDocument(txDoc.getKey(), BaseDocument.class, null)).isNotNull(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void insertDocuments(ArangoDatabase db) { + assumeTrue(isSingleServer()); + assumeTrue(isAtLeastVersion(3, 5)); + assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); + + StreamTransactionEntity tx = db.beginStreamTransaction( + new StreamTransactionOptions().readCollections(COLLECTION_NAME).writeCollections(COLLECTION_NAME)); + ArangoCollection collection = db.collection(COLLECTION_NAME); + + // insert documents from within the tx + MultiDocumentEntity> txDocs = collection + .insertDocuments(Arrays.asList(new BaseDocument(), new BaseDocument(), new BaseDocument()), + new DocumentCreateOptions().streamTransactionId(tx.getId())); + + List keys = txDocs.getDocuments().stream().map(DocumentEntity::getKey).collect(Collectors.toList()); + + // assert that the documents are not found from outside the tx + assertThat(collection.getDocuments(keys, BaseDocument.class, null).getDocuments()).isEmpty(); + + // assert that the documents are found from within the tx + assertThat(collection + .getDocuments(keys, BaseDocument.class, new DocumentReadOptions().streamTransactionId(tx.getId())) + .getDocuments()).hasSize(keys.size()); + + db.commitStreamTransaction(tx.getId()); + + // assert that the document is found after commit + assertThat(collection.getDocuments(keys, BaseDocument.class, null).getDocuments()).hasSize(keys.size()); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void replaceDocument(ArangoDatabase db) { + assumeTrue(isSingleServer()); + assumeTrue(isAtLeastVersion(3, 5)); + assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); + + BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); + doc.addAttribute("test", "foo"); + + ArangoCollection collection = db.collection(COLLECTION_NAME); + DocumentCreateEntity createdDoc = collection.insertDocument(doc, null); + + StreamTransactionEntity tx = db.beginStreamTransaction( + new StreamTransactionOptions().readCollections(COLLECTION_NAME).writeCollections(COLLECTION_NAME)); + + // replace document from within the tx + doc.updateAttribute("test", "bar"); + collection.replaceDocument(createdDoc.getKey(), doc, + new DocumentReplaceOptions().streamTransactionId(tx.getId())); + + // assert that the document has not been replaced from outside the tx + assertThat(collection.getDocument(createdDoc.getKey(), BaseDocument.class, null) + .getProperties()).containsEntry("test", "foo"); + + // assert that the document has been replaced from within the tx + assertThat(collection.getDocument(createdDoc.getKey(), BaseDocument.class, + new DocumentReadOptions().streamTransactionId(tx.getId())).getProperties()).containsEntry("test", + "bar"); + + db.commitStreamTransaction(tx.getId()); + + // assert that the document has been replaced after commit + assertThat(collection.getDocument(createdDoc.getKey(), BaseDocument.class, null) + .getProperties()).containsEntry("test", "bar"); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void replaceDocuments(ArangoDatabase db) { + assumeTrue(isSingleServer()); + assumeTrue(isAtLeastVersion(3, 5)); + assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); + + List docs = IntStream.range(0, 3).mapToObj(it -> new BaseDocument()) + .peek(doc -> doc.addAttribute("test", "foo")).collect(Collectors.toList()); + + ArangoCollection collection = db.collection(COLLECTION_NAME); + List createdDocs = collection + .insertDocuments(docs, new DocumentCreateOptions().returnNew(true)).getDocuments().stream() + .map(DocumentCreateEntity::getNew).collect(Collectors.toList()); + + List keys = createdDocs.stream().map(BaseDocument::getKey).collect(Collectors.toList()); + + StreamTransactionEntity tx = db.beginStreamTransaction( + new StreamTransactionOptions().readCollections(COLLECTION_NAME).writeCollections(COLLECTION_NAME)); + + List modifiedDocs = createdDocs.stream().peek(doc -> { + doc.updateAttribute("test", "bar"); + }).collect(Collectors.toList()); + + // replace document from within the tx + collection + .replaceDocuments(modifiedDocs, new DocumentReplaceOptions().streamTransactionId(tx.getId())); + + // assert that the documents has not been replaced from outside the tx + collection.getDocuments(keys, BaseDocument.class, null).getDocuments().stream() + .map(it -> ((String) it.getAttribute("test"))) + .forEach(it -> assertThat(it).isEqualTo("foo")); + + // assert that the document has been replaced from within the tx + collection + .getDocuments(keys, BaseDocument.class, new DocumentReadOptions().streamTransactionId(tx.getId())) + .getDocuments().stream().map(it -> ((String) it.getAttribute("test"))) + .forEach(it -> assertThat(it).isEqualTo("bar")); + + db.commitStreamTransaction(tx.getId()); + + // assert that the document has been replaced after commit + collection.getDocuments(keys, BaseDocument.class, null).getDocuments().stream() + .map(it -> ((String) it.getAttribute("test"))) + .forEach(it -> assertThat(it).isEqualTo("bar")); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void updateDocument(ArangoDatabase db) { + assumeTrue(isSingleServer()); + assumeTrue(isAtLeastVersion(3, 5)); + assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); + + BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); + doc.addAttribute("test", "foo"); + + ArangoCollection collection = db.collection(COLLECTION_NAME); + DocumentCreateEntity createdDoc = collection.insertDocument(doc, null); + + StreamTransactionEntity tx = db.beginStreamTransaction( + new StreamTransactionOptions().readCollections(COLLECTION_NAME).writeCollections(COLLECTION_NAME)); + + // update document from within the tx + doc.updateAttribute("test", "bar"); + collection + .updateDocument(createdDoc.getKey(), doc, new DocumentUpdateOptions().streamTransactionId(tx.getId())); + + // assert that the document has not been updated from outside the tx + assertThat(collection.getDocument(createdDoc.getKey(), BaseDocument.class, null) + .getProperties()).containsEntry("test", "foo"); + + // assert that the document has been updated from within the tx + assertThat(collection.getDocument(createdDoc.getKey(), BaseDocument.class, + new DocumentReadOptions().streamTransactionId(tx.getId())).getProperties()).containsEntry("test", "bar") + ; + + db.commitStreamTransaction(tx.getId()); + + // assert that the document has been updated after commit + assertThat(collection.getDocument(createdDoc.getKey(), BaseDocument.class, null) + .getProperties()).containsEntry("test", "bar"); + + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void updateDocuments(ArangoDatabase db) { + assumeTrue(isSingleServer()); + assumeTrue(isAtLeastVersion(3, 5)); + assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); + + List docs = IntStream.range(0, 3).mapToObj(it -> new BaseDocument()) + .peek(doc -> doc.addAttribute("test", "foo")).collect(Collectors.toList()); + + ArangoCollection collection = db.collection(COLLECTION_NAME); + List createdDocs = collection + .insertDocuments(docs, new DocumentCreateOptions().returnNew(true)).getDocuments().stream() + .map(DocumentCreateEntity::getNew).collect(Collectors.toList()); + + List keys = createdDocs.stream().map(BaseDocument::getKey).collect(Collectors.toList()); + + StreamTransactionEntity tx = db.beginStreamTransaction( + new StreamTransactionOptions().readCollections(COLLECTION_NAME).writeCollections(COLLECTION_NAME)); + + List modifiedDocs = createdDocs.stream().peek(doc -> { + doc.updateAttribute("test", "bar"); + }).collect(Collectors.toList()); + + // update documents from within the tx + collection + .updateDocuments(modifiedDocs, new DocumentUpdateOptions().streamTransactionId(tx.getId())); + + // assert that the documents have not been updated from outside the tx + collection.getDocuments(keys, BaseDocument.class, null).getDocuments().stream() + .map(it -> ((String) it.getAttribute("test"))) + .forEach(it -> assertThat(it).isEqualTo("foo")); + + // assert that the documents have been updated from within the tx + collection + .getDocuments(keys, BaseDocument.class, new DocumentReadOptions().streamTransactionId(tx.getId())) + .getDocuments().stream().map(it -> ((String) it.getAttribute("test"))) + .forEach(it -> assertThat(it).isEqualTo("bar")); + + db.commitStreamTransaction(tx.getId()); + + // assert that the document has been updated after commit + collection.getDocuments(keys, BaseDocument.class, null).getDocuments().stream() + .map(it -> ((String) it.getAttribute("test"))) + .forEach(it -> assertThat(it).isEqualTo("bar")); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void deleteDocument(ArangoDatabase db) { + assumeTrue(isSingleServer()); + assumeTrue(isAtLeastVersion(3, 5)); + assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); + + ArangoCollection collection = db.collection(COLLECTION_NAME); + DocumentCreateEntity createdDoc = collection + .insertDocument(new BaseDocument(), null); + + StreamTransactionEntity tx = db.beginStreamTransaction( + new StreamTransactionOptions().readCollections(COLLECTION_NAME).writeCollections(COLLECTION_NAME)); + + // delete document from within the tx + collection + .deleteDocument(createdDoc.getKey(), new DocumentDeleteOptions().streamTransactionId(tx.getId())); + + // assert that the document has not been deleted from outside the tx + assertThat(collection.getDocument(createdDoc.getKey(), BaseDocument.class, null)).isNotNull(); + + // assert that the document has been deleted from within the tx + assertThat(collection.getDocument(createdDoc.getKey(), BaseDocument.class, + new DocumentReadOptions().streamTransactionId(tx.getId()))).isNull(); + + db.commitStreamTransaction(tx.getId()); + + // assert that the document has been deleted after commit + assertThat(collection.getDocument(createdDoc.getKey(), BaseDocument.class, null)).isNull(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void deleteDocuments(ArangoDatabase db) { + assumeTrue(isSingleServer()); + assumeTrue(isAtLeastVersion(3, 5)); + assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); + + ArangoCollection collection = db.collection(COLLECTION_NAME); + List keys = collection + .insertDocuments(Arrays.asList(new BaseDocument(), new BaseDocument(), new BaseDocument())) + .getDocuments().stream().map(DocumentEntity::getKey).collect(Collectors.toList()); + + StreamTransactionEntity tx = db.beginStreamTransaction( + new StreamTransactionOptions().readCollections(COLLECTION_NAME).writeCollections(COLLECTION_NAME)); + + // delete document from within the tx + collection + .deleteDocuments(keys, new DocumentDeleteOptions().streamTransactionId(tx.getId())); + + // assert that the documents has not been deleted from outside the tx + assertThat(collection.getDocuments(keys, BaseDocument.class, null).getDocuments()).hasSize(keys.size()); + + // assert that the document has been deleted from within the tx + assertThat(collection + .getDocuments(keys, BaseDocument.class, new DocumentReadOptions().streamTransactionId(tx.getId())) + .getDocuments()).isEmpty(); + + db.commitStreamTransaction(tx.getId()); + + // assert that the document has been deleted after commit + assertThat(collection.getDocuments(keys, BaseDocument.class, null).getDocuments()).isEmpty(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void documentExists(ArangoDatabase db) { + assumeTrue(isSingleServer()); + assumeTrue(isAtLeastVersion(3, 5)); + assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); + + StreamTransactionEntity tx = db + .beginStreamTransaction(new StreamTransactionOptions().readCollections(COLLECTION_NAME)); + ArangoCollection collection = db.collection(COLLECTION_NAME); + + // insert a document from outside the tx + DocumentCreateEntity externalDoc = collection + .insertDocument(new BaseDocument(), null); + + // assert that the document is not found from within the tx + assertThat(collection + .documentExists(externalDoc.getKey(), new DocumentExistsOptions().streamTransactionId(tx.getId()))).isFalse(); + + db.abortStreamTransaction(tx.getId()); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void count(ArangoDatabase db) { + assumeTrue(isSingleServer()); + assumeTrue(isAtLeastVersion(3, 5)); + assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); + + ArangoCollection collection = db.collection(COLLECTION_NAME); + Long initialCount = collection.count().getCount(); + + StreamTransactionEntity tx = db + .beginStreamTransaction(new StreamTransactionOptions().readCollections(COLLECTION_NAME)); + + // insert a document from outside the tx + collection.insertDocument(new BaseDocument(), null); + + // assert that the document is not counted from within the tx + assertThat(collection.count(new CollectionCountOptions().streamTransactionId(tx.getId())) + .getCount()).isEqualTo(initialCount); + + db.abortStreamTransaction(tx.getId()); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void truncate(ArangoDatabase db) { + assumeTrue(isSingleServer()); + assumeTrue(isAtLeastVersion(3, 5)); + assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); + + ArangoCollection collection = db.collection(COLLECTION_NAME); + collection.insertDocument(new BaseDocument(), null); + + StreamTransactionEntity tx = db.beginStreamTransaction( + new StreamTransactionOptions().readCollections(COLLECTION_NAME).writeCollections(COLLECTION_NAME)); + + // truncate document from within the tx + collection.truncate(new CollectionTruncateOptions().streamTransactionId(tx.getId())); + + // assert that the collection has not been truncated from outside the tx + assertThat(collection.count().getCount()).isPositive(); + + // assert that the collection has been truncated from within the tx + assertThat(collection.count(new CollectionCountOptions().streamTransactionId(tx.getId())) + .getCount()).isZero(); + + db.commitStreamTransaction(tx.getId()); + + // assert that the collection has been truncated after commit + assertThat(collection.count().getCount()).isZero(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void createCursor(ArangoDatabase db) { + assumeTrue(isSingleServer()); + assumeTrue(isAtLeastVersion(3, 5)); + assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); + + StreamTransactionEntity tx = db + .beginStreamTransaction(new StreamTransactionOptions().readCollections(COLLECTION_NAME)); + ArangoCollection collection = db.collection(COLLECTION_NAME); + + // insert a document from outside the tx + DocumentCreateEntity externalDoc = collection + .insertDocument(new BaseDocument(), null); + + final Map bindVars = new HashMap<>(); + bindVars.put("@collection", COLLECTION_NAME); + bindVars.put("key", externalDoc.getKey()); + + ArangoCursor cursor = db + .query("FOR doc IN @@collection FILTER doc._key == @key RETURN doc", bindVars, + new AqlQueryOptions().streamTransactionId(tx.getId()), BaseDocument.class); + + // assert that the document is not found from within the tx + assertThat(cursor.hasNext()).isFalse(); + + db.abortStreamTransaction(tx.getId()); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void nextCursor(ArangoDatabase db) { + assumeTrue(isSingleServer()); + assumeTrue(isAtLeastVersion(3, 5)); + assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); + + StreamTransactionEntity tx = db.beginStreamTransaction( + new StreamTransactionOptions().readCollections(COLLECTION_NAME).writeCollections(COLLECTION_NAME)); + ArangoCollection collection = db.collection(COLLECTION_NAME); + + // insert documents from within the tx + List keys = collection + .insertDocuments(IntStream.range(0, 10).mapToObj(it -> new BaseDocument()).collect(Collectors.toList()), + new DocumentCreateOptions().streamTransactionId(tx.getId())).getDocuments().stream() + .map(DocumentEntity::getKey).collect(Collectors.toList()); + + final Map bindVars = new HashMap<>(); + bindVars.put("@collection", COLLECTION_NAME); + bindVars.put("keys", keys); + + ArangoCursor cursor = db + .query("FOR doc IN @@collection FILTER CONTAINS_ARRAY(@keys, doc._key) RETURN doc", bindVars, + new AqlQueryOptions().streamTransactionId(tx.getId()).batchSize(2), BaseDocument.class); + + List docs = cursor.asListRemaining(); + + // assert that all the keys are returned from the query + assertThat(docs.stream().map(BaseDocument::getKey).collect(Collectors.toList())).containsAll(keys); + + db.abortStreamTransaction(tx.getId()); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void getStreamTransactions(ArangoDatabase db) { + assumeTrue(isSingleServer()); + assumeTrue(isAtLeastVersion(3, 5)); + assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); + + StreamTransactionEntity tx1 = db.beginStreamTransaction(null); + StreamTransactionEntity tx2 = db.beginStreamTransaction(null); + + List createdIds = Arrays.asList(tx1.getId(), tx2.getId()); + Set gotTxs = db.getStreamTransactions().stream(). + filter(it -> createdIds.contains(it.getId())).collect(Collectors.toSet()); + + assertThat(gotTxs).hasSameSizeAs(createdIds); + assertThat(gotTxs.stream() + .allMatch(it -> it.getState() == StreamTransactionStatus.running)).isTrue(); + + db.abortStreamTransaction(tx1.getId()); + db.abortStreamTransaction(tx2.getId()); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void transactionAllowImplicitFalse(ArangoDatabase db) { + assumeTrue(isSingleServer()); + assumeTrue(isAtLeastVersion(3, 5)); + assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); + + StreamTransactionEntity tx = db + .beginStreamTransaction(new StreamTransactionOptions().allowImplicit(false)); + ArangoCollection collection = db.collection(COLLECTION_NAME); + + // insert a document from outside the tx + DocumentCreateEntity externalDoc = collection + .insertDocument(new BaseDocument(), null); + + // assert that we cannot read from collection + Throwable thrown = catchThrowable(() -> collection.getDocument(externalDoc.getKey(), BaseDocument.class, + new DocumentReadOptions().streamTransactionId(tx.getId()))); + assertThat(thrown).isInstanceOf(ArangoDBException.class); + ArangoDBException e = (ArangoDBException) thrown; + assertThat(e.getResponseCode()).isEqualTo(400); + assertThat(e.getErrorNum()).isEqualTo(1652); + assertThat(e.getMessage()).contains("unregistered collection used in transaction"); + + db.abortStreamTransaction(tx.getId()); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void transactionDirtyRead(ArangoDatabase db) throws IOException { + assumeTrue(isCluster()); + assumeTrue(isAtLeastVersion(3, 10)); + + ArangoCollection collection = db.collection(COLLECTION_NAME); + DocumentCreateEntity doc = collection.insertDocument(new BaseDocument()); + + StreamTransactionEntity tx = db + .beginStreamTransaction(new StreamTransactionOptions() + .readCollections(COLLECTION_NAME) + .allowDirtyRead(true)); + + MultiDocumentEntity readDocs = collection.getDocuments(Collections.singletonList(doc.getKey()), + BaseDocument.class, + new DocumentReadOptions().streamTransactionId(tx.getId())); + + assertThat(readDocs.isPotentialDirtyRead()).isTrue(); + assertThat(readDocs.getDocuments()).hasSize(1); + + final ArangoCursor cursor = db.query("FOR i IN @@col RETURN i", + Collections.singletonMap("@col", COLLECTION_NAME), + new AqlQueryOptions().streamTransactionId(tx.getId()), BaseDocument.class); + assertThat(cursor.isPotentialDirtyRead()).isTrue(); + cursor.close(); + + db.abortStreamTransaction(tx.getId()); + } + +} diff --git a/shaded-integration-tests/src/test/jackson/java/com/arangodb/annotations/AnnotatedEntity.java b/shaded-integration-tests/src/test/jackson/java/com/arangodb/annotations/AnnotatedEntity.java new file mode 100644 index 000000000..993fff0ec --- /dev/null +++ b/shaded-integration-tests/src/test/jackson/java/com/arangodb/annotations/AnnotatedEntity.java @@ -0,0 +1,81 @@ +package com.arangodb.annotations; + +import com.arangodb.serde.jackson.*; + +import java.util.Objects; + +public class AnnotatedEntity { + + @Id + private String id; + + @Key + private String key; + + @Rev + private String rev; + + @From + private String from; + + @To + private String to; + + public AnnotatedEntity() { + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getKey() { + return key; + } + + public void setKey(String key) { + this.key = key; + } + + public String getRev() { + return rev; + } + + public void setRev(String rev) { + this.rev = rev; + } + + public String getFrom() { + return from; + } + + public void setFrom(String from) { + this.from = from; + } + + public String getTo() { + return to; + } + + public void setTo(String to) { + this.to = to; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + AnnotatedEntity that = (AnnotatedEntity) o; + return Objects.equals(getId(), that.getId()) && Objects.equals(getKey(), that.getKey()) && Objects + .equals(getRev(), that.getRev()) && Objects.equals(getFrom(), that.getFrom()) && Objects + .equals(getTo(), that.getTo()); + } + + @Override + public int hashCode() { + return Objects.hash(getId(), getKey(), getRev(), getFrom(), getTo()); + } +} diff --git a/shaded-integration-tests/src/test/jackson/java/com/arangodb/annotations/ArangoAnnotationsTest.java b/shaded-integration-tests/src/test/jackson/java/com/arangodb/annotations/ArangoAnnotationsTest.java new file mode 100644 index 000000000..e3363f3c0 --- /dev/null +++ b/shaded-integration-tests/src/test/jackson/java/com/arangodb/annotations/ArangoAnnotationsTest.java @@ -0,0 +1,64 @@ +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed 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. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.annotations; + +import com.arangodb.ContentType; +import com.arangodb.serde.ArangoSerde; +import com.arangodb.serde.jackson.JacksonSerdeProvider; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.EnumSource; + +import java.util.Map; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * @author Michele Rastelli + */ +class ArangoAnnotationsTest { + + @ParameterizedTest + @EnumSource(ContentType.class) + void documentFieldAnnotations(ContentType contentType) { + ArangoSerde mapper = new JacksonSerdeProvider().of(contentType); + + AnnotatedEntity e = new AnnotatedEntity(); + e.setId("Id"); + e.setKey("Key"); + e.setRev("Rev"); + e.setFrom("From"); + e.setTo("To"); + + byte[] serialized = mapper.serialize(e); + Map deserialized = mapper.deserialize(serialized, Map.class); + assertThat(deserialized) + .containsEntry("_id", e.getId()) + .containsEntry("_key", e.getKey()) + .containsEntry("_rev", e.getRev()) + .containsEntry("_from", e.getFrom()) + .containsEntry("_to", e.getTo()) + .hasSize(5); + + AnnotatedEntity deserializedEntity = mapper.deserialize(serialized, AnnotatedEntity.class); + assertThat(deserializedEntity).isEqualTo(e); + } + +} diff --git a/shaded-integration-tests/src/test/jackson/java/com/arangodb/async/ArangoCollectionTest.java b/shaded-integration-tests/src/test/jackson/java/com/arangodb/async/ArangoCollectionTest.java new file mode 100644 index 000000000..720b1d261 --- /dev/null +++ b/shaded-integration-tests/src/test/jackson/java/com/arangodb/async/ArangoCollectionTest.java @@ -0,0 +1,2514 @@ +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed 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. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.async; + +import com.arangodb.ArangoDBException; +import com.arangodb.entity.*; +import com.arangodb.internal.serde.SerdeUtils; +import com.arangodb.model.*; +import com.arangodb.model.DocumentImportOptions.OnDuplicate; +import com.arangodb.serde.jackson.JacksonSerde; +import com.arangodb.serde.jackson.Key; +import com.arangodb.shaded.fasterxml.jackson.databind.JsonNode; +import com.arangodb.util.RawData; +import com.arangodb.util.RawJson; +import com.fasterxml.jackson.annotation.JsonTypeInfo; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; + +import java.util.*; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutionException; +import java.util.stream.Collectors; +import java.util.stream.IntStream; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.catchThrowable; +import static org.junit.jupiter.api.Assertions.fail; +import static org.junit.jupiter.api.Assumptions.assumeTrue; + +/** + * @author Mark Vollmary + * @author Michele Rastelli + */ +class ArangoCollectionTest extends BaseTest { + + private static final String COLLECTION_NAME = "db_collection_test"; + + ArangoCollectionTest() throws ExecutionException, InterruptedException { + ArangoCollectionAsync collection = db.collection(COLLECTION_NAME); + if (!collection.exists().get()) { + collection.create().get(); + } + } + + @BeforeAll + static void setup() throws InterruptedException, ExecutionException { + db.createCollection(COLLECTION_NAME, null).get(); + } + + @AfterEach + void teardown() throws InterruptedException, ExecutionException { + db.collection(COLLECTION_NAME).drop().get(); + } + + @Test + void create() throws InterruptedException, ExecutionException { + final CollectionEntity result = db.collection(COLLECTION_NAME + "_1").create().get(); + assertThat(result).isNotNull(); + assertThat(result.getId()).isNotNull(); + db.collection(COLLECTION_NAME + "_1").drop().get(); + } + + @Test + void insertDocument() throws InterruptedException, ExecutionException { + db.collection(COLLECTION_NAME) + .insertDocument(new BaseDocument(), null) + .whenComplete((doc, ex) -> { + assertThat(ex).isNull(); + assertThat(doc.getId()).isNotNull(); + assertThat(doc.getKey()).isNotNull(); + assertThat(doc.getRev()).isNotNull(); + assertThat(doc.getNew()).isNull(); + assertThat(doc.getId()).isEqualTo(COLLECTION_NAME + "/" + doc.getKey()); + }) + .get(); + } + + @Test + void insertDocumentReturnNew() throws InterruptedException, ExecutionException { + final DocumentCreateOptions options = new DocumentCreateOptions().returnNew(true); + db.collection(COLLECTION_NAME) + .insertDocument(new BaseDocument(), options) + .whenComplete((doc, ex) -> { + assertThat(doc).isNotNull(); + assertThat(doc.getId()).isNotNull(); + assertThat(doc.getKey()).isNotNull(); + assertThat(doc.getRev()).isNotNull(); + assertThat(doc.getNew()).isNotNull(); + }) + .get(); + } + + @Test + void insertDocumentWithTypeOverwriteModeReplace() throws InterruptedException, ExecutionException { + assumeTrue(isAtLeastVersion(3, 7)); + assumeTrue(db.getSerde().getUserSerde() instanceof JacksonSerde, "polymorphic deserialization support " + + "required"); + ArangoCollectionAsync collection = db.collection(COLLECTION_NAME); + String key = UUID.randomUUID().toString(); + Dog dog = new Dog(key, "Teddy"); + Cat cat = new Cat(key, "Luna"); + + final DocumentCreateOptions options = new DocumentCreateOptions() + .returnNew(true) + .returnOld(true) + .overwriteMode(OverwriteMode.replace); + collection.insertDocument(dog, options).get(); + final DocumentCreateEntity doc = collection.insertDocument(cat, options, Animal.class).get(); + assertThat(doc).isNotNull(); + assertThat(doc.getId()).isNotNull(); + assertThat(doc.getKey()).isNotNull().isEqualTo(key); + assertThat(doc.getRev()).isNotNull(); + + assertThat(doc.getOld()) + .isNotNull() + .isInstanceOf(Dog.class); + assertThat(doc.getOld().getKey()).isEqualTo(key); + assertThat(doc.getOld().getName()).isEqualTo("Teddy"); + + assertThat(doc.getNew()) + .isNotNull() + .isInstanceOf(Cat.class); + assertThat(doc.getNew().getKey()).isEqualTo(key); + assertThat(doc.getNew().getName()).isEqualTo("Luna"); + } + + @Test + void insertDocumentWaitForSync() throws InterruptedException, ExecutionException { + final DocumentCreateOptions options = new DocumentCreateOptions().waitForSync(true); + db.collection(COLLECTION_NAME) + .insertDocument(new BaseDocument(), options) + .whenComplete((doc, ex) -> { + assertThat(doc).isNotNull(); + assertThat(doc.getId()).isNotNull(); + assertThat(doc.getKey()).isNotNull(); + assertThat(doc.getRev()).isNotNull(); + assertThat(doc.getNew()).isNull(); + }) + .get(); + } + + @Test + void insertDocumentAsJson() throws InterruptedException, ExecutionException { + db.collection(COLLECTION_NAME) + .insertDocument(RawJson.of("{\"_key\":\"docRaw\",\"a\":\"test\"}"), null) + .whenComplete((doc, ex) -> { + assertThat(doc).isNotNull(); + assertThat(doc.getId()).isNotNull(); + assertThat(doc.getKey()).isNotNull(); + assertThat(doc.getRev()).isNotNull(); + }) + .get(); + } + + @Test + void getDocument() throws InterruptedException, ExecutionException { + final DocumentCreateEntity createResult = db.collection(COLLECTION_NAME) + .insertDocument(new BaseDocument(), null).get(); + assertThat(createResult.getKey()).isNotNull(); + db.collection(COLLECTION_NAME).getDocument(createResult.getKey(), BaseDocument.class, null) + .whenComplete((readResult, ex) -> { + assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); + assertThat(readResult.getId()).isEqualTo(COLLECTION_NAME + "/" + createResult.getKey()); + }) + .get(); + } + + @Test + void getDocumentIfMatch() throws InterruptedException, ExecutionException { + final DocumentCreateEntity createResult = db.collection(COLLECTION_NAME) + .insertDocument(new BaseDocument(), null).get(); + assertThat(createResult.getKey()).isNotNull(); + final DocumentReadOptions options = new DocumentReadOptions().ifMatch(createResult.getRev()); + db.collection(COLLECTION_NAME).getDocument(createResult.getKey(), BaseDocument.class, options) + .whenComplete((readResult, ex) -> { + assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); + assertThat(readResult.getId()).isEqualTo(COLLECTION_NAME + "/" + createResult.getKey()); + }) + .get(); + } + + @Test + void getDocumentIfMatchFail() throws InterruptedException, ExecutionException { + final DocumentCreateEntity createResult = db.collection(COLLECTION_NAME) + .insertDocument(new BaseDocument(), null).get(); + assertThat(createResult.getKey()).isNotNull(); + final DocumentReadOptions options = new DocumentReadOptions().ifMatch("no"); + db.collection(COLLECTION_NAME).getDocument(createResult.getKey(), BaseDocument.class, options) + .whenComplete((doc, ex) -> assertThat(doc).isNull()) + .get(); + } + + @Test + void getDocumentIfNoneMatch() throws InterruptedException, ExecutionException { + final DocumentCreateEntity createResult = db.collection(COLLECTION_NAME) + .insertDocument(new BaseDocument(), null).get(); + assertThat(createResult.getKey()).isNotNull(); + final DocumentReadOptions options = new DocumentReadOptions().ifNoneMatch("no"); + db.collection(COLLECTION_NAME).getDocument(createResult.getKey(), BaseDocument.class, options) + .whenComplete((readResult, ex) -> { + assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); + assertThat(readResult.getId()).isEqualTo(COLLECTION_NAME + "/" + createResult.getKey()); + }) + .get(); + } + + @Test + void getDocumentIfNoneMatchFail() throws InterruptedException, ExecutionException { + final DocumentCreateEntity createResult = db.collection(COLLECTION_NAME) + .insertDocument(new BaseDocument(), null).get(); + assertThat(createResult.getKey()).isNotNull(); + final DocumentReadOptions options = new DocumentReadOptions().ifNoneMatch(createResult.getRev()); + db.collection(COLLECTION_NAME).getDocument(createResult.getKey(), BaseDocument.class, options) + .whenComplete((doc, ex) -> assertThat(doc).isNull()) + .get(); + } + + @Test + void getDocumentAsJson() throws InterruptedException, ExecutionException { + db.collection(COLLECTION_NAME).insertDocument(RawJson.of("{\"_key\":\"docRaw\",\"a\":\"test\"}")).get(); + db.collection(COLLECTION_NAME).getDocument("docRaw", RawJson.class) + .whenComplete((readResult, ex) -> { + assertThat(readResult.getValue().contains("\"_key\":\"docRaw\"")).isEqualTo(true); + assertThat(readResult.getValue().contains("\"_id\":\"db_collection_test/docRaw\"")).isEqualTo(true); + }) + .get(); + } + + @Test + void getDocumentNotFound() throws InterruptedException, ExecutionException { + db.collection(COLLECTION_NAME).getDocument("no", BaseDocument.class) + .whenComplete((doc, ex) -> assertThat(doc).isNull()) + .get(); + } + + @Test + void getDocumentWrongKey() { + Throwable thrown = catchThrowable(() -> db.collection(COLLECTION_NAME).getDocument("no/no", + BaseDocument.class)); + assertThat(thrown).isInstanceOf(ArangoDBException.class); + } + + @Test + void getDocuments() throws InterruptedException, ExecutionException { + final Collection values = new ArrayList<>(); + values.add(new BaseDocument("1")); + values.add(new BaseDocument("2")); + values.add(new BaseDocument("3")); + db.collection(COLLECTION_NAME).insertDocuments(values).get(); + final MultiDocumentEntity documents = db.collection(COLLECTION_NAME) + .getDocuments(Arrays.asList("1", "2", "3"), BaseDocument.class).get(); + assertThat(documents).isNotNull(); + assertThat(documents.getDocuments()).hasSize(3); + for (final BaseDocument document : documents.getDocuments()) { + assertThat(document.getId()).isIn(COLLECTION_NAME + "/" + "1", COLLECTION_NAME + "/" + "2", + COLLECTION_NAME + "/" + "3"); + } + } + + @Test + void getDocumentsNotFound() throws InterruptedException, ExecutionException { + final MultiDocumentEntity readResult = db.collection(COLLECTION_NAME) + .getDocuments(Collections.singleton("no"), BaseDocument.class).get(); + assertThat(readResult).isNotNull(); + assertThat(readResult.getDocuments()).isEmpty(); + assertThat(readResult.getErrors()).hasSize(1); + } + + @Test + void getDocumentsWrongKey() throws InterruptedException, ExecutionException { + final MultiDocumentEntity readResult = db.collection(COLLECTION_NAME) + .getDocuments(Collections.singleton("no/no"), BaseDocument.class).get(); + assertThat(readResult).isNotNull(); + assertThat(readResult.getDocuments()).isEmpty(); + assertThat(readResult.getErrors()).hasSize(1); + } + + @Test + void updateDocument() throws InterruptedException, ExecutionException { + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); + doc.addAttribute("a", "test"); + doc.addAttribute("c", "test"); + final DocumentCreateEntity createResult = db.collection(COLLECTION_NAME).insertDocument(doc, null) + .get(); + doc.updateAttribute("a", "test1"); + doc.addAttribute("b", "test"); + doc.updateAttribute("c", null); + + final CompletableFuture> f = db.collection(COLLECTION_NAME) + .updateDocument(createResult.getKey(), doc, null); + f.whenComplete((updateResult, ex) -> { + assertThat(updateResult).isNotNull(); + assertThat(updateResult.getId()).isEqualTo(createResult.getId()); + assertThat(updateResult.getNew()).isNull(); + assertThat(updateResult.getOld()).isNull(); + assertThat(updateResult.getRev()).isNotEqualTo(updateResult.getOldRev()); + assertThat(updateResult.getOldRev()).isEqualTo(createResult.getRev()); + }).get(); + final DocumentUpdateEntity updateResult = f.get(); + + final BaseDocument readResult = db.collection(COLLECTION_NAME) + .getDocument(createResult.getKey(), BaseDocument.class, null).get(); + assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); + assertThat(readResult.getAttribute("a")).isNotNull(); + assertThat(String.valueOf(readResult.getAttribute("a"))).isEqualTo("test1"); + assertThat(readResult.getAttribute("b")).isNotNull(); + assertThat(String.valueOf(readResult.getAttribute("b"))).isEqualTo("test"); + assertThat(readResult.getRevision()).isEqualTo(updateResult.getRev()); + assertThat(readResult.getProperties()).containsKey("c"); + } + + @Test + void updateDocumentWithDifferentReturnType() throws ExecutionException, InterruptedException { + ArangoCollectionAsync collection = db.collection(COLLECTION_NAME); + final String key = "key-" + UUID.randomUUID(); + final BaseDocument doc = new BaseDocument(key); + doc.addAttribute("a", "test"); + collection.insertDocument(doc).get(); + + final DocumentUpdateEntity updateResult = collection + .updateDocument(key, Collections.singletonMap("b", "test"), + new DocumentUpdateOptions().returnNew(true), BaseDocument.class).get(); + assertThat(updateResult).isNotNull(); + assertThat(updateResult.getKey()).isEqualTo(key); + BaseDocument updated = updateResult.getNew(); + assertThat(updated).isNotNull(); + assertThat(updated.getAttribute("a")).isEqualTo("test"); + assertThat(updated.getAttribute("b")).isEqualTo("test"); + } + + @Test + void updateDocumentIfMatch() throws InterruptedException, ExecutionException { + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); + doc.addAttribute("a", "test"); + doc.addAttribute("c", "test"); + final DocumentCreateEntity createResult = db.collection(COLLECTION_NAME).insertDocument(doc, null) + .get(); + doc.updateAttribute("a", "test1"); + doc.addAttribute("b", "test"); + doc.updateAttribute("c", null); + final DocumentUpdateOptions options = new DocumentUpdateOptions().ifMatch(createResult.getRev()); + final CompletableFuture> f = db.collection(COLLECTION_NAME) + .updateDocument(createResult.getKey(), doc, options); + assertThat(f).isNotNull(); + f.whenComplete((updateResult, ex) -> { + assertThat(updateResult).isNotNull(); + assertThat(updateResult.getId()).isEqualTo(createResult.getId()); + assertThat(updateResult.getRev()).isNotEqualTo(updateResult.getOldRev()); + assertThat(updateResult.getOldRev()).isEqualTo(createResult.getRev()); + }).get(); + final DocumentUpdateEntity updateResult = f.get(); + + final BaseDocument readResult = db.collection(COLLECTION_NAME) + .getDocument(createResult.getKey(), BaseDocument.class, null).get(); + assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); + assertThat(readResult.getAttribute("a")).isNotNull(); + assertThat(String.valueOf(readResult.getAttribute("a"))).isEqualTo("test1"); + assertThat(readResult.getAttribute("b")).isNotNull(); + assertThat(String.valueOf(readResult.getAttribute("b"))).isEqualTo("test"); + assertThat(readResult.getRevision()).isEqualTo(updateResult.getRev()); + assertThat(readResult.getProperties()).containsKey("c"); + } + + @Test + void updateDocumentIfMatchFail() throws InterruptedException, ExecutionException { + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); + doc.addAttribute("a", "test"); + doc.addAttribute("c", "test"); + final DocumentCreateEntity createResult = db.collection(COLLECTION_NAME).insertDocument(doc, null) + .get(); + doc.updateAttribute("a", "test1"); + doc.addAttribute("b", "test"); + doc.updateAttribute("c", null); + try { + final DocumentUpdateOptions options = new DocumentUpdateOptions().ifMatch("no"); + db.collection(COLLECTION_NAME).updateDocument(createResult.getKey(), doc, options).get(); + fail(); + } catch (final ExecutionException e) { + assertThat(e.getCause()).isInstanceOf(ArangoDBException.class); + } + } + + @Test + void updateDocumentReturnNew() throws InterruptedException, ExecutionException { + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); + doc.addAttribute("a", "test"); + final DocumentCreateEntity createResult = db.collection(COLLECTION_NAME).insertDocument(doc, null) + .get(); + doc.updateAttribute("a", "test1"); + doc.addAttribute("b", "test"); + final DocumentUpdateOptions options = new DocumentUpdateOptions().returnNew(true); + db.collection(COLLECTION_NAME).updateDocument(createResult.getKey(), doc, options) + .whenComplete((updateResult, ex) -> { + assertThat(updateResult).isNotNull(); + assertThat(updateResult.getId()).isEqualTo(createResult.getId()); + assertThat(updateResult.getOldRev()).isEqualTo(createResult.getRev()); + assertThat(updateResult.getNew()).isNotNull(); + assertThat(updateResult.getNew().getKey()).isEqualTo(createResult.getKey()); + assertThat(updateResult.getNew().getRevision()).isNotEqualTo(createResult.getRev()); + assertThat(updateResult.getNew().getAttribute("a")).isNotNull(); + assertThat(String.valueOf(updateResult.getNew().getAttribute("a"))).isEqualTo("test1"); + assertThat(updateResult.getNew().getAttribute("b")).isNotNull(); + assertThat(String.valueOf(updateResult.getNew().getAttribute("b"))).isEqualTo("test"); + }) + .get(); + } + + @Test + void updateDocumentReturnOld() throws InterruptedException, ExecutionException { + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); + doc.addAttribute("a", "test"); + final DocumentCreateEntity createResult = db.collection(COLLECTION_NAME).insertDocument(doc, null) + .get(); + doc.updateAttribute("a", "test1"); + doc.addAttribute("b", "test"); + final DocumentUpdateOptions options = new DocumentUpdateOptions().returnOld(true); + db.collection(COLLECTION_NAME).updateDocument(createResult.getKey(), doc, options) + .whenComplete((updateResult, ex) -> { + assertThat(updateResult).isNotNull(); + assertThat(updateResult.getId()).isEqualTo(createResult.getId()); + assertThat(updateResult.getOldRev()).isEqualTo(createResult.getRev()); + assertThat(updateResult.getOld()).isNotNull(); + assertThat(updateResult.getOld().getKey()).isEqualTo(createResult.getKey()); + assertThat(updateResult.getOld().getRevision()).isEqualTo(createResult.getRev()); + assertThat(updateResult.getOld().getAttribute("a")).isNotNull(); + assertThat(String.valueOf(updateResult.getOld().getAttribute("a"))).isEqualTo("test"); + assertThat(updateResult.getOld().getProperties().keySet()).doesNotContain("b"); + }) + .get(); + } + + @Test + void updateDocumentKeepNullTrue() throws InterruptedException, ExecutionException { + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); + doc.addAttribute("a", "test"); + final DocumentCreateEntity createResult = db.collection(COLLECTION_NAME).insertDocument(doc, null) + .get(); + doc.updateAttribute("a", null); + final DocumentUpdateOptions options = new DocumentUpdateOptions().keepNull(true); + db.collection(COLLECTION_NAME).updateDocument(createResult.getKey(), doc, options) + .whenComplete((updateResult, ex) -> { + assertThat(updateResult).isNotNull(); + assertThat(updateResult.getId()).isEqualTo(createResult.getId()); + assertThat(updateResult.getRev()).isNotEqualTo(updateResult.getOldRev()); + assertThat(updateResult.getOldRev()).isEqualTo(createResult.getRev()); + }) + .get(); + + final BaseDocument readResult = db.collection(COLLECTION_NAME) + .getDocument(createResult.getKey(), BaseDocument.class, null).get(); + assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); + assertThat(readResult.getProperties()).containsKey("a"); + } + + @Test + void updateDocumentKeepNullFalse() throws InterruptedException, ExecutionException { + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); + doc.addAttribute("a", "test"); + final DocumentCreateEntity createResult = db.collection(COLLECTION_NAME).insertDocument(doc, null) + .get(); + doc.updateAttribute("a", null); + final DocumentUpdateOptions options = new DocumentUpdateOptions().keepNull(false); + db.collection(COLLECTION_NAME).updateDocument(createResult.getKey(), doc, options) + .whenComplete((updateResult, ex) -> { + assertThat(updateResult).isNotNull(); + assertThat(updateResult.getId()).isEqualTo(createResult.getId()); + assertThat(updateResult.getRev()).isNotEqualTo(updateResult.getOldRev()); + assertThat(updateResult.getOldRev()).isEqualTo(createResult.getRev()); + }) + .get(); + + final BaseDocument readResult = db.collection(COLLECTION_NAME) + .getDocument(createResult.getKey(), BaseDocument.class, null).get(); + assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); + assertThat(readResult.getId()).isEqualTo(createResult.getId()); + assertThat(readResult.getRevision()).isNotNull(); + assertThat(readResult.getProperties().keySet()).doesNotContain("a"); + } + + @Test + void updateDocumentMergeObjectsTrue() throws InterruptedException, ExecutionException { + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); + final Map a = new HashMap<>(); + a.put("a", "test"); + doc.addAttribute("a", a); + final DocumentCreateEntity createResult = db.collection(COLLECTION_NAME).insertDocument(doc, null) + .get(); + a.clear(); + a.put("b", "test"); + doc.updateAttribute("a", a); + final DocumentUpdateOptions options = new DocumentUpdateOptions().mergeObjects(true); + db.collection(COLLECTION_NAME).updateDocument(createResult.getKey(), doc, options) + .whenComplete((updateResult, ex) -> { + assertThat(updateResult).isNotNull(); + assertThat(updateResult.getId()).isEqualTo(createResult.getId()); + assertThat(updateResult.getRev()).isNotEqualTo(updateResult.getOldRev()); + assertThat(updateResult.getOldRev()).isEqualTo(createResult.getRev()); + }) + .get(); + + final BaseDocument readResult = db.collection(COLLECTION_NAME) + .getDocument(createResult.getKey(), BaseDocument.class, null).get(); + assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); + final Object aResult = readResult.getAttribute("a"); + assertThat(aResult).isInstanceOf(Map.class); + final Map aMap = (Map) aResult; + assertThat(aMap).containsKey("a"); + assertThat(aMap).containsKey("b"); + } + + @Test + void updateDocumentMergeObjectsFalse() throws InterruptedException, ExecutionException { + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); + final Map a = new HashMap<>(); + a.put("a", "test"); + doc.addAttribute("a", a); + final DocumentCreateEntity createResult = db.collection(COLLECTION_NAME).insertDocument(doc, null) + .get(); + a.clear(); + a.put("b", "test"); + doc.updateAttribute("a", a); + final DocumentUpdateOptions options = new DocumentUpdateOptions().mergeObjects(false); + db.collection(COLLECTION_NAME).updateDocument(createResult.getKey(), doc, options) + .whenComplete((updateResult, ex) -> { + assertThat(updateResult).isNotNull(); + assertThat(updateResult.getId()).isEqualTo(createResult.getId()); + assertThat(updateResult.getRev()).isNotEqualTo(updateResult.getOldRev()); + assertThat(updateResult.getOldRev()).isEqualTo(createResult.getRev()); + }) + .get(); + + final BaseDocument readResult = db.collection(COLLECTION_NAME) + .getDocument(createResult.getKey(), BaseDocument.class, null).get(); + assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); + final Object aResult = readResult.getAttribute("a"); + assertThat(aResult).isInstanceOf(Map.class); + final Map aMap = (Map) aResult; + assertThat(aMap.keySet()).doesNotContain("a"); + assertThat(aMap).containsKey("b"); + } + + @Test + void updateDocumentIgnoreRevsFalse() throws InterruptedException, ExecutionException { + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); + doc.addAttribute("a", "test"); + final DocumentCreateEntity createResult = db.collection(COLLECTION_NAME).insertDocument(doc, null) + .get(); + doc.updateAttribute("a", "test1"); + doc.setRevision("no"); + try { + final DocumentUpdateOptions options = new DocumentUpdateOptions().ignoreRevs(false); + db.collection(COLLECTION_NAME).updateDocument(createResult.getKey(), doc, options).get(); + fail(); + } catch (final ExecutionException e) { + assertThat(e.getCause()).isInstanceOf(ArangoDBException.class); + } + } + + @Test + void replaceDocument() throws InterruptedException, ExecutionException { + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); + doc.addAttribute("a", "test"); + final DocumentCreateEntity createResult = db.collection(COLLECTION_NAME).insertDocument(doc, null) + .get(); + doc.removeAttribute("a"); + doc.addAttribute("b", "test"); + final CompletableFuture> f = db.collection(COLLECTION_NAME) + .replaceDocument(createResult.getKey(), doc, null); + f.whenComplete((replaceResult, ex) -> { + assertThat(replaceResult).isNotNull(); + assertThat(replaceResult.getId()).isEqualTo(createResult.getId()); + assertThat(replaceResult.getNew()).isNull(); + assertThat(replaceResult.getOld()).isNull(); + assertThat(replaceResult.getRev()).isNotEqualTo(replaceResult.getOldRev()); + assertThat(replaceResult.getOldRev()).isEqualTo(createResult.getRev()); + }).get(); + final DocumentUpdateEntity replaceResult = f.get(); + + final BaseDocument readResult = db.collection(COLLECTION_NAME) + .getDocument(createResult.getKey(), BaseDocument.class, null).get(); + assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); + assertThat(readResult.getRevision()).isEqualTo(replaceResult.getRev()); + assertThat(readResult.getProperties().keySet()).doesNotContain("a"); + assertThat(readResult.getAttribute("b")).isNotNull(); + assertThat(String.valueOf(readResult.getAttribute("b"))).isEqualTo("test"); + } + + @Test + void replaceDocumentIfMatch() throws InterruptedException, ExecutionException { + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); + doc.addAttribute("a", "test"); + final DocumentCreateEntity createResult = db.collection(COLLECTION_NAME).insertDocument(doc, null) + .get(); + doc.removeAttribute("a"); + doc.addAttribute("b", "test"); + final DocumentReplaceOptions options = new DocumentReplaceOptions().ifMatch(createResult.getRev()); + final CompletableFuture> f = db.collection(COLLECTION_NAME) + .replaceDocument(createResult.getKey(), doc, options); + f.whenComplete((replaceResult, ex) -> { + assertThat(replaceResult).isNotNull(); + assertThat(replaceResult.getId()).isEqualTo(createResult.getId()); + assertThat(replaceResult.getRev()).isNotEqualTo(replaceResult.getOldRev()); + assertThat(replaceResult.getOldRev()).isEqualTo(createResult.getRev()); + }).get(); + final DocumentUpdateEntity replaceResult = f.get(); + + final BaseDocument readResult = db.collection(COLLECTION_NAME) + .getDocument(createResult.getKey(), BaseDocument.class, null).get(); + assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); + assertThat(readResult.getRevision()).isEqualTo(replaceResult.getRev()); + assertThat(readResult.getProperties().keySet()).doesNotContain("a"); + assertThat(readResult.getAttribute("b")).isNotNull(); + assertThat(String.valueOf(readResult.getAttribute("b"))).isEqualTo("test"); + } + + @Test + void replaceDocumentIfMatchFail() throws InterruptedException, ExecutionException { + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); + doc.addAttribute("a", "test"); + final DocumentCreateEntity createResult = db.collection(COLLECTION_NAME).insertDocument(doc, null) + .get(); + doc.removeAttribute("a"); + doc.addAttribute("b", "test"); + try { + final DocumentReplaceOptions options = new DocumentReplaceOptions().ifMatch("no"); + db.collection(COLLECTION_NAME).replaceDocument(createResult.getKey(), doc, options).get(); + fail(); + } catch (final ExecutionException e) { + assertThat(e.getCause()).isInstanceOf(ArangoDBException.class); + } + } + + @Test + void replaceDocumentIgnoreRevsFalse() throws InterruptedException, ExecutionException { + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); + doc.addAttribute("a", "test"); + final DocumentCreateEntity createResult = db.collection(COLLECTION_NAME).insertDocument(doc, null) + .get(); + doc.removeAttribute("a"); + doc.addAttribute("b", "test"); + doc.setRevision("no"); + try { + final DocumentReplaceOptions options = new DocumentReplaceOptions().ignoreRevs(false); + db.collection(COLLECTION_NAME).replaceDocument(createResult.getKey(), doc, options).get(); + fail(); + } catch (final ExecutionException e) { + assertThat(e.getCause()).isInstanceOf(ArangoDBException.class); + } + } + + @Test + void replaceDocumentReturnNew() throws InterruptedException, ExecutionException { + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); + doc.addAttribute("a", "test"); + final DocumentCreateEntity createResult = db.collection(COLLECTION_NAME).insertDocument(doc, null) + .get(); + doc.removeAttribute("a"); + doc.addAttribute("b", "test"); + final DocumentReplaceOptions options = new DocumentReplaceOptions().returnNew(true); + db.collection(COLLECTION_NAME).replaceDocument(createResult.getKey(), doc, options) + .whenComplete((replaceResult, ex) -> { + assertThat(replaceResult).isNotNull(); + assertThat(replaceResult.getId()).isEqualTo(createResult.getId()); + assertThat(replaceResult.getOldRev()).isEqualTo(createResult.getRev()); + assertThat(replaceResult.getNew()).isNotNull(); + assertThat(replaceResult.getNew().getKey()).isEqualTo(createResult.getKey()); + assertThat(replaceResult.getNew().getRevision()).isNotEqualTo(createResult.getRev()); + assertThat(replaceResult.getNew().getProperties().keySet()).doesNotContain("a"); + assertThat(replaceResult.getNew().getAttribute("b")).isNotNull(); + assertThat(String.valueOf(replaceResult.getNew().getAttribute("b"))).isEqualTo("test"); + }) + .get(); + } + + @Test + void replaceDocumentReturnOld() throws InterruptedException, ExecutionException { + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); + doc.addAttribute("a", "test"); + final DocumentCreateEntity createResult = db.collection(COLLECTION_NAME).insertDocument(doc, null) + .get(); + doc.removeAttribute("a"); + doc.addAttribute("b", "test"); + final DocumentReplaceOptions options = new DocumentReplaceOptions().returnOld(true); + db.collection(COLLECTION_NAME).replaceDocument(createResult.getKey(), doc, options) + .whenComplete((replaceResult, ex) -> { + assertThat(replaceResult).isNotNull(); + assertThat(replaceResult.getId()).isEqualTo(createResult.getId()); + assertThat(replaceResult.getOldRev()).isEqualTo(createResult.getRev()); + assertThat(replaceResult.getOld()).isNotNull(); + assertThat(replaceResult.getOld().getKey()).isEqualTo(createResult.getKey()); + assertThat(replaceResult.getOld().getRevision()).isEqualTo(createResult.getRev()); + assertThat(replaceResult.getOld().getAttribute("a")).isNotNull(); + assertThat(String.valueOf(replaceResult.getOld().getAttribute("a"))).isEqualTo("test"); + assertThat(replaceResult.getOld().getProperties().keySet()).doesNotContain("b"); + }) + .get(); + } + + @Test + void deleteDocument() throws InterruptedException, ExecutionException { + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); + final DocumentCreateEntity createResult = db.collection(COLLECTION_NAME).insertDocument(doc, null) + .get(); + db.collection(COLLECTION_NAME).deleteDocument(createResult.getKey()).get(); + db.collection(COLLECTION_NAME).getDocument(createResult.getKey(), BaseDocument.class, null) + .whenComplete((document, ex) -> assertThat(document).isNull()) + .get(); + } + + @Test + void deleteDocumentReturnOld() throws InterruptedException, ExecutionException { + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); + doc.addAttribute("a", "test"); + final DocumentCreateEntity createResult = db.collection(COLLECTION_NAME).insertDocument(doc, null) + .get(); + final DocumentDeleteOptions options = new DocumentDeleteOptions().returnOld(true); + db.collection(COLLECTION_NAME).deleteDocument(createResult.getKey(), options, BaseDocument.class) + .whenComplete((deleteResult, ex) -> { + assertThat(deleteResult.getOld()).isNotNull(); + assertThat(deleteResult.getOld()).isInstanceOf(BaseDocument.class); + assertThat(deleteResult.getOld().getAttribute("a")).isNotNull(); + assertThat(String.valueOf(deleteResult.getOld().getAttribute("a"))).isEqualTo("test"); + }) + .get(); + } + + @Test + void deleteDocumentIfMatch() throws InterruptedException, ExecutionException { + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); + final DocumentCreateEntity createResult = db.collection(COLLECTION_NAME).insertDocument(doc, null) + .get(); + final DocumentDeleteOptions options = new DocumentDeleteOptions().ifMatch(createResult.getRev()); + db.collection(COLLECTION_NAME).deleteDocument(createResult.getKey(), options).get(); + db.collection(COLLECTION_NAME).getDocument(createResult.getKey(), BaseDocument.class, null) + .whenComplete((document, ex) -> assertThat(document).isNull()) + .get(); + } + + @Test + void deleteDocumentIfMatchFail() throws InterruptedException, ExecutionException { + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); + final DocumentCreateEntity createResult = db.collection(COLLECTION_NAME).insertDocument(doc, null) + .get(); + final DocumentDeleteOptions options = new DocumentDeleteOptions().ifMatch("no"); + try { + db.collection(COLLECTION_NAME).deleteDocument(createResult.getKey(), options).get(); + fail(); + } catch (final ExecutionException e) { + assertThat(e.getCause()).isInstanceOf(ArangoDBException.class); + } + } + + @Test + void getIndex() throws InterruptedException, ExecutionException { + final Collection fields = new ArrayList<>(); + fields.add("a"); + final IndexEntity createResult = db.collection(COLLECTION_NAME).ensureHashIndex(fields, null).get(); + db.collection(COLLECTION_NAME).getIndex(createResult.getId()) + .whenComplete((readResult, ex) -> { + assertThat(readResult.getId()).isEqualTo(createResult.getId()); + assertThat(readResult.getType()).isEqualTo(createResult.getType()); + }) + .get(); + } + + @Test + void getIndexByKey() throws InterruptedException, ExecutionException { + final Collection fields = new ArrayList<>(); + fields.add("a"); + final IndexEntity createResult = db.collection(COLLECTION_NAME).ensureHashIndex(fields, null).get(); + db.collection(COLLECTION_NAME).getIndex(createResult.getId().split("/")[1]) + .whenComplete((readResult, ex) -> { + assertThat(readResult.getId()).isEqualTo(createResult.getId()); + assertThat(readResult.getType()).isEqualTo(createResult.getType()); + }) + .get(); + } + + @Test + void deleteIndex() throws InterruptedException, ExecutionException { + final Collection fields = new ArrayList<>(); + fields.add("deleteIndexField"); + final IndexEntity createResult = db.collection(COLLECTION_NAME).ensureHashIndex(fields, null).get(); + db.getIndex(createResult.getId()).get(); + db.collection(COLLECTION_NAME).deleteIndex(createResult.getId()) + .whenComplete((id, ex) -> { + assertThat(id).isEqualTo(createResult.getId()); + try { + db.getIndex(id).get(); + fail(); + } catch (final InterruptedException exception) { + exception.printStackTrace(); + fail(); + } catch (final ExecutionException exception) { + assertThat(exception.getCause()).isInstanceOf(ArangoDBException.class); + } + }) + .get(); + } + + @Test + void deleteIndexByKey() throws InterruptedException, ExecutionException { + final Collection fields = new ArrayList<>(); + fields.add("deleteIndexByKeyField"); + final IndexEntity createResult = db.collection(COLLECTION_NAME).ensureHashIndex(fields, null).get(); + db.getIndex(createResult.getId()).get(); + db.collection(COLLECTION_NAME).deleteIndex(createResult.getId().split("/")[1]) + .whenComplete((id, ex) -> { + assertThat(id).isEqualTo(createResult.getId()); + try { + db.getIndex(id).get(); + fail(); + } catch (final InterruptedException exception) { + exception.printStackTrace(); + fail(); + } catch (final ExecutionException exception) { + assertThat(exception.getCause()).isInstanceOf(ArangoDBException.class); + } + }) + .get(); + } + + @Test + void createHashIndex() throws InterruptedException, ExecutionException { + final boolean singleServer = isSingleServer(); + final Collection fields = new ArrayList<>(); + fields.add("a"); + fields.add("b"); + db.collection(COLLECTION_NAME).ensureHashIndex(fields, null) + .whenComplete((indexResult, ex) -> { + assertThat(indexResult).isNotNull(); + assertThat(indexResult.getConstraint()).isNull(); + assertThat(indexResult.getFields()).contains("a"); + assertThat(indexResult.getFields()).contains("b"); + assertThat(indexResult.getGeoJson()).isNull(); + assertThat(indexResult.getId()).startsWith(COLLECTION_NAME); + assertThat(indexResult.getIsNewlyCreated()).isEqualTo(true); + assertThat(indexResult.getMinLength()).isNull(); + if (singleServer) { + assertThat(indexResult.getSelectivityEstimate()).isEqualTo(1.0); + } + assertThat(indexResult.getSparse()).isEqualTo(false); + assertThat(indexResult.getType()).isEqualTo(IndexType.hash); + assertThat(indexResult.getUnique()).isEqualTo(false); + }) + .get(); + } + + @Test + void createHashIndexWithOptions() throws ExecutionException, InterruptedException { + assumeTrue(isAtLeastVersion(3, 5)); + final HashIndexOptions options = new HashIndexOptions(); + options.name("myHashIndex"); + + final Collection fields = new ArrayList<>(); + fields.add("a"); + fields.add("b"); + final IndexEntity indexResult = db.collection(COLLECTION_NAME).ensureHashIndex(fields, options).get(); + assertThat(indexResult).isNotNull(); + assertThat(indexResult.getConstraint()).isNull(); + assertThat(indexResult.getFields()).contains("a"); + assertThat(indexResult.getFields()).contains("b"); + assertThat(indexResult.getId()).startsWith(COLLECTION_NAME); + assertThat(indexResult.getIsNewlyCreated()).isTrue(); + assertThat(indexResult.getMinLength()).isNull(); + if (isSingleServer()) { + assertThat(indexResult.getSelectivityEstimate()).isEqualTo(1.); + } + assertThat(indexResult.getSparse()).isFalse(); + assertThat(indexResult.getType()).isEqualTo(IndexType.hash); + assertThat(indexResult.getUnique()).isFalse(); + assertThat(indexResult.getName()).isEqualTo("myHashIndex"); + } + + @Test + void createGeoIndex() throws InterruptedException, ExecutionException { + final Collection fields = new ArrayList<>(); + fields.add("a"); + db.collection(COLLECTION_NAME).ensureGeoIndex(fields, null) + .whenComplete((indexResult, ex) -> { + assertThat(indexResult).isNotNull(); + assertThat(indexResult.getFields()).contains("a"); + assertThat(indexResult.getGeoJson()).isEqualTo(false); + assertThat(indexResult.getId()).startsWith(COLLECTION_NAME); + assertThat(indexResult.getIsNewlyCreated()).isEqualTo(true); + assertThat(indexResult.getMinLength()).isNull(); + assertThat(indexResult.getSelectivityEstimate()).isNull(); + assertThat(indexResult.getSparse()).isEqualTo(true); + assertThat(indexResult.getType()).isIn(IndexType.geo, IndexType.geo1); + assertThat(indexResult.getUnique()).isEqualTo(false); + }) + .get(); + } + + @Test + void createGeoIndexWithOptions() throws ExecutionException, InterruptedException { + assumeTrue(isAtLeastVersion(3, 5)); + final GeoIndexOptions options = new GeoIndexOptions(); + options.name("myGeoIndex1"); + + final Collection fields = new ArrayList<>(); + fields.add("a"); + final IndexEntity indexResult = db.collection(COLLECTION_NAME).ensureGeoIndex(fields, options).get(); + assertThat(indexResult).isNotNull(); + assertThat(indexResult.getFields()).contains("a"); + assertThat(indexResult.getId()).startsWith(COLLECTION_NAME); + assertThat(indexResult.getIsNewlyCreated()).isTrue(); + assertThat(indexResult.getMinLength()).isNull(); + assertThat(indexResult.getSparse()).isTrue(); + assertThat(indexResult.getUnique()).isFalse(); + if (isAtLeastVersion(3, 4)) { + assertThat(indexResult.getType()).isEqualTo(IndexType.geo); + } else { + assertThat(indexResult.getType()).isEqualTo(IndexType.geo1); + } + assertThat(indexResult.getName()).isEqualTo("myGeoIndex1"); + } + + @Test + void createGeo2Index() throws ExecutionException, InterruptedException { + final Collection fields = new ArrayList<>(); + fields.add("a"); + fields.add("b"); + db.collection(COLLECTION_NAME).ensureGeoIndex(fields, null).whenComplete((indexResult, ex) -> { + assertThat(indexResult).isNotNull(); + assertThat(indexResult.getFields()).contains("a"); + assertThat(indexResult.getFields()).contains("b"); + assertThat(indexResult.getId()).startsWith(COLLECTION_NAME); + assertThat(indexResult.getIsNewlyCreated()).isEqualTo(true); + assertThat(indexResult.getMinLength()).isNull(); + assertThat(indexResult.getSparse()).isEqualTo(true); + assertThat(indexResult.getUnique()).isEqualTo(false); + try { + if (isAtLeastVersion(3, 4)) { + assertThat(indexResult.getType()).isEqualTo(IndexType.geo); + } else { + assertThat(indexResult.getType()).isEqualTo(IndexType.geo2); + } + } catch (InterruptedException | ExecutionException e) { + e.printStackTrace(); + fail(); + } + }).get(); + } + + @Test + void createGeo2IndexWithOptions() throws ExecutionException, InterruptedException { + assumeTrue(isAtLeastVersion(3, 5)); + final GeoIndexOptions options = new GeoIndexOptions(); + options.name("myGeoIndex2"); + + final Collection fields = new ArrayList<>(); + fields.add("a"); + fields.add("b"); + final IndexEntity indexResult = db.collection(COLLECTION_NAME).ensureGeoIndex(fields, options).get(); + assertThat(indexResult).isNotNull(); + assertThat(indexResult.getFields()).contains("a"); + assertThat(indexResult.getFields()).contains("b"); + assertThat(indexResult.getId()).startsWith(COLLECTION_NAME); + assertThat(indexResult.getIsNewlyCreated()).isTrue(); + assertThat(indexResult.getMinLength()).isNull(); + assertThat(indexResult.getSparse()).isTrue(); + assertThat(indexResult.getUnique()).isFalse(); + if (isAtLeastVersion(3, 4)) { + assertThat(indexResult.getType()).isEqualTo(IndexType.geo); + } else { + assertThat(indexResult.getType()).isEqualTo(IndexType.geo2); + } + assertThat(indexResult.getName()).isEqualTo("myGeoIndex2"); + } + + @Test + void createSkiplistIndex() throws InterruptedException, ExecutionException { + final Collection fields = new ArrayList<>(); + fields.add("a"); + fields.add("b"); + db.collection(COLLECTION_NAME).ensureSkiplistIndex(fields, null) + .whenComplete((indexResult, ex) -> { + assertThat(indexResult).isNotNull(); + assertThat(indexResult.getConstraint()).isNull(); + assertThat(indexResult.getFields()).contains("a"); + assertThat(indexResult.getFields()).contains("b"); + assertThat(indexResult.getGeoJson()).isNull(); + assertThat(indexResult.getId()).startsWith(COLLECTION_NAME); + assertThat(indexResult.getIsNewlyCreated()).isEqualTo(true); + assertThat(indexResult.getMinLength()).isNull(); + assertThat(indexResult.getSparse()).isEqualTo(false); + assertThat(indexResult.getType()).isEqualTo(IndexType.skiplist); + assertThat(indexResult.getUnique()).isEqualTo(false); + }) + .get(); + } + + @Test + void createSkiplistIndexWithOptions() throws ExecutionException, InterruptedException { + assumeTrue(isAtLeastVersion(3, 5)); + final SkiplistIndexOptions options = new SkiplistIndexOptions(); + options.name("mySkiplistIndex"); + + final Collection fields = new ArrayList<>(); + fields.add("a"); + fields.add("b"); + final IndexEntity indexResult = db.collection(COLLECTION_NAME).ensureSkiplistIndex(fields, options).get(); + assertThat(indexResult).isNotNull(); + assertThat(indexResult.getConstraint()).isNull(); + assertThat(indexResult.getFields()).contains("a"); + assertThat(indexResult.getFields()).contains("b"); + assertThat(indexResult.getId()).startsWith(COLLECTION_NAME); + assertThat(indexResult.getIsNewlyCreated()).isTrue(); + assertThat(indexResult.getMinLength()).isNull(); + assertThat(indexResult.getSparse()).isFalse(); + assertThat(indexResult.getType()).isEqualTo(IndexType.skiplist); + assertThat(indexResult.getUnique()).isFalse(); + assertThat(indexResult.getName()).isEqualTo("mySkiplistIndex"); + } + + @Test + void createPersistentIndex() throws InterruptedException, ExecutionException { + final Collection fields = new ArrayList<>(); + fields.add("a"); + fields.add("b"); + db.collection(COLLECTION_NAME).ensurePersistentIndex(fields, null) + .whenComplete((indexResult, ex) -> { + assertThat(indexResult).isNotNull(); + assertThat(indexResult.getConstraint()).isNull(); + assertThat(indexResult.getFields()).contains("a"); + assertThat(indexResult.getFields()).contains("b"); + assertThat(indexResult.getGeoJson()).isNull(); + assertThat(indexResult.getId()).startsWith(COLLECTION_NAME); + assertThat(indexResult.getIsNewlyCreated()).isEqualTo(true); + assertThat(indexResult.getMinLength()).isNull(); + assertThat(indexResult.getSparse()).isEqualTo(false); + assertThat(indexResult.getType()).isEqualTo(IndexType.persistent); + assertThat(indexResult.getUnique()).isEqualTo(false); + assertThat(indexResult.getDeduplicate()).isTrue(); + }) + .get(); + } + + @Test + void createPersistentIndexWithOptions() throws ExecutionException, InterruptedException { + assumeTrue(isAtLeastVersion(3, 5)); + final PersistentIndexOptions options = new PersistentIndexOptions(); + options.name("myPersistentIndex"); + + final Collection fields = new ArrayList<>(); + fields.add("a"); + fields.add("b"); + final IndexEntity indexResult = db.collection(COLLECTION_NAME).ensurePersistentIndex(fields, options).get(); + assertThat(indexResult).isNotNull(); + assertThat(indexResult.getConstraint()).isNull(); + assertThat(indexResult.getFields()).contains("a"); + assertThat(indexResult.getFields()).contains("b"); + assertThat(indexResult.getId()).startsWith(COLLECTION_NAME); + assertThat(indexResult.getIsNewlyCreated()).isTrue(); + assertThat(indexResult.getMinLength()).isNull(); + assertThat(indexResult.getSparse()).isFalse(); + assertThat(indexResult.getType()).isEqualTo(IndexType.persistent); + assertThat(indexResult.getUnique()).isFalse(); + assertThat(indexResult.getName()).isEqualTo("myPersistentIndex"); + } + + @Test + void indexDeduplicate() throws ExecutionException, InterruptedException { + assumeTrue(isAtLeastVersion(3, 8)); + + String name = "persistentIndex-" + rnd(); + final PersistentIndexOptions options = new PersistentIndexOptions(); + options.name(name); + options.deduplicate(true); + + String f1 = "field-" + rnd(); + String f2 = "field-" + rnd(); + + final Collection fields = Arrays.asList(f1, f2); + final IndexEntity indexResult = db.collection(COLLECTION_NAME).ensurePersistentIndex(fields, options).get(); + assertThat(indexResult).isNotNull(); + assertThat(indexResult.getDeduplicate()).isTrue(); + } + + @Test + void indexDeduplicateFalse() throws ExecutionException, InterruptedException { + assumeTrue(isAtLeastVersion(3, 8)); + + String name = "persistentIndex-" + rnd(); + final PersistentIndexOptions options = new PersistentIndexOptions(); + options.name(name); + options.deduplicate(false); + + String f1 = "field-" + rnd(); + String f2 = "field-" + rnd(); + + final Collection fields = Arrays.asList(f1, f2); + final IndexEntity indexResult = db.collection(COLLECTION_NAME).ensurePersistentIndex(fields, options).get(); + assertThat(indexResult).isNotNull(); + assertThat(indexResult.getDeduplicate()).isFalse(); + } + + @Test + void createFulltextIndex() throws InterruptedException, ExecutionException { + final Collection fields = new ArrayList<>(); + fields.add("a"); + db.collection(COLLECTION_NAME).ensureFulltextIndex(fields, null) + .whenComplete((indexResult, ex) -> { + assertThat(indexResult).isNotNull(); + assertThat(indexResult.getConstraint()).isNull(); + assertThat(indexResult.getFields()).contains("a"); + assertThat(indexResult.getGeoJson()).isNull(); + assertThat(indexResult.getId()).startsWith(COLLECTION_NAME); + assertThat(indexResult.getIsNewlyCreated()).isEqualTo(true); + assertThat(indexResult.getSelectivityEstimate()).isNull(); + assertThat(indexResult.getSparse()).isEqualTo(true); + assertThat(indexResult.getType()).isEqualTo(IndexType.fulltext); + assertThat(indexResult.getUnique()).isEqualTo(false); + }) + .get(); + } + + @Test + void createFulltextIndexWithOptions() throws ExecutionException, InterruptedException { + assumeTrue(isAtLeastVersion(3, 5)); + final FulltextIndexOptions options = new FulltextIndexOptions(); + options.name("myFulltextIndex"); + + final Collection fields = new ArrayList<>(); + fields.add("a"); + final IndexEntity indexResult = db.collection(COLLECTION_NAME).ensureFulltextIndex(fields, options).get(); + assertThat(indexResult).isNotNull(); + assertThat(indexResult.getConstraint()).isNull(); + assertThat(indexResult.getFields()).contains("a"); + assertThat(indexResult.getId()).startsWith(COLLECTION_NAME); + assertThat(indexResult.getIsNewlyCreated()).isTrue(); + assertThat(indexResult.getSparse()).isTrue(); + assertThat(indexResult.getType()).isEqualTo(IndexType.fulltext); + assertThat(indexResult.getUnique()).isFalse(); + assertThat(indexResult.getName()).isEqualTo("myFulltextIndex"); + } + + @Test + void createTtlIndexWithoutOptions() throws ExecutionException, InterruptedException { + assumeTrue(isAtLeastVersion(3, 5)); + final Collection fields = new ArrayList<>(); + fields.add("a"); + try { + db.collection(COLLECTION_NAME).ensureTtlIndex(fields, null).get(); + fail(); + } catch (ExecutionException e) { + assertThat(e.getCause()).isInstanceOf(ArangoDBException.class); + assertThat(e.getCause().getMessage()).contains("expireAfter attribute must be a number"); + assertThat(((ArangoDBException) e.getCause()).getResponseCode()).isEqualTo(400); + assertThat(((ArangoDBException) e.getCause()).getErrorNum()).isEqualTo(10); + } + } + + @Test + void createTtlIndexWithOptions() throws ExecutionException, InterruptedException { + assumeTrue(isAtLeastVersion(3, 5)); + final Collection fields = new ArrayList<>(); + fields.add("a"); + + final TtlIndexOptions options = new TtlIndexOptions(); + options.name("myTtlIndex"); + options.expireAfter(3600); + + final IndexEntity indexResult = db.collection(COLLECTION_NAME).ensureTtlIndex(fields, options).get(); + assertThat(indexResult).isNotNull(); + assertThat(indexResult.getFields()).contains("a"); + assertThat(indexResult.getId()).startsWith(COLLECTION_NAME); + assertThat(indexResult.getIsNewlyCreated()).isTrue(); + assertThat(indexResult.getType()).isEqualTo(IndexType.ttl); + assertThat(indexResult.getExpireAfter()).isEqualTo(3600); + assertThat(indexResult.getName()).isEqualTo("myTtlIndex"); + } + + @Test + void createZKDIndex() throws InterruptedException, ExecutionException { + assumeTrue(isAtLeastVersion(3, 9)); + db.collection(COLLECTION_NAME).truncate().get(); + + final Collection fields = new ArrayList<>(); + fields.add("a"); + fields.add("b"); + IndexEntity indexResult = db.collection(COLLECTION_NAME).ensureZKDIndex(fields, null).get(); + assertThat(indexResult).isNotNull(); + assertThat(indexResult.getConstraint()).isNull(); + assertThat(indexResult.getFields()).contains("a"); + assertThat(indexResult.getFields()).contains("b"); + assertThat(indexResult.getGeoJson()).isNull(); + assertThat(indexResult.getId()).startsWith(COLLECTION_NAME); + assertThat(indexResult.getIsNewlyCreated()).isTrue(); + assertThat(indexResult.getMinLength()).isNull(); + assertThat(indexResult.getType()).isEqualTo(IndexType.zkd); + assertThat(indexResult.getUnique()).isFalse(); + db.collection(COLLECTION_NAME).deleteIndex(indexResult.getId()).get(); + } + + @Test + void createZKDIndexWithOptions() throws ExecutionException, InterruptedException { + assumeTrue(isAtLeastVersion(3, 9)); + db.collection(COLLECTION_NAME).truncate().get(); + + final ZKDIndexOptions options = new ZKDIndexOptions() + .name("myZKDIndex") + .fieldValueTypes(ZKDIndexOptions.FieldValueTypes.DOUBLE); + + final Collection fields = new ArrayList<>(); + fields.add("a"); + fields.add("b"); + final IndexEntity indexResult = db.collection(COLLECTION_NAME).ensureZKDIndex(fields, options).get(); + assertThat(indexResult).isNotNull(); + assertThat(indexResult.getConstraint()).isNull(); + assertThat(indexResult.getFields()).contains("a"); + assertThat(indexResult.getFields()).contains("b"); + assertThat(indexResult.getId()).startsWith(COLLECTION_NAME); + assertThat(indexResult.getIsNewlyCreated()).isTrue(); + assertThat(indexResult.getMinLength()).isNull(); + assertThat(indexResult.getType()).isEqualTo(IndexType.zkd); + assertThat(indexResult.getUnique()).isFalse(); + assertThat(indexResult.getName()).isEqualTo("myZKDIndex"); + db.collection(COLLECTION_NAME).deleteIndex(indexResult.getId()).get(); + } + + @Test + void getIndexes() throws InterruptedException, ExecutionException { + final int initialIndexCount = db.collection(COLLECTION_NAME).getIndexes().get().size(); + final Collection fields = new ArrayList<>(); + fields.add("a"); + db.collection(COLLECTION_NAME).ensureHashIndex(fields, null).get(); + db.collection(COLLECTION_NAME).getIndexes() + .whenComplete((indexes, ex) -> { + assertThat(indexes).isNotNull(); + assertThat(indexes.size()).isEqualTo(initialIndexCount + 1); + for (final IndexEntity i : indexes) { + if (i.getType() == IndexType.hash) { + assertThat(i.getFields().size()).isEqualTo(1); + assertThat(i.getFields()).contains("a"); + } + } + }) + .get(); + } + + @Test + void exists() throws InterruptedException, ExecutionException { + assertThat(db.collection(COLLECTION_NAME).exists().get()).isTrue(); + assertThat(db.collection(COLLECTION_NAME + "no").exists().get()).isFalse(); + } + + @Test + void truncate() throws InterruptedException, ExecutionException { + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); + db.collection(COLLECTION_NAME).insertDocument(doc, null).get(); + final BaseDocument readResult = db.collection(COLLECTION_NAME) + .getDocument(doc.getKey(), BaseDocument.class, null).get(); + assertThat(readResult.getKey()).isEqualTo(doc.getKey()); + db.collection(COLLECTION_NAME).truncate() + .whenComplete((truncateResult, ex) -> { + assertThat(truncateResult).isNotNull(); + assertThat(truncateResult.getId()).isNotNull(); + }) + .get(); + final BaseDocument document = db.collection(COLLECTION_NAME).getDocument(doc.getKey(), BaseDocument.class, null) + .get(); + assertThat(document).isNull(); + } + + @Test + void getCount() throws InterruptedException, ExecutionException { + db.collection(COLLECTION_NAME).count() + .whenComplete((countEmpty, ex) -> { + assertThat(countEmpty).isNotNull(); + assertThat(countEmpty.getCount()).isEqualTo(0L); + }) + .get(); + + db.collection(COLLECTION_NAME).insertDocument(RawJson.of("{}"), null).get(); + + db.collection(COLLECTION_NAME).count() + .whenComplete((count, ex) -> assertThat(count.getCount()).isEqualTo(1L)) + .get(); + } + + @Test + void documentExists() throws InterruptedException, ExecutionException { + db.collection(COLLECTION_NAME).documentExists("no", null) + .whenComplete((existsNot, ex) -> assertThat(existsNot).isEqualTo(false)) + .get(); + + db.collection(COLLECTION_NAME).insertDocument(RawJson.of("{\"_key\":\"abc\"}")).get(); + + db.collection(COLLECTION_NAME).documentExists("abc", null) + .whenComplete((exists, ex) -> assertThat(exists).isEqualTo(true)) + .get(); + } + + @Test + void documentExistsIfMatch() throws InterruptedException, ExecutionException { + final DocumentCreateEntity createResult = db.collection(COLLECTION_NAME) + .insertDocument(RawJson.of("{\"_key\":\"abc\"}")).get(); + final DocumentExistsOptions options = new DocumentExistsOptions().ifMatch(createResult.getRev()); + db.collection(COLLECTION_NAME).documentExists("abc", options) + .whenComplete((exists, ex) -> assertThat(exists).isEqualTo(true)) + .get(); + } + + @Test + void documentExistsIfMatchFail() throws InterruptedException, ExecutionException { + db.collection(COLLECTION_NAME).insertDocument(RawJson.of("{\"_key\":\"abc\"}")).get(); + final DocumentExistsOptions options = new DocumentExistsOptions().ifMatch("no"); + db.collection(COLLECTION_NAME).documentExists("abc", options) + .whenComplete((exists, ex) -> assertThat(exists).isEqualTo(false)) + .get(); + } + + @Test + void documentExistsIfNoneMatch() throws InterruptedException, ExecutionException { + db.collection(COLLECTION_NAME).insertDocument(RawJson.of("{\"_key\":\"abc\"}")).get(); + final DocumentExistsOptions options = new DocumentExistsOptions().ifNoneMatch("no"); + db.collection(COLLECTION_NAME).documentExists("abc", options) + .whenComplete((exists, ex) -> assertThat(exists).isEqualTo(true)) + .get(); + } + + @Test + void documentExistsIfNoneMatchFail() throws InterruptedException, ExecutionException { + final DocumentCreateEntity createResult = db.collection(COLLECTION_NAME) + .insertDocument(RawJson.of("{\"_key\":\"abc\"}")).get(); + final DocumentExistsOptions options = new DocumentExistsOptions().ifNoneMatch(createResult.getRev()); + db.collection(COLLECTION_NAME).documentExists("abc", options) + .whenComplete((exists, ex) -> assertThat(exists).isEqualTo(false)) + .get(); + } + + @Test + void insertDocuments() throws InterruptedException, ExecutionException { + final Collection values = new ArrayList<>(); + values.add(new BaseDocument()); + values.add(new BaseDocument()); + values.add(new BaseDocument()); + db.collection(COLLECTION_NAME).insertDocuments(values) + .whenComplete((docs, ex) -> { + assertThat(docs).isNotNull(); + assertThat(docs.getDocuments()).isNotNull(); + assertThat(docs.getDocuments().size()).isEqualTo(3); + assertThat(docs.getErrors()).isNotNull(); + assertThat(docs.getErrors().size()).isEqualTo(0); + }) + .get(); + } + + @Test + void insertDocumentsOne() throws InterruptedException, ExecutionException { + final Collection values = new ArrayList<>(); + values.add(new BaseDocument()); + db.collection(COLLECTION_NAME).insertDocuments(values) + .whenComplete((docs, ex) -> { + assertThat(docs).isNotNull(); + assertThat(docs.getDocuments()).isNotNull(); + assertThat(docs.getDocuments().size()).isEqualTo(1); + assertThat(docs.getErrors()).isNotNull(); + assertThat(docs.getErrors().size()).isEqualTo(0); + }) + .get(); + } + + @Test + void insertDocumentsEmpty() throws InterruptedException, ExecutionException { + final Collection values = new ArrayList<>(); + db.collection(COLLECTION_NAME).insertDocuments(values) + .whenComplete((docs, ex) -> { + assertThat(docs).isNotNull(); + assertThat(docs.getDocuments()).isNotNull(); + assertThat(docs.getDocuments().size()).isEqualTo(0); + assertThat(docs.getErrors()).isNotNull(); + assertThat(docs.getErrors().size()).isEqualTo(0); + }) + .get(); + } + + @Test + void insertDocumentsReturnNew() throws InterruptedException, ExecutionException { + final Collection values = new ArrayList<>(); + values.add(new BaseDocument()); + values.add(new BaseDocument()); + values.add(new BaseDocument()); + final DocumentCreateOptions options = new DocumentCreateOptions().returnNew(true); + db.collection(COLLECTION_NAME).insertDocuments(values, options) + .whenComplete((docs, ex) -> { + assertThat(docs).isNotNull(); + assertThat(docs.getDocuments()).isNotNull(); + assertThat(docs.getDocuments().size()).isEqualTo(3); + assertThat(docs.getErrors()).isNotNull(); + assertThat(docs.getErrors().size()).isEqualTo(0); + for (final DocumentCreateEntity doc : docs.getDocuments()) { + assertThat(doc.getNew()).isNotNull(); + final BaseDocument baseDocument = doc.getNew(); + assertThat(baseDocument.getKey()).isNotNull(); + } + }) + .get(); + } + + @Test + void insertDocumentsFail() throws InterruptedException, ExecutionException { + final Collection values = new ArrayList<>(); + values.add(new BaseDocument("1")); + values.add(new BaseDocument("2")); + values.add(new BaseDocument("2")); + db.collection(COLLECTION_NAME).insertDocuments(values) + .whenComplete((docs, ex) -> { + assertThat(docs).isNotNull(); + assertThat(docs.getDocuments()).isNotNull(); + assertThat(docs.getDocuments().size()).isEqualTo(2); + assertThat(docs.getErrors()).isNotNull(); + assertThat(docs.getErrors().size()).isEqualTo(1); + assertThat(docs.getErrors().iterator().next().getErrorNum()).isEqualTo(1210); + }) + .get(); + } + + @Test + void insertDocumentsRawData() throws ExecutionException, InterruptedException { + final RawData values = RawData.of("[{},{},{}]"); + final MultiDocumentEntity docs = db.collection(COLLECTION_NAME).insertDocuments(values).get(); + assertThat(docs).isNotNull(); + assertThat(docs.getDocuments()).isNotNull(); + assertThat(docs.getDocuments()).hasSize(3); + assertThat(docs.getErrors()).isNotNull(); + assertThat(docs.getErrors()).isEmpty(); + } + + @Test + void insertDocumentsRawDataReturnNew() throws ExecutionException, InterruptedException { + final RawData values = RawData.of("[{\"aaa\":33},{\"aaa\":33},{\"aaa\":33}]"); + final MultiDocumentEntity> docs = + db.collection(COLLECTION_NAME).insertDocuments(values, new DocumentCreateOptions().returnNew(true)).get(); + assertThat(docs).isNotNull(); + assertThat(docs.getDocuments()).isNotNull(); + assertThat(docs.getDocuments()).hasSize(3); + assertThat(docs.getErrors()).isNotNull(); + assertThat(docs.getErrors()).isEmpty(); + + for (final DocumentCreateEntity doc : docs.getDocuments()) { + RawData d = doc.getNew(); + assertThat(d) + .isNotNull() + .isInstanceOf(RawJson.class); + + JsonNode jn = SerdeUtils.INSTANCE.parseJson(((RawJson) d).getValue()); + assertThat(jn.has("aaa")).isTrue(); + assertThat(jn.get("aaa").intValue()).isEqualTo(33); + } + } + + @Test + void importDocuments() throws InterruptedException, ExecutionException { + final Collection values = new ArrayList<>(); + values.add(new BaseDocument()); + values.add(new BaseDocument()); + values.add(new BaseDocument()); + db.collection(COLLECTION_NAME).importDocuments(values) + .whenComplete((docs, ex) -> { + assertThat(docs).isNotNull(); + assertThat(docs.getCreated()).isEqualTo(values.size()); + assertThat(docs.getEmpty()).isEqualTo(0); + assertThat(docs.getErrors()).isEqualTo(0); + assertThat(docs.getIgnored()).isEqualTo(0); + assertThat(docs.getUpdated()).isEqualTo(0); + assertThat(docs.getDetails()).isEmpty(); + }) + .get(); + } + + @Test + void importDocumentsDuplicateDefaultError() throws InterruptedException, ExecutionException { + final Collection values = new ArrayList<>(); + values.add(new BaseDocument("1")); + values.add(new BaseDocument("2")); + values.add(new BaseDocument("2")); + db.collection(COLLECTION_NAME).importDocuments(values) + .whenComplete((docs, ex) -> { + assertThat(docs).isNotNull(); + assertThat(docs.getCreated()).isEqualTo(2); + assertThat(docs.getEmpty()).isEqualTo(0); + assertThat(docs.getErrors()).isEqualTo(1); + assertThat(docs.getIgnored()).isEqualTo(0); + assertThat(docs.getUpdated()).isEqualTo(0); + assertThat(docs.getDetails()).isEmpty(); + }) + .get(); + } + + @Test + void importDocumentsDuplicateError() throws InterruptedException, ExecutionException { + final Collection values = new ArrayList<>(); + values.add(new BaseDocument("1")); + values.add(new BaseDocument("2")); + values.add(new BaseDocument("2")); + db.collection(COLLECTION_NAME).importDocuments(values, +new DocumentImportOptions().onDuplicate(OnDuplicate.error)) + .whenComplete((docs, ex) -> { + assertThat(docs).isNotNull(); + assertThat(docs.getCreated()).isEqualTo(2); + assertThat(docs.getEmpty()).isEqualTo(0); + assertThat(docs.getErrors()).isEqualTo(1); + assertThat(docs.getIgnored()).isEqualTo(0); + assertThat(docs.getUpdated()).isEqualTo(0); + assertThat(docs.getDetails()).isEmpty(); + }) + .get(); + } + + @Test + void importDocumentsDuplicateIgnore() throws InterruptedException, ExecutionException { + final Collection values = new ArrayList<>(); + values.add(new BaseDocument("1")); + values.add(new BaseDocument("2")); + values.add(new BaseDocument("2")); + db.collection(COLLECTION_NAME).importDocuments(values, + new DocumentImportOptions().onDuplicate(OnDuplicate.ignore)) + .whenComplete((docs, ex) -> { + assertThat(docs).isNotNull(); + assertThat(docs.getCreated()).isEqualTo(2); + assertThat(docs.getEmpty()).isEqualTo(0); + assertThat(docs.getErrors()).isEqualTo(0); + assertThat(docs.getIgnored()).isEqualTo(1); + assertThat(docs.getUpdated()).isEqualTo(0); + assertThat(docs.getDetails()).isEmpty(); + }) + .get(); + } + + @Test + void importDocumentsDuplicateReplace() throws InterruptedException, ExecutionException { + final Collection values = new ArrayList<>(); + values.add(new BaseDocument("1")); + values.add(new BaseDocument("2")); + values.add(new BaseDocument("2")); + db.collection(COLLECTION_NAME).importDocuments(values, +new DocumentImportOptions().onDuplicate(OnDuplicate.replace)) + .whenComplete((docs, ex) -> { + assertThat(docs).isNotNull(); + assertThat(docs.getCreated()).isEqualTo(2); + assertThat(docs.getEmpty()).isEqualTo(0); + assertThat(docs.getErrors()).isEqualTo(0); + assertThat(docs.getIgnored()).isEqualTo(0); + assertThat(docs.getUpdated()).isEqualTo(1); + assertThat(docs.getDetails()).isEmpty(); + }) + .get(); + } + + @Test + void importDocumentsDuplicateUpdate() throws InterruptedException, ExecutionException { + final Collection values = new ArrayList<>(); + values.add(new BaseDocument("1")); + values.add(new BaseDocument("2")); + values.add(new BaseDocument("2")); + db.collection(COLLECTION_NAME).importDocuments(values, + new DocumentImportOptions().onDuplicate(OnDuplicate.update)) + .whenComplete((docs, ex) -> { + assertThat(docs).isNotNull(); + assertThat(docs.getCreated()).isEqualTo(2); + assertThat(docs.getEmpty()).isEqualTo(0); + assertThat(docs.getErrors()).isEqualTo(0); + assertThat(docs.getIgnored()).isEqualTo(0); + assertThat(docs.getUpdated()).isEqualTo(1); + assertThat(docs.getDetails()).isEmpty(); + }) + .get(); + } + + @Test + void importDocumentsCompleteFail() throws InterruptedException { + final Collection values = new ArrayList<>(); + values.add(new BaseDocument("1")); + values.add(new BaseDocument("2")); + values.add(new BaseDocument("2")); + try { + db.collection(COLLECTION_NAME).importDocuments(values, new DocumentImportOptions().complete(true)).get(); + fail(); + } catch (ExecutionException e) { + assertThat(e.getCause()).isInstanceOf(ArangoDBException.class); + assertThat(((ArangoDBException) e.getCause()).getErrorNum()).isEqualTo(1210); + } + } + + @Test + void importDocumentsDetails() throws InterruptedException, ExecutionException { + final Collection values = new ArrayList<>(); + values.add(new BaseDocument("1")); + values.add(new BaseDocument("2")); + values.add(new BaseDocument("2")); + db.collection(COLLECTION_NAME).importDocuments(values, new DocumentImportOptions().details(true)) + .whenComplete((docs, ex) -> { + assertThat(docs).isNotNull(); + assertThat(docs.getCreated()).isEqualTo(2); + assertThat(docs.getEmpty()).isEqualTo(0); + assertThat(docs.getErrors()).isEqualTo(1); + assertThat(docs.getIgnored()).isEqualTo(0); + assertThat(docs.getUpdated()).isEqualTo(0); + assertThat(docs.getDetails().size()).isEqualTo(1); + assertThat(docs.getDetails().iterator().next()).contains("unique constraint violated"); + }) + .get(); + } + + @Test + void importDocumentsOverwriteFalse() throws InterruptedException, ExecutionException { + final ArangoCollectionAsync collection = db.collection(COLLECTION_NAME); + collection.insertDocument(new BaseDocument()).get(); + assertThat(collection.count().get().getCount()).isEqualTo(1L); + + final Collection values = new ArrayList<>(); + values.add(new BaseDocument()); + values.add(new BaseDocument()); + collection.importDocuments(values, new DocumentImportOptions().overwrite(false)).get(); + assertThat(collection.count().get().getCount()).isEqualTo(3L); + } + + @Test + void importDocumentsOverwriteTrue() throws InterruptedException, ExecutionException { + final ArangoCollectionAsync collection = db.collection(COLLECTION_NAME); + collection.insertDocument(new BaseDocument()).get(); + assertThat(collection.count().get().getCount()).isEqualTo(1L); + + final Collection values = new ArrayList<>(); + values.add(new BaseDocument()); + values.add(new BaseDocument()); + collection.importDocuments(values, new DocumentImportOptions().overwrite(true)).get(); + assertThat(collection.count().get().getCount()).isEqualTo(2L); + } + + @Test + void importDocumentsFromToPrefix() throws InterruptedException, ExecutionException { + db.createCollection(COLLECTION_NAME + "_edge", new CollectionCreateOptions().type(CollectionType.EDGES)).get(); + final ArangoCollectionAsync collection = db.collection(COLLECTION_NAME + "_edge"); + try { + final Collection values = new ArrayList<>(); + final String[] keys = {"1", "2"}; + for (String s : keys) { + values.add(new BaseEdgeDocument(s, "from", "to")); + } + assertThat(values).hasSize(keys.length); + + final DocumentImportEntity importResult = collection + .importDocuments(values, new DocumentImportOptions().fromPrefix("foo").toPrefix("bar")).get(); + assertThat(importResult).isNotNull(); + assertThat(importResult.getCreated()).isEqualTo(values.size()); + for (String key : keys) { + BaseEdgeDocument doc; + doc = collection.getDocument(key, BaseEdgeDocument.class).get(); + assertThat(doc).isNotNull(); + assertThat(doc.getFrom()).isEqualTo("foo/from"); + assertThat(doc.getTo()).isEqualTo("bar/to"); + } + } finally { + collection.drop().get(); + } + } + + @Test + void importDocumentsJson() throws InterruptedException, ExecutionException { + final String values = "[{\"_key\":\"1\"},{\"_key\":\"2\"}]"; + db.collection(COLLECTION_NAME).importDocuments(RawData.of(values)) + .whenComplete((docs, ex) -> { + assertThat(docs).isNotNull(); + assertThat(docs.getCreated()).isEqualTo(2); + assertThat(docs.getEmpty()).isEqualTo(0); + assertThat(docs.getErrors()).isEqualTo(0); + assertThat(docs.getIgnored()).isEqualTo(0); + assertThat(docs.getUpdated()).isEqualTo(0); + assertThat(docs.getDetails()).isEmpty(); + }) + .get(); + } + + @Test + void importDocumentsJsonDuplicateDefaultError() throws InterruptedException, ExecutionException { + final String values = "[{\"_key\":\"1\"},{\"_key\":\"2\"},{\"_key\":\"2\"}]"; + db.collection(COLLECTION_NAME).importDocuments(RawData.of(values)) + .whenComplete((docs, ex) -> { + assertThat(docs).isNotNull(); + assertThat(docs.getCreated()).isEqualTo(2); + assertThat(docs.getEmpty()).isEqualTo(0); + assertThat(docs.getErrors()).isEqualTo(1); + assertThat(docs.getIgnored()).isEqualTo(0); + assertThat(docs.getUpdated()).isEqualTo(0); + assertThat(docs.getDetails()).isEmpty(); + }) + .get(); + } + + @Test + void importDocumentsJsonDuplicateError() throws InterruptedException, ExecutionException { + final String values = "[{\"_key\":\"1\"},{\"_key\":\"2\"},{\"_key\":\"2\"}]"; + db.collection(COLLECTION_NAME).importDocuments(RawData.of(values), + new DocumentImportOptions().onDuplicate(OnDuplicate.error)) + .whenComplete((docs, ex) -> { + assertThat(docs).isNotNull(); + assertThat(docs.getCreated()).isEqualTo(2); + assertThat(docs.getEmpty()).isEqualTo(0); + assertThat(docs.getErrors()).isEqualTo(1); + assertThat(docs.getIgnored()).isEqualTo(0); + assertThat(docs.getUpdated()).isEqualTo(0); + assertThat(docs.getDetails()).isEmpty(); + }) + .get(); + } + + @Test + void importDocumentsJsonDuplicateIgnore() throws InterruptedException, ExecutionException { + final String values = "[{\"_key\":\"1\"},{\"_key\":\"2\"},{\"_key\":\"2\"}]"; + db.collection(COLLECTION_NAME).importDocuments(RawData.of(values), + new DocumentImportOptions().onDuplicate(OnDuplicate.ignore)) + .whenComplete((docs, ex) -> { + assertThat(docs).isNotNull(); + assertThat(docs.getCreated()).isEqualTo(2); + assertThat(docs.getEmpty()).isEqualTo(0); + assertThat(docs.getErrors()).isEqualTo(0); + assertThat(docs.getIgnored()).isEqualTo(1); + assertThat(docs.getUpdated()).isEqualTo(0); + assertThat(docs.getDetails()).isEmpty(); + }) + .get(); + } + + @Test + void importDocumentsJsonDuplicateReplace() throws InterruptedException, ExecutionException { + final String values = "[{\"_key\":\"1\"},{\"_key\":\"2\"},{\"_key\":\"2\"}]"; + db.collection(COLLECTION_NAME).importDocuments(RawData.of(values), + new DocumentImportOptions().onDuplicate(OnDuplicate.replace)) + .whenComplete((docs, ex) -> { + assertThat(docs).isNotNull(); + assertThat(docs.getCreated()).isEqualTo(2); + assertThat(docs.getEmpty()).isEqualTo(0); + assertThat(docs.getErrors()).isEqualTo(0); + assertThat(docs.getIgnored()).isEqualTo(0); + assertThat(docs.getUpdated()).isEqualTo(1); + assertThat(docs.getDetails()).isEmpty(); + }) + .get(); + } + + @Test + void importDocumentsJsonDuplicateUpdate() throws InterruptedException, ExecutionException { + final String values = "[{\"_key\":\"1\"},{\"_key\":\"2\"},{\"_key\":\"2\"}]"; + db.collection(COLLECTION_NAME).importDocuments(RawData.of(values), + new DocumentImportOptions().onDuplicate(OnDuplicate.update)) + .whenComplete((docs, ex) -> { + assertThat(docs).isNotNull(); + assertThat(docs.getCreated()).isEqualTo(2); + assertThat(docs.getEmpty()).isEqualTo(0); + assertThat(docs.getErrors()).isEqualTo(0); + assertThat(docs.getIgnored()).isEqualTo(0); + assertThat(docs.getUpdated()).isEqualTo(1); + assertThat(docs.getDetails()).isEmpty(); + }) + .get(); + } + + @Test + void importDocumentsJsonCompleteFail() throws InterruptedException { + final String values = "[{\"_key\":\"1\"},{\"_key\":\"2\"},{\"_key\":\"2\"}]"; + try { + db.collection(COLLECTION_NAME).importDocuments(RawData.of(values), + new DocumentImportOptions().complete(true)).get(); + fail(); + } catch (ExecutionException e) { + assertThat(e.getCause()).isInstanceOf(ArangoDBException.class); + assertThat(((ArangoDBException) e.getCause()).getErrorNum()).isEqualTo(1210); + } + } + + @Test + void importDocumentsJsonDetails() throws InterruptedException, ExecutionException { + final String values = "[{\"_key\":\"1\"},{\"_key\":\"2\"},{\"_key\":\"2\"}]"; + db.collection(COLLECTION_NAME).importDocuments(RawData.of(values), new DocumentImportOptions().details(true)) + .whenComplete((docs, ex) -> { + assertThat(docs).isNotNull(); + assertThat(docs.getCreated()).isEqualTo(2); + assertThat(docs.getEmpty()).isEqualTo(0); + assertThat(docs.getErrors()).isEqualTo(1); + assertThat(docs.getIgnored()).isEqualTo(0); + assertThat(docs.getUpdated()).isEqualTo(0); + assertThat(docs.getDetails().size()).isEqualTo(1); + assertThat(docs.getDetails().iterator().next()).contains("unique constraint violated"); + }) + .get(); + } + + @Test + void importDocumentsJsonOverwriteFalse() throws InterruptedException, ExecutionException { + final ArangoCollectionAsync collection = db.collection(COLLECTION_NAME); + collection.insertDocument(new BaseDocument()).get(); + assertThat(collection.count().get().getCount()).isEqualTo(1L); + + final String values = "[{\"_key\":\"1\"},{\"_key\":\"2\"}]"; + collection.importDocuments(RawData.of(values), new DocumentImportOptions().overwrite(false)).get(); + assertThat(collection.count().get().getCount()).isEqualTo(3L); + } + + @Test + void importDocumentsJsonOverwriteTrue() throws InterruptedException, ExecutionException { + final ArangoCollectionAsync collection = db.collection(COLLECTION_NAME); + collection.insertDocument(new BaseDocument()).get(); + assertThat(collection.count().get().getCount()).isEqualTo(1L); + + final String values = "[{\"_key\":\"1\"},{\"_key\":\"2\"}]"; + collection.importDocuments(RawData.of(values), new DocumentImportOptions().overwrite(true)).get(); + assertThat(collection.count().get().getCount()).isEqualTo(2L); + } + + @Test + void importDocumentsJsonFromToPrefix() throws InterruptedException, ExecutionException { + db.createCollection(COLLECTION_NAME + "_edge", new CollectionCreateOptions().type(CollectionType.EDGES)).get(); + final ArangoCollectionAsync collection = db.collection(COLLECTION_NAME + "_edge"); + try { + final String[] keys = {"1", "2"}; + final String values = "[{\"_key\":\"1\",\"_from\":\"from\",\"_to\":\"to\"},{\"_key\":\"2\"," + + "\"_from\":\"from\",\"_to\":\"to\"}]"; + + final DocumentImportEntity importResult = collection + .importDocuments(RawData.of(values), + new DocumentImportOptions().fromPrefix("foo").toPrefix("bar")).get(); + assertThat(importResult).isNotNull(); + assertThat(importResult.getCreated()).isEqualTo(2); + for (String key : keys) { + BaseEdgeDocument doc; + doc = collection.getDocument(key, BaseEdgeDocument.class).get(); + assertThat(doc).isNotNull(); + assertThat(doc.getFrom()).isEqualTo("foo/from"); + assertThat(doc.getTo()).isEqualTo("bar/to"); + } + } finally { + collection.drop().get(); + } + } + + @Test + void deleteDocumentsByKey() throws InterruptedException, ExecutionException { + final Collection values = new ArrayList<>(); + { + final BaseDocument e = new BaseDocument(UUID.randomUUID().toString()); + e.setKey("1"); + values.add(e); + } + { + final BaseDocument e = new BaseDocument(UUID.randomUUID().toString()); + e.setKey("2"); + values.add(e); + } + db.collection(COLLECTION_NAME).insertDocuments(values).get(); + final Collection keys = new ArrayList<>(); + keys.add("1"); + keys.add("2"); + db.collection(COLLECTION_NAME).deleteDocuments(keys) + .whenComplete((deleteResult, ex) -> { + assertThat(deleteResult).isNotNull(); + assertThat(deleteResult.getDocuments().size()).isEqualTo(2); + for (final DocumentDeleteEntity i : deleteResult.getDocuments()) { + assertThat(i.getKey()).isIn("1", "2"); + } + assertThat(deleteResult.getErrors().size()).isEqualTo(0); + }) + .get(); + } + + @Test + void deleteDocumentsByDocuments() throws InterruptedException, ExecutionException { + final Collection values = new ArrayList<>(); + { + final BaseDocument e = new BaseDocument(UUID.randomUUID().toString()); + e.setKey("1"); + values.add(e); + } + { + final BaseDocument e = new BaseDocument(UUID.randomUUID().toString()); + e.setKey("2"); + values.add(e); + } + db.collection(COLLECTION_NAME).insertDocuments(values).get(); + db.collection(COLLECTION_NAME).deleteDocuments(values) + .whenComplete((deleteResult, ex) -> { + assertThat(deleteResult).isNotNull(); + assertThat(deleteResult.getDocuments().size()).isEqualTo(2); + for (final DocumentDeleteEntity i : deleteResult.getDocuments()) { + assertThat(i.getKey()).isIn("1", "2"); + } + assertThat(deleteResult.getErrors().size()).isEqualTo(0); + }) + .get(); + } + + @Test + void deleteDocumentsByKeyOne() throws InterruptedException, ExecutionException { + final Collection values = new ArrayList<>(); + { + final BaseDocument e = new BaseDocument(UUID.randomUUID().toString()); + e.setKey("1"); + values.add(e); + } + db.collection(COLLECTION_NAME).insertDocuments(values).get(); + final Collection keys = new ArrayList<>(); + keys.add("1"); + db.collection(COLLECTION_NAME).deleteDocuments(keys) + .whenComplete((deleteResult, ex) -> { + assertThat(deleteResult).isNotNull(); + assertThat(deleteResult.getDocuments().size()).isEqualTo(1); + for (final DocumentDeleteEntity i : deleteResult.getDocuments()) { + assertThat(i.getKey()).isEqualTo("1"); + } + assertThat(deleteResult.getErrors().size()).isEqualTo(0); + }) + .get(); + } + + @Test + void deleteDocumentsByDocumentOne() throws InterruptedException, ExecutionException { + final Collection values = new ArrayList<>(); + { + final BaseDocument e = new BaseDocument(UUID.randomUUID().toString()); + e.setKey("1"); + values.add(e); + } + db.collection(COLLECTION_NAME).insertDocuments(values).get(); + db.collection(COLLECTION_NAME).deleteDocuments(values) + .whenComplete((deleteResult, ex) -> { + assertThat(deleteResult).isNotNull(); + assertThat(deleteResult.getDocuments().size()).isEqualTo(1); + for (final DocumentDeleteEntity i : deleteResult.getDocuments()) { + assertThat(i.getKey()).isEqualTo("1"); + } + assertThat(deleteResult.getErrors().size()).isEqualTo(0); + }) + .get(); + } + + @Test + void deleteDocumentsEmpty() throws InterruptedException, ExecutionException { + final Collection values = new ArrayList<>(); + db.collection(COLLECTION_NAME).insertDocuments(values).get(); + final Collection keys = new ArrayList<>(); + db.collection(COLLECTION_NAME).deleteDocuments(keys) + .whenComplete((deleteResult, ex) -> { + assertThat(deleteResult).isNotNull(); + assertThat(deleteResult.getDocuments().size()).isEqualTo(0); + assertThat(deleteResult.getErrors().size()).isEqualTo(0); + }) + .get(); + } + + @Test + void deleteDocumentsByKeyNotExisting() throws InterruptedException, ExecutionException { + final Collection values = new ArrayList<>(); + db.collection(COLLECTION_NAME).insertDocuments(values).get(); + final Collection keys = new ArrayList<>(); + keys.add("1"); + keys.add("2"); + db.collection(COLLECTION_NAME).deleteDocuments(keys) + .whenComplete((deleteResult, ex) -> { + assertThat(deleteResult).isNotNull(); + assertThat(deleteResult.getDocuments().size()).isEqualTo(0); + assertThat(deleteResult.getErrors().size()).isEqualTo(2); + }) + .get(); + } + + @Test + void deleteDocumentsByDocumentsNotExisting() throws InterruptedException, ExecutionException { + final Collection values = new ArrayList<>(); + { + final BaseDocument e = new BaseDocument(UUID.randomUUID().toString()); + e.setKey("1"); + values.add(e); + } + { + final BaseDocument e = new BaseDocument(UUID.randomUUID().toString()); + e.setKey("2"); + values.add(e); + } + db.collection(COLLECTION_NAME).deleteDocuments(values) + .whenComplete((deleteResult, ex) -> { + assertThat(deleteResult).isNotNull(); + assertThat(deleteResult.getDocuments().size()).isEqualTo(0); + assertThat(deleteResult.getErrors().size()).isEqualTo(2); + }) + .get(); + } + + @Test + void deleteDocumentsRawDataByKeyReturnOld() throws ExecutionException, InterruptedException { + ArangoCollectionAsync collection = db.collection(COLLECTION_NAME); + final RawData values = RawData.of("[{\"_key\":\"1\"},{\"_key\":\"2\"}]"); + collection.insertDocuments(values).get(); + final RawData keys = RawData.of("[\"1\",\"2\"]"); + MultiDocumentEntity> deleteResult = collection.deleteDocuments(keys, + new DocumentDeleteOptions().returnOld(true)).get(); + assertThat(deleteResult).isNotNull(); + assertThat(deleteResult.getDocuments()).hasSize(2); + for (final DocumentDeleteEntity i : deleteResult.getDocuments()) { + assertThat(i.getKey()).isIn("1", "2"); + assertThat(i.getOld()).isNotNull().isInstanceOf(RawJson.class); + JsonNode jn = SerdeUtils.INSTANCE.parseJson(((RawJson) i.getOld()).getValue()); + assertThat(jn.get("_key").asText()).isEqualTo(i.getKey()); + } + assertThat(deleteResult.getErrors()).isEmpty(); + } + + @Test + void updateDocuments() throws InterruptedException, ExecutionException { + final Collection values = new ArrayList<>(); + { + final BaseDocument e = new BaseDocument(UUID.randomUUID().toString()); + e.setKey("1"); + values.add(e); + } + { + final BaseDocument e = new BaseDocument(UUID.randomUUID().toString()); + e.setKey("2"); + values.add(e); + } + db.collection(COLLECTION_NAME).insertDocuments(values).get(); + final Collection updatedValues = new ArrayList<>(); + for (final BaseDocument i : values) { + i.addAttribute("a", "test"); + updatedValues.add(i); + } + db.collection(COLLECTION_NAME).updateDocuments(updatedValues) + .whenComplete((updateResult, ex) -> { + assertThat(updateResult.getDocuments().size()).isEqualTo(2); + assertThat(updateResult.getErrors().size()).isEqualTo(0); + }) + .get(); + } + + @Test + void updateDocumentsWithDifferentReturnType() throws ExecutionException, InterruptedException { + ArangoCollectionAsync collection = db.collection(COLLECTION_NAME); + List keys = + IntStream.range(0, 3).mapToObj(it -> "key-" + UUID.randomUUID()).collect(Collectors.toList()); + List docs = keys.stream() + .map(BaseDocument::new) + .peek(it -> it.addAttribute("a", "test")) + .collect(Collectors.toList()); + + collection.insertDocuments(docs).get(); + + List> modifiedDocs = docs.stream() + .peek(it -> it.addAttribute("b", "test")) + .map(it -> { + Map map = new HashMap<>(); + map.put("_key", it.getKey()); + map.put("a", it.getAttribute("a")); + map.put("b", it.getAttribute("b")); + return map; + }) + .collect(Collectors.toList()); + + final MultiDocumentEntity> updateResult = collection + .updateDocuments(modifiedDocs, new DocumentUpdateOptions().returnNew(true), BaseDocument.class).get(); + assertThat(updateResult.getDocuments()).hasSize(3); + assertThat(updateResult.getErrors()).isEmpty(); + assertThat(updateResult.getDocuments().stream().map(DocumentUpdateEntity::getNew) + .allMatch(it -> it.getAttribute("a").equals("test") && it.getAttribute("b").equals("test"))) + .isTrue(); + } + + @Test + void updateDocumentsOne() throws InterruptedException, ExecutionException { + final Collection values = new ArrayList<>(); + { + final BaseDocument e = new BaseDocument(UUID.randomUUID().toString()); + e.setKey("1"); + values.add(e); + } + db.collection(COLLECTION_NAME).insertDocuments(values).get(); + final Collection updatedValues = new ArrayList<>(); + final BaseDocument first = values.iterator().next(); + first.addAttribute("a", "test"); + updatedValues.add(first); + db.collection(COLLECTION_NAME).updateDocuments(updatedValues) + .whenComplete((updateResult, ex) -> { + assertThat(updateResult.getDocuments().size()).isEqualTo(1); + assertThat(updateResult.getErrors().size()).isEqualTo(0); + }) + .get(); + } + + @Test + void updateDocumentsEmpty() throws InterruptedException, ExecutionException { + final Collection values = new ArrayList<>(); + db.collection(COLLECTION_NAME).updateDocuments(values) + .whenComplete((updateResult, ex) -> { + assertThat(updateResult.getDocuments().size()).isEqualTo(0); + assertThat(updateResult.getErrors().size()).isEqualTo(0); + }) + .get(); + } + + @Test + void updateDocumentsWithoutKey() throws InterruptedException, ExecutionException { + final Collection values = new ArrayList<>(); + { + values.add(new BaseDocument("1")); + } + db.collection(COLLECTION_NAME).insertDocuments(values).get(); + final Collection updatedValues = new ArrayList<>(); + for (final BaseDocument i : values) { + i.addAttribute("a", "test"); + updatedValues.add(i); + } + updatedValues.add(new BaseDocument()); + db.collection(COLLECTION_NAME).updateDocuments(updatedValues) + .whenComplete((updateResult, ex) -> { + assertThat(updateResult.getDocuments().size()).isEqualTo(1); + assertThat(updateResult.getErrors().size()).isEqualTo(1); + }) + .get(); + } + + @Test + void updateDocumentsRawData() throws ExecutionException, InterruptedException { + ArangoCollectionAsync collection = db.collection(COLLECTION_NAME); + final RawData values = RawData.of("[{\"_key\":\"1\"}, {\"_key\":\"2\"}]"); + collection.insertDocuments(values).get(); + + final RawData updatedValues = RawData.of("[{\"_key\":\"1\", \"foo\":\"bar\"}, {\"_key\":\"2\", " + + "\"foo\":\"bar\"}]"); + final MultiDocumentEntity updateResult = collection.updateDocuments(updatedValues).get(); + assertThat(updateResult.getDocuments()).hasSize(2); + assertThat(updateResult.getErrors()).isEmpty(); + } + + @Test + void updateDocumentsRawDataReturnNew() throws ExecutionException, InterruptedException { + ArangoCollectionAsync collection = db.collection(COLLECTION_NAME); + final RawData values = RawData.of("[{\"_key\":\"1\"}, {\"_key\":\"2\"}]"); + collection.insertDocuments(values).get(); + + final RawData updatedValues = RawData.of("[{\"_key\":\"1\", \"foo\":\"bar\"}, {\"_key\":\"2\", " + +"\"foo\":\"bar\"}]"); + MultiDocumentEntity> updateResult = + collection.updateDocuments(updatedValues, new DocumentUpdateOptions().returnNew(true)).get(); + assertThat(updateResult.getDocuments()).hasSize(2); + assertThat(updateResult.getErrors()).isEmpty(); + for (DocumentUpdateEntity doc : updateResult.getDocuments()) { + RawData d = doc.getNew(); + assertThat(d) + .isNotNull() + .isInstanceOf(RawJson.class); + + JsonNode jn = SerdeUtils.INSTANCE.parseJson(((RawJson) d).getValue()); + assertThat(jn.has("foo")).isTrue(); + assertThat(jn.get("foo").textValue()).isEqualTo("bar"); + } + } + + @Test + void replaceDocuments() throws InterruptedException, ExecutionException { + final Collection values = new ArrayList<>(); + { + values.add(new BaseDocument("1")); + values.add(new BaseDocument("2")); + } + db.collection(COLLECTION_NAME).insertDocuments(values).get(); + final Collection updatedValues = new ArrayList<>(); + for (final BaseDocument i : values) { + i.addAttribute("a", "test"); + updatedValues.add(i); + } + db.collection(COLLECTION_NAME).replaceDocuments(updatedValues) + .whenComplete((updateResult, ex) -> { + assertThat(updateResult.getDocuments().size()).isEqualTo(2); + assertThat(updateResult.getErrors().size()).isEqualTo(0); + }) + .get(); + } + + @Test + void replaceDocumentsOne() throws InterruptedException, ExecutionException { + final Collection values = new ArrayList<>(); + { + final BaseDocument e = new BaseDocument(UUID.randomUUID().toString()); + e.setKey("1"); + values.add(e); + } + db.collection(COLLECTION_NAME).insertDocuments(values).get(); + final Collection updatedValues = new ArrayList<>(); + final BaseDocument first = values.iterator().next(); + first.addAttribute("a", "test"); + updatedValues.add(first); + db.collection(COLLECTION_NAME).updateDocuments(updatedValues) + .whenComplete((updateResult, ex) -> { + assertThat(updateResult.getDocuments().size()).isEqualTo(1); + assertThat(updateResult.getErrors().size()).isEqualTo(0); + }) + .get(); + } + + @Test + void replaceDocumentsEmpty() throws InterruptedException, ExecutionException { + final Collection values = new ArrayList<>(); + db.collection(COLLECTION_NAME).updateDocuments(values) + .whenComplete((updateResult, ex) -> { + assertThat(updateResult.getDocuments().size()).isEqualTo(0); + assertThat(updateResult.getErrors().size()).isEqualTo(0); + }) + .get(); + } + + @Test + void replaceDocumentsWithoutKey() throws InterruptedException, ExecutionException { + final Collection values = new ArrayList<>(); + { + values.add(new BaseDocument("1")); + } + db.collection(COLLECTION_NAME).insertDocuments(values).get(); + final Collection updatedValues = new ArrayList<>(); + for (final BaseDocument i : values) { + i.addAttribute("a", "test"); + updatedValues.add(i); + } + updatedValues.add(new BaseDocument()); + db.collection(COLLECTION_NAME).updateDocuments(updatedValues) + .whenComplete((updateResult, ex) -> { + assertThat(updateResult.getDocuments().size()).isEqualTo(1); + assertThat(updateResult.getErrors().size()).isEqualTo(1); + }) + .get(); + } + + @Test + void replaceDocumentsRawData() throws ExecutionException, InterruptedException { + ArangoCollectionAsync collection = db.collection(COLLECTION_NAME); + + final RawData values = RawData.of("[{\"_key\":\"1\"}, {\"_key\":\"2\"}]"); + collection.insertDocuments(values).get(); + + final RawData updatedValues = RawData.of("[{\"_key\":\"1\", \"foo\":\"bar\"}, {\"_key\":\"2\", " + +"\"foo\":\"bar\"}]"); + final MultiDocumentEntity updateResult = collection.replaceDocuments(updatedValues).get(); + assertThat(updateResult.getDocuments()).hasSize(2); + assertThat(updateResult.getErrors()).isEmpty(); + } + + @Test + void replaceDocumentsRawDataReturnNew() throws ExecutionException, InterruptedException { + ArangoCollectionAsync collection = db.collection(COLLECTION_NAME); + + final RawData values = RawData.of("[{\"_key\":\"1\"}, {\"_key\":\"2\"}]"); + collection.insertDocuments(values).get(); + + final RawData updatedValues = RawData.of("[{\"_key\":\"1\", \"foo\":\"bar\"}, {\"_key\":\"2\", " + + "\"foo\":\"bar\"}]"); + MultiDocumentEntity> updateResult = + collection.replaceDocuments(updatedValues, new DocumentReplaceOptions().returnNew(true)).get(); + assertThat(updateResult.getDocuments()).hasSize(2); + assertThat(updateResult.getErrors()).isEmpty(); + for (DocumentUpdateEntity doc : updateResult.getDocuments()) { + RawData d = doc.getNew(); + assertThat(d) + .isNotNull() + .isInstanceOf(RawJson.class); + + JsonNode jn = SerdeUtils.INSTANCE.parseJson(((RawJson) d).getValue()); + assertThat(jn.has("foo")).isTrue(); + assertThat(jn.get("foo").textValue()).isEqualTo("bar"); + } + } + + @Test + void getInfo() throws InterruptedException, ExecutionException { + db.collection(COLLECTION_NAME).getInfo() + .whenComplete((result, ex) -> assertThat(result.getName()).isEqualTo(COLLECTION_NAME)) + .get(); + } + + @Test + void getPropeties() throws InterruptedException, ExecutionException { + db.collection(COLLECTION_NAME).getProperties() + .whenComplete((result, ex) -> { + assertThat(result.getName()).isEqualTo(COLLECTION_NAME); + assertThat(result.getCount()).isNull(); + }) + .get(); + } + + @Test + void changeProperties() throws InterruptedException, ExecutionException { + final String collection = COLLECTION_NAME + "_prop"; + try { + db.createCollection(collection).get(); + final CollectionPropertiesEntity properties = db.collection(collection).getProperties().get(); + assertThat(properties.getWaitForSync()).isNotNull(); + final CollectionPropertiesOptions options = new CollectionPropertiesOptions(); + options.waitForSync(!properties.getWaitForSync()); + db.collection(collection).changeProperties(options) + .whenComplete((changedProperties, ex) -> { + assertThat(changedProperties.getWaitForSync()).isNotNull(); + assertThat(changedProperties.getWaitForSync()).isNotEqualTo(properties.getWaitForSync()); + }) + .get(); + } finally { + db.collection(collection).drop().get(); + } + } + + @Test + void rename() throws InterruptedException, ExecutionException { + assumeTrue(isSingleServer()); + db.collection(COLLECTION_NAME).rename(COLLECTION_NAME + "1") + .whenComplete((result, ex) -> { + assertThat(result).isNotNull(); + assertThat(result.getName()).isEqualTo(COLLECTION_NAME + "1"); + }) + .get(); + final CollectionEntity info = db.collection(COLLECTION_NAME + "1").getInfo().get(); + assertThat(info.getName()).isEqualTo(COLLECTION_NAME + "1"); + try { + db.collection(COLLECTION_NAME).getInfo().get(); + fail(); + } catch (final ExecutionException e) { + assertThat(e.getCause()).isInstanceOf(ArangoDBException.class); + } + db.collection(COLLECTION_NAME + "1").rename(COLLECTION_NAME).get(); + } + + @Test + void responsibleShard() throws ExecutionException, InterruptedException { + assumeTrue(isCluster()); + assumeTrue(isAtLeastVersion(3, 5)); + ShardEntity shard = db.collection(COLLECTION_NAME).getResponsibleShard(new BaseDocument("testKey")).get(); + assertThat(shard).isNotNull(); + assertThat(shard.getShardId()).isNotNull(); + } + + @Test + void getRevision() throws InterruptedException, ExecutionException { + db.collection(COLLECTION_NAME).getRevision() + .whenComplete((result, ex) -> { + assertThat(result).isNotNull(); + assertThat(result.getName()).isEqualTo(COLLECTION_NAME); + assertThat(result.getRevision()).isNotNull(); + }) + .get(); + } + + @Test + void grantAccessRW() throws InterruptedException, ExecutionException { + try { + arangoDB.createUser("user1", "1234", null).get(); + db.collection(COLLECTION_NAME).grantAccess("user1", Permissions.RW).get(); + } finally { + arangoDB.deleteUser("user1").get(); + } + } + + @Test + void grantAccessRO() throws InterruptedException, ExecutionException { + try { + arangoDB.createUser("user1", "1234", null).get(); + db.collection(COLLECTION_NAME).grantAccess("user1", Permissions.RO).get(); + } finally { + arangoDB.deleteUser("user1").get(); + } + } + + @Test + void grantAccessNONE() throws InterruptedException, ExecutionException { + try { + arangoDB.createUser("user1", "1234", null).get(); + db.collection(COLLECTION_NAME).grantAccess("user1", Permissions.NONE).get(); + } finally { + arangoDB.deleteUser("user1").get(); + } + } + + @Test + void grantAccessUserNotFound() { + Throwable thrown = + catchThrowable(() -> db.collection(COLLECTION_NAME).grantAccess("user1", Permissions.RW).get()); + assertThat(thrown).isInstanceOf(ExecutionException.class); + } + + @Test + void revokeAccess() throws InterruptedException, ExecutionException { + try { + arangoDB.createUser("user1", "1234", null).get(); + db.collection(COLLECTION_NAME).grantAccess("user1", Permissions.NONE).get(); + } finally { + arangoDB.deleteUser("user1").get(); + } + } + + @Test + void revokeAccessUserNotFound() { + Throwable thrown = + catchThrowable(() -> db.collection(COLLECTION_NAME).grantAccess("user1", Permissions.NONE).get()); + assertThat(thrown).isInstanceOf(ExecutionException.class); + } + + @Test + void resetAccess() throws InterruptedException, ExecutionException { + try { + arangoDB.createUser("user1", "1234", null).get(); + db.collection(COLLECTION_NAME).resetAccess("user1").get(); + } finally { + arangoDB.deleteUser("user1").get(); + } + } + + @Test + void resetAccessUserNotFound() { + Throwable thrown = catchThrowable(() -> db.collection(COLLECTION_NAME).resetAccess("user1").get()); + assertThat(thrown).isInstanceOf(ExecutionException.class); + } + + @Test + void getPermissions() throws InterruptedException, ExecutionException { + assertThat(db.collection(COLLECTION_NAME).getPermissions("root").get()).isEqualTo(Permissions.RW); + } + + @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, property = "type") + public interface Animal { + String getKey(); + + String getName(); + } + + public static class Dog implements Animal { + + @Key + private String key; + private String name; + + public Dog() { + } + + public Dog(String key, String name) { + this.key = key; + this.name = name; + } + + @Override + public String getKey() { + return key; + } + + public void setKey(String key) { + this.key = key; + } + + @Override + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + } + + public static class Cat implements Animal { + @Key + private String key; + private String name; + + public Cat() { + } + + public Cat(String key, String name) { + this.key = key; + this.name = name; + } + + @Override + public String getKey() { + return key; + } + + public void setKey(String key) { + this.key = key; + } + + @Override + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + } +} diff --git a/shaded-integration-tests/src/test/jackson/java/com/arangodb/async/ArangoDBTest.java b/shaded-integration-tests/src/test/jackson/java/com/arangodb/async/ArangoDBTest.java new file mode 100644 index 000000000..19f77ca5c --- /dev/null +++ b/shaded-integration-tests/src/test/jackson/java/com/arangodb/async/ArangoDBTest.java @@ -0,0 +1,566 @@ +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed 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. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.async; + +import com.arangodb.*; +import com.arangodb.entity.*; +import com.arangodb.internal.config.FileConfigPropertiesProvider; +import com.arangodb.internal.serde.SerdeUtils; +import com.arangodb.model.*; +import com.arangodb.util.RawJson; +import com.arangodb.util.TestUtils; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.Timeout; + +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutionException; +import java.util.stream.Collectors; +import java.util.stream.IntStream; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.fail; +import static org.junit.jupiter.api.Assumptions.assumeTrue; + +/** + * @author Mark Vollmary + * @author Michele Rastelli + */ +class ArangoDBTest { + + private static final String ROOT = "root"; + private static final String USER = "mit dem mund"; + private static final String PW = "machts der hund"; + private static Boolean extendedNames; + + private final ArangoDBAsync arangoDB = new ArangoDBAsync.Builder() + .loadProperties(new FileConfigPropertiesProvider()) + .build(); + private final ArangoDB arangoDBSync = new ArangoDB.Builder() + .loadProperties(new FileConfigPropertiesProvider()) + .build(); + + private boolean isEnterprise() { + return arangoDBSync.getVersion().getLicense() == License.ENTERPRISE; + } + + private boolean isCluster() { + return arangoDBSync.getRole() == ServerRole.COORDINATOR; + } + + private boolean isAtLeastVersion(final int major, final int minor) { + return TestUtils.isAtLeastVersion(arangoDBSync.getVersion().getVersion(), major, minor, 0); + } + + private boolean isLessThanVersion(final int major, final int minor) { + return TestUtils.isLessThanVersion(arangoDBSync.getVersion().getVersion(), major, minor, 0); + } + + private boolean supportsExtendedNames() { + if (extendedNames == null) { + try { + ArangoDatabase testDb = arangoDBSync.db(DbName.of("test-" + TestUtils.generateRandomDbName(20, true))); + testDb.create(); + extendedNames = true; + testDb.drop(); + } catch (ArangoDBException e) { + extendedNames = false; + } + } + return extendedNames; + } + + @Test + void getVersion() throws InterruptedException, ExecutionException { + arangoDB.getVersion() + .whenComplete((version, ex) -> { + assertThat(version).isNotNull(); + assertThat(version.getServer()).isNotNull(); + assertThat(version.getVersion()).isNotNull(); + }) + .get(); + } + + @Test + @Timeout(2) + void nestedGetVersion() { + for (int i = 0; i < 100; i++) { + try { + arangoDB.getVersion() + .whenComplete((v1, ex1) -> { + assertThat(v1).isNotNull(); + assertThat(v1.getServer()).isNotNull(); + assertThat(v1.getVersion()).isNotNull(); + try { + arangoDB.getVersion() + .whenComplete((v2, ex2) -> { + assertThat(v2).isNotNull(); + assertThat(v2.getServer()).isNotNull(); + assertThat(v2.getVersion()).isNotNull(); + try { + arangoDB.getVersion() + .whenComplete((v3, ex3) -> { + assertThat(v3).isNotNull(); + assertThat(v3.getServer()).isNotNull(); + assertThat(v3.getVersion()).isNotNull(); + }) + .get(); + } catch (InterruptedException | ExecutionException e) { + e.printStackTrace(); + fail(); + } + }) + .get(); + } catch (InterruptedException | ExecutionException e) { + e.printStackTrace(); + fail(); + } + }) + .get(); + } catch (InterruptedException | ExecutionException e) { + e.printStackTrace(); + fail(); + } + } + } + + @Test + void createDatabase() throws InterruptedException, ExecutionException { + arangoDB.createDatabase(BaseTest.TEST_DB) + .whenComplete((result, ex) -> assertThat(result).isEqualTo(true)) + .get(); + arangoDB.db(BaseTest.TEST_DB).drop().get(); + } + + @Test + void createDatabaseWithOptions() throws ExecutionException, InterruptedException { + assumeTrue(isCluster()); + assumeTrue(isAtLeastVersion(3, 6)); + + final DbName dbName = DbName.of("testDB-" + TestUtils.generateRandomDbName(20, supportsExtendedNames())); + final Boolean resultCreate = arangoDB.createDatabase(new DBCreateOptions() + .name(dbName) + .options(new DatabaseOptions() + .writeConcern(2) + .replicationFactor(2) + .sharding("") + ) + ).get(); + assertThat(resultCreate).isTrue(); + + DatabaseEntity info = arangoDB.db(dbName).getInfo().get(); + assertThat(info.getReplicationFactor().getValue()).isEqualTo(2); + assertThat(info.getWriteConcern()).isEqualTo(2); + assertThat(info.getSharding()).isEmpty(); + + final Boolean resultDelete = arangoDB.db(dbName).drop().get(); + assertThat(resultDelete).isTrue(); + } + + @Test + void createDatabaseWithOptionsSatellite() throws ExecutionException, InterruptedException { + assumeTrue(isCluster()); + assumeTrue(isEnterprise()); + assumeTrue(isAtLeastVersion(3, 6)); + + final DbName dbName = DbName.of("testDB-" + TestUtils.generateRandomDbName(20, supportsExtendedNames())); + final Boolean resultCreate = arangoDB.createDatabase(new DBCreateOptions() + .name(dbName) + .options(new DatabaseOptions() + .writeConcern(2) + .replicationFactor(ReplicationFactor.ofSatellite()) + .sharding("") + ) + ).get(); + assertThat(resultCreate).isTrue(); + + DatabaseEntity info = arangoDB.db(dbName).getInfo().get(); + assertThat(info.getReplicationFactor()).isEqualTo(ReplicationFactor.ofSatellite()); + assertThat(info.getWriteConcern()).isEqualTo(2); + assertThat(info.getSharding()).isEmpty(); + + final Boolean resultDelete = arangoDB.db(dbName).drop().get(); + assertThat(resultDelete).isTrue(); + } + + @Test + void deleteDatabase() throws InterruptedException, ExecutionException { + final Boolean resultCreate = arangoDB.createDatabase(BaseTest.TEST_DB).get(); + assertThat(resultCreate).isTrue(); + arangoDB.db(BaseTest.TEST_DB).drop() + .whenComplete((resultDelete, ex) -> assertThat(resultDelete).isEqualTo(true)) + .get(); + } + + @Test + void getDatabases() throws InterruptedException, ExecutionException { + Collection dbs = arangoDB.getDatabases().get(); + assertThat(dbs).isNotNull(); + assertThat(dbs).isNotEmpty(); + final int dbCount = dbs.size(); + assertThat(dbs).contains("_system"); + arangoDB.createDatabase(BaseTest.TEST_DB).get(); + dbs = arangoDB.getDatabases().get(); + assertThat(dbs).hasSizeGreaterThan(dbCount); + assertThat(dbs).contains("_system"); + assertThat(dbs).contains(BaseTest.TEST_DB.get()); + arangoDB.db(BaseTest.TEST_DB).drop().get(); + } + + @Test + void getAccessibleDatabases() throws InterruptedException, ExecutionException { + arangoDB.getAccessibleDatabases() + .whenComplete((dbs, ex) -> { + assertThat(dbs).isNotNull(); + assertThat(dbs).isNotEmpty(); + assertThat(dbs).contains("_system"); + }) + .get(); + } + + @Test + void getAccessibleDatabasesFor() throws InterruptedException, ExecutionException { + arangoDB.getAccessibleDatabasesFor("root") + .whenComplete((dbs, ex) -> { + assertThat(dbs).isNotNull(); + assertThat(dbs).isNotNull(); + assertThat(dbs).isNotEmpty(); + assertThat(dbs).contains("_system"); + }) + .get(); + } + + @Test + void createUser() throws InterruptedException, ExecutionException { + try { + arangoDB.createUser(USER, PW, null) + .whenComplete((result, ex) -> { + assertThat(result).isNotNull(); + assertThat(result.getUser()).isEqualTo(USER); + }) + .get(); + } finally { + arangoDB.deleteUser(USER).get(); + } + } + + @Test + void deleteUser() throws InterruptedException, ExecutionException { + arangoDB.createUser(USER, PW, null).get(); + arangoDB.deleteUser(USER).get(); + } + + @Test + void getUserRoot() throws InterruptedException, ExecutionException { + arangoDB.getUser(ROOT) + .whenComplete((user, ex) -> { + assertThat(user).isNotNull(); + assertThat(user.getUser()).isEqualTo(ROOT); + }) + .get(); + } + + @Test + void getUser() throws InterruptedException, ExecutionException { + try { + arangoDB.createUser(USER, PW, null).get(); + arangoDB.getUser(USER) + .whenComplete((user, ex) -> assertThat(user.getUser()).isEqualTo(USER)) + .get(); + } finally { + arangoDB.deleteUser(USER).get(); + } + + } + + @Test + void getUsersOnlyRoot() throws InterruptedException, ExecutionException { + arangoDB.getUsers() + .whenComplete((users, ex) -> { + assertThat(users).isNotNull(); + assertThat(users).isNotEmpty(); + }) + .get(); + } + + @Test + void getUsers() throws InterruptedException, ExecutionException { + try { + arangoDB.createUser(USER, PW, null).get(); + arangoDB.getUsers() + .whenComplete((users, ex) -> { + assertThat(users).isNotNull(); + assertThat(users).hasSizeGreaterThanOrEqualTo(2); + assertThat( + users.stream().map(UserEntity::getUser).collect(Collectors.toList()) + ).contains(ROOT, USER); + }) + .get(); + } finally { + arangoDB.deleteUser(USER).get(); + } + } + + @Test + void updateUserNoOptions() throws InterruptedException, ExecutionException { + try { + arangoDB.createUser(USER, PW, null).get(); + arangoDB.updateUser(USER, null).get(); + } finally { + arangoDB.deleteUser(USER).get(); + } + } + + @Test + void updateUser() throws InterruptedException, ExecutionException { + try { + final Map extra = new HashMap<>(); + extra.put("hund", false); + arangoDB.createUser(USER, PW, new UserCreateOptions().extra(extra)).get(); + extra.put("hund", true); + extra.put("mund", true); + { + arangoDB.updateUser(USER, new UserUpdateOptions().extra(extra)) + .whenComplete((user, ex) -> { + assertThat(user).isNotNull(); + assertThat(user.getExtra()).hasSize(2); + assertThat(user.getExtra().get("hund")).isNotNull(); + assertThat(Boolean.valueOf(String.valueOf(user.getExtra().get("hund")))).isTrue(); + }) + .get(); + } + arangoDB.getUser(USER) + .whenComplete((user2, ex) -> { + assertThat(user2.getExtra()).hasSize(2); + assertThat(user2.getExtra().get("hund")).isNotNull(); + assertThat(Boolean.valueOf(String.valueOf(user2.getExtra().get("hund")))).isTrue(); + }) + .get(); + } finally { + arangoDB.deleteUser(USER).get(); + } + } + + @Test + void replaceUser() throws InterruptedException, ExecutionException { + try { + final Map extra = new HashMap<>(); + extra.put("hund", false); + arangoDB.createUser(USER, PW, new UserCreateOptions().extra(extra)).get(); + extra.remove("hund"); + extra.put("mund", true); + { + arangoDB.replaceUser(USER, new UserUpdateOptions().extra(extra)) + .whenComplete((user, ex) -> { + assertThat(user).isNotNull(); + assertThat(user.getExtra()).hasSize(1); + assertThat(user.getExtra().get("mund")).isNotNull(); + assertThat(Boolean.valueOf(String.valueOf(user.getExtra().get("mund")))).isTrue(); + }) + .get(); + } + { + arangoDB.getUser(USER) + .whenComplete((user2, ex) -> { + assertThat(user2.getExtra()).hasSize(1); + assertThat(user2.getExtra().get("mund")).isNotNull(); + assertThat(Boolean.valueOf(String.valueOf(user2.getExtra().get("mund")))).isTrue(); + }) + .get(); + } + } finally { + arangoDB.deleteUser(USER).get(); + } + } + + @Test + void updateUserDefaultDatabaseAccess() throws InterruptedException, ExecutionException { + try { + arangoDB.createUser(USER, PW).get(); + arangoDB.grantDefaultDatabaseAccess(USER, Permissions.RW).get(); + } finally { + arangoDB.deleteUser(USER).get(); + } + } + + @Test + void updateUserDefaultCollectionAccess() throws InterruptedException, ExecutionException { + try { + arangoDB.createUser(USER, PW).get(); + arangoDB.grantDefaultCollectionAccess(USER, Permissions.RW).get(); + } finally { + arangoDB.deleteUser(USER).get(); + } + } + + @Test + void authenticationFailPassword() throws InterruptedException { + final ArangoDBAsync arangoDB = new ArangoDBAsync.Builder() + .loadProperties(new FileConfigPropertiesProvider()) + .password("no").jwt(null).build(); + try { + arangoDB.getVersion().get(); + fail(); + } catch (final ExecutionException exception) { + assertThat(exception.getCause()).isInstanceOf(ArangoDBException.class); + } + } + + @Test + void authenticationFailUser() throws InterruptedException { + final ArangoDBAsync arangoDB = new ArangoDBAsync.Builder() + .loadProperties(new FileConfigPropertiesProvider()) + .user("no").jwt(null).build(); + try { + arangoDB.getVersion().get(); + fail(); + } catch (final ExecutionException exception) { + assertThat(exception.getCause()).isInstanceOf(ArangoDBException.class); + } + } + + @Test + void execute() throws InterruptedException, ExecutionException { + arangoDB + .execute(Request.builder() + .db(DbName.SYSTEM) + .method(Request.Method.GET) + .path("/_api/version") + .build(), RawJson.class) + .whenComplete((response, ex) -> { + assertThat(response.getBody()).isNotNull(); + assertThat(SerdeUtils.INSTANCE.parseJson(response.getBody().getValue()).get("version").isTextual()).isTrue(); + }) + .get(); + } + + @Test + void execute_acquireHostList_enabled() throws InterruptedException, ExecutionException { + final ArangoDBAsync arangoDB = new ArangoDBAsync.Builder() + .loadProperties(new FileConfigPropertiesProvider()) + .acquireHostList(true).build(); + arangoDB + .execute(Request.builder() + .db(DbName.SYSTEM) + .method(Request.Method.GET) + .path("/_api/version") + .build(), RawJson.class) + .whenComplete((response, ex) -> { + assertThat(response.getBody()).isNotNull(); + assertThat(SerdeUtils.INSTANCE.parseJson(response.getBody().getValue()).get("version").isTextual()).isTrue(); + }) + .get(); + } + + @Test + void getLogEntries() throws InterruptedException, ExecutionException { + assumeTrue(isAtLeastVersion(3, 8)); + arangoDB.getLogEntries(null) + .whenComplete((logs, ex) -> { + assertThat(logs).isNotNull(); + assertThat(logs.getTotal()).isPositive(); + assertThat((long) logs.getMessages().size()).isEqualTo(logs.getTotal()); + }) + .get(); + } + + @Test + void getLogLevel() throws InterruptedException, ExecutionException { + assumeTrue(isAtLeastVersion(3, 7)); // it fails in 3.6 active-failover (BTS-362) + arangoDB.getLogLevel() + .whenComplete((logLevel, ex) -> { + assertThat(logLevel).isNotNull(); + assertThat(logLevel.getAgency()).isEqualTo(LogLevelEntity.LogLevel.INFO); + }) + .get(); + } + + @Test + void setLogLevel() throws InterruptedException, ExecutionException { + assumeTrue(isAtLeastVersion(3, 7)); // it fails in 3.6 active-failover (BTS-362) + final LogLevelEntity entity = new LogLevelEntity(); + try { + entity.setAgency(LogLevelEntity.LogLevel.ERROR); + arangoDB.setLogLevel(entity) + .whenComplete((logLevel, ex) -> { + assertThat(logLevel).isNotNull(); + assertThat(logLevel.getAgency()).isEqualTo(LogLevelEntity.LogLevel.ERROR); + }) + .get(); + } finally { + entity.setAgency(LogLevelEntity.LogLevel.INFO); + arangoDB.setLogLevel(entity).get(); + } + } + + @Test + @Disabled("Manual execution only") + void queueTime() throws InterruptedException, ExecutionException { + List>> reqs = IntStream.range(0, 80) + .mapToObj(__ -> arangoDB.db().query("RETURN SLEEP(1)", Void.class)) + .collect(Collectors.toList()); + for (CompletableFuture> req : reqs) { + req.get(); + } + + QueueTimeMetrics qt = arangoDB.metrics().getQueueTime(); + double avg = qt.getAvg(); + QueueTimeSample[] values = qt.getValues(); + if (isAtLeastVersion(3, 9)) { + assertThat(values).hasSize(20); + for (int i = 0; i < values.length; i++) { + assertThat(values[i]).isNotNull(); + assertThat(values[i].value).isGreaterThanOrEqualTo(0.0); + if (i > 0) { + assertThat(values[i].timestamp).isGreaterThanOrEqualTo(values[i - 1].timestamp); + } + } + assertThat(avg).isGreaterThan(0.0); + } else { + assertThat(avg).isEqualTo(0.0); + assertThat(values).isEmpty(); + } + } + + @Test + void getQueryOptimizerRules() throws ExecutionException, InterruptedException { + assumeTrue(isAtLeastVersion(3, 10)); + final Collection rules = arangoDB.getQueryOptimizerRules().get(); + assertThat(rules).isNotEmpty(); + for (QueryOptimizerRule rule : rules) { + assertThat(rule).isNotNull(); + assertThat(rule.getName()).isNotNull(); + QueryOptimizerRule.Flags flags = rule.getFlags(); + assertThat(flags.getHidden()).isNotNull(); + assertThat(flags.getClusterOnly()).isNotNull(); + assertThat(flags.getCanBeDisabled()).isNotNull(); + assertThat(flags.getCanCreateAdditionalPlans()).isNotNull(); + assertThat(flags.getDisabledByDefault()).isNotNull(); + assertThat(flags.getEnterpriseOnly()).isNotNull(); + } + } + + +} diff --git a/shaded-integration-tests/src/test/jackson/java/com/arangodb/async/ArangoDatabaseTest.java b/shaded-integration-tests/src/test/jackson/java/com/arangodb/async/ArangoDatabaseTest.java new file mode 100644 index 000000000..a12bf84ec --- /dev/null +++ b/shaded-integration-tests/src/test/jackson/java/com/arangodb/async/ArangoDatabaseTest.java @@ -0,0 +1,1024 @@ +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed 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. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.async; + +import com.arangodb.ArangoDBException; +import com.arangodb.DbName; +import com.arangodb.entity.AqlExecutionExplainEntity.ExecutionPlan; +import com.arangodb.entity.*; +import com.arangodb.entity.AqlParseEntity.AstNode; +import com.arangodb.entity.QueryCachePropertiesEntity.CacheMode; +import com.arangodb.model.*; +import com.arangodb.util.RawJson; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.node.JsonNodeFactory; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; + +import java.io.IOException; +import java.util.*; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.atomic.AtomicInteger; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.catchThrowable; +import static org.junit.jupiter.api.Assertions.fail; +import static org.junit.jupiter.api.Assumptions.assumeTrue; + + +/** + * @author Mark Vollmary + * @author Michele Rastelli + */ +class ArangoDatabaseTest extends BaseTest { + + private static final String COLLECTION_NAME = "db_test"; + private static final String GRAPH_NAME = "graph_test"; + + @Test + void create() throws InterruptedException, ExecutionException { + try { + final Boolean result = arangoDB.db(DbName.of(BaseTest.TEST_DB.get() + "_1")).create().get(); + assertThat(result).isTrue(); + } finally { + arangoDB.db(DbName.of(BaseTest.TEST_DB.get() + "_1")).drop().get(); + } + } + + @Test + void getVersion() throws InterruptedException, ExecutionException { + db.getVersion() + .whenComplete((version, ex) -> { + assertThat(version).isNotNull(); + assertThat(version.getServer()).isNotNull(); + assertThat(version.getVersion()).isNotNull(); + }) + .get(); + } + + @Test + void getEngine() throws ExecutionException, InterruptedException { + final ArangoDBEngine engine = db.getEngine().get(); + assertThat(engine).isNotNull(); + assertThat(engine.getName()).isNotNull(); + } + + @Test + void exists() throws InterruptedException, ExecutionException { + assertThat(db.exists().get()).isTrue(); + assertThat(arangoDB.db(DbName.of("no")).exists().get()).isFalse(); + } + + @Test + void getAccessibleDatabases() throws InterruptedException, ExecutionException { + db.getAccessibleDatabases() + .whenComplete((dbs, ex) -> { + assertThat(dbs).isNotNull(); + assertThat(dbs.size()).isGreaterThan(0); + assertThat(dbs).contains("_system"); + }) + .get(); + } + + @Test + void createCollection() throws InterruptedException, ExecutionException { + db.createCollection(COLLECTION_NAME, null) + .whenComplete((result, ex) -> { + assertThat(result).isNotNull(); + assertThat(result.getId()).isNotNull(); + }) + .get(); + db.collection(COLLECTION_NAME).drop().get(); + } + + @Test + void createCollectionWithReplicationFactor() throws InterruptedException, ExecutionException { + assumeTrue(isCluster()); + final CollectionEntity result = db + .createCollection(COLLECTION_NAME, new CollectionCreateOptions().replicationFactor(2)).get(); + assertThat(result).isNotNull(); + assertThat(result.getId()).isNotNull(); + assertThat(db.collection(COLLECTION_NAME).getProperties().get().getReplicationFactor().getValue()).isEqualTo(2); + db.collection(COLLECTION_NAME).drop().get(); + } + + @Test + void createCollectionWithWriteConcern() throws ExecutionException, InterruptedException { + assumeTrue(isAtLeastVersion(3, 5)); + assumeTrue(isCluster()); + + final CollectionEntity result = db.createCollection(COLLECTION_NAME, + new CollectionCreateOptions().replicationFactor(2).writeConcern(2)).get(); + assertThat(result).isNotNull(); + assertThat(result.getId()).isNotNull(); + assertThat(db.collection(COLLECTION_NAME).getProperties().get().getReplicationFactor().getValue()).isEqualTo(2); + assertThat(db.collection(COLLECTION_NAME).getProperties().get().getWriteConcern()).isEqualTo(2); + db.collection(COLLECTION_NAME).drop(); + } + + @Test + void createCollectionWithNumberOfShards() throws InterruptedException, ExecutionException { + assumeTrue(isCluster()); + final CollectionEntity result = db + .createCollection(COLLECTION_NAME, new CollectionCreateOptions().numberOfShards(2)).get(); + assertThat(result).isNotNull(); + assertThat(result.getId()).isNotNull(); + assertThat(db.collection(COLLECTION_NAME).getProperties().get().getNumberOfShards()).isEqualTo(2); + db.collection(COLLECTION_NAME).drop().get(); + } + + @Test + void createCollectionWithNumberOfShardsAndShardKey() throws InterruptedException, ExecutionException { + assumeTrue(isCluster()); + final CollectionEntity result = db + .createCollection(COLLECTION_NAME, new CollectionCreateOptions().numberOfShards(2).shardKeys("a")) + .get(); + assertThat(result).isNotNull(); + assertThat(result.getId()).isNotNull(); + final CollectionPropertiesEntity properties = db.collection(COLLECTION_NAME).getProperties().get(); + assertThat(properties.getNumberOfShards()).isEqualTo(2); + assertThat(properties.getShardKeys()).hasSize(1); + db.collection(COLLECTION_NAME).drop().get(); + } + + @Test + void createCollectionWithNumberOfShardsAndShardKeys() throws InterruptedException, ExecutionException { + assumeTrue(isCluster()); + final CollectionEntity result = db.createCollection(COLLECTION_NAME, + new CollectionCreateOptions().numberOfShards(2).shardKeys("a", "b")).get(); + assertThat(result).isNotNull(); + assertThat(result.getId()).isNotNull(); + final CollectionPropertiesEntity properties = db.collection(COLLECTION_NAME).getProperties().get(); + assertThat(properties.getNumberOfShards()).isEqualTo(2); + assertThat(properties.getShardKeys()).hasSize(2); + db.collection(COLLECTION_NAME).drop().get(); + } + + @Test + void deleteCollection() throws InterruptedException, ExecutionException { + db.createCollection(COLLECTION_NAME, null).get(); + db.collection(COLLECTION_NAME).drop().get(); + try { + db.collection(COLLECTION_NAME).getInfo().get(); + fail(); + } catch (final ExecutionException e) { + assertThat(e.getCause()).isInstanceOf(ArangoDBException.class); + } + } + + @Test + void deleteSystemCollection() throws InterruptedException, ExecutionException { + final String name = "_system_test"; + db.createCollection(name, new CollectionCreateOptions().isSystem(true)).get(); + db.collection(name).drop(true).get(); + try { + db.collection(name).getInfo().get(); + fail(); + } catch (final ExecutionException e) { + assertThat(e.getCause()).isInstanceOf(ArangoDBException.class); + } + } + + @Test + void deleteSystemCollectionFail() throws InterruptedException, ExecutionException { + final String name = "_system_test"; + db.createCollection(name, new CollectionCreateOptions().isSystem(true)).get(); + try { + db.collection(name).drop().get(); + fail(); + } catch (final ExecutionException e) { + assertThat(e.getCause()).isInstanceOf(ArangoDBException.class); + } + db.collection(name).drop(true).get(); + try { + db.collection(name).getInfo().get(); + fail(); + } catch (final ExecutionException e) { + assertThat(e.getCause()).isInstanceOf(ArangoDBException.class); + } + } + + @Test + void getIndex() throws InterruptedException, ExecutionException { + db.createCollection(COLLECTION_NAME, null).get(); + final Collection fields = new ArrayList<>(); + fields.add("a"); + final IndexEntity createResult = db.collection(COLLECTION_NAME).ensureHashIndex(fields, null).get(); + db.getIndex(createResult.getId()) + .whenComplete((readResult, ex) -> { + assertThat(readResult.getId()).isEqualTo(createResult.getId()); + assertThat(readResult.getType()).isEqualTo(createResult.getType()); + }) + .get(); + db.collection(COLLECTION_NAME).drop().get(); + } + + @Test + void deleteIndex() throws InterruptedException, ExecutionException { + try { + db.createCollection(COLLECTION_NAME, null).get(); + final Collection fields = new ArrayList<>(); + fields.add("a"); + final IndexEntity createResult = db.collection(COLLECTION_NAME).ensureHashIndex(fields, null).get(); + db.deleteIndex(createResult.getId()) + .whenComplete((id, ex) -> { + assertThat(id).isEqualTo(createResult.getId()); + try { + db.getIndex(id).get(); + fail(); + } catch (InterruptedException e) { + fail(); + } catch (ExecutionException e) { + assertThat(e.getCause()).isInstanceOf(ArangoDBException.class); + } + }) + .get(); + } finally { + db.collection(COLLECTION_NAME).drop().get(); + } + } + + @Test + void getCollections() throws InterruptedException, ExecutionException { + try { + final Collection systemCollections = db.getCollections(null).get(); + db.createCollection(COLLECTION_NAME + "1", null).get(); + db.createCollection(COLLECTION_NAME + "2", null).get(); + db.getCollections(null) + .whenComplete((collections, ex) -> { + assertThat(collections.size()).isEqualTo(2 + systemCollections.size()); + assertThat(collections).isNotNull(); + }) + .get(); + } finally { + db.collection(COLLECTION_NAME + "1").drop().get(); + db.collection(COLLECTION_NAME + "2").drop().get(); + } + } + + @Test + void getCollectionsExcludeSystem() throws InterruptedException, ExecutionException { + try { + final CollectionsReadOptions options = new CollectionsReadOptions().excludeSystem(true); + final Collection systemCollections = db.getCollections(options).get(); + assertThat(systemCollections).isEmpty(); + db.createCollection(COLLECTION_NAME + "1", null).get(); + db.createCollection(COLLECTION_NAME + "2", null).get(); + db.getCollections(options) + .whenComplete((collections, ex) -> { + assertThat(collections.size()).isEqualTo(2); + assertThat(collections).isNotNull(); + }) + .get(); + } finally { + db.collection(COLLECTION_NAME + "1").drop().get(); + db.collection(COLLECTION_NAME + "2").drop().get(); + } + } + + @Test + void grantAccess() throws InterruptedException, ExecutionException { + try { + arangoDB.createUser("user1", "1234", null).get(); + db.grantAccess("user1").get(); + } finally { + arangoDB.deleteUser("user1").get(); + } + } + + @Test + void grantAccessRW() throws InterruptedException, ExecutionException { + try { + arangoDB.createUser("user1", "1234", null).get(); + db.grantAccess("user1", Permissions.RW).get(); + } finally { + arangoDB.deleteUser("user1").get(); + } + } + + @Test + void grantAccessRO() throws InterruptedException, ExecutionException { + try { + arangoDB.createUser("user1", "1234", null).get(); + db.grantAccess("user1", Permissions.RO).get(); + } finally { + arangoDB.deleteUser("user1").get(); + } + } + + @Test + void grantAccessNONE() throws InterruptedException, ExecutionException { + try { + arangoDB.createUser("user1", "1234", null).get(); + db.grantAccess("user1", Permissions.NONE).get(); + } finally { + arangoDB.deleteUser("user1").get(); + } + } + + @Test + void grantAccessUserNotFound() { + Throwable thrown = catchThrowable(() -> db.grantAccess("user1", Permissions.RW).get()); + assertThat(thrown).isInstanceOf(ExecutionException.class); + } + + @Test + void revokeAccess() throws InterruptedException, ExecutionException { + try { + arangoDB.createUser("user1", "1234", null).get(); + db.revokeAccess("user1").get(); + } finally { + arangoDB.deleteUser("user1").get(); + } + } + + @Test + void revokeAccessUserNotFound() { + Throwable thrown = catchThrowable(() -> db.revokeAccess("user1").get()); + assertThat(thrown).isInstanceOf(ExecutionException.class); + } + + @Test + void resetAccess() throws InterruptedException, ExecutionException { + try { + arangoDB.createUser("user1", "1234", null).get(); + db.resetAccess("user1").get(); + } finally { + arangoDB.deleteUser("user1").get(); + } + } + + @Test + void resetAccessUserNotFound() { + Throwable thrown = catchThrowable(() -> db.resetAccess("user1").get()); + assertThat(thrown).isInstanceOf(ExecutionException.class); + } + + @Test + void grantDefaultCollectionAccess() throws InterruptedException, ExecutionException { + try { + arangoDB.createUser("user1", "1234").get(); + db.grantDefaultCollectionAccess("user1", Permissions.RW).get(); + } finally { + arangoDB.deleteUser("user1").get(); + } + } + + @Test + void getPermissions() throws InterruptedException, ExecutionException { + assertThat(db.getPermissions("root").get()).isEqualTo(Permissions.RW); + } + + @Test + void query() throws InterruptedException, ExecutionException { + try { + db.createCollection(COLLECTION_NAME, null).get(); + for (int i = 0; i < 10; i++) { + db.collection(COLLECTION_NAME).insertDocument(new BaseDocument(), null).get(); + } + db.query("for i in db_test return i._id", null, null, String.class) + .whenComplete((cursor, ex) -> { + for (int i = 0; i < 10; i++, cursor.next()) { + assertThat(cursor.hasNext()).isEqualTo(true); + } + }) + .get(); + } finally { + db.collection(COLLECTION_NAME).drop().get(); + } + } + + @Test + void queryForEach() throws InterruptedException, ExecutionException { + try { + db.createCollection(COLLECTION_NAME, null).get(); + for (int i = 0; i < 10; i++) { + db.collection(COLLECTION_NAME).insertDocument(new BaseDocument(), null).get(); + } + db.query("for i in db_test return i._id", null, null, String.class) + .whenComplete((cursor, ex) -> { + final AtomicInteger i = new AtomicInteger(0); + cursor.forEachRemaining(e -> i.incrementAndGet()); + assertThat(i.get()).isEqualTo(10); + }) + .get(); + } finally { + db.collection(COLLECTION_NAME).drop().get(); + } + } + + @Test + void queryStream() throws InterruptedException, ExecutionException { + try { + db.createCollection(COLLECTION_NAME, null).get(); + for (int i = 0; i < 10; i++) { + db.collection(COLLECTION_NAME).insertDocument(new BaseDocument(), null).get(); + } + db.query("for i in db_test return i._id", null, null, String.class) + .whenComplete((cursor, ex) -> { + final AtomicInteger i = new AtomicInteger(0); + cursor.forEachRemaining(e -> i.incrementAndGet()); + assertThat(i.get()).isEqualTo(10); + }) + .get(); + } finally { + db.collection(COLLECTION_NAME).drop().get(); + } + } + + @Test + void queryWithTimeout() throws ExecutionException, InterruptedException { + assumeTrue(isAtLeastVersion(3, 6)); + + try { + db.query("RETURN SLEEP(1)", null, new AqlQueryOptions().maxRuntime(0.1), String.class).get().next(); + fail(); + } catch (ExecutionException e) { + assertThat(e.getCause()).isInstanceOf(ArangoDBException.class); + assertThat(((ArangoDBException) e.getCause()).getResponseCode()).isEqualTo(410); + } + } + + @Test + void queryWithCount() throws InterruptedException, ExecutionException { + try { + db.createCollection(COLLECTION_NAME, null).get(); + for (int i = 0; i < 10; i++) { + db.collection(COLLECTION_NAME).insertDocument(new BaseDocument(), null).get(); + } + + db.query("for i in db_test Limit 6 return i._id", null, new AqlQueryOptions().count(true), String.class) + .whenComplete((cursor, ex) -> { + for (int i = 0; i < 6; i++, cursor.next()) { + assertThat(cursor.hasNext()).isEqualTo(true); + } + assertThat(cursor.getCount()).isEqualTo(6); + }) + .get(); + } finally { + db.collection(COLLECTION_NAME).drop().get(); + } + } + + @Test + void queryWithLimitAndFullCount() throws InterruptedException, ExecutionException { + try { + db.createCollection(COLLECTION_NAME, null).get(); + for (int i = 0; i < 10; i++) { + db.collection(COLLECTION_NAME).insertDocument(new BaseDocument(), null).get(); + } + + db.query("for i in db_test Limit 5 return i._id", null, new AqlQueryOptions().fullCount(true), String.class) + .whenComplete((cursor, ex) -> { + for (int i = 0; i < 5; i++, cursor.next()) { + assertThat(cursor.hasNext()).isEqualTo(true); + } + assertThat(cursor.getStats()).isNotNull(); + assertThat(((Number) cursor.getStats().get("fullCount")).intValue()) + .isGreaterThanOrEqualTo(10); + }) + .get(); + } finally { + db.collection(COLLECTION_NAME).drop().get(); + } + } + + @Test + void queryWithBatchSize() throws InterruptedException, ExecutionException { + try { + db.createCollection(COLLECTION_NAME, null).get(); + for (int i = 0; i < 10; i++) { + db.collection(COLLECTION_NAME).insertDocument(new BaseDocument(), null).get(); + } + final ArangoCursorAsync cursor = db.query("for i in db_test return i._id", null, + new AqlQueryOptions().batchSize(5).count(true), String.class).get(); + for (int i = 0; i < 10; i++, cursor.next()) { + assertThat(cursor.hasNext()).isTrue(); + } + } finally { + db.collection(COLLECTION_NAME).drop().get(); + } + } + + @Test + void queryStreamWithBatchSize() throws InterruptedException, ExecutionException { + try { + db.createCollection(COLLECTION_NAME, null).get(); + for (int i = 0; i < 10; i++) { + db.collection(COLLECTION_NAME).insertDocument(new BaseDocument(), null).get(); + } + final ArangoCursorAsync cursor = db.query("for i in db_test return i._id", null, + new AqlQueryOptions().batchSize(5).count(true), String.class).get(); + final AtomicInteger i = new AtomicInteger(0); + cursor.streamRemaining().forEach(e -> i.incrementAndGet()); + assertThat(i.get()).isEqualTo(10); + } finally { + db.collection(COLLECTION_NAME).drop().get(); + } + } + + /** + * ignored. takes to long + */ + @Test + @Disabled + void queryWithTTL() throws InterruptedException, ExecutionException { + // set TTL to 1 seconds and get the second batch after 2 seconds! + final int ttl = 1; + final int wait = 2; + try { + db.createCollection(COLLECTION_NAME, null).get(); + for (int i = 0; i < 10; i++) { + db.collection(COLLECTION_NAME).insertDocument(new BaseDocument(), null).get(); + } + final ArangoCursorAsync cursor = db.query("for i in db_test return i._id", null, + new AqlQueryOptions().batchSize(5).ttl(ttl), String.class).get(); + for (int i = 0; i < 10; i++, cursor.next()) { + assertThat(cursor.hasNext()).isTrue(); + if (i == 1) { + Thread.sleep(wait * 1000); + } + } + fail(); + } catch (final ArangoDBException ex) { + assertThat(ex.getResponseCode()).isEqualTo(404); + assertThat(ex.getErrorNum()).isEqualTo(1600); + } finally { + db.collection(COLLECTION_NAME).drop().get(); + } + } + + @Test + void changeQueryCache() throws InterruptedException, ExecutionException { + try { + QueryCachePropertiesEntity properties = db.getQueryCacheProperties().get(); + assertThat(properties).isNotNull(); + assertThat(properties.getMode()).isEqualTo(CacheMode.off); + assertThat(properties.getMaxResults()).isPositive(); + + properties.setMode(CacheMode.on); + properties = db.setQueryCacheProperties(properties).get(); + assertThat(properties).isNotNull(); + assertThat(properties.getMode()).isEqualTo(CacheMode.on); + + properties = db.getQueryCacheProperties().get(); + assertThat(properties.getMode()).isEqualTo(CacheMode.on); + } finally { + final QueryCachePropertiesEntity properties = new QueryCachePropertiesEntity(); + properties.setMode(CacheMode.off); + db.setQueryCacheProperties(properties).get(); + } + } + + @Test + void queryWithCache() throws InterruptedException, ExecutionException { + assumeTrue(isSingleServer()); + try { + db.createCollection(COLLECTION_NAME, null).get(); + for (int i = 0; i < 10; i++) { + db.collection(COLLECTION_NAME).insertDocument(new BaseDocument(), null).get(); + } + + final QueryCachePropertiesEntity properties = new QueryCachePropertiesEntity(); + properties.setMode(CacheMode.on); + db.setQueryCacheProperties(properties).get(); + + final ArangoCursorAsync cursor = db + .query("FOR t IN db_test FILTER t.age >= 10 SORT t.age RETURN t._id", null, + new AqlQueryOptions().cache(true), String.class) + .get(); + + assertThat(cursor.isCached()).isFalse(); + + final ArangoCursorAsync cachedCursor = db + .query("FOR t IN db_test FILTER t.age >= 10 SORT t.age RETURN t._id", null, + new AqlQueryOptions().cache(true), String.class) + .get(); + + assertThat(cachedCursor.isCached()).isTrue(); + + } finally { + db.collection(COLLECTION_NAME).drop().get(); + final QueryCachePropertiesEntity properties = new QueryCachePropertiesEntity(); + properties.setMode(CacheMode.off); + db.setQueryCacheProperties(properties).get(); + } + } + + @Test + void queryCursor() throws InterruptedException, ExecutionException { + try { + db.createCollection(COLLECTION_NAME, null).get(); + final int numbDocs = 10; + for (int i = 0; i < numbDocs; i++) { + db.collection(COLLECTION_NAME).insertDocument(new BaseDocument(), null).get(); + } + + final int batchSize = 5; + final ArangoCursorAsync cursor = db.query("for i in db_test return i._id", null, + new AqlQueryOptions().batchSize(batchSize).count(true), String.class).get(); + assertThat(cursor.getCount()).isEqualTo(numbDocs); + + final ArangoCursorAsync cursor2 = db.cursor(cursor.getId(), String.class).get(); + assertThat(cursor2.getCount()).isEqualTo(numbDocs); + assertThat(cursor2.hasNext()).isTrue(); + + for (int i = 0; i < batchSize; i++, cursor.next()) { + assertThat(cursor.hasNext()).isTrue(); + } + } finally { + db.collection(COLLECTION_NAME).drop().get(); + } + } + + @Test + void changeQueryTrackingProperties() throws InterruptedException, ExecutionException { + try { + QueryTrackingPropertiesEntity properties = db.getQueryTrackingProperties().get(); + assertThat(properties).isNotNull(); + assertThat(properties.getEnabled()).isTrue(); + assertThat(properties.getTrackSlowQueries()).isTrue(); + assertThat(properties.getMaxQueryStringLength()).isPositive(); + assertThat(properties.getMaxSlowQueries()).isPositive(); + assertThat(properties.getSlowQueryThreshold()).isPositive(); + properties.setEnabled(false); + properties = db.setQueryTrackingProperties(properties).get(); + assertThat(properties).isNotNull(); + assertThat(properties.getEnabled()).isFalse(); + properties = db.getQueryTrackingProperties().get(); + assertThat(properties.getEnabled()).isFalse(); + } finally { + final QueryTrackingPropertiesEntity properties = new QueryTrackingPropertiesEntity(); + properties.setEnabled(true); + db.setQueryTrackingProperties(properties).get(); + } + } + + @Test + void queryWithBindVars() throws InterruptedException, ExecutionException { + try { + db.createCollection(COLLECTION_NAME, null).get(); + for (int i = 0; i < 10; i++) { + final BaseDocument baseDocument = new BaseDocument(UUID.randomUUID().toString()); + baseDocument.addAttribute("age", 20 + i); + db.collection(COLLECTION_NAME).insertDocument(baseDocument, null).get(); + } + final Map bindVars = new HashMap<>(); + bindVars.put("@coll", COLLECTION_NAME); + bindVars.put("age", 25); + db.query("FOR t IN @@coll FILTER t.age >= @age SORT t.age RETURN t._id", bindVars, null, String.class) + .whenComplete((cursor, ex) -> { + for (int i = 0; i < 5; i++, cursor.next()) { + assertThat(cursor.hasNext()).isEqualTo(true); + } + }) + .get(); + } finally { + db.collection(COLLECTION_NAME).drop().get(); + } + } + + @Test + void queryWithWarning() throws InterruptedException, ExecutionException { + arangoDB.db().query("return 1/0", null, null, String.class) + .whenComplete((cursor, ex) -> { + assertThat(cursor.getWarnings()).isNotNull(); + assertThat(cursor.getWarnings()).isNotEmpty(); + }) + .get(); + } + + @Test + void queryClose() throws IOException, InterruptedException, ExecutionException { + final ArangoCursorAsync cursor = arangoDB.db() + .query("for i in 1..2 return i", null, new AqlQueryOptions().batchSize(1), String.class).get(); + cursor.close(); + int count = 0; + try { + for (; cursor.hasNext(); cursor.next(), count++) { + } + fail(); + } catch (final ArangoDBException e) { + assertThat(count).isEqualTo(1); + } + + } + + @Test + void explainQuery() throws InterruptedException, ExecutionException { + arangoDB.db().explainQuery("for i in 1..1 return i", null, null) + .whenComplete((explain, ex) -> { + assertThat(explain).isNotNull(); + assertThat(explain.getPlan()).isNotNull(); + assertThat(explain.getPlans()).isNull(); + final ExecutionPlan plan = explain.getPlan(); + assertThat(plan.getCollections().size()).isEqualTo(0); + assertThat(plan.getEstimatedCost()).isGreaterThan(0); + assertThat(plan.getEstimatedNrItems()).isGreaterThan(0); + assertThat(plan.getVariables().size()).isEqualTo(2); + assertThat(plan.getNodes().size()).isGreaterThan(0); + }) + .get(); + } + + @Test + void parseQuery() throws InterruptedException, ExecutionException { + assumeTrue(isAtLeastVersion(3, 4)); + arangoDB.db().parseQuery("for i in _apps return i") + .whenComplete((parse, ex) -> { + assertThat(parse).isNotNull(); + assertThat(parse.getBindVars()).isEmpty(); + assertThat(parse.getCollections().size()).isEqualTo(1); + assertThat(parse.getCollections().iterator().next()).isEqualTo("_apps"); + assertThat(parse.getAst().size()).isEqualTo(1); + final AstNode root = parse.getAst().iterator().next(); + assertThat(root.getType()).isEqualTo("root"); + assertThat(root.getName()).isNull(); + assertThat(root.getSubNodes()).isNotNull(); + assertThat(root.getSubNodes().size()).isEqualTo(2); + final Iterator iterator = root.getSubNodes().iterator(); + final AstNode for_ = iterator.next(); + assertThat(for_.getType()).isEqualTo("for"); + assertThat(for_.getSubNodes()).isNotNull(); + assertThat(for_.getSubNodes().size()).isEqualTo(3); + final Iterator iterator2 = for_.getSubNodes().iterator(); + final AstNode first = iterator2.next(); + assertThat(first.getType()).isEqualTo("variable"); + assertThat(first.getName()).isEqualTo("i"); + final AstNode second = iterator2.next(); + assertThat(second.getType()).isEqualTo("collection"); + assertThat(second.getName()).isEqualTo("_apps"); + final AstNode return_ = iterator.next(); + assertThat(return_.getType()).isEqualTo("return"); + assertThat(return_.getSubNodes()).isNotNull(); + assertThat(return_.getSubNodes().size()).isEqualTo(1); + assertThat(return_.getSubNodes().iterator().next().getType()).isEqualTo("reference"); + assertThat(return_.getSubNodes().iterator().next().getName()).isEqualTo("i"); + }) + .get(); + } + + @Test + @Disabled + void getAndClearSlowQueries() throws InterruptedException, ExecutionException { + final QueryTrackingPropertiesEntity properties = db.getQueryTrackingProperties().get(); + final Long slowQueryThreshold = properties.getSlowQueryThreshold(); + try { + properties.setSlowQueryThreshold(1L); + db.setQueryTrackingProperties(properties); + + db.query("return sleep(1.1)", null, null, Void.class); + final Collection slowQueries = db.getSlowQueries().get(); + assertThat(slowQueries).isNotNull(); + assertThat(slowQueries).hasSize(1); + final QueryEntity queryEntity = slowQueries.iterator().next(); + assertThat(queryEntity.getQuery()).isEqualTo("return sleep(1.1)"); + + db.clearSlowQueries().get(); + assertThat(db.getSlowQueries().get().size()).isZero(); + } finally { + properties.setSlowQueryThreshold(slowQueryThreshold); + db.setQueryTrackingProperties(properties); + } + } + + @Test + void createGetDeleteAqlFunction() throws InterruptedException, ExecutionException { + final Collection aqlFunctionsInitial = db.getAqlFunctions(null).get(); + assertThat(aqlFunctionsInitial).isEmpty(); + try { + db.createAqlFunction("myfunctions::temperature::celsiustofahrenheit", + "function (celsius) { return celsius * 1.8 + 32; }", null).get(); + + final Collection aqlFunctions = db.getAqlFunctions(null).get(); + assertThat(aqlFunctions).hasSizeGreaterThan(aqlFunctionsInitial.size()); + } finally { + final Integer deleteCount = db.deleteAqlFunction("myfunctions::temperature::celsiustofahrenheit", null) + .get(); + // compatibility with ArangoDB < 3.4 + if (isAtLeastVersion(3, 4)) { + assertThat(deleteCount).isEqualTo(1); + } else { + assertThat(deleteCount).isNull(); + } + + final Collection aqlFunctions = db.getAqlFunctions(null).get(); + assertThat(aqlFunctions).hasSameSizeAs(aqlFunctionsInitial); + } + } + + @Test + void createGetDeleteAqlFunctionWithNamespace() throws InterruptedException, ExecutionException { + final Collection aqlFunctionsInitial = db.getAqlFunctions(null).get(); + assertThat(aqlFunctionsInitial).isEmpty(); + try { + db.createAqlFunction("myfunctions::temperature::celsiustofahrenheit1", + "function (celsius) { return celsius * 1.8 + 32; }", null).get(); + db.createAqlFunction("myfunctions::temperature::celsiustofahrenheit2", + "function (celsius) { return celsius * 1.8 + 32; }", null).get(); + + } finally { + db.deleteAqlFunction("myfunctions::temperature", new AqlFunctionDeleteOptions().group(true)).get(); + + final Collection aqlFunctions = db.getAqlFunctions(null).get(); + assertThat(aqlFunctions).hasSameSizeAs(aqlFunctionsInitial); + } + } + + @Test + void createGraph() throws InterruptedException, ExecutionException { + try { + db.createGraph(GRAPH_NAME, null, null) + .whenComplete((result, ex) -> { + assertThat(result).isNotNull(); + assertThat(result.getName()).isEqualTo(GRAPH_NAME); + }) + .get(); + } finally { + db.graph(GRAPH_NAME).drop().get(); + } + } + + @Test + void getGraphs() throws InterruptedException, ExecutionException { + try { + db.createGraph(GRAPH_NAME, null, null).get(); + db.getGraphs() + .whenComplete((graphs, ex) -> { + assertThat(graphs).isNotNull(); + assertThat(graphs.size()).isEqualTo(1); + }) + .get(); + } finally { + db.graph(GRAPH_NAME).drop().get(); + } + } + + @Test + void transactionString() throws InterruptedException, ExecutionException { + final TransactionOptions options = new TransactionOptions().params("test"); + db.transaction("function (params) {return params;}", RawJson.class, options) + .whenComplete((result, ex) -> assertThat(result.getValue()).isEqualTo("\"test\"")) + .get(); + } + + @Test + void transactionNumber() throws InterruptedException, ExecutionException { + final TransactionOptions options = new TransactionOptions().params(5); + db.transaction("function (params) {return params;}", Integer.class, options) + .whenComplete((result, ex) -> assertThat(result).isEqualTo(5)) + .get(); + } + + @Test + void transactionJsonNode() throws InterruptedException, ExecutionException { + final TransactionOptions options = new TransactionOptions().params(JsonNodeFactory.instance.textNode("test")); + db.transaction("function (params) {return params;}", JsonNode.class, options) + .whenComplete((result, ex) -> { + assertThat(result.isTextual()).isEqualTo(true); + assertThat(result.asText()).isEqualTo("test"); + }) + .get(); + } + + @Test + void transactionEmpty() throws InterruptedException, ExecutionException { + db.transaction("function () {}", Void.class, null).get(); + } + + @Test + void transactionAllowImplicit() throws InterruptedException, ExecutionException { + try { + db.createCollection("someCollection", null).get(); + db.createCollection("someOtherCollection", null).get(); + final String action = "function (params) {" + "var db = require('internal').db;" + + "return {'a':db.someCollection.all().toArray()[0], 'b':db.someOtherCollection.all().toArray()" + + "[0]};" + + "}"; + final TransactionOptions options = new TransactionOptions().readCollections("someCollection"); + db.transaction(action, Void.class, options).get(); + try { + options.allowImplicit(false); + db.transaction(action, Void.class, options).get(); + fail(); + } catch (final ExecutionException e) { + assertThat(e.getCause()).isInstanceOf(ArangoDBException.class); + } + } finally { + db.collection("someCollection").drop().get(); + db.collection("someOtherCollection").drop().get(); + } + } + + @Test + void transactionPojoReturn() throws ExecutionException, InterruptedException { + final String action = "function() { return {'value':'hello world'}; }"; + db.transaction(action, TransactionTestEntity.class, new TransactionOptions()) + .whenComplete((res, ex) -> { + assertThat(res).isNotNull(); + assertThat(res.value).isEqualTo("hello world"); + }) + .get(); + } + + @Test + void getInfo() throws InterruptedException, ExecutionException { + final CompletableFuture f = db.getInfo(); + assertThat(f).isNotNull(); + f.whenComplete((info, ex) -> { + assertThat(info).isNotNull(); + assertThat(info.getId()).isNotNull(); + assertThat(info.getName()).isEqualTo(TEST_DB.get()); + assertThat(info.getPath()).isNotNull(); + assertThat(info.getIsSystem()).isFalse(); + + try { + if (isAtLeastVersion(3, 6) && isCluster()) { + assertThat(info.getSharding()).isNotNull(); + assertThat(info.getWriteConcern()).isNotNull(); + assertThat(info.getReplicationFactor()).isNotNull(); + } + } catch (InterruptedException | ExecutionException e) { + e.printStackTrace(); + fail(); + } + + }); + f.get(); + } + + @Test + void getDocument() throws InterruptedException, ExecutionException { + String collectionName = COLLECTION_NAME + "getDocument"; + db.createCollection(collectionName).get(); + final BaseDocument value = new BaseDocument(UUID.randomUUID().toString()); + value.setKey("123"); + db.collection(collectionName).insertDocument(value).get(); + db.getDocument(collectionName + "/123", BaseDocument.class) + .whenComplete((document, ex) -> { + assertThat(document).isNotNull(); + assertThat(document.getKey()).isEqualTo("123"); + }) + .get(); + db.collection(collectionName).drop().get(); + } + + @Test + void shouldIncludeExceptionMessage() throws InterruptedException, ExecutionException { + final String exceptionMessage = "My error context"; + final String action = "function (params) {" + "throw '" + exceptionMessage + "';" + "}"; + try { + db.transaction(action, Void.class, null).get(); + fail(); + } catch (final ExecutionException e) { + assertThat(e.getCause()).isInstanceOf(ArangoDBException.class); + ArangoDBException cause = ((ArangoDBException) e.getCause()); + assertThat(cause.getErrorNum()).isEqualTo(1650); + if (isAtLeastVersion(3, 4)) { + assertThat(cause.getErrorMessage()).isEqualTo(exceptionMessage); + } + } + } + + @Test + void getDocumentWrongId() { + Throwable thrown = catchThrowable(() -> db.getDocument("123", BaseDocument.class).get()); + assertThat(thrown).isInstanceOf(ArangoDBException.class); + } + + @Test + void reloadRouting() throws InterruptedException, ExecutionException { + db.reloadRouting().get(); + } + + public static class TransactionTestEntity { + private String value; + + public TransactionTestEntity() { + super(); + } + + public String getValue() { + return value; + } + } +} diff --git a/shaded-integration-tests/src/test/jackson/java/com/arangodb/async/ArangoEdgeCollectionTest.java b/shaded-integration-tests/src/test/jackson/java/com/arangodb/async/ArangoEdgeCollectionTest.java new file mode 100644 index 000000000..e1b106875 --- /dev/null +++ b/shaded-integration-tests/src/test/jackson/java/com/arangodb/async/ArangoEdgeCollectionTest.java @@ -0,0 +1,367 @@ +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed 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. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.async; + +import com.arangodb.ArangoDBException; +import com.arangodb.entity.*; +import com.arangodb.model.*; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.concurrent.ExecutionException; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.fail; + +/** + * @author Mark Vollmary + */ +class ArangoEdgeCollectionTest extends BaseTest { + + private static final String GRAPH_NAME = "db_collection_test"; + private static final String EDGE_COLLECTION_NAME = "db_edge_collection_test"; + private static final String VERTEX_COLLECTION_NAME = "db_vertex_collection_test"; + + @BeforeAll + static void setup() throws InterruptedException, ExecutionException { + if (!db.collection(VERTEX_COLLECTION_NAME).exists().get()) { + db.createCollection(VERTEX_COLLECTION_NAME, null).get(); + } + if (!db.collection(EDGE_COLLECTION_NAME).exists().get()) { + db.createCollection(EDGE_COLLECTION_NAME, new CollectionCreateOptions().type(CollectionType.EDGES)).get(); + } + final Collection edgeDefinitions = new ArrayList<>(); + edgeDefinitions.add(new EdgeDefinition().collection(EDGE_COLLECTION_NAME).from(VERTEX_COLLECTION_NAME) + .to(VERTEX_COLLECTION_NAME)); + db.createGraph(GRAPH_NAME, edgeDefinitions, null).get(); + } + + @AfterEach + void teardown() throws InterruptedException, ExecutionException { + for (final String collection : new String[]{VERTEX_COLLECTION_NAME, EDGE_COLLECTION_NAME}) { + db.collection(collection).truncate().get(); + } + } + + private BaseEdgeDocument createEdgeValue() throws InterruptedException, ExecutionException { + final VertexEntity v1 = db.graph(GRAPH_NAME).vertexCollection(VERTEX_COLLECTION_NAME) + .insertVertex(new BaseDocument(), null).get(); + final VertexEntity v2 = db.graph(GRAPH_NAME).vertexCollection(VERTEX_COLLECTION_NAME) + .insertVertex(new BaseDocument(), null).get(); + + final BaseEdgeDocument value = new BaseEdgeDocument(); + value.setFrom(v1.getId()); + value.setTo(v2.getId()); + return value; + } + + @Test + void insertEdge() throws InterruptedException, ExecutionException { + final BaseEdgeDocument value = createEdgeValue(); + final EdgeEntity edge = db.graph(GRAPH_NAME).edgeCollection(EDGE_COLLECTION_NAME).insertEdge(value, null).get(); + assertThat(edge).isNotNull(); + final BaseEdgeDocument document = db.collection(EDGE_COLLECTION_NAME) + .getDocument(edge.getKey(), BaseEdgeDocument.class, null).get(); + assertThat(document).isNotNull(); + assertThat(document.getKey()).isEqualTo(edge.getKey()); + } + + @Test + void getEdge() throws InterruptedException, ExecutionException { + final BaseEdgeDocument value = createEdgeValue(); + final EdgeEntity edge = db.graph(GRAPH_NAME).edgeCollection(EDGE_COLLECTION_NAME).insertEdge(value, null).get(); + final BaseDocument document = db.graph(GRAPH_NAME).edgeCollection(EDGE_COLLECTION_NAME) + .getEdge(edge.getKey(), BaseDocument.class, null).get(); + assertThat(document).isNotNull(); + assertThat(document.getKey()).isEqualTo(edge.getKey()); + } + + @Test + void getEdgeIfMatch() throws InterruptedException, ExecutionException { + final BaseEdgeDocument value = createEdgeValue(); + final EdgeEntity edge = db.graph(GRAPH_NAME).edgeCollection(EDGE_COLLECTION_NAME).insertEdge(value, null).get(); + final GraphDocumentReadOptions options = new GraphDocumentReadOptions().ifMatch(edge.getRev()); + final BaseDocument document = db.graph(GRAPH_NAME).edgeCollection(EDGE_COLLECTION_NAME) + .getEdge(edge.getKey(), BaseDocument.class, options).get(); + assertThat(document).isNotNull(); + assertThat(document.getKey()).isEqualTo(edge.getKey()); + } + + @Test + void getEdgeIfMatchFail() throws InterruptedException, ExecutionException { + final BaseEdgeDocument value = createEdgeValue(); + final EdgeEntity edge = db.graph(GRAPH_NAME).edgeCollection(EDGE_COLLECTION_NAME).insertEdge(value, null).get(); + final GraphDocumentReadOptions options = new GraphDocumentReadOptions().ifMatch("no"); + BaseEdgeDocument doc = db.graph(GRAPH_NAME).edgeCollection(EDGE_COLLECTION_NAME) + .getEdge(edge.getKey(), BaseEdgeDocument.class, options).get(); + assertThat(doc).isNull(); + } + + @Test + void getEdgeIfNoneMatch() throws InterruptedException, ExecutionException { + final BaseEdgeDocument value = createEdgeValue(); + final EdgeEntity edge = db.graph(GRAPH_NAME).edgeCollection(EDGE_COLLECTION_NAME).insertEdge(value, null).get(); + final GraphDocumentReadOptions options = new GraphDocumentReadOptions().ifNoneMatch("no"); + final BaseDocument document = db.graph(GRAPH_NAME).edgeCollection(EDGE_COLLECTION_NAME) + .getEdge(edge.getKey(), BaseDocument.class, options).get(); + assertThat(document).isNotNull(); + assertThat(document.getKey()).isEqualTo(edge.getKey()); + } + + @Test + void getEdgeIfNoneMatchFail() throws InterruptedException, ExecutionException { + final BaseEdgeDocument value = createEdgeValue(); + final EdgeEntity edge = db.graph(GRAPH_NAME).edgeCollection(EDGE_COLLECTION_NAME).insertEdge(value, null).get(); + final GraphDocumentReadOptions options = new GraphDocumentReadOptions().ifNoneMatch(edge.getRev()); + BaseEdgeDocument doc = db.graph(GRAPH_NAME).edgeCollection(EDGE_COLLECTION_NAME) + .getEdge(edge.getKey(), BaseEdgeDocument.class, options).get(); + assertThat(doc).isNull(); + } + + @Test + void replaceEdge() throws InterruptedException, ExecutionException { + final BaseEdgeDocument doc = createEdgeValue(); + doc.addAttribute("a", "test"); + final EdgeEntity createResult = db.graph(GRAPH_NAME).edgeCollection(EDGE_COLLECTION_NAME).insertEdge(doc, null) + .get(); + doc.removeAttribute("a"); + doc.addAttribute("b", "test"); + final EdgeUpdateEntity replaceResult = db.graph(GRAPH_NAME).edgeCollection(EDGE_COLLECTION_NAME) + .replaceEdge(createResult.getKey(), doc, null).get(); + assertThat(replaceResult).isNotNull(); + assertThat(replaceResult.getId()).isEqualTo(createResult.getId()); + assertThat(replaceResult.getRev()).isNotEqualTo(replaceResult.getOldRev()); + assertThat(replaceResult.getOldRev()).isEqualTo(createResult.getRev()); + + final BaseEdgeDocument readResult = db.graph(GRAPH_NAME).edgeCollection(EDGE_COLLECTION_NAME) + .getEdge(createResult.getKey(), BaseEdgeDocument.class, null).get(); + assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); + assertThat(readResult.getRevision()).isEqualTo(replaceResult.getRev()); + assertThat(readResult.getProperties().keySet()).doesNotContain("a"); + assertThat(readResult.getAttribute("b")).isNotNull(); + assertThat(String.valueOf(readResult.getAttribute("b"))).isEqualTo("test"); + } + + @Test + void replaceEdgeIfMatch() throws InterruptedException, ExecutionException { + final BaseEdgeDocument doc = createEdgeValue(); + doc.addAttribute("a", "test"); + final EdgeEntity createResult = db.graph(GRAPH_NAME).edgeCollection(EDGE_COLLECTION_NAME).insertEdge(doc, null) + .get(); + doc.removeAttribute("a"); + doc.addAttribute("b", "test"); + final EdgeReplaceOptions options = new EdgeReplaceOptions().ifMatch(createResult.getRev()); + final EdgeUpdateEntity replaceResult = db.graph(GRAPH_NAME).edgeCollection(EDGE_COLLECTION_NAME) + .replaceEdge(createResult.getKey(), doc, options).get(); + assertThat(replaceResult).isNotNull(); + assertThat(replaceResult.getId()).isEqualTo(createResult.getId()); + assertThat(replaceResult.getRev()).isNotEqualTo(replaceResult.getOldRev()); + assertThat(replaceResult.getOldRev()).isEqualTo(createResult.getRev()); + + final BaseEdgeDocument readResult = db.graph(GRAPH_NAME).edgeCollection(EDGE_COLLECTION_NAME) + .getEdge(createResult.getKey(), BaseEdgeDocument.class, null).get(); + assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); + assertThat(readResult.getRevision()).isEqualTo(replaceResult.getRev()); + assertThat(readResult.getProperties().keySet()).doesNotContain("a"); + assertThat(readResult.getAttribute("b")).isNotNull(); + assertThat(String.valueOf(readResult.getAttribute("b"))).isEqualTo("test"); + } + + @Test + void replaceEdgeIfMatchFail() throws InterruptedException, ExecutionException { + final BaseEdgeDocument doc = createEdgeValue(); + doc.addAttribute("a", "test"); + final EdgeEntity createResult = db.graph(GRAPH_NAME).edgeCollection(EDGE_COLLECTION_NAME).insertEdge(doc, null) + .get(); + doc.removeAttribute("a"); + doc.addAttribute("b", "test"); + try { + final EdgeReplaceOptions options = new EdgeReplaceOptions().ifMatch("no"); + db.graph(GRAPH_NAME).edgeCollection(EDGE_COLLECTION_NAME).replaceEdge(createResult.getKey(), doc, options) + .get(); + fail(); + } catch (final ExecutionException e) { + assertThat(e.getCause()).isInstanceOf(ArangoDBException.class); + } + } + + @Test + void updateEdge() throws InterruptedException, ExecutionException { + final BaseEdgeDocument doc = createEdgeValue(); + doc.addAttribute("a", "test"); + doc.addAttribute("c", "test"); + final EdgeEntity createResult = db.graph(GRAPH_NAME).edgeCollection(EDGE_COLLECTION_NAME).insertEdge(doc, null) + .get(); + doc.updateAttribute("a", "test1"); + doc.addAttribute("b", "test"); + doc.updateAttribute("c", null); + final EdgeUpdateEntity updateResult = db.graph(GRAPH_NAME).edgeCollection(EDGE_COLLECTION_NAME) + .updateEdge(createResult.getKey(), doc, null).get(); + assertThat(updateResult).isNotNull(); + assertThat(updateResult.getId()).isEqualTo(createResult.getId()); + assertThat(updateResult.getRev()).isNotEqualTo(updateResult.getOldRev()); + assertThat(updateResult.getOldRev()).isEqualTo(createResult.getRev()); + + final BaseEdgeDocument readResult = db.graph(GRAPH_NAME).edgeCollection(EDGE_COLLECTION_NAME) + .getEdge(createResult.getKey(), BaseEdgeDocument.class, null).get(); + assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); + assertThat(readResult.getAttribute("a")).isNotNull(); + assertThat(String.valueOf(readResult.getAttribute("a"))).isEqualTo("test1"); + assertThat(readResult.getAttribute("b")).isNotNull(); + assertThat(String.valueOf(readResult.getAttribute("b"))).isEqualTo("test"); + assertThat(readResult.getRevision()).isEqualTo(updateResult.getRev()); + assertThat(readResult.getProperties()).containsKey("c"); + } + + @Test + void updateEdgeIfMatch() throws InterruptedException, ExecutionException { + final BaseEdgeDocument doc = createEdgeValue(); + doc.addAttribute("a", "test"); + doc.addAttribute("c", "test"); + final EdgeEntity createResult = db.graph(GRAPH_NAME).edgeCollection(EDGE_COLLECTION_NAME).insertEdge(doc, null) + .get(); + doc.updateAttribute("a", "test1"); + doc.addAttribute("b", "test"); + doc.updateAttribute("c", null); + final EdgeUpdateOptions options = new EdgeUpdateOptions().ifMatch(createResult.getRev()); + final EdgeUpdateEntity updateResult = db.graph(GRAPH_NAME).edgeCollection(EDGE_COLLECTION_NAME) + .updateEdge(createResult.getKey(), doc, options).get(); + assertThat(updateResult).isNotNull(); + assertThat(updateResult.getId()).isEqualTo(createResult.getId()); + assertThat(updateResult.getRev()).isNotEqualTo(updateResult.getOldRev()); + assertThat(updateResult.getOldRev()).isEqualTo(createResult.getRev()); + + final BaseEdgeDocument readResult = db.graph(GRAPH_NAME).edgeCollection(EDGE_COLLECTION_NAME) + .getEdge(createResult.getKey(), BaseEdgeDocument.class, null).get(); + assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); + assertThat(readResult.getAttribute("a")).isNotNull(); + assertThat(String.valueOf(readResult.getAttribute("a"))).isEqualTo("test1"); + assertThat(readResult.getAttribute("b")).isNotNull(); + assertThat(String.valueOf(readResult.getAttribute("b"))).isEqualTo("test"); + assertThat(readResult.getRevision()).isEqualTo(updateResult.getRev()); + assertThat(readResult.getProperties()).containsKey("c"); + } + + @Test + void updateEdgeIfMatchFail() throws InterruptedException, ExecutionException { + final BaseEdgeDocument doc = createEdgeValue(); + doc.addAttribute("a", "test"); + doc.addAttribute("c", "test"); + final EdgeEntity createResult = db.graph(GRAPH_NAME).edgeCollection(EDGE_COLLECTION_NAME).insertEdge(doc, null) + .get(); + doc.updateAttribute("a", "test1"); + doc.addAttribute("b", "test"); + doc.updateAttribute("c", null); + try { + final EdgeUpdateOptions options = new EdgeUpdateOptions().ifMatch("no"); + db.graph(GRAPH_NAME).edgeCollection(EDGE_COLLECTION_NAME).updateEdge(createResult.getKey(), doc, options) + .get(); + fail(); + } catch (final ExecutionException e) { + assertThat(e.getCause()).isInstanceOf(ArangoDBException.class); + } + } + + @Test + void updateEdgeKeepNullTrue() throws InterruptedException, ExecutionException { + final BaseEdgeDocument doc = createEdgeValue(); + doc.addAttribute("a", "test"); + final EdgeEntity createResult = db.graph(GRAPH_NAME).edgeCollection(EDGE_COLLECTION_NAME).insertEdge(doc, null) + .get(); + doc.updateAttribute("a", null); + final EdgeUpdateOptions options = new EdgeUpdateOptions().keepNull(true); + final EdgeUpdateEntity updateResult = db.graph(GRAPH_NAME).edgeCollection(EDGE_COLLECTION_NAME) + .updateEdge(createResult.getKey(), doc, options).get(); + assertThat(updateResult).isNotNull(); + assertThat(updateResult.getId()).isEqualTo(createResult.getId()); + assertThat(updateResult.getRev()).isNotEqualTo(updateResult.getOldRev()); + assertThat(updateResult.getOldRev()).isEqualTo(createResult.getRev()); + + final BaseEdgeDocument readResult = db.graph(GRAPH_NAME).edgeCollection(EDGE_COLLECTION_NAME) + .getEdge(createResult.getKey(), BaseEdgeDocument.class, null).get(); + assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); + assertThat(readResult.getProperties().keySet()).hasSize(6); + assertThat(readResult.getProperties()).containsKey("a"); + } + + @Test + void updateEdgeKeepNullFalse() throws InterruptedException, ExecutionException { + final BaseEdgeDocument doc = createEdgeValue(); + doc.addAttribute("a", "test"); + final EdgeEntity createResult = db.graph(GRAPH_NAME).edgeCollection(EDGE_COLLECTION_NAME).insertEdge(doc, null) + .get(); + doc.updateAttribute("a", null); + final EdgeUpdateOptions options = new EdgeUpdateOptions().keepNull(false); + final EdgeUpdateEntity updateResult = db.graph(GRAPH_NAME).edgeCollection(EDGE_COLLECTION_NAME) + .updateEdge(createResult.getKey(), doc, options).get(); + assertThat(updateResult).isNotNull(); + assertThat(updateResult.getId()).isEqualTo(createResult.getId()); + assertThat(updateResult.getRev()).isNotEqualTo(updateResult.getOldRev()); + assertThat(updateResult.getOldRev()).isEqualTo(createResult.getRev()); + + final BaseEdgeDocument readResult = db.graph(GRAPH_NAME).edgeCollection(EDGE_COLLECTION_NAME) + .getEdge(createResult.getKey(), BaseEdgeDocument.class, null).get(); + assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); + assertThat(readResult.getId()).isEqualTo(createResult.getId()); + assertThat(readResult.getRevision()).isNotNull(); + assertThat(readResult.getProperties().keySet()).doesNotContain("a"); + } + + @Test + void deleteEdge() throws InterruptedException, ExecutionException { + final BaseEdgeDocument doc = createEdgeValue(); + final EdgeEntity createResult = db.graph(GRAPH_NAME).edgeCollection(EDGE_COLLECTION_NAME).insertEdge(doc, null) + .get(); + db.graph(GRAPH_NAME).edgeCollection(EDGE_COLLECTION_NAME).deleteEdge(createResult.getKey(), null).get(); + BaseEdgeDocument res = db.graph(GRAPH_NAME).edgeCollection(EDGE_COLLECTION_NAME) + .getEdge(createResult.getKey(), BaseEdgeDocument.class, new GraphDocumentReadOptions()).get(); + assertThat(res).isNull(); + } + + @Test + void deleteEdgeIfMatch() throws InterruptedException, ExecutionException { + final BaseEdgeDocument doc = createEdgeValue(); + final EdgeEntity createResult = db.graph(GRAPH_NAME).edgeCollection(EDGE_COLLECTION_NAME).insertEdge(doc, null) + .get(); + final EdgeDeleteOptions options = new EdgeDeleteOptions().ifMatch(createResult.getRev()); + db.graph(GRAPH_NAME).edgeCollection(EDGE_COLLECTION_NAME).deleteEdge(createResult.getKey(), options).get(); + BaseEdgeDocument res = db.graph(GRAPH_NAME).edgeCollection(EDGE_COLLECTION_NAME) + .getEdge(createResult.getKey(), BaseEdgeDocument.class, new GraphDocumentReadOptions()).get(); + assertThat(res).isNull(); + } + + @Test + void deleteEdgeIfMatchFail() throws InterruptedException, ExecutionException { + final BaseEdgeDocument doc = createEdgeValue(); + final EdgeEntity createResult = db.graph(GRAPH_NAME).edgeCollection(EDGE_COLLECTION_NAME).insertEdge(doc, null) + .get(); + final EdgeDeleteOptions options = new EdgeDeleteOptions().ifMatch("no"); + try { + db.graph(GRAPH_NAME).edgeCollection(EDGE_COLLECTION_NAME).deleteEdge(createResult.getKey(), options).get(); + fail(); + } catch (final ExecutionException e) { + assertThat(e.getCause()).isInstanceOf(ArangoDBException.class); + } + } +} diff --git a/shaded-integration-tests/src/test/jackson/java/com/arangodb/async/ArangoGraphTest.java b/shaded-integration-tests/src/test/jackson/java/com/arangodb/async/ArangoGraphTest.java new file mode 100644 index 000000000..beed0bf10 --- /dev/null +++ b/shaded-integration-tests/src/test/jackson/java/com/arangodb/async/ArangoGraphTest.java @@ -0,0 +1,387 @@ +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed 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. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.async; + +import com.arangodb.entity.*; +import com.arangodb.model.GraphCreateOptions; +import com.arangodb.model.VertexCollectionCreateOptions; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Iterator; +import java.util.concurrent.ExecutionException; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assumptions.assumeTrue; + +/** + * @author Mark Vollmary + */ +class ArangoGraphTest extends BaseTest { + + private static final String GRAPH_NAME = "db_collection_test"; + private static final String EDGE_COL_1 = "db_edge1_collection_test"; + private static final String EDGE_COL_2 = "db_edge2_collection_test"; + private static final String EDGE_COL_3 = "db_edge3_collection_test"; + private static final String VERTEX_COL_1 = "db_vertex1_collection_test"; + private static final String VERTEX_COL_2 = "db_vertex2_collection_test"; + private static final String VERTEX_COL_3 = "db_vertex3_collection_test"; + private static final String VERTEX_COL_4 = "db_vertex4_collection_test"; + private static final Integer REPLICATION_FACTOR = 2; + private static final Integer NUMBER_OF_SHARDS = 2; + + @BeforeAll + static void setup() throws InterruptedException, ExecutionException { + if (db.graph(GRAPH_NAME).exists().get()) { + db.graph(GRAPH_NAME).drop().get(); + } + final Collection edgeDefinitions = new ArrayList<>(); + edgeDefinitions.add(new EdgeDefinition().collection(EDGE_COL_1).from(VERTEX_COL_1).to(VERTEX_COL_2)); + edgeDefinitions + .add(new EdgeDefinition().collection(EDGE_COL_2).from(VERTEX_COL_2).to(VERTEX_COL_1, VERTEX_COL_3)); + final GraphCreateOptions options = new GraphCreateOptions(); + if (arangoDB.getRole().get() != ServerRole.SINGLE) { + options.replicationFactor(REPLICATION_FACTOR).numberOfShards(NUMBER_OF_SHARDS); + } + db.createGraph(GRAPH_NAME, edgeDefinitions, options).get(); + } + + @AfterEach + void teardown() throws InterruptedException, ExecutionException { + for (final String collection : new String[]{EDGE_COL_1, EDGE_COL_2, VERTEX_COL_1, VERTEX_COL_2, VERTEX_COL_3, + VERTEX_COL_4}) { + final ArangoCollectionAsync c = db.collection(collection); + if (c.exists().get()) { + c.truncate().get(); + } + } + } + + @Test + void create() throws InterruptedException, ExecutionException { + try { + final GraphEntity result = db.graph(GRAPH_NAME + "_1").create(null).get(); + assertThat(result).isNotNull(); + assertThat(result.getName()).isEqualTo(GRAPH_NAME + "_1"); + } finally { + db.graph(GRAPH_NAME + "_1").drop().get(); + } + } + + @Test + void createWithReplicationAndWriteConcern() throws ExecutionException, InterruptedException { + assumeTrue(isAtLeastVersion(3, 5)); + assumeTrue(isCluster()); + final Collection edgeDefinitions = new ArrayList<>(); + final GraphEntity graph = db.createGraph(GRAPH_NAME + "_1", edgeDefinitions, + new GraphCreateOptions().isSmart(true).replicationFactor(2).writeConcern(2)).get(); + assertThat(graph).isNotNull(); + assertThat(graph.getName()).isEqualTo(GRAPH_NAME + "_1"); + assertThat(graph.getWriteConcern()).isEqualTo(2); + assertThat(graph.getReplicationFactor().getValue()).isEqualTo(2); + db.graph(GRAPH_NAME + "_1").drop(); + } + + @Test + void getGraphs() throws InterruptedException, ExecutionException { + final Collection graphs = db.getGraphs().get(); + assertThat(graphs).isNotNull(); + assertThat(graphs).isNotEmpty(); + } + + @Test + void getInfo() throws InterruptedException, ExecutionException { + final GraphEntity info = db.graph(GRAPH_NAME).getInfo().get(); + assertThat(info).isNotNull(); + assertThat(info.getName()).isEqualTo(GRAPH_NAME); + assertThat(info.getEdgeDefinitions()).hasSize(2); + final Iterator iterator = info.getEdgeDefinitions().iterator(); + final EdgeDefinition e1 = iterator.next(); + assertThat(e1.getCollection()).isEqualTo(EDGE_COL_1); + assertThat(e1.getFrom()).contains(VERTEX_COL_1); + assertThat(e1.getTo()).contains(VERTEX_COL_2); + final EdgeDefinition e2 = iterator.next(); + assertThat(e2.getCollection()).isEqualTo(EDGE_COL_2); + assertThat(e2.getFrom()).contains(VERTEX_COL_2); + assertThat(e2.getTo()).contains(VERTEX_COL_1, VERTEX_COL_3); + assertThat(info.getOrphanCollections()).isEmpty(); + + if (isCluster()) { + for (final String collection : new String[]{VERTEX_COL_1, VERTEX_COL_2}) { + final CollectionPropertiesEntity properties = db.collection(collection).getProperties().get(); + assertThat(properties.getReplicationFactor().getValue()).isEqualTo(REPLICATION_FACTOR); + assertThat(properties.getNumberOfShards()).isEqualTo(NUMBER_OF_SHARDS); + } + for (final String collection : new String[]{EDGE_COL_1, EDGE_COL_2}) { + final CollectionPropertiesEntity properties = db.collection(collection).getProperties().get(); + assertThat(properties.getReplicationFactor().getValue()).isEqualTo(REPLICATION_FACTOR); + } + } + } + + @Test + void getVertexCollections() throws InterruptedException, ExecutionException { + final Collection vertexCollections = db.graph(GRAPH_NAME).getVertexCollections().get(); + assertThat(vertexCollections).isNotNull(); + assertThat(vertexCollections).hasSize(3); + assertThat(vertexCollections).contains(VERTEX_COL_1, VERTEX_COL_2, VERTEX_COL_3); + } + + @Test + void addVertexCollection() throws InterruptedException, ExecutionException { + final GraphEntity graph = db.graph(GRAPH_NAME).addVertexCollection(VERTEX_COL_4).get(); + assertThat(graph).isNotNull(); + final Collection vertexCollections = db.graph(GRAPH_NAME).getVertexCollections().get(); + assertThat(vertexCollections).contains(VERTEX_COL_1, VERTEX_COL_2, VERTEX_COL_3, VERTEX_COL_4); + setup(); + } + + @Test + 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(null, new GraphCreateOptions().isSmart(true).smartGraphAttribute("test")).get(); + g.addVertexCollection(v1Name, new VertexCollectionCreateOptions().satellites(v1Name)).get(); + + Collection vertexCollections = g.getVertexCollections().get(); + assertThat(vertexCollections).contains(v1Name); + assertThat(db.collection(v1Name).getProperties().get().getReplicationFactor()).isEqualTo(ReplicationFactor.ofSatellite()); + + // revert + g.drop().get(); + } + + @Test + void getEdgeCollections() throws InterruptedException, ExecutionException { + final Collection edgeCollections = db.graph(GRAPH_NAME).getEdgeDefinitions().get(); + assertThat(edgeCollections).isNotNull(); + assertThat(edgeCollections).hasSize(2); + assertThat(edgeCollections).contains(EDGE_COL_1, EDGE_COL_2); + } + + @Test + void addEdgeDefinition() throws InterruptedException, ExecutionException { + final GraphEntity graph = db.graph(GRAPH_NAME) + .addEdgeDefinition(new EdgeDefinition().collection(EDGE_COL_3).from(VERTEX_COL_1).to(VERTEX_COL_2)) + .get(); + assertThat(graph).isNotNull(); + final Collection edgeDefinitions = graph.getEdgeDefinitions(); + assertThat(edgeDefinitions).hasSize(3); + int count = 0; + for (final EdgeDefinition e : edgeDefinitions) { + if (e.getCollection().equals(EDGE_COL_3)) { + count++; + } + } + assertThat(count).isEqualTo(1); + for (final EdgeDefinition e : edgeDefinitions) { + if (e.getCollection().equals(EDGE_COL_3)) { + assertThat(e.getFrom()).contains(VERTEX_COL_1); + assertThat(e.getTo()).contains(VERTEX_COL_2); + } + } + if (isCluster()) { + final CollectionPropertiesEntity properties = db.collection(EDGE_COL_3).getProperties().get(); + assertThat(properties.getReplicationFactor().getValue()).isEqualTo(REPLICATION_FACTOR); + assertThat(properties.getNumberOfShards()).isEqualTo(NUMBER_OF_SHARDS); + } + setup(); + } + + @Test + 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(null, new GraphCreateOptions().isSmart(true).smartGraphAttribute("test")).get(); + g.addEdgeDefinition(ed).get(); + final GraphEntity ge = g.getInfo().get(); + assertThat(ge).isNotNull(); + final Collection edgeDefinitions = ge.getEdgeDefinitions(); + assertThat(edgeDefinitions).hasSize(1); + EdgeDefinition e = edgeDefinitions.iterator().next(); + assertThat(e.getCollection()).isEqualTo(eName); + assertThat(e.getFrom()).contains(v1Name); + assertThat(e.getTo()).contains(v2Name); + + assertThat(db.collection(v1Name).getProperties().get().getReplicationFactor()).isEqualTo(ReplicationFactor.ofSatellite()); + + // revert + g.drop().get(); + } + + @Test + void replaceEdgeDefinition() throws InterruptedException, ExecutionException { + final GraphEntity graph = db.graph(GRAPH_NAME) + .replaceEdgeDefinition(new EdgeDefinition().collection(EDGE_COL_1).from(VERTEX_COL_3).to(VERTEX_COL_4)) + .get(); + final Collection edgeDefinitions = graph.getEdgeDefinitions(); + assertThat(edgeDefinitions).hasSize(2); + int count = 0; + for (final EdgeDefinition e : edgeDefinitions) { + if (e.getCollection().equals(EDGE_COL_1)) { + count++; + } + } + assertThat(count).isEqualTo(1); + for (final EdgeDefinition e : edgeDefinitions) { + if (e.getCollection().equals(EDGE_COL_1)) { + assertThat(e.getFrom()).contains(VERTEX_COL_3); + assertThat(e.getTo()).contains(VERTEX_COL_4); + } + } + setup(); + } + + @Test + void removeEdgeDefinition() throws InterruptedException, ExecutionException { + final GraphEntity graph = db.graph(GRAPH_NAME).removeEdgeDefinition(EDGE_COL_1).get(); + final Collection edgeDefinitions = graph.getEdgeDefinitions(); + assertThat(edgeDefinitions).hasSize(1); + assertThat(edgeDefinitions.iterator().next().getCollection()).isEqualTo(EDGE_COL_2); + setup(); + } + + @Test + void smartGraph() throws InterruptedException, ExecutionException { + assumeTrue(isCluster()); + assumeTrue(isEnterprise()); + for (final String collection : new String[]{EDGE_COL_1, EDGE_COL_2, VERTEX_COL_1, VERTEX_COL_2, + VERTEX_COL_3, VERTEX_COL_4}) { + if (db.collection(collection).exists().get()) { + db.collection(collection).drop().get(); + } + } + final Collection edgeDefinitions = new ArrayList<>(); + edgeDefinitions.add(new EdgeDefinition().collection(EDGE_COL_1).from(VERTEX_COL_1).to(VERTEX_COL_2)); + 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)) + .get(); + assertThat(graph).isNotNull(); + assertThat(graph.getIsSmart()).isTrue(); + assertThat(graph.getSmartGraphAttribute()).isEqualTo("test"); + assertThat(graph.getNumberOfShards()).isEqualTo(2); + if (db.graph(GRAPH_NAME + "_smart").exists().get()) { + db.graph(GRAPH_NAME + "_smart").drop().get(); + } + } + + @Test + 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).isNotNull(); + assertThat(g.getIsSmart()).isTrue(); + assertThat(g.getSmartGraphAttribute()).isEqualTo("test"); + assertThat(g.getNumberOfShards()).isEqualTo(2); + + assertThat(db.collection(eName).getProperties().get().getReplicationFactor()).isEqualTo(ReplicationFactor.ofSatellite()); + assertThat(db.collection(v1Name).getProperties().get().getReplicationFactor()).isEqualTo(ReplicationFactor.ofSatellite()); + assertThat(db.collection(v2Name).getProperties().get().getReplicationFactor().getValue()).isEqualTo(2); + } + + @Test + 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).isNotNull(); + assertThat(g.getIsSmart()).isTrue(); + assertThat(g.getIsDisjoint()).isTrue(); + assertThat(g.getSmartGraphAttribute()).isEqualTo("test"); + assertThat(g.getNumberOfShards()).isEqualTo(2); + + assertThat(db.collection(v1Name).getProperties().get().getReplicationFactor()).isEqualTo(ReplicationFactor.ofSatellite()); + assertThat(db.collection(v2Name).getProperties().get().getReplicationFactor().getValue()).isEqualTo(2); + } + + @Test + 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))) + .get(); + assertThat(result).isNotNull(); + db.graph(graph).drop().get(); + assertThat(db.collection(edgeCollection).exists().get()).isTrue(); + assertThat(db.collection(vertexCollection).exists().get()).isTrue(); + } + + @Test + void dropPlusDropCollections() throws InterruptedException, ExecutionException { + final String edgeCollection = "edge_dropC"; + 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))) + .get(); + assertThat(result).isNotNull(); + db.graph(graph).drop(true).get(); + assertThat(db.collection(edgeCollection).exists().get()).isFalse(); + assertThat(db.collection(vertexCollection).exists().get()).isFalse(); + } +} diff --git a/shaded-integration-tests/src/test/jackson/java/com/arangodb/async/ArangoRouteTest.java b/shaded-integration-tests/src/test/jackson/java/com/arangodb/async/ArangoRouteTest.java new file mode 100644 index 000000000..772e593f5 --- /dev/null +++ b/shaded-integration-tests/src/test/jackson/java/com/arangodb/async/ArangoRouteTest.java @@ -0,0 +1,81 @@ +/* + * DISCLAIMER + * + * Copyright 2018 ArangoDB GmbH, Cologne, Germany + * + * Licensed 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. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.async; + +import com.arangodb.ArangoDBException; +import com.arangodb.entity.BaseDocument; +import com.arangodb.internal.ArangoRequestParam; +import org.junit.jupiter.api.Test; + +import java.util.UUID; +import java.util.concurrent.ExecutionException; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.fail; + +/** + * @author Mark Vollmary + */ +class ArangoRouteTest extends BaseTest { + + /* + @Test + void get() throws InterruptedException, ExecutionException { + final Response res = db.route("/_api/version").get().get(); + assertThat(res.getBody().get("version").isString()).isEqualTo(true); + }*/ + + /* + @Test + void withHeader() throws InterruptedException, ExecutionException { + final ArangoCollectionAsync collection = db.collection("route-test-col"); + try { + collection.create(); + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); + collection.insertDocument(doc).get(); + db.route("/_api/document", doc.getId()).withHeader(ArangoRequestParam.IF_NONE_MATCH, doc.getRevision()) + .get().get(); + fail(); + } catch (final ExecutionException e) { + assertThat(e.getCause() instanceof ArangoDBException).isEqualTo(true); + } finally { + collection.drop(); + } + } + */ + + @Test + void withParentHeader() throws InterruptedException, ExecutionException { + final ArangoCollectionAsync collection = db.collection("route-test-col"); + try { + collection.create().get(); + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); + collection.insertDocument(doc).get(); + db.route("/_api/document").withHeader(ArangoRequestParam.IF_NONE_MATCH, doc.getRevision()) + .route(doc.getId()).get().get(); + fail(); + } catch (final ExecutionException e) { + assertThat(e.getCause()).isInstanceOf(ArangoDBException.class); + } + collection.drop().get(); + } + +} diff --git a/shaded-integration-tests/src/test/jackson/java/com/arangodb/async/ArangoSearchTest.java b/shaded-integration-tests/src/test/jackson/java/com/arangodb/async/ArangoSearchTest.java new file mode 100644 index 000000000..84dc1ba01 --- /dev/null +++ b/shaded-integration-tests/src/test/jackson/java/com/arangodb/async/ArangoSearchTest.java @@ -0,0 +1,551 @@ +/* + * DISCLAIMER + * + * Copyright 2018 ArangoDB GmbH, Cologne, Germany + * + * Licensed 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. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.async; + +import com.arangodb.ArangoDBException; +import com.arangodb.entity.InvertedIndexField; +import com.arangodb.entity.ViewEntity; +import com.arangodb.entity.ViewType; +import com.arangodb.entity.arangosearch.*; +import com.arangodb.entity.arangosearch.analyzer.*; +import com.arangodb.model.InvertedIndexOptions; +import com.arangodb.model.arangosearch.*; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; + +import java.util.Collection; +import java.util.HashSet; +import java.util.Set; +import java.util.UUID; +import java.util.concurrent.ExecutionException; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.fail; +import static org.junit.jupiter.api.Assumptions.assumeTrue; + +/** + * @author Mark Vollmary + */ + +class ArangoSearchTest extends BaseTest { + + private static final String VIEW_NAME = "view_test"; + private static final String COLL_1 = "view_update_prop_test_collection"; + private static final String COLL_2 = "view_replace_prop_test_collection"; + + @BeforeAll + static void setup() throws InterruptedException, ExecutionException { + if (!isAtLeastVersion(arangoDB, 3, 4)) + return; + db.createArangoSearch(VIEW_NAME, new ArangoSearchCreateOptions()).get(); + db.createCollection(COLL_1).get(); + db.createCollection(COLL_2).get(); + } + + @Test + void exists() throws InterruptedException, ExecutionException { + assumeTrue(isAtLeastVersion(3, 4)); + assertThat(db.arangoSearch(VIEW_NAME).exists().get()).isTrue(); + } + + @Test + void createAndExistsSearchAlias() throws ExecutionException, InterruptedException { + assumeTrue(isAtLeastVersion(3, 10)); + String viewName = "view-" + rnd(); + db.createSearchAlias(viewName, new SearchAliasCreateOptions()).get(); + assertThat(db.arangoSearch(viewName).exists().get()).isTrue(); + } + + @Test + void getInfo() throws InterruptedException, ExecutionException { + assumeTrue(isAtLeastVersion(3, 4)); + final ViewEntity info = db.arangoSearch(VIEW_NAME).getInfo().get(); + assertThat(info).isNotNull(); + assertThat(info.getId()).isNotNull(); + assertThat(info.getName()).isEqualTo(VIEW_NAME); + assertThat(info.getType()).isEqualTo(ViewType.ARANGO_SEARCH); + } + + @Test + void drop() throws InterruptedException, ExecutionException { + assumeTrue(isAtLeastVersion(3, 4)); + final String name = VIEW_NAME + "_droptest"; + db.createArangoSearch(name, new ArangoSearchCreateOptions()).get(); + final ArangoViewAsync view = db.arangoSearch(name); + view.drop().get(); + assertThat(view.exists().get()).isFalse(); + } + + @Test + void rename() throws InterruptedException, ExecutionException { + assumeTrue(isSingleServer()); + assumeTrue(isAtLeastVersion(3, 4)); + final String name = VIEW_NAME + "_renametest"; + final String newName = name + "_new"; + db.createArangoSearch(name, new ArangoSearchCreateOptions()).get(); + db.arangoSearch(name).rename(newName).get(); + assertThat(db.arangoSearch(name).exists().get()).isFalse(); + assertThat(db.arangoSearch(newName).exists().get()).isTrue(); + } + + @Test + void createArangoSearchView() throws InterruptedException, ExecutionException { + assumeTrue(isAtLeastVersion(3, 4)); + final String name = VIEW_NAME + "_createtest"; + final ViewEntity info = db.arangoSearch(name).create().get(); + assertThat(info).isNotNull(); + assertThat(info.getId()).isNotNull(); + assertThat(info.getName()).isEqualTo(name); + assertThat(info.getType()).isEqualTo(ViewType.ARANGO_SEARCH); + assertThat(db.arangoSearch(name).exists().get()).isTrue(); + } + + @Test + void createSearchAliasView() throws ExecutionException, InterruptedException { + assumeTrue(isAtLeastVersion(3, 10)); + String viewName = "view-" + rnd(); + final ViewEntity info = db.searchAlias(viewName).create().get(); + assertThat(info).isNotNull(); + assertThat(info.getId()).isNotNull(); + assertThat(info.getName()).isEqualTo(viewName); + assertThat(info.getType()).isEqualTo(ViewType.SEARCH_ALIAS); + assertThat(db.searchAlias(viewName).exists().get()).isTrue(); + } + + @Test + void createArangoSearchViewWithOptions() throws InterruptedException, ExecutionException { + assumeTrue(isAtLeastVersion(3, 4)); + final String name = VIEW_NAME + "_createtest_withotpions"; + final ViewEntity info = db.arangoSearch(name).create(new ArangoSearchCreateOptions()).get(); + assertThat(info).isNotNull(); + assertThat(info.getId()).isNotNull(); + assertThat(info.getName()).isEqualTo(name); + assertThat(info.getType()).isEqualTo(ViewType.ARANGO_SEARCH); + assertThat(db.arangoSearch(name).exists().get()).isTrue(); + } + + @Test + void createArangoSearchViewWithPrimarySort() throws ExecutionException, InterruptedException { + assumeTrue(isAtLeastVersion(3, 5)); + final String name = "createWithPrimarySort"; + final ArangoSearchCreateOptions options = new ArangoSearchCreateOptions(); + + final PrimarySort primarySort = PrimarySort.on("myFieldName"); + primarySort.ascending(true); + options.primarySort(primarySort); + options.consolidationIntervalMsec(666666L); + + final ViewEntity info = db.arangoSearch(name).create(options).get(); + assertThat(info).isNotNull(); + assertThat(info.getId()).isNotNull(); + assertThat(info.getName()).isEqualTo(name); + assertThat(info.getType()).isEqualTo(ViewType.ARANGO_SEARCH); + assertThat(db.arangoSearch(name).exists().get()).isTrue(); + } + + @Test + void createArangoSearchViewWithCommitIntervalMsec() throws ExecutionException, InterruptedException { + assumeTrue(isAtLeastVersion(3, 5)); + final String name = "createWithCommitIntervalMsec"; + final ArangoSearchCreateOptions options = new ArangoSearchCreateOptions(); + options.commitIntervalMsec(666666L); + + final ViewEntity info = db.arangoSearch(name).create(options).get(); + assertThat(info).isNotNull(); + assertThat(info.getId()).isNotNull(); + assertThat(info.getName()).isEqualTo(name); + assertThat(info.getType()).isEqualTo(ViewType.ARANGO_SEARCH); + assertThat(db.arangoSearch(name).exists().get()).isTrue(); + + // check commit interval msec property + final ArangoSearchAsync view = db.arangoSearch(name); + final ArangoSearchPropertiesEntity properties = view.getProperties().get(); + assertThat(properties.getCommitIntervalMsec()).isEqualTo(666666L); + } + + @Test + void createSearchAliasViewWithOptions() throws ExecutionException, InterruptedException { + assumeTrue(isAtLeastVersion(3, 10)); + String viewName = "view-" + rnd(); + final SearchAliasCreateOptions options = new SearchAliasCreateOptions(); + final ViewEntity info = db.searchAlias(viewName).create(options).get(); + assertThat(info).isNotNull(); + assertThat(info.getId()).isNotNull(); + assertThat(info.getName()).isEqualTo(viewName); + assertThat(info.getType()).isEqualTo(ViewType.SEARCH_ALIAS); + assertThat(db.searchAlias(viewName).exists().get()).isTrue(); + } + + @Test + void createSearchAliasViewWithIndexesAndGetProperties() throws ExecutionException, InterruptedException { + assumeTrue(isAtLeastVersion(3, 10)); + ArangoCollectionAsync col = db.collection(COLL_1); + String idxName = "idx-" + rnd(); + col.ensureInvertedIndex(new InvertedIndexOptions() + .name(idxName) + .fields(new InvertedIndexField().name("a" + rnd()))) + .get(); + String viewName = "view-" + rnd(); + final SearchAliasCreateOptions options = new SearchAliasCreateOptions() + .indexes(new SearchAliasIndex(COLL_1, idxName)); + final ViewEntity info = db.searchAlias(viewName).create(options).get(); + assertThat(info).isNotNull(); + assertThat(info.getId()).isNotNull(); + assertThat(info.getName()).isEqualTo(viewName); + assertThat(info.getType()).isEqualTo(ViewType.SEARCH_ALIAS); + + final SearchAliasPropertiesEntity properties = db.searchAlias(viewName).getProperties().get(); + assertThat(properties).isNotNull(); + assertThat(properties.getId()).isNotNull(); + assertThat(properties.getName()).isEqualTo(viewName); + assertThat(properties.getType()).isEqualTo(ViewType.SEARCH_ALIAS); + assertThat(properties.getIndexes()) + .isNotNull() + .isNotEmpty() + .anyMatch(i -> i.getCollection().equals(COLL_1) && i.getIndex().equals(idxName)); + } + + @Test + void getArangoSearchViewProperties() throws InterruptedException, ExecutionException { + assumeTrue(isAtLeastVersion(3, 4)); + final String name = VIEW_NAME + "_getpropertiestest"; + final ArangoSearchAsync view = db.arangoSearch(name); + view.create(new ArangoSearchCreateOptions()).get(); + final ArangoSearchPropertiesEntity properties = view.getProperties().get(); + assertThat(properties).isNotNull(); + assertThat(properties.getId()).isNotNull(); + assertThat(properties.getName()).isEqualTo(name); + assertThat(properties.getType()).isEqualTo(ViewType.ARANGO_SEARCH); + assertThat(properties.getConsolidationIntervalMsec()).isNotNull(); + assertThat(properties.getCleanupIntervalStep()).isNotNull(); + final ConsolidationPolicy consolidate = properties.getConsolidationPolicy(); + assertThat(consolidate).isNotNull(); + final Collection links = properties.getLinks(); + assertThat(links).isEmpty(); + } + + @Test + void updateArangoSearchViewProperties() throws InterruptedException, ExecutionException { + assumeTrue(isAtLeastVersion(3, 4)); + final String name = VIEW_NAME + "_updatepropertiestest"; + final ArangoSearchAsync view = db.arangoSearch(name); + view.create(new ArangoSearchCreateOptions()).get(); + final ArangoSearchPropertiesOptions options = new ArangoSearchPropertiesOptions(); + options.cleanupIntervalStep(15L); + options.consolidationIntervalMsec(65000L); + options.consolidationPolicy(ConsolidationPolicy.of(ConsolidationType.BYTES_ACCUM).threshold(1.)); + options.link( + CollectionLink.on("view_update_prop_test_collection").fields(FieldLink.on("value").analyzers("identity") + .trackListPositions(true).includeAllFields(true).storeValues(StoreValuesType.ID))); + final ArangoSearchPropertiesEntity properties = view.updateProperties(options).get(); + assertThat(properties).isNotNull(); + assertThat(properties.getCleanupIntervalStep()).isEqualTo(15L); + assertThat(properties.getConsolidationIntervalMsec()).isEqualTo(65000L); + final ConsolidationPolicy consolidate = properties.getConsolidationPolicy(); + assertThat(consolidate).isNotNull(); + assertThat(consolidate.getType()).isEqualTo(ConsolidationType.BYTES_ACCUM); + assertThat(consolidate.getThreshold()).isEqualTo(1.); + assertThat(properties.getLinks()).hasSize(1); + final CollectionLink link = properties.getLinks().iterator().next(); + assertThat(link.getName()).isEqualTo("view_update_prop_test_collection"); + assertThat(link.getFields()).hasSize(1); + final FieldLink next = link.getFields().iterator().next(); + assertThat(next.getName()).isEqualTo("value"); + assertThat(next.getIncludeAllFields()).isTrue(); + assertThat(next.getTrackListPositions()).isTrue(); + assertThat(next.getStoreValues()).isEqualTo(StoreValuesType.ID); + } + + @Test + void updateSearchAliasViewWithIndexesAndGetProperties() throws ExecutionException, InterruptedException { + assumeTrue(isAtLeastVersion(3, 10)); + ArangoCollectionAsync col = db.collection(COLL_1); + String idxName = "idx-" + rnd(); + col.ensureInvertedIndex(new InvertedIndexOptions() + .name(idxName) + .fields(new InvertedIndexField().name("a" + rnd()))) + .get(); + ArangoCollectionAsync col2 = db.collection(COLL_2); + String idxName2 = "idx-" + rnd(); + col2.ensureInvertedIndex(new InvertedIndexOptions() + .name(idxName2) + .fields(new InvertedIndexField().name("a" + rnd()))) + .get(); + + String viewName = "view-" + rnd(); + final SearchAliasCreateOptions options = new SearchAliasCreateOptions() + .indexes(new SearchAliasIndex(COLL_1, idxName)); + final ViewEntity info = db.searchAlias(viewName).create(options).get(); + db.searchAlias(viewName).updateProperties(new SearchAliasPropertiesOptions() + .indexes(new SearchAliasIndex(COLL_2, idxName2))).get(); + + assertThat(info).isNotNull(); + assertThat(info.getId()).isNotNull(); + assertThat(info.getName()).isEqualTo(viewName); + assertThat(info.getType()).isEqualTo(ViewType.SEARCH_ALIAS); + + final SearchAliasPropertiesEntity properties = db.searchAlias(viewName).getProperties().get(); + assertThat(properties).isNotNull(); + assertThat(properties.getId()).isNotNull(); + assertThat(properties.getName()).isEqualTo(viewName); + assertThat(properties.getType()).isEqualTo(ViewType.SEARCH_ALIAS); + assertThat(properties.getIndexes()) + .isNotNull() + .isNotEmpty() + .hasSize(2) + .anyMatch(i -> i.getCollection().equals(COLL_1) && i.getIndex().equals(idxName)) + .anyMatch(i -> i.getCollection().equals(COLL_2) && i.getIndex().equals(idxName2)); + } + + @Test + void replaceArangoSearchViewProperties() throws InterruptedException, ExecutionException { + assumeTrue(isAtLeastVersion(3, 4)); + final String name = VIEW_NAME + "_replacepropertiestest"; + final ArangoSearchAsync view = db.arangoSearch(name); + view.create(new ArangoSearchCreateOptions()).get(); + final ArangoSearchPropertiesOptions options = new ArangoSearchPropertiesOptions(); + options.link( + CollectionLink.on("view_replace_prop_test_collection").fields(FieldLink.on("value").analyzers( + "identity"))); + final ArangoSearchPropertiesEntity properties = view.replaceProperties(options).get(); + assertThat(properties).isNotNull(); + assertThat(properties.getLinks()).hasSize(1); + final CollectionLink link = properties.getLinks().iterator().next(); + assertThat(link.getName()).isEqualTo("view_replace_prop_test_collection"); + assertThat(link.getFields()).hasSize(1); + assertThat(link.getFields().iterator().next().getName()).isEqualTo("value"); + } + + @Test + void replaceSearchAliasViewWithIndexesAndGetProperties() throws ExecutionException, InterruptedException { + assumeTrue(isAtLeastVersion(3, 10)); + ArangoCollectionAsync col = db.collection(COLL_1); + String idxName = "idx-" + rnd(); + col.ensureInvertedIndex(new InvertedIndexOptions() + .name(idxName) + .fields(new InvertedIndexField().name("a" + rnd()))) + .get(); + ArangoCollectionAsync col2 = db.collection(COLL_2); + String idxName2 = "idx-" + rnd(); + col2.ensureInvertedIndex(new InvertedIndexOptions() + .name(idxName2) + .fields(new InvertedIndexField().name("a" + rnd()))) + .get(); + + String viewName = "view-" + rnd(); + final SearchAliasCreateOptions options = new SearchAliasCreateOptions() + .indexes(new SearchAliasIndex(COLL_1, idxName)); + final ViewEntity info = db.searchAlias(viewName).create(options).get(); + db.searchAlias(viewName).replaceProperties(new SearchAliasPropertiesOptions() + .indexes(new SearchAliasIndex(COLL_2, idxName2))).get(); + + assertThat(info).isNotNull(); + assertThat(info.getId()).isNotNull(); + assertThat(info.getName()).isEqualTo(viewName); + assertThat(info.getType()).isEqualTo(ViewType.SEARCH_ALIAS); + + final SearchAliasPropertiesEntity properties = db.searchAlias(viewName).getProperties().get(); + assertThat(properties).isNotNull(); + assertThat(properties.getId()).isNotNull(); + assertThat(properties.getName()).isEqualTo(viewName); + assertThat(properties.getType()).isEqualTo(ViewType.SEARCH_ALIAS); + assertThat(properties.getIndexes()) + .isNotNull() + .isNotEmpty() + .hasSize(1) + .anyMatch(i -> i.getCollection().equals(COLL_2) && i.getIndex().equals(idxName2)); + } + + private void createGetAndDeleteTypedAnalyzer(SearchAnalyzer analyzer) throws ExecutionException, + InterruptedException { + + String fullyQualifiedName = db.dbName().get() + "::" + analyzer.getName(); + analyzer.setName(fullyQualifiedName); + + // createAnalyzer + SearchAnalyzer createdAnalyzer = db.createSearchAnalyzer(analyzer).get(); + assertThat(createdAnalyzer).isEqualTo(analyzer); + + // getAnalyzer + SearchAnalyzer gotAnalyzer = db.getSearchAnalyzer(analyzer.getName()).get(); + assertThat(gotAnalyzer).isEqualTo(analyzer); + + // getAnalyzers + SearchAnalyzer foundAnalyzer = + db.getSearchAnalyzers().get().stream().filter(it -> it.getName().equals(fullyQualifiedName)) + .findFirst().get(); + assertThat(foundAnalyzer).isEqualTo(analyzer); + + // deleteAnalyzer + AnalyzerDeleteOptions deleteOptions = new AnalyzerDeleteOptions(); + deleteOptions.setForce(true); + + db.deleteSearchAnalyzer(analyzer.getName(), deleteOptions).get(); + + try { + db.getSearchAnalyzer(analyzer.getName()).get(); + fail("deleted analyzer should not be found!"); + } catch (ExecutionException e) { + assertThat(e.getCause()).isInstanceOf(ArangoDBException.class); + assertThat(((ArangoDBException) e.getCause()).getResponseCode()).isEqualTo(404); + assertThat(((ArangoDBException) e.getCause()).getErrorNum()).isEqualTo(1202); + } + + } + + @Test + void identityAnalyzerTyped() throws ExecutionException, InterruptedException { + assumeTrue(isAtLeastVersion(3, 5)); + + String name = "test-" + UUID.randomUUID(); + + Set features = new HashSet<>(); + features.add(AnalyzerFeature.frequency); + features.add(AnalyzerFeature.norm); + features.add(AnalyzerFeature.position); + + IdentityAnalyzer analyzer = new IdentityAnalyzer(); + analyzer.setFeatures(features); + analyzer.setName(name); + + createGetAndDeleteTypedAnalyzer(analyzer); + } + + @Test + void delimiterAnalyzerTyped() throws ExecutionException, InterruptedException { + assumeTrue(isAtLeastVersion(3, 5)); + + String name = "test-" + UUID.randomUUID(); + + Set features = new HashSet<>(); + features.add(AnalyzerFeature.frequency); + features.add(AnalyzerFeature.norm); + features.add(AnalyzerFeature.position); + + DelimiterAnalyzerProperties properties = new DelimiterAnalyzerProperties(); + properties.setDelimiter("-"); + + DelimiterAnalyzer analyzer = new DelimiterAnalyzer(); + analyzer.setFeatures(features); + analyzer.setName(name); + analyzer.setProperties(properties); + + createGetAndDeleteTypedAnalyzer(analyzer); + } + + @Test + void stemAnalyzerTyped() throws ExecutionException, InterruptedException { + assumeTrue(isAtLeastVersion(3, 5)); + + String name = "test-" + UUID.randomUUID(); + + Set features = new HashSet<>(); + features.add(AnalyzerFeature.frequency); + features.add(AnalyzerFeature.norm); + features.add(AnalyzerFeature.position); + + StemAnalyzerProperties properties = new StemAnalyzerProperties(); + properties.setLocale("ru"); + + StemAnalyzer options = new StemAnalyzer(); + options.setFeatures(features); + options.setName(name); + options.setProperties(properties); + + createGetAndDeleteTypedAnalyzer(options); + } + + @Test + void normAnalyzerTyped() throws ExecutionException, InterruptedException { + assumeTrue(isAtLeastVersion(3, 5)); + + String name = "test-" + UUID.randomUUID(); + + Set features = new HashSet<>(); + features.add(AnalyzerFeature.frequency); + features.add(AnalyzerFeature.norm); + features.add(AnalyzerFeature.position); + + NormAnalyzerProperties properties = new NormAnalyzerProperties(); + properties.setLocale("ru"); + properties.setAnalyzerCase(SearchAnalyzerCase.lower); + properties.setAccent(true); + + NormAnalyzer options = new NormAnalyzer(); + options.setFeatures(features); + options.setName(name); + options.setProperties(properties); + + createGetAndDeleteTypedAnalyzer(options); + } + + @Test + void ngramAnalyzerTyped() throws ExecutionException, InterruptedException { + assumeTrue(isAtLeastVersion(3, 5)); + + String name = "test-" + UUID.randomUUID(); + + Set features = new HashSet<>(); + features.add(AnalyzerFeature.frequency); + features.add(AnalyzerFeature.norm); + features.add(AnalyzerFeature.position); + + NGramAnalyzerProperties properties = new NGramAnalyzerProperties(); + properties.setMax(6L); + properties.setMin(3L); + properties.setPreserveOriginal(true); + + NGramAnalyzer analyzer = new NGramAnalyzer(); + analyzer.setFeatures(features); + analyzer.setName(name); + analyzer.setType(AnalyzerType.ngram); + analyzer.setProperties(properties); + + createGetAndDeleteTypedAnalyzer(analyzer); + } + + @Test + void textAnalyzerTyped() throws ExecutionException, InterruptedException { + assumeTrue(isAtLeastVersion(3, 5)); + + String name = "test-" + UUID.randomUUID(); + + Set features = new HashSet<>(); + features.add(AnalyzerFeature.frequency); + features.add(AnalyzerFeature.norm); + features.add(AnalyzerFeature.position); + + TextAnalyzerProperties properties = new TextAnalyzerProperties(); + properties.setLocale("ru"); + properties.setAnalyzerCase(SearchAnalyzerCase.lower); + properties.setAccent(true); + properties.setStemming(true); + + TextAnalyzer analyzer = new TextAnalyzer(); + analyzer.setFeatures(features); + analyzer.setName(name); + analyzer.setType(AnalyzerType.text); + analyzer.setProperties(properties); + + createGetAndDeleteTypedAnalyzer(analyzer); + } + +} diff --git a/shaded-integration-tests/src/test/jackson/java/com/arangodb/async/ArangoVertexCollectionTest.java b/shaded-integration-tests/src/test/jackson/java/com/arangodb/async/ArangoVertexCollectionTest.java new file mode 100644 index 000000000..4da5b6735 --- /dev/null +++ b/shaded-integration-tests/src/test/jackson/java/com/arangodb/async/ArangoVertexCollectionTest.java @@ -0,0 +1,356 @@ +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed 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. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.async; + +import com.arangodb.ArangoDBException; +import com.arangodb.entity.BaseDocument; +import com.arangodb.entity.VertexEntity; +import com.arangodb.entity.VertexUpdateEntity; +import com.arangodb.model.*; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; + +import java.util.Collection; +import java.util.UUID; +import java.util.concurrent.ExecutionException; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.fail; + +/** + * @author Mark Vollmary + */ +class ArangoVertexCollectionTest extends BaseTest { + + private static final String GRAPH_NAME = "db_collection_test"; + private static final String COLLECTION_NAME = "db_vertex_collection_test"; + + @BeforeAll + static void setup() throws InterruptedException, ExecutionException { + if (!db.collection(COLLECTION_NAME).exists().get()) { + db.createCollection(COLLECTION_NAME, null).get(); + } + final GraphCreateOptions options = new GraphCreateOptions().orphanCollections(COLLECTION_NAME); + db.createGraph(GRAPH_NAME, null, options).get(); + } + + @AfterEach + void teardown() throws InterruptedException, ExecutionException { + db.collection(COLLECTION_NAME).truncate().get(); + } + + @Test + void dropVertexCollection() throws InterruptedException, ExecutionException { + db.graph(GRAPH_NAME).vertexCollection(COLLECTION_NAME).drop().get(); + final Collection vertexCollections = db.graph(GRAPH_NAME).getVertexCollections().get(); + assertThat(vertexCollections).doesNotContain(COLLECTION_NAME); + } + + @Test + void insertVertex() throws InterruptedException, ExecutionException { + final VertexEntity vertex = db.graph(GRAPH_NAME).vertexCollection(COLLECTION_NAME) + .insertVertex(new BaseDocument(), null).get(); + assertThat(vertex).isNotNull(); + final BaseDocument document = db.collection(COLLECTION_NAME) + .getDocument(vertex.getKey(), BaseDocument.class, null).get(); + assertThat(document).isNotNull(); + assertThat(document.getKey()).isEqualTo(vertex.getKey()); + } + + @Test + void getVertex() throws InterruptedException, ExecutionException { + final VertexEntity vertex = db.graph(GRAPH_NAME).vertexCollection(COLLECTION_NAME) + .insertVertex(new BaseDocument(), null).get(); + final BaseDocument document = db.graph(GRAPH_NAME).vertexCollection(COLLECTION_NAME) + .getVertex(vertex.getKey(), BaseDocument.class, null).get(); + assertThat(document).isNotNull(); + assertThat(document.getKey()).isEqualTo(vertex.getKey()); + } + + @Test + void getVertexIfMatch() throws InterruptedException, ExecutionException { + final VertexEntity vertex = db.graph(GRAPH_NAME).vertexCollection(COLLECTION_NAME) + .insertVertex(new BaseDocument(), null).get(); + final GraphDocumentReadOptions options = new GraphDocumentReadOptions().ifMatch(vertex.getRev()); + final BaseDocument document = db.graph(GRAPH_NAME).vertexCollection(COLLECTION_NAME) + .getVertex(vertex.getKey(), BaseDocument.class, options).get(); + assertThat(document).isNotNull(); + assertThat(document.getKey()).isEqualTo(vertex.getKey()); + } + + @Test + void getVertexIfMatchFail() throws InterruptedException, ExecutionException { + final VertexEntity vertex = db.graph(GRAPH_NAME).vertexCollection(COLLECTION_NAME) + .insertVertex(new BaseDocument(), null).get(); + final GraphDocumentReadOptions options = new GraphDocumentReadOptions().ifMatch("no"); + BaseDocument res = db.graph(GRAPH_NAME).vertexCollection(COLLECTION_NAME) + .getVertex(vertex.getKey(), BaseDocument.class, options).get(); + assertThat(res).isNull(); + } + + @Test + void getVertexIfNoneMatch() throws InterruptedException, ExecutionException { + final VertexEntity vertex = db.graph(GRAPH_NAME).vertexCollection(COLLECTION_NAME) + .insertVertex(new BaseDocument(), null).get(); + final GraphDocumentReadOptions options = new GraphDocumentReadOptions().ifNoneMatch("no"); + final BaseDocument document = db.graph(GRAPH_NAME).vertexCollection(COLLECTION_NAME) + .getVertex(vertex.getKey(), BaseDocument.class, options).get(); + assertThat(document).isNotNull(); + assertThat(document.getKey()).isEqualTo(vertex.getKey()); + } + + @Test + void getVertexIfNoneMatchFail() throws InterruptedException, ExecutionException { + final VertexEntity vertex = db.graph(GRAPH_NAME).vertexCollection(COLLECTION_NAME) + .insertVertex(new BaseDocument(), null).get(); + final GraphDocumentReadOptions options = new GraphDocumentReadOptions().ifNoneMatch(vertex.getRev()); + BaseDocument res = db.graph(GRAPH_NAME).vertexCollection(COLLECTION_NAME) + .getVertex(vertex.getKey(), BaseDocument.class, options).get(); + assertThat(res).isNull(); + } + + @Test + void replaceVertex() throws InterruptedException, ExecutionException { + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); + doc.addAttribute("a", "test"); + final VertexEntity createResult = db.graph(GRAPH_NAME).vertexCollection(COLLECTION_NAME).insertVertex(doc, null) + .get(); + doc.removeAttribute("a"); + doc.addAttribute("b", "test"); + final VertexUpdateEntity replaceResult = db.graph(GRAPH_NAME).vertexCollection(COLLECTION_NAME) + .replaceVertex(createResult.getKey(), doc, null).get(); + assertThat(replaceResult).isNotNull(); + assertThat(replaceResult.getId()).isEqualTo(createResult.getId()); + assertThat(replaceResult.getRev()).isNotEqualTo(replaceResult.getOldRev()); + assertThat(replaceResult.getOldRev()).isEqualTo(createResult.getRev()); + + final BaseDocument readResult = db.graph(GRAPH_NAME).vertexCollection(COLLECTION_NAME) + .getVertex(createResult.getKey(), BaseDocument.class, null).get(); + assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); + assertThat(readResult.getRevision()).isEqualTo(replaceResult.getRev()); + assertThat(readResult.getProperties().keySet()).doesNotContain("a"); + assertThat(readResult.getAttribute("b")).isNotNull(); + assertThat(String.valueOf(readResult.getAttribute("b"))).isEqualTo("test"); + } + + @Test + void replaceVertexIfMatch() throws InterruptedException, ExecutionException { + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); + doc.addAttribute("a", "test"); + final VertexEntity createResult = db.graph(GRAPH_NAME).vertexCollection(COLLECTION_NAME).insertVertex(doc, null) + .get(); + doc.removeAttribute("a"); + doc.addAttribute("b", "test"); + final VertexReplaceOptions options = new VertexReplaceOptions().ifMatch(createResult.getRev()); + final VertexUpdateEntity replaceResult = db.graph(GRAPH_NAME).vertexCollection(COLLECTION_NAME) + .replaceVertex(createResult.getKey(), doc, options).get(); + assertThat(replaceResult).isNotNull(); + assertThat(replaceResult.getId()).isEqualTo(createResult.getId()); + assertThat(replaceResult.getRev()).isNotEqualTo(replaceResult.getOldRev()); + assertThat(replaceResult.getOldRev()).isEqualTo(createResult.getRev()); + + final BaseDocument readResult = db.graph(GRAPH_NAME).vertexCollection(COLLECTION_NAME) + .getVertex(createResult.getKey(), BaseDocument.class, null).get(); + assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); + assertThat(readResult.getRevision()).isEqualTo(replaceResult.getRev()); + assertThat(readResult.getProperties().keySet()).doesNotContain("a"); + assertThat(readResult.getAttribute("b")).isNotNull(); + assertThat(String.valueOf(readResult.getAttribute("b"))).isEqualTo("test"); + } + + @Test + void replaceVertexIfMatchFail() throws InterruptedException, ExecutionException { + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); + doc.addAttribute("a", "test"); + final VertexEntity createResult = db.graph(GRAPH_NAME).vertexCollection(COLLECTION_NAME).insertVertex(doc, null) + .get(); + doc.removeAttribute("a"); + doc.addAttribute("b", "test"); + try { + final VertexReplaceOptions options = new VertexReplaceOptions().ifMatch("no"); + db.graph(GRAPH_NAME).vertexCollection(COLLECTION_NAME).replaceVertex(createResult.getKey(), doc, options) + .get(); + fail(); + } catch (final ExecutionException e) { + assertThat(e.getCause()).isInstanceOf(ArangoDBException.class); + } + } + + @Test + void updateVertex() throws InterruptedException, ExecutionException { + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); + doc.addAttribute("a", "test"); + doc.addAttribute("c", "test"); + final VertexEntity createResult = db.graph(GRAPH_NAME).vertexCollection(COLLECTION_NAME).insertVertex(doc, null) + .get(); + doc.updateAttribute("a", "test1"); + doc.addAttribute("b", "test"); + doc.updateAttribute("c", null); + final VertexUpdateEntity updateResult = db.graph(GRAPH_NAME).vertexCollection(COLLECTION_NAME) + .updateVertex(createResult.getKey(), doc, null).get(); + assertThat(updateResult).isNotNull(); + assertThat(updateResult.getId()).isEqualTo(createResult.getId()); + assertThat(updateResult.getRev()).isNotEqualTo(updateResult.getOldRev()); + assertThat(updateResult.getOldRev()).isEqualTo(createResult.getRev()); + + final BaseDocument readResult = db.graph(GRAPH_NAME).vertexCollection(COLLECTION_NAME) + .getVertex(createResult.getKey(), BaseDocument.class, null).get(); + assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); + assertThat(readResult.getAttribute("a")).isNotNull(); + assertThat(String.valueOf(readResult.getAttribute("a"))).isEqualTo("test1"); + assertThat(readResult.getAttribute("b")).isNotNull(); + assertThat(String.valueOf(readResult.getAttribute("b"))).isEqualTo("test"); + assertThat(readResult.getRevision()).isEqualTo(updateResult.getRev()); + assertThat(readResult.getProperties()).containsKey("c"); + } + + @Test + void updateVertexIfMatch() throws InterruptedException, ExecutionException { + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); + doc.addAttribute("a", "test"); + doc.addAttribute("c", "test"); + final VertexEntity createResult = db.graph(GRAPH_NAME).vertexCollection(COLLECTION_NAME).insertVertex(doc, null) + .get(); + doc.updateAttribute("a", "test1"); + doc.addAttribute("b", "test"); + doc.updateAttribute("c", null); + final VertexUpdateOptions options = new VertexUpdateOptions().ifMatch(createResult.getRev()); + final VertexUpdateEntity updateResult = db.graph(GRAPH_NAME).vertexCollection(COLLECTION_NAME) + .updateVertex(createResult.getKey(), doc, options).get(); + assertThat(updateResult).isNotNull(); + assertThat(updateResult.getId()).isEqualTo(createResult.getId()); + assertThat(updateResult.getRev()).isNotEqualTo(updateResult.getOldRev()); + assertThat(updateResult.getOldRev()).isEqualTo(createResult.getRev()); + + final BaseDocument readResult = db.graph(GRAPH_NAME).vertexCollection(COLLECTION_NAME) + .getVertex(createResult.getKey(), BaseDocument.class, null).get(); + assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); + assertThat(readResult.getAttribute("a")).isNotNull(); + assertThat(String.valueOf(readResult.getAttribute("a"))).isEqualTo("test1"); + assertThat(readResult.getAttribute("b")).isNotNull(); + assertThat(String.valueOf(readResult.getAttribute("b"))).isEqualTo("test"); + assertThat(readResult.getRevision()).isEqualTo(updateResult.getRev()); + assertThat(readResult.getProperties()).containsKey("c"); + } + + @Test + void updateVertexIfMatchFail() throws InterruptedException, ExecutionException { + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); + doc.addAttribute("a", "test"); + doc.addAttribute("c", "test"); + final VertexEntity createResult = db.graph(GRAPH_NAME).vertexCollection(COLLECTION_NAME).insertVertex(doc, null) + .get(); + doc.updateAttribute("a", "test1"); + doc.addAttribute("b", "test"); + doc.updateAttribute("c", null); + try { + final VertexUpdateOptions options = new VertexUpdateOptions().ifMatch("no"); + db.graph(GRAPH_NAME).vertexCollection(COLLECTION_NAME).updateVertex(createResult.getKey(), doc, options) + .get(); + fail(); + } catch (final ExecutionException e) { + assertThat(e.getCause()).isInstanceOf(ArangoDBException.class); + } + } + + @Test + void updateVertexKeepNullTrue() throws InterruptedException, ExecutionException { + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); + doc.addAttribute("a", "test"); + final VertexEntity createResult = db.graph(GRAPH_NAME).vertexCollection(COLLECTION_NAME).insertVertex(doc, null) + .get(); + doc.updateAttribute("a", null); + final VertexUpdateOptions options = new VertexUpdateOptions().keepNull(true); + final VertexUpdateEntity updateResult = db.graph(GRAPH_NAME).vertexCollection(COLLECTION_NAME) + .updateVertex(createResult.getKey(), doc, options).get(); + assertThat(updateResult).isNotNull(); + assertThat(updateResult.getId()).isEqualTo(createResult.getId()); + assertThat(updateResult.getRev()).isNotEqualTo(updateResult.getOldRev()); + assertThat(updateResult.getOldRev()).isEqualTo(createResult.getRev()); + + final BaseDocument readResult = db.graph(GRAPH_NAME).vertexCollection(COLLECTION_NAME) + .getVertex(createResult.getKey(), BaseDocument.class, null).get(); + assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); + assertThat(readResult.getProperties().keySet()).hasSize(4); + assertThat(readResult.getProperties()).containsKey("a"); + } + + @Test + void updateVertexKeepNullFalse() throws InterruptedException, ExecutionException { + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); + doc.addAttribute("a", "test"); + final VertexEntity createResult = db.graph(GRAPH_NAME).vertexCollection(COLLECTION_NAME).insertVertex(doc, null) + .get(); + doc.updateAttribute("a", null); + final VertexUpdateOptions options = new VertexUpdateOptions().keepNull(false); + final VertexUpdateEntity updateResult = db.graph(GRAPH_NAME).vertexCollection(COLLECTION_NAME) + .updateVertex(createResult.getKey(), doc, options).get(); + assertThat(updateResult).isNotNull(); + assertThat(updateResult.getId()).isEqualTo(createResult.getId()); + assertThat(updateResult.getRev()).isNotEqualTo(updateResult.getOldRev()); + assertThat(updateResult.getOldRev()).isEqualTo(createResult.getRev()); + + final BaseDocument readResult = db.graph(GRAPH_NAME).vertexCollection(COLLECTION_NAME) + .getVertex(createResult.getKey(), BaseDocument.class, null).get(); + assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); + assertThat(readResult.getId()).isEqualTo(createResult.getId()); + assertThat(readResult.getRevision()).isNotNull(); + assertThat(readResult.getProperties().keySet()).doesNotContain("a"); + } + + @Test + void deleteVertex() throws InterruptedException, ExecutionException { + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); + final VertexEntity createResult = db.graph(GRAPH_NAME).vertexCollection(COLLECTION_NAME).insertVertex(doc, null) + .get(); + db.graph(GRAPH_NAME).vertexCollection(COLLECTION_NAME).deleteVertex(createResult.getKey(), null).get(); + BaseDocument res = db.graph(GRAPH_NAME).vertexCollection(COLLECTION_NAME) + .getVertex(createResult.getKey(), BaseDocument.class, new GraphDocumentReadOptions()).get(); + assertThat(res).isNull(); + } + + @Test + void deleteVertexIfMatch() throws InterruptedException, ExecutionException { + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); + final VertexEntity createResult = db.graph(GRAPH_NAME).vertexCollection(COLLECTION_NAME).insertVertex(doc, null) + .get(); + final VertexDeleteOptions options = new VertexDeleteOptions().ifMatch(createResult.getRev()); + db.graph(GRAPH_NAME).vertexCollection(COLLECTION_NAME).deleteVertex(createResult.getKey(), options).get(); + BaseDocument res = db.graph(GRAPH_NAME).vertexCollection(COLLECTION_NAME) + .getVertex(createResult.getKey(), BaseDocument.class, new GraphDocumentReadOptions()).get(); + assertThat(res).isNull(); + } + + @Test + void deleteVertexIfMatchFail() throws InterruptedException, ExecutionException { + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); + final VertexEntity createResult = db.graph(GRAPH_NAME).vertexCollection(COLLECTION_NAME).insertVertex(doc, null) + .get(); + final VertexDeleteOptions options = new VertexDeleteOptions().ifMatch("no"); + try { + db.graph(GRAPH_NAME).vertexCollection(COLLECTION_NAME).deleteVertex(createResult.getKey(), options).get(); + fail(); + } catch (final ExecutionException e) { + assertThat(e.getCause()).isInstanceOf(ArangoDBException.class); + } + } +} diff --git a/shaded-integration-tests/src/test/jackson/java/com/arangodb/async/ArangoViewTest.java b/shaded-integration-tests/src/test/jackson/java/com/arangodb/async/ArangoViewTest.java new file mode 100644 index 000000000..8bc81b238 --- /dev/null +++ b/shaded-integration-tests/src/test/jackson/java/com/arangodb/async/ArangoViewTest.java @@ -0,0 +1,86 @@ +/* + * DISCLAIMER + * + * Copyright 2018 ArangoDB GmbH, Cologne, Germany + * + * Licensed 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. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.async; + +import com.arangodb.entity.ViewEntity; +import com.arangodb.entity.ViewType; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; + +import java.util.concurrent.ExecutionException; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assumptions.assumeTrue; + +/** + * @author Mark Vollmary + */ + +class ArangoViewTest extends BaseTest { + + private static final String VIEW_NAME = "view_test"; + + @BeforeAll + static void setup() throws InterruptedException, ExecutionException { + if (!isAtLeastVersion(arangoDB, 3, 4)) + return; + db.createView(VIEW_NAME, ViewType.ARANGO_SEARCH).get(); + } + + @Test + void exists() throws InterruptedException, ExecutionException { + assumeTrue(isAtLeastVersion(3, 4)); + assertThat(db.view(VIEW_NAME).exists().get()).isTrue(); + } + + @Test + void getInfo() throws InterruptedException, ExecutionException { + assumeTrue(isAtLeastVersion(3, 4)); + final ViewEntity info = db.view(VIEW_NAME).getInfo().get(); + assertThat(info).isNotNull(); + assertThat(info.getId()).isNotNull(); + assertThat(info.getName()).isEqualTo(VIEW_NAME); + assertThat(info.getType()).isEqualTo(ViewType.ARANGO_SEARCH); + } + + @Test + void drop() throws InterruptedException, ExecutionException { + assumeTrue(isAtLeastVersion(3, 4)); + final String name = VIEW_NAME + "_droptest"; + db.createView(name, ViewType.ARANGO_SEARCH).get(); + final ArangoViewAsync view = db.view(name); + view.drop().get(); + assertThat(view.exists().get()).isFalse(); + } + + @Test + void rename() throws InterruptedException, ExecutionException { + assumeTrue(isSingleServer()); + assumeTrue(isAtLeastVersion(3, 4)); + final String name = VIEW_NAME + "_renametest"; + final String newName = name + "_new"; + db.createView(name, ViewType.ARANGO_SEARCH).get(); + db.view(name).rename(newName).get(); + assertThat(db.view(name).exists().get()).isFalse(); + assertThat(db.view(newName).exists().get()).isTrue(); + } + +} diff --git a/shaded-integration-tests/src/test/jackson/java/com/arangodb/async/BaseTest.java b/shaded-integration-tests/src/test/jackson/java/com/arangodb/async/BaseTest.java new file mode 100644 index 000000000..729596e3c --- /dev/null +++ b/shaded-integration-tests/src/test/jackson/java/com/arangodb/async/BaseTest.java @@ -0,0 +1,118 @@ +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed 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. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.async; + +import com.arangodb.DbName; +import com.arangodb.entity.ArangoDBEngine; +import com.arangodb.entity.License; +import com.arangodb.entity.ServerRole; +import com.arangodb.internal.config.FileConfigPropertiesProvider; +import com.arangodb.util.TestUtils; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; + +import java.util.UUID; +import java.util.concurrent.ExecutionException; + + +/** + * @author Mark Vollmary + */ +public abstract class BaseTest { + + static final DbName TEST_DB = DbName.of("java_driver_test_db"); + static ArangoDBAsync arangoDB; + static ArangoDatabaseAsync db; + + @BeforeAll + static void init() throws InterruptedException, ExecutionException { + if (arangoDB == null) { + arangoDB = new ArangoDBAsync.Builder() + .loadProperties(new FileConfigPropertiesProvider()) + .build(); + } + + if (arangoDB.db(TEST_DB).exists().get()) { + arangoDB.db(TEST_DB).drop().get(); + } + + arangoDB.createDatabase(TEST_DB).get(); + BaseTest.db = arangoDB.db(TEST_DB); + } + + @AfterAll + static void shutdown() throws InterruptedException, ExecutionException { + arangoDB.db(TEST_DB).drop().get(); + arangoDB.shutdown(); + 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 TestUtils.isAtLeastVersion(arangoDB.getVersion().get().getVersion(), major, minor, + patch); + } + + protected static boolean isAtLeastVersion(final ArangoDBAsync arangoDB, final int major, final int minor) + throws InterruptedException, ExecutionException { + return isAtLeastVersion(arangoDB, major, minor, 0); + } + + protected boolean isAtLeastVersion(final int major, final int minor, final int patch) throws InterruptedException + , ExecutionException { + return isAtLeastVersion(arangoDB, major, minor, patch); + } + + protected boolean isAtLeastVersion(final int major, final int minor) throws InterruptedException, + ExecutionException { + return isAtLeastVersion(major, minor, 0); + } + + boolean isLessThanVersion(final int major, final int minor) throws ExecutionException, InterruptedException { + return isLessThanVersion(major, minor, 0); + } + + boolean isLessThanVersion(final int major, final int minor, final int patch) throws ExecutionException, InterruptedException { + return TestUtils.isLessThanVersion(db.getVersion().get().getVersion(), major, minor, patch); + } + + boolean isStorageEngine(ArangoDBEngine.StorageEngineName name) throws ExecutionException, InterruptedException { + return name.equals(db.getEngine().get().getName()); + } + + boolean isSingleServer() throws ExecutionException, InterruptedException { + return (arangoDB.getRole().get() == ServerRole.SINGLE); + } + + boolean isCluster() throws ExecutionException, InterruptedException { + return arangoDB.getRole().get() == ServerRole.COORDINATOR; + } + + boolean isEnterprise() throws ExecutionException, InterruptedException { + return arangoDB.getVersion().get().getLicense() == License.ENTERPRISE; + } + +} diff --git a/shaded-integration-tests/src/test/jackson/java/com/arangodb/async/CommunicationTest.java b/shaded-integration-tests/src/test/jackson/java/com/arangodb/async/CommunicationTest.java new file mode 100644 index 000000000..0b2b6c962 --- /dev/null +++ b/shaded-integration-tests/src/test/jackson/java/com/arangodb/async/CommunicationTest.java @@ -0,0 +1,46 @@ +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed 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. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.async; + +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; + +import java.util.concurrent.CompletableFuture; + +import static org.assertj.core.api.Assertions.assertThat; + + +/** + * @author Mark Vollmary + */ +class CommunicationTest { + + @Test + @Disabled + void disconnect() { + final ArangoDBAsync arangoDB = new ArangoDBAsync.Builder().build(); + final CompletableFuture> result = arangoDB.db().query("return sleep(1)", null, null, + null); + arangoDB.shutdown(); + assertThat(result.isCompletedExceptionally()).isEqualTo(true); + } + +} diff --git a/shaded-integration-tests/src/test/jackson/java/com/arangodb/async/ConcurrencyTest.java b/shaded-integration-tests/src/test/jackson/java/com/arangodb/async/ConcurrencyTest.java new file mode 100644 index 000000000..f0643c2ca --- /dev/null +++ b/shaded-integration-tests/src/test/jackson/java/com/arangodb/async/ConcurrencyTest.java @@ -0,0 +1,94 @@ +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed 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. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.async; + + +import com.arangodb.async.internal.ArangoExecutorAsync; +import com.arangodb.entity.ArangoDBVersion; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.Timeout; + +import java.util.List; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutionException; +import java.util.stream.Collectors; +import java.util.stream.IntStream; + +import static org.junit.jupiter.api.Assertions.fail; + + +/** + * @author Michele Rastelli + */ +class ConcurrencyTest { + + private ArangoDBAsync arangoDB; + + @BeforeEach + void initialize() { + arangoDB = new ArangoDBAsync.Builder().build(); + } + + /** + * FIXME: make the user executor configurable in com.arangodb.internal.ArangoExecutorAsync::execute + * (eg. this test passes using a CachedThreadPool) + */ + @Disabled + @Test + @Timeout(2) + void executorLimit() { + List> futures = IntStream.range(0, 20) + .mapToObj(i -> arangoDB.getVersion() + .whenComplete((dbVersion, ex) -> { + System.out.println(Thread.currentThread().getName()); + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + })) + .collect(Collectors.toList()); + + futures.forEach(future -> { + try { + future.get(); + } catch (InterruptedException | ExecutionException e) { + e.printStackTrace(); + fail(); + } + }); + } + + + /** + * outgoing requests should be queued in the {@link ArangoExecutorAsync} outgoingExecutor + */ + @Disabled + @Test + @Timeout(1) + void outgoingRequestsParallelismTest() { + for (int i = 0; i < 50_000; i++) { + arangoDB.getVersion(); + } + } +} diff --git a/shaded-integration-tests/src/test/jackson/java/com/arangodb/async/ConcurrencyTests.java b/shaded-integration-tests/src/test/jackson/java/com/arangodb/async/ConcurrencyTests.java new file mode 100644 index 000000000..504c550a7 --- /dev/null +++ b/shaded-integration-tests/src/test/jackson/java/com/arangodb/async/ConcurrencyTests.java @@ -0,0 +1,29 @@ +package com.arangodb.async; + + +import com.arangodb.internal.config.FileConfigPropertiesProvider; +import org.junit.jupiter.api.Test; + +import java.util.List; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutionException; +import java.util.stream.Collectors; +import java.util.stream.IntStream; + +class ConcurrencyTests { + + @Test + void concurrentPendingRequests() throws ExecutionException, InterruptedException { + ArangoDBAsync adb = new ArangoDBAsync.Builder() + .loadProperties(new FileConfigPropertiesProvider()) + .build(); + List>> reqs = IntStream.range(0, 10) + .mapToObj(__ -> adb.db().query("RETURN SLEEP(1)", Void.class)) + .collect(Collectors.toList()); + for (CompletableFuture> req : reqs) { + req.get(); + } + adb.shutdown(); + } + +} diff --git a/shaded-integration-tests/src/test/jackson/java/com/arangodb/async/InvertedIndexTest.java b/shaded-integration-tests/src/test/jackson/java/com/arangodb/async/InvertedIndexTest.java new file mode 100644 index 000000000..8ee509526 --- /dev/null +++ b/shaded-integration-tests/src/test/jackson/java/com/arangodb/async/InvertedIndexTest.java @@ -0,0 +1,199 @@ +package com.arangodb.async; + +import com.arangodb.entity.*; +import com.arangodb.entity.arangosearch.*; +import com.arangodb.entity.arangosearch.analyzer.DelimiterAnalyzer; +import com.arangodb.entity.arangosearch.analyzer.DelimiterAnalyzerProperties; +import com.arangodb.model.InvertedIndexOptions; +import com.arangodb.model.PersistentIndexOptions; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; + +import java.util.*; +import java.util.concurrent.ExecutionException; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assumptions.assumeTrue; + +public class InvertedIndexTest extends BaseTest { + + private static final String COLLECTION_NAME = "InvertedIndexTestAsync_collection"; + + InvertedIndexTest() throws ExecutionException, InterruptedException { + ArangoCollectionAsync collection = db.collection(COLLECTION_NAME); + if (!collection.exists().get()) { + collection.create().get(); + } + } + + @BeforeAll + static void setup() throws InterruptedException, ExecutionException { + db.createCollection(COLLECTION_NAME, null).get(); + } + + @AfterEach + void teardown() throws InterruptedException, ExecutionException { + db.collection(COLLECTION_NAME).drop().get(); + } + + + private void createAnalyzer(String analyzerName, ArangoDatabaseAsync db) throws ExecutionException, InterruptedException { + Set features = new HashSet<>(); + features.add(AnalyzerFeature.frequency); + features.add(AnalyzerFeature.norm); + features.add(AnalyzerFeature.position); + + DelimiterAnalyzer da = new DelimiterAnalyzer(); + da.setName(analyzerName); + da.setFeatures(features); + DelimiterAnalyzerProperties props = new DelimiterAnalyzerProperties(); + props.setDelimiter("-"); + da.setProperties(props); + + db.createSearchAnalyzer(da).get(); + } + + private InvertedIndexOptions createOptions(String analyzerName) throws ExecutionException, InterruptedException { + InvertedIndexField field = new InvertedIndexField() + .name("foo") + .analyzer(AnalyzerType.identity.toString()) + .includeAllFields(true) + .searchField(false) + .trackListPositions(false) + .features( + AnalyzerFeature.position, + AnalyzerFeature.frequency, + AnalyzerFeature.norm, + AnalyzerFeature.offset + ); + + if (isEnterprise()) { + field.nested( + new InvertedIndexField() + .name("bar") + .analyzer(analyzerName) + .searchField(true) + .features(AnalyzerFeature.position, AnalyzerFeature.frequency) + .nested( + new InvertedIndexField() + .name("baz") + .analyzer(AnalyzerType.identity.toString()) + .searchField(false) + .features(AnalyzerFeature.frequency) + ) + ); + } + + return new InvertedIndexOptions() + .name("invertedIndex-" + UUID.randomUUID()) + .inBackground(true) + .parallelism(5) + .primarySort(new InvertedIndexPrimarySort() + .fields( + new InvertedIndexPrimarySort.Field("f1", InvertedIndexPrimarySort.Field.Direction.asc), + new InvertedIndexPrimarySort.Field("f2", InvertedIndexPrimarySort.Field.Direction.desc) + ) + .compression(ArangoSearchCompression.lz4) + ) + .storedValues(new StoredValue(Arrays.asList("f3", "f4"), ArangoSearchCompression.none)) + .analyzer(analyzerName) + .features(AnalyzerFeature.position, AnalyzerFeature.frequency) + .includeAllFields(false) + .trackListPositions(true) + .searchField(true) + .fields(field) + .consolidationIntervalMsec(11L) + .commitIntervalMsec(22L) + .cleanupIntervalStep(33L) + .consolidationPolicy(ConsolidationPolicy.of(ConsolidationType.BYTES_ACCUM).threshold(1.)) + .writebufferIdle(44L) + .writebufferActive(55L) + .writebufferSizeMax(66L); + } + + private void assertCorrectIndexEntity(InvertedIndexEntity indexResult, InvertedIndexOptions options) { + assertThat(indexResult).isNotNull(); + assertThat(indexResult.getId()).isNotNull().isNotEmpty(); + // FIXME: in single server this is null + // assertThat(indexResult.getIsNewlyCreated()).isTrue(); + assertThat(indexResult.getUnique()).isFalse(); + assertThat(indexResult.getSparse()).isTrue(); + assertThat(indexResult.getVersion()).isNotNull(); + assertThat(indexResult.getCode()).isNotNull(); + assertThat(indexResult.getType()).isEqualTo(IndexType.inverted); + assertThat(indexResult.getName()).isEqualTo(options.getName()); + assertThat(indexResult.getFields()).containsExactlyElementsOf(options.getFields()); + assertThat(indexResult.getSearchField()).isEqualTo(options.getSearchField()); + assertThat(indexResult.getStoredValues()).containsExactlyElementsOf(options.getStoredValues()); + assertThat(indexResult.getPrimarySort()).isEqualTo(options.getPrimarySort()); + assertThat(indexResult.getAnalyzer()).isEqualTo(options.getAnalyzer()); + assertThat(indexResult.getFeatures()).hasSameElementsAs(options.getFeatures()); + assertThat(indexResult.getIncludeAllFields()).isEqualTo(options.getIncludeAllFields()); + assertThat(indexResult.getTrackListPositions()).isEqualTo(options.getTrackListPositions()); + assertThat(indexResult.getCleanupIntervalStep()).isEqualTo(options.getCleanupIntervalStep()); + assertThat(indexResult.getCommitIntervalMsec()).isEqualTo(options.getCommitIntervalMsec()); + assertThat(indexResult.getConsolidationIntervalMsec()).isEqualTo(options.getConsolidationIntervalMsec()); + assertThat(indexResult.getConsolidationPolicy()).isEqualTo(options.getConsolidationPolicy()); + assertThat(indexResult.getWritebufferIdle()).isEqualTo(options.getWritebufferIdle()); + assertThat(indexResult.getWritebufferActive()).isEqualTo(options.getWritebufferActive()); + assertThat(indexResult.getWritebufferSizeMax()).isEqualTo(options.getWritebufferSizeMax()); + } + + @Test + void createAndGetInvertedIndex() throws ExecutionException, InterruptedException { + assumeTrue(isAtLeastVersion(3, 10)); + + ArangoCollectionAsync collection = db.collection(COLLECTION_NAME); + String analyzerName = "delimiter-" + UUID.randomUUID(); + createAnalyzer(analyzerName, collection.db()); + InvertedIndexOptions options = createOptions(analyzerName); + InvertedIndexEntity created = collection.ensureInvertedIndex(options).get(); + assertCorrectIndexEntity(created, options); + InvertedIndexEntity loadedIndex = collection.getInvertedIndex(created.getName()).get(); + assertCorrectIndexEntity(loadedIndex, options); + } + + @Test + void getInvertedIndexesShouldNotReturnOtherIndexTypes() throws ExecutionException, InterruptedException { + assumeTrue(isAtLeastVersion(3, 10)); + + ArangoCollectionAsync collection = db.collection(COLLECTION_NAME); + + // create persistent index + collection.ensurePersistentIndex(Collections.singletonList("foo"), new PersistentIndexOptions().name("persistentIndex")); + + // create inverted index + String analyzerName = "delimiter-" + UUID.randomUUID(); + createAnalyzer(analyzerName, collection.db()); + InvertedIndexOptions options = createOptions(analyzerName); + InvertedIndexEntity created = collection.ensureInvertedIndex(options).get(); + + Collection loadedIndexes = collection.getInvertedIndexes().get(); + assertThat(loadedIndexes).map(InvertedIndexEntity::getName) + .doesNotContain("persistentIndex") + .contains(created.getName()); + } + + @Test + void getIndexesShouldNotReturnInvertedIndexes() throws ExecutionException, InterruptedException { + assumeTrue(isAtLeastVersion(3, 10)); + + ArangoCollectionAsync collection = db.collection(COLLECTION_NAME); + + // create persistent index + collection.ensurePersistentIndex(Collections.singletonList("foo"), new PersistentIndexOptions().name("persistentIndex")); + + // create inverted index + String analyzerName = "delimiter-" + UUID.randomUUID(); + createAnalyzer(analyzerName, collection.db()); + InvertedIndexOptions options = createOptions(analyzerName); + InvertedIndexEntity created = collection.ensureInvertedIndex(options).get(); + + Collection loadedIndexes = collection.getIndexes().get(); + assertThat(loadedIndexes).map(IndexEntity::getName) + .doesNotContain(created.getName()) + .contains("persistentIndex"); + } + +} diff --git a/shaded-integration-tests/src/test/jackson/java/com/arangodb/async/JwtAuthTest.java b/shaded-integration-tests/src/test/jackson/java/com/arangodb/async/JwtAuthTest.java new file mode 100644 index 000000000..f821f3ea9 --- /dev/null +++ b/shaded-integration-tests/src/test/jackson/java/com/arangodb/async/JwtAuthTest.java @@ -0,0 +1,103 @@ +package com.arangodb.async; + +import com.arangodb.*; +import com.arangodb.internal.config.FileConfigPropertiesProvider; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; + +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.ExecutionException; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.fail; + +class JwtAuthTest { + + private static String jwt; + private ArangoDBAsync arangoDB; + + @BeforeAll + static void init() { + ArangoDB arangoDB = new ArangoDB.Builder() + .loadProperties(new FileConfigPropertiesProvider()) + .build(); + jwt = getJwt(arangoDB); + arangoDB.shutdown(); + } + + private static String getJwt(ArangoDB arangoDB) { + Map reqBody = new HashMap<>(); + reqBody.put("username", "root"); + reqBody.put("password", "test"); + + Request req = Request.builder() + .db(DbName.SYSTEM) + .method(Request.Method.POST) + .path("/_open/auth") + .body(reqBody) + .build(); + + Response resp = arangoDB.execute(req, Map.class); + return (String) resp.getBody().get("jwt"); + } + + @AfterEach + void after() { + if (arangoDB != null) + arangoDB.shutdown(); + } + + @Test + void notAuthenticated() throws InterruptedException { + arangoDB = getBuilder().build(); + try { + arangoDB.getVersion().get(); + fail(); + } catch (ExecutionException e) { + assertThat(e.getCause()).isInstanceOf(ArangoDBException.class); + assertThat(((ArangoDBException) e.getCause()).getResponseCode()).isEqualTo(401); + } + arangoDB.shutdown(); + } + + @Test + void authenticated() throws ExecutionException, InterruptedException { + arangoDB = getBuilder() + .jwt(jwt) + .build(); + arangoDB.getVersion().get(); + arangoDB.shutdown(); + } + + @Test + @Disabled("DE-423") + void updateJwt() throws ExecutionException, InterruptedException { + arangoDB = getBuilder() + .jwt(jwt) + .build(); + arangoDB.getVersion().get(); + arangoDB.updateJwt("bla"); + try { + arangoDB.getVersion().get(); + fail(); + } catch (ExecutionException e) { + assertThat(e.getCause()).isInstanceOf(ArangoDBException.class); + assertThat(((ArangoDBException) e.getCause()).getResponseCode()).isEqualTo(401); + } + + arangoDB.updateJwt(jwt); + arangoDB.getVersion().get(); + arangoDB.shutdown(); + } + + private ArangoDBAsync.Builder getBuilder() { + return new ArangoDBAsync.Builder() + .loadProperties(new FileConfigPropertiesProvider()) + .jwt(null) // unset credentials from properties file + .user(null) // unset credentials from properties file + .password(null); // unset credentials from properties file + } +} diff --git a/shaded-integration-tests/src/test/jackson/java/com/arangodb/async/StreamTransactionConflictsTest.java b/shaded-integration-tests/src/test/jackson/java/com/arangodb/async/StreamTransactionConflictsTest.java new file mode 100644 index 000000000..659781ae2 --- /dev/null +++ b/shaded-integration-tests/src/test/jackson/java/com/arangodb/async/StreamTransactionConflictsTest.java @@ -0,0 +1,120 @@ +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed 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. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.async; + +import com.arangodb.ArangoDBException; +import com.arangodb.entity.ArangoDBEngine; +import com.arangodb.entity.BaseDocument; +import com.arangodb.entity.StreamTransactionEntity; +import com.arangodb.model.DocumentCreateOptions; +import com.arangodb.model.StreamTransactionOptions; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Test; + +import java.util.UUID; +import java.util.concurrent.ExecutionException; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.fail; +import static org.junit.jupiter.api.Assumptions.assumeTrue; + +/** + * @author Michele Rastelli + */ +class StreamTransactionConflictsTest extends BaseTest { + + private static final String COLLECTION_NAME = "db_concurrent_stream_transactions_test"; + + public StreamTransactionConflictsTest() throws ExecutionException, InterruptedException { + if (db.collection(COLLECTION_NAME).exists().get()) + db.collection(COLLECTION_NAME).drop().get(); + + db.createCollection(COLLECTION_NAME, null).get(); + } + + @AfterEach + void teardown() throws ExecutionException, InterruptedException { + if (db.collection(COLLECTION_NAME).exists().get()) + db.collection(COLLECTION_NAME).drop().get(); + } + + @Test + void conflictOnInsertDocumentWithNotYetCommittedTx() throws ExecutionException, InterruptedException { + assumeTrue(isAtLeastVersion(3, 5)); + assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); + + StreamTransactionEntity tx1 = db.beginStreamTransaction( + new StreamTransactionOptions().readCollections(COLLECTION_NAME).writeCollections(COLLECTION_NAME)).get(); + + StreamTransactionEntity tx2 = db.beginStreamTransaction( + new StreamTransactionOptions().readCollections(COLLECTION_NAME).writeCollections(COLLECTION_NAME)).get(); + + String key = UUID.randomUUID().toString(); + + // insert a document from within tx1 + db.collection(COLLECTION_NAME) + .insertDocument(new BaseDocument(key), new DocumentCreateOptions().streamTransactionId(tx1.getId())).get(); + + try { + // insert conflicting document from within tx2 + db.collection(COLLECTION_NAME).insertDocument(new BaseDocument(key), + new DocumentCreateOptions().streamTransactionId(tx2.getId())).get(); + fail(); + } catch (ExecutionException e) { + assertThat(e.getCause()).isInstanceOf(ArangoDBException.class); + } + + db.abortStreamTransaction(tx1.getId()).get(); + db.abortStreamTransaction(tx2.getId()).get(); + } + + @Test + void conflictOnInsertDocumentWithAlreadyCommittedTx() throws ExecutionException, InterruptedException { + assumeTrue(isAtLeastVersion(3, 5)); + assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); + + StreamTransactionEntity tx1 = db.beginStreamTransaction( + new StreamTransactionOptions().readCollections(COLLECTION_NAME).writeCollections(COLLECTION_NAME)).get(); + + StreamTransactionEntity tx2 = db.beginStreamTransaction( + new StreamTransactionOptions().readCollections(COLLECTION_NAME).writeCollections(COLLECTION_NAME)).get(); + + String key = UUID.randomUUID().toString(); + + // insert a document from within tx1 + db.collection(COLLECTION_NAME) + .insertDocument(new BaseDocument(key), new DocumentCreateOptions().streamTransactionId(tx1.getId())).get(); + + // commit tx1 + db.commitStreamTransaction(tx1.getId()).get(); + + try { + // insert conflicting document from within tx2 + db.collection(COLLECTION_NAME).insertDocument(new BaseDocument(key), + new DocumentCreateOptions().streamTransactionId(tx2.getId())).get(); + fail(); + } catch (ExecutionException e) { + assertThat(e.getCause()).isInstanceOf(ArangoDBException.class); + } + + db.abortStreamTransaction(tx2.getId()).get(); + } +} diff --git a/shaded-integration-tests/src/test/jackson/java/com/arangodb/async/StreamTransactionGraphTest.java b/shaded-integration-tests/src/test/jackson/java/com/arangodb/async/StreamTransactionGraphTest.java new file mode 100644 index 000000000..60ee6ea11 --- /dev/null +++ b/shaded-integration-tests/src/test/jackson/java/com/arangodb/async/StreamTransactionGraphTest.java @@ -0,0 +1,398 @@ +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed 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. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.async; + + +import com.arangodb.entity.*; +import com.arangodb.model.*; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Test; + +import java.util.Collections; +import java.util.UUID; +import java.util.concurrent.ExecutionException; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assumptions.assumeTrue; + + +/** + * @author Michele Rastelli + */ +class StreamTransactionGraphTest extends BaseTest { + + private static final String GRAPH_NAME = "graph_stream_transaction_graph_test"; + private static final String EDGE_COLLECTION = "edge_collection_stream_transaction_graph_test"; + private static final String VERTEX_COLLECTION_1 = "vertex_collection_1_stream_transaction_graph_test"; + private static final String VERTEX_COLLECTION_2 = "vertex_collection_2_stream_transaction_graph_test"; + + private final ArangoGraphAsync graph; + private final ArangoVertexCollectionAsync vertexCollection1; + private final ArangoVertexCollectionAsync vertexCollection2; + private final ArangoEdgeCollectionAsync edgeCollection; + + public StreamTransactionGraphTest() throws ExecutionException, InterruptedException { + + graph = db.graph(GRAPH_NAME); + + if (graph.exists().get()) + graph.drop().get(); + + graph.create(Collections.singletonList(new EdgeDefinition().collection(EDGE_COLLECTION).from(VERTEX_COLLECTION_1).to(VERTEX_COLLECTION_2))).get(); + + vertexCollection1 = graph.vertexCollection(VERTEX_COLLECTION_1); + vertexCollection2 = graph.vertexCollection(VERTEX_COLLECTION_2); + edgeCollection = graph.edgeCollection(EDGE_COLLECTION); + } + + @AfterEach + void teardown() throws ExecutionException, InterruptedException { + if (graph.exists().get()) + graph.drop().get(); + if (db.collection(EDGE_COLLECTION).exists().get()) + db.collection(EDGE_COLLECTION).drop().get(); + if (db.collection(VERTEX_COLLECTION_1).exists().get()) + db.collection(VERTEX_COLLECTION_1).drop().get(); + if (db.collection(VERTEX_COLLECTION_2).exists().get()) + db.collection(VERTEX_COLLECTION_2).drop().get(); + } + + private BaseEdgeDocument createEdgeValue(String streamTransactionId) throws ExecutionException, + InterruptedException { + final VertexEntity v1 = vertexCollection1.insertVertex(new BaseDocument(), + new VertexCreateOptions().streamTransactionId(streamTransactionId)).get(); + final VertexEntity v2 = vertexCollection2.insertVertex(new BaseDocument(), + new VertexCreateOptions().streamTransactionId(streamTransactionId)).get(); + final BaseEdgeDocument value = new BaseEdgeDocument(); + value.setFrom(v1.getId()); + value.setTo(v2.getId()); + return value; + } + + @Test + void getVertex() throws ExecutionException, InterruptedException { + assumeTrue(isSingleServer()); + assumeTrue(isAtLeastVersion(3, 5)); + assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); + + StreamTransactionEntity tx = db + .beginStreamTransaction(new StreamTransactionOptions() + .readCollections(VERTEX_COLLECTION_1, VERTEX_COLLECTION_2, EDGE_COLLECTION) + .writeCollections(VERTEX_COLLECTION_1, VERTEX_COLLECTION_2, EDGE_COLLECTION)).get(); + + // insert a vertex from outside the tx + VertexEntity createdVertex = vertexCollection1.insertVertex(new BaseDocument()).get(); + + // assert that the vertex is not found from within the tx + assertThat(vertexCollection1.getVertex(createdVertex.getKey(), BaseDocument.class, + new GraphDocumentReadOptions().streamTransactionId(tx.getId())).get()).isNull(); + + db.abortStreamTransaction(tx.getId()).get(); + } + + + @Test + void createVertex() throws ExecutionException, InterruptedException { + assumeTrue(isSingleServer()); + assumeTrue(isAtLeastVersion(3, 5)); + assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); + + StreamTransactionEntity tx = db.beginStreamTransaction( + new StreamTransactionOptions() + .readCollections(VERTEX_COLLECTION_1, VERTEX_COLLECTION_2, EDGE_COLLECTION) + .writeCollections(VERTEX_COLLECTION_1, VERTEX_COLLECTION_2, EDGE_COLLECTION)).get(); + + // insert a vertex from within the tx + VertexEntity createdVertex = vertexCollection1.insertVertex(new BaseDocument(), + new VertexCreateOptions().streamTransactionId(tx.getId())).get(); + + // assert that the vertex is not found from outside the tx + assertThat(vertexCollection1.getVertex(createdVertex.getKey(), BaseDocument.class, null).get()).isNull(); + + // assert that the vertex is found from within the tx + assertThat(vertexCollection1.getVertex(createdVertex.getKey(), BaseDocument.class, + new GraphDocumentReadOptions().streamTransactionId(tx.getId())).get()).isNotNull(); + + db.commitStreamTransaction(tx.getId()).get(); + + // assert that the vertex is found after commit + assertThat(vertexCollection1.getVertex(createdVertex.getKey(), BaseDocument.class, null).get()).isNotNull(); + } + + @Test + void replaceVertex() throws ExecutionException, InterruptedException { + assumeTrue(isSingleServer()); + assumeTrue(isAtLeastVersion(3, 5)); + assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); + + BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); + doc.addAttribute("test", "foo"); + + VertexEntity createdVertex = vertexCollection1.insertVertex(doc, null).get(); + + StreamTransactionEntity tx = db.beginStreamTransaction( + new StreamTransactionOptions() + .readCollections(VERTEX_COLLECTION_1, VERTEX_COLLECTION_2, EDGE_COLLECTION) + .writeCollections(VERTEX_COLLECTION_1, VERTEX_COLLECTION_2, EDGE_COLLECTION)).get(); + + // replace vertex from within the tx + doc.updateAttribute("test", "bar"); + vertexCollection1.replaceVertex(createdVertex.getKey(), doc, + new VertexReplaceOptions().streamTransactionId(tx.getId())).get(); + + // assert that the vertex has not been replaced from outside the tx + assertThat(vertexCollection1.getVertex(createdVertex.getKey(), BaseDocument.class, null).get() + .getProperties()).containsEntry("test", "foo"); + + // assert that the vertex has been replaced from within the tx + assertThat(vertexCollection1.getVertex(createdVertex.getKey(), BaseDocument.class, + new GraphDocumentReadOptions().streamTransactionId(tx.getId())).get().getProperties()).containsEntry( + "test", "bar"); + + db.commitStreamTransaction(tx.getId()).get(); + + // assert that the vertex has been replaced after commit + assertThat(vertexCollection1.getVertex(createdVertex.getKey(), BaseDocument.class, null).get() + .getProperties()).containsEntry("test", "bar"); + } + + @Test + void updateVertex() throws ExecutionException, InterruptedException { + assumeTrue(isSingleServer()); + assumeTrue(isAtLeastVersion(3, 5)); + assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); + + BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); + doc.addAttribute("test", "foo"); + + VertexEntity createdDoc = vertexCollection1.insertVertex(doc, null).get(); + + StreamTransactionEntity tx = db.beginStreamTransaction( + new StreamTransactionOptions() + .readCollections(VERTEX_COLLECTION_1, VERTEX_COLLECTION_2, EDGE_COLLECTION) + .writeCollections(VERTEX_COLLECTION_1, VERTEX_COLLECTION_2, EDGE_COLLECTION)).get(); + + // update vertex from within the tx + doc.updateAttribute("test", "bar"); + vertexCollection1.updateVertex(createdDoc.getKey(), doc, + new VertexUpdateOptions().streamTransactionId(tx.getId())).get(); + + // assert that the vertex has not been updated from outside the tx + assertThat(vertexCollection1.getVertex(createdDoc.getKey(), BaseDocument.class, null).get() + .getProperties()).containsEntry("test", "foo"); + + // assert that the vertex has been updated from within the tx + assertThat(vertexCollection1.getVertex(createdDoc.getKey(), BaseDocument.class, + new GraphDocumentReadOptions().streamTransactionId(tx.getId())).get().getProperties()).containsEntry( + "test", "bar"); + + db.commitStreamTransaction(tx.getId()).get(); + + // assert that the vertex has been updated after commit + assertThat(vertexCollection1.getVertex(createdDoc.getKey(), BaseDocument.class, null).get() + .getProperties()).containsEntry("test", "bar"); + } + + @Test + void deleteVertex() throws ExecutionException, InterruptedException { + assumeTrue(isSingleServer()); + assumeTrue(isAtLeastVersion(3, 5)); + assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); + + VertexEntity createdDoc = vertexCollection1.insertVertex(new BaseDocument(), null).get(); + + StreamTransactionEntity tx = db.beginStreamTransaction( + new StreamTransactionOptions() + .readCollections(VERTEX_COLLECTION_1, VERTEX_COLLECTION_2, EDGE_COLLECTION) + .writeCollections(VERTEX_COLLECTION_1, VERTEX_COLLECTION_2, EDGE_COLLECTION)).get(); + + // delete vertex from within the tx + vertexCollection1.deleteVertex(createdDoc.getKey(), + new VertexDeleteOptions().streamTransactionId(tx.getId())).get(); + + // assert that the vertex has not been deleted from outside the tx + assertThat(vertexCollection1.getVertex(createdDoc.getKey(), BaseDocument.class, null).get()).isNotNull(); + + // assert that the vertex has been deleted from within the tx + assertThat(vertexCollection1.getVertex(createdDoc.getKey(), BaseDocument.class, + new GraphDocumentReadOptions().streamTransactionId(tx.getId())).get()).isNull(); + + db.commitStreamTransaction(tx.getId()).get(); + + // assert that the vertex has been deleted after commit + assertThat(vertexCollection1.getVertex(createdDoc.getKey(), BaseDocument.class, null).get()).isNull(); + } + + + @Test + void getEdge() throws ExecutionException, InterruptedException { + assumeTrue(isSingleServer()); + assumeTrue(isAtLeastVersion(3, 5)); + assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); + + StreamTransactionEntity tx = db + .beginStreamTransaction(new StreamTransactionOptions() + .readCollections(VERTEX_COLLECTION_1, VERTEX_COLLECTION_2, EDGE_COLLECTION) + .writeCollections(VERTEX_COLLECTION_1, VERTEX_COLLECTION_2, EDGE_COLLECTION)).get(); + + // insert an edge from outside the tx + EdgeEntity createdEdge = edgeCollection.insertEdge(createEdgeValue(null)).get(); + + // assert that the edge is not found from within the tx + assertThat(edgeCollection.getEdge(createdEdge.getKey(), BaseEdgeDocument.class, + new GraphDocumentReadOptions().streamTransactionId(tx.getId())).get()).isNull(); + + db.abortStreamTransaction(tx.getId()).get(); + } + + + @Test + void createEdge() throws ExecutionException, InterruptedException { + assumeTrue(isSingleServer()); + assumeTrue(isAtLeastVersion(3, 5)); + assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); + + StreamTransactionEntity tx = db.beginStreamTransaction( + new StreamTransactionOptions() + .readCollections(VERTEX_COLLECTION_1, VERTEX_COLLECTION_2, EDGE_COLLECTION) + .writeCollections(VERTEX_COLLECTION_1, VERTEX_COLLECTION_2, EDGE_COLLECTION)).get(); + + // insert an edge from within the tx + EdgeEntity createdEdge = edgeCollection.insertEdge(createEdgeValue(tx.getId()), + new EdgeCreateOptions().streamTransactionId(tx.getId())).get(); + + // assert that the edge is not found from outside the tx + assertThat(edgeCollection.getEdge(createdEdge.getKey(), BaseEdgeDocument.class, null).get()).isNull(); + + // assert that the edge is found from within the tx + assertThat(edgeCollection.getEdge(createdEdge.getKey(), BaseEdgeDocument.class, + new GraphDocumentReadOptions().streamTransactionId(tx.getId())).get()).isNotNull(); + + db.commitStreamTransaction(tx.getId()).get(); + + // assert that the edge is found after commit + assertThat(edgeCollection.getEdge(createdEdge.getKey(), BaseEdgeDocument.class, null).get()).isNotNull(); + } + + @Test + void replaceEdge() throws ExecutionException, InterruptedException { + assumeTrue(isSingleServer()); + assumeTrue(isAtLeastVersion(3, 5)); + assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); + + BaseEdgeDocument doc = createEdgeValue(null); + doc.addAttribute("test", "foo"); + + EdgeEntity createdEdge = edgeCollection.insertEdge(doc, null).get(); + + StreamTransactionEntity tx = db.beginStreamTransaction( + new StreamTransactionOptions() + .readCollections(VERTEX_COLLECTION_1, VERTEX_COLLECTION_2, EDGE_COLLECTION) + .writeCollections(VERTEX_COLLECTION_1, VERTEX_COLLECTION_2, EDGE_COLLECTION)).get(); + + // replace edge from within the tx + doc.updateAttribute("test", "bar"); + edgeCollection.replaceEdge(createdEdge.getKey(), doc, + new EdgeReplaceOptions().streamTransactionId(tx.getId())).get(); + + // assert that the edge has not been replaced from outside the tx + assertThat(edgeCollection.getEdge(createdEdge.getKey(), BaseEdgeDocument.class, null).get() + .getProperties()).containsEntry("test", "foo"); + + // assert that the edge has been replaced from within the tx + assertThat(edgeCollection.getEdge(createdEdge.getKey(), BaseEdgeDocument.class, + new GraphDocumentReadOptions().streamTransactionId(tx.getId())).get().getProperties()).containsEntry( + "test", "bar"); + + db.commitStreamTransaction(tx.getId()).get(); + + // assert that the edge has been replaced after commit + assertThat(edgeCollection.getEdge(createdEdge.getKey(), BaseEdgeDocument.class, null).get() + .getProperties()).containsEntry("test", "bar"); + } + + @Test + void updateEdge() throws ExecutionException, InterruptedException { + assumeTrue(isSingleServer()); + assumeTrue(isAtLeastVersion(3, 5)); + assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); + + BaseEdgeDocument doc = createEdgeValue(null); + doc.addAttribute("test", "foo"); + + EdgeEntity createdDoc = edgeCollection.insertEdge(doc, null).get(); + + StreamTransactionEntity tx = db.beginStreamTransaction( + new StreamTransactionOptions() + .readCollections(VERTEX_COLLECTION_1, VERTEX_COLLECTION_2, EDGE_COLLECTION) + .writeCollections(VERTEX_COLLECTION_1, VERTEX_COLLECTION_2, EDGE_COLLECTION)).get(); + + // update edge from within the tx + doc.updateAttribute("test", "bar"); + edgeCollection.updateEdge(createdDoc.getKey(), doc, new EdgeUpdateOptions().streamTransactionId(tx.getId())) + .get(); + + // assert that the edge has not been updated from outside the tx + assertThat(edgeCollection.getEdge(createdDoc.getKey(), BaseEdgeDocument.class, null).get() + .getProperties()).containsEntry("test", "foo"); + + // assert that the edge has been updated from within the tx + assertThat(edgeCollection.getEdge(createdDoc.getKey(), BaseEdgeDocument.class, + new GraphDocumentReadOptions().streamTransactionId(tx.getId())).get().getProperties()).containsEntry( + "test", "bar"); + + db.commitStreamTransaction(tx.getId()).get(); + + // assert that the edge has been updated after commit + assertThat(edgeCollection.getEdge(createdDoc.getKey(), BaseEdgeDocument.class, null).get() + .getProperties()).containsEntry("test", "bar"); + } + + @Test + void deleteEdge() throws ExecutionException, InterruptedException { + assumeTrue(isSingleServer()); + assumeTrue(isAtLeastVersion(3, 5)); + assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); + + EdgeEntity createdDoc = edgeCollection.insertEdge(createEdgeValue(null), null).get(); + + StreamTransactionEntity tx = db.beginStreamTransaction( + new StreamTransactionOptions() + .readCollections(VERTEX_COLLECTION_1, VERTEX_COLLECTION_2, EDGE_COLLECTION) + .writeCollections(VERTEX_COLLECTION_1, VERTEX_COLLECTION_2, EDGE_COLLECTION)).get(); + + // delete edge from within the tx + edgeCollection.deleteEdge(createdDoc.getKey(), new EdgeDeleteOptions().streamTransactionId(tx.getId())).get(); + + // assert that the edge has not been deleted from outside the tx + assertThat(edgeCollection.getEdge(createdDoc.getKey(), BaseEdgeDocument.class, null).get()).isNotNull(); + + // assert that the edge has been deleted from within the tx + assertThat(edgeCollection.getEdge(createdDoc.getKey(), BaseEdgeDocument.class, + new GraphDocumentReadOptions().streamTransactionId(tx.getId())).get()).isNull(); + + db.commitStreamTransaction(tx.getId()).get(); + + // assert that the edge has been deleted after commit + assertThat(edgeCollection.getEdge(createdDoc.getKey(), BaseEdgeDocument.class, null).get()).isNull(); + } + +} diff --git a/shaded-integration-tests/src/test/jackson/java/com/arangodb/async/StreamTransactionTest.java b/shaded-integration-tests/src/test/jackson/java/com/arangodb/async/StreamTransactionTest.java new file mode 100644 index 000000000..658bab18b --- /dev/null +++ b/shaded-integration-tests/src/test/jackson/java/com/arangodb/async/StreamTransactionTest.java @@ -0,0 +1,362 @@ +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed 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. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.async; + +import com.arangodb.ArangoDBException; +import com.arangodb.entity.*; +import com.arangodb.model.DocumentCreateOptions; +import com.arangodb.model.DocumentReadOptions; +import com.arangodb.model.StreamTransactionOptions; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Test; + +import java.util.Arrays; +import java.util.List; +import java.util.Set; +import java.util.concurrent.ExecutionException; +import java.util.stream.Collectors; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.fail; +import static org.junit.jupiter.api.Assumptions.assumeTrue; + +/** + * @author Michele Rastelli + */ +class StreamTransactionTest extends BaseTest { + + private static final String COLLECTION_NAME = "db_stream_transaction_test"; + + public StreamTransactionTest() throws ExecutionException, InterruptedException { + if (db.collection(COLLECTION_NAME).exists().get()) + db.collection(COLLECTION_NAME).drop().get(); + + db.createCollection(COLLECTION_NAME, null).get(); + } + + @AfterEach + void teardown() throws ExecutionException, InterruptedException { + if (db.collection(COLLECTION_NAME).exists().get()) + db.collection(COLLECTION_NAME).drop().get(); + } + + @Test + void beginStreamTransaction() throws ExecutionException, InterruptedException { + assumeTrue(isSingleServer()); + assumeTrue(isAtLeastVersion(3, 5)); + assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); + + StreamTransactionEntity tx = db.beginStreamTransaction(null).get(); + assertThat(tx.getId()).isNotNull(); + assertThat(tx.getStatus()).isEqualTo(StreamTransactionStatus.running); + db.abortStreamTransaction(tx.getId()).get(); + } + + @Test + void beginStreamTransactionWithNonExistingCollectionsShouldThrow() throws ExecutionException, InterruptedException { + assumeTrue(isSingleServer()); + assumeTrue(isAtLeastVersion(3, 5)); + assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); + + try { + db.beginStreamTransaction(new StreamTransactionOptions().writeCollections("notExistingCollection")).get(); + fail(); + } catch (ExecutionException e) { + assertThat(e.getCause()).isInstanceOf(ArangoDBException.class); + } + } + + @Test + void abortStreamTransaction() throws ExecutionException, InterruptedException { + assumeTrue(isSingleServer()); + assumeTrue(isAtLeastVersion(3, 5)); + assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); + + StreamTransactionEntity begunTx = db.beginStreamTransaction(null).get(); + StreamTransactionEntity abortedTx = db.abortStreamTransaction(begunTx.getId()).get(); + + assertThat(abortedTx.getId()).isNotNull(); + assertThat(abortedTx.getId()).isEqualTo(begunTx.getId()); + assertThat(abortedTx.getStatus()).isEqualTo(StreamTransactionStatus.aborted); + } + + @Test + void abortStreamTransactionTwice() throws ExecutionException, InterruptedException { + assumeTrue(isSingleServer()); + assumeTrue(isAtLeastVersion(3, 5)); + assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); + + StreamTransactionEntity begunTx = db.beginStreamTransaction(null).get(); + db.abortStreamTransaction(begunTx.getId()).get(); + db.abortStreamTransaction(begunTx.getId()).get(); + } + + @Test + void abortStreamTransactionWhenTransactionIdDoesNotExistsShouldThrow() throws ExecutionException, + InterruptedException { + assumeTrue(isSingleServer()); + assumeTrue(isAtLeastVersion(3, 5)); + assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); + + try { + db.abortStreamTransaction("000000").get(); + fail(); + } catch (ExecutionException e) { + assertThat(e.getCause()).isInstanceOf(ArangoDBException.class); + } + } + + @Test + void abortStreamTransactionWithInvalidTransactionIdShouldThrow() throws ExecutionException, InterruptedException { + assumeTrue(isSingleServer()); + assumeTrue(isAtLeastVersion(3, 5)); + assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); + + try { + db.abortStreamTransaction("invalidTransactionId").get(); + fail(); + } catch (ExecutionException e) { + assertThat(e.getCause()).isInstanceOf(ArangoDBException.class); + } + } + + @Test + void abortCommittedStreamTransactionShouldThrow() throws ExecutionException, InterruptedException { + assumeTrue(isSingleServer()); + assumeTrue(isAtLeastVersion(3, 5)); + assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); + + StreamTransactionEntity createdTx = db.beginStreamTransaction(null).get(); + db.commitStreamTransaction(createdTx.getId()).get(); + + try { + db.abortStreamTransaction(createdTx.getId()).get(); + fail(); + } catch (ExecutionException e) { + assertThat(e.getCause()).isInstanceOf(ArangoDBException.class); + } + } + + @Test + void getStreamTransaction() throws ExecutionException, InterruptedException { + assumeTrue(isSingleServer()); + assumeTrue(isAtLeastVersion(3, 5)); + assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); + + StreamTransactionEntity createdTx = db.beginStreamTransaction(null).get(); + StreamTransactionEntity gotTx = db.getStreamTransaction(createdTx.getId()).get(); + + assertThat(gotTx.getId()).isNotNull(); + assertThat(gotTx.getId()).isEqualTo(createdTx.getId()); + assertThat(gotTx.getStatus()).isEqualTo(StreamTransactionStatus.running); + + db.abortStreamTransaction(createdTx.getId()).get(); + } + + @Test + void getStreamTransactionWhenTransactionIdDoesNotExistsShouldThrow() throws ExecutionException, + InterruptedException { + assumeTrue(isSingleServer()); + assumeTrue(isAtLeastVersion(3, 5)); + assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); + + try { + db.getStreamTransaction("000000").get(); + fail(); + } catch (ExecutionException e) { + assertThat(e.getCause()).isInstanceOf(ArangoDBException.class); + } + } + + @Test + void getStreamTransactionWithInvalidTransactionIdShouldThrow() throws ExecutionException, InterruptedException { + assumeTrue(isSingleServer()); + assumeTrue(isAtLeastVersion(3, 5)); + assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); + + try { + db.getStreamTransaction("invalidTransactionId").get(); + fail(); + } catch (ExecutionException e) { + assertThat(e.getCause()).isInstanceOf(ArangoDBException.class); + } + } + + @Test + void commitStreamTransaction() throws ExecutionException, InterruptedException { + assumeTrue(isSingleServer()); + assumeTrue(isAtLeastVersion(3, 5)); + assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); + + StreamTransactionEntity createdTx = db.beginStreamTransaction(null).get(); + StreamTransactionEntity committedTx = db.commitStreamTransaction(createdTx.getId()).get(); + + assertThat(committedTx.getId()).isNotNull(); + assertThat(committedTx.getId()).isEqualTo(createdTx.getId()); + assertThat(committedTx.getStatus()).isEqualTo(StreamTransactionStatus.committed); + } + + @Test + void commitStreamTransactionTwice() throws ExecutionException, InterruptedException { + assumeTrue(isSingleServer()); + assumeTrue(isAtLeastVersion(3, 5)); + assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); + + StreamTransactionEntity createdTx = db.beginStreamTransaction(null).get(); + db.commitStreamTransaction(createdTx.getId()).get(); + db.commitStreamTransaction(createdTx.getId()).get(); + } + + @Test + void commitStreamTransactionWhenTransactionIdDoesNotExistsShouldThrow() throws ExecutionException, + InterruptedException { + assumeTrue(isSingleServer()); + assumeTrue(isAtLeastVersion(3, 5)); + assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); + + try { + db.commitStreamTransaction("000000").get(); + fail(); + } catch (ExecutionException e) { + assertThat(e.getCause()).isInstanceOf(ArangoDBException.class); + } + } + + @Test + void commitStreamTransactionWithInvalidTransactionIdShouldThrow() throws ExecutionException, InterruptedException { + assumeTrue(isSingleServer()); + assumeTrue(isAtLeastVersion(3, 5)); + assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); + + try { + db.commitStreamTransaction("invalidTransactionId").get(); + fail(); + } catch (ExecutionException e) { + assertThat(e.getCause()).isInstanceOf(ArangoDBException.class); + } + } + + @Test + void commitAbortedStreamTransactionShouldThrow() throws ExecutionException, InterruptedException { + assumeTrue(isSingleServer()); + assumeTrue(isAtLeastVersion(3, 5)); + assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); + + StreamTransactionEntity createdTx = db.beginStreamTransaction(null).get(); + db.abortStreamTransaction(createdTx.getId()).get(); + + try { + db.commitStreamTransaction(createdTx.getId()).get(); + fail(); + } catch (ExecutionException e) { + assertThat(e.getCause()).isInstanceOf(ArangoDBException.class); + } + } + + @Test + void getDocument() throws ExecutionException, InterruptedException { + assumeTrue(isSingleServer()); + assumeTrue(isAtLeastVersion(3, 5)); + assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); + + StreamTransactionEntity tx = db + .beginStreamTransaction(new StreamTransactionOptions().readCollections(COLLECTION_NAME)).get(); + + // insert a document from outside the tx + DocumentCreateEntity externalDoc = db.collection(COLLECTION_NAME) + .insertDocument(new BaseDocument(), null).get(); + + // assert that the document is not found from within the tx + assertThat(db.collection(COLLECTION_NAME).getDocument(externalDoc.getKey(), BaseDocument.class, + new DocumentReadOptions().streamTransactionId(tx.getId())).get()).isNull(); + + db.abortStreamTransaction(tx.getId()).get(); + } + + @Test + void getDocumentWithNonExistingTransactionIdShouldThrow() throws ExecutionException, InterruptedException { + assumeTrue(isSingleServer()); + assumeTrue(isAtLeastVersion(3, 5)); + assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); + + try { + db.collection(COLLECTION_NAME) + .getDocument("docId", BaseDocument.class, new DocumentReadOptions().streamTransactionId("123456")) + .get(); + fail(); + } catch (ExecutionException e) { + assertThat(e.getCause()).isInstanceOf(ArangoDBException.class); + } + } + + @Test + void insertDocumentWithNonExistingTransactionIdShouldThrow() throws ExecutionException, InterruptedException { + assumeTrue(isSingleServer()); + assumeTrue(isAtLeastVersion(3, 5)); + assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); + + try { + db.collection(COLLECTION_NAME) + .insertDocument(new BaseDocument(), new DocumentCreateOptions().streamTransactionId("123456")).get(); + fail(); + } catch (ExecutionException e) { + assertThat(e.getCause()).isInstanceOf(ArangoDBException.class); + } + } + + @Test + void getDocumentWithInvalidTransactionIdShouldThrow() throws ExecutionException, InterruptedException { + assumeTrue(isSingleServer()); + assumeTrue(isAtLeastVersion(3, 5)); + assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); + + try { + db.collection(COLLECTION_NAME) + .getDocument("docId", BaseDocument.class, new DocumentReadOptions().streamTransactionId("abcde")) + .get(); + fail(); + } catch (ExecutionException e) { + assertThat(e.getCause()).isInstanceOf(ArangoDBException.class); + } + } + + @Test + void getStreamTransactions() throws ExecutionException, InterruptedException { + assumeTrue(isSingleServer()); + assumeTrue(isAtLeastVersion(3, 5)); + assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); + + StreamTransactionEntity tx1 = db.beginStreamTransaction(null).get(); + StreamTransactionEntity tx2 = db.beginStreamTransaction(null).get(); + + List createdIds = Arrays.asList(tx1.getId(), tx2.getId()); + Set gotTxs = db.getStreamTransactions().get().stream(). + filter(it -> createdIds.contains(it.getId())).collect(Collectors.toSet()); + + assertThat(gotTxs).hasSameSizeAs(createdIds); + assertThat(gotTxs.stream() + .allMatch(it -> it.getState() == StreamTransactionStatus.running)).isTrue(); + + db.abortStreamTransaction(tx1.getId()).get(); + db.abortStreamTransaction(tx2.getId()).get(); + } + +} diff --git a/shaded-integration-tests/src/test/jackson/java/com/arangodb/async/debug/ConsolidationIntervalMsecTest.java b/shaded-integration-tests/src/test/jackson/java/com/arangodb/async/debug/ConsolidationIntervalMsecTest.java new file mode 100644 index 000000000..5a3d0ddad --- /dev/null +++ b/shaded-integration-tests/src/test/jackson/java/com/arangodb/async/debug/ConsolidationIntervalMsecTest.java @@ -0,0 +1,83 @@ +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed 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. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.async.debug; + +import com.arangodb.DbName; +import com.arangodb.async.ArangoDBAsync; +import com.arangodb.async.ArangoDatabaseAsync; +import com.arangodb.async.BaseTest; +import com.arangodb.entity.ViewEntity; +import com.arangodb.entity.ViewType; +import com.arangodb.entity.arangosearch.ArangoSearchPropertiesEntity; +import com.arangodb.entity.arangosearch.CollectionLink; +import com.arangodb.entity.arangosearch.FieldLink; +import com.arangodb.internal.config.FileConfigPropertiesProvider; +import com.arangodb.model.arangosearch.ArangoSearchCreateOptions; +import org.junit.jupiter.api.Test; + +import java.util.concurrent.ExecutionException; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assumptions.assumeTrue; + +/** + * @author Michele Rastelli + *

    + * https://github.com/arangodb/arangodb-java-driver-async/issues/15 + */ +class ConsolidationIntervalMsecTest extends BaseTest { + + @Test + void consolidationIntervalMsec() throws ExecutionException, InterruptedException { + assumeTrue(isAtLeastVersion(3, 4)); + + ArangoDBAsync arango = new ArangoDBAsync.Builder() + .loadProperties(new FileConfigPropertiesProvider()) + .user("root") + .password("test") + .build(); + + ArangoDatabaseAsync db = arango.db(DbName.of("database_of_things")); + if (db.exists().join()) { + db.drop().join(); + } + + db.create().join(); + db.collection("Thing").create().join(); + + ViewEntity result = db.createArangoSearch("ThingsSearchView", new ArangoSearchCreateOptions() + .consolidationIntervalMsec(60000L) //<== This line breaks it + .link(CollectionLink.on("Thing") + .fields(FieldLink.on("name") + .analyzers("identity")))) + .join(); + + assertThat(result.getName()).isEqualTo("ThingsSearchView"); + assertThat(result.getType()).isEqualTo(ViewType.ARANGO_SEARCH); + + ArangoSearchPropertiesEntity props = db.arangoSearch("ThingsSearchView").getProperties().join(); + assertThat(props.getName()).isEqualTo("ThingsSearchView"); + assertThat(props.getConsolidationIntervalMsec()).isEqualTo(60000L); + assertThat(props.getLinks().iterator().hasNext()).isTrue(); + assertThat(props.getLinks().iterator().next().getName()).isEqualTo("Thing"); + } + +} diff --git a/shaded-integration-tests/src/test/jackson/java/com/arangodb/async/example/ExampleBase.java b/shaded-integration-tests/src/test/jackson/java/com/arangodb/async/example/ExampleBase.java new file mode 100644 index 000000000..9c1ce81e2 --- /dev/null +++ b/shaded-integration-tests/src/test/jackson/java/com/arangodb/async/example/ExampleBase.java @@ -0,0 +1,64 @@ +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed 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. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.async.example; + +import com.arangodb.DbName; +import com.arangodb.async.ArangoCollectionAsync; +import com.arangodb.async.ArangoDBAsync; +import com.arangodb.async.ArangoDatabaseAsync; +import com.arangodb.internal.config.FileConfigPropertiesProvider; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; + +import java.util.concurrent.ExecutionException; + +/** + * @author Mark Vollmary + */ +public class ExampleBase { + + protected static final String COLLECTION_NAME = "json_example_collection"; + private static final DbName DB_NAME = DbName.of("json_example_db"); + protected static ArangoDatabaseAsync db; + protected static ArangoCollectionAsync collection; + private static ArangoDBAsync arangoDB; + + @BeforeAll + static void setUp() throws InterruptedException, ExecutionException { + arangoDB = new ArangoDBAsync.Builder() + .loadProperties(new FileConfigPropertiesProvider()) + .build(); + if (arangoDB.db(DB_NAME).exists().get()) { + arangoDB.db(DB_NAME).drop().get(); + } + arangoDB.createDatabase(DB_NAME).get(); + db = arangoDB.db(DB_NAME); + db.createCollection(COLLECTION_NAME).get(); + collection = db.collection(COLLECTION_NAME); + } + + @AfterAll + static void tearDown() throws InterruptedException, ExecutionException { + db.drop().get(); + arangoDB.shutdown(); + } + +} diff --git a/shaded-integration-tests/src/test/jackson/java/com/arangodb/async/example/document/AqlQueryWithSpecialReturnTypesExampleTest.java b/shaded-integration-tests/src/test/jackson/java/com/arangodb/async/example/document/AqlQueryWithSpecialReturnTypesExampleTest.java new file mode 100644 index 000000000..9ab6624df --- /dev/null +++ b/shaded-integration-tests/src/test/jackson/java/com/arangodb/async/example/document/AqlQueryWithSpecialReturnTypesExampleTest.java @@ -0,0 +1,128 @@ +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed 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. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.async.example.document; + +import com.arangodb.async.example.ExampleBase; +import com.arangodb.entity.BaseDocument; +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.fasterxml.jackson.databind.node.ObjectNode; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; + +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.UUID; +import java.util.concurrent.ExecutionException; + +import static org.assertj.core.api.Assertions.assertThat; + + +/** + * @author Mark Vollmary + */ +class AqlQueryWithSpecialReturnTypesExampleTest extends ExampleBase { + + @BeforeAll + static void before() throws InterruptedException, ExecutionException { + createExamples(); + } + + private static void createExamples() throws InterruptedException, ExecutionException { + for (int i = 0; i < 100; i++) { + final BaseDocument value = new BaseDocument(UUID.randomUUID().toString()); + value.addAttribute("name", "TestUser" + i); + value.addAttribute("gender", (i % 2) == 0 ? Gender.MALE : Gender.FEMALE); + value.addAttribute("age", i + 10); + db.collection(COLLECTION_NAME).insertDocument(value).get(); + } + } + + @Test + void aqlWithLimitQueryAsJsonObject() throws InterruptedException, ExecutionException { + final String query = "FOR t IN " + COLLECTION_NAME + + " FILTER t.age >= 20 && t.age < 30 && t.gender == @gender RETURN t"; + final Map bindVars = Collections.singletonMap("gender", Gender.FEMALE); + db.query(query, bindVars, null, ObjectNode.class) + .whenComplete((cursor, ex) -> cursor.forEachRemaining(node -> { + assertThat(node.get("name").asText()).isIn("TestUser11", "TestUser13", "TestUser15", "TestUser17" + , "TestUser19"); + assertThat(node.get("gender").asText()).isEqualTo(Gender.FEMALE.name()); + assertThat(node.get("age").asInt()).isIn(21, 23, 25, 27, 29); + })) + .get(); + } + + @Test + void aqlWithLimitQueryAsArrayNode() throws InterruptedException, ExecutionException { + final String query = "FOR t IN " + COLLECTION_NAME + + " FILTER t.age >= 20 && t.age < 30 && t.gender == @gender RETURN [t.name, t.gender, t.age]"; + final Map bindVars = Collections.singletonMap("gender", Gender.FEMALE); + db.query(query, bindVars, null, ArrayNode.class) + .whenComplete((cursor, ex) -> cursor.forEachRemaining(arrNode -> { + assertThat(arrNode.get(0).asText()).isIn("TestUser11", "TestUser13", "TestUser15", "TestUser17", + "TestUser19"); + assertThat(arrNode.get(1).asText()).isEqualTo(Gender.FEMALE.name()); + assertThat(arrNode.get(2).asInt()).isIn(21, 23, 25, 27, 29); + })) + .get(); + } + + @Test + void aqlWithLimitQueryAsMap() throws InterruptedException, ExecutionException { + final String query = "FOR t IN " + COLLECTION_NAME + + " FILTER t.age >= 20 && t.age < 30 && t.gender == @gender RETURN t"; + final Map bindVars = Collections.singletonMap("gender", Gender.FEMALE); + db.query(query, bindVars, null, Map.class) + .whenComplete((cursor, ex) -> cursor.forEachRemaining(map -> { + assertThat(map.get("name")).isNotNull(); + assertThat(String.valueOf(map.get("name"))).isIn("TestUser11", "TestUser13", "TestUser15", + "TestUser17", "TestUser19"); + assertThat(map.get("gender")).isNotNull(); + assertThat(String.valueOf(map.get("gender"))).isEqualTo(Gender.FEMALE.name()); + assertThat(map.get("age")).isNotNull(); + assertThat(Long.valueOf(map.get("age").toString())).isIn(21L, 23L, 25L, 27L, 29L); + })) + .get(); + } + + @Test + void aqlWithLimitQueryAsList() throws InterruptedException, ExecutionException { + final String query = "FOR t IN " + COLLECTION_NAME + + " FILTER t.age >= 20 && t.age < 30 && t.gender == @gender RETURN [t.name, t.gender, t.age]"; + final Map bindVars = Collections.singletonMap("gender", Gender.FEMALE); + db.query(query, bindVars, null, List.class) + .whenComplete((cursor, ex) -> cursor.forEachRemaining(list -> { + assertThat(list.get(0)).isNotNull(); + assertThat(String.valueOf(list.get(0))).isIn("TestUser11", "TestUser13", "TestUser15", + "TestUser17", "TestUser19"); + assertThat(list.get(1)).isNotNull(); + assertThat(Gender.valueOf(String.valueOf(list.get(1)))).isEqualTo(Gender.FEMALE); + assertThat(list.get(2)).isNotNull(); + assertThat(Long.valueOf(String.valueOf(list.get(2)))).isIn(21L, 23L, 25L, 27L, 29L); + })) + .get(); + } + + public enum Gender { + MALE, FEMALE + } +} diff --git a/shaded-integration-tests/src/test/jackson/java/com/arangodb/async/example/document/GetDocumentExampleTest.java b/shaded-integration-tests/src/test/jackson/java/com/arangodb/async/example/document/GetDocumentExampleTest.java new file mode 100644 index 000000000..11ef3c63f --- /dev/null +++ b/shaded-integration-tests/src/test/jackson/java/com/arangodb/async/example/document/GetDocumentExampleTest.java @@ -0,0 +1,94 @@ +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed 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. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.async.example.document; + +import com.arangodb.async.example.ExampleBase; +import com.arangodb.entity.BaseDocument; +import com.arangodb.util.RawJson; +import com.fasterxml.jackson.databind.JsonNode; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; + +import java.util.UUID; +import java.util.concurrent.ExecutionException; + +import static org.assertj.core.api.Assertions.assertThat; + + +/** + * @author Mark Vollmary + */ +class GetDocumentExampleTest extends ExampleBase { + + private static String key = null; + + @BeforeAll + static void before() throws InterruptedException, ExecutionException { + final BaseDocument value = new BaseDocument(UUID.randomUUID().toString()); + value.addAttribute("foo", "bar"); + key = collection.insertDocument(value).get().getKey(); + } + + @Test + void getAsBean() throws InterruptedException, ExecutionException { + collection.getDocument(key, TestEntity.class) + .whenComplete((doc, ex) -> { + assertThat(doc).isNotNull(); + assertThat(doc.getFoo()).isEqualTo("bar"); + }) + .get(); + } + + @Test + void getAsBaseDocument() throws InterruptedException, ExecutionException { + collection.getDocument(key, BaseDocument.class) + .whenComplete((doc, ex) -> { + assertThat(doc).isNotNull(); + assertThat(doc.getAttribute("foo")).isNotNull(); + assertThat(String.valueOf(doc.getAttribute("foo"))).isEqualTo("bar"); + }) + .get(); + } + + @Test + void getAsVPack() throws InterruptedException, ExecutionException { + collection.getDocument(key, JsonNode.class) + .whenComplete((doc, ex) -> { + assertThat(doc).isNotNull(); + assertThat(doc.get("foo").isTextual()).isEqualTo(true); + assertThat(doc.get("foo").asText()).isEqualTo("bar"); + }) + .get(); + } + + @Test + void getAsJson() throws InterruptedException, ExecutionException { + collection.getDocument(key, RawJson.class) + .whenComplete((doc, ex) -> { + assertThat(doc.getValue()) + .isNotNull() + .contains("foo") + .contains("bar"); + }) + .get(); + } + +} diff --git a/shaded-integration-tests/src/test/jackson/java/com/arangodb/async/example/document/ImportDocumentExampleTest.java b/shaded-integration-tests/src/test/jackson/java/com/arangodb/async/example/document/ImportDocumentExampleTest.java new file mode 100644 index 000000000..dacf1bd87 --- /dev/null +++ b/shaded-integration-tests/src/test/jackson/java/com/arangodb/async/example/document/ImportDocumentExampleTest.java @@ -0,0 +1,87 @@ +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed 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. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.async.example.document; + +import com.arangodb.async.example.ExampleBase; +import com.arangodb.entity.DocumentImportEntity; +import com.arangodb.model.DocumentImportOptions; +import org.junit.jupiter.api.Test; + +import java.util.List; +import java.util.UUID; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.atomic.AtomicLong; +import java.util.stream.Collectors; +import java.util.stream.IntStream; +import java.util.stream.Stream; + +import static org.junit.jupiter.api.Assertions.fail; + +/** + * @author Michele Rastelli + */ +class ImportDocumentExampleTest extends ExampleBase { + + private static final int MAX_PENDING_REQUESTS = 10; + + @Test + void importDocument() { + AtomicLong pendingReqsCount = new AtomicLong(); + + Stream> chunks = IntStream.range(0, 100) + .mapToObj(i -> IntStream.range(0, 500) + .mapToObj(it -> new TestEntity(UUID.randomUUID().toString())).collect(Collectors.toList()) + ); + + List> completableFutures = chunks + .map(p -> { + // wait for pending requests + while (pendingReqsCount.get() > MAX_PENDING_REQUESTS) { + try { + Thread.sleep(10); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + + pendingReqsCount.incrementAndGet(); + return collection.importDocuments(p, new DocumentImportOptions()) + .thenApply(it -> { + pendingReqsCount.decrementAndGet(); + return it; + }); + } + ) + .collect(Collectors.toList()); + + completableFutures.forEach(cf -> { + try { + cf.get(); + } catch (InterruptedException | ExecutionException e) { + e.printStackTrace(); + fail(); + } + }); + + } + +} diff --git a/shaded-integration-tests/src/test/jackson/java/com/arangodb/async/example/document/InsertDocumentExampleTest.java b/shaded-integration-tests/src/test/jackson/java/com/arangodb/async/example/document/InsertDocumentExampleTest.java new file mode 100644 index 000000000..e55eda546 --- /dev/null +++ b/shaded-integration-tests/src/test/jackson/java/com/arangodb/async/example/document/InsertDocumentExampleTest.java @@ -0,0 +1,74 @@ +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed 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. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.async.example.document; + +import com.arangodb.async.example.ExampleBase; +import com.arangodb.entity.BaseDocument; +import com.arangodb.util.RawJson; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ObjectNode; +import org.junit.jupiter.api.Test; + +import java.util.UUID; +import java.util.concurrent.ExecutionException; + +import static org.assertj.core.api.Assertions.assertThat; + + +/** + * @author Mark Vollmary + */ +class InsertDocumentExampleTest extends ExampleBase { + + @Test + void insertBean() throws ExecutionException, InterruptedException { + collection.insertDocument(new TestEntity("bar")) + .whenComplete((doc, ex) -> assertThat(doc.getKey()).isNotNull()) + .get(); + } + + @Test + void insertBaseDocument() throws ExecutionException, InterruptedException { + final BaseDocument value = new BaseDocument(UUID.randomUUID().toString()); + value.addAttribute("foo", "bar"); + collection.insertDocument(value) + .whenComplete((doc, ex) -> assertThat(doc.getKey()).isNotNull()) + .get(); + } + + @Test + void insertJsonNode() throws ExecutionException, InterruptedException { + ObjectMapper mapper = new ObjectMapper(); + ObjectNode node = mapper.createObjectNode(); + node.put("foo", "bar"); + collection.insertDocument(node) + .whenComplete((doc, ex) -> assertThat(doc.getKey()).isNotNull()) + .get(); + } + + @Test + void insertJson() throws ExecutionException, InterruptedException { + collection.insertDocument(RawJson.of("{\"foo\":\"bar\"}")) + .whenComplete((doc, ex) -> assertThat(doc.getKey()).isNotNull()) + .get(); + } + +} diff --git a/shaded-integration-tests/src/test/jackson/java/com/arangodb/async/example/document/TestEntity.java b/shaded-integration-tests/src/test/jackson/java/com/arangodb/async/example/document/TestEntity.java new file mode 100644 index 000000000..2ef89c19f --- /dev/null +++ b/shaded-integration-tests/src/test/jackson/java/com/arangodb/async/example/document/TestEntity.java @@ -0,0 +1,47 @@ +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed 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. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.async.example.document; + +/** + * @author Mark Vollmary + */ +public class TestEntity { + + private String foo; + + public TestEntity() { + super(); + } + + public TestEntity(final String foo) { + super(); + this.foo = foo; + } + + public String getFoo() { + return foo; + } + + void setFoo(final String foo) { + this.foo = foo; + } + +} diff --git a/shaded-integration-tests/src/test/jackson/java/com/arangodb/async/example/graph/AQLActorsAndMoviesExampleTest.java b/shaded-integration-tests/src/test/jackson/java/com/arangodb/async/example/graph/AQLActorsAndMoviesExampleTest.java new file mode 100644 index 000000000..259cc4451 --- /dev/null +++ b/shaded-integration-tests/src/test/jackson/java/com/arangodb/async/example/graph/AQLActorsAndMoviesExampleTest.java @@ -0,0 +1,605 @@ +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed 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. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.async.example.graph; + +import com.arangodb.DbName; +import com.arangodb.async.ArangoCollectionAsync; +import com.arangodb.async.ArangoCursorAsync; +import com.arangodb.async.ArangoDBAsync; +import com.arangodb.async.ArangoDatabaseAsync; +import com.arangodb.entity.BaseDocument; +import com.arangodb.entity.BaseEdgeDocument; +import com.arangodb.entity.CollectionType; +import com.arangodb.entity.DocumentCreateEntity; +import com.arangodb.internal.config.FileConfigPropertiesProvider; +import com.arangodb.model.CollectionCreateOptions; +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; + +import java.util.UUID; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutionException; + +import static org.assertj.core.api.Assertions.assertThat; + + +/** + * @author Mark Vollmary + * @see + * AQL Example Queries on an + * Actors and Movies Database + */ +class AQLActorsAndMoviesExampleTest { + + private static final DbName TEST_DB = DbName.of("actors_movies_test_db"); + private static ArangoDBAsync arangoDB; + private static ArangoDatabaseAsync db; + + @BeforeAll + static void setUp() throws InterruptedException, ExecutionException { + arangoDB = new ArangoDBAsync.Builder() + .loadProperties(new FileConfigPropertiesProvider()) + .build(); + if (arangoDB.db(TEST_DB).exists().get()) { + arangoDB.db(TEST_DB).drop().get(); + } + arangoDB.createDatabase(TEST_DB).get(); + db = arangoDB.db(TEST_DB); + createData(); + } + + @AfterAll + static void tearDown() throws InterruptedException, ExecutionException { + db.drop().get(); + arangoDB.shutdown(); + } + + private static DocumentCreateEntity saveMovie( + final ArangoCollectionAsync movies, + final String key, + final String title, + final int released, + final String tagline) throws InterruptedException, ExecutionException { + final BaseDocument value = new BaseDocument(UUID.randomUUID().toString()); + value.setKey(key); + value.addAttribute("title", title); + value.addAttribute("released", released); + value.addAttribute("tagline", tagline); + return movies.insertDocument(value).get(); + } + + private static DocumentCreateEntity saveActor( + final ArangoCollectionAsync actors, + final String key, + final String name, + final int born) throws InterruptedException, ExecutionException { + final BaseDocument value = new BaseDocument(UUID.randomUUID().toString()); + value.setKey(key); + value.addAttribute("name", name); + value.addAttribute("born", born); + return actors.insertDocument(value).get(); + } + + private static void saveActsIn( + final ArangoCollectionAsync actsIn, + final String actor, + final String movie, + final String[] roles, + final int year) throws InterruptedException, ExecutionException { + final BaseEdgeDocument value = new BaseEdgeDocument(); + value.setFrom(actor); + value.setTo(movie); + value.addAttribute("roles", roles); + value.addAttribute("year", year); + actsIn.insertDocument(value).get(); + } + + private static void createData() throws InterruptedException, ExecutionException { + db.createCollection("actors").get(); + final ArangoCollectionAsync actors = db.collection("actors"); + db.createCollection("movies").get(); + final ArangoCollectionAsync movies = db.collection("movies"); + db.createCollection("actsIn", new CollectionCreateOptions().type(CollectionType.EDGES)).get(); + final ArangoCollectionAsync actsIn = db.collection("actsIn"); + + final String theMatrix = saveMovie(movies, "TheMatrix", "The Matrix", 1999, "Welcome to the Real World") + .getId(); + final String keanu = saveActor(actors, "Keanu", "Keanu Reeves", 1964).getId(); + final String carrie = saveActor(actors, "Carrie", "Carrie-Anne Moss", 1967).getId(); + final String laurence = saveActor(actors, "Laurence", "Laurence Fishburne", 1961).getId(); + final String hugo = saveActor(actors, "Hugo", "Hugo Weaving", 1960).getId(); + final String emil = saveActor(actors, "Emil", "Emil Eifrem", 1978).getId(); + + saveActsIn(actsIn, keanu, theMatrix, new String[]{"Neo"}, 1999); + saveActsIn(actsIn, carrie, theMatrix, new String[]{"Trinity"}, 1999); + saveActsIn(actsIn, laurence, theMatrix, new String[]{"Morpheus"}, 1999); + saveActsIn(actsIn, hugo, theMatrix, new String[]{"Agent Smith"}, 1999); + saveActsIn(actsIn, emil, theMatrix, new String[]{"Emil"}, 1999); + + final String theMatrixReloaded = saveMovie(movies, "TheMatrixReloaded", "The Matrix Reloaded", 2003, + "Free your mind").getId(); + saveActsIn(actsIn, keanu, theMatrixReloaded, new String[]{"Neo"}, 2003); + saveActsIn(actsIn, carrie, theMatrixReloaded, new String[]{"Trinity"}, 2003); + saveActsIn(actsIn, laurence, theMatrixReloaded, new String[]{"Morpheus"}, 2003); + saveActsIn(actsIn, hugo, theMatrixReloaded, new String[]{"Agent Smith"}, 2003); + + final String theMatrixRevolutions = saveMovie(movies, "TheMatrixRevolutions", "The Matrix Revolutions", 2003, + "Everything that has a beginning has an end").getId(); + saveActsIn(actsIn, keanu, theMatrixRevolutions, new String[]{"Neo"}, 2003); + saveActsIn(actsIn, carrie, theMatrixRevolutions, new String[]{"Trinity"}, 2003); + saveActsIn(actsIn, laurence, theMatrixRevolutions, new String[]{"Morpheus"}, 2003); + saveActsIn(actsIn, hugo, theMatrixRevolutions, new String[]{"Agent Smith"}, 2003); + + final String theDevilsAdvocate = saveMovie(movies, "TheDevilsAdvocate", "The Devil's Advocate", 1997, + "Evil has its winning ways").getId(); + final String charlize = saveActor(actors, "Charlize", "Charlize Theron", 1975).getId(); + final String al = saveActor(actors, "Al", "Al Pacino", 1940).getId(); + saveActsIn(actsIn, keanu, theDevilsAdvocate, new String[]{"Kevin Lomax"}, 1997); + saveActsIn(actsIn, charlize, theDevilsAdvocate, new String[]{"Mary Ann Lomax"}, 1997); + saveActsIn(actsIn, al, theDevilsAdvocate, new String[]{"John Milton"}, 1997); + + final String AFewGoodMen = saveMovie(movies, "AFewGoodMen", "A Few Good Men", 1992, + "In the heart of the nation's capital, in a courthouse of the U.S. government, one man will stop at " + + "nothing to keep his honor, and one will stop at nothing to find the truth.") + .getId(); + final String tomC = saveActor(actors, "TomC", "Tom Cruise", 1962).getId(); + final String jackN = saveActor(actors, "JackN", "Jack Nicholson", 1937).getId(); + final String demiM = saveActor(actors, "DemiM", "Demi Moore", 1962).getId(); + final String kevinB = saveActor(actors, "KevinB", "Kevin Bacon", 1958).getId(); + final String kieferS = saveActor(actors, "KieferS", "Kiefer Sutherland", 1966).getId(); + final String noahW = saveActor(actors, "NoahW", "Noah Wyle", 1971).getId(); + final String cubaG = saveActor(actors, "CubaG", "Cuba Gooding Jr.", 1968).getId(); + final String kevinP = saveActor(actors, "KevinP", "Kevin Pollak", 1957).getId(); + final String jTW = saveActor(actors, "JTW", "J.T. Walsh", 1943).getId(); + final String jamesM = saveActor(actors, "JamesM", "James Marshall", 1967).getId(); + final String christopherG = saveActor(actors, "ChristopherG", "Christopher Guest", 1948).getId(); + saveActsIn(actsIn, tomC, AFewGoodMen, new String[]{"Lt. Daniel Kaffee"}, 1992); + saveActsIn(actsIn, jackN, AFewGoodMen, new String[]{"Col. Nathan R. Jessup"}, 1992); + saveActsIn(actsIn, demiM, AFewGoodMen, new String[]{"Lt. Cdr. JoAnne Galloway"}, 1992); + saveActsIn(actsIn, kevinB, AFewGoodMen, new String[]{"Capt. Jack Ross"}, 1992); + saveActsIn(actsIn, kieferS, AFewGoodMen, new String[]{"Lt. Jonathan Kendrick"}, 1992); + saveActsIn(actsIn, noahW, AFewGoodMen, new String[]{"Cpl. Jeffrey Barnes"}, 1992); + saveActsIn(actsIn, cubaG, AFewGoodMen, new String[]{"Cpl. Carl Hammaker"}, 1992); + saveActsIn(actsIn, kevinP, AFewGoodMen, new String[]{"Lt. Sam Weinberg"}, 1992); + saveActsIn(actsIn, jTW, AFewGoodMen, new String[]{"Lt. Col. Matthew Andrew Markinson"}, 1992); + saveActsIn(actsIn, jamesM, AFewGoodMen, new String[]{"Pfc. Louden Downey"}, 1992); + saveActsIn(actsIn, christopherG, AFewGoodMen, new String[]{"Dr. Stone"}, 1992); + + final String topGun = saveMovie(movies, "TopGun", "Top Gun", 1986, "I feel the need, the need for speed.") + .getId(); + final String kellyM = saveActor(actors, "KellyM", "Kelly McGillis", 1957).getId(); + final String valK = saveActor(actors, "ValK", "Val Kilmer", 1959).getId(); + final String anthonyE = saveActor(actors, "AnthonyE", "Anthony Edwards", 1962).getId(); + final String tomS = saveActor(actors, "TomS", "Tom Skerritt", 1933).getId(); + final String megR = saveActor(actors, "MegR", "Meg Ryan", 1961).getId(); + saveActsIn(actsIn, tomC, topGun, new String[]{"Maverick"}, 1986); + saveActsIn(actsIn, kellyM, topGun, new String[]{"Charlie"}, 1986); + saveActsIn(actsIn, valK, topGun, new String[]{"Iceman"}, 1986); + saveActsIn(actsIn, anthonyE, topGun, new String[]{"Goose"}, 1986); + saveActsIn(actsIn, tomS, topGun, new String[]{"Viper"}, 1986); + saveActsIn(actsIn, megR, topGun, new String[]{"Carole"}, 1986); + + final String jerryMaguire = saveMovie(movies, "JerryMaguire", "Jerry Maguire", 2000, + "The rest of his life begins now.").getId(); + final String reneeZ = saveActor(actors, "ReneeZ", "Renee Zellweger", 1969).getId(); + final String kellyP = saveActor(actors, "KellyP", "Kelly Preston", 1962).getId(); + final String jerryO = saveActor(actors, "JerryO", "Jerry O'Connell", 1974).getId(); + final String jayM = saveActor(actors, "JayM", "Jay Mohr", 1970).getId(); + final String bonnieH = saveActor(actors, "BonnieH", "Bonnie Hunt", 1961).getId(); + final String reginaK = saveActor(actors, "ReginaK", "Regina King", 1971).getId(); + final String jonathanL = saveActor(actors, "JonathanL", "Jonathan Lipnicki", 1996).getId(); + saveActsIn(actsIn, tomC, jerryMaguire, new String[]{"Jerry Maguire"}, 2000); + saveActsIn(actsIn, cubaG, jerryMaguire, new String[]{"Rod Tidwell"}, 2000); + saveActsIn(actsIn, reneeZ, jerryMaguire, new String[]{"Dorothy Boyd"}, 2000); + saveActsIn(actsIn, kellyP, jerryMaguire, new String[]{"Avery Bishop"}, 2000); + saveActsIn(actsIn, jerryO, jerryMaguire, new String[]{"Frank Cushman"}, 2000); + saveActsIn(actsIn, jayM, jerryMaguire, new String[]{"Bob Sugar"}, 2000); + saveActsIn(actsIn, bonnieH, jerryMaguire, new String[]{"Laurel Boyd"}, 2000); + saveActsIn(actsIn, reginaK, jerryMaguire, new String[]{"Marcee Tidwell"}, 2000); + saveActsIn(actsIn, jonathanL, jerryMaguire, new String[]{"Ray Boyd"}, 2000); + + final String standByMe = saveMovie(movies, "StandByMe", "Stand By Me", 1986, + "For some, it's the last real taste of innocence, and the first real taste of life. But for everyone," + + " it's the time that memories are made of.") + .getId(); + final String riverP = saveActor(actors, "RiverP", "River Phoenix", 1970).getId(); + final String coreyF = saveActor(actors, "CoreyF", "Corey Feldman", 1971).getId(); + final String wilW = saveActor(actors, "WilW", "Wil Wheaton", 1972).getId(); + final String johnC = saveActor(actors, "JohnC", "John Cusack", 1966).getId(); + final String marshallB = saveActor(actors, "MarshallB", "Marshall Bell", 1942).getId(); + saveActsIn(actsIn, wilW, standByMe, new String[]{"Gordie Lachance"}, 1986); + saveActsIn(actsIn, riverP, standByMe, new String[]{"Chris Chambers"}, 1986); + saveActsIn(actsIn, jerryO, standByMe, new String[]{"Vern Tessio"}, 1986); + saveActsIn(actsIn, coreyF, standByMe, new String[]{"Teddy Duchamp"}, 1986); + saveActsIn(actsIn, johnC, standByMe, new String[]{"Denny Lachance"}, 1986); + saveActsIn(actsIn, kieferS, standByMe, new String[]{"Ace Merrill"}, 1986); + saveActsIn(actsIn, marshallB, standByMe, new String[]{"Mr. Lachance"}, 1986); + + final String asGoodAsItGets = saveMovie(movies, "AsGoodAsItGets", "As Good as It Gets", 1997, + "A comedy from the heart that goes for the throat.").getId(); + final String helenH = saveActor(actors, "HelenH", "Helen Hunt", 1963).getId(); + final String gregK = saveActor(actors, "GregK", "Greg Kinnear", 1963).getId(); + saveActsIn(actsIn, jackN, asGoodAsItGets, new String[]{"Melvin Udall"}, 1997); + saveActsIn(actsIn, helenH, asGoodAsItGets, new String[]{"Carol Connelly"}, 1997); + saveActsIn(actsIn, gregK, asGoodAsItGets, new String[]{"Simon Bishop"}, 1997); + saveActsIn(actsIn, cubaG, asGoodAsItGets, new String[]{"Frank Sachs"}, 1997); + + final String whatDreamsMayCome = saveMovie(movies, "WhatDreamsMayCome", "What Dreams May Come", 1998, + "After life there is more. The end is just the beginning.").getId(); + final String annabellaS = saveActor(actors, "AnnabellaS", "Annabella Sciorra", 1960).getId(); + final String maxS = saveActor(actors, "MaxS", "Max von Sydow", 1929).getId(); + final String wernerH = saveActor(actors, "WernerH", "Werner Herzog", 1942).getId(); + final String robin = saveActor(actors, "Robin", "Robin Williams", 1951).getId(); + saveActsIn(actsIn, robin, whatDreamsMayCome, new String[]{"Chris Nielsen"}, 1998); + saveActsIn(actsIn, cubaG, whatDreamsMayCome, new String[]{"Albert Lewis"}, 1998); + saveActsIn(actsIn, annabellaS, whatDreamsMayCome, new String[]{"Annie Collins-Nielsen"}, 1998); + saveActsIn(actsIn, maxS, whatDreamsMayCome, new String[]{"The Tracker"}, 1998); + saveActsIn(actsIn, wernerH, whatDreamsMayCome, new String[]{"The Face"}, 1998); + + final String snowFallingonCedars = saveMovie(movies, "SnowFallingonCedars", "Snow Falling on Cedars", 1999, + "First loves last. Forever.").getId(); + final String ethanH = saveActor(actors, "EthanH", "Ethan Hawke", 1970).getId(); + final String rickY = saveActor(actors, "RickY", "Rick Yune", 1971).getId(); + final String jamesC = saveActor(actors, "JamesC", "James Cromwell", 1940).getId(); + saveActsIn(actsIn, ethanH, snowFallingonCedars, new String[]{"Ishmael Chambers"}, 1999); + saveActsIn(actsIn, rickY, snowFallingonCedars, new String[]{"Kazuo Miyamoto"}, 1999); + saveActsIn(actsIn, maxS, snowFallingonCedars, new String[]{"Nels Gudmundsson"}, 1999); + saveActsIn(actsIn, jamesC, snowFallingonCedars, new String[]{"Judge Fielding"}, 1999); + + final String youveGotMail = saveMovie(movies, "YouveGotMail", "You've Got Mail", 1998, + "At odds in life... in love on-line.").getId(); + final String parkerP = saveActor(actors, "ParkerP", "Parker Posey", 1968).getId(); + final String daveC = saveActor(actors, "DaveC", "Dave Chappelle", 1973).getId(); + final String steveZ = saveActor(actors, "SteveZ", "Steve Zahn", 1967).getId(); + final String tomH = saveActor(actors, "TomH", "Tom Hanks", 1956).getId(); + saveActsIn(actsIn, tomH, youveGotMail, new String[]{"Joe Fox"}, 1998); + saveActsIn(actsIn, megR, youveGotMail, new String[]{"Kathleen Kelly"}, 1998); + saveActsIn(actsIn, gregK, youveGotMail, new String[]{"Frank Navasky"}, 1998); + saveActsIn(actsIn, parkerP, youveGotMail, new String[]{"Patricia Eden"}, 1998); + saveActsIn(actsIn, daveC, youveGotMail, new String[]{"Kevin Jackson"}, 1998); + saveActsIn(actsIn, steveZ, youveGotMail, new String[]{"George Pappas"}, 1998); + + final String sleeplessInSeattle = saveMovie(movies, "SleeplessInSeattle", "Sleepless in Seattle", 1993, + "What if someone you never met, someone you never saw, someone you never knew was the only someone " + + "for you?") + .getId(); + final String ritaW = saveActor(actors, "RitaW", "Rita Wilson", 1956).getId(); + final String billPull = saveActor(actors, "BillPull", "Bill Pullman", 1953).getId(); + final String victorG = saveActor(actors, "VictorG", "Victor Garber", 1949).getId(); + final String rosieO = saveActor(actors, "RosieO", "Rosie O'Donnell", 1962).getId(); + saveActsIn(actsIn, tomH, sleeplessInSeattle, new String[]{"Sam Baldwin"}, 1993); + saveActsIn(actsIn, megR, sleeplessInSeattle, new String[]{"Annie Reed"}, 1993); + saveActsIn(actsIn, ritaW, sleeplessInSeattle, new String[]{"Suzy"}, 1993); + saveActsIn(actsIn, billPull, sleeplessInSeattle, new String[]{"Walter"}, 1993); + saveActsIn(actsIn, victorG, sleeplessInSeattle, new String[]{"Greg"}, 1993); + saveActsIn(actsIn, rosieO, sleeplessInSeattle, new String[]{"Becky"}, 1993); + + final String joeVersustheVolcano = saveMovie(movies, "JoeVersustheVolcano", "Joe Versus the Volcano", 1990, + "A story of love, lava and burning desire.").getId(); + final String nathan = saveActor(actors, "Nathan", "Nathan Lane", 1956).getId(); + saveActsIn(actsIn, tomH, joeVersustheVolcano, new String[]{"Joe Banks"}, 1990); + saveActsIn(actsIn, megR, joeVersustheVolcano, + new String[]{"DeDe', 'Angelica Graynamore', 'Patricia Graynamore"}, 1990); + saveActsIn(actsIn, nathan, joeVersustheVolcano, new String[]{"Baw"}, 1990); + + final String whenHarryMetSally = saveMovie(movies, "WhenHarryMetSally", "When Harry Met Sally", 1998, + "At odds in life... in love on-line.").getId(); + final String billyC = saveActor(actors, "BillyC", "Billy Crystal", 1948).getId(); + final String carrieF = saveActor(actors, "CarrieF", "Carrie Fisher", 1956).getId(); + final String brunoK = saveActor(actors, "BrunoK", "Bruno Kirby", 1949).getId(); + saveActsIn(actsIn, billyC, whenHarryMetSally, new String[]{"Harry Burns"}, 1998); + saveActsIn(actsIn, megR, whenHarryMetSally, new String[]{"Sally Albright"}, 1998); + saveActsIn(actsIn, carrieF, whenHarryMetSally, new String[]{"Marie"}, 1998); + saveActsIn(actsIn, brunoK, whenHarryMetSally, new String[]{"Jess"}, 1998); + } + + /** + * @throws ExecutionException + * @throws InterruptedException + * @see AQL + * Example Queries on an Actors and Movies Database + */ + @Test + void allActorsActsInMovie1or2() throws InterruptedException, ExecutionException { + final CompletableFuture> f = db.query( + "WITH actors, movies FOR x IN ANY 'movies/TheMatrix' actsIn OPTIONS {bfs: true, uniqueVertices: " + + "'global'} RETURN x._id", + null, null, String.class); + f.whenComplete((cursor, ex) -> assertThat(cursor.asListRemaining()).contains("actors/Keanu", "actors/Hugo", + "actors/Emil", "actors/Carrie", "actors/Laurence")).get(); + } + + /** + * @throws ExecutionException + * @throws InterruptedException + * @see AQL + * Example Queries on an Actors and Movies Database + */ + @Test + void allActorsActsInMovie1or2UnionDistinct() throws InterruptedException, ExecutionException { + final CompletableFuture> f = db.query( + "WITH actors, movies FOR x IN UNION_DISTINCT ((FOR y IN ANY 'movies/TheMatrix' actsIn OPTIONS {bfs: " + + "true, uniqueVertices: 'global'} RETURN y._id), (FOR y IN ANY 'movies/TheDevilsAdvocate' " + + "actsIn OPTIONS {bfs: true, uniqueVertices: 'global'} RETURN y._id)) RETURN x", + null, null, String.class); + f.whenComplete((cursor, ex) -> assertThat(cursor.asListRemaining()).contains( + "actors/Emil", "actors/Hugo", "actors/Carrie", + "actors/Laurence", "actors/Keanu", "actors/Al", "actors/Charlize")).get(); + } + + /** + * @throws ExecutionException + * @throws InterruptedException + * @see AQL + * Example Queries on an Actors and Movies Database + */ + @Test + void allActorsActsInMovie1and2() throws InterruptedException, ExecutionException { + final CompletableFuture> f = db.query( + "WITH actors, movies FOR x IN INTERSECTION ((FOR y IN ANY 'movies/TheMatrix' actsIn OPTIONS {bfs: " + + "true, uniqueVertices: 'global'} RETURN y._id), (FOR y IN ANY 'movies/TheDevilsAdvocate' " + + "actsIn OPTIONS {bfs: true, uniqueVertices: 'global'} RETURN y._id)) RETURN x", + null, null, String.class); + f.whenComplete((cursor, ex) -> assertThat(cursor.asListRemaining()).contains("actors/Keanu")).get(); + } + + /** + * @throws ExecutionException + * @throws InterruptedException + * @see AQL + * Example Queries on an Actors and Movies Database + */ + @Test + void allMoviesBetweenActor1andActor2() throws InterruptedException, ExecutionException { + final CompletableFuture> f = db.query( + "WITH actors, movies FOR x IN INTERSECTION ((FOR y IN ANY 'actors/Hugo' actsIn OPTIONS {bfs: true, " + + "uniqueVertices: 'global'} RETURN y._id), (FOR y IN ANY 'actors/Keanu' actsIn OPTIONS {bfs: " + + "true, uniqueVertices: 'global'} RETURN y._id)) RETURN x", + null, null, String.class); + f.whenComplete((cursor, ex) -> assertThat(cursor.asListRemaining()).contains("movies/TheMatrixRevolutions", + "movies/TheMatrixReloaded", "movies/TheMatrix")).get(); + } + + /** + * @throws ExecutionException + * @throws InterruptedException + * @see AQL + * Example Queries on an Actors and Movies Database + */ + @Test + void allActorsWhoActedIn3orMoreMovies() throws InterruptedException, ExecutionException { + final CompletableFuture> f = db.query( + "FOR x IN actsIn COLLECT actor = x._from WITH COUNT INTO counter FILTER counter >= 3 RETURN {actor: " + + "actor, movies: counter}", + null, null, Actor.class); + f.whenComplete((cursor, ex) -> assertThat(cursor.asListRemaining()).contains( + new Actor("actors/Carrie", 3), new Actor("actors/CubaG", 4), new Actor("actors/Hugo", 3), + new Actor("actors/Keanu", 4), new Actor("actors/Laurence", 3), new Actor("actors/MegR", 5), + new Actor("actors/TomC", 3), new Actor("actors/TomH", 3))).get(); + } + + /** + * @throws ExecutionException + * @throws InterruptedException + * @see AQL + * Example Queries on an Actors and Movies Database + */ + @Test + void allMoviesWhereExactly6ActorsActedIn() throws InterruptedException, ExecutionException { + final CompletableFuture> f = db.query( + "FOR x IN actsIn COLLECT movie = x._to WITH COUNT INTO counter FILTER counter == 6 RETURN movie", null, + null, String.class); + f.whenComplete((cursor, ex) -> assertThat(cursor.asListRemaining()).contains("movies/SleeplessInSeattle", + "movies/TopGun", "movies/YouveGotMail")).get(); + } + + /** + * @throws ExecutionException + * @throws InterruptedException + * @see AQL + * Example Queries on an Actors and Movies Database + */ + @Test + void theNumberOfActorsByMovie() throws InterruptedException, ExecutionException { + final CompletableFuture> f = db.query( + "FOR x IN actsIn COLLECT movie = x._to WITH COUNT INTO counter RETURN {movie: movie, actors: counter}", + null, null, Movie.class); + f.whenComplete((cursor, ex) -> assertThat(cursor.asListRemaining()).contains( + new Movie("movies/AFewGoodMen", 11), new Movie("movies/AsGoodAsItGets", 4), + new Movie("movies/JerryMaguire", 9), new Movie("movies/JoeVersustheVolcano", 3), + new Movie("movies/SleeplessInSeattle", 6), new Movie("movies/SnowFallingonCedars", 4), + new Movie("movies/StandByMe", 7), new Movie("movies/TheDevilsAdvocate", 3), + new Movie("movies/TheMatrix", 5), new Movie("movies/TheMatrixReloaded", 4), + new Movie("movies/TheMatrixRevolutions", 4), new Movie("movies/TopGun", 6), + new Movie("movies/WhatDreamsMayCome", 5), new Movie("movies/WhenHarryMetSally", 4), + new Movie("movies/YouveGotMail", 6))).get(); + } + + /** + * @throws ExecutionException + * @throws InterruptedException + * @see AQL + * Example Queries on an Actors and Movies Database + */ + @Test + void theNumberOfMoviesByActor() throws InterruptedException, ExecutionException { + final CompletableFuture> f = db.query( + "FOR x IN actsIn COLLECT actor = x._from WITH COUNT INTO counter RETURN {actor: actor, movies: " + + "counter}", + null, null, Actor.class); + f.whenComplete((cursor, ex) -> assertThat(cursor.asListRemaining()).contains( + new Actor("actors/Al", 1), new Actor("actors/AnnabellaS", 1), new Actor("actors/AnthonyE", 1), + new Actor("actors/BillPull", 1), new Actor("actors/BillyC", 1), new Actor("actors/BonnieH", 1), + new Actor("actors/BrunoK", 1), new Actor("actors/Carrie", 3), new Actor("actors/CarrieF", 1), + new Actor("actors/Charlize", 1), new Actor("actors/ChristopherG", 1), new Actor("actors/CoreyF", 1), + new Actor("actors/CubaG", 4), new Actor("actors/DaveC", 1), new Actor("actors/DemiM", 1), + new Actor("actors/Emil", 1), new Actor("actors/EthanH", 1), new Actor("actors/GregK", 2), + new Actor("actors/HelenH", 1), new Actor("actors/Hugo", 3), new Actor("actors/JackN", 2), + new Actor("actors/JamesC", 1), new Actor("actors/JamesM", 1), new Actor("actors/JayM", 1), + new Actor("actors/JerryO", 2), new Actor("actors/JohnC", 1), new Actor("actors/JonathanL", 1), + new Actor("actors/JTW", 1), new Actor("actors/Keanu", 4), new Actor("actors/KellyM", 1), + new Actor("actors/KellyP", 1), new Actor("actors/KevinB", 1), new Actor("actors/KevinP", 1), + new Actor("actors/KieferS", 2), new Actor("actors/Laurence", 3), new Actor("actors/MarshallB", 1), + new Actor("actors/MaxS", 2), new Actor("actors/MegR", 5), new Actor("actors/Nathan", 1), + new Actor("actors/NoahW", 1), new Actor("actors/ParkerP", 1), new Actor("actors/ReginaK", 1), + new Actor("actors/ReneeZ", 1), new Actor("actors/RickY", 1), new Actor("actors/RitaW", 1), + new Actor("actors/RiverP", 1), new Actor("actors/Robin", 1), new Actor("actors/RosieO", 1), + new Actor("actors/SteveZ", 1), new Actor("actors/TomC", 3), new Actor("actors/TomH", 3), + new Actor("actors/TomS", 1), new Actor("actors/ValK", 1), new Actor("actors/VictorG", 1), + new Actor("actors/WernerH", 1), new Actor("actors/WilW", 1))).get(); + } + + /** + * @throws ExecutionException + * @throws InterruptedException + * @see AQL + * Example Queries on an Actors and Movies Database + */ + @Test + void theNumberOfMoviesActedInBetween2005and2010byActor() throws InterruptedException, ExecutionException { + final CompletableFuture> f = db.query( + "FOR x IN actsIn FILTER x.year >= 1990 && x.year <= 1995 COLLECT actor = x._from WITH COUNT INTO " + + "counter RETURN {actor: actor, movies: counter}", + null, null, Actor.class); + f.whenComplete((cursor, ex) -> assertThat(cursor.asListRemaining()).contains( + new Actor("actors/BillPull", 1), new Actor("actors/ChristopherG", 1), + new Actor("actors/CubaG", 1), new Actor("actors/DemiM", 1), new Actor("actors/JackN", 1), + new Actor("actors/JamesM", 1), new Actor("actors/JTW", 1), new Actor("actors/KevinB", 1), + new Actor("actors/KieferS", 1), new Actor("actors/MegR", 2), new Actor("actors/Nathan", 1), + new Actor("actors/NoahW", 1), new Actor("actors/RitaW", 1), new Actor("actors/RosieO", 1), + new Actor("actors/TomC", 1), new Actor("actors/TomH", 2), new Actor("actors/VictorG", 1))).get(); + } + + public static class Actor { + private final String actor; + private final Integer movies; + + + @JsonCreator + public Actor(@JsonProperty("actor") final String actor, @JsonProperty("movies") final Integer movies) { + super(); + this.actor = actor; + this.movies = movies; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((actor == null) ? 0 : actor.hashCode()); + result = prime * result + ((movies == null) ? 0 : movies.hashCode()); + return result; + } + + @Override + public boolean equals(final Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + final Actor other = (Actor) obj; + if (actor == null) { + if (other.actor != null) { + return false; + } + } else if (!actor.equals(other.actor)) { + return false; + } + if (movies == null) { + return other.movies == null; + } else return movies.equals(other.movies); + } + + } + + public static class Movie { + private final String movie; + private final Integer actors; + + @JsonCreator + public Movie(@JsonProperty("movie") final String movie, @JsonProperty("actors") final Integer actors) { + super(); + this.movie = movie; + this.actors = actors; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((actors == null) ? 0 : actors.hashCode()); + result = prime * result + ((movie == null) ? 0 : movie.hashCode()); + return result; + } + + @Override + public boolean equals(final Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + final Movie other = (Movie) obj; + if (actors == null) { + if (other.actors != null) { + return false; + } + } else if (!actors.equals(other.actors)) { + return false; + } + if (movie == null) { + return other.movie == null; + } else return movie.equals(other.movie); + } + + } + +} diff --git a/shaded-integration-tests/src/test/jackson/java/com/arangodb/async/example/graph/BaseGraphTest.java b/shaded-integration-tests/src/test/jackson/java/com/arangodb/async/example/graph/BaseGraphTest.java new file mode 100644 index 000000000..8a16b9231 --- /dev/null +++ b/shaded-integration-tests/src/test/jackson/java/com/arangodb/async/example/graph/BaseGraphTest.java @@ -0,0 +1,116 @@ +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed 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. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.async.example.graph; + +import com.arangodb.DbName; +import com.arangodb.async.ArangoDBAsync; +import com.arangodb.async.ArangoDatabaseAsync; +import com.arangodb.entity.EdgeDefinition; +import com.arangodb.entity.VertexEntity; +import com.arangodb.internal.config.FileConfigPropertiesProvider; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.concurrent.ExecutionException; + +/** + * @author Mark Vollmary + */ +public abstract class BaseGraphTest { + + private static final DbName TEST_DB = DbName.of("java_driver_graph_test_db"); + private static final String GRAPH_NAME = "traversalGraph"; + private static final String EDGE_COLLECTION_NAME = "edges"; + private static final String VERTEX_COLLECTION_NAME = "circles"; + static ArangoDatabaseAsync db; + private static ArangoDBAsync arangoDB; + + @BeforeAll + static void init() throws InterruptedException, ExecutionException { + if (arangoDB == null) { + arangoDB = new ArangoDBAsync.Builder() + .loadProperties(new FileConfigPropertiesProvider()) + .build(); + } + if (arangoDB.db(TEST_DB).exists().get()) { + arangoDB.db(TEST_DB).drop().get(); + } + arangoDB.createDatabase(TEST_DB).get(); + BaseGraphTest.db = arangoDB.db(TEST_DB); + + final Collection edgeDefinitions = new ArrayList<>(); + final EdgeDefinition edgeDefinition = new EdgeDefinition().collection(EDGE_COLLECTION_NAME) + .from(VERTEX_COLLECTION_NAME).to(VERTEX_COLLECTION_NAME); + edgeDefinitions.add(edgeDefinition); + db.createGraph(GRAPH_NAME, edgeDefinitions, null).get(); + addExampleElements(); + } + + @AfterAll + static void shutdown() throws InterruptedException, ExecutionException { + arangoDB.db(TEST_DB).drop().get(); + arangoDB.shutdown(); + arangoDB = null; + } + + private static void addExampleElements() throws InterruptedException, ExecutionException { + + // Add circle circles + final VertexEntity vA = createVertex(new Circle("A", "1")); + final VertexEntity vB = createVertex(new Circle("B", "2")); + final VertexEntity vC = createVertex(new Circle("C", "3")); + final VertexEntity vD = createVertex(new Circle("D", "4")); + final VertexEntity vE = createVertex(new Circle("E", "5")); + final VertexEntity vF = createVertex(new Circle("F", "6")); + final VertexEntity vG = createVertex(new Circle("G", "7")); + final VertexEntity vH = createVertex(new Circle("H", "8")); + final VertexEntity vI = createVertex(new Circle("I", "9")); + final VertexEntity vJ = createVertex(new Circle("J", "10")); + final VertexEntity vK = createVertex(new Circle("K", "11")); + + // Add relevant edges - left branch: + saveEdge(new CircleEdge(vA.getId(), vB.getId(), false, true, "left_bar")); + saveEdge(new CircleEdge(vB.getId(), vC.getId(), false, true, "left_blarg")); + saveEdge(new CircleEdge(vC.getId(), vD.getId(), false, true, "left_blorg")); + saveEdge(new CircleEdge(vB.getId(), vE.getId(), false, true, "left_blub")); + saveEdge(new CircleEdge(vE.getId(), vF.getId(), false, true, "left_schubi")); + + // Add relevant edges - right branch: + saveEdge(new CircleEdge(vA.getId(), vG.getId(), false, true, "right_foo")); + saveEdge(new CircleEdge(vG.getId(), vH.getId(), false, true, "right_blob")); + saveEdge(new CircleEdge(vH.getId(), vI.getId(), false, true, "right_blub")); + saveEdge(new CircleEdge(vG.getId(), vJ.getId(), false, true, "right_zip")); + saveEdge(new CircleEdge(vJ.getId(), vK.getId(), false, true, "right_zup")); + } + + private static void saveEdge(final CircleEdge edge) + throws InterruptedException, ExecutionException { + db.graph(GRAPH_NAME).edgeCollection(EDGE_COLLECTION_NAME).insertEdge(edge).get(); + } + + private static VertexEntity createVertex(final Circle vertex) + throws InterruptedException, ExecutionException { + return db.graph(GRAPH_NAME).vertexCollection(VERTEX_COLLECTION_NAME).insertVertex(vertex).get(); + } + +} diff --git a/shaded-integration-tests/src/test/jackson/java/com/arangodb/async/example/graph/Circle.java b/shaded-integration-tests/src/test/jackson/java/com/arangodb/async/example/graph/Circle.java new file mode 100644 index 000000000..e828aaeb3 --- /dev/null +++ b/shaded-integration-tests/src/test/jackson/java/com/arangodb/async/example/graph/Circle.java @@ -0,0 +1,80 @@ +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed 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. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.async.example.graph; + +import com.arangodb.serde.jackson.Id; +import com.arangodb.serde.jackson.Key; +import com.arangodb.serde.jackson.Rev; + +/** + * @author a-brandt + */ +class Circle { + + @Id + private String id; + + @Key + private String key; + + @Rev + private String revision; + + private String label; + + public Circle(String key, String label) { + this.key = key; + this.label = label; + } + + public String getId() { + return id; + } + + void setId(String id) { + this.id = id; + } + + public String getKey() { + return key; + } + + void setKey(String key) { + this.key = key; + } + + public String getRevision() { + return revision; + } + + void setRevision(String revision) { + this.revision = revision; + } + + public String getLabel() { + return label; + } + + void setLabel(String label) { + this.label = label; + } + +} diff --git a/shaded-integration-tests/src/test/jackson/java/com/arangodb/async/example/graph/CircleEdge.java b/shaded-integration-tests/src/test/jackson/java/com/arangodb/async/example/graph/CircleEdge.java new file mode 100644 index 000000000..bfaa65210 --- /dev/null +++ b/shaded-integration-tests/src/test/jackson/java/com/arangodb/async/example/graph/CircleEdge.java @@ -0,0 +1,122 @@ +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed 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. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.async.example.graph; + +import com.arangodb.serde.jackson.*; + +/** + * @author a-brandt + */ +class CircleEdge { + + @Id + private String id; + + @Key + private String key; + + @Rev + private String revision; + + @From + private String from; + + @To + private String to; + + private Boolean theFalse; + private Boolean theTruth; + private String label; + + public CircleEdge(final String from, final String to, final Boolean theFalse, final Boolean theTruth, + final String label) { + this.from = from; + this.to = to; + this.theFalse = theFalse; + this.theTruth = theTruth; + this.label = label; + } + + public String getId() { + return id; + } + + void setId(String id) { + this.id = id; + } + + public String getKey() { + return key; + } + + void setKey(String key) { + this.key = key; + } + + public String getRevision() { + return revision; + } + + void setRevision(String revision) { + this.revision = revision; + } + + public String getFrom() { + return from; + } + + void setFrom(String from) { + this.from = from; + } + + public String getTo() { + return to; + } + + void setTo(String to) { + this.to = to; + } + + public Boolean getTheFalse() { + return theFalse; + } + + void setTheFalse(Boolean theFalse) { + this.theFalse = theFalse; + } + + public Boolean getTheTruth() { + return theTruth; + } + + void setTheTruth(Boolean theTruth) { + this.theTruth = theTruth; + } + + public String getLabel() { + return label; + } + + void setLabel(String label) { + this.label = label; + } + +} diff --git a/shaded-integration-tests/src/test/jackson/java/com/arangodb/async/example/graph/GraphTraversalsInAQLExampleTest.java b/shaded-integration-tests/src/test/jackson/java/com/arangodb/async/example/graph/GraphTraversalsInAQLExampleTest.java new file mode 100644 index 000000000..b3628f572 --- /dev/null +++ b/shaded-integration-tests/src/test/jackson/java/com/arangodb/async/example/graph/GraphTraversalsInAQLExampleTest.java @@ -0,0 +1,122 @@ +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed 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. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.async.example.graph; + +import com.arangodb.async.ArangoCursorAsync; +import org.junit.jupiter.api.Test; + +import java.util.Collection; +import java.util.concurrent.ExecutionException; + +import static org.assertj.core.api.Assertions.assertThat; + + +/** + * Graph traversals in AQL + * + * @author a-brandt + * @see Graph traversals in AQL + */ +class GraphTraversalsInAQLExampleTest extends BaseGraphTest { + + @Test + void queryAllVertices() throws InterruptedException, ExecutionException { + String queryString = "FOR v IN 1..3 OUTBOUND 'circles/A' GRAPH 'traversalGraph' RETURN v._key"; + ArangoCursorAsync cursor = db.query(queryString, null, null, String.class).get(); + Collection result = cursor.asListRemaining(); + assertThat(result).hasSize(10); + + queryString = "WITH circles FOR v IN 1..3 OUTBOUND 'circles/A' edges RETURN v._key"; + cursor = db.query(queryString, null, null, String.class).get(); + result = cursor.asListRemaining(); + assertThat(result).hasSize(10); + } + + @Test + void queryDepthTwo() throws InterruptedException, ExecutionException { + String queryString = "FOR v IN 2..2 OUTBOUND 'circles/A' GRAPH 'traversalGraph' return v._key"; + ArangoCursorAsync cursor = db.query(queryString, null, null, String.class).get(); + Collection result = cursor.asListRemaining(); + assertThat(result).hasSize(4); + assertThat(result).contains("C", "E", "H", "J"); + + queryString = "FOR v IN 2 OUTBOUND 'circles/A' GRAPH 'traversalGraph' return v._key"; + cursor = db.query(queryString, null, null, String.class).get(); + result = cursor.asListRemaining(); + assertThat(result).hasSize(4); + assertThat(result).contains("C", "E", "H", "J"); + } + + @Test + void queryWithFilter() throws InterruptedException, ExecutionException { + String queryString = "FOR v, e, p IN 1..3 OUTBOUND 'circles/A' GRAPH 'traversalGraph' FILTER p.vertices[1]" + + "._key != 'G' RETURN v._key"; + ArangoCursorAsync cursor = db.query(queryString, null, null, String.class).get(); + Collection result = cursor.asListRemaining(); + assertThat(result).hasSize(5); + assertThat(result).contains("B", "C", "D", "E", "F"); + + queryString = "FOR v, e, p IN 1..3 OUTBOUND 'circles/A' GRAPH 'traversalGraph' FILTER p.edges[0].label != " + + "'right_foo' RETURN v._key"; + cursor = db.query(queryString, null, null, String.class).get(); + result = cursor.asListRemaining(); + assertThat(result).hasSize(5); + assertThat(result).contains("B", "C", "D", "E", "F"); + + queryString = "FOR v,e,p IN 1..3 OUTBOUND 'circles/A' GRAPH 'traversalGraph' FILTER p.vertices[1]._key != 'G'" + + " FILTER p.edges[1].label != 'left_blub' return v._key"; + cursor = db.query(queryString, null, null, String.class).get(); + + result = cursor.asListRemaining(); + assertThat(result).hasSize(3); + assertThat(result).contains("B", "C", "D"); + + queryString = "FOR v,e,p IN 1..3 OUTBOUND 'circles/A' GRAPH 'traversalGraph' FILTER p.vertices[1]._key != 'G'" + + " AND p.edges[1].label != 'left_blub' return v._key"; + cursor = db.query(queryString, null, null, String.class).get(); + result = cursor.asListRemaining(); + assertThat(result).hasSize(3); + assertThat(result).contains("B", "C", "D"); + } + + @Test + void queryOutboundInbound() throws InterruptedException, ExecutionException { + String queryString = "FOR v IN 1..3 OUTBOUND 'circles/E' GRAPH 'traversalGraph' return v._key"; + ArangoCursorAsync cursor = db.query(queryString, null, null, String.class).get(); + Collection result = cursor.asListRemaining(); + assertThat(result).hasSize(1); + assertThat(result).contains("F"); + + queryString = "FOR v IN 1..3 INBOUND 'circles/E' GRAPH 'traversalGraph' return v._key"; + cursor = db.query(queryString, null, null, String.class).get(); + result = cursor.asListRemaining(); + assertThat(result).hasSize(2); + assertThat(result).contains("B", "A"); + + queryString = "FOR v IN 1..3 ANY 'circles/E' GRAPH 'traversalGraph' return v._key"; + cursor = db.query(queryString, null, null, String.class).get(); + + result = cursor.asListRemaining(); + assertThat(result).hasSize(6); + assertThat(result).contains("F", "B", "C", "D", "A", "G"); + } + +} diff --git a/shaded-integration-tests/src/test/jackson/java/com/arangodb/async/example/graph/ShortestPathInAQLExampleTest.java b/shaded-integration-tests/src/test/jackson/java/com/arangodb/async/example/graph/ShortestPathInAQLExampleTest.java new file mode 100644 index 000000000..515f8e13f --- /dev/null +++ b/shaded-integration-tests/src/test/jackson/java/com/arangodb/async/example/graph/ShortestPathInAQLExampleTest.java @@ -0,0 +1,106 @@ +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed 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. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.async.example.graph; + +import com.arangodb.async.ArangoCursorAsync; +import org.junit.jupiter.api.Test; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.concurrent.ExecutionException; + +import static org.assertj.core.api.Assertions.assertThat; + + +/** + * Shortest Path in AQL + * + * @author a-brandt + * @see Shortest Path in AQL + */ +class ShortestPathInAQLExampleTest extends BaseGraphTest { + + @Test + void queryShortestPathFromAToD() throws InterruptedException, ExecutionException { + String queryString = "FOR v, e IN OUTBOUND SHORTEST_PATH 'circles/A' TO 'circles/D' GRAPH 'traversalGraph' " + + "RETURN {'vertex': v._key, 'edge': e._key}"; + ArangoCursorAsync cursor = db.query(queryString, null, null, Pair.class).get(); + final Collection collection = toVertexCollection(cursor); + assertThat(collection).hasSize(4); + assertThat(collection).contains("A", "B", "C", "D"); + + queryString = "WITH circles FOR v, e IN OUTBOUND SHORTEST_PATH 'circles/A' TO 'circles/D' edges RETURN " + + "{'vertex': v._key, 'edge': e._key}"; + db.query(queryString, null, null, Pair.class).get(); + assertThat(collection).hasSize(4); + assertThat(collection).contains("A", "B", "C", "D"); + } + + @Test + void queryShortestPathByFilter() throws InterruptedException, ExecutionException { + String queryString = "FOR a IN circles FILTER a._key == 'A' FOR d IN circles FILTER d._key == 'D' FOR v, e IN" + + " OUTBOUND SHORTEST_PATH a TO d GRAPH 'traversalGraph' RETURN {'vertex':v._key, 'edge':e._key}"; + ArangoCursorAsync cursor = db.query(queryString, null, null, Pair.class).get(); + final Collection collection = toVertexCollection(cursor); + assertThat(collection).hasSize(4); + assertThat(collection).contains("A", "B", "C", "D"); + + queryString = "FOR a IN circles FILTER a._key == 'A' FOR d IN circles FILTER d._key == 'D' FOR v, e IN " + + "OUTBOUND SHORTEST_PATH a TO d edges RETURN {'vertex': v._key, 'edge': e._key}"; + db.query(queryString, null, null, Pair.class).get(); + assertThat(collection).hasSize(4); + assertThat(collection).contains("A", "B", "C", "D"); + } + + private Collection toVertexCollection(final ArangoCursorAsync cursor) { + final List result = new ArrayList<>(); + while (cursor.hasNext()) { + final Pair pair = cursor.next(); + result.add(pair.getVertex()); + } + return result; + } + + public static class Pair { + + private String vertex; + private String edge; + + public String getVertex() { + return vertex; + } + + void setVertex(final String vertex) { + this.vertex = vertex; + } + + public String getEdge() { + return edge; + } + + void setEdge(final String edge) { + this.edge = edge; + } + + } + +} diff --git a/shaded-integration-tests/src/test/jackson/java/com/arangodb/async/example/ssl/SslExampleTest.java b/shaded-integration-tests/src/test/jackson/java/com/arangodb/async/example/ssl/SslExampleTest.java new file mode 100644 index 000000000..c90175310 --- /dev/null +++ b/shaded-integration-tests/src/test/jackson/java/com/arangodb/async/example/ssl/SslExampleTest.java @@ -0,0 +1,79 @@ +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed 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. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.async.example.ssl; + +import com.arangodb.async.ArangoDBAsync; +import com.arangodb.entity.ArangoDBVersion; +import org.junit.jupiter.api.Tag; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.condition.EnabledIfSystemProperty; + +import javax.net.ssl.KeyManagerFactory; +import javax.net.ssl.SSLContext; +import javax.net.ssl.TrustManagerFactory; +import java.security.KeyStore; + +import static org.assertj.core.api.Assertions.assertThat; + + +/** + * @author Mark Vollmary + */ +@Tag("ssl") +@EnabledIfSystemProperty(named = "SslTest", matches = "true") +class SslExampleTest { + + /*- + * a SSL trust store + * + * create the trust store for the self signed certificate: + * keytool -import -alias "my arangodb server cert" -file UnitTests/server.pem -keystore example.truststore + * + * Documentation: + * https://hc.apache.org/httpcomponents-client-ga/httpclient/apidocs/org/apache/http/conn/ssl/SSLSocketFactory.html + */ + private static final String SSL_TRUSTSTORE = "/example.truststore"; + private static final String SSL_TRUSTSTORE_PASSWORD = "12345678"; + + @Test + void connect() throws Exception { + final KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType()); + ks.load(this.getClass().getResourceAsStream(SSL_TRUSTSTORE), SSL_TRUSTSTORE_PASSWORD.toCharArray()); + + final KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); + kmf.init(ks, SSL_TRUSTSTORE_PASSWORD.toCharArray()); + + final TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); + tmf.init(ks); + + final SSLContext sc = SSLContext.getInstance("TLS"); + sc.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null); + + final ArangoDBAsync arangoDB = new ArangoDBAsync.Builder() + .host("localhost", 8529) + .password("test") + .useSsl(true) + .sslContext(sc).build(); + final ArangoDBVersion version = arangoDB.getVersion().get(); + assertThat(version).isNotNull(); + } + +} diff --git a/shaded-integration-tests/src/test/jackson/java/com/arangodb/async/serde/CustomSerdeTest.java b/shaded-integration-tests/src/test/jackson/java/com/arangodb/async/serde/CustomSerdeTest.java new file mode 100644 index 000000000..c6e65ca50 --- /dev/null +++ b/shaded-integration-tests/src/test/jackson/java/com/arangodb/async/serde/CustomSerdeTest.java @@ -0,0 +1,177 @@ +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed 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. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.async.serde; + + +import com.arangodb.ContentType; +import com.arangodb.DbName; +import com.arangodb.async.ArangoCollectionAsync; +import com.arangodb.async.ArangoDBAsync; +import com.arangodb.async.ArangoDatabaseAsync; +import com.arangodb.internal.config.FileConfigPropertiesProvider; +import com.arangodb.model.DocumentCreateOptions; +import com.arangodb.serde.jackson.JacksonSerde; +import com.arangodb.serde.jackson.JacksonSerdeProvider; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import java.math.BigInteger; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; +import java.util.concurrent.ExecutionException; + +import static com.fasterxml.jackson.databind.DeserializationFeature.USE_BIG_INTEGER_FOR_INTS; +import static com.fasterxml.jackson.databind.SerializationFeature.WRITE_SINGLE_ELEM_ARRAYS_UNWRAPPED; +import static org.assertj.core.api.Assertions.assertThat; + + +/** + * @author Michele Rastelli + */ +class CustomSerdeTest { + + private static final String COLLECTION_NAME = "collection"; + + private ArangoDatabaseAsync db; + private ArangoCollectionAsync collection; + + @BeforeEach + void init() throws ExecutionException, InterruptedException { + JacksonSerde serde = new JacksonSerdeProvider().of(ContentType.VPACK); + serde.configure((mapper) -> { + mapper.configure(WRITE_SINGLE_ELEM_ARRAYS_UNWRAPPED, true); + mapper.configure(USE_BIG_INTEGER_FOR_INTS, true); + }); + ArangoDBAsync arangoDB = new ArangoDBAsync.Builder() + .loadProperties(new FileConfigPropertiesProvider()) + .serializer(serde).build(); + + DbName TEST_DB = DbName.of("custom-serde-test"); + db = arangoDB.db(TEST_DB); + if (!db.exists().get()) { + db.create().get(); + } + + collection = db.collection(COLLECTION_NAME); + if (!collection.exists().get()) { + collection.create().get(); + } + } + + @AfterEach + void shutdown() throws ExecutionException, InterruptedException { + db.drop().get(); + } + + @Test + void aqlSerialization() throws ExecutionException, InterruptedException { + String key = "test-" + UUID.randomUUID(); + + Map doc = new HashMap<>(); + doc.put("_key", key); + doc.put("arr", Collections.singletonList("hello")); + doc.put("int", 10); + + HashMap params = new HashMap<>(); + params.put("doc", doc); + params.put("@collection", COLLECTION_NAME); + + Map result = db.query( + "INSERT @doc INTO @@collection RETURN NEW", + params, + Map.class + ).get().next(); + + assertThat(result.get("arr")).isInstanceOf(String.class); + assertThat(result.get("arr")).isEqualTo("hello"); + assertThat(result.get("int")).isInstanceOf(BigInteger.class); + assertThat(result.get("int")).isEqualTo(BigInteger.valueOf(10)); + } + + @Test + void aqlDeserialization() throws ExecutionException, InterruptedException { + String key = "test-" + UUID.randomUUID(); + + Map doc = new HashMap<>(); + doc.put("_key", key); + doc.put("arr", Collections.singletonList("hello")); + doc.put("int", 10); + + collection.insertDocument(doc).get(); + + final Map result = db.query( + "RETURN DOCUMENT(@docId)", + Collections.singletonMap("docId", COLLECTION_NAME + "/" + key), + Map.class + ).get().next(); + + assertThat(result.get("arr")).isInstanceOf(String.class); + assertThat(result.get("arr")).isEqualTo("hello"); + assertThat(result.get("int")).isInstanceOf(BigInteger.class); + assertThat(result.get("int")).isEqualTo(BigInteger.valueOf(10)); + } + + @Test + void insertDocument() throws ExecutionException, InterruptedException { + String key = "test-" + UUID.randomUUID(); + + Map doc = new HashMap<>(); + doc.put("_key", key); + doc.put("arr", Collections.singletonList("hello")); + doc.put("int", 10); + + Map result = collection.insertDocument( + doc, + new DocumentCreateOptions().returnNew(true) + ).get().getNew(); + + assertThat(result.get("arr")).isInstanceOf(String.class); + assertThat(result.get("arr")).isEqualTo("hello"); + assertThat(result.get("int")).isInstanceOf(BigInteger.class); + assertThat(result.get("int")).isEqualTo(BigInteger.valueOf(10)); + } + + @Test + void getDocument() throws ExecutionException, InterruptedException { + String key = "test-" + UUID.randomUUID(); + + Map doc = new HashMap<>(); + doc.put("_key", key); + doc.put("arr", Collections.singletonList("hello")); + doc.put("int", 10); + + collection.insertDocument(doc).get(); + + final Map result = db.collection(COLLECTION_NAME).getDocument( + key, + Map.class, + null).get(); + + assertThat(result.get("arr")).isInstanceOf(String.class); + assertThat(result.get("arr")).isEqualTo("hello"); + assertThat(result.get("int")).isInstanceOf(BigInteger.class); + assertThat(result.get("int")).isEqualTo(BigInteger.valueOf(10)); + } + +} diff --git a/shaded-integration-tests/src/test/jackson/java/com/arangodb/example/ExampleBase.java b/shaded-integration-tests/src/test/jackson/java/com/arangodb/example/ExampleBase.java new file mode 100644 index 000000000..c99610836 --- /dev/null +++ b/shaded-integration-tests/src/test/jackson/java/com/arangodb/example/ExampleBase.java @@ -0,0 +1,62 @@ +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed 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. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.example; + +import com.arangodb.ArangoCollection; +import com.arangodb.ArangoDB; +import com.arangodb.ArangoDatabase; +import com.arangodb.DbName; +import com.arangodb.internal.config.FileConfigPropertiesProvider; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; + +/** + * @author Mark Vollmary + */ +public class ExampleBase { + + protected static final String COLLECTION_NAME = "json_example_collection"; + private static final String DB_NAME = "json_example_db"; + protected static ArangoDatabase db; + protected static ArangoCollection collection; + private static ArangoDB arangoDB; + + @BeforeAll + static void setUp() { + arangoDB = new ArangoDB.Builder() + .loadProperties(new FileConfigPropertiesProvider()) + .build(); + DbName dbName = DbName.of(DB_NAME); + if (arangoDB.db(dbName).exists()) + arangoDB.db(dbName).drop(); + arangoDB.createDatabase(dbName); + db = arangoDB.db(dbName); + db.createCollection(COLLECTION_NAME); + collection = db.collection(COLLECTION_NAME); + } + + @AfterAll + static void tearDown() { + db.drop(); + arangoDB.shutdown(); + } + +} diff --git a/shaded-integration-tests/src/test/jackson/java/com/arangodb/example/FirstProject.java b/shaded-integration-tests/src/test/jackson/java/com/arangodb/example/FirstProject.java new file mode 100644 index 000000000..454bfabc7 --- /dev/null +++ b/shaded-integration-tests/src/test/jackson/java/com/arangodb/example/FirstProject.java @@ -0,0 +1,134 @@ +package com.arangodb.example; + +import com.arangodb.*; +import com.arangodb.entity.BaseDocument; +import com.arangodb.entity.CollectionEntity; +import com.fasterxml.jackson.databind.JsonNode; + +import java.util.Collections; +import java.util.Map; +import java.util.UUID; + +public class FirstProject { + + public static void main(final String[] args) { + final ArangoDB arangoDB = new ArangoDB.Builder().user("root").build(); + + // create database + final DbName dbName = DbName.of("mydb"); + try { + arangoDB.createDatabase(dbName); + System.out.println("Database created: " + dbName); + } catch (final ArangoDBException e) { + System.err.println("Failed to create database: " + dbName + "; " + e.getMessage()); + } + + // create collection + final String collectionName = "firstCollection"; + try { + final CollectionEntity myArangoCollection = arangoDB.db(dbName).createCollection(collectionName); + System.out.println("Collection created: " + myArangoCollection.getName()); + } catch (final ArangoDBException e) { + System.err.println("Failed to create collection: " + collectionName + "; " + e.getMessage()); + } + + // creating a document + final BaseDocument myObject = new BaseDocument(UUID.randomUUID().toString()); + myObject.setKey("myKey"); + myObject.addAttribute("a", "Foo"); + myObject.addAttribute("b", 42); + try { + arangoDB.db(dbName).collection(collectionName).insertDocument(myObject); + System.out.println("Document created"); + } catch (final ArangoDBException e) { + System.err.println("Failed to create document. " + e.getMessage()); + } + + // read a document + try { + final BaseDocument myDocument = arangoDB.db(dbName).collection(collectionName).getDocument("myKey", + BaseDocument.class); + System.out.println("Key: " + myDocument.getKey()); + System.out.println("Attribute a: " + myDocument.getAttribute("a")); + System.out.println("Attribute b: " + myDocument.getAttribute("b")); + } catch (final ArangoDBException e) { + System.err.println("Failed to get document: myKey; " + e.getMessage()); + } + + // read a document as JsonNode + try { + final JsonNode myDocument = arangoDB.db(dbName).collection(collectionName).getDocument("myKey", + JsonNode.class); + System.out.println("Key: " + myDocument.get("_key").textValue()); + System.out.println("Attribute a: " + myDocument.get("a").textValue()); + System.out.println("Attribute b: " + myDocument.get("b").textValue()); + } catch (final ArangoDBException e) { + System.err.println("Failed to get document: myKey; " + e.getMessage()); + } + + // update a document + myObject.addAttribute("c", "Bar"); + try { + arangoDB.db(dbName).collection(collectionName).updateDocument("myKey", myObject); + } catch (final ArangoDBException e) { + System.err.println("Failed to update document. " + e.getMessage()); + } + + // read the document again + try { + final BaseDocument myUpdatedDocument = arangoDB.db(dbName).collection(collectionName).getDocument("myKey", + BaseDocument.class); + System.out.println("Key: " + myUpdatedDocument.getKey()); + System.out.println("Attribute a: " + myUpdatedDocument.getAttribute("a")); + System.out.println("Attribute b: " + myUpdatedDocument.getAttribute("b")); + System.out.println("Attribute c: " + myUpdatedDocument.getAttribute("c")); + } catch (final ArangoDBException e) { + System.err.println("Failed to get document: myKey; " + e.getMessage()); + } + + // delete a document + try { + arangoDB.db(dbName).collection(collectionName).deleteDocument("myKey"); + } catch (final ArangoDBException e) { + System.err.println("Failed to delete document. " + e.getMessage()); + } + + // create some documents for the next step + final ArangoCollection collection = arangoDB.db(dbName).collection(collectionName); + for (int i = 0; i < 10; i++) { + final BaseDocument value = new BaseDocument(UUID.randomUUID().toString()); + value.setKey(String.valueOf(i)); + value.addAttribute("name", "Homer"); + collection.insertDocument(value); + } + + // execute AQL queries + try { + final String query = "FOR t IN firstCollection FILTER t.name == @name RETURN t"; + final Map bindVars = Collections.singletonMap("name", "Homer"); + final ArangoCursor cursor = arangoDB.db(dbName).query(query, bindVars, null, + BaseDocument.class); + while (cursor.hasNext()) { + System.out.println("Key: " + cursor.next().getKey()); + } + } catch (final ArangoDBException e) { + System.err.println("Failed to execute query. " + e.getMessage()); + } + + // delete a document with AQL + try { + final String query = "FOR t IN firstCollection FILTER t.name == @name " + + "REMOVE t IN firstCollection LET removed = OLD RETURN removed"; + final Map bindVars = Collections.singletonMap("name", "Homer"); + final ArangoCursor cursor = arangoDB.db(dbName).query(query, bindVars, null, + BaseDocument.class); + while (cursor.hasNext()) { + System.out.println("Removed document " + cursor.next().getKey()); + } + } catch (final ArangoDBException e) { + System.err.println("Failed to execute query. " + e.getMessage()); + } + + } + +} diff --git a/shaded-integration-tests/src/test/jackson/java/com/arangodb/example/document/AqlQueryWithSpecialReturnTypesExampleTest.java b/shaded-integration-tests/src/test/jackson/java/com/arangodb/example/document/AqlQueryWithSpecialReturnTypesExampleTest.java new file mode 100644 index 000000000..9c9279c28 --- /dev/null +++ b/shaded-integration-tests/src/test/jackson/java/com/arangodb/example/document/AqlQueryWithSpecialReturnTypesExampleTest.java @@ -0,0 +1,132 @@ +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed 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. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.example.document; + +import com.arangodb.ArangoCursor; +import com.arangodb.entity.BaseDocument; +import com.arangodb.example.ExampleBase; +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.fasterxml.jackson.databind.node.ObjectNode; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; + +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.UUID; + +import static org.assertj.core.api.Assertions.assertThat; + + +/** + * @author Mark Vollmary + */ +class AqlQueryWithSpecialReturnTypesExampleTest extends ExampleBase { + + @BeforeAll + static void before() { + createExamples(); + } + + private static void createExamples() { + for (int i = 0; i < 100; i++) { + final BaseDocument value = new BaseDocument(UUID.randomUUID().toString()); + value.addAttribute("name", "TestUser" + i); + value.addAttribute("gender", (i % 2) == 0 ? Gender.MALE : Gender.FEMALE); + value.addAttribute("age", i + 10); + db.collection(COLLECTION_NAME).insertDocument(value); + } + } + + @Test + void aqlWithLimitQueryAsJsonObject() { + final String query = "FOR t IN " + COLLECTION_NAME + + " FILTER t.age >= 20 && t.age < 30 && t.gender == @gender RETURN t"; + final Map bindVars = Collections.singletonMap("gender", Gender.FEMALE); + final ArangoCursor cursor = db.query(query, bindVars, null, ObjectNode.class); + assertThat((Object) cursor).isNotNull(); + while (cursor.hasNext()) { + final ObjectNode vpack = cursor.next(); + assertThat(vpack.get("name").asText()) + .isIn("TestUser11", "TestUser13", "TestUser15", "TestUser17", "TestUser19"); + assertThat(vpack.get("gender").asText()).isEqualTo(Gender.FEMALE.name()); + assertThat(vpack.get("age").asInt()).isIn(21, 23, 25, 27, 29); + } + } + + @Test + void aqlWithLimitQueryAsJsonArray() { + final String query = "FOR t IN " + COLLECTION_NAME + + " FILTER t.age >= 20 && t.age < 30 && t.gender == @gender RETURN [t.name, t.gender, t.age]"; + final Map bindVars = Collections.singletonMap("gender", Gender.FEMALE); + final ArangoCursor cursor = db.query(query, bindVars, null, ArrayNode.class); + assertThat((Object) cursor).isNotNull(); + while (cursor.hasNext()) { + final ArrayNode arrNode = cursor.next(); + assertThat(arrNode.get(0).asText()) + .isIn("TestUser11", "TestUser13", "TestUser15", "TestUser17", "TestUser19"); + assertThat(arrNode.get(1).asText()).isEqualTo(Gender.FEMALE.name()); + assertThat(arrNode.get(2).asInt()).isIn(21, 23, 25, 27, 29); + } + } + + @Test + void aqlWithLimitQueryAsMap() { + final String query = "FOR t IN " + COLLECTION_NAME + + " FILTER t.age >= 20 && t.age < 30 && t.gender == @gender RETURN t"; + final Map bindVars = Collections.singletonMap("gender", Gender.FEMALE); + final ArangoCursor cursor = db.query(query, bindVars, null, Map.class); + assertThat((Object) cursor).isNotNull(); + while (cursor.hasNext()) { + final Map map = cursor.next(); + assertThat(map.get("name")).isNotNull(); + assertThat(String.valueOf(map.get("name"))) + .isIn("TestUser11", "TestUser13", "TestUser15", "TestUser17", "TestUser19"); + assertThat(map.get("gender")).isNotNull(); + assertThat(String.valueOf(map.get("gender"))).isEqualTo(Gender.FEMALE.name()); + assertThat(map.get("age")).isNotNull(); + assertThat(Long.valueOf(map.get("age").toString())).isIn(21L, 23L, 25L, 27L, 29L); + } + } + + @Test + void aqlWithLimitQueryAsList() { + final String query = "FOR t IN " + COLLECTION_NAME + + " FILTER t.age >= 20 && t.age < 30 && t.gender == @gender RETURN [t.name, t.gender, t.age]"; + final Map bindVars = Collections.singletonMap("gender", Gender.FEMALE); + final ArangoCursor cursor = db.query(query, bindVars, null, List.class); + assertThat((Object) cursor).isNotNull(); + while (cursor.hasNext()) { + final List list = cursor.next(); + assertThat(list.get(0)).isNotNull(); + assertThat(String.valueOf(list.get(0))) + .isIn("TestUser11", "TestUser13", "TestUser15", "TestUser17", "TestUser19"); + assertThat(list.get(1)).isNotNull(); + assertThat(Gender.valueOf(String.valueOf(list.get(1)))).isEqualTo(Gender.FEMALE); + assertThat(list.get(2)).isNotNull(); + assertThat(Long.valueOf(String.valueOf(list.get(2)))).isIn(21L, 23L, 25L, 27L, 29L); + } + } + + enum Gender { + MALE, FEMALE + } +} diff --git a/shaded-integration-tests/src/test/jackson/java/com/arangodb/example/document/GetDocumentExampleTest.java b/shaded-integration-tests/src/test/jackson/java/com/arangodb/example/document/GetDocumentExampleTest.java new file mode 100644 index 000000000..dc7318139 --- /dev/null +++ b/shaded-integration-tests/src/test/jackson/java/com/arangodb/example/document/GetDocumentExampleTest.java @@ -0,0 +1,98 @@ +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed 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. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.example.document; + +import com.arangodb.entity.BaseDocument; +import com.arangodb.example.ExampleBase; +import com.arangodb.util.RawBytes; +import com.arangodb.util.RawJson; +import com.fasterxml.jackson.databind.JsonNode; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; + +import java.util.Map; +import java.util.UUID; + +import static org.assertj.core.api.Assertions.assertThat; + + +/** + * @author Mark Vollmary + */ +class GetDocumentExampleTest extends ExampleBase { + + private static String key = null; + + @BeforeAll + static void before() { + final BaseDocument value = new BaseDocument(UUID.randomUUID().toString()); + value.addAttribute("foo", "bar"); + key = collection.insertDocument(value).getKey(); + } + + @Test + void getAsBean() { + final TestEntity doc = collection.getDocument(key, TestEntity.class); + assertThat(doc).isNotNull(); + assertThat(doc.getFoo()).isEqualTo("bar"); + } + + @Test + void getAsBaseDocument() { + final BaseDocument doc = collection.getDocument(key, BaseDocument.class); + assertThat(doc).isNotNull(); + assertThat(doc.getAttribute("foo")).isNotNull(); + assertThat(String.valueOf(doc.getAttribute("foo"))).isEqualTo("bar"); + } + + @Test + void getAsMap() { + final Map doc = collection.getDocument(key, Map.class); + assertThat(doc).isNotNull(); + assertThat(doc.get("foo")).isNotNull(); + assertThat(String.valueOf(doc.get("foo"))).isEqualTo("bar"); + } + + @Test + void getAsJsonNode() { + final JsonNode doc = collection.getDocument(key, JsonNode.class); + assertThat(doc).isNotNull(); + assertThat(doc.get("foo").isTextual()).isTrue(); + assertThat(doc.get("foo").asText()).isEqualTo("bar"); + } + + @Test + void getAsJson() { + final RawJson doc = collection.getDocument(key, RawJson.class); + assertThat(doc.getValue()).isNotNull() + .contains("foo") + .contains("bar"); + } + + @Test + void getAsBytes() { + final RawBytes doc = collection.getDocument(key, RawBytes.class); + assertThat(doc.getValue()).isNotNull(); + Map mapDoc = collection.getSerde().deserializeUserData(doc.getValue(), Map.class); + assertThat(mapDoc).containsEntry("foo", "bar"); + } + +} diff --git a/shaded-integration-tests/src/test/jackson/java/com/arangodb/example/document/InsertDocumentExampleTest.java b/shaded-integration-tests/src/test/jackson/java/com/arangodb/example/document/InsertDocumentExampleTest.java new file mode 100644 index 000000000..000b6ddd6 --- /dev/null +++ b/shaded-integration-tests/src/test/jackson/java/com/arangodb/example/document/InsertDocumentExampleTest.java @@ -0,0 +1,70 @@ +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed 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. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.example.document; + +import com.arangodb.entity.BaseDocument; +import com.arangodb.entity.DocumentCreateEntity; +import com.arangodb.example.ExampleBase; +import com.arangodb.util.RawJson; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ObjectNode; +import org.junit.jupiter.api.Test; + +import java.util.UUID; + +import static org.assertj.core.api.Assertions.assertThat; + + +/** + * @author Mark Vollmary + */ +class InsertDocumentExampleTest extends ExampleBase { + + @Test + void insertBean() { + final DocumentCreateEntity doc = collection.insertDocument(new TestEntity("bar")); + assertThat(doc.getKey()).isNotNull(); + } + + @Test + void insertBaseDocument() { + final BaseDocument value = new BaseDocument(UUID.randomUUID().toString()); + value.addAttribute("foo", "bar"); + final DocumentCreateEntity doc = collection.insertDocument(value); + assertThat(doc.getKey()).isNotNull(); + } + + @Test + void insertJsonNode() { + ObjectMapper mapper = new ObjectMapper(); + ObjectNode node = mapper.createObjectNode(); + node.put("foo", "bar"); + final DocumentCreateEntity doc = collection.insertDocument(node); + assertThat(doc.getKey()).isNotNull(); + } + + @Test + void insertJson() { + final DocumentCreateEntity doc = collection.insertDocument(RawJson.of("{\"foo\":\"bar\"}")); + assertThat(doc.getKey()).isNotNull(); + } + +} diff --git a/shaded-integration-tests/src/test/jackson/java/com/arangodb/example/document/TestEntity.java b/shaded-integration-tests/src/test/jackson/java/com/arangodb/example/document/TestEntity.java new file mode 100644 index 000000000..8a59c2b60 --- /dev/null +++ b/shaded-integration-tests/src/test/jackson/java/com/arangodb/example/document/TestEntity.java @@ -0,0 +1,47 @@ +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed 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. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.example.document; + +/** + * @author Mark Vollmary + */ +public class TestEntity { + + private String foo; + + public TestEntity() { + super(); + } + + public TestEntity(final String foo) { + super(); + this.foo = foo; + } + + public String getFoo() { + return foo; + } + + public void setFoo(final String foo) { + this.foo = foo; + } + +} diff --git a/shaded-integration-tests/src/test/jackson/java/com/arangodb/example/graph/AQLActorsAndMoviesExampleTest.java b/shaded-integration-tests/src/test/jackson/java/com/arangodb/example/graph/AQLActorsAndMoviesExampleTest.java new file mode 100644 index 000000000..682bed1b1 --- /dev/null +++ b/shaded-integration-tests/src/test/jackson/java/com/arangodb/example/graph/AQLActorsAndMoviesExampleTest.java @@ -0,0 +1,581 @@ +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed 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. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.example.graph; + +import com.arangodb.*; +import com.arangodb.entity.BaseDocument; +import com.arangodb.entity.BaseEdgeDocument; +import com.arangodb.entity.CollectionType; +import com.arangodb.entity.DocumentCreateEntity; +import com.arangodb.internal.config.FileConfigPropertiesProvider; +import com.arangodb.model.CollectionCreateOptions; +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; + +import java.util.UUID; + +import static org.assertj.core.api.Assertions.assertThat; + + +/** + * @author Mark Vollmary + * @see + * AQL Example Queries on an + * Actors and Movies Database + */ +class AQLActorsAndMoviesExampleTest { + + private static final DbName TEST_DB = DbName.of("actors_movies_test_db"); + private static ArangoDB arangoDB; + private static ArangoDatabase db; + + @BeforeAll + static void setUp() { + arangoDB = new ArangoDB.Builder() + .loadProperties(new FileConfigPropertiesProvider()) + .build(); + if (arangoDB.db(TEST_DB).exists()) + arangoDB.db(TEST_DB).drop(); + arangoDB.createDatabase(TEST_DB); + db = arangoDB.db(TEST_DB); + createData(); + } + + @AfterAll + static void tearDown() { + db.drop(); + arangoDB.shutdown(); + } + + private static DocumentCreateEntity saveMovie( + final ArangoCollection movies, + final String key, + final String title, + final int released, + final String tagline) { + final BaseDocument value = new BaseDocument(UUID.randomUUID().toString()); + value.setKey(key); + value.addAttribute("title", title); + value.addAttribute("released", released); + value.addAttribute("tagline", tagline); + return movies.insertDocument(value); + } + + private static DocumentCreateEntity saveActor( + final ArangoCollection actors, + final String key, + final String name, + final int born) { + final BaseDocument value = new BaseDocument(UUID.randomUUID().toString()); + value.setKey(key); + value.addAttribute("name", name); + value.addAttribute("born", born); + return actors.insertDocument(value); + } + + private static void saveActsIn( + final ArangoCollection actsIn, + final String actor, + final String movie, + final String[] roles, + final int year) { + final BaseEdgeDocument value = new BaseEdgeDocument(); + value.setFrom(actor); + value.setTo(movie); + value.addAttribute("roles", roles); + value.addAttribute("year", year); + actsIn.insertDocument(value); + } + + private static void createData() { + db.createCollection("actors"); + final ArangoCollection actors = db.collection("actors"); + db.createCollection("movies"); + final ArangoCollection movies = db.collection("movies"); + db.createCollection("actsIn", new CollectionCreateOptions().type(CollectionType.EDGES)); + final ArangoCollection actsIn = db.collection("actsIn"); + + final String theMatrix = saveMovie(movies, "TheMatrix", "The Matrix", 1999, "Welcome to the Real World") + .getId(); + final String keanu = saveActor(actors, "Keanu", "Keanu Reeves", 1964).getId(); + final String carrie = saveActor(actors, "Carrie", "Carrie-Anne Moss", 1967).getId(); + final String laurence = saveActor(actors, "Laurence", "Laurence Fishburne", 1961).getId(); + final String hugo = saveActor(actors, "Hugo", "Hugo Weaving", 1960).getId(); + final String emil = saveActor(actors, "Emil", "Emil Eifrem", 1978).getId(); + + saveActsIn(actsIn, keanu, theMatrix, new String[]{"Neo"}, 1999); + saveActsIn(actsIn, carrie, theMatrix, new String[]{"Trinity"}, 1999); + saveActsIn(actsIn, laurence, theMatrix, new String[]{"Morpheus"}, 1999); + saveActsIn(actsIn, hugo, theMatrix, new String[]{"Agent Smith"}, 1999); + saveActsIn(actsIn, emil, theMatrix, new String[]{"Emil"}, 1999); + + final String theMatrixReloaded = saveMovie(movies, "TheMatrixReloaded", "The Matrix Reloaded", 2003, + "Free your mind").getId(); + saveActsIn(actsIn, keanu, theMatrixReloaded, new String[]{"Neo"}, 2003); + saveActsIn(actsIn, carrie, theMatrixReloaded, new String[]{"Trinity"}, 2003); + saveActsIn(actsIn, laurence, theMatrixReloaded, new String[]{"Morpheus"}, 2003); + saveActsIn(actsIn, hugo, theMatrixReloaded, new String[]{"Agent Smith"}, 2003); + + final String theMatrixRevolutions = saveMovie(movies, "TheMatrixRevolutions", "The Matrix Revolutions", 2003, + "Everything that has a beginning has an end").getId(); + saveActsIn(actsIn, keanu, theMatrixRevolutions, new String[]{"Neo"}, 2003); + saveActsIn(actsIn, carrie, theMatrixRevolutions, new String[]{"Trinity"}, 2003); + saveActsIn(actsIn, laurence, theMatrixRevolutions, new String[]{"Morpheus"}, 2003); + saveActsIn(actsIn, hugo, theMatrixRevolutions, new String[]{"Agent Smith"}, 2003); + + final String theDevilsAdvocate = saveMovie(movies, "TheDevilsAdvocate", "The Devil's Advocate", 1997, + "Evil has its winning ways").getId(); + final String charlize = saveActor(actors, "Charlize", "Charlize Theron", 1975).getId(); + final String al = saveActor(actors, "Al", "Al Pacino", 1940).getId(); + saveActsIn(actsIn, keanu, theDevilsAdvocate, new String[]{"Kevin Lomax"}, 1997); + saveActsIn(actsIn, charlize, theDevilsAdvocate, new String[]{"Mary Ann Lomax"}, 1997); + saveActsIn(actsIn, al, theDevilsAdvocate, new String[]{"John Milton"}, 1997); + + final String AFewGoodMen = saveMovie(movies, "AFewGoodMen", "A Few Good Men", 1992, + "In the heart of the nation's capital, in a courthouse of the U.S. government, one man will stop at " + + "nothing to keep his honor, and one will stop at nothing to find the truth.") + .getId(); + final String tomC = saveActor(actors, "TomC", "Tom Cruise", 1962).getId(); + final String jackN = saveActor(actors, "JackN", "Jack Nicholson", 1937).getId(); + final String demiM = saveActor(actors, "DemiM", "Demi Moore", 1962).getId(); + final String kevinB = saveActor(actors, "KevinB", "Kevin Bacon", 1958).getId(); + final String kieferS = saveActor(actors, "KieferS", "Kiefer Sutherland", 1966).getId(); + final String noahW = saveActor(actors, "NoahW", "Noah Wyle", 1971).getId(); + final String cubaG = saveActor(actors, "CubaG", "Cuba Gooding Jr.", 1968).getId(); + final String kevinP = saveActor(actors, "KevinP", "Kevin Pollak", 1957).getId(); + final String jTW = saveActor(actors, "JTW", "J.T. Walsh", 1943).getId(); + final String jamesM = saveActor(actors, "JamesM", "James Marshall", 1967).getId(); + final String christopherG = saveActor(actors, "ChristopherG", "Christopher Guest", 1948).getId(); + saveActsIn(actsIn, tomC, AFewGoodMen, new String[]{"Lt. Daniel Kaffee"}, 1992); + saveActsIn(actsIn, jackN, AFewGoodMen, new String[]{"Col. Nathan R. Jessup"}, 1992); + saveActsIn(actsIn, demiM, AFewGoodMen, new String[]{"Lt. Cdr. JoAnne Galloway"}, 1992); + saveActsIn(actsIn, kevinB, AFewGoodMen, new String[]{"Capt. Jack Ross"}, 1992); + saveActsIn(actsIn, kieferS, AFewGoodMen, new String[]{"Lt. Jonathan Kendrick"}, 1992); + saveActsIn(actsIn, noahW, AFewGoodMen, new String[]{"Cpl. Jeffrey Barnes"}, 1992); + saveActsIn(actsIn, cubaG, AFewGoodMen, new String[]{"Cpl. Carl Hammaker"}, 1992); + saveActsIn(actsIn, kevinP, AFewGoodMen, new String[]{"Lt. Sam Weinberg"}, 1992); + saveActsIn(actsIn, jTW, AFewGoodMen, new String[]{"Lt. Col. Matthew Andrew Markinson"}, 1992); + saveActsIn(actsIn, jamesM, AFewGoodMen, new String[]{"Pfc. Louden Downey"}, 1992); + saveActsIn(actsIn, christopherG, AFewGoodMen, new String[]{"Dr. Stone"}, 1992); + + final String topGun = saveMovie(movies, "TopGun", "Top Gun", 1986, "I feel the need, the need for speed.") + .getId(); + final String kellyM = saveActor(actors, "KellyM", "Kelly McGillis", 1957).getId(); + final String valK = saveActor(actors, "ValK", "Val Kilmer", 1959).getId(); + final String anthonyE = saveActor(actors, "AnthonyE", "Anthony Edwards", 1962).getId(); + final String tomS = saveActor(actors, "TomS", "Tom Skerritt", 1933).getId(); + final String megR = saveActor(actors, "MegR", "Meg Ryan", 1961).getId(); + saveActsIn(actsIn, tomC, topGun, new String[]{"Maverick"}, 1986); + saveActsIn(actsIn, kellyM, topGun, new String[]{"Charlie"}, 1986); + saveActsIn(actsIn, valK, topGun, new String[]{"Iceman"}, 1986); + saveActsIn(actsIn, anthonyE, topGun, new String[]{"Goose"}, 1986); + saveActsIn(actsIn, tomS, topGun, new String[]{"Viper"}, 1986); + saveActsIn(actsIn, megR, topGun, new String[]{"Carole"}, 1986); + + final String jerryMaguire = saveMovie(movies, "JerryMaguire", "Jerry Maguire", 2000, + "The rest of his life begins now.").getId(); + final String reneeZ = saveActor(actors, "ReneeZ", "Renee Zellweger", 1969).getId(); + final String kellyP = saveActor(actors, "KellyP", "Kelly Preston", 1962).getId(); + final String jerryO = saveActor(actors, "JerryO", "Jerry O'Connell", 1974).getId(); + final String jayM = saveActor(actors, "JayM", "Jay Mohr", 1970).getId(); + final String bonnieH = saveActor(actors, "BonnieH", "Bonnie Hunt", 1961).getId(); + final String reginaK = saveActor(actors, "ReginaK", "Regina King", 1971).getId(); + final String jonathanL = saveActor(actors, "JonathanL", "Jonathan Lipnicki", 1996).getId(); + saveActsIn(actsIn, tomC, jerryMaguire, new String[]{"Jerry Maguire"}, 2000); + saveActsIn(actsIn, cubaG, jerryMaguire, new String[]{"Rod Tidwell"}, 2000); + saveActsIn(actsIn, reneeZ, jerryMaguire, new String[]{"Dorothy Boyd"}, 2000); + saveActsIn(actsIn, kellyP, jerryMaguire, new String[]{"Avery Bishop"}, 2000); + saveActsIn(actsIn, jerryO, jerryMaguire, new String[]{"Frank Cushman"}, 2000); + saveActsIn(actsIn, jayM, jerryMaguire, new String[]{"Bob Sugar"}, 2000); + saveActsIn(actsIn, bonnieH, jerryMaguire, new String[]{"Laurel Boyd"}, 2000); + saveActsIn(actsIn, reginaK, jerryMaguire, new String[]{"Marcee Tidwell"}, 2000); + saveActsIn(actsIn, jonathanL, jerryMaguire, new String[]{"Ray Boyd"}, 2000); + + final String standByMe = saveMovie(movies, "StandByMe", "Stand By Me", 1986, + "For some, it's the last real taste of innocence, and the first real taste of life. But for everyone," + + " it's the time that memories are made of.") + .getId(); + final String riverP = saveActor(actors, "RiverP", "River Phoenix", 1970).getId(); + final String coreyF = saveActor(actors, "CoreyF", "Corey Feldman", 1971).getId(); + final String wilW = saveActor(actors, "WilW", "Wil Wheaton", 1972).getId(); + final String johnC = saveActor(actors, "JohnC", "John Cusack", 1966).getId(); + final String marshallB = saveActor(actors, "MarshallB", "Marshall Bell", 1942).getId(); + saveActsIn(actsIn, wilW, standByMe, new String[]{"Gordie Lachance"}, 1986); + saveActsIn(actsIn, riverP, standByMe, new String[]{"Chris Chambers"}, 1986); + saveActsIn(actsIn, jerryO, standByMe, new String[]{"Vern Tessio"}, 1986); + saveActsIn(actsIn, coreyF, standByMe, new String[]{"Teddy Duchamp"}, 1986); + saveActsIn(actsIn, johnC, standByMe, new String[]{"Denny Lachance"}, 1986); + saveActsIn(actsIn, kieferS, standByMe, new String[]{"Ace Merrill"}, 1986); + saveActsIn(actsIn, marshallB, standByMe, new String[]{"Mr. Lachance"}, 1986); + + final String asGoodAsItGets = saveMovie(movies, "AsGoodAsItGets", "As Good as It Gets", 1997, + "A comedy from the heart that goes for the throat.").getId(); + final String helenH = saveActor(actors, "HelenH", "Helen Hunt", 1963).getId(); + final String gregK = saveActor(actors, "GregK", "Greg Kinnear", 1963).getId(); + saveActsIn(actsIn, jackN, asGoodAsItGets, new String[]{"Melvin Udall"}, 1997); + saveActsIn(actsIn, helenH, asGoodAsItGets, new String[]{"Carol Connelly"}, 1997); + saveActsIn(actsIn, gregK, asGoodAsItGets, new String[]{"Simon Bishop"}, 1997); + saveActsIn(actsIn, cubaG, asGoodAsItGets, new String[]{"Frank Sachs"}, 1997); + + final String whatDreamsMayCome = saveMovie(movies, "WhatDreamsMayCome", "What Dreams May Come", 1998, + "After life there is more. The end is just the beginning.").getId(); + final String annabellaS = saveActor(actors, "AnnabellaS", "Annabella Sciorra", 1960).getId(); + final String maxS = saveActor(actors, "MaxS", "Max von Sydow", 1929).getId(); + final String wernerH = saveActor(actors, "WernerH", "Werner Herzog", 1942).getId(); + final String robin = saveActor(actors, "Robin", "Robin Williams", 1951).getId(); + saveActsIn(actsIn, robin, whatDreamsMayCome, new String[]{"Chris Nielsen"}, 1998); + saveActsIn(actsIn, cubaG, whatDreamsMayCome, new String[]{"Albert Lewis"}, 1998); + saveActsIn(actsIn, annabellaS, whatDreamsMayCome, new String[]{"Annie Collins-Nielsen"}, 1998); + saveActsIn(actsIn, maxS, whatDreamsMayCome, new String[]{"The Tracker"}, 1998); + saveActsIn(actsIn, wernerH, whatDreamsMayCome, new String[]{"The Face"}, 1998); + + final String snowFallingonCedars = saveMovie(movies, "SnowFallingonCedars", "Snow Falling on Cedars", 1999, + "First loves last. Forever.").getId(); + final String ethanH = saveActor(actors, "EthanH", "Ethan Hawke", 1970).getId(); + final String rickY = saveActor(actors, "RickY", "Rick Yune", 1971).getId(); + final String jamesC = saveActor(actors, "JamesC", "James Cromwell", 1940).getId(); + saveActsIn(actsIn, ethanH, snowFallingonCedars, new String[]{"Ishmael Chambers"}, 1999); + saveActsIn(actsIn, rickY, snowFallingonCedars, new String[]{"Kazuo Miyamoto"}, 1999); + saveActsIn(actsIn, maxS, snowFallingonCedars, new String[]{"Nels Gudmundsson"}, 1999); + saveActsIn(actsIn, jamesC, snowFallingonCedars, new String[]{"Judge Fielding"}, 1999); + + final String youveGotMail = saveMovie(movies, "YouveGotMail", "You've Got Mail", 1998, + "At odds in life... in love on-line.").getId(); + final String parkerP = saveActor(actors, "ParkerP", "Parker Posey", 1968).getId(); + final String daveC = saveActor(actors, "DaveC", "Dave Chappelle", 1973).getId(); + final String steveZ = saveActor(actors, "SteveZ", "Steve Zahn", 1967).getId(); + final String tomH = saveActor(actors, "TomH", "Tom Hanks", 1956).getId(); + saveActsIn(actsIn, tomH, youveGotMail, new String[]{"Joe Fox"}, 1998); + saveActsIn(actsIn, megR, youveGotMail, new String[]{"Kathleen Kelly"}, 1998); + saveActsIn(actsIn, gregK, youveGotMail, new String[]{"Frank Navasky"}, 1998); + saveActsIn(actsIn, parkerP, youveGotMail, new String[]{"Patricia Eden"}, 1998); + saveActsIn(actsIn, daveC, youveGotMail, new String[]{"Kevin Jackson"}, 1998); + saveActsIn(actsIn, steveZ, youveGotMail, new String[]{"George Pappas"}, 1998); + + final String sleeplessInSeattle = saveMovie(movies, "SleeplessInSeattle", "Sleepless in Seattle", 1993, + "What if someone you never met, someone you never saw, someone you never knew was the only someone " + + "for you?") + .getId(); + final String ritaW = saveActor(actors, "RitaW", "Rita Wilson", 1956).getId(); + final String billPull = saveActor(actors, "BillPull", "Bill Pullman", 1953).getId(); + final String victorG = saveActor(actors, "VictorG", "Victor Garber", 1949).getId(); + final String rosieO = saveActor(actors, "RosieO", "Rosie O'Donnell", 1962).getId(); + saveActsIn(actsIn, tomH, sleeplessInSeattle, new String[]{"Sam Baldwin"}, 1993); + saveActsIn(actsIn, megR, sleeplessInSeattle, new String[]{"Annie Reed"}, 1993); + saveActsIn(actsIn, ritaW, sleeplessInSeattle, new String[]{"Suzy"}, 1993); + saveActsIn(actsIn, billPull, sleeplessInSeattle, new String[]{"Walter"}, 1993); + saveActsIn(actsIn, victorG, sleeplessInSeattle, new String[]{"Greg"}, 1993); + saveActsIn(actsIn, rosieO, sleeplessInSeattle, new String[]{"Becky"}, 1993); + + final String joeVersustheVolcano = saveMovie(movies, "JoeVersustheVolcano", "Joe Versus the Volcano", 1990, + "A story of love, lava and burning desire.").getId(); + final String nathan = saveActor(actors, "Nathan", "Nathan Lane", 1956).getId(); + saveActsIn(actsIn, tomH, joeVersustheVolcano, new String[]{"Joe Banks"}, 1990); + saveActsIn(actsIn, megR, joeVersustheVolcano, + new String[]{"DeDe', 'Angelica Graynamore', 'Patricia Graynamore"}, 1990); + saveActsIn(actsIn, nathan, joeVersustheVolcano, new String[]{"Baw"}, 1990); + + final String whenHarryMetSally = saveMovie(movies, "WhenHarryMetSally", "When Harry Met Sally", 1998, + "At odds in life... in love on-line.").getId(); + final String billyC = saveActor(actors, "BillyC", "Billy Crystal", 1948).getId(); + final String carrieF = saveActor(actors, "CarrieF", "Carrie Fisher", 1956).getId(); + final String brunoK = saveActor(actors, "BrunoK", "Bruno Kirby", 1949).getId(); + saveActsIn(actsIn, billyC, whenHarryMetSally, new String[]{"Harry Burns"}, 1998); + saveActsIn(actsIn, megR, whenHarryMetSally, new String[]{"Sally Albright"}, 1998); + saveActsIn(actsIn, carrieF, whenHarryMetSally, new String[]{"Marie"}, 1998); + saveActsIn(actsIn, brunoK, whenHarryMetSally, new String[]{"Jess"}, 1998); + } + + /** + * @see AQL + * Example Queries on an Actors and Movies Database + */ + @Test + void allActorsActsInMovie1or2() { + final ArangoCursor cursor = db.query( + "WITH actors, movies FOR x IN ANY 'movies/TheMatrix' actsIn OPTIONS {bfs: true, uniqueVertices: " + + "'global'} RETURN x._id", + null, null, String.class); + assertThat(cursor.asListRemaining()) + .contains("actors/Keanu", "actors/Hugo", "actors/Emil", "actors/Carrie", "actors/Laurence"); + } + + /** + * @see AQL + * Example Queries on an Actors and Movies Database + */ + @Test + void allActorsActsInMovie1or2UnionDistinct() { + final ArangoCursor cursor = db.query( + "WITH actors, movies FOR x IN UNION_DISTINCT ((FOR y IN ANY 'movies/TheMatrix' actsIn OPTIONS {bfs: " + + "true, uniqueVertices: 'global'} RETURN y._id), (FOR y IN ANY 'movies/TheDevilsAdvocate' " + + "actsIn OPTIONS {bfs: true, uniqueVertices: 'global'} RETURN y._id)) RETURN x", + null, null, String.class); + assertThat(cursor.asListRemaining()).contains("actors/Emil", "actors/Hugo", "actors/Carrie", "actors/Laurence", + "actors/Keanu", "actors/Al", "actors/Charlize"); + } + + /** + * @see AQL + * Example Queries on an Actors and Movies Database + */ + @Test + void allActorsActsInMovie1and2() { + final ArangoCursor cursor = db.query( + "WITH actors, movies FOR x IN INTERSECTION ((FOR y IN ANY 'movies/TheMatrix' actsIn OPTIONS {bfs: " + + "true, uniqueVertices: 'global'} RETURN y._id), (FOR y IN ANY 'movies/TheDevilsAdvocate' " + + "actsIn OPTIONS {bfs: true, uniqueVertices: 'global'} RETURN y._id)) RETURN x", + null, null, String.class); + assertThat(cursor.asListRemaining()).contains("actors/Keanu"); + } + + /** + * @see AQL + * Example Queries on an Actors and Movies Database + */ + @Test + void allMoviesBetweenActor1andActor2() { + final ArangoCursor cursor = db.query( + "WITH actors, movies FOR x IN INTERSECTION ((FOR y IN ANY 'actors/Hugo' actsIn OPTIONS {bfs: true, " + + "uniqueVertices: 'global'} RETURN y._id), (FOR y IN ANY 'actors/Keanu' actsIn OPTIONS {bfs: " + + "true, uniqueVertices: 'global'} RETURN y._id)) RETURN x", + null, null, String.class); + assertThat(cursor.asListRemaining()) + .contains("movies/TheMatrixRevolutions", "movies/TheMatrixReloaded", "movies/TheMatrix"); + } + + /** + * @see AQL + * Example Queries on an Actors and Movies Database + */ + @Test + void allActorsWhoActedIn3orMoreMovies() { + final ArangoCursor cursor = db.query( + "FOR x IN actsIn COLLECT actor = x._from WITH COUNT INTO counter FILTER counter >= 3 RETURN {actor: " + + "actor, movies: counter}", + null, null, Actor.class); + assertThat(cursor.asListRemaining()) + .contains(new Actor("actors/Carrie", 3), new Actor("actors/CubaG", 4), new Actor("actors/Hugo", 3), + new Actor("actors/Keanu", 4), new Actor("actors/Laurence", 3), new Actor("actors/MegR", 5), + new Actor("actors/TomC", 3), new Actor("actors/TomH", 3)); + } + + /** + * @see AQL + * Example Queries on an Actors and Movies Database + */ + @Test + void allMoviesWhereExactly6ActorsActedIn() { + final ArangoCursor cursor = db.query( + "FOR x IN actsIn COLLECT movie = x._to WITH COUNT INTO counter FILTER counter == 6 RETURN movie", null, + null, String.class); + assertThat(cursor.asListRemaining()) + .contains("movies/SleeplessInSeattle", "movies/TopGun", "movies/YouveGotMail"); + } + + /** + * @see AQL + * Example Queries on an Actors and Movies Database + */ + @Test + void theNumberOfActorsByMovie() { + final ArangoCursor cursor = db.query( + "FOR x IN actsIn COLLECT movie = x._to WITH COUNT INTO counter RETURN {movie: movie, actors: counter}", + null, null, Movie.class); + assertThat(cursor.asListRemaining()) + .contains(new Movie("movies/AFewGoodMen", 11), new Movie("movies/AsGoodAsItGets", 4), + new Movie("movies/JerryMaguire", 9), new Movie("movies/JoeVersustheVolcano", 3), + new Movie("movies/SleeplessInSeattle", 6), new Movie("movies/SnowFallingonCedars", 4), + new Movie("movies/StandByMe", 7), new Movie("movies/TheDevilsAdvocate", 3), + new Movie("movies/TheMatrix", 5), new Movie("movies/TheMatrixReloaded", 4), + new Movie("movies/TheMatrixRevolutions", 4), new Movie("movies/TopGun", 6), + new Movie("movies/WhatDreamsMayCome", 5), new Movie("movies/WhenHarryMetSally", 4), + new Movie("movies/YouveGotMail", 6)); + } + + /** + * @see AQL + * Example Queries on an Actors and Movies Database + */ + @Test + void theNumberOfMoviesByActor() { + final ArangoCursor cursor = db.query( + "FOR x IN actsIn COLLECT actor = x._from WITH COUNT INTO counter RETURN {actor: actor, movies: " + + "counter}", + null, null, Actor.class); + assertThat(cursor.asListRemaining()) + .contains(new Actor("actors/Al", 1), new Actor("actors/AnnabellaS", 1), new Actor("actors/AnthonyE", 1), + new Actor("actors/BillPull", 1), new Actor("actors/BillyC", 1), new Actor("actors/BonnieH", 1), + new Actor("actors/BrunoK", 1), new Actor("actors/Carrie", 3), new Actor("actors/CarrieF", 1), + new Actor("actors/Charlize", 1), new Actor("actors/ChristopherG", 1), new Actor("actors" + + "/CoreyF", 1), + new Actor("actors/CubaG", 4), new Actor("actors/DaveC", 1), new Actor("actors/DemiM", 1), + new Actor("actors/Emil", 1), new Actor("actors/EthanH", 1), new Actor("actors/GregK", 2), + new Actor("actors/HelenH", 1), new Actor("actors/Hugo", 3), new Actor("actors/JackN", 2), + new Actor("actors/JamesC", 1), new Actor("actors/JamesM", 1), new Actor("actors/JayM", 1), + new Actor("actors/JerryO", 2), new Actor("actors/JohnC", 1), new Actor("actors/JonathanL", 1), + new Actor("actors/JTW", 1), new Actor("actors/Keanu", 4), new Actor("actors/KellyM", 1), + new Actor("actors/KellyP", 1), new Actor("actors/KevinB", 1), new Actor("actors/KevinP", 1), + new Actor("actors/KieferS", 2), new Actor("actors/Laurence", 3), new Actor("actors/MarshallB" + , 1), + new Actor("actors/MaxS", 2), new Actor("actors/MegR", 5), new Actor("actors/Nathan", 1), + new Actor("actors/NoahW", 1), new Actor("actors/ParkerP", 1), new Actor("actors/ReginaK", 1), + new Actor("actors/ReneeZ", 1), new Actor("actors/RickY", 1), new Actor("actors/RitaW", 1), + new Actor("actors/RiverP", 1), new Actor("actors/Robin", 1), new Actor("actors/RosieO", 1), + new Actor("actors/SteveZ", 1), new Actor("actors/TomC", 3), new Actor("actors/TomH", 3), + new Actor("actors/TomS", 1), new Actor("actors/ValK", 1), new Actor("actors/VictorG", 1), + new Actor("actors/WernerH", 1), new Actor("actors/WilW", 1)); + } + + /** + * @see AQL + * Example Queries on an Actors and Movies Database + */ + @Test + void theNumberOfMoviesActedInBetween2005and2010byActor() { + final ArangoCursor cursor = db.query( + "FOR x IN actsIn FILTER x.year >= 1990 && x.year <= 1995 COLLECT actor = x._from WITH COUNT INTO " + + "counter RETURN {actor: actor, movies: counter}", + null, null, Actor.class); + assertThat(cursor.asListRemaining()) + .contains(new Actor("actors/BillPull", 1), new Actor("actors/ChristopherG", 1), new Actor("actors" + + "/CubaG", 1), + new Actor("actors/DemiM", 1), new Actor("actors/JackN", 1), new Actor("actors/JamesM", 1), + new Actor("actors/JTW", 1), new Actor("actors/KevinB", 1), new Actor("actors/KieferS", 1), + new Actor("actors/MegR", 2), new Actor("actors/Nathan", 1), new Actor("actors/NoahW", 1), + new Actor("actors/RitaW", 1), new Actor("actors/RosieO", 1), new Actor("actors/TomC", 1), + new Actor("actors/TomH", 2), new Actor("actors/VictorG", 1)); + } + + public static class Actor { + private final String actor; + private final Integer movies; + + @JsonCreator + Actor(@JsonProperty("actor") final String actor, @JsonProperty("movies") final Integer movies) { + super(); + this.actor = actor; + this.movies = movies; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((actor == null) ? 0 : actor.hashCode()); + result = prime * result + ((movies == null) ? 0 : movies.hashCode()); + return result; + } + + @Override + public boolean equals(final Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + final Actor other = (Actor) obj; + if (actor == null) { + if (other.actor != null) { + return false; + } + } else if (!actor.equals(other.actor)) { + return false; + } + if (movies == null) { + return other.movies == null; + } else return movies.equals(other.movies); + } + + } + + public static class Movie { + private final String movie; + private final Integer actors; + + @JsonCreator + public Movie(@JsonProperty("movie") final String movie, @JsonProperty("actors") final Integer actors) { + super(); + this.movie = movie; + this.actors = actors; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((actors == null) ? 0 : actors.hashCode()); + result = prime * result + ((movie == null) ? 0 : movie.hashCode()); + return result; + } + + @Override + public boolean equals(final Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + final Movie other = (Movie) obj; + if (actors == null) { + if (other.actors != null) { + return false; + } + } else if (!actors.equals(other.actors)) { + return false; + } + if (movie == null) { + return other.movie == null; + } else return movie.equals(other.movie); + } + + } + +} diff --git a/shaded-integration-tests/src/test/jackson/java/com/arangodb/example/graph/BaseGraphTest.java b/shaded-integration-tests/src/test/jackson/java/com/arangodb/example/graph/BaseGraphTest.java new file mode 100644 index 000000000..514af943f --- /dev/null +++ b/shaded-integration-tests/src/test/jackson/java/com/arangodb/example/graph/BaseGraphTest.java @@ -0,0 +1,114 @@ +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed 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. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.example.graph; + +import com.arangodb.ArangoDB; +import com.arangodb.ArangoDBException; +import com.arangodb.ArangoDatabase; +import com.arangodb.DbName; +import com.arangodb.entity.EdgeDefinition; +import com.arangodb.entity.VertexEntity; +import com.arangodb.internal.config.FileConfigPropertiesProvider; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; + +import java.util.ArrayList; +import java.util.Collection; + +/** + * @author Mark Vollmary + */ +abstract class BaseGraphTest { + + private static final DbName TEST_DB = DbName.of("java_driver_graph_test_db"); + private static final String GRAPH_NAME = "traversalGraph"; + private static final String EDGE_COLLECTION_NAME = "edges"; + private static final String VERTEX_COLLECTION_NAME = "circles"; + static ArangoDatabase db; + private static ArangoDB arangoDB; + + @BeforeAll + static void init() { + if (arangoDB == null) { + arangoDB = new ArangoDB.Builder() + .loadProperties(new FileConfigPropertiesProvider()) + .build(); + } + if (arangoDB.db(TEST_DB).exists()) + arangoDB.db(TEST_DB).drop(); + arangoDB.createDatabase(TEST_DB); + BaseGraphTest.db = arangoDB.db(TEST_DB); + + final Collection edgeDefinitions = new ArrayList<>(); + final EdgeDefinition edgeDefinition = new EdgeDefinition().collection(EDGE_COLLECTION_NAME) + .from(VERTEX_COLLECTION_NAME).to(VERTEX_COLLECTION_NAME); + edgeDefinitions.add(edgeDefinition); + if (!db.graph(GRAPH_NAME).exists()) + db.createGraph(GRAPH_NAME, edgeDefinitions, null); + addExampleElements(); + } + + @AfterAll + static void shutdown() { + arangoDB.db(TEST_DB).drop(); + arangoDB.shutdown(); + arangoDB = null; + } + + private static void addExampleElements() throws ArangoDBException { + + // Add circle circles + final VertexEntity vA = createVertex(new Circle("A", "1")); + final VertexEntity vB = createVertex(new Circle("B", "2")); + final VertexEntity vC = createVertex(new Circle("C", "3")); + final VertexEntity vD = createVertex(new Circle("D", "4")); + final VertexEntity vE = createVertex(new Circle("E", "5")); + final VertexEntity vF = createVertex(new Circle("F", "6")); + final VertexEntity vG = createVertex(new Circle("G", "7")); + final VertexEntity vH = createVertex(new Circle("H", "8")); + final VertexEntity vI = createVertex(new Circle("I", "9")); + final VertexEntity vJ = createVertex(new Circle("J", "10")); + final VertexEntity vK = createVertex(new Circle("K", "11")); + + // Add relevant edges - left branch: + saveEdge(new CircleEdge(vA.getId(), vB.getId(), false, true, "left_bar")); + saveEdge(new CircleEdge(vB.getId(), vC.getId(), false, true, "left_blarg")); + saveEdge(new CircleEdge(vC.getId(), vD.getId(), false, true, "left_blorg")); + saveEdge(new CircleEdge(vB.getId(), vE.getId(), false, true, "left_blub")); + saveEdge(new CircleEdge(vE.getId(), vF.getId(), false, true, "left_schubi")); + + // Add relevant edges - right branch: + saveEdge(new CircleEdge(vA.getId(), vG.getId(), false, true, "right_foo")); + saveEdge(new CircleEdge(vG.getId(), vH.getId(), false, true, "right_blob")); + saveEdge(new CircleEdge(vH.getId(), vI.getId(), false, true, "right_blub")); + saveEdge(new CircleEdge(vG.getId(), vJ.getId(), false, true, "right_zip")); + saveEdge(new CircleEdge(vJ.getId(), vK.getId(), false, true, "right_zup")); + } + + private static void saveEdge(final CircleEdge edge) throws ArangoDBException { + db.graph(GRAPH_NAME).edgeCollection(EDGE_COLLECTION_NAME).insertEdge(edge); + } + + private static VertexEntity createVertex(final Circle vertex) throws ArangoDBException { + return db.graph(GRAPH_NAME).vertexCollection(VERTEX_COLLECTION_NAME).insertVertex(vertex); + } + +} diff --git a/shaded-integration-tests/src/test/jackson/java/com/arangodb/example/graph/Circle.java b/shaded-integration-tests/src/test/jackson/java/com/arangodb/example/graph/Circle.java new file mode 100644 index 000000000..f40783bdd --- /dev/null +++ b/shaded-integration-tests/src/test/jackson/java/com/arangodb/example/graph/Circle.java @@ -0,0 +1,80 @@ +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed 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. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.example.graph; + +import com.arangodb.serde.jackson.Id; +import com.arangodb.serde.jackson.Key; +import com.arangodb.serde.jackson.Rev; + +/** + * @author a-brandt + */ +class Circle { + + @Id + private String id; + + @Key + private String key; + + @Rev + private String revision; + + private String label; + + public Circle(String key, String label) { + this.key = key; + this.label = label; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getKey() { + return key; + } + + public void setKey(String key) { + this.key = key; + } + + public String getRevision() { + return revision; + } + + public void setRevision(String revision) { + this.revision = revision; + } + + public String getLabel() { + return label; + } + + public void setLabel(String label) { + this.label = label; + } + +} diff --git a/shaded-integration-tests/src/test/jackson/java/com/arangodb/example/graph/CircleEdge.java b/shaded-integration-tests/src/test/jackson/java/com/arangodb/example/graph/CircleEdge.java new file mode 100644 index 000000000..96afa9f00 --- /dev/null +++ b/shaded-integration-tests/src/test/jackson/java/com/arangodb/example/graph/CircleEdge.java @@ -0,0 +1,122 @@ +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed 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. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.example.graph; + +import com.arangodb.serde.jackson.*; + +/** + * @author a-brandt + */ +class CircleEdge { + + @Id + private String id; + + @Key + private String key; + + @Rev + private String revision; + + @From + private String from; + + @To + private String to; + + private Boolean theFalse; + private Boolean theTruth; + private String label; + + public CircleEdge(final String from, final String to, final Boolean theFalse, final Boolean theTruth, + final String label) { + this.from = from; + this.to = to; + this.theFalse = theFalse; + this.theTruth = theTruth; + this.label = label; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getKey() { + return key; + } + + public void setKey(String key) { + this.key = key; + } + + public String getRevision() { + return revision; + } + + public void setRevision(String revision) { + this.revision = revision; + } + + public String getFrom() { + return from; + } + + public void setFrom(String from) { + this.from = from; + } + + public String getTo() { + return to; + } + + public void setTo(String to) { + this.to = to; + } + + public Boolean getTheFalse() { + return theFalse; + } + + public void setTheFalse(Boolean theFalse) { + this.theFalse = theFalse; + } + + public Boolean getTheTruth() { + return theTruth; + } + + public void setTheTruth(Boolean theTruth) { + this.theTruth = theTruth; + } + + public String getLabel() { + return label; + } + + public void setLabel(String label) { + this.label = label; + } + +} diff --git a/shaded-integration-tests/src/test/jackson/java/com/arangodb/example/graph/GraphTraversalsInAQLExampleTest.java b/shaded-integration-tests/src/test/jackson/java/com/arangodb/example/graph/GraphTraversalsInAQLExampleTest.java new file mode 100644 index 000000000..94e48a307 --- /dev/null +++ b/shaded-integration-tests/src/test/jackson/java/com/arangodb/example/graph/GraphTraversalsInAQLExampleTest.java @@ -0,0 +1,113 @@ +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed 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. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.example.graph; + +import com.arangodb.ArangoCursor; +import com.arangodb.ArangoDBException; +import org.junit.jupiter.api.Test; + +import java.util.Collection; + +import static org.assertj.core.api.Assertions.assertThat; + + +/** + * Graph traversals in AQL + * + * @author a-brandt + * @see Graph traversals in AQL + */ +class GraphTraversalsInAQLExampleTest extends BaseGraphTest { + + @Test + void queryAllVertices() throws ArangoDBException { + String queryString = "FOR v IN 1..3 OUTBOUND 'circles/A' GRAPH 'traversalGraph' RETURN v._key"; + ArangoCursor cursor = db.query(queryString, null, null, String.class); + Collection result = cursor.asListRemaining(); + assertThat(result).hasSize(10); + + queryString = "WITH circles FOR v IN 1..3 OUTBOUND 'circles/A' edges RETURN v._key"; + cursor = db.query(queryString, null, null, String.class); + result = cursor.asListRemaining(); + assertThat(result).hasSize(10); + } + + @Test + void queryDepthTwo() throws ArangoDBException { + String queryString = "FOR v IN 2..2 OUTBOUND 'circles/A' GRAPH 'traversalGraph' return v._key"; + ArangoCursor cursor = db.query(queryString, null, null, String.class); + Collection result = cursor.asListRemaining(); + assertThat(result).containsExactlyInAnyOrder("C", "E", "H", "J"); + + queryString = "FOR v IN 2 OUTBOUND 'circles/A' GRAPH 'traversalGraph' return v._key"; + cursor = db.query(queryString, null, null, String.class); + result = cursor.asListRemaining(); + assertThat(result).containsExactlyInAnyOrder("C", "E", "H", "J"); + } + + @Test + void queryWithFilter() throws ArangoDBException { + String queryString = "FOR v, e, p IN 1..3 OUTBOUND 'circles/A' GRAPH 'traversalGraph' FILTER p.vertices[1]" + + "._key != 'G' RETURN v._key"; + ArangoCursor cursor = db.query(queryString, null, null, String.class); + Collection result = cursor.asListRemaining(); + assertThat(result).containsExactlyInAnyOrder("B", "C", "D", "E", "F"); + + queryString = "FOR v, e, p IN 1..3 OUTBOUND 'circles/A' GRAPH 'traversalGraph' FILTER p.edges[0].label != " + + "'right_foo' RETURN v._key"; + cursor = db.query(queryString, null, null, String.class); + result = cursor.asListRemaining(); + assertThat(result).containsExactlyInAnyOrder("B", "C", "D", "E", "F"); + + queryString = "FOR v,e,p IN 1..3 OUTBOUND 'circles/A' GRAPH 'traversalGraph' FILTER p.vertices[1]._key != 'G'" + + " FILTER p.edges[1].label != 'left_blub' return v._key"; + cursor = db.query(queryString, null, null, String.class); + + result = cursor.asListRemaining(); + assertThat(result).containsExactlyInAnyOrder("B", "C", "D"); + + queryString = "FOR v,e,p IN 1..3 OUTBOUND 'circles/A' GRAPH 'traversalGraph' FILTER p.vertices[1]._key != 'G'" + + " AND p.edges[1].label != 'left_blub' return v._key"; + cursor = db.query(queryString, null, null, String.class); + result = cursor.asListRemaining(); + assertThat(result).containsExactlyInAnyOrder("B", "C", "D"); + } + + @Test + void queryOutboundInbound() throws ArangoDBException { + String queryString = "FOR v IN 1..3 OUTBOUND 'circles/E' GRAPH 'traversalGraph' return v._key"; + ArangoCursor cursor = db.query(queryString, null, null, String.class); + Collection result = cursor.asListRemaining(); + assertThat(result).containsExactlyInAnyOrder("F"); + + queryString = "FOR v IN 1..3 INBOUND 'circles/E' GRAPH 'traversalGraph' return v._key"; + cursor = db.query(queryString, null, null, String.class); + result = cursor.asListRemaining(); + assertThat(result).containsExactlyInAnyOrder("B", "A"); + + queryString = "FOR v IN 1..3 ANY 'circles/E' GRAPH 'traversalGraph' return v._key"; + cursor = db.query(queryString, null, null, String.class); + + result = cursor.asListRemaining(); + assertThat(result).containsExactlyInAnyOrder("F", "B", "C", "D", "A", "G"); + } + +} diff --git a/shaded-integration-tests/src/test/jackson/java/com/arangodb/example/graph/ShortestPathInAQLExampleTest.java b/shaded-integration-tests/src/test/jackson/java/com/arangodb/example/graph/ShortestPathInAQLExampleTest.java new file mode 100644 index 000000000..aecf7321a --- /dev/null +++ b/shaded-integration-tests/src/test/jackson/java/com/arangodb/example/graph/ShortestPathInAQLExampleTest.java @@ -0,0 +1,105 @@ +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed 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. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.example.graph; + +import com.arangodb.ArangoCursor; +import com.arangodb.ArangoDBException; +import org.junit.jupiter.api.Test; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Shortest Path in AQL + * + * @author a-brandt + * @see Shortest Path in AQL + */ +class ShortestPathInAQLExampleTest extends BaseGraphTest { + + @Test + void queryShortestPathFromAToD() throws ArangoDBException { + String queryString = "FOR v, e IN OUTBOUND SHORTEST_PATH 'circles/A' TO 'circles/D' GRAPH 'traversalGraph' " + + "RETURN {'vertex': v._key, 'edge': e._key}"; + ArangoCursor cursor = db.query(queryString, null, null, Pair.class); + final Collection collection = toVertexCollection(cursor); + assertThat(collection.size()).isEqualTo(4); + assertThat(collection).containsExactlyInAnyOrder("A", "B", "C", "D"); + + queryString = "WITH circles FOR v, e IN OUTBOUND SHORTEST_PATH 'circles/A' TO 'circles/D' edges RETURN " + + "{'vertex': v._key, 'edge': e._key}"; + db.query(queryString, null, null, Pair.class); + assertThat(collection.size()).isEqualTo(4); + assertThat(collection).containsExactlyInAnyOrder("A", "B", "C", "D"); + } + + @Test + void queryShortestPathByFilter() throws ArangoDBException { + String queryString = "FOR a IN circles FILTER a._key == 'A' FOR d IN circles FILTER d._key == 'D' FOR v, e IN" + + " OUTBOUND SHORTEST_PATH a TO d GRAPH 'traversalGraph' RETURN {'vertex':v._key, 'edge':e._key}"; + ArangoCursor cursor = db.query(queryString, null, null, Pair.class); + final Collection collection = toVertexCollection(cursor); + assertThat(collection.size()).isEqualTo(4); + assertThat(collection).containsExactlyInAnyOrder("A", "B", "C", "D"); + + queryString = "FOR a IN circles FILTER a._key == 'A' FOR d IN circles FILTER d._key == 'D' FOR v, e IN " + + "OUTBOUND SHORTEST_PATH a TO d edges RETURN {'vertex': v._key, 'edge': e._key}"; + db.query(queryString, null, null, Pair.class); + assertThat(collection.size()).isEqualTo(4); + assertThat(collection).containsExactlyInAnyOrder("A", "B", "C", "D"); + } + + private Collection toVertexCollection(final ArangoCursor cursor) { + final List result = new ArrayList<>(); + while (cursor.hasNext()) { + final Pair pair = cursor.next(); + result.add(pair.getVertex()); + } + return result; + } + + public static class Pair { + + private String vertex; + private String edge; + + String getVertex() { + return vertex; + } + + void setVertex(final String vertex) { + this.vertex = vertex; + } + + String getEdge() { + return edge; + } + + void setEdge(final String edge) { + this.edge = edge; + } + + } + +} diff --git a/shaded-integration-tests/src/test/jackson/java/com/arangodb/example/ssl/SslExampleTest.java b/shaded-integration-tests/src/test/jackson/java/com/arangodb/example/ssl/SslExampleTest.java new file mode 100644 index 000000000..168e4d4da --- /dev/null +++ b/shaded-integration-tests/src/test/jackson/java/com/arangodb/example/ssl/SslExampleTest.java @@ -0,0 +1,131 @@ +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed 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. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.example.ssl; + +import com.arangodb.ArangoDB; +import com.arangodb.ArangoDBException; +import com.arangodb.ArangoDBMultipleException; +import com.arangodb.Protocol; +import com.arangodb.entity.ArangoDBVersion; +import org.junit.jupiter.api.Tag; +import org.junit.jupiter.api.condition.EnabledIfSystemProperty; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.EnumSource; + +import javax.net.ssl.KeyManagerFactory; +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLHandshakeException; +import javax.net.ssl.TrustManagerFactory; +import java.security.KeyStore; +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.catchThrowable; +import static org.junit.jupiter.api.Assumptions.assumeTrue; + +/** + * @author Mark Vollmary + * @author Michele Rastelli + */ +@Tag("ssl") +@EnabledIfSystemProperty(named = "SslTest", matches = "true") +class SslExampleTest { + + /*- + * a SSL trust store + * + * create the trust store for the self signed certificate: + * keytool -import -alias "my arangodb server cert" -file server.pem -keystore example.truststore + * + * Documentation: + * https://hc.apache.org/httpcomponents-client-ga/httpclient/apidocs/org/apache/http/conn/ssl/SSLSocketFactory.html + */ + private static final String SSL_TRUSTSTORE = "/example.truststore"; + private static final String SSL_TRUSTSTORE_PASSWORD = "12345678"; + + @ParameterizedTest + @EnumSource(Protocol.class) + void connect(Protocol protocol) throws Exception { + final ArangoDB arangoDB = new ArangoDB.Builder() + .host("localhost", 8529) + .password("test") + .useSsl(true) + .sslContext(createSslContext()) + .useProtocol(protocol) + .build(); + final ArangoDBVersion version = arangoDB.getVersion(); + assertThat(version).isNotNull(); + System.out.println(version.getVersion()); + } + + @ParameterizedTest + @EnumSource(Protocol.class) + void noopHostnameVerifier(Protocol protocol) throws Exception { + final ArangoDB arangoDB = new ArangoDB.Builder() + .host("127.0.0.1", 8529) + .password("test") + .useSsl(true) + .sslContext(createSslContext()) + .verifyHost(false) + .useProtocol(protocol) + .build(); + final ArangoDBVersion version = arangoDB.getVersion(); + assertThat(version).isNotNull(); + System.out.println(version.getVersion()); + } + + @ParameterizedTest + @EnumSource(Protocol.class) + void hostnameVerifierFailure(Protocol protocol) throws Exception { + assumeTrue(protocol != Protocol.VST, "VST does not support hostname verification"); + final ArangoDB arangoDB = new ArangoDB.Builder() + .host("127.0.0.1", 8529) + .password("test") + .useSsl(true) + .sslContext(createSslContext()) + .verifyHost(true) + .useProtocol(protocol) + .build(); + Throwable thrown = catchThrowable(arangoDB::getVersion); + assertThat(thrown).isInstanceOf(ArangoDBException.class); + ArangoDBException ex = (ArangoDBException) thrown; + assertThat(ex.getCause()).isInstanceOf(ArangoDBMultipleException.class); + List exceptions = ((ArangoDBMultipleException) ex.getCause()).getExceptions(); + exceptions.forEach(e -> assertThat(e).isInstanceOf(SSLHandshakeException.class)); + } + + private SSLContext createSslContext() throws Exception { + final KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType()); + ks.load(this.getClass().getResourceAsStream(SSL_TRUSTSTORE), SSL_TRUSTSTORE_PASSWORD.toCharArray()); + + final KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); + kmf.init(ks, SSL_TRUSTSTORE_PASSWORD.toCharArray()); + + final TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); + tmf.init(ks); + + final SSLContext sc = SSLContext.getInstance("TLS"); + sc.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null); + + return sc; + } + +} diff --git a/shaded-integration-tests/src/test/jackson/java/com/arangodb/internal/HostHandlerTest.java b/shaded-integration-tests/src/test/jackson/java/com/arangodb/internal/HostHandlerTest.java new file mode 100644 index 000000000..ceff3a79e --- /dev/null +++ b/shaded-integration-tests/src/test/jackson/java/com/arangodb/internal/HostHandlerTest.java @@ -0,0 +1,189 @@ +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed 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. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.internal; + +import com.arangodb.ArangoDBException; +import com.arangodb.ArangoDBMultipleException; +import com.arangodb.internal.net.*; +import com.arangodb.internal.serde.InternalSerde; +import org.junit.jupiter.api.Test; + +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.fail; + +/** + * @author Mark Vollmary + */ +class HostHandlerTest { + + private static final ConnectionPool mockCP = new ConnectionPool() { + @Override + public Connection createConnection(HostDescription host) { + return null; + } + + @Override + public Connection connection() { + return null; + } + + @Override + public void setJwt(String jwt) { + + } + + @Override + public void close() { + + } + }; + + private static final Host HOST_0 = new HostImpl(mockCP, new HostDescription("127.0.0.1", 8529)); + private static final HostResolver SINGLE_HOST = new HostResolver() { + + @Override + public HostSet resolve(final boolean initial, final boolean closeConnections) { + + HostSet set = new HostSet(); + set.addHost(HOST_0); + return set; + } + + @Override + public void init(ArangoExecutorSync executor, InternalSerde arangoSerialization) { + + } + + }; + private static final Host HOST_1 = new HostImpl(mockCP, new HostDescription("127.0.0.2", 8529)); + private static final Host HOST_2 = new HostImpl(mockCP, new HostDescription("127.0.0.3", 8529)); + private static final HostResolver MULTIPLE_HOSTS = new HostResolver() { + + @Override + public HostSet resolve(final boolean initial, final boolean closeConnections) { + + HostSet set = new HostSet(); + set.addHost(HOST_0); + set.addHost(HOST_1); + set.addHost(HOST_2); + return set; + } + + @Override + public void init(ArangoExecutorSync executor, InternalSerde arangoSerialization) { + + } + + }; + + @Test + void fallbackHostHandlerSingleHost() { + final HostHandler handler = new FallbackHostHandler(SINGLE_HOST); + assertThat(handler.get(null, null)).isEqualTo(HOST_0); + handler.fail(new RuntimeException()); + assertThat(handler.get(null, null)).isEqualTo(HOST_0); + } + + @Test + void fallbackHostHandlerMultipleHosts() { + final HostHandler handler = new FallbackHostHandler(MULTIPLE_HOSTS); + for (int i = 0; i < 3; i++) { + assertThat(handler.get(null, null)).isEqualTo(HOST_0); + handler.fail(new RuntimeException("HOST_0 failed")); + assertThat(handler.get(null, null)).isEqualTo(HOST_1); + handler.fail(new RuntimeException("HOST_1 failed")); + assertThat(handler.get(null, null)).isEqualTo(HOST_2); + handler.fail(new RuntimeException("HOST_2 failed")); + if (i < 2) { + assertThat(handler.get(null, null)).isEqualTo(HOST_0); + } else { + try { + handler.get(null, null); + fail(); + } catch (ArangoDBException e) { + assertThat(e.getCause()).isNotNull(); + assertThat(e.getCause()).isInstanceOf(ArangoDBMultipleException.class); + List exceptions = ((ArangoDBMultipleException) e.getCause()).getExceptions(); + assertThat(exceptions.get(0)).isInstanceOf(RuntimeException.class); + assertThat(exceptions.get(0).getMessage()).isEqualTo("HOST_0 failed"); + assertThat(exceptions.get(1)).isInstanceOf(RuntimeException.class); + assertThat(exceptions.get(1).getMessage()).isEqualTo("HOST_1 failed"); + assertThat(exceptions.get(2)).isInstanceOf(RuntimeException.class); + assertThat(exceptions.get(2).getMessage()).isEqualTo("HOST_2 failed"); + } + } + } + } + + @Test + void randomHostHandlerSingleHost() { + final HostHandler handler = new RandomHostHandler(SINGLE_HOST, new FallbackHostHandler(SINGLE_HOST)); + assertThat(handler.get(null, null)).isEqualTo(HOST_0); + handler.fail(new RuntimeException()); + assertThat(handler.get(null, null)).isEqualTo(HOST_0); + } + + @Test + void randomHostHandlerMultipleHosts() { + final HostHandler handler = new RandomHostHandler(MULTIPLE_HOSTS, new FallbackHostHandler(MULTIPLE_HOSTS)); + + final Host pick0 = handler.get(null, null); + assertThat(pick0).isIn(HOST_0, HOST_1, HOST_2); + handler.fail(new RuntimeException()); + + final Host pick1 = handler.get(null, null); + assertThat(pick1).isIn(HOST_0, HOST_1, HOST_2); + handler.success(); + + final Host pick3 = handler.get(null, null); + assertThat(pick3) + .isIn(HOST_0, HOST_1, HOST_2) + .isEqualTo(pick1); + } + + @Test + void roundRobinHostHandlerSingleHost() { + final HostHandler handler = new RoundRobinHostHandler(SINGLE_HOST); + assertThat(handler.get(null, null)).isEqualTo(HOST_0); + handler.fail(new RuntimeException()); + assertThat(handler.get(null, null)).isEqualTo(HOST_0); + } + + @Test + void roundRobinHostHandlerMultipleHosts() { + final HostHandler handler = new RoundRobinHostHandler(MULTIPLE_HOSTS); + final Host pick0 = handler.get(null, null); + assertThat(pick0).isIn(HOST_0, HOST_1, HOST_2); + final Host pick1 = handler.get(null, null); + assertThat(pick1) + .isIn(HOST_0, HOST_1, HOST_2) + .isNotEqualTo(pick0); + final Host pick2 = handler.get(null, null); + assertThat(pick2) + .isIn(HOST_0, HOST_1, HOST_2) + .isNotIn(pick0, pick1); + final Host pick4 = handler.get(null, null); + assertThat(pick4).isEqualTo(pick0); + } + +} diff --git a/shaded-integration-tests/src/test/jackson/java/com/arangodb/internal/QueueTimeMetricsImplTest.java b/shaded-integration-tests/src/test/jackson/java/com/arangodb/internal/QueueTimeMetricsImplTest.java new file mode 100644 index 000000000..7c4ca4c8a --- /dev/null +++ b/shaded-integration-tests/src/test/jackson/java/com/arangodb/internal/QueueTimeMetricsImplTest.java @@ -0,0 +1,61 @@ +package com.arangodb.internal; + +import com.arangodb.model.QueueTimeSample; +import org.junit.jupiter.api.Test; + +import java.util.Arrays; +import java.util.Random; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.within; + + +class QueueTimeMetricsImplTest { + private final static int QSIZE = 1024; + private final Random rnd = new Random(); + private final QueueTimeMetricsImpl q = new QueueTimeMetricsImpl(QSIZE); + + @Test + void halfSizeTest() { + testQueue(QSIZE / 2); + } + + @Test + void fullSizeTest() { + testQueue(QSIZE); + } + + @Test + void emptySizeTest() { + testQueue(0); + } + + @Test + void overSizeTest() { + testQueue((int) (QSIZE * 1.2)); + testQueue((int) (QSIZE * 3000.4)); + } + + private void testQueue(int size) { + q.clear(); + for (int i = 0; i < size; i++) { + q.add(new QueueTimeSample(i, rnd.nextDouble())); + } + QueueTimeSample[] values = q.getValues(); + assertThat(values).hasSize(Math.min(size, QSIZE)); + assertThat(q.getAvg()).isEqualTo(getAvg(values), within(1.0E-12)); + assertThat(q.getAvg()).isGreaterThanOrEqualTo(0.0); + + for (int i = 0; i < values.length; i++) { + assertThat(values[i]).isNotNull(); + if (i > 0) { + assertThat(values[i].timestamp).isGreaterThan(values[i - 1].timestamp); + } + } + } + + private double getAvg(QueueTimeSample[] elements) { + return Arrays.stream(elements).mapToDouble(it -> it.value).average().orElse(0.0); + } + +} \ No newline at end of file diff --git a/shaded-integration-tests/src/test/jackson/java/com/arangodb/internal/velocystream/CommunicationTest.java b/shaded-integration-tests/src/test/jackson/java/com/arangodb/internal/velocystream/CommunicationTest.java new file mode 100644 index 000000000..bfdeb444a --- /dev/null +++ b/shaded-integration-tests/src/test/jackson/java/com/arangodb/internal/velocystream/CommunicationTest.java @@ -0,0 +1,122 @@ +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed 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. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.internal.velocystream; + +import com.arangodb.ArangoDB; +import com.arangodb.ArangoDatabase; +import com.arangodb.entity.ArangoDBVersion; +import com.arangodb.internal.config.FileConfigPropertiesProvider; +import org.junit.jupiter.api.Test; + +import java.util.Collection; +import java.util.Iterator; +import java.util.concurrent.ConcurrentLinkedQueue; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * @author Mark Vollmary + */ +class CommunicationTest { + + private static final String FAST = "fast"; + private static final String SLOW = "slow"; + + @Test + void chunkSizeSmall() { + final ArangoDB arangoDB = new ArangoDB.Builder() + .loadProperties(new FileConfigPropertiesProvider()) + .chunksize(20).build(); + final ArangoDBVersion version = arangoDB.getVersion(); + assertThat(version).isNotNull(); + } + + @Test + void multiThread() throws Exception { + final ArangoDB arangoDB = new ArangoDB.Builder() + .loadProperties(new FileConfigPropertiesProvider()) + .build(); + arangoDB.getUsers(); // authentication and active-failover connection redirect to master + + final Collection result = new ConcurrentLinkedQueue<>(); + final Thread fast = new Thread(() -> { + arangoDB.db().query("return sleep(0.1)", null, null, null); + result.add(FAST); + }); + final Thread slow = new Thread(() -> { + arangoDB.db().query("return sleep(0.5)", null, null, null); + result.add(SLOW); + }); + slow.start(); + fast.start(); + + slow.join(); + fast.join(); + + assertThat(result.size()).isEqualTo(2); + final Iterator iterator = result.iterator(); + assertThat(iterator.next()).isEqualTo(FAST); + assertThat(iterator.next()).isEqualTo(SLOW); + } + + @Test + void multiThreadSameDatabases() throws Exception { + final ArangoDB arangoDB = new ArangoDB.Builder() + .loadProperties(new FileConfigPropertiesProvider()) + .build(); + arangoDB.getUsers(); // authentication and active-failover connection redirect to master + + final ArangoDatabase db = arangoDB.db(); + + final Collection result = new ConcurrentLinkedQueue<>(); + final Thread t1 = new Thread(() -> { + db.query("return sleep(0.1)", null, null, null); + result.add("1"); + }); + final Thread t2 = new Thread(() -> { + db.query("return sleep(0.1)", null, null, null); + result.add("1"); + }); + t2.start(); + t1.start(); + t2.join(); + t1.join(); + assertThat(result.size()).isEqualTo(2); + } + + @Test + void minOneConnection() { + final ArangoDB arangoDB = new ArangoDB.Builder() + .loadProperties(new FileConfigPropertiesProvider()) + .maxConnections(0).build(); + final ArangoDBVersion version = arangoDB.getVersion(); + assertThat(version).isNotNull(); + } + + @Test + void defaultMaxConnection() { + final ArangoDB arangoDB = new ArangoDB.Builder() + .loadProperties(new FileConfigPropertiesProvider()) + .maxConnections(null).build(); + final ArangoDBVersion version = arangoDB.getVersion(); + assertThat(version).isNotNull(); + } +} diff --git a/shaded-integration-tests/src/test/jackson/java/com/arangodb/serde/CustomSerdeTest.java b/shaded-integration-tests/src/test/jackson/java/com/arangodb/serde/CustomSerdeTest.java new file mode 100644 index 000000000..428363da6 --- /dev/null +++ b/shaded-integration-tests/src/test/jackson/java/com/arangodb/serde/CustomSerdeTest.java @@ -0,0 +1,242 @@ +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed 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. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.serde; + + +import com.arangodb.*; +import com.arangodb.internal.config.FileConfigPropertiesProvider; +import com.arangodb.internal.serde.InternalSerde; +import com.arangodb.model.DocumentCreateOptions; +import com.arangodb.serde.jackson.JacksonSerde; +import com.arangodb.serde.jackson.JacksonSerdeProvider; +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.databind.*; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.databind.module.SimpleModule; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; + +import java.io.IOException; +import java.math.BigInteger; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +import static com.fasterxml.jackson.databind.DeserializationFeature.USE_BIG_INTEGER_FOR_INTS; +import static com.fasterxml.jackson.databind.SerializationFeature.WRITE_SINGLE_ELEM_ARRAYS_UNWRAPPED; +import static org.assertj.core.api.Assertions.assertThat; + + +/** + * @author Michele Rastelli + */ +class CustomSerdeTest { + + private static final String COLLECTION_NAME = "collection"; + private static final String PERSON_SERIALIZER_ADDED_PREFIX = "MyNameIs"; + private static final String PERSON_DESERIALIZER_ADDED_PREFIX = "Hello"; + + private static ArangoDB arangoDB; + private static ArangoDatabase db; + private static ArangoCollection collection; + + @BeforeAll + static void init() { + JacksonSerde serde = new JacksonSerdeProvider().of(ContentType.VPACK); + serde.configure((mapper) -> { + mapper.configure(WRITE_SINGLE_ELEM_ARRAYS_UNWRAPPED, true); + mapper.configure(USE_BIG_INTEGER_FOR_INTS, true); + SimpleModule module = new SimpleModule("PersonModule"); + module.addDeserializer(Person.class, new PersonDeserializer()); + mapper.registerModule(module); + }); + arangoDB = new ArangoDB.Builder() + .loadProperties(new FileConfigPropertiesProvider()) + .useProtocol(Protocol.VST) + .serde(serde).build(); + + db = arangoDB.db(DbName.of("custom-serde-test")); + if (!db.exists()) { + db.create(); + } + + collection = db.collection(COLLECTION_NAME); + if (!collection.exists()) { + collection.create(); + } + } + + @AfterAll + static void shutdown() { + if (db.exists()) + db.drop(); + } + + @Test + void customPersonDeserializer() { + Person person = new Person(); + person.name = "Joe"; + Person result = collection.insertDocument( + person, + new DocumentCreateOptions().returnNew(true) + ).getNew(); + assertThat(result.name).isEqualTo(PERSON_DESERIALIZER_ADDED_PREFIX + PERSON_SERIALIZER_ADDED_PREFIX + person.name); + } + + @Test + void manualCustomPersonDeserializer() { + Person person = new Person(); + person.name = "Joe"; + InternalSerde serialization = arangoDB.getSerde(); + byte[] serialized = serialization.serializeUserData(person); + Person deserializedPerson = serialization.deserializeUserData(serialized, Person.class); + assertThat(deserializedPerson.name).isEqualTo(PERSON_DESERIALIZER_ADDED_PREFIX + PERSON_SERIALIZER_ADDED_PREFIX + person.name); + } + + @Test + void aqlSerialization() { + String key = "test-" + UUID.randomUUID(); + + Map doc = new HashMap<>(); + doc.put("_key", key); + doc.put("arr", Collections.singletonList("hello")); + doc.put("int", 10); + + HashMap params = new HashMap<>(); + params.put("doc", doc); + params.put("@collection", COLLECTION_NAME); + + Map result = db.query( + "INSERT @doc INTO @@collection RETURN NEW", + params, + Map.class + ).next(); + + assertThat(result.get("arr")).isInstanceOf(String.class); + assertThat(result.get("arr")).isEqualTo("hello"); + assertThat(result.get("int")).isInstanceOf(BigInteger.class); + assertThat(result.get("int")).isEqualTo(BigInteger.valueOf(10)); + } + + @Test + void aqlDeserialization() { + String key = "test-" + UUID.randomUUID(); + + Map doc = new HashMap<>(); + doc.put("_key", key); + doc.put("arr", Collections.singletonList("hello")); + doc.put("int", 10); + + collection.insertDocument(doc); + + final Map result = db.query( + "RETURN DOCUMENT(@docId)", + Collections.singletonMap("docId", COLLECTION_NAME + "/" + key), + Map.class + ).next(); + + assertThat(result.get("arr")).isInstanceOf(String.class); + assertThat(result.get("arr")).isEqualTo("hello"); + assertThat(result.get("int")).isInstanceOf(BigInteger.class); + assertThat(result.get("int")).isEqualTo(BigInteger.valueOf(10)); + } + + @Test + void insertDocument() { + String key = "test-" + UUID.randomUUID(); + + Map doc = new HashMap<>(); + doc.put("_key", key); + doc.put("arr", Collections.singletonList("hello")); + doc.put("int", 10); + + Map result = collection.insertDocument( + doc, + new DocumentCreateOptions().returnNew(true) + ).getNew(); + + assertThat(result.get("arr")).isInstanceOf(String.class); + assertThat(result.get("arr")).isEqualTo("hello"); + assertThat(result.get("int")).isInstanceOf(BigInteger.class); + assertThat(result.get("int")).isEqualTo(BigInteger.valueOf(10)); + } + + @Test + void getDocument() { + String key = "test-" + UUID.randomUUID(); + + Map doc = new HashMap<>(); + doc.put("_key", key); + doc.put("arr", Collections.singletonList("hello")); + doc.put("int", 10); + + collection.insertDocument(doc); + + final Map result = db.collection(COLLECTION_NAME).getDocument( + key, + Map.class, + null); + + assertThat(result.get("arr")).isInstanceOf(String.class); + assertThat(result.get("arr")).isEqualTo("hello"); + assertThat(result.get("int")).isInstanceOf(BigInteger.class); + assertThat(result.get("int")).isEqualTo(BigInteger.valueOf(10)); + } + + @Test + void parseNullString() { + final String json = arangoDB.getSerde().deserializeUserData(arangoDB.getSerde().serializeUserData(null), + String.class); + assertThat(json).isNull(); + } + + static class PersonSerializer extends JsonSerializer { + @Override + public void serialize(Person value, JsonGenerator gen, SerializerProvider serializers) throws IOException { + gen.writeStartObject(); + gen.writeFieldName("name"); + gen.writeString(PERSON_SERIALIZER_ADDED_PREFIX + value.name); + gen.writeEndObject(); + } + } + + static class PersonDeserializer extends JsonDeserializer { + @Override + public Person deserialize(JsonParser parser, DeserializationContext ctx) throws IOException { + Person person = new Person(); + JsonNode rootNode = parser.getCodec().readTree(parser); + JsonNode nameNode = rootNode.get("name"); + if (nameNode != null && nameNode.isTextual()) { + person.name = PERSON_DESERIALIZER_ADDED_PREFIX + nameNode.asText(); + } + return person; + } + } + + @JsonSerialize(using = PersonSerializer.class) + static class Person { + String name; + } + +} diff --git a/shaded-integration-tests/src/test/jackson/java/com/arangodb/serde/CustomTypeHintTest.java b/shaded-integration-tests/src/test/jackson/java/com/arangodb/serde/CustomTypeHintTest.java new file mode 100644 index 000000000..fed63354e --- /dev/null +++ b/shaded-integration-tests/src/test/jackson/java/com/arangodb/serde/CustomTypeHintTest.java @@ -0,0 +1,145 @@ +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed 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. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.serde; + + +import com.arangodb.ArangoCollection; +import com.arangodb.ArangoDB; +import com.arangodb.ArangoDatabase; +import com.arangodb.DbName; +import com.arangodb.internal.config.FileConfigPropertiesProvider; +import com.arangodb.model.DocumentCreateOptions; +import com.arangodb.serde.jackson.Key; +import com.fasterxml.jackson.annotation.JsonTypeInfo; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + + +/** + * @author Michele Rastelli + */ +class CustomTypeHintTest { + + private static final String COLLECTION_NAME = "collection"; + private ArangoDatabase db; + private ArangoCollection collection; + + @BeforeEach + void init() { + ArangoDB arangoDB = new ArangoDB.Builder() + .loadProperties(new FileConfigPropertiesProvider()) + .build(); + + db = arangoDB.db(DbName.of("custom-serde-test")); + if (!db.exists()) { + db.create(); + } + + collection = db.collection(COLLECTION_NAME); + if (!collection.exists()) { + collection.create(); + } + } + + @AfterEach + void shutdown() { + if (db.exists()) + db.drop(); + } + + @Test + void insertDocument() { + Gorilla gorilla = new Gorilla(); + gorilla.setName("kingKong"); + + Zoo doc = new Zoo(); + doc.setAnimal(gorilla); + + Zoo insertedDoc = collection.insertDocument( + doc, + new DocumentCreateOptions().returnNew(true) + ).getNew(); + + assertThat((insertedDoc.getAnimal().getName())).isEqualTo("kingKong"); + + String key = insertedDoc.getKey(); + + // in the db a document like this is created: + // { + // "animal": { + // "type": "com.arangodb.serde.CustomTypeHintTest$Gorilla", + // "name": "kingKong" + // } + // } + + final Zoo readDoc = collection.getDocument( + key, + Zoo.class, + null); + + assertThat((readDoc.getAnimal().getName())).isEqualTo("kingKong"); + } + + @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, property = "type") + public interface Animal { + String getName(); + } + + public static class Gorilla implements Animal { + private String name; + + @Override + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + } + + public static class Zoo { + + @Key + private String key; + + private Animal animal; + + public String getKey() { + return key; + } + + public void setKey(String key) { + this.key = key; + } + + public Animal getAnimal() { + return animal; + } + + public void setAnimal(Animal animal) { + this.animal = animal; + } + } +} diff --git a/shaded-integration-tests/src/test/jackson/java/com/arangodb/serde/SerdeTest.java b/shaded-integration-tests/src/test/jackson/java/com/arangodb/serde/SerdeTest.java new file mode 100644 index 000000000..36daf7450 --- /dev/null +++ b/shaded-integration-tests/src/test/jackson/java/com/arangodb/serde/SerdeTest.java @@ -0,0 +1,71 @@ +package com.arangodb.serde; + +import com.arangodb.ContentType; +import com.arangodb.internal.serde.InternalSerde; +import com.arangodb.internal.serde.SerdeUtils; +import com.arangodb.shaded.fasterxml.jackson.databind.JsonNode; +import com.arangodb.shaded.fasterxml.jackson.databind.node.JsonNodeFactory; +import com.arangodb.shaded.fasterxml.jackson.databind.node.ObjectNode; +import com.arangodb.util.RawBytes; +import com.arangodb.util.RawJson; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.EnumSource; + +import java.sql.Date; + +import static org.assertj.core.api.Assertions.assertThat; + + +class SerdeTest { + + @ParameterizedTest + @EnumSource(ContentType.class) + void rawJsonSerde(ContentType type) { + InternalSerde s = InternalSerde.of(type, null); + ObjectNode node = JsonNodeFactory.instance.objectNode().put("foo", "bar"); + RawJson raw = RawJson.of(SerdeUtils.INSTANCE.writeJson(node)); + byte[] serialized = s.serialize(raw); + RawJson deserialized = s.deserialize(serialized, RawJson.class); + assertThat(deserialized).isEqualTo(raw); + } + + @ParameterizedTest + @EnumSource(ContentType.class) + void rawBytesSerde(ContentType type) { + InternalSerde s = InternalSerde.of(type, null); + ObjectNode node = JsonNodeFactory.instance.objectNode().put("foo", "bar"); + RawBytes raw = RawBytes.of(s.serialize(node)); + byte[] serialized = s.serialize(raw); + RawBytes deserialized = s.deserialize(serialized, RawBytes.class); + assertThat(deserialized).isEqualTo(raw); + } + + @ParameterizedTest + @EnumSource(ContentType.class) + void utilDateSerde(ContentType type) { + InternalSerde s = InternalSerde.of(type, null); + long ts = 1000000000000L; + java.util.Date date = new java.util.Date(ts); + byte[] ser = s.serialize(date); + JsonNode node = s.parse(ser); + assertThat(node.isLong()).isTrue(); + assertThat(node.longValue()).isEqualTo(ts); + java.util.Date deser = s.deserialize(ser, java.util.Date.class); + assertThat(deser).isEqualTo(date); + } + + @ParameterizedTest + @EnumSource(ContentType.class) + void sqlDateSerde(ContentType type) { + InternalSerde s = InternalSerde.of(type, null); + long ts = 1000000000000L; + Date date = new Date(ts); + byte[] ser = s.serialize(date); + JsonNode node = s.parse(ser); + assertThat(node.isLong()).isTrue(); + assertThat(node.longValue()).isEqualTo(ts); + Date deser = s.deserialize(ser, Date.class); + assertThat(deser).isEqualTo(date); + } + +} diff --git a/shaded-integration-tests/src/test/jackson/java/com/arangodb/util/MapBuilder.java b/shaded-integration-tests/src/test/jackson/java/com/arangodb/util/MapBuilder.java new file mode 100644 index 000000000..61d05865e --- /dev/null +++ b/shaded-integration-tests/src/test/jackson/java/com/arangodb/util/MapBuilder.java @@ -0,0 +1,46 @@ +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed 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. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.util; + +import java.util.LinkedHashMap; +import java.util.Map; + +/** + * @author Mark Vollmary + */ +public class MapBuilder { + + private final Map map; + + public MapBuilder() { + super(); + map = new LinkedHashMap<>(); + } + + public MapBuilder put(final String key, final Object value) { + map.put(key, value); + return this; + } + + public Map get() { + return map; + } +} diff --git a/shaded-integration-tests/src/test/jackson/java/com/arangodb/util/MapBuilderTest.java b/shaded-integration-tests/src/test/jackson/java/com/arangodb/util/MapBuilderTest.java new file mode 100644 index 000000000..0496a685a --- /dev/null +++ b/shaded-integration-tests/src/test/jackson/java/com/arangodb/util/MapBuilderTest.java @@ -0,0 +1,43 @@ +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed 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. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.util; + + +import org.junit.jupiter.api.Test; + +import java.util.Map; + +import static org.assertj.core.api.Assertions.assertThat; + + +/** + * @author Mark Vollmary + */ +class MapBuilderTest { + + @Test + void build() { + final Map map = new MapBuilder().put("foo", "bar").get(); + assertThat(map).hasSize(1); + assertThat(map.get("foo")).isNotNull(); + assertThat(map).containsEntry("foo", "bar"); + } +} diff --git a/shaded-integration-tests/src/test/jackson/java/com/arangodb/util/TestUtils.java b/shaded-integration-tests/src/test/jackson/java/com/arangodb/util/TestUtils.java new file mode 100644 index 000000000..a8faab73a --- /dev/null +++ b/shaded-integration-tests/src/test/jackson/java/com/arangodb/util/TestUtils.java @@ -0,0 +1,112 @@ +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed 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. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + + +package com.arangodb.util; + + +import java.util.ArrayList; +import java.util.List; +import java.util.Random; +import java.util.UUID; + +/** + * @author Michele Rastelli + */ +public final class TestUtils { + + private static final String[] allChars = TestUtils.generateAllInputChars(); + private static final Random r = new Random(); + + private TestUtils() { + } + + /** + * Parses {@param version} and checks whether it is greater or equal to + * <{@param otherMajor}, {@param otherMinor}, {@param otherPatch}> + * comparing the corresponding version components in lexicographical order. + */ + public static boolean isAtLeastVersion(final String version, final int otherMajor, final int otherMinor, + final int otherPatch) { + return compareVersion(version, otherMajor, otherMinor, otherPatch) >= 0; + } + + /** + * Parses {@param version} and checks whether it is less than + * <{@param otherMajor}, {@param otherMinor}, {@param otherPatch}> + * comparing the corresponding version components in lexicographical order. + */ + public static boolean isLessThanVersion(final String version, final int otherMajor, final int otherMinor, + final int otherPatch) { + return compareVersion(version, otherMajor, otherMinor, otherPatch) < 0; + } + + private static int compareVersion(final String version, final int otherMajor, final int otherMinor, + final int otherPatch) { + String[] parts = version.split("-")[0].split("\\."); + + int major = Integer.parseInt(parts[0]); + int minor = Integer.parseInt(parts[1]); + int patch = Integer.parseInt(parts[2]); + + int majorComparison = Integer.compare(major, otherMajor); + if (majorComparison != 0) { + return majorComparison; + } + + int minorComparison = Integer.compare(minor, otherMinor); + if (minorComparison != 0) { + return minorComparison; + } + + return Integer.compare(patch, otherPatch); + } + + private static String[] generateAllInputChars() { + List list = new ArrayList<>(); + for (int codePoint = 0; codePoint < Character.MAX_CODE_POINT + 1; codePoint++) { + String s = new String(Character.toChars(codePoint)); + if (codePoint == 47 || // '/' + codePoint == 58 || // ':' + Character.isISOControl(codePoint) || + Character.isLowSurrogate(s.charAt(0)) || + (Character.isHighSurrogate(s.charAt(0)) && s.length() == 1)) { + continue; + } + list.add(s); + } + return list.toArray(new String[0]); + } + + public static String generateRandomDbName(int length, boolean extendedNames) { + if (extendedNames) { + int max = allChars.length; + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < length; i++) { + String allChar = allChars[r.nextInt(max)]; + sb.append(allChar); + } + return UnicodeUtils.normalize(sb.toString()); + } else { + return UUID.randomUUID().toString(); + } + } + +} diff --git a/shaded-integration-tests/src/test/jsonb/java/arch/AdbTest.java b/shaded-integration-tests/src/test/jsonb/java/arch/AdbTest.java new file mode 100644 index 000000000..fc320db4e --- /dev/null +++ b/shaded-integration-tests/src/test/jsonb/java/arch/AdbTest.java @@ -0,0 +1,18 @@ +package arch; + +import com.arangodb.ArangoDB; +import com.arangodb.entity.ArangoDBVersion; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + +import static org.assertj.core.api.Assertions.assertThat; + +class AdbTest extends BaseTest { + @ParameterizedTest + @MethodSource("adbByProtocol") + void getVersion(ArangoDB adb) { + final ArangoDBVersion version = adb.getVersion(); + assertThat(version.getServer()).isNotNull(); + assertThat(version.getVersion()).isNotNull(); + } +} diff --git a/shaded-integration-tests/src/test/jsonb/java/arch/BaseTest.java b/shaded-integration-tests/src/test/jsonb/java/arch/BaseTest.java new file mode 100644 index 000000000..c6851582b --- /dev/null +++ b/shaded-integration-tests/src/test/jsonb/java/arch/BaseTest.java @@ -0,0 +1,74 @@ +package arch; + +import com.arangodb.ArangoDB; +import com.arangodb.ContentType; +import com.arangodb.DbName; +import com.arangodb.Protocol; +import com.arangodb.internal.serde.ContentTypeFactory; +import org.junit.jupiter.params.provider.Arguments; + +import java.util.Arrays; +import java.util.Locale; +import java.util.stream.Stream; + +public class BaseTest { + protected static final DbName TEST_DB = DbName.of("java_driver_integration_tests"); + protected static final String HOST = "172.28.0.1"; + protected static final int PORT = 8529; + protected static final String PASSWD = "test"; + private static final Serde serde = Serde.valueOf(System.getProperty("serde").toUpperCase(Locale.ROOT)); + + private enum Serde { + JACKSON, JSONB + } + + protected static ArangoDB createAdb() { + return new ArangoDB.Builder() + .host(HOST, PORT) + .password(PASSWD) + .build(); + } + + protected static ArangoDB createAdb(ContentType contentType) { + Protocol protocol = contentType == ContentType.VPACK ? Protocol.HTTP2_VPACK : Protocol.HTTP2_JSON; + return new ArangoDB.Builder() + .host(HOST, PORT) + .password(PASSWD) + .useProtocol(protocol) + .build(); + } + + protected static ArangoDB createAdb(Protocol protocol) { + return new ArangoDB.Builder() + .host(HOST, PORT) + .password(PASSWD) + .useProtocol(protocol) + .build(); + } + + protected static Stream adbByProtocol() { + return Arrays.stream(Protocol.values()) + .filter(BaseTest::isProtocolSupported) + .map(BaseTest::createAdb) + .map(Arguments::of); + } + + protected static Stream adbByContentType() { + return Arrays.stream(ContentType.values()) + .filter(BaseTest::isContentTypeSupported) + .map(BaseTest::createAdb) + .map(Arguments::of); + } + + private static boolean isProtocolSupported(Protocol protocol) { + return isContentTypeSupported(ContentTypeFactory.of(protocol)); + } + + private static boolean isContentTypeSupported(ContentType contentType) { + if (serde == Serde.JACKSON) { + return true; + } else { + return contentType == ContentType.JSON; + } + } +} diff --git a/shaded-integration-tests/src/test/jsonb/java/arch/Person.java b/shaded-integration-tests/src/test/jsonb/java/arch/Person.java new file mode 100644 index 000000000..c67dab135 --- /dev/null +++ b/shaded-integration-tests/src/test/jsonb/java/arch/Person.java @@ -0,0 +1,61 @@ +package arch; + + +import com.arangodb.serde.jsonb.Key; +import jakarta.json.bind.annotation.JsonbProperty; + +import java.util.Objects; + +public class Person { + @Key + private String key; + @JsonbProperty("firstName") + private String name; + private int age; + + public Person() { + } + + public Person(String key, String name, int age) { + this.key = key; + this.name = name; + this.age = age; + } + + public String getKey() { + return key; + } + + public void setKey(String key) { + this.key = key; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public int getAge() { + return age; + } + + public void setAge(int age) { + this.age = age; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + Person person = (Person) o; + return age == person.age && Objects.equals(key, person.key) && Objects.equals(name, person.name); + } + + @Override + public int hashCode() { + return Objects.hash(key, name, age); + } +} \ No newline at end of file diff --git a/shaded-integration-tests/src/test/jsonb/java/arch/RelocationsTest.java b/shaded-integration-tests/src/test/jsonb/java/arch/RelocationsTest.java new file mode 100644 index 000000000..db2516a94 --- /dev/null +++ b/shaded-integration-tests/src/test/jsonb/java/arch/RelocationsTest.java @@ -0,0 +1,54 @@ +package arch; + +import com.tngtech.archunit.core.importer.ImportOption.DoNotIncludeTests; +import com.tngtech.archunit.junit.AnalyzeClasses; +import com.tngtech.archunit.junit.ArchTest; +import com.tngtech.archunit.lang.ArchRule; + +import static com.tngtech.archunit.lang.syntax.ArchRuleDefinition.noClasses; + + +@AnalyzeClasses(packages = "com.arangodb..", importOptions = {DoNotIncludeTests.class}) +public class RelocationsTest { + + @ArchTest + public static final ArchRule nettyRelocation = noClasses().that() + .resideInAPackage("com.arangodb..") + .should().dependOnClassesThat() + .resideInAPackage("io.netty.."); + + @ArchTest + public static final ArchRule vertxRelocation = noClasses().that() + .resideInAPackage("com.arangodb..") + .should().dependOnClassesThat() + .resideInAPackage("io.vertx.."); + + @ArchTest + public static final ArchRule noJacksonDependency = noClasses().that() + .resideInAPackage("com.arangodb..") + .should().dependOnClassesThat() + .resideInAPackage("com.fasterxml.jackson.."); + + @ArchTest + public static final ArchRule noJacksonDataformatVelocypackDependency = noClasses().that() + .resideInAPackage("com.arangodb..") + .should().dependOnClassesThat() + .resideInAPackage("com.arangodb.jackson.dataformat.velocypack.."); + + @ArchTest + public static final ArchRule noVelocypackDependency = noClasses().that() + .resideInAPackage("com.arangodb..").and() + .resideOutsideOfPackage("..velocystream..").and() + .resideOutsideOfPackage("com.arangodb.shaded.jackson.dataformat.velocypack..") + .should().dependOnClassesThat() + .resideInAPackage("com.arangodb.velocypack.."); + + @ArchTest + // jsonb-serde is accessed via SPI + public static final ArchRule noExplicitDependencyOnJsonbSerde = noClasses().that() + .resideInAPackage("com.arangodb..").and() + .resideOutsideOfPackage("com.arangodb.serde.jsonb..") + .should().dependOnClassesThat() + .resideInAPackage("com.arangodb.serde.jsonb.."); + +} diff --git a/shaded-integration-tests/src/test/jsonb/java/arch/SerdeTest.java b/shaded-integration-tests/src/test/jsonb/java/arch/SerdeTest.java new file mode 100644 index 000000000..c679a4310 --- /dev/null +++ b/shaded-integration-tests/src/test/jsonb/java/arch/SerdeTest.java @@ -0,0 +1,66 @@ +package arch; + +import com.arangodb.ArangoDB; +import com.arangodb.util.RawJson; +import jakarta.json.*; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + +import java.util.Collections; +import java.util.Map; + +import static org.assertj.core.api.Assertions.assertThat; + +class SerdeTest extends BaseTest { + + @ParameterizedTest + @MethodSource("adbByContentType") + void jsonNode(ArangoDB adb) { + JsonObject doc = Json.createObjectBuilder() + .add("foo", "bar") + .build(); + JsonObject res = adb.db().query("return @d", Collections.singletonMap("d", doc), JsonObject.class).next(); + assertThat(res.size()).isEqualTo(1); + assertThat(res.getString("foo")).isEqualTo("bar"); + JsonValue value = adb.db().query("return @d.foo", Collections.singletonMap("d", doc), JsonValue.class).next(); + assertThat(value) + .isInstanceOf(JsonString.class) + .extracting(v -> ((JsonString) v).getString()) + .isEqualTo("bar"); + } + + @ParameterizedTest + @MethodSource("adbByContentType") + void map(ArangoDB adb) { + Map doc = Collections.singletonMap("foo", "bar"); + Map res = adb.db().query("return @d", Collections.singletonMap("d", doc), Map.class).next(); + assertThat(res).hasSize(1); + assertThat(res.get("foo")).isEqualTo("bar"); + String value = adb.db().query("return @d.foo", Collections.singletonMap("d", doc), String.class).next(); + assertThat(value).isEqualTo("bar"); + } + + @ParameterizedTest + @MethodSource("adbByContentType") + void rawJson(ArangoDB adb) { + RawJson doc = RawJson.of(""" + {"foo":"bar"}"""); + RawJson res = adb.db().query("return @d", Collections.singletonMap("d", doc), RawJson.class).next(); + assertThat(res.getValue()).isEqualTo(doc.getValue()); + RawJson value = adb.db().query("return @d.foo", Collections.singletonMap("d", doc), RawJson.class).next(); + assertThat(value.getValue()).isEqualTo("\"bar\""); + } + + @ParameterizedTest + @MethodSource("adbByContentType") + void person(ArangoDB adb) { + Person doc = new Person("key", "Jim", 22); + Person res = adb.db().query("return @d", Collections.singletonMap("d", doc), Person.class).next(); + assertThat(res).isEqualTo(doc); + String key = adb.db().query("return @d._key", Collections.singletonMap("d", doc), String.class).next(); + assertThat(key).isEqualTo("key"); + String name = adb.db().query("return @d.firstName", Collections.singletonMap("d", doc), String.class).next(); + assertThat(name).isEqualTo("Jim"); + } + +} diff --git a/shaded-integration-tests/src/test/resources/arangodb-bad.properties b/shaded-integration-tests/src/test/resources/arangodb-bad.properties new file mode 100644 index 000000000..2b2743531 --- /dev/null +++ b/shaded-integration-tests/src/test/resources/arangodb-bad.properties @@ -0,0 +1 @@ +arangodb.hosts=127.0.0.1:8529,127.0.0.1:fail \ No newline at end of file diff --git a/shaded-integration-tests/src/test/resources/arangodb.properties b/shaded-integration-tests/src/test/resources/arangodb.properties new file mode 100644 index 000000000..c47741102 --- /dev/null +++ b/shaded-integration-tests/src/test/resources/arangodb.properties @@ -0,0 +1,5 @@ +arangodb.hosts=172.28.0.1:8529 +arangodb.acquireHostList=true +arangodb.password=test +arangodb.timeout=30000 +arangodb.metrics.responseQueueTimeSamples=20 diff --git a/shaded-integration-tests/src/test/resources/logback-test.xml b/shaded-integration-tests/src/test/resources/logback-test.xml new file mode 100644 index 000000000..b1d65b196 --- /dev/null +++ b/shaded-integration-tests/src/test/resources/logback-test.xml @@ -0,0 +1,18 @@ + + + + + + %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n + + + + + + + + + + + diff --git a/shaded/pom.xml b/shaded/pom.xml new file mode 100644 index 000000000..1c0334a67 --- /dev/null +++ b/shaded/pom.xml @@ -0,0 +1,133 @@ + + + 4.0.0 + + + com.arangodb + arangodb-java-driver-parent + 7.0.0-SNAPSHOT + + + arangodb-java-driver-shaded + arangodb-java-driver-shaded + ArangoDB Java Driver Shaded + + + false + + + + + com.arangodb + arangodb-java-driver + + + com.arangodb + serde-api + + + + + com.arangodb + jackson-dataformat-velocypack + + + com.arangodb + jackson-serde + + + org.slf4j + slf4j-api + + + + + + + maven-shade-plugin + 3.4.1 + + + shade-core-dependencies + package + + shade + + + true + true + + + org.slf4j:slf4j-api + com.arangodb:jackson-serde + com.arangodb:velocypack + + + + + + io.netty + com.arangodb.shaded.netty + + + com.fasterxml.jackson + com.arangodb.shaded.fasterxml.jackson + + + com.arangodb.jackson.dataformat.velocypack + com.arangodb.shaded.jackson.dataformat.velocypack + + + io.vertx + com.arangodb.shaded.vertx + + + + + com.arangodb:arangodb-java-driver + + META-INF/MANIFEST.MF + + + + com.arangodb:jackson-dataformat-velocypack + + META-INF/** + + + + com.fasterxml.jackson.core:* + + META-INF/** + module-info.class + + + + io.netty:* + + META-INF/** + module-info.class + + + + io.vertx:* + + *.adoc + examples/** + META-INF/** + module-info.class + + + + + + + + + + + \ No newline at end of file From 24d79a16f3b3b3ec8cccdf7f081a81f44c43cb66 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Thu, 8 Dec 2022 21:23:44 +0100 Subject: [PATCH 201/254] fixed CI tests --- .github/workflows/maven.yml | 18 ++++++------------ .github/workflows/native.yml | 6 ++---- .github/workflows/resilience.yml | 1 - 3 files changed, 8 insertions(+), 17 deletions(-) diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index 7d9b0eb40..3e4af66bc 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -67,8 +67,7 @@ jobs: - name: Info run: mvn -version - name: Test - working-directory: driver - run: mvn --no-transfer-progress test -DargLine="-Duser.language=${{matrix.user-language}}" + run: mvn --no-transfer-progress -am -pl driver test -DargLine="-Duser.language=${{matrix.user-language}}" test-ssl: timeout-minutes: 10 @@ -102,8 +101,7 @@ jobs: - name: Info run: mvn -version - name: Test - working-directory: driver - run: mvn --no-transfer-progress -Dgroups=ssl -DSslTest=true test + run: mvn --no-transfer-progress -Dgroups=ssl -DSslTest=true -am -pl driver test # test encodeURIComponent() and normalize('NFC') comparing to Javascript behavior test-graalvm: @@ -119,8 +117,7 @@ jobs: - name: Info run: mvn -version - name: Test - working-directory: driver - run: mvn -e --no-transfer-progress test -Dtest=com.arangodb.util.UnicodeUtilsTest + run: mvn -e --no-transfer-progress -am -pl driver test -Dtest=com.arangodb.util.UnicodeUtilsTest test-jwt: timeout-minutes: 20 @@ -167,8 +164,7 @@ jobs: - name: Info run: mvn -version - name: Test - working-directory: driver - run: mvn --no-transfer-progress test -DargLine="-Duser.language=${{matrix.user-language}}" + run: mvn --no-transfer-progress -am -pl driver test -DargLine="-Duser.language=${{matrix.user-language}}" jackson-test: timeout-minutes: 20 @@ -212,8 +208,7 @@ jobs: - name: Info run: mvn -version - name: Test - working-directory: driver - run: mvn --no-transfer-progress test -Djackson.version=${{matrix.jackson-version}} + run: mvn --no-transfer-progress -am -pl driver test -Djackson.version=${{matrix.jackson-version}} sonar: timeout-minutes: 10 @@ -260,8 +255,7 @@ jobs: env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Needed to get PR information, if any SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} - working-directory: driver - run: mvn -B --no-transfer-progress -Dgpg.skip=true verify org.sonarsource.scanner.maven:sonar-maven-plugin:sonar -Dsonar.projectKey=arangodb_arangodb-java-driver + run: mvn -B --no-transfer-progress -Dgpg.skip=true -am -pl driver verify org.sonarsource.scanner.maven:sonar-maven-plugin:sonar -Dsonar.projectKey=arangodb_arangodb-java-driver shaded-integration-tests: timeout-minutes: 20 diff --git a/.github/workflows/native.yml b/.github/workflows/native.yml index f3edda3f7..afdd2b805 100644 --- a/.github/workflows/native.yml +++ b/.github/workflows/native.yml @@ -40,8 +40,7 @@ jobs: - name: Info run: mvn -version - name: Test Native - working-directory: driver - run: mvn -Pnative --no-transfer-progress test + run: mvn -Pnative --no-transfer-progress -am -pl driver test test-native-ssl: timeout-minutes: 20 @@ -75,5 +74,4 @@ jobs: - name: Info run: mvn -version - name: Test Native - working-directory: driver - run: mvn -Pnative --no-transfer-progress -Dgroups=ssl -DSslTest=true test + run: mvn -Pnative --no-transfer-progress -Dgroups=ssl -DSslTest=true -am -pl driver test diff --git a/.github/workflows/resilience.yml b/.github/workflows/resilience.yml index f3115a2c9..14b5d0e75 100644 --- a/.github/workflows/resilience.yml +++ b/.github/workflows/resilience.yml @@ -29,7 +29,6 @@ jobs: - name: Info run: mvn -version - name: Start Toxiproxy - working-directory: resilience-tests run: ./bin/startProxy.sh - name: Test run: mvn --no-transfer-progress -am -pl resilience-tests test From e921d39ee78e0039f6e2daf2ee7d20dcdf79959d Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Fri, 9 Dec 2022 09:37:57 +0100 Subject: [PATCH 202/254] fixed java 8 tests --- .../config/FileConfigPropertiesProvider.java | 5 ++--- pom.xml | 2 +- .../src/test/jackson/java/arch/BaseTest.java | 13 ++++--------- .../src/test/resources/arangodb.properties | 2 -- 4 files changed, 7 insertions(+), 15 deletions(-) diff --git a/driver/src/main/java/com/arangodb/internal/config/FileConfigPropertiesProvider.java b/driver/src/main/java/com/arangodb/internal/config/FileConfigPropertiesProvider.java index 99763ca39..ed147dd05 100644 --- a/driver/src/main/java/com/arangodb/internal/config/FileConfigPropertiesProvider.java +++ b/driver/src/main/java/com/arangodb/internal/config/FileConfigPropertiesProvider.java @@ -3,7 +3,6 @@ import com.arangodb.ArangoDBException; import com.arangodb.config.ConfigPropertiesProvider; -import java.io.IOException; import java.io.InputStream; import java.util.Properties; @@ -38,8 +37,8 @@ private Properties initProperties(String fileName) { Properties p = new Properties(); try (InputStream is = FileConfigPropertiesProvider.class.getResourceAsStream(fileName)) { p.load(is); - } catch (IOException e) { - throw new ArangoDBException(e); + } catch (Exception e) { + throw new ArangoDBException("Got exception while reading properties file " + fileName, e); } return p; } diff --git a/pom.xml b/pom.xml index 008081829..1db3a5ac2 100644 --- a/pom.xml +++ b/pom.xml @@ -148,7 +148,7 @@ ch.qos.logback logback-classic - 1.4.5 + 1.3.5 org.assertj diff --git a/shaded-integration-tests/src/test/jackson/java/arch/BaseTest.java b/shaded-integration-tests/src/test/jackson/java/arch/BaseTest.java index 3927d7fff..1833d3521 100644 --- a/shaded-integration-tests/src/test/jackson/java/arch/BaseTest.java +++ b/shaded-integration-tests/src/test/jackson/java/arch/BaseTest.java @@ -4,6 +4,7 @@ import com.arangodb.ContentType; import com.arangodb.DbName; import com.arangodb.Protocol; +import com.arangodb.internal.config.FileConfigPropertiesProvider; import org.junit.jupiter.params.provider.Arguments; import java.util.Arrays; @@ -11,30 +12,24 @@ public class BaseTest { protected static final DbName TEST_DB = DbName.of("java_driver_integration_tests"); - protected static final String HOST = "172.28.0.1"; - protected static final int PORT = 8529; - protected static final String PASSWD = "test"; protected static ArangoDB createAdb() { return new ArangoDB.Builder() - .host(HOST, PORT) - .password(PASSWD) + .loadProperties(new FileConfigPropertiesProvider()) .build(); } protected static ArangoDB createAdb(ContentType contentType) { Protocol protocol = contentType == ContentType.VPACK ? Protocol.HTTP2_VPACK : Protocol.HTTP2_JSON; return new ArangoDB.Builder() - .host(HOST, PORT) - .password(PASSWD) + .loadProperties(new FileConfigPropertiesProvider()) .useProtocol(protocol) .build(); } protected static ArangoDB createAdb(Protocol protocol) { return new ArangoDB.Builder() - .host(HOST, PORT) - .password(PASSWD) + .loadProperties(new FileConfigPropertiesProvider()) .useProtocol(protocol) .build(); } diff --git a/shaded-integration-tests/src/test/resources/arangodb.properties b/shaded-integration-tests/src/test/resources/arangodb.properties index c47741102..68329ae86 100644 --- a/shaded-integration-tests/src/test/resources/arangodb.properties +++ b/shaded-integration-tests/src/test/resources/arangodb.properties @@ -1,5 +1,3 @@ arangodb.hosts=172.28.0.1:8529 arangodb.acquireHostList=true arangodb.password=test -arangodb.timeout=30000 -arangodb.metrics.responseQueueTimeSamples=20 From d25384251b5f23c0996fc445dff7a9705e8c7708 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Fri, 9 Dec 2022 10:06:33 +0100 Subject: [PATCH 203/254] test fixes --- .github/workflows/maven.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index 3e4af66bc..d6e99cf41 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -117,7 +117,7 @@ jobs: - name: Info run: mvn -version - name: Test - run: mvn -e --no-transfer-progress -am -pl driver test -Dtest=com.arangodb.util.UnicodeUtilsTest + run: mvn -e --no-transfer-progress -am -pl driver test -Dtest=com.arangodb.util.UnicodeUtilsTest -Dsurefire.failIfNoSpecifiedTests=false test-jwt: timeout-minutes: 20 From 16815888c7a566f0b4ff2fb1699c7fed8c95a38e Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Fri, 9 Dec 2022 10:12:28 +0100 Subject: [PATCH 204/254] static-code-analysis mvn profile --- .github/workflows/maven.yml | 68 +++++++++++++-------------- driver/pom.xml | 91 ++++++++++++++++++++----------------- 2 files changed, 83 insertions(+), 76 deletions(-) diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index d6e99cf41..07cdaaa15 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -210,26 +210,23 @@ jobs: - name: Test run: mvn --no-transfer-progress -am -pl driver test -Djackson.version=${{matrix.jackson-version}} - sonar: - timeout-minutes: 10 + shaded-integration-tests: + timeout-minutes: 20 runs-on: ubuntu-latest strategy: fail-fast: false matrix: docker-img: - - docker.io/arangodb/enterprise:3.10.1 + - docker.io/arangodb/arangodb:3.10.1 topology: + - single - cluster - db-ext-names: - - false java-version: - - 11 + - 17 steps: - uses: actions/checkout@v2 - with: - fetch-depth: 0 - name: Set up JDK uses: actions/setup-java@v2 with: @@ -239,41 +236,39 @@ jobs: - name: Start Database run: ./docker/start_db.sh env: - ARANGO_LICENSE_KEY: ${{ secrets.ARANGO_LICENSE_KEY }} STARTER_MODE: ${{matrix.topology}} DOCKER_IMAGE: ${{matrix.docker-img}} - DATABASE_EXTENDED_NAMES: ${{matrix.db-ext-names}} - name: Info run: mvn -version - - name: Cache SonarCloud packages - uses: actions/cache@v1 - with: - path: ~/.sonar/cache - key: ${{ runner.os }}-sonar - restore-keys: ${{ runner.os }}-sonar - - name: Build and analyze - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Needed to get PR information, if any - SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} - run: mvn -B --no-transfer-progress -Dgpg.skip=true -am -pl driver verify org.sonarsource.scanner.maven:sonar-maven-plugin:sonar -Dsonar.projectKey=arangodb_arangodb-java-driver + - name: Install + run: mvn --no-transfer-progress install -DskipTests=true -Dgpg.skip=true -Dmaven.javadoc.skip=true + - name: Test jackson-serde + working-directory: shaded-integration-tests + run: mvn --no-transfer-progress -P jackson-serde test + - name: Test jsonb-serde + working-directory: shaded-integration-tests + run: mvn --no-transfer-progress -P jsonb-serde test - shaded-integration-tests: - timeout-minutes: 20 + sonar: + timeout-minutes: 10 runs-on: ubuntu-latest strategy: fail-fast: false matrix: docker-img: - - docker.io/arangodb/arangodb:3.10.1 + - docker.io/arangodb/enterprise:3.10.1 topology: - - single - cluster + db-ext-names: + - false java-version: - - 17 + - 11 steps: - uses: actions/checkout@v2 + with: + fetch-depth: 0 - name: Set up JDK uses: actions/setup-java@v2 with: @@ -283,15 +278,20 @@ jobs: - name: Start Database run: ./docker/start_db.sh env: + ARANGO_LICENSE_KEY: ${{ secrets.ARANGO_LICENSE_KEY }} STARTER_MODE: ${{matrix.topology}} DOCKER_IMAGE: ${{matrix.docker-img}} + DATABASE_EXTENDED_NAMES: ${{matrix.db-ext-names}} - name: Info run: mvn -version - - name: Install - run: mvn --no-transfer-progress install -DskipTests=true -Dgpg.skip=true -Dmaven.javadoc.skip=true - - name: Test jackson-serde - working-directory: shaded-integration-tests - run: mvn --no-transfer-progress -P jackson-serde test - - name: Test jsonb-serde - working-directory: shaded-integration-tests - run: mvn --no-transfer-progress -P jsonb-serde test + - name: Cache SonarCloud packages + uses: actions/cache@v1 + with: + path: ~/.sonar/cache + key: ${{ runner.os }}-sonar + restore-keys: ${{ runner.os }}-sonar + - name: Build and analyze + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Needed to get PR information, if any + SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} + run: mvn -Pstatic-code-analysis -B --no-transfer-progress -Dgpg.skip=true -am -pl driver verify org.sonarsource.scanner.maven:sonar-maven-plugin:sonar -Dsonar.projectKey=arangodb_arangodb-java-driver diff --git a/driver/pom.xml b/driver/pom.xml index 11c48edb8..7f3374935 100644 --- a/driver/pom.xml +++ b/driver/pom.xml @@ -83,6 +83,55 @@ + + static-code-analysis + + + + org.jacoco + jacoco-maven-plugin + 0.8.8 + + + + prepare-agent + + + + report + prepare-package + + report + + + + + + com.github.spotbugs + spotbugs-maven-plugin + 4.7.3.0 + + spotbugs/spotbugs-exclude.xml + + + + compile + + check + + + + + + com.github.spotbugs + spotbugs + 4.7.3 + + + + + + @@ -129,48 +178,6 @@ - - org.jacoco - jacoco-maven-plugin - 0.8.8 - - - - prepare-agent - - - - report - prepare-package - - report - - - - - - com.github.spotbugs - spotbugs-maven-plugin - 4.7.3.0 - - spotbugs/spotbugs-exclude.xml - - - - compile - - check - - - - - - com.github.spotbugs - spotbugs - 4.7.3 - - - org.apache.maven.plugins maven-enforcer-plugin From c48dcb954440812a87d7f2d2f0c3482b1a98aa5f Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Fri, 9 Dec 2022 10:16:44 +0100 Subject: [PATCH 205/254] test fixes --- .github/workflows/maven.yml | 2 +- pom.xml | 4 ++-- shaded-integration-tests/pom.xml | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index 07cdaaa15..564cc8cd0 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -208,7 +208,7 @@ jobs: - name: Info run: mvn -version - name: Test - run: mvn --no-transfer-progress -am -pl driver test -Djackson.version=${{matrix.jackson-version}} + run: mvn --no-transfer-progress -am -pl driver test -Dadb.jackson.version=${{matrix.jackson-version}} shaded-integration-tests: timeout-minutes: 20 diff --git a/pom.xml b/pom.xml index 1db3a5ac2..97702973f 100644 --- a/pom.xml +++ b/pom.xml @@ -32,7 +32,7 @@ 1.8 UTF-8 true - 2.14.1 + 2.14.1 @@ -90,7 +90,7 @@ com.fasterxml.jackson jackson-bom - ${jackson.version} + ${adb.jackson.version} import pom diff --git a/shaded-integration-tests/pom.xml b/shaded-integration-tests/pom.xml index b2f8c0331..e80463f53 100644 --- a/shaded-integration-tests/pom.xml +++ b/shaded-integration-tests/pom.xml @@ -12,7 +12,7 @@ 17 17 UTF-8 - 2.14.1 + 2.14.1 @@ -61,7 +61,7 @@ com.fasterxml.jackson jackson-bom - ${jackson.version} + ${adb.jackson.version} import pom From bd559ceb6dbecb0a2164a59f4028c8882af08fe4 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Fri, 9 Dec 2022 10:26:02 +0100 Subject: [PATCH 206/254] test fixes --- driver/pom.xml | 2 -- pom.xml | 2 ++ 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/driver/pom.xml b/driver/pom.xml index 7f3374935..512ad36bc 100644 --- a/driver/pom.xml +++ b/driver/pom.xml @@ -15,8 +15,6 @@ ArangoDB Java Driver - arangodb-1 - https://sonarcloud.io false false diff --git a/pom.xml b/pom.xml index 97702973f..f519de36a 100644 --- a/pom.xml +++ b/pom.xml @@ -32,6 +32,8 @@ 1.8 UTF-8 true + arangodb-1 + https://sonarcloud.io 2.14.1 From d18f621d828e56d39be3735007e68e39175c7ca5 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Fri, 9 Dec 2022 10:44:01 +0100 Subject: [PATCH 207/254] excluded tests from sonarcloud --- driver/pom.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/driver/pom.xml b/driver/pom.xml index 512ad36bc..12440d0bf 100644 --- a/driver/pom.xml +++ b/driver/pom.xml @@ -17,6 +17,7 @@ false false + src/test/**/* From 3e646f4eadee8c76b50dfd8a2c9ba03592bfef35 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Fri, 9 Dec 2022 11:27:11 +0100 Subject: [PATCH 208/254] fixed JacksonSerdeImpl --- .../arangodb/serde/jackson/internal/JacksonSerdeImpl.java | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/jackson-serde/src/main/java/com/arangodb/serde/jackson/internal/JacksonSerdeImpl.java b/jackson-serde/src/main/java/com/arangodb/serde/jackson/internal/JacksonSerdeImpl.java index f439d7c3e..887ceed31 100644 --- a/jackson-serde/src/main/java/com/arangodb/serde/jackson/internal/JacksonSerdeImpl.java +++ b/jackson-serde/src/main/java/com/arangodb/serde/jackson/internal/JacksonSerdeImpl.java @@ -18,12 +18,7 @@ public final class JacksonSerdeImpl implements JacksonSerde { public JacksonSerdeImpl(final ObjectMapper mapper) { this.mapper = mapper; - try { - mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); - } catch (Exception e) { - // to be safe in case the provided Jackson version does not support the methods above - e.printStackTrace(); - } + mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); } @Override From cf2a3e5e6665c3322305dfe98fb14c55fbe50db0 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Fri, 9 Dec 2022 12:51:23 +0100 Subject: [PATCH 209/254] fixed native tests --- .github/workflows/native.yml | 10 +- .../native-image.properties | 2 +- .../arangodb-java-driver/reflect-config.json | 94 +------------------ .../test/java/helper/NativeImageHelper.java | 8 +- 4 files changed, 14 insertions(+), 100 deletions(-) diff --git a/.github/workflows/native.yml b/.github/workflows/native.yml index afdd2b805..bae454bee 100644 --- a/.github/workflows/native.yml +++ b/.github/workflows/native.yml @@ -39,8 +39,11 @@ jobs: DATABASE_EXTENDED_NAMES: ${{matrix.db-ext-names}} - name: Info run: mvn -version + - name: Install + run: mvn --no-transfer-progress install -DskipTests=true -Dgpg.skip=true -Dmaven.javadoc.skip=true - name: Test Native - run: mvn -Pnative --no-transfer-progress -am -pl driver test + working-directory: driver + run: mvn -Pnative --no-transfer-progress test test-native-ssl: timeout-minutes: 20 @@ -73,5 +76,8 @@ jobs: SSL: true - name: Info run: mvn -version + - name: Install + run: mvn --no-transfer-progress install -DskipTests=true -Dgpg.skip=true -Dmaven.javadoc.skip=true - name: Test Native - run: mvn -Pnative --no-transfer-progress -Dgroups=ssl -DSslTest=true -am -pl driver test + working-directory: driver + run: mvn -Pnative --no-transfer-progress -Dgroups=ssl -DSslTest=true test diff --git a/driver/src/main/resources/META-INF/native-image/com.arangodb/arangodb-java-driver/native-image.properties b/driver/src/main/resources/META-INF/native-image/com.arangodb/arangodb-java-driver/native-image.properties index 264093215..0fac2f045 100644 --- a/driver/src/main/resources/META-INF/native-image/com.arangodb/arangodb-java-driver/native-image.properties +++ b/driver/src/main/resources/META-INF/native-image/com.arangodb/arangodb-java-driver/native-image.properties @@ -1,5 +1,5 @@ Args=\ --H:ResourceConfigurationFiles=target/classes/META-INF/native-image/com.arangodb/arangodb-java-driver/resource-config.json \ +-H:ResourceConfigurationResources=${.}/resource-config.json \ -H:ReflectionConfigurationResources=${.}/reflect-config.json \ -H:SerializationConfigurationResources=${.}/serialization-config.json \ --initialize-at-run-time=\ diff --git a/driver/src/main/resources/META-INF/native-image/com.arangodb/arangodb-java-driver/reflect-config.json b/driver/src/main/resources/META-INF/native-image/com.arangodb/arangodb-java-driver/reflect-config.json index c2874757c..6ff37492a 100644 --- a/driver/src/main/resources/META-INF/native-image/com.arangodb/arangodb-java-driver/reflect-config.json +++ b/driver/src/main/resources/META-INF/native-image/com.arangodb/arangodb-java-driver/reflect-config.json @@ -41,36 +41,12 @@ "allDeclaredMethods": true, "allDeclaredConstructors": true }, - { - "name": "java.lang.Enum", - "allDeclaredFields": true, - "allDeclaredMethods": true, - "allDeclaredConstructors": true - }, - { - "name": "java.lang.annotation.Annotation", - "allDeclaredFields": true, - "allDeclaredMethods": true, - "allDeclaredConstructors": true - }, - { - "name": "java.lang.Comparable", - "allDeclaredFields": true, - "allDeclaredMethods": true, - "allDeclaredConstructors": true - }, { "name": "com.arangodb.entity.CollectionEntity", "allDeclaredFields": true, "allDeclaredMethods": true, "allDeclaredConstructors": true }, - { - "name": "java.lang.Object", - "allDeclaredFields": true, - "allDeclaredMethods": true, - "allDeclaredConstructors": true - }, { "name": "com.arangodb.entity.ReplicationFactor", "allDeclaredFields": true, @@ -95,12 +71,6 @@ "allDeclaredMethods": true, "allDeclaredConstructors": true }, - { - "name": "java.io.Serializable", - "allDeclaredFields": true, - "allDeclaredMethods": true, - "allDeclaredConstructors": true - }, { "name": "com.arangodb.entity.arangosearch.SearchAliasPropertiesEntity", "allDeclaredFields": true, @@ -293,36 +263,6 @@ "allDeclaredMethods": true, "allDeclaredConstructors": true }, - { - "name": "com.arangodb.entity.Key", - "allDeclaredFields": true, - "allDeclaredMethods": true, - "allDeclaredConstructors": true - }, - { - "name": "com.arangodb.entity.Rev", - "allDeclaredFields": true, - "allDeclaredMethods": true, - "allDeclaredConstructors": true - }, - { - "name": "com.arangodb.entity.Id", - "allDeclaredFields": true, - "allDeclaredMethods": true, - "allDeclaredConstructors": true - }, - { - "name": "com.arangodb.entity.To", - "allDeclaredFields": true, - "allDeclaredMethods": true, - "allDeclaredConstructors": true - }, - { - "name": "com.arangodb.entity.From", - "allDeclaredFields": true, - "allDeclaredMethods": true, - "allDeclaredConstructors": true - }, { "name": "com.arangodb.entity.CollectionRevisionEntity", "allDeclaredFields": true, @@ -486,13 +426,13 @@ "allDeclaredConstructors": true }, { - "name": "com.arangodb.entity.AqlExecutionExplainEntity$ExecutionStats", + "name": "com.arangodb.entity.arangosearch.analyzer.DelimiterAnalyzerProperties", "allDeclaredFields": true, "allDeclaredMethods": true, "allDeclaredConstructors": true }, { - "name": "com.arangodb.entity.arangosearch.analyzer.DelimiterAnalyzerProperties", + "name": "com.arangodb.entity.AqlExecutionExplainEntity$ExecutionStats", "allDeclaredFields": true, "allDeclaredMethods": true, "allDeclaredConstructors": true @@ -1043,36 +983,12 @@ "allDeclaredMethods": true, "allDeclaredConstructors": true }, - { - "name": "java.lang.Enum", - "allDeclaredFields": true, - "allDeclaredMethods": true, - "allDeclaredConstructors": true - }, - { - "name": "java.lang.Comparable", - "allDeclaredFields": true, - "allDeclaredMethods": true, - "allDeclaredConstructors": true - }, - { - "name": "java.lang.Object", - "allDeclaredFields": true, - "allDeclaredMethods": true, - "allDeclaredConstructors": true - }, { "name": "com.arangodb.model.IndexOptions", "allDeclaredFields": true, "allDeclaredMethods": true, "allDeclaredConstructors": true }, - { - "name": "java.io.Serializable", - "allDeclaredFields": true, - "allDeclaredMethods": true, - "allDeclaredConstructors": true - }, { "name": "com.arangodb.model.DocumentImportOptions$OnDuplicate", "allDeclaredFields": true, @@ -1559,12 +1475,6 @@ "allDeclaredMethods": true, "allDeclaredConstructors": true }, - { - "name": "java.lang.Object", - "allDeclaredFields": true, - "allDeclaredMethods": true, - "allDeclaredConstructors": true - }, { "name": "com.arangodb.entity.MetaAware", "allDeclaredFields": true, diff --git a/driver/src/test/java/helper/NativeImageHelper.java b/driver/src/test/java/helper/NativeImageHelper.java index 638410dab..0b3b51c64 100644 --- a/driver/src/test/java/helper/NativeImageHelper.java +++ b/driver/src/test/java/helper/NativeImageHelper.java @@ -43,15 +43,12 @@ private static void generateReflectConfig() throws JsonProcessingException { ObjectMapper mapper = new ObjectMapper(); ArrayNode rootNode = mapper.createArrayNode(); - String serdePackage = "com.arangodb.serde"; String internalSerdePackage = "com.arangodb.internal.serde"; - Collection serdeUrls = new HashSet<>(); - serdeUrls.addAll(ClasspathHelper.forPackage(serdePackage)); - serdeUrls.addAll(ClasspathHelper.forPackage(internalSerdePackage)); + Collection serdeUrls = ClasspathHelper.forPackage(internalSerdePackage); Reflections r = new Reflections(new ConfigurationBuilder() .setScanners(new SubTypesScanner(false)) .setUrls(serdeUrls) - .filterInputsBy(new FilterBuilder().includePackage(serdePackage).includePackage(internalSerdePackage))); + .filterInputsBy(new FilterBuilder().includePackage(internalSerdePackage))); Stream serializers = r.getSubTypesOf(JsonSerializer.class).stream() .filter(it -> !it.isAnonymousClass()) .map(Class::getName); @@ -78,6 +75,7 @@ private static void generateReflectConfig() throws JsonProcessingException { ); }); Stream.concat(serdeClasses, entityClasses) + .filter(className -> className.startsWith("com.arangodb")) .map(className -> { ObjectNode entry = mapper.createObjectNode(); entry.put("name", className); From 4df778dcda693fe7086476a5850acb2f53c68ecc Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Mon, 12 Dec 2022 10:56:04 +0100 Subject: [PATCH 210/254] [DE-439] Shaded native image configuration (#475) * shaded native tests * shaded native tests CI --- .github/workflows/native.yml | 13 +- .../native-image.properties | 4 +- .../java/com/arangodb/serde/SerdeTest.java | 31 - .../native-image/native-image.properties | 2 +- shaded-integration-tests/pom.xml | 36 +- .../com/arangodb/ArangoCollectionTest.java | 0 .../java/com/arangodb/ArangoCursorTest.java | 0 .../java/com/arangodb/ArangoDBTest.java | 0 .../java/com/arangodb/ArangoDatabaseTest.java | 0 .../com/arangodb/ArangoDocumentUtilTest.java | 0 .../arangodb/ArangoEdgeCollectionTest.java | 0 .../java/com/arangodb/ArangoGraphTest.java | 0 .../java/com/arangodb/ArangoSearchTest.java | 0 .../java/com/arangodb/ArangoSslTest.java | 0 .../arangodb/ArangoVertexCollectionTest.java | 0 .../java/com/arangodb/ArangoViewTest.java | 0 .../java/com/arangodb/BaseJunit5.java | 0 .../java/com/arangodb/ConcurrencyTests.java | 0 .../java/com/arangodb/DocumentTest.java | 0 .../java/com/arangodb/InvertedIndexTest.java | 0 .../java/com/arangodb/JwtAuthTest.java | 0 .../java/com/arangodb/ParallelTest.java | 0 .../java/com/arangodb/SerializableTest.java | 0 .../StreamTransactionConflictsTest.java | 0 .../arangodb/StreamTransactionGraphTest.java | 0 .../com/arangodb/StreamTransactionTest.java | 0 .../arangodb/annotations/AnnotatedEntity.java | 0 .../annotations/ArangoAnnotationsTest.java | 0 .../arangodb/async/ArangoCollectionTest.java | 0 .../java/com/arangodb/async/ArangoDBTest.java | 0 .../arangodb/async/ArangoDatabaseTest.java | 0 .../async/ArangoEdgeCollectionTest.java | 0 .../com/arangodb/async/ArangoGraphTest.java | 0 .../com/arangodb/async/ArangoRouteTest.java | 0 .../com/arangodb/async/ArangoSearchTest.java | 0 .../async/ArangoVertexCollectionTest.java | 0 .../com/arangodb/async/ArangoViewTest.java | 0 .../java/com/arangodb/async/BaseTest.java | 0 .../com/arangodb/async/CommunicationTest.java | 0 .../com/arangodb/async/ConcurrencyTest.java | 0 .../com/arangodb/async/ConcurrencyTests.java | 0 .../com/arangodb/async/InvertedIndexTest.java | 0 .../java/com/arangodb/async/JwtAuthTest.java | 0 .../async/StreamTransactionConflictsTest.java | 0 .../async/StreamTransactionGraphTest.java | 0 .../arangodb/async/StreamTransactionTest.java | 0 .../debug/ConsolidationIntervalMsecTest.java | 0 .../arangodb/async/example/ExampleBase.java | 0 ...ueryWithSpecialReturnTypesExampleTest.java | 0 .../document/GetDocumentExampleTest.java | 0 .../document/ImportDocumentExampleTest.java | 0 .../document/InsertDocumentExampleTest.java | 0 .../async/example/document/TestEntity.java | 0 .../graph/AQLActorsAndMoviesExampleTest.java | 0 .../async/example/graph/BaseGraphTest.java | 0 .../arangodb/async/example/graph/Circle.java | 0 .../async/example/graph/CircleEdge.java | 0 .../GraphTraversalsInAQLExampleTest.java | 0 .../graph/ShortestPathInAQLExampleTest.java | 0 .../async/example/ssl/SslExampleTest.java | 0 .../arangodb/async/serde/CustomSerdeTest.java | 0 .../com/arangodb/example/ExampleBase.java | 0 .../com/arangodb/example/FirstProject.java | 0 ...ueryWithSpecialReturnTypesExampleTest.java | 0 .../document/GetDocumentExampleTest.java | 0 .../document/InsertDocumentExampleTest.java | 0 .../arangodb/example/document/TestEntity.java | 0 .../graph/AQLActorsAndMoviesExampleTest.java | 0 .../arangodb/example/graph/BaseGraphTest.java | 0 .../com/arangodb/example/graph/Circle.java | 0 .../arangodb/example/graph/CircleEdge.java | 0 .../GraphTraversalsInAQLExampleTest.java | 0 .../graph/ShortestPathInAQLExampleTest.java | 0 .../arangodb/example/ssl/SslExampleTest.java | 0 .../arangodb/internal/HostHandlerTest.java | 0 .../internal/QueueTimeMetricsImplTest.java | 0 .../velocystream/CommunicationTest.java | 0 .../com/arangodb/serde/CustomSerdeTest.java | 0 .../arangodb/serde/CustomTypeHintTest.java | 0 .../java/com/arangodb/serde/SerdeTest.java | 31 - .../java/com/arangodb/util/MapBuilder.java | 0 .../com/arangodb/util/MapBuilderTest.java | 0 .../java/com/arangodb/util/TestUtils.java | 0 .../native-image/native-image.properties | 8 + .../META-INF/native-image/reflect-config.json | 359 ++++ .../native-image/resource-config.json | 22 + .../native-image/serialization-config.json | 23 + .../src/test/resources/example.truststore | Bin 0 -> 2251 bytes shaded/pom.xml | 4 +- .../native-image.properties | 9 + .../netty-reflect-config.json | 923 ++++++++++ .../reflect-config.json | 1496 +++++++++++++++++ .../resource-config.json | 10 + .../serialization-config.json | 26 + 94 files changed, 2919 insertions(+), 78 deletions(-) rename shaded-integration-tests/src/test/{jackson => native}/java/com/arangodb/ArangoCollectionTest.java (100%) rename shaded-integration-tests/src/test/{jackson => native}/java/com/arangodb/ArangoCursorTest.java (100%) rename shaded-integration-tests/src/test/{jackson => native}/java/com/arangodb/ArangoDBTest.java (100%) rename shaded-integration-tests/src/test/{jackson => native}/java/com/arangodb/ArangoDatabaseTest.java (100%) rename shaded-integration-tests/src/test/{jackson => native}/java/com/arangodb/ArangoDocumentUtilTest.java (100%) rename shaded-integration-tests/src/test/{jackson => native}/java/com/arangodb/ArangoEdgeCollectionTest.java (100%) rename shaded-integration-tests/src/test/{jackson => native}/java/com/arangodb/ArangoGraphTest.java (100%) rename shaded-integration-tests/src/test/{jackson => native}/java/com/arangodb/ArangoSearchTest.java (100%) rename shaded-integration-tests/src/test/{jackson => native}/java/com/arangodb/ArangoSslTest.java (100%) rename shaded-integration-tests/src/test/{jackson => native}/java/com/arangodb/ArangoVertexCollectionTest.java (100%) rename shaded-integration-tests/src/test/{jackson => native}/java/com/arangodb/ArangoViewTest.java (100%) rename shaded-integration-tests/src/test/{jackson => native}/java/com/arangodb/BaseJunit5.java (100%) rename shaded-integration-tests/src/test/{jackson => native}/java/com/arangodb/ConcurrencyTests.java (100%) rename shaded-integration-tests/src/test/{jackson => native}/java/com/arangodb/DocumentTest.java (100%) rename shaded-integration-tests/src/test/{jackson => native}/java/com/arangodb/InvertedIndexTest.java (100%) rename shaded-integration-tests/src/test/{jackson => native}/java/com/arangodb/JwtAuthTest.java (100%) rename shaded-integration-tests/src/test/{jackson => native}/java/com/arangodb/ParallelTest.java (100%) rename shaded-integration-tests/src/test/{jackson => native}/java/com/arangodb/SerializableTest.java (100%) rename shaded-integration-tests/src/test/{jackson => native}/java/com/arangodb/StreamTransactionConflictsTest.java (100%) rename shaded-integration-tests/src/test/{jackson => native}/java/com/arangodb/StreamTransactionGraphTest.java (100%) rename shaded-integration-tests/src/test/{jackson => native}/java/com/arangodb/StreamTransactionTest.java (100%) rename shaded-integration-tests/src/test/{jackson => native}/java/com/arangodb/annotations/AnnotatedEntity.java (100%) rename shaded-integration-tests/src/test/{jackson => native}/java/com/arangodb/annotations/ArangoAnnotationsTest.java (100%) rename shaded-integration-tests/src/test/{jackson => native}/java/com/arangodb/async/ArangoCollectionTest.java (100%) rename shaded-integration-tests/src/test/{jackson => native}/java/com/arangodb/async/ArangoDBTest.java (100%) rename shaded-integration-tests/src/test/{jackson => native}/java/com/arangodb/async/ArangoDatabaseTest.java (100%) rename shaded-integration-tests/src/test/{jackson => native}/java/com/arangodb/async/ArangoEdgeCollectionTest.java (100%) rename shaded-integration-tests/src/test/{jackson => native}/java/com/arangodb/async/ArangoGraphTest.java (100%) rename shaded-integration-tests/src/test/{jackson => native}/java/com/arangodb/async/ArangoRouteTest.java (100%) rename shaded-integration-tests/src/test/{jackson => native}/java/com/arangodb/async/ArangoSearchTest.java (100%) rename shaded-integration-tests/src/test/{jackson => native}/java/com/arangodb/async/ArangoVertexCollectionTest.java (100%) rename shaded-integration-tests/src/test/{jackson => native}/java/com/arangodb/async/ArangoViewTest.java (100%) rename shaded-integration-tests/src/test/{jackson => native}/java/com/arangodb/async/BaseTest.java (100%) rename shaded-integration-tests/src/test/{jackson => native}/java/com/arangodb/async/CommunicationTest.java (100%) rename shaded-integration-tests/src/test/{jackson => native}/java/com/arangodb/async/ConcurrencyTest.java (100%) rename shaded-integration-tests/src/test/{jackson => native}/java/com/arangodb/async/ConcurrencyTests.java (100%) rename shaded-integration-tests/src/test/{jackson => native}/java/com/arangodb/async/InvertedIndexTest.java (100%) rename shaded-integration-tests/src/test/{jackson => native}/java/com/arangodb/async/JwtAuthTest.java (100%) rename shaded-integration-tests/src/test/{jackson => native}/java/com/arangodb/async/StreamTransactionConflictsTest.java (100%) rename shaded-integration-tests/src/test/{jackson => native}/java/com/arangodb/async/StreamTransactionGraphTest.java (100%) rename shaded-integration-tests/src/test/{jackson => native}/java/com/arangodb/async/StreamTransactionTest.java (100%) rename shaded-integration-tests/src/test/{jackson => native}/java/com/arangodb/async/debug/ConsolidationIntervalMsecTest.java (100%) rename shaded-integration-tests/src/test/{jackson => native}/java/com/arangodb/async/example/ExampleBase.java (100%) rename shaded-integration-tests/src/test/{jackson => native}/java/com/arangodb/async/example/document/AqlQueryWithSpecialReturnTypesExampleTest.java (100%) rename shaded-integration-tests/src/test/{jackson => native}/java/com/arangodb/async/example/document/GetDocumentExampleTest.java (100%) rename shaded-integration-tests/src/test/{jackson => native}/java/com/arangodb/async/example/document/ImportDocumentExampleTest.java (100%) rename shaded-integration-tests/src/test/{jackson => native}/java/com/arangodb/async/example/document/InsertDocumentExampleTest.java (100%) rename shaded-integration-tests/src/test/{jackson => native}/java/com/arangodb/async/example/document/TestEntity.java (100%) rename shaded-integration-tests/src/test/{jackson => native}/java/com/arangodb/async/example/graph/AQLActorsAndMoviesExampleTest.java (100%) rename shaded-integration-tests/src/test/{jackson => native}/java/com/arangodb/async/example/graph/BaseGraphTest.java (100%) rename shaded-integration-tests/src/test/{jackson => native}/java/com/arangodb/async/example/graph/Circle.java (100%) rename shaded-integration-tests/src/test/{jackson => native}/java/com/arangodb/async/example/graph/CircleEdge.java (100%) rename shaded-integration-tests/src/test/{jackson => native}/java/com/arangodb/async/example/graph/GraphTraversalsInAQLExampleTest.java (100%) rename shaded-integration-tests/src/test/{jackson => native}/java/com/arangodb/async/example/graph/ShortestPathInAQLExampleTest.java (100%) rename shaded-integration-tests/src/test/{jackson => native}/java/com/arangodb/async/example/ssl/SslExampleTest.java (100%) rename shaded-integration-tests/src/test/{jackson => native}/java/com/arangodb/async/serde/CustomSerdeTest.java (100%) rename shaded-integration-tests/src/test/{jackson => native}/java/com/arangodb/example/ExampleBase.java (100%) rename shaded-integration-tests/src/test/{jackson => native}/java/com/arangodb/example/FirstProject.java (100%) rename shaded-integration-tests/src/test/{jackson => native}/java/com/arangodb/example/document/AqlQueryWithSpecialReturnTypesExampleTest.java (100%) rename shaded-integration-tests/src/test/{jackson => native}/java/com/arangodb/example/document/GetDocumentExampleTest.java (100%) rename shaded-integration-tests/src/test/{jackson => native}/java/com/arangodb/example/document/InsertDocumentExampleTest.java (100%) rename shaded-integration-tests/src/test/{jackson => native}/java/com/arangodb/example/document/TestEntity.java (100%) rename shaded-integration-tests/src/test/{jackson => native}/java/com/arangodb/example/graph/AQLActorsAndMoviesExampleTest.java (100%) rename shaded-integration-tests/src/test/{jackson => native}/java/com/arangodb/example/graph/BaseGraphTest.java (100%) rename shaded-integration-tests/src/test/{jackson => native}/java/com/arangodb/example/graph/Circle.java (100%) rename shaded-integration-tests/src/test/{jackson => native}/java/com/arangodb/example/graph/CircleEdge.java (100%) rename shaded-integration-tests/src/test/{jackson => native}/java/com/arangodb/example/graph/GraphTraversalsInAQLExampleTest.java (100%) rename shaded-integration-tests/src/test/{jackson => native}/java/com/arangodb/example/graph/ShortestPathInAQLExampleTest.java (100%) rename shaded-integration-tests/src/test/{jackson => native}/java/com/arangodb/example/ssl/SslExampleTest.java (100%) rename shaded-integration-tests/src/test/{jackson => native}/java/com/arangodb/internal/HostHandlerTest.java (100%) rename shaded-integration-tests/src/test/{jackson => native}/java/com/arangodb/internal/QueueTimeMetricsImplTest.java (100%) rename shaded-integration-tests/src/test/{jackson => native}/java/com/arangodb/internal/velocystream/CommunicationTest.java (100%) rename shaded-integration-tests/src/test/{jackson => native}/java/com/arangodb/serde/CustomSerdeTest.java (100%) rename shaded-integration-tests/src/test/{jackson => native}/java/com/arangodb/serde/CustomTypeHintTest.java (100%) rename shaded-integration-tests/src/test/{jackson => native}/java/com/arangodb/serde/SerdeTest.java (57%) rename shaded-integration-tests/src/test/{jackson => native}/java/com/arangodb/util/MapBuilder.java (100%) rename shaded-integration-tests/src/test/{jackson => native}/java/com/arangodb/util/MapBuilderTest.java (100%) rename shaded-integration-tests/src/test/{jackson => native}/java/com/arangodb/util/TestUtils.java (100%) create mode 100644 shaded-integration-tests/src/test/resources/META-INF/native-image/native-image.properties create mode 100644 shaded-integration-tests/src/test/resources/META-INF/native-image/reflect-config.json create mode 100644 shaded-integration-tests/src/test/resources/META-INF/native-image/resource-config.json create mode 100644 shaded-integration-tests/src/test/resources/META-INF/native-image/serialization-config.json create mode 100644 shaded-integration-tests/src/test/resources/example.truststore create mode 100644 shaded/src/main/resources/META-INF/native-image/com.arangodb/arangodb-java-driver-shaded/native-image.properties create mode 100644 shaded/src/main/resources/META-INF/native-image/com.arangodb/arangodb-java-driver-shaded/netty-reflect-config.json create mode 100644 shaded/src/main/resources/META-INF/native-image/com.arangodb/arangodb-java-driver-shaded/reflect-config.json create mode 100644 shaded/src/main/resources/META-INF/native-image/com.arangodb/arangodb-java-driver-shaded/resource-config.json create mode 100644 shaded/src/main/resources/META-INF/native-image/com.arangodb/arangodb-java-driver-shaded/serialization-config.json diff --git a/.github/workflows/native.yml b/.github/workflows/native.yml index bae454bee..163ab1bbb 100644 --- a/.github/workflows/native.yml +++ b/.github/workflows/native.yml @@ -17,10 +17,11 @@ jobs: - docker.io/arangodb/enterprise:3.10.1 topology: - cluster - db-ext-names: - - false java-version: - 17 + module: + - driver + - shaded steps: - uses: actions/checkout@v2 @@ -36,13 +37,12 @@ jobs: ARANGO_LICENSE_KEY: ${{ secrets.ARANGO_LICENSE_KEY }} STARTER_MODE: ${{matrix.topology}} DOCKER_IMAGE: ${{matrix.docker-img}} - DATABASE_EXTENDED_NAMES: ${{matrix.db-ext-names}} - name: Info run: mvn -version - name: Install run: mvn --no-transfer-progress install -DskipTests=true -Dgpg.skip=true -Dmaven.javadoc.skip=true - name: Test Native - working-directory: driver + working-directory: ${{matrix.module}} run: mvn -Pnative --no-transfer-progress test test-native-ssl: @@ -58,6 +58,9 @@ jobs: - single java-version: - 17 + module: + - driver + - shaded steps: - uses: actions/checkout@v2 @@ -79,5 +82,5 @@ jobs: - name: Install run: mvn --no-transfer-progress install -DskipTests=true -Dgpg.skip=true -Dmaven.javadoc.skip=true - name: Test Native - working-directory: driver + working-directory: ${{matrix.module}} run: mvn -Pnative --no-transfer-progress -Dgroups=ssl -DSslTest=true test diff --git a/driver/src/main/resources/META-INF/native-image/com.arangodb/arangodb-java-driver/native-image.properties b/driver/src/main/resources/META-INF/native-image/com.arangodb/arangodb-java-driver/native-image.properties index 0fac2f045..60c5b90d2 100644 --- a/driver/src/main/resources/META-INF/native-image/com.arangodb/arangodb-java-driver/native-image.properties +++ b/driver/src/main/resources/META-INF/native-image/com.arangodb/arangodb-java-driver/native-image.properties @@ -4,4 +4,6 @@ Args=\ -H:SerializationConfigurationResources=${.}/serialization-config.json \ --initialize-at-run-time=\ io.netty.handler.ssl.BouncyCastleAlpnSslUtils,\ - io.netty.handler.codec.compression.ZstdOptions + io.netty.handler.codec.compression.ZstdOptions \ +-Dio.netty.noUnsafe=true \ +-Dio.netty.leakDetection.level=DISABLED diff --git a/driver/src/test/java/com/arangodb/serde/SerdeTest.java b/driver/src/test/java/com/arangodb/serde/SerdeTest.java index 73517f8b7..35605178f 100644 --- a/driver/src/test/java/com/arangodb/serde/SerdeTest.java +++ b/driver/src/test/java/com/arangodb/serde/SerdeTest.java @@ -5,14 +5,11 @@ import com.arangodb.internal.serde.SerdeUtils; import com.arangodb.util.RawBytes; import com.arangodb.util.RawJson; -import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.node.JsonNodeFactory; import com.fasterxml.jackson.databind.node.ObjectNode; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.EnumSource; -import java.sql.Date; - import static org.assertj.core.api.Assertions.assertThat; @@ -40,32 +37,4 @@ void rawBytesSerde(ContentType type) { assertThat(deserialized).isEqualTo(raw); } - @ParameterizedTest - @EnumSource(ContentType.class) - void utilDateSerde(ContentType type) { - InternalSerde s = InternalSerde.of(type, null); - long ts = 1000000000000L; - java.util.Date date = new java.util.Date(ts); - byte[] ser = s.serialize(date); - JsonNode node = s.parse(ser); - assertThat(node.isLong()).isTrue(); - assertThat(node.longValue()).isEqualTo(ts); - java.util.Date deser = s.deserialize(ser, java.util.Date.class); - assertThat(deser).isEqualTo(date); - } - - @ParameterizedTest - @EnumSource(ContentType.class) - void sqlDateSerde(ContentType type) { - InternalSerde s = InternalSerde.of(type, null); - long ts = 1000000000000L; - java.sql.Date date = new Date(ts); - byte[] ser = s.serialize(date); - JsonNode node = s.parse(ser); - assertThat(node.isLong()).isTrue(); - assertThat(node.longValue()).isEqualTo(ts); - java.sql.Date deser = s.deserialize(ser, java.sql.Date.class); - assertThat(deser).isEqualTo(date); - } - } diff --git a/driver/src/test/resources/META-INF/native-image/native-image.properties b/driver/src/test/resources/META-INF/native-image/native-image.properties index 0c3f4b841..b039368e7 100644 --- a/driver/src/test/resources/META-INF/native-image/native-image.properties +++ b/driver/src/test/resources/META-INF/native-image/native-image.properties @@ -1,5 +1,5 @@ Args=\ - -H:ResourceConfigurationFiles=target/test-classes/META-INF/native-image/resource-config.json \ + -H:ResourceConfigurationResources=${.}/resource-config.json \ -H:ReflectionConfigurationResources=${.}/reflect-config.json \ -H:SerializationConfigurationResources=${.}/serialization-config.json \ --initialize-at-build-time=\ diff --git a/shaded-integration-tests/pom.xml b/shaded-integration-tests/pom.xml index e80463f53..8194e89a5 100644 --- a/shaded-integration-tests/pom.xml +++ b/shaded-integration-tests/pom.xml @@ -48,12 +48,6 @@ 3.23.1 test - - com.tngtech.archunit - archunit-junit5 - 1.0.1 - test - @@ -128,6 +122,12 @@ 3.1.0 test + + com.tngtech.archunit + archunit-junit5 + 1.0.1 + test + @@ -160,10 +160,34 @@ yasson 3.0.2 + + com.tngtech.archunit + archunit-junit5 + 1.0.1 + test + native + + src/test/native/java + jackson + + + + com.arangodb + arangodb-java-driver-shaded + 7.0.0-SNAPSHOT + test + + + com.arangodb + jackson-dataformat-velocypack + 3.1.0 + test + + diff --git a/shaded-integration-tests/src/test/jackson/java/com/arangodb/ArangoCollectionTest.java b/shaded-integration-tests/src/test/native/java/com/arangodb/ArangoCollectionTest.java similarity index 100% rename from shaded-integration-tests/src/test/jackson/java/com/arangodb/ArangoCollectionTest.java rename to shaded-integration-tests/src/test/native/java/com/arangodb/ArangoCollectionTest.java diff --git a/shaded-integration-tests/src/test/jackson/java/com/arangodb/ArangoCursorTest.java b/shaded-integration-tests/src/test/native/java/com/arangodb/ArangoCursorTest.java similarity index 100% rename from shaded-integration-tests/src/test/jackson/java/com/arangodb/ArangoCursorTest.java rename to shaded-integration-tests/src/test/native/java/com/arangodb/ArangoCursorTest.java diff --git a/shaded-integration-tests/src/test/jackson/java/com/arangodb/ArangoDBTest.java b/shaded-integration-tests/src/test/native/java/com/arangodb/ArangoDBTest.java similarity index 100% rename from shaded-integration-tests/src/test/jackson/java/com/arangodb/ArangoDBTest.java rename to shaded-integration-tests/src/test/native/java/com/arangodb/ArangoDBTest.java diff --git a/shaded-integration-tests/src/test/jackson/java/com/arangodb/ArangoDatabaseTest.java b/shaded-integration-tests/src/test/native/java/com/arangodb/ArangoDatabaseTest.java similarity index 100% rename from shaded-integration-tests/src/test/jackson/java/com/arangodb/ArangoDatabaseTest.java rename to shaded-integration-tests/src/test/native/java/com/arangodb/ArangoDatabaseTest.java diff --git a/shaded-integration-tests/src/test/jackson/java/com/arangodb/ArangoDocumentUtilTest.java b/shaded-integration-tests/src/test/native/java/com/arangodb/ArangoDocumentUtilTest.java similarity index 100% rename from shaded-integration-tests/src/test/jackson/java/com/arangodb/ArangoDocumentUtilTest.java rename to shaded-integration-tests/src/test/native/java/com/arangodb/ArangoDocumentUtilTest.java diff --git a/shaded-integration-tests/src/test/jackson/java/com/arangodb/ArangoEdgeCollectionTest.java b/shaded-integration-tests/src/test/native/java/com/arangodb/ArangoEdgeCollectionTest.java similarity index 100% rename from shaded-integration-tests/src/test/jackson/java/com/arangodb/ArangoEdgeCollectionTest.java rename to shaded-integration-tests/src/test/native/java/com/arangodb/ArangoEdgeCollectionTest.java diff --git a/shaded-integration-tests/src/test/jackson/java/com/arangodb/ArangoGraphTest.java b/shaded-integration-tests/src/test/native/java/com/arangodb/ArangoGraphTest.java similarity index 100% rename from shaded-integration-tests/src/test/jackson/java/com/arangodb/ArangoGraphTest.java rename to shaded-integration-tests/src/test/native/java/com/arangodb/ArangoGraphTest.java diff --git a/shaded-integration-tests/src/test/jackson/java/com/arangodb/ArangoSearchTest.java b/shaded-integration-tests/src/test/native/java/com/arangodb/ArangoSearchTest.java similarity index 100% rename from shaded-integration-tests/src/test/jackson/java/com/arangodb/ArangoSearchTest.java rename to shaded-integration-tests/src/test/native/java/com/arangodb/ArangoSearchTest.java diff --git a/shaded-integration-tests/src/test/jackson/java/com/arangodb/ArangoSslTest.java b/shaded-integration-tests/src/test/native/java/com/arangodb/ArangoSslTest.java similarity index 100% rename from shaded-integration-tests/src/test/jackson/java/com/arangodb/ArangoSslTest.java rename to shaded-integration-tests/src/test/native/java/com/arangodb/ArangoSslTest.java diff --git a/shaded-integration-tests/src/test/jackson/java/com/arangodb/ArangoVertexCollectionTest.java b/shaded-integration-tests/src/test/native/java/com/arangodb/ArangoVertexCollectionTest.java similarity index 100% rename from shaded-integration-tests/src/test/jackson/java/com/arangodb/ArangoVertexCollectionTest.java rename to shaded-integration-tests/src/test/native/java/com/arangodb/ArangoVertexCollectionTest.java diff --git a/shaded-integration-tests/src/test/jackson/java/com/arangodb/ArangoViewTest.java b/shaded-integration-tests/src/test/native/java/com/arangodb/ArangoViewTest.java similarity index 100% rename from shaded-integration-tests/src/test/jackson/java/com/arangodb/ArangoViewTest.java rename to shaded-integration-tests/src/test/native/java/com/arangodb/ArangoViewTest.java diff --git a/shaded-integration-tests/src/test/jackson/java/com/arangodb/BaseJunit5.java b/shaded-integration-tests/src/test/native/java/com/arangodb/BaseJunit5.java similarity index 100% rename from shaded-integration-tests/src/test/jackson/java/com/arangodb/BaseJunit5.java rename to shaded-integration-tests/src/test/native/java/com/arangodb/BaseJunit5.java diff --git a/shaded-integration-tests/src/test/jackson/java/com/arangodb/ConcurrencyTests.java b/shaded-integration-tests/src/test/native/java/com/arangodb/ConcurrencyTests.java similarity index 100% rename from shaded-integration-tests/src/test/jackson/java/com/arangodb/ConcurrencyTests.java rename to shaded-integration-tests/src/test/native/java/com/arangodb/ConcurrencyTests.java diff --git a/shaded-integration-tests/src/test/jackson/java/com/arangodb/DocumentTest.java b/shaded-integration-tests/src/test/native/java/com/arangodb/DocumentTest.java similarity index 100% rename from shaded-integration-tests/src/test/jackson/java/com/arangodb/DocumentTest.java rename to shaded-integration-tests/src/test/native/java/com/arangodb/DocumentTest.java diff --git a/shaded-integration-tests/src/test/jackson/java/com/arangodb/InvertedIndexTest.java b/shaded-integration-tests/src/test/native/java/com/arangodb/InvertedIndexTest.java similarity index 100% rename from shaded-integration-tests/src/test/jackson/java/com/arangodb/InvertedIndexTest.java rename to shaded-integration-tests/src/test/native/java/com/arangodb/InvertedIndexTest.java diff --git a/shaded-integration-tests/src/test/jackson/java/com/arangodb/JwtAuthTest.java b/shaded-integration-tests/src/test/native/java/com/arangodb/JwtAuthTest.java similarity index 100% rename from shaded-integration-tests/src/test/jackson/java/com/arangodb/JwtAuthTest.java rename to shaded-integration-tests/src/test/native/java/com/arangodb/JwtAuthTest.java diff --git a/shaded-integration-tests/src/test/jackson/java/com/arangodb/ParallelTest.java b/shaded-integration-tests/src/test/native/java/com/arangodb/ParallelTest.java similarity index 100% rename from shaded-integration-tests/src/test/jackson/java/com/arangodb/ParallelTest.java rename to shaded-integration-tests/src/test/native/java/com/arangodb/ParallelTest.java diff --git a/shaded-integration-tests/src/test/jackson/java/com/arangodb/SerializableTest.java b/shaded-integration-tests/src/test/native/java/com/arangodb/SerializableTest.java similarity index 100% rename from shaded-integration-tests/src/test/jackson/java/com/arangodb/SerializableTest.java rename to shaded-integration-tests/src/test/native/java/com/arangodb/SerializableTest.java diff --git a/shaded-integration-tests/src/test/jackson/java/com/arangodb/StreamTransactionConflictsTest.java b/shaded-integration-tests/src/test/native/java/com/arangodb/StreamTransactionConflictsTest.java similarity index 100% rename from shaded-integration-tests/src/test/jackson/java/com/arangodb/StreamTransactionConflictsTest.java rename to shaded-integration-tests/src/test/native/java/com/arangodb/StreamTransactionConflictsTest.java diff --git a/shaded-integration-tests/src/test/jackson/java/com/arangodb/StreamTransactionGraphTest.java b/shaded-integration-tests/src/test/native/java/com/arangodb/StreamTransactionGraphTest.java similarity index 100% rename from shaded-integration-tests/src/test/jackson/java/com/arangodb/StreamTransactionGraphTest.java rename to shaded-integration-tests/src/test/native/java/com/arangodb/StreamTransactionGraphTest.java diff --git a/shaded-integration-tests/src/test/jackson/java/com/arangodb/StreamTransactionTest.java b/shaded-integration-tests/src/test/native/java/com/arangodb/StreamTransactionTest.java similarity index 100% rename from shaded-integration-tests/src/test/jackson/java/com/arangodb/StreamTransactionTest.java rename to shaded-integration-tests/src/test/native/java/com/arangodb/StreamTransactionTest.java diff --git a/shaded-integration-tests/src/test/jackson/java/com/arangodb/annotations/AnnotatedEntity.java b/shaded-integration-tests/src/test/native/java/com/arangodb/annotations/AnnotatedEntity.java similarity index 100% rename from shaded-integration-tests/src/test/jackson/java/com/arangodb/annotations/AnnotatedEntity.java rename to shaded-integration-tests/src/test/native/java/com/arangodb/annotations/AnnotatedEntity.java diff --git a/shaded-integration-tests/src/test/jackson/java/com/arangodb/annotations/ArangoAnnotationsTest.java b/shaded-integration-tests/src/test/native/java/com/arangodb/annotations/ArangoAnnotationsTest.java similarity index 100% rename from shaded-integration-tests/src/test/jackson/java/com/arangodb/annotations/ArangoAnnotationsTest.java rename to shaded-integration-tests/src/test/native/java/com/arangodb/annotations/ArangoAnnotationsTest.java diff --git a/shaded-integration-tests/src/test/jackson/java/com/arangodb/async/ArangoCollectionTest.java b/shaded-integration-tests/src/test/native/java/com/arangodb/async/ArangoCollectionTest.java similarity index 100% rename from shaded-integration-tests/src/test/jackson/java/com/arangodb/async/ArangoCollectionTest.java rename to shaded-integration-tests/src/test/native/java/com/arangodb/async/ArangoCollectionTest.java diff --git a/shaded-integration-tests/src/test/jackson/java/com/arangodb/async/ArangoDBTest.java b/shaded-integration-tests/src/test/native/java/com/arangodb/async/ArangoDBTest.java similarity index 100% rename from shaded-integration-tests/src/test/jackson/java/com/arangodb/async/ArangoDBTest.java rename to shaded-integration-tests/src/test/native/java/com/arangodb/async/ArangoDBTest.java diff --git a/shaded-integration-tests/src/test/jackson/java/com/arangodb/async/ArangoDatabaseTest.java b/shaded-integration-tests/src/test/native/java/com/arangodb/async/ArangoDatabaseTest.java similarity index 100% rename from shaded-integration-tests/src/test/jackson/java/com/arangodb/async/ArangoDatabaseTest.java rename to shaded-integration-tests/src/test/native/java/com/arangodb/async/ArangoDatabaseTest.java diff --git a/shaded-integration-tests/src/test/jackson/java/com/arangodb/async/ArangoEdgeCollectionTest.java b/shaded-integration-tests/src/test/native/java/com/arangodb/async/ArangoEdgeCollectionTest.java similarity index 100% rename from shaded-integration-tests/src/test/jackson/java/com/arangodb/async/ArangoEdgeCollectionTest.java rename to shaded-integration-tests/src/test/native/java/com/arangodb/async/ArangoEdgeCollectionTest.java diff --git a/shaded-integration-tests/src/test/jackson/java/com/arangodb/async/ArangoGraphTest.java b/shaded-integration-tests/src/test/native/java/com/arangodb/async/ArangoGraphTest.java similarity index 100% rename from shaded-integration-tests/src/test/jackson/java/com/arangodb/async/ArangoGraphTest.java rename to shaded-integration-tests/src/test/native/java/com/arangodb/async/ArangoGraphTest.java diff --git a/shaded-integration-tests/src/test/jackson/java/com/arangodb/async/ArangoRouteTest.java b/shaded-integration-tests/src/test/native/java/com/arangodb/async/ArangoRouteTest.java similarity index 100% rename from shaded-integration-tests/src/test/jackson/java/com/arangodb/async/ArangoRouteTest.java rename to shaded-integration-tests/src/test/native/java/com/arangodb/async/ArangoRouteTest.java diff --git a/shaded-integration-tests/src/test/jackson/java/com/arangodb/async/ArangoSearchTest.java b/shaded-integration-tests/src/test/native/java/com/arangodb/async/ArangoSearchTest.java similarity index 100% rename from shaded-integration-tests/src/test/jackson/java/com/arangodb/async/ArangoSearchTest.java rename to shaded-integration-tests/src/test/native/java/com/arangodb/async/ArangoSearchTest.java diff --git a/shaded-integration-tests/src/test/jackson/java/com/arangodb/async/ArangoVertexCollectionTest.java b/shaded-integration-tests/src/test/native/java/com/arangodb/async/ArangoVertexCollectionTest.java similarity index 100% rename from shaded-integration-tests/src/test/jackson/java/com/arangodb/async/ArangoVertexCollectionTest.java rename to shaded-integration-tests/src/test/native/java/com/arangodb/async/ArangoVertexCollectionTest.java diff --git a/shaded-integration-tests/src/test/jackson/java/com/arangodb/async/ArangoViewTest.java b/shaded-integration-tests/src/test/native/java/com/arangodb/async/ArangoViewTest.java similarity index 100% rename from shaded-integration-tests/src/test/jackson/java/com/arangodb/async/ArangoViewTest.java rename to shaded-integration-tests/src/test/native/java/com/arangodb/async/ArangoViewTest.java diff --git a/shaded-integration-tests/src/test/jackson/java/com/arangodb/async/BaseTest.java b/shaded-integration-tests/src/test/native/java/com/arangodb/async/BaseTest.java similarity index 100% rename from shaded-integration-tests/src/test/jackson/java/com/arangodb/async/BaseTest.java rename to shaded-integration-tests/src/test/native/java/com/arangodb/async/BaseTest.java diff --git a/shaded-integration-tests/src/test/jackson/java/com/arangodb/async/CommunicationTest.java b/shaded-integration-tests/src/test/native/java/com/arangodb/async/CommunicationTest.java similarity index 100% rename from shaded-integration-tests/src/test/jackson/java/com/arangodb/async/CommunicationTest.java rename to shaded-integration-tests/src/test/native/java/com/arangodb/async/CommunicationTest.java diff --git a/shaded-integration-tests/src/test/jackson/java/com/arangodb/async/ConcurrencyTest.java b/shaded-integration-tests/src/test/native/java/com/arangodb/async/ConcurrencyTest.java similarity index 100% rename from shaded-integration-tests/src/test/jackson/java/com/arangodb/async/ConcurrencyTest.java rename to shaded-integration-tests/src/test/native/java/com/arangodb/async/ConcurrencyTest.java diff --git a/shaded-integration-tests/src/test/jackson/java/com/arangodb/async/ConcurrencyTests.java b/shaded-integration-tests/src/test/native/java/com/arangodb/async/ConcurrencyTests.java similarity index 100% rename from shaded-integration-tests/src/test/jackson/java/com/arangodb/async/ConcurrencyTests.java rename to shaded-integration-tests/src/test/native/java/com/arangodb/async/ConcurrencyTests.java diff --git a/shaded-integration-tests/src/test/jackson/java/com/arangodb/async/InvertedIndexTest.java b/shaded-integration-tests/src/test/native/java/com/arangodb/async/InvertedIndexTest.java similarity index 100% rename from shaded-integration-tests/src/test/jackson/java/com/arangodb/async/InvertedIndexTest.java rename to shaded-integration-tests/src/test/native/java/com/arangodb/async/InvertedIndexTest.java diff --git a/shaded-integration-tests/src/test/jackson/java/com/arangodb/async/JwtAuthTest.java b/shaded-integration-tests/src/test/native/java/com/arangodb/async/JwtAuthTest.java similarity index 100% rename from shaded-integration-tests/src/test/jackson/java/com/arangodb/async/JwtAuthTest.java rename to shaded-integration-tests/src/test/native/java/com/arangodb/async/JwtAuthTest.java diff --git a/shaded-integration-tests/src/test/jackson/java/com/arangodb/async/StreamTransactionConflictsTest.java b/shaded-integration-tests/src/test/native/java/com/arangodb/async/StreamTransactionConflictsTest.java similarity index 100% rename from shaded-integration-tests/src/test/jackson/java/com/arangodb/async/StreamTransactionConflictsTest.java rename to shaded-integration-tests/src/test/native/java/com/arangodb/async/StreamTransactionConflictsTest.java diff --git a/shaded-integration-tests/src/test/jackson/java/com/arangodb/async/StreamTransactionGraphTest.java b/shaded-integration-tests/src/test/native/java/com/arangodb/async/StreamTransactionGraphTest.java similarity index 100% rename from shaded-integration-tests/src/test/jackson/java/com/arangodb/async/StreamTransactionGraphTest.java rename to shaded-integration-tests/src/test/native/java/com/arangodb/async/StreamTransactionGraphTest.java diff --git a/shaded-integration-tests/src/test/jackson/java/com/arangodb/async/StreamTransactionTest.java b/shaded-integration-tests/src/test/native/java/com/arangodb/async/StreamTransactionTest.java similarity index 100% rename from shaded-integration-tests/src/test/jackson/java/com/arangodb/async/StreamTransactionTest.java rename to shaded-integration-tests/src/test/native/java/com/arangodb/async/StreamTransactionTest.java diff --git a/shaded-integration-tests/src/test/jackson/java/com/arangodb/async/debug/ConsolidationIntervalMsecTest.java b/shaded-integration-tests/src/test/native/java/com/arangodb/async/debug/ConsolidationIntervalMsecTest.java similarity index 100% rename from shaded-integration-tests/src/test/jackson/java/com/arangodb/async/debug/ConsolidationIntervalMsecTest.java rename to shaded-integration-tests/src/test/native/java/com/arangodb/async/debug/ConsolidationIntervalMsecTest.java diff --git a/shaded-integration-tests/src/test/jackson/java/com/arangodb/async/example/ExampleBase.java b/shaded-integration-tests/src/test/native/java/com/arangodb/async/example/ExampleBase.java similarity index 100% rename from shaded-integration-tests/src/test/jackson/java/com/arangodb/async/example/ExampleBase.java rename to shaded-integration-tests/src/test/native/java/com/arangodb/async/example/ExampleBase.java diff --git a/shaded-integration-tests/src/test/jackson/java/com/arangodb/async/example/document/AqlQueryWithSpecialReturnTypesExampleTest.java b/shaded-integration-tests/src/test/native/java/com/arangodb/async/example/document/AqlQueryWithSpecialReturnTypesExampleTest.java similarity index 100% rename from shaded-integration-tests/src/test/jackson/java/com/arangodb/async/example/document/AqlQueryWithSpecialReturnTypesExampleTest.java rename to shaded-integration-tests/src/test/native/java/com/arangodb/async/example/document/AqlQueryWithSpecialReturnTypesExampleTest.java diff --git a/shaded-integration-tests/src/test/jackson/java/com/arangodb/async/example/document/GetDocumentExampleTest.java b/shaded-integration-tests/src/test/native/java/com/arangodb/async/example/document/GetDocumentExampleTest.java similarity index 100% rename from shaded-integration-tests/src/test/jackson/java/com/arangodb/async/example/document/GetDocumentExampleTest.java rename to shaded-integration-tests/src/test/native/java/com/arangodb/async/example/document/GetDocumentExampleTest.java diff --git a/shaded-integration-tests/src/test/jackson/java/com/arangodb/async/example/document/ImportDocumentExampleTest.java b/shaded-integration-tests/src/test/native/java/com/arangodb/async/example/document/ImportDocumentExampleTest.java similarity index 100% rename from shaded-integration-tests/src/test/jackson/java/com/arangodb/async/example/document/ImportDocumentExampleTest.java rename to shaded-integration-tests/src/test/native/java/com/arangodb/async/example/document/ImportDocumentExampleTest.java diff --git a/shaded-integration-tests/src/test/jackson/java/com/arangodb/async/example/document/InsertDocumentExampleTest.java b/shaded-integration-tests/src/test/native/java/com/arangodb/async/example/document/InsertDocumentExampleTest.java similarity index 100% rename from shaded-integration-tests/src/test/jackson/java/com/arangodb/async/example/document/InsertDocumentExampleTest.java rename to shaded-integration-tests/src/test/native/java/com/arangodb/async/example/document/InsertDocumentExampleTest.java diff --git a/shaded-integration-tests/src/test/jackson/java/com/arangodb/async/example/document/TestEntity.java b/shaded-integration-tests/src/test/native/java/com/arangodb/async/example/document/TestEntity.java similarity index 100% rename from shaded-integration-tests/src/test/jackson/java/com/arangodb/async/example/document/TestEntity.java rename to shaded-integration-tests/src/test/native/java/com/arangodb/async/example/document/TestEntity.java diff --git a/shaded-integration-tests/src/test/jackson/java/com/arangodb/async/example/graph/AQLActorsAndMoviesExampleTest.java b/shaded-integration-tests/src/test/native/java/com/arangodb/async/example/graph/AQLActorsAndMoviesExampleTest.java similarity index 100% rename from shaded-integration-tests/src/test/jackson/java/com/arangodb/async/example/graph/AQLActorsAndMoviesExampleTest.java rename to shaded-integration-tests/src/test/native/java/com/arangodb/async/example/graph/AQLActorsAndMoviesExampleTest.java diff --git a/shaded-integration-tests/src/test/jackson/java/com/arangodb/async/example/graph/BaseGraphTest.java b/shaded-integration-tests/src/test/native/java/com/arangodb/async/example/graph/BaseGraphTest.java similarity index 100% rename from shaded-integration-tests/src/test/jackson/java/com/arangodb/async/example/graph/BaseGraphTest.java rename to shaded-integration-tests/src/test/native/java/com/arangodb/async/example/graph/BaseGraphTest.java diff --git a/shaded-integration-tests/src/test/jackson/java/com/arangodb/async/example/graph/Circle.java b/shaded-integration-tests/src/test/native/java/com/arangodb/async/example/graph/Circle.java similarity index 100% rename from shaded-integration-tests/src/test/jackson/java/com/arangodb/async/example/graph/Circle.java rename to shaded-integration-tests/src/test/native/java/com/arangodb/async/example/graph/Circle.java diff --git a/shaded-integration-tests/src/test/jackson/java/com/arangodb/async/example/graph/CircleEdge.java b/shaded-integration-tests/src/test/native/java/com/arangodb/async/example/graph/CircleEdge.java similarity index 100% rename from shaded-integration-tests/src/test/jackson/java/com/arangodb/async/example/graph/CircleEdge.java rename to shaded-integration-tests/src/test/native/java/com/arangodb/async/example/graph/CircleEdge.java diff --git a/shaded-integration-tests/src/test/jackson/java/com/arangodb/async/example/graph/GraphTraversalsInAQLExampleTest.java b/shaded-integration-tests/src/test/native/java/com/arangodb/async/example/graph/GraphTraversalsInAQLExampleTest.java similarity index 100% rename from shaded-integration-tests/src/test/jackson/java/com/arangodb/async/example/graph/GraphTraversalsInAQLExampleTest.java rename to shaded-integration-tests/src/test/native/java/com/arangodb/async/example/graph/GraphTraversalsInAQLExampleTest.java diff --git a/shaded-integration-tests/src/test/jackson/java/com/arangodb/async/example/graph/ShortestPathInAQLExampleTest.java b/shaded-integration-tests/src/test/native/java/com/arangodb/async/example/graph/ShortestPathInAQLExampleTest.java similarity index 100% rename from shaded-integration-tests/src/test/jackson/java/com/arangodb/async/example/graph/ShortestPathInAQLExampleTest.java rename to shaded-integration-tests/src/test/native/java/com/arangodb/async/example/graph/ShortestPathInAQLExampleTest.java diff --git a/shaded-integration-tests/src/test/jackson/java/com/arangodb/async/example/ssl/SslExampleTest.java b/shaded-integration-tests/src/test/native/java/com/arangodb/async/example/ssl/SslExampleTest.java similarity index 100% rename from shaded-integration-tests/src/test/jackson/java/com/arangodb/async/example/ssl/SslExampleTest.java rename to shaded-integration-tests/src/test/native/java/com/arangodb/async/example/ssl/SslExampleTest.java diff --git a/shaded-integration-tests/src/test/jackson/java/com/arangodb/async/serde/CustomSerdeTest.java b/shaded-integration-tests/src/test/native/java/com/arangodb/async/serde/CustomSerdeTest.java similarity index 100% rename from shaded-integration-tests/src/test/jackson/java/com/arangodb/async/serde/CustomSerdeTest.java rename to shaded-integration-tests/src/test/native/java/com/arangodb/async/serde/CustomSerdeTest.java diff --git a/shaded-integration-tests/src/test/jackson/java/com/arangodb/example/ExampleBase.java b/shaded-integration-tests/src/test/native/java/com/arangodb/example/ExampleBase.java similarity index 100% rename from shaded-integration-tests/src/test/jackson/java/com/arangodb/example/ExampleBase.java rename to shaded-integration-tests/src/test/native/java/com/arangodb/example/ExampleBase.java diff --git a/shaded-integration-tests/src/test/jackson/java/com/arangodb/example/FirstProject.java b/shaded-integration-tests/src/test/native/java/com/arangodb/example/FirstProject.java similarity index 100% rename from shaded-integration-tests/src/test/jackson/java/com/arangodb/example/FirstProject.java rename to shaded-integration-tests/src/test/native/java/com/arangodb/example/FirstProject.java diff --git a/shaded-integration-tests/src/test/jackson/java/com/arangodb/example/document/AqlQueryWithSpecialReturnTypesExampleTest.java b/shaded-integration-tests/src/test/native/java/com/arangodb/example/document/AqlQueryWithSpecialReturnTypesExampleTest.java similarity index 100% rename from shaded-integration-tests/src/test/jackson/java/com/arangodb/example/document/AqlQueryWithSpecialReturnTypesExampleTest.java rename to shaded-integration-tests/src/test/native/java/com/arangodb/example/document/AqlQueryWithSpecialReturnTypesExampleTest.java diff --git a/shaded-integration-tests/src/test/jackson/java/com/arangodb/example/document/GetDocumentExampleTest.java b/shaded-integration-tests/src/test/native/java/com/arangodb/example/document/GetDocumentExampleTest.java similarity index 100% rename from shaded-integration-tests/src/test/jackson/java/com/arangodb/example/document/GetDocumentExampleTest.java rename to shaded-integration-tests/src/test/native/java/com/arangodb/example/document/GetDocumentExampleTest.java diff --git a/shaded-integration-tests/src/test/jackson/java/com/arangodb/example/document/InsertDocumentExampleTest.java b/shaded-integration-tests/src/test/native/java/com/arangodb/example/document/InsertDocumentExampleTest.java similarity index 100% rename from shaded-integration-tests/src/test/jackson/java/com/arangodb/example/document/InsertDocumentExampleTest.java rename to shaded-integration-tests/src/test/native/java/com/arangodb/example/document/InsertDocumentExampleTest.java diff --git a/shaded-integration-tests/src/test/jackson/java/com/arangodb/example/document/TestEntity.java b/shaded-integration-tests/src/test/native/java/com/arangodb/example/document/TestEntity.java similarity index 100% rename from shaded-integration-tests/src/test/jackson/java/com/arangodb/example/document/TestEntity.java rename to shaded-integration-tests/src/test/native/java/com/arangodb/example/document/TestEntity.java diff --git a/shaded-integration-tests/src/test/jackson/java/com/arangodb/example/graph/AQLActorsAndMoviesExampleTest.java b/shaded-integration-tests/src/test/native/java/com/arangodb/example/graph/AQLActorsAndMoviesExampleTest.java similarity index 100% rename from shaded-integration-tests/src/test/jackson/java/com/arangodb/example/graph/AQLActorsAndMoviesExampleTest.java rename to shaded-integration-tests/src/test/native/java/com/arangodb/example/graph/AQLActorsAndMoviesExampleTest.java diff --git a/shaded-integration-tests/src/test/jackson/java/com/arangodb/example/graph/BaseGraphTest.java b/shaded-integration-tests/src/test/native/java/com/arangodb/example/graph/BaseGraphTest.java similarity index 100% rename from shaded-integration-tests/src/test/jackson/java/com/arangodb/example/graph/BaseGraphTest.java rename to shaded-integration-tests/src/test/native/java/com/arangodb/example/graph/BaseGraphTest.java diff --git a/shaded-integration-tests/src/test/jackson/java/com/arangodb/example/graph/Circle.java b/shaded-integration-tests/src/test/native/java/com/arangodb/example/graph/Circle.java similarity index 100% rename from shaded-integration-tests/src/test/jackson/java/com/arangodb/example/graph/Circle.java rename to shaded-integration-tests/src/test/native/java/com/arangodb/example/graph/Circle.java diff --git a/shaded-integration-tests/src/test/jackson/java/com/arangodb/example/graph/CircleEdge.java b/shaded-integration-tests/src/test/native/java/com/arangodb/example/graph/CircleEdge.java similarity index 100% rename from shaded-integration-tests/src/test/jackson/java/com/arangodb/example/graph/CircleEdge.java rename to shaded-integration-tests/src/test/native/java/com/arangodb/example/graph/CircleEdge.java diff --git a/shaded-integration-tests/src/test/jackson/java/com/arangodb/example/graph/GraphTraversalsInAQLExampleTest.java b/shaded-integration-tests/src/test/native/java/com/arangodb/example/graph/GraphTraversalsInAQLExampleTest.java similarity index 100% rename from shaded-integration-tests/src/test/jackson/java/com/arangodb/example/graph/GraphTraversalsInAQLExampleTest.java rename to shaded-integration-tests/src/test/native/java/com/arangodb/example/graph/GraphTraversalsInAQLExampleTest.java diff --git a/shaded-integration-tests/src/test/jackson/java/com/arangodb/example/graph/ShortestPathInAQLExampleTest.java b/shaded-integration-tests/src/test/native/java/com/arangodb/example/graph/ShortestPathInAQLExampleTest.java similarity index 100% rename from shaded-integration-tests/src/test/jackson/java/com/arangodb/example/graph/ShortestPathInAQLExampleTest.java rename to shaded-integration-tests/src/test/native/java/com/arangodb/example/graph/ShortestPathInAQLExampleTest.java diff --git a/shaded-integration-tests/src/test/jackson/java/com/arangodb/example/ssl/SslExampleTest.java b/shaded-integration-tests/src/test/native/java/com/arangodb/example/ssl/SslExampleTest.java similarity index 100% rename from shaded-integration-tests/src/test/jackson/java/com/arangodb/example/ssl/SslExampleTest.java rename to shaded-integration-tests/src/test/native/java/com/arangodb/example/ssl/SslExampleTest.java diff --git a/shaded-integration-tests/src/test/jackson/java/com/arangodb/internal/HostHandlerTest.java b/shaded-integration-tests/src/test/native/java/com/arangodb/internal/HostHandlerTest.java similarity index 100% rename from shaded-integration-tests/src/test/jackson/java/com/arangodb/internal/HostHandlerTest.java rename to shaded-integration-tests/src/test/native/java/com/arangodb/internal/HostHandlerTest.java diff --git a/shaded-integration-tests/src/test/jackson/java/com/arangodb/internal/QueueTimeMetricsImplTest.java b/shaded-integration-tests/src/test/native/java/com/arangodb/internal/QueueTimeMetricsImplTest.java similarity index 100% rename from shaded-integration-tests/src/test/jackson/java/com/arangodb/internal/QueueTimeMetricsImplTest.java rename to shaded-integration-tests/src/test/native/java/com/arangodb/internal/QueueTimeMetricsImplTest.java diff --git a/shaded-integration-tests/src/test/jackson/java/com/arangodb/internal/velocystream/CommunicationTest.java b/shaded-integration-tests/src/test/native/java/com/arangodb/internal/velocystream/CommunicationTest.java similarity index 100% rename from shaded-integration-tests/src/test/jackson/java/com/arangodb/internal/velocystream/CommunicationTest.java rename to shaded-integration-tests/src/test/native/java/com/arangodb/internal/velocystream/CommunicationTest.java diff --git a/shaded-integration-tests/src/test/jackson/java/com/arangodb/serde/CustomSerdeTest.java b/shaded-integration-tests/src/test/native/java/com/arangodb/serde/CustomSerdeTest.java similarity index 100% rename from shaded-integration-tests/src/test/jackson/java/com/arangodb/serde/CustomSerdeTest.java rename to shaded-integration-tests/src/test/native/java/com/arangodb/serde/CustomSerdeTest.java diff --git a/shaded-integration-tests/src/test/jackson/java/com/arangodb/serde/CustomTypeHintTest.java b/shaded-integration-tests/src/test/native/java/com/arangodb/serde/CustomTypeHintTest.java similarity index 100% rename from shaded-integration-tests/src/test/jackson/java/com/arangodb/serde/CustomTypeHintTest.java rename to shaded-integration-tests/src/test/native/java/com/arangodb/serde/CustomTypeHintTest.java diff --git a/shaded-integration-tests/src/test/jackson/java/com/arangodb/serde/SerdeTest.java b/shaded-integration-tests/src/test/native/java/com/arangodb/serde/SerdeTest.java similarity index 57% rename from shaded-integration-tests/src/test/jackson/java/com/arangodb/serde/SerdeTest.java rename to shaded-integration-tests/src/test/native/java/com/arangodb/serde/SerdeTest.java index 36daf7450..f6a190b1f 100644 --- a/shaded-integration-tests/src/test/jackson/java/com/arangodb/serde/SerdeTest.java +++ b/shaded-integration-tests/src/test/native/java/com/arangodb/serde/SerdeTest.java @@ -3,7 +3,6 @@ import com.arangodb.ContentType; import com.arangodb.internal.serde.InternalSerde; import com.arangodb.internal.serde.SerdeUtils; -import com.arangodb.shaded.fasterxml.jackson.databind.JsonNode; import com.arangodb.shaded.fasterxml.jackson.databind.node.JsonNodeFactory; import com.arangodb.shaded.fasterxml.jackson.databind.node.ObjectNode; import com.arangodb.util.RawBytes; @@ -11,8 +10,6 @@ import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.EnumSource; -import java.sql.Date; - import static org.assertj.core.api.Assertions.assertThat; @@ -40,32 +37,4 @@ void rawBytesSerde(ContentType type) { assertThat(deserialized).isEqualTo(raw); } - @ParameterizedTest - @EnumSource(ContentType.class) - void utilDateSerde(ContentType type) { - InternalSerde s = InternalSerde.of(type, null); - long ts = 1000000000000L; - java.util.Date date = new java.util.Date(ts); - byte[] ser = s.serialize(date); - JsonNode node = s.parse(ser); - assertThat(node.isLong()).isTrue(); - assertThat(node.longValue()).isEqualTo(ts); - java.util.Date deser = s.deserialize(ser, java.util.Date.class); - assertThat(deser).isEqualTo(date); - } - - @ParameterizedTest - @EnumSource(ContentType.class) - void sqlDateSerde(ContentType type) { - InternalSerde s = InternalSerde.of(type, null); - long ts = 1000000000000L; - Date date = new Date(ts); - byte[] ser = s.serialize(date); - JsonNode node = s.parse(ser); - assertThat(node.isLong()).isTrue(); - assertThat(node.longValue()).isEqualTo(ts); - Date deser = s.deserialize(ser, Date.class); - assertThat(deser).isEqualTo(date); - } - } diff --git a/shaded-integration-tests/src/test/jackson/java/com/arangodb/util/MapBuilder.java b/shaded-integration-tests/src/test/native/java/com/arangodb/util/MapBuilder.java similarity index 100% rename from shaded-integration-tests/src/test/jackson/java/com/arangodb/util/MapBuilder.java rename to shaded-integration-tests/src/test/native/java/com/arangodb/util/MapBuilder.java diff --git a/shaded-integration-tests/src/test/jackson/java/com/arangodb/util/MapBuilderTest.java b/shaded-integration-tests/src/test/native/java/com/arangodb/util/MapBuilderTest.java similarity index 100% rename from shaded-integration-tests/src/test/jackson/java/com/arangodb/util/MapBuilderTest.java rename to shaded-integration-tests/src/test/native/java/com/arangodb/util/MapBuilderTest.java diff --git a/shaded-integration-tests/src/test/jackson/java/com/arangodb/util/TestUtils.java b/shaded-integration-tests/src/test/native/java/com/arangodb/util/TestUtils.java similarity index 100% rename from shaded-integration-tests/src/test/jackson/java/com/arangodb/util/TestUtils.java rename to shaded-integration-tests/src/test/native/java/com/arangodb/util/TestUtils.java diff --git a/shaded-integration-tests/src/test/resources/META-INF/native-image/native-image.properties b/shaded-integration-tests/src/test/resources/META-INF/native-image/native-image.properties new file mode 100644 index 000000000..b039368e7 --- /dev/null +++ b/shaded-integration-tests/src/test/resources/META-INF/native-image/native-image.properties @@ -0,0 +1,8 @@ +Args=\ + -H:ResourceConfigurationResources=${.}/resource-config.json \ + -H:ReflectionConfigurationResources=${.}/reflect-config.json \ + -H:SerializationConfigurationResources=${.}/serialization-config.json \ + --initialize-at-build-time=\ + ch.qos.logback,\ + org.slf4j,\ + org.junit.platform.engine.TestTag diff --git a/shaded-integration-tests/src/test/resources/META-INF/native-image/reflect-config.json b/shaded-integration-tests/src/test/resources/META-INF/native-image/reflect-config.json new file mode 100644 index 000000000..43c06539e --- /dev/null +++ b/shaded-integration-tests/src/test/resources/META-INF/native-image/reflect-config.json @@ -0,0 +1,359 @@ +[ + { + "name":"org.junit.jupiter.engine.extension.TimeoutInvocationFactory$SingleThreadExecutorResource", + "methods":[{"name":"","parameterTypes":[] }] + }, + { + "name": "org.junit.jupiter.engine.extension.TimeoutInvocationFactory$SingleThreadExecutorResource", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + }, + { + "name": "ch.qos.logback.classic.encoder.PatternLayoutEncoder", + "allPublicMethods": true, + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + }, + { + "name": "ch.qos.logback.classic.pattern.DateConverter", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + }, + { + "name": "ch.qos.logback.classic.pattern.LevelConverter", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + }, + { + "name": "ch.qos.logback.classic.pattern.LineSeparatorConverter", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + }, + { + "name": "ch.qos.logback.classic.pattern.LoggerConverter", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + }, + { + "name": "ch.qos.logback.classic.pattern.MessageConverter", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + }, + { + "name": "ch.qos.logback.classic.pattern.ThreadConverter", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + }, + { + "name": "ch.qos.logback.core.ConsoleAppender", + "allPublicMethods": true, + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + }, + { + "name": "com.arangodb.ArangoCollectionTest$TestUpdateEntity", + "allDeclaredFields":true, + "allDeclaredMethods":true, + "allPublicMethods":true, + "allDeclaredConstructors":true, + "allDeclaredClasses":true + }, + { + "name": "com.arangodb.ArangoCollectionTest$TestUpdateEntitySerializeNullFalse", + "allDeclaredFields":true, + "allDeclaredMethods":true, + "allPublicMethods":true, + "allDeclaredConstructors":true, + "allDeclaredClasses":true + }, + { + "name": "com.arangodb.ArangoDatabaseTest$TransactionTestEntity", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allPublicMethods": true, + "allDeclaredConstructors": true, + "allDeclaredClasses": true + }, + { + "name": "com.arangodb.async.ArangoDatabaseTest$TransactionTestEntity", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allPublicMethods": true, + "allDeclaredConstructors": true, + "allDeclaredClasses": true + }, + { + "name": "com.arangodb.async.example.document.AqlQueryWithSpecialReturnTypesExampleTest$Gender", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allPublicMethods": true, + "allDeclaredClasses": true + }, + { + "name": "com.arangodb.async.example.document.TestEntity", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allPublicMethods": true, + "allDeclaredConstructors": true, + "allDeclaredClasses": true + }, + { + "name": "com.arangodb.async.example.graph.AQLActorsAndMoviesExampleTest$Actor", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allPublicMethods": true, + "allDeclaredConstructors": true, + "allDeclaredClasses": true + }, + { + "name": "com.arangodb.async.example.graph.AQLActorsAndMoviesExampleTest$Movie", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allPublicMethods": true, + "allDeclaredConstructors": true, + "allDeclaredClasses": true + }, + { + "name": "com.arangodb.async.example.graph.Circle", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allPublicMethods": true, + "allDeclaredConstructors": true, + "allDeclaredClasses": true + }, + { + "name": "com.arangodb.async.example.graph.CircleEdge", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allPublicMethods": true, + "allDeclaredConstructors": true, + "allDeclaredClasses": true + }, + { + "name": "com.arangodb.async.example.graph.ShortestPathInAQLExampleTest$Pair", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allPublicMethods": true, + "allDeclaredConstructors": true, + "allDeclaredClasses": true + }, + { + "name": "com.arangodb.example.document.AqlQueryWithSpecialReturnTypesExampleTest$Gender", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allPublicMethods": true, + "allDeclaredClasses": true + }, + { + "name": "com.arangodb.example.document.TestEntity", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allPublicMethods": true, + "allDeclaredConstructors": true, + "allDeclaredClasses": true + }, + { + "name": "com.arangodb.example.graph.AQLActorsAndMoviesExampleTest$Actor", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allPublicMethods": true, + "allDeclaredConstructors": true, + "allDeclaredClasses": true + }, + { + "name": "com.arangodb.example.graph.AQLActorsAndMoviesExampleTest$Movie", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allPublicMethods": true, + "allDeclaredConstructors": true, + "allDeclaredClasses": true + }, + { + "name": "com.arangodb.example.graph.Circle", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allPublicMethods": true, + "allDeclaredConstructors": true, + "allDeclaredClasses": true + }, + { + "name": "com.arangodb.example.graph.CircleEdge", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allPublicMethods": true, + "allDeclaredConstructors": true, + "allDeclaredClasses": true + }, + { + "name": "com.arangodb.example.graph.ShortestPathInAQLExampleTest$Pair", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allPublicMethods": true, + "allDeclaredConstructors": true, + "allDeclaredClasses": true + }, + { + "name": "com.arangodb.serde.CustomSerdeTest$Person", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allPublicMethods": true, + "allDeclaredClasses": true + }, + { + "name": "com.arangodb.serde.CustomSerdeTest$PersonDeserializer", + "allDeclaredMethods": true, + "allPublicMethods": true, + "allDeclaredClasses": true + }, + { + "name": "com.arangodb.serde.CustomSerdeTest$PersonSerializer", + "allDeclaredMethods": true, + "allPublicMethods": true, + "allDeclaredClasses": true, + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + }, + { + "name": "com.arangodb.serde.CustomTypeHintTest$Animal", + "allDeclaredMethods": true, + "allPublicMethods": true, + "allDeclaredClasses": true + }, + { + "name": "com.arangodb.serde.CustomTypeHintTest$Gorilla", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allPublicMethods": true, + "allDeclaredConstructors": true, + "allDeclaredClasses": true + }, + { + "name": "com.arangodb.serde.CustomTypeHintTest$Zoo", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allPublicMethods": true, + "allDeclaredConstructors": true, + "allDeclaredClasses": true + }, + { + "name": "java.util.HashSet", + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.annotations.AnnotatedEntity", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.fasterxml.jackson.databind.deser.std.DateDeserializers$SqlDateDeserializer", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + }, + { + "name": "com.fasterxml.jackson.databind.ser.std.SqlDateSerializer", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + }, + { + "name":"com.arangodb.async.ArangoCollectionTest$Animal", + "allDeclaredMethods":true, + "allPublicMethods":true, + "allDeclaredClasses":true + }, + { + "name":"com.arangodb.async.ArangoCollectionTest$Cat", + "allDeclaredFields":true, + "allDeclaredMethods":true, + "allPublicMethods":true, + "allDeclaredConstructors":true, + "allDeclaredClasses":true + }, + { + "name":"com.arangodb.async.ArangoCollectionTest$Dog", + "allDeclaredFields":true, + "allDeclaredMethods":true, + "allPublicMethods":true, + "allDeclaredConstructors":true, + "allDeclaredClasses":true + }, + { + "name":"com.arangodb.ArangoCollectionTest$Animal", + "allDeclaredMethods":true, + "allPublicMethods":true, + "allDeclaredClasses":true + }, + { + "name":"com.arangodb.ArangoCollectionTest$AnnotatedEntity", + "allDeclaredFields":true, + "allDeclaredMethods":true, + "allPublicMethods":true, + "allDeclaredConstructors":true, + "allDeclaredClasses":true + }, + { + "name":"com.arangodb.ArangoCollectionTest$Cat", + "allDeclaredFields":true, + "allDeclaredMethods":true, + "allPublicMethods":true, + "allDeclaredConstructors":true, + "allDeclaredClasses":true + }, + { + "name":"com.arangodb.ArangoCollectionTest$Dog", + "allDeclaredFields":true, + "allDeclaredMethods":true, + "allPublicMethods":true, + "allDeclaredConstructors":true, + "allDeclaredClasses":true + } +] diff --git a/shaded-integration-tests/src/test/resources/META-INF/native-image/resource-config.json b/shaded-integration-tests/src/test/resources/META-INF/native-image/resource-config.json new file mode 100644 index 000000000..a603a885a --- /dev/null +++ b/shaded-integration-tests/src/test/resources/META-INF/native-image/resource-config.json @@ -0,0 +1,22 @@ +{ + "resources": { + "includes": [ + { + "pattern": "\\Qarangodb.properties\\E" + }, + { + "pattern": "\\Qarangodb-bad.properties\\E" + }, + { + "pattern": "\\Qarangodb-bad2.properties\\E" + }, + { + "pattern": "\\Qlogback-test.xml\\E" + }, + { + "pattern": "\\Qexample.truststore\\E" + } + ] + }, + "bundles": [] +} diff --git a/shaded-integration-tests/src/test/resources/META-INF/native-image/serialization-config.json b/shaded-integration-tests/src/test/resources/META-INF/native-image/serialization-config.json new file mode 100644 index 000000000..2871e9998 --- /dev/null +++ b/shaded-integration-tests/src/test/resources/META-INF/native-image/serialization-config.json @@ -0,0 +1,23 @@ +[ + { + "name": "java.lang.Exception" + }, + { + "name": "java.lang.RuntimeException" + }, + { + "name": "java.lang.StackTraceElement" + }, + { + "name": "java.lang.StackTraceElement[]" + }, + { + "name": "java.lang.String" + }, + { + "name": "java.lang.Throwable" + }, + { + "name": "java.util.Collections$EmptyList" + } +] diff --git a/shaded-integration-tests/src/test/resources/example.truststore b/shaded-integration-tests/src/test/resources/example.truststore new file mode 100644 index 0000000000000000000000000000000000000000..e683a48b8a25067c921385081a3a930eae74f05a GIT binary patch literal 2251 zcmchYc{J1w7sux}E5;y8B}*YomhrQUl4Zh33fZ&o%D!YgWO-yNOR|<_MwZAv^b|$1 z4p~c&WULXdElUw2YK+JGyyv{{b58%i=iKif_w&a+_k8a?_p;VlYY+$odLZC$akyT0 z4Y(Fa^b8>$pwM`R4<`hI06-Fa59C5}$RPnZAPYSN00;=21pnMR(%M&}Km!(L7TSc* z=$^fFKa5!fuSahq`Sr?``myydFdA9qeJmmU%K3y1N=h%0vMB{%-vm;*#xs}G*+Y{B z1BAKeQf>IA?PRq(J09eo^7pmNV*73U_o12+&ZolmB6Odb@>Fv{X(@(B&7|!Q&6~bh zU|rD7uu*l}%BNB0Av&LZ-NA^wVP{Q~p-e|fe2mM?9(V)l-=NHZtmjlR;JnoZbH^6;I2x zuKt3aE+TJ;G@`t`#4Z| zV(PfByq(zoF>?>64;uFPiCYl_4(UEV+D-vu&?Jv`z6`JIaJVF^`$I8JT_~CR`ybak zs|<83L@1XJ|Mr!_Q3QAL3|g?ZRM@|pu~QU#U*3Mh?)hN;38dZdz9M3$N&-hCbUC!W zy6W}rjrOyXh{!1Y!q5#`l;yjxpd_($j6&bFalp7%>|w*rD8?u$Dh& zhnSbYn_C9^KZI4oO|C@uU;DM zeKFHuyIJkq3qz`NinbLonP@6!SM5oD^KM7--m1mebq!*|XLSFzd1@6ByH*gJvOXod zH(Fa0OMrFT9^zUL3W;j}s@jGgH(}Ld$d13z1c5n|g z#CZC9>E{QEdUS@gVr4$eW#)5!Fvef**m+kO1IeTQTkGnF*;IXR#@P^h>uB1?T8f9l zr7nuXJP=c;1XRnGLp;L^qGVuR?(%y3 zBiXKS^_-a7&Y+XIiSqrZG|eVmJ@Yauyy9v<2k%l1o2_D#SyFQ9DZwvLIi{<~&y2e| z*c&;Uk#49GV{c=HXX)`R1nH?@$Cv3G?s`F>?XWK2phUwn8+Z>HZX#f`9DGwFBcuQa z6Ksuo$<(Ph+Z!V9>&Y%Um2N{yOPy5o9}FXPf`6hU9@10%d#=vbCzn<`|9u=0Hdq{} z4uQa8KoTqxBthK^VNd`Hg@=Q+&L9TKE*p0t?mGqm&0z-(P=n;%EsHAidXK+eN>UKvkDxea0 zp#P-*_kKu#_&+T_vtC@ko6OJq($nC3Il0R9b)`T|= z(TxpI;UvM~h;ya`j%K$|DveUkqwOgxNgW`~(B`skW_svLblMZd>t(7~!=6F@g`yRh zy~z;$fyd*DmFg$PXLh0{VrXUhDcn#P00D}{z~i9E!7N3%;D_P-?KS)7I!>)kVlVg? zCil$0Y`yt5{huZt?A3vZ07N{{S9^WVja*wIE@lvVMTo9J=QQJLe0*qjRXJ9<+`E4);>i4nt=K)EXsJ@Ens#;)OFz`Z~h}JB90br*0qe?J@UWS#m<`(ucTBh(~WY zT&qusDCN_NPebRa37L7#jufzt-IZ~Y0Fs64s48}{7E*XyrWW9KvG9JHWT9Luz zG78>gPEO>WFbehVA~h|BOCn7Dn0iJ@Vu^MxM|7z9?a7_m(|c`x0-q`#d>rb?oD+4F zL~7~s-r&?vRV+qho|h!e+L~La@@Qp~zfF1($h`xXcX)*5h6zn^@?GOf`Rr7t&~Bju mlH*f^c*Ep6%5+rI!$=hPYi literal 0 HcmV?d00001 diff --git a/shaded/pom.xml b/shaded/pom.xml index 1c0334a67..5cdf4e309 100644 --- a/shaded/pom.xml +++ b/shaded/pom.xml @@ -66,9 +66,6 @@ - io.netty com.arangodb.shaded.netty @@ -91,6 +88,7 @@ com.arangodb:arangodb-java-driver META-INF/MANIFEST.MF + META-INF/native-image/** diff --git a/shaded/src/main/resources/META-INF/native-image/com.arangodb/arangodb-java-driver-shaded/native-image.properties b/shaded/src/main/resources/META-INF/native-image/com.arangodb/arangodb-java-driver-shaded/native-image.properties new file mode 100644 index 000000000..ecbea5c1b --- /dev/null +++ b/shaded/src/main/resources/META-INF/native-image/com.arangodb/arangodb-java-driver-shaded/native-image.properties @@ -0,0 +1,9 @@ +Args=\ +-H:ResourceConfigurationResources=${.}/resource-config.json \ +-H:ReflectionConfigurationResources=${.}/reflect-config.json,${.}/netty-reflect-config.json \ +-H:SerializationConfigurationResources=${.}/serialization-config.json \ +--initialize-at-run-time=\ + com.arangodb.shaded.netty.handler.ssl.BouncyCastleAlpnSslUtils,\ + com.arangodb.shaded.netty.handler.codec.compression.ZstdOptions \ +-Dcom.arangodb.shaded.netty.noUnsafe=true \ +-Dcom.arangodb.shaded.netty.leakDetection.level=DISABLED diff --git a/shaded/src/main/resources/META-INF/native-image/com.arangodb/arangodb-java-driver-shaded/netty-reflect-config.json b/shaded/src/main/resources/META-INF/native-image/com.arangodb/arangodb-java-driver-shaded/netty-reflect-config.json new file mode 100644 index 000000000..f0ec33a5b --- /dev/null +++ b/shaded/src/main/resources/META-INF/native-image/com.arangodb/arangodb-java-driver-shaded/netty-reflect-config.json @@ -0,0 +1,923 @@ +[ + { + "name": "com.arangodb.shaded.netty.buffer.AbstractByteBufAllocator", + "queryAllDeclaredMethods": true + }, + { + "name": "com.arangodb.shaded.netty.buffer.AbstractReferenceCountedByteBuf", + "fields": [ + { + "name": "refCnt" + } + ] + }, + { + "name": "com.arangodb.shaded.netty.channel.ChannelDuplexHandler", + "methods": [ + { + "name": "bind", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext", + "java.net.SocketAddress", + "com.arangodb.shaded.netty.channel.ChannelPromise" + ] + }, + { + "name": "connect", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext", + "java.net.SocketAddress", + "java.net.SocketAddress", + "com.arangodb.shaded.netty.channel.ChannelPromise" + ] + }, + { + "name": "deregister", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext", + "com.arangodb.shaded.netty.channel.ChannelPromise" + ] + }, + { + "name": "disconnect", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext", + "com.arangodb.shaded.netty.channel.ChannelPromise" + ] + }, + { + "name": "flush", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext" + ] + }, + { + "name": "read", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext" + ] + }, + { + "name": "write", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext", + "java.lang.Object", + "com.arangodb.shaded.netty.channel.ChannelPromise" + ] + } + ] + }, + { + "name": "com.arangodb.shaded.netty.channel.ChannelHandlerAdapter", + "methods": [ + { + "name": "exceptionCaught", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext", + "java.lang.Throwable" + ] + } + ] + }, + { + "name": "com.arangodb.shaded.netty.channel.ChannelInboundHandlerAdapter", + "methods": [ + { + "name": "channelActive", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext" + ] + }, + { + "name": "channelInactive", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext" + ] + }, + { + "name": "channelRead", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext", + "java.lang.Object" + ] + }, + { + "name": "channelReadComplete", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext" + ] + }, + { + "name": "channelRegistered", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext" + ] + }, + { + "name": "channelUnregistered", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext" + ] + }, + { + "name": "channelWritabilityChanged", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext" + ] + }, + { + "name": "exceptionCaught", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext", + "java.lang.Throwable" + ] + }, + { + "name": "userEventTriggered", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext", + "java.lang.Object" + ] + } + ] + }, + { + "name": "com.arangodb.shaded.netty.channel.ChannelInitializer", + "methods": [ + { + "name": "channelRegistered", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext" + ] + }, + { + "name": "exceptionCaught", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext", + "java.lang.Throwable" + ] + } + ] + }, + { + "name": "com.arangodb.shaded.netty.channel.ChannelOutboundHandlerAdapter", + "methods": [ + { + "name": "bind", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext", + "java.net.SocketAddress", + "com.arangodb.shaded.netty.channel.ChannelPromise" + ] + }, + { + "name": "close", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext", + "com.arangodb.shaded.netty.channel.ChannelPromise" + ] + }, + { + "name": "connect", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext", + "java.net.SocketAddress", + "java.net.SocketAddress", + "com.arangodb.shaded.netty.channel.ChannelPromise" + ] + }, + { + "name": "deregister", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext", + "com.arangodb.shaded.netty.channel.ChannelPromise" + ] + }, + { + "name": "disconnect", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext", + "com.arangodb.shaded.netty.channel.ChannelPromise" + ] + }, + { + "name": "flush", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext" + ] + }, + { + "name": "read", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext" + ] + } + ] + }, + { + "name": "com.arangodb.shaded.netty.channel.CombinedChannelDuplexHandler", + "methods": [ + { + "name": "bind", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext", + "java.net.SocketAddress", + "com.arangodb.shaded.netty.channel.ChannelPromise" + ] + }, + { + "name": "channelActive", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext" + ] + }, + { + "name": "channelInactive", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext" + ] + }, + { + "name": "channelRead", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext", + "java.lang.Object" + ] + }, + { + "name": "channelReadComplete", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext" + ] + }, + { + "name": "channelRegistered", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext" + ] + }, + { + "name": "channelUnregistered", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext" + ] + }, + { + "name": "channelWritabilityChanged", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext" + ] + }, + { + "name": "close", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext", + "com.arangodb.shaded.netty.channel.ChannelPromise" + ] + }, + { + "name": "connect", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext", + "java.net.SocketAddress", + "java.net.SocketAddress", + "com.arangodb.shaded.netty.channel.ChannelPromise" + ] + }, + { + "name": "deregister", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext", + "com.arangodb.shaded.netty.channel.ChannelPromise" + ] + }, + { + "name": "disconnect", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext", + "com.arangodb.shaded.netty.channel.ChannelPromise" + ] + }, + { + "name": "exceptionCaught", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext", + "java.lang.Throwable" + ] + }, + { + "name": "flush", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext" + ] + }, + { + "name": "read", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext" + ] + }, + { + "name": "userEventTriggered", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext", + "java.lang.Object" + ] + }, + { + "name": "write", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext", + "java.lang.Object", + "com.arangodb.shaded.netty.channel.ChannelPromise" + ] + } + ] + }, + { + "name": "com.arangodb.shaded.netty.channel.DefaultChannelPipeline$HeadContext", + "methods": [ + { + "name": "bind", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext", + "java.net.SocketAddress", + "com.arangodb.shaded.netty.channel.ChannelPromise" + ] + }, + { + "name": "channelActive", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext" + ] + }, + { + "name": "channelInactive", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext" + ] + }, + { + "name": "channelRead", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext", + "java.lang.Object" + ] + }, + { + "name": "channelReadComplete", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext" + ] + }, + { + "name": "channelRegistered", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext" + ] + }, + { + "name": "channelUnregistered", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext" + ] + }, + { + "name": "channelWritabilityChanged", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext" + ] + }, + { + "name": "close", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext", + "com.arangodb.shaded.netty.channel.ChannelPromise" + ] + }, + { + "name": "connect", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext", + "java.net.SocketAddress", + "java.net.SocketAddress", + "com.arangodb.shaded.netty.channel.ChannelPromise" + ] + }, + { + "name": "deregister", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext", + "com.arangodb.shaded.netty.channel.ChannelPromise" + ] + }, + { + "name": "disconnect", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext", + "com.arangodb.shaded.netty.channel.ChannelPromise" + ] + }, + { + "name": "exceptionCaught", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext", + "java.lang.Throwable" + ] + }, + { + "name": "flush", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext" + ] + }, + { + "name": "read", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext" + ] + }, + { + "name": "userEventTriggered", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext", + "java.lang.Object" + ] + }, + { + "name": "write", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext", + "java.lang.Object", + "com.arangodb.shaded.netty.channel.ChannelPromise" + ] + } + ] + }, + { + "name": "com.arangodb.shaded.netty.channel.DefaultChannelPipeline$TailContext", + "methods": [ + { + "name": "channelActive", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext" + ] + }, + { + "name": "channelInactive", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext" + ] + }, + { + "name": "channelRead", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext", + "java.lang.Object" + ] + }, + { + "name": "channelReadComplete", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext" + ] + }, + { + "name": "channelRegistered", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext" + ] + }, + { + "name": "channelUnregistered", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext" + ] + }, + { + "name": "channelWritabilityChanged", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext" + ] + }, + { + "name": "exceptionCaught", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext", + "java.lang.Throwable" + ] + }, + { + "name": "userEventTriggered", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext", + "java.lang.Object" + ] + } + ] + }, + { + "name": "com.arangodb.shaded.netty.handler.codec.MessageToMessageDecoder", + "methods": [ + { + "name": "channelRead", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext", + "java.lang.Object" + ] + } + ] + }, + { + "name": "com.arangodb.shaded.netty.handler.codec.MessageToMessageEncoder", + "methods": [ + { + "name": "write", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext", + "java.lang.Object", + "com.arangodb.shaded.netty.channel.ChannelPromise" + ] + } + ] + }, + { + "name": "com.arangodb.shaded.netty.handler.codec.dns.DatagramDnsQueryEncoder" + }, + { + "name": "com.arangodb.shaded.netty.handler.codec.http.HttpClientCodec" + }, + { + "name": "com.arangodb.shaded.netty.handler.codec.http2.Http2ConnectionHandler", + "methods": [ + { + "name": "bind", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext", + "java.net.SocketAddress", + "com.arangodb.shaded.netty.channel.ChannelPromise" + ] + }, + { + "name": "channelActive", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext" + ] + }, + { + "name": "channelReadComplete", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext" + ] + }, + { + "name": "channelWritabilityChanged", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext" + ] + }, + { + "name": "close", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext", + "com.arangodb.shaded.netty.channel.ChannelPromise" + ] + }, + { + "name": "connect", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext", + "java.net.SocketAddress", + "java.net.SocketAddress", + "com.arangodb.shaded.netty.channel.ChannelPromise" + ] + }, + { + "name": "deregister", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext", + "com.arangodb.shaded.netty.channel.ChannelPromise" + ] + }, + { + "name": "disconnect", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext", + "com.arangodb.shaded.netty.channel.ChannelPromise" + ] + }, + { + "name": "flush", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext" + ] + }, + { + "name": "read", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext" + ] + }, + { + "name": "write", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext", + "java.lang.Object", + "com.arangodb.shaded.netty.channel.ChannelPromise" + ] + } + ] + }, + { + "name": "com.arangodb.shaded.netty.handler.logging.LoggingHandler", + "methods": [ + { + "name": "bind", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext", + "java.net.SocketAddress", + "com.arangodb.shaded.netty.channel.ChannelPromise" + ] + }, + { + "name": "channelActive", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext" + ] + }, + { + "name": "channelInactive", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext" + ] + }, + { + "name": "channelRead", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext", + "java.lang.Object" + ] + }, + { + "name": "channelReadComplete", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext" + ] + }, + { + "name": "channelRegistered", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext" + ] + }, + { + "name": "channelUnregistered", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext" + ] + }, + { + "name": "channelWritabilityChanged", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext" + ] + }, + { + "name": "close", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext", + "com.arangodb.shaded.netty.channel.ChannelPromise" + ] + }, + { + "name": "connect", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext", + "java.net.SocketAddress", + "java.net.SocketAddress", + "com.arangodb.shaded.netty.channel.ChannelPromise" + ] + }, + { + "name": "deregister", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext", + "com.arangodb.shaded.netty.channel.ChannelPromise" + ] + }, + { + "name": "disconnect", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext", + "com.arangodb.shaded.netty.channel.ChannelPromise" + ] + }, + { + "name": "exceptionCaught", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext", + "java.lang.Throwable" + ] + }, + { + "name": "flush", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext" + ] + }, + { + "name": "userEventTriggered", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext", + "java.lang.Object" + ] + }, + { + "name": "write", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext", + "java.lang.Object", + "com.arangodb.shaded.netty.channel.ChannelPromise" + ] + } + ] + }, + { + "name": "com.arangodb.shaded.netty.resolver.dns.DnsNameResolver$1" + }, + { + "name": "com.arangodb.shaded.netty.resolver.dns.DnsNameResolver$3" + }, + { + "name": "com.arangodb.shaded.netty.resolver.dns.DnsNameResolver$DnsResponseHandler", + "methods": [ + { + "name": "channelActive", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext" + ] + }, + { + "name": "channelRead", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext", + "java.lang.Object" + ] + }, + { + "name": "exceptionCaught", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext", + "java.lang.Throwable" + ] + } + ] + }, + { + "name": "com.arangodb.shaded.netty.util.ReferenceCountUtil", + "queryAllDeclaredMethods": true + }, + { + "name": "com.arangodb.shaded.netty.util.internal.shaded.org.jctools.queues.BaseMpscLinkedArrayQueueColdProducerFields", + "fields": [ + { + "name": "producerLimit" + } + ] + }, + { + "name": "com.arangodb.shaded.netty.util.internal.shaded.org.jctools.queues.BaseMpscLinkedArrayQueueConsumerFields", + "fields": [ + { + "name": "consumerIndex" + } + ] + }, + { + "name": "com.arangodb.shaded.netty.util.internal.shaded.org.jctools.queues.BaseMpscLinkedArrayQueueProducerFields", + "fields": [ + { + "name": "producerIndex" + } + ] + }, + { + "name": "com.arangodb.shaded.netty.util.internal.shaded.org.jctools.queues.MpscArrayQueueConsumerIndexField", + "fields": [ + { + "name": "consumerIndex" + } + ] + }, + { + "name": "com.arangodb.shaded.netty.util.internal.shaded.org.jctools.queues.MpscArrayQueueProducerIndexField", + "fields": [ + { + "name": "producerIndex" + } + ] + }, + { + "name": "com.arangodb.shaded.netty.util.internal.shaded.org.jctools.queues.MpscArrayQueueProducerLimitField", + "fields": [ + { + "name": "producerLimit" + } + ] + }, + { + "name": "com.arangodb.shaded.vertx.core.http.impl.VertxHttp2ConnectionHandler", + "methods": [ + { + "name": "channelInactive", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext" + ] + }, + { + "name": "channelRead", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext", + "java.lang.Object" + ] + }, + { + "name": "exceptionCaught", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext", + "java.lang.Throwable" + ] + }, + { + "name": "userEventTriggered", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext", + "java.lang.Object" + ] + } + ] + }, + { + "name": "com.arangodb.shaded.vertx.core.logging.SLF4JLogDelegateFactory", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + }, + { + "name": "com.arangodb.shaded.vertx.core.net.impl.ChannelProvider$2" + }, + { + "name": "com.arangodb.shaded.vertx.core.net.impl.VertxHandler", + "methods": [ + { + "name": "channelInactive", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext" + ] + }, + { + "name": "channelRead", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext", + "java.lang.Object" + ] + }, + { + "name": "channelReadComplete", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext" + ] + }, + { + "name": "channelWritabilityChanged", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext" + ] + }, + { + "name": "close", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext", + "com.arangodb.shaded.netty.channel.ChannelPromise" + ] + }, + { + "name": "exceptionCaught", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext", + "java.lang.Throwable" + ] + }, + { + "name": "userEventTriggered", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext", + "java.lang.Object" + ] + } + ] + } +] diff --git a/shaded/src/main/resources/META-INF/native-image/com.arangodb/arangodb-java-driver-shaded/reflect-config.json b/shaded/src/main/resources/META-INF/native-image/com.arangodb/arangodb-java-driver-shaded/reflect-config.json new file mode 100644 index 000000000..6ff37492a --- /dev/null +++ b/shaded/src/main/resources/META-INF/native-image/com.arangodb/arangodb-java-driver-shaded/reflect-config.json @@ -0,0 +1,1496 @@ +[ + { + "name": "com.arangodb.internal.serde.InternalSerializers$FieldLinksSerializer", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.internal.serde.InternalSerializers$CollectionLinksSerializer", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.internal.serde.InternalSerializers$CollectionSchemaRuleSerializer", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.internal.serde.InternalDeserializers$CollectionLinksDeserializer", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.internal.serde.InternalDeserializers$CollectionSchemaRuleDeserializer", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.internal.serde.InternalDeserializers$FieldLinksDeserializer", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.ViewEntity", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.CollectionEntity", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.ReplicationFactor", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.AbstractBaseDocument", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.DocumentEntity", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.analyzer.SearchAnalyzer", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.SearchAliasPropertiesEntity", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.ArangoSearchPropertiesEntity", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.ServerRole", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.ReplicationFactor$SatelliteReplicationFactor", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.analyzer.SegmentationAnalyzerProperties$BreakMode", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.AnalyzerFeature", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.ArangoDBEngine$StorageEngineName", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.SearchAliasIndex$OperationType", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.StreamTransactionStatus", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.QueryExecutionState", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.LogLevel", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.QueryCachePropertiesEntity$CacheMode", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.LogLevelEntity$LogLevel", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.StoreValuesType", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.LoadBalancingStrategy", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.InvertedIndexPrimarySort$Field$Direction", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.IndexType", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.ArangoSearchCompression", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.License", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.CollectionStatus", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.analyzer.SearchAnalyzerCase", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.analyzer.AQLAnalyzerProperties$ReturnType", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.analyzer.StreamType", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.CollectionType", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.KeyType", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.ViewType", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.ServerMode", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.AnalyzerType", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.analyzer.GeoJSONAnalyzerProperties$GeoJSONAnalyzerType", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.ShardingStrategy", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.ConsolidationType", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.Permissions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.CollectionRevisionEntity", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.CollectionPropertiesEntity", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.QueryOptimizerRule", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.InvertedIndexPrimarySort$Field", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.analyzer.GeoJSONAnalyzerProperties", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.analyzer.GeoPointAnalyzerProperties", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.analyzer.ClassificationAnalyzerProperties", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.SearchAliasIndex", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.MetaAware", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.IndexEntity", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.AqlExecutionExplainEntity", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.AqlParseEntity", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.EdgeDefinition", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.MultiDocumentEntity", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.analyzer.StopwordsAnalyzerProperties", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.AqlExecutionExplainEntity$ExecutionVariable", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.QueryCachePropertiesEntity", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.GraphEntity", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.AqlFunctionEntity", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.DatabaseEntity", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.PrimarySort", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.analyzer.EdgeNgram", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.AqlExecutionExplainEntity$ExecutionNode", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.TransactionEntity", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.ArangoDBEngine", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.UserEntity", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.ErrorEntity", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.analyzer.DelimiterAnalyzerProperties", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.AqlExecutionExplainEntity$ExecutionStats", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.FieldLink", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.AqlParseEntity$AstNode", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.analyzer.GeoAnalyzerOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.ShardEntity", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.QueryOptimizerRule$Flags", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.AqlExecutionExplainEntity$ExecutionCollection", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.analyzer.NearestNeighborsAnalyzerProperties", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.analyzer.PipelineAnalyzerProperties", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.ReplicationFactor$NumericReplicationFactor", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.analyzer.TextAnalyzerProperties", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.EdgeDefinition$Options", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.ArangoDBVersion", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.analyzer.SegmentationAnalyzerProperties", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.analyzer.AQLAnalyzerProperties", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.analyzer.MinHashAnalyzerProperties", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.ConsolidationPolicy", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.analyzer.NormAnalyzerProperties", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.KeyOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.AqlExecutionExplainEntity$ExecutionPlan", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.LogLevelEntity", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.analyzer.NGramAnalyzerProperties", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.CursorWarning", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.analyzer.StemAnalyzerProperties", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.StreamTransactionEntity", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.LogEntriesEntity", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.QueryEntity", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.CollectionLink", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.StoredValue", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.DocumentImportEntity", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.analyzer.CollationAnalyzerProperties", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.InvertedIndexPrimarySort", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.QueryTrackingPropertiesEntity", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.LogEntriesEntity$Message", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.InvertedIndexEntity", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.InvertedIndexField", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.AqlExecutionExplainEntity$ExecutionExpression", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.BaseEdgeDocument", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.BaseDocument", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.EdgeUpdateEntity", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.DocumentCreateEntity", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.VertexUpdateEntity", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.DocumentDeleteEntity", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.VertexEntity", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.DocumentUpdateEntity", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.EdgeEntity", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.analyzer.SegmentationAnalyzer", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.analyzer.IdentityAnalyzer", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.analyzer.GeoPointAnalyzer", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.analyzer.AQLAnalyzer", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.analyzer.GeoJSONAnalyzer", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.analyzer.PipelineAnalyzer", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.analyzer.NearestNeighborsAnalyzer", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.analyzer.MinHashAnalyzer", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.analyzer.ClassificationAnalyzer", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.analyzer.StemAnalyzer", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.analyzer.NormAnalyzer", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.analyzer.DelimiterAnalyzer", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.analyzer.CollationAnalyzer", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.analyzer.TextAnalyzer", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.analyzer.NGramAnalyzer", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.analyzer.StopwordsAnalyzer", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.ServerRole", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.ReplicationFactor$SatelliteReplicationFactor", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.analyzer.SegmentationAnalyzerProperties$BreakMode", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.AnalyzerFeature", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.ArangoDBEngine$StorageEngineName", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.SearchAliasIndex$OperationType", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.StreamTransactionStatus", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.QueryExecutionState", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.LogLevel", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.QueryCachePropertiesEntity$CacheMode", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.LogLevelEntity$LogLevel", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.StoreValuesType", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.LoadBalancingStrategy", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.InvertedIndexPrimarySort$Field$Direction", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.IndexType", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.ArangoSearchCompression", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.License", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.CollectionStatus", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.analyzer.SearchAnalyzerCase", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.analyzer.AQLAnalyzerProperties$ReturnType", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.analyzer.StreamType", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.CollectionType", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.KeyType", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.ViewType", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.ServerMode", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.AnalyzerType", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.analyzer.GeoJSONAnalyzerProperties$GeoJSONAnalyzerType", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.ShardingStrategy", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.ConsolidationType", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.Permissions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.IndexOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.DocumentImportOptions$OnDuplicate", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.OverwriteMode", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.ImportType", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.LogOptions$SortOrder", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.ComputedValue$ComputeOn", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.CollectionSchema$Level", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.ZKDIndexOptions$FieldValueTypes", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.DocumentReadOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.AqlQueryOptions$Optimizer", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.DBCreateOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.VertexCreateOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.AqlFunctionDeleteOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.arangosearch.AnalyzerDeleteOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.AqlQueryOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.UserUpdateOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.StreamTransactionOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.DocumentReplaceOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.DatabaseUsersOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.ViewRenameOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.arangosearch.SearchAliasPropertiesOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.CollectionCreateOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.AqlQueryExplainOptions$Options", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.ViewCreateOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.VertexCollectionCreateOptions$Options", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.arangosearch.ArangoSearchOptionsBuilder", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.AqlQueryParseOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.UserAccessOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.ComputedValue", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.arangosearch.ArangoSearchPropertiesOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.EdgeUpdateOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.VertexCollectionCreateOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.arangosearch.ArangoSearchCreateOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.VertexDeleteOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.EdgeCreateOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.GraphCreateOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.CollectionsReadOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.TransactionOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.CollectionTruncateOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.CollectionSchema", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.DocumentImportOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.DocumentDeleteOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.AqlQueryOptions$Options", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.EdgeReplaceOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.VertexReplaceOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.GraphDocumentReadOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.DocumentUpdateOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.VertexUpdateOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.OptionsBuilder", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.TransactionCollectionOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.LogOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.UserCreateOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.CollectionPropertiesOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.DatabaseOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.DocumentCreateOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.GraphCreateOptions$SmartOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.CollectionCountOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.EdgeDeleteOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.arangosearch.SearchAliasOptionsBuilder", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.CollectionRenameOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.arangosearch.SearchAliasCreateOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.DocumentExistsOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.AqlFunctionGetOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.AqlFunctionCreateOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.AqlQueryExplainOptions$Optimizer", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.AqlQueryExplainOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.QueueTimeSample", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.SkiplistIndexOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.GeoIndexOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.TtlIndexOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.FulltextIndexOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.HashIndexOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.ZKDIndexOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.InvertedIndexOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.PersistentIndexOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.DocumentImportOptions$OnDuplicate", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.OverwriteMode", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.ImportType", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.LogOptions$SortOrder", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.ComputedValue$ComputeOn", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.CollectionSchema$Level", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.ZKDIndexOptions$FieldValueTypes", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.MetaAware", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.internal.cursor.entity.InternalCursorEntity", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.internal.cursor.entity.InternalCursorEntity$Extras", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + } +] diff --git a/shaded/src/main/resources/META-INF/native-image/com.arangodb/arangodb-java-driver-shaded/resource-config.json b/shaded/src/main/resources/META-INF/native-image/com.arangodb/arangodb-java-driver-shaded/resource-config.json new file mode 100644 index 000000000..3bb430bb1 --- /dev/null +++ b/shaded/src/main/resources/META-INF/native-image/com.arangodb/arangodb-java-driver-shaded/resource-config.json @@ -0,0 +1,10 @@ +{ + "resources": { + "includes": [ + { + "pattern": "META-INF/vertx/vertx-version.txt" + } + ] + }, + "bundles": [] +} diff --git a/shaded/src/main/resources/META-INF/native-image/com.arangodb/arangodb-java-driver-shaded/serialization-config.json b/shaded/src/main/resources/META-INF/native-image/com.arangodb/arangodb-java-driver-shaded/serialization-config.json new file mode 100644 index 000000000..24dd5cb27 --- /dev/null +++ b/shaded/src/main/resources/META-INF/native-image/com.arangodb/arangodb-java-driver-shaded/serialization-config.json @@ -0,0 +1,26 @@ +[ + { + "name": "com.arangodb.entity.AbstractBaseDocument" + }, + { + "name": "com.arangodb.entity.BaseDocument" + }, + { + "name": "com.arangodb.entity.BaseEdgeDocument" + }, + { + "name": "java.util.HashMap" + }, + { + "name": "com.arangodb.entity.ErrorEntity" + }, + { + "name": "com.arangodb.ArangoDBException" + }, + { + "name": "com.arangodb.ArangoDBMultipleException" + }, + { + "name": "com.arangodb.internal.net.ArangoDBRedirectException" + } +] From ebfb394e0f6fdbb8fdd025293844dad87f30e4dc Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Mon, 12 Dec 2022 11:19:41 +0100 Subject: [PATCH 211/254] fixed shaded native tests CI --- .github/workflows/native.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/native.yml b/.github/workflows/native.yml index 163ab1bbb..e6c34a55a 100644 --- a/.github/workflows/native.yml +++ b/.github/workflows/native.yml @@ -21,7 +21,7 @@ jobs: - 17 module: - driver - - shaded + - shaded-integration-tests steps: - uses: actions/checkout@v2 @@ -60,7 +60,7 @@ jobs: - 17 module: - driver - - shaded + - shaded-integration-tests steps: - uses: actions/checkout@v2 From 957af28c1b4a920cc48090fda29f83aaca9ae506 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Mon, 12 Dec 2022 11:21:23 +0100 Subject: [PATCH 212/254] BaseDocument not serializable --- .../arangodb/entity/AbstractBaseDocument.java | 5 +-- .../com/arangodb/entity/BaseDocument.java | 5 +-- .../com/arangodb/entity/BaseEdgeDocument.java | 5 +-- .../serialization-config.json | 12 ------- .../java/com/arangodb/SerializableTest.java | 36 +++++++++++-------- resilience-tests/pom.xml | 5 +++ .../java/com/arangodb/SerializableTest.java | 36 +++++++++++-------- .../serialization-config.json | 12 ------- 8 files changed, 52 insertions(+), 64 deletions(-) diff --git a/driver/src/main/java/com/arangodb/entity/AbstractBaseDocument.java b/driver/src/main/java/com/arangodb/entity/AbstractBaseDocument.java index 8c1367242..6a46168dd 100644 --- a/driver/src/main/java/com/arangodb/entity/AbstractBaseDocument.java +++ b/driver/src/main/java/com/arangodb/entity/AbstractBaseDocument.java @@ -26,7 +26,6 @@ import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonInclude; -import java.io.Serializable; import java.util.Collections; import java.util.HashMap; import java.util.Map; @@ -36,9 +35,7 @@ * @author Mark Vollmary * @author Michele Rastelli */ -abstract class AbstractBaseDocument implements Serializable { - - private static final long serialVersionUID = 846874908582L; +abstract class AbstractBaseDocument { private static final String[] META_PROPS = new String[]{ DocumentFields.ID, diff --git a/driver/src/main/java/com/arangodb/entity/BaseDocument.java b/driver/src/main/java/com/arangodb/entity/BaseDocument.java index db6de1d47..88b0d6173 100644 --- a/driver/src/main/java/com/arangodb/entity/BaseDocument.java +++ b/driver/src/main/java/com/arangodb/entity/BaseDocument.java @@ -20,16 +20,13 @@ package com.arangodb.entity; -import java.io.Serializable; import java.util.Map; /** * @author Mark Vollmary * @author Michele Rastelli */ -public final class BaseDocument extends AbstractBaseDocument implements Serializable { - - private static final long serialVersionUID = 733033350470L; +public final class BaseDocument extends AbstractBaseDocument { public BaseDocument() { super(); diff --git a/driver/src/main/java/com/arangodb/entity/BaseEdgeDocument.java b/driver/src/main/java/com/arangodb/entity/BaseEdgeDocument.java index 28b582447..7dd5170ca 100644 --- a/driver/src/main/java/com/arangodb/entity/BaseEdgeDocument.java +++ b/driver/src/main/java/com/arangodb/entity/BaseEdgeDocument.java @@ -23,16 +23,13 @@ import com.arangodb.internal.DocumentFields; import com.fasterxml.jackson.annotation.JsonIgnore; -import java.io.Serializable; import java.util.Map; /** * @author Mark Vollmary * @author Michele Rastelli */ -public final class BaseEdgeDocument extends AbstractBaseDocument implements Serializable { - - private static final long serialVersionUID = 356629614444L; +public final class BaseEdgeDocument extends AbstractBaseDocument { private static final String[] META_PROPS = new String[]{ DocumentFields.ID, diff --git a/driver/src/main/resources/META-INF/native-image/com.arangodb/arangodb-java-driver/serialization-config.json b/driver/src/main/resources/META-INF/native-image/com.arangodb/arangodb-java-driver/serialization-config.json index 24dd5cb27..7160b9bd4 100644 --- a/driver/src/main/resources/META-INF/native-image/com.arangodb/arangodb-java-driver/serialization-config.json +++ b/driver/src/main/resources/META-INF/native-image/com.arangodb/arangodb-java-driver/serialization-config.json @@ -1,16 +1,4 @@ [ - { - "name": "com.arangodb.entity.AbstractBaseDocument" - }, - { - "name": "com.arangodb.entity.BaseDocument" - }, - { - "name": "com.arangodb.entity.BaseEdgeDocument" - }, - { - "name": "java.util.HashMap" - }, { "name": "com.arangodb.entity.ErrorEntity" }, diff --git a/driver/src/test/java/com/arangodb/SerializableTest.java b/driver/src/test/java/com/arangodb/SerializableTest.java index c1e770530..17b1ec1da 100644 --- a/driver/src/test/java/com/arangodb/SerializableTest.java +++ b/driver/src/test/java/com/arangodb/SerializableTest.java @@ -1,31 +1,22 @@ package com.arangodb; -import com.arangodb.entity.BaseDocument; import com.arangodb.entity.ErrorEntity; +import com.arangodb.internal.net.ArangoDBRedirectException; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.node.JsonNodeFactory; import org.junit.jupiter.api.Test; import java.io.*; +import java.util.Collections; +import java.util.List; import static org.assertj.core.api.Assertions.assertThat; -public class SerializableTest { +class SerializableTest { @Test - public void serializeBaseDocument() throws IOException, ClassNotFoundException { - BaseDocument bd = new BaseDocument("poaids"); - bd.setId("apdso/02193"); - bd.setRevision("poip"); - bd.addAttribute("aaa", "bbb"); - - BaseDocument bd2 = roundTrip(bd); - assertThat(bd).isEqualTo(bd2); - } - - @Test - public void serializeArangoDBException() throws IOException, ClassNotFoundException { + void serializeArangoDBException() throws IOException, ClassNotFoundException { ObjectMapper mapper = new ObjectMapper(); JsonNode jn = JsonNodeFactory.instance.objectNode() .put("errorMessage", "boomError") @@ -42,6 +33,23 @@ public void serializeArangoDBException() throws IOException, ClassNotFoundExcept assertThat(e2.getRequestId()).isEqualTo(e.getRequestId()); } + @Test + void serializeArangoDBRedirectException() throws IOException, ClassNotFoundException { + ArangoDBRedirectException e = new ArangoDBRedirectException("foo", "bar"); + ArangoDBRedirectException e2 = roundTrip(e); + assertThat(e2.getMessage()).isEqualTo(e.getMessage()); + assertThat(e2.getLocation()).isEqualTo(e.getLocation()); + } + + @Test + void serializeArangoDBMultipleException() throws IOException, ClassNotFoundException { + List exceptions = Collections.singletonList(new RuntimeException("foo")); + ArangoDBMultipleException e = new ArangoDBMultipleException(exceptions); + ArangoDBMultipleException e2 = roundTrip(e); + assertThat(e2.getExceptions()).hasSize(1); + assertThat(e2.getExceptions().iterator().next().getMessage()).isEqualTo("foo"); + } + private T roundTrip(T input) throws IOException, ClassNotFoundException { ByteArrayOutputStream os = new ByteArrayOutputStream(); ObjectOutputStream objectOutputStream = new ObjectOutputStream(os); diff --git a/resilience-tests/pom.xml b/resilience-tests/pom.xml index 341474a48..bd8c567c7 100644 --- a/resilience-tests/pom.xml +++ b/resilience-tests/pom.xml @@ -11,6 +11,11 @@ resilience-tests + + 17 + 17 + + org.mock-server diff --git a/shaded-integration-tests/src/test/native/java/com/arangodb/SerializableTest.java b/shaded-integration-tests/src/test/native/java/com/arangodb/SerializableTest.java index c1e770530..17b1ec1da 100644 --- a/shaded-integration-tests/src/test/native/java/com/arangodb/SerializableTest.java +++ b/shaded-integration-tests/src/test/native/java/com/arangodb/SerializableTest.java @@ -1,31 +1,22 @@ package com.arangodb; -import com.arangodb.entity.BaseDocument; import com.arangodb.entity.ErrorEntity; +import com.arangodb.internal.net.ArangoDBRedirectException; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.node.JsonNodeFactory; import org.junit.jupiter.api.Test; import java.io.*; +import java.util.Collections; +import java.util.List; import static org.assertj.core.api.Assertions.assertThat; -public class SerializableTest { +class SerializableTest { @Test - public void serializeBaseDocument() throws IOException, ClassNotFoundException { - BaseDocument bd = new BaseDocument("poaids"); - bd.setId("apdso/02193"); - bd.setRevision("poip"); - bd.addAttribute("aaa", "bbb"); - - BaseDocument bd2 = roundTrip(bd); - assertThat(bd).isEqualTo(bd2); - } - - @Test - public void serializeArangoDBException() throws IOException, ClassNotFoundException { + void serializeArangoDBException() throws IOException, ClassNotFoundException { ObjectMapper mapper = new ObjectMapper(); JsonNode jn = JsonNodeFactory.instance.objectNode() .put("errorMessage", "boomError") @@ -42,6 +33,23 @@ public void serializeArangoDBException() throws IOException, ClassNotFoundExcept assertThat(e2.getRequestId()).isEqualTo(e.getRequestId()); } + @Test + void serializeArangoDBRedirectException() throws IOException, ClassNotFoundException { + ArangoDBRedirectException e = new ArangoDBRedirectException("foo", "bar"); + ArangoDBRedirectException e2 = roundTrip(e); + assertThat(e2.getMessage()).isEqualTo(e.getMessage()); + assertThat(e2.getLocation()).isEqualTo(e.getLocation()); + } + + @Test + void serializeArangoDBMultipleException() throws IOException, ClassNotFoundException { + List exceptions = Collections.singletonList(new RuntimeException("foo")); + ArangoDBMultipleException e = new ArangoDBMultipleException(exceptions); + ArangoDBMultipleException e2 = roundTrip(e); + assertThat(e2.getExceptions()).hasSize(1); + assertThat(e2.getExceptions().iterator().next().getMessage()).isEqualTo("foo"); + } + private T roundTrip(T input) throws IOException, ClassNotFoundException { ByteArrayOutputStream os = new ByteArrayOutputStream(); ObjectOutputStream objectOutputStream = new ObjectOutputStream(os); diff --git a/shaded/src/main/resources/META-INF/native-image/com.arangodb/arangodb-java-driver-shaded/serialization-config.json b/shaded/src/main/resources/META-INF/native-image/com.arangodb/arangodb-java-driver-shaded/serialization-config.json index 24dd5cb27..7160b9bd4 100644 --- a/shaded/src/main/resources/META-INF/native-image/com.arangodb/arangodb-java-driver-shaded/serialization-config.json +++ b/shaded/src/main/resources/META-INF/native-image/com.arangodb/arangodb-java-driver-shaded/serialization-config.json @@ -1,16 +1,4 @@ [ - { - "name": "com.arangodb.entity.AbstractBaseDocument" - }, - { - "name": "com.arangodb.entity.BaseDocument" - }, - { - "name": "com.arangodb.entity.BaseEdgeDocument" - }, - { - "name": "java.util.HashMap" - }, { "name": "com.arangodb.entity.ErrorEntity" }, From ed386f7695d143e7070b8e3c7aa7863429c2fe36 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Mon, 12 Dec 2022 12:50:17 +0100 Subject: [PATCH 213/254] removed deserializa by type from ArangoSerde --- .../arangodb/internal/serde/InternalSerde.java | 10 ++++++++++ .../internal/serde/InternalSerdeImpl.java | 7 ++++++- .../serde/jackson/internal/JacksonSerdeImpl.java | 3 +-- .../com/arangodb/serde/jsonb/JsonbSerde.java | 3 +-- .../java/com/arangodb/serde/ArangoSerde.java | 16 +--------------- 5 files changed, 19 insertions(+), 20 deletions(-) diff --git a/driver/src/main/java/com/arangodb/internal/serde/InternalSerde.java b/driver/src/main/java/com/arangodb/internal/serde/InternalSerde.java index aeca0e880..b6d6a8dfd 100644 --- a/driver/src/main/java/com/arangodb/internal/serde/InternalSerde.java +++ b/driver/src/main/java/com/arangodb/internal/serde/InternalSerde.java @@ -37,6 +37,16 @@ static InternalSerde of(final ContentType contentType, ArangoSerde userSerde) { */ byte[] extract(byte[] content, String jsonPointer); + /** + * Deserializes the content and binds it to the target data type. + * For data type {@link ContentType#JSON}, the byte array is the JSON string encoded using the UTF-8 charset. + * + * @param content byte array to deserialize + * @param type target data type + * @return deserialized object + */ + T deserialize(byte[] content, Type type); + /** * Deserializes the parsed json node and binds it to the target data type. * diff --git a/driver/src/main/java/com/arangodb/internal/serde/InternalSerdeImpl.java b/driver/src/main/java/com/arangodb/internal/serde/InternalSerdeImpl.java index 6e3e4c349..12a2dc40c 100644 --- a/driver/src/main/java/com/arangodb/internal/serde/InternalSerdeImpl.java +++ b/driver/src/main/java/com/arangodb/internal/serde/InternalSerdeImpl.java @@ -51,6 +51,11 @@ public byte[] serialize(final Object value) { } } + @Override + public T deserialize(byte[] content, Class clazz) { + return deserialize(content, (Type) clazz); + } + @Override public String toJsonString(final byte[] content) { try { @@ -125,7 +130,7 @@ public T deserializeUserData(byte[] content, Type type) { if (type instanceof Class) { return deserializeUserData(content, (Class) type); } else { - return userSerde.deserialize(content, type); + throw new UnsupportedOperationException(); } } diff --git a/jackson-serde/src/main/java/com/arangodb/serde/jackson/internal/JacksonSerdeImpl.java b/jackson-serde/src/main/java/com/arangodb/serde/jackson/internal/JacksonSerdeImpl.java index 887ceed31..7b6e812c1 100644 --- a/jackson-serde/src/main/java/com/arangodb/serde/jackson/internal/JacksonSerdeImpl.java +++ b/jackson-serde/src/main/java/com/arangodb/serde/jackson/internal/JacksonSerdeImpl.java @@ -6,7 +6,6 @@ import com.fasterxml.jackson.databind.ObjectMapper; import java.io.IOException; -import java.lang.reflect.Type; import java.util.function.Consumer; /** @@ -31,7 +30,7 @@ public byte[] serialize(final Object value) { } @Override - public T deserialize(final byte[] content, final Type type) { + public T deserialize(final byte[] content, final Class type) { try { return mapper.readerFor(mapper.constructType(type)).readValue(content); } catch (IOException e) { diff --git a/jsonb-serde/src/main/java/com/arangodb/serde/jsonb/JsonbSerde.java b/jsonb-serde/src/main/java/com/arangodb/serde/jsonb/JsonbSerde.java index 45c98c0bd..b1d2baa36 100644 --- a/jsonb-serde/src/main/java/com/arangodb/serde/jsonb/JsonbSerde.java +++ b/jsonb-serde/src/main/java/com/arangodb/serde/jsonb/JsonbSerde.java @@ -5,7 +5,6 @@ import jakarta.json.bind.JsonbBuilder; import jakarta.json.bind.JsonbConfig; -import java.lang.reflect.Type; import java.nio.charset.StandardCharsets; /** @@ -29,7 +28,7 @@ public byte[] serialize(Object value) { } @Override - public T deserialize(byte[] content, Type type) { + public T deserialize(byte[] content, Class type) { return jsonb.fromJson(new String(content, StandardCharsets.UTF_8), type); } diff --git a/serde-api/src/main/java/com/arangodb/serde/ArangoSerde.java b/serde-api/src/main/java/com/arangodb/serde/ArangoSerde.java index 4218bbc12..9e15ce097 100644 --- a/serde-api/src/main/java/com/arangodb/serde/ArangoSerde.java +++ b/serde-api/src/main/java/com/arangodb/serde/ArangoSerde.java @@ -2,8 +2,6 @@ import com.arangodb.ContentType; -import java.lang.reflect.Type; - /** * Contract for serialization/deserialization of user data. * Implementations of this interface could be used for customizing serialization/deserialization of user related data @@ -32,18 +30,6 @@ public interface ArangoSerde { * @param clazz class of target data type * @return deserialized object */ - default T deserialize(byte[] content, Class clazz) { - return deserialize(content, (Type) clazz); - } - - /** - * Deserializes the content and binds it to the target data type. - * For data type {@link ContentType#JSON}, the byte array is the JSON string encoded using the UTF-8 charset. - * - * @param content byte array to deserialize - * @param type target data type - * @return deserialized object - */ - T deserialize(byte[] content, Type type); + T deserialize(byte[] content, Class clazz); } From df64849c9fce2a1a1b175de86c013a59affca15e Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Mon, 12 Dec 2022 13:29:13 +0100 Subject: [PATCH 214/254] fixed native tests --- .../resources/META-INF/native-image/serialization-config.json | 3 +++ .../resources/META-INF/native-image/serialization-config.json | 3 +++ 2 files changed, 6 insertions(+) diff --git a/driver/src/test/resources/META-INF/native-image/serialization-config.json b/driver/src/test/resources/META-INF/native-image/serialization-config.json index 2871e9998..8c832f7ba 100644 --- a/driver/src/test/resources/META-INF/native-image/serialization-config.json +++ b/driver/src/test/resources/META-INF/native-image/serialization-config.json @@ -19,5 +19,8 @@ }, { "name": "java.util.Collections$EmptyList" + }, + { + "name": "java.util.Collections$SingletonList" } ] diff --git a/shaded-integration-tests/src/test/resources/META-INF/native-image/serialization-config.json b/shaded-integration-tests/src/test/resources/META-INF/native-image/serialization-config.json index 2871e9998..8c832f7ba 100644 --- a/shaded-integration-tests/src/test/resources/META-INF/native-image/serialization-config.json +++ b/shaded-integration-tests/src/test/resources/META-INF/native-image/serialization-config.json @@ -19,5 +19,8 @@ }, { "name": "java.util.Collections$EmptyList" + }, + { + "name": "java.util.Collections$SingletonList" } ] From 729d8804092b672ca3885fe5a5613c80553bb627 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Mon, 12 Dec 2022 13:44:30 +0100 Subject: [PATCH 215/254] mvn clean shaded pom --- pom.xml | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/pom.xml b/pom.xml index f519de36a..b242aabac 100644 --- a/pom.xml +++ b/pom.xml @@ -303,6 +303,19 @@ false + + maven-clean-plugin + + + + ${project.basedir} + + **/dependency-reduced-pom.xml + + + + + From d3cd212f3d80dc579f431bcfff89ccc625117928 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Mon, 12 Dec 2022 20:47:58 +0100 Subject: [PATCH 216/254] fixed flatten plugin order --- driver/pom.xml | 4 ++++ pom.xml | 2 +- shaded/pom.xml | 4 ++++ 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/driver/pom.xml b/driver/pom.xml index 12440d0bf..a99e084e2 100644 --- a/driver/pom.xml +++ b/driver/pom.xml @@ -227,6 +227,10 @@ + + org.codehaus.mojo + flatten-maven-plugin + diff --git a/pom.xml b/pom.xml index b242aabac..a2b0e5dce 100644 --- a/pom.xml +++ b/pom.xml @@ -248,7 +248,7 @@ flatten - process-resources + package flatten diff --git a/shaded/pom.xml b/shaded/pom.xml index 5cdf4e309..a9f29b576 100644 --- a/shaded/pom.xml +++ b/shaded/pom.xml @@ -125,6 +125,10 @@ + + org.codehaus.mojo + flatten-maven-plugin + From e6ba67af78c571090c8902c31e4f655c62c07726 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Thu, 15 Dec 2022 20:10:59 +0100 Subject: [PATCH 217/254] [DE-437] added jvm version to user agent header --- .../java/com/arangodb/internal/http/HttpConnection.java | 6 +++++- driver/src/test/java/com/arangodb/PackageVersionTest.java | 7 ++++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/driver/src/main/java/com/arangodb/internal/http/HttpConnection.java b/driver/src/main/java/com/arangodb/internal/http/HttpConnection.java index e031c636d..5f6a422df 100644 --- a/driver/src/main/java/com/arangodb/internal/http/HttpConnection.java +++ b/driver/src/main/java/com/arangodb/internal/http/HttpConnection.java @@ -71,7 +71,7 @@ public class HttpConnection implements Connection { private static final Logger LOGGER = LoggerFactory.getLogger(HttpConnection.class); private static final String CONTENT_TYPE_APPLICATION_JSON_UTF8 = "application/json; charset=utf-8"; private static final String CONTENT_TYPE_VPACK = "application/x-velocypack"; - private static final String USER_AGENT = "JavaDriver/" + PackageVersion.VERSION; + private static final String USER_AGENT = getUserAgent(); private static final AtomicInteger THREAD_COUNT = new AtomicInteger(); private final InternalSerde util; private final ContentType contentType; @@ -80,6 +80,10 @@ public class HttpConnection implements Connection { private final Integer timeout; private final Vertx vertx; + private static String getUserAgent() { + return "JavaDriver/" + PackageVersion.VERSION + " (JVM/" + System.getProperty("java.specification.version") + ")"; + } + private HttpConnection(final HostDescription host, final Integer timeout, final String user, final String password, final Boolean useSsl, final SSLContext sslContext, final Boolean verifyHost, final InternalSerde util, final Protocol protocol, final Long ttl) { diff --git a/driver/src/test/java/com/arangodb/PackageVersionTest.java b/driver/src/test/java/com/arangodb/PackageVersionTest.java index 70a036ac3..85a082088 100644 --- a/driver/src/test/java/com/arangodb/PackageVersionTest.java +++ b/driver/src/test/java/com/arangodb/PackageVersionTest.java @@ -43,7 +43,12 @@ void userAgentHeader(Protocol protocol) { .method(Request.Method.GET) .path("/_admin/echo") .build(), JsonNode.class); - assertThat(resp.getBody().get("headers").get("x-arango-driver").textValue()).endsWith(PackageVersion.VERSION); + String headerValue = resp.getBody().get("headers").get("x-arango-driver").textValue(); + + String jvmVersion = System.getProperty("java.specification.version"); + String expected = "JavaDriver/" + PackageVersion.VERSION + " (JVM/" + jvmVersion + ")"; + + assertThat(headerValue).isEqualTo(expected); adb.shutdown(); } } From 6eeff5cbf0eadd93feccddb6c59952ff6e58583c Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Thu, 15 Dec 2022 21:12:40 +0100 Subject: [PATCH 218/254] fixed VST debug logging --- .../internal/velocystream/VstCommunicationAsync.java | 12 ++++++++---- .../internal/velocystream/VstCommunicationSync.java | 12 ++++++++---- .../internal/velocystream/internal/MessageStore.java | 4 ---- 3 files changed, 16 insertions(+), 12 deletions(-) diff --git a/driver/src/main/java/com/arangodb/async/internal/velocystream/VstCommunicationAsync.java b/driver/src/main/java/com/arangodb/async/internal/velocystream/VstCommunicationAsync.java index 98edbc61b..ab8319070 100644 --- a/driver/src/main/java/com/arangodb/async/internal/velocystream/VstCommunicationAsync.java +++ b/driver/src/main/java/com/arangodb/async/internal/velocystream/VstCommunicationAsync.java @@ -67,6 +67,10 @@ protected CompletableFuture execute(final InternalRequest requ final CompletableFuture rfuture = new CompletableFuture<>(); try { final Message message = createMessage(request); + if (LOGGER.isDebugEnabled()) { + String body = request.getBody() == null ? "" : util.toJsonString(request.getBody()); + LOGGER.debug("Send Request [id={}]: {} {}", message.getId(), request, body); + } send(message, connection).whenComplete((m, ex) -> { if (m != null) { final InternalResponse response; @@ -102,6 +106,10 @@ protected CompletableFuture execute(final InternalRequest requ } catch (ArangoDBException e) { rfuture.completeExceptionally(e); } + if (LOGGER.isDebugEnabled()) { + String body = response.getBody() == null ? "" : util.toJsonString(response.getBody()); + LOGGER.debug("Received Response [id={}]: {} {}", m.getId(), response, body); + } rfuture.complete(response); } else if (ex != null) { LOGGER.error(ex.getMessage(), ex); @@ -118,10 +126,6 @@ protected CompletableFuture execute(final InternalRequest requ } private CompletableFuture send(final Message message, final VstConnectionAsync connection) { - if (LOGGER.isDebugEnabled()) { - LOGGER.debug(String.format("Send Message (id=%s, head=%s, body=%s)", message.getId(), message.getHead(), - message.getBody() != null ? message.getBody() : "{}")); - } return connection.write(message, buildChunks(message)); } diff --git a/driver/src/main/java/com/arangodb/internal/velocystream/VstCommunicationSync.java b/driver/src/main/java/com/arangodb/internal/velocystream/VstCommunicationSync.java index 837e12d50..affd94887 100644 --- a/driver/src/main/java/com/arangodb/internal/velocystream/VstCommunicationSync.java +++ b/driver/src/main/java/com/arangodb/internal/velocystream/VstCommunicationSync.java @@ -62,8 +62,16 @@ protected InternalResponse execute(final InternalRequest request, final VstConne protected InternalResponse execute(final InternalRequest request, final VstConnectionSync connection, final int attemptCount) { try { final Message requestMessage = createMessage(request); + if (LOGGER.isDebugEnabled()) { + String body = request.getBody() == null ? "" : util.toJsonString(request.getBody()); + LOGGER.debug("Send Request [id={}]: {} {}", requestMessage.getId(), request, body); + } final Message responseMessage = send(requestMessage, connection); final InternalResponse response = createResponse(responseMessage); + if (LOGGER.isDebugEnabled()) { + String body = response.getBody() == null ? "" : util.toJsonString(response.getBody()); + LOGGER.debug("Received Response [id={}]: {} {}", responseMessage.getId(), response, body); + } checkError(response); return response; } catch (final VPackParserException e) { @@ -80,10 +88,6 @@ protected InternalResponse execute(final InternalRequest request, final VstConne } private Message send(final Message message, final VstConnectionSync connection) { - if (LOGGER.isDebugEnabled()) { - LOGGER.debug(String.format("Send Message (id=%s, head=%s, body=%s)", message.getId(), message.getHead(), - message.getBody() != null ? message.getBody() : "{}")); - } return connection.write(message, buildChunks(message)); } diff --git a/driver/src/main/java/com/arangodb/internal/velocystream/internal/MessageStore.java b/driver/src/main/java/com/arangodb/internal/velocystream/internal/MessageStore.java index 62fd4ae2a..9e9184a5c 100644 --- a/driver/src/main/java/com/arangodb/internal/velocystream/internal/MessageStore.java +++ b/driver/src/main/java/com/arangodb/internal/velocystream/internal/MessageStore.java @@ -54,10 +54,6 @@ public void storeMessage(final long messageId, final FutureTask future) public void consume(final Message message) { final FutureTask future = task.remove(message.getId()); if (future != null) { - if (LOGGER.isDebugEnabled()) { - LOGGER.debug(String.format("Received Message (id=%s, head=%s, body=%s)", message.getId(), - message.getHead(), message.getBody() != null ? message.getBody() : "{}")); - } response.put(message.getId(), message); future.run(); } From be57b9f9b7b4d7fc6f60d0dbbf69fa39837ad630 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Fri, 16 Dec 2022 08:50:32 +0100 Subject: [PATCH 219/254] test fix: getIndexesShouldNotReturnInvertedIndexes() --- driver/src/test/java/com/arangodb/async/InvertedIndexTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/driver/src/test/java/com/arangodb/async/InvertedIndexTest.java b/driver/src/test/java/com/arangodb/async/InvertedIndexTest.java index 8ee509526..e4451f77c 100644 --- a/driver/src/test/java/com/arangodb/async/InvertedIndexTest.java +++ b/driver/src/test/java/com/arangodb/async/InvertedIndexTest.java @@ -182,7 +182,7 @@ void getIndexesShouldNotReturnInvertedIndexes() throws ExecutionException, Inter ArangoCollectionAsync collection = db.collection(COLLECTION_NAME); // create persistent index - collection.ensurePersistentIndex(Collections.singletonList("foo"), new PersistentIndexOptions().name("persistentIndex")); + collection.ensurePersistentIndex(Collections.singletonList("foo"), new PersistentIndexOptions().name("persistentIndex")).get(); // create inverted index String analyzerName = "delimiter-" + UUID.randomUUID(); From 3855127abbff9dd61f6f0c96835380f79816a8c2 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Tue, 20 Dec 2022 11:13:30 +0100 Subject: [PATCH 220/254] [DE-445] JPMS compatibility (#477) * removed unneeded methods from ConfigPropertiesProvider * [DE-445] fixed FileConfigPropertiesProvider with JPMS * [DE-445] JPMS module names --- driver/pom.xml | 1 + .../arangodb/config/ConfigPropertiesProvider.java | 13 ------------- .../arangodb/internal/InternalArangoDBBuilder.java | 8 +++++--- .../config/FileConfigPropertiesProvider.java | 4 ++-- jackson-serde/pom.xml | 1 + jsonb-serde/pom.xml | 1 + pom.xml | 11 +++++++++++ resilience-tests/pom.xml | 5 ----- .../test/java/resilience/ActiveFailoverTest.java | 3 ++- .../src/test/java/resilience/ClusterTest.java | 3 ++- serde-api/pom.xml | 4 ++++ shaded/pom.xml | 5 +++++ 12 files changed, 34 insertions(+), 25 deletions(-) diff --git a/driver/pom.xml b/driver/pom.xml index a99e084e2..757a214a0 100644 --- a/driver/pom.xml +++ b/driver/pom.xml @@ -18,6 +18,7 @@ false false src/test/**/* + com.arangodb.driver diff --git a/driver/src/main/java/com/arangodb/config/ConfigPropertiesProvider.java b/driver/src/main/java/com/arangodb/config/ConfigPropertiesProvider.java index 2e3f6af0c..0e1fe2417 100644 --- a/driver/src/main/java/com/arangodb/config/ConfigPropertiesProvider.java +++ b/driver/src/main/java/com/arangodb/config/ConfigPropertiesProvider.java @@ -9,17 +9,4 @@ public interface ConfigPropertiesProvider { */ String getProperty(String key); - default String getProperty(ConfigPropertyKey key) { - return getProperty(key.getValue()); - } - - default String getProperty(String key, String defaultValue) { - String p = getProperty(key); - return p != null ? p : defaultValue; - } - - default String getProperty(ConfigPropertyKey key, String defaultValue) { - String p = getProperty(key); - return p != null ? p : defaultValue; - } } diff --git a/driver/src/main/java/com/arangodb/internal/InternalArangoDBBuilder.java b/driver/src/main/java/com/arangodb/internal/InternalArangoDBBuilder.java index e493a6207..b3b4eae1e 100644 --- a/driver/src/main/java/com/arangodb/internal/InternalArangoDBBuilder.java +++ b/driver/src/main/java/com/arangodb/internal/InternalArangoDBBuilder.java @@ -60,7 +60,7 @@ public abstract class InternalArangoDBBuilder { protected Integer responseQueueTimeSamples = ArangoDefaults.DEFAULT_RESPONSE_QUEUE_TIME_SAMPLES; private static void loadHosts(final ConfigPropertiesProvider properties, final Collection hosts) { - final String hostsProp = properties.getProperty(ConfigPropertyKey.HOSTS); + final String hostsProp = properties.getProperty(ConfigPropertyKey.HOSTS.getValue()); if (hostsProp != null) { final String[] hostsSplit = hostsProp.split(","); for (final String host : hostsSplit) { @@ -138,8 +138,10 @@ private static LoadBalancingStrategy loadLoadBalancingStrategy( } protected static String getProperty(ConfigPropertiesProvider props, ConfigPropertyKey key, Object currentValue) { - String defaultValue = currentValue == null ? null : currentValue.toString(); - return props.getProperty(key, defaultValue); + String p = props.getProperty(key.getValue()); + if (p != null) return p; + if (currentValue != null) return currentValue.toString(); + return null; } protected static ArangoSerdeProvider serdeProvider() { diff --git a/driver/src/main/java/com/arangodb/internal/config/FileConfigPropertiesProvider.java b/driver/src/main/java/com/arangodb/internal/config/FileConfigPropertiesProvider.java index ed147dd05..4e54ce196 100644 --- a/driver/src/main/java/com/arangodb/internal/config/FileConfigPropertiesProvider.java +++ b/driver/src/main/java/com/arangodb/internal/config/FileConfigPropertiesProvider.java @@ -12,7 +12,7 @@ */ public class FileConfigPropertiesProvider implements ConfigPropertiesProvider { private static final String DEFAULT_PREFIX = "arangodb"; - private static final String DEFAULT_PROPERTY_FILE = "/arangodb.properties"; + private static final String DEFAULT_PROPERTY_FILE = "arangodb.properties"; private final Properties properties; private final String prefix; @@ -35,7 +35,7 @@ private String initPrefix(String p) { private Properties initProperties(String fileName) { Properties p = new Properties(); - try (InputStream is = FileConfigPropertiesProvider.class.getResourceAsStream(fileName)) { + try (InputStream is = getClass().getClassLoader().getResourceAsStream(fileName)) { p.load(is); } catch (Exception e) { throw new ArangoDBException("Got exception while reading properties file " + fileName, e); diff --git a/jackson-serde/pom.xml b/jackson-serde/pom.xml index 7ce85c92e..0c55732f6 100644 --- a/jackson-serde/pom.xml +++ b/jackson-serde/pom.xml @@ -15,6 +15,7 @@ false + com.arangodb.serde.jackson diff --git a/jsonb-serde/pom.xml b/jsonb-serde/pom.xml index 3776e7e3a..63314250c 100644 --- a/jsonb-serde/pom.xml +++ b/jsonb-serde/pom.xml @@ -16,6 +16,7 @@ true + com.arangodb.serde.jsonb diff --git a/pom.xml b/pom.xml index a2b0e5dce..cd1b82232 100644 --- a/pom.xml +++ b/pom.xml @@ -263,6 +263,17 @@ + + org.apache.maven.plugins + maven-jar-plugin + + + + ${moduleName} + + + + org.apache.maven.plugins maven-enforcer-plugin diff --git a/resilience-tests/pom.xml b/resilience-tests/pom.xml index bd8c567c7..341474a48 100644 --- a/resilience-tests/pom.xml +++ b/resilience-tests/pom.xml @@ -11,11 +11,6 @@ resilience-tests - - 17 - 17 - - org.mock-server diff --git a/resilience-tests/src/test/java/resilience/ActiveFailoverTest.java b/resilience-tests/src/test/java/resilience/ActiveFailoverTest.java index 4c639c55b..8b2573a5b 100644 --- a/resilience-tests/src/test/java/resilience/ActiveFailoverTest.java +++ b/resilience-tests/src/test/java/resilience/ActiveFailoverTest.java @@ -12,6 +12,7 @@ import org.junit.jupiter.api.Tag; import java.io.IOException; +import java.util.Arrays; import java.util.List; @Tag("activeFailover") @@ -20,7 +21,7 @@ public abstract class ActiveFailoverTest { protected static final String HOST = "127.0.0.1"; protected static final String PASSWORD = "test"; protected static final MemoryAppender logs = new MemoryAppender(Level.WARN); - private static final List endpoints = List.of( + private static final List endpoints = Arrays.asList( new Endpoint("activeFailover1", HOST, 18529, "172.28.0.1:8529"), new Endpoint("activeFailover2", HOST, 18539, "172.28.0.1:8539"), new Endpoint("activeFailover3", HOST, 18549, "172.28.0.1:8549") diff --git a/resilience-tests/src/test/java/resilience/ClusterTest.java b/resilience-tests/src/test/java/resilience/ClusterTest.java index 5b343bb28..a757f5f76 100644 --- a/resilience-tests/src/test/java/resilience/ClusterTest.java +++ b/resilience-tests/src/test/java/resilience/ClusterTest.java @@ -12,6 +12,7 @@ import org.junit.jupiter.api.Tag; import java.io.IOException; +import java.util.Arrays; import java.util.List; @Tag("cluster") @@ -20,7 +21,7 @@ public abstract class ClusterTest { protected static final String HOST = "127.0.0.1"; protected static final String PASSWORD = "test"; protected static final MemoryAppender logs = new MemoryAppender(Level.WARN); - private static final List endpoints = List.of( + private static final List endpoints = Arrays.asList( new Endpoint("cluster1", HOST, 18529, "172.28.0.1:8529"), new Endpoint("cluster2", HOST, 18539, "172.28.0.1:8539"), new Endpoint("cluster3", HOST, 18549, "172.28.0.1:8549") diff --git a/serde-api/pom.xml b/serde-api/pom.xml index c567b1159..d43145b9c 100644 --- a/serde-api/pom.xml +++ b/serde-api/pom.xml @@ -11,4 +11,8 @@ serde-api + + com.arangodb.serde + + \ No newline at end of file diff --git a/shaded/pom.xml b/shaded/pom.xml index a9f29b576..0d9e3e9e0 100644 --- a/shaded/pom.xml +++ b/shaded/pom.xml @@ -16,6 +16,7 @@ false + com.arangodb.driver @@ -45,6 +46,10 @@ + + org.apache.maven.plugins + maven-jar-plugin + maven-shade-plugin 3.4.1 From c47ab753b6d2f7c7ec0ae139100824117f9744ee Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Tue, 20 Dec 2022 14:15:28 +0100 Subject: [PATCH 221/254] fixed mvn plugins versions --- pom.xml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pom.xml b/pom.xml index cd1b82232..be0d8458a 100644 --- a/pom.xml +++ b/pom.xml @@ -35,6 +35,7 @@ arangodb-1 https://sonarcloud.io 2.14.1 + @@ -266,6 +267,7 @@ org.apache.maven.plugins maven-jar-plugin + 3.3.0 @@ -315,7 +317,9 @@ + org.apache.maven.plugins maven-clean-plugin + 3.2.0 From 0ab2f195dfd90681a53526772024625a8f8e3286 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Wed, 21 Dec 2022 11:03:39 +0100 Subject: [PATCH 222/254] added integration-tests as module --- .github/workflows/resilience.yml | 5 +- driver/pom.xml | 33 --------- pom.xml | 53 +++++++++++++- shaded-integration-tests/pom.xml | 117 ++----------------------------- 4 files changed, 61 insertions(+), 147 deletions(-) diff --git a/.github/workflows/resilience.yml b/.github/workflows/resilience.yml index 14b5d0e75..061aa41ac 100644 --- a/.github/workflows/resilience.yml +++ b/.github/workflows/resilience.yml @@ -30,5 +30,8 @@ jobs: run: mvn -version - name: Start Toxiproxy run: ./bin/startProxy.sh + - name: Install + run: mvn --no-transfer-progress install -DskipTests=true -Dgpg.skip=true -Dmaven.javadoc.skip=true - name: Test - run: mvn --no-transfer-progress -am -pl resilience-tests test + working-directory: resilience-tests + run: mvn --no-transfer-progress test diff --git a/driver/pom.xml b/driver/pom.xml index 757a214a0..c5c66e384 100644 --- a/driver/pom.xml +++ b/driver/pom.xml @@ -50,39 +50,6 @@ - - native - - - - org.graalvm.buildtools - native-maven-plugin - 0.9.19 - true - - - test-native - - generateTestResourceConfig - test - - test - - - - true - false - - --no-fallback - - - ${SslTest} - - - - - - static-code-analysis diff --git a/pom.xml b/pom.xml index be0d8458a..044388ee9 100644 --- a/pom.xml +++ b/pom.xml @@ -9,7 +9,6 @@ 2016 driver - resilience-tests shaded jackson-serde serde-api @@ -36,6 +35,7 @@ https://sonarcloud.io 2.14.1 + @@ -133,6 +133,11 @@ jackson-serde ${project.version} + + com.arangodb + jsonb-serde + ${project.version} + com.arangodb arangodb-java-driver-shaded @@ -158,6 +163,16 @@ assertj-core 3.23.1 + + com.tngtech.archunit + archunit-junit5 + 1.0.1 + + + org.eclipse + yasson + 3.0.2 + @@ -173,8 +188,6 @@ -Xlint:deprecation true - 1.8 - 1.8 @@ -274,6 +287,7 @@ ${moduleName} + true @@ -363,6 +377,39 @@ jsonb-serde + + native + + + + org.graalvm.buildtools + native-maven-plugin + 0.9.19 + true + + + test-native + + generateTestResourceConfig + test + + test + + + + true + false + + --no-fallback + + + ${SslTest} + + + + + + diff --git a/shaded-integration-tests/pom.xml b/shaded-integration-tests/pom.xml index 8194e89a5..d436669a3 100644 --- a/shaded-integration-tests/pom.xml +++ b/shaded-integration-tests/pom.xml @@ -4,92 +4,25 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 - com.arangodb - integration-tests - 7.0.0-SNAPSHOT + + com.arangodb + arangodb-java-driver-parent + 7.0.0-SNAPSHOT + + + shaded-integration-tests 17 17 - UTF-8 - 2.14.1 - - - ch.qos.logback - logback-classic - 1.4.5 - test - - - org.junit.platform - junit-platform-launcher - test - - - org.junit.jupiter - junit-jupiter-api - test - - - org.junit.jupiter - junit-jupiter-engine - test - - - org.junit.jupiter - junit-jupiter-params - test - - - org.assertj - assertj-core - 3.23.1 - test - - - - - - - com.fasterxml.jackson - jackson-bom - ${adb.jackson.version} - import - pom - - - io.vertx - vertx-stack-depchain - 4.3.5 - pom - import - - - io.netty - netty-bom - 4.1.85.Final - pom - import - - - org.junit - junit-bom - 5.9.1 - pom - import - - - - ${testSourceDirectory} org.apache.maven.plugins maven-surefire-plugin - 3.0.0-M7 ${serde} @@ -113,19 +46,16 @@ com.arangodb arangodb-java-driver-shaded - 7.0.0-SNAPSHOT test com.arangodb jackson-dataformat-velocypack - 3.1.0 test com.tngtech.archunit archunit-junit5 - 1.0.1 test @@ -140,7 +70,6 @@ com.arangodb arangodb-java-driver-shaded - 7.0.0-SNAPSHOT test @@ -152,18 +81,15 @@ com.arangodb jsonb-serde - 7.0.0-SNAPSHOT test org.eclipse yasson - 3.0.2 com.tngtech.archunit archunit-junit5 - 1.0.1 test @@ -178,43 +104,14 @@ com.arangodb arangodb-java-driver-shaded - 7.0.0-SNAPSHOT test com.arangodb jackson-dataformat-velocypack - 3.1.0 test - - - - org.graalvm.buildtools - native-maven-plugin - 0.9.19 - true - - - test-native - - generateTestResourceConfig - test - - test - - - - true - false - - --no-fallback - - - - - \ No newline at end of file From 68fe1eb5182a2937a01a9269730833bcb3b29ef5 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Thu, 22 Dec 2022 21:13:35 +0100 Subject: [PATCH 223/254] [DE-322] v7 documentation (#478) * loadpropertiesWithPrefix test * upd doc * serde doc * shaded doc * upd ChangeLog.md --- ChangeLog.md | 75 +++--- docs/v7_detailed_changes.md | 152 ++++++++---- docs/v7_java-reference-serialization.md | 233 ++++++++++++++++++ .../test/java/com/arangodb/ArangoDBTest.java | 12 +- .../resources/arangodb-with-prefix.properties | 3 + 5 files changed, 391 insertions(+), 84 deletions(-) create mode 100644 docs/v7_java-reference-serialization.md create mode 100644 driver/src/test/resources/arangodb-with-prefix.properties diff --git a/ChangeLog.md b/ChangeLog.md index 2bcbc63d2..90d9a586e 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -10,61 +10,48 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) a ### Changed -- configuration properties from local files are not read automatically anymore +- configuration properties from local files are not loaded automatically anymore - `ArangoDB.execute()` accepts now target deserialization type -- `Request` and `Response` support now generic body type -- removed default host configuration to `127.0.0.1:8529` +- `Request` and `Response` support now generic body type +- removed default host configuration (`127.0.0.1:8529`) - changed http client library to Vert.x WebClient - changed default communication protocol from `VST` to `HTTP/2` -- changed default content-type encoding format from `VPACK` to `JSON` -- VPACK support is now provided by the optional dependency `com.arangodb:jackson-dataformat-velocypack` as dataformat - backend for Jackson -- changed serialization module, which is now based on Jackson API -- data objects passed as arguments to API methods are now treated as immutable and the related metadata fields are not - updated anymore (updated metadata can be found anyway in the object returned by the API method) -- changed some API signatures which were using unnecessary generics +- changed default content-type format from `VPACK` to `JSON` +- changed internal serialization, now based on Jackson API +- `VPACK` support is now provided by `JacksonSerde` including the optional dependency + `com.arangodb:jackson-dataformat-velocypack` (`VPACK` dataformat backend for Jackson) +- data objects passed as arguments to API methods are treated as immutable and the related metadata fields are not + updated in place anymore (updated metadata can be found in the returned object) +- changed some API signatures which were using unnecessary generics from `ArangoCollection`, `ArangoVertexCollection` and `ArangoEdgeCollection` - changed `ArangoCursor#getStats()` to return untyped map -- modeled replication factor with a new interface (`ReplicationFactor`) with +- replication factor is now represented by a new interface (`ReplicationFactor`) with implementations: `NumericReplicationFactor` and `SatelliteReplicationFactor` -- all data definition classes are now `final` +- all data definition classes are now `final` (packages `com.arangodb.entity` and `com.arangodb.model`) - `BaseDocument` and `BaseEdgeDocument` are now `final` - `BaseDocument#getProperties()` and `BaseEdgeDocument#getProperties()` return now an unmodifiable map -- changed API method signatures removing throw declarations like: `throws ArangoDBException` (unchecked exception) -- removed passwords from debug level requests logs - -### Removed - -- removed user data custom serializer API based on `ArangoSerialization` (in favor of `ArangoSerde`) -- removed user data custom serializer implementation `ArangoJack` (in favor of `JacksonSerde`) -- removed support for interpreting raw strings as JSON (in favor of `RawJson`) -- removed support of data type `VPackSlice` (in favor of Jackson types: `JsonNode`, `ArrayNode`, `ObjectNode`, ...) -- removed client APIs already deprecated in Java Driver version `6.19.0` -- removed deprecated server APIs: - - `MMFiles` related APIs - - `ArangoDatabase.executeTraversal()` - - `ArangoDB.getLogs()` - - `minReplicationFactor` in collections and graphs - - `overwrite` flag in `DocumentCreateOptions` -- removed `ArangoCursorInitializer` +- removed `throws ArangoDBException` from API method signatures (unchecked exception) +- removed passwords from debug level requests logs (#410) +- JPMS: explicit automatic module name ### Added - added `ArangoDB.Builder.loadProperties(ConfigPropertiesProvider)` to register custom configuration providers - added `FileConfigPropertiesProvider` to load properties from local files - added support to `HTTP/2` communication protocol -- added transitive dependency on `io.vertx:vertx-web-client`, which can be excluded if using VST only +- added optional transitive dependency on `io.vertx:vertx-web-client` (can be excluded if using VST only) - added transitive dependency on Jackson Core, Databind and Annotations - added wrapper class for raw JSON content (`RawJson`) - added wrapper class for content already encoded as byte array (`RawBytes`) - added support for Jackson types (`JsonNode`, `ArrayNode`, `ObjectNode`, ...) - added support for Jackson annotations in data types - added new user data custom serializer API based on `ArangoSerde` -- added new user data custom serializer implementation based on Jackson (`JacksonSerde`) +- added new user data custom serializer implementation based on Jackson (`JacksonSerde`), supporting both `JSON` and `VPACK`) - added methods and parameters targets to meta binding annotations - added overloaded methods for CRUD operations allowing specifying the return type - added API to support CRUD operations from raw data (`RawBytes` and `RawJson`) containing multiple documents - added `BaseDocument#removeAttribute(String)` and `BaseEdgeDocument#removeAttribute(String)` - added request id to `ArangoDBException` +- shaded version of the driver (`com.arangodb:arangodb-java-driver-shaded`) ### Fixed @@ -72,9 +59,30 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) a - ability to control whether `null` values are included in the serialization (#389) - added support to `DocumentCreateOptions#keepNull` (#374) - allow specifying the return type on insertDocuments (#373) -- removed credentials logging (#410) +- credentials logging (#410) + +### Removed + +- removed user data custom serializer API based on `ArangoSerialization` (in favor of `ArangoSerde`) +- removed user data custom serializer implementation `ArangoJack` (in favor of `JacksonSerde`) +- removed support for interpreting raw strings as JSON (in favor of `RawJson`) +- removed support of data type `VPackSlice` (in favor of Jackson types: `JsonNode`, `ArrayNode`, `ObjectNode`, ...) +- removed client APIs already deprecated in Java Driver version `6` +- removed deprecated server APIs: + - `MMFiles` related APIs + - `ArangoDatabase.executeTraversal()` + - `ArangoDB.getLogs()` + - `minReplicationFactor` in collections and graphs + - `overwrite` flag in `DocumentCreateOptions` +- removed `ArangoCursorInitializer` + +## [6.20.0] - 2022-11-29 + +- ArangoSearch cache (#472) +- support for `enterprise-hex-smart-vertex` shardingStrategy +- deprecated `com.arangodb.Function` -## [6.19.0] +## [6.19.0] - 2022-10-04 - added support for `search-alias` views (ArangoDB 3.10 #461) - added support for nested search (ArangoDB 3.10, #460) @@ -90,6 +98,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) a - deprecated fulltext indexes (ArangoDB 3.10, #454) - fixed `ConsolidationPolicy` API - deprecated MMFiles collection attributes (#442) +- deprecated for removal `ArangoCursorInitializer` and `GraphDocumentReadOptions#isCatchException()` - documented thead safe classes (#445) ## [6.18.0] - 2022-06-07 diff --git a/docs/v7_detailed_changes.md b/docs/v7_detailed_changes.md index f63fc6578..d31886ef1 100644 --- a/docs/v7_detailed_changes.md +++ b/docs/v7_detailed_changes.md @@ -1,9 +1,12 @@ # Version 7.0: detailed changes + ## HTTP client -The HTTP client has been changed to Vert.x WebClient. `HTTP/2` is now supported. `HTTP/2` supports multiplexing and uses -`1` connection per host by default. +The HTTP client has been changed to Vert.x WebClient. + +`HTTP/2` is now supported. `HTTP/2` supports multiplexing and uses `1` connection per host by default. + ## Configuration changes @@ -12,11 +15,35 @@ The default communication protocol is now `HTTP2_JSON` (`HTTP/2` with `JSON` con The default host configuration to `127.0.0.1:8529` has been removed. Configuration properties are not read automatically from properties files anymore. +A new API for loading properties has been introduced: `ArangoDB.Builder.loadProperties(ConfigPropertiesProvider)`. +Implementations could supply configuration properties coming from different sources, eg. system properties, remote +stores, frameworks facilities, etc. +An implementation for loading properties from local files is provided by `FileConfigPropertiesProvider`. + +Here is an example to read config properties from `arangodb.properties` file (same behavior as in version `6`): + +```java +ArangoDB adb = new ArangoDB.Builder() + .loadProperties(new FileConfigPropertiesProvider()) + // ... + .build(); +``` + +Here is an example to read config properties from `arangodb-with-prefix.properties` file, where the config properties +are prefixed with `adb`: + +```java +// arangodb-with-prefix.properties content: +// +// adb.hosts=172.28.0.1:8529 +// adb.acquireHostList=true +// ... + +ArangoDB adb = new ArangoDB.Builder() + .loadProperties(new FileConfigPropertiesProvider("adb", "arangodb-with-prefix.properties")) + .build(); +``` -A new configuration option for loading properties has been -introduced: `ArangoDB.Builder.loadProperties(ConfigPropertiesProvider)`. Implementations could supply configuration -properties coming from different sources, eg. system properties, remote stores, frameworks facilities, etc. An -implementation for loading properties from local files is provided by `FileConfigPropertiesProvider`. ## Transitive dependencies @@ -30,63 +57,86 @@ on `com.arangodb:jackson-dataformat-velocypack` must be provided. When using protocol `HTTP_JSON` or `HTTP2_JSON` (default), no dependencies on `VPACK` libraries are required. -Transitive dependencies on Jackson Core, Databind and Annotations have been added, using by default version `2.13`. +Transitive dependencies on Jackson Core, Databind and Annotations have been added, using by default version `2.14`. The versions of such libraries can be overridden, the driver is compatible with Jackson versions: `2.10`, `2.11`, `2.12` -, `2.13`. +, `2.13`, `2.14`. + +If these dependency requirements cannot be satisfied, you might need to use the [shaded version](#arangodb-java-driver-shaded) of this driver. + ## User Data Types Before version `7.0` the driver always parsed raw strings as JSON, but unfortunately this does not allow distinguishing the case when the intent is to use the raw string as such, without parsing it. Since version `7.0`, strings are not -interpreted as JSON anymore. To represent user data as raw JSON, the wrapper class `RawJson` has been added. +interpreted as JSON anymore. To represent user data as raw JSON, the wrapper class `RawJson` has been added: + +```java +RawJson rawJsonIn = RawJson.of(""" + {"foo":"bar"} + """); +ArangoCursor res = adb.db().query("RETURN @v", Map.of("v", rawJsonIn), RawJson.class); +RawJson rawJsonOut = res.next(); +String json = rawJsonOut.getValue(); // {"foo":"bar"} +``` To represent user data already encoded as byte array, the wrapper class `RawBytes` has been added. -The byte array can either represent a `JSON` string (UTF-8 encoded) or a `VPACK` value, but the encoding must be the +The byte array can either represent a `JSON` string (UTF-8 encoded) or a `VPACK` value, but the format must be the same used for the driver protocol configuration (`JSON` for `HTTP_JSON` and `HTTP2_JSON`, `VPACK` otherwise). -`BaseDocument` and `BaseEdgeDocument` are now `final`, they have a new method `removeAttribute(String)` -and `getProperties()` returns now an unmodifiable map. +The following changes have been applied to `BaseDocument` and `BaseEdgeDocument`: +- `final` classes +- not serializable anymore (Java serialization) +- new method `removeAttribute(String)` +- `getProperties()` returns an unmodifiable map -Before version `7.0` when performing write operations, the metadata of the input data objects was updated with the -metadata received in the response. Since version `7.0`, the input data objects passed as arguments to API methods are -treated as immutable and the related metadata fields are not updated anymore. The updated metadata can still be found in -the object returned by the API method. +Before version `7.0` when performing write operations, the metadata of the input data objects was updated in place with +the metadata received in the response. +Since version `7.0`, the input data objects passed as arguments to API methods are treated as immutable and the related +metadata fields are not updated anymore. The updated metadata can be found in the returned object. -## Serialization -The serialization module has been changed and is now based on the Jackson API. +## Serialization -Up to version 6, the (de)serialization was always performed to/from `VPACK`. In case the JSON representation was +Up to version 6, the (de)serialization was always performed to/from `VPACK`. In case the JSON format was required, the raw `VPACK` was then converted to `JSON`. Since version 7, the serialization module is a dataformat -agnostic API, based on the Jackson API. By default, it reads and writes `JSON` format. `VPACK` support is provided by -the optional dependency `com.arangodb:jackson-dataformat-velocypack`, which is a dataformat backend implementation for -Jackson. - -The (de)serialization of user data can be customized by registering an implementation of `ArangoSerde` -via `ArangoDB.Builder#serializer()`. The default user data serializer is `JacksonSerde`, which is based on Jackson API -and is available for both `JSON` and `VPACK`. It (de)serializes user data using Jackson Databind and can handle Jackson -Annotations. It can be customized through `JacksonSerde#configure(Consumer)`, i.e. registering Kotlin or -Scala modules. Furthermore, meta binding annotations (`@Id`, `@Key`, `@Rev`, `@From`, `@To`) are supported for mapping -documents and edges metadata fields (`_id`, `_key`, `_rev`, `_from`, `_to`). - -`ArangoSerde` interface is not constrained to Jackson. It is instead an abstract API that can be implemented using any -custom serialization library, e.g. an example of `JSON-B` implementation can be found in -the [tests](../src/test/java/com/arangodb/serde/JsonbSerdeImpl.java). - -Independently of the user data serializer, the following data types are (de)serialized with specific handlers (not -customizable): - -- `JsonNode` and its children (`ArrayNode`, `ObjectNode`, ...) -- `RawJson` -- `RawBytes` -- `BaseDocument` -- `BaseEdgeDocument` +agnostic API, by default using `JSON` format. + +Support of data type `VPackSlice` has been removed (in favor of Jackson types: `JsonNode`, `ArrayNode`, `ObjectNode`, +...), for example: + +```java +JsonNode jsonNodeIn = JsonNodeFactory.instance.objectNode() + .put("foo", "bar"); + +ArangoCursor res = adb.db().query("RETURN @v", Map.of("v", jsonNodeIn), JsonNode.class); +JsonNode jsonNodeOut = res.next(); +String foo = jsonNodeOut.get("foo").textValue(); // bar +``` + +The dependency on `com.arangodb:velocypack` has been removed. + +The user data custom serializer implementation `ArangoJack` has been removed in favor of `JacksonSerde`. + +Updated reference documentation can be found [here](v7_java-reference-serialization.md). + + +## ArangoDB Java Driver Shaded + +Since version `7`, a shaded variant of the driver is also published with maven coordinates: +`com.arangodb:arangodb-java-driver-shaded`. + +It bundles and relocates the following packages from transitive dependencies: +- `com.fasterxml.jackson` +- `com.arangodb.jackson.dataformat.velocypack` +- `io.vertx` +- `io.netty` + ## Removed APIs The following client APIs have been removed: -- client APIs already deprecated in Java Driver version `6.19.0` +- client APIs already deprecated in Java Driver version `6` - client API to interact with deprecated server APIs: - `MMFiles` related APIs - `ArangoDatabase.executeTraversal()` @@ -104,6 +154,7 @@ Support of data type `VPackSlice` has been removed (in favor of Jackson types: ` Support for custom initialization of cursors (`ArangoDB._setCursorInitializer(ArangoCursorInitializer cursorInitializer)`) has been removed. + ## API methods changes Before version `7.0` some CRUD API methods inferred the return type from the type of the data object passed as input. @@ -114,24 +165,25 @@ and `RawJson`) containing multiple documents. `ArangoCursor#getStats()` returns now an untyped map. -`Request` and `Response` classes have been refactored to support generic body -type. `ArangoDB.execute(Request, Class): Response` accepts now the target deserialization type for the response -body. +`Request` and `Response` classes have been refactored to support generic body type. +`ArangoDB.execute(Request, Class): Response` accepts now the target deserialization type for the response body. `ArangoDBException` has been enhanced with the id of the request causing it. + ## API entities -All entities and options classes are now `final`. +All entities and options classes (in packages `com.arangodb.model` and `com.arangodb.entity`) are now `final`. The replication factor is now modeled with a new interface (`ReplicationFactor`) with implementations: `NumericReplicationFactor` and `SatelliteReplicationFactor`. + ## Migration -To migrate your existing project to Java Driver version `7.0`, it is recommended updating to version `6.19` first and -make sure that your code does not use any deprecated API. This can be done by checking the presence of deprecation -warnings in the Java compiler output. +To migrate your existing project to Java Driver version `7.0`, it is recommended updating to the latest version of +branch `6` and make sure that your code does not use any deprecated API. +This can be done by checking the presence of deprecation warnings in the Java compiler output. The deprecation notes in the related javadoc contain information about the reason of the deprecation and suggest migration alternatives to use. diff --git a/docs/v7_java-reference-serialization.md b/docs/v7_java-reference-serialization.md new file mode 100644 index 000000000..a2459abca --- /dev/null +++ b/docs/v7_java-reference-serialization.md @@ -0,0 +1,233 @@ +# Serialization + +The driver functionalities related to serialization and deserialization (serde) are provided by 2 different components: +- internal serde +- user-data serde + +The **internal serde** is based on [Jackson](https://github.com/FasterXML/jackson) API and is responsible for serializing/deserializing data definition classes (in +packages `com.arangodb.model` and `com.arangodb.entity`). +This includes all the information that is not domain user data, such as configuration properties, definitions metadata +for databases, collections, graphs, ... + +Furthermore, it is used to serialize and deserialize user data of the following types: +- `JsonNode` and its children (`ArrayNode`, `ObjectNode`, ...) +- `RawJson` +- `RawBytes` +- `BaseDocument` +- `BaseEdgeDocument` + + +The **user-data serde** is used to serialize and deserialize the user data, namely the data payloads related to: +- documents +- vertexes +- edges +- AQL bind variables +- transactions parameters +- custom requests and responses (`Request` and `Response` payloads) + +User-data serde implementations must implement the `ArangoSerde` interface, which is an abstract API with no +dependencies on specific libraries. +Custom implementations can be registered via `ArangoDB.Builder#serde(ArangoSerde)`. +For example, you can find [here](../jsonb-serde/src/main/java/com/arangodb/serde/jsonb) an implementation of +`ArangoSerde` based on `JSON-B` (supporting `JSON` format only). + + +## JacksonSerde (default user-data serde) + +The default user-data serde is `JacksonSerde`, which is provided by the module `com.arangodb:jackson-serde`. +This is used by default from the driver, if no custom serde is registered explicitly. +It is implemented delegating [Jackson](https://github.com/FasterXML/jackson) `ObjectMapper`, therefore it is compatible +with Jackson Streaming, Data Binding and Tree Model API. +It supports both `JSON` and `VPACK` data formats. To use `VPACK`, the optional dependency on +[jackson-dataformat-velocypack](https://github.com/arangodb/jackson-dataformat-velocypack) is required. + + +### Configure + +Create an instance of `JacksonSerde`, configure the underlying `ObjectMapper` and pass it to the driver: + +```java +JacksonSerde serde = new JacksonSerdeProvider().of(ContentType.JSON); +serde.configure((ObjectMapper mapper) -> { + // ... +}); + +ArangoDB adb = new ArangoDB.Builder() + .serde(serde) + // ... + .build(); +``` + +See also [Jackson Databind](https://github.com/FasterXML/jackson-databind/wiki/JacksonFeatures) configurable features. + + +### Mapping API + +The library is fully compatible with [Jackson Databind](https://github.com/FasterXML/jackson-databind) +API. To customize the serialization and deserialization behavior using the +Jackson Data Binding API, entities can be annotated with +[Jackson Annotations](https://github.com/FasterXML/jackson-annotations). +For more advanced customizations refer to [Custom serializer](#custom-serializer) section. + + +### Renaming Properties + +To use a different serialized name for a field, use the annotation `@JsonProperty`. + +```java +public class MyObject { + @JsonProperty("title") + private String name; +} +``` + +### Ignoring properties + +To ignore fields use the annotation `@JsonIgnore`. + +```java +public class Value { + @JsonIgnore + public int internalValue; +} +``` + +### Custom serializers + +The serialization and deserialization can be customized using the lower level +Streaming API or the Tree Model API, creating and registering respectively +`JsonSerializer` and `JsonDeserializer`, as specified by the Jackson API +for [CustomSerializers](https://github.com/FasterXML/jackson-docs/wiki/JacksonHowToCustomSerializers). + +```java +static class PersonSerializer extends JsonSerializer { + @Override + public void serialize(Person value, JsonGenerator gen, SerializerProvider serializers) throws IOException { + // example using the Streaming API + gen.writeStartObject(); + gen.writeFieldName("name"); + gen.writeString(value.name); + gen.writeEndObject(); + } +} + +static class PersonDeserializer extends JsonDeserializer { + @Override + public Person deserialize(JsonParser parser, DeserializationContext ctxt) throws IOException { + // example using the Tree Model API + Person person = new Person(); + JsonNode rootNode = parser.getCodec().readTree(parser); + JsonNode nameNode = rootNode.get("name"); + if (nameNode != null && nameNode.isTextual()) { + person.name = nameNode.asText(); + } + return person; + } +} + +// registering using annotation +@JsonSerialize(using = PersonSerializer.class) +public static class Person { + public String name; +} + +// registering programmatically +JacksonSerde serde = new JacksonSerdeProvider().of(ContentType.JSON); +serde.configure(mapper -> { + SimpleModule module = new SimpleModule("PersonModule"); + module.addDeserializer(Person.class, new PersonDeserializer()); + mapper.registerModule(module); +}); + +ArangoDB adb = new ArangoDB.Builder() + .serde(serde) + // ... + .build(); +``` + +### Jackson datatype and language modules + +The `JacksonSerde` can be configured +with [Jackson datatype modules](https://github.com/FasterXML/jackson#third-party-datatype-modules) +as well as [Jackson JVM Language modules](https://github.com/FasterXML/jackson#jvm-language-modules). + +### Kotlin + +[Kotlin language module](https://github.com/FasterXML/jackson-module-kotlin) +enables support for Kotlin native types and can be registered in the following way: + +```kotlin +val arangoDB = ArangoDB.Builder() + .serde(JacksonSerdeProvider().of(ContentType.JSON).apply { + configure { it.registerModule(KotlinModule()) } + }) + .build() +``` + +### Scala + +[Scala language module](https://github.com/FasterXML/jackson-module-scala) +enables support for Scala native types and can be registered in the following way: + +```scala +val serde = JacksonSerdeProvider().of(ContentType.JSON) +serde.configure(mapper => mapper.registerModule(DefaultScalaModule)) + +val arangoDB = new ArangoDB.Builder() + .serde(arangoJack) + .build() +``` + +### Java 8 types + +Support for Java 8 features is offered by +[jackson-modules-java8](https://github.com/FasterXML/jackson-modules-java8). + +### Joda types + +Support for Joda data types, such as DateTime, is offered by +[jackson-datatype-joda](https://github.com/FasterXML/jackson-datatype-joda). + +### Metadata fields + +Metadata fields `_id`, `_key`, `_rev`, `_from`, `_to` can be mapped using respectively the annotations: +`@Id`, `@Key`, `@Rev`, `@From`, `@To`. + +```java +public class MyObject { + + @Key + private String key; + + // ... +} +``` + + +## Dependency convergence + +The driver and the `jackson-serde` module depend on `jackson-core`, `jackson-databind` and `jackson-annotations` +packages. +You might need to include [jackson-bom](https://github.com/FasterXML/jackson-bom) +to ensure dependency convergence across the entire project, for example in case +there are in your project other libraries depending on different versions of +the same Jackson packages. + +```xml + + + + com.fasterxml.jackson + jackson-bom + ... + import + pom + + + +``` + +The driver and the `JacksonSerde` are compatible with Jackson 2.10, 2.11, 2.12, 2.13 and 2.14. + +If these dependency requirements cannot be satisfied, you might need to use the +[shaded version](v7_detailed_changes.md#arangodb-java-driver-shaded) of the driver. diff --git a/driver/src/test/java/com/arangodb/ArangoDBTest.java b/driver/src/test/java/com/arangodb/ArangoDBTest.java index eb92489b0..fc7f6a35c 100644 --- a/driver/src/test/java/com/arangodb/ArangoDBTest.java +++ b/driver/src/test/java/com/arangodb/ArangoDBTest.java @@ -599,11 +599,21 @@ void fallbackHost() { @MethodSource("arangos") void loadproperties() { Throwable thrown = catchThrowable(() -> new ArangoDB.Builder() - .loadProperties(new FileConfigPropertiesProvider("arangodb", "/arangodb-bad.properties")) + .loadProperties(new FileConfigPropertiesProvider("arangodb", "arangodb-bad.properties")) ); assertThat(thrown).isInstanceOf(ArangoDBException.class); } + @ParameterizedTest(name = "{index}") + @MethodSource("arangos") + void loadpropertiesWithPrefix() { + ArangoDB adb = new ArangoDB.Builder() + .loadProperties(new FileConfigPropertiesProvider("adb", "arangodb-with-prefix.properties")) + .build(); + adb.getVersion(); + adb.shutdown(); + } + @ParameterizedTest(name = "{index}") @MethodSource("arangos") void accessMultipleDatabases(ArangoDB arangoDB) { diff --git a/driver/src/test/resources/arangodb-with-prefix.properties b/driver/src/test/resources/arangodb-with-prefix.properties new file mode 100644 index 000000000..36fb2d0a5 --- /dev/null +++ b/driver/src/test/resources/arangodb-with-prefix.properties @@ -0,0 +1,3 @@ +adb.hosts=172.28.0.1:8529 +adb.acquireHostList=true +adb.password=test From bc1de3df6f3f7dfb0170fb4ccddd36140d28074f Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Thu, 22 Dec 2022 22:15:01 +0100 Subject: [PATCH 224/254] fixed shaded javadoc --- driver/pom.xml | 9 --------- pom.xml | 9 +++++++++ shaded/pom.xml | 41 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 50 insertions(+), 9 deletions(-) diff --git a/driver/pom.xml b/driver/pom.xml index c5c66e384..dea7f553a 100644 --- a/driver/pom.xml +++ b/driver/pom.xml @@ -22,15 +22,6 @@ - - doclint-java8-disable - - [1.8,) - - - none - - no-graalvm diff --git a/pom.xml b/pom.xml index 044388ee9..e85082048 100644 --- a/pom.xml +++ b/pom.xml @@ -377,6 +377,15 @@ jsonb-serde + + doclint-java8-disable + + [1.8,) + + + none + + native diff --git a/shaded/pom.xml b/shaded/pom.xml index 0d9e3e9e0..59e786792 100644 --- a/shaded/pom.xml +++ b/shaded/pom.xml @@ -130,6 +130,47 @@ + + org.apache.maven.plugins + maven-dependency-plugin + 3.4.0 + + + unpack-shaded-sources + package + + unpack + + + + + com.arangodb + arangodb-java-driver-shaded + jar + sources + ${project.build.directory}/shaded-sources + + + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + + + attach-javadocs + + jar + + + ${project.build.directory}/shaded-sources + com.arangodb.shaded.**,**.internal** + + + + org.codehaus.mojo flatten-maven-plugin From 6b29cb734f644a926f0a2d2045dac7fd13be2b8b Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Thu, 22 Dec 2022 23:06:36 +0100 Subject: [PATCH 225/254] fixed PackageVersionTest --- driver/src/test/java/com/arangodb/PackageVersionTest.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/driver/src/test/java/com/arangodb/PackageVersionTest.java b/driver/src/test/java/com/arangodb/PackageVersionTest.java index 85a082088..f680486ad 100644 --- a/driver/src/test/java/com/arangodb/PackageVersionTest.java +++ b/driver/src/test/java/com/arangodb/PackageVersionTest.java @@ -5,6 +5,9 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.EnumSource; + +import static ru.lanwen.verbalregex.VerbalExpression.regex; + import ru.lanwen.verbalregex.VerbalExpression; import static org.assertj.core.api.Assertions.assertThat; @@ -14,7 +17,7 @@ class PackageVersionTest extends BaseJunit5 { @Test void packageVersion() { - VerbalExpression testRegex = VerbalExpression.regex() + VerbalExpression testRegex = regex() .startOfLine() // major .digit().atLeast(1) @@ -24,7 +27,7 @@ void packageVersion() { .then(".") // patch .digit().atLeast(1) - .maybe("-SNAPSHOT") + .maybe(regex().anything()) .endOfLine() .build(); assertThat(PackageVersion.VERSION).matches(testRegex.toString()); From da6c95540c534d3110faf368d754b0a0241b4c5a Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Thu, 22 Dec 2022 23:39:44 +0100 Subject: [PATCH 226/254] doc: mvn setup --- docs/v7_detailed_changes.md | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/docs/v7_detailed_changes.md b/docs/v7_detailed_changes.md index d31886ef1..14a2830f8 100644 --- a/docs/v7_detailed_changes.md +++ b/docs/v7_detailed_changes.md @@ -1,5 +1,32 @@ # Version 7.0: detailed changes +## Maven Setup + +In your `pom.xml`, set the snapshots repository: + +``` + + + snapshots + https://oss.sonatype.org/content/repositories/snapshots + + true + + + +``` + +and include the dependency: + +``` + + + com.arangodb + arangodb-java-driver + 7.0.0-SNAPSHOT + + +``` ## HTTP client From 72095dac6bf1d746ce1bb10c46c4f04d0c616b1a Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Tue, 3 Jan 2023 14:48:24 +0100 Subject: [PATCH 227/254] default internal serde --- .../src/main/java/com/arangodb/ArangoDB.java | 3 +- .../com/arangodb/async/ArangoDBAsync.java | 3 +- .../internal/InternalArangoDBBuilder.java | 14 +++++---- .../internal/serde/InternalSerde.java | 10 ------- .../internal/serde/InternalSerdeProvider.java | 30 +++++++++++++++++++ .../java/com/arangodb/serde/SerdeTest.java | 5 ++-- 6 files changed, 46 insertions(+), 19 deletions(-) create mode 100644 driver/src/main/java/com/arangodb/internal/serde/InternalSerdeProvider.java diff --git a/driver/src/main/java/com/arangodb/ArangoDB.java b/driver/src/main/java/com/arangodb/ArangoDB.java index 956583e0a..62ceb1874 100644 --- a/driver/src/main/java/com/arangodb/ArangoDB.java +++ b/driver/src/main/java/com/arangodb/ArangoDB.java @@ -34,6 +34,7 @@ import com.arangodb.internal.net.HostResolver; import com.arangodb.internal.serde.ContentTypeFactory; import com.arangodb.internal.serde.InternalSerde; +import com.arangodb.internal.serde.InternalSerdeProvider; import com.arangodb.internal.velocystream.VstCommunicationSync; import com.arangodb.internal.velocystream.VstConnectionFactorySync; import com.arangodb.model.DBCreateOptions; @@ -587,7 +588,7 @@ public ArangoDB build() { final ArangoSerde userSerde = this.userDataSerde != null ? this.userDataSerde : serdeProvider().of(ContentTypeFactory.of(protocol)); - final InternalSerde serde = InternalSerde.of(ContentTypeFactory.of(protocol), userSerde); + final InternalSerde serde = InternalSerdeProvider.create(ContentTypeFactory.of(protocol), userSerde); int protocolMaxConnections; switch (protocol) { diff --git a/driver/src/main/java/com/arangodb/async/ArangoDBAsync.java b/driver/src/main/java/com/arangodb/async/ArangoDBAsync.java index c6eaf5db4..0f7ff179e 100644 --- a/driver/src/main/java/com/arangodb/async/ArangoDBAsync.java +++ b/driver/src/main/java/com/arangodb/async/ArangoDBAsync.java @@ -32,6 +32,7 @@ import com.arangodb.internal.net.HostHandler; import com.arangodb.internal.net.HostResolver; import com.arangodb.internal.serde.InternalSerde; +import com.arangodb.internal.serde.InternalSerdeProvider; import com.arangodb.internal.velocystream.VstCommunicationSync; import com.arangodb.internal.velocystream.VstConnectionFactorySync; import com.arangodb.model.DBCreateOptions; @@ -516,7 +517,7 @@ public ArangoDBAsync build() { } final ArangoSerde userSerde = this.userDataSerde != null ? this.userDataSerde : serdeProvider().of(ContentType.VPACK); - final InternalSerde serde = InternalSerde.of(ContentType.VPACK, userSerde); + final InternalSerde serde = InternalSerdeProvider.create(ContentType.VPACK, userSerde); final int max = maxConnections != null ? Math.max(1, maxConnections) : ArangoDefaults.MAX_CONNECTIONS_VST_DEFAULT; diff --git a/driver/src/main/java/com/arangodb/internal/InternalArangoDBBuilder.java b/driver/src/main/java/com/arangodb/internal/InternalArangoDBBuilder.java index b3b4eae1e..68022fab6 100644 --- a/driver/src/main/java/com/arangodb/internal/InternalArangoDBBuilder.java +++ b/driver/src/main/java/com/arangodb/internal/InternalArangoDBBuilder.java @@ -25,6 +25,7 @@ import com.arangodb.config.ConfigPropertyKey; import com.arangodb.entity.LoadBalancingStrategy; import com.arangodb.internal.net.*; +import com.arangodb.internal.serde.InternalSerdeProvider; import com.arangodb.internal.util.HostUtils; import com.arangodb.serde.ArangoSerde; import com.arangodb.serde.ArangoSerdeProvider; @@ -147,12 +148,15 @@ protected static String getProperty(ConfigPropertiesProvider props, ConfigProper protected static ArangoSerdeProvider serdeProvider() { ServiceLoader loader = ServiceLoader.load(ArangoSerdeProvider.class); Iterator it = loader.iterator(); + ArangoSerdeProvider serdeProvider; if (!it.hasNext()) { - throw new ArangoDBException("No ArangoSerdeProvider found!"); - } - ArangoSerdeProvider serdeProvider = it.next(); - if (it.hasNext()) { - throw new ArangoDBException("Found multiple serde providers! Please set explicitly the one to use."); + LOG.info("No ArangoSerdeProvider found, using InternalSerdeProvider."); + serdeProvider = new InternalSerdeProvider(); + } else { + serdeProvider = it.next(); + if (it.hasNext()) { + throw new ArangoDBException("Found multiple serde providers! Please set explicitly the one to use."); + } } return serdeProvider; } diff --git a/driver/src/main/java/com/arangodb/internal/serde/InternalSerde.java b/driver/src/main/java/com/arangodb/internal/serde/InternalSerde.java index b6d6a8dfd..97e7f2333 100644 --- a/driver/src/main/java/com/arangodb/internal/serde/InternalSerde.java +++ b/driver/src/main/java/com/arangodb/internal/serde/InternalSerde.java @@ -9,16 +9,6 @@ public interface InternalSerde extends ArangoSerde { - /** - * Creates a new InternalSerde with default settings for the specified data type. - * - * @param contentType serialization target data type - * @return the created InternalSerde - */ - static InternalSerde of(final ContentType contentType, ArangoSerde userSerde) { - return new InternalSerdeImpl(InternalMapperProvider.of(contentType), userSerde); - } - /** * Used for logging and debugging. * diff --git a/driver/src/main/java/com/arangodb/internal/serde/InternalSerdeProvider.java b/driver/src/main/java/com/arangodb/internal/serde/InternalSerdeProvider.java new file mode 100644 index 000000000..9136d6a68 --- /dev/null +++ b/driver/src/main/java/com/arangodb/internal/serde/InternalSerdeProvider.java @@ -0,0 +1,30 @@ +package com.arangodb.internal.serde; + +import com.arangodb.ContentType; +import com.arangodb.serde.ArangoSerde; +import com.arangodb.serde.ArangoSerdeProvider; + +public class InternalSerdeProvider implements ArangoSerdeProvider { + + /** + * Creates a new InternalSerde with default settings for the specified data type. + * + * @param contentType serialization target data type + * @return the created InternalSerde + */ + @Override + public InternalSerde of(final ContentType contentType) { + return create(contentType, null); + } + + /** + * Creates a new InternalSerde with default settings for the specified data type. + * + * @param contentType serialization target data type + * @return the created InternalSerde + */ + public static InternalSerde create(final ContentType contentType, ArangoSerde userSerde) { + return new InternalSerdeImpl(InternalMapperProvider.of(contentType), userSerde); + } + +} diff --git a/driver/src/test/java/com/arangodb/serde/SerdeTest.java b/driver/src/test/java/com/arangodb/serde/SerdeTest.java index 35605178f..d99b7e0a6 100644 --- a/driver/src/test/java/com/arangodb/serde/SerdeTest.java +++ b/driver/src/test/java/com/arangodb/serde/SerdeTest.java @@ -2,6 +2,7 @@ import com.arangodb.ContentType; import com.arangodb.internal.serde.InternalSerde; +import com.arangodb.internal.serde.InternalSerdeProvider; import com.arangodb.internal.serde.SerdeUtils; import com.arangodb.util.RawBytes; import com.arangodb.util.RawJson; @@ -18,7 +19,7 @@ class SerdeTest { @ParameterizedTest @EnumSource(ContentType.class) void rawJsonSerde(ContentType type) { - InternalSerde s = InternalSerde.of(type, null); + InternalSerde s = new InternalSerdeProvider().of(type); ObjectNode node = JsonNodeFactory.instance.objectNode().put("foo", "bar"); RawJson raw = RawJson.of(SerdeUtils.INSTANCE.writeJson(node)); byte[] serialized = s.serialize(raw); @@ -29,7 +30,7 @@ void rawJsonSerde(ContentType type) { @ParameterizedTest @EnumSource(ContentType.class) void rawBytesSerde(ContentType type) { - InternalSerde s = InternalSerde.of(type, null); + InternalSerde s = new InternalSerdeProvider().of(type); ObjectNode node = JsonNodeFactory.instance.objectNode().put("foo", "bar"); RawBytes raw = RawBytes.of(s.serialize(node)); byte[] serialized = s.serialize(raw); From 7376e477ad478704b5ab56923a9814f560a94c95 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Tue, 3 Jan 2023 14:49:04 +0100 Subject: [PATCH 228/254] rm jackson-serde from shaded driver deps --- .github/workflows/maven.yml | 7 +- shaded-integration-tests/pom.xml | 38 +++++++++-- .../src/test/internal/java/arch/AdbTest.java | 18 +++++ .../src/test/internal/java/arch/BaseTest.java | 49 ++++++++++++++ .../src/test/internal/java/arch/Person.java | 13 ++++ .../internal/java/arch/RelocationsTest.java | 56 ++++++++++++++++ .../test/internal/java/arch/SerdeTest.java | 65 +++++++++++++++++++ shaded/pom.xml | 9 ++- 8 files changed, 242 insertions(+), 13 deletions(-) create mode 100644 shaded-integration-tests/src/test/internal/java/arch/AdbTest.java create mode 100644 shaded-integration-tests/src/test/internal/java/arch/BaseTest.java create mode 100644 shaded-integration-tests/src/test/internal/java/arch/Person.java create mode 100644 shaded-integration-tests/src/test/internal/java/arch/RelocationsTest.java create mode 100644 shaded-integration-tests/src/test/internal/java/arch/SerdeTest.java diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index 564cc8cd0..97cceed89 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -242,12 +242,15 @@ jobs: run: mvn -version - name: Install run: mvn --no-transfer-progress install -DskipTests=true -Dgpg.skip=true -Dmaven.javadoc.skip=true + - name: Test internal-serde + working-directory: shaded-integration-tests + run: mvn --no-transfer-progress -Pinternal-serde test - name: Test jackson-serde working-directory: shaded-integration-tests - run: mvn --no-transfer-progress -P jackson-serde test + run: mvn --no-transfer-progress -Pjackson-serde test - name: Test jsonb-serde working-directory: shaded-integration-tests - run: mvn --no-transfer-progress -P jsonb-serde test + run: mvn --no-transfer-progress -Pjsonb-serde test sonar: timeout-minutes: 10 diff --git a/shaded-integration-tests/pom.xml b/shaded-integration-tests/pom.xml index d436669a3..d8195d15b 100644 --- a/shaded-integration-tests/pom.xml +++ b/shaded-integration-tests/pom.xml @@ -33,6 +33,33 @@ + + internal-serde + + true + + + src/test/internal/java + jackson + + + + com.arangodb + arangodb-java-driver-shaded + test + + + com.arangodb + jackson-dataformat-velocypack + test + + + com.tngtech.archunit + archunit-junit5 + test + + + jackson-serde @@ -48,6 +75,11 @@ arangodb-java-driver-shaded test + + com.arangodb + jackson-serde + test + com.arangodb jackson-dataformat-velocypack @@ -71,12 +103,6 @@ com.arangodb arangodb-java-driver-shaded test - - - com.arangodb - jackson-serde - - com.arangodb diff --git a/shaded-integration-tests/src/test/internal/java/arch/AdbTest.java b/shaded-integration-tests/src/test/internal/java/arch/AdbTest.java new file mode 100644 index 000000000..fc320db4e --- /dev/null +++ b/shaded-integration-tests/src/test/internal/java/arch/AdbTest.java @@ -0,0 +1,18 @@ +package arch; + +import com.arangodb.ArangoDB; +import com.arangodb.entity.ArangoDBVersion; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + +import static org.assertj.core.api.Assertions.assertThat; + +class AdbTest extends BaseTest { + @ParameterizedTest + @MethodSource("adbByProtocol") + void getVersion(ArangoDB adb) { + final ArangoDBVersion version = adb.getVersion(); + assertThat(version.getServer()).isNotNull(); + assertThat(version.getVersion()).isNotNull(); + } +} diff --git a/shaded-integration-tests/src/test/internal/java/arch/BaseTest.java b/shaded-integration-tests/src/test/internal/java/arch/BaseTest.java new file mode 100644 index 000000000..1833d3521 --- /dev/null +++ b/shaded-integration-tests/src/test/internal/java/arch/BaseTest.java @@ -0,0 +1,49 @@ +package arch; + +import com.arangodb.ArangoDB; +import com.arangodb.ContentType; +import com.arangodb.DbName; +import com.arangodb.Protocol; +import com.arangodb.internal.config.FileConfigPropertiesProvider; +import org.junit.jupiter.params.provider.Arguments; + +import java.util.Arrays; +import java.util.stream.Stream; + +public class BaseTest { + protected static final DbName TEST_DB = DbName.of("java_driver_integration_tests"); + + protected static ArangoDB createAdb() { + return new ArangoDB.Builder() + .loadProperties(new FileConfigPropertiesProvider()) + .build(); + } + + protected static ArangoDB createAdb(ContentType contentType) { + Protocol protocol = contentType == ContentType.VPACK ? Protocol.HTTP2_VPACK : Protocol.HTTP2_JSON; + return new ArangoDB.Builder() + .loadProperties(new FileConfigPropertiesProvider()) + .useProtocol(protocol) + .build(); + } + + protected static ArangoDB createAdb(Protocol protocol) { + return new ArangoDB.Builder() + .loadProperties(new FileConfigPropertiesProvider()) + .useProtocol(protocol) + .build(); + } + + protected static Stream adbByProtocol() { + return Arrays.stream(Protocol.values()) + .map(BaseTest::createAdb) + .map(Arguments::of); + } + + protected static Stream adbByContentType() { + return Arrays.stream(ContentType.values()) + .map(BaseTest::createAdb) + .map(Arguments::of); + } + +} diff --git a/shaded-integration-tests/src/test/internal/java/arch/Person.java b/shaded-integration-tests/src/test/internal/java/arch/Person.java new file mode 100644 index 000000000..3dc3cd7f2 --- /dev/null +++ b/shaded-integration-tests/src/test/internal/java/arch/Person.java @@ -0,0 +1,13 @@ +package arch; + + +import com.arangodb.shaded.fasterxml.jackson.annotation.JsonProperty; + +public record Person( + @JsonProperty("_key") + String key, + @JsonProperty("firstName") + String name, + int age +) { +} diff --git a/shaded-integration-tests/src/test/internal/java/arch/RelocationsTest.java b/shaded-integration-tests/src/test/internal/java/arch/RelocationsTest.java new file mode 100644 index 000000000..761556d78 --- /dev/null +++ b/shaded-integration-tests/src/test/internal/java/arch/RelocationsTest.java @@ -0,0 +1,56 @@ +package arch; + +import com.tngtech.archunit.core.importer.ImportOption.DoNotIncludeTests; +import com.tngtech.archunit.junit.AnalyzeClasses; +import com.tngtech.archunit.junit.ArchTest; +import com.tngtech.archunit.lang.ArchRule; + +import static com.tngtech.archunit.lang.syntax.ArchRuleDefinition.noClasses; + + +@AnalyzeClasses(packages = "com.arangodb..", importOptions = {DoNotIncludeTests.class}) +public class RelocationsTest { + + @ArchTest + public static final ArchRule nettyRelocation = noClasses().that() + .resideInAPackage("com.arangodb..") + .should().dependOnClassesThat() + .resideInAPackage("io.netty.."); + + @ArchTest + public static final ArchRule vertxRelocation = noClasses().that() + .resideInAPackage("com.arangodb..") + .should().dependOnClassesThat() + .resideInAPackage("io.vertx.."); + + @ArchTest + public static final ArchRule jacksonRelocation = noClasses().that() + .resideInAPackage("com.arangodb..").and() + .resideOutsideOfPackage("com.arangodb.jackson.dataformat.velocypack..").and() + .resideOutsideOfPackage("com.arangodb.serde.jackson..") + .should().dependOnClassesThat() + .resideInAPackage("com.fasterxml.jackson.."); + + @ArchTest + public static final ArchRule jacksonDataformatVelocypackRelocation = noClasses().that() + .resideInAPackage("com.arangodb..").and() + .resideOutsideOfPackage("com.arangodb.jackson.dataformat.velocypack..").and() + .resideOutsideOfPackage("com.arangodb.serde.jackson..") + .should().dependOnClassesThat() + .resideInAPackage("com.arangodb.jackson.dataformat.velocypack.."); + + @ArchTest + public static final ArchRule noJsonbDependency = noClasses().that() + .resideInAPackage("com.arangodb..") + .should().dependOnClassesThat() + .resideInAPackage("com.arangodb.serde.jsonb.."); + + @ArchTest + // jackson-serde is accessed via SPI + public static final ArchRule noExplicitDependencyOnJacksonSerde = noClasses().that() + .resideInAPackage("com.arangodb..").and() + .resideOutsideOfPackage("com.arangodb.serde.jackson..") + .should().dependOnClassesThat() + .resideInAPackage("com.arangodb.serde.jackson.."); + +} diff --git a/shaded-integration-tests/src/test/internal/java/arch/SerdeTest.java b/shaded-integration-tests/src/test/internal/java/arch/SerdeTest.java new file mode 100644 index 000000000..6b03aa7df --- /dev/null +++ b/shaded-integration-tests/src/test/internal/java/arch/SerdeTest.java @@ -0,0 +1,65 @@ +package arch; + +import com.arangodb.ArangoDB; +import com.arangodb.shaded.fasterxml.jackson.databind.JsonNode; +import com.arangodb.shaded.fasterxml.jackson.databind.node.JsonNodeFactory; +import com.arangodb.util.RawJson; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + +import java.util.Collections; +import java.util.Map; + +import static org.assertj.core.api.Assertions.assertThat; + +class SerdeTest extends BaseTest { + + @ParameterizedTest + @MethodSource("adbByContentType") + void shadedJsonNode(ArangoDB adb) { + // uses the internal serde + JsonNode doc = JsonNodeFactory.instance + .objectNode() + .put("foo", "bar"); + JsonNode res = adb.db().query("return @d", Collections.singletonMap("d", doc), JsonNode.class).next(); + assertThat(res.size()).isEqualTo(1); + assertThat(res.get("foo").asText()).isEqualTo("bar"); + JsonNode value = adb.db().query("return @d.foo", Collections.singletonMap("d", doc), JsonNode.class).next(); + assertThat(value.textValue()).isEqualTo("bar"); + } + + @ParameterizedTest + @MethodSource("adbByContentType") + void map(ArangoDB adb) { + Map doc = Collections.singletonMap("foo", "bar"); + Map res = adb.db().query("return @d", Collections.singletonMap("d", doc), Map.class).next(); + assertThat(res).hasSize(1); + assertThat(res.get("foo")).isEqualTo("bar"); + String value = adb.db().query("return @d.foo", Collections.singletonMap("d", doc), String.class).next(); + assertThat(value).isEqualTo("bar"); + } + + @ParameterizedTest + @MethodSource("adbByContentType") + void rawJson(ArangoDB adb) { + RawJson doc = RawJson.of(""" + {"foo":"bar"}"""); + RawJson res = adb.db().query("return @d", Collections.singletonMap("d", doc), RawJson.class).next(); + assertThat(res.getValue()).isEqualTo(doc.getValue()); + RawJson value = adb.db().query("return @d.foo", Collections.singletonMap("d", doc), RawJson.class).next(); + assertThat(value.getValue()).isEqualTo("\"bar\""); + } + + @ParameterizedTest + @MethodSource("adbByContentType") + void person(ArangoDB adb) { + Person doc = new Person("key", "Jim", 22); + Person res = adb.db().query("return @d", Collections.singletonMap("d", doc), Person.class).next(); + assertThat(res).isEqualTo(doc); + String key = adb.db().query("return @d._key", Collections.singletonMap("d", doc), String.class).next(); + assertThat(key).isEqualTo("key"); + String name = adb.db().query("return @d.firstName", Collections.singletonMap("d", doc), String.class).next(); + assertThat(name).isEqualTo("Jim"); + } + +} diff --git a/shaded/pom.xml b/shaded/pom.xml index 59e786792..486dc20fa 100644 --- a/shaded/pom.xml +++ b/shaded/pom.xml @@ -28,16 +28,16 @@ com.arangodb serde-api + + com.arangodb + jackson-serde + com.arangodb jackson-dataformat-velocypack - - com.arangodb - jackson-serde - org.slf4j slf4j-api @@ -66,7 +66,6 @@ org.slf4j:slf4j-api - com.arangodb:jackson-serde com.arangodb:velocypack From 80e15589da191d4d2b302210ebf6166bec5e1a42 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Wed, 11 Jan 2023 17:39:33 +0100 Subject: [PATCH 229/254] [DE-452] Typed Config (#480) * setup MicroProfile Config * replaced ConfigProvider with ArangoConfigProperties * extracted ArangoConfigProperties interface * use HostDescription instead of com.arangodb.config.Host * ArangoConfigProperties.fromFile * fixed shaded integration tests * doc upd --- ChangeLog.md | 4 +- docs/v7_detailed_changes.md | 15 +- driver/pom.xml | 6 + .../src/main/java/com/arangodb/ArangoDB.java | 12 +- .../com/arangodb/async/ArangoDBAsync.java | 4 +- .../velocystream/VstCommunicationAsync.java | 2 +- .../velocystream/VstConnectionAsync.java | 2 +- .../VstConnectionFactoryAsync.java | 2 +- .../config/ArangoConfigProperties.java | 100 +++++++++++ .../config/ConfigPropertiesProvider.java | 12 -- .../arangodb/config/ConfigPropertyKey.java | 31 ---- .../net => config}/HostDescription.java | 54 +++--- .../com/arangodb/internal/ArangoDefaults.java | 26 +-- .../internal/InternalArangoDBBuilder.java | 164 +++++------------- .../config/ArangoConfigPropertiesImpl.java | 148 ++++++++++++++++ .../config/FileConfigPropertiesProvider.java | 51 ------ .../internal/http/HttpCommunication.java | 1 + .../internal/http/HttpConnection.java | 2 +- .../internal/http/HttpConnectionFactory.java | 2 +- .../internal/net/ConnectionFactory.java | 2 + .../arangodb/internal/net/ConnectionPool.java | 2 + .../internal/net/ConnectionPoolImpl.java | 1 + .../internal/net/DirtyReadHostHandler.java | 2 + .../internal/net/ExtendedHostResolver.java | 1 + .../internal/net/FallbackHostHandler.java | 1 + .../java/com/arangodb/internal/net/Host.java | 2 + .../com/arangodb/internal/net/HostHandle.java | 2 + .../arangodb/internal/net/HostHandler.java | 2 + .../com/arangodb/internal/net/HostImpl.java | 1 + .../internal/net/RandomHostHandler.java | 2 + .../internal/net/RoundRobinHostHandler.java | 1 + .../com/arangodb/internal/util/HostUtils.java | 1 + .../velocystream/VstCommunication.java | 3 +- .../velocystream/VstCommunicationSync.java | 2 +- .../VstConnectionFactorySync.java | 2 +- .../velocystream/internal/VstConnection.java | 6 +- .../internal/VstConnectionSync.java | 2 +- .../test/java/com/arangodb/ArangoDBTest.java | 16 +- .../test/java/com/arangodb/BaseJunit5.java | 15 +- .../java/com/arangodb/ConcurrencyTests.java | 4 +- .../test/java/com/arangodb/JwtAuthTest.java | 6 +- .../java/com/arangodb/PackageVersionTest.java | 3 +- .../test/java/com/arangodb/ParallelTest.java | 4 +- .../java/com/arangodb/async/ArangoDBTest.java | 12 +- .../java/com/arangodb/async/BaseTest.java | 7 +- .../com/arangodb/async/ConcurrencyTests.java | 4 +- .../java/com/arangodb/async/JwtAuthTest.java | 6 +- .../debug/ConsolidationIntervalMsecTest.java | 3 +- .../arangodb/async/example/ExampleBase.java | 4 +- .../graph/AQLActorsAndMoviesExampleTest.java | 4 +- .../async/example/graph/BaseGraphTest.java | 4 +- .../arangodb/async/serde/CustomSerdeTest.java | 4 +- .../config/ArangoConfigPropertiesMPImpl.java | 145 ++++++++++++++++ .../arangodb/config/ConfigDefaultsTest.java | 34 ++++ .../java/com/arangodb/config/ConfigTest.java | 66 +++++++ .../java/com/arangodb/config/ConfigUtils.java | 37 ++++ .../com/arangodb/example/ExampleBase.java | 4 +- .../graph/AQLActorsAndMoviesExampleTest.java | 4 +- .../arangodb/example/graph/BaseGraphTest.java | 4 +- .../arangodb/internal/HostHandlerTest.java | 1 + .../velocystream/CommunicationTest.java | 12 +- .../com/arangodb/serde/CustomSerdeTest.java | 4 +- .../arangodb/serde/CustomTypeHintTest.java | 4 +- .../resources/arangodb-config-test.properties | 17 ++ driver/src/test/resources/arangodb.properties | 2 +- shaded-integration-tests/pom.xml | 25 +-- .../src/test/internal/java/arch/BaseTest.java | 9 +- .../test/internal/java/arch/ConfigUtils.java | 22 +++ .../src/test/jackson/java/arch/BaseTest.java | 9 +- .../test/jackson/java/arch/ConfigUtils.java | 22 +++ .../src/test/jsonb/java/arch/BaseTest.java | 2 + .../src/test/jsonb/java/arch/ConfigUtils.java | 22 +++ .../java/com/arangodb/ArangoDBTest.java | 24 ++- .../native/java/com/arangodb/BaseJunit5.java | 17 +- .../java/com/arangodb/ConcurrencyTests.java | 4 +- .../native/java/com/arangodb/JwtAuthTest.java | 6 +- .../java/com/arangodb/ParallelTest.java | 4 +- .../java/com/arangodb/async/ArangoDBTest.java | 16 +- .../java/com/arangodb/async/BaseTest.java | 9 +- .../com/arangodb/async/ConcurrencyTests.java | 4 +- .../com/arangodb/async/InvertedIndexTest.java | 2 +- .../java/com/arangodb/async/JwtAuthTest.java | 6 +- .../debug/ConsolidationIntervalMsecTest.java | 3 +- .../arangodb/async/example/ExampleBase.java | 4 +- .../graph/AQLActorsAndMoviesExampleTest.java | 4 +- .../async/example/graph/BaseGraphTest.java | 4 +- .../arangodb/async/serde/CustomSerdeTest.java | 6 +- .../java/com/arangodb/config/ConfigUtils.java | 18 ++ .../com/arangodb/example/ExampleBase.java | 4 +- .../graph/AQLActorsAndMoviesExampleTest.java | 4 +- .../arangodb/example/graph/BaseGraphTest.java | 4 +- .../arangodb/example/ssl/SslExampleTest.java | 5 +- .../arangodb/internal/HostHandlerTest.java | 1 + .../velocystream/CommunicationTest.java | 12 +- .../annotations/AnnotatedEntity.java | 2 +- .../annotations/ArangoAnnotationsTest.java | 2 +- .../com/arangodb/serde/CustomSerdeTest.java | 4 +- .../arangodb/serde/CustomTypeHintTest.java | 4 +- .../java/com/arangodb/serde/SerdeTest.java | 5 +- .../com/arangodb/util/UnicodeUtilsTest.java | 60 +++++++ .../src/test/native/java/perf/Benchmark.java | 123 +++++++++++++ .../native/java/perf/SimpleSyncPerfTest.java | 57 ++++++ .../native/java/perf/SyncBenchmarkTest.java | 71 ++++++++ .../META-INF/native-image/reflect-config.json | 2 +- .../resources/arangodb-config-test.properties | 17 ++ .../resources/arangodb-with-prefix.properties | 3 + .../src/test/resources/arangodb.properties | 2 + 107 files changed, 1283 insertions(+), 444 deletions(-) create mode 100644 driver/src/main/java/com/arangodb/config/ArangoConfigProperties.java delete mode 100644 driver/src/main/java/com/arangodb/config/ConfigPropertiesProvider.java delete mode 100644 driver/src/main/java/com/arangodb/config/ConfigPropertyKey.java rename driver/src/main/java/com/arangodb/{internal/net => config}/HostDescription.java (54%) create mode 100644 driver/src/main/java/com/arangodb/internal/config/ArangoConfigPropertiesImpl.java delete mode 100644 driver/src/main/java/com/arangodb/internal/config/FileConfigPropertiesProvider.java create mode 100644 driver/src/test/java/com/arangodb/config/ArangoConfigPropertiesMPImpl.java create mode 100644 driver/src/test/java/com/arangodb/config/ConfigDefaultsTest.java create mode 100644 driver/src/test/java/com/arangodb/config/ConfigTest.java create mode 100644 driver/src/test/java/com/arangodb/config/ConfigUtils.java create mode 100644 driver/src/test/resources/arangodb-config-test.properties create mode 100644 shaded-integration-tests/src/test/internal/java/arch/ConfigUtils.java create mode 100644 shaded-integration-tests/src/test/jackson/java/arch/ConfigUtils.java create mode 100644 shaded-integration-tests/src/test/jsonb/java/arch/ConfigUtils.java create mode 100644 shaded-integration-tests/src/test/native/java/com/arangodb/config/ConfigUtils.java rename shaded-integration-tests/src/test/native/java/com/arangodb/{ => mapping}/annotations/AnnotatedEntity.java (97%) rename shaded-integration-tests/src/test/native/java/com/arangodb/{ => mapping}/annotations/ArangoAnnotationsTest.java (97%) create mode 100644 shaded-integration-tests/src/test/native/java/com/arangodb/util/UnicodeUtilsTest.java create mode 100644 shaded-integration-tests/src/test/native/java/perf/Benchmark.java create mode 100644 shaded-integration-tests/src/test/native/java/perf/SimpleSyncPerfTest.java create mode 100644 shaded-integration-tests/src/test/native/java/perf/SyncBenchmarkTest.java create mode 100644 shaded-integration-tests/src/test/resources/arangodb-config-test.properties create mode 100644 shaded-integration-tests/src/test/resources/arangodb-with-prefix.properties diff --git a/ChangeLog.md b/ChangeLog.md index 90d9a586e..2576c7e39 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -35,8 +35,8 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) a ### Added -- added `ArangoDB.Builder.loadProperties(ConfigPropertiesProvider)` to register custom configuration providers -- added `FileConfigPropertiesProvider` to load properties from local files +- added `ArangoDB.Builder.loadProperties(ArangoConfigProperties)` to register custom configuration suppliers +- added `ArangoConfigProperties.fromFile()` to load properties from local files - added support to `HTTP/2` communication protocol - added optional transitive dependency on `io.vertx:vertx-web-client` (can be excluded if using VST only) - added transitive dependency on Jackson Core, Databind and Annotations diff --git a/docs/v7_detailed_changes.md b/docs/v7_detailed_changes.md index 14a2830f8..31e71520d 100644 --- a/docs/v7_detailed_changes.md +++ b/docs/v7_detailed_changes.md @@ -42,16 +42,17 @@ The default communication protocol is now `HTTP2_JSON` (`HTTP/2` with `JSON` con The default host configuration to `127.0.0.1:8529` has been removed. Configuration properties are not read automatically from properties files anymore. -A new API for loading properties has been introduced: `ArangoDB.Builder.loadProperties(ConfigPropertiesProvider)`. +A new API for loading properties has been introduced: `ArangoDB.Builder.loadProperties(ArangoConfigProperties)`. Implementations could supply configuration properties coming from different sources, eg. system properties, remote -stores, frameworks facilities, etc. -An implementation for loading properties from local files is provided by `FileConfigPropertiesProvider`. +stores, frameworks facilities, etc. +An implementation for loading properties from local files is provided by `ArangoConfigProperties.fromFile()` and its +overloaded variants. -Here is an example to read config properties from `arangodb.properties` file (same behavior as in version `6`): +Here is an example to read config properties from `arangodb.properties` file (as in version `6`): ```java ArangoDB adb = new ArangoDB.Builder() - .loadProperties(new FileConfigPropertiesProvider()) + .loadProperties(ArangoConfigProperties.fromFile()) // ... .build(); ``` @@ -67,10 +68,12 @@ are prefixed with `adb`: // ... ArangoDB adb = new ArangoDB.Builder() - .loadProperties(new FileConfigPropertiesProvider("adb", "arangodb-with-prefix.properties")) + .loadProperties(new FileConfigPropertiesProvider("arangodb-with-prefix.properties", "adb")) .build(); ``` +An example showing how to provide configuration using Eclipse MicroProfile Config can be found +[here](../driver/src/test/java/com/arangodb/config). ## Transitive dependencies diff --git a/driver/pom.xml b/driver/pom.xml index dea7f553a..93eb6566a 100644 --- a/driver/pom.xml +++ b/driver/pom.xml @@ -251,6 +251,12 @@ 1.8 test + + io.smallrye.config + smallrye-config-core + 3.1.1 + test + diff --git a/driver/src/main/java/com/arangodb/ArangoDB.java b/driver/src/main/java/com/arangodb/ArangoDB.java index 62ceb1874..5533c9bef 100644 --- a/driver/src/main/java/com/arangodb/ArangoDB.java +++ b/driver/src/main/java/com/arangodb/ArangoDB.java @@ -20,8 +20,7 @@ package com.arangodb; -import com.arangodb.config.ConfigPropertiesProvider; -import com.arangodb.config.ConfigPropertyKey; +import com.arangodb.config.ArangoConfigProperties; import com.arangodb.entity.*; import com.arangodb.internal.ArangoDBImpl; import com.arangodb.internal.ArangoDefaults; @@ -336,19 +335,12 @@ public interface ArangoDB extends ArangoSerdeAccessor { */ class Builder extends InternalArangoDBBuilder { - protected Protocol protocol = ArangoDefaults.DEFAULT_NETWORK_PROTOCOL; - public Builder() { super(); } - private static Protocol loadProtocol(final ConfigPropertiesProvider properties, final Protocol currentValue) { - return Protocol.valueOf(getProperty(properties, ConfigPropertyKey.PROTOCOL, currentValue).toUpperCase(Locale.ROOT)); - } - - public Builder loadProperties(final ConfigPropertiesProvider properties) { + public Builder loadProperties(final ArangoConfigProperties properties) { doLoadProperties(properties); - protocol = loadProtocol(properties, protocol); return this; } diff --git a/driver/src/main/java/com/arangodb/async/ArangoDBAsync.java b/driver/src/main/java/com/arangodb/async/ArangoDBAsync.java index 0f7ff179e..46ab0d422 100644 --- a/driver/src/main/java/com/arangodb/async/ArangoDBAsync.java +++ b/driver/src/main/java/com/arangodb/async/ArangoDBAsync.java @@ -24,7 +24,7 @@ import com.arangodb.async.internal.ArangoDBAsyncImpl; import com.arangodb.async.internal.velocystream.VstCommunicationAsync; import com.arangodb.async.internal.velocystream.VstConnectionFactoryAsync; -import com.arangodb.config.ConfigPropertiesProvider; +import com.arangodb.config.ArangoConfigProperties; import com.arangodb.entity.*; import com.arangodb.internal.ArangoDefaults; import com.arangodb.internal.InternalArangoDBBuilder; @@ -315,7 +315,7 @@ public Builder() { super(); } - public Builder loadProperties(final ConfigPropertiesProvider config) { + public Builder loadProperties(final ArangoConfigProperties config) { super.doLoadProperties(config); return this; } diff --git a/driver/src/main/java/com/arangodb/async/internal/velocystream/VstCommunicationAsync.java b/driver/src/main/java/com/arangodb/async/internal/velocystream/VstCommunicationAsync.java index ab8319070..bc111aa63 100644 --- a/driver/src/main/java/com/arangodb/async/internal/velocystream/VstCommunicationAsync.java +++ b/driver/src/main/java/com/arangodb/async/internal/velocystream/VstCommunicationAsync.java @@ -22,7 +22,7 @@ import com.arangodb.ArangoDBException; import com.arangodb.internal.net.ArangoDBRedirectException; -import com.arangodb.internal.net.HostDescription; +import com.arangodb.config.HostDescription; import com.arangodb.internal.net.HostHandle; import com.arangodb.internal.net.HostHandler; import com.arangodb.internal.serde.InternalSerde; diff --git a/driver/src/main/java/com/arangodb/async/internal/velocystream/VstConnectionAsync.java b/driver/src/main/java/com/arangodb/async/internal/velocystream/VstConnectionAsync.java index 8805fd674..0e94bcc30 100644 --- a/driver/src/main/java/com/arangodb/async/internal/velocystream/VstConnectionAsync.java +++ b/driver/src/main/java/com/arangodb/async/internal/velocystream/VstConnectionAsync.java @@ -21,7 +21,7 @@ package com.arangodb.async.internal.velocystream; import com.arangodb.async.internal.utils.CompletableFutureUtils; -import com.arangodb.internal.net.HostDescription; +import com.arangodb.config.HostDescription; import com.arangodb.internal.velocystream.internal.Chunk; import com.arangodb.internal.velocystream.internal.Message; import com.arangodb.internal.velocystream.internal.MessageStore; diff --git a/driver/src/main/java/com/arangodb/async/internal/velocystream/VstConnectionFactoryAsync.java b/driver/src/main/java/com/arangodb/async/internal/velocystream/VstConnectionFactoryAsync.java index 443a90865..72018d182 100644 --- a/driver/src/main/java/com/arangodb/async/internal/velocystream/VstConnectionFactoryAsync.java +++ b/driver/src/main/java/com/arangodb/async/internal/velocystream/VstConnectionFactoryAsync.java @@ -22,7 +22,7 @@ import com.arangodb.internal.net.Connection; import com.arangodb.internal.net.ConnectionFactory; -import com.arangodb.internal.net.HostDescription; +import com.arangodb.config.HostDescription; import com.arangodb.internal.velocystream.internal.MessageStore; import javax.net.ssl.SSLContext; diff --git a/driver/src/main/java/com/arangodb/config/ArangoConfigProperties.java b/driver/src/main/java/com/arangodb/config/ArangoConfigProperties.java new file mode 100644 index 000000000..5ef63676f --- /dev/null +++ b/driver/src/main/java/com/arangodb/config/ArangoConfigProperties.java @@ -0,0 +1,100 @@ +package com.arangodb.config; + +import com.arangodb.Protocol; +import com.arangodb.entity.LoadBalancingStrategy; +import com.arangodb.internal.config.ArangoConfigPropertiesImpl; + +import java.util.List; +import java.util.Optional; + +public interface ArangoConfigProperties { + + /** + * Reads properties from file arangodb.properties. + * Properties must be prefixed with @{code "arangodb"}, eg. @{code "arangodb.hosts=localhost:8529"}. + */ + static ArangoConfigProperties fromFile() { + return new ArangoConfigPropertiesImpl(); + } + + /** + * Reads properties from file {@code fileName}. + * Properties must be prefixed with @{code "arangodb"}, eg. @{code "arangodb.hosts=localhost:8529"}. + */ + static ArangoConfigProperties fromFile(final String fileName) { + return new ArangoConfigPropertiesImpl(fileName); + } + + /** + * Reads properties from file {@code fileName}. + * Properties must be prefixed with @{code prefix}, eg. @{code ".hosts=localhost:8529"}. + */ + static ArangoConfigProperties fromFile(final String fileName, final String prefix) { + return new ArangoConfigPropertiesImpl(fileName, prefix); + } + + default Optional> getHosts() { + return Optional.empty(); + } + + default Optional getProtocol() { + return Optional.empty(); + } + + default Optional getUser() { + return Optional.empty(); + } + + default Optional getPassword() { + return Optional.empty(); + } + + default Optional getJwt() { + return Optional.empty(); + } + + default Optional getTimeout() { + return Optional.empty(); + } + + default Optional getUseSsl() { + return Optional.empty(); + } + + default Optional getVerifyHost() { + return Optional.empty(); + } + + default Optional getChunkSize() { + return Optional.empty(); + } + + default Optional getMaxConnections() { + return Optional.empty(); + } + + default Optional getConnectionTtl() { + return Optional.empty(); + } + + default Optional getKeepAliveInterval() { + return Optional.empty(); + } + + default Optional getAcquireHostList() { + return Optional.empty(); + } + + default Optional getAcquireHostListInterval() { + return Optional.empty(); + } + + default Optional getLoadBalancingStrategy() { + return Optional.empty(); + } + + default Optional getResponseQueueTimeSamples() { + return Optional.empty(); + } + +} diff --git a/driver/src/main/java/com/arangodb/config/ConfigPropertiesProvider.java b/driver/src/main/java/com/arangodb/config/ConfigPropertiesProvider.java deleted file mode 100644 index 0e1fe2417..000000000 --- a/driver/src/main/java/com/arangodb/config/ConfigPropertiesProvider.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.arangodb.config; - - -public interface ConfigPropertiesProvider { - - /** - * @param key the property key - * @return the configuration property with the specified key if present, {@code null} otherwise - */ - String getProperty(String key); - -} diff --git a/driver/src/main/java/com/arangodb/config/ConfigPropertyKey.java b/driver/src/main/java/com/arangodb/config/ConfigPropertyKey.java deleted file mode 100644 index db82cd09b..000000000 --- a/driver/src/main/java/com/arangodb/config/ConfigPropertyKey.java +++ /dev/null @@ -1,31 +0,0 @@ -package com.arangodb.config; - -public enum ConfigPropertyKey { - HOSTS("hosts"), - TIMEOUT("timeout"), - USER("user"), - PASSWORD("password"), - JWT("jwt"), - USE_SSL("ssl"), - VERIFY_HOST("verifyHost"), - VST_CHUNK_SIZE("chunkSize"), - MAX_CONNECTIONS("connections.max"), - CONNECTION_TTL("connections.ttl"), - KEEP_ALIVE_INTERVAL("connections.keepAlive.interval"), - ACQUIRE_HOST_LIST("acquireHostList"), - ACQUIRE_HOST_LIST_INTERVAL("acquireHostList.interval"), - LOAD_BALANCING_STRATEGY("loadBalancingStrategy"), - RESPONSE_QUEUE_TIME_SAMPLES("metrics.responseQueueTimeSamples"), - PROTOCOL("protocol"); - - private final String value; - - ConfigPropertyKey(String value) { - this.value = value; - } - - public String getValue() { - return value; - } - -} diff --git a/driver/src/main/java/com/arangodb/internal/net/HostDescription.java b/driver/src/main/java/com/arangodb/config/HostDescription.java similarity index 54% rename from driver/src/main/java/com/arangodb/internal/net/HostDescription.java rename to driver/src/main/java/com/arangodb/config/HostDescription.java index 53d54b10b..2e26177ed 100644 --- a/driver/src/main/java/com/arangodb/internal/net/HostDescription.java +++ b/driver/src/main/java/com/arangodb/config/HostDescription.java @@ -18,16 +18,35 @@ * Copyright holder is ArangoDB GmbH, Cologne, Germany */ -package com.arangodb.internal.net; +package com.arangodb.config; + +import java.util.Objects; /** * @author Mark Vollmary + * @author Michele Rastelli */ public class HostDescription { private final String host; private final int port; + /** + * Factory method used by MicroProfile Config as + * automatic converter. + * + * @param value hostname:port + * @return Host + */ + public static HostDescription parse(CharSequence value) { + Objects.requireNonNull(value); + final String[] split = value.toString().split(":"); + if (split.length != 2) { + throw new IllegalArgumentException("Could not parse host. Expected hostname:port, but got: " + value); + } + return new HostDescription(split[0], Integer.parseInt(split[1])); + } + public HostDescription(final String host, final int port) { super(); this.host = host; @@ -48,34 +67,15 @@ public String toString() { } @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((host == null) ? 0 : host.hashCode()); - result = prime * result + port; - return result; + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + HostDescription that = (HostDescription) o; + return port == that.port && Objects.equals(host, that.host); } @Override - public boolean equals(final Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (getClass() != obj.getClass()) { - return false; - } - final HostDescription other = (HostDescription) obj; - if (host == null) { - if (other.host != null) { - return false; - } - } else if (!host.equals(other.host)) { - return false; - } - return port == other.port; + public int hashCode() { + return Objects.hash(host, port); } - } diff --git a/driver/src/main/java/com/arangodb/internal/ArangoDefaults.java b/driver/src/main/java/com/arangodb/internal/ArangoDefaults.java index ce452eed0..aab635dd3 100644 --- a/driver/src/main/java/com/arangodb/internal/ArangoDefaults.java +++ b/driver/src/main/java/com/arangodb/internal/ArangoDefaults.java @@ -21,8 +21,12 @@ package com.arangodb.internal; import com.arangodb.Protocol; +import com.arangodb.config.HostDescription; import com.arangodb.entity.LoadBalancingStrategy; +import java.util.Collections; +import java.util.List; + /** * @author Mark Vollmary */ @@ -30,22 +34,24 @@ public final class ArangoDefaults { public static final int INTEGER_BYTES = Integer.SIZE / Byte.SIZE; public static final int LONG_BYTES = Long.SIZE / Byte.SIZE; - public static final Integer DEFAULT_TIMEOUT = 0; - public static final String DEFAULT_USER = "root"; - public static final Boolean DEFAULT_USE_SSL = false; - public static final Boolean DEFAULT_VERIFY_HOST = true; public static final int CHUNK_MIN_HEADER_SIZE = INTEGER_BYTES + INTEGER_BYTES + LONG_BYTES; public static final int CHUNK_MAX_HEADER_SIZE = CHUNK_MIN_HEADER_SIZE + LONG_BYTES; - public static final int CHUNK_DEFAULT_CONTENT_SIZE = 30000; public static final int MAX_CONNECTIONS_VST_DEFAULT = 1; - public static final Long CONNECTION_TTL_VST_DEFAULT = null; public static final int MAX_CONNECTIONS_HTTP_DEFAULT = 20; public static final int MAX_CONNECTIONS_HTTP2_DEFAULT = 1; - public static final Protocol DEFAULT_NETWORK_PROTOCOL = Protocol.HTTP2_JSON; - public static final boolean DEFAULT_ACQUIRE_HOST_LIST = false; - public static final int DEFAULT_ACQUIRE_HOST_LIST_INTERVAL = 60 * 60 * 1000; // hour + + // default config properties + public static final List DEFAULT_HOSTS = Collections.emptyList(); + public static final Protocol DEFAULT_PROTOCOL = Protocol.HTTP2_JSON; + public static final String DEFAULT_USER = "root"; + public static final Integer DEFAULT_TIMEOUT = 0; + public static final Boolean DEFAULT_USE_SSL = false; + public static final Boolean DEFAULT_VERIFY_HOST = true; + public static final Integer DEFAULT_CHUNK_SIZE = 30_000; + public static final Boolean DEFAULT_ACQUIRE_HOST_LIST = false; + public static final Integer DEFAULT_ACQUIRE_HOST_LIST_INTERVAL = 60 * 60 * 1000; // hour public static final LoadBalancingStrategy DEFAULT_LOAD_BALANCING_STRATEGY = LoadBalancingStrategy.NONE; - public static final int DEFAULT_RESPONSE_QUEUE_TIME_SAMPLES = 10; + public static final Integer DEFAULT_RESPONSE_QUEUE_TIME_SAMPLES = 10; private ArangoDefaults() { super(); diff --git a/driver/src/main/java/com/arangodb/internal/InternalArangoDBBuilder.java b/driver/src/main/java/com/arangodb/internal/InternalArangoDBBuilder.java index 68022fab6..02c3f5bf6 100644 --- a/driver/src/main/java/com/arangodb/internal/InternalArangoDBBuilder.java +++ b/driver/src/main/java/com/arangodb/internal/InternalArangoDBBuilder.java @@ -21,8 +21,9 @@ package com.arangodb.internal; import com.arangodb.ArangoDBException; -import com.arangodb.config.ConfigPropertiesProvider; -import com.arangodb.config.ConfigPropertyKey; +import com.arangodb.Protocol; +import com.arangodb.config.ArangoConfigProperties; +import com.arangodb.config.HostDescription; import com.arangodb.entity.LoadBalancingStrategy; import com.arangodb.internal.net.*; import com.arangodb.internal.serde.InternalSerdeProvider; @@ -34,6 +35,7 @@ import javax.net.ssl.SSLContext; import java.util.*; +import java.util.stream.Collectors; /** @@ -43,106 +45,28 @@ public abstract class InternalArangoDBBuilder { private static final Logger LOG = LoggerFactory.getLogger(InternalArangoDBBuilder.class); protected final List hosts = new ArrayList<>(); - protected Integer timeout = ArangoDefaults.DEFAULT_TIMEOUT; - protected String user = ArangoDefaults.DEFAULT_USER; - protected String password = null; - protected String jwt = null; - protected Boolean useSsl = ArangoDefaults.DEFAULT_USE_SSL; - protected SSLContext sslContext = null; - protected Boolean verifyHost = ArangoDefaults.DEFAULT_VERIFY_HOST; - protected Integer chunkSize = ArangoDefaults.CHUNK_DEFAULT_CONTENT_SIZE; - protected Integer maxConnections = null; - protected Long connectionTtl = ArangoDefaults.CONNECTION_TTL_VST_DEFAULT; - protected Integer keepAliveInterval = null; - protected Boolean acquireHostList = ArangoDefaults.DEFAULT_ACQUIRE_HOST_LIST; - protected Integer acquireHostListInterval = ArangoDefaults.DEFAULT_ACQUIRE_HOST_LIST_INTERVAL; - protected LoadBalancingStrategy loadBalancingStrategy = ArangoDefaults.DEFAULT_LOAD_BALANCING_STRATEGY; + protected Protocol protocol; + protected Integer timeout; + protected String user; + protected String password; + protected String jwt; + protected Boolean useSsl; + protected SSLContext sslContext; + protected Boolean verifyHost; + protected Integer chunkSize; + protected Integer maxConnections; + protected Long connectionTtl; + protected Integer keepAliveInterval; + protected Boolean acquireHostList; + protected Integer acquireHostListInterval; + protected LoadBalancingStrategy loadBalancingStrategy; protected ArangoSerde userDataSerde; - protected Integer responseQueueTimeSamples = ArangoDefaults.DEFAULT_RESPONSE_QUEUE_TIME_SAMPLES; - - private static void loadHosts(final ConfigPropertiesProvider properties, final Collection hosts) { - final String hostsProp = properties.getProperty(ConfigPropertyKey.HOSTS.getValue()); - if (hostsProp != null) { - final String[] hostsSplit = hostsProp.split(","); - for (final String host : hostsSplit) { - final String[] split = host.split(":"); - if (split.length != 2 || !split[1].matches("[0-9]+")) { - throw new ArangoDBException(String.format( - "Could not load property-value arangodb.hosts=%s. Expected format ip:port,ip:port,...", - hostsProp)); - } else { - hosts.add(new HostDescription(split[0], Integer.parseInt(split[1]))); - } - } - } - } - - private static Integer loadTimeout(final ConfigPropertiesProvider properties, final Integer currentValue) { - return Integer.parseInt(getProperty(properties, ConfigPropertyKey.TIMEOUT, currentValue)); - } - - private static String loadUser(final ConfigPropertiesProvider properties, final String currentValue) { - return getProperty(properties, ConfigPropertyKey.USER, currentValue); - } - - private static String loadPassword(final ConfigPropertiesProvider properties, final String currentValue) { - return getProperty(properties, ConfigPropertyKey.PASSWORD, currentValue); - } - - private static String loadJwt(final ConfigPropertiesProvider properties, final String currentValue) { - return getProperty(properties, ConfigPropertyKey.JWT, currentValue); - } - - private static Boolean loadUseSsl(final ConfigPropertiesProvider properties, final Boolean currentValue) { - return Boolean.parseBoolean(getProperty(properties, ConfigPropertyKey.USE_SSL, currentValue)); - } - - private static Boolean loadVerifyHost(final ConfigPropertiesProvider properties, final Boolean currentValue) { - return Boolean.parseBoolean(getProperty(properties, ConfigPropertyKey.VERIFY_HOST, currentValue)); - } - - private static Integer loadChunkSize(final ConfigPropertiesProvider properties, final Integer currentValue) { - return Integer.parseInt(getProperty(properties, ConfigPropertyKey.VST_CHUNK_SIZE, currentValue)); - } - - private static Integer loadMaxConnections(final ConfigPropertiesProvider properties, final Integer currentValue) { - String value = getProperty(properties, ConfigPropertyKey.MAX_CONNECTIONS, currentValue); - return value != null ? Integer.parseInt(value) : null; - } - - private static Long loadConnectionTtl(final ConfigPropertiesProvider properties, final Long currentValue) { - final String ttl = getProperty(properties, ConfigPropertyKey.CONNECTION_TTL, currentValue); - return ttl != null ? Long.parseLong(ttl) : null; - } - - private static Integer loadKeepAliveInterval(final ConfigPropertiesProvider properties, final Integer currentValue) { - final String keepAliveInterval = getProperty(properties, ConfigPropertyKey.KEEP_ALIVE_INTERVAL, currentValue); - return keepAliveInterval != null ? Integer.parseInt(keepAliveInterval) : null; - } - - private static Boolean loadAcquireHostList(final ConfigPropertiesProvider properties, final Boolean currentValue) { - return Boolean.parseBoolean(getProperty(properties, ConfigPropertyKey.ACQUIRE_HOST_LIST, currentValue)); - } - - private static int loadAcquireHostListInterval(final ConfigPropertiesProvider properties, final Integer currentValue) { - return Integer.parseInt(getProperty(properties, ConfigPropertyKey.ACQUIRE_HOST_LIST_INTERVAL, currentValue)); - } - - private static int loadResponseQueueTimeSamples(final ConfigPropertiesProvider properties, final Integer currentValue) { - return Integer.parseInt(getProperty(properties, ConfigPropertyKey.RESPONSE_QUEUE_TIME_SAMPLES, currentValue)); - } - - private static LoadBalancingStrategy loadLoadBalancingStrategy( - final ConfigPropertiesProvider properties, - final LoadBalancingStrategy currentValue) { - return LoadBalancingStrategy.valueOf(getProperty(properties, ConfigPropertyKey.LOAD_BALANCING_STRATEGY, currentValue).toUpperCase(Locale.ROOT)); - } + protected Integer responseQueueTimeSamples; - protected static String getProperty(ConfigPropertiesProvider props, ConfigPropertyKey key, Object currentValue) { - String p = props.getProperty(key.getValue()); - if (p != null) return p; - if (currentValue != null) return currentValue.toString(); - return null; + protected InternalArangoDBBuilder() { + // load default properties + doLoadProperties(new ArangoConfigProperties() { + }); } protected static ArangoSerdeProvider serdeProvider() { @@ -161,22 +85,30 @@ protected static ArangoSerdeProvider serdeProvider() { return serdeProvider; } - protected void doLoadProperties(final ConfigPropertiesProvider properties) { - loadHosts(properties, hosts); - timeout = loadTimeout(properties, timeout); - user = loadUser(properties, user); - password = loadPassword(properties, password); - jwt = loadJwt(properties, jwt); - useSsl = loadUseSsl(properties, useSsl); - verifyHost = loadVerifyHost(properties, verifyHost); - chunkSize = loadChunkSize(properties, chunkSize); - maxConnections = loadMaxConnections(properties, maxConnections); - connectionTtl = loadConnectionTtl(properties, connectionTtl); - keepAliveInterval = loadKeepAliveInterval(properties, keepAliveInterval); - acquireHostList = loadAcquireHostList(properties, acquireHostList); - acquireHostListInterval = loadAcquireHostListInterval(properties, acquireHostListInterval); - loadBalancingStrategy = loadLoadBalancingStrategy(properties, loadBalancingStrategy); - responseQueueTimeSamples = loadResponseQueueTimeSamples(properties, responseQueueTimeSamples); + protected void doLoadProperties(final ArangoConfigProperties properties) { + hosts.addAll(properties.getHosts().orElse(ArangoDefaults.DEFAULT_HOSTS).stream() + .map(it -> new HostDescription(it.getHost(), it.getPort())) + .collect(Collectors.toList())); + protocol = properties.getProtocol().orElse(ArangoDefaults.DEFAULT_PROTOCOL); + timeout = properties.getTimeout().orElse(ArangoDefaults.DEFAULT_TIMEOUT); + user = properties.getUser().orElse(ArangoDefaults.DEFAULT_USER); + // FIXME: make password field Optional + password = properties.getPassword().orElse(null); + // FIXME: make jwt field Optional + jwt = properties.getJwt().orElse(null); + useSsl = properties.getUseSsl().orElse(ArangoDefaults.DEFAULT_USE_SSL); + verifyHost = properties.getVerifyHost().orElse(ArangoDefaults.DEFAULT_VERIFY_HOST); + chunkSize = properties.getChunkSize().orElse(ArangoDefaults.DEFAULT_CHUNK_SIZE); + // FIXME: make maxConnections field Optional + maxConnections = properties.getMaxConnections().orElse(null); + // FIXME: make connectionTtl field Optional + connectionTtl = properties.getConnectionTtl().orElse(null); + // FIXME: make keepAliveInterval field Optional + keepAliveInterval = properties.getKeepAliveInterval().orElse(null); + acquireHostList = properties.getAcquireHostList().orElse(ArangoDefaults.DEFAULT_ACQUIRE_HOST_LIST); + acquireHostListInterval = properties.getAcquireHostListInterval().orElse(ArangoDefaults.DEFAULT_ACQUIRE_HOST_LIST_INTERVAL); + loadBalancingStrategy = properties.getLoadBalancingStrategy().orElse(ArangoDefaults.DEFAULT_LOAD_BALANCING_STRATEGY); + responseQueueTimeSamples = properties.getResponseQueueTimeSamples().orElse(ArangoDefaults.DEFAULT_RESPONSE_QUEUE_TIME_SAMPLES); } protected void setHost(final String host, final int port) { diff --git a/driver/src/main/java/com/arangodb/internal/config/ArangoConfigPropertiesImpl.java b/driver/src/main/java/com/arangodb/internal/config/ArangoConfigPropertiesImpl.java new file mode 100644 index 000000000..7484c6e23 --- /dev/null +++ b/driver/src/main/java/com/arangodb/internal/config/ArangoConfigPropertiesImpl.java @@ -0,0 +1,148 @@ +package com.arangodb.internal.config; + +import com.arangodb.ArangoDBException; +import com.arangodb.Protocol; +import com.arangodb.config.ArangoConfigProperties; +import com.arangodb.config.HostDescription; +import com.arangodb.entity.LoadBalancingStrategy; + +import java.io.InputStream; +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; +import java.util.Properties; + +/** + * ArangoConfigProperties implementation that reads configuration entries from local file. Properties path prefix can be + * configured, so that it is possible to distinguish configurations for multiple driver instances in the same file. + */ +public final class ArangoConfigPropertiesImpl implements ArangoConfigProperties { + private static final String DEFAULT_PREFIX = "arangodb"; + private static final String DEFAULT_PROPERTY_FILE = "arangodb.properties"; + private final Properties properties; + private final String prefix; + + public ArangoConfigPropertiesImpl() { + this(DEFAULT_PROPERTY_FILE, DEFAULT_PREFIX); + } + + public ArangoConfigPropertiesImpl(final String fileName) { + this(fileName, DEFAULT_PREFIX); + } + + public ArangoConfigPropertiesImpl(final String fileName, final String prefix) { + properties = initProperties(fileName); + this.prefix = initPrefix(prefix); + } + + private String initPrefix(String p) { + if (p == null) { + return ""; + } else { + return p + "."; + } + } + + private Properties initProperties(String fileName) { + Properties p = new Properties(); + try (InputStream is = getClass().getClassLoader().getResourceAsStream(fileName)) { + p.load(is); + } catch (Exception e) { + throw new ArangoDBException("Got exception while reading properties file " + fileName, e); + } + return p; + } + + private String getProperty(String key) { + return properties.getProperty(prefix + key); + } + + @Override + public Optional> getHosts() { + return Optional.ofNullable(getProperty("hosts")) + .map(s -> { + List hostDescriptions = new ArrayList<>(); + String[] hosts = s.split(","); + for (String host : hosts) { + hostDescriptions.add(HostDescription.parse(host)); + } + return hostDescriptions; + }); + } + + @Override + public Optional getProtocol() { + return Optional.ofNullable(getProperty("protocol")).map(Protocol::valueOf); + } + + @Override + public Optional getUser() { + return Optional.ofNullable(getProperty("user")); + } + + @Override + public Optional getPassword() { + return Optional.ofNullable(getProperty("password")); + } + + @Override + public Optional getJwt() { + return Optional.ofNullable(getProperty("jwt")); + } + + @Override + public Optional getTimeout() { + return Optional.ofNullable(getProperty("timeout")).map(Integer::valueOf); + } + + @Override + public Optional getUseSsl() { + return Optional.ofNullable(getProperty("useSsl")).map(Boolean::valueOf); + } + + @Override + public Optional getVerifyHost() { + return Optional.ofNullable(getProperty("verifyHost")).map(Boolean::valueOf); + } + + @Override + public Optional getChunkSize() { + return Optional.ofNullable(getProperty("chunkSize")).map(Integer::valueOf); + } + + @Override + public Optional getMaxConnections() { + return Optional.ofNullable(getProperty("maxConnections")).map(Integer::valueOf); + } + + @Override + public Optional getConnectionTtl() { + return Optional.ofNullable(getProperty("connectionTtl")).map(Long::valueOf); + } + + @Override + public Optional getKeepAliveInterval() { + return Optional.ofNullable(getProperty("keepAliveInterval")).map(Integer::valueOf); + } + + @Override + public Optional getAcquireHostList() { + return Optional.ofNullable(getProperty("acquireHostList")).map(Boolean::valueOf); + } + + @Override + public Optional getAcquireHostListInterval() { + return Optional.ofNullable(getProperty("acquireHostListInterval")).map(Integer::valueOf); + } + + @Override + public Optional getLoadBalancingStrategy() { + return Optional.ofNullable(getProperty("loadBalancingStrategy")).map(LoadBalancingStrategy::valueOf); + } + + @Override + public Optional getResponseQueueTimeSamples() { + return Optional.ofNullable(getProperty("responseQueueTimeSamples")).map(Integer::valueOf); + } + +} diff --git a/driver/src/main/java/com/arangodb/internal/config/FileConfigPropertiesProvider.java b/driver/src/main/java/com/arangodb/internal/config/FileConfigPropertiesProvider.java deleted file mode 100644 index 4e54ce196..000000000 --- a/driver/src/main/java/com/arangodb/internal/config/FileConfigPropertiesProvider.java +++ /dev/null @@ -1,51 +0,0 @@ -package com.arangodb.internal.config; - -import com.arangodb.ArangoDBException; -import com.arangodb.config.ConfigPropertiesProvider; - -import java.io.InputStream; -import java.util.Properties; - -/** - * ConfigProvider that reads configuration entries from local file. Properties path prefix can be configured, so that it - * is possible to distinguish configurations for multiple driver instances in the same file. - */ -public class FileConfigPropertiesProvider implements ConfigPropertiesProvider { - private static final String DEFAULT_PREFIX = "arangodb"; - private static final String DEFAULT_PROPERTY_FILE = "arangodb.properties"; - private final Properties properties; - private final String prefix; - - public FileConfigPropertiesProvider() { - this(DEFAULT_PREFIX, DEFAULT_PROPERTY_FILE); - } - - public FileConfigPropertiesProvider(String prefix, String fileName) { - this.prefix = initPrefix(prefix); - properties = initProperties(fileName); - } - - private String initPrefix(String p) { - if (p == null) { - return ""; - } else { - return p + "."; - } - } - - private Properties initProperties(String fileName) { - Properties p = new Properties(); - try (InputStream is = getClass().getClassLoader().getResourceAsStream(fileName)) { - p.load(is); - } catch (Exception e) { - throw new ArangoDBException("Got exception while reading properties file " + fileName, e); - } - return p; - } - - @Override - public String getProperty(String key) { - return properties.getProperty(prefix + key); - } -} - diff --git a/driver/src/main/java/com/arangodb/internal/http/HttpCommunication.java b/driver/src/main/java/com/arangodb/internal/http/HttpCommunication.java index f68f86f01..a0be3f649 100644 --- a/driver/src/main/java/com/arangodb/internal/http/HttpCommunication.java +++ b/driver/src/main/java/com/arangodb/internal/http/HttpCommunication.java @@ -21,6 +21,7 @@ package com.arangodb.internal.http; import com.arangodb.ArangoDBException; +import com.arangodb.config.HostDescription; import com.arangodb.internal.InternalRequest; import com.arangodb.internal.RequestType; import com.arangodb.internal.InternalResponse; diff --git a/driver/src/main/java/com/arangodb/internal/http/HttpConnection.java b/driver/src/main/java/com/arangodb/internal/http/HttpConnection.java index 5f6a422df..f81786432 100644 --- a/driver/src/main/java/com/arangodb/internal/http/HttpConnection.java +++ b/driver/src/main/java/com/arangodb/internal/http/HttpConnection.java @@ -22,7 +22,7 @@ import com.arangodb.*; import com.arangodb.internal.net.Connection; -import com.arangodb.internal.net.HostDescription; +import com.arangodb.config.HostDescription; import com.arangodb.internal.serde.ContentTypeFactory; import com.arangodb.internal.serde.InternalSerde; import com.arangodb.internal.util.EncodeUtils; diff --git a/driver/src/main/java/com/arangodb/internal/http/HttpConnectionFactory.java b/driver/src/main/java/com/arangodb/internal/http/HttpConnectionFactory.java index 59783cdf9..e4525511e 100644 --- a/driver/src/main/java/com/arangodb/internal/http/HttpConnectionFactory.java +++ b/driver/src/main/java/com/arangodb/internal/http/HttpConnectionFactory.java @@ -23,7 +23,7 @@ import com.arangodb.Protocol; import com.arangodb.internal.net.Connection; import com.arangodb.internal.net.ConnectionFactory; -import com.arangodb.internal.net.HostDescription; +import com.arangodb.config.HostDescription; import com.arangodb.internal.serde.InternalSerde; import javax.net.ssl.SSLContext; diff --git a/driver/src/main/java/com/arangodb/internal/net/ConnectionFactory.java b/driver/src/main/java/com/arangodb/internal/net/ConnectionFactory.java index 4987a40cb..65c83fc15 100644 --- a/driver/src/main/java/com/arangodb/internal/net/ConnectionFactory.java +++ b/driver/src/main/java/com/arangodb/internal/net/ConnectionFactory.java @@ -20,6 +20,8 @@ package com.arangodb.internal.net; +import com.arangodb.config.HostDescription; + /** * @author Mark Vollmary */ diff --git a/driver/src/main/java/com/arangodb/internal/net/ConnectionPool.java b/driver/src/main/java/com/arangodb/internal/net/ConnectionPool.java index d1ad313d0..91c12bb02 100644 --- a/driver/src/main/java/com/arangodb/internal/net/ConnectionPool.java +++ b/driver/src/main/java/com/arangodb/internal/net/ConnectionPool.java @@ -20,6 +20,8 @@ package com.arangodb.internal.net; +import com.arangodb.config.HostDescription; + import java.io.Closeable; /** diff --git a/driver/src/main/java/com/arangodb/internal/net/ConnectionPoolImpl.java b/driver/src/main/java/com/arangodb/internal/net/ConnectionPoolImpl.java index c86f07a47..b393ae421 100644 --- a/driver/src/main/java/com/arangodb/internal/net/ConnectionPoolImpl.java +++ b/driver/src/main/java/com/arangodb/internal/net/ConnectionPoolImpl.java @@ -21,6 +21,7 @@ package com.arangodb.internal.net; import com.arangodb.ArangoDBException; +import com.arangodb.config.HostDescription; import com.arangodb.internal.velocystream.internal.VstConnection; import com.arangodb.internal.velocystream.internal.VstConnectionSync; import org.slf4j.Logger; diff --git a/driver/src/main/java/com/arangodb/internal/net/DirtyReadHostHandler.java b/driver/src/main/java/com/arangodb/internal/net/DirtyReadHostHandler.java index db3879d80..2fded0c99 100644 --- a/driver/src/main/java/com/arangodb/internal/net/DirtyReadHostHandler.java +++ b/driver/src/main/java/com/arangodb/internal/net/DirtyReadHostHandler.java @@ -20,6 +20,8 @@ package com.arangodb.internal.net; +import com.arangodb.config.HostDescription; + import java.io.IOException; /** diff --git a/driver/src/main/java/com/arangodb/internal/net/ExtendedHostResolver.java b/driver/src/main/java/com/arangodb/internal/net/ExtendedHostResolver.java index 4d111af37..ade06a47e 100644 --- a/driver/src/main/java/com/arangodb/internal/net/ExtendedHostResolver.java +++ b/driver/src/main/java/com/arangodb/internal/net/ExtendedHostResolver.java @@ -22,6 +22,7 @@ import com.arangodb.ArangoDBException; import com.arangodb.DbName; +import com.arangodb.config.HostDescription; import com.arangodb.internal.ArangoExecutorSync; import com.arangodb.internal.serde.InternalSerde; import com.arangodb.internal.util.HostUtils; diff --git a/driver/src/main/java/com/arangodb/internal/net/FallbackHostHandler.java b/driver/src/main/java/com/arangodb/internal/net/FallbackHostHandler.java index 05ee6ebac..5ea722d6d 100644 --- a/driver/src/main/java/com/arangodb/internal/net/FallbackHostHandler.java +++ b/driver/src/main/java/com/arangodb/internal/net/FallbackHostHandler.java @@ -22,6 +22,7 @@ import com.arangodb.ArangoDBException; import com.arangodb.ArangoDBMultipleException; +import com.arangodb.config.HostDescription; import java.util.ArrayList; import java.util.List; diff --git a/driver/src/main/java/com/arangodb/internal/net/Host.java b/driver/src/main/java/com/arangodb/internal/net/Host.java index 28b2571d7..91a6e50da 100644 --- a/driver/src/main/java/com/arangodb/internal/net/Host.java +++ b/driver/src/main/java/com/arangodb/internal/net/Host.java @@ -20,6 +20,8 @@ package com.arangodb.internal.net; +import com.arangodb.config.HostDescription; + import java.io.IOException; /** diff --git a/driver/src/main/java/com/arangodb/internal/net/HostHandle.java b/driver/src/main/java/com/arangodb/internal/net/HostHandle.java index c26b184d3..e288c2171 100644 --- a/driver/src/main/java/com/arangodb/internal/net/HostHandle.java +++ b/driver/src/main/java/com/arangodb/internal/net/HostHandle.java @@ -20,6 +20,8 @@ package com.arangodb.internal.net; +import com.arangodb.config.HostDescription; + /** * @author Mark Vollmary */ diff --git a/driver/src/main/java/com/arangodb/internal/net/HostHandler.java b/driver/src/main/java/com/arangodb/internal/net/HostHandler.java index 1a3ad8d92..911a219b0 100644 --- a/driver/src/main/java/com/arangodb/internal/net/HostHandler.java +++ b/driver/src/main/java/com/arangodb/internal/net/HostHandler.java @@ -20,6 +20,8 @@ package com.arangodb.internal.net; +import com.arangodb.config.HostDescription; + import java.io.IOException; /** diff --git a/driver/src/main/java/com/arangodb/internal/net/HostImpl.java b/driver/src/main/java/com/arangodb/internal/net/HostImpl.java index 419645db4..2477bee9c 100644 --- a/driver/src/main/java/com/arangodb/internal/net/HostImpl.java +++ b/driver/src/main/java/com/arangodb/internal/net/HostImpl.java @@ -21,6 +21,7 @@ package com.arangodb.internal.net; import com.arangodb.ArangoDBException; +import com.arangodb.config.HostDescription; import java.io.IOException; diff --git a/driver/src/main/java/com/arangodb/internal/net/RandomHostHandler.java b/driver/src/main/java/com/arangodb/internal/net/RandomHostHandler.java index 7e7a4464b..4fd00e3b8 100644 --- a/driver/src/main/java/com/arangodb/internal/net/RandomHostHandler.java +++ b/driver/src/main/java/com/arangodb/internal/net/RandomHostHandler.java @@ -20,6 +20,8 @@ package com.arangodb.internal.net; +import com.arangodb.config.HostDescription; + import java.util.ArrayList; import java.util.Collections; diff --git a/driver/src/main/java/com/arangodb/internal/net/RoundRobinHostHandler.java b/driver/src/main/java/com/arangodb/internal/net/RoundRobinHostHandler.java index c4b925471..d980ef5cc 100644 --- a/driver/src/main/java/com/arangodb/internal/net/RoundRobinHostHandler.java +++ b/driver/src/main/java/com/arangodb/internal/net/RoundRobinHostHandler.java @@ -22,6 +22,7 @@ import com.arangodb.ArangoDBException; import com.arangodb.ArangoDBMultipleException; +import com.arangodb.config.HostDescription; import java.util.ArrayList; import java.util.List; diff --git a/driver/src/main/java/com/arangodb/internal/util/HostUtils.java b/driver/src/main/java/com/arangodb/internal/util/HostUtils.java index 094830f5f..c03d955b0 100644 --- a/driver/src/main/java/com/arangodb/internal/util/HostUtils.java +++ b/driver/src/main/java/com/arangodb/internal/util/HostUtils.java @@ -20,6 +20,7 @@ package com.arangodb.internal.util; +import com.arangodb.config.HostDescription; import com.arangodb.internal.net.*; /** diff --git a/driver/src/main/java/com/arangodb/internal/velocystream/VstCommunication.java b/driver/src/main/java/com/arangodb/internal/velocystream/VstCommunication.java index 430af425f..9276834bc 100644 --- a/driver/src/main/java/com/arangodb/internal/velocystream/VstCommunication.java +++ b/driver/src/main/java/com/arangodb/internal/velocystream/VstCommunication.java @@ -21,6 +21,7 @@ package com.arangodb.internal.velocystream; import com.arangodb.ArangoDBException; +import com.arangodb.config.ArangoConfigProperties; import com.arangodb.internal.ArangoDefaults; import com.arangodb.internal.net.AccessType; import com.arangodb.internal.net.Host; @@ -71,7 +72,7 @@ protected VstCommunication(final Integer timeout, final String user, final Strin this.jwt = jwt; this.util = util; this.hostHandler = hostHandler; - this.chunksize = chunksize != null ? chunksize : ArangoDefaults.CHUNK_DEFAULT_CONTENT_SIZE; + this.chunksize = chunksize; } @SuppressWarnings("unchecked") diff --git a/driver/src/main/java/com/arangodb/internal/velocystream/VstCommunicationSync.java b/driver/src/main/java/com/arangodb/internal/velocystream/VstCommunicationSync.java index affd94887..f8416c74c 100644 --- a/driver/src/main/java/com/arangodb/internal/velocystream/VstCommunicationSync.java +++ b/driver/src/main/java/com/arangodb/internal/velocystream/VstCommunicationSync.java @@ -22,7 +22,7 @@ import com.arangodb.ArangoDBException; import com.arangodb.internal.net.ArangoDBRedirectException; -import com.arangodb.internal.net.HostDescription; +import com.arangodb.config.HostDescription; import com.arangodb.internal.net.HostHandle; import com.arangodb.internal.net.HostHandler; import com.arangodb.internal.serde.InternalSerde; diff --git a/driver/src/main/java/com/arangodb/internal/velocystream/VstConnectionFactorySync.java b/driver/src/main/java/com/arangodb/internal/velocystream/VstConnectionFactorySync.java index 902b1a2be..713e5a422 100644 --- a/driver/src/main/java/com/arangodb/internal/velocystream/VstConnectionFactorySync.java +++ b/driver/src/main/java/com/arangodb/internal/velocystream/VstConnectionFactorySync.java @@ -22,7 +22,7 @@ import com.arangodb.internal.net.Connection; import com.arangodb.internal.net.ConnectionFactory; -import com.arangodb.internal.net.HostDescription; +import com.arangodb.config.HostDescription; import com.arangodb.internal.velocystream.internal.MessageStore; import com.arangodb.internal.velocystream.internal.VstConnectionSync; diff --git a/driver/src/main/java/com/arangodb/internal/velocystream/internal/VstConnection.java b/driver/src/main/java/com/arangodb/internal/velocystream/internal/VstConnection.java index 9bb834f09..29d80e0ea 100644 --- a/driver/src/main/java/com/arangodb/internal/velocystream/internal/VstConnection.java +++ b/driver/src/main/java/com/arangodb/internal/velocystream/internal/VstConnection.java @@ -21,9 +21,10 @@ package com.arangodb.internal.velocystream.internal; import com.arangodb.ArangoDBException; +import com.arangodb.config.ArangoConfigProperties; import com.arangodb.internal.ArangoDefaults; import com.arangodb.internal.net.Connection; -import com.arangodb.internal.net.HostDescription; +import com.arangodb.config.HostDescription; import com.arangodb.velocypack.VPackBuilder; import com.arangodb.velocypack.VPackSlice; import com.arangodb.velocypack.ValueType; @@ -159,8 +160,7 @@ public synchronized void open() throws IOException { } else { socket = SocketFactory.getDefault().createSocket(); } - socket.connect(new InetSocketAddress(host.getHost(), host.getPort()), timeout != null ? timeout : - ArangoDefaults.DEFAULT_TIMEOUT); + socket.connect(new InetSocketAddress(host.getHost(), host.getPort()), timeout); socket.setKeepAlive(true); socket.setTcpNoDelay(true); if (LOGGER.isDebugEnabled()) { diff --git a/driver/src/main/java/com/arangodb/internal/velocystream/internal/VstConnectionSync.java b/driver/src/main/java/com/arangodb/internal/velocystream/internal/VstConnectionSync.java index 6530a0656..7c8b71384 100644 --- a/driver/src/main/java/com/arangodb/internal/velocystream/internal/VstConnectionSync.java +++ b/driver/src/main/java/com/arangodb/internal/velocystream/internal/VstConnectionSync.java @@ -21,7 +21,7 @@ package com.arangodb.internal.velocystream.internal; import com.arangodb.ArangoDBException; -import com.arangodb.internal.net.HostDescription; +import com.arangodb.config.HostDescription; import javax.net.ssl.SSLContext; import java.util.Collection; diff --git a/driver/src/test/java/com/arangodb/ArangoDBTest.java b/driver/src/test/java/com/arangodb/ArangoDBTest.java index fc7f6a35c..31b42bb9d 100644 --- a/driver/src/test/java/com/arangodb/ArangoDBTest.java +++ b/driver/src/test/java/com/arangodb/ArangoDBTest.java @@ -20,8 +20,8 @@ package com.arangodb; +import com.arangodb.config.ConfigUtils; import com.arangodb.entity.*; -import com.arangodb.internal.config.FileConfigPropertiesProvider; import com.arangodb.internal.serde.SerdeUtils; import com.arangodb.model.*; import com.arangodb.model.LogOptions.SortOrder; @@ -210,7 +210,7 @@ void createDatabaseWithUsers(ArangoDB arangoDB) throws InterruptedException { Thread.sleep(2_000); ArangoDB arangoDBTestUser = new ArangoDB.Builder() - .loadProperties(new FileConfigPropertiesProvider()) + .loadProperties(config) .user("testUser") .password("testPasswd") .build(); @@ -373,7 +373,7 @@ void updateUserDefaultCollectionAccess(ArangoDB arangoDB) { @Test void authenticationFailPassword() { final ArangoDB arangoDB = new ArangoDB.Builder() - .loadProperties(new FileConfigPropertiesProvider()) + .loadProperties(config) .password("no").jwt(null).build(); Throwable thrown = catchThrowable(arangoDB::getVersion); assertThat(thrown).isInstanceOf(ArangoDBException.class); @@ -384,7 +384,7 @@ void authenticationFailPassword() { @MethodSource("arangos") void authenticationFailUser() { final ArangoDB arangoDB = new ArangoDB.Builder() - .loadProperties(new FileConfigPropertiesProvider()) + .loadProperties(config) .user("no").jwt(null).build(); Throwable thrown = catchThrowable(arangoDB::getVersion); assertThat(thrown).isInstanceOf(ArangoDBException.class); @@ -589,7 +589,7 @@ void arangoDBException(ArangoDB arangoDB) { @MethodSource("arangos") void fallbackHost() { final ArangoDB arangoDB = new ArangoDB.Builder() - .loadProperties(new FileConfigPropertiesProvider()) + .loadProperties(config) .host("not-accessible", 8529).host("127.0.0.1", 8529).build(); final ArangoDBVersion version = arangoDB.getVersion(); assertThat(version).isNotNull(); @@ -599,16 +599,16 @@ void fallbackHost() { @MethodSource("arangos") void loadproperties() { Throwable thrown = catchThrowable(() -> new ArangoDB.Builder() - .loadProperties(new FileConfigPropertiesProvider("arangodb", "arangodb-bad.properties")) + .loadProperties(ConfigUtils.loadConfig("arangodb-bad.properties")) ); - assertThat(thrown).isInstanceOf(ArangoDBException.class); + assertThat(thrown).isInstanceOf(IllegalArgumentException.class); } @ParameterizedTest(name = "{index}") @MethodSource("arangos") void loadpropertiesWithPrefix() { ArangoDB adb = new ArangoDB.Builder() - .loadProperties(new FileConfigPropertiesProvider("adb", "arangodb-with-prefix.properties")) + .loadProperties(ConfigUtils.loadConfig("arangodb-with-prefix.properties", "adb")) .build(); adb.getVersion(); adb.shutdown(); diff --git a/driver/src/test/java/com/arangodb/BaseJunit5.java b/driver/src/test/java/com/arangodb/BaseJunit5.java index ed1813514..3e6c8e30a 100644 --- a/driver/src/test/java/com/arangodb/BaseJunit5.java +++ b/driver/src/test/java/com/arangodb/BaseJunit5.java @@ -1,7 +1,8 @@ package com.arangodb; +import com.arangodb.config.ArangoConfigProperties; +import com.arangodb.config.ConfigUtils; import com.arangodb.entity.*; -import com.arangodb.internal.config.FileConfigPropertiesProvider; import com.arangodb.model.CollectionCreateOptions; import com.arangodb.model.GraphCreateOptions; import com.arangodb.util.TestUtils; @@ -17,13 +18,13 @@ class BaseJunit5 { protected static final DbName TEST_DB = DbName.of("java_driver_test_db"); - + protected static final ArangoConfigProperties config = ConfigUtils.loadConfig(); private static final List adbs = Arrays.asList( - new ArangoDB.Builder().loadProperties(new FileConfigPropertiesProvider()).useProtocol(Protocol.VST).build(), - new ArangoDB.Builder().loadProperties(new FileConfigPropertiesProvider()).useProtocol(Protocol.HTTP_VPACK).build(), - new ArangoDB.Builder().loadProperties(new FileConfigPropertiesProvider()).useProtocol(Protocol.HTTP_JSON).build(), - new ArangoDB.Builder().loadProperties(new FileConfigPropertiesProvider()).useProtocol(Protocol.HTTP2_VPACK).build(), - new ArangoDB.Builder().loadProperties(new FileConfigPropertiesProvider()).useProtocol(Protocol.HTTP2_JSON).build() + new ArangoDB.Builder().loadProperties(config).useProtocol(Protocol.VST).build(), + new ArangoDB.Builder().loadProperties(config).useProtocol(Protocol.HTTP_VPACK).build(), + new ArangoDB.Builder().loadProperties(config).useProtocol(Protocol.HTTP_JSON).build(), + new ArangoDB.Builder().loadProperties(config).useProtocol(Protocol.HTTP2_VPACK).build(), + new ArangoDB.Builder().loadProperties(config).useProtocol(Protocol.HTTP2_JSON).build() ); protected static Stream dbsStream() { diff --git a/driver/src/test/java/com/arangodb/ConcurrencyTests.java b/driver/src/test/java/com/arangodb/ConcurrencyTests.java index 1103cb6df..3efdacc9c 100644 --- a/driver/src/test/java/com/arangodb/ConcurrencyTests.java +++ b/driver/src/test/java/com/arangodb/ConcurrencyTests.java @@ -1,6 +1,6 @@ package com.arangodb; -import com.arangodb.internal.config.FileConfigPropertiesProvider; +import com.arangodb.config.ConfigUtils; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.EnumSource; @@ -19,7 +19,7 @@ class ConcurrencyTests { void concurrentPendingRequests(Protocol protocol) throws ExecutionException, InterruptedException { ExecutorService es = Executors.newFixedThreadPool(10); ArangoDB adb = new ArangoDB.Builder() - .loadProperties(new FileConfigPropertiesProvider()) + .loadProperties(ConfigUtils.loadConfig()) .useProtocol(protocol).build(); List> futures = IntStream.range(0, 10) .mapToObj(__ -> CompletableFuture.runAsync(() -> adb.db().query("RETURN SLEEP(1)", Void.class), es)) diff --git a/driver/src/test/java/com/arangodb/JwtAuthTest.java b/driver/src/test/java/com/arangodb/JwtAuthTest.java index 34d41a751..d2127e7ba 100644 --- a/driver/src/test/java/com/arangodb/JwtAuthTest.java +++ b/driver/src/test/java/com/arangodb/JwtAuthTest.java @@ -1,6 +1,6 @@ package com.arangodb; -import com.arangodb.internal.config.FileConfigPropertiesProvider; +import com.arangodb.config.ConfigUtils; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.EnumSource; @@ -23,7 +23,7 @@ class JwtAuthTest { @BeforeAll static void init() { ArangoDB arangoDB = new ArangoDB.Builder() - .loadProperties(new FileConfigPropertiesProvider()) + .loadProperties(ConfigUtils.loadConfig()) .build(); jwt = getJwt(arangoDB); arangoDB.shutdown(); @@ -88,7 +88,7 @@ void updateJwt(Protocol protocol) { private ArangoDB.Builder getBuilder(Protocol protocol) { return new ArangoDB.Builder() - .loadProperties(new FileConfigPropertiesProvider()) + .loadProperties(ConfigUtils.loadConfig()) .useProtocol(protocol) .jwt(null) // unset credentials from properties file .user(null) // unset credentials from properties file diff --git a/driver/src/test/java/com/arangodb/PackageVersionTest.java b/driver/src/test/java/com/arangodb/PackageVersionTest.java index f680486ad..afef0ee5c 100644 --- a/driver/src/test/java/com/arangodb/PackageVersionTest.java +++ b/driver/src/test/java/com/arangodb/PackageVersionTest.java @@ -1,6 +1,5 @@ package com.arangodb; -import com.arangodb.internal.config.FileConfigPropertiesProvider; import com.fasterxml.jackson.databind.JsonNode; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; @@ -38,7 +37,7 @@ void packageVersion() { void userAgentHeader(Protocol protocol) { assumeTrue(protocol != Protocol.VST); ArangoDB adb = new ArangoDB.Builder() - .loadProperties(new FileConfigPropertiesProvider()) + .loadProperties(config) .useProtocol(protocol) .build(); diff --git a/driver/src/test/java/com/arangodb/ParallelTest.java b/driver/src/test/java/com/arangodb/ParallelTest.java index 2df8079bb..9c4b98f96 100644 --- a/driver/src/test/java/com/arangodb/ParallelTest.java +++ b/driver/src/test/java/com/arangodb/ParallelTest.java @@ -1,6 +1,6 @@ package com.arangodb; -import com.arangodb.internal.config.FileConfigPropertiesProvider; +import com.arangodb.config.ConfigUtils; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.EnumSource; @@ -22,7 +22,7 @@ void connectionParallelism(Protocol protocol) throws InterruptedException { // BTS-1102: the server does not run pipelined HTTP/1.1 requests in parallel assumeTrue(protocol != Protocol.HTTP_JSON && protocol != Protocol.HTTP_VPACK); ArangoDB adb = new ArangoDB.Builder() - .loadProperties(new FileConfigPropertiesProvider()) + .loadProperties(ConfigUtils.loadConfig()) .useProtocol(protocol) .maxConnections(1) .build(); diff --git a/driver/src/test/java/com/arangodb/async/ArangoDBTest.java b/driver/src/test/java/com/arangodb/async/ArangoDBTest.java index 34d645582..2a76db54c 100644 --- a/driver/src/test/java/com/arangodb/async/ArangoDBTest.java +++ b/driver/src/test/java/com/arangodb/async/ArangoDBTest.java @@ -21,8 +21,8 @@ package com.arangodb.async; import com.arangodb.*; +import com.arangodb.config.ConfigUtils; import com.arangodb.entity.*; -import com.arangodb.internal.config.FileConfigPropertiesProvider; import com.arangodb.internal.serde.SerdeUtils; import com.arangodb.model.*; import com.arangodb.util.RawJson; @@ -56,10 +56,10 @@ class ArangoDBTest { private static Boolean extendedNames; private final ArangoDBAsync arangoDB = new ArangoDBAsync.Builder() - .loadProperties(new FileConfigPropertiesProvider()) + .loadProperties(ConfigUtils.loadConfig()) .build(); private final ArangoDB arangoDBSync = new ArangoDB.Builder() - .loadProperties(new FileConfigPropertiesProvider()) + .loadProperties(ConfigUtils.loadConfig()) .build(); private boolean isEnterprise() { @@ -418,7 +418,7 @@ void updateUserDefaultCollectionAccess() throws InterruptedException, ExecutionE @Test void authenticationFailPassword() throws InterruptedException { final ArangoDBAsync arangoDB = new ArangoDBAsync.Builder() - .loadProperties(new FileConfigPropertiesProvider()) + .loadProperties(ConfigUtils.loadConfig()) .password("no").jwt(null).build(); try { arangoDB.getVersion().get(); @@ -431,7 +431,7 @@ void authenticationFailPassword() throws InterruptedException { @Test void authenticationFailUser() throws InterruptedException { final ArangoDBAsync arangoDB = new ArangoDBAsync.Builder() - .loadProperties(new FileConfigPropertiesProvider()) + .loadProperties(ConfigUtils.loadConfig()) .user("no").jwt(null).build(); try { arangoDB.getVersion().get(); @@ -459,7 +459,7 @@ void execute() throws InterruptedException, ExecutionException { @Test void execute_acquireHostList_enabled() throws InterruptedException, ExecutionException { final ArangoDBAsync arangoDB = new ArangoDBAsync.Builder() - .loadProperties(new FileConfigPropertiesProvider()) + .loadProperties(ConfigUtils.loadConfig()) .acquireHostList(true).build(); arangoDB .execute(Request.builder() diff --git a/driver/src/test/java/com/arangodb/async/BaseTest.java b/driver/src/test/java/com/arangodb/async/BaseTest.java index 354e689f8..261996ab9 100644 --- a/driver/src/test/java/com/arangodb/async/BaseTest.java +++ b/driver/src/test/java/com/arangodb/async/BaseTest.java @@ -21,10 +21,11 @@ package com.arangodb.async; import com.arangodb.DbName; +import com.arangodb.config.ArangoConfigProperties; +import com.arangodb.config.ConfigUtils; import com.arangodb.entity.ArangoDBEngine; import com.arangodb.entity.License; import com.arangodb.entity.ServerRole; -import com.arangodb.internal.config.FileConfigPropertiesProvider; import com.arangodb.util.TestUtils; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; @@ -37,7 +38,7 @@ * @author Mark Vollmary */ public abstract class BaseTest { - + protected static final ArangoConfigProperties config = ConfigUtils.loadConfig(); static final DbName TEST_DB = DbName.of("java_driver_test_db"); static ArangoDBAsync arangoDB; static ArangoDatabaseAsync db; @@ -46,7 +47,7 @@ public abstract class BaseTest { static void init() throws InterruptedException, ExecutionException { if (arangoDB == null) { arangoDB = new ArangoDBAsync.Builder() - .loadProperties(new FileConfigPropertiesProvider()) + .loadProperties(ConfigUtils.loadConfig()) .build(); } diff --git a/driver/src/test/java/com/arangodb/async/ConcurrencyTests.java b/driver/src/test/java/com/arangodb/async/ConcurrencyTests.java index 504c550a7..278486efc 100644 --- a/driver/src/test/java/com/arangodb/async/ConcurrencyTests.java +++ b/driver/src/test/java/com/arangodb/async/ConcurrencyTests.java @@ -1,7 +1,7 @@ package com.arangodb.async; -import com.arangodb.internal.config.FileConfigPropertiesProvider; +import com.arangodb.config.ConfigUtils; import org.junit.jupiter.api.Test; import java.util.List; @@ -15,7 +15,7 @@ class ConcurrencyTests { @Test void concurrentPendingRequests() throws ExecutionException, InterruptedException { ArangoDBAsync adb = new ArangoDBAsync.Builder() - .loadProperties(new FileConfigPropertiesProvider()) + .loadProperties(ConfigUtils.loadConfig()) .build(); List>> reqs = IntStream.range(0, 10) .mapToObj(__ -> adb.db().query("RETURN SLEEP(1)", Void.class)) diff --git a/driver/src/test/java/com/arangodb/async/JwtAuthTest.java b/driver/src/test/java/com/arangodb/async/JwtAuthTest.java index f821f3ea9..04bbfc98d 100644 --- a/driver/src/test/java/com/arangodb/async/JwtAuthTest.java +++ b/driver/src/test/java/com/arangodb/async/JwtAuthTest.java @@ -1,7 +1,7 @@ package com.arangodb.async; import com.arangodb.*; -import com.arangodb.internal.config.FileConfigPropertiesProvider; +import com.arangodb.config.ConfigUtils; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Disabled; @@ -22,7 +22,7 @@ class JwtAuthTest { @BeforeAll static void init() { ArangoDB arangoDB = new ArangoDB.Builder() - .loadProperties(new FileConfigPropertiesProvider()) + .loadProperties(ConfigUtils.loadConfig()) .build(); jwt = getJwt(arangoDB); arangoDB.shutdown(); @@ -95,7 +95,7 @@ void updateJwt() throws ExecutionException, InterruptedException { private ArangoDBAsync.Builder getBuilder() { return new ArangoDBAsync.Builder() - .loadProperties(new FileConfigPropertiesProvider()) + .loadProperties(ConfigUtils.loadConfig()) .jwt(null) // unset credentials from properties file .user(null) // unset credentials from properties file .password(null); // unset credentials from properties file diff --git a/driver/src/test/java/com/arangodb/async/debug/ConsolidationIntervalMsecTest.java b/driver/src/test/java/com/arangodb/async/debug/ConsolidationIntervalMsecTest.java index 5a3d0ddad..330ce8eb9 100644 --- a/driver/src/test/java/com/arangodb/async/debug/ConsolidationIntervalMsecTest.java +++ b/driver/src/test/java/com/arangodb/async/debug/ConsolidationIntervalMsecTest.java @@ -29,7 +29,6 @@ import com.arangodb.entity.arangosearch.ArangoSearchPropertiesEntity; import com.arangodb.entity.arangosearch.CollectionLink; import com.arangodb.entity.arangosearch.FieldLink; -import com.arangodb.internal.config.FileConfigPropertiesProvider; import com.arangodb.model.arangosearch.ArangoSearchCreateOptions; import org.junit.jupiter.api.Test; @@ -50,7 +49,7 @@ void consolidationIntervalMsec() throws ExecutionException, InterruptedException assumeTrue(isAtLeastVersion(3, 4)); ArangoDBAsync arango = new ArangoDBAsync.Builder() - .loadProperties(new FileConfigPropertiesProvider()) + .loadProperties(config) .user("root") .password("test") .build(); diff --git a/driver/src/test/java/com/arangodb/async/example/ExampleBase.java b/driver/src/test/java/com/arangodb/async/example/ExampleBase.java index 9c1ce81e2..7881fd617 100644 --- a/driver/src/test/java/com/arangodb/async/example/ExampleBase.java +++ b/driver/src/test/java/com/arangodb/async/example/ExampleBase.java @@ -24,7 +24,7 @@ import com.arangodb.async.ArangoCollectionAsync; import com.arangodb.async.ArangoDBAsync; import com.arangodb.async.ArangoDatabaseAsync; -import com.arangodb.internal.config.FileConfigPropertiesProvider; +import com.arangodb.config.ConfigUtils; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; @@ -44,7 +44,7 @@ public class ExampleBase { @BeforeAll static void setUp() throws InterruptedException, ExecutionException { arangoDB = new ArangoDBAsync.Builder() - .loadProperties(new FileConfigPropertiesProvider()) + .loadProperties(ConfigUtils.loadConfig()) .build(); if (arangoDB.db(DB_NAME).exists().get()) { arangoDB.db(DB_NAME).drop().get(); diff --git a/driver/src/test/java/com/arangodb/async/example/graph/AQLActorsAndMoviesExampleTest.java b/driver/src/test/java/com/arangodb/async/example/graph/AQLActorsAndMoviesExampleTest.java index 259cc4451..d21f78f02 100644 --- a/driver/src/test/java/com/arangodb/async/example/graph/AQLActorsAndMoviesExampleTest.java +++ b/driver/src/test/java/com/arangodb/async/example/graph/AQLActorsAndMoviesExampleTest.java @@ -25,11 +25,11 @@ import com.arangodb.async.ArangoCursorAsync; import com.arangodb.async.ArangoDBAsync; import com.arangodb.async.ArangoDatabaseAsync; +import com.arangodb.config.ConfigUtils; import com.arangodb.entity.BaseDocument; import com.arangodb.entity.BaseEdgeDocument; import com.arangodb.entity.CollectionType; import com.arangodb.entity.DocumentCreateEntity; -import com.arangodb.internal.config.FileConfigPropertiesProvider; import com.arangodb.model.CollectionCreateOptions; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; @@ -59,7 +59,7 @@ class AQLActorsAndMoviesExampleTest { @BeforeAll static void setUp() throws InterruptedException, ExecutionException { arangoDB = new ArangoDBAsync.Builder() - .loadProperties(new FileConfigPropertiesProvider()) + .loadProperties(ConfigUtils.loadConfig()) .build(); if (arangoDB.db(TEST_DB).exists().get()) { arangoDB.db(TEST_DB).drop().get(); diff --git a/driver/src/test/java/com/arangodb/async/example/graph/BaseGraphTest.java b/driver/src/test/java/com/arangodb/async/example/graph/BaseGraphTest.java index 8a16b9231..41a4e6edf 100644 --- a/driver/src/test/java/com/arangodb/async/example/graph/BaseGraphTest.java +++ b/driver/src/test/java/com/arangodb/async/example/graph/BaseGraphTest.java @@ -23,9 +23,9 @@ import com.arangodb.DbName; import com.arangodb.async.ArangoDBAsync; import com.arangodb.async.ArangoDatabaseAsync; +import com.arangodb.config.ConfigUtils; import com.arangodb.entity.EdgeDefinition; import com.arangodb.entity.VertexEntity; -import com.arangodb.internal.config.FileConfigPropertiesProvider; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; @@ -49,7 +49,7 @@ public abstract class BaseGraphTest { static void init() throws InterruptedException, ExecutionException { if (arangoDB == null) { arangoDB = new ArangoDBAsync.Builder() - .loadProperties(new FileConfigPropertiesProvider()) + .loadProperties(ConfigUtils.loadConfig()) .build(); } if (arangoDB.db(TEST_DB).exists().get()) { diff --git a/driver/src/test/java/com/arangodb/async/serde/CustomSerdeTest.java b/driver/src/test/java/com/arangodb/async/serde/CustomSerdeTest.java index 982381db9..fdca9d3c0 100644 --- a/driver/src/test/java/com/arangodb/async/serde/CustomSerdeTest.java +++ b/driver/src/test/java/com/arangodb/async/serde/CustomSerdeTest.java @@ -25,7 +25,7 @@ import com.arangodb.async.ArangoCollectionAsync; import com.arangodb.async.ArangoDBAsync; import com.arangodb.async.ArangoDatabaseAsync; -import com.arangodb.internal.config.FileConfigPropertiesProvider; +import com.arangodb.config.ConfigUtils; import com.arangodb.model.DocumentCreateOptions; import com.arangodb.ContentType; import com.arangodb.serde.jackson.JacksonSerde; @@ -64,7 +64,7 @@ void init() throws ExecutionException, InterruptedException { mapper.configure(USE_BIG_INTEGER_FOR_INTS, true); }); ArangoDBAsync arangoDB = new ArangoDBAsync.Builder() - .loadProperties(new FileConfigPropertiesProvider()) + .loadProperties(ConfigUtils.loadConfig()) .serializer(serde).build(); DbName TEST_DB = DbName.of("custom-serde-test"); diff --git a/driver/src/test/java/com/arangodb/config/ArangoConfigPropertiesMPImpl.java b/driver/src/test/java/com/arangodb/config/ArangoConfigPropertiesMPImpl.java new file mode 100644 index 000000000..940d0a2dd --- /dev/null +++ b/driver/src/test/java/com/arangodb/config/ArangoConfigPropertiesMPImpl.java @@ -0,0 +1,145 @@ +package com.arangodb.config; + +import com.arangodb.Protocol; +import com.arangodb.entity.LoadBalancingStrategy; + +import java.util.List; +import java.util.Objects; +import java.util.Optional; + +/** + * Implementation of ArangoConfigProperties compatible with MicroProfile Config. + */ +public final class ArangoConfigPropertiesMPImpl implements ArangoConfigProperties { + private Optional> hosts; + private Optional protocol; + private Optional user; + private Optional password; + private Optional jwt; + private Optional timeout; + private Optional useSsl; + private Optional verifyHost; + private Optional chunkSize; + private Optional maxConnections; + private Optional connectionTtl; + private Optional keepAliveInterval; + private Optional acquireHostList; + private Optional acquireHostListInterval; + private Optional loadBalancingStrategy; + private Optional responseQueueTimeSamples; + + @Override + public Optional> getHosts() { + return hosts; + } + + @Override + public Optional getProtocol() { + return protocol; + } + + @Override + public Optional getUser() { + return user; + } + + @Override + public Optional getPassword() { + return password; + } + + @Override + public Optional getJwt() { + return jwt; + } + + @Override + public Optional getTimeout() { + return timeout; + } + + @Override + public Optional getUseSsl() { + return useSsl; + } + + @Override + public Optional getVerifyHost() { + return verifyHost; + } + + @Override + public Optional getChunkSize() { + return chunkSize; + } + + @Override + public Optional getMaxConnections() { + return maxConnections; + } + + @Override + public Optional getConnectionTtl() { + return connectionTtl; + } + + @Override + public Optional getKeepAliveInterval() { + return keepAliveInterval; + } + + @Override + public Optional getAcquireHostList() { + return acquireHostList; + } + + @Override + public Optional getAcquireHostListInterval() { + return acquireHostListInterval; + } + + @Override + public Optional getLoadBalancingStrategy() { + return loadBalancingStrategy; + } + + @Override + public Optional getResponseQueueTimeSamples() { + return responseQueueTimeSamples; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + ArangoConfigPropertiesMPImpl that = (ArangoConfigPropertiesMPImpl) o; + return Objects.equals(hosts, that.hosts) && Objects.equals(protocol, that.protocol) && Objects.equals(user, that.user) && Objects.equals(password, that.password) && Objects.equals(jwt, that.jwt) && Objects.equals(timeout, that.timeout) && Objects.equals(useSsl, that.useSsl) && Objects.equals(verifyHost, that.verifyHost) && Objects.equals(chunkSize, that.chunkSize) && Objects.equals(maxConnections, that.maxConnections) && Objects.equals(connectionTtl, that.connectionTtl) && Objects.equals(keepAliveInterval, that.keepAliveInterval) && Objects.equals(acquireHostList, that.acquireHostList) && Objects.equals(acquireHostListInterval, that.acquireHostListInterval) && Objects.equals(loadBalancingStrategy, that.loadBalancingStrategy) && Objects.equals(responseQueueTimeSamples, that.responseQueueTimeSamples); + } + + @Override + public int hashCode() { + return Objects.hash(hosts, protocol, user, password, jwt, timeout, useSsl, verifyHost, chunkSize, maxConnections, connectionTtl, keepAliveInterval, acquireHostList, acquireHostListInterval, loadBalancingStrategy, responseQueueTimeSamples); + } + + @Override + public String toString() { + return "ArangoConfigPropertiesImpl{" + + "hosts=" + hosts + + ", protocol=" + protocol + + ", user=" + user + + ", password=" + password + + ", jwt=" + jwt + + ", timeout=" + timeout + + ", useSsl=" + useSsl + + ", verifyHost=" + verifyHost + + ", chunkSize=" + chunkSize + + ", maxConnections=" + maxConnections + + ", connectionTtl=" + connectionTtl + + ", keepAliveInterval=" + keepAliveInterval + + ", acquireHostList=" + acquireHostList + + ", acquireHostListInterval=" + acquireHostListInterval + + ", loadBalancingStrategy=" + loadBalancingStrategy + + ", responseQueueTimeSamples=" + responseQueueTimeSamples + + '}'; + } +} diff --git a/driver/src/test/java/com/arangodb/config/ConfigDefaultsTest.java b/driver/src/test/java/com/arangodb/config/ConfigDefaultsTest.java new file mode 100644 index 000000000..e4fad9c3c --- /dev/null +++ b/driver/src/test/java/com/arangodb/config/ConfigDefaultsTest.java @@ -0,0 +1,34 @@ +package com.arangodb.config; + +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +class ConfigDefaultsTest { + + @Test + void defaultValues() { + ArangoConfigProperties config = ConfigUtils.loadConfigMP("arangodb.properties", "wrong"); + checkResult(config); + } + + private void checkResult(ArangoConfigProperties config) { + assertThat(config.getHosts()).isEmpty(); + assertThat(config.getProtocol()).isEmpty(); + assertThat(config.getUser()).isEmpty(); + assertThat(config.getPassword()).isNotPresent(); + assertThat(config.getJwt()).isNotPresent(); + assertThat(config.getTimeout()).isEmpty(); + assertThat(config.getUseSsl()).isEmpty(); + assertThat(config.getVerifyHost()).isEmpty(); + assertThat(config.getChunkSize()).isEmpty(); + assertThat(config.getMaxConnections()).isNotPresent(); + assertThat(config.getConnectionTtl()).isNotPresent(); + assertThat(config.getKeepAliveInterval()).isNotPresent(); + assertThat(config.getAcquireHostList()).isEmpty(); + assertThat(config.getAcquireHostListInterval()).isEmpty(); + assertThat(config.getLoadBalancingStrategy()).isEmpty(); + assertThat(config.getResponseQueueTimeSamples()).isEmpty(); + } + +} diff --git a/driver/src/test/java/com/arangodb/config/ConfigTest.java b/driver/src/test/java/com/arangodb/config/ConfigTest.java new file mode 100644 index 000000000..8e8f4228e --- /dev/null +++ b/driver/src/test/java/com/arangodb/config/ConfigTest.java @@ -0,0 +1,66 @@ +package com.arangodb.config; + +import com.arangodb.Protocol; +import com.arangodb.entity.LoadBalancingStrategy; +import org.assertj.core.api.InstanceOfAssertFactories; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +class ConfigTest { + private final HostDescription hostA = new HostDescription("aaa", 1111); + private final HostDescription hostB = new HostDescription("bbb", 2222); + private final Protocol protocol = Protocol.HTTP_VPACK; + private final String user = "testUser"; + private final String password = "testPassword"; + private final String jwt = "testJwt"; + private final Integer timeout = 9876; + private final Boolean useSsl = true; + private final Boolean verifyHost = false; + private final Integer vstChunkSize = 1234; + private final Integer maxConnections = 123; + private final Long connectionTtl = 12345L; + private final Integer keepAliveInterval = 123456; + private final Boolean acquireHostList = true; + private final Integer acquireHostListInterval = 1234567; + private final LoadBalancingStrategy loadBalancingStrategy = LoadBalancingStrategy.ROUND_ROBIN; + private final Integer responseQueueTimeSamples = 12345678; + + @Test + void readConfig() { + ArangoConfigProperties config = ConfigUtils.loadConfigMP("arangodb-config-test.properties", "adb"); + checkResult(config); + } + + private void checkResult(ArangoConfigProperties config) { + assertThat(config.getHosts()) + .isPresent() + .get(InstanceOfAssertFactories.LIST) + .containsExactly(hostA, hostB); + assertThat(config.getProtocol()).hasValue(protocol); + assertThat(config.getUser()).hasValue(user); + assertThat(config.getPassword()) + .isPresent() + .hasValue(password); + assertThat(config.getJwt()) + .isPresent() + .hasValue(jwt); + assertThat(config.getTimeout()).hasValue(timeout); + assertThat(config.getUseSsl()).hasValue(useSsl); + assertThat(config.getVerifyHost()).hasValue(verifyHost); + assertThat(config.getChunkSize()).hasValue(vstChunkSize); + assertThat(config.getMaxConnections()) + .isPresent() + .hasValue(maxConnections); + assertThat(config.getConnectionTtl()) + .isPresent() + .hasValue(connectionTtl); + assertThat(config.getKeepAliveInterval()) + .isPresent() + .hasValue(keepAliveInterval); + assertThat(config.getAcquireHostList()).hasValue(acquireHostList); + assertThat(config.getAcquireHostListInterval()).hasValue(acquireHostListInterval); + assertThat(config.getLoadBalancingStrategy()).hasValue(loadBalancingStrategy); + assertThat(config.getResponseQueueTimeSamples()).hasValue(responseQueueTimeSamples); + } +} diff --git a/driver/src/test/java/com/arangodb/config/ConfigUtils.java b/driver/src/test/java/com/arangodb/config/ConfigUtils.java new file mode 100644 index 000000000..99b12ca34 --- /dev/null +++ b/driver/src/test/java/com/arangodb/config/ConfigUtils.java @@ -0,0 +1,37 @@ +package com.arangodb.config; + +import io.smallrye.config.PropertiesConfigSourceProvider; +import io.smallrye.config.SmallRyeConfig; +import io.smallrye.config.SmallRyeConfigBuilder; + +public class ConfigUtils { + + public static ArangoConfigProperties loadConfigMP() { + return loadConfigMP("arangodb.properties"); + } + + public static ArangoConfigProperties loadConfigMP(final String location) { + return loadConfigMP(location, "arangodb"); + } + + public static ArangoConfigProperties loadConfigMP(final String location, final String prefix) { + SmallRyeConfig cfg = new SmallRyeConfigBuilder() + .withSources(new PropertiesConfigSourceProvider(location, ConfigUtils.class.getClassLoader(), false)) + .withMapping(ArangoConfigPropertiesMPImpl.class, prefix) + .build(); + return cfg.getConfigMapping(ArangoConfigPropertiesMPImpl.class, prefix); + } + + public static ArangoConfigProperties loadConfig() { + return ArangoConfigProperties.fromFile(); + } + + public static ArangoConfigProperties loadConfig(final String location) { + return ArangoConfigProperties.fromFile(location); + } + + public static ArangoConfigProperties loadConfig(final String location, final String prefix) { + return ArangoConfigProperties.fromFile(location, prefix); + } + +} diff --git a/driver/src/test/java/com/arangodb/example/ExampleBase.java b/driver/src/test/java/com/arangodb/example/ExampleBase.java index c99610836..01399b1cb 100644 --- a/driver/src/test/java/com/arangodb/example/ExampleBase.java +++ b/driver/src/test/java/com/arangodb/example/ExampleBase.java @@ -24,7 +24,7 @@ import com.arangodb.ArangoDB; import com.arangodb.ArangoDatabase; import com.arangodb.DbName; -import com.arangodb.internal.config.FileConfigPropertiesProvider; +import com.arangodb.config.ConfigUtils; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; @@ -42,7 +42,7 @@ public class ExampleBase { @BeforeAll static void setUp() { arangoDB = new ArangoDB.Builder() - .loadProperties(new FileConfigPropertiesProvider()) + .loadProperties(ConfigUtils.loadConfig()) .build(); DbName dbName = DbName.of(DB_NAME); if (arangoDB.db(dbName).exists()) diff --git a/driver/src/test/java/com/arangodb/example/graph/AQLActorsAndMoviesExampleTest.java b/driver/src/test/java/com/arangodb/example/graph/AQLActorsAndMoviesExampleTest.java index 682bed1b1..c23b4097d 100644 --- a/driver/src/test/java/com/arangodb/example/graph/AQLActorsAndMoviesExampleTest.java +++ b/driver/src/test/java/com/arangodb/example/graph/AQLActorsAndMoviesExampleTest.java @@ -21,11 +21,11 @@ package com.arangodb.example.graph; import com.arangodb.*; +import com.arangodb.config.ConfigUtils; import com.arangodb.entity.BaseDocument; import com.arangodb.entity.BaseEdgeDocument; import com.arangodb.entity.CollectionType; import com.arangodb.entity.DocumentCreateEntity; -import com.arangodb.internal.config.FileConfigPropertiesProvider; import com.arangodb.model.CollectionCreateOptions; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; @@ -53,7 +53,7 @@ class AQLActorsAndMoviesExampleTest { @BeforeAll static void setUp() { arangoDB = new ArangoDB.Builder() - .loadProperties(new FileConfigPropertiesProvider()) + .loadProperties(ConfigUtils.loadConfig()) .build(); if (arangoDB.db(TEST_DB).exists()) arangoDB.db(TEST_DB).drop(); diff --git a/driver/src/test/java/com/arangodb/example/graph/BaseGraphTest.java b/driver/src/test/java/com/arangodb/example/graph/BaseGraphTest.java index 514af943f..8b742e52d 100644 --- a/driver/src/test/java/com/arangodb/example/graph/BaseGraphTest.java +++ b/driver/src/test/java/com/arangodb/example/graph/BaseGraphTest.java @@ -24,9 +24,9 @@ import com.arangodb.ArangoDBException; import com.arangodb.ArangoDatabase; import com.arangodb.DbName; +import com.arangodb.config.ConfigUtils; import com.arangodb.entity.EdgeDefinition; import com.arangodb.entity.VertexEntity; -import com.arangodb.internal.config.FileConfigPropertiesProvider; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; @@ -49,7 +49,7 @@ abstract class BaseGraphTest { static void init() { if (arangoDB == null) { arangoDB = new ArangoDB.Builder() - .loadProperties(new FileConfigPropertiesProvider()) + .loadProperties(ConfigUtils.loadConfig()) .build(); } if (arangoDB.db(TEST_DB).exists()) diff --git a/driver/src/test/java/com/arangodb/internal/HostHandlerTest.java b/driver/src/test/java/com/arangodb/internal/HostHandlerTest.java index ceff3a79e..973d3a7c1 100644 --- a/driver/src/test/java/com/arangodb/internal/HostHandlerTest.java +++ b/driver/src/test/java/com/arangodb/internal/HostHandlerTest.java @@ -22,6 +22,7 @@ import com.arangodb.ArangoDBException; import com.arangodb.ArangoDBMultipleException; +import com.arangodb.config.HostDescription; import com.arangodb.internal.net.*; import com.arangodb.internal.serde.InternalSerde; import org.junit.jupiter.api.Test; diff --git a/driver/src/test/java/com/arangodb/internal/velocystream/CommunicationTest.java b/driver/src/test/java/com/arangodb/internal/velocystream/CommunicationTest.java index bfdeb444a..120939786 100644 --- a/driver/src/test/java/com/arangodb/internal/velocystream/CommunicationTest.java +++ b/driver/src/test/java/com/arangodb/internal/velocystream/CommunicationTest.java @@ -22,8 +22,8 @@ import com.arangodb.ArangoDB; import com.arangodb.ArangoDatabase; +import com.arangodb.config.ConfigUtils; import com.arangodb.entity.ArangoDBVersion; -import com.arangodb.internal.config.FileConfigPropertiesProvider; import org.junit.jupiter.api.Test; import java.util.Collection; @@ -43,7 +43,7 @@ class CommunicationTest { @Test void chunkSizeSmall() { final ArangoDB arangoDB = new ArangoDB.Builder() - .loadProperties(new FileConfigPropertiesProvider()) + .loadProperties(ConfigUtils.loadConfig()) .chunksize(20).build(); final ArangoDBVersion version = arangoDB.getVersion(); assertThat(version).isNotNull(); @@ -52,7 +52,7 @@ void chunkSizeSmall() { @Test void multiThread() throws Exception { final ArangoDB arangoDB = new ArangoDB.Builder() - .loadProperties(new FileConfigPropertiesProvider()) + .loadProperties(ConfigUtils.loadConfig()) .build(); arangoDB.getUsers(); // authentication and active-failover connection redirect to master @@ -80,7 +80,7 @@ void multiThread() throws Exception { @Test void multiThreadSameDatabases() throws Exception { final ArangoDB arangoDB = new ArangoDB.Builder() - .loadProperties(new FileConfigPropertiesProvider()) + .loadProperties(ConfigUtils.loadConfig()) .build(); arangoDB.getUsers(); // authentication and active-failover connection redirect to master @@ -105,7 +105,7 @@ void multiThreadSameDatabases() throws Exception { @Test void minOneConnection() { final ArangoDB arangoDB = new ArangoDB.Builder() - .loadProperties(new FileConfigPropertiesProvider()) + .loadProperties(ConfigUtils.loadConfig()) .maxConnections(0).build(); final ArangoDBVersion version = arangoDB.getVersion(); assertThat(version).isNotNull(); @@ -114,7 +114,7 @@ void minOneConnection() { @Test void defaultMaxConnection() { final ArangoDB arangoDB = new ArangoDB.Builder() - .loadProperties(new FileConfigPropertiesProvider()) + .loadProperties(ConfigUtils.loadConfig()) .maxConnections(null).build(); final ArangoDBVersion version = arangoDB.getVersion(); assertThat(version).isNotNull(); diff --git a/driver/src/test/java/com/arangodb/serde/CustomSerdeTest.java b/driver/src/test/java/com/arangodb/serde/CustomSerdeTest.java index 428363da6..4e42730ba 100644 --- a/driver/src/test/java/com/arangodb/serde/CustomSerdeTest.java +++ b/driver/src/test/java/com/arangodb/serde/CustomSerdeTest.java @@ -22,7 +22,7 @@ import com.arangodb.*; -import com.arangodb.internal.config.FileConfigPropertiesProvider; +import com.arangodb.config.ConfigUtils; import com.arangodb.internal.serde.InternalSerde; import com.arangodb.model.DocumentCreateOptions; import com.arangodb.serde.jackson.JacksonSerde; @@ -72,7 +72,7 @@ static void init() { mapper.registerModule(module); }); arangoDB = new ArangoDB.Builder() - .loadProperties(new FileConfigPropertiesProvider()) + .loadProperties(ConfigUtils.loadConfig()) .useProtocol(Protocol.VST) .serde(serde).build(); diff --git a/driver/src/test/java/com/arangodb/serde/CustomTypeHintTest.java b/driver/src/test/java/com/arangodb/serde/CustomTypeHintTest.java index fed63354e..f8f79f444 100644 --- a/driver/src/test/java/com/arangodb/serde/CustomTypeHintTest.java +++ b/driver/src/test/java/com/arangodb/serde/CustomTypeHintTest.java @@ -25,7 +25,7 @@ import com.arangodb.ArangoDB; import com.arangodb.ArangoDatabase; import com.arangodb.DbName; -import com.arangodb.internal.config.FileConfigPropertiesProvider; +import com.arangodb.config.ConfigUtils; import com.arangodb.model.DocumentCreateOptions; import com.arangodb.serde.jackson.Key; import com.fasterxml.jackson.annotation.JsonTypeInfo; @@ -48,7 +48,7 @@ class CustomTypeHintTest { @BeforeEach void init() { ArangoDB arangoDB = new ArangoDB.Builder() - .loadProperties(new FileConfigPropertiesProvider()) + .loadProperties(ConfigUtils.loadConfig()) .build(); db = arangoDB.db(DbName.of("custom-serde-test")); diff --git a/driver/src/test/resources/arangodb-config-test.properties b/driver/src/test/resources/arangodb-config-test.properties new file mode 100644 index 000000000..48fe4f1ed --- /dev/null +++ b/driver/src/test/resources/arangodb-config-test.properties @@ -0,0 +1,17 @@ +adb.hosts=aaa:1111,bbb:2222 +adb.protocol=HTTP_VPACK +adb.user=testUser +adb.password=testPassword +adb.jwt=testJwt +adb.timeout=9876 +adb.useSsl=true +adb.verifyHost=false +adb.chunkSize=1234 +adb.maxConnections=123 +adb.connectionTtl=12345 +adb.keepAliveInterval=123456 +adb.acquireHostList=true +adb.acquireHostListInterval=1234567 +adb.loadBalancingStrategy=ROUND_ROBIN +adb.responseQueueTimeSamples=12345678 + diff --git a/driver/src/test/resources/arangodb.properties b/driver/src/test/resources/arangodb.properties index c47741102..fa580e439 100644 --- a/driver/src/test/resources/arangodb.properties +++ b/driver/src/test/resources/arangodb.properties @@ -2,4 +2,4 @@ arangodb.hosts=172.28.0.1:8529 arangodb.acquireHostList=true arangodb.password=test arangodb.timeout=30000 -arangodb.metrics.responseQueueTimeSamples=20 +arangodb.responseQueueTimeSamples=20 diff --git a/shaded-integration-tests/pom.xml b/shaded-integration-tests/pom.xml index d8195d15b..db0b73330 100644 --- a/shaded-integration-tests/pom.xml +++ b/shaded-integration-tests/pom.xml @@ -43,11 +43,6 @@ jackson - - com.arangodb - arangodb-java-driver-shaded - test - com.arangodb jackson-dataformat-velocypack @@ -70,11 +65,6 @@ jackson - - com.arangodb - arangodb-java-driver-shaded - test - com.arangodb jackson-serde @@ -99,11 +89,6 @@ jsonb - - com.arangodb - arangodb-java-driver-shaded - test - com.arangodb jsonb-serde @@ -129,7 +114,7 @@ com.arangodb - arangodb-java-driver-shaded + jackson-serde test @@ -140,4 +125,12 @@ + + + + com.arangodb + arangodb-java-driver-shaded + test + + \ No newline at end of file diff --git a/shaded-integration-tests/src/test/internal/java/arch/BaseTest.java b/shaded-integration-tests/src/test/internal/java/arch/BaseTest.java index 1833d3521..3fcbb5aa8 100644 --- a/shaded-integration-tests/src/test/internal/java/arch/BaseTest.java +++ b/shaded-integration-tests/src/test/internal/java/arch/BaseTest.java @@ -4,32 +4,33 @@ import com.arangodb.ContentType; import com.arangodb.DbName; import com.arangodb.Protocol; -import com.arangodb.internal.config.FileConfigPropertiesProvider; +import com.arangodb.config.ArangoConfigProperties; import org.junit.jupiter.params.provider.Arguments; import java.util.Arrays; import java.util.stream.Stream; public class BaseTest { + private static final ArangoConfigProperties config = ConfigUtils.loadConfig(); protected static final DbName TEST_DB = DbName.of("java_driver_integration_tests"); protected static ArangoDB createAdb() { return new ArangoDB.Builder() - .loadProperties(new FileConfigPropertiesProvider()) + .loadProperties(config) .build(); } protected static ArangoDB createAdb(ContentType contentType) { Protocol protocol = contentType == ContentType.VPACK ? Protocol.HTTP2_VPACK : Protocol.HTTP2_JSON; return new ArangoDB.Builder() - .loadProperties(new FileConfigPropertiesProvider()) + .loadProperties(config) .useProtocol(protocol) .build(); } protected static ArangoDB createAdb(Protocol protocol) { return new ArangoDB.Builder() - .loadProperties(new FileConfigPropertiesProvider()) + .loadProperties(config) .useProtocol(protocol) .build(); } diff --git a/shaded-integration-tests/src/test/internal/java/arch/ConfigUtils.java b/shaded-integration-tests/src/test/internal/java/arch/ConfigUtils.java new file mode 100644 index 000000000..68167d9e2 --- /dev/null +++ b/shaded-integration-tests/src/test/internal/java/arch/ConfigUtils.java @@ -0,0 +1,22 @@ +package arch; + +import com.arangodb.config.ArangoConfigProperties; +import io.smallrye.config.PropertiesConfigSourceProvider; +import io.smallrye.config.SmallRyeConfig; +import io.smallrye.config.SmallRyeConfigBuilder; + +public class ConfigUtils { + + public static ArangoConfigProperties loadConfig() { + return ArangoConfigProperties.fromFile(); + } + + public static ArangoConfigProperties loadConfig(final String location) { + return ArangoConfigProperties.fromFile(location); + } + + public static ArangoConfigProperties loadConfig(final String location, final String prefix) { + return ArangoConfigProperties.fromFile(location, prefix); + } + +} diff --git a/shaded-integration-tests/src/test/jackson/java/arch/BaseTest.java b/shaded-integration-tests/src/test/jackson/java/arch/BaseTest.java index 1833d3521..3fcbb5aa8 100644 --- a/shaded-integration-tests/src/test/jackson/java/arch/BaseTest.java +++ b/shaded-integration-tests/src/test/jackson/java/arch/BaseTest.java @@ -4,32 +4,33 @@ import com.arangodb.ContentType; import com.arangodb.DbName; import com.arangodb.Protocol; -import com.arangodb.internal.config.FileConfigPropertiesProvider; +import com.arangodb.config.ArangoConfigProperties; import org.junit.jupiter.params.provider.Arguments; import java.util.Arrays; import java.util.stream.Stream; public class BaseTest { + private static final ArangoConfigProperties config = ConfigUtils.loadConfig(); protected static final DbName TEST_DB = DbName.of("java_driver_integration_tests"); protected static ArangoDB createAdb() { return new ArangoDB.Builder() - .loadProperties(new FileConfigPropertiesProvider()) + .loadProperties(config) .build(); } protected static ArangoDB createAdb(ContentType contentType) { Protocol protocol = contentType == ContentType.VPACK ? Protocol.HTTP2_VPACK : Protocol.HTTP2_JSON; return new ArangoDB.Builder() - .loadProperties(new FileConfigPropertiesProvider()) + .loadProperties(config) .useProtocol(protocol) .build(); } protected static ArangoDB createAdb(Protocol protocol) { return new ArangoDB.Builder() - .loadProperties(new FileConfigPropertiesProvider()) + .loadProperties(config) .useProtocol(protocol) .build(); } diff --git a/shaded-integration-tests/src/test/jackson/java/arch/ConfigUtils.java b/shaded-integration-tests/src/test/jackson/java/arch/ConfigUtils.java new file mode 100644 index 000000000..68167d9e2 --- /dev/null +++ b/shaded-integration-tests/src/test/jackson/java/arch/ConfigUtils.java @@ -0,0 +1,22 @@ +package arch; + +import com.arangodb.config.ArangoConfigProperties; +import io.smallrye.config.PropertiesConfigSourceProvider; +import io.smallrye.config.SmallRyeConfig; +import io.smallrye.config.SmallRyeConfigBuilder; + +public class ConfigUtils { + + public static ArangoConfigProperties loadConfig() { + return ArangoConfigProperties.fromFile(); + } + + public static ArangoConfigProperties loadConfig(final String location) { + return ArangoConfigProperties.fromFile(location); + } + + public static ArangoConfigProperties loadConfig(final String location, final String prefix) { + return ArangoConfigProperties.fromFile(location, prefix); + } + +} diff --git a/shaded-integration-tests/src/test/jsonb/java/arch/BaseTest.java b/shaded-integration-tests/src/test/jsonb/java/arch/BaseTest.java index c6851582b..661742202 100644 --- a/shaded-integration-tests/src/test/jsonb/java/arch/BaseTest.java +++ b/shaded-integration-tests/src/test/jsonb/java/arch/BaseTest.java @@ -4,6 +4,7 @@ import com.arangodb.ContentType; import com.arangodb.DbName; import com.arangodb.Protocol; +import com.arangodb.config.ArangoConfigProperties; import com.arangodb.internal.serde.ContentTypeFactory; import org.junit.jupiter.params.provider.Arguments; @@ -12,6 +13,7 @@ import java.util.stream.Stream; public class BaseTest { + private static final ArangoConfigProperties config = ConfigUtils.loadConfig(); protected static final DbName TEST_DB = DbName.of("java_driver_integration_tests"); protected static final String HOST = "172.28.0.1"; protected static final int PORT = 8529; diff --git a/shaded-integration-tests/src/test/jsonb/java/arch/ConfigUtils.java b/shaded-integration-tests/src/test/jsonb/java/arch/ConfigUtils.java new file mode 100644 index 000000000..68167d9e2 --- /dev/null +++ b/shaded-integration-tests/src/test/jsonb/java/arch/ConfigUtils.java @@ -0,0 +1,22 @@ +package arch; + +import com.arangodb.config.ArangoConfigProperties; +import io.smallrye.config.PropertiesConfigSourceProvider; +import io.smallrye.config.SmallRyeConfig; +import io.smallrye.config.SmallRyeConfigBuilder; + +public class ConfigUtils { + + public static ArangoConfigProperties loadConfig() { + return ArangoConfigProperties.fromFile(); + } + + public static ArangoConfigProperties loadConfig(final String location) { + return ArangoConfigProperties.fromFile(location); + } + + public static ArangoConfigProperties loadConfig(final String location, final String prefix) { + return ArangoConfigProperties.fromFile(location, prefix); + } + +} diff --git a/shaded-integration-tests/src/test/native/java/com/arangodb/ArangoDBTest.java b/shaded-integration-tests/src/test/native/java/com/arangodb/ArangoDBTest.java index 0bf363642..522ce6926 100644 --- a/shaded-integration-tests/src/test/native/java/com/arangodb/ArangoDBTest.java +++ b/shaded-integration-tests/src/test/native/java/com/arangodb/ArangoDBTest.java @@ -20,8 +20,8 @@ package com.arangodb; +import com.arangodb.config.ConfigUtils; import com.arangodb.entity.*; -import com.arangodb.internal.config.FileConfigPropertiesProvider; import com.arangodb.internal.serde.SerdeUtils; import com.arangodb.model.*; import com.arangodb.model.LogOptions.SortOrder; @@ -210,7 +210,7 @@ void createDatabaseWithUsers(ArangoDB arangoDB) throws InterruptedException { Thread.sleep(2_000); ArangoDB arangoDBTestUser = new ArangoDB.Builder() - .loadProperties(new FileConfigPropertiesProvider()) + .loadProperties(config) .user("testUser") .password("testPasswd") .build(); @@ -373,7 +373,7 @@ void updateUserDefaultCollectionAccess(ArangoDB arangoDB) { @Test void authenticationFailPassword() { final ArangoDB arangoDB = new ArangoDB.Builder() - .loadProperties(new FileConfigPropertiesProvider()) + .loadProperties(config) .password("no").jwt(null).build(); Throwable thrown = catchThrowable(arangoDB::getVersion); assertThat(thrown).isInstanceOf(ArangoDBException.class); @@ -384,7 +384,7 @@ void authenticationFailPassword() { @MethodSource("arangos") void authenticationFailUser() { final ArangoDB arangoDB = new ArangoDB.Builder() - .loadProperties(new FileConfigPropertiesProvider()) + .loadProperties(config) .user("no").jwt(null).build(); Throwable thrown = catchThrowable(arangoDB::getVersion); assertThat(thrown).isInstanceOf(ArangoDBException.class); @@ -589,7 +589,7 @@ void arangoDBException(ArangoDB arangoDB) { @MethodSource("arangos") void fallbackHost() { final ArangoDB arangoDB = new ArangoDB.Builder() - .loadProperties(new FileConfigPropertiesProvider()) + .loadProperties(config) .host("not-accessible", 8529).host("127.0.0.1", 8529).build(); final ArangoDBVersion version = arangoDB.getVersion(); assertThat(version).isNotNull(); @@ -599,9 +599,19 @@ void fallbackHost() { @MethodSource("arangos") void loadproperties() { Throwable thrown = catchThrowable(() -> new ArangoDB.Builder() - .loadProperties(new FileConfigPropertiesProvider("arangodb", "/arangodb-bad.properties")) + .loadProperties(ConfigUtils.loadConfig("arangodb-bad.properties")) ); - assertThat(thrown).isInstanceOf(ArangoDBException.class); + assertThat(thrown).isInstanceOf(IllegalArgumentException.class); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("arangos") + void loadpropertiesWithPrefix() { + ArangoDB adb = new ArangoDB.Builder() + .loadProperties(ConfigUtils.loadConfig("arangodb-with-prefix.properties", "adb")) + .build(); + adb.getVersion(); + adb.shutdown(); } @ParameterizedTest(name = "{index}") diff --git a/shaded-integration-tests/src/test/native/java/com/arangodb/BaseJunit5.java b/shaded-integration-tests/src/test/native/java/com/arangodb/BaseJunit5.java index fd2aa8415..3e6c8e30a 100644 --- a/shaded-integration-tests/src/test/native/java/com/arangodb/BaseJunit5.java +++ b/shaded-integration-tests/src/test/native/java/com/arangodb/BaseJunit5.java @@ -1,7 +1,8 @@ package com.arangodb; +import com.arangodb.config.ArangoConfigProperties; +import com.arangodb.config.ConfigUtils; import com.arangodb.entity.*; -import com.arangodb.internal.config.FileConfigPropertiesProvider; import com.arangodb.model.CollectionCreateOptions; import com.arangodb.model.GraphCreateOptions; import com.arangodb.util.TestUtils; @@ -16,14 +17,14 @@ import java.util.stream.Stream; class BaseJunit5 { - protected static final DbName TEST_DB = DbName.of("java_driver_shaded_test_db"); - + protected static final DbName TEST_DB = DbName.of("java_driver_test_db"); + protected static final ArangoConfigProperties config = ConfigUtils.loadConfig(); private static final List adbs = Arrays.asList( - new ArangoDB.Builder().loadProperties(new FileConfigPropertiesProvider()).useProtocol(Protocol.VST).build(), - new ArangoDB.Builder().loadProperties(new FileConfigPropertiesProvider()).useProtocol(Protocol.HTTP_VPACK).build(), - new ArangoDB.Builder().loadProperties(new FileConfigPropertiesProvider()).useProtocol(Protocol.HTTP_JSON).build(), - new ArangoDB.Builder().loadProperties(new FileConfigPropertiesProvider()).useProtocol(Protocol.HTTP2_VPACK).build(), - new ArangoDB.Builder().loadProperties(new FileConfigPropertiesProvider()).useProtocol(Protocol.HTTP2_JSON).build() + new ArangoDB.Builder().loadProperties(config).useProtocol(Protocol.VST).build(), + new ArangoDB.Builder().loadProperties(config).useProtocol(Protocol.HTTP_VPACK).build(), + new ArangoDB.Builder().loadProperties(config).useProtocol(Protocol.HTTP_JSON).build(), + new ArangoDB.Builder().loadProperties(config).useProtocol(Protocol.HTTP2_VPACK).build(), + new ArangoDB.Builder().loadProperties(config).useProtocol(Protocol.HTTP2_JSON).build() ); protected static Stream dbsStream() { diff --git a/shaded-integration-tests/src/test/native/java/com/arangodb/ConcurrencyTests.java b/shaded-integration-tests/src/test/native/java/com/arangodb/ConcurrencyTests.java index 1103cb6df..3efdacc9c 100644 --- a/shaded-integration-tests/src/test/native/java/com/arangodb/ConcurrencyTests.java +++ b/shaded-integration-tests/src/test/native/java/com/arangodb/ConcurrencyTests.java @@ -1,6 +1,6 @@ package com.arangodb; -import com.arangodb.internal.config.FileConfigPropertiesProvider; +import com.arangodb.config.ConfigUtils; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.EnumSource; @@ -19,7 +19,7 @@ class ConcurrencyTests { void concurrentPendingRequests(Protocol protocol) throws ExecutionException, InterruptedException { ExecutorService es = Executors.newFixedThreadPool(10); ArangoDB adb = new ArangoDB.Builder() - .loadProperties(new FileConfigPropertiesProvider()) + .loadProperties(ConfigUtils.loadConfig()) .useProtocol(protocol).build(); List> futures = IntStream.range(0, 10) .mapToObj(__ -> CompletableFuture.runAsync(() -> adb.db().query("RETURN SLEEP(1)", Void.class), es)) diff --git a/shaded-integration-tests/src/test/native/java/com/arangodb/JwtAuthTest.java b/shaded-integration-tests/src/test/native/java/com/arangodb/JwtAuthTest.java index 34d41a751..d2127e7ba 100644 --- a/shaded-integration-tests/src/test/native/java/com/arangodb/JwtAuthTest.java +++ b/shaded-integration-tests/src/test/native/java/com/arangodb/JwtAuthTest.java @@ -1,6 +1,6 @@ package com.arangodb; -import com.arangodb.internal.config.FileConfigPropertiesProvider; +import com.arangodb.config.ConfigUtils; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.EnumSource; @@ -23,7 +23,7 @@ class JwtAuthTest { @BeforeAll static void init() { ArangoDB arangoDB = new ArangoDB.Builder() - .loadProperties(new FileConfigPropertiesProvider()) + .loadProperties(ConfigUtils.loadConfig()) .build(); jwt = getJwt(arangoDB); arangoDB.shutdown(); @@ -88,7 +88,7 @@ void updateJwt(Protocol protocol) { private ArangoDB.Builder getBuilder(Protocol protocol) { return new ArangoDB.Builder() - .loadProperties(new FileConfigPropertiesProvider()) + .loadProperties(ConfigUtils.loadConfig()) .useProtocol(protocol) .jwt(null) // unset credentials from properties file .user(null) // unset credentials from properties file diff --git a/shaded-integration-tests/src/test/native/java/com/arangodb/ParallelTest.java b/shaded-integration-tests/src/test/native/java/com/arangodb/ParallelTest.java index 2df8079bb..9c4b98f96 100644 --- a/shaded-integration-tests/src/test/native/java/com/arangodb/ParallelTest.java +++ b/shaded-integration-tests/src/test/native/java/com/arangodb/ParallelTest.java @@ -1,6 +1,6 @@ package com.arangodb; -import com.arangodb.internal.config.FileConfigPropertiesProvider; +import com.arangodb.config.ConfigUtils; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.EnumSource; @@ -22,7 +22,7 @@ void connectionParallelism(Protocol protocol) throws InterruptedException { // BTS-1102: the server does not run pipelined HTTP/1.1 requests in parallel assumeTrue(protocol != Protocol.HTTP_JSON && protocol != Protocol.HTTP_VPACK); ArangoDB adb = new ArangoDB.Builder() - .loadProperties(new FileConfigPropertiesProvider()) + .loadProperties(ConfigUtils.loadConfig()) .useProtocol(protocol) .maxConnections(1) .build(); diff --git a/shaded-integration-tests/src/test/native/java/com/arangodb/async/ArangoDBTest.java b/shaded-integration-tests/src/test/native/java/com/arangodb/async/ArangoDBTest.java index 19f77ca5c..2a76db54c 100644 --- a/shaded-integration-tests/src/test/native/java/com/arangodb/async/ArangoDBTest.java +++ b/shaded-integration-tests/src/test/native/java/com/arangodb/async/ArangoDBTest.java @@ -21,8 +21,8 @@ package com.arangodb.async; import com.arangodb.*; +import com.arangodb.config.ConfigUtils; import com.arangodb.entity.*; -import com.arangodb.internal.config.FileConfigPropertiesProvider; import com.arangodb.internal.serde.SerdeUtils; import com.arangodb.model.*; import com.arangodb.util.RawJson; @@ -56,10 +56,10 @@ class ArangoDBTest { private static Boolean extendedNames; private final ArangoDBAsync arangoDB = new ArangoDBAsync.Builder() - .loadProperties(new FileConfigPropertiesProvider()) + .loadProperties(ConfigUtils.loadConfig()) .build(); private final ArangoDB arangoDBSync = new ArangoDB.Builder() - .loadProperties(new FileConfigPropertiesProvider()) + .loadProperties(ConfigUtils.loadConfig()) .build(); private boolean isEnterprise() { @@ -71,11 +71,11 @@ private boolean isCluster() { } private boolean isAtLeastVersion(final int major, final int minor) { - return TestUtils.isAtLeastVersion(arangoDBSync.getVersion().getVersion(), major, minor, 0); + return com.arangodb.util.TestUtils.isAtLeastVersion(arangoDBSync.getVersion().getVersion(), major, minor, 0); } private boolean isLessThanVersion(final int major, final int minor) { - return TestUtils.isLessThanVersion(arangoDBSync.getVersion().getVersion(), major, minor, 0); + return com.arangodb.util.TestUtils.isLessThanVersion(arangoDBSync.getVersion().getVersion(), major, minor, 0); } private boolean supportsExtendedNames() { @@ -418,7 +418,7 @@ void updateUserDefaultCollectionAccess() throws InterruptedException, ExecutionE @Test void authenticationFailPassword() throws InterruptedException { final ArangoDBAsync arangoDB = new ArangoDBAsync.Builder() - .loadProperties(new FileConfigPropertiesProvider()) + .loadProperties(ConfigUtils.loadConfig()) .password("no").jwt(null).build(); try { arangoDB.getVersion().get(); @@ -431,7 +431,7 @@ void authenticationFailPassword() throws InterruptedException { @Test void authenticationFailUser() throws InterruptedException { final ArangoDBAsync arangoDB = new ArangoDBAsync.Builder() - .loadProperties(new FileConfigPropertiesProvider()) + .loadProperties(ConfigUtils.loadConfig()) .user("no").jwt(null).build(); try { arangoDB.getVersion().get(); @@ -459,7 +459,7 @@ void execute() throws InterruptedException, ExecutionException { @Test void execute_acquireHostList_enabled() throws InterruptedException, ExecutionException { final ArangoDBAsync arangoDB = new ArangoDBAsync.Builder() - .loadProperties(new FileConfigPropertiesProvider()) + .loadProperties(ConfigUtils.loadConfig()) .acquireHostList(true).build(); arangoDB .execute(Request.builder() diff --git a/shaded-integration-tests/src/test/native/java/com/arangodb/async/BaseTest.java b/shaded-integration-tests/src/test/native/java/com/arangodb/async/BaseTest.java index 729596e3c..261996ab9 100644 --- a/shaded-integration-tests/src/test/native/java/com/arangodb/async/BaseTest.java +++ b/shaded-integration-tests/src/test/native/java/com/arangodb/async/BaseTest.java @@ -21,10 +21,11 @@ package com.arangodb.async; import com.arangodb.DbName; +import com.arangodb.config.ArangoConfigProperties; +import com.arangodb.config.ConfigUtils; import com.arangodb.entity.ArangoDBEngine; import com.arangodb.entity.License; import com.arangodb.entity.ServerRole; -import com.arangodb.internal.config.FileConfigPropertiesProvider; import com.arangodb.util.TestUtils; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; @@ -37,7 +38,7 @@ * @author Mark Vollmary */ public abstract class BaseTest { - + protected static final ArangoConfigProperties config = ConfigUtils.loadConfig(); static final DbName TEST_DB = DbName.of("java_driver_test_db"); static ArangoDBAsync arangoDB; static ArangoDatabaseAsync db; @@ -46,7 +47,7 @@ public abstract class BaseTest { static void init() throws InterruptedException, ExecutionException { if (arangoDB == null) { arangoDB = new ArangoDBAsync.Builder() - .loadProperties(new FileConfigPropertiesProvider()) + .loadProperties(ConfigUtils.loadConfig()) .build(); } @@ -72,7 +73,7 @@ static String rnd() { protected static boolean isAtLeastVersion(final ArangoDBAsync arangoDB, final int major, final int minor, final int patch) throws InterruptedException, ExecutionException { - return TestUtils.isAtLeastVersion(arangoDB.getVersion().get().getVersion(), major, minor, + return com.arangodb.util.TestUtils.isAtLeastVersion(arangoDB.getVersion().get().getVersion(), major, minor, patch); } diff --git a/shaded-integration-tests/src/test/native/java/com/arangodb/async/ConcurrencyTests.java b/shaded-integration-tests/src/test/native/java/com/arangodb/async/ConcurrencyTests.java index 504c550a7..278486efc 100644 --- a/shaded-integration-tests/src/test/native/java/com/arangodb/async/ConcurrencyTests.java +++ b/shaded-integration-tests/src/test/native/java/com/arangodb/async/ConcurrencyTests.java @@ -1,7 +1,7 @@ package com.arangodb.async; -import com.arangodb.internal.config.FileConfigPropertiesProvider; +import com.arangodb.config.ConfigUtils; import org.junit.jupiter.api.Test; import java.util.List; @@ -15,7 +15,7 @@ class ConcurrencyTests { @Test void concurrentPendingRequests() throws ExecutionException, InterruptedException { ArangoDBAsync adb = new ArangoDBAsync.Builder() - .loadProperties(new FileConfigPropertiesProvider()) + .loadProperties(ConfigUtils.loadConfig()) .build(); List>> reqs = IntStream.range(0, 10) .mapToObj(__ -> adb.db().query("RETURN SLEEP(1)", Void.class)) diff --git a/shaded-integration-tests/src/test/native/java/com/arangodb/async/InvertedIndexTest.java b/shaded-integration-tests/src/test/native/java/com/arangodb/async/InvertedIndexTest.java index 8ee509526..e4451f77c 100644 --- a/shaded-integration-tests/src/test/native/java/com/arangodb/async/InvertedIndexTest.java +++ b/shaded-integration-tests/src/test/native/java/com/arangodb/async/InvertedIndexTest.java @@ -182,7 +182,7 @@ void getIndexesShouldNotReturnInvertedIndexes() throws ExecutionException, Inter ArangoCollectionAsync collection = db.collection(COLLECTION_NAME); // create persistent index - collection.ensurePersistentIndex(Collections.singletonList("foo"), new PersistentIndexOptions().name("persistentIndex")); + collection.ensurePersistentIndex(Collections.singletonList("foo"), new PersistentIndexOptions().name("persistentIndex")).get(); // create inverted index String analyzerName = "delimiter-" + UUID.randomUUID(); diff --git a/shaded-integration-tests/src/test/native/java/com/arangodb/async/JwtAuthTest.java b/shaded-integration-tests/src/test/native/java/com/arangodb/async/JwtAuthTest.java index f821f3ea9..04bbfc98d 100644 --- a/shaded-integration-tests/src/test/native/java/com/arangodb/async/JwtAuthTest.java +++ b/shaded-integration-tests/src/test/native/java/com/arangodb/async/JwtAuthTest.java @@ -1,7 +1,7 @@ package com.arangodb.async; import com.arangodb.*; -import com.arangodb.internal.config.FileConfigPropertiesProvider; +import com.arangodb.config.ConfigUtils; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Disabled; @@ -22,7 +22,7 @@ class JwtAuthTest { @BeforeAll static void init() { ArangoDB arangoDB = new ArangoDB.Builder() - .loadProperties(new FileConfigPropertiesProvider()) + .loadProperties(ConfigUtils.loadConfig()) .build(); jwt = getJwt(arangoDB); arangoDB.shutdown(); @@ -95,7 +95,7 @@ void updateJwt() throws ExecutionException, InterruptedException { private ArangoDBAsync.Builder getBuilder() { return new ArangoDBAsync.Builder() - .loadProperties(new FileConfigPropertiesProvider()) + .loadProperties(ConfigUtils.loadConfig()) .jwt(null) // unset credentials from properties file .user(null) // unset credentials from properties file .password(null); // unset credentials from properties file diff --git a/shaded-integration-tests/src/test/native/java/com/arangodb/async/debug/ConsolidationIntervalMsecTest.java b/shaded-integration-tests/src/test/native/java/com/arangodb/async/debug/ConsolidationIntervalMsecTest.java index 5a3d0ddad..330ce8eb9 100644 --- a/shaded-integration-tests/src/test/native/java/com/arangodb/async/debug/ConsolidationIntervalMsecTest.java +++ b/shaded-integration-tests/src/test/native/java/com/arangodb/async/debug/ConsolidationIntervalMsecTest.java @@ -29,7 +29,6 @@ import com.arangodb.entity.arangosearch.ArangoSearchPropertiesEntity; import com.arangodb.entity.arangosearch.CollectionLink; import com.arangodb.entity.arangosearch.FieldLink; -import com.arangodb.internal.config.FileConfigPropertiesProvider; import com.arangodb.model.arangosearch.ArangoSearchCreateOptions; import org.junit.jupiter.api.Test; @@ -50,7 +49,7 @@ void consolidationIntervalMsec() throws ExecutionException, InterruptedException assumeTrue(isAtLeastVersion(3, 4)); ArangoDBAsync arango = new ArangoDBAsync.Builder() - .loadProperties(new FileConfigPropertiesProvider()) + .loadProperties(config) .user("root") .password("test") .build(); diff --git a/shaded-integration-tests/src/test/native/java/com/arangodb/async/example/ExampleBase.java b/shaded-integration-tests/src/test/native/java/com/arangodb/async/example/ExampleBase.java index 9c1ce81e2..7881fd617 100644 --- a/shaded-integration-tests/src/test/native/java/com/arangodb/async/example/ExampleBase.java +++ b/shaded-integration-tests/src/test/native/java/com/arangodb/async/example/ExampleBase.java @@ -24,7 +24,7 @@ import com.arangodb.async.ArangoCollectionAsync; import com.arangodb.async.ArangoDBAsync; import com.arangodb.async.ArangoDatabaseAsync; -import com.arangodb.internal.config.FileConfigPropertiesProvider; +import com.arangodb.config.ConfigUtils; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; @@ -44,7 +44,7 @@ public class ExampleBase { @BeforeAll static void setUp() throws InterruptedException, ExecutionException { arangoDB = new ArangoDBAsync.Builder() - .loadProperties(new FileConfigPropertiesProvider()) + .loadProperties(ConfigUtils.loadConfig()) .build(); if (arangoDB.db(DB_NAME).exists().get()) { arangoDB.db(DB_NAME).drop().get(); diff --git a/shaded-integration-tests/src/test/native/java/com/arangodb/async/example/graph/AQLActorsAndMoviesExampleTest.java b/shaded-integration-tests/src/test/native/java/com/arangodb/async/example/graph/AQLActorsAndMoviesExampleTest.java index 259cc4451..d21f78f02 100644 --- a/shaded-integration-tests/src/test/native/java/com/arangodb/async/example/graph/AQLActorsAndMoviesExampleTest.java +++ b/shaded-integration-tests/src/test/native/java/com/arangodb/async/example/graph/AQLActorsAndMoviesExampleTest.java @@ -25,11 +25,11 @@ import com.arangodb.async.ArangoCursorAsync; import com.arangodb.async.ArangoDBAsync; import com.arangodb.async.ArangoDatabaseAsync; +import com.arangodb.config.ConfigUtils; import com.arangodb.entity.BaseDocument; import com.arangodb.entity.BaseEdgeDocument; import com.arangodb.entity.CollectionType; import com.arangodb.entity.DocumentCreateEntity; -import com.arangodb.internal.config.FileConfigPropertiesProvider; import com.arangodb.model.CollectionCreateOptions; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; @@ -59,7 +59,7 @@ class AQLActorsAndMoviesExampleTest { @BeforeAll static void setUp() throws InterruptedException, ExecutionException { arangoDB = new ArangoDBAsync.Builder() - .loadProperties(new FileConfigPropertiesProvider()) + .loadProperties(ConfigUtils.loadConfig()) .build(); if (arangoDB.db(TEST_DB).exists().get()) { arangoDB.db(TEST_DB).drop().get(); diff --git a/shaded-integration-tests/src/test/native/java/com/arangodb/async/example/graph/BaseGraphTest.java b/shaded-integration-tests/src/test/native/java/com/arangodb/async/example/graph/BaseGraphTest.java index 8a16b9231..41a4e6edf 100644 --- a/shaded-integration-tests/src/test/native/java/com/arangodb/async/example/graph/BaseGraphTest.java +++ b/shaded-integration-tests/src/test/native/java/com/arangodb/async/example/graph/BaseGraphTest.java @@ -23,9 +23,9 @@ import com.arangodb.DbName; import com.arangodb.async.ArangoDBAsync; import com.arangodb.async.ArangoDatabaseAsync; +import com.arangodb.config.ConfigUtils; import com.arangodb.entity.EdgeDefinition; import com.arangodb.entity.VertexEntity; -import com.arangodb.internal.config.FileConfigPropertiesProvider; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; @@ -49,7 +49,7 @@ public abstract class BaseGraphTest { static void init() throws InterruptedException, ExecutionException { if (arangoDB == null) { arangoDB = new ArangoDBAsync.Builder() - .loadProperties(new FileConfigPropertiesProvider()) + .loadProperties(ConfigUtils.loadConfig()) .build(); } if (arangoDB.db(TEST_DB).exists().get()) { diff --git a/shaded-integration-tests/src/test/native/java/com/arangodb/async/serde/CustomSerdeTest.java b/shaded-integration-tests/src/test/native/java/com/arangodb/async/serde/CustomSerdeTest.java index c6e65ca50..fdca9d3c0 100644 --- a/shaded-integration-tests/src/test/native/java/com/arangodb/async/serde/CustomSerdeTest.java +++ b/shaded-integration-tests/src/test/native/java/com/arangodb/async/serde/CustomSerdeTest.java @@ -21,13 +21,13 @@ package com.arangodb.async.serde; -import com.arangodb.ContentType; import com.arangodb.DbName; import com.arangodb.async.ArangoCollectionAsync; import com.arangodb.async.ArangoDBAsync; import com.arangodb.async.ArangoDatabaseAsync; -import com.arangodb.internal.config.FileConfigPropertiesProvider; +import com.arangodb.config.ConfigUtils; import com.arangodb.model.DocumentCreateOptions; +import com.arangodb.ContentType; import com.arangodb.serde.jackson.JacksonSerde; import com.arangodb.serde.jackson.JacksonSerdeProvider; import org.junit.jupiter.api.AfterEach; @@ -64,7 +64,7 @@ void init() throws ExecutionException, InterruptedException { mapper.configure(USE_BIG_INTEGER_FOR_INTS, true); }); ArangoDBAsync arangoDB = new ArangoDBAsync.Builder() - .loadProperties(new FileConfigPropertiesProvider()) + .loadProperties(ConfigUtils.loadConfig()) .serializer(serde).build(); DbName TEST_DB = DbName.of("custom-serde-test"); diff --git a/shaded-integration-tests/src/test/native/java/com/arangodb/config/ConfigUtils.java b/shaded-integration-tests/src/test/native/java/com/arangodb/config/ConfigUtils.java new file mode 100644 index 000000000..7f15d6270 --- /dev/null +++ b/shaded-integration-tests/src/test/native/java/com/arangodb/config/ConfigUtils.java @@ -0,0 +1,18 @@ +package com.arangodb.config; + + +public class ConfigUtils { + + public static ArangoConfigProperties loadConfig() { + return ArangoConfigProperties.fromFile(); + } + + public static ArangoConfigProperties loadConfig(final String location) { + return ArangoConfigProperties.fromFile(location); + } + + public static ArangoConfigProperties loadConfig(final String location, final String prefix) { + return ArangoConfigProperties.fromFile(location, prefix); + } + +} diff --git a/shaded-integration-tests/src/test/native/java/com/arangodb/example/ExampleBase.java b/shaded-integration-tests/src/test/native/java/com/arangodb/example/ExampleBase.java index c99610836..01399b1cb 100644 --- a/shaded-integration-tests/src/test/native/java/com/arangodb/example/ExampleBase.java +++ b/shaded-integration-tests/src/test/native/java/com/arangodb/example/ExampleBase.java @@ -24,7 +24,7 @@ import com.arangodb.ArangoDB; import com.arangodb.ArangoDatabase; import com.arangodb.DbName; -import com.arangodb.internal.config.FileConfigPropertiesProvider; +import com.arangodb.config.ConfigUtils; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; @@ -42,7 +42,7 @@ public class ExampleBase { @BeforeAll static void setUp() { arangoDB = new ArangoDB.Builder() - .loadProperties(new FileConfigPropertiesProvider()) + .loadProperties(ConfigUtils.loadConfig()) .build(); DbName dbName = DbName.of(DB_NAME); if (arangoDB.db(dbName).exists()) diff --git a/shaded-integration-tests/src/test/native/java/com/arangodb/example/graph/AQLActorsAndMoviesExampleTest.java b/shaded-integration-tests/src/test/native/java/com/arangodb/example/graph/AQLActorsAndMoviesExampleTest.java index 682bed1b1..c23b4097d 100644 --- a/shaded-integration-tests/src/test/native/java/com/arangodb/example/graph/AQLActorsAndMoviesExampleTest.java +++ b/shaded-integration-tests/src/test/native/java/com/arangodb/example/graph/AQLActorsAndMoviesExampleTest.java @@ -21,11 +21,11 @@ package com.arangodb.example.graph; import com.arangodb.*; +import com.arangodb.config.ConfigUtils; import com.arangodb.entity.BaseDocument; import com.arangodb.entity.BaseEdgeDocument; import com.arangodb.entity.CollectionType; import com.arangodb.entity.DocumentCreateEntity; -import com.arangodb.internal.config.FileConfigPropertiesProvider; import com.arangodb.model.CollectionCreateOptions; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; @@ -53,7 +53,7 @@ class AQLActorsAndMoviesExampleTest { @BeforeAll static void setUp() { arangoDB = new ArangoDB.Builder() - .loadProperties(new FileConfigPropertiesProvider()) + .loadProperties(ConfigUtils.loadConfig()) .build(); if (arangoDB.db(TEST_DB).exists()) arangoDB.db(TEST_DB).drop(); diff --git a/shaded-integration-tests/src/test/native/java/com/arangodb/example/graph/BaseGraphTest.java b/shaded-integration-tests/src/test/native/java/com/arangodb/example/graph/BaseGraphTest.java index 514af943f..8b742e52d 100644 --- a/shaded-integration-tests/src/test/native/java/com/arangodb/example/graph/BaseGraphTest.java +++ b/shaded-integration-tests/src/test/native/java/com/arangodb/example/graph/BaseGraphTest.java @@ -24,9 +24,9 @@ import com.arangodb.ArangoDBException; import com.arangodb.ArangoDatabase; import com.arangodb.DbName; +import com.arangodb.config.ConfigUtils; import com.arangodb.entity.EdgeDefinition; import com.arangodb.entity.VertexEntity; -import com.arangodb.internal.config.FileConfigPropertiesProvider; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; @@ -49,7 +49,7 @@ abstract class BaseGraphTest { static void init() { if (arangoDB == null) { arangoDB = new ArangoDB.Builder() - .loadProperties(new FileConfigPropertiesProvider()) + .loadProperties(ConfigUtils.loadConfig()) .build(); } if (arangoDB.db(TEST_DB).exists()) diff --git a/shaded-integration-tests/src/test/native/java/com/arangodb/example/ssl/SslExampleTest.java b/shaded-integration-tests/src/test/native/java/com/arangodb/example/ssl/SslExampleTest.java index 168e4d4da..b3f97ff16 100644 --- a/shaded-integration-tests/src/test/native/java/com/arangodb/example/ssl/SslExampleTest.java +++ b/shaded-integration-tests/src/test/native/java/com/arangodb/example/ssl/SslExampleTest.java @@ -30,10 +30,7 @@ import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.EnumSource; -import javax.net.ssl.KeyManagerFactory; -import javax.net.ssl.SSLContext; -import javax.net.ssl.SSLHandshakeException; -import javax.net.ssl.TrustManagerFactory; +import javax.net.ssl.*; import java.security.KeyStore; import java.util.List; diff --git a/shaded-integration-tests/src/test/native/java/com/arangodb/internal/HostHandlerTest.java b/shaded-integration-tests/src/test/native/java/com/arangodb/internal/HostHandlerTest.java index ceff3a79e..973d3a7c1 100644 --- a/shaded-integration-tests/src/test/native/java/com/arangodb/internal/HostHandlerTest.java +++ b/shaded-integration-tests/src/test/native/java/com/arangodb/internal/HostHandlerTest.java @@ -22,6 +22,7 @@ import com.arangodb.ArangoDBException; import com.arangodb.ArangoDBMultipleException; +import com.arangodb.config.HostDescription; import com.arangodb.internal.net.*; import com.arangodb.internal.serde.InternalSerde; import org.junit.jupiter.api.Test; diff --git a/shaded-integration-tests/src/test/native/java/com/arangodb/internal/velocystream/CommunicationTest.java b/shaded-integration-tests/src/test/native/java/com/arangodb/internal/velocystream/CommunicationTest.java index bfdeb444a..120939786 100644 --- a/shaded-integration-tests/src/test/native/java/com/arangodb/internal/velocystream/CommunicationTest.java +++ b/shaded-integration-tests/src/test/native/java/com/arangodb/internal/velocystream/CommunicationTest.java @@ -22,8 +22,8 @@ import com.arangodb.ArangoDB; import com.arangodb.ArangoDatabase; +import com.arangodb.config.ConfigUtils; import com.arangodb.entity.ArangoDBVersion; -import com.arangodb.internal.config.FileConfigPropertiesProvider; import org.junit.jupiter.api.Test; import java.util.Collection; @@ -43,7 +43,7 @@ class CommunicationTest { @Test void chunkSizeSmall() { final ArangoDB arangoDB = new ArangoDB.Builder() - .loadProperties(new FileConfigPropertiesProvider()) + .loadProperties(ConfigUtils.loadConfig()) .chunksize(20).build(); final ArangoDBVersion version = arangoDB.getVersion(); assertThat(version).isNotNull(); @@ -52,7 +52,7 @@ void chunkSizeSmall() { @Test void multiThread() throws Exception { final ArangoDB arangoDB = new ArangoDB.Builder() - .loadProperties(new FileConfigPropertiesProvider()) + .loadProperties(ConfigUtils.loadConfig()) .build(); arangoDB.getUsers(); // authentication and active-failover connection redirect to master @@ -80,7 +80,7 @@ void multiThread() throws Exception { @Test void multiThreadSameDatabases() throws Exception { final ArangoDB arangoDB = new ArangoDB.Builder() - .loadProperties(new FileConfigPropertiesProvider()) + .loadProperties(ConfigUtils.loadConfig()) .build(); arangoDB.getUsers(); // authentication and active-failover connection redirect to master @@ -105,7 +105,7 @@ void multiThreadSameDatabases() throws Exception { @Test void minOneConnection() { final ArangoDB arangoDB = new ArangoDB.Builder() - .loadProperties(new FileConfigPropertiesProvider()) + .loadProperties(ConfigUtils.loadConfig()) .maxConnections(0).build(); final ArangoDBVersion version = arangoDB.getVersion(); assertThat(version).isNotNull(); @@ -114,7 +114,7 @@ void minOneConnection() { @Test void defaultMaxConnection() { final ArangoDB arangoDB = new ArangoDB.Builder() - .loadProperties(new FileConfigPropertiesProvider()) + .loadProperties(ConfigUtils.loadConfig()) .maxConnections(null).build(); final ArangoDBVersion version = arangoDB.getVersion(); assertThat(version).isNotNull(); diff --git a/shaded-integration-tests/src/test/native/java/com/arangodb/annotations/AnnotatedEntity.java b/shaded-integration-tests/src/test/native/java/com/arangodb/mapping/annotations/AnnotatedEntity.java similarity index 97% rename from shaded-integration-tests/src/test/native/java/com/arangodb/annotations/AnnotatedEntity.java rename to shaded-integration-tests/src/test/native/java/com/arangodb/mapping/annotations/AnnotatedEntity.java index 993fff0ec..f26fb6f25 100644 --- a/shaded-integration-tests/src/test/native/java/com/arangodb/annotations/AnnotatedEntity.java +++ b/shaded-integration-tests/src/test/native/java/com/arangodb/mapping/annotations/AnnotatedEntity.java @@ -1,4 +1,4 @@ -package com.arangodb.annotations; +package com.arangodb.mapping.annotations; import com.arangodb.serde.jackson.*; diff --git a/shaded-integration-tests/src/test/native/java/com/arangodb/annotations/ArangoAnnotationsTest.java b/shaded-integration-tests/src/test/native/java/com/arangodb/mapping/annotations/ArangoAnnotationsTest.java similarity index 97% rename from shaded-integration-tests/src/test/native/java/com/arangodb/annotations/ArangoAnnotationsTest.java rename to shaded-integration-tests/src/test/native/java/com/arangodb/mapping/annotations/ArangoAnnotationsTest.java index e3363f3c0..084f67ba9 100644 --- a/shaded-integration-tests/src/test/native/java/com/arangodb/annotations/ArangoAnnotationsTest.java +++ b/shaded-integration-tests/src/test/native/java/com/arangodb/mapping/annotations/ArangoAnnotationsTest.java @@ -18,7 +18,7 @@ * Copyright holder is ArangoDB GmbH, Cologne, Germany */ -package com.arangodb.annotations; +package com.arangodb.mapping.annotations; import com.arangodb.ContentType; import com.arangodb.serde.ArangoSerde; diff --git a/shaded-integration-tests/src/test/native/java/com/arangodb/serde/CustomSerdeTest.java b/shaded-integration-tests/src/test/native/java/com/arangodb/serde/CustomSerdeTest.java index 428363da6..4e42730ba 100644 --- a/shaded-integration-tests/src/test/native/java/com/arangodb/serde/CustomSerdeTest.java +++ b/shaded-integration-tests/src/test/native/java/com/arangodb/serde/CustomSerdeTest.java @@ -22,7 +22,7 @@ import com.arangodb.*; -import com.arangodb.internal.config.FileConfigPropertiesProvider; +import com.arangodb.config.ConfigUtils; import com.arangodb.internal.serde.InternalSerde; import com.arangodb.model.DocumentCreateOptions; import com.arangodb.serde.jackson.JacksonSerde; @@ -72,7 +72,7 @@ static void init() { mapper.registerModule(module); }); arangoDB = new ArangoDB.Builder() - .loadProperties(new FileConfigPropertiesProvider()) + .loadProperties(ConfigUtils.loadConfig()) .useProtocol(Protocol.VST) .serde(serde).build(); diff --git a/shaded-integration-tests/src/test/native/java/com/arangodb/serde/CustomTypeHintTest.java b/shaded-integration-tests/src/test/native/java/com/arangodb/serde/CustomTypeHintTest.java index fed63354e..f8f79f444 100644 --- a/shaded-integration-tests/src/test/native/java/com/arangodb/serde/CustomTypeHintTest.java +++ b/shaded-integration-tests/src/test/native/java/com/arangodb/serde/CustomTypeHintTest.java @@ -25,7 +25,7 @@ import com.arangodb.ArangoDB; import com.arangodb.ArangoDatabase; import com.arangodb.DbName; -import com.arangodb.internal.config.FileConfigPropertiesProvider; +import com.arangodb.config.ConfigUtils; import com.arangodb.model.DocumentCreateOptions; import com.arangodb.serde.jackson.Key; import com.fasterxml.jackson.annotation.JsonTypeInfo; @@ -48,7 +48,7 @@ class CustomTypeHintTest { @BeforeEach void init() { ArangoDB arangoDB = new ArangoDB.Builder() - .loadProperties(new FileConfigPropertiesProvider()) + .loadProperties(ConfigUtils.loadConfig()) .build(); db = arangoDB.db(DbName.of("custom-serde-test")); diff --git a/shaded-integration-tests/src/test/native/java/com/arangodb/serde/SerdeTest.java b/shaded-integration-tests/src/test/native/java/com/arangodb/serde/SerdeTest.java index f6a190b1f..ab225bd23 100644 --- a/shaded-integration-tests/src/test/native/java/com/arangodb/serde/SerdeTest.java +++ b/shaded-integration-tests/src/test/native/java/com/arangodb/serde/SerdeTest.java @@ -2,6 +2,7 @@ import com.arangodb.ContentType; import com.arangodb.internal.serde.InternalSerde; +import com.arangodb.internal.serde.InternalSerdeProvider; import com.arangodb.internal.serde.SerdeUtils; import com.arangodb.shaded.fasterxml.jackson.databind.node.JsonNodeFactory; import com.arangodb.shaded.fasterxml.jackson.databind.node.ObjectNode; @@ -18,7 +19,7 @@ class SerdeTest { @ParameterizedTest @EnumSource(ContentType.class) void rawJsonSerde(ContentType type) { - InternalSerde s = InternalSerde.of(type, null); + InternalSerde s = new InternalSerdeProvider().of(type); ObjectNode node = JsonNodeFactory.instance.objectNode().put("foo", "bar"); RawJson raw = RawJson.of(SerdeUtils.INSTANCE.writeJson(node)); byte[] serialized = s.serialize(raw); @@ -29,7 +30,7 @@ void rawJsonSerde(ContentType type) { @ParameterizedTest @EnumSource(ContentType.class) void rawBytesSerde(ContentType type) { - InternalSerde s = InternalSerde.of(type, null); + InternalSerde s = new InternalSerdeProvider().of(type); ObjectNode node = JsonNodeFactory.instance.objectNode().put("foo", "bar"); RawBytes raw = RawBytes.of(s.serialize(node)); byte[] serialized = s.serialize(raw); diff --git a/shaded-integration-tests/src/test/native/java/com/arangodb/util/UnicodeUtilsTest.java b/shaded-integration-tests/src/test/native/java/com/arangodb/util/UnicodeUtilsTest.java new file mode 100644 index 000000000..b295223bd --- /dev/null +++ b/shaded-integration-tests/src/test/native/java/com/arangodb/util/UnicodeUtilsTest.java @@ -0,0 +1,60 @@ +package com.arangodb.util; + +import com.arangodb.internal.util.EncodeUtils; +import org.graalvm.home.Version; +import org.graalvm.nativeimage.ImageInfo; +import org.graalvm.polyglot.Context; +import org.graalvm.polyglot.Value; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assumptions.assumeFalse; +import static org.junit.jupiter.api.Assumptions.assumeTrue; + + +class UnicodeUtilsTest { + + private static final String encodeFn = "(function encode(x){return encodeURIComponent(x);})"; + private static final String normalizeFn = "(function normalize(x){return x.normalize('NFC');})"; + private static Context context; + private static Value jsEncoder; + private static Value jsNormalizer; + + @BeforeAll + static void beforeClass() { + assumeFalse(ImageInfo.inImageCode(), "skipped in native mode"); + assumeTrue(Version.getCurrent().isRelease(), "This test requires GraalVM"); + context = Context.create(); + jsEncoder = context.eval("js", encodeFn); + jsNormalizer = context.eval("js", normalizeFn); + } + + @AfterAll + static void afterClass() { + if (context != null) + context.close(); + } + + @Test + void normalizeShouldBehaveAsJs() { + for (int i = 0; i < 10_000; i++) { + String value = TestUtils.generateRandomDbName(100, true); + String jsNormalized = jsNormalizer.execute(value).as(String.class); + String javaNormalized = UnicodeUtils.normalize(value); + assertThat(javaNormalized).isEqualTo(jsNormalized); + } + } + + @Test + void encodeURIComponentShouldBehaveAsJs() { + for (int i = 0; i < 10_000; i++) { + String value = TestUtils.generateRandomDbName(100, true); + String jsEncoded = jsEncoder.execute(value).as(String.class); + String driverJavaEncoded = EncodeUtils.encodeURIComponent(value); + assertThat(driverJavaEncoded).isEqualTo(jsEncoded); + } + } + +} \ No newline at end of file diff --git a/shaded-integration-tests/src/test/native/java/perf/Benchmark.java b/shaded-integration-tests/src/test/native/java/perf/Benchmark.java new file mode 100644 index 000000000..8fade9e17 --- /dev/null +++ b/shaded-integration-tests/src/test/native/java/perf/Benchmark.java @@ -0,0 +1,123 @@ +package perf; + +import java.util.Date; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.atomic.AtomicInteger; + +public abstract class Benchmark { + + private static final int SYNC_THREADS = 128; + private final CountDownLatch completed = new CountDownLatch(1); + private volatile Long startTime = null; + private volatile Long endTime = null; + private volatile int targetCount = Integer.MAX_VALUE; + private final AtomicInteger counter = new AtomicInteger(); + private final ExecutorService es = Executors.newFixedThreadPool(SYNC_THREADS); + private final int warmupDurationSeconds; + private final int numberOfRequests; + + public Benchmark(int warmupDurationSeconds, int numberOfRequests) { + this.warmupDurationSeconds = warmupDurationSeconds; + this.numberOfRequests = numberOfRequests; + } + + public void run() { + // warmup + startBenchmark(); + + // start monitor / warmup + startMonitor(); + + // start benchmark + startMeasuring(); + } + + private void startMonitor() { + for (int i = 0; i < warmupDurationSeconds; i++) { + counter.set(0); + long start = new Date().getTime(); + try { + Thread.sleep(1_000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + + long current = new Date().getTime(); + long elapsed = current - start; + double reqsPerSec = 1_000.0 * counter.get() / elapsed; + System.out.println("reqs/s: \t" + reqsPerSec); + } + } + + private void startBenchmark() { + start(); + new Thread(() -> { + try { + completed.await(); + // wait graceful shutdown + Thread.sleep(1_000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + // force shutdown + es.shutdown(); + shutdown(); + }).start(); + } + + private void startMeasuring() { + counter.set(0); + targetCount = numberOfRequests; + startTime = System.currentTimeMillis(); + } + + public long waitComplete() { + try { + completed.await(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + return endTime - startTime; + } + + /** + * @return req/s + */ + public long getThroughput() { + return targetCount * 1000L / (endTime - startTime); + } + + /** + * notify the success of #count requests + * + * @return whether more requests should be performed + */ + private boolean success() { + if (endTime != null) return false; + if (counter.addAndGet(1) >= targetCount) { + endTime = System.currentTimeMillis(); + completed.countDown(); + return false; + } + return true; + } + + private void start() { + for (int i = 0; i < SYNC_THREADS; i++) { + es.execute(() -> { + boolean more = true; + while (more) { + sendRequest(); + more = success(); + } + }); + } + } + + protected abstract void sendRequest(); + + protected abstract void shutdown(); + +} diff --git a/shaded-integration-tests/src/test/native/java/perf/SimpleSyncPerfTest.java b/shaded-integration-tests/src/test/native/java/perf/SimpleSyncPerfTest.java new file mode 100644 index 000000000..2d230779f --- /dev/null +++ b/shaded-integration-tests/src/test/native/java/perf/SimpleSyncPerfTest.java @@ -0,0 +1,57 @@ +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed 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. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package perf; + +import com.arangodb.ArangoDB; +import com.arangodb.Protocol; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.EnumSource; + +import java.util.Date; + +/** + * @author Michele Rastelli + */ +@Disabled +class SimpleSyncPerfTest { + private static final int REPETITIONS = 50_000; + + private void doGetVersion(ArangoDB arangoDB) { + for (int i = 0; i < REPETITIONS; i++) { + arangoDB.getVersion(); + } + } + + @ParameterizedTest + @EnumSource(Protocol.class) + void getVersion(Protocol protocol) throws InterruptedException { + ArangoDB arangoDB = new ArangoDB.Builder().useProtocol(protocol).build(); + // warmup + doGetVersion(arangoDB); + + long start = new Date().getTime(); + doGetVersion(arangoDB); + long end = new Date().getTime(); + System.out.println("elapsed ms: " + (end - start)); + Thread.sleep(5000); + } +} diff --git a/shaded-integration-tests/src/test/native/java/perf/SyncBenchmarkTest.java b/shaded-integration-tests/src/test/native/java/perf/SyncBenchmarkTest.java new file mode 100644 index 000000000..f30ef331a --- /dev/null +++ b/shaded-integration-tests/src/test/native/java/perf/SyncBenchmarkTest.java @@ -0,0 +1,71 @@ +package perf; + +import com.arangodb.ArangoDB; +import com.arangodb.DbName; +import com.arangodb.Protocol; +import com.arangodb.Request; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.EnumSource; + +@Disabled +public class SyncBenchmarkTest { + private final int warmupDurationSeconds = 15; + private final int numberOfRequests = 1_000_000; + + @ParameterizedTest + @EnumSource(Protocol.class) + void getVersion(Protocol protocol) { + System.out.println("-----------------------------------------"); + System.out.println("--- getVersion(): " + protocol); + System.out.println("-----------------------------------------"); + + ArangoDB adb = new ArangoDB.Builder().useProtocol(protocol).build(); + Benchmark benchmark = new Benchmark(warmupDurationSeconds, numberOfRequests) { + @Override + protected void sendRequest() { + adb.getVersion(); + } + + @Override + protected void shutdown() { + adb.shutdown(); + } + }; + benchmark.run(); + System.out.println("elapsed time [ms]: \t" + benchmark.waitComplete()); + System.out.println("throughput [req/s]: \t" + benchmark.getThroughput()); + } + + @ParameterizedTest + @EnumSource(Protocol.class) + void getVersionWithDetails(Protocol protocol) { + System.out.println("-----------------------------------------"); + System.out.println("--- getVersion w/ details: " + protocol); + System.out.println("-----------------------------------------"); + + ArangoDB adb = new ArangoDB.Builder().useProtocol(protocol).build(); + Benchmark benchmark = new Benchmark(warmupDurationSeconds, numberOfRequests) { + private final Request request = Request.builder() + .db(DbName.SYSTEM) + .method(Request.Method.GET) + .path("/_api/version") + .queryParam("details", "true") + .build(); + + @Override + protected void sendRequest() { + adb.execute(request, Void.class); + } + + @Override + protected void shutdown() { + adb.shutdown(); + } + }; + benchmark.run(); + System.out.println("elapsed time [ms]: \t" + benchmark.waitComplete()); + System.out.println("throughput [req/s]: \t" + benchmark.getThroughput()); + } + +} diff --git a/shaded-integration-tests/src/test/resources/META-INF/native-image/reflect-config.json b/shaded-integration-tests/src/test/resources/META-INF/native-image/reflect-config.json index 43c06539e..e8a1f86bc 100644 --- a/shaded-integration-tests/src/test/resources/META-INF/native-image/reflect-config.json +++ b/shaded-integration-tests/src/test/resources/META-INF/native-image/reflect-config.json @@ -281,7 +281,7 @@ "allDeclaredConstructors": true }, { - "name": "com.arangodb.annotations.AnnotatedEntity", + "name": "com.arangodb.mapping.annotations.AnnotatedEntity", "allDeclaredFields": true, "allDeclaredMethods": true, "allDeclaredConstructors": true diff --git a/shaded-integration-tests/src/test/resources/arangodb-config-test.properties b/shaded-integration-tests/src/test/resources/arangodb-config-test.properties new file mode 100644 index 000000000..23c912293 --- /dev/null +++ b/shaded-integration-tests/src/test/resources/arangodb-config-test.properties @@ -0,0 +1,17 @@ +adb.hosts=aaa:1111,bbb:2222 +adb.protocol=HTTP_VPACK +adb.user=testUser +adb.password=testPassword +adb.jwt=testJwt +adb.timeout=9876 +adb.useSsl=true +adb.verifyHost=false +adb.vstChunkSize=1234 +adb.maxConnections=123 +adb.connectionTtl=12345 +adb.keepAliveInterval=123456 +adb.acquireHostList=true +adb.acquireHostListInterval=1234567 +adb.loadBalancingStrategy=ROUND_ROBIN +adb.responseQueueTimeSamples=12345678 + diff --git a/shaded-integration-tests/src/test/resources/arangodb-with-prefix.properties b/shaded-integration-tests/src/test/resources/arangodb-with-prefix.properties new file mode 100644 index 000000000..36fb2d0a5 --- /dev/null +++ b/shaded-integration-tests/src/test/resources/arangodb-with-prefix.properties @@ -0,0 +1,3 @@ +adb.hosts=172.28.0.1:8529 +adb.acquireHostList=true +adb.password=test diff --git a/shaded-integration-tests/src/test/resources/arangodb.properties b/shaded-integration-tests/src/test/resources/arangodb.properties index 68329ae86..fa580e439 100644 --- a/shaded-integration-tests/src/test/resources/arangodb.properties +++ b/shaded-integration-tests/src/test/resources/arangodb.properties @@ -1,3 +1,5 @@ arangodb.hosts=172.28.0.1:8529 arangodb.acquireHostList=true arangodb.password=test +arangodb.timeout=30000 +arangodb.responseQueueTimeSamples=20 From b5cba3e94cf253735988cab96cba75a782efd5c2 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Wed, 11 Jan 2023 17:59:51 +0100 Subject: [PATCH 230/254] log warn on internal serde --- .../java/com/arangodb/internal/InternalArangoDBBuilder.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/driver/src/main/java/com/arangodb/internal/InternalArangoDBBuilder.java b/driver/src/main/java/com/arangodb/internal/InternalArangoDBBuilder.java index 02c3f5bf6..b98d9b561 100644 --- a/driver/src/main/java/com/arangodb/internal/InternalArangoDBBuilder.java +++ b/driver/src/main/java/com/arangodb/internal/InternalArangoDBBuilder.java @@ -74,7 +74,8 @@ protected static ArangoSerdeProvider serdeProvider() { Iterator it = loader.iterator(); ArangoSerdeProvider serdeProvider; if (!it.hasNext()) { - LOG.info("No ArangoSerdeProvider found, using InternalSerdeProvider."); + LOG.warn("No ArangoSerdeProvider found, using InternalSerdeProvider. Please consider registering a custom " + + "ArangoSerdeProvider to avoid depending on internal classes which are not part of the public API."); serdeProvider = new InternalSerdeProvider(); } else { serdeProvider = it.next(); From 47513b50fd9a1e5c2614b4b36bb74435ec769783 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Wed, 11 Jan 2023 18:03:58 +0100 Subject: [PATCH 231/254] re-added jackson-serde transitive dependency to shaded driver --- shaded/pom.xml | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/shaded/pom.xml b/shaded/pom.xml index 486dc20fa..59e786792 100644 --- a/shaded/pom.xml +++ b/shaded/pom.xml @@ -28,16 +28,16 @@ com.arangodb serde-api - - com.arangodb - jackson-serde - com.arangodb jackson-dataformat-velocypack + + com.arangodb + jackson-serde + org.slf4j slf4j-api @@ -66,6 +66,7 @@ org.slf4j:slf4j-api + com.arangodb:jackson-serde com.arangodb:velocypack From cefe41b02b9f6ac7c260b0bdfc0d730f58e7e5ee Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Wed, 11 Jan 2023 20:01:51 +0100 Subject: [PATCH 232/254] tests fixes --- driver/pom.xml | 2 +- shaded-integration-tests/pom.xml | 44 ++++++++++++------- .../test/internal/java/arch/ConfigUtils.java | 3 -- .../test/jackson/java/arch/ConfigUtils.java | 3 -- .../src/test/jsonb/java/arch/ConfigUtils.java | 3 -- 5 files changed, 29 insertions(+), 26 deletions(-) diff --git a/driver/pom.xml b/driver/pom.xml index 93eb6566a..55702f282 100644 --- a/driver/pom.xml +++ b/driver/pom.xml @@ -254,7 +254,7 @@ io.smallrye.config smallrye-config-core - 3.1.1 + 2.13.1 test diff --git a/shaded-integration-tests/pom.xml b/shaded-integration-tests/pom.xml index db0b73330..c8ed5ced5 100644 --- a/shaded-integration-tests/pom.xml +++ b/shaded-integration-tests/pom.xml @@ -43,15 +43,23 @@ jackson + + com.arangodb + arangodb-java-driver-shaded + + + com.arangodb + jackson-serde + + + com.arangodb jackson-dataformat-velocypack - test com.tngtech.archunit archunit-junit5 - test @@ -65,20 +73,21 @@ jackson + + com.arangodb + arangodb-java-driver-shaded + com.arangodb jackson-serde - test com.arangodb jackson-dataformat-velocypack - test com.tngtech.archunit archunit-junit5 - test @@ -89,10 +98,19 @@ jsonb + + com.arangodb + arangodb-java-driver-shaded + + + com.arangodb + jackson-serde + + + com.arangodb jsonb-serde - test org.eclipse @@ -101,7 +119,6 @@ com.tngtech.archunit archunit-junit5 - test @@ -112,25 +129,20 @@ jackson + + com.arangodb + arangodb-java-driver-shaded + com.arangodb jackson-serde - test com.arangodb jackson-dataformat-velocypack - test - - - com.arangodb - arangodb-java-driver-shaded - test - - \ No newline at end of file diff --git a/shaded-integration-tests/src/test/internal/java/arch/ConfigUtils.java b/shaded-integration-tests/src/test/internal/java/arch/ConfigUtils.java index 68167d9e2..9f18a7bb8 100644 --- a/shaded-integration-tests/src/test/internal/java/arch/ConfigUtils.java +++ b/shaded-integration-tests/src/test/internal/java/arch/ConfigUtils.java @@ -1,9 +1,6 @@ package arch; import com.arangodb.config.ArangoConfigProperties; -import io.smallrye.config.PropertiesConfigSourceProvider; -import io.smallrye.config.SmallRyeConfig; -import io.smallrye.config.SmallRyeConfigBuilder; public class ConfigUtils { diff --git a/shaded-integration-tests/src/test/jackson/java/arch/ConfigUtils.java b/shaded-integration-tests/src/test/jackson/java/arch/ConfigUtils.java index 68167d9e2..9f18a7bb8 100644 --- a/shaded-integration-tests/src/test/jackson/java/arch/ConfigUtils.java +++ b/shaded-integration-tests/src/test/jackson/java/arch/ConfigUtils.java @@ -1,9 +1,6 @@ package arch; import com.arangodb.config.ArangoConfigProperties; -import io.smallrye.config.PropertiesConfigSourceProvider; -import io.smallrye.config.SmallRyeConfig; -import io.smallrye.config.SmallRyeConfigBuilder; public class ConfigUtils { diff --git a/shaded-integration-tests/src/test/jsonb/java/arch/ConfigUtils.java b/shaded-integration-tests/src/test/jsonb/java/arch/ConfigUtils.java index 68167d9e2..9f18a7bb8 100644 --- a/shaded-integration-tests/src/test/jsonb/java/arch/ConfigUtils.java +++ b/shaded-integration-tests/src/test/jsonb/java/arch/ConfigUtils.java @@ -1,9 +1,6 @@ package arch; import com.arangodb.config.ArangoConfigProperties; -import io.smallrye.config.PropertiesConfigSourceProvider; -import io.smallrye.config.SmallRyeConfig; -import io.smallrye.config.SmallRyeConfigBuilder; public class ConfigUtils { From 484ad6217dd7af6a64006a0d713e12d5f02a8dbf Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Wed, 11 Jan 2023 21:06:19 +0100 Subject: [PATCH 233/254] native tests fixes --- .../test/java/com/arangodb/config/ConfigDefaultsTest.java | 8 ++++++++ driver/src/test/java/com/arangodb/config/ConfigTest.java | 8 ++++++++ .../resources/META-INF/native-image/resource-config.json | 3 +++ .../resources/META-INF/native-image/resource-config.json | 3 +++ 4 files changed, 22 insertions(+) diff --git a/driver/src/test/java/com/arangodb/config/ConfigDefaultsTest.java b/driver/src/test/java/com/arangodb/config/ConfigDefaultsTest.java index e4fad9c3c..8ecd443c3 100644 --- a/driver/src/test/java/com/arangodb/config/ConfigDefaultsTest.java +++ b/driver/src/test/java/com/arangodb/config/ConfigDefaultsTest.java @@ -1,11 +1,19 @@ package com.arangodb.config; +import org.graalvm.nativeimage.ImageInfo; +import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assumptions.assumeFalse; class ConfigDefaultsTest { + @BeforeAll + static void beforeClass() { + assumeFalse(ImageInfo.inImageCode(), "skipped in native mode"); + } + @Test void defaultValues() { ArangoConfigProperties config = ConfigUtils.loadConfigMP("arangodb.properties", "wrong"); diff --git a/driver/src/test/java/com/arangodb/config/ConfigTest.java b/driver/src/test/java/com/arangodb/config/ConfigTest.java index 8e8f4228e..b111cd1b3 100644 --- a/driver/src/test/java/com/arangodb/config/ConfigTest.java +++ b/driver/src/test/java/com/arangodb/config/ConfigTest.java @@ -3,9 +3,12 @@ import com.arangodb.Protocol; import com.arangodb.entity.LoadBalancingStrategy; import org.assertj.core.api.InstanceOfAssertFactories; +import org.graalvm.nativeimage.ImageInfo; +import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assumptions.assumeFalse; class ConfigTest { private final HostDescription hostA = new HostDescription("aaa", 1111); @@ -26,6 +29,11 @@ class ConfigTest { private final LoadBalancingStrategy loadBalancingStrategy = LoadBalancingStrategy.ROUND_ROBIN; private final Integer responseQueueTimeSamples = 12345678; + @BeforeAll + static void beforeClass() { + assumeFalse(ImageInfo.inImageCode(), "skipped in native mode"); + } + @Test void readConfig() { ArangoConfigProperties config = ConfigUtils.loadConfigMP("arangodb-config-test.properties", "adb"); diff --git a/driver/src/test/resources/META-INF/native-image/resource-config.json b/driver/src/test/resources/META-INF/native-image/resource-config.json index a603a885a..a6eea307e 100644 --- a/driver/src/test/resources/META-INF/native-image/resource-config.json +++ b/driver/src/test/resources/META-INF/native-image/resource-config.json @@ -10,6 +10,9 @@ { "pattern": "\\Qarangodb-bad2.properties\\E" }, + { + "pattern":"\\Qarangodb-with-prefix.properties\\E" + }, { "pattern": "\\Qlogback-test.xml\\E" }, diff --git a/shaded-integration-tests/src/test/resources/META-INF/native-image/resource-config.json b/shaded-integration-tests/src/test/resources/META-INF/native-image/resource-config.json index a603a885a..a6eea307e 100644 --- a/shaded-integration-tests/src/test/resources/META-INF/native-image/resource-config.json +++ b/shaded-integration-tests/src/test/resources/META-INF/native-image/resource-config.json @@ -10,6 +10,9 @@ { "pattern": "\\Qarangodb-bad2.properties\\E" }, + { + "pattern":"\\Qarangodb-with-prefix.properties\\E" + }, { "pattern": "\\Qlogback-test.xml\\E" }, From e405cbab8812a3a2e444dc083d59cf48754c6743 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Wed, 11 Jan 2023 21:32:55 +0100 Subject: [PATCH 234/254] resilience tests fixes --- .github/workflows/resilience.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/resilience.yml b/.github/workflows/resilience.yml index 061aa41ac..cfba2570c 100644 --- a/.github/workflows/resilience.yml +++ b/.github/workflows/resilience.yml @@ -29,6 +29,7 @@ jobs: - name: Info run: mvn -version - name: Start Toxiproxy + working-directory: resilience-tests run: ./bin/startProxy.sh - name: Install run: mvn --no-transfer-progress install -DskipTests=true -Dgpg.skip=true -Dmaven.javadoc.skip=true From 55c256e6e2e01c191a50934f907dd2d28f1fc87c Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Wed, 11 Jan 2023 21:43:36 +0100 Subject: [PATCH 235/254] tests fixes --- .../java/com/arangodb/config/ConfigDefaultsTest.java | 10 ++-------- .../src/test/java/com/arangodb/config/ConfigTest.java | 10 ++-------- 2 files changed, 4 insertions(+), 16 deletions(-) diff --git a/driver/src/test/java/com/arangodb/config/ConfigDefaultsTest.java b/driver/src/test/java/com/arangodb/config/ConfigDefaultsTest.java index 8ecd443c3..fc65af6e4 100644 --- a/driver/src/test/java/com/arangodb/config/ConfigDefaultsTest.java +++ b/driver/src/test/java/com/arangodb/config/ConfigDefaultsTest.java @@ -1,19 +1,13 @@ package com.arangodb.config; -import org.graalvm.nativeimage.ImageInfo; -import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.condition.DisabledInNativeImage; import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assumptions.assumeFalse; +@DisabledInNativeImage class ConfigDefaultsTest { - @BeforeAll - static void beforeClass() { - assumeFalse(ImageInfo.inImageCode(), "skipped in native mode"); - } - @Test void defaultValues() { ArangoConfigProperties config = ConfigUtils.loadConfigMP("arangodb.properties", "wrong"); diff --git a/driver/src/test/java/com/arangodb/config/ConfigTest.java b/driver/src/test/java/com/arangodb/config/ConfigTest.java index b111cd1b3..8aa4c3188 100644 --- a/driver/src/test/java/com/arangodb/config/ConfigTest.java +++ b/driver/src/test/java/com/arangodb/config/ConfigTest.java @@ -3,13 +3,12 @@ import com.arangodb.Protocol; import com.arangodb.entity.LoadBalancingStrategy; import org.assertj.core.api.InstanceOfAssertFactories; -import org.graalvm.nativeimage.ImageInfo; -import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.condition.DisabledInNativeImage; import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assumptions.assumeFalse; +@DisabledInNativeImage class ConfigTest { private final HostDescription hostA = new HostDescription("aaa", 1111); private final HostDescription hostB = new HostDescription("bbb", 2222); @@ -29,11 +28,6 @@ class ConfigTest { private final LoadBalancingStrategy loadBalancingStrategy = LoadBalancingStrategy.ROUND_ROBIN; private final Integer responseQueueTimeSamples = 12345678; - @BeforeAll - static void beforeClass() { - assumeFalse(ImageInfo.inImageCode(), "skipped in native mode"); - } - @Test void readConfig() { ArangoConfigProperties config = ConfigUtils.loadConfigMP("arangodb-config-test.properties", "adb"); From fbd3327f560821cb49a916c4d1471179038e131d Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Thu, 12 Jan 2023 15:36:19 +0100 Subject: [PATCH 236/254] publish CI --- .github/workflows/codeql.yml | 4 ++-- .github/workflows/maven.yml | 4 ++-- .github/workflows/publish.yml | 32 ++++++++++++++++++++++++++++++++ pom.xml | 6 ++++++ 4 files changed, 42 insertions(+), 4 deletions(-) create mode 100644 .github/workflows/publish.yml diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 1c453d168..003154699 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -15,12 +15,12 @@ on: push: branches: - master - - v7 - - v6 pull_request: types: [ opened, synchronize, reopened ] branches: - master + - v7 + - v6 schedule: - cron: '0 0 * * *' diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index 97cceed89..3505be4cb 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -4,12 +4,12 @@ on: push: branches: - master - - v7 - - v6 pull_request: types: [ opened, synchronize, reopened ] branches: - master + - v7 + - v6 jobs: diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml new file mode 100644 index 000000000..137897f3a --- /dev/null +++ b/.github/workflows/publish.yml @@ -0,0 +1,32 @@ +name: Publish + +on: + workflow_dispatch: + +jobs: + verify: + timeout-minutes: 20 + runs-on: ubuntu-latest + + strategy: + fail-fast: false + + steps: + - uses: actions/checkout@v2 + - name: Set up JDK + uses: actions/setup-java@v3 + with: + java-version: '8' + distribution: 'adopt' + cache: 'maven' + server-id: ossrh + server-username: MAVEN_USERNAME + server-password: MAVEN_CENTRAL_TOKEN + gpg-private-key: ${{ secrets.MAVEN_GPG_PRIVATE_KEY }} + gpg-passphrase: MAVEN_GPG_PASSPHRASE + - name: Publish to Apache Maven Central + run: mvn deploy -Ddeploy -Dmaven.test.skip=true + env: + MAVEN_USERNAME: ${{ secrets.OSSRH_USERNAME }} + MAVEN_CENTRAL_TOKEN: ${{ secrets.OSSRH_PASSWORD }} + MAVEN_GPG_PASSPHRASE: ${{ secrets.MAVEN_GPG_PASSPHRASE }} diff --git a/pom.xml b/pom.xml index e85082048..3b07086c2 100644 --- a/pom.xml +++ b/pom.xml @@ -241,6 +241,12 @@ org.apache.maven.plugins maven-gpg-plugin 3.0.1 + + + --pinentry-mode + loopback + + sign-artifacts From a79112790a31588bc390716617078b9466a757ef Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Thu, 12 Jan 2023 15:39:32 +0100 Subject: [PATCH 237/254] v7.0.0-SNAPSHOT-2 --- .github/workflows/publish.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 137897f3a..52f307908 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -2,6 +2,8 @@ name: Publish on: workflow_dispatch: + push: + tags: [ v** ] jobs: verify: From adfbc642b390084ad698a6900fa3dc3258f76bac Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Fri, 13 Jan 2023 09:27:37 +0100 Subject: [PATCH 238/254] deploy and release CI workflows (DE-438) --- .github/workflows/codeql.yml | 8 ++++ .../{publish.yml => maven-deploy.yml} | 8 ++-- .github/workflows/maven-release.yml | 40 +++++++++++++++++++ .github/workflows/native.yml | 4 +- .github/workflows/{maven.yml => test.yml} | 12 +++++- 5 files changed, 64 insertions(+), 8 deletions(-) rename .github/workflows/{publish.yml => maven-deploy.yml} (86%) create mode 100644 .github/workflows/maven-release.yml rename .github/workflows/{maven.yml => test.yml} (96%) diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 003154699..abda817c9 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -15,10 +15,18 @@ on: push: branches: - master + paths-ignore: + - '.github/**' + - 'docker/**' + - 'docs/**' + - 'tutorial/**' + - 'ChangeLog.md' + - 'README.md' pull_request: types: [ opened, synchronize, reopened ] branches: - master + - main - v7 - v6 schedule: diff --git a/.github/workflows/publish.yml b/.github/workflows/maven-deploy.yml similarity index 86% rename from .github/workflows/publish.yml rename to .github/workflows/maven-deploy.yml index 52f307908..f7532d404 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/maven-deploy.yml @@ -1,12 +1,12 @@ -name: Publish +name: Deploy on: workflow_dispatch: push: - tags: [ v** ] + tags: [ deploy** ] jobs: - verify: + deploy: timeout-minutes: 20 runs-on: ubuntu-latest @@ -27,7 +27,7 @@ jobs: gpg-private-key: ${{ secrets.MAVEN_GPG_PRIVATE_KEY }} gpg-passphrase: MAVEN_GPG_PASSPHRASE - name: Publish to Apache Maven Central - run: mvn deploy -Ddeploy -Dmaven.test.skip=true + run: mvn --no-transfer-progress -Ddeploy -Dmaven.test.skip=true deploy env: MAVEN_USERNAME: ${{ secrets.OSSRH_USERNAME }} MAVEN_CENTRAL_TOKEN: ${{ secrets.OSSRH_PASSWORD }} diff --git a/.github/workflows/maven-release.yml b/.github/workflows/maven-release.yml new file mode 100644 index 000000000..61217e1b3 --- /dev/null +++ b/.github/workflows/maven-release.yml @@ -0,0 +1,40 @@ +name: Release + +on: + workflow_dispatch: + push: + tags: [ release** ] + +jobs: + release: + timeout-minutes: 20 + runs-on: ubuntu-latest + + strategy: + fail-fast: false + + steps: + - uses: actions/checkout@v2 + - name: Set up JDK + uses: actions/setup-java@v3 + with: + java-version: '8' + distribution: 'adopt' + cache: 'maven' + server-id: ossrh + server-username: MAVEN_USERNAME + server-password: MAVEN_CENTRAL_TOKEN + gpg-private-key: ${{ secrets.MAVEN_GPG_PRIVATE_KEY }} + gpg-passphrase: MAVEN_GPG_PASSPHRASE + - name: Publish to Apache Maven Central + run: mvn --no-transfer-progress -Ddeploy -Dmaven.test.skip=true deploy + env: + MAVEN_USERNAME: ${{ secrets.OSSRH_USERNAME }} + MAVEN_CENTRAL_TOKEN: ${{ secrets.OSSRH_PASSWORD }} + MAVEN_GPG_PASSPHRASE: ${{ secrets.MAVEN_GPG_PASSPHRASE }} + - name: Release to Apache Maven Central + run: mvn --no-transfer-progress -Ddeploy -Dmaven.test.skip=true nexus-staging:release + env: + MAVEN_USERNAME: ${{ secrets.OSSRH_USERNAME }} + MAVEN_CENTRAL_TOKEN: ${{ secrets.OSSRH_PASSWORD }} + MAVEN_GPG_PASSPHRASE: ${{ secrets.MAVEN_GPG_PASSPHRASE }} diff --git a/.github/workflows/native.yml b/.github/workflows/native.yml index e6c34a55a..9df54ccf5 100644 --- a/.github/workflows/native.yml +++ b/.github/workflows/native.yml @@ -43,7 +43,7 @@ jobs: run: mvn --no-transfer-progress install -DskipTests=true -Dgpg.skip=true -Dmaven.javadoc.skip=true - name: Test Native working-directory: ${{matrix.module}} - run: mvn -Pnative --no-transfer-progress test + run: mvn --no-transfer-progress -Pnative test test-native-ssl: timeout-minutes: 20 @@ -83,4 +83,4 @@ jobs: run: mvn --no-transfer-progress install -DskipTests=true -Dgpg.skip=true -Dmaven.javadoc.skip=true - name: Test Native working-directory: ${{matrix.module}} - run: mvn -Pnative --no-transfer-progress -Dgroups=ssl -DSslTest=true test + run: mvn --no-transfer-progress -Pnative -Dgroups=ssl -DSslTest=true test diff --git a/.github/workflows/maven.yml b/.github/workflows/test.yml similarity index 96% rename from .github/workflows/maven.yml rename to .github/workflows/test.yml index 3505be4cb..084fce099 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/test.yml @@ -1,13 +1,21 @@ -name: Java CI +name: Test on: push: branches: - master + paths-ignore: + - '.github/**' + - 'docker/**' + - 'docs/**' + - 'tutorial/**' + - 'ChangeLog.md' + - 'README.md' pull_request: types: [ opened, synchronize, reopened ] branches: - master + - main - v7 - v6 @@ -297,4 +305,4 @@ jobs: env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Needed to get PR information, if any SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} - run: mvn -Pstatic-code-analysis -B --no-transfer-progress -Dgpg.skip=true -am -pl driver verify org.sonarsource.scanner.maven:sonar-maven-plugin:sonar -Dsonar.projectKey=arangodb_arangodb-java-driver + run: mvn --no-transfer-progress -Pstatic-code-analysis -B -Dgpg.skip=true -am -pl driver verify org.sonarsource.scanner.maven:sonar-maven-plugin:sonar -Dsonar.projectKey=arangodb_arangodb-java-driver From f7299792b8d04452038cf8ff5cbf771fa31d71b8 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Fri, 13 Jan 2023 11:04:50 +0100 Subject: [PATCH 239/254] v7.0.0-ALPHA.1 --- .github/workflows/codeql.yml | 1 + .github/workflows/test.yml | 4 ++++ ChangeLog.md | 2 +- docs/v7_detailed_changes.md | 18 ++---------------- driver/pom.xml | 2 +- jackson-serde/pom.xml | 2 +- jsonb-serde/pom.xml | 2 +- pom.xml | 4 +++- resilience-tests/pom.xml | 2 +- serde-api/pom.xml | 4 +++- shaded-integration-tests/pom.xml | 2 +- shaded/pom.xml | 2 +- tutorial/gradle/build.gradle | 5 +---- tutorial/maven/pom.xml | 2 +- 14 files changed, 22 insertions(+), 30 deletions(-) diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index abda817c9..8a7945ee6 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -12,6 +12,7 @@ name: "CodeQL" on: + workflow_dispatch: push: branches: - master diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 084fce099..a4d9b52ab 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -1,9 +1,13 @@ name: Test on: + workflow_dispatch: push: branches: - master + - main + - v7 + - v6 paths-ignore: - '.github/**' - 'docker/**' diff --git a/ChangeLog.md b/ChangeLog.md index 2576c7e39..df64c397b 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -6,7 +6,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) a ## [Unreleased] -## [7.0.0] +## [7.0.0-ALPHA.1] ### Changed diff --git a/docs/v7_detailed_changes.md b/docs/v7_detailed_changes.md index 31e71520d..2b6bf34d1 100644 --- a/docs/v7_detailed_changes.md +++ b/docs/v7_detailed_changes.md @@ -2,28 +2,14 @@ ## Maven Setup -In your `pom.xml`, set the snapshots repository: - -``` - - - snapshots - https://oss.sonatype.org/content/repositories/snapshots - - true - - - -``` - -and include the dependency: +In your `pom.xml` include the dependency: ``` com.arangodb arangodb-java-driver - 7.0.0-SNAPSHOT + 7.0.0-ALPHA.1 ``` diff --git a/driver/pom.xml b/driver/pom.xml index 55702f282..269d92cbd 100644 --- a/driver/pom.xml +++ b/driver/pom.xml @@ -7,7 +7,7 @@ arangodb-java-driver-parent com.arangodb - 7.0.0-SNAPSHOT + 7.0.0-ALPHA.1 arangodb-java-driver diff --git a/jackson-serde/pom.xml b/jackson-serde/pom.xml index 0c55732f6..69f00e2f5 100644 --- a/jackson-serde/pom.xml +++ b/jackson-serde/pom.xml @@ -6,7 +6,7 @@ com.arangodb arangodb-java-driver-parent - 7.0.0-SNAPSHOT + 7.0.0-ALPHA.1 jackson-serde diff --git a/jsonb-serde/pom.xml b/jsonb-serde/pom.xml index 63314250c..ea16f025c 100644 --- a/jsonb-serde/pom.xml +++ b/jsonb-serde/pom.xml @@ -6,7 +6,7 @@ com.arangodb arangodb-java-driver-parent - 7.0.0-SNAPSHOT + 7.0.0-ALPHA.1 jsonb-serde diff --git a/pom.xml b/pom.xml index 3b07086c2..ece44143b 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ com.arangodb arangodb-java-driver-parent - 7.0.0-SNAPSHOT + 7.0.0-ALPHA.1 2016 driver @@ -16,6 +16,7 @@ pom arangodb-java-driver-parent + ArangoDB Java Driver Project https://github.com/arangodb/arangodb-java-driver @@ -334,6 +335,7 @@ https://oss.sonatype.org/ 84aff6e87e214c false + ${maven.deploy.skip} diff --git a/resilience-tests/pom.xml b/resilience-tests/pom.xml index 341474a48..b323cb36b 100644 --- a/resilience-tests/pom.xml +++ b/resilience-tests/pom.xml @@ -5,7 +5,7 @@ arangodb-java-driver-parent com.arangodb - 7.0.0-SNAPSHOT + 7.0.0-ALPHA.1 4.0.0 diff --git a/serde-api/pom.xml b/serde-api/pom.xml index d43145b9c..67003f219 100644 --- a/serde-api/pom.xml +++ b/serde-api/pom.xml @@ -6,10 +6,12 @@ com.arangodb arangodb-java-driver-parent - 7.0.0-SNAPSHOT + 7.0.0-ALPHA.1 + serde-api serde-api + Serde API module for ArangoDB Java Driver com.arangodb.serde diff --git a/shaded-integration-tests/pom.xml b/shaded-integration-tests/pom.xml index c8ed5ced5..a32599b1b 100644 --- a/shaded-integration-tests/pom.xml +++ b/shaded-integration-tests/pom.xml @@ -7,7 +7,7 @@ com.arangodb arangodb-java-driver-parent - 7.0.0-SNAPSHOT + 7.0.0-ALPHA.1 shaded-integration-tests diff --git a/shaded/pom.xml b/shaded/pom.xml index 59e786792..81fc19503 100644 --- a/shaded/pom.xml +++ b/shaded/pom.xml @@ -7,7 +7,7 @@ com.arangodb arangodb-java-driver-parent - 7.0.0-SNAPSHOT + 7.0.0-ALPHA.1 arangodb-java-driver-shaded diff --git a/tutorial/gradle/build.gradle b/tutorial/gradle/build.gradle index 7071475df..759ef5fbc 100644 --- a/tutorial/gradle/build.gradle +++ b/tutorial/gradle/build.gradle @@ -7,11 +7,8 @@ version '1.0-SNAPSHOT' repositories { mavenCentral() - maven { - url "https://oss.sonatype.org/content/repositories/snapshots" - } } dependencies { - implementation 'com.arangodb:arangodb-java-driver:7.0.0-SNAPSHOT' + implementation 'com.arangodb:arangodb-java-driver:7.0.0-ALPHA.1' } diff --git a/tutorial/maven/pom.xml b/tutorial/maven/pom.xml index 51600f8e7..5e4a51329 100644 --- a/tutorial/maven/pom.xml +++ b/tutorial/maven/pom.xml @@ -19,7 +19,7 @@ com.arangodb arangodb-java-driver - 7.0.0-SNAPSHOT + 7.0.0-ALPHA.1 From bb1feb573dae2e20858bc7f9208c5c5b2f49ffa5 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Thu, 16 Feb 2023 19:49:18 +0100 Subject: [PATCH 240/254] [DE-425] modules refactoring (#482) * prepare next release * title and version manifest entries * core module * discover and register Jackson modules via SPI * http module * config refactoring * config refactoring * rm protocol from async builder * builders internal refactoring * AsyncProtocolProvider * vst module * JsonFactory service loader * removed connection builders * removed communication builders * merged serde-api into core * fixed shaded module * fixed shaded native tests * updated jackson-dataformat --- ChangeLog.md | 2 +- core/pom.xml | 91 +++++ .../java/com/arangodb/ArangoCollection.java | 0 .../main/java/com/arangodb/ArangoCursor.java | 0 .../src/main/java/com/arangodb/ArangoDB.java | 301 +-------------- .../java/com/arangodb/ArangoDBException.java | 0 .../arangodb/ArangoDBMultipleException.java | 0 .../java/com/arangodb/ArangoDatabase.java | 0 .../com/arangodb/ArangoEdgeCollection.java | 0 .../main/java/com/arangodb/ArangoGraph.java | 0 .../java/com/arangodb/ArangoIterable.java | 0 .../java/com/arangodb/ArangoIterator.java | 0 .../main/java/com/arangodb/ArangoMetrics.java | 0 .../main/java/com/arangodb/ArangoSearch.java | 0 .../com/arangodb/ArangoSerdeAccessor.java | 0 .../com/arangodb/ArangoVertexCollection.java | 0 .../main/java/com/arangodb/ArangoView.java | 0 .../main/java/com/arangodb/ContentType.java | 0 .../src/main/java/com/arangodb/DbName.java | 0 .../java/com/arangodb/PackageVersion.java.in | 0 .../src/main/java/com/arangodb/Protocol.java | 0 .../java/com/arangodb/QueueTimeMetrics.java | 0 .../src/main/java/com/arangodb/Request.java | 0 .../src/main/java/com/arangodb/Response.java | 0 .../main/java/com/arangodb/SearchAlias.java | 0 .../arangodb/async/ArangoCollectionAsync.java | 0 .../com/arangodb/async/ArangoCursorAsync.java | 0 .../com/arangodb/async/ArangoDBAsync.java | 274 ++------------ .../arangodb/async/ArangoDatabaseAsync.java | 0 .../async/ArangoEdgeCollectionAsync.java | 0 .../com/arangodb/async/ArangoGraphAsync.java | 0 .../com/arangodb/async/ArangoRouteAsync.java | 0 .../com/arangodb/async/ArangoSearchAsync.java | 0 .../async/ArangoVertexCollectionAsync.java | 0 .../com/arangodb/async/ArangoViewAsync.java | 0 .../com/arangodb/async/SearchAliasAsync.java | 0 .../internal/ArangoCollectionAsyncImpl.java | 0 .../async/internal/ArangoCursorAsyncImpl.java | 0 .../async/internal/ArangoDBAsyncImpl.java | 43 +-- .../internal/ArangoDatabaseAsyncImpl.java | 0 .../ArangoEdgeCollectionAsyncImpl.java | 0 .../async/internal/ArangoExecutorAsync.java | 14 +- .../async/internal/ArangoGraphAsyncImpl.java | 0 .../async/internal/ArangoRouteAsyncImpl.java | 0 .../async/internal/ArangoSearchAsyncImpl.java | 0 .../ArangoVertexCollectionAsyncImpl.java | 0 .../async/internal/ArangoViewAsyncImpl.java | 0 .../async/internal/ExceptionUtil.java | 0 .../async/internal/SearchAliasAsyncImpl.java | 0 .../utils/CompletableFutureUtils.java | 0 .../config/ArangoConfigProperties.java | 0 .../com/arangodb/config/HostDescription.java | 0 .../arangodb/entity/AbstractBaseDocument.java | 0 .../entity/AqlExecutionExplainEntity.java | 0 .../arangodb/entity/AqlFunctionEntity.java | 0 .../com/arangodb/entity/AqlParseEntity.java | 0 .../com/arangodb/entity/ArangoDBEngine.java | 0 .../com/arangodb/entity/ArangoDBVersion.java | 0 .../com/arangodb/entity/BaseDocument.java | 0 .../com/arangodb/entity/BaseEdgeDocument.java | 0 .../com/arangodb/entity/CollectionEntity.java | 0 .../entity/CollectionPropertiesEntity.java | 0 .../entity/CollectionRevisionEntity.java | 0 .../com/arangodb/entity/CollectionStatus.java | 0 .../com/arangodb/entity/CollectionType.java | 0 .../com/arangodb/entity/CursorWarning.java | 0 .../com/arangodb/entity/DatabaseEntity.java | 0 .../arangodb/entity/DocumentCreateEntity.java | 0 .../arangodb/entity/DocumentDeleteEntity.java | 0 .../com/arangodb/entity/DocumentEntity.java | 0 .../arangodb/entity/DocumentImportEntity.java | 0 .../arangodb/entity/DocumentUpdateEntity.java | 0 .../com/arangodb/entity/EdgeDefinition.java | 0 .../java/com/arangodb/entity/EdgeEntity.java | 0 .../com/arangodb/entity/EdgeUpdateEntity.java | 0 .../java/com/arangodb/entity/ErrorEntity.java | 0 .../java/com/arangodb/entity/GraphEntity.java | 0 .../java/com/arangodb/entity/IndexEntity.java | 0 .../java/com/arangodb/entity/IndexType.java | 0 .../arangodb/entity/InvertedIndexEntity.java | 0 .../arangodb/entity/InvertedIndexField.java | 0 .../entity/InvertedIndexPrimarySort.java | 0 .../java/com/arangodb/entity/KeyOptions.java | 0 .../java/com/arangodb/entity/KeyType.java | 0 .../java/com/arangodb/entity/License.java | 0 .../entity/LoadBalancingStrategy.java | 0 .../com/arangodb/entity/LogEntriesEntity.java | 0 .../java/com/arangodb/entity/LogLevel.java | 0 .../com/arangodb/entity/LogLevelEntity.java | 0 .../java/com/arangodb/entity/MetaAware.java | 0 .../arangodb/entity/MultiDocumentEntity.java | 0 .../java/com/arangodb/entity/Permissions.java | 0 .../entity/QueryCachePropertiesEntity.java | 0 .../java/com/arangodb/entity/QueryEntity.java | 0 .../arangodb/entity/QueryExecutionState.java | 0 .../arangodb/entity/QueryOptimizerRule.java | 0 .../entity/QueryTrackingPropertiesEntity.java | 0 .../arangodb/entity/ReplicationFactor.java | 0 .../java/com/arangodb/entity/ServerMode.java | 0 .../java/com/arangodb/entity/ServerRole.java | 0 .../java/com/arangodb/entity/ShardEntity.java | 0 .../com/arangodb/entity/ShardingStrategy.java | 0 .../entity/StreamTransactionEntity.java | 0 .../entity/StreamTransactionStatus.java | 0 .../arangodb/entity/TransactionEntity.java | 0 .../java/com/arangodb/entity/UserEntity.java | 0 .../com/arangodb/entity/VertexEntity.java | 0 .../arangodb/entity/VertexUpdateEntity.java | 0 .../java/com/arangodb/entity/ViewEntity.java | 0 .../java/com/arangodb/entity/ViewType.java | 0 .../entity/arangosearch/AnalyzerFeature.java | 0 .../entity/arangosearch/AnalyzerType.java | 0 .../arangosearch/ArangoSearchCompression.java | 0 .../ArangoSearchPropertiesEntity.java | 0 .../entity/arangosearch/CollectionLink.java | 0 .../arangosearch/ConsolidationPolicy.java | 0 .../arangosearch/ConsolidationType.java | 0 .../entity/arangosearch/FieldLink.java | 0 .../entity/arangosearch/PrimarySort.java | 0 .../entity/arangosearch/SearchAliasIndex.java | 0 .../SearchAliasPropertiesEntity.java | 0 .../entity/arangosearch/StoreValuesType.java | 0 .../entity/arangosearch/StoredValue.java | 0 .../arangosearch/analyzer/AQLAnalyzer.java | 0 .../analyzer/AQLAnalyzerProperties.java | 0 .../analyzer/ClassificationAnalyzer.java | 0 .../ClassificationAnalyzerProperties.java | 0 .../analyzer/CollationAnalyzer.java | 0 .../analyzer/CollationAnalyzerProperties.java | 0 .../analyzer/DelimiterAnalyzer.java | 0 .../analyzer/DelimiterAnalyzerProperties.java | 0 .../arangosearch/analyzer/EdgeNgram.java | 0 .../analyzer/GeoAnalyzerOptions.java | 0 .../analyzer/GeoJSONAnalyzer.java | 0 .../analyzer/GeoJSONAnalyzerProperties.java | 0 .../analyzer/GeoPointAnalyzer.java | 0 .../analyzer/GeoPointAnalyzerProperties.java | 0 .../analyzer/IdentityAnalyzer.java | 0 .../analyzer/MinHashAnalyzer.java | 0 .../analyzer/MinHashAnalyzerProperties.java | 0 .../arangosearch/analyzer/NGramAnalyzer.java | 0 .../analyzer/NGramAnalyzerProperties.java | 0 .../analyzer/NearestNeighborsAnalyzer.java | 0 .../NearestNeighborsAnalyzerProperties.java | 0 .../arangosearch/analyzer/NormAnalyzer.java | 0 .../analyzer/NormAnalyzerProperties.java | 0 .../analyzer/PipelineAnalyzer.java | 0 .../analyzer/PipelineAnalyzerProperties.java | 0 .../arangosearch/analyzer/SearchAnalyzer.java | 0 .../analyzer/SearchAnalyzerCase.java | 0 .../analyzer/SegmentationAnalyzer.java | 0 .../SegmentationAnalyzerProperties.java | 0 .../arangosearch/analyzer/StemAnalyzer.java | 0 .../analyzer/StemAnalyzerProperties.java | 0 .../analyzer/StopwordsAnalyzer.java | 0 .../analyzer/StopwordsAnalyzerProperties.java | 0 .../arangosearch/analyzer/StreamType.java | 0 .../arangosearch/analyzer/TextAnalyzer.java | 0 .../analyzer/TextAnalyzerProperties.java | 0 .../internal/ArangoCollectionImpl.java | 0 .../internal/ArangoCursorExecute.java | 0 .../com/arangodb/internal/ArangoDBImpl.java | 44 +-- .../arangodb/internal/ArangoDatabaseImpl.java | 0 .../com/arangodb/internal/ArangoDefaults.java | 0 .../internal/ArangoEdgeCollectionImpl.java | 0 .../com/arangodb/internal/ArangoErrors.java | 0 .../arangodb/internal/ArangoExecuteable.java | 0 .../com/arangodb/internal/ArangoExecutor.java | 9 +- .../arangodb/internal/ArangoExecutorSync.java | 7 +- .../arangodb/internal/ArangoGraphImpl.java | 0 .../arangodb/internal/ArangoMetricsImpl.java | 0 .../arangodb/internal/ArangoRequestParam.java | 0 .../internal/ArangoResponseField.java | 0 .../arangodb/internal/ArangoSearchImpl.java | 0 .../internal/ArangoVertexCollectionImpl.java | 0 .../com/arangodb/internal/ArangoViewImpl.java | 0 .../com/arangodb/internal/DocumentFields.java | 0 .../internal/InternalArangoCollection.java | 0 .../arangodb/internal/InternalArangoDB.java | 0 .../internal/InternalArangoDBBuilder.java | 349 ++++++++++++++++++ .../internal/InternalArangoDatabase.java | 0 .../InternalArangoEdgeCollection.java | 0 .../internal/InternalArangoGraph.java | 0 .../internal/InternalArangoRoute.java | 0 .../internal/InternalArangoSearch.java | 0 .../InternalArangoVertexCollection.java | 0 .../arangodb/internal/InternalArangoView.java | 0 .../arangodb/internal/InternalRequest.java | 0 .../arangodb/internal/InternalResponse.java | 0 .../internal/InternalSearchAlias.java | 0 .../internal/QueueTimeMetricsImpl.java | 0 .../com/arangodb/internal/RequestType.java | 0 .../arangodb/internal/SearchAliasImpl.java | 0 .../internal/config/ArangoConfig.java | 275 ++++++++++++++ .../config/ArangoConfigPropertiesImpl.java | 0 .../cursor/AbstractArangoIterable.java | 0 .../internal/cursor/ArangoCursorImpl.java | 0 .../internal/cursor/ArangoCursorIterator.java | 0 .../cursor/entity/InternalCursorEntity.java | 0 .../com/arangodb/internal/net/AccessType.java | 0 .../net/ArangoDBRedirectException.java | 0 .../internal/net/AsyncCommunication.java | 14 + .../internal/net/AsyncProtocolProvider.java | 18 + .../internal/net/CommunicationProtocol.java | 0 .../com/arangodb/internal/net/Connection.java | 0 .../internal/net/ConnectionFactory.java | 5 +- .../arangodb/internal/net/ConnectionPool.java | 0 .../internal/net/ConnectionPoolImpl.java | 21 +- .../internal/net/DirtyReadHostHandler.java | 0 .../internal/net/ExtendedHostResolver.java | 11 +- .../internal/net/FallbackHostHandler.java | 0 .../java/com/arangodb/internal/net/Host.java | 0 .../com/arangodb/internal/net/HostHandle.java | 0 .../arangodb/internal/net/HostHandler.java | 0 .../com/arangodb/internal/net/HostImpl.java | 0 .../arangodb/internal/net/HostResolver.java | 0 .../com/arangodb/internal/net/HostSet.java | 0 .../internal/net/ProtocolProvider.java | 17 + .../internal/net/RandomHostHandler.java | 0 .../internal/net/RoundRobinHostHandler.java | 0 .../internal/net/SimpleHostResolver.java | 0 .../internal/serde/ContentTypeFactory.java | 0 .../serde/InternalAnnotationIntrospector.java | 0 .../internal/serde/InternalDeserializers.java | 0 .../serde/InternalMapperProvider.java | 31 ++ .../internal/serde/InternalModule.java | 4 - .../serde/InternalParameterizedType.java | 0 .../internal/serde/InternalSerde.java | 0 .../internal/serde/InternalSerdeImpl.java | 6 +- .../internal/serde/InternalSerdeProvider.java | 9 +- .../internal/serde/InternalSerializers.java | 28 -- .../arangodb/internal/serde/SerdeUtils.java | 0 .../com/arangodb/internal/serde/UserData.java | 0 .../internal/serde/UserDataDeserializer.java | 0 .../internal/serde/UserDataInside.java | 0 .../internal/serde/UserDataSerializer.java | 0 .../arangodb/internal/util/DocumentUtil.java | 0 .../arangodb/internal/util/EncodeUtils.java | 0 .../com/arangodb/internal/util/HostUtils.java | 5 +- .../arangodb/internal/util/RequestUtils.java | 0 .../arangodb/internal/util/ResponseUtils.java | 0 .../model/AqlFunctionCreateOptions.java | 0 .../model/AqlFunctionDeleteOptions.java | 0 .../arangodb/model/AqlFunctionGetOptions.java | 0 .../model/AqlQueryExplainOptions.java | 0 .../com/arangodb/model/AqlQueryOptions.java | 0 .../arangodb/model/AqlQueryParseOptions.java | 0 .../model/CollectionCountOptions.java | 0 .../model/CollectionCreateOptions.java | 0 .../model/CollectionPropertiesOptions.java | 0 .../model/CollectionRenameOptions.java | 0 .../com/arangodb/model/CollectionSchema.java | 0 .../model/CollectionTruncateOptions.java | 0 .../model/CollectionsReadOptions.java | 0 .../com/arangodb/model/ComputedValue.java | 0 .../com/arangodb/model/DBCreateOptions.java | 0 .../com/arangodb/model/DatabaseOptions.java | 0 .../arangodb/model/DatabaseUsersOptions.java | 0 .../arangodb/model/DocumentCreateOptions.java | 0 .../arangodb/model/DocumentDeleteOptions.java | 0 .../arangodb/model/DocumentExistsOptions.java | 0 .../arangodb/model/DocumentImportOptions.java | 0 .../arangodb/model/DocumentReadOptions.java | 0 .../model/DocumentReplaceOptions.java | 0 .../arangodb/model/DocumentUpdateOptions.java | 0 .../com/arangodb/model/EdgeCreateOptions.java | 0 .../com/arangodb/model/EdgeDeleteOptions.java | 0 .../arangodb/model/EdgeReplaceOptions.java | 0 .../com/arangodb/model/EdgeUpdateOptions.java | 0 .../arangodb/model/FulltextIndexOptions.java | 0 .../com/arangodb/model/GeoIndexOptions.java | 0 .../arangodb/model/GraphCreateOptions.java | 0 .../model/GraphDocumentReadOptions.java | 0 .../com/arangodb/model/HashIndexOptions.java | 0 .../java/com/arangodb/model/ImportType.java | 0 .../java/com/arangodb/model/IndexOptions.java | 0 .../arangodb/model/InvertedIndexOptions.java | 0 .../java/com/arangodb/model/LogOptions.java | 0 .../com/arangodb/model/OptionsBuilder.java | 0 .../com/arangodb/model/OverwriteMode.java | 0 .../model/PersistentIndexOptions.java | 0 .../com/arangodb/model/QueueTimeSample.java | 0 .../arangodb/model/SkiplistIndexOptions.java | 0 .../model/StreamTransactionOptions.java | 0 .../model/TransactionCollectionOptions.java | 0 .../arangodb/model/TransactionOptions.java | 0 .../com/arangodb/model/TtlIndexOptions.java | 0 .../com/arangodb/model/UserAccessOptions.java | 0 .../com/arangodb/model/UserCreateOptions.java | 0 .../com/arangodb/model/UserUpdateOptions.java | 0 .../model/VertexCollectionCreateOptions.java | 0 .../arangodb/model/VertexCreateOptions.java | 0 .../arangodb/model/VertexDeleteOptions.java | 0 .../arangodb/model/VertexReplaceOptions.java | 0 .../arangodb/model/VertexUpdateOptions.java | 0 .../com/arangodb/model/ViewCreateOptions.java | 0 .../com/arangodb/model/ViewRenameOptions.java | 0 .../com/arangodb/model/ZKDIndexOptions.java | 0 .../arangosearch/AnalyzerDeleteOptions.java | 0 .../ArangoSearchCreateOptions.java | 0 .../ArangoSearchOptionsBuilder.java | 0 .../ArangoSearchPropertiesOptions.java | 0 .../SearchAliasCreateOptions.java | 0 .../SearchAliasOptionsBuilder.java | 0 .../SearchAliasPropertiesOptions.java | 0 .../java/com/arangodb/serde/ArangoSerde.java | 0 .../arangodb/serde/ArangoSerdeProvider.java | 0 .../main/java/com/arangodb/util/RawBytes.java | 0 .../main/java/com/arangodb/util/RawData.java | 0 .../main/java/com/arangodb/util/RawJson.java | 0 .../java/com/arangodb/util/UnicodeUtils.java | 0 docs/v7_detailed_changes.md | 2 +- docs/v7_java-reference-serialization.md | 2 +- driver/pom.xml | 106 +----- .../velocystream/VstConnectionAsync.java | 126 ------- .../internal/InternalArangoDBBuilder.java | 232 ------------ .../serde/InternalJsonMapperProvider.java | 12 - .../serde/InternalMapperProvider.java | 18 - .../serde/InternalVPackMapperProvider.java | 13 - .../internal/VstConnectionSync.java | 116 ------ .../arangodb/async/serde/CustomSerdeTest.java | 2 +- .../velocystream/CommunicationTest.java | 9 - http/pom.xml | 51 +++ .../com/arangodb}/http/HttpCommunication.java | 26 +- .../com/arangodb}/http/HttpConnection.java | 105 ++---- .../arangodb}/http/HttpConnectionFactory.java | 27 +- .../java/com/arangodb}/http/HttpProtocol.java | 2 +- .../arangodb/http/HttpProtocolProvider.java | 36 ++ ...com.arangodb.internal.net.ProtocolProvider | 1 + .../META-INF/vertx/vertx-version.txt | 0 jackson-serde/pom.xml | 17 +- .../serde/jackson/JacksonSerdeProvider.java | 9 +- .../internal/JacksonMapperProvider.java | 17 +- .../internal/JsonJacksonMapperProvider.java | 15 - .../internal/VPackJacksonMapperProvider.java | 16 - jsonb-serde/pom.xml | 4 +- pom.xml | 41 +- resilience-tests/pom.xml | 2 +- serde-api/pom.xml | 20 - shaded-integration-tests/pom.xml | 14 +- .../test/jsonb/java/arch/RelocationsTest.java | 8 - .../arangodb/async/serde/CustomSerdeTest.java | 2 +- .../velocystream/CommunicationTest.java | 9 - shaded/pom.xml | 56 +-- ...rangodb.internal.net.AsyncProtocolProvider | 1 + ...com.arangodb.internal.net.ProtocolProvider | 2 + ....shaded.fasterxml.jackson.core.JsonFactory | 2 + tutorial/gradle/build.gradle | 2 +- tutorial/maven/pom.xml | 2 +- vst/pom.xml | 33 ++ .../vst/VstAsyncProtocolProvider.java | 30 ++ .../com/arangodb/vst}/VstCommunication.java | 39 +- .../arangodb/vst}/VstCommunicationSync.java | 109 +----- .../vst}/VstConnectionFactorySync.java | 26 +- .../main/java/com/arangodb/vst/VstModule.java | 26 ++ .../java/com/arangodb/vst}/VstProtocol.java | 4 +- .../com/arangodb/vst/VstProtocolProvider.java | 32 ++ .../java/com/arangodb/vst/VstSerializers.java | 40 ++ .../vst/async}/VstCommunicationAsync.java | 105 +----- .../vst/async/VstConnectionAsync.java | 69 ++++ .../vst/async}/VstConnectionFactoryAsync.java | 24 +- .../vst}/internal/AuthenticationRequest.java | 2 +- .../com/arangodb/vst}/internal/Chunk.java | 2 +- .../arangodb/vst}/internal/ChunkStore.java | 2 +- .../internal/JwtAuthenticationRequest.java | 2 +- .../com/arangodb/vst}/internal/Message.java | 2 +- .../arangodb/vst}/internal/MessageStore.java | 2 +- .../arangodb/vst}/internal/VstConnection.java | 27 +- .../vst/internal/VstConnectionSync.java | 63 ++++ ...rangodb.internal.net.AsyncProtocolProvider | 1 + ...com.arangodb.internal.net.ProtocolProvider | 1 + 371 files changed, 1502 insertions(+), 1842 deletions(-) create mode 100644 core/pom.xml rename {driver => core}/src/main/java/com/arangodb/ArangoCollection.java (100%) rename {driver => core}/src/main/java/com/arangodb/ArangoCursor.java (100%) rename {driver => core}/src/main/java/com/arangodb/ArangoDB.java (51%) rename {driver => core}/src/main/java/com/arangodb/ArangoDBException.java (100%) rename {driver => core}/src/main/java/com/arangodb/ArangoDBMultipleException.java (100%) rename {driver => core}/src/main/java/com/arangodb/ArangoDatabase.java (100%) rename {driver => core}/src/main/java/com/arangodb/ArangoEdgeCollection.java (100%) rename {driver => core}/src/main/java/com/arangodb/ArangoGraph.java (100%) rename {driver => core}/src/main/java/com/arangodb/ArangoIterable.java (100%) rename {driver => core}/src/main/java/com/arangodb/ArangoIterator.java (100%) rename {driver => core}/src/main/java/com/arangodb/ArangoMetrics.java (100%) rename {driver => core}/src/main/java/com/arangodb/ArangoSearch.java (100%) rename {driver => core}/src/main/java/com/arangodb/ArangoSerdeAccessor.java (100%) rename {driver => core}/src/main/java/com/arangodb/ArangoVertexCollection.java (100%) rename {driver => core}/src/main/java/com/arangodb/ArangoView.java (100%) rename {serde-api => core}/src/main/java/com/arangodb/ContentType.java (100%) rename {driver => core}/src/main/java/com/arangodb/DbName.java (100%) rename {driver => core}/src/main/java/com/arangodb/PackageVersion.java.in (100%) rename {driver => core}/src/main/java/com/arangodb/Protocol.java (100%) rename {driver => core}/src/main/java/com/arangodb/QueueTimeMetrics.java (100%) rename {driver => core}/src/main/java/com/arangodb/Request.java (100%) rename {driver => core}/src/main/java/com/arangodb/Response.java (100%) rename {driver => core}/src/main/java/com/arangodb/SearchAlias.java (100%) rename {driver => core}/src/main/java/com/arangodb/async/ArangoCollectionAsync.java (100%) rename {driver => core}/src/main/java/com/arangodb/async/ArangoCursorAsync.java (100%) rename {driver => core}/src/main/java/com/arangodb/async/ArangoDBAsync.java (54%) rename {driver => core}/src/main/java/com/arangodb/async/ArangoDatabaseAsync.java (100%) rename {driver => core}/src/main/java/com/arangodb/async/ArangoEdgeCollectionAsync.java (100%) rename {driver => core}/src/main/java/com/arangodb/async/ArangoGraphAsync.java (100%) rename {driver => core}/src/main/java/com/arangodb/async/ArangoRouteAsync.java (100%) rename {driver => core}/src/main/java/com/arangodb/async/ArangoSearchAsync.java (100%) rename {driver => core}/src/main/java/com/arangodb/async/ArangoVertexCollectionAsync.java (100%) rename {driver => core}/src/main/java/com/arangodb/async/ArangoViewAsync.java (100%) rename {driver => core}/src/main/java/com/arangodb/async/SearchAliasAsync.java (100%) rename {driver => core}/src/main/java/com/arangodb/async/internal/ArangoCollectionAsyncImpl.java (100%) rename {driver => core}/src/main/java/com/arangodb/async/internal/ArangoCursorAsyncImpl.java (100%) rename {driver => core}/src/main/java/com/arangodb/async/internal/ArangoDBAsyncImpl.java (83%) rename {driver => core}/src/main/java/com/arangodb/async/internal/ArangoDatabaseAsyncImpl.java (100%) rename {driver => core}/src/main/java/com/arangodb/async/internal/ArangoEdgeCollectionAsyncImpl.java (100%) rename {driver => core}/src/main/java/com/arangodb/async/internal/ArangoExecutorAsync.java (85%) rename {driver => core}/src/main/java/com/arangodb/async/internal/ArangoGraphAsyncImpl.java (100%) rename {driver => core}/src/main/java/com/arangodb/async/internal/ArangoRouteAsyncImpl.java (100%) rename {driver => core}/src/main/java/com/arangodb/async/internal/ArangoSearchAsyncImpl.java (100%) rename {driver => core}/src/main/java/com/arangodb/async/internal/ArangoVertexCollectionAsyncImpl.java (100%) rename {driver => core}/src/main/java/com/arangodb/async/internal/ArangoViewAsyncImpl.java (100%) rename {driver => core}/src/main/java/com/arangodb/async/internal/ExceptionUtil.java (100%) rename {driver => core}/src/main/java/com/arangodb/async/internal/SearchAliasAsyncImpl.java (100%) rename {driver => core}/src/main/java/com/arangodb/async/internal/utils/CompletableFutureUtils.java (100%) rename {driver => core}/src/main/java/com/arangodb/config/ArangoConfigProperties.java (100%) rename {driver => core}/src/main/java/com/arangodb/config/HostDescription.java (100%) rename {driver => core}/src/main/java/com/arangodb/entity/AbstractBaseDocument.java (100%) rename {driver => core}/src/main/java/com/arangodb/entity/AqlExecutionExplainEntity.java (100%) rename {driver => core}/src/main/java/com/arangodb/entity/AqlFunctionEntity.java (100%) rename {driver => core}/src/main/java/com/arangodb/entity/AqlParseEntity.java (100%) rename {driver => core}/src/main/java/com/arangodb/entity/ArangoDBEngine.java (100%) rename {driver => core}/src/main/java/com/arangodb/entity/ArangoDBVersion.java (100%) rename {driver => core}/src/main/java/com/arangodb/entity/BaseDocument.java (100%) rename {driver => core}/src/main/java/com/arangodb/entity/BaseEdgeDocument.java (100%) rename {driver => core}/src/main/java/com/arangodb/entity/CollectionEntity.java (100%) rename {driver => core}/src/main/java/com/arangodb/entity/CollectionPropertiesEntity.java (100%) rename {driver => core}/src/main/java/com/arangodb/entity/CollectionRevisionEntity.java (100%) rename {driver => core}/src/main/java/com/arangodb/entity/CollectionStatus.java (100%) rename {driver => core}/src/main/java/com/arangodb/entity/CollectionType.java (100%) rename {driver => core}/src/main/java/com/arangodb/entity/CursorWarning.java (100%) rename {driver => core}/src/main/java/com/arangodb/entity/DatabaseEntity.java (100%) rename {driver => core}/src/main/java/com/arangodb/entity/DocumentCreateEntity.java (100%) rename {driver => core}/src/main/java/com/arangodb/entity/DocumentDeleteEntity.java (100%) rename {driver => core}/src/main/java/com/arangodb/entity/DocumentEntity.java (100%) rename {driver => core}/src/main/java/com/arangodb/entity/DocumentImportEntity.java (100%) rename {driver => core}/src/main/java/com/arangodb/entity/DocumentUpdateEntity.java (100%) rename {driver => core}/src/main/java/com/arangodb/entity/EdgeDefinition.java (100%) rename {driver => core}/src/main/java/com/arangodb/entity/EdgeEntity.java (100%) rename {driver => core}/src/main/java/com/arangodb/entity/EdgeUpdateEntity.java (100%) rename {driver => core}/src/main/java/com/arangodb/entity/ErrorEntity.java (100%) rename {driver => core}/src/main/java/com/arangodb/entity/GraphEntity.java (100%) rename {driver => core}/src/main/java/com/arangodb/entity/IndexEntity.java (100%) rename {driver => core}/src/main/java/com/arangodb/entity/IndexType.java (100%) rename {driver => core}/src/main/java/com/arangodb/entity/InvertedIndexEntity.java (100%) rename {driver => core}/src/main/java/com/arangodb/entity/InvertedIndexField.java (100%) rename {driver => core}/src/main/java/com/arangodb/entity/InvertedIndexPrimarySort.java (100%) rename {driver => core}/src/main/java/com/arangodb/entity/KeyOptions.java (100%) rename {driver => core}/src/main/java/com/arangodb/entity/KeyType.java (100%) rename {driver => core}/src/main/java/com/arangodb/entity/License.java (100%) rename {driver => core}/src/main/java/com/arangodb/entity/LoadBalancingStrategy.java (100%) rename {driver => core}/src/main/java/com/arangodb/entity/LogEntriesEntity.java (100%) rename {driver => core}/src/main/java/com/arangodb/entity/LogLevel.java (100%) rename {driver => core}/src/main/java/com/arangodb/entity/LogLevelEntity.java (100%) rename {driver => core}/src/main/java/com/arangodb/entity/MetaAware.java (100%) rename {driver => core}/src/main/java/com/arangodb/entity/MultiDocumentEntity.java (100%) rename {driver => core}/src/main/java/com/arangodb/entity/Permissions.java (100%) rename {driver => core}/src/main/java/com/arangodb/entity/QueryCachePropertiesEntity.java (100%) rename {driver => core}/src/main/java/com/arangodb/entity/QueryEntity.java (100%) rename {driver => core}/src/main/java/com/arangodb/entity/QueryExecutionState.java (100%) rename {driver => core}/src/main/java/com/arangodb/entity/QueryOptimizerRule.java (100%) rename {driver => core}/src/main/java/com/arangodb/entity/QueryTrackingPropertiesEntity.java (100%) rename {driver => core}/src/main/java/com/arangodb/entity/ReplicationFactor.java (100%) rename {driver => core}/src/main/java/com/arangodb/entity/ServerMode.java (100%) rename {driver => core}/src/main/java/com/arangodb/entity/ServerRole.java (100%) rename {driver => core}/src/main/java/com/arangodb/entity/ShardEntity.java (100%) rename {driver => core}/src/main/java/com/arangodb/entity/ShardingStrategy.java (100%) rename {driver => core}/src/main/java/com/arangodb/entity/StreamTransactionEntity.java (100%) rename {driver => core}/src/main/java/com/arangodb/entity/StreamTransactionStatus.java (100%) rename {driver => core}/src/main/java/com/arangodb/entity/TransactionEntity.java (100%) rename {driver => core}/src/main/java/com/arangodb/entity/UserEntity.java (100%) rename {driver => core}/src/main/java/com/arangodb/entity/VertexEntity.java (100%) rename {driver => core}/src/main/java/com/arangodb/entity/VertexUpdateEntity.java (100%) rename {driver => core}/src/main/java/com/arangodb/entity/ViewEntity.java (100%) rename {driver => core}/src/main/java/com/arangodb/entity/ViewType.java (100%) rename {driver => core}/src/main/java/com/arangodb/entity/arangosearch/AnalyzerFeature.java (100%) rename {driver => core}/src/main/java/com/arangodb/entity/arangosearch/AnalyzerType.java (100%) rename {driver => core}/src/main/java/com/arangodb/entity/arangosearch/ArangoSearchCompression.java (100%) rename {driver => core}/src/main/java/com/arangodb/entity/arangosearch/ArangoSearchPropertiesEntity.java (100%) rename {driver => core}/src/main/java/com/arangodb/entity/arangosearch/CollectionLink.java (100%) rename {driver => core}/src/main/java/com/arangodb/entity/arangosearch/ConsolidationPolicy.java (100%) rename {driver => core}/src/main/java/com/arangodb/entity/arangosearch/ConsolidationType.java (100%) rename {driver => core}/src/main/java/com/arangodb/entity/arangosearch/FieldLink.java (100%) rename {driver => core}/src/main/java/com/arangodb/entity/arangosearch/PrimarySort.java (100%) rename {driver => core}/src/main/java/com/arangodb/entity/arangosearch/SearchAliasIndex.java (100%) rename {driver => core}/src/main/java/com/arangodb/entity/arangosearch/SearchAliasPropertiesEntity.java (100%) rename {driver => core}/src/main/java/com/arangodb/entity/arangosearch/StoreValuesType.java (100%) rename {driver => core}/src/main/java/com/arangodb/entity/arangosearch/StoredValue.java (100%) rename {driver => core}/src/main/java/com/arangodb/entity/arangosearch/analyzer/AQLAnalyzer.java (100%) rename {driver => core}/src/main/java/com/arangodb/entity/arangosearch/analyzer/AQLAnalyzerProperties.java (100%) rename {driver => core}/src/main/java/com/arangodb/entity/arangosearch/analyzer/ClassificationAnalyzer.java (100%) rename {driver => core}/src/main/java/com/arangodb/entity/arangosearch/analyzer/ClassificationAnalyzerProperties.java (100%) rename {driver => core}/src/main/java/com/arangodb/entity/arangosearch/analyzer/CollationAnalyzer.java (100%) rename {driver => core}/src/main/java/com/arangodb/entity/arangosearch/analyzer/CollationAnalyzerProperties.java (100%) rename {driver => core}/src/main/java/com/arangodb/entity/arangosearch/analyzer/DelimiterAnalyzer.java (100%) rename {driver => core}/src/main/java/com/arangodb/entity/arangosearch/analyzer/DelimiterAnalyzerProperties.java (100%) rename {driver => core}/src/main/java/com/arangodb/entity/arangosearch/analyzer/EdgeNgram.java (100%) rename {driver => core}/src/main/java/com/arangodb/entity/arangosearch/analyzer/GeoAnalyzerOptions.java (100%) rename {driver => core}/src/main/java/com/arangodb/entity/arangosearch/analyzer/GeoJSONAnalyzer.java (100%) rename {driver => core}/src/main/java/com/arangodb/entity/arangosearch/analyzer/GeoJSONAnalyzerProperties.java (100%) rename {driver => core}/src/main/java/com/arangodb/entity/arangosearch/analyzer/GeoPointAnalyzer.java (100%) rename {driver => core}/src/main/java/com/arangodb/entity/arangosearch/analyzer/GeoPointAnalyzerProperties.java (100%) rename {driver => core}/src/main/java/com/arangodb/entity/arangosearch/analyzer/IdentityAnalyzer.java (100%) rename {driver => core}/src/main/java/com/arangodb/entity/arangosearch/analyzer/MinHashAnalyzer.java (100%) rename {driver => core}/src/main/java/com/arangodb/entity/arangosearch/analyzer/MinHashAnalyzerProperties.java (100%) rename {driver => core}/src/main/java/com/arangodb/entity/arangosearch/analyzer/NGramAnalyzer.java (100%) rename {driver => core}/src/main/java/com/arangodb/entity/arangosearch/analyzer/NGramAnalyzerProperties.java (100%) rename {driver => core}/src/main/java/com/arangodb/entity/arangosearch/analyzer/NearestNeighborsAnalyzer.java (100%) rename {driver => core}/src/main/java/com/arangodb/entity/arangosearch/analyzer/NearestNeighborsAnalyzerProperties.java (100%) rename {driver => core}/src/main/java/com/arangodb/entity/arangosearch/analyzer/NormAnalyzer.java (100%) rename {driver => core}/src/main/java/com/arangodb/entity/arangosearch/analyzer/NormAnalyzerProperties.java (100%) rename {driver => core}/src/main/java/com/arangodb/entity/arangosearch/analyzer/PipelineAnalyzer.java (100%) rename {driver => core}/src/main/java/com/arangodb/entity/arangosearch/analyzer/PipelineAnalyzerProperties.java (100%) rename {driver => core}/src/main/java/com/arangodb/entity/arangosearch/analyzer/SearchAnalyzer.java (100%) rename {driver => core}/src/main/java/com/arangodb/entity/arangosearch/analyzer/SearchAnalyzerCase.java (100%) rename {driver => core}/src/main/java/com/arangodb/entity/arangosearch/analyzer/SegmentationAnalyzer.java (100%) rename {driver => core}/src/main/java/com/arangodb/entity/arangosearch/analyzer/SegmentationAnalyzerProperties.java (100%) rename {driver => core}/src/main/java/com/arangodb/entity/arangosearch/analyzer/StemAnalyzer.java (100%) rename {driver => core}/src/main/java/com/arangodb/entity/arangosearch/analyzer/StemAnalyzerProperties.java (100%) rename {driver => core}/src/main/java/com/arangodb/entity/arangosearch/analyzer/StopwordsAnalyzer.java (100%) rename {driver => core}/src/main/java/com/arangodb/entity/arangosearch/analyzer/StopwordsAnalyzerProperties.java (100%) rename {driver => core}/src/main/java/com/arangodb/entity/arangosearch/analyzer/StreamType.java (100%) rename {driver => core}/src/main/java/com/arangodb/entity/arangosearch/analyzer/TextAnalyzer.java (100%) rename {driver => core}/src/main/java/com/arangodb/entity/arangosearch/analyzer/TextAnalyzerProperties.java (100%) rename {driver => core}/src/main/java/com/arangodb/internal/ArangoCollectionImpl.java (100%) rename {driver => core}/src/main/java/com/arangodb/internal/ArangoCursorExecute.java (100%) rename {driver => core}/src/main/java/com/arangodb/internal/ArangoDBImpl.java (78%) rename {driver => core}/src/main/java/com/arangodb/internal/ArangoDatabaseImpl.java (100%) rename {driver => core}/src/main/java/com/arangodb/internal/ArangoDefaults.java (100%) rename {driver => core}/src/main/java/com/arangodb/internal/ArangoEdgeCollectionImpl.java (100%) rename {driver => core}/src/main/java/com/arangodb/internal/ArangoErrors.java (100%) rename {driver => core}/src/main/java/com/arangodb/internal/ArangoExecuteable.java (100%) rename {driver => core}/src/main/java/com/arangodb/internal/ArangoExecutor.java (84%) rename {driver => core}/src/main/java/com/arangodb/internal/ArangoExecutorSync.java (92%) rename {driver => core}/src/main/java/com/arangodb/internal/ArangoGraphImpl.java (100%) rename {driver => core}/src/main/java/com/arangodb/internal/ArangoMetricsImpl.java (100%) rename {driver => core}/src/main/java/com/arangodb/internal/ArangoRequestParam.java (100%) rename {driver => core}/src/main/java/com/arangodb/internal/ArangoResponseField.java (100%) rename {driver => core}/src/main/java/com/arangodb/internal/ArangoSearchImpl.java (100%) rename {driver => core}/src/main/java/com/arangodb/internal/ArangoVertexCollectionImpl.java (100%) rename {driver => core}/src/main/java/com/arangodb/internal/ArangoViewImpl.java (100%) rename {driver => core}/src/main/java/com/arangodb/internal/DocumentFields.java (100%) rename {driver => core}/src/main/java/com/arangodb/internal/InternalArangoCollection.java (100%) rename {driver => core}/src/main/java/com/arangodb/internal/InternalArangoDB.java (100%) create mode 100644 core/src/main/java/com/arangodb/internal/InternalArangoDBBuilder.java rename {driver => core}/src/main/java/com/arangodb/internal/InternalArangoDatabase.java (100%) rename {driver => core}/src/main/java/com/arangodb/internal/InternalArangoEdgeCollection.java (100%) rename {driver => core}/src/main/java/com/arangodb/internal/InternalArangoGraph.java (100%) rename {driver => core}/src/main/java/com/arangodb/internal/InternalArangoRoute.java (100%) rename {driver => core}/src/main/java/com/arangodb/internal/InternalArangoSearch.java (100%) rename {driver => core}/src/main/java/com/arangodb/internal/InternalArangoVertexCollection.java (100%) rename {driver => core}/src/main/java/com/arangodb/internal/InternalArangoView.java (100%) rename {driver => core}/src/main/java/com/arangodb/internal/InternalRequest.java (100%) rename {driver => core}/src/main/java/com/arangodb/internal/InternalResponse.java (100%) rename {driver => core}/src/main/java/com/arangodb/internal/InternalSearchAlias.java (100%) rename {driver => core}/src/main/java/com/arangodb/internal/QueueTimeMetricsImpl.java (100%) rename {driver => core}/src/main/java/com/arangodb/internal/RequestType.java (100%) rename {driver => core}/src/main/java/com/arangodb/internal/SearchAliasImpl.java (100%) create mode 100644 core/src/main/java/com/arangodb/internal/config/ArangoConfig.java rename {driver => core}/src/main/java/com/arangodb/internal/config/ArangoConfigPropertiesImpl.java (100%) rename {driver => core}/src/main/java/com/arangodb/internal/cursor/AbstractArangoIterable.java (100%) rename {driver => core}/src/main/java/com/arangodb/internal/cursor/ArangoCursorImpl.java (100%) rename {driver => core}/src/main/java/com/arangodb/internal/cursor/ArangoCursorIterator.java (100%) rename {driver => core}/src/main/java/com/arangodb/internal/cursor/entity/InternalCursorEntity.java (100%) rename {driver => core}/src/main/java/com/arangodb/internal/net/AccessType.java (100%) rename {driver => core}/src/main/java/com/arangodb/internal/net/ArangoDBRedirectException.java (100%) create mode 100644 core/src/main/java/com/arangodb/internal/net/AsyncCommunication.java create mode 100644 core/src/main/java/com/arangodb/internal/net/AsyncProtocolProvider.java rename {driver => core}/src/main/java/com/arangodb/internal/net/CommunicationProtocol.java (100%) rename {driver => core}/src/main/java/com/arangodb/internal/net/Connection.java (100%) rename {driver => core}/src/main/java/com/arangodb/internal/net/ConnectionFactory.java (87%) rename {driver => core}/src/main/java/com/arangodb/internal/net/ConnectionPool.java (100%) rename {driver => core}/src/main/java/com/arangodb/internal/net/ConnectionPoolImpl.java (81%) rename {driver => core}/src/main/java/com/arangodb/internal/net/DirtyReadHostHandler.java (100%) rename {driver => core}/src/main/java/com/arangodb/internal/net/ExtendedHostResolver.java (95%) rename {driver => core}/src/main/java/com/arangodb/internal/net/FallbackHostHandler.java (100%) rename {driver => core}/src/main/java/com/arangodb/internal/net/Host.java (100%) rename {driver => core}/src/main/java/com/arangodb/internal/net/HostHandle.java (100%) rename {driver => core}/src/main/java/com/arangodb/internal/net/HostHandler.java (100%) rename {driver => core}/src/main/java/com/arangodb/internal/net/HostImpl.java (100%) rename {driver => core}/src/main/java/com/arangodb/internal/net/HostResolver.java (100%) rename {driver => core}/src/main/java/com/arangodb/internal/net/HostSet.java (100%) create mode 100644 core/src/main/java/com/arangodb/internal/net/ProtocolProvider.java rename {driver => core}/src/main/java/com/arangodb/internal/net/RandomHostHandler.java (100%) rename {driver => core}/src/main/java/com/arangodb/internal/net/RoundRobinHostHandler.java (100%) rename {driver => core}/src/main/java/com/arangodb/internal/net/SimpleHostResolver.java (100%) rename {driver => core}/src/main/java/com/arangodb/internal/serde/ContentTypeFactory.java (100%) rename {driver => core}/src/main/java/com/arangodb/internal/serde/InternalAnnotationIntrospector.java (100%) rename {driver => core}/src/main/java/com/arangodb/internal/serde/InternalDeserializers.java (100%) create mode 100644 core/src/main/java/com/arangodb/internal/serde/InternalMapperProvider.java rename {driver => core}/src/main/java/com/arangodb/internal/serde/InternalModule.java (83%) rename {driver => core}/src/main/java/com/arangodb/internal/serde/InternalParameterizedType.java (100%) rename {driver => core}/src/main/java/com/arangodb/internal/serde/InternalSerde.java (100%) rename {driver => core}/src/main/java/com/arangodb/internal/serde/InternalSerdeImpl.java (96%) rename {driver => core}/src/main/java/com/arangodb/internal/serde/InternalSerdeProvider.java (73%) rename {driver => core}/src/main/java/com/arangodb/internal/serde/InternalSerializers.java (73%) rename {driver => core}/src/main/java/com/arangodb/internal/serde/SerdeUtils.java (100%) rename {driver => core}/src/main/java/com/arangodb/internal/serde/UserData.java (100%) rename {driver => core}/src/main/java/com/arangodb/internal/serde/UserDataDeserializer.java (100%) rename {driver => core}/src/main/java/com/arangodb/internal/serde/UserDataInside.java (100%) rename {driver => core}/src/main/java/com/arangodb/internal/serde/UserDataSerializer.java (100%) rename {driver => core}/src/main/java/com/arangodb/internal/util/DocumentUtil.java (100%) rename {driver => core}/src/main/java/com/arangodb/internal/util/EncodeUtils.java (100%) rename {driver => core}/src/main/java/com/arangodb/internal/util/HostUtils.java (92%) rename {driver => core}/src/main/java/com/arangodb/internal/util/RequestUtils.java (100%) rename {driver => core}/src/main/java/com/arangodb/internal/util/ResponseUtils.java (100%) rename {driver => core}/src/main/java/com/arangodb/model/AqlFunctionCreateOptions.java (100%) rename {driver => core}/src/main/java/com/arangodb/model/AqlFunctionDeleteOptions.java (100%) rename {driver => core}/src/main/java/com/arangodb/model/AqlFunctionGetOptions.java (100%) rename {driver => core}/src/main/java/com/arangodb/model/AqlQueryExplainOptions.java (100%) rename {driver => core}/src/main/java/com/arangodb/model/AqlQueryOptions.java (100%) rename {driver => core}/src/main/java/com/arangodb/model/AqlQueryParseOptions.java (100%) rename {driver => core}/src/main/java/com/arangodb/model/CollectionCountOptions.java (100%) rename {driver => core}/src/main/java/com/arangodb/model/CollectionCreateOptions.java (100%) rename {driver => core}/src/main/java/com/arangodb/model/CollectionPropertiesOptions.java (100%) rename {driver => core}/src/main/java/com/arangodb/model/CollectionRenameOptions.java (100%) rename {driver => core}/src/main/java/com/arangodb/model/CollectionSchema.java (100%) rename {driver => core}/src/main/java/com/arangodb/model/CollectionTruncateOptions.java (100%) rename {driver => core}/src/main/java/com/arangodb/model/CollectionsReadOptions.java (100%) rename {driver => core}/src/main/java/com/arangodb/model/ComputedValue.java (100%) rename {driver => core}/src/main/java/com/arangodb/model/DBCreateOptions.java (100%) rename {driver => core}/src/main/java/com/arangodb/model/DatabaseOptions.java (100%) rename {driver => core}/src/main/java/com/arangodb/model/DatabaseUsersOptions.java (100%) rename {driver => core}/src/main/java/com/arangodb/model/DocumentCreateOptions.java (100%) rename {driver => core}/src/main/java/com/arangodb/model/DocumentDeleteOptions.java (100%) rename {driver => core}/src/main/java/com/arangodb/model/DocumentExistsOptions.java (100%) rename {driver => core}/src/main/java/com/arangodb/model/DocumentImportOptions.java (100%) rename {driver => core}/src/main/java/com/arangodb/model/DocumentReadOptions.java (100%) rename {driver => core}/src/main/java/com/arangodb/model/DocumentReplaceOptions.java (100%) rename {driver => core}/src/main/java/com/arangodb/model/DocumentUpdateOptions.java (100%) rename {driver => core}/src/main/java/com/arangodb/model/EdgeCreateOptions.java (100%) rename {driver => core}/src/main/java/com/arangodb/model/EdgeDeleteOptions.java (100%) rename {driver => core}/src/main/java/com/arangodb/model/EdgeReplaceOptions.java (100%) rename {driver => core}/src/main/java/com/arangodb/model/EdgeUpdateOptions.java (100%) rename {driver => core}/src/main/java/com/arangodb/model/FulltextIndexOptions.java (100%) rename {driver => core}/src/main/java/com/arangodb/model/GeoIndexOptions.java (100%) rename {driver => core}/src/main/java/com/arangodb/model/GraphCreateOptions.java (100%) rename {driver => core}/src/main/java/com/arangodb/model/GraphDocumentReadOptions.java (100%) rename {driver => core}/src/main/java/com/arangodb/model/HashIndexOptions.java (100%) rename {driver => core}/src/main/java/com/arangodb/model/ImportType.java (100%) rename {driver => core}/src/main/java/com/arangodb/model/IndexOptions.java (100%) rename {driver => core}/src/main/java/com/arangodb/model/InvertedIndexOptions.java (100%) rename {driver => core}/src/main/java/com/arangodb/model/LogOptions.java (100%) rename {driver => core}/src/main/java/com/arangodb/model/OptionsBuilder.java (100%) rename {driver => core}/src/main/java/com/arangodb/model/OverwriteMode.java (100%) rename {driver => core}/src/main/java/com/arangodb/model/PersistentIndexOptions.java (100%) rename {driver => core}/src/main/java/com/arangodb/model/QueueTimeSample.java (100%) rename {driver => core}/src/main/java/com/arangodb/model/SkiplistIndexOptions.java (100%) rename {driver => core}/src/main/java/com/arangodb/model/StreamTransactionOptions.java (100%) rename {driver => core}/src/main/java/com/arangodb/model/TransactionCollectionOptions.java (100%) rename {driver => core}/src/main/java/com/arangodb/model/TransactionOptions.java (100%) rename {driver => core}/src/main/java/com/arangodb/model/TtlIndexOptions.java (100%) rename {driver => core}/src/main/java/com/arangodb/model/UserAccessOptions.java (100%) rename {driver => core}/src/main/java/com/arangodb/model/UserCreateOptions.java (100%) rename {driver => core}/src/main/java/com/arangodb/model/UserUpdateOptions.java (100%) rename {driver => core}/src/main/java/com/arangodb/model/VertexCollectionCreateOptions.java (100%) rename {driver => core}/src/main/java/com/arangodb/model/VertexCreateOptions.java (100%) rename {driver => core}/src/main/java/com/arangodb/model/VertexDeleteOptions.java (100%) rename {driver => core}/src/main/java/com/arangodb/model/VertexReplaceOptions.java (100%) rename {driver => core}/src/main/java/com/arangodb/model/VertexUpdateOptions.java (100%) rename {driver => core}/src/main/java/com/arangodb/model/ViewCreateOptions.java (100%) rename {driver => core}/src/main/java/com/arangodb/model/ViewRenameOptions.java (100%) rename {driver => core}/src/main/java/com/arangodb/model/ZKDIndexOptions.java (100%) rename {driver => core}/src/main/java/com/arangodb/model/arangosearch/AnalyzerDeleteOptions.java (100%) rename {driver => core}/src/main/java/com/arangodb/model/arangosearch/ArangoSearchCreateOptions.java (100%) rename {driver => core}/src/main/java/com/arangodb/model/arangosearch/ArangoSearchOptionsBuilder.java (100%) rename {driver => core}/src/main/java/com/arangodb/model/arangosearch/ArangoSearchPropertiesOptions.java (100%) rename {driver => core}/src/main/java/com/arangodb/model/arangosearch/SearchAliasCreateOptions.java (100%) rename {driver => core}/src/main/java/com/arangodb/model/arangosearch/SearchAliasOptionsBuilder.java (100%) rename {driver => core}/src/main/java/com/arangodb/model/arangosearch/SearchAliasPropertiesOptions.java (100%) rename {serde-api => core}/src/main/java/com/arangodb/serde/ArangoSerde.java (100%) rename {serde-api => core}/src/main/java/com/arangodb/serde/ArangoSerdeProvider.java (100%) rename {driver => core}/src/main/java/com/arangodb/util/RawBytes.java (100%) rename {driver => core}/src/main/java/com/arangodb/util/RawData.java (100%) rename {driver => core}/src/main/java/com/arangodb/util/RawJson.java (100%) rename {driver => core}/src/main/java/com/arangodb/util/UnicodeUtils.java (100%) delete mode 100644 driver/src/main/java/com/arangodb/async/internal/velocystream/VstConnectionAsync.java delete mode 100644 driver/src/main/java/com/arangodb/internal/InternalArangoDBBuilder.java delete mode 100644 driver/src/main/java/com/arangodb/internal/serde/InternalJsonMapperProvider.java delete mode 100644 driver/src/main/java/com/arangodb/internal/serde/InternalMapperProvider.java delete mode 100644 driver/src/main/java/com/arangodb/internal/serde/InternalVPackMapperProvider.java delete mode 100644 driver/src/main/java/com/arangodb/internal/velocystream/internal/VstConnectionSync.java create mode 100644 http/pom.xml rename {driver/src/main/java/com/arangodb/internal => http/src/main/java/com/arangodb}/http/HttpCommunication.java (88%) rename {driver/src/main/java/com/arangodb/internal => http/src/main/java/com/arangodb}/http/HttpConnection.java (79%) rename {driver/src/main/java/com/arangodb/internal => http/src/main/java/com/arangodb}/http/HttpConnectionFactory.java (51%) rename {driver/src/main/java/com/arangodb/internal => http/src/main/java/com/arangodb}/http/HttpProtocol.java (97%) create mode 100644 http/src/main/java/com/arangodb/http/HttpProtocolProvider.java create mode 100644 http/src/main/resources/META-INF/services/com.arangodb.internal.net.ProtocolProvider rename {driver => http}/src/main/resources/META-INF/vertx/vertx-version.txt (100%) delete mode 100644 jackson-serde/src/main/java/com/arangodb/serde/jackson/internal/JsonJacksonMapperProvider.java delete mode 100644 jackson-serde/src/main/java/com/arangodb/serde/jackson/internal/VPackJacksonMapperProvider.java delete mode 100644 serde-api/pom.xml create mode 100644 shaded/src/main/resources/META-INF/services/com.arangodb.internal.net.AsyncProtocolProvider create mode 100644 shaded/src/main/resources/META-INF/services/com.arangodb.internal.net.ProtocolProvider create mode 100644 shaded/src/main/resources/META-INF/services/com.arangodb.shaded.fasterxml.jackson.core.JsonFactory create mode 100644 vst/pom.xml create mode 100644 vst/src/main/java/com/arangodb/vst/VstAsyncProtocolProvider.java rename {driver/src/main/java/com/arangodb/internal/velocystream => vst/src/main/java/com/arangodb/vst}/VstCommunication.java (86%) rename {driver/src/main/java/com/arangodb/internal/velocystream => vst/src/main/java/com/arangodb/vst}/VstCommunicationSync.java (51%) rename {driver/src/main/java/com/arangodb/internal/velocystream => vst/src/main/java/com/arangodb/vst}/VstConnectionFactorySync.java (52%) create mode 100644 vst/src/main/java/com/arangodb/vst/VstModule.java rename {driver/src/main/java/com/arangodb/internal/velocystream => vst/src/main/java/com/arangodb/vst}/VstProtocol.java (93%) create mode 100644 vst/src/main/java/com/arangodb/vst/VstProtocolProvider.java create mode 100644 vst/src/main/java/com/arangodb/vst/VstSerializers.java rename {driver/src/main/java/com/arangodb/async/internal/velocystream => vst/src/main/java/com/arangodb/vst/async}/VstCommunicationAsync.java (64%) create mode 100644 vst/src/main/java/com/arangodb/vst/async/VstConnectionAsync.java rename {driver/src/main/java/com/arangodb/async/internal/velocystream => vst/src/main/java/com/arangodb/vst/async}/VstConnectionFactoryAsync.java (54%) rename {driver/src/main/java/com/arangodb/internal/velocystream => vst/src/main/java/com/arangodb/vst}/internal/AuthenticationRequest.java (96%) rename {driver/src/main/java/com/arangodb/internal/velocystream => vst/src/main/java/com/arangodb/vst}/internal/Chunk.java (97%) rename {driver/src/main/java/com/arangodb/internal/velocystream => vst/src/main/java/com/arangodb/vst}/internal/ChunkStore.java (97%) rename {driver/src/main/java/com/arangodb/internal/velocystream => vst/src/main/java/com/arangodb/vst}/internal/JwtAuthenticationRequest.java (91%) rename {driver/src/main/java/com/arangodb/internal/velocystream => vst/src/main/java/com/arangodb/vst}/internal/Message.java (97%) rename {driver/src/main/java/com/arangodb/internal/velocystream => vst/src/main/java/com/arangodb/vst}/internal/MessageStore.java (98%) rename {driver/src/main/java/com/arangodb/internal/velocystream => vst/src/main/java/com/arangodb/vst}/internal/VstConnection.java (94%) create mode 100644 vst/src/main/java/com/arangodb/vst/internal/VstConnectionSync.java create mode 100644 vst/src/main/resources/META-INF/services/com.arangodb.internal.net.AsyncProtocolProvider create mode 100644 vst/src/main/resources/META-INF/services/com.arangodb.internal.net.ProtocolProvider diff --git a/ChangeLog.md b/ChangeLog.md index df64c397b..09a65730a 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -6,7 +6,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) a ## [Unreleased] -## [7.0.0-ALPHA.1] +## [7.0.0-ALPHA.2] ### Changed diff --git a/core/pom.xml b/core/pom.xml new file mode 100644 index 000000000..2ea81eb5c --- /dev/null +++ b/core/pom.xml @@ -0,0 +1,91 @@ + + + 4.0.0 + + com.arangodb + arangodb-java-driver-parent + 7.0.0-ALPHA.2 + + + core + core + Core module for ArangoDB Java Driver + + + com.arangodb.core + + + + + org.slf4j + slf4j-api + + + com.fasterxml.jackson.core + jackson-databind + + + com.fasterxml.jackson.core + jackson-core + + + com.fasterxml.jackson.core + jackson-annotations + + + com.google.code.findbugs + jsr305 + 3.0.2 + provided + + + + + + + com.google.code.maven-replacer-plugin + replacer + 1.5.3 + + + generate-sources + + replace + + + + + ${project.basedir}/src/main/java/com/arangodb/PackageVersion.java.in + ${project.build.directory}/generated-sources/replacer/com/arangodb/PackageVersion.java + + + + @project.version@ + ${project.version} + + + + + + org.codehaus.mojo + build-helper-maven-plugin + 3.3.0 + + + generate-sources + + add-source + + + + ${project.build.directory}/generated-sources/replacer + + + + + + + + \ No newline at end of file diff --git a/driver/src/main/java/com/arangodb/ArangoCollection.java b/core/src/main/java/com/arangodb/ArangoCollection.java similarity index 100% rename from driver/src/main/java/com/arangodb/ArangoCollection.java rename to core/src/main/java/com/arangodb/ArangoCollection.java diff --git a/driver/src/main/java/com/arangodb/ArangoCursor.java b/core/src/main/java/com/arangodb/ArangoCursor.java similarity index 100% rename from driver/src/main/java/com/arangodb/ArangoCursor.java rename to core/src/main/java/com/arangodb/ArangoCursor.java diff --git a/driver/src/main/java/com/arangodb/ArangoDB.java b/core/src/main/java/com/arangodb/ArangoDB.java similarity index 51% rename from driver/src/main/java/com/arangodb/ArangoDB.java rename to core/src/main/java/com/arangodb/ArangoDB.java index 5533c9bef..1a22d50c3 100644 --- a/driver/src/main/java/com/arangodb/ArangoDB.java +++ b/core/src/main/java/com/arangodb/ArangoDB.java @@ -20,32 +20,17 @@ package com.arangodb; -import com.arangodb.config.ArangoConfigProperties; import com.arangodb.entity.*; import com.arangodb.internal.ArangoDBImpl; -import com.arangodb.internal.ArangoDefaults; import com.arangodb.internal.InternalArangoDBBuilder; -import com.arangodb.internal.http.HttpCommunication; -import com.arangodb.internal.http.HttpConnectionFactory; -import com.arangodb.internal.net.ConnectionFactory; -import com.arangodb.internal.net.Host; -import com.arangodb.internal.net.HostHandler; -import com.arangodb.internal.net.HostResolver; -import com.arangodb.internal.serde.ContentTypeFactory; -import com.arangodb.internal.serde.InternalSerde; -import com.arangodb.internal.serde.InternalSerdeProvider; -import com.arangodb.internal.velocystream.VstCommunicationSync; -import com.arangodb.internal.velocystream.VstConnectionFactorySync; +import com.arangodb.internal.net.*; import com.arangodb.model.DBCreateOptions; import com.arangodb.model.LogOptions; import com.arangodb.model.UserCreateOptions; import com.arangodb.model.UserUpdateOptions; -import com.arangodb.serde.ArangoSerde; import javax.annotation.concurrent.ThreadSafe; -import javax.net.ssl.SSLContext; import java.util.Collection; -import java.util.Locale; /** * Central access point for applications to communicate with an ArangoDB server. @@ -333,238 +318,10 @@ public interface ArangoDB extends ArangoSerdeAccessor { * * @author Mark Vollmary */ - class Builder extends InternalArangoDBBuilder { - - public Builder() { - super(); - } - - public Builder loadProperties(final ArangoConfigProperties properties) { - doLoadProperties(properties); - return this; - } + class Builder extends InternalArangoDBBuilder { public Builder useProtocol(final Protocol protocol) { - this.protocol = protocol; - return this; - } - - /** - * Adds a host to connect to. Multiple hosts can be added to provide fallbacks. - * - * @param host address of the host - * @param port port of the host - * @return {@link ArangoDB.Builder} - */ - public Builder host(final String host, final int port) { - setHost(host, port); - return this; - } - - /** - * Sets the connection and request timeout in milliseconds. - * - * @param timeout timeout in milliseconds - * @return {@link ArangoDB.Builder} - */ - public Builder timeout(final Integer timeout) { - setTimeout(timeout); - return this; - } - - /** - * Sets the username to use for authentication. - * - * @param user the user in the database (default: {@code root}) - * @return {@link ArangoDB.Builder} - */ - public Builder user(final String user) { - setUser(user); - return this; - } - - /** - * Sets the password for the user for authentication. - * - * @param password the password of the user in the database (default: {@code null}) - * @return {@link ArangoDB.Builder} - */ - public Builder password(final String password) { - setPassword(password); - return this; - } - - /** - * Sets the JWT for the user authentication. - * - * @param jwt token to use (default: {@code null}) - * @return {@link ArangoDB.Builder} - */ - public Builder jwt(final String jwt) { - setJwt(jwt); - return this; - } - - /** - * If set to {@code true} SSL will be used when connecting to an ArangoDB server. - * - * @param useSsl whether or not use SSL (default: {@code false}) - * @return {@link ArangoDB.Builder} - */ - public Builder useSsl(final Boolean useSsl) { - setUseSsl(useSsl); - return this; - } - - /** - * Sets the SSL context to be used when {@code true} is passed through {@link #useSsl(Boolean)}. - * - * @param sslContext SSL context to be used - * @return {@link ArangoDB.Builder} - */ - public Builder sslContext(final SSLContext sslContext) { - setSslContext(sslContext); - return this; - } - - /** - * Set whether hostname verification is enabled - * - * @param verifyHost {@code true} if enabled - * @return {@link ArangoDB.Builder} - */ - public Builder verifyHost(final Boolean verifyHost) { - setVerifyHost(verifyHost); - return this; - } - - /** - * Sets the chunk size when {@link Protocol#VST} is used. - * - * @param chunksize size of a chunk in bytes - * @return {@link ArangoDB.Builder} - */ - public Builder chunksize(final Integer chunksize) { - setChunkSize(chunksize); - return this; - } - - /** - * Sets the maximum number of connections the built in connection pool will open per host. - * - *

    - * Defaults: - *

    - * - *
    -         * {@link Protocol#VST} == 1
    -         * {@link Protocol#HTTP_JSON} == 20
    -         * {@link Protocol#HTTP_VPACK} == 20
    -         * 
    - * - * @param maxConnections max number of connections - * @return {@link ArangoDB.Builder} - */ - public Builder maxConnections(final Integer maxConnections) { - setMaxConnections(maxConnections); - return this; - } - - /** - * Set the maximum time to life of a connection. After this time the connection will be closed automatically. - * - * @param connectionTtl the maximum time to life of a connection in milliseconds - * @return {@link ArangoDB.Builder} - */ - public Builder connectionTtl(final Long connectionTtl) { - setConnectionTtl(connectionTtl); - return this; - } - - /** - * Set the keep-alive interval for VST connections. If set, every VST connection will perform a no-op request - * every {@code keepAliveInterval} seconds, to avoid to be closed due to inactivity by the server (or by the - * external environment, eg. firewall, intermediate routers, operating system). - * - * @param keepAliveInterval interval in seconds - * @return {@link ArangoDB.Builder} - */ - public Builder keepAliveInterval(final Integer keepAliveInterval) { - setKeepAliveInterval(keepAliveInterval); - return this; - } - - /** - * Whether or not the driver should acquire a list of available coordinators in an ArangoDB cluster or a single - * server with active failover. In case of Active-Failover deployment set to {@code true} to enable automatic - * master discovery. - * - *

    - * The host list will be used for failover and load balancing. - *

    - * - * @param acquireHostList whether or not automatically acquire a list of available hosts (default: false) - * @return {@link ArangoDB.Builder} - */ - public Builder acquireHostList(final Boolean acquireHostList) { - setAcquireHostList(acquireHostList); - return this; - } - - /** - * Setting the Interval for acquireHostList - * - * @param acquireHostListInterval Interval in milliseconds - * @return {@link ArangoDB.Builder} - */ - public Builder acquireHostListInterval(final Integer acquireHostListInterval) { - setAcquireHostListInterval(acquireHostListInterval); - return this; - } - - /** - * Sets the load balancing strategy to be used in an ArangoDB cluster setup. In case of Active-Failover - * deployment set to {@link LoadBalancingStrategy#NONE} or not set at all, since that would be the default. - * - * @param loadBalancingStrategy the load balancing strategy to be used (default: - * {@link LoadBalancingStrategy#NONE} - * @return {@link ArangoDB.Builder} - */ - public Builder loadBalancingStrategy(final LoadBalancingStrategy loadBalancingStrategy) { - setLoadBalancingStrategy(loadBalancingStrategy); - return this; - } - - /** - * Setting the amount of samples kept for queue time metrics - * - * @param responseQueueTimeSamples amount of samples to keep - * @return {@link ArangoDB.Builder} - */ - public Builder responseQueueTimeSamples(final Integer responseQueueTimeSamples) { - setResponseQueueTimeSamples(responseQueueTimeSamples); - return this; - } - - /** - * Sets the serde for the user data. - * This is used to serialize and deserialize all the data payload such as: - * - documents, vertexes, edges - * - AQL bind vars - * - body payload of requests and responses in {@link ArangoDB#execute(Request, Class)} - *

    - * However, note that the following types will always be serialized and deserialized using the internal serde: - * - {@link com.fasterxml.jackson.databind.JsonNode} - * - {@link com.arangodb.util.RawJson} - * - {@link com.arangodb.util.RawBytes} - * - {@link com.arangodb.entity.BaseDocument} - * - {@link com.arangodb.entity.BaseEdgeDocument} - * - * @param serde custom serde for the user data - * @return {@link ArangoDB.Builder} - */ - public Builder serde(final ArangoSerde serde) { - setUserDataSerde(serde); + config.setProtocol(protocol); return this; } @@ -574,53 +331,25 @@ public Builder serde(final ArangoSerde serde) { * @return {@link ArangoDB} */ public ArangoDB build() { - if (hosts.isEmpty()) { + if (config.getHosts().isEmpty()) { throw new ArangoDBException("No host has been set!"); } - final ArangoSerde userSerde = this.userDataSerde != null ? this.userDataSerde : - serdeProvider().of(ContentTypeFactory.of(protocol)); - final InternalSerde serde = InternalSerdeProvider.create(ContentTypeFactory.of(protocol), userSerde); - - int protocolMaxConnections; - switch (protocol) { - case VST: - protocolMaxConnections = ArangoDefaults.MAX_CONNECTIONS_VST_DEFAULT; - break; - case HTTP_JSON: - case HTTP_VPACK: - protocolMaxConnections = ArangoDefaults.MAX_CONNECTIONS_HTTP_DEFAULT; - break; - case HTTP2_JSON: - case HTTP2_VPACK: - protocolMaxConnections = ArangoDefaults.MAX_CONNECTIONS_HTTP2_DEFAULT; - break; - default: - throw new IllegalArgumentException(); - } - - final int max = maxConnections != null ? Math.max(1, maxConnections) : protocolMaxConnections; - - final ConnectionFactory connectionFactory = Protocol.VST == protocol - ? new VstConnectionFactorySync(timeout, connectionTtl, keepAliveInterval, useSsl, sslContext) - : new HttpConnectionFactory(timeout, user, password, useSsl, sslContext, verifyHost, serde, - protocol, connectionTtl); + ProtocolProvider protocolProvider = protocolProvider(config.getProtocol()); + config.setProtocolModule(protocolProvider.protocolModule()); - final Collection hostList = createHostList(max, connectionFactory); - final HostResolver hostResolver = createHostResolver(hostList, max, connectionFactory); - final HostHandler hostHandler = createHostHandler(hostResolver); - hostHandler.setJwt(jwt); + ConnectionFactory connectionFactory = protocolProvider.createConnectionFactory(); + Collection hostList = createHostList(connectionFactory); + HostResolver hostResolver = createHostResolver(hostList, connectionFactory); + HostHandler hostHandler = createHostHandler(hostResolver); + hostHandler.setJwt(config.getJwt()); return new ArangoDBImpl( - new VstCommunicationSync.Builder(hostHandler).timeout(timeout).user(user).password(password) - .jwt(jwt).useSsl(useSsl).sslContext(sslContext).chunksize(chunkSize) - .maxConnections(maxConnections).connectionTtl(connectionTtl), - new HttpCommunication.Builder().hostHandler(hostHandler), - serde, - protocol, + config, hostResolver, - hostHandler, - responseQueueTimeSamples, timeout); + protocolProvider, + hostHandler + ); } } diff --git a/driver/src/main/java/com/arangodb/ArangoDBException.java b/core/src/main/java/com/arangodb/ArangoDBException.java similarity index 100% rename from driver/src/main/java/com/arangodb/ArangoDBException.java rename to core/src/main/java/com/arangodb/ArangoDBException.java diff --git a/driver/src/main/java/com/arangodb/ArangoDBMultipleException.java b/core/src/main/java/com/arangodb/ArangoDBMultipleException.java similarity index 100% rename from driver/src/main/java/com/arangodb/ArangoDBMultipleException.java rename to core/src/main/java/com/arangodb/ArangoDBMultipleException.java diff --git a/driver/src/main/java/com/arangodb/ArangoDatabase.java b/core/src/main/java/com/arangodb/ArangoDatabase.java similarity index 100% rename from driver/src/main/java/com/arangodb/ArangoDatabase.java rename to core/src/main/java/com/arangodb/ArangoDatabase.java diff --git a/driver/src/main/java/com/arangodb/ArangoEdgeCollection.java b/core/src/main/java/com/arangodb/ArangoEdgeCollection.java similarity index 100% rename from driver/src/main/java/com/arangodb/ArangoEdgeCollection.java rename to core/src/main/java/com/arangodb/ArangoEdgeCollection.java diff --git a/driver/src/main/java/com/arangodb/ArangoGraph.java b/core/src/main/java/com/arangodb/ArangoGraph.java similarity index 100% rename from driver/src/main/java/com/arangodb/ArangoGraph.java rename to core/src/main/java/com/arangodb/ArangoGraph.java diff --git a/driver/src/main/java/com/arangodb/ArangoIterable.java b/core/src/main/java/com/arangodb/ArangoIterable.java similarity index 100% rename from driver/src/main/java/com/arangodb/ArangoIterable.java rename to core/src/main/java/com/arangodb/ArangoIterable.java diff --git a/driver/src/main/java/com/arangodb/ArangoIterator.java b/core/src/main/java/com/arangodb/ArangoIterator.java similarity index 100% rename from driver/src/main/java/com/arangodb/ArangoIterator.java rename to core/src/main/java/com/arangodb/ArangoIterator.java diff --git a/driver/src/main/java/com/arangodb/ArangoMetrics.java b/core/src/main/java/com/arangodb/ArangoMetrics.java similarity index 100% rename from driver/src/main/java/com/arangodb/ArangoMetrics.java rename to core/src/main/java/com/arangodb/ArangoMetrics.java diff --git a/driver/src/main/java/com/arangodb/ArangoSearch.java b/core/src/main/java/com/arangodb/ArangoSearch.java similarity index 100% rename from driver/src/main/java/com/arangodb/ArangoSearch.java rename to core/src/main/java/com/arangodb/ArangoSearch.java diff --git a/driver/src/main/java/com/arangodb/ArangoSerdeAccessor.java b/core/src/main/java/com/arangodb/ArangoSerdeAccessor.java similarity index 100% rename from driver/src/main/java/com/arangodb/ArangoSerdeAccessor.java rename to core/src/main/java/com/arangodb/ArangoSerdeAccessor.java diff --git a/driver/src/main/java/com/arangodb/ArangoVertexCollection.java b/core/src/main/java/com/arangodb/ArangoVertexCollection.java similarity index 100% rename from driver/src/main/java/com/arangodb/ArangoVertexCollection.java rename to core/src/main/java/com/arangodb/ArangoVertexCollection.java diff --git a/driver/src/main/java/com/arangodb/ArangoView.java b/core/src/main/java/com/arangodb/ArangoView.java similarity index 100% rename from driver/src/main/java/com/arangodb/ArangoView.java rename to core/src/main/java/com/arangodb/ArangoView.java diff --git a/serde-api/src/main/java/com/arangodb/ContentType.java b/core/src/main/java/com/arangodb/ContentType.java similarity index 100% rename from serde-api/src/main/java/com/arangodb/ContentType.java rename to core/src/main/java/com/arangodb/ContentType.java diff --git a/driver/src/main/java/com/arangodb/DbName.java b/core/src/main/java/com/arangodb/DbName.java similarity index 100% rename from driver/src/main/java/com/arangodb/DbName.java rename to core/src/main/java/com/arangodb/DbName.java diff --git a/driver/src/main/java/com/arangodb/PackageVersion.java.in b/core/src/main/java/com/arangodb/PackageVersion.java.in similarity index 100% rename from driver/src/main/java/com/arangodb/PackageVersion.java.in rename to core/src/main/java/com/arangodb/PackageVersion.java.in diff --git a/driver/src/main/java/com/arangodb/Protocol.java b/core/src/main/java/com/arangodb/Protocol.java similarity index 100% rename from driver/src/main/java/com/arangodb/Protocol.java rename to core/src/main/java/com/arangodb/Protocol.java diff --git a/driver/src/main/java/com/arangodb/QueueTimeMetrics.java b/core/src/main/java/com/arangodb/QueueTimeMetrics.java similarity index 100% rename from driver/src/main/java/com/arangodb/QueueTimeMetrics.java rename to core/src/main/java/com/arangodb/QueueTimeMetrics.java diff --git a/driver/src/main/java/com/arangodb/Request.java b/core/src/main/java/com/arangodb/Request.java similarity index 100% rename from driver/src/main/java/com/arangodb/Request.java rename to core/src/main/java/com/arangodb/Request.java diff --git a/driver/src/main/java/com/arangodb/Response.java b/core/src/main/java/com/arangodb/Response.java similarity index 100% rename from driver/src/main/java/com/arangodb/Response.java rename to core/src/main/java/com/arangodb/Response.java diff --git a/driver/src/main/java/com/arangodb/SearchAlias.java b/core/src/main/java/com/arangodb/SearchAlias.java similarity index 100% rename from driver/src/main/java/com/arangodb/SearchAlias.java rename to core/src/main/java/com/arangodb/SearchAlias.java diff --git a/driver/src/main/java/com/arangodb/async/ArangoCollectionAsync.java b/core/src/main/java/com/arangodb/async/ArangoCollectionAsync.java similarity index 100% rename from driver/src/main/java/com/arangodb/async/ArangoCollectionAsync.java rename to core/src/main/java/com/arangodb/async/ArangoCollectionAsync.java diff --git a/driver/src/main/java/com/arangodb/async/ArangoCursorAsync.java b/core/src/main/java/com/arangodb/async/ArangoCursorAsync.java similarity index 100% rename from driver/src/main/java/com/arangodb/async/ArangoCursorAsync.java rename to core/src/main/java/com/arangodb/async/ArangoCursorAsync.java diff --git a/driver/src/main/java/com/arangodb/async/ArangoDBAsync.java b/core/src/main/java/com/arangodb/async/ArangoDBAsync.java similarity index 54% rename from driver/src/main/java/com/arangodb/async/ArangoDBAsync.java rename to core/src/main/java/com/arangodb/async/ArangoDBAsync.java index 46ab0d422..98386c500 100644 --- a/driver/src/main/java/com/arangodb/async/ArangoDBAsync.java +++ b/core/src/main/java/com/arangodb/async/ArangoDBAsync.java @@ -22,28 +22,17 @@ import com.arangodb.*; import com.arangodb.async.internal.ArangoDBAsyncImpl; -import com.arangodb.async.internal.velocystream.VstCommunicationAsync; -import com.arangodb.async.internal.velocystream.VstConnectionFactoryAsync; -import com.arangodb.config.ArangoConfigProperties; import com.arangodb.entity.*; -import com.arangodb.internal.ArangoDefaults; import com.arangodb.internal.InternalArangoDBBuilder; -import com.arangodb.internal.net.ConnectionFactory; -import com.arangodb.internal.net.HostHandler; -import com.arangodb.internal.net.HostResolver; -import com.arangodb.internal.serde.InternalSerde; -import com.arangodb.internal.serde.InternalSerdeProvider; -import com.arangodb.internal.velocystream.VstCommunicationSync; -import com.arangodb.internal.velocystream.VstConnectionFactorySync; +import com.arangodb.internal.net.*; import com.arangodb.model.DBCreateOptions; import com.arangodb.model.LogOptions; import com.arangodb.model.UserCreateOptions; import com.arangodb.model.UserUpdateOptions; -import com.arangodb.serde.ArangoSerde; import javax.annotation.concurrent.ThreadSafe; -import javax.net.ssl.SSLContext; import java.util.Collection; +import java.util.ServiceLoader; import java.util.concurrent.CompletableFuture; /** @@ -276,8 +265,7 @@ public interface ArangoDBAsync extends ArangoSerdeAccessor { * * @param options Additional options, can be null * @return the log messages - * @see - * API + * @see API * Documentation * @since ArangoDB 3.8 */ @@ -309,201 +297,16 @@ public interface ArangoDBAsync extends ArangoSerdeAccessor { * * @author Mark Vollmary */ - class Builder extends InternalArangoDBBuilder { - - public Builder() { - super(); - } - - public Builder loadProperties(final ArangoConfigProperties config) { - super.doLoadProperties(config); - return this; - } - - /** - * Adds a host to connect to. Multiple hosts can be added to provide fallbacks. - * - * @param host address of the host - * @param port port of the host - * @return {@link ArangoDBAsync.Builder} - */ - public Builder host(final String host, final int port) { - setHost(host, port); - return this; - } - - /** - * Sets the timeout in milliseconds. It is used as socket timeout when opening a VecloyStream. - * - * @param timeout timeout in milliseconds - * @return {@link ArangoDBAsync.Builder} - */ - public Builder timeout(final Integer timeout) { - setTimeout(timeout); - return this; - } - - /** - * Sets the username to use for authentication. - * - * @param user the user in the database (default: root) - * @return {@link ArangoDBAsync.Builder} - */ - public Builder user(final String user) { - setUser(user); - return this; - } - - /** - * Sets the password for the user for authentication. - * - * @param password the password of the user in the database (default: null) - * @return {@link ArangoDBAsync.Builder} - */ - public Builder password(final String password) { - setPassword(password); - return this; - } - - /** - * Sets the JWT for the user authentication. - * - * @param jwt token to use (default: {@code null}) - * @return {@link ArangoDBAsync.Builder} - */ - public Builder jwt(final String jwt) { - setJwt(jwt); - return this; - } - - /** - * If set to true SSL will be used when connecting to an ArangoDB server. - * - * @param useSsl whether or not use SSL (default: false) - * @return {@link ArangoDBAsync.Builder} - */ - public Builder useSsl(final Boolean useSsl) { - setUseSsl(useSsl); - return this; - } - - /** - * Sets the SSL context to be used when true is passed through {@link #useSsl(Boolean)}. - * - * @param sslContext SSL context to be used - * @return {@link ArangoDBAsync.Builder} - */ - public Builder sslContext(final SSLContext sslContext) { - setSslContext(sslContext); - return this; - } - - /** - * Sets the chunk size when {@link Protocol#VST} is used. - * - * @param chunksize size of a chunk in bytes - * @return {@link ArangoDBAsync.Builder} - */ - public Builder chunksize(final Integer chunksize) { - setChunkSize(chunksize); - return this; - } - - /** - * Sets the maximum number of connections the built in connection pool will open. - * - *

    - * In an ArangoDB cluster setup with {@link LoadBalancingStrategy#ROUND_ROBIN} set, this value should be at - * least as high as the number of ArangoDB coordinators in the cluster. - *

    - * - * @param maxConnections max number of connections (default: 1) - * @return {@link ArangoDBAsync.Builder} - */ - public Builder maxConnections(final Integer maxConnections) { - setMaxConnections(maxConnections); - return this; - } - - /** - * Set the maximum time to life of a connection. After this time the connection will be closed automatically. - * - * @param connectionTtl the maximum time to life of a connection. - * @return {@link ArangoDBAsync.Builder} - */ - public Builder connectionTtl(final Long connectionTtl) { - setConnectionTtl(connectionTtl); - return this; - } - - /** - * Set the keep-alive interval for VST connections. If set, every VST connection will perform a no-op request - * every - * {@code keepAliveInterval} seconds, to avoid to be closed due to inactivity by the server (or by the external - * environment, eg. firewall, intermediate routers, operating system). - * - * @param keepAliveInterval interval in seconds - * @return {@link ArangoDBAsync.Builder} - */ - public Builder keepAliveInterval(final Integer keepAliveInterval) { - setKeepAliveInterval(keepAliveInterval); - return this; - } - - /** - * Whether or not the driver should acquire a list of available coordinators in an ArangoDB cluster or a single - * server with active failover. - * In case of Active-Failover deployment set to {@code true} to enable automatic master discovery. - * - *

    - * The host list will be used for failover and load balancing. - *

    - * - * @param acquireHostList whether or not automatically acquire a list of available hosts (default: false) - * @return {@link ArangoDBAsync.Builder} - */ - public Builder acquireHostList(final Boolean acquireHostList) { - setAcquireHostList(acquireHostList); - return this; - } - - /** - * Setting the amount of samples kept for queue time metrics - * - * @param responseQueueTimeSamples amount of samples to keep - * @return {@link ArangoDBAsync.Builder} - */ - public Builder responseQueueTimeSamples(final Integer responseQueueTimeSamples) { - setResponseQueueTimeSamples(responseQueueTimeSamples); - return this; - } - - /** - * Sets the load balancing strategy to be used in an ArangoDB cluster setup. - * In case of Active-Failover deployment set to {@link LoadBalancingStrategy#NONE} or not set at all, since that - * would be the default. - * - * @param loadBalancingStrategy the load balancing strategy to be used (default: - * {@link LoadBalancingStrategy#NONE} - * @return {@link ArangoDBAsync.Builder} - */ - public Builder loadBalancingStrategy(final LoadBalancingStrategy loadBalancingStrategy) { - setLoadBalancingStrategy(loadBalancingStrategy); - return this; - } - - /** - * Replace the built-in serializer/deserializer with the given one. - *

    - *
    - * ATTENTION!: Any registered custom serializer/deserializer or module will be ignored. - * - * @param serialization custom serializer/deserializer - * @return {@link ArangoDBAsync.Builder} - */ - public Builder serializer(final ArangoSerde serialization) { - setUserDataSerde(serialization); - return this; + class Builder extends InternalArangoDBBuilder { + + private AsyncProtocolProvider asyncProtocolProvider(Protocol protocol) { + ServiceLoader loader = ServiceLoader.load(AsyncProtocolProvider.class); + for (AsyncProtocolProvider p : loader) { + if (p.supportsProtocol(protocol)) { + return p; + } + } + throw new ArangoDBException("No ProtocolProvider found for protocol: " + protocol); } /** @@ -512,48 +315,31 @@ public Builder serializer(final ArangoSerde serialization) { * @return {@link ArangoDBAsync} */ public ArangoDBAsync build() { - if (hosts.isEmpty()) { + if (config.getHosts().isEmpty()) { throw new ArangoDBException("No host has been set!"); } - final ArangoSerde userSerde = this.userDataSerde != null ? this.userDataSerde : serdeProvider().of(ContentType.VPACK); - final InternalSerde serde = InternalSerdeProvider.create(ContentType.VPACK, userSerde); - - final int max = maxConnections != null ? Math.max(1, maxConnections) - : ArangoDefaults.MAX_CONNECTIONS_VST_DEFAULT; - final ConnectionFactory syncConnectionFactory = new VstConnectionFactorySync(timeout, connectionTtl, - keepAliveInterval, useSsl, sslContext); - final ConnectionFactory asyncConnectionFactory = new VstConnectionFactoryAsync(timeout, connectionTtl, - keepAliveInterval, useSsl, sslContext); - final HostResolver syncHostResolver = createHostResolver(createHostList(max, syncConnectionFactory), max, - syncConnectionFactory); - final HostResolver asyncHostResolver = createHostResolver(createHostList(max, asyncConnectionFactory), max, - asyncConnectionFactory); - final HostHandler syncHostHandler = createHostHandler(syncHostResolver); + AsyncProtocolProvider asyncProtocolProvider = asyncProtocolProvider(Protocol.VST); + ProtocolProvider protocolProvider = protocolProvider(Protocol.VST); + + config.setProtocol(Protocol.VST); + config.setProtocolModule(asyncProtocolProvider.protocolModule()); + + final ConnectionFactory asyncConnectionFactory = asyncProtocolProvider.createConnectionFactory(); + final ConnectionFactory syncConnectionFactory = protocolProvider.createConnectionFactory(); + final HostResolver asyncHostResolver = createHostResolver(createHostList(asyncConnectionFactory), asyncConnectionFactory); + final HostResolver syncHostResolver = createHostResolver(createHostList(syncConnectionFactory), syncConnectionFactory); final HostHandler asyncHostHandler = createHostHandler(asyncHostResolver); + final HostHandler syncHostHandler = createHostHandler(syncHostResolver); return new ArangoDBAsyncImpl( - asyncBuilder(asyncHostHandler), - serde, - syncBuilder(syncHostHandler), + config, asyncHostResolver, syncHostResolver, + asyncProtocolProvider, + protocolProvider, asyncHostHandler, - syncHostHandler, - responseQueueTimeSamples, - timeout); + syncHostHandler + ); } - - private VstCommunicationAsync.Builder asyncBuilder(final HostHandler hostHandler) { - return new VstCommunicationAsync.Builder(hostHandler).timeout(timeout).user(user).password(password) - .jwt(jwt).useSsl(useSsl).sslContext(sslContext).chunksize(chunkSize).maxConnections(maxConnections) - .connectionTtl(connectionTtl); - } - - private VstCommunicationSync.Builder syncBuilder(final HostHandler hostHandler) { - return new VstCommunicationSync.Builder(hostHandler).timeout(timeout).user(user).password(password) - .jwt(jwt).useSsl(useSsl).sslContext(sslContext).chunksize(chunkSize).maxConnections(maxConnections) - .connectionTtl(connectionTtl); - } - } } diff --git a/driver/src/main/java/com/arangodb/async/ArangoDatabaseAsync.java b/core/src/main/java/com/arangodb/async/ArangoDatabaseAsync.java similarity index 100% rename from driver/src/main/java/com/arangodb/async/ArangoDatabaseAsync.java rename to core/src/main/java/com/arangodb/async/ArangoDatabaseAsync.java diff --git a/driver/src/main/java/com/arangodb/async/ArangoEdgeCollectionAsync.java b/core/src/main/java/com/arangodb/async/ArangoEdgeCollectionAsync.java similarity index 100% rename from driver/src/main/java/com/arangodb/async/ArangoEdgeCollectionAsync.java rename to core/src/main/java/com/arangodb/async/ArangoEdgeCollectionAsync.java diff --git a/driver/src/main/java/com/arangodb/async/ArangoGraphAsync.java b/core/src/main/java/com/arangodb/async/ArangoGraphAsync.java similarity index 100% rename from driver/src/main/java/com/arangodb/async/ArangoGraphAsync.java rename to core/src/main/java/com/arangodb/async/ArangoGraphAsync.java diff --git a/driver/src/main/java/com/arangodb/async/ArangoRouteAsync.java b/core/src/main/java/com/arangodb/async/ArangoRouteAsync.java similarity index 100% rename from driver/src/main/java/com/arangodb/async/ArangoRouteAsync.java rename to core/src/main/java/com/arangodb/async/ArangoRouteAsync.java diff --git a/driver/src/main/java/com/arangodb/async/ArangoSearchAsync.java b/core/src/main/java/com/arangodb/async/ArangoSearchAsync.java similarity index 100% rename from driver/src/main/java/com/arangodb/async/ArangoSearchAsync.java rename to core/src/main/java/com/arangodb/async/ArangoSearchAsync.java diff --git a/driver/src/main/java/com/arangodb/async/ArangoVertexCollectionAsync.java b/core/src/main/java/com/arangodb/async/ArangoVertexCollectionAsync.java similarity index 100% rename from driver/src/main/java/com/arangodb/async/ArangoVertexCollectionAsync.java rename to core/src/main/java/com/arangodb/async/ArangoVertexCollectionAsync.java diff --git a/driver/src/main/java/com/arangodb/async/ArangoViewAsync.java b/core/src/main/java/com/arangodb/async/ArangoViewAsync.java similarity index 100% rename from driver/src/main/java/com/arangodb/async/ArangoViewAsync.java rename to core/src/main/java/com/arangodb/async/ArangoViewAsync.java diff --git a/driver/src/main/java/com/arangodb/async/SearchAliasAsync.java b/core/src/main/java/com/arangodb/async/SearchAliasAsync.java similarity index 100% rename from driver/src/main/java/com/arangodb/async/SearchAliasAsync.java rename to core/src/main/java/com/arangodb/async/SearchAliasAsync.java diff --git a/driver/src/main/java/com/arangodb/async/internal/ArangoCollectionAsyncImpl.java b/core/src/main/java/com/arangodb/async/internal/ArangoCollectionAsyncImpl.java similarity index 100% rename from driver/src/main/java/com/arangodb/async/internal/ArangoCollectionAsyncImpl.java rename to core/src/main/java/com/arangodb/async/internal/ArangoCollectionAsyncImpl.java diff --git a/driver/src/main/java/com/arangodb/async/internal/ArangoCursorAsyncImpl.java b/core/src/main/java/com/arangodb/async/internal/ArangoCursorAsyncImpl.java similarity index 100% rename from driver/src/main/java/com/arangodb/async/internal/ArangoCursorAsyncImpl.java rename to core/src/main/java/com/arangodb/async/internal/ArangoCursorAsyncImpl.java diff --git a/driver/src/main/java/com/arangodb/async/internal/ArangoDBAsyncImpl.java b/core/src/main/java/com/arangodb/async/internal/ArangoDBAsyncImpl.java similarity index 83% rename from driver/src/main/java/com/arangodb/async/internal/ArangoDBAsyncImpl.java rename to core/src/main/java/com/arangodb/async/internal/ArangoDBAsyncImpl.java index 2ad1b2b0d..12e946976 100644 --- a/driver/src/main/java/com/arangodb/async/internal/ArangoDBAsyncImpl.java +++ b/core/src/main/java/com/arangodb/async/internal/ArangoDBAsyncImpl.java @@ -26,23 +26,17 @@ import com.arangodb.Response; import com.arangodb.async.ArangoDBAsync; import com.arangodb.async.ArangoDatabaseAsync; -import com.arangodb.async.internal.velocystream.VstCommunicationAsync; import com.arangodb.entity.*; -import com.arangodb.internal.*; -import com.arangodb.internal.net.CommunicationProtocol; -import com.arangodb.internal.net.HostHandler; -import com.arangodb.internal.net.HostResolver; -import com.arangodb.internal.serde.InternalSerde; +import com.arangodb.internal.ArangoExecutorSync; +import com.arangodb.internal.ArangoMetricsImpl; +import com.arangodb.internal.InternalArangoDB; +import com.arangodb.internal.config.ArangoConfig; +import com.arangodb.internal.net.*; import com.arangodb.internal.serde.SerdeUtils; -import com.arangodb.internal.velocystream.VstCommunication; -import com.arangodb.internal.velocystream.VstCommunicationSync; -import com.arangodb.internal.velocystream.VstProtocol; -import com.arangodb.internal.velocystream.internal.VstConnectionSync; import com.arangodb.model.DBCreateOptions; import com.arangodb.model.LogOptions; import com.arangodb.model.UserCreateOptions; import com.arangodb.model.UserUpdateOptions; -import com.arangodb.internal.InternalResponse; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -62,31 +56,22 @@ public class ArangoDBAsyncImpl extends InternalArangoDB imp private final HostHandler syncHostHandler; public ArangoDBAsyncImpl( - final VstCommunicationAsync.Builder asyncCommBuilder, - final InternalSerde util, - final VstCommunicationSync.Builder syncCommBuilder, + final ArangoConfig config, final HostResolver asyncHostResolver, final HostResolver syncHostResolver, + final AsyncProtocolProvider asyncProtocolProvider, + final ProtocolProvider protocolProvider, final HostHandler asyncHostHandler, - final HostHandler syncHostHandler, - final int responseQueueTimeSamples, - final int timeoutMs + final HostHandler syncHostHandler ) { - - super(new ArangoExecutorAsync(asyncCommBuilder.build(util), util, - new QueueTimeMetricsImpl(responseQueueTimeSamples), timeoutMs), util); - - final VstCommunication cacheCom = syncCommBuilder.build(util); - - cp = new VstProtocol(cacheCom); + super(new ArangoExecutorAsync(asyncProtocolProvider.createCommunication(config, asyncHostHandler), config), config.getInternalSerde()); + cp = protocolProvider.createProtocol(config, syncHostHandler); this.asyncHostHandler = asyncHostHandler; this.syncHostHandler = syncHostHandler; - ArangoExecutorSync arangoExecutorSync = new ArangoExecutorSync(cp, util, - new QueueTimeMetricsImpl(responseQueueTimeSamples), timeoutMs); - asyncHostResolver.init(arangoExecutorSync, util); - syncHostResolver.init(arangoExecutorSync, util); - + ArangoExecutorSync arangoExecutorSync = new ArangoExecutorSync(cp, config); + asyncHostResolver.init(arangoExecutorSync, config.getInternalSerde()); + syncHostResolver.init(arangoExecutorSync, config.getInternalSerde()); } @Override diff --git a/driver/src/main/java/com/arangodb/async/internal/ArangoDatabaseAsyncImpl.java b/core/src/main/java/com/arangodb/async/internal/ArangoDatabaseAsyncImpl.java similarity index 100% rename from driver/src/main/java/com/arangodb/async/internal/ArangoDatabaseAsyncImpl.java rename to core/src/main/java/com/arangodb/async/internal/ArangoDatabaseAsyncImpl.java diff --git a/driver/src/main/java/com/arangodb/async/internal/ArangoEdgeCollectionAsyncImpl.java b/core/src/main/java/com/arangodb/async/internal/ArangoEdgeCollectionAsyncImpl.java similarity index 100% rename from driver/src/main/java/com/arangodb/async/internal/ArangoEdgeCollectionAsyncImpl.java rename to core/src/main/java/com/arangodb/async/internal/ArangoEdgeCollectionAsyncImpl.java diff --git a/driver/src/main/java/com/arangodb/async/internal/ArangoExecutorAsync.java b/core/src/main/java/com/arangodb/async/internal/ArangoExecutorAsync.java similarity index 85% rename from driver/src/main/java/com/arangodb/async/internal/ArangoExecutorAsync.java rename to core/src/main/java/com/arangodb/async/internal/ArangoExecutorAsync.java index 831b64e40..7c85ef495 100644 --- a/driver/src/main/java/com/arangodb/async/internal/ArangoExecutorAsync.java +++ b/core/src/main/java/com/arangodb/async/internal/ArangoExecutorAsync.java @@ -21,12 +21,11 @@ package com.arangodb.async.internal; import com.arangodb.ArangoDBException; -import com.arangodb.async.internal.velocystream.VstCommunicationAsync; import com.arangodb.internal.ArangoExecutor; -import com.arangodb.internal.QueueTimeMetricsImpl; -import com.arangodb.internal.net.HostHandle; -import com.arangodb.internal.serde.InternalSerde; import com.arangodb.internal.InternalRequest; +import com.arangodb.internal.config.ArangoConfig; +import com.arangodb.internal.net.AsyncCommunication; +import com.arangodb.internal.net.HostHandle; import java.io.IOException; import java.lang.reflect.Type; @@ -40,12 +39,11 @@ */ public class ArangoExecutorAsync extends ArangoExecutor { - private final VstCommunicationAsync communication; + private final AsyncCommunication communication; private final ExecutorService outgoingExecutor = Executors.newSingleThreadExecutor(); - public ArangoExecutorAsync(final VstCommunicationAsync communication, final InternalSerde util, - final QueueTimeMetricsImpl qtMetrics, final int timeoutMs) { - super(util, qtMetrics, timeoutMs); + public ArangoExecutorAsync(final AsyncCommunication communication, final ArangoConfig config) { + super(config); this.communication = communication; } diff --git a/driver/src/main/java/com/arangodb/async/internal/ArangoGraphAsyncImpl.java b/core/src/main/java/com/arangodb/async/internal/ArangoGraphAsyncImpl.java similarity index 100% rename from driver/src/main/java/com/arangodb/async/internal/ArangoGraphAsyncImpl.java rename to core/src/main/java/com/arangodb/async/internal/ArangoGraphAsyncImpl.java diff --git a/driver/src/main/java/com/arangodb/async/internal/ArangoRouteAsyncImpl.java b/core/src/main/java/com/arangodb/async/internal/ArangoRouteAsyncImpl.java similarity index 100% rename from driver/src/main/java/com/arangodb/async/internal/ArangoRouteAsyncImpl.java rename to core/src/main/java/com/arangodb/async/internal/ArangoRouteAsyncImpl.java diff --git a/driver/src/main/java/com/arangodb/async/internal/ArangoSearchAsyncImpl.java b/core/src/main/java/com/arangodb/async/internal/ArangoSearchAsyncImpl.java similarity index 100% rename from driver/src/main/java/com/arangodb/async/internal/ArangoSearchAsyncImpl.java rename to core/src/main/java/com/arangodb/async/internal/ArangoSearchAsyncImpl.java diff --git a/driver/src/main/java/com/arangodb/async/internal/ArangoVertexCollectionAsyncImpl.java b/core/src/main/java/com/arangodb/async/internal/ArangoVertexCollectionAsyncImpl.java similarity index 100% rename from driver/src/main/java/com/arangodb/async/internal/ArangoVertexCollectionAsyncImpl.java rename to core/src/main/java/com/arangodb/async/internal/ArangoVertexCollectionAsyncImpl.java diff --git a/driver/src/main/java/com/arangodb/async/internal/ArangoViewAsyncImpl.java b/core/src/main/java/com/arangodb/async/internal/ArangoViewAsyncImpl.java similarity index 100% rename from driver/src/main/java/com/arangodb/async/internal/ArangoViewAsyncImpl.java rename to core/src/main/java/com/arangodb/async/internal/ArangoViewAsyncImpl.java diff --git a/driver/src/main/java/com/arangodb/async/internal/ExceptionUtil.java b/core/src/main/java/com/arangodb/async/internal/ExceptionUtil.java similarity index 100% rename from driver/src/main/java/com/arangodb/async/internal/ExceptionUtil.java rename to core/src/main/java/com/arangodb/async/internal/ExceptionUtil.java diff --git a/driver/src/main/java/com/arangodb/async/internal/SearchAliasAsyncImpl.java b/core/src/main/java/com/arangodb/async/internal/SearchAliasAsyncImpl.java similarity index 100% rename from driver/src/main/java/com/arangodb/async/internal/SearchAliasAsyncImpl.java rename to core/src/main/java/com/arangodb/async/internal/SearchAliasAsyncImpl.java diff --git a/driver/src/main/java/com/arangodb/async/internal/utils/CompletableFutureUtils.java b/core/src/main/java/com/arangodb/async/internal/utils/CompletableFutureUtils.java similarity index 100% rename from driver/src/main/java/com/arangodb/async/internal/utils/CompletableFutureUtils.java rename to core/src/main/java/com/arangodb/async/internal/utils/CompletableFutureUtils.java diff --git a/driver/src/main/java/com/arangodb/config/ArangoConfigProperties.java b/core/src/main/java/com/arangodb/config/ArangoConfigProperties.java similarity index 100% rename from driver/src/main/java/com/arangodb/config/ArangoConfigProperties.java rename to core/src/main/java/com/arangodb/config/ArangoConfigProperties.java diff --git a/driver/src/main/java/com/arangodb/config/HostDescription.java b/core/src/main/java/com/arangodb/config/HostDescription.java similarity index 100% rename from driver/src/main/java/com/arangodb/config/HostDescription.java rename to core/src/main/java/com/arangodb/config/HostDescription.java diff --git a/driver/src/main/java/com/arangodb/entity/AbstractBaseDocument.java b/core/src/main/java/com/arangodb/entity/AbstractBaseDocument.java similarity index 100% rename from driver/src/main/java/com/arangodb/entity/AbstractBaseDocument.java rename to core/src/main/java/com/arangodb/entity/AbstractBaseDocument.java diff --git a/driver/src/main/java/com/arangodb/entity/AqlExecutionExplainEntity.java b/core/src/main/java/com/arangodb/entity/AqlExecutionExplainEntity.java similarity index 100% rename from driver/src/main/java/com/arangodb/entity/AqlExecutionExplainEntity.java rename to core/src/main/java/com/arangodb/entity/AqlExecutionExplainEntity.java diff --git a/driver/src/main/java/com/arangodb/entity/AqlFunctionEntity.java b/core/src/main/java/com/arangodb/entity/AqlFunctionEntity.java similarity index 100% rename from driver/src/main/java/com/arangodb/entity/AqlFunctionEntity.java rename to core/src/main/java/com/arangodb/entity/AqlFunctionEntity.java diff --git a/driver/src/main/java/com/arangodb/entity/AqlParseEntity.java b/core/src/main/java/com/arangodb/entity/AqlParseEntity.java similarity index 100% rename from driver/src/main/java/com/arangodb/entity/AqlParseEntity.java rename to core/src/main/java/com/arangodb/entity/AqlParseEntity.java diff --git a/driver/src/main/java/com/arangodb/entity/ArangoDBEngine.java b/core/src/main/java/com/arangodb/entity/ArangoDBEngine.java similarity index 100% rename from driver/src/main/java/com/arangodb/entity/ArangoDBEngine.java rename to core/src/main/java/com/arangodb/entity/ArangoDBEngine.java diff --git a/driver/src/main/java/com/arangodb/entity/ArangoDBVersion.java b/core/src/main/java/com/arangodb/entity/ArangoDBVersion.java similarity index 100% rename from driver/src/main/java/com/arangodb/entity/ArangoDBVersion.java rename to core/src/main/java/com/arangodb/entity/ArangoDBVersion.java diff --git a/driver/src/main/java/com/arangodb/entity/BaseDocument.java b/core/src/main/java/com/arangodb/entity/BaseDocument.java similarity index 100% rename from driver/src/main/java/com/arangodb/entity/BaseDocument.java rename to core/src/main/java/com/arangodb/entity/BaseDocument.java diff --git a/driver/src/main/java/com/arangodb/entity/BaseEdgeDocument.java b/core/src/main/java/com/arangodb/entity/BaseEdgeDocument.java similarity index 100% rename from driver/src/main/java/com/arangodb/entity/BaseEdgeDocument.java rename to core/src/main/java/com/arangodb/entity/BaseEdgeDocument.java diff --git a/driver/src/main/java/com/arangodb/entity/CollectionEntity.java b/core/src/main/java/com/arangodb/entity/CollectionEntity.java similarity index 100% rename from driver/src/main/java/com/arangodb/entity/CollectionEntity.java rename to core/src/main/java/com/arangodb/entity/CollectionEntity.java diff --git a/driver/src/main/java/com/arangodb/entity/CollectionPropertiesEntity.java b/core/src/main/java/com/arangodb/entity/CollectionPropertiesEntity.java similarity index 100% rename from driver/src/main/java/com/arangodb/entity/CollectionPropertiesEntity.java rename to core/src/main/java/com/arangodb/entity/CollectionPropertiesEntity.java diff --git a/driver/src/main/java/com/arangodb/entity/CollectionRevisionEntity.java b/core/src/main/java/com/arangodb/entity/CollectionRevisionEntity.java similarity index 100% rename from driver/src/main/java/com/arangodb/entity/CollectionRevisionEntity.java rename to core/src/main/java/com/arangodb/entity/CollectionRevisionEntity.java diff --git a/driver/src/main/java/com/arangodb/entity/CollectionStatus.java b/core/src/main/java/com/arangodb/entity/CollectionStatus.java similarity index 100% rename from driver/src/main/java/com/arangodb/entity/CollectionStatus.java rename to core/src/main/java/com/arangodb/entity/CollectionStatus.java diff --git a/driver/src/main/java/com/arangodb/entity/CollectionType.java b/core/src/main/java/com/arangodb/entity/CollectionType.java similarity index 100% rename from driver/src/main/java/com/arangodb/entity/CollectionType.java rename to core/src/main/java/com/arangodb/entity/CollectionType.java diff --git a/driver/src/main/java/com/arangodb/entity/CursorWarning.java b/core/src/main/java/com/arangodb/entity/CursorWarning.java similarity index 100% rename from driver/src/main/java/com/arangodb/entity/CursorWarning.java rename to core/src/main/java/com/arangodb/entity/CursorWarning.java diff --git a/driver/src/main/java/com/arangodb/entity/DatabaseEntity.java b/core/src/main/java/com/arangodb/entity/DatabaseEntity.java similarity index 100% rename from driver/src/main/java/com/arangodb/entity/DatabaseEntity.java rename to core/src/main/java/com/arangodb/entity/DatabaseEntity.java diff --git a/driver/src/main/java/com/arangodb/entity/DocumentCreateEntity.java b/core/src/main/java/com/arangodb/entity/DocumentCreateEntity.java similarity index 100% rename from driver/src/main/java/com/arangodb/entity/DocumentCreateEntity.java rename to core/src/main/java/com/arangodb/entity/DocumentCreateEntity.java diff --git a/driver/src/main/java/com/arangodb/entity/DocumentDeleteEntity.java b/core/src/main/java/com/arangodb/entity/DocumentDeleteEntity.java similarity index 100% rename from driver/src/main/java/com/arangodb/entity/DocumentDeleteEntity.java rename to core/src/main/java/com/arangodb/entity/DocumentDeleteEntity.java diff --git a/driver/src/main/java/com/arangodb/entity/DocumentEntity.java b/core/src/main/java/com/arangodb/entity/DocumentEntity.java similarity index 100% rename from driver/src/main/java/com/arangodb/entity/DocumentEntity.java rename to core/src/main/java/com/arangodb/entity/DocumentEntity.java diff --git a/driver/src/main/java/com/arangodb/entity/DocumentImportEntity.java b/core/src/main/java/com/arangodb/entity/DocumentImportEntity.java similarity index 100% rename from driver/src/main/java/com/arangodb/entity/DocumentImportEntity.java rename to core/src/main/java/com/arangodb/entity/DocumentImportEntity.java diff --git a/driver/src/main/java/com/arangodb/entity/DocumentUpdateEntity.java b/core/src/main/java/com/arangodb/entity/DocumentUpdateEntity.java similarity index 100% rename from driver/src/main/java/com/arangodb/entity/DocumentUpdateEntity.java rename to core/src/main/java/com/arangodb/entity/DocumentUpdateEntity.java diff --git a/driver/src/main/java/com/arangodb/entity/EdgeDefinition.java b/core/src/main/java/com/arangodb/entity/EdgeDefinition.java similarity index 100% rename from driver/src/main/java/com/arangodb/entity/EdgeDefinition.java rename to core/src/main/java/com/arangodb/entity/EdgeDefinition.java diff --git a/driver/src/main/java/com/arangodb/entity/EdgeEntity.java b/core/src/main/java/com/arangodb/entity/EdgeEntity.java similarity index 100% rename from driver/src/main/java/com/arangodb/entity/EdgeEntity.java rename to core/src/main/java/com/arangodb/entity/EdgeEntity.java diff --git a/driver/src/main/java/com/arangodb/entity/EdgeUpdateEntity.java b/core/src/main/java/com/arangodb/entity/EdgeUpdateEntity.java similarity index 100% rename from driver/src/main/java/com/arangodb/entity/EdgeUpdateEntity.java rename to core/src/main/java/com/arangodb/entity/EdgeUpdateEntity.java diff --git a/driver/src/main/java/com/arangodb/entity/ErrorEntity.java b/core/src/main/java/com/arangodb/entity/ErrorEntity.java similarity index 100% rename from driver/src/main/java/com/arangodb/entity/ErrorEntity.java rename to core/src/main/java/com/arangodb/entity/ErrorEntity.java diff --git a/driver/src/main/java/com/arangodb/entity/GraphEntity.java b/core/src/main/java/com/arangodb/entity/GraphEntity.java similarity index 100% rename from driver/src/main/java/com/arangodb/entity/GraphEntity.java rename to core/src/main/java/com/arangodb/entity/GraphEntity.java diff --git a/driver/src/main/java/com/arangodb/entity/IndexEntity.java b/core/src/main/java/com/arangodb/entity/IndexEntity.java similarity index 100% rename from driver/src/main/java/com/arangodb/entity/IndexEntity.java rename to core/src/main/java/com/arangodb/entity/IndexEntity.java diff --git a/driver/src/main/java/com/arangodb/entity/IndexType.java b/core/src/main/java/com/arangodb/entity/IndexType.java similarity index 100% rename from driver/src/main/java/com/arangodb/entity/IndexType.java rename to core/src/main/java/com/arangodb/entity/IndexType.java diff --git a/driver/src/main/java/com/arangodb/entity/InvertedIndexEntity.java b/core/src/main/java/com/arangodb/entity/InvertedIndexEntity.java similarity index 100% rename from driver/src/main/java/com/arangodb/entity/InvertedIndexEntity.java rename to core/src/main/java/com/arangodb/entity/InvertedIndexEntity.java diff --git a/driver/src/main/java/com/arangodb/entity/InvertedIndexField.java b/core/src/main/java/com/arangodb/entity/InvertedIndexField.java similarity index 100% rename from driver/src/main/java/com/arangodb/entity/InvertedIndexField.java rename to core/src/main/java/com/arangodb/entity/InvertedIndexField.java diff --git a/driver/src/main/java/com/arangodb/entity/InvertedIndexPrimarySort.java b/core/src/main/java/com/arangodb/entity/InvertedIndexPrimarySort.java similarity index 100% rename from driver/src/main/java/com/arangodb/entity/InvertedIndexPrimarySort.java rename to core/src/main/java/com/arangodb/entity/InvertedIndexPrimarySort.java diff --git a/driver/src/main/java/com/arangodb/entity/KeyOptions.java b/core/src/main/java/com/arangodb/entity/KeyOptions.java similarity index 100% rename from driver/src/main/java/com/arangodb/entity/KeyOptions.java rename to core/src/main/java/com/arangodb/entity/KeyOptions.java diff --git a/driver/src/main/java/com/arangodb/entity/KeyType.java b/core/src/main/java/com/arangodb/entity/KeyType.java similarity index 100% rename from driver/src/main/java/com/arangodb/entity/KeyType.java rename to core/src/main/java/com/arangodb/entity/KeyType.java diff --git a/driver/src/main/java/com/arangodb/entity/License.java b/core/src/main/java/com/arangodb/entity/License.java similarity index 100% rename from driver/src/main/java/com/arangodb/entity/License.java rename to core/src/main/java/com/arangodb/entity/License.java diff --git a/driver/src/main/java/com/arangodb/entity/LoadBalancingStrategy.java b/core/src/main/java/com/arangodb/entity/LoadBalancingStrategy.java similarity index 100% rename from driver/src/main/java/com/arangodb/entity/LoadBalancingStrategy.java rename to core/src/main/java/com/arangodb/entity/LoadBalancingStrategy.java diff --git a/driver/src/main/java/com/arangodb/entity/LogEntriesEntity.java b/core/src/main/java/com/arangodb/entity/LogEntriesEntity.java similarity index 100% rename from driver/src/main/java/com/arangodb/entity/LogEntriesEntity.java rename to core/src/main/java/com/arangodb/entity/LogEntriesEntity.java diff --git a/driver/src/main/java/com/arangodb/entity/LogLevel.java b/core/src/main/java/com/arangodb/entity/LogLevel.java similarity index 100% rename from driver/src/main/java/com/arangodb/entity/LogLevel.java rename to core/src/main/java/com/arangodb/entity/LogLevel.java diff --git a/driver/src/main/java/com/arangodb/entity/LogLevelEntity.java b/core/src/main/java/com/arangodb/entity/LogLevelEntity.java similarity index 100% rename from driver/src/main/java/com/arangodb/entity/LogLevelEntity.java rename to core/src/main/java/com/arangodb/entity/LogLevelEntity.java diff --git a/driver/src/main/java/com/arangodb/entity/MetaAware.java b/core/src/main/java/com/arangodb/entity/MetaAware.java similarity index 100% rename from driver/src/main/java/com/arangodb/entity/MetaAware.java rename to core/src/main/java/com/arangodb/entity/MetaAware.java diff --git a/driver/src/main/java/com/arangodb/entity/MultiDocumentEntity.java b/core/src/main/java/com/arangodb/entity/MultiDocumentEntity.java similarity index 100% rename from driver/src/main/java/com/arangodb/entity/MultiDocumentEntity.java rename to core/src/main/java/com/arangodb/entity/MultiDocumentEntity.java diff --git a/driver/src/main/java/com/arangodb/entity/Permissions.java b/core/src/main/java/com/arangodb/entity/Permissions.java similarity index 100% rename from driver/src/main/java/com/arangodb/entity/Permissions.java rename to core/src/main/java/com/arangodb/entity/Permissions.java diff --git a/driver/src/main/java/com/arangodb/entity/QueryCachePropertiesEntity.java b/core/src/main/java/com/arangodb/entity/QueryCachePropertiesEntity.java similarity index 100% rename from driver/src/main/java/com/arangodb/entity/QueryCachePropertiesEntity.java rename to core/src/main/java/com/arangodb/entity/QueryCachePropertiesEntity.java diff --git a/driver/src/main/java/com/arangodb/entity/QueryEntity.java b/core/src/main/java/com/arangodb/entity/QueryEntity.java similarity index 100% rename from driver/src/main/java/com/arangodb/entity/QueryEntity.java rename to core/src/main/java/com/arangodb/entity/QueryEntity.java diff --git a/driver/src/main/java/com/arangodb/entity/QueryExecutionState.java b/core/src/main/java/com/arangodb/entity/QueryExecutionState.java similarity index 100% rename from driver/src/main/java/com/arangodb/entity/QueryExecutionState.java rename to core/src/main/java/com/arangodb/entity/QueryExecutionState.java diff --git a/driver/src/main/java/com/arangodb/entity/QueryOptimizerRule.java b/core/src/main/java/com/arangodb/entity/QueryOptimizerRule.java similarity index 100% rename from driver/src/main/java/com/arangodb/entity/QueryOptimizerRule.java rename to core/src/main/java/com/arangodb/entity/QueryOptimizerRule.java diff --git a/driver/src/main/java/com/arangodb/entity/QueryTrackingPropertiesEntity.java b/core/src/main/java/com/arangodb/entity/QueryTrackingPropertiesEntity.java similarity index 100% rename from driver/src/main/java/com/arangodb/entity/QueryTrackingPropertiesEntity.java rename to core/src/main/java/com/arangodb/entity/QueryTrackingPropertiesEntity.java diff --git a/driver/src/main/java/com/arangodb/entity/ReplicationFactor.java b/core/src/main/java/com/arangodb/entity/ReplicationFactor.java similarity index 100% rename from driver/src/main/java/com/arangodb/entity/ReplicationFactor.java rename to core/src/main/java/com/arangodb/entity/ReplicationFactor.java diff --git a/driver/src/main/java/com/arangodb/entity/ServerMode.java b/core/src/main/java/com/arangodb/entity/ServerMode.java similarity index 100% rename from driver/src/main/java/com/arangodb/entity/ServerMode.java rename to core/src/main/java/com/arangodb/entity/ServerMode.java diff --git a/driver/src/main/java/com/arangodb/entity/ServerRole.java b/core/src/main/java/com/arangodb/entity/ServerRole.java similarity index 100% rename from driver/src/main/java/com/arangodb/entity/ServerRole.java rename to core/src/main/java/com/arangodb/entity/ServerRole.java diff --git a/driver/src/main/java/com/arangodb/entity/ShardEntity.java b/core/src/main/java/com/arangodb/entity/ShardEntity.java similarity index 100% rename from driver/src/main/java/com/arangodb/entity/ShardEntity.java rename to core/src/main/java/com/arangodb/entity/ShardEntity.java diff --git a/driver/src/main/java/com/arangodb/entity/ShardingStrategy.java b/core/src/main/java/com/arangodb/entity/ShardingStrategy.java similarity index 100% rename from driver/src/main/java/com/arangodb/entity/ShardingStrategy.java rename to core/src/main/java/com/arangodb/entity/ShardingStrategy.java diff --git a/driver/src/main/java/com/arangodb/entity/StreamTransactionEntity.java b/core/src/main/java/com/arangodb/entity/StreamTransactionEntity.java similarity index 100% rename from driver/src/main/java/com/arangodb/entity/StreamTransactionEntity.java rename to core/src/main/java/com/arangodb/entity/StreamTransactionEntity.java diff --git a/driver/src/main/java/com/arangodb/entity/StreamTransactionStatus.java b/core/src/main/java/com/arangodb/entity/StreamTransactionStatus.java similarity index 100% rename from driver/src/main/java/com/arangodb/entity/StreamTransactionStatus.java rename to core/src/main/java/com/arangodb/entity/StreamTransactionStatus.java diff --git a/driver/src/main/java/com/arangodb/entity/TransactionEntity.java b/core/src/main/java/com/arangodb/entity/TransactionEntity.java similarity index 100% rename from driver/src/main/java/com/arangodb/entity/TransactionEntity.java rename to core/src/main/java/com/arangodb/entity/TransactionEntity.java diff --git a/driver/src/main/java/com/arangodb/entity/UserEntity.java b/core/src/main/java/com/arangodb/entity/UserEntity.java similarity index 100% rename from driver/src/main/java/com/arangodb/entity/UserEntity.java rename to core/src/main/java/com/arangodb/entity/UserEntity.java diff --git a/driver/src/main/java/com/arangodb/entity/VertexEntity.java b/core/src/main/java/com/arangodb/entity/VertexEntity.java similarity index 100% rename from driver/src/main/java/com/arangodb/entity/VertexEntity.java rename to core/src/main/java/com/arangodb/entity/VertexEntity.java diff --git a/driver/src/main/java/com/arangodb/entity/VertexUpdateEntity.java b/core/src/main/java/com/arangodb/entity/VertexUpdateEntity.java similarity index 100% rename from driver/src/main/java/com/arangodb/entity/VertexUpdateEntity.java rename to core/src/main/java/com/arangodb/entity/VertexUpdateEntity.java diff --git a/driver/src/main/java/com/arangodb/entity/ViewEntity.java b/core/src/main/java/com/arangodb/entity/ViewEntity.java similarity index 100% rename from driver/src/main/java/com/arangodb/entity/ViewEntity.java rename to core/src/main/java/com/arangodb/entity/ViewEntity.java diff --git a/driver/src/main/java/com/arangodb/entity/ViewType.java b/core/src/main/java/com/arangodb/entity/ViewType.java similarity index 100% rename from driver/src/main/java/com/arangodb/entity/ViewType.java rename to core/src/main/java/com/arangodb/entity/ViewType.java diff --git a/driver/src/main/java/com/arangodb/entity/arangosearch/AnalyzerFeature.java b/core/src/main/java/com/arangodb/entity/arangosearch/AnalyzerFeature.java similarity index 100% rename from driver/src/main/java/com/arangodb/entity/arangosearch/AnalyzerFeature.java rename to core/src/main/java/com/arangodb/entity/arangosearch/AnalyzerFeature.java diff --git a/driver/src/main/java/com/arangodb/entity/arangosearch/AnalyzerType.java b/core/src/main/java/com/arangodb/entity/arangosearch/AnalyzerType.java similarity index 100% rename from driver/src/main/java/com/arangodb/entity/arangosearch/AnalyzerType.java rename to core/src/main/java/com/arangodb/entity/arangosearch/AnalyzerType.java diff --git a/driver/src/main/java/com/arangodb/entity/arangosearch/ArangoSearchCompression.java b/core/src/main/java/com/arangodb/entity/arangosearch/ArangoSearchCompression.java similarity index 100% rename from driver/src/main/java/com/arangodb/entity/arangosearch/ArangoSearchCompression.java rename to core/src/main/java/com/arangodb/entity/arangosearch/ArangoSearchCompression.java diff --git a/driver/src/main/java/com/arangodb/entity/arangosearch/ArangoSearchPropertiesEntity.java b/core/src/main/java/com/arangodb/entity/arangosearch/ArangoSearchPropertiesEntity.java similarity index 100% rename from driver/src/main/java/com/arangodb/entity/arangosearch/ArangoSearchPropertiesEntity.java rename to core/src/main/java/com/arangodb/entity/arangosearch/ArangoSearchPropertiesEntity.java diff --git a/driver/src/main/java/com/arangodb/entity/arangosearch/CollectionLink.java b/core/src/main/java/com/arangodb/entity/arangosearch/CollectionLink.java similarity index 100% rename from driver/src/main/java/com/arangodb/entity/arangosearch/CollectionLink.java rename to core/src/main/java/com/arangodb/entity/arangosearch/CollectionLink.java diff --git a/driver/src/main/java/com/arangodb/entity/arangosearch/ConsolidationPolicy.java b/core/src/main/java/com/arangodb/entity/arangosearch/ConsolidationPolicy.java similarity index 100% rename from driver/src/main/java/com/arangodb/entity/arangosearch/ConsolidationPolicy.java rename to core/src/main/java/com/arangodb/entity/arangosearch/ConsolidationPolicy.java diff --git a/driver/src/main/java/com/arangodb/entity/arangosearch/ConsolidationType.java b/core/src/main/java/com/arangodb/entity/arangosearch/ConsolidationType.java similarity index 100% rename from driver/src/main/java/com/arangodb/entity/arangosearch/ConsolidationType.java rename to core/src/main/java/com/arangodb/entity/arangosearch/ConsolidationType.java diff --git a/driver/src/main/java/com/arangodb/entity/arangosearch/FieldLink.java b/core/src/main/java/com/arangodb/entity/arangosearch/FieldLink.java similarity index 100% rename from driver/src/main/java/com/arangodb/entity/arangosearch/FieldLink.java rename to core/src/main/java/com/arangodb/entity/arangosearch/FieldLink.java diff --git a/driver/src/main/java/com/arangodb/entity/arangosearch/PrimarySort.java b/core/src/main/java/com/arangodb/entity/arangosearch/PrimarySort.java similarity index 100% rename from driver/src/main/java/com/arangodb/entity/arangosearch/PrimarySort.java rename to core/src/main/java/com/arangodb/entity/arangosearch/PrimarySort.java diff --git a/driver/src/main/java/com/arangodb/entity/arangosearch/SearchAliasIndex.java b/core/src/main/java/com/arangodb/entity/arangosearch/SearchAliasIndex.java similarity index 100% rename from driver/src/main/java/com/arangodb/entity/arangosearch/SearchAliasIndex.java rename to core/src/main/java/com/arangodb/entity/arangosearch/SearchAliasIndex.java diff --git a/driver/src/main/java/com/arangodb/entity/arangosearch/SearchAliasPropertiesEntity.java b/core/src/main/java/com/arangodb/entity/arangosearch/SearchAliasPropertiesEntity.java similarity index 100% rename from driver/src/main/java/com/arangodb/entity/arangosearch/SearchAliasPropertiesEntity.java rename to core/src/main/java/com/arangodb/entity/arangosearch/SearchAliasPropertiesEntity.java diff --git a/driver/src/main/java/com/arangodb/entity/arangosearch/StoreValuesType.java b/core/src/main/java/com/arangodb/entity/arangosearch/StoreValuesType.java similarity index 100% rename from driver/src/main/java/com/arangodb/entity/arangosearch/StoreValuesType.java rename to core/src/main/java/com/arangodb/entity/arangosearch/StoreValuesType.java diff --git a/driver/src/main/java/com/arangodb/entity/arangosearch/StoredValue.java b/core/src/main/java/com/arangodb/entity/arangosearch/StoredValue.java similarity index 100% rename from driver/src/main/java/com/arangodb/entity/arangosearch/StoredValue.java rename to core/src/main/java/com/arangodb/entity/arangosearch/StoredValue.java diff --git a/driver/src/main/java/com/arangodb/entity/arangosearch/analyzer/AQLAnalyzer.java b/core/src/main/java/com/arangodb/entity/arangosearch/analyzer/AQLAnalyzer.java similarity index 100% rename from driver/src/main/java/com/arangodb/entity/arangosearch/analyzer/AQLAnalyzer.java rename to core/src/main/java/com/arangodb/entity/arangosearch/analyzer/AQLAnalyzer.java diff --git a/driver/src/main/java/com/arangodb/entity/arangosearch/analyzer/AQLAnalyzerProperties.java b/core/src/main/java/com/arangodb/entity/arangosearch/analyzer/AQLAnalyzerProperties.java similarity index 100% rename from driver/src/main/java/com/arangodb/entity/arangosearch/analyzer/AQLAnalyzerProperties.java rename to core/src/main/java/com/arangodb/entity/arangosearch/analyzer/AQLAnalyzerProperties.java diff --git a/driver/src/main/java/com/arangodb/entity/arangosearch/analyzer/ClassificationAnalyzer.java b/core/src/main/java/com/arangodb/entity/arangosearch/analyzer/ClassificationAnalyzer.java similarity index 100% rename from driver/src/main/java/com/arangodb/entity/arangosearch/analyzer/ClassificationAnalyzer.java rename to core/src/main/java/com/arangodb/entity/arangosearch/analyzer/ClassificationAnalyzer.java diff --git a/driver/src/main/java/com/arangodb/entity/arangosearch/analyzer/ClassificationAnalyzerProperties.java b/core/src/main/java/com/arangodb/entity/arangosearch/analyzer/ClassificationAnalyzerProperties.java similarity index 100% rename from driver/src/main/java/com/arangodb/entity/arangosearch/analyzer/ClassificationAnalyzerProperties.java rename to core/src/main/java/com/arangodb/entity/arangosearch/analyzer/ClassificationAnalyzerProperties.java diff --git a/driver/src/main/java/com/arangodb/entity/arangosearch/analyzer/CollationAnalyzer.java b/core/src/main/java/com/arangodb/entity/arangosearch/analyzer/CollationAnalyzer.java similarity index 100% rename from driver/src/main/java/com/arangodb/entity/arangosearch/analyzer/CollationAnalyzer.java rename to core/src/main/java/com/arangodb/entity/arangosearch/analyzer/CollationAnalyzer.java diff --git a/driver/src/main/java/com/arangodb/entity/arangosearch/analyzer/CollationAnalyzerProperties.java b/core/src/main/java/com/arangodb/entity/arangosearch/analyzer/CollationAnalyzerProperties.java similarity index 100% rename from driver/src/main/java/com/arangodb/entity/arangosearch/analyzer/CollationAnalyzerProperties.java rename to core/src/main/java/com/arangodb/entity/arangosearch/analyzer/CollationAnalyzerProperties.java diff --git a/driver/src/main/java/com/arangodb/entity/arangosearch/analyzer/DelimiterAnalyzer.java b/core/src/main/java/com/arangodb/entity/arangosearch/analyzer/DelimiterAnalyzer.java similarity index 100% rename from driver/src/main/java/com/arangodb/entity/arangosearch/analyzer/DelimiterAnalyzer.java rename to core/src/main/java/com/arangodb/entity/arangosearch/analyzer/DelimiterAnalyzer.java diff --git a/driver/src/main/java/com/arangodb/entity/arangosearch/analyzer/DelimiterAnalyzerProperties.java b/core/src/main/java/com/arangodb/entity/arangosearch/analyzer/DelimiterAnalyzerProperties.java similarity index 100% rename from driver/src/main/java/com/arangodb/entity/arangosearch/analyzer/DelimiterAnalyzerProperties.java rename to core/src/main/java/com/arangodb/entity/arangosearch/analyzer/DelimiterAnalyzerProperties.java diff --git a/driver/src/main/java/com/arangodb/entity/arangosearch/analyzer/EdgeNgram.java b/core/src/main/java/com/arangodb/entity/arangosearch/analyzer/EdgeNgram.java similarity index 100% rename from driver/src/main/java/com/arangodb/entity/arangosearch/analyzer/EdgeNgram.java rename to core/src/main/java/com/arangodb/entity/arangosearch/analyzer/EdgeNgram.java diff --git a/driver/src/main/java/com/arangodb/entity/arangosearch/analyzer/GeoAnalyzerOptions.java b/core/src/main/java/com/arangodb/entity/arangosearch/analyzer/GeoAnalyzerOptions.java similarity index 100% rename from driver/src/main/java/com/arangodb/entity/arangosearch/analyzer/GeoAnalyzerOptions.java rename to core/src/main/java/com/arangodb/entity/arangosearch/analyzer/GeoAnalyzerOptions.java diff --git a/driver/src/main/java/com/arangodb/entity/arangosearch/analyzer/GeoJSONAnalyzer.java b/core/src/main/java/com/arangodb/entity/arangosearch/analyzer/GeoJSONAnalyzer.java similarity index 100% rename from driver/src/main/java/com/arangodb/entity/arangosearch/analyzer/GeoJSONAnalyzer.java rename to core/src/main/java/com/arangodb/entity/arangosearch/analyzer/GeoJSONAnalyzer.java diff --git a/driver/src/main/java/com/arangodb/entity/arangosearch/analyzer/GeoJSONAnalyzerProperties.java b/core/src/main/java/com/arangodb/entity/arangosearch/analyzer/GeoJSONAnalyzerProperties.java similarity index 100% rename from driver/src/main/java/com/arangodb/entity/arangosearch/analyzer/GeoJSONAnalyzerProperties.java rename to core/src/main/java/com/arangodb/entity/arangosearch/analyzer/GeoJSONAnalyzerProperties.java diff --git a/driver/src/main/java/com/arangodb/entity/arangosearch/analyzer/GeoPointAnalyzer.java b/core/src/main/java/com/arangodb/entity/arangosearch/analyzer/GeoPointAnalyzer.java similarity index 100% rename from driver/src/main/java/com/arangodb/entity/arangosearch/analyzer/GeoPointAnalyzer.java rename to core/src/main/java/com/arangodb/entity/arangosearch/analyzer/GeoPointAnalyzer.java diff --git a/driver/src/main/java/com/arangodb/entity/arangosearch/analyzer/GeoPointAnalyzerProperties.java b/core/src/main/java/com/arangodb/entity/arangosearch/analyzer/GeoPointAnalyzerProperties.java similarity index 100% rename from driver/src/main/java/com/arangodb/entity/arangosearch/analyzer/GeoPointAnalyzerProperties.java rename to core/src/main/java/com/arangodb/entity/arangosearch/analyzer/GeoPointAnalyzerProperties.java diff --git a/driver/src/main/java/com/arangodb/entity/arangosearch/analyzer/IdentityAnalyzer.java b/core/src/main/java/com/arangodb/entity/arangosearch/analyzer/IdentityAnalyzer.java similarity index 100% rename from driver/src/main/java/com/arangodb/entity/arangosearch/analyzer/IdentityAnalyzer.java rename to core/src/main/java/com/arangodb/entity/arangosearch/analyzer/IdentityAnalyzer.java diff --git a/driver/src/main/java/com/arangodb/entity/arangosearch/analyzer/MinHashAnalyzer.java b/core/src/main/java/com/arangodb/entity/arangosearch/analyzer/MinHashAnalyzer.java similarity index 100% rename from driver/src/main/java/com/arangodb/entity/arangosearch/analyzer/MinHashAnalyzer.java rename to core/src/main/java/com/arangodb/entity/arangosearch/analyzer/MinHashAnalyzer.java diff --git a/driver/src/main/java/com/arangodb/entity/arangosearch/analyzer/MinHashAnalyzerProperties.java b/core/src/main/java/com/arangodb/entity/arangosearch/analyzer/MinHashAnalyzerProperties.java similarity index 100% rename from driver/src/main/java/com/arangodb/entity/arangosearch/analyzer/MinHashAnalyzerProperties.java rename to core/src/main/java/com/arangodb/entity/arangosearch/analyzer/MinHashAnalyzerProperties.java diff --git a/driver/src/main/java/com/arangodb/entity/arangosearch/analyzer/NGramAnalyzer.java b/core/src/main/java/com/arangodb/entity/arangosearch/analyzer/NGramAnalyzer.java similarity index 100% rename from driver/src/main/java/com/arangodb/entity/arangosearch/analyzer/NGramAnalyzer.java rename to core/src/main/java/com/arangodb/entity/arangosearch/analyzer/NGramAnalyzer.java diff --git a/driver/src/main/java/com/arangodb/entity/arangosearch/analyzer/NGramAnalyzerProperties.java b/core/src/main/java/com/arangodb/entity/arangosearch/analyzer/NGramAnalyzerProperties.java similarity index 100% rename from driver/src/main/java/com/arangodb/entity/arangosearch/analyzer/NGramAnalyzerProperties.java rename to core/src/main/java/com/arangodb/entity/arangosearch/analyzer/NGramAnalyzerProperties.java diff --git a/driver/src/main/java/com/arangodb/entity/arangosearch/analyzer/NearestNeighborsAnalyzer.java b/core/src/main/java/com/arangodb/entity/arangosearch/analyzer/NearestNeighborsAnalyzer.java similarity index 100% rename from driver/src/main/java/com/arangodb/entity/arangosearch/analyzer/NearestNeighborsAnalyzer.java rename to core/src/main/java/com/arangodb/entity/arangosearch/analyzer/NearestNeighborsAnalyzer.java diff --git a/driver/src/main/java/com/arangodb/entity/arangosearch/analyzer/NearestNeighborsAnalyzerProperties.java b/core/src/main/java/com/arangodb/entity/arangosearch/analyzer/NearestNeighborsAnalyzerProperties.java similarity index 100% rename from driver/src/main/java/com/arangodb/entity/arangosearch/analyzer/NearestNeighborsAnalyzerProperties.java rename to core/src/main/java/com/arangodb/entity/arangosearch/analyzer/NearestNeighborsAnalyzerProperties.java diff --git a/driver/src/main/java/com/arangodb/entity/arangosearch/analyzer/NormAnalyzer.java b/core/src/main/java/com/arangodb/entity/arangosearch/analyzer/NormAnalyzer.java similarity index 100% rename from driver/src/main/java/com/arangodb/entity/arangosearch/analyzer/NormAnalyzer.java rename to core/src/main/java/com/arangodb/entity/arangosearch/analyzer/NormAnalyzer.java diff --git a/driver/src/main/java/com/arangodb/entity/arangosearch/analyzer/NormAnalyzerProperties.java b/core/src/main/java/com/arangodb/entity/arangosearch/analyzer/NormAnalyzerProperties.java similarity index 100% rename from driver/src/main/java/com/arangodb/entity/arangosearch/analyzer/NormAnalyzerProperties.java rename to core/src/main/java/com/arangodb/entity/arangosearch/analyzer/NormAnalyzerProperties.java diff --git a/driver/src/main/java/com/arangodb/entity/arangosearch/analyzer/PipelineAnalyzer.java b/core/src/main/java/com/arangodb/entity/arangosearch/analyzer/PipelineAnalyzer.java similarity index 100% rename from driver/src/main/java/com/arangodb/entity/arangosearch/analyzer/PipelineAnalyzer.java rename to core/src/main/java/com/arangodb/entity/arangosearch/analyzer/PipelineAnalyzer.java diff --git a/driver/src/main/java/com/arangodb/entity/arangosearch/analyzer/PipelineAnalyzerProperties.java b/core/src/main/java/com/arangodb/entity/arangosearch/analyzer/PipelineAnalyzerProperties.java similarity index 100% rename from driver/src/main/java/com/arangodb/entity/arangosearch/analyzer/PipelineAnalyzerProperties.java rename to core/src/main/java/com/arangodb/entity/arangosearch/analyzer/PipelineAnalyzerProperties.java diff --git a/driver/src/main/java/com/arangodb/entity/arangosearch/analyzer/SearchAnalyzer.java b/core/src/main/java/com/arangodb/entity/arangosearch/analyzer/SearchAnalyzer.java similarity index 100% rename from driver/src/main/java/com/arangodb/entity/arangosearch/analyzer/SearchAnalyzer.java rename to core/src/main/java/com/arangodb/entity/arangosearch/analyzer/SearchAnalyzer.java diff --git a/driver/src/main/java/com/arangodb/entity/arangosearch/analyzer/SearchAnalyzerCase.java b/core/src/main/java/com/arangodb/entity/arangosearch/analyzer/SearchAnalyzerCase.java similarity index 100% rename from driver/src/main/java/com/arangodb/entity/arangosearch/analyzer/SearchAnalyzerCase.java rename to core/src/main/java/com/arangodb/entity/arangosearch/analyzer/SearchAnalyzerCase.java diff --git a/driver/src/main/java/com/arangodb/entity/arangosearch/analyzer/SegmentationAnalyzer.java b/core/src/main/java/com/arangodb/entity/arangosearch/analyzer/SegmentationAnalyzer.java similarity index 100% rename from driver/src/main/java/com/arangodb/entity/arangosearch/analyzer/SegmentationAnalyzer.java rename to core/src/main/java/com/arangodb/entity/arangosearch/analyzer/SegmentationAnalyzer.java diff --git a/driver/src/main/java/com/arangodb/entity/arangosearch/analyzer/SegmentationAnalyzerProperties.java b/core/src/main/java/com/arangodb/entity/arangosearch/analyzer/SegmentationAnalyzerProperties.java similarity index 100% rename from driver/src/main/java/com/arangodb/entity/arangosearch/analyzer/SegmentationAnalyzerProperties.java rename to core/src/main/java/com/arangodb/entity/arangosearch/analyzer/SegmentationAnalyzerProperties.java diff --git a/driver/src/main/java/com/arangodb/entity/arangosearch/analyzer/StemAnalyzer.java b/core/src/main/java/com/arangodb/entity/arangosearch/analyzer/StemAnalyzer.java similarity index 100% rename from driver/src/main/java/com/arangodb/entity/arangosearch/analyzer/StemAnalyzer.java rename to core/src/main/java/com/arangodb/entity/arangosearch/analyzer/StemAnalyzer.java diff --git a/driver/src/main/java/com/arangodb/entity/arangosearch/analyzer/StemAnalyzerProperties.java b/core/src/main/java/com/arangodb/entity/arangosearch/analyzer/StemAnalyzerProperties.java similarity index 100% rename from driver/src/main/java/com/arangodb/entity/arangosearch/analyzer/StemAnalyzerProperties.java rename to core/src/main/java/com/arangodb/entity/arangosearch/analyzer/StemAnalyzerProperties.java diff --git a/driver/src/main/java/com/arangodb/entity/arangosearch/analyzer/StopwordsAnalyzer.java b/core/src/main/java/com/arangodb/entity/arangosearch/analyzer/StopwordsAnalyzer.java similarity index 100% rename from driver/src/main/java/com/arangodb/entity/arangosearch/analyzer/StopwordsAnalyzer.java rename to core/src/main/java/com/arangodb/entity/arangosearch/analyzer/StopwordsAnalyzer.java diff --git a/driver/src/main/java/com/arangodb/entity/arangosearch/analyzer/StopwordsAnalyzerProperties.java b/core/src/main/java/com/arangodb/entity/arangosearch/analyzer/StopwordsAnalyzerProperties.java similarity index 100% rename from driver/src/main/java/com/arangodb/entity/arangosearch/analyzer/StopwordsAnalyzerProperties.java rename to core/src/main/java/com/arangodb/entity/arangosearch/analyzer/StopwordsAnalyzerProperties.java diff --git a/driver/src/main/java/com/arangodb/entity/arangosearch/analyzer/StreamType.java b/core/src/main/java/com/arangodb/entity/arangosearch/analyzer/StreamType.java similarity index 100% rename from driver/src/main/java/com/arangodb/entity/arangosearch/analyzer/StreamType.java rename to core/src/main/java/com/arangodb/entity/arangosearch/analyzer/StreamType.java diff --git a/driver/src/main/java/com/arangodb/entity/arangosearch/analyzer/TextAnalyzer.java b/core/src/main/java/com/arangodb/entity/arangosearch/analyzer/TextAnalyzer.java similarity index 100% rename from driver/src/main/java/com/arangodb/entity/arangosearch/analyzer/TextAnalyzer.java rename to core/src/main/java/com/arangodb/entity/arangosearch/analyzer/TextAnalyzer.java diff --git a/driver/src/main/java/com/arangodb/entity/arangosearch/analyzer/TextAnalyzerProperties.java b/core/src/main/java/com/arangodb/entity/arangosearch/analyzer/TextAnalyzerProperties.java similarity index 100% rename from driver/src/main/java/com/arangodb/entity/arangosearch/analyzer/TextAnalyzerProperties.java rename to core/src/main/java/com/arangodb/entity/arangosearch/analyzer/TextAnalyzerProperties.java diff --git a/driver/src/main/java/com/arangodb/internal/ArangoCollectionImpl.java b/core/src/main/java/com/arangodb/internal/ArangoCollectionImpl.java similarity index 100% rename from driver/src/main/java/com/arangodb/internal/ArangoCollectionImpl.java rename to core/src/main/java/com/arangodb/internal/ArangoCollectionImpl.java diff --git a/driver/src/main/java/com/arangodb/internal/ArangoCursorExecute.java b/core/src/main/java/com/arangodb/internal/ArangoCursorExecute.java similarity index 100% rename from driver/src/main/java/com/arangodb/internal/ArangoCursorExecute.java rename to core/src/main/java/com/arangodb/internal/ArangoCursorExecute.java diff --git a/driver/src/main/java/com/arangodb/internal/ArangoDBImpl.java b/core/src/main/java/com/arangodb/internal/ArangoDBImpl.java similarity index 78% rename from driver/src/main/java/com/arangodb/internal/ArangoDBImpl.java rename to core/src/main/java/com/arangodb/internal/ArangoDBImpl.java index 22a0e95a1..52801b51e 100644 --- a/driver/src/main/java/com/arangodb/internal/ArangoDBImpl.java +++ b/core/src/main/java/com/arangodb/internal/ArangoDBImpl.java @@ -22,15 +22,11 @@ import com.arangodb.*; import com.arangodb.entity.*; -import com.arangodb.internal.http.HttpCommunication; -import com.arangodb.internal.http.HttpProtocol; -import com.arangodb.internal.net.CommunicationProtocol; +import com.arangodb.internal.config.ArangoConfig; import com.arangodb.internal.net.HostHandler; import com.arangodb.internal.net.HostResolver; -import com.arangodb.internal.serde.InternalSerde; +import com.arangodb.internal.net.ProtocolProvider; import com.arangodb.internal.serde.SerdeUtils; -import com.arangodb.internal.velocystream.VstCommunicationSync; -import com.arangodb.internal.velocystream.VstProtocol; import com.arangodb.model.DBCreateOptions; import com.arangodb.model.LogOptions; import com.arangodb.model.UserCreateOptions; @@ -50,43 +46,15 @@ public class ArangoDBImpl extends InternalArangoDB implement private static final Logger LOGGER = LoggerFactory.getLogger(ArangoDBImpl.class); private final HostHandler hostHandler; - public ArangoDBImpl(final VstCommunicationSync.Builder vstBuilder, final HttpCommunication.Builder httpBuilder, - final InternalSerde util, final Protocol protocol, final HostResolver hostResolver, - final HostHandler hostHandler, int responseQueueTimeSamples, - final int timeoutMs) { - - super(new ArangoExecutorSync( - createProtocol(vstBuilder, httpBuilder, util, protocol), - util, new QueueTimeMetricsImpl(responseQueueTimeSamples), timeoutMs), - util); - + public ArangoDBImpl(final ArangoConfig config, + final HostResolver hostResolver, final ProtocolProvider protocolProvider, + final HostHandler hostHandler) { + super(new ArangoExecutorSync(protocolProvider.createProtocol(config, hostHandler), config), config.getInternalSerde()); this.hostHandler = hostHandler; hostResolver.init(this.executor(), getSerde()); LOGGER.debug("ArangoDB Client is ready to use"); } - private static CommunicationProtocol createProtocol( - final VstCommunicationSync.Builder vstBuilder, - final HttpCommunication.Builder httpBuilder, - final InternalSerde util, - final Protocol protocol) { - - return (protocol == null || Protocol.VST == protocol) ? createVST(vstBuilder, util) - : createHTTP(httpBuilder, util); - } - - private static CommunicationProtocol createVST( - final VstCommunicationSync.Builder builder, - final InternalSerde util) { - return new VstProtocol(builder.build(util)); - } - - private static CommunicationProtocol createHTTP( - final HttpCommunication.Builder builder, - final InternalSerde util) { - return new HttpProtocol(builder.serde(util).build()); - } - @Override protected ArangoExecutorSync executor() { return executor; diff --git a/driver/src/main/java/com/arangodb/internal/ArangoDatabaseImpl.java b/core/src/main/java/com/arangodb/internal/ArangoDatabaseImpl.java similarity index 100% rename from driver/src/main/java/com/arangodb/internal/ArangoDatabaseImpl.java rename to core/src/main/java/com/arangodb/internal/ArangoDatabaseImpl.java diff --git a/driver/src/main/java/com/arangodb/internal/ArangoDefaults.java b/core/src/main/java/com/arangodb/internal/ArangoDefaults.java similarity index 100% rename from driver/src/main/java/com/arangodb/internal/ArangoDefaults.java rename to core/src/main/java/com/arangodb/internal/ArangoDefaults.java diff --git a/driver/src/main/java/com/arangodb/internal/ArangoEdgeCollectionImpl.java b/core/src/main/java/com/arangodb/internal/ArangoEdgeCollectionImpl.java similarity index 100% rename from driver/src/main/java/com/arangodb/internal/ArangoEdgeCollectionImpl.java rename to core/src/main/java/com/arangodb/internal/ArangoEdgeCollectionImpl.java diff --git a/driver/src/main/java/com/arangodb/internal/ArangoErrors.java b/core/src/main/java/com/arangodb/internal/ArangoErrors.java similarity index 100% rename from driver/src/main/java/com/arangodb/internal/ArangoErrors.java rename to core/src/main/java/com/arangodb/internal/ArangoErrors.java diff --git a/driver/src/main/java/com/arangodb/internal/ArangoExecuteable.java b/core/src/main/java/com/arangodb/internal/ArangoExecuteable.java similarity index 100% rename from driver/src/main/java/com/arangodb/internal/ArangoExecuteable.java rename to core/src/main/java/com/arangodb/internal/ArangoExecuteable.java diff --git a/driver/src/main/java/com/arangodb/internal/ArangoExecutor.java b/core/src/main/java/com/arangodb/internal/ArangoExecutor.java similarity index 84% rename from driver/src/main/java/com/arangodb/internal/ArangoExecutor.java rename to core/src/main/java/com/arangodb/internal/ArangoExecutor.java index ad9e0acda..a37f4b11c 100644 --- a/driver/src/main/java/com/arangodb/internal/ArangoExecutor.java +++ b/core/src/main/java/com/arangodb/internal/ArangoExecutor.java @@ -21,6 +21,7 @@ package com.arangodb.internal; import com.arangodb.QueueTimeMetrics; +import com.arangodb.internal.config.ArangoConfig; import com.arangodb.internal.serde.InternalSerde; import java.lang.reflect.Type; @@ -34,11 +35,11 @@ public abstract class ArangoExecutor { private final InternalSerde serde; private final String timeoutS; - protected ArangoExecutor(final InternalSerde serde, final QueueTimeMetricsImpl qtMetrics, final int timeoutMs) { + protected ArangoExecutor(final ArangoConfig config) { super(); - this.qtMetrics = qtMetrics; - this.serde = serde; - timeoutS = timeoutMs >= 1000 ? Integer.toString(timeoutMs / 1000) : null; + qtMetrics = new QueueTimeMetricsImpl(config.getResponseQueueTimeSamples()); + serde = config.getInternalSerde(); + timeoutS = config.getTimeout() >= 1000 ? Integer.toString(config.getTimeout() / 1000) : null; } protected T createResult(final Type type, final InternalResponse response) { diff --git a/driver/src/main/java/com/arangodb/internal/ArangoExecutorSync.java b/core/src/main/java/com/arangodb/internal/ArangoExecutorSync.java similarity index 92% rename from driver/src/main/java/com/arangodb/internal/ArangoExecutorSync.java rename to core/src/main/java/com/arangodb/internal/ArangoExecutorSync.java index 88b2f6f0f..00a6ae6f7 100644 --- a/driver/src/main/java/com/arangodb/internal/ArangoExecutorSync.java +++ b/core/src/main/java/com/arangodb/internal/ArangoExecutorSync.java @@ -22,9 +22,9 @@ import com.arangodb.ArangoDBException; import com.arangodb.entity.MetaAware; +import com.arangodb.internal.config.ArangoConfig; import com.arangodb.internal.net.CommunicationProtocol; import com.arangodb.internal.net.HostHandle; -import com.arangodb.internal.serde.InternalSerde; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -40,9 +40,8 @@ public class ArangoExecutorSync extends ArangoExecutor { private final CommunicationProtocol protocol; - public ArangoExecutorSync(final CommunicationProtocol protocol, final InternalSerde util, - final QueueTimeMetricsImpl qtMetrics, final int timeoutMs) { - super(util, qtMetrics, timeoutMs); + public ArangoExecutorSync(final CommunicationProtocol protocol, final ArangoConfig config) { + super(config); this.protocol = protocol; } diff --git a/driver/src/main/java/com/arangodb/internal/ArangoGraphImpl.java b/core/src/main/java/com/arangodb/internal/ArangoGraphImpl.java similarity index 100% rename from driver/src/main/java/com/arangodb/internal/ArangoGraphImpl.java rename to core/src/main/java/com/arangodb/internal/ArangoGraphImpl.java diff --git a/driver/src/main/java/com/arangodb/internal/ArangoMetricsImpl.java b/core/src/main/java/com/arangodb/internal/ArangoMetricsImpl.java similarity index 100% rename from driver/src/main/java/com/arangodb/internal/ArangoMetricsImpl.java rename to core/src/main/java/com/arangodb/internal/ArangoMetricsImpl.java diff --git a/driver/src/main/java/com/arangodb/internal/ArangoRequestParam.java b/core/src/main/java/com/arangodb/internal/ArangoRequestParam.java similarity index 100% rename from driver/src/main/java/com/arangodb/internal/ArangoRequestParam.java rename to core/src/main/java/com/arangodb/internal/ArangoRequestParam.java diff --git a/driver/src/main/java/com/arangodb/internal/ArangoResponseField.java b/core/src/main/java/com/arangodb/internal/ArangoResponseField.java similarity index 100% rename from driver/src/main/java/com/arangodb/internal/ArangoResponseField.java rename to core/src/main/java/com/arangodb/internal/ArangoResponseField.java diff --git a/driver/src/main/java/com/arangodb/internal/ArangoSearchImpl.java b/core/src/main/java/com/arangodb/internal/ArangoSearchImpl.java similarity index 100% rename from driver/src/main/java/com/arangodb/internal/ArangoSearchImpl.java rename to core/src/main/java/com/arangodb/internal/ArangoSearchImpl.java diff --git a/driver/src/main/java/com/arangodb/internal/ArangoVertexCollectionImpl.java b/core/src/main/java/com/arangodb/internal/ArangoVertexCollectionImpl.java similarity index 100% rename from driver/src/main/java/com/arangodb/internal/ArangoVertexCollectionImpl.java rename to core/src/main/java/com/arangodb/internal/ArangoVertexCollectionImpl.java diff --git a/driver/src/main/java/com/arangodb/internal/ArangoViewImpl.java b/core/src/main/java/com/arangodb/internal/ArangoViewImpl.java similarity index 100% rename from driver/src/main/java/com/arangodb/internal/ArangoViewImpl.java rename to core/src/main/java/com/arangodb/internal/ArangoViewImpl.java diff --git a/driver/src/main/java/com/arangodb/internal/DocumentFields.java b/core/src/main/java/com/arangodb/internal/DocumentFields.java similarity index 100% rename from driver/src/main/java/com/arangodb/internal/DocumentFields.java rename to core/src/main/java/com/arangodb/internal/DocumentFields.java diff --git a/driver/src/main/java/com/arangodb/internal/InternalArangoCollection.java b/core/src/main/java/com/arangodb/internal/InternalArangoCollection.java similarity index 100% rename from driver/src/main/java/com/arangodb/internal/InternalArangoCollection.java rename to core/src/main/java/com/arangodb/internal/InternalArangoCollection.java diff --git a/driver/src/main/java/com/arangodb/internal/InternalArangoDB.java b/core/src/main/java/com/arangodb/internal/InternalArangoDB.java similarity index 100% rename from driver/src/main/java/com/arangodb/internal/InternalArangoDB.java rename to core/src/main/java/com/arangodb/internal/InternalArangoDB.java diff --git a/core/src/main/java/com/arangodb/internal/InternalArangoDBBuilder.java b/core/src/main/java/com/arangodb/internal/InternalArangoDBBuilder.java new file mode 100644 index 000000000..e482e405c --- /dev/null +++ b/core/src/main/java/com/arangodb/internal/InternalArangoDBBuilder.java @@ -0,0 +1,349 @@ +/* + * DISCLAIMER + * + * Copyright 2018 ArangoDB GmbH, Cologne, Germany + * + * Licensed 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. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.internal; + +import com.arangodb.ArangoDB; +import com.arangodb.ArangoDBException; +import com.arangodb.Protocol; +import com.arangodb.Request; +import com.arangodb.config.ArangoConfigProperties; +import com.arangodb.config.HostDescription; +import com.arangodb.entity.LoadBalancingStrategy; +import com.arangodb.internal.config.ArangoConfig; +import com.arangodb.internal.net.*; +import com.arangodb.internal.util.HostUtils; +import com.arangodb.serde.ArangoSerde; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.net.ssl.SSLContext; +import java.util.ArrayList; +import java.util.Collection; +import java.util.ServiceLoader; + + +/** + * @author Mark Vollmary + */ +public abstract class InternalArangoDBBuilder> { + private static final Logger LOG = LoggerFactory.getLogger(InternalArangoDBBuilder.class); + protected final ArangoConfig config = new ArangoConfig(); + + @SuppressWarnings("unchecked") + public T loadProperties(final ArangoConfigProperties properties) { + config.loadProperties(properties); + return (T) this; + } + + /** + * Adds a host to connect to. Multiple hosts can be added to provide fallbacks. + * + * @param host address of the host + * @param port port of the host + * @return {@link ArangoDB.Builder} + */ + @SuppressWarnings("unchecked") + public T host(final String host, final int port) { + config.addHost(new HostDescription(host, port)); + return (T) this; + } + + /** + * Sets the connection and request timeout in milliseconds. + * + * @param timeout timeout in milliseconds + * @return {@link ArangoDB.Builder} + */ + @SuppressWarnings("unchecked") + public T timeout(final Integer timeout) { + config.setTimeout(timeout); + return (T) this; + } + + /** + * Sets the username to use for authentication. + * + * @param user the user in the database (default: {@code root}) + * @return {@link ArangoDB.Builder} + */ + @SuppressWarnings("unchecked") + public T user(final String user) { + config.setUser(user); + return (T) this; + } + + /** + * Sets the password for the user for authentication. + * + * @param password the password of the user in the database (default: {@code null}) + * @return {@link ArangoDB.Builder} + */ + @SuppressWarnings("unchecked") + public T password(final String password) { + config.setPassword(password); + return (T) this; + } + + /** + * Sets the JWT for the user authentication. + * + * @param jwt token to use (default: {@code null}) + * @return {@link ArangoDB.Builder} + */ + @SuppressWarnings("unchecked") + public T jwt(final String jwt) { + config.setJwt(jwt); + return (T) this; + } + + /** + * If set to {@code true} SSL will be used when connecting to an ArangoDB server. + * + * @param useSsl whether or not use SSL (default: {@code false}) + * @return {@link ArangoDB.Builder} + */ + @SuppressWarnings("unchecked") + public T useSsl(final Boolean useSsl) { + config.setUseSsl(useSsl); + return (T) this; + } + + /** + * Sets the SSL context to be used when {@code true} is passed through {@link #useSsl(Boolean)}. + * + * @param sslContext SSL context to be used + * @return {@link ArangoDB.Builder} + */ + @SuppressWarnings("unchecked") + public T sslContext(final SSLContext sslContext) { + config.setSslContext(sslContext); + return (T) this; + } + + /** + * Set whether hostname verification is enabled + * + * @param verifyHost {@code true} if enabled + * @return {@link ArangoDB.Builder} + */ + @SuppressWarnings("unchecked") + public T verifyHost(final Boolean verifyHost) { + config.setVerifyHost(verifyHost); + return (T) this; + } + + /** + * Sets the chunk size when {@link Protocol#VST} is used. + * + * @param chunksize size of a chunk in bytes + * @return {@link ArangoDB.Builder} + */ + @SuppressWarnings("unchecked") + public T chunksize(final Integer chunksize) { + config.setChunkSize(chunksize); + return (T) this; + } + + /** + * Sets the maximum number of connections the built in connection pool will open per host. + * + *

    + * Defaults: + *

    + * + *
    +     * {@link Protocol#VST} == 1
    +     * {@link Protocol#HTTP_JSON} == 20
    +     * {@link Protocol#HTTP_VPACK} == 20
    +     * 
    + * + * @param maxConnections max number of connections + * @return {@link ArangoDB.Builder} + */ + @SuppressWarnings("unchecked") + public T maxConnections(final Integer maxConnections) { + config.setMaxConnections(maxConnections); + return (T) this; + } + + /** + * Set the maximum time to life of a connection. After this time the connection will be closed automatically. + * + * @param connectionTtl the maximum time to life of a connection in milliseconds + * @return {@link ArangoDB.Builder} + */ + @SuppressWarnings("unchecked") + public T connectionTtl(final Long connectionTtl) { + config.setConnectionTtl(connectionTtl); + return (T) this; + } + + /** + * Set the keep-alive interval for VST connections. If set, every VST connection will perform a no-op request + * every {@code keepAliveInterval} seconds, to avoid to be closed due to inactivity by the server (or by the + * external environment, eg. firewall, intermediate routers, operating system). + * + * @param keepAliveInterval interval in seconds + * @return {@link ArangoDB.Builder} + */ + @SuppressWarnings("unchecked") + public T keepAliveInterval(final Integer keepAliveInterval) { + config.setKeepAliveInterval(keepAliveInterval); + return (T) this; + } + + /** + * Whether or not the driver should acquire a list of available coordinators in an ArangoDB cluster or a single + * server with active failover. In case of Active-Failover deployment set to {@code true} to enable automatic + * master discovery. + * + *

    + * The host list will be used for failover and load balancing. + *

    + * + * @param acquireHostList whether or not automatically acquire a list of available hosts (default: false) + * @return {@link ArangoDB.Builder} + */ + @SuppressWarnings("unchecked") + public T acquireHostList(final Boolean acquireHostList) { + config.setAcquireHostList(acquireHostList); + return (T) this; + } + + /** + * Setting the Interval for acquireHostList + * + * @param acquireHostListInterval Interval in milliseconds + * @return {@link ArangoDB.Builder} + */ + @SuppressWarnings("unchecked") + public T acquireHostListInterval(final Integer acquireHostListInterval) { + config.setAcquireHostListInterval(acquireHostListInterval); + return (T) this; + } + + /** + * Sets the load balancing strategy to be used in an ArangoDB cluster setup. In case of Active-Failover + * deployment set to {@link LoadBalancingStrategy#NONE} or not set at all, since that would be the default. + * + * @param loadBalancingStrategy the load balancing strategy to be used (default: + * {@link LoadBalancingStrategy#NONE} + * @return {@link ArangoDB.Builder} + */ + @SuppressWarnings("unchecked") + public T loadBalancingStrategy(final LoadBalancingStrategy loadBalancingStrategy) { + config.setLoadBalancingStrategy(loadBalancingStrategy); + return (T) this; + } + + /** + * Setting the amount of samples kept for queue time metrics + * + * @param responseQueueTimeSamples amount of samples to keep + * @return {@link ArangoDB.Builder} + */ + @SuppressWarnings("unchecked") + public T responseQueueTimeSamples(final Integer responseQueueTimeSamples) { + config.setResponseQueueTimeSamples(responseQueueTimeSamples); + return (T) this; + } + + /** + * Sets the serde for the user data. + * This is used to serialize and deserialize all the data payload such as: + * - documents, vertexes, edges + * - AQL bind vars + * - body payload of requests and responses in {@link ArangoDB#execute(Request, Class)} + *

    + * However, note that the following types will always be serialized and deserialized using the internal serde: + * - {@link com.fasterxml.jackson.databind.JsonNode} + * - {@link com.arangodb.util.RawJson} + * - {@link com.arangodb.util.RawBytes} + * - {@link com.arangodb.entity.BaseDocument} + * - {@link com.arangodb.entity.BaseEdgeDocument} + * + * @param serde custom serde for the user data + * @return {@link ArangoDB.Builder} + */ + @SuppressWarnings("unchecked") + public T serde(final ArangoSerde serde) { + config.setUserDataSerde(serde); + return (T) this; + } + + protected ProtocolProvider protocolProvider(Protocol protocol) { + ServiceLoader loader = ServiceLoader.load(ProtocolProvider.class); + for (ProtocolProvider p : loader) { + if (p.supportsProtocol(protocol)) { + return p; + } + } + throw new ArangoDBException("No ProtocolProvider found for protocol: " + protocol); + } + + protected HostHandler createHostHandler(final HostResolver hostResolver) { + + final HostHandler hostHandler; + + LoadBalancingStrategy loadBalancingStrategy = config.getLoadBalancingStrategy(); + if (loadBalancingStrategy != null) { + switch (loadBalancingStrategy) { + case ONE_RANDOM: + hostHandler = new RandomHostHandler(hostResolver, new FallbackHostHandler(hostResolver)); + break; + case ROUND_ROBIN: + hostHandler = new RoundRobinHostHandler(hostResolver); + break; + case NONE: + default: + hostHandler = new FallbackHostHandler(hostResolver); + break; + } + } else { + hostHandler = new FallbackHostHandler(hostResolver); + } + + LOG.debug("HostHandler is {}", hostHandler.getClass().getSimpleName()); + + return new DirtyReadHostHandler(hostHandler, new RoundRobinHostHandler(hostResolver)); + } + + protected HostResolver createHostResolver(final Collection hosts, final ConnectionFactory connectionFactory) { + Boolean acquireHostList = config.getAcquireHostList(); + if (acquireHostList != null && acquireHostList) { + LOG.debug("acquireHostList -> Use ExtendedHostResolver"); + return new ExtendedHostResolver(new ArrayList<>(hosts), config, connectionFactory, + config.getAcquireHostListInterval()); + } else { + LOG.debug("Use SimpleHostResolver"); + return new SimpleHostResolver(new ArrayList<>(hosts)); + } + + } + + protected Collection createHostList(final ConnectionFactory connectionFactory) { + final Collection hostList = new ArrayList<>(); + for (final HostDescription host : config.getHosts()) { + hostList.add(HostUtils.createHost(host, config, connectionFactory)); + } + return hostList; + } +} diff --git a/driver/src/main/java/com/arangodb/internal/InternalArangoDatabase.java b/core/src/main/java/com/arangodb/internal/InternalArangoDatabase.java similarity index 100% rename from driver/src/main/java/com/arangodb/internal/InternalArangoDatabase.java rename to core/src/main/java/com/arangodb/internal/InternalArangoDatabase.java diff --git a/driver/src/main/java/com/arangodb/internal/InternalArangoEdgeCollection.java b/core/src/main/java/com/arangodb/internal/InternalArangoEdgeCollection.java similarity index 100% rename from driver/src/main/java/com/arangodb/internal/InternalArangoEdgeCollection.java rename to core/src/main/java/com/arangodb/internal/InternalArangoEdgeCollection.java diff --git a/driver/src/main/java/com/arangodb/internal/InternalArangoGraph.java b/core/src/main/java/com/arangodb/internal/InternalArangoGraph.java similarity index 100% rename from driver/src/main/java/com/arangodb/internal/InternalArangoGraph.java rename to core/src/main/java/com/arangodb/internal/InternalArangoGraph.java diff --git a/driver/src/main/java/com/arangodb/internal/InternalArangoRoute.java b/core/src/main/java/com/arangodb/internal/InternalArangoRoute.java similarity index 100% rename from driver/src/main/java/com/arangodb/internal/InternalArangoRoute.java rename to core/src/main/java/com/arangodb/internal/InternalArangoRoute.java diff --git a/driver/src/main/java/com/arangodb/internal/InternalArangoSearch.java b/core/src/main/java/com/arangodb/internal/InternalArangoSearch.java similarity index 100% rename from driver/src/main/java/com/arangodb/internal/InternalArangoSearch.java rename to core/src/main/java/com/arangodb/internal/InternalArangoSearch.java diff --git a/driver/src/main/java/com/arangodb/internal/InternalArangoVertexCollection.java b/core/src/main/java/com/arangodb/internal/InternalArangoVertexCollection.java similarity index 100% rename from driver/src/main/java/com/arangodb/internal/InternalArangoVertexCollection.java rename to core/src/main/java/com/arangodb/internal/InternalArangoVertexCollection.java diff --git a/driver/src/main/java/com/arangodb/internal/InternalArangoView.java b/core/src/main/java/com/arangodb/internal/InternalArangoView.java similarity index 100% rename from driver/src/main/java/com/arangodb/internal/InternalArangoView.java rename to core/src/main/java/com/arangodb/internal/InternalArangoView.java diff --git a/driver/src/main/java/com/arangodb/internal/InternalRequest.java b/core/src/main/java/com/arangodb/internal/InternalRequest.java similarity index 100% rename from driver/src/main/java/com/arangodb/internal/InternalRequest.java rename to core/src/main/java/com/arangodb/internal/InternalRequest.java diff --git a/driver/src/main/java/com/arangodb/internal/InternalResponse.java b/core/src/main/java/com/arangodb/internal/InternalResponse.java similarity index 100% rename from driver/src/main/java/com/arangodb/internal/InternalResponse.java rename to core/src/main/java/com/arangodb/internal/InternalResponse.java diff --git a/driver/src/main/java/com/arangodb/internal/InternalSearchAlias.java b/core/src/main/java/com/arangodb/internal/InternalSearchAlias.java similarity index 100% rename from driver/src/main/java/com/arangodb/internal/InternalSearchAlias.java rename to core/src/main/java/com/arangodb/internal/InternalSearchAlias.java diff --git a/driver/src/main/java/com/arangodb/internal/QueueTimeMetricsImpl.java b/core/src/main/java/com/arangodb/internal/QueueTimeMetricsImpl.java similarity index 100% rename from driver/src/main/java/com/arangodb/internal/QueueTimeMetricsImpl.java rename to core/src/main/java/com/arangodb/internal/QueueTimeMetricsImpl.java diff --git a/driver/src/main/java/com/arangodb/internal/RequestType.java b/core/src/main/java/com/arangodb/internal/RequestType.java similarity index 100% rename from driver/src/main/java/com/arangodb/internal/RequestType.java rename to core/src/main/java/com/arangodb/internal/RequestType.java diff --git a/driver/src/main/java/com/arangodb/internal/SearchAliasImpl.java b/core/src/main/java/com/arangodb/internal/SearchAliasImpl.java similarity index 100% rename from driver/src/main/java/com/arangodb/internal/SearchAliasImpl.java rename to core/src/main/java/com/arangodb/internal/SearchAliasImpl.java diff --git a/core/src/main/java/com/arangodb/internal/config/ArangoConfig.java b/core/src/main/java/com/arangodb/internal/config/ArangoConfig.java new file mode 100644 index 000000000..987200ad6 --- /dev/null +++ b/core/src/main/java/com/arangodb/internal/config/ArangoConfig.java @@ -0,0 +1,275 @@ +package com.arangodb.internal.config; + +import com.arangodb.ArangoDBException; +import com.arangodb.Protocol; +import com.arangodb.config.ArangoConfigProperties; +import com.arangodb.config.HostDescription; +import com.arangodb.entity.LoadBalancingStrategy; +import com.arangodb.internal.ArangoDefaults; +import com.arangodb.internal.serde.ContentTypeFactory; +import com.arangodb.internal.serde.InternalSerde; +import com.arangodb.internal.serde.InternalSerdeProvider; +import com.arangodb.serde.ArangoSerde; +import com.arangodb.serde.ArangoSerdeProvider; +import com.fasterxml.jackson.databind.Module; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.net.ssl.SSLContext; +import java.util.*; +import java.util.stream.Collectors; + +public class ArangoConfig { + private final List hosts = new ArrayList<>(); + private Protocol protocol; + private Integer timeout; + private String user; + private String password; + private String jwt; + private Boolean useSsl; + private SSLContext sslContext; + private Boolean verifyHost; + private Integer chunkSize; + private Integer maxConnections; + private Long connectionTtl; + private Integer keepAliveInterval; + private Boolean acquireHostList; + private Integer acquireHostListInterval; + private LoadBalancingStrategy loadBalancingStrategy; + private InternalSerde internalSerde; + private ArangoSerde userDataSerde; + private Integer responseQueueTimeSamples; + private Module protocolModule; + + private static final Logger LOG = LoggerFactory.getLogger(ArangoConfig.class); + + private static ArangoSerdeProvider serdeProvider() { + ServiceLoader loader = ServiceLoader.load(ArangoSerdeProvider.class); + Iterator it = loader.iterator(); + ArangoSerdeProvider serdeProvider; + if (!it.hasNext()) { + LOG.warn("No ArangoSerdeProvider found, using InternalSerdeProvider. Please consider registering a custom " + + "ArangoSerdeProvider to avoid depending on internal classes which are not part of the public API."); + serdeProvider = new InternalSerdeProvider(); + } else { + serdeProvider = it.next(); + if (it.hasNext()) { + throw new ArangoDBException("Found multiple serde providers! Please set explicitly the one to use."); + } + } + return serdeProvider; + } + + public ArangoConfig() { + // load default properties + loadProperties(new ArangoConfigProperties() { + }); + } + + public void loadProperties(final ArangoConfigProperties properties) { + hosts.addAll(properties.getHosts().orElse(ArangoDefaults.DEFAULT_HOSTS).stream() + .map(it -> new HostDescription(it.getHost(), it.getPort())) + .collect(Collectors.toList())); + protocol = properties.getProtocol().orElse(ArangoDefaults.DEFAULT_PROTOCOL); + timeout = properties.getTimeout().orElse(ArangoDefaults.DEFAULT_TIMEOUT); + user = properties.getUser().orElse(ArangoDefaults.DEFAULT_USER); + // FIXME: make password field Optional + password = properties.getPassword().orElse(null); + // FIXME: make jwt field Optional + jwt = properties.getJwt().orElse(null); + useSsl = properties.getUseSsl().orElse(ArangoDefaults.DEFAULT_USE_SSL); + verifyHost = properties.getVerifyHost().orElse(ArangoDefaults.DEFAULT_VERIFY_HOST); + chunkSize = properties.getChunkSize().orElse(ArangoDefaults.DEFAULT_CHUNK_SIZE); + // FIXME: make maxConnections field Optional + maxConnections = properties.getMaxConnections().orElse(null); + // FIXME: make connectionTtl field Optional + connectionTtl = properties.getConnectionTtl().orElse(null); + // FIXME: make keepAliveInterval field Optional + keepAliveInterval = properties.getKeepAliveInterval().orElse(null); + acquireHostList = properties.getAcquireHostList().orElse(ArangoDefaults.DEFAULT_ACQUIRE_HOST_LIST); + acquireHostListInterval = properties.getAcquireHostListInterval().orElse(ArangoDefaults.DEFAULT_ACQUIRE_HOST_LIST_INTERVAL); + loadBalancingStrategy = properties.getLoadBalancingStrategy().orElse(ArangoDefaults.DEFAULT_LOAD_BALANCING_STRATEGY); + responseQueueTimeSamples = properties.getResponseQueueTimeSamples().orElse(ArangoDefaults.DEFAULT_RESPONSE_QUEUE_TIME_SAMPLES); + } + + public List getHosts() { + return hosts; + } + + public void addHost(HostDescription hostDescription) { + hosts.add(hostDescription); + } + + public Protocol getProtocol() { + return protocol; + } + + public void setProtocol(Protocol protocol) { + this.protocol = protocol; + } + + public Integer getTimeout() { + return timeout; + } + + public void setTimeout(Integer timeout) { + this.timeout = timeout; + } + + public String getUser() { + return user; + } + + public void setUser(String user) { + this.user = user; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + public String getJwt() { + return jwt; + } + + public void setJwt(String jwt) { + this.jwt = jwt; + } + + public Boolean getUseSsl() { + return useSsl; + } + + public void setUseSsl(Boolean useSsl) { + this.useSsl = useSsl; + } + + public SSLContext getSslContext() { + return sslContext; + } + + public void setSslContext(SSLContext sslContext) { + this.sslContext = sslContext; + } + + public Boolean getVerifyHost() { + return verifyHost; + } + + public void setVerifyHost(Boolean verifyHost) { + this.verifyHost = verifyHost; + } + + public Integer getChunkSize() { + return chunkSize; + } + + public void setChunkSize(Integer chunkSize) { + this.chunkSize = chunkSize; + } + + public Integer getMaxConnections() { + if (maxConnections == null) { + maxConnections = getDefaultMaxConnections(); + } + return maxConnections; + } + + private int getDefaultMaxConnections() { + int defaultMaxConnections; + switch (getProtocol()) { + case VST: + defaultMaxConnections = ArangoDefaults.MAX_CONNECTIONS_VST_DEFAULT; + break; + case HTTP_JSON: + case HTTP_VPACK: + defaultMaxConnections = ArangoDefaults.MAX_CONNECTIONS_HTTP_DEFAULT; + break; + case HTTP2_JSON: + case HTTP2_VPACK: + defaultMaxConnections = ArangoDefaults.MAX_CONNECTIONS_HTTP2_DEFAULT; + break; + default: + throw new IllegalArgumentException(); + } + return defaultMaxConnections; + } + + public void setMaxConnections(Integer maxConnections) { + this.maxConnections = maxConnections; + } + + public Long getConnectionTtl() { + return connectionTtl; + } + + public void setConnectionTtl(Long connectionTtl) { + this.connectionTtl = connectionTtl; + } + + public Integer getKeepAliveInterval() { + return keepAliveInterval; + } + + public void setKeepAliveInterval(Integer keepAliveInterval) { + this.keepAliveInterval = keepAliveInterval; + } + + public Boolean getAcquireHostList() { + return acquireHostList; + } + + public void setAcquireHostList(Boolean acquireHostList) { + this.acquireHostList = acquireHostList; + } + + public Integer getAcquireHostListInterval() { + return acquireHostListInterval; + } + + public void setAcquireHostListInterval(Integer acquireHostListInterval) { + this.acquireHostListInterval = acquireHostListInterval; + } + + public LoadBalancingStrategy getLoadBalancingStrategy() { + return loadBalancingStrategy; + } + + public void setLoadBalancingStrategy(LoadBalancingStrategy loadBalancingStrategy) { + this.loadBalancingStrategy = loadBalancingStrategy; + } + + public ArangoSerde getUserDataSerde() { + if (userDataSerde == null) { + userDataSerde = serdeProvider().of(ContentTypeFactory.of(getProtocol())); + } + return userDataSerde; + } + + public InternalSerde getInternalSerde() { + if (internalSerde == null) { + internalSerde = InternalSerdeProvider.create(ContentTypeFactory.of(getProtocol()), getUserDataSerde(), protocolModule); + } + return internalSerde; + } + + public void setUserDataSerde(ArangoSerde userDataSerde) { + this.userDataSerde = userDataSerde; + } + + public Integer getResponseQueueTimeSamples() { + return responseQueueTimeSamples; + } + + public void setResponseQueueTimeSamples(Integer responseQueueTimeSamples) { + this.responseQueueTimeSamples = responseQueueTimeSamples; + } + + public void setProtocolModule(Module m) { + protocolModule = m; + } +} diff --git a/driver/src/main/java/com/arangodb/internal/config/ArangoConfigPropertiesImpl.java b/core/src/main/java/com/arangodb/internal/config/ArangoConfigPropertiesImpl.java similarity index 100% rename from driver/src/main/java/com/arangodb/internal/config/ArangoConfigPropertiesImpl.java rename to core/src/main/java/com/arangodb/internal/config/ArangoConfigPropertiesImpl.java diff --git a/driver/src/main/java/com/arangodb/internal/cursor/AbstractArangoIterable.java b/core/src/main/java/com/arangodb/internal/cursor/AbstractArangoIterable.java similarity index 100% rename from driver/src/main/java/com/arangodb/internal/cursor/AbstractArangoIterable.java rename to core/src/main/java/com/arangodb/internal/cursor/AbstractArangoIterable.java diff --git a/driver/src/main/java/com/arangodb/internal/cursor/ArangoCursorImpl.java b/core/src/main/java/com/arangodb/internal/cursor/ArangoCursorImpl.java similarity index 100% rename from driver/src/main/java/com/arangodb/internal/cursor/ArangoCursorImpl.java rename to core/src/main/java/com/arangodb/internal/cursor/ArangoCursorImpl.java diff --git a/driver/src/main/java/com/arangodb/internal/cursor/ArangoCursorIterator.java b/core/src/main/java/com/arangodb/internal/cursor/ArangoCursorIterator.java similarity index 100% rename from driver/src/main/java/com/arangodb/internal/cursor/ArangoCursorIterator.java rename to core/src/main/java/com/arangodb/internal/cursor/ArangoCursorIterator.java diff --git a/driver/src/main/java/com/arangodb/internal/cursor/entity/InternalCursorEntity.java b/core/src/main/java/com/arangodb/internal/cursor/entity/InternalCursorEntity.java similarity index 100% rename from driver/src/main/java/com/arangodb/internal/cursor/entity/InternalCursorEntity.java rename to core/src/main/java/com/arangodb/internal/cursor/entity/InternalCursorEntity.java diff --git a/driver/src/main/java/com/arangodb/internal/net/AccessType.java b/core/src/main/java/com/arangodb/internal/net/AccessType.java similarity index 100% rename from driver/src/main/java/com/arangodb/internal/net/AccessType.java rename to core/src/main/java/com/arangodb/internal/net/AccessType.java diff --git a/driver/src/main/java/com/arangodb/internal/net/ArangoDBRedirectException.java b/core/src/main/java/com/arangodb/internal/net/ArangoDBRedirectException.java similarity index 100% rename from driver/src/main/java/com/arangodb/internal/net/ArangoDBRedirectException.java rename to core/src/main/java/com/arangodb/internal/net/ArangoDBRedirectException.java diff --git a/core/src/main/java/com/arangodb/internal/net/AsyncCommunication.java b/core/src/main/java/com/arangodb/internal/net/AsyncCommunication.java new file mode 100644 index 000000000..abb630780 --- /dev/null +++ b/core/src/main/java/com/arangodb/internal/net/AsyncCommunication.java @@ -0,0 +1,14 @@ +package com.arangodb.internal.net; + +import com.arangodb.internal.InternalRequest; +import com.arangodb.internal.InternalResponse; + +import java.io.Closeable; +import java.util.concurrent.CompletableFuture; + +public interface AsyncCommunication extends Closeable { + + CompletableFuture execute(final InternalRequest request, final HostHandle hostHandle); + void setJwt(String jwt); + +} diff --git a/core/src/main/java/com/arangodb/internal/net/AsyncProtocolProvider.java b/core/src/main/java/com/arangodb/internal/net/AsyncProtocolProvider.java new file mode 100644 index 000000000..d77a8e2a9 --- /dev/null +++ b/core/src/main/java/com/arangodb/internal/net/AsyncProtocolProvider.java @@ -0,0 +1,18 @@ +package com.arangodb.internal.net; + + +import com.arangodb.Protocol; +import com.arangodb.internal.config.ArangoConfig; +import com.fasterxml.jackson.databind.Module; + +public interface AsyncProtocolProvider { + + boolean supportsProtocol(Protocol protocol); + + ConnectionFactory createConnectionFactory(); + + AsyncCommunication createCommunication(ArangoConfig config, HostHandler hostHandler); + + Module protocolModule(); + +} diff --git a/driver/src/main/java/com/arangodb/internal/net/CommunicationProtocol.java b/core/src/main/java/com/arangodb/internal/net/CommunicationProtocol.java similarity index 100% rename from driver/src/main/java/com/arangodb/internal/net/CommunicationProtocol.java rename to core/src/main/java/com/arangodb/internal/net/CommunicationProtocol.java diff --git a/driver/src/main/java/com/arangodb/internal/net/Connection.java b/core/src/main/java/com/arangodb/internal/net/Connection.java similarity index 100% rename from driver/src/main/java/com/arangodb/internal/net/Connection.java rename to core/src/main/java/com/arangodb/internal/net/Connection.java diff --git a/driver/src/main/java/com/arangodb/internal/net/ConnectionFactory.java b/core/src/main/java/com/arangodb/internal/net/ConnectionFactory.java similarity index 87% rename from driver/src/main/java/com/arangodb/internal/net/ConnectionFactory.java rename to core/src/main/java/com/arangodb/internal/net/ConnectionFactory.java index 65c83fc15..ed3d5571c 100644 --- a/driver/src/main/java/com/arangodb/internal/net/ConnectionFactory.java +++ b/core/src/main/java/com/arangodb/internal/net/ConnectionFactory.java @@ -21,12 +21,11 @@ package com.arangodb.internal.net; import com.arangodb.config.HostDescription; +import com.arangodb.internal.config.ArangoConfig; /** * @author Mark Vollmary */ public interface ConnectionFactory { - - Connection create(final HostDescription host); - + Connection create(ArangoConfig config, HostDescription host); } diff --git a/driver/src/main/java/com/arangodb/internal/net/ConnectionPool.java b/core/src/main/java/com/arangodb/internal/net/ConnectionPool.java similarity index 100% rename from driver/src/main/java/com/arangodb/internal/net/ConnectionPool.java rename to core/src/main/java/com/arangodb/internal/net/ConnectionPool.java diff --git a/driver/src/main/java/com/arangodb/internal/net/ConnectionPoolImpl.java b/core/src/main/java/com/arangodb/internal/net/ConnectionPoolImpl.java similarity index 81% rename from driver/src/main/java/com/arangodb/internal/net/ConnectionPoolImpl.java rename to core/src/main/java/com/arangodb/internal/net/ConnectionPoolImpl.java index b393ae421..0de7d3474 100644 --- a/driver/src/main/java/com/arangodb/internal/net/ConnectionPoolImpl.java +++ b/core/src/main/java/com/arangodb/internal/net/ConnectionPoolImpl.java @@ -22,11 +22,7 @@ import com.arangodb.ArangoDBException; import com.arangodb.config.HostDescription; -import com.arangodb.internal.velocystream.internal.VstConnection; -import com.arangodb.internal.velocystream.internal.VstConnectionSync; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - +import com.arangodb.internal.config.ArangoConfig; import java.io.IOException; import java.util.ArrayList; import java.util.List; @@ -36,9 +32,8 @@ */ public class ConnectionPoolImpl implements ConnectionPool { - private static final Logger LOGGER = LoggerFactory.getLogger(ConnectionPoolImpl.class); - private final HostDescription host; + private final ArangoConfig config; private final int maxConnections; private final List connections; private final ConnectionFactory factory; @@ -46,11 +41,11 @@ public class ConnectionPoolImpl implements ConnectionPool { private volatile String jwt = null; private boolean closed = false; - public ConnectionPoolImpl(final HostDescription host, final Integer maxConnections, - final ConnectionFactory factory) { + public ConnectionPoolImpl(final HostDescription host, final ArangoConfig config, final ConnectionFactory factory) { super(); this.host = host; - this.maxConnections = maxConnections; + this.config = config; + this.maxConnections = config.getMaxConnections(); this.factory = factory; connections = new ArrayList<>(); current = 0; @@ -58,7 +53,7 @@ public ConnectionPoolImpl(final HostDescription host, final Integer maxConnectio @Override public Connection createConnection(final HostDescription host) { - Connection c = factory.create(host); + Connection c = factory.create(config, host); c.setJwt(jwt); return c; } @@ -80,10 +75,6 @@ public synchronized Connection connection() { connection = connections.get(index); } - if (connection instanceof VstConnectionSync) { - LOGGER.debug("Return Connection {}", ((VstConnection) connection).getConnectionName()); - } - return connection; } diff --git a/driver/src/main/java/com/arangodb/internal/net/DirtyReadHostHandler.java b/core/src/main/java/com/arangodb/internal/net/DirtyReadHostHandler.java similarity index 100% rename from driver/src/main/java/com/arangodb/internal/net/DirtyReadHostHandler.java rename to core/src/main/java/com/arangodb/internal/net/DirtyReadHostHandler.java diff --git a/driver/src/main/java/com/arangodb/internal/net/ExtendedHostResolver.java b/core/src/main/java/com/arangodb/internal/net/ExtendedHostResolver.java similarity index 95% rename from driver/src/main/java/com/arangodb/internal/net/ExtendedHostResolver.java rename to core/src/main/java/com/arangodb/internal/net/ExtendedHostResolver.java index ade06a47e..ad2c3c915 100644 --- a/driver/src/main/java/com/arangodb/internal/net/ExtendedHostResolver.java +++ b/core/src/main/java/com/arangodb/internal/net/ExtendedHostResolver.java @@ -24,6 +24,7 @@ import com.arangodb.DbName; import com.arangodb.config.HostDescription; import com.arangodb.internal.ArangoExecutorSync; +import com.arangodb.internal.config.ArangoConfig; import com.arangodb.internal.serde.InternalSerde; import com.arangodb.internal.util.HostUtils; import com.arangodb.internal.InternalRequest; @@ -44,7 +45,7 @@ public class ExtendedHostResolver implements HostResolver { private final HostSet hosts; - private final Integer maxConnections; + private final ArangoConfig config; private final ConnectionFactory connectionFactory; private final Integer acquireHostListInterval; private long lastUpdate; @@ -52,12 +53,12 @@ public class ExtendedHostResolver implements HostResolver { private InternalSerde arangoSerialization; - public ExtendedHostResolver(final List hosts, final Integer maxConnections, + public ExtendedHostResolver(final List hosts, final ArangoConfig config, final ConnectionFactory connectionFactory, Integer acquireHostListInterval) { this.acquireHostListInterval = acquireHostListInterval; this.hosts = new HostSet(hosts); - this.maxConnections = maxConnections; + this.config = config; this.connectionFactory = connectionFactory; lastUpdate = 0; @@ -94,12 +95,12 @@ public HostSet resolve(boolean initial, boolean closeConnections) { final String[] s = endpoint.replaceAll(".*://", "").split(":"); if (s.length == 2) { final HostDescription description = new HostDescription(s[0], Integer.parseInt(s[1])); - hosts.addHost(HostUtils.createHost(description, maxConnections, connectionFactory)); + hosts.addHost(HostUtils.createHost(description, config, connectionFactory)); } else if (s.length == 4) { // IPV6 Address - TODO: we need a proper function to resolve AND support IPV4 & IPV6 functions // globally final HostDescription description = new HostDescription("127.0.0.1", Integer.parseInt(s[3])); - hosts.addHost(HostUtils.createHost(description, maxConnections, connectionFactory)); + hosts.addHost(HostUtils.createHost(description, config, connectionFactory)); } else { LOGGER.warn("Skip Endpoint (Missing Port) {}", endpoint); } diff --git a/driver/src/main/java/com/arangodb/internal/net/FallbackHostHandler.java b/core/src/main/java/com/arangodb/internal/net/FallbackHostHandler.java similarity index 100% rename from driver/src/main/java/com/arangodb/internal/net/FallbackHostHandler.java rename to core/src/main/java/com/arangodb/internal/net/FallbackHostHandler.java diff --git a/driver/src/main/java/com/arangodb/internal/net/Host.java b/core/src/main/java/com/arangodb/internal/net/Host.java similarity index 100% rename from driver/src/main/java/com/arangodb/internal/net/Host.java rename to core/src/main/java/com/arangodb/internal/net/Host.java diff --git a/driver/src/main/java/com/arangodb/internal/net/HostHandle.java b/core/src/main/java/com/arangodb/internal/net/HostHandle.java similarity index 100% rename from driver/src/main/java/com/arangodb/internal/net/HostHandle.java rename to core/src/main/java/com/arangodb/internal/net/HostHandle.java diff --git a/driver/src/main/java/com/arangodb/internal/net/HostHandler.java b/core/src/main/java/com/arangodb/internal/net/HostHandler.java similarity index 100% rename from driver/src/main/java/com/arangodb/internal/net/HostHandler.java rename to core/src/main/java/com/arangodb/internal/net/HostHandler.java diff --git a/driver/src/main/java/com/arangodb/internal/net/HostImpl.java b/core/src/main/java/com/arangodb/internal/net/HostImpl.java similarity index 100% rename from driver/src/main/java/com/arangodb/internal/net/HostImpl.java rename to core/src/main/java/com/arangodb/internal/net/HostImpl.java diff --git a/driver/src/main/java/com/arangodb/internal/net/HostResolver.java b/core/src/main/java/com/arangodb/internal/net/HostResolver.java similarity index 100% rename from driver/src/main/java/com/arangodb/internal/net/HostResolver.java rename to core/src/main/java/com/arangodb/internal/net/HostResolver.java diff --git a/driver/src/main/java/com/arangodb/internal/net/HostSet.java b/core/src/main/java/com/arangodb/internal/net/HostSet.java similarity index 100% rename from driver/src/main/java/com/arangodb/internal/net/HostSet.java rename to core/src/main/java/com/arangodb/internal/net/HostSet.java diff --git a/core/src/main/java/com/arangodb/internal/net/ProtocolProvider.java b/core/src/main/java/com/arangodb/internal/net/ProtocolProvider.java new file mode 100644 index 000000000..583740938 --- /dev/null +++ b/core/src/main/java/com/arangodb/internal/net/ProtocolProvider.java @@ -0,0 +1,17 @@ +package com.arangodb.internal.net; + + +import com.arangodb.Protocol; +import com.arangodb.internal.config.ArangoConfig; +import com.fasterxml.jackson.databind.Module; + +public interface ProtocolProvider { + + boolean supportsProtocol(Protocol protocol); + + ConnectionFactory createConnectionFactory(); + + CommunicationProtocol createProtocol(ArangoConfig config, HostHandler hostHandler); + + Module protocolModule(); +} diff --git a/driver/src/main/java/com/arangodb/internal/net/RandomHostHandler.java b/core/src/main/java/com/arangodb/internal/net/RandomHostHandler.java similarity index 100% rename from driver/src/main/java/com/arangodb/internal/net/RandomHostHandler.java rename to core/src/main/java/com/arangodb/internal/net/RandomHostHandler.java diff --git a/driver/src/main/java/com/arangodb/internal/net/RoundRobinHostHandler.java b/core/src/main/java/com/arangodb/internal/net/RoundRobinHostHandler.java similarity index 100% rename from driver/src/main/java/com/arangodb/internal/net/RoundRobinHostHandler.java rename to core/src/main/java/com/arangodb/internal/net/RoundRobinHostHandler.java diff --git a/driver/src/main/java/com/arangodb/internal/net/SimpleHostResolver.java b/core/src/main/java/com/arangodb/internal/net/SimpleHostResolver.java similarity index 100% rename from driver/src/main/java/com/arangodb/internal/net/SimpleHostResolver.java rename to core/src/main/java/com/arangodb/internal/net/SimpleHostResolver.java diff --git a/driver/src/main/java/com/arangodb/internal/serde/ContentTypeFactory.java b/core/src/main/java/com/arangodb/internal/serde/ContentTypeFactory.java similarity index 100% rename from driver/src/main/java/com/arangodb/internal/serde/ContentTypeFactory.java rename to core/src/main/java/com/arangodb/internal/serde/ContentTypeFactory.java diff --git a/driver/src/main/java/com/arangodb/internal/serde/InternalAnnotationIntrospector.java b/core/src/main/java/com/arangodb/internal/serde/InternalAnnotationIntrospector.java similarity index 100% rename from driver/src/main/java/com/arangodb/internal/serde/InternalAnnotationIntrospector.java rename to core/src/main/java/com/arangodb/internal/serde/InternalAnnotationIntrospector.java diff --git a/driver/src/main/java/com/arangodb/internal/serde/InternalDeserializers.java b/core/src/main/java/com/arangodb/internal/serde/InternalDeserializers.java similarity index 100% rename from driver/src/main/java/com/arangodb/internal/serde/InternalDeserializers.java rename to core/src/main/java/com/arangodb/internal/serde/InternalDeserializers.java diff --git a/core/src/main/java/com/arangodb/internal/serde/InternalMapperProvider.java b/core/src/main/java/com/arangodb/internal/serde/InternalMapperProvider.java new file mode 100644 index 000000000..241e0893d --- /dev/null +++ b/core/src/main/java/com/arangodb/internal/serde/InternalMapperProvider.java @@ -0,0 +1,31 @@ +package com.arangodb.internal.serde; + +import com.arangodb.ArangoDBException; +import com.arangodb.ContentType; +import com.fasterxml.jackson.core.JsonFactory; +import com.fasterxml.jackson.databind.ObjectMapper; + +import java.util.ServiceLoader; +import java.util.function.Supplier; + +public interface InternalMapperProvider extends Supplier { + static ObjectMapper of(final ContentType contentType) { + String formatName; + if (contentType == ContentType.JSON) { + formatName = "JSON"; + } else if (contentType == ContentType.VPACK) { + formatName = "Velocypack"; + } else { + throw new IllegalArgumentException("Unexpected value: " + contentType); + } + + ServiceLoader sl = ServiceLoader.load(JsonFactory.class); + for (JsonFactory jf : sl) { + if(formatName.equals(jf.getFormatName())){ + return new ObjectMapper(jf); + } + } + + throw new ArangoDBException("No JsonFactory found for content type: " + contentType); + } +} diff --git a/driver/src/main/java/com/arangodb/internal/serde/InternalModule.java b/core/src/main/java/com/arangodb/internal/serde/InternalModule.java similarity index 83% rename from driver/src/main/java/com/arangodb/internal/serde/InternalModule.java rename to core/src/main/java/com/arangodb/internal/serde/InternalModule.java index 40943086f..3aeae3c24 100644 --- a/driver/src/main/java/com/arangodb/internal/serde/InternalModule.java +++ b/core/src/main/java/com/arangodb/internal/serde/InternalModule.java @@ -4,8 +4,6 @@ import com.arangodb.entity.CollectionType; import com.arangodb.entity.InvertedIndexPrimarySort; import com.arangodb.entity.ReplicationFactor; -import com.arangodb.internal.velocystream.internal.AuthenticationRequest; -import com.arangodb.internal.velocystream.internal.JwtAuthenticationRequest; import com.arangodb.util.RawBytes; import com.arangodb.util.RawJson; import com.arangodb.internal.InternalRequest; @@ -25,8 +23,6 @@ enum InternalModule implements Supplier { module.addSerializer(RawJson.class, InternalSerializers.RAW_JSON_SERIALIZER); module.addSerializer(RawBytes.class, InternalSerializers.RAW_BYTES_SERIALIZER); - module.addSerializer(AuthenticationRequest.class, InternalSerializers.AUTHENTICATION_REQUEST); - module.addSerializer(JwtAuthenticationRequest.class, InternalSerializers.JWT_AUTHENTICATION_REQUEST); module.addSerializer(InternalRequest.class, InternalSerializers.REQUEST); module.addSerializer(CollectionType.class, InternalSerializers.COLLECTION_TYPE); diff --git a/driver/src/main/java/com/arangodb/internal/serde/InternalParameterizedType.java b/core/src/main/java/com/arangodb/internal/serde/InternalParameterizedType.java similarity index 100% rename from driver/src/main/java/com/arangodb/internal/serde/InternalParameterizedType.java rename to core/src/main/java/com/arangodb/internal/serde/InternalParameterizedType.java diff --git a/driver/src/main/java/com/arangodb/internal/serde/InternalSerde.java b/core/src/main/java/com/arangodb/internal/serde/InternalSerde.java similarity index 100% rename from driver/src/main/java/com/arangodb/internal/serde/InternalSerde.java rename to core/src/main/java/com/arangodb/internal/serde/InternalSerde.java diff --git a/driver/src/main/java/com/arangodb/internal/serde/InternalSerdeImpl.java b/core/src/main/java/com/arangodb/internal/serde/InternalSerdeImpl.java similarity index 96% rename from driver/src/main/java/com/arangodb/internal/serde/InternalSerdeImpl.java rename to core/src/main/java/com/arangodb/internal/serde/InternalSerdeImpl.java index 12a2dc40c..a7de05b20 100644 --- a/driver/src/main/java/com/arangodb/internal/serde/InternalSerdeImpl.java +++ b/core/src/main/java/com/arangodb/internal/serde/InternalSerdeImpl.java @@ -10,6 +10,7 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.Module; import com.fasterxml.jackson.databind.ObjectMapper; import java.io.IOException; @@ -29,12 +30,15 @@ final class InternalSerdeImpl implements InternalSerde { private final ArangoSerde userSerde; private final ObjectMapper mapper; - InternalSerdeImpl(final ObjectMapper mapper, final ArangoSerde userSerde) { + InternalSerdeImpl(final ObjectMapper mapper, final ArangoSerde userSerde, final Module protocolModule) { this.mapper = mapper; this.userSerde = userSerde; mapper.deactivateDefaultTyping(); mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); mapper.registerModule(InternalModule.INSTANCE.get()); + if (protocolModule != null) { + mapper.registerModule(protocolModule); + } mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); mapper.setAnnotationIntrospector(new InternalAnnotationIntrospector( new UserDataSerializer(this), diff --git a/driver/src/main/java/com/arangodb/internal/serde/InternalSerdeProvider.java b/core/src/main/java/com/arangodb/internal/serde/InternalSerdeProvider.java similarity index 73% rename from driver/src/main/java/com/arangodb/internal/serde/InternalSerdeProvider.java rename to core/src/main/java/com/arangodb/internal/serde/InternalSerdeProvider.java index 9136d6a68..4044d6f17 100644 --- a/driver/src/main/java/com/arangodb/internal/serde/InternalSerdeProvider.java +++ b/core/src/main/java/com/arangodb/internal/serde/InternalSerdeProvider.java @@ -3,6 +3,7 @@ import com.arangodb.ContentType; import com.arangodb.serde.ArangoSerde; import com.arangodb.serde.ArangoSerdeProvider; +import com.fasterxml.jackson.databind.Module; public class InternalSerdeProvider implements ArangoSerdeProvider { @@ -14,17 +15,19 @@ public class InternalSerdeProvider implements ArangoSerdeProvider { */ @Override public InternalSerde of(final ContentType contentType) { - return create(contentType, null); + return create(contentType, null, null); } /** * Creates a new InternalSerde with default settings for the specified data type. * * @param contentType serialization target data type + * @param userSerde user serde + * @param protocolModule optional Jackson module to support protocol specific types * @return the created InternalSerde */ - public static InternalSerde create(final ContentType contentType, ArangoSerde userSerde) { - return new InternalSerdeImpl(InternalMapperProvider.of(contentType), userSerde); + public static InternalSerde create(final ContentType contentType, ArangoSerde userSerde, Module protocolModule) { + return new InternalSerdeImpl(InternalMapperProvider.of(contentType), userSerde, protocolModule); } } diff --git a/driver/src/main/java/com/arangodb/internal/serde/InternalSerializers.java b/core/src/main/java/com/arangodb/internal/serde/InternalSerializers.java similarity index 73% rename from driver/src/main/java/com/arangodb/internal/serde/InternalSerializers.java rename to core/src/main/java/com/arangodb/internal/serde/InternalSerializers.java index 7012f67fc..813025c49 100644 --- a/driver/src/main/java/com/arangodb/internal/serde/InternalSerializers.java +++ b/core/src/main/java/com/arangodb/internal/serde/InternalSerializers.java @@ -3,8 +3,6 @@ import com.arangodb.entity.CollectionType; import com.arangodb.entity.arangosearch.CollectionLink; import com.arangodb.entity.arangosearch.FieldLink; -import com.arangodb.internal.velocystream.internal.AuthenticationRequest; -import com.arangodb.internal.velocystream.internal.JwtAuthenticationRequest; import com.arangodb.util.RawBytes; import com.arangodb.util.RawJson; import com.arangodb.internal.InternalRequest; @@ -36,32 +34,6 @@ public void serialize(RawBytes value, JsonGenerator gen, SerializerProvider seri } } }; - static final JsonSerializer AUTHENTICATION_REQUEST = - new JsonSerializer() { - @Override - public void serialize(AuthenticationRequest value, JsonGenerator gen, SerializerProvider serializers) throws IOException { - gen.writeStartArray(); - gen.writeNumber(value.getVersion()); - gen.writeNumber(value.getType()); - gen.writeString(value.getEncryption()); - gen.writeString(value.getUser()); - gen.writeString(value.getPassword()); - gen.writeEndArray(); - } - }; - static final JsonSerializer JWT_AUTHENTICATION_REQUEST = - new JsonSerializer() { - @Override - public void serialize(JwtAuthenticationRequest value, JsonGenerator gen, - SerializerProvider serializers) throws IOException { - gen.writeStartArray(); - gen.writeNumber(value.getVersion()); - gen.writeNumber(value.getType()); - gen.writeString(value.getEncryption()); - gen.writeString(value.getToken()); - gen.writeEndArray(); - } - }; static final JsonSerializer REQUEST = new JsonSerializer() { @Override public void serialize(InternalRequest value, JsonGenerator gen, SerializerProvider serializers) throws IOException { diff --git a/driver/src/main/java/com/arangodb/internal/serde/SerdeUtils.java b/core/src/main/java/com/arangodb/internal/serde/SerdeUtils.java similarity index 100% rename from driver/src/main/java/com/arangodb/internal/serde/SerdeUtils.java rename to core/src/main/java/com/arangodb/internal/serde/SerdeUtils.java diff --git a/driver/src/main/java/com/arangodb/internal/serde/UserData.java b/core/src/main/java/com/arangodb/internal/serde/UserData.java similarity index 100% rename from driver/src/main/java/com/arangodb/internal/serde/UserData.java rename to core/src/main/java/com/arangodb/internal/serde/UserData.java diff --git a/driver/src/main/java/com/arangodb/internal/serde/UserDataDeserializer.java b/core/src/main/java/com/arangodb/internal/serde/UserDataDeserializer.java similarity index 100% rename from driver/src/main/java/com/arangodb/internal/serde/UserDataDeserializer.java rename to core/src/main/java/com/arangodb/internal/serde/UserDataDeserializer.java diff --git a/driver/src/main/java/com/arangodb/internal/serde/UserDataInside.java b/core/src/main/java/com/arangodb/internal/serde/UserDataInside.java similarity index 100% rename from driver/src/main/java/com/arangodb/internal/serde/UserDataInside.java rename to core/src/main/java/com/arangodb/internal/serde/UserDataInside.java diff --git a/driver/src/main/java/com/arangodb/internal/serde/UserDataSerializer.java b/core/src/main/java/com/arangodb/internal/serde/UserDataSerializer.java similarity index 100% rename from driver/src/main/java/com/arangodb/internal/serde/UserDataSerializer.java rename to core/src/main/java/com/arangodb/internal/serde/UserDataSerializer.java diff --git a/driver/src/main/java/com/arangodb/internal/util/DocumentUtil.java b/core/src/main/java/com/arangodb/internal/util/DocumentUtil.java similarity index 100% rename from driver/src/main/java/com/arangodb/internal/util/DocumentUtil.java rename to core/src/main/java/com/arangodb/internal/util/DocumentUtil.java diff --git a/driver/src/main/java/com/arangodb/internal/util/EncodeUtils.java b/core/src/main/java/com/arangodb/internal/util/EncodeUtils.java similarity index 100% rename from driver/src/main/java/com/arangodb/internal/util/EncodeUtils.java rename to core/src/main/java/com/arangodb/internal/util/EncodeUtils.java diff --git a/driver/src/main/java/com/arangodb/internal/util/HostUtils.java b/core/src/main/java/com/arangodb/internal/util/HostUtils.java similarity index 92% rename from driver/src/main/java/com/arangodb/internal/util/HostUtils.java rename to core/src/main/java/com/arangodb/internal/util/HostUtils.java index c03d955b0..591ed91af 100644 --- a/driver/src/main/java/com/arangodb/internal/util/HostUtils.java +++ b/core/src/main/java/com/arangodb/internal/util/HostUtils.java @@ -21,6 +21,7 @@ package com.arangodb.internal.util; import com.arangodb.config.HostDescription; +import com.arangodb.internal.config.ArangoConfig; import com.arangodb.internal.net.*; /** @@ -45,8 +46,8 @@ public static HostDescription createFromLocation(final String location) { public static Host createHost( final HostDescription description, - final int maxConnections, + final ArangoConfig config, final ConnectionFactory factory) { - return new HostImpl(new ConnectionPoolImpl(description, maxConnections, factory), description); + return new HostImpl(new ConnectionPoolImpl(description, config, factory), description); } } diff --git a/driver/src/main/java/com/arangodb/internal/util/RequestUtils.java b/core/src/main/java/com/arangodb/internal/util/RequestUtils.java similarity index 100% rename from driver/src/main/java/com/arangodb/internal/util/RequestUtils.java rename to core/src/main/java/com/arangodb/internal/util/RequestUtils.java diff --git a/driver/src/main/java/com/arangodb/internal/util/ResponseUtils.java b/core/src/main/java/com/arangodb/internal/util/ResponseUtils.java similarity index 100% rename from driver/src/main/java/com/arangodb/internal/util/ResponseUtils.java rename to core/src/main/java/com/arangodb/internal/util/ResponseUtils.java diff --git a/driver/src/main/java/com/arangodb/model/AqlFunctionCreateOptions.java b/core/src/main/java/com/arangodb/model/AqlFunctionCreateOptions.java similarity index 100% rename from driver/src/main/java/com/arangodb/model/AqlFunctionCreateOptions.java rename to core/src/main/java/com/arangodb/model/AqlFunctionCreateOptions.java diff --git a/driver/src/main/java/com/arangodb/model/AqlFunctionDeleteOptions.java b/core/src/main/java/com/arangodb/model/AqlFunctionDeleteOptions.java similarity index 100% rename from driver/src/main/java/com/arangodb/model/AqlFunctionDeleteOptions.java rename to core/src/main/java/com/arangodb/model/AqlFunctionDeleteOptions.java diff --git a/driver/src/main/java/com/arangodb/model/AqlFunctionGetOptions.java b/core/src/main/java/com/arangodb/model/AqlFunctionGetOptions.java similarity index 100% rename from driver/src/main/java/com/arangodb/model/AqlFunctionGetOptions.java rename to core/src/main/java/com/arangodb/model/AqlFunctionGetOptions.java diff --git a/driver/src/main/java/com/arangodb/model/AqlQueryExplainOptions.java b/core/src/main/java/com/arangodb/model/AqlQueryExplainOptions.java similarity index 100% rename from driver/src/main/java/com/arangodb/model/AqlQueryExplainOptions.java rename to core/src/main/java/com/arangodb/model/AqlQueryExplainOptions.java diff --git a/driver/src/main/java/com/arangodb/model/AqlQueryOptions.java b/core/src/main/java/com/arangodb/model/AqlQueryOptions.java similarity index 100% rename from driver/src/main/java/com/arangodb/model/AqlQueryOptions.java rename to core/src/main/java/com/arangodb/model/AqlQueryOptions.java diff --git a/driver/src/main/java/com/arangodb/model/AqlQueryParseOptions.java b/core/src/main/java/com/arangodb/model/AqlQueryParseOptions.java similarity index 100% rename from driver/src/main/java/com/arangodb/model/AqlQueryParseOptions.java rename to core/src/main/java/com/arangodb/model/AqlQueryParseOptions.java diff --git a/driver/src/main/java/com/arangodb/model/CollectionCountOptions.java b/core/src/main/java/com/arangodb/model/CollectionCountOptions.java similarity index 100% rename from driver/src/main/java/com/arangodb/model/CollectionCountOptions.java rename to core/src/main/java/com/arangodb/model/CollectionCountOptions.java diff --git a/driver/src/main/java/com/arangodb/model/CollectionCreateOptions.java b/core/src/main/java/com/arangodb/model/CollectionCreateOptions.java similarity index 100% rename from driver/src/main/java/com/arangodb/model/CollectionCreateOptions.java rename to core/src/main/java/com/arangodb/model/CollectionCreateOptions.java diff --git a/driver/src/main/java/com/arangodb/model/CollectionPropertiesOptions.java b/core/src/main/java/com/arangodb/model/CollectionPropertiesOptions.java similarity index 100% rename from driver/src/main/java/com/arangodb/model/CollectionPropertiesOptions.java rename to core/src/main/java/com/arangodb/model/CollectionPropertiesOptions.java diff --git a/driver/src/main/java/com/arangodb/model/CollectionRenameOptions.java b/core/src/main/java/com/arangodb/model/CollectionRenameOptions.java similarity index 100% rename from driver/src/main/java/com/arangodb/model/CollectionRenameOptions.java rename to core/src/main/java/com/arangodb/model/CollectionRenameOptions.java diff --git a/driver/src/main/java/com/arangodb/model/CollectionSchema.java b/core/src/main/java/com/arangodb/model/CollectionSchema.java similarity index 100% rename from driver/src/main/java/com/arangodb/model/CollectionSchema.java rename to core/src/main/java/com/arangodb/model/CollectionSchema.java diff --git a/driver/src/main/java/com/arangodb/model/CollectionTruncateOptions.java b/core/src/main/java/com/arangodb/model/CollectionTruncateOptions.java similarity index 100% rename from driver/src/main/java/com/arangodb/model/CollectionTruncateOptions.java rename to core/src/main/java/com/arangodb/model/CollectionTruncateOptions.java diff --git a/driver/src/main/java/com/arangodb/model/CollectionsReadOptions.java b/core/src/main/java/com/arangodb/model/CollectionsReadOptions.java similarity index 100% rename from driver/src/main/java/com/arangodb/model/CollectionsReadOptions.java rename to core/src/main/java/com/arangodb/model/CollectionsReadOptions.java diff --git a/driver/src/main/java/com/arangodb/model/ComputedValue.java b/core/src/main/java/com/arangodb/model/ComputedValue.java similarity index 100% rename from driver/src/main/java/com/arangodb/model/ComputedValue.java rename to core/src/main/java/com/arangodb/model/ComputedValue.java diff --git a/driver/src/main/java/com/arangodb/model/DBCreateOptions.java b/core/src/main/java/com/arangodb/model/DBCreateOptions.java similarity index 100% rename from driver/src/main/java/com/arangodb/model/DBCreateOptions.java rename to core/src/main/java/com/arangodb/model/DBCreateOptions.java diff --git a/driver/src/main/java/com/arangodb/model/DatabaseOptions.java b/core/src/main/java/com/arangodb/model/DatabaseOptions.java similarity index 100% rename from driver/src/main/java/com/arangodb/model/DatabaseOptions.java rename to core/src/main/java/com/arangodb/model/DatabaseOptions.java diff --git a/driver/src/main/java/com/arangodb/model/DatabaseUsersOptions.java b/core/src/main/java/com/arangodb/model/DatabaseUsersOptions.java similarity index 100% rename from driver/src/main/java/com/arangodb/model/DatabaseUsersOptions.java rename to core/src/main/java/com/arangodb/model/DatabaseUsersOptions.java diff --git a/driver/src/main/java/com/arangodb/model/DocumentCreateOptions.java b/core/src/main/java/com/arangodb/model/DocumentCreateOptions.java similarity index 100% rename from driver/src/main/java/com/arangodb/model/DocumentCreateOptions.java rename to core/src/main/java/com/arangodb/model/DocumentCreateOptions.java diff --git a/driver/src/main/java/com/arangodb/model/DocumentDeleteOptions.java b/core/src/main/java/com/arangodb/model/DocumentDeleteOptions.java similarity index 100% rename from driver/src/main/java/com/arangodb/model/DocumentDeleteOptions.java rename to core/src/main/java/com/arangodb/model/DocumentDeleteOptions.java diff --git a/driver/src/main/java/com/arangodb/model/DocumentExistsOptions.java b/core/src/main/java/com/arangodb/model/DocumentExistsOptions.java similarity index 100% rename from driver/src/main/java/com/arangodb/model/DocumentExistsOptions.java rename to core/src/main/java/com/arangodb/model/DocumentExistsOptions.java diff --git a/driver/src/main/java/com/arangodb/model/DocumentImportOptions.java b/core/src/main/java/com/arangodb/model/DocumentImportOptions.java similarity index 100% rename from driver/src/main/java/com/arangodb/model/DocumentImportOptions.java rename to core/src/main/java/com/arangodb/model/DocumentImportOptions.java diff --git a/driver/src/main/java/com/arangodb/model/DocumentReadOptions.java b/core/src/main/java/com/arangodb/model/DocumentReadOptions.java similarity index 100% rename from driver/src/main/java/com/arangodb/model/DocumentReadOptions.java rename to core/src/main/java/com/arangodb/model/DocumentReadOptions.java diff --git a/driver/src/main/java/com/arangodb/model/DocumentReplaceOptions.java b/core/src/main/java/com/arangodb/model/DocumentReplaceOptions.java similarity index 100% rename from driver/src/main/java/com/arangodb/model/DocumentReplaceOptions.java rename to core/src/main/java/com/arangodb/model/DocumentReplaceOptions.java diff --git a/driver/src/main/java/com/arangodb/model/DocumentUpdateOptions.java b/core/src/main/java/com/arangodb/model/DocumentUpdateOptions.java similarity index 100% rename from driver/src/main/java/com/arangodb/model/DocumentUpdateOptions.java rename to core/src/main/java/com/arangodb/model/DocumentUpdateOptions.java diff --git a/driver/src/main/java/com/arangodb/model/EdgeCreateOptions.java b/core/src/main/java/com/arangodb/model/EdgeCreateOptions.java similarity index 100% rename from driver/src/main/java/com/arangodb/model/EdgeCreateOptions.java rename to core/src/main/java/com/arangodb/model/EdgeCreateOptions.java diff --git a/driver/src/main/java/com/arangodb/model/EdgeDeleteOptions.java b/core/src/main/java/com/arangodb/model/EdgeDeleteOptions.java similarity index 100% rename from driver/src/main/java/com/arangodb/model/EdgeDeleteOptions.java rename to core/src/main/java/com/arangodb/model/EdgeDeleteOptions.java diff --git a/driver/src/main/java/com/arangodb/model/EdgeReplaceOptions.java b/core/src/main/java/com/arangodb/model/EdgeReplaceOptions.java similarity index 100% rename from driver/src/main/java/com/arangodb/model/EdgeReplaceOptions.java rename to core/src/main/java/com/arangodb/model/EdgeReplaceOptions.java diff --git a/driver/src/main/java/com/arangodb/model/EdgeUpdateOptions.java b/core/src/main/java/com/arangodb/model/EdgeUpdateOptions.java similarity index 100% rename from driver/src/main/java/com/arangodb/model/EdgeUpdateOptions.java rename to core/src/main/java/com/arangodb/model/EdgeUpdateOptions.java diff --git a/driver/src/main/java/com/arangodb/model/FulltextIndexOptions.java b/core/src/main/java/com/arangodb/model/FulltextIndexOptions.java similarity index 100% rename from driver/src/main/java/com/arangodb/model/FulltextIndexOptions.java rename to core/src/main/java/com/arangodb/model/FulltextIndexOptions.java diff --git a/driver/src/main/java/com/arangodb/model/GeoIndexOptions.java b/core/src/main/java/com/arangodb/model/GeoIndexOptions.java similarity index 100% rename from driver/src/main/java/com/arangodb/model/GeoIndexOptions.java rename to core/src/main/java/com/arangodb/model/GeoIndexOptions.java diff --git a/driver/src/main/java/com/arangodb/model/GraphCreateOptions.java b/core/src/main/java/com/arangodb/model/GraphCreateOptions.java similarity index 100% rename from driver/src/main/java/com/arangodb/model/GraphCreateOptions.java rename to core/src/main/java/com/arangodb/model/GraphCreateOptions.java diff --git a/driver/src/main/java/com/arangodb/model/GraphDocumentReadOptions.java b/core/src/main/java/com/arangodb/model/GraphDocumentReadOptions.java similarity index 100% rename from driver/src/main/java/com/arangodb/model/GraphDocumentReadOptions.java rename to core/src/main/java/com/arangodb/model/GraphDocumentReadOptions.java diff --git a/driver/src/main/java/com/arangodb/model/HashIndexOptions.java b/core/src/main/java/com/arangodb/model/HashIndexOptions.java similarity index 100% rename from driver/src/main/java/com/arangodb/model/HashIndexOptions.java rename to core/src/main/java/com/arangodb/model/HashIndexOptions.java diff --git a/driver/src/main/java/com/arangodb/model/ImportType.java b/core/src/main/java/com/arangodb/model/ImportType.java similarity index 100% rename from driver/src/main/java/com/arangodb/model/ImportType.java rename to core/src/main/java/com/arangodb/model/ImportType.java diff --git a/driver/src/main/java/com/arangodb/model/IndexOptions.java b/core/src/main/java/com/arangodb/model/IndexOptions.java similarity index 100% rename from driver/src/main/java/com/arangodb/model/IndexOptions.java rename to core/src/main/java/com/arangodb/model/IndexOptions.java diff --git a/driver/src/main/java/com/arangodb/model/InvertedIndexOptions.java b/core/src/main/java/com/arangodb/model/InvertedIndexOptions.java similarity index 100% rename from driver/src/main/java/com/arangodb/model/InvertedIndexOptions.java rename to core/src/main/java/com/arangodb/model/InvertedIndexOptions.java diff --git a/driver/src/main/java/com/arangodb/model/LogOptions.java b/core/src/main/java/com/arangodb/model/LogOptions.java similarity index 100% rename from driver/src/main/java/com/arangodb/model/LogOptions.java rename to core/src/main/java/com/arangodb/model/LogOptions.java diff --git a/driver/src/main/java/com/arangodb/model/OptionsBuilder.java b/core/src/main/java/com/arangodb/model/OptionsBuilder.java similarity index 100% rename from driver/src/main/java/com/arangodb/model/OptionsBuilder.java rename to core/src/main/java/com/arangodb/model/OptionsBuilder.java diff --git a/driver/src/main/java/com/arangodb/model/OverwriteMode.java b/core/src/main/java/com/arangodb/model/OverwriteMode.java similarity index 100% rename from driver/src/main/java/com/arangodb/model/OverwriteMode.java rename to core/src/main/java/com/arangodb/model/OverwriteMode.java diff --git a/driver/src/main/java/com/arangodb/model/PersistentIndexOptions.java b/core/src/main/java/com/arangodb/model/PersistentIndexOptions.java similarity index 100% rename from driver/src/main/java/com/arangodb/model/PersistentIndexOptions.java rename to core/src/main/java/com/arangodb/model/PersistentIndexOptions.java diff --git a/driver/src/main/java/com/arangodb/model/QueueTimeSample.java b/core/src/main/java/com/arangodb/model/QueueTimeSample.java similarity index 100% rename from driver/src/main/java/com/arangodb/model/QueueTimeSample.java rename to core/src/main/java/com/arangodb/model/QueueTimeSample.java diff --git a/driver/src/main/java/com/arangodb/model/SkiplistIndexOptions.java b/core/src/main/java/com/arangodb/model/SkiplistIndexOptions.java similarity index 100% rename from driver/src/main/java/com/arangodb/model/SkiplistIndexOptions.java rename to core/src/main/java/com/arangodb/model/SkiplistIndexOptions.java diff --git a/driver/src/main/java/com/arangodb/model/StreamTransactionOptions.java b/core/src/main/java/com/arangodb/model/StreamTransactionOptions.java similarity index 100% rename from driver/src/main/java/com/arangodb/model/StreamTransactionOptions.java rename to core/src/main/java/com/arangodb/model/StreamTransactionOptions.java diff --git a/driver/src/main/java/com/arangodb/model/TransactionCollectionOptions.java b/core/src/main/java/com/arangodb/model/TransactionCollectionOptions.java similarity index 100% rename from driver/src/main/java/com/arangodb/model/TransactionCollectionOptions.java rename to core/src/main/java/com/arangodb/model/TransactionCollectionOptions.java diff --git a/driver/src/main/java/com/arangodb/model/TransactionOptions.java b/core/src/main/java/com/arangodb/model/TransactionOptions.java similarity index 100% rename from driver/src/main/java/com/arangodb/model/TransactionOptions.java rename to core/src/main/java/com/arangodb/model/TransactionOptions.java diff --git a/driver/src/main/java/com/arangodb/model/TtlIndexOptions.java b/core/src/main/java/com/arangodb/model/TtlIndexOptions.java similarity index 100% rename from driver/src/main/java/com/arangodb/model/TtlIndexOptions.java rename to core/src/main/java/com/arangodb/model/TtlIndexOptions.java diff --git a/driver/src/main/java/com/arangodb/model/UserAccessOptions.java b/core/src/main/java/com/arangodb/model/UserAccessOptions.java similarity index 100% rename from driver/src/main/java/com/arangodb/model/UserAccessOptions.java rename to core/src/main/java/com/arangodb/model/UserAccessOptions.java diff --git a/driver/src/main/java/com/arangodb/model/UserCreateOptions.java b/core/src/main/java/com/arangodb/model/UserCreateOptions.java similarity index 100% rename from driver/src/main/java/com/arangodb/model/UserCreateOptions.java rename to core/src/main/java/com/arangodb/model/UserCreateOptions.java diff --git a/driver/src/main/java/com/arangodb/model/UserUpdateOptions.java b/core/src/main/java/com/arangodb/model/UserUpdateOptions.java similarity index 100% rename from driver/src/main/java/com/arangodb/model/UserUpdateOptions.java rename to core/src/main/java/com/arangodb/model/UserUpdateOptions.java diff --git a/driver/src/main/java/com/arangodb/model/VertexCollectionCreateOptions.java b/core/src/main/java/com/arangodb/model/VertexCollectionCreateOptions.java similarity index 100% rename from driver/src/main/java/com/arangodb/model/VertexCollectionCreateOptions.java rename to core/src/main/java/com/arangodb/model/VertexCollectionCreateOptions.java diff --git a/driver/src/main/java/com/arangodb/model/VertexCreateOptions.java b/core/src/main/java/com/arangodb/model/VertexCreateOptions.java similarity index 100% rename from driver/src/main/java/com/arangodb/model/VertexCreateOptions.java rename to core/src/main/java/com/arangodb/model/VertexCreateOptions.java diff --git a/driver/src/main/java/com/arangodb/model/VertexDeleteOptions.java b/core/src/main/java/com/arangodb/model/VertexDeleteOptions.java similarity index 100% rename from driver/src/main/java/com/arangodb/model/VertexDeleteOptions.java rename to core/src/main/java/com/arangodb/model/VertexDeleteOptions.java diff --git a/driver/src/main/java/com/arangodb/model/VertexReplaceOptions.java b/core/src/main/java/com/arangodb/model/VertexReplaceOptions.java similarity index 100% rename from driver/src/main/java/com/arangodb/model/VertexReplaceOptions.java rename to core/src/main/java/com/arangodb/model/VertexReplaceOptions.java diff --git a/driver/src/main/java/com/arangodb/model/VertexUpdateOptions.java b/core/src/main/java/com/arangodb/model/VertexUpdateOptions.java similarity index 100% rename from driver/src/main/java/com/arangodb/model/VertexUpdateOptions.java rename to core/src/main/java/com/arangodb/model/VertexUpdateOptions.java diff --git a/driver/src/main/java/com/arangodb/model/ViewCreateOptions.java b/core/src/main/java/com/arangodb/model/ViewCreateOptions.java similarity index 100% rename from driver/src/main/java/com/arangodb/model/ViewCreateOptions.java rename to core/src/main/java/com/arangodb/model/ViewCreateOptions.java diff --git a/driver/src/main/java/com/arangodb/model/ViewRenameOptions.java b/core/src/main/java/com/arangodb/model/ViewRenameOptions.java similarity index 100% rename from driver/src/main/java/com/arangodb/model/ViewRenameOptions.java rename to core/src/main/java/com/arangodb/model/ViewRenameOptions.java diff --git a/driver/src/main/java/com/arangodb/model/ZKDIndexOptions.java b/core/src/main/java/com/arangodb/model/ZKDIndexOptions.java similarity index 100% rename from driver/src/main/java/com/arangodb/model/ZKDIndexOptions.java rename to core/src/main/java/com/arangodb/model/ZKDIndexOptions.java diff --git a/driver/src/main/java/com/arangodb/model/arangosearch/AnalyzerDeleteOptions.java b/core/src/main/java/com/arangodb/model/arangosearch/AnalyzerDeleteOptions.java similarity index 100% rename from driver/src/main/java/com/arangodb/model/arangosearch/AnalyzerDeleteOptions.java rename to core/src/main/java/com/arangodb/model/arangosearch/AnalyzerDeleteOptions.java diff --git a/driver/src/main/java/com/arangodb/model/arangosearch/ArangoSearchCreateOptions.java b/core/src/main/java/com/arangodb/model/arangosearch/ArangoSearchCreateOptions.java similarity index 100% rename from driver/src/main/java/com/arangodb/model/arangosearch/ArangoSearchCreateOptions.java rename to core/src/main/java/com/arangodb/model/arangosearch/ArangoSearchCreateOptions.java diff --git a/driver/src/main/java/com/arangodb/model/arangosearch/ArangoSearchOptionsBuilder.java b/core/src/main/java/com/arangodb/model/arangosearch/ArangoSearchOptionsBuilder.java similarity index 100% rename from driver/src/main/java/com/arangodb/model/arangosearch/ArangoSearchOptionsBuilder.java rename to core/src/main/java/com/arangodb/model/arangosearch/ArangoSearchOptionsBuilder.java diff --git a/driver/src/main/java/com/arangodb/model/arangosearch/ArangoSearchPropertiesOptions.java b/core/src/main/java/com/arangodb/model/arangosearch/ArangoSearchPropertiesOptions.java similarity index 100% rename from driver/src/main/java/com/arangodb/model/arangosearch/ArangoSearchPropertiesOptions.java rename to core/src/main/java/com/arangodb/model/arangosearch/ArangoSearchPropertiesOptions.java diff --git a/driver/src/main/java/com/arangodb/model/arangosearch/SearchAliasCreateOptions.java b/core/src/main/java/com/arangodb/model/arangosearch/SearchAliasCreateOptions.java similarity index 100% rename from driver/src/main/java/com/arangodb/model/arangosearch/SearchAliasCreateOptions.java rename to core/src/main/java/com/arangodb/model/arangosearch/SearchAliasCreateOptions.java diff --git a/driver/src/main/java/com/arangodb/model/arangosearch/SearchAliasOptionsBuilder.java b/core/src/main/java/com/arangodb/model/arangosearch/SearchAliasOptionsBuilder.java similarity index 100% rename from driver/src/main/java/com/arangodb/model/arangosearch/SearchAliasOptionsBuilder.java rename to core/src/main/java/com/arangodb/model/arangosearch/SearchAliasOptionsBuilder.java diff --git a/driver/src/main/java/com/arangodb/model/arangosearch/SearchAliasPropertiesOptions.java b/core/src/main/java/com/arangodb/model/arangosearch/SearchAliasPropertiesOptions.java similarity index 100% rename from driver/src/main/java/com/arangodb/model/arangosearch/SearchAliasPropertiesOptions.java rename to core/src/main/java/com/arangodb/model/arangosearch/SearchAliasPropertiesOptions.java diff --git a/serde-api/src/main/java/com/arangodb/serde/ArangoSerde.java b/core/src/main/java/com/arangodb/serde/ArangoSerde.java similarity index 100% rename from serde-api/src/main/java/com/arangodb/serde/ArangoSerde.java rename to core/src/main/java/com/arangodb/serde/ArangoSerde.java diff --git a/serde-api/src/main/java/com/arangodb/serde/ArangoSerdeProvider.java b/core/src/main/java/com/arangodb/serde/ArangoSerdeProvider.java similarity index 100% rename from serde-api/src/main/java/com/arangodb/serde/ArangoSerdeProvider.java rename to core/src/main/java/com/arangodb/serde/ArangoSerdeProvider.java diff --git a/driver/src/main/java/com/arangodb/util/RawBytes.java b/core/src/main/java/com/arangodb/util/RawBytes.java similarity index 100% rename from driver/src/main/java/com/arangodb/util/RawBytes.java rename to core/src/main/java/com/arangodb/util/RawBytes.java diff --git a/driver/src/main/java/com/arangodb/util/RawData.java b/core/src/main/java/com/arangodb/util/RawData.java similarity index 100% rename from driver/src/main/java/com/arangodb/util/RawData.java rename to core/src/main/java/com/arangodb/util/RawData.java diff --git a/driver/src/main/java/com/arangodb/util/RawJson.java b/core/src/main/java/com/arangodb/util/RawJson.java similarity index 100% rename from driver/src/main/java/com/arangodb/util/RawJson.java rename to core/src/main/java/com/arangodb/util/RawJson.java diff --git a/driver/src/main/java/com/arangodb/util/UnicodeUtils.java b/core/src/main/java/com/arangodb/util/UnicodeUtils.java similarity index 100% rename from driver/src/main/java/com/arangodb/util/UnicodeUtils.java rename to core/src/main/java/com/arangodb/util/UnicodeUtils.java diff --git a/docs/v7_detailed_changes.md b/docs/v7_detailed_changes.md index 2b6bf34d1..f3e873477 100644 --- a/docs/v7_detailed_changes.md +++ b/docs/v7_detailed_changes.md @@ -9,7 +9,7 @@ In your `pom.xml` include the dependency: com.arangodb arangodb-java-driver - 7.0.0-ALPHA.1 + 7.0.0-ALPHA.2 ``` diff --git a/docs/v7_java-reference-serialization.md b/docs/v7_java-reference-serialization.md index a2459abca..da9127f08 100644 --- a/docs/v7_java-reference-serialization.md +++ b/docs/v7_java-reference-serialization.md @@ -38,7 +38,7 @@ The default user-data serde is `JacksonSerde`, which is provided by the module ` This is used by default from the driver, if no custom serde is registered explicitly. It is implemented delegating [Jackson](https://github.com/FasterXML/jackson) `ObjectMapper`, therefore it is compatible with Jackson Streaming, Data Binding and Tree Model API. -It supports both `JSON` and `VPACK` data formats. To use `VPACK`, the optional dependency on +It supports both `JSON` and `VPACK` data formats. To use `VPACK`, the additional dependency on [jackson-dataformat-velocypack](https://github.com/arangodb/jackson-dataformat-velocypack) is required. diff --git a/driver/pom.xml b/driver/pom.xml index 269d92cbd..e379c3639 100644 --- a/driver/pom.xml +++ b/driver/pom.xml @@ -7,7 +7,7 @@ arangodb-java-driver-parent com.arangodb - 7.0.0-ALPHA.1 + 7.0.0-ALPHA.2 arangodb-java-driver @@ -94,48 +94,6 @@ - - com.google.code.maven-replacer-plugin - replacer - 1.5.3 - - - generate-sources - - replace - - - - - ${project.basedir}/src/main/java/com/arangodb/PackageVersion.java.in - ${project.build.directory}/generated-sources/replacer/com/arangodb/PackageVersion.java - - - - @project.version@ - ${project.version} - - - - - - org.codehaus.mojo - build-helper-maven-plugin - 3.3.0 - - - generate-sources - - add-source - - - - ${project.build.directory}/generated-sources/replacer - - - - - org.apache.maven.plugins maven-enforcer-plugin @@ -157,35 +115,6 @@ - - maven-shade-plugin - 3.4.1 - - - package - - shade - - - true - true - - - com.arangodb:serde-api - - - - - com.arangodb:serde-api - - META-INF/MANIFEST.MF - - - - - - - org.codehaus.mojo flatten-maven-plugin @@ -196,42 +125,25 @@ com.arangodb - serde-api + core com.arangodb - jackson-serde + http-protocol - org.slf4j - slf4j-api - - - com.fasterxml.jackson.core - jackson-databind - - - com.fasterxml.jackson.core - jackson-core - - - com.fasterxml.jackson.core - jackson-annotations - - - io.vertx - vertx-web-client + com.arangodb + jackson-serde com.arangodb jackson-dataformat-velocypack - true + test - com.google.code.findbugs - jsr305 - 3.0.2 - provided + com.arangodb + vst-protocol + test org.reflections diff --git a/driver/src/main/java/com/arangodb/async/internal/velocystream/VstConnectionAsync.java b/driver/src/main/java/com/arangodb/async/internal/velocystream/VstConnectionAsync.java deleted file mode 100644 index 0e94bcc30..000000000 --- a/driver/src/main/java/com/arangodb/async/internal/velocystream/VstConnectionAsync.java +++ /dev/null @@ -1,126 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.async.internal.velocystream; - -import com.arangodb.async.internal.utils.CompletableFutureUtils; -import com.arangodb.config.HostDescription; -import com.arangodb.internal.velocystream.internal.Chunk; -import com.arangodb.internal.velocystream.internal.Message; -import com.arangodb.internal.velocystream.internal.MessageStore; -import com.arangodb.internal.velocystream.internal.VstConnection; - -import javax.net.ssl.SSLContext; -import java.util.Collection; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.FutureTask; -import java.util.concurrent.TimeUnit; - -/** - * @author Mark Vollmary - */ -public class VstConnectionAsync extends VstConnection> { - - private VstConnectionAsync(final HostDescription host, final Integer timeout, final Long ttl, - final Integer keepAliveInterval, - final Boolean useSsl, final SSLContext sslContext, final MessageStore messageStore) { - super(host, timeout, ttl, keepAliveInterval, useSsl, sslContext, messageStore); - } - - @Override - public synchronized CompletableFuture write(final Message message, final Collection chunks) { - final CompletableFuture future = new CompletableFuture<>(); - final FutureTask task = new FutureTask<>(() -> { - try { - future.complete(messageStore.get(message.getId())); - } catch (final Exception e) { - future.completeExceptionally(e); - } - return null; - }); - messageStore.storeMessage(message.getId(), task); - super.writeIntern(message, chunks); - if (timeout == null || timeout == 0L) { - return future; - } else { - return CompletableFutureUtils.orTimeout(future, timeout, TimeUnit.MILLISECONDS); - } - } - - @Override - protected void doKeepAlive() { - sendKeepAlive().join(); - } - - public static class Builder { - - private MessageStore messageStore; - private HostDescription host; - private Integer timeout; - private Long ttl; - private Integer keepAliveInterval; - private Boolean useSsl; - private SSLContext sslContext; - - public Builder() { - super(); - } - - public Builder messageStore(final MessageStore messageStore) { - this.messageStore = messageStore; - return this; - } - - public Builder host(final HostDescription host) { - this.host = host; - return this; - } - - public Builder timeout(final Integer timeout) { - this.timeout = timeout; - return this; - } - - public Builder ttl(final Long ttl) { - this.ttl = ttl; - return this; - } - - public Builder keepAliveInterval(final Integer keepAliveInterval) { - this.keepAliveInterval = keepAliveInterval; - return this; - } - - public Builder useSsl(final Boolean useSsl) { - this.useSsl = useSsl; - return this; - } - - public Builder sslContext(final SSLContext sslContext) { - this.sslContext = sslContext; - return this; - } - - public VstConnectionAsync build() { - return new VstConnectionAsync(host, timeout, ttl, keepAliveInterval, useSsl, sslContext, messageStore); - } - } - -} diff --git a/driver/src/main/java/com/arangodb/internal/InternalArangoDBBuilder.java b/driver/src/main/java/com/arangodb/internal/InternalArangoDBBuilder.java deleted file mode 100644 index b98d9b561..000000000 --- a/driver/src/main/java/com/arangodb/internal/InternalArangoDBBuilder.java +++ /dev/null @@ -1,232 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2018 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.internal; - -import com.arangodb.ArangoDBException; -import com.arangodb.Protocol; -import com.arangodb.config.ArangoConfigProperties; -import com.arangodb.config.HostDescription; -import com.arangodb.entity.LoadBalancingStrategy; -import com.arangodb.internal.net.*; -import com.arangodb.internal.serde.InternalSerdeProvider; -import com.arangodb.internal.util.HostUtils; -import com.arangodb.serde.ArangoSerde; -import com.arangodb.serde.ArangoSerdeProvider; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import javax.net.ssl.SSLContext; -import java.util.*; -import java.util.stream.Collectors; - - -/** - * @author Mark Vollmary - */ -public abstract class InternalArangoDBBuilder { - private static final Logger LOG = LoggerFactory.getLogger(InternalArangoDBBuilder.class); - - protected final List hosts = new ArrayList<>(); - protected Protocol protocol; - protected Integer timeout; - protected String user; - protected String password; - protected String jwt; - protected Boolean useSsl; - protected SSLContext sslContext; - protected Boolean verifyHost; - protected Integer chunkSize; - protected Integer maxConnections; - protected Long connectionTtl; - protected Integer keepAliveInterval; - protected Boolean acquireHostList; - protected Integer acquireHostListInterval; - protected LoadBalancingStrategy loadBalancingStrategy; - protected ArangoSerde userDataSerde; - protected Integer responseQueueTimeSamples; - - protected InternalArangoDBBuilder() { - // load default properties - doLoadProperties(new ArangoConfigProperties() { - }); - } - - protected static ArangoSerdeProvider serdeProvider() { - ServiceLoader loader = ServiceLoader.load(ArangoSerdeProvider.class); - Iterator it = loader.iterator(); - ArangoSerdeProvider serdeProvider; - if (!it.hasNext()) { - LOG.warn("No ArangoSerdeProvider found, using InternalSerdeProvider. Please consider registering a custom " + - "ArangoSerdeProvider to avoid depending on internal classes which are not part of the public API."); - serdeProvider = new InternalSerdeProvider(); - } else { - serdeProvider = it.next(); - if (it.hasNext()) { - throw new ArangoDBException("Found multiple serde providers! Please set explicitly the one to use."); - } - } - return serdeProvider; - } - - protected void doLoadProperties(final ArangoConfigProperties properties) { - hosts.addAll(properties.getHosts().orElse(ArangoDefaults.DEFAULT_HOSTS).stream() - .map(it -> new HostDescription(it.getHost(), it.getPort())) - .collect(Collectors.toList())); - protocol = properties.getProtocol().orElse(ArangoDefaults.DEFAULT_PROTOCOL); - timeout = properties.getTimeout().orElse(ArangoDefaults.DEFAULT_TIMEOUT); - user = properties.getUser().orElse(ArangoDefaults.DEFAULT_USER); - // FIXME: make password field Optional - password = properties.getPassword().orElse(null); - // FIXME: make jwt field Optional - jwt = properties.getJwt().orElse(null); - useSsl = properties.getUseSsl().orElse(ArangoDefaults.DEFAULT_USE_SSL); - verifyHost = properties.getVerifyHost().orElse(ArangoDefaults.DEFAULT_VERIFY_HOST); - chunkSize = properties.getChunkSize().orElse(ArangoDefaults.DEFAULT_CHUNK_SIZE); - // FIXME: make maxConnections field Optional - maxConnections = properties.getMaxConnections().orElse(null); - // FIXME: make connectionTtl field Optional - connectionTtl = properties.getConnectionTtl().orElse(null); - // FIXME: make keepAliveInterval field Optional - keepAliveInterval = properties.getKeepAliveInterval().orElse(null); - acquireHostList = properties.getAcquireHostList().orElse(ArangoDefaults.DEFAULT_ACQUIRE_HOST_LIST); - acquireHostListInterval = properties.getAcquireHostListInterval().orElse(ArangoDefaults.DEFAULT_ACQUIRE_HOST_LIST_INTERVAL); - loadBalancingStrategy = properties.getLoadBalancingStrategy().orElse(ArangoDefaults.DEFAULT_LOAD_BALANCING_STRATEGY); - responseQueueTimeSamples = properties.getResponseQueueTimeSamples().orElse(ArangoDefaults.DEFAULT_RESPONSE_QUEUE_TIME_SAMPLES); - } - - protected void setHost(final String host, final int port) { - hosts.add(new HostDescription(host, port)); - } - - protected void setTimeout(final Integer timeout) { - this.timeout = timeout; - } - - protected void setUser(final String user) { - this.user = user; - } - - protected void setPassword(final String password) { - this.password = password; - } - - protected void setJwt(final String jwt) { - this.jwt = jwt; - } - - protected void setUseSsl(final Boolean useSsl) { - this.useSsl = useSsl; - } - - protected void setSslContext(final SSLContext sslContext) { - this.sslContext = sslContext; - } - - protected void setVerifyHost(final Boolean verifyHost) { - this.verifyHost = verifyHost; - } - - protected void setChunkSize(final Integer chunkSize) { - this.chunkSize = chunkSize; - } - - protected void setMaxConnections(final Integer maxConnections) { - this.maxConnections = maxConnections; - } - - protected void setConnectionTtl(final Long connectionTtl) { - this.connectionTtl = connectionTtl; - } - - protected void setKeepAliveInterval(final Integer keepAliveInterval) { - this.keepAliveInterval = keepAliveInterval; - } - - protected void setAcquireHostList(final Boolean acquireHostList) { - this.acquireHostList = acquireHostList; - } - - protected void setAcquireHostListInterval(final Integer acquireHostListInterval) { - this.acquireHostListInterval = acquireHostListInterval; - } - - protected void setLoadBalancingStrategy(final LoadBalancingStrategy loadBalancingStrategy) { - this.loadBalancingStrategy = loadBalancingStrategy; - } - - protected void setResponseQueueTimeSamples(final Integer responseQueueTimeSamples) { - this.responseQueueTimeSamples = responseQueueTimeSamples; - } - - protected void setUserDataSerde(final ArangoSerde serde) { - this.userDataSerde = serde; - } - - protected HostHandler createHostHandler(final HostResolver hostResolver) { - - final HostHandler hostHandler; - - if (loadBalancingStrategy != null) { - switch (loadBalancingStrategy) { - case ONE_RANDOM: - hostHandler = new RandomHostHandler(hostResolver, new FallbackHostHandler(hostResolver)); - break; - case ROUND_ROBIN: - hostHandler = new RoundRobinHostHandler(hostResolver); - break; - case NONE: - default: - hostHandler = new FallbackHostHandler(hostResolver); - break; - } - } else { - hostHandler = new FallbackHostHandler(hostResolver); - } - - LOG.debug("HostHandler is {}", hostHandler.getClass().getSimpleName()); - - return new DirtyReadHostHandler(hostHandler, new RoundRobinHostHandler(hostResolver)); - } - - protected HostResolver createHostResolver(final Collection hosts, final int maxConnections, - final ConnectionFactory connectionFactory) { - - if (acquireHostList != null && acquireHostList) { - LOG.debug("acquireHostList -> Use ExtendedHostResolver"); - return new ExtendedHostResolver(new ArrayList<>(hosts), maxConnections, connectionFactory, - acquireHostListInterval); - } else { - LOG.debug("Use SimpleHostResolver"); - return new SimpleHostResolver(new ArrayList<>(hosts)); - } - - } - - protected Collection createHostList( - final int maxConnections, - final ConnectionFactory connectionFactory) { - final Collection hostList = new ArrayList<>(); - for (final HostDescription host : hosts) { - hostList.add(HostUtils.createHost(host, maxConnections, connectionFactory)); - } - return hostList; - } -} diff --git a/driver/src/main/java/com/arangodb/internal/serde/InternalJsonMapperProvider.java b/driver/src/main/java/com/arangodb/internal/serde/InternalJsonMapperProvider.java deleted file mode 100644 index 343c387d6..000000000 --- a/driver/src/main/java/com/arangodb/internal/serde/InternalJsonMapperProvider.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.arangodb.internal.serde; - -import com.fasterxml.jackson.databind.ObjectMapper; - -enum InternalJsonMapperProvider implements InternalMapperProvider { - INSTANCE; - - @Override - public ObjectMapper get() { - return new ObjectMapper(); - } -} diff --git a/driver/src/main/java/com/arangodb/internal/serde/InternalMapperProvider.java b/driver/src/main/java/com/arangodb/internal/serde/InternalMapperProvider.java deleted file mode 100644 index fca65bd24..000000000 --- a/driver/src/main/java/com/arangodb/internal/serde/InternalMapperProvider.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.arangodb.internal.serde; - -import com.arangodb.ContentType; -import com.fasterxml.jackson.databind.ObjectMapper; - -import java.util.function.Supplier; - -public interface InternalMapperProvider extends Supplier { - static ObjectMapper of(final ContentType contentType) { - if (contentType == ContentType.JSON) { - return InternalJsonMapperProvider.INSTANCE.get(); - } else if (contentType == ContentType.VPACK) { - return InternalVPackMapperProvider.INSTANCE.get(); - } else { - throw new IllegalArgumentException("Unexpected value: " + contentType); - } - } -} diff --git a/driver/src/main/java/com/arangodb/internal/serde/InternalVPackMapperProvider.java b/driver/src/main/java/com/arangodb/internal/serde/InternalVPackMapperProvider.java deleted file mode 100644 index e157b3dc2..000000000 --- a/driver/src/main/java/com/arangodb/internal/serde/InternalVPackMapperProvider.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.arangodb.internal.serde; - -import com.arangodb.jackson.dataformat.velocypack.VPackMapper; -import com.fasterxml.jackson.databind.ObjectMapper; - -enum InternalVPackMapperProvider implements InternalMapperProvider { - INSTANCE; - - @Override - public ObjectMapper get() { - return new VPackMapper(); - } -} diff --git a/driver/src/main/java/com/arangodb/internal/velocystream/internal/VstConnectionSync.java b/driver/src/main/java/com/arangodb/internal/velocystream/internal/VstConnectionSync.java deleted file mode 100644 index 7c8b71384..000000000 --- a/driver/src/main/java/com/arangodb/internal/velocystream/internal/VstConnectionSync.java +++ /dev/null @@ -1,116 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.internal.velocystream.internal; - -import com.arangodb.ArangoDBException; -import com.arangodb.config.HostDescription; - -import javax.net.ssl.SSLContext; -import java.util.Collection; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.FutureTask; -import java.util.concurrent.TimeUnit; - -/** - * @author Mark Vollmary - */ -public class VstConnectionSync extends VstConnection { - - private VstConnectionSync(final HostDescription host, final Integer timeout, final Long ttl, - final Integer keepAliveInterval, - final Boolean useSsl, final SSLContext sslContext, final MessageStore messageStore) { - super(host, timeout, ttl, keepAliveInterval, useSsl, sslContext, messageStore); - } - - @Override - public Message write(final Message message, final Collection chunks) { - final FutureTask task = new FutureTask<>(() -> messageStore.get(message.getId())); - messageStore.storeMessage(message.getId(), task); - super.writeIntern(message, chunks); - try { - return timeout == null || timeout == 0L ? task.get() : task.get(timeout, TimeUnit.MILLISECONDS); - } catch (final ExecutionException e) { - throw ArangoDBException.wrap(e.getCause()); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - throw new ArangoDBException(e); - } catch (final Exception e) { - throw ArangoDBException.wrap(e); - } - } - - @Override - protected void doKeepAlive() { - sendKeepAlive(); - } - - public static class Builder { - - private HostDescription host; - private MessageStore messageStore; - private Integer timeout; - private Long ttl; - private Integer keepAliveInterval; - private Boolean useSsl; - private SSLContext sslContext; - - public Builder host(final HostDescription host) { - this.host = host; - return this; - } - - public Builder messageStore(final MessageStore messageStore) { - this.messageStore = messageStore; - return this; - } - - public Builder timeout(final Integer timeout) { - this.timeout = timeout; - return this; - } - - public Builder useSsl(final Boolean useSsl) { - this.useSsl = useSsl; - return this; - } - - public Builder sslContext(final SSLContext sslContext) { - this.sslContext = sslContext; - return this; - } - - public Builder ttl(final Long ttl) { - this.ttl = ttl; - return this; - } - - public Builder keepAliveInterval(final Integer keepAliveInterval) { - this.keepAliveInterval = keepAliveInterval; - return this; - } - - public VstConnectionSync build() { - return new VstConnectionSync(host, timeout, ttl, keepAliveInterval, - useSsl, sslContext, messageStore); - } - } - -} diff --git a/driver/src/test/java/com/arangodb/async/serde/CustomSerdeTest.java b/driver/src/test/java/com/arangodb/async/serde/CustomSerdeTest.java index fdca9d3c0..6756ef847 100644 --- a/driver/src/test/java/com/arangodb/async/serde/CustomSerdeTest.java +++ b/driver/src/test/java/com/arangodb/async/serde/CustomSerdeTest.java @@ -65,7 +65,7 @@ void init() throws ExecutionException, InterruptedException { }); ArangoDBAsync arangoDB = new ArangoDBAsync.Builder() .loadProperties(ConfigUtils.loadConfig()) - .serializer(serde).build(); + .serde(serde).build(); DbName TEST_DB = DbName.of("custom-serde-test"); db = arangoDB.db(TEST_DB); diff --git a/driver/src/test/java/com/arangodb/internal/velocystream/CommunicationTest.java b/driver/src/test/java/com/arangodb/internal/velocystream/CommunicationTest.java index 120939786..58a87bd71 100644 --- a/driver/src/test/java/com/arangodb/internal/velocystream/CommunicationTest.java +++ b/driver/src/test/java/com/arangodb/internal/velocystream/CommunicationTest.java @@ -102,15 +102,6 @@ void multiThreadSameDatabases() throws Exception { assertThat(result.size()).isEqualTo(2); } - @Test - void minOneConnection() { - final ArangoDB arangoDB = new ArangoDB.Builder() - .loadProperties(ConfigUtils.loadConfig()) - .maxConnections(0).build(); - final ArangoDBVersion version = arangoDB.getVersion(); - assertThat(version).isNotNull(); - } - @Test void defaultMaxConnection() { final ArangoDB arangoDB = new ArangoDB.Builder() diff --git a/http/pom.xml b/http/pom.xml new file mode 100644 index 000000000..10e710bb7 --- /dev/null +++ b/http/pom.xml @@ -0,0 +1,51 @@ + + + 4.0.0 + + com.arangodb + arangodb-java-driver-parent + 7.0.0-ALPHA.2 + + + http-protocol + http-protocol + HTTP Protocol module for ArangoDB Java Driver + + + false + com.arangodb.http + + + + + com.arangodb + core + provided + + + io.vertx + vertx-web-client + + + + + + + io.vertx + vertx-stack-depchain + 4.3.5 + pom + import + + + io.netty + netty-bom + 4.1.85.Final + pom + import + + + + \ No newline at end of file diff --git a/driver/src/main/java/com/arangodb/internal/http/HttpCommunication.java b/http/src/main/java/com/arangodb/http/HttpCommunication.java similarity index 88% rename from driver/src/main/java/com/arangodb/internal/http/HttpCommunication.java rename to http/src/main/java/com/arangodb/http/HttpCommunication.java index a0be3f649..fafc1b721 100644 --- a/driver/src/main/java/com/arangodb/internal/http/HttpCommunication.java +++ b/http/src/main/java/com/arangodb/http/HttpCommunication.java @@ -18,13 +18,14 @@ * Copyright holder is ArangoDB GmbH, Cologne, Germany */ -package com.arangodb.internal.http; +package com.arangodb.http; import com.arangodb.ArangoDBException; import com.arangodb.config.HostDescription; import com.arangodb.internal.InternalRequest; import com.arangodb.internal.RequestType; import com.arangodb.internal.InternalResponse; +import com.arangodb.internal.config.ArangoConfig; import com.arangodb.internal.net.*; import com.arangodb.internal.serde.InternalSerde; import com.arangodb.internal.util.HostUtils; @@ -48,10 +49,10 @@ public class HttpCommunication implements Closeable { private final InternalSerde serde; private final AtomicLong reqCount; - private HttpCommunication(final HostHandler hostHandler, final InternalSerde serde) { + HttpCommunication(final HostHandler hostHandler, final ArangoConfig config) { super(); this.hostHandler = hostHandler; - this.serde = serde; + this.serde = config.getInternalSerde(); reqCount = new AtomicLong(); } @@ -123,23 +124,4 @@ private boolean isSafe(final InternalRequest request) { return type == RequestType.GET || type == RequestType.HEAD || type == RequestType.OPTIONS; } - public static class Builder { - private HostHandler hostHandler; - private InternalSerde serde; - - public Builder hostHandler(HostHandler hostHandler) { - this.hostHandler = hostHandler; - return this; - } - - public Builder serde(InternalSerde serde) { - this.serde = serde; - return this; - } - - public HttpCommunication build() { - return new HttpCommunication(hostHandler, serde); - } - } - } diff --git a/driver/src/main/java/com/arangodb/internal/http/HttpConnection.java b/http/src/main/java/com/arangodb/http/HttpConnection.java similarity index 79% rename from driver/src/main/java/com/arangodb/internal/http/HttpConnection.java rename to http/src/main/java/com/arangodb/http/HttpConnection.java index f81786432..5c8d424cf 100644 --- a/driver/src/main/java/com/arangodb/internal/http/HttpConnection.java +++ b/http/src/main/java/com/arangodb/http/HttpConnection.java @@ -18,11 +18,12 @@ * Copyright holder is ArangoDB GmbH, Cologne, Germany */ -package com.arangodb.internal.http; +package com.arangodb.http; import com.arangodb.*; -import com.arangodb.internal.net.Connection; import com.arangodb.config.HostDescription; +import com.arangodb.internal.config.ArangoConfig; +import com.arangodb.internal.net.Connection; import com.arangodb.internal.serde.ContentTypeFactory; import com.arangodb.internal.serde.InternalSerde; import com.arangodb.internal.util.EncodeUtils; @@ -56,6 +57,7 @@ import java.security.NoSuchAlgorithmException; import java.util.Iterator; import java.util.Map.Entry; +import java.util.Optional; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; @@ -73,7 +75,7 @@ public class HttpConnection implements Connection { private static final String CONTENT_TYPE_VPACK = "application/x-velocypack"; private static final String USER_AGENT = getUserAgent(); private static final AtomicInteger THREAD_COUNT = new AtomicInteger(); - private final InternalSerde util; + private final InternalSerde serde; private final ContentType contentType; private String auth; private final WebClient client; @@ -84,21 +86,24 @@ private static String getUserAgent() { return "JavaDriver/" + PackageVersion.VERSION + " (JVM/" + System.getProperty("java.specification.version") + ")"; } - private HttpConnection(final HostDescription host, final Integer timeout, final String user, final String password, - final Boolean useSsl, final SSLContext sslContext, final Boolean verifyHost, - final InternalSerde util, final Protocol protocol, final Long ttl) { + HttpConnection(final ArangoConfig config, final HostDescription host) { super(); - this.util = util; - this.contentType = ContentTypeFactory.of(protocol); - this.timeout = timeout; + serde = config.getInternalSerde(); + Protocol protocol = config.getProtocol(); + contentType = ContentTypeFactory.of(protocol); + timeout = config.getTimeout(); vertx = Vertx.vertx(new VertxOptions().setPreferNativeTransport(true).setEventLoopPoolSize(1)); vertx.runOnContext(e -> { Thread.currentThread().setName("adb-eventloop-" + THREAD_COUNT.getAndIncrement()); - auth = new UsernamePasswordCredentials(user, password != null ? password : "").toHttpAuthorization(); + auth = new UsernamePasswordCredentials( + config.getUser(), Optional.ofNullable(config.getPassword()).orElse("") + ).toHttpAuthorization(); LOGGER.debug("Created Vert.x context"); }); - int intTtl = ttl == null ? 0 : Math.toIntExact(ttl / 1000); + int intTtl = Optional.ofNullable(config.getConnectionTtl()) + .map(ttl -> Math.toIntExact(ttl / 1000)) + .orElse(0); HttpVersion httpVersion = protocol == Protocol.HTTP_JSON || protocol == Protocol.HTTP_VPACK ? HttpVersion.HTTP_1_1 : HttpVersion.HTTP_2; @@ -125,10 +130,10 @@ private HttpConnection(final HostDescription host, final Integer timeout, final .setDefaultPort(host.getPort()); - if (Boolean.TRUE.equals(useSsl)) { + if (Boolean.TRUE.equals(config.getUseSsl())) { SSLContext ctx; - if (sslContext != null) { - ctx = sslContext; + if (config.getSslContext() != null) { + ctx = config.getSslContext(); } else { try { ctx = SSLContext.getDefault(); @@ -140,7 +145,7 @@ private HttpConnection(final HostDescription host, final Integer timeout, final webClientOptions .setSsl(true) .setUseAlpn(true) - .setVerifyHost(verifyHost == null || verifyHost) + .setVerifyHost(config.getVerifyHost()) .setJdkSslEngineOptions(new JdkSSLEngineOptions() { @Override public JdkSSLEngineOptions copy() { @@ -291,7 +296,7 @@ private InternalResponse buildResponse(final HttpResponse httpResponse) } protected void checkError(final InternalResponse response) { - ResponseUtils.checkError(util, response); + ResponseUtils.checkError(serde, response); } @Override @@ -301,72 +306,4 @@ public void setJwt(String jwt) { } } - public static class Builder { - private String user; - private String password; - private InternalSerde util; - private Boolean useSsl; - private Protocol protocol; - private HostDescription host; - private Long ttl; - private SSLContext sslContext; - private Boolean verifyHost; - private Integer timeout; - - public Builder user(final String user) { - this.user = user; - return this; - } - - public Builder password(final String password) { - this.password = password; - return this; - } - - public Builder serializationUtil(final InternalSerde util) { - this.util = util; - return this; - } - - public Builder useSsl(final Boolean useSsl) { - this.useSsl = useSsl; - return this; - } - - public Builder protocol(final Protocol protocol) { - this.protocol = protocol; - return this; - } - - public Builder host(final HostDescription host) { - this.host = host; - return this; - } - - public Builder ttl(final Long ttl) { - this.ttl = ttl; - return this; - } - - public Builder sslContext(final SSLContext sslContext) { - this.sslContext = sslContext; - return this; - } - - public Builder verifyHost(final Boolean verifyHost) { - this.verifyHost = verifyHost; - return this; - } - - public Builder timeout(final Integer timeout) { - this.timeout = timeout; - return this; - } - - public HttpConnection build() { - return new HttpConnection(host, timeout, user, password, useSsl, sslContext, verifyHost, util, - protocol, ttl); - } - } - } diff --git a/driver/src/main/java/com/arangodb/internal/http/HttpConnectionFactory.java b/http/src/main/java/com/arangodb/http/HttpConnectionFactory.java similarity index 51% rename from driver/src/main/java/com/arangodb/internal/http/HttpConnectionFactory.java rename to http/src/main/java/com/arangodb/http/HttpConnectionFactory.java index e4525511e..4c24c06c1 100644 --- a/driver/src/main/java/com/arangodb/internal/http/HttpConnectionFactory.java +++ b/http/src/main/java/com/arangodb/http/HttpConnectionFactory.java @@ -18,36 +18,19 @@ * Copyright holder is ArangoDB GmbH, Cologne, Germany */ -package com.arangodb.internal.http; +package com.arangodb.http; -import com.arangodb.Protocol; +import com.arangodb.config.HostDescription; +import com.arangodb.internal.config.ArangoConfig; import com.arangodb.internal.net.Connection; import com.arangodb.internal.net.ConnectionFactory; -import com.arangodb.config.HostDescription; -import com.arangodb.internal.serde.InternalSerde; - -import javax.net.ssl.SSLContext; /** * @author Mark Vollmary */ public class HttpConnectionFactory implements ConnectionFactory { - - private final HttpConnection.Builder builder; - - public HttpConnectionFactory(final Integer timeout, final String user, final String password, final Boolean useSsl, - final SSLContext sslContext, final Boolean verifyHost, - final InternalSerde util, final Protocol protocol, final Long connectionTtl) { - super(); - builder = new HttpConnection.Builder().timeout(timeout).user(user).password(password).useSsl(useSsl) - .sslContext(sslContext).verifyHost(verifyHost).serializationUtil(util).protocol(protocol) - .ttl(connectionTtl); - - } - @Override - public Connection create(final HostDescription host) { - return builder.host(host).build(); + public Connection create(final ArangoConfig config, final HostDescription host) { + return new HttpConnection(config, host); } - } diff --git a/driver/src/main/java/com/arangodb/internal/http/HttpProtocol.java b/http/src/main/java/com/arangodb/http/HttpProtocol.java similarity index 97% rename from driver/src/main/java/com/arangodb/internal/http/HttpProtocol.java rename to http/src/main/java/com/arangodb/http/HttpProtocol.java index 15d35c2d4..a78f5487f 100644 --- a/driver/src/main/java/com/arangodb/internal/http/HttpProtocol.java +++ b/http/src/main/java/com/arangodb/http/HttpProtocol.java @@ -18,7 +18,7 @@ * Copyright holder is ArangoDB GmbH, Cologne, Germany */ -package com.arangodb.internal.http; +package com.arangodb.http; import com.arangodb.internal.net.CommunicationProtocol; import com.arangodb.internal.net.HostHandle; diff --git a/http/src/main/java/com/arangodb/http/HttpProtocolProvider.java b/http/src/main/java/com/arangodb/http/HttpProtocolProvider.java new file mode 100644 index 000000000..e6bc1d3b9 --- /dev/null +++ b/http/src/main/java/com/arangodb/http/HttpProtocolProvider.java @@ -0,0 +1,36 @@ +package com.arangodb.http; + +import com.arangodb.Protocol; +import com.arangodb.internal.config.ArangoConfig; +import com.arangodb.internal.net.CommunicationProtocol; +import com.arangodb.internal.net.ConnectionFactory; +import com.arangodb.internal.net.HostHandler; +import com.arangodb.internal.net.ProtocolProvider; +import com.fasterxml.jackson.databind.Module; + +public class HttpProtocolProvider implements ProtocolProvider { + + @Override + public boolean supportsProtocol(Protocol protocol) { + return Protocol.HTTP_VPACK.equals(protocol) || + Protocol.HTTP_JSON.equals(protocol) || + Protocol.HTTP2_VPACK.equals(protocol) || + Protocol.HTTP2_JSON.equals(protocol); + } + + @Override + public ConnectionFactory createConnectionFactory() { + return new HttpConnectionFactory(); + } + + @Override + public CommunicationProtocol createProtocol(ArangoConfig config, HostHandler hostHandler) { + return new HttpProtocol(new HttpCommunication(hostHandler, config)); + } + + @Override + public Module protocolModule() { + return null; + } + +} diff --git a/http/src/main/resources/META-INF/services/com.arangodb.internal.net.ProtocolProvider b/http/src/main/resources/META-INF/services/com.arangodb.internal.net.ProtocolProvider new file mode 100644 index 000000000..f48d178b7 --- /dev/null +++ b/http/src/main/resources/META-INF/services/com.arangodb.internal.net.ProtocolProvider @@ -0,0 +1 @@ +com.arangodb.http.HttpProtocolProvider diff --git a/driver/src/main/resources/META-INF/vertx/vertx-version.txt b/http/src/main/resources/META-INF/vertx/vertx-version.txt similarity index 100% rename from driver/src/main/resources/META-INF/vertx/vertx-version.txt rename to http/src/main/resources/META-INF/vertx/vertx-version.txt diff --git a/jackson-serde/pom.xml b/jackson-serde/pom.xml index 69f00e2f5..fcdf5ded7 100644 --- a/jackson-serde/pom.xml +++ b/jackson-serde/pom.xml @@ -6,7 +6,7 @@ com.arangodb arangodb-java-driver-parent - 7.0.0-ALPHA.1 + 7.0.0-ALPHA.2 jackson-serde @@ -19,6 +19,11 @@ + + com.arangodb + core + provided + com.fasterxml.jackson.core jackson-databind @@ -31,15 +36,5 @@ com.fasterxml.jackson.core jackson-annotations - - com.arangodb - jackson-dataformat-velocypack - true - - - com.arangodb - serde-api - provided - \ No newline at end of file diff --git a/jackson-serde/src/main/java/com/arangodb/serde/jackson/JacksonSerdeProvider.java b/jackson-serde/src/main/java/com/arangodb/serde/jackson/JacksonSerdeProvider.java index 4fcbf2fcf..c2f437e21 100644 --- a/jackson-serde/src/main/java/com/arangodb/serde/jackson/JacksonSerdeProvider.java +++ b/jackson-serde/src/main/java/com/arangodb/serde/jackson/JacksonSerdeProvider.java @@ -1,22 +1,25 @@ package com.arangodb.serde.jackson; import com.arangodb.ContentType; -import com.arangodb.serde.jackson.internal.JacksonSerdeImpl; -import com.arangodb.serde.jackson.internal.JacksonMapperProvider; import com.arangodb.serde.ArangoSerdeProvider; +import com.arangodb.serde.jackson.internal.JacksonMapperProvider; +import com.arangodb.serde.jackson.internal.JacksonSerdeImpl; import com.fasterxml.jackson.databind.ObjectMapper; public class JacksonSerdeProvider implements ArangoSerdeProvider { /** * Creates a new JacksonSerde with default settings for the specified data type. + * Registers all the Jackson modules ({@link com.fasterxml.jackson.databind.Module}) discovered via SPI. * * @param contentType serialization target data type * @return the created JacksonSerde */ @Override public JacksonSerde of(final ContentType contentType) { - return create(JacksonMapperProvider.of(contentType)); + JacksonSerde serde = create(JacksonMapperProvider.of(contentType)); + serde.configure(mapper -> mapper.registerModules(ObjectMapper.findModules())); + return serde; } /** diff --git a/jackson-serde/src/main/java/com/arangodb/serde/jackson/internal/JacksonMapperProvider.java b/jackson-serde/src/main/java/com/arangodb/serde/jackson/internal/JacksonMapperProvider.java index b961b009d..936192d0e 100644 --- a/jackson-serde/src/main/java/com/arangodb/serde/jackson/internal/JacksonMapperProvider.java +++ b/jackson-serde/src/main/java/com/arangodb/serde/jackson/internal/JacksonMapperProvider.java @@ -1,8 +1,11 @@ package com.arangodb.serde.jackson.internal; +import com.arangodb.ArangoDBException; import com.arangodb.ContentType; +import com.fasterxml.jackson.core.JsonFactory; import com.fasterxml.jackson.databind.ObjectMapper; +import java.util.ServiceLoader; import java.util.function.Supplier; /** @@ -10,12 +13,22 @@ */ public interface JacksonMapperProvider extends Supplier { static ObjectMapper of(final ContentType contentType) { + String formatName; if (contentType == ContentType.JSON) { - return JsonJacksonMapperProvider.INSTANCE.get(); + formatName = "JSON"; } else if (contentType == ContentType.VPACK) { - return VPackJacksonMapperProvider.INSTANCE.get(); + formatName = "Velocypack"; } else { throw new IllegalArgumentException("Unexpected value: " + contentType); } + + ServiceLoader sl = ServiceLoader.load(JsonFactory.class); + for (JsonFactory jf : sl) { + if(formatName.equals(jf.getFormatName())){ + return new ObjectMapper(jf); + } + } + + throw new ArangoDBException("No JsonFactory found for content type: " + contentType); } } diff --git a/jackson-serde/src/main/java/com/arangodb/serde/jackson/internal/JsonJacksonMapperProvider.java b/jackson-serde/src/main/java/com/arangodb/serde/jackson/internal/JsonJacksonMapperProvider.java deleted file mode 100644 index c2e1c4afd..000000000 --- a/jackson-serde/src/main/java/com/arangodb/serde/jackson/internal/JsonJacksonMapperProvider.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.arangodb.serde.jackson.internal; - -import com.fasterxml.jackson.databind.ObjectMapper; - -/** - * Not shaded in arangodb-java-driver-shaded. - */ -enum JsonJacksonMapperProvider implements JacksonMapperProvider { - INSTANCE; - - @Override - public ObjectMapper get() { - return new ObjectMapper(); - } -} diff --git a/jackson-serde/src/main/java/com/arangodb/serde/jackson/internal/VPackJacksonMapperProvider.java b/jackson-serde/src/main/java/com/arangodb/serde/jackson/internal/VPackJacksonMapperProvider.java deleted file mode 100644 index d44ed0a2d..000000000 --- a/jackson-serde/src/main/java/com/arangodb/serde/jackson/internal/VPackJacksonMapperProvider.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.arangodb.serde.jackson.internal; - -import com.arangodb.jackson.dataformat.velocypack.VPackMapper; -import com.fasterxml.jackson.databind.ObjectMapper; - -/** - * Not shaded in arangodb-java-driver-shaded. - */ -enum VPackJacksonMapperProvider implements JacksonMapperProvider { - INSTANCE; - - @Override - public ObjectMapper get() { - return new VPackMapper(); - } -} diff --git a/jsonb-serde/pom.xml b/jsonb-serde/pom.xml index ea16f025c..b28ea81b6 100644 --- a/jsonb-serde/pom.xml +++ b/jsonb-serde/pom.xml @@ -6,7 +6,7 @@ com.arangodb arangodb-java-driver-parent - 7.0.0-ALPHA.1 + 7.0.0-ALPHA.2 jsonb-serde @@ -22,7 +22,7 @@ com.arangodb - serde-api + core provided diff --git a/pom.xml b/pom.xml index ece44143b..c17fb6232 100644 --- a/pom.xml +++ b/pom.xml @@ -5,13 +5,15 @@ com.arangodb arangodb-java-driver-parent - 7.0.0-ALPHA.1 + 7.0.0-ALPHA.2 2016 + core driver shaded jackson-serde - serde-api + http + vst pom @@ -98,20 +100,6 @@ import pom - - io.vertx - vertx-stack-depchain - 4.3.5 - pom - import - - - io.netty - netty-bom - 4.1.85.Final - pom - import - org.junit junit-bom @@ -126,7 +114,17 @@ com.arangodb - serde-api + core + ${project.version} + + + com.arangodb + http-protocol + ${project.version} + + + com.arangodb + vst-protocol ${project.version} @@ -144,10 +142,15 @@ arangodb-java-driver-shaded ${project.version} + + com.arangodb + velocypack + 3.0.0 + com.arangodb jackson-dataformat-velocypack - 3.1.0 + 4.0.0 org.slf4j @@ -291,6 +294,8 @@ + ${project.name} + ${project.version} ${moduleName} diff --git a/resilience-tests/pom.xml b/resilience-tests/pom.xml index b323cb36b..8d379f9bf 100644 --- a/resilience-tests/pom.xml +++ b/resilience-tests/pom.xml @@ -5,7 +5,7 @@ arangodb-java-driver-parent com.arangodb - 7.0.0-ALPHA.1 + 7.0.0-ALPHA.2 4.0.0 diff --git a/serde-api/pom.xml b/serde-api/pom.xml deleted file mode 100644 index 67003f219..000000000 --- a/serde-api/pom.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - 4.0.0 - - com.arangodb - arangodb-java-driver-parent - 7.0.0-ALPHA.1 - - - serde-api - serde-api - Serde API module for ArangoDB Java Driver - - - com.arangodb.serde - - - \ No newline at end of file diff --git a/shaded-integration-tests/pom.xml b/shaded-integration-tests/pom.xml index a32599b1b..bbbcf47b9 100644 --- a/shaded-integration-tests/pom.xml +++ b/shaded-integration-tests/pom.xml @@ -7,7 +7,7 @@ com.arangodb arangodb-java-driver-parent - 7.0.0-ALPHA.1 + 7.0.0-ALPHA.2 shaded-integration-tests @@ -46,12 +46,6 @@ com.arangodb arangodb-java-driver-shaded - - - com.arangodb - jackson-serde - - com.arangodb @@ -101,12 +95,6 @@ com.arangodb arangodb-java-driver-shaded - - - com.arangodb - jackson-serde - - com.arangodb diff --git a/shaded-integration-tests/src/test/jsonb/java/arch/RelocationsTest.java b/shaded-integration-tests/src/test/jsonb/java/arch/RelocationsTest.java index db2516a94..b78a416bb 100644 --- a/shaded-integration-tests/src/test/jsonb/java/arch/RelocationsTest.java +++ b/shaded-integration-tests/src/test/jsonb/java/arch/RelocationsTest.java @@ -35,14 +35,6 @@ public class RelocationsTest { .should().dependOnClassesThat() .resideInAPackage("com.arangodb.jackson.dataformat.velocypack.."); - @ArchTest - public static final ArchRule noVelocypackDependency = noClasses().that() - .resideInAPackage("com.arangodb..").and() - .resideOutsideOfPackage("..velocystream..").and() - .resideOutsideOfPackage("com.arangodb.shaded.jackson.dataformat.velocypack..") - .should().dependOnClassesThat() - .resideInAPackage("com.arangodb.velocypack.."); - @ArchTest // jsonb-serde is accessed via SPI public static final ArchRule noExplicitDependencyOnJsonbSerde = noClasses().that() diff --git a/shaded-integration-tests/src/test/native/java/com/arangodb/async/serde/CustomSerdeTest.java b/shaded-integration-tests/src/test/native/java/com/arangodb/async/serde/CustomSerdeTest.java index fdca9d3c0..6756ef847 100644 --- a/shaded-integration-tests/src/test/native/java/com/arangodb/async/serde/CustomSerdeTest.java +++ b/shaded-integration-tests/src/test/native/java/com/arangodb/async/serde/CustomSerdeTest.java @@ -65,7 +65,7 @@ void init() throws ExecutionException, InterruptedException { }); ArangoDBAsync arangoDB = new ArangoDBAsync.Builder() .loadProperties(ConfigUtils.loadConfig()) - .serializer(serde).build(); + .serde(serde).build(); DbName TEST_DB = DbName.of("custom-serde-test"); db = arangoDB.db(TEST_DB); diff --git a/shaded-integration-tests/src/test/native/java/com/arangodb/internal/velocystream/CommunicationTest.java b/shaded-integration-tests/src/test/native/java/com/arangodb/internal/velocystream/CommunicationTest.java index 120939786..58a87bd71 100644 --- a/shaded-integration-tests/src/test/native/java/com/arangodb/internal/velocystream/CommunicationTest.java +++ b/shaded-integration-tests/src/test/native/java/com/arangodb/internal/velocystream/CommunicationTest.java @@ -102,15 +102,6 @@ void multiThreadSameDatabases() throws Exception { assertThat(result.size()).isEqualTo(2); } - @Test - void minOneConnection() { - final ArangoDB arangoDB = new ArangoDB.Builder() - .loadProperties(ConfigUtils.loadConfig()) - .maxConnections(0).build(); - final ArangoDBVersion version = arangoDB.getVersion(); - assertThat(version).isNotNull(); - } - @Test void defaultMaxConnection() { final ArangoDB arangoDB = new ArangoDB.Builder() diff --git a/shaded/pom.xml b/shaded/pom.xml index 81fc19503..40db119e9 100644 --- a/shaded/pom.xml +++ b/shaded/pom.xml @@ -7,7 +7,7 @@ com.arangodb arangodb-java-driver-parent - 7.0.0-ALPHA.1 + 7.0.0-ALPHA.2 arangodb-java-driver-shaded @@ -22,21 +22,19 @@ com.arangodb - arangodb-java-driver - - - com.arangodb - serde-api - - + core com.arangodb - jackson-dataformat-velocypack + http-protocol + + + com.arangodb + vst-protocol com.arangodb - jackson-serde + jackson-dataformat-velocypack org.slf4j @@ -66,15 +64,9 @@ org.slf4j:slf4j-api - com.arangodb:jackson-serde - com.arangodb:velocypack - - io.netty - com.arangodb.shaded.netty - com.fasterxml.jackson com.arangodb.shaded.fasterxml.jackson @@ -83,6 +75,10 @@ com.arangodb.jackson.dataformat.velocypack com.arangodb.shaded.jackson.dataformat.velocypack + + io.netty + com.arangodb.shaded.netty + io.vertx com.arangodb.shaded.vertx @@ -90,10 +86,28 @@ - com.arangodb:arangodb-java-driver + com.arangodb:core + + META-INF/** + + + + com.arangodb:vst-protocol + + META-INF/** + + + + com.arangodb:http-protocol META-INF/MANIFEST.MF - META-INF/native-image/** + META-INF/services/** + + + + com.arangodb:velocypack + + META-INF/** @@ -113,7 +127,6 @@ io.netty:* META-INF/** - module-info.class @@ -122,7 +135,6 @@ *.adoc examples/** META-INF/** - module-info.class @@ -166,7 +178,9 @@ ${project.build.directory}/shaded-sources - com.arangodb.shaded.**,**.internal** + + com.arangodb.shaded.**,**.internal**,com.arangodb.vst.**,com.arangodb.http.**,com.arangodb.velocypack.** + diff --git a/shaded/src/main/resources/META-INF/services/com.arangodb.internal.net.AsyncProtocolProvider b/shaded/src/main/resources/META-INF/services/com.arangodb.internal.net.AsyncProtocolProvider new file mode 100644 index 000000000..dc7f09560 --- /dev/null +++ b/shaded/src/main/resources/META-INF/services/com.arangodb.internal.net.AsyncProtocolProvider @@ -0,0 +1 @@ +com.arangodb.vst.VstAsyncProtocolProvider diff --git a/shaded/src/main/resources/META-INF/services/com.arangodb.internal.net.ProtocolProvider b/shaded/src/main/resources/META-INF/services/com.arangodb.internal.net.ProtocolProvider new file mode 100644 index 000000000..faf8cac63 --- /dev/null +++ b/shaded/src/main/resources/META-INF/services/com.arangodb.internal.net.ProtocolProvider @@ -0,0 +1,2 @@ +com.arangodb.http.HttpProtocolProvider +com.arangodb.vst.VstProtocolProvider diff --git a/shaded/src/main/resources/META-INF/services/com.arangodb.shaded.fasterxml.jackson.core.JsonFactory b/shaded/src/main/resources/META-INF/services/com.arangodb.shaded.fasterxml.jackson.core.JsonFactory new file mode 100644 index 000000000..89123f5a5 --- /dev/null +++ b/shaded/src/main/resources/META-INF/services/com.arangodb.shaded.fasterxml.jackson.core.JsonFactory @@ -0,0 +1,2 @@ +com.arangodb.shaded.fasterxml.jackson.core.JsonFactory +com.arangodb.shaded.jackson.dataformat.velocypack.VPackFactory diff --git a/tutorial/gradle/build.gradle b/tutorial/gradle/build.gradle index 759ef5fbc..fad8b8db1 100644 --- a/tutorial/gradle/build.gradle +++ b/tutorial/gradle/build.gradle @@ -10,5 +10,5 @@ repositories { } dependencies { - implementation 'com.arangodb:arangodb-java-driver:7.0.0-ALPHA.1' + implementation 'com.arangodb:arangodb-java-driver:7.0.0-ALPHA.2' } diff --git a/tutorial/maven/pom.xml b/tutorial/maven/pom.xml index 5e4a51329..5154baa86 100644 --- a/tutorial/maven/pom.xml +++ b/tutorial/maven/pom.xml @@ -19,7 +19,7 @@ com.arangodb arangodb-java-driver - 7.0.0-ALPHA.1 + 7.0.0-ALPHA.2 diff --git a/vst/pom.xml b/vst/pom.xml new file mode 100644 index 000000000..76943f277 --- /dev/null +++ b/vst/pom.xml @@ -0,0 +1,33 @@ + + + 4.0.0 + + com.arangodb + arangodb-java-driver-parent + 7.0.0-ALPHA.2 + + + vst-protocol + vst-protocol + VST Protocol module for ArangoDB Java Driver + + + false + com.arangodb.vst + + + + + com.arangodb + core + provided + + + com.arangodb + velocypack + + + + \ No newline at end of file diff --git a/vst/src/main/java/com/arangodb/vst/VstAsyncProtocolProvider.java b/vst/src/main/java/com/arangodb/vst/VstAsyncProtocolProvider.java new file mode 100644 index 000000000..8bb1a19d9 --- /dev/null +++ b/vst/src/main/java/com/arangodb/vst/VstAsyncProtocolProvider.java @@ -0,0 +1,30 @@ +package com.arangodb.vst; + +import com.arangodb.Protocol; +import com.arangodb.internal.config.ArangoConfig; +import com.arangodb.internal.net.*; +import com.arangodb.vst.async.VstCommunicationAsync; +import com.arangodb.vst.async.VstConnectionFactoryAsync; +import com.fasterxml.jackson.databind.Module; + +public class VstAsyncProtocolProvider implements AsyncProtocolProvider { + @Override + public boolean supportsProtocol(Protocol protocol) { + return Protocol.VST.equals(protocol); + } + + @Override + public ConnectionFactory createConnectionFactory() { + return new VstConnectionFactoryAsync(); + } + + @Override + public AsyncCommunication createCommunication(final ArangoConfig config, final HostHandler hostHandler) { + return new VstCommunicationAsync(config, hostHandler); + } + + @Override + public Module protocolModule() { + return VstModule.INSTANCE.get(); + } +} diff --git a/driver/src/main/java/com/arangodb/internal/velocystream/VstCommunication.java b/vst/src/main/java/com/arangodb/vst/VstCommunication.java similarity index 86% rename from driver/src/main/java/com/arangodb/internal/velocystream/VstCommunication.java rename to vst/src/main/java/com/arangodb/vst/VstCommunication.java index 9276834bc..d90510f6d 100644 --- a/driver/src/main/java/com/arangodb/internal/velocystream/VstCommunication.java +++ b/vst/src/main/java/com/arangodb/vst/VstCommunication.java @@ -18,11 +18,12 @@ * Copyright holder is ArangoDB GmbH, Cologne, Germany */ -package com.arangodb.internal.velocystream; +package com.arangodb.vst; import com.arangodb.ArangoDBException; -import com.arangodb.config.ArangoConfigProperties; -import com.arangodb.internal.ArangoDefaults; +import com.arangodb.internal.InternalRequest; +import com.arangodb.internal.InternalResponse; +import com.arangodb.internal.config.ArangoConfig; import com.arangodb.internal.net.AccessType; import com.arangodb.internal.net.Host; import com.arangodb.internal.net.HostHandle; @@ -30,17 +31,14 @@ import com.arangodb.internal.serde.InternalSerde; import com.arangodb.internal.util.RequestUtils; import com.arangodb.internal.util.ResponseUtils; -import com.arangodb.internal.velocystream.internal.Chunk; -import com.arangodb.internal.velocystream.internal.Message; -import com.arangodb.internal.velocystream.internal.VstConnection; import com.arangodb.velocypack.VPackSlice; import com.arangodb.velocypack.exception.VPackParserException; -import com.arangodb.internal.InternalRequest; -import com.arangodb.internal.InternalResponse; +import com.arangodb.vst.internal.Chunk; +import com.arangodb.vst.internal.Message; +import com.arangodb.vst.internal.VstConnection; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import javax.net.ssl.SSLContext; import java.io.Closeable; import java.io.IOException; import java.util.ArrayList; @@ -56,7 +54,7 @@ public abstract class VstCommunication> implements protected static final String ENCRYPTION_JWT = "jwt"; protected static final AtomicLong mId = new AtomicLong(0L); private static final Logger LOGGER = LoggerFactory.getLogger(VstCommunication.class); - protected final InternalSerde util; + protected final InternalSerde serde; protected final String user; protected final String password; @@ -64,15 +62,13 @@ public abstract class VstCommunication> implements protected final HostHandler hostHandler; protected volatile String jwt; - protected VstCommunication(final Integer timeout, final String user, final String password, final String jwt, - final Boolean useSsl, final SSLContext sslContext, final InternalSerde util, - final Integer chunksize, final HostHandler hostHandler) { - this.user = user; - this.password = password; - this.jwt = jwt; - this.util = util; + protected VstCommunication(final ArangoConfig config, final HostHandler hostHandler) { + user = config.getUser(); + password = config.getPassword(); + jwt = config.getJwt(); + serde = config.getInternalSerde(); + chunksize = config.getChunkSize(); this.hostHandler = hostHandler; - this.chunksize = chunksize; } @SuppressWarnings("unchecked") @@ -153,11 +149,11 @@ protected R execute(final InternalRequest request, final HostHandle hostHandle, protected abstract R execute(final InternalRequest request, C connection, final int attemptCount); protected void checkError(final InternalResponse response) { - ResponseUtils.checkError(util, response); + ResponseUtils.checkError(serde, response); } protected InternalResponse createResponse(final Message message) throws VPackParserException { - final InternalResponse response = util.deserialize(message.getHead().toByteArray(), InternalResponse.class); + final InternalResponse response = serde.deserialize(message.getHead().toByteArray(), InternalResponse.class); if (message.getBody() != null) { response.setBody(message.getBody().toByteArray()); } @@ -168,7 +164,7 @@ protected final Message createMessage(final InternalRequest request) throws VPac request.putHeaderParam("accept", "application/x-velocypack"); request.putHeaderParam("content-type", "application/x-velocypack"); final long id = mId.incrementAndGet(); - return new Message(id, util.serialize(request), request.getBody()); + return new Message(id, serde.serialize(request), request.getBody()); } protected Collection buildChunks(final Message message) { @@ -197,5 +193,4 @@ public void setJwt(String jwt) { this.jwt = jwt; } - } diff --git a/driver/src/main/java/com/arangodb/internal/velocystream/VstCommunicationSync.java b/vst/src/main/java/com/arangodb/vst/VstCommunicationSync.java similarity index 51% rename from driver/src/main/java/com/arangodb/internal/velocystream/VstCommunicationSync.java rename to vst/src/main/java/com/arangodb/vst/VstCommunicationSync.java index f8416c74c..97b7671c7 100644 --- a/driver/src/main/java/com/arangodb/internal/velocystream/VstCommunicationSync.java +++ b/vst/src/main/java/com/arangodb/vst/VstCommunicationSync.java @@ -18,27 +18,25 @@ * Copyright holder is ArangoDB GmbH, Cologne, Germany */ -package com.arangodb.internal.velocystream; +package com.arangodb.vst; import com.arangodb.ArangoDBException; -import com.arangodb.internal.net.ArangoDBRedirectException; import com.arangodb.config.HostDescription; +import com.arangodb.internal.InternalRequest; +import com.arangodb.internal.InternalResponse; +import com.arangodb.internal.config.ArangoConfig; +import com.arangodb.internal.net.ArangoDBRedirectException; import com.arangodb.internal.net.HostHandle; import com.arangodb.internal.net.HostHandler; -import com.arangodb.internal.serde.InternalSerde; import com.arangodb.internal.util.HostUtils; -import com.arangodb.internal.velocystream.internal.AuthenticationRequest; -import com.arangodb.internal.velocystream.internal.JwtAuthenticationRequest; -import com.arangodb.internal.velocystream.internal.Message; -import com.arangodb.internal.velocystream.internal.VstConnectionSync; import com.arangodb.velocypack.exception.VPackParserException; -import com.arangodb.internal.InternalRequest; -import com.arangodb.internal.InternalResponse; +import com.arangodb.vst.internal.AuthenticationRequest; +import com.arangodb.vst.internal.JwtAuthenticationRequest; +import com.arangodb.vst.internal.Message; +import com.arangodb.vst.internal.VstConnectionSync; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import javax.net.ssl.SSLContext; - /** * @author Mark Vollmary */ @@ -46,11 +44,8 @@ public class VstCommunicationSync extends VstCommunication build(final InternalSerde util) { - return new VstCommunicationSync(hostHandler, timeout, user, password, jwt, useSsl, sslContext, util, - chunksize, - maxConnections, connectionTtl); - } - - } - } diff --git a/driver/src/main/java/com/arangodb/internal/velocystream/VstConnectionFactorySync.java b/vst/src/main/java/com/arangodb/vst/VstConnectionFactorySync.java similarity index 52% rename from driver/src/main/java/com/arangodb/internal/velocystream/VstConnectionFactorySync.java rename to vst/src/main/java/com/arangodb/vst/VstConnectionFactorySync.java index 713e5a422..0ab5860aa 100644 --- a/driver/src/main/java/com/arangodb/internal/velocystream/VstConnectionFactorySync.java +++ b/vst/src/main/java/com/arangodb/vst/VstConnectionFactorySync.java @@ -18,35 +18,21 @@ * Copyright holder is ArangoDB GmbH, Cologne, Germany */ -package com.arangodb.internal.velocystream; +package com.arangodb.vst; +import com.arangodb.config.HostDescription; +import com.arangodb.internal.config.ArangoConfig; import com.arangodb.internal.net.Connection; import com.arangodb.internal.net.ConnectionFactory; -import com.arangodb.config.HostDescription; -import com.arangodb.internal.velocystream.internal.MessageStore; -import com.arangodb.internal.velocystream.internal.VstConnectionSync; - -import javax.net.ssl.SSLContext; +import com.arangodb.vst.internal.VstConnectionSync; /** * @author Mark Vollmary */ public class VstConnectionFactorySync implements ConnectionFactory { - private final VstConnectionSync.Builder builder; - - public VstConnectionFactorySync(final Integer timeout, final Long connectionTtl, - final Integer keepAliveInterval, final Boolean useSsl, - final SSLContext sslContext) { - super(); - builder = new VstConnectionSync.Builder().timeout(timeout).ttl(connectionTtl) - .keepAliveInterval(keepAliveInterval).useSsl(useSsl) - .sslContext(sslContext); - } - @Override - public Connection create(final HostDescription host) { - return builder.messageStore(new MessageStore()).host(host).build(); + public Connection create(final ArangoConfig config, final HostDescription host) { + return new VstConnectionSync(config, host); } - } diff --git a/vst/src/main/java/com/arangodb/vst/VstModule.java b/vst/src/main/java/com/arangodb/vst/VstModule.java new file mode 100644 index 000000000..255a041fd --- /dev/null +++ b/vst/src/main/java/com/arangodb/vst/VstModule.java @@ -0,0 +1,26 @@ +package com.arangodb.vst; + +import com.arangodb.vst.internal.AuthenticationRequest; +import com.arangodb.vst.internal.JwtAuthenticationRequest; +import com.fasterxml.jackson.databind.Module; +import com.fasterxml.jackson.databind.module.SimpleModule; + +import java.util.function.Supplier; + +enum VstModule implements Supplier { + INSTANCE; + + private final SimpleModule module; + + VstModule() { + module = new SimpleModule(); + module.addSerializer(AuthenticationRequest.class, VstSerializers.AUTHENTICATION_REQUEST); + module.addSerializer(JwtAuthenticationRequest.class, VstSerializers.JWT_AUTHENTICATION_REQUEST); + } + + @Override + public Module get() { + return module; + } + +} diff --git a/driver/src/main/java/com/arangodb/internal/velocystream/VstProtocol.java b/vst/src/main/java/com/arangodb/vst/VstProtocol.java similarity index 93% rename from driver/src/main/java/com/arangodb/internal/velocystream/VstProtocol.java rename to vst/src/main/java/com/arangodb/vst/VstProtocol.java index 4782cea74..3642f1826 100644 --- a/driver/src/main/java/com/arangodb/internal/velocystream/VstProtocol.java +++ b/vst/src/main/java/com/arangodb/vst/VstProtocol.java @@ -18,13 +18,13 @@ * Copyright holder is ArangoDB GmbH, Cologne, Germany */ -package com.arangodb.internal.velocystream; +package com.arangodb.vst; import com.arangodb.internal.net.CommunicationProtocol; import com.arangodb.internal.net.HostHandle; -import com.arangodb.internal.velocystream.internal.VstConnectionSync; import com.arangodb.internal.InternalRequest; import com.arangodb.internal.InternalResponse; +import com.arangodb.vst.internal.VstConnectionSync; import java.io.IOException; diff --git a/vst/src/main/java/com/arangodb/vst/VstProtocolProvider.java b/vst/src/main/java/com/arangodb/vst/VstProtocolProvider.java new file mode 100644 index 000000000..8a6341fc7 --- /dev/null +++ b/vst/src/main/java/com/arangodb/vst/VstProtocolProvider.java @@ -0,0 +1,32 @@ +package com.arangodb.vst; + +import com.arangodb.Protocol; +import com.arangodb.internal.config.ArangoConfig; +import com.arangodb.internal.net.CommunicationProtocol; +import com.arangodb.internal.net.ConnectionFactory; +import com.arangodb.internal.net.HostHandler; +import com.arangodb.internal.net.ProtocolProvider; +import com.fasterxml.jackson.databind.Module; + +public class VstProtocolProvider implements ProtocolProvider { + @Override + public boolean supportsProtocol(Protocol protocol) { + return Protocol.VST.equals(protocol); + } + + @Override + public ConnectionFactory createConnectionFactory() { + return new VstConnectionFactorySync(); + } + + @Override + public CommunicationProtocol createProtocol(ArangoConfig config, HostHandler hostHandler) { + return new VstProtocol(new VstCommunicationSync(config, hostHandler)); + } + + @Override + public Module protocolModule() { + return VstModule.INSTANCE.get(); + } + +} diff --git a/vst/src/main/java/com/arangodb/vst/VstSerializers.java b/vst/src/main/java/com/arangodb/vst/VstSerializers.java new file mode 100644 index 000000000..72289ec42 --- /dev/null +++ b/vst/src/main/java/com/arangodb/vst/VstSerializers.java @@ -0,0 +1,40 @@ +package com.arangodb.vst; + +import com.arangodb.vst.internal.AuthenticationRequest; +import com.arangodb.vst.internal.JwtAuthenticationRequest; +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.databind.JsonSerializer; +import com.fasterxml.jackson.databind.SerializerProvider; + +import java.io.IOException; + +public final class VstSerializers { + + static final JsonSerializer AUTHENTICATION_REQUEST = + new JsonSerializer() { + @Override + public void serialize(AuthenticationRequest value, JsonGenerator gen, SerializerProvider serializers) throws IOException { + gen.writeStartArray(); + gen.writeNumber(value.getVersion()); + gen.writeNumber(value.getType()); + gen.writeString(value.getEncryption()); + gen.writeString(value.getUser()); + gen.writeString(value.getPassword()); + gen.writeEndArray(); + } + }; + static final JsonSerializer JWT_AUTHENTICATION_REQUEST = + new JsonSerializer() { + @Override + public void serialize(JwtAuthenticationRequest value, JsonGenerator gen, + SerializerProvider serializers) throws IOException { + gen.writeStartArray(); + gen.writeNumber(value.getVersion()); + gen.writeNumber(value.getType()); + gen.writeString(value.getEncryption()); + gen.writeString(value.getToken()); + gen.writeEndArray(); + } + }; + +} diff --git a/driver/src/main/java/com/arangodb/async/internal/velocystream/VstCommunicationAsync.java b/vst/src/main/java/com/arangodb/vst/async/VstCommunicationAsync.java similarity index 64% rename from driver/src/main/java/com/arangodb/async/internal/velocystream/VstCommunicationAsync.java rename to vst/src/main/java/com/arangodb/vst/async/VstCommunicationAsync.java index bc111aa63..c787c0cbf 100644 --- a/driver/src/main/java/com/arangodb/async/internal/velocystream/VstCommunicationAsync.java +++ b/vst/src/main/java/com/arangodb/vst/async/VstCommunicationAsync.java @@ -18,42 +18,41 @@ * Copyright holder is ArangoDB GmbH, Cologne, Germany */ -package com.arangodb.async.internal.velocystream; +package com.arangodb.vst.async; import com.arangodb.ArangoDBException; -import com.arangodb.internal.net.ArangoDBRedirectException; import com.arangodb.config.HostDescription; +import com.arangodb.internal.InternalRequest; +import com.arangodb.internal.InternalResponse; +import com.arangodb.internal.config.ArangoConfig; +import com.arangodb.internal.net.ArangoDBRedirectException; +import com.arangodb.internal.net.AsyncCommunication; import com.arangodb.internal.net.HostHandle; import com.arangodb.internal.net.HostHandler; -import com.arangodb.internal.serde.InternalSerde; import com.arangodb.internal.util.HostUtils; -import com.arangodb.internal.velocystream.VstCommunication; -import com.arangodb.internal.velocystream.internal.AuthenticationRequest; -import com.arangodb.internal.velocystream.internal.JwtAuthenticationRequest; -import com.arangodb.internal.velocystream.internal.Message; import com.arangodb.velocypack.exception.VPackException; import com.arangodb.velocypack.exception.VPackParserException; -import com.arangodb.internal.InternalRequest; -import com.arangodb.internal.InternalResponse; +import com.arangodb.vst.VstCommunication; +import com.arangodb.vst.internal.AuthenticationRequest; +import com.arangodb.vst.internal.JwtAuthenticationRequest; +import com.arangodb.vst.internal.Message; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import javax.net.ssl.SSLContext; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; /** * @author Mark Vollmary */ -public class VstCommunicationAsync extends VstCommunication, VstConnectionAsync> { +public class VstCommunicationAsync + extends VstCommunication, VstConnectionAsync> + implements AsyncCommunication { private static final Logger LOGGER = LoggerFactory.getLogger(VstCommunicationAsync.class); - private VstCommunicationAsync(final HostHandler hostHandler, final Integer timeout, final String user, - final String password, final String jwt, final Boolean useSsl, - final SSLContext sslContext, final InternalSerde util, - final Integer chunksize, final Integer maxConnections, final Long connectionTtl) { - super(timeout, user, password, jwt, useSsl, sslContext, util, chunksize, hostHandler); + public VstCommunicationAsync(ArangoConfig config, HostHandler hostHandler) { + super(config, hostHandler); } @Override @@ -68,7 +67,7 @@ protected CompletableFuture execute(final InternalRequest requ try { final Message message = createMessage(request); if (LOGGER.isDebugEnabled()) { - String body = request.getBody() == null ? "" : util.toJsonString(request.getBody()); + String body = request.getBody() == null ? "" : serde.toJsonString(request.getBody()); LOGGER.debug("Send Request [id={}]: {} {}", message.getId(), request, body); } send(message, connection).whenComplete((m, ex) -> { @@ -107,7 +106,7 @@ protected CompletableFuture execute(final InternalRequest requ rfuture.completeExceptionally(e); } if (LOGGER.isDebugEnabled()) { - String body = response.getBody() == null ? "" : util.toJsonString(response.getBody()); + String body = response.getBody() == null ? "" : serde.toJsonString(response.getBody()); LOGGER.debug("Received Response [id={}]: {} {}", m.getId(), response, body); } rfuture.complete(response); @@ -155,74 +154,4 @@ protected void authenticate(final VstConnectionAsync connection) { checkError(response); } - public static class Builder { - - private final HostHandler hostHandler; - private Integer timeout; - private Long connectionTtl; - private String user; - private String password; - private String jwt; - private Boolean useSsl; - private SSLContext sslContext; - private Integer chunksize; - private Integer maxConnections; - - public Builder(final HostHandler hostHandler) { - super(); - this.hostHandler = hostHandler; - } - - public Builder timeout(final Integer timeout) { - this.timeout = timeout; - return this; - } - - public Builder user(final String user) { - this.user = user; - return this; - } - - public Builder password(final String password) { - this.password = password; - return this; - } - - public Builder jwt(final String jwt) { - this.jwt = jwt; - return this; - } - - public Builder useSsl(final Boolean useSsl) { - this.useSsl = useSsl; - return this; - } - - public Builder sslContext(final SSLContext sslContext) { - this.sslContext = sslContext; - return this; - } - - public Builder chunksize(final Integer chunksize) { - this.chunksize = chunksize; - return this; - } - - public Builder maxConnections(final Integer maxConnections) { - this.maxConnections = maxConnections; - return this; - } - - public Builder connectionTtl(final Long connectionTtl) { - this.connectionTtl = connectionTtl; - return this; - } - - public VstCommunicationAsync build(final InternalSerde util) { - return new VstCommunicationAsync(hostHandler, timeout, user, password, jwt, useSsl, sslContext, util, - chunksize, - maxConnections, connectionTtl); - } - } - } diff --git a/vst/src/main/java/com/arangodb/vst/async/VstConnectionAsync.java b/vst/src/main/java/com/arangodb/vst/async/VstConnectionAsync.java new file mode 100644 index 000000000..41e6265d3 --- /dev/null +++ b/vst/src/main/java/com/arangodb/vst/async/VstConnectionAsync.java @@ -0,0 +1,69 @@ +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed 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. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.vst.async; + +import com.arangodb.async.internal.utils.CompletableFutureUtils; +import com.arangodb.config.HostDescription; +import com.arangodb.internal.config.ArangoConfig; +import com.arangodb.vst.internal.Chunk; +import com.arangodb.vst.internal.Message; +import com.arangodb.vst.internal.VstConnection; + +import java.util.Collection; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.FutureTask; +import java.util.concurrent.TimeUnit; + +/** + * @author Mark Vollmary + */ +public class VstConnectionAsync extends VstConnection> { + + VstConnectionAsync(final ArangoConfig config, final HostDescription host) { + super(config, host); + } + + @Override + public synchronized CompletableFuture write(final Message message, final Collection chunks) { + final CompletableFuture future = new CompletableFuture<>(); + final FutureTask task = new FutureTask<>(() -> { + try { + future.complete(messageStore.get(message.getId())); + } catch (final Exception e) { + future.completeExceptionally(e); + } + return null; + }); + messageStore.storeMessage(message.getId(), task); + super.writeIntern(message, chunks); + if (timeout == null || timeout == 0L) { + return future; + } else { + return CompletableFutureUtils.orTimeout(future, timeout, TimeUnit.MILLISECONDS); + } + } + + @Override + protected void doKeepAlive() { + sendKeepAlive().join(); + } + +} diff --git a/driver/src/main/java/com/arangodb/async/internal/velocystream/VstConnectionFactoryAsync.java b/vst/src/main/java/com/arangodb/vst/async/VstConnectionFactoryAsync.java similarity index 54% rename from driver/src/main/java/com/arangodb/async/internal/velocystream/VstConnectionFactoryAsync.java rename to vst/src/main/java/com/arangodb/vst/async/VstConnectionFactoryAsync.java index 72018d182..3c02a24fd 100644 --- a/driver/src/main/java/com/arangodb/async/internal/velocystream/VstConnectionFactoryAsync.java +++ b/vst/src/main/java/com/arangodb/vst/async/VstConnectionFactoryAsync.java @@ -18,34 +18,20 @@ * Copyright holder is ArangoDB GmbH, Cologne, Germany */ -package com.arangodb.async.internal.velocystream; +package com.arangodb.vst.async; +import com.arangodb.config.HostDescription; +import com.arangodb.internal.config.ArangoConfig; import com.arangodb.internal.net.Connection; import com.arangodb.internal.net.ConnectionFactory; -import com.arangodb.config.HostDescription; -import com.arangodb.internal.velocystream.internal.MessageStore; - -import javax.net.ssl.SSLContext; /** * @author Mark Vollmary */ public class VstConnectionFactoryAsync implements ConnectionFactory { - private final VstConnectionAsync.Builder builder; - - public VstConnectionFactoryAsync(final Integer timeout, final Long connectionTtl, - final Integer keepAliveInterval, final Boolean useSsl, - final SSLContext sslContext) { - super(); - builder = new VstConnectionAsync.Builder().timeout(timeout).ttl(connectionTtl) - .keepAliveInterval(keepAliveInterval).useSsl(useSsl) - .sslContext(sslContext); - } - @Override - public Connection create(final HostDescription host) { - return builder.messageStore(new MessageStore()).host(host).build(); + public Connection create(final ArangoConfig config, final HostDescription host) { + return new VstConnectionAsync(config, host); } - } diff --git a/driver/src/main/java/com/arangodb/internal/velocystream/internal/AuthenticationRequest.java b/vst/src/main/java/com/arangodb/vst/internal/AuthenticationRequest.java similarity index 96% rename from driver/src/main/java/com/arangodb/internal/velocystream/internal/AuthenticationRequest.java rename to vst/src/main/java/com/arangodb/vst/internal/AuthenticationRequest.java index a7498e4ce..e57217011 100644 --- a/driver/src/main/java/com/arangodb/internal/velocystream/internal/AuthenticationRequest.java +++ b/vst/src/main/java/com/arangodb/vst/internal/AuthenticationRequest.java @@ -18,7 +18,7 @@ * Copyright holder is ArangoDB GmbH, Cologne, Germany */ -package com.arangodb.internal.velocystream.internal; +package com.arangodb.vst.internal; import com.arangodb.DbName; import com.arangodb.internal.InternalRequest; diff --git a/driver/src/main/java/com/arangodb/internal/velocystream/internal/Chunk.java b/vst/src/main/java/com/arangodb/vst/internal/Chunk.java similarity index 97% rename from driver/src/main/java/com/arangodb/internal/velocystream/internal/Chunk.java rename to vst/src/main/java/com/arangodb/vst/internal/Chunk.java index 294aa18bb..93e2d7848 100644 --- a/driver/src/main/java/com/arangodb/internal/velocystream/internal/Chunk.java +++ b/vst/src/main/java/com/arangodb/vst/internal/Chunk.java @@ -18,7 +18,7 @@ * Copyright holder is ArangoDB GmbH, Cologne, Germany */ -package com.arangodb.internal.velocystream.internal; +package com.arangodb.vst.internal; /** * @author Mark Vollmary diff --git a/driver/src/main/java/com/arangodb/internal/velocystream/internal/ChunkStore.java b/vst/src/main/java/com/arangodb/vst/internal/ChunkStore.java similarity index 97% rename from driver/src/main/java/com/arangodb/internal/velocystream/internal/ChunkStore.java rename to vst/src/main/java/com/arangodb/vst/internal/ChunkStore.java index e95be998b..a945ec79d 100644 --- a/driver/src/main/java/com/arangodb/internal/velocystream/internal/ChunkStore.java +++ b/vst/src/main/java/com/arangodb/vst/internal/ChunkStore.java @@ -18,7 +18,7 @@ * Copyright holder is ArangoDB GmbH, Cologne, Germany */ -package com.arangodb.internal.velocystream.internal; +package com.arangodb.vst.internal; import java.nio.BufferUnderflowException; import java.nio.ByteBuffer; diff --git a/driver/src/main/java/com/arangodb/internal/velocystream/internal/JwtAuthenticationRequest.java b/vst/src/main/java/com/arangodb/vst/internal/JwtAuthenticationRequest.java similarity index 91% rename from driver/src/main/java/com/arangodb/internal/velocystream/internal/JwtAuthenticationRequest.java rename to vst/src/main/java/com/arangodb/vst/internal/JwtAuthenticationRequest.java index 3d9fe56f9..982ee32df 100644 --- a/driver/src/main/java/com/arangodb/internal/velocystream/internal/JwtAuthenticationRequest.java +++ b/vst/src/main/java/com/arangodb/vst/internal/JwtAuthenticationRequest.java @@ -1,4 +1,4 @@ -package com.arangodb.internal.velocystream.internal; +package com.arangodb.vst.internal; import com.arangodb.DbName; import com.arangodb.internal.InternalRequest; diff --git a/driver/src/main/java/com/arangodb/internal/velocystream/internal/Message.java b/vst/src/main/java/com/arangodb/vst/internal/Message.java similarity index 97% rename from driver/src/main/java/com/arangodb/internal/velocystream/internal/Message.java rename to vst/src/main/java/com/arangodb/vst/internal/Message.java index b2b7cc34e..7b673fb68 100644 --- a/driver/src/main/java/com/arangodb/internal/velocystream/internal/Message.java +++ b/vst/src/main/java/com/arangodb/vst/internal/Message.java @@ -18,7 +18,7 @@ * Copyright holder is ArangoDB GmbH, Cologne, Germany */ -package com.arangodb.internal.velocystream.internal; +package com.arangodb.vst.internal; import com.arangodb.velocypack.VPackSlice; diff --git a/driver/src/main/java/com/arangodb/internal/velocystream/internal/MessageStore.java b/vst/src/main/java/com/arangodb/vst/internal/MessageStore.java similarity index 98% rename from driver/src/main/java/com/arangodb/internal/velocystream/internal/MessageStore.java rename to vst/src/main/java/com/arangodb/vst/internal/MessageStore.java index 9e9184a5c..7e8417205 100644 --- a/driver/src/main/java/com/arangodb/internal/velocystream/internal/MessageStore.java +++ b/vst/src/main/java/com/arangodb/vst/internal/MessageStore.java @@ -18,7 +18,7 @@ * Copyright holder is ArangoDB GmbH, Cologne, Germany */ -package com.arangodb.internal.velocystream.internal; +package com.arangodb.vst.internal; import com.arangodb.ArangoDBException; import org.slf4j.Logger; diff --git a/driver/src/main/java/com/arangodb/internal/velocystream/internal/VstConnection.java b/vst/src/main/java/com/arangodb/vst/internal/VstConnection.java similarity index 94% rename from driver/src/main/java/com/arangodb/internal/velocystream/internal/VstConnection.java rename to vst/src/main/java/com/arangodb/vst/internal/VstConnection.java index 29d80e0ea..59ce03e0c 100644 --- a/driver/src/main/java/com/arangodb/internal/velocystream/internal/VstConnection.java +++ b/vst/src/main/java/com/arangodb/vst/internal/VstConnection.java @@ -18,13 +18,13 @@ * Copyright holder is ArangoDB GmbH, Cologne, Germany */ -package com.arangodb.internal.velocystream.internal; +package com.arangodb.vst.internal; import com.arangodb.ArangoDBException; -import com.arangodb.config.ArangoConfigProperties; +import com.arangodb.config.HostDescription; import com.arangodb.internal.ArangoDefaults; +import com.arangodb.internal.config.ArangoConfig; import com.arangodb.internal.net.Connection; -import com.arangodb.config.HostDescription; import com.arangodb.velocypack.VPackBuilder; import com.arangodb.velocypack.VPackSlice; import com.arangodb.velocypack.ValueType; @@ -56,7 +56,7 @@ public abstract class VstConnection implements Connection { private static final Logger LOGGER = LoggerFactory.getLogger(VstConnection.class); private static final byte[] PROTOCOL_HEADER = "VST/1.0\r\n\r\n".getBytes(); - protected final MessageStore messageStore; + protected final MessageStore messageStore = new MessageStore(); protected final Integer timeout; private final AtomicLong keepAliveId = new AtomicLong(); private final Long ttl; @@ -87,21 +87,14 @@ public abstract class VstConnection implements Connection { private OutputStream outputStream; private InputStream inputStream; - protected VstConnection(final HostDescription host, - final Integer timeout, - final Long ttl, - final Integer keepAliveInterval, - final Boolean useSsl, - final SSLContext sslContext, - final MessageStore messageStore) { + protected VstConnection(final ArangoConfig config, final HostDescription host) { super(); + timeout = config.getTimeout(); + ttl = config.getConnectionTtl(); + keepAliveInterval = config.getKeepAliveInterval(); + useSsl = config.getUseSsl(); + sslContext = config.getSslContext(); this.host = host; - this.timeout = timeout; - this.ttl = ttl; - this.keepAliveInterval = keepAliveInterval; - this.useSsl = useSsl; - this.sslContext = sslContext; - this.messageStore = messageStore; connectionName = "connection_" + System.currentTimeMillis() + "_" + Math.random(); LOGGER.debug("[" + connectionName + "]: Connection created"); diff --git a/vst/src/main/java/com/arangodb/vst/internal/VstConnectionSync.java b/vst/src/main/java/com/arangodb/vst/internal/VstConnectionSync.java new file mode 100644 index 000000000..28a8bcd89 --- /dev/null +++ b/vst/src/main/java/com/arangodb/vst/internal/VstConnectionSync.java @@ -0,0 +1,63 @@ +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed 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. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.vst.internal; + +import com.arangodb.ArangoDBException; +import com.arangodb.config.HostDescription; +import com.arangodb.internal.config.ArangoConfig; + +import java.util.Collection; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.FutureTask; +import java.util.concurrent.TimeUnit; + +/** + * @author Mark Vollmary + */ +public class VstConnectionSync extends VstConnection { + + public VstConnectionSync(final ArangoConfig config, final HostDescription host) { + super(config, host); + } + + @Override + public Message write(final Message message, final Collection chunks) { + final FutureTask task = new FutureTask<>(() -> messageStore.get(message.getId())); + messageStore.storeMessage(message.getId(), task); + super.writeIntern(message, chunks); + try { + return timeout == null || timeout == 0L ? task.get() : task.get(timeout, TimeUnit.MILLISECONDS); + } catch (final ExecutionException e) { + throw ArangoDBException.wrap(e.getCause()); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new ArangoDBException(e); + } catch (final Exception e) { + throw ArangoDBException.wrap(e); + } + } + + @Override + protected void doKeepAlive() { + sendKeepAlive(); + } + +} diff --git a/vst/src/main/resources/META-INF/services/com.arangodb.internal.net.AsyncProtocolProvider b/vst/src/main/resources/META-INF/services/com.arangodb.internal.net.AsyncProtocolProvider new file mode 100644 index 000000000..dc7f09560 --- /dev/null +++ b/vst/src/main/resources/META-INF/services/com.arangodb.internal.net.AsyncProtocolProvider @@ -0,0 +1 @@ +com.arangodb.vst.VstAsyncProtocolProvider diff --git a/vst/src/main/resources/META-INF/services/com.arangodb.internal.net.ProtocolProvider b/vst/src/main/resources/META-INF/services/com.arangodb.internal.net.ProtocolProvider new file mode 100644 index 000000000..6d11ca0c7 --- /dev/null +++ b/vst/src/main/resources/META-INF/services/com.arangodb.internal.net.ProtocolProvider @@ -0,0 +1 @@ +com.arangodb.vst.VstProtocolProvider From 91de964d1c6b331ea65c1241322f05f2c8f94b55 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Fri, 17 Feb 2023 11:04:13 +0100 Subject: [PATCH 241/254] [DE-425] jackson-serde-json and jackson-serde-vpack modules --- driver/pom.xml | 4 +- {jackson-serde => jackson-serde-json}/pom.xml | 8 ++-- .../java/com/arangodb/serde/jackson/From.java | 0 .../java/com/arangodb/serde/jackson/Id.java | 0 .../arangodb/serde/jackson/JacksonSerde.java | 0 .../serde/jackson/JacksonSerdeProvider.java | 0 .../java/com/arangodb/serde/jackson/Key.java | 0 .../java/com/arangodb/serde/jackson/Rev.java | 0 .../java/com/arangodb/serde/jackson/To.java | 0 .../internal/JacksonMapperProvider.java | 0 .../jackson/internal/JacksonSerdeImpl.java | 0 .../com.arangodb.serde.ArangoSerdeProvider | 0 jackson-serde-vpack/pom.xml | 37 +++++++++++++++++++ .../arangodb/serde/jackson/vpack/Package.java | 5 +++ pom.xml | 10 ++++- shaded-integration-tests/pom.xml | 8 ++-- 16 files changed, 60 insertions(+), 12 deletions(-) rename {jackson-serde => jackson-serde-json}/pom.xml (84%) rename {jackson-serde => jackson-serde-json}/src/main/java/com/arangodb/serde/jackson/From.java (100%) rename {jackson-serde => jackson-serde-json}/src/main/java/com/arangodb/serde/jackson/Id.java (100%) rename {jackson-serde => jackson-serde-json}/src/main/java/com/arangodb/serde/jackson/JacksonSerde.java (100%) rename {jackson-serde => jackson-serde-json}/src/main/java/com/arangodb/serde/jackson/JacksonSerdeProvider.java (100%) rename {jackson-serde => jackson-serde-json}/src/main/java/com/arangodb/serde/jackson/Key.java (100%) rename {jackson-serde => jackson-serde-json}/src/main/java/com/arangodb/serde/jackson/Rev.java (100%) rename {jackson-serde => jackson-serde-json}/src/main/java/com/arangodb/serde/jackson/To.java (100%) rename {jackson-serde => jackson-serde-json}/src/main/java/com/arangodb/serde/jackson/internal/JacksonMapperProvider.java (100%) rename {jackson-serde => jackson-serde-json}/src/main/java/com/arangodb/serde/jackson/internal/JacksonSerdeImpl.java (100%) rename {jackson-serde => jackson-serde-json}/src/main/resources/META-INF/services/com.arangodb.serde.ArangoSerdeProvider (100%) create mode 100644 jackson-serde-vpack/pom.xml create mode 100644 jackson-serde-vpack/src/main/java/com/arangodb/serde/jackson/vpack/Package.java diff --git a/driver/pom.xml b/driver/pom.xml index e379c3639..4c865a1a1 100644 --- a/driver/pom.xml +++ b/driver/pom.xml @@ -133,11 +133,11 @@ com.arangodb - jackson-serde + jackson-serde-json com.arangodb - jackson-dataformat-velocypack + jackson-serde-vpack test diff --git a/jackson-serde/pom.xml b/jackson-serde-json/pom.xml similarity index 84% rename from jackson-serde/pom.xml rename to jackson-serde-json/pom.xml index fcdf5ded7..29421c675 100644 --- a/jackson-serde/pom.xml +++ b/jackson-serde-json/pom.xml @@ -9,13 +9,13 @@ 7.0.0-ALPHA.2 - jackson-serde - jackson-serde - Jackson Serde module for ArangoDB Java Driver + jackson-serde-json + jackson-serde-json + Jackson Serde JSON module for ArangoDB Java Driver false - com.arangodb.serde.jackson + com.arangodb.serde.jackson.json diff --git a/jackson-serde/src/main/java/com/arangodb/serde/jackson/From.java b/jackson-serde-json/src/main/java/com/arangodb/serde/jackson/From.java similarity index 100% rename from jackson-serde/src/main/java/com/arangodb/serde/jackson/From.java rename to jackson-serde-json/src/main/java/com/arangodb/serde/jackson/From.java diff --git a/jackson-serde/src/main/java/com/arangodb/serde/jackson/Id.java b/jackson-serde-json/src/main/java/com/arangodb/serde/jackson/Id.java similarity index 100% rename from jackson-serde/src/main/java/com/arangodb/serde/jackson/Id.java rename to jackson-serde-json/src/main/java/com/arangodb/serde/jackson/Id.java diff --git a/jackson-serde/src/main/java/com/arangodb/serde/jackson/JacksonSerde.java b/jackson-serde-json/src/main/java/com/arangodb/serde/jackson/JacksonSerde.java similarity index 100% rename from jackson-serde/src/main/java/com/arangodb/serde/jackson/JacksonSerde.java rename to jackson-serde-json/src/main/java/com/arangodb/serde/jackson/JacksonSerde.java diff --git a/jackson-serde/src/main/java/com/arangodb/serde/jackson/JacksonSerdeProvider.java b/jackson-serde-json/src/main/java/com/arangodb/serde/jackson/JacksonSerdeProvider.java similarity index 100% rename from jackson-serde/src/main/java/com/arangodb/serde/jackson/JacksonSerdeProvider.java rename to jackson-serde-json/src/main/java/com/arangodb/serde/jackson/JacksonSerdeProvider.java diff --git a/jackson-serde/src/main/java/com/arangodb/serde/jackson/Key.java b/jackson-serde-json/src/main/java/com/arangodb/serde/jackson/Key.java similarity index 100% rename from jackson-serde/src/main/java/com/arangodb/serde/jackson/Key.java rename to jackson-serde-json/src/main/java/com/arangodb/serde/jackson/Key.java diff --git a/jackson-serde/src/main/java/com/arangodb/serde/jackson/Rev.java b/jackson-serde-json/src/main/java/com/arangodb/serde/jackson/Rev.java similarity index 100% rename from jackson-serde/src/main/java/com/arangodb/serde/jackson/Rev.java rename to jackson-serde-json/src/main/java/com/arangodb/serde/jackson/Rev.java diff --git a/jackson-serde/src/main/java/com/arangodb/serde/jackson/To.java b/jackson-serde-json/src/main/java/com/arangodb/serde/jackson/To.java similarity index 100% rename from jackson-serde/src/main/java/com/arangodb/serde/jackson/To.java rename to jackson-serde-json/src/main/java/com/arangodb/serde/jackson/To.java diff --git a/jackson-serde/src/main/java/com/arangodb/serde/jackson/internal/JacksonMapperProvider.java b/jackson-serde-json/src/main/java/com/arangodb/serde/jackson/internal/JacksonMapperProvider.java similarity index 100% rename from jackson-serde/src/main/java/com/arangodb/serde/jackson/internal/JacksonMapperProvider.java rename to jackson-serde-json/src/main/java/com/arangodb/serde/jackson/internal/JacksonMapperProvider.java diff --git a/jackson-serde/src/main/java/com/arangodb/serde/jackson/internal/JacksonSerdeImpl.java b/jackson-serde-json/src/main/java/com/arangodb/serde/jackson/internal/JacksonSerdeImpl.java similarity index 100% rename from jackson-serde/src/main/java/com/arangodb/serde/jackson/internal/JacksonSerdeImpl.java rename to jackson-serde-json/src/main/java/com/arangodb/serde/jackson/internal/JacksonSerdeImpl.java diff --git a/jackson-serde/src/main/resources/META-INF/services/com.arangodb.serde.ArangoSerdeProvider b/jackson-serde-json/src/main/resources/META-INF/services/com.arangodb.serde.ArangoSerdeProvider similarity index 100% rename from jackson-serde/src/main/resources/META-INF/services/com.arangodb.serde.ArangoSerdeProvider rename to jackson-serde-json/src/main/resources/META-INF/services/com.arangodb.serde.ArangoSerdeProvider diff --git a/jackson-serde-vpack/pom.xml b/jackson-serde-vpack/pom.xml new file mode 100644 index 000000000..875b6b5b9 --- /dev/null +++ b/jackson-serde-vpack/pom.xml @@ -0,0 +1,37 @@ + + + 4.0.0 + + + com.arangodb + arangodb-java-driver-parent + 7.0.0-ALPHA.2 + + + jackson-serde-vpack + jackson-serde-vpack + Jackson Serde VPACK module for ArangoDB Java Driver + + + false + com.arangodb.serde.jackson.vpack + + + + + com.arangodb + jackson-serde-json + + + com.arangodb + jackson-dataformat-velocypack + + + com.arangodb + velocypack + + + + diff --git a/jackson-serde-vpack/src/main/java/com/arangodb/serde/jackson/vpack/Package.java b/jackson-serde-vpack/src/main/java/com/arangodb/serde/jackson/vpack/Package.java new file mode 100644 index 000000000..3ee62dbe7 --- /dev/null +++ b/jackson-serde-vpack/src/main/java/com/arangodb/serde/jackson/vpack/Package.java @@ -0,0 +1,5 @@ +package com.arangodb.serde.jackson.vpack; + +class Package { + // no-op, just to trigger package creation +} diff --git a/pom.xml b/pom.xml index c17fb6232..24508f88f 100644 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,8 @@ core driver shaded - jackson-serde + jackson-serde-json + jackson-serde-vpack http vst @@ -129,7 +130,12 @@ com.arangodb - jackson-serde + jackson-serde-json + ${project.version} + + + com.arangodb + jackson-serde-vpack ${project.version} diff --git a/shaded-integration-tests/pom.xml b/shaded-integration-tests/pom.xml index bbbcf47b9..2f0bb93ff 100644 --- a/shaded-integration-tests/pom.xml +++ b/shaded-integration-tests/pom.xml @@ -73,11 +73,11 @@ com.arangodb - jackson-serde + jackson-serde-json com.arangodb - jackson-dataformat-velocypack + jackson-serde-vpack com.tngtech.archunit @@ -123,11 +123,11 @@ com.arangodb - jackson-serde + jackson-serde-json com.arangodb - jackson-dataformat-velocypack + jackson-serde-vpack From b9a5c50cfb23d5effbc7a815ef679ce7196ed028 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Fri, 17 Feb 2023 12:19:42 +0100 Subject: [PATCH 242/254] fixed empty javadoc --- .../arangodb/serde/jackson/vpack/{Package.java => NoOp.java} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename jackson-serde-vpack/src/main/java/com/arangodb/serde/jackson/vpack/{Package.java => NoOp.java} (82%) diff --git a/jackson-serde-vpack/src/main/java/com/arangodb/serde/jackson/vpack/Package.java b/jackson-serde-vpack/src/main/java/com/arangodb/serde/jackson/vpack/NoOp.java similarity index 82% rename from jackson-serde-vpack/src/main/java/com/arangodb/serde/jackson/vpack/Package.java rename to jackson-serde-vpack/src/main/java/com/arangodb/serde/jackson/vpack/NoOp.java index 3ee62dbe7..122d3561b 100644 --- a/jackson-serde-vpack/src/main/java/com/arangodb/serde/jackson/vpack/Package.java +++ b/jackson-serde-vpack/src/main/java/com/arangodb/serde/jackson/vpack/NoOp.java @@ -1,5 +1,5 @@ package com.arangodb.serde.jackson.vpack; -class Package { +public enum NoOp { // no-op, just to trigger package creation } From 93dd0e4414c397ac68ca5c5d67d3572bf77752c6 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Mon, 20 Feb 2023 10:19:48 +0100 Subject: [PATCH 243/254] fixed queueTime test --- driver/src/test/java/com/arangodb/ArangoDBTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/driver/src/test/java/com/arangodb/ArangoDBTest.java b/driver/src/test/java/com/arangodb/ArangoDBTest.java index 31b42bb9d..5bd5e613e 100644 --- a/driver/src/test/java/com/arangodb/ArangoDBTest.java +++ b/driver/src/test/java/com/arangodb/ArangoDBTest.java @@ -656,7 +656,7 @@ void queueTime(ArangoDB arangoDB) throws InterruptedException, ExecutionExceptio System.err.println(v.value); } } - assertThat(avg).isPositive(); + assertThat(avg).isNotNegative(); } else { assertThat(avg).isEqualTo(0.0); assertThat(values).isEmpty(); From 3a9980a4432e88ea766de0e2f971adff7e6aa0c3 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Mon, 20 Feb 2023 11:11:21 +0100 Subject: [PATCH 244/254] [DE-425] doc upd --- docs/v7_detailed_changes.md | 89 ++++++++++++++++++++++--- docs/v7_java-reference-serialization.md | 73 ++++++-------------- 2 files changed, 98 insertions(+), 64 deletions(-) diff --git a/docs/v7_detailed_changes.md b/docs/v7_detailed_changes.md index f3e873477..ff893e95d 100644 --- a/docs/v7_detailed_changes.md +++ b/docs/v7_detailed_changes.md @@ -61,23 +61,90 @@ ArangoDB adb = new ArangoDB.Builder() An example showing how to provide configuration using Eclipse MicroProfile Config can be found [here](../driver/src/test/java/com/arangodb/config). -## Transitive dependencies -A transitive dependency on `io.vertx:vertx-web-client` has been added. In can be excluded when using `VST` protocol -only. +## Modules + +Support for different serializers and communication protocols is offered by separate modules. +Defaults modules are transitively included, but they could be excluded if not needed. + +The driver artifact `com.arangodb:arangodb-java-driver` has transitive dependencies on default modules: +- `com.arangodb:http-protocol`: `HTTP` communication protocol +- `com.arangodb:jackson-serde-json`: `JSON` user serde module based on Jackson Databind +Alternative modules are respectively: +- `com.arangodb:vst-protocol`: `VST` communication protocol +- `com.arangodb:jackson-serde-vpack`: `VPACK` user serde module based on Jackson Databind + +In case a non-default communication protocol or user serde are used, the related module(s) must be explicitly included +and the corresponding default module(s) can be excluded. + +For example, to use the driver with `VPACK` over `VST`, we must include: +- `com.arangodb:vst-protocol` and +- `com.arangodb:jackson-serde-vpack` +and could exclude: +- `com.arangodb:http-protocol` and +- `com.arangodb:jackson-serde-json` + +```xml + + + com.arangodb + arangodb-java-driver + + + com.arangodb + http-protocol + + + com.arangodb + jackson-serde-json + + + + + com.arangodb + vst-protocol + + + com.arangodb + jackson-serde-vpack + + +``` -The dependency on `com.arangodb:velocypack` has been removed. -When using protocol `VST`, `HTTP_VPACK` or `HTTP2_VPACK`, the optional dependency -on `com.arangodb:jackson-dataformat-velocypack` must be provided. +## Transitive dependencies + +`com.arangodb:arangodb-java-driver` has transitive dependencies on `jackson-core`, `jackson-databind` +and `jackson-annotations`, using by default version `2.14`. + +The versions of such libraries can be overridden, the driver is compatible with Jackson 2 (at least `2.10` or greater). + +To do this, you might need to include [jackson-bom](https://github.com/FasterXML/jackson-bom) +to ensure dependency convergence across the entire project, for example in case +there are in your project other libraries depending on different versions of Jackson. + +```xml + + + + com.fasterxml.jackson + jackson-bom + ... + import + pom + + + +``` -When using protocol `HTTP_JSON` or `HTTP2_JSON` (default), no dependencies on `VPACK` libraries are required. +The module `http-protocol` has transitive dependency on `io.vertx:vertx-web-client:4.3.5`. -Transitive dependencies on Jackson Core, Databind and Annotations have been added, using by default version `2.14`. -The versions of such libraries can be overridden, the driver is compatible with Jackson versions: `2.10`, `2.11`, `2.12` -, `2.13`, `2.14`. +If these dependency requirements cannot be satisfied, you might need to use the +[shaded version](#arangodb-java-driver-shaded) of this driver, which bundles together all modules with relocated +external dependencies. -If these dependency requirements cannot be satisfied, you might need to use the [shaded version](#arangodb-java-driver-shaded) of this driver. +The dependency on `com.arangodb:velocypack` has been removed from core module and is now only used +by `com.arangodb:vst-protocol` and `com.arangodb:jackson-serde-vpack`. ## User Data Types diff --git a/docs/v7_java-reference-serialization.md b/docs/v7_java-reference-serialization.md index da9127f08..c59329210 100644 --- a/docs/v7_java-reference-serialization.md +++ b/docs/v7_java-reference-serialization.md @@ -34,12 +34,12 @@ For example, you can find [here](../jsonb-serde/src/main/java/com/arangodb/serde ## JacksonSerde (default user-data serde) -The default user-data serde is `JacksonSerde`, which is provided by the module `com.arangodb:jackson-serde`. +The default user-data serde is `JacksonSerde`, which is provided by the module `com.arangodb:jackson-serde-json`. This is used by default from the driver, if no custom serde is registered explicitly. It is implemented delegating [Jackson](https://github.com/FasterXML/jackson) `ObjectMapper`, therefore it is compatible with Jackson Streaming, Data Binding and Tree Model API. It supports both `JSON` and `VPACK` data formats. To use `VPACK`, the additional dependency on -[jackson-dataformat-velocypack](https://github.com/arangodb/jackson-dataformat-velocypack) is required. +`com.arangodb:jackson-serde-vpack` is required. ### Configure @@ -147,36 +147,32 @@ ArangoDB adb = new ArangoDB.Builder() ### Jackson datatype and language modules -The `JacksonSerde` can be configured -with [Jackson datatype modules](https://github.com/FasterXML/jackson#third-party-datatype-modules) -as well as [Jackson JVM Language modules](https://github.com/FasterXML/jackson#jvm-language-modules). +By default, Jackson modules in the classpath are discovered via SPI and registered to the `JacksonSerde`. +For example, this will automatically +register [Jackson datatype modules](https://github.com/FasterXML/jackson#third-party-datatype-modules) +as well as [Jackson JVM Language modules](https://github.com/FasterXML/jackson#jvm-language-modules) +like Kotlin or Scala module (see sections below). + +To avoid automatic Jackson modules discovery and registration, an instance of `JacksonSerde` can be manually created +using `JacksonSerdeProvider.create(ObjectMapper)` and registered using `ArangoDBBuilder.serde(ArangoSerde)`, e.g.: + +```java +ArangoDB adb = new ArangoDB.Builder() + .serde(new JacksonSerdeProvider().create(new ObjectMapper())) + .build(); +``` ### Kotlin [Kotlin language module](https://github.com/FasterXML/jackson-module-kotlin) -enables support for Kotlin native types and can be registered in the following way: - -```kotlin -val arangoDB = ArangoDB.Builder() - .serde(JacksonSerdeProvider().of(ContentType.JSON).apply { - configure { it.registerModule(KotlinModule()) } - }) - .build() -``` +enables support for Kotlin classes and types. +It can be used including `com.fasterxml.jackson.module:jackson-module-kotlin`. ### Scala [Scala language module](https://github.com/FasterXML/jackson-module-scala) -enables support for Scala native types and can be registered in the following way: - -```scala -val serde = JacksonSerdeProvider().of(ContentType.JSON) -serde.configure(mapper => mapper.registerModule(DefaultScalaModule)) - -val arangoDB = new ArangoDB.Builder() - .serde(arangoJack) - .build() -``` +enables support for Scala classes and types. +It can be used including `com.fasterxml.jackson.module:jackson-module-scala_`. ### Java 8 types @@ -202,32 +198,3 @@ public class MyObject { // ... } ``` - - -## Dependency convergence - -The driver and the `jackson-serde` module depend on `jackson-core`, `jackson-databind` and `jackson-annotations` -packages. -You might need to include [jackson-bom](https://github.com/FasterXML/jackson-bom) -to ensure dependency convergence across the entire project, for example in case -there are in your project other libraries depending on different versions of -the same Jackson packages. - -```xml - - - - com.fasterxml.jackson - jackson-bom - ... - import - pom - - - -``` - -The driver and the `JacksonSerde` are compatible with Jackson 2.10, 2.11, 2.12, 2.13 and 2.14. - -If these dependency requirements cannot be satisfied, you might need to use the -[shaded version](v7_detailed_changes.md#arangodb-java-driver-shaded) of the driver. From 349d00abb9be3495da8a058f9929edd19c6e88e3 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Mon, 20 Feb 2023 11:50:52 +0100 Subject: [PATCH 245/254] fixed empty jar in serde-vpack --- .../src/main/java/com/arangodb/serde/jackson/vpack/NoOp.java | 5 ----- jackson-serde-vpack/src/main/resources/META-INF/MANIFEST.MF | 0 2 files changed, 5 deletions(-) delete mode 100644 jackson-serde-vpack/src/main/java/com/arangodb/serde/jackson/vpack/NoOp.java create mode 100644 jackson-serde-vpack/src/main/resources/META-INF/MANIFEST.MF diff --git a/jackson-serde-vpack/src/main/java/com/arangodb/serde/jackson/vpack/NoOp.java b/jackson-serde-vpack/src/main/java/com/arangodb/serde/jackson/vpack/NoOp.java deleted file mode 100644 index 122d3561b..000000000 --- a/jackson-serde-vpack/src/main/java/com/arangodb/serde/jackson/vpack/NoOp.java +++ /dev/null @@ -1,5 +0,0 @@ -package com.arangodb.serde.jackson.vpack; - -public enum NoOp { - // no-op, just to trigger package creation -} diff --git a/jackson-serde-vpack/src/main/resources/META-INF/MANIFEST.MF b/jackson-serde-vpack/src/main/resources/META-INF/MANIFEST.MF new file mode 100644 index 000000000..e69de29bb From 97a0c229b18bc2671759d004755f046c15836a76 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Mon, 20 Feb 2023 12:03:06 +0100 Subject: [PATCH 246/254] internal serde annotations --- .../java/com/arangodb/serde/InternalFrom.java | 22 +++++++++++++++++++ .../java/com/arangodb/serde/InternalId.java | 22 +++++++++++++++++++ .../java/com/arangodb/serde/InternalKey.java | 22 +++++++++++++++++++ .../java/com/arangodb/serde/InternalRev.java | 22 +++++++++++++++++++ .../java/com/arangodb/serde/InternalTo.java | 22 +++++++++++++++++++ .../src/test/internal/java/arch/Person.java | 3 ++- 6 files changed, 112 insertions(+), 1 deletion(-) create mode 100644 core/src/main/java/com/arangodb/serde/InternalFrom.java create mode 100644 core/src/main/java/com/arangodb/serde/InternalId.java create mode 100644 core/src/main/java/com/arangodb/serde/InternalKey.java create mode 100644 core/src/main/java/com/arangodb/serde/InternalRev.java create mode 100644 core/src/main/java/com/arangodb/serde/InternalTo.java diff --git a/core/src/main/java/com/arangodb/serde/InternalFrom.java b/core/src/main/java/com/arangodb/serde/InternalFrom.java new file mode 100644 index 000000000..1963a5fa9 --- /dev/null +++ b/core/src/main/java/com/arangodb/serde/InternalFrom.java @@ -0,0 +1,22 @@ +package com.arangodb.serde; + +import com.fasterxml.jackson.annotation.JacksonAnnotationsInside; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * @author Michele Rastelli + * Annotation for `_from` field used by the InternalSerde. It works with shaded driver and relocated Jackson. + */ +@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER}) +@Retention(RetentionPolicy.RUNTIME) +@JacksonAnnotationsInside +@JsonProperty("_from") +@JsonInclude(JsonInclude.Include.NON_NULL) +public @interface InternalFrom { +} diff --git a/core/src/main/java/com/arangodb/serde/InternalId.java b/core/src/main/java/com/arangodb/serde/InternalId.java new file mode 100644 index 000000000..7ac590fbf --- /dev/null +++ b/core/src/main/java/com/arangodb/serde/InternalId.java @@ -0,0 +1,22 @@ +package com.arangodb.serde; + +import com.fasterxml.jackson.annotation.JacksonAnnotationsInside; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * @author Michele Rastelli + * Annotation for `_id` field used by the InternalSerde. It works with shaded driver and relocated Jackson. + */ +@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER}) +@Retention(RetentionPolicy.RUNTIME) +@JacksonAnnotationsInside +@JsonProperty("_id") +@JsonInclude(JsonInclude.Include.NON_NULL) +public @interface InternalId { +} diff --git a/core/src/main/java/com/arangodb/serde/InternalKey.java b/core/src/main/java/com/arangodb/serde/InternalKey.java new file mode 100644 index 000000000..932ecc942 --- /dev/null +++ b/core/src/main/java/com/arangodb/serde/InternalKey.java @@ -0,0 +1,22 @@ +package com.arangodb.serde; + +import com.fasterxml.jackson.annotation.JacksonAnnotationsInside; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * @author Michele Rastelli + * Annotation for `_key` field used by the InternalSerde. It works with shaded driver and relocated Jackson. + */ +@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER}) +@Retention(RetentionPolicy.RUNTIME) +@JacksonAnnotationsInside +@JsonProperty("_key") +@JsonInclude(JsonInclude.Include.NON_NULL) +public @interface InternalKey { +} diff --git a/core/src/main/java/com/arangodb/serde/InternalRev.java b/core/src/main/java/com/arangodb/serde/InternalRev.java new file mode 100644 index 000000000..c528d18e1 --- /dev/null +++ b/core/src/main/java/com/arangodb/serde/InternalRev.java @@ -0,0 +1,22 @@ +package com.arangodb.serde; + +import com.fasterxml.jackson.annotation.JacksonAnnotationsInside; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * @author Michele Rastelli + * Annotation for `_rev` field used by the InternalSerde. It works with shaded driver and relocated Jackson. + */ +@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER}) +@Retention(RetentionPolicy.RUNTIME) +@JacksonAnnotationsInside +@JsonProperty("_rev") +@JsonInclude(JsonInclude.Include.NON_NULL) +public @interface InternalRev { +} diff --git a/core/src/main/java/com/arangodb/serde/InternalTo.java b/core/src/main/java/com/arangodb/serde/InternalTo.java new file mode 100644 index 000000000..7505a337b --- /dev/null +++ b/core/src/main/java/com/arangodb/serde/InternalTo.java @@ -0,0 +1,22 @@ +package com.arangodb.serde; + +import com.fasterxml.jackson.annotation.JacksonAnnotationsInside; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * @author Michele Rastelli + * Annotation for `_to` field used by the InternalSerde. It works with shaded driver and relocated Jackson. + */ +@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER}) +@Retention(RetentionPolicy.RUNTIME) +@JacksonAnnotationsInside +@JsonProperty("_to") +@JsonInclude(JsonInclude.Include.NON_NULL) +public @interface InternalTo { +} diff --git a/shaded-integration-tests/src/test/internal/java/arch/Person.java b/shaded-integration-tests/src/test/internal/java/arch/Person.java index 3dc3cd7f2..67a0b4501 100644 --- a/shaded-integration-tests/src/test/internal/java/arch/Person.java +++ b/shaded-integration-tests/src/test/internal/java/arch/Person.java @@ -1,10 +1,11 @@ package arch; +import com.arangodb.serde.InternalKey; import com.arangodb.shaded.fasterxml.jackson.annotation.JsonProperty; public record Person( - @JsonProperty("_key") + @InternalKey String key, @JsonProperty("firstName") String name, From 75993fa9cb89d8ca0b48088ce748e12d96c0dc39 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Mon, 20 Feb 2023 12:12:01 +0100 Subject: [PATCH 247/254] [DE-474] make BaseEdgeDocument extend BaseDocument --- .../main/java/com/arangodb/entity/AbstractBaseDocument.java | 3 +-- core/src/main/java/com/arangodb/entity/BaseDocument.java | 4 ++-- core/src/main/java/com/arangodb/entity/BaseEdgeDocument.java | 4 ++-- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/core/src/main/java/com/arangodb/entity/AbstractBaseDocument.java b/core/src/main/java/com/arangodb/entity/AbstractBaseDocument.java index 6a46168dd..cce54a832 100644 --- a/core/src/main/java/com/arangodb/entity/AbstractBaseDocument.java +++ b/core/src/main/java/com/arangodb/entity/AbstractBaseDocument.java @@ -133,8 +133,7 @@ private void requireString(final String k, final Object v) { } } - @Override - public String toString() { + String stringify() { return "{" + "properties=" + properties + '}'; diff --git a/core/src/main/java/com/arangodb/entity/BaseDocument.java b/core/src/main/java/com/arangodb/entity/BaseDocument.java index 88b0d6173..0e8860e74 100644 --- a/core/src/main/java/com/arangodb/entity/BaseDocument.java +++ b/core/src/main/java/com/arangodb/entity/BaseDocument.java @@ -26,7 +26,7 @@ * @author Mark Vollmary * @author Michele Rastelli */ -public final class BaseDocument extends AbstractBaseDocument { +public class BaseDocument extends AbstractBaseDocument { public BaseDocument() { super(); @@ -42,7 +42,7 @@ public BaseDocument(final Map properties) { @Override public String toString() { - return "BaseDocument" + super.toString(); + return "BaseDocument" + stringify(); } } diff --git a/core/src/main/java/com/arangodb/entity/BaseEdgeDocument.java b/core/src/main/java/com/arangodb/entity/BaseEdgeDocument.java index 7dd5170ca..46abcc246 100644 --- a/core/src/main/java/com/arangodb/entity/BaseEdgeDocument.java +++ b/core/src/main/java/com/arangodb/entity/BaseEdgeDocument.java @@ -29,7 +29,7 @@ * @author Mark Vollmary * @author Michele Rastelli */ -public final class BaseEdgeDocument extends AbstractBaseDocument { +public class BaseEdgeDocument extends BaseDocument { private static final String[] META_PROPS = new String[]{ DocumentFields.ID, @@ -84,7 +84,7 @@ protected String[] getMetaProps() { @Override public String toString() { - return "BaseEdgeDocument" + super.toString(); + return "BaseEdgeDocument" + stringify(); } } From c61d706db4cb8c298a644dd386cb6c14a9e89570 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Mon, 20 Feb 2023 12:34:13 +0100 Subject: [PATCH 248/254] [DE-473] cursor stats fullCount --- .../main/java/com/arangodb/ArangoCursor.java | 4 +-- .../java/com/arangodb/entity/CursorStats.java | 26 +++++++++++++++++++ .../internal/cursor/ArangoCursorImpl.java | 4 +-- .../cursor/entity/InternalCursorEntity.java | 5 ++-- .../java/com/arangodb/ArangoDatabaseTest.java | 4 +-- .../arangodb/async/ArangoDatabaseTest.java | 4 +-- 6 files changed, 37 insertions(+), 10 deletions(-) create mode 100644 core/src/main/java/com/arangodb/entity/CursorStats.java diff --git a/core/src/main/java/com/arangodb/ArangoCursor.java b/core/src/main/java/com/arangodb/ArangoCursor.java index 45f3bf1e2..259b81d73 100644 --- a/core/src/main/java/com/arangodb/ArangoCursor.java +++ b/core/src/main/java/com/arangodb/ArangoCursor.java @@ -20,12 +20,12 @@ package com.arangodb; +import com.arangodb.entity.CursorStats; import com.arangodb.entity.CursorWarning; import java.io.Closeable; import java.util.Collection; import java.util.List; -import java.util.Map; /** * @author Mark Vollmary @@ -53,7 +53,7 @@ public interface ArangoCursor extends ArangoIterable, ArangoIterator, C * number of modified documents and the number of documents that could not be modified due to an error (if * ignoreErrors query option is specified) */ - Map getStats(); + CursorStats getStats(); /** * @return warnings which the query could have been produced diff --git a/core/src/main/java/com/arangodb/entity/CursorStats.java b/core/src/main/java/com/arangodb/entity/CursorStats.java new file mode 100644 index 000000000..58f99dc38 --- /dev/null +++ b/core/src/main/java/com/arangodb/entity/CursorStats.java @@ -0,0 +1,26 @@ +package com.arangodb.entity; + +import com.fasterxml.jackson.annotation.JsonAnySetter; + +import java.util.HashMap; +import java.util.Map; + +public final class CursorStats { + + private Long fullCount; + private final Map properties = new HashMap<>(); + + @JsonAnySetter + public void add(String key, Object value) { + properties.put(key, value); + } + + public Long getFullCount() { + return fullCount; + } + + public Object get(String key) { + return properties.get(key); + } + +} diff --git a/core/src/main/java/com/arangodb/internal/cursor/ArangoCursorImpl.java b/core/src/main/java/com/arangodb/internal/cursor/ArangoCursorImpl.java index cff3dd4b5..2dfdbd194 100644 --- a/core/src/main/java/com/arangodb/internal/cursor/ArangoCursorImpl.java +++ b/core/src/main/java/com/arangodb/internal/cursor/ArangoCursorImpl.java @@ -22,6 +22,7 @@ import com.arangodb.ArangoCursor; import com.arangodb.ArangoIterator; +import com.arangodb.entity.CursorStats; import com.arangodb.entity.CursorWarning; import com.arangodb.internal.ArangoCursorExecute; import com.arangodb.internal.InternalArangoDatabase; @@ -31,7 +32,6 @@ import java.util.ArrayList; import java.util.Collection; import java.util.List; -import java.util.Map; /** * @author Mark Vollmary @@ -78,7 +78,7 @@ public Integer getCount() { } @Override - public Map getStats() { + public CursorStats getStats() { final Extras extra = iterator.getResult().getExtra(); return extra != null ? extra.getStats() : null; } diff --git a/core/src/main/java/com/arangodb/internal/cursor/entity/InternalCursorEntity.java b/core/src/main/java/com/arangodb/internal/cursor/entity/InternalCursorEntity.java index 1145d5646..535715e3b 100644 --- a/core/src/main/java/com/arangodb/internal/cursor/entity/InternalCursorEntity.java +++ b/core/src/main/java/com/arangodb/internal/cursor/entity/InternalCursorEntity.java @@ -20,6 +20,7 @@ package com.arangodb.internal.cursor.entity; +import com.arangodb.entity.CursorStats; import com.arangodb.entity.CursorWarning; import com.arangodb.entity.MetaAware; import com.fasterxml.jackson.databind.JsonNode; @@ -113,9 +114,9 @@ public Map cleanupMeta(Map meta) { public static final class Extras { private final Collection warnings = Collections.emptyList(); - private Map stats; + private CursorStats stats; - public Map getStats() { + public CursorStats getStats() { return stats; } diff --git a/driver/src/test/java/com/arangodb/ArangoDatabaseTest.java b/driver/src/test/java/com/arangodb/ArangoDatabaseTest.java index bfd9924cd..ce900828b 100644 --- a/driver/src/test/java/com/arangodb/ArangoDatabaseTest.java +++ b/driver/src/test/java/com/arangodb/ArangoDatabaseTest.java @@ -627,8 +627,8 @@ void queryWithLimitAndFullCount(ArangoDatabase db) { assertThat((Iterator) cursor).hasNext(); } assertThat(cursor.getStats()).isNotNull(); - assertThat(((Number) cursor.getStats().get("fullCount")).intValue()) - .isGreaterThanOrEqualTo(10); + assertThat(((Number) cursor.getStats().get("executionTime")).doubleValue()).isPositive(); + assertThat((cursor.getStats().getFullCount())).isGreaterThanOrEqualTo(10); } @ParameterizedTest(name = "{index}") diff --git a/driver/src/test/java/com/arangodb/async/ArangoDatabaseTest.java b/driver/src/test/java/com/arangodb/async/ArangoDatabaseTest.java index a12bf84ec..be4d23a6a 100644 --- a/driver/src/test/java/com/arangodb/async/ArangoDatabaseTest.java +++ b/driver/src/test/java/com/arangodb/async/ArangoDatabaseTest.java @@ -493,8 +493,8 @@ void queryWithLimitAndFullCount() throws InterruptedException, ExecutionExceptio assertThat(cursor.hasNext()).isEqualTo(true); } assertThat(cursor.getStats()).isNotNull(); - assertThat(((Number) cursor.getStats().get("fullCount")).intValue()) - .isGreaterThanOrEqualTo(10); + assertThat(((Number) cursor.getStats().get("executionTime")).doubleValue()).isPositive(); + assertThat((cursor.getStats().getFullCount())).isGreaterThanOrEqualTo(10); }) .get(); } finally { From 2bcb2ba82364edfe1918ac634491865eada95068 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Tue, 21 Feb 2023 09:27:09 +0100 Subject: [PATCH 249/254] [DE-436] reuse code in shaded integration tests --- .../src/test/native/java/com | 1 + .../com/arangodb/ArangoCollectionTest.java | 3220 ----------------- .../java/com/arangodb/ArangoCursorTest.java | 133 - .../java/com/arangodb/ArangoDBTest.java | 666 ---- .../java/com/arangodb/ArangoDatabaseTest.java | 1413 -------- .../com/arangodb/ArangoDocumentUtilTest.java | 84 - .../arangodb/ArangoEdgeCollectionTest.java | 445 --- .../java/com/arangodb/ArangoGraphTest.java | 438 --- .../java/com/arangodb/ArangoSearchTest.java | 1010 ------ .../java/com/arangodb/ArangoSslTest.java | 101 - .../arangodb/ArangoVertexCollectionTest.java | 480 --- .../java/com/arangodb/ArangoViewTest.java | 114 - .../native/java/com/arangodb/BaseJunit5.java | 129 - .../java/com/arangodb/ConcurrencyTests.java | 34 - .../java/com/arangodb/DocumentTest.java | 138 - .../java/com/arangodb/InvertedIndexTest.java | 194 - .../native/java/com/arangodb/JwtAuthTest.java | 97 - .../java/com/arangodb/ParallelTest.java | 42 - .../java/com/arangodb/SerializableTest.java | 65 - .../StreamTransactionConflictsTest.java | 119 - .../arangodb/StreamTransactionGraphTest.java | 407 --- .../com/arangodb/StreamTransactionTest.java | 820 ----- .../arangodb/async/ArangoCollectionTest.java | 2514 ------------- .../java/com/arangodb/async/ArangoDBTest.java | 566 --- .../arangodb/async/ArangoDatabaseTest.java | 1024 ------ .../async/ArangoEdgeCollectionTest.java | 367 -- .../com/arangodb/async/ArangoGraphTest.java | 387 -- .../com/arangodb/async/ArangoRouteTest.java | 81 - .../com/arangodb/async/ArangoSearchTest.java | 551 --- .../async/ArangoVertexCollectionTest.java | 356 -- .../com/arangodb/async/ArangoViewTest.java | 86 - .../java/com/arangodb/async/BaseTest.java | 119 - .../com/arangodb/async/CommunicationTest.java | 46 - .../com/arangodb/async/ConcurrencyTest.java | 94 - .../com/arangodb/async/ConcurrencyTests.java | 29 - .../com/arangodb/async/InvertedIndexTest.java | 199 - .../java/com/arangodb/async/JwtAuthTest.java | 103 - .../async/StreamTransactionConflictsTest.java | 120 - .../async/StreamTransactionGraphTest.java | 398 -- .../arangodb/async/StreamTransactionTest.java | 362 -- .../debug/ConsolidationIntervalMsecTest.java | 82 - .../arangodb/async/example/ExampleBase.java | 64 - ...ueryWithSpecialReturnTypesExampleTest.java | 128 - .../document/GetDocumentExampleTest.java | 94 - .../document/ImportDocumentExampleTest.java | 87 - .../document/InsertDocumentExampleTest.java | 74 - .../async/example/document/TestEntity.java | 47 - .../graph/AQLActorsAndMoviesExampleTest.java | 605 ---- .../async/example/graph/BaseGraphTest.java | 116 - .../arangodb/async/example/graph/Circle.java | 80 - .../async/example/graph/CircleEdge.java | 122 - .../GraphTraversalsInAQLExampleTest.java | 122 - .../graph/ShortestPathInAQLExampleTest.java | 106 - .../async/example/ssl/SslExampleTest.java | 79 - .../arangodb/async/serde/CustomSerdeTest.java | 177 - .../java/com/arangodb/config/ConfigUtils.java | 18 - .../com/arangodb/example/ExampleBase.java | 62 - .../com/arangodb/example/FirstProject.java | 134 - ...ueryWithSpecialReturnTypesExampleTest.java | 132 - .../document/GetDocumentExampleTest.java | 98 - .../document/InsertDocumentExampleTest.java | 70 - .../arangodb/example/document/TestEntity.java | 47 - .../graph/AQLActorsAndMoviesExampleTest.java | 581 --- .../arangodb/example/graph/BaseGraphTest.java | 114 - .../com/arangodb/example/graph/Circle.java | 80 - .../arangodb/example/graph/CircleEdge.java | 122 - .../GraphTraversalsInAQLExampleTest.java | 113 - .../graph/ShortestPathInAQLExampleTest.java | 105 - .../arangodb/example/ssl/SslExampleTest.java | 128 - .../arangodb/internal/HostHandlerTest.java | 190 - .../internal/QueueTimeMetricsImplTest.java | 61 - .../velocystream/CommunicationTest.java | 113 - .../mapping/annotations/AnnotatedEntity.java | 81 - .../annotations/ArangoAnnotationsTest.java | 64 - .../com/arangodb/serde/CustomSerdeTest.java | 242 -- .../arangodb/serde/CustomTypeHintTest.java | 145 - .../java/com/arangodb/serde/SerdeTest.java | 41 - .../java/com/arangodb/util/MapBuilder.java | 46 - .../com/arangodb/util/MapBuilderTest.java | 43 - .../java/com/arangodb/util/TestUtils.java | 112 - .../com/arangodb/util/UnicodeUtilsTest.java | 60 - .../src/test/native/java/perf/Benchmark.java | 123 - .../native/java/perf/SimpleSyncPerfTest.java | 57 - .../native/java/perf/SyncBenchmarkTest.java | 71 - shaded-integration-tests/src/test/resources | 1 + .../native-image/native-image.properties | 8 - .../META-INF/native-image/reflect-config.json | 359 -- .../native-image/resource-config.json | 25 - .../native-image/serialization-config.json | 26 - .../test/resources/arangodb-bad.properties | 1 - .../resources/arangodb-config-test.properties | 17 - .../resources/arangodb-with-prefix.properties | 3 - .../src/test/resources/arangodb.properties | 5 - .../src/test/resources/example.truststore | Bin 2251 -> 0 bytes .../src/test/resources/logback-test.xml | 18 - 95 files changed, 2 insertions(+), 23249 deletions(-) create mode 120000 shaded-integration-tests/src/test/native/java/com delete mode 100644 shaded-integration-tests/src/test/native/java/com/arangodb/ArangoCollectionTest.java delete mode 100644 shaded-integration-tests/src/test/native/java/com/arangodb/ArangoCursorTest.java delete mode 100644 shaded-integration-tests/src/test/native/java/com/arangodb/ArangoDBTest.java delete mode 100644 shaded-integration-tests/src/test/native/java/com/arangodb/ArangoDatabaseTest.java delete mode 100644 shaded-integration-tests/src/test/native/java/com/arangodb/ArangoDocumentUtilTest.java delete mode 100644 shaded-integration-tests/src/test/native/java/com/arangodb/ArangoEdgeCollectionTest.java delete mode 100644 shaded-integration-tests/src/test/native/java/com/arangodb/ArangoGraphTest.java delete mode 100644 shaded-integration-tests/src/test/native/java/com/arangodb/ArangoSearchTest.java delete mode 100644 shaded-integration-tests/src/test/native/java/com/arangodb/ArangoSslTest.java delete mode 100644 shaded-integration-tests/src/test/native/java/com/arangodb/ArangoVertexCollectionTest.java delete mode 100644 shaded-integration-tests/src/test/native/java/com/arangodb/ArangoViewTest.java delete mode 100644 shaded-integration-tests/src/test/native/java/com/arangodb/BaseJunit5.java delete mode 100644 shaded-integration-tests/src/test/native/java/com/arangodb/ConcurrencyTests.java delete mode 100644 shaded-integration-tests/src/test/native/java/com/arangodb/DocumentTest.java delete mode 100644 shaded-integration-tests/src/test/native/java/com/arangodb/InvertedIndexTest.java delete mode 100644 shaded-integration-tests/src/test/native/java/com/arangodb/JwtAuthTest.java delete mode 100644 shaded-integration-tests/src/test/native/java/com/arangodb/ParallelTest.java delete mode 100644 shaded-integration-tests/src/test/native/java/com/arangodb/SerializableTest.java delete mode 100644 shaded-integration-tests/src/test/native/java/com/arangodb/StreamTransactionConflictsTest.java delete mode 100644 shaded-integration-tests/src/test/native/java/com/arangodb/StreamTransactionGraphTest.java delete mode 100644 shaded-integration-tests/src/test/native/java/com/arangodb/StreamTransactionTest.java delete mode 100644 shaded-integration-tests/src/test/native/java/com/arangodb/async/ArangoCollectionTest.java delete mode 100644 shaded-integration-tests/src/test/native/java/com/arangodb/async/ArangoDBTest.java delete mode 100644 shaded-integration-tests/src/test/native/java/com/arangodb/async/ArangoDatabaseTest.java delete mode 100644 shaded-integration-tests/src/test/native/java/com/arangodb/async/ArangoEdgeCollectionTest.java delete mode 100644 shaded-integration-tests/src/test/native/java/com/arangodb/async/ArangoGraphTest.java delete mode 100644 shaded-integration-tests/src/test/native/java/com/arangodb/async/ArangoRouteTest.java delete mode 100644 shaded-integration-tests/src/test/native/java/com/arangodb/async/ArangoSearchTest.java delete mode 100644 shaded-integration-tests/src/test/native/java/com/arangodb/async/ArangoVertexCollectionTest.java delete mode 100644 shaded-integration-tests/src/test/native/java/com/arangodb/async/ArangoViewTest.java delete mode 100644 shaded-integration-tests/src/test/native/java/com/arangodb/async/BaseTest.java delete mode 100644 shaded-integration-tests/src/test/native/java/com/arangodb/async/CommunicationTest.java delete mode 100644 shaded-integration-tests/src/test/native/java/com/arangodb/async/ConcurrencyTest.java delete mode 100644 shaded-integration-tests/src/test/native/java/com/arangodb/async/ConcurrencyTests.java delete mode 100644 shaded-integration-tests/src/test/native/java/com/arangodb/async/InvertedIndexTest.java delete mode 100644 shaded-integration-tests/src/test/native/java/com/arangodb/async/JwtAuthTest.java delete mode 100644 shaded-integration-tests/src/test/native/java/com/arangodb/async/StreamTransactionConflictsTest.java delete mode 100644 shaded-integration-tests/src/test/native/java/com/arangodb/async/StreamTransactionGraphTest.java delete mode 100644 shaded-integration-tests/src/test/native/java/com/arangodb/async/StreamTransactionTest.java delete mode 100644 shaded-integration-tests/src/test/native/java/com/arangodb/async/debug/ConsolidationIntervalMsecTest.java delete mode 100644 shaded-integration-tests/src/test/native/java/com/arangodb/async/example/ExampleBase.java delete mode 100644 shaded-integration-tests/src/test/native/java/com/arangodb/async/example/document/AqlQueryWithSpecialReturnTypesExampleTest.java delete mode 100644 shaded-integration-tests/src/test/native/java/com/arangodb/async/example/document/GetDocumentExampleTest.java delete mode 100644 shaded-integration-tests/src/test/native/java/com/arangodb/async/example/document/ImportDocumentExampleTest.java delete mode 100644 shaded-integration-tests/src/test/native/java/com/arangodb/async/example/document/InsertDocumentExampleTest.java delete mode 100644 shaded-integration-tests/src/test/native/java/com/arangodb/async/example/document/TestEntity.java delete mode 100644 shaded-integration-tests/src/test/native/java/com/arangodb/async/example/graph/AQLActorsAndMoviesExampleTest.java delete mode 100644 shaded-integration-tests/src/test/native/java/com/arangodb/async/example/graph/BaseGraphTest.java delete mode 100644 shaded-integration-tests/src/test/native/java/com/arangodb/async/example/graph/Circle.java delete mode 100644 shaded-integration-tests/src/test/native/java/com/arangodb/async/example/graph/CircleEdge.java delete mode 100644 shaded-integration-tests/src/test/native/java/com/arangodb/async/example/graph/GraphTraversalsInAQLExampleTest.java delete mode 100644 shaded-integration-tests/src/test/native/java/com/arangodb/async/example/graph/ShortestPathInAQLExampleTest.java delete mode 100644 shaded-integration-tests/src/test/native/java/com/arangodb/async/example/ssl/SslExampleTest.java delete mode 100644 shaded-integration-tests/src/test/native/java/com/arangodb/async/serde/CustomSerdeTest.java delete mode 100644 shaded-integration-tests/src/test/native/java/com/arangodb/config/ConfigUtils.java delete mode 100644 shaded-integration-tests/src/test/native/java/com/arangodb/example/ExampleBase.java delete mode 100644 shaded-integration-tests/src/test/native/java/com/arangodb/example/FirstProject.java delete mode 100644 shaded-integration-tests/src/test/native/java/com/arangodb/example/document/AqlQueryWithSpecialReturnTypesExampleTest.java delete mode 100644 shaded-integration-tests/src/test/native/java/com/arangodb/example/document/GetDocumentExampleTest.java delete mode 100644 shaded-integration-tests/src/test/native/java/com/arangodb/example/document/InsertDocumentExampleTest.java delete mode 100644 shaded-integration-tests/src/test/native/java/com/arangodb/example/document/TestEntity.java delete mode 100644 shaded-integration-tests/src/test/native/java/com/arangodb/example/graph/AQLActorsAndMoviesExampleTest.java delete mode 100644 shaded-integration-tests/src/test/native/java/com/arangodb/example/graph/BaseGraphTest.java delete mode 100644 shaded-integration-tests/src/test/native/java/com/arangodb/example/graph/Circle.java delete mode 100644 shaded-integration-tests/src/test/native/java/com/arangodb/example/graph/CircleEdge.java delete mode 100644 shaded-integration-tests/src/test/native/java/com/arangodb/example/graph/GraphTraversalsInAQLExampleTest.java delete mode 100644 shaded-integration-tests/src/test/native/java/com/arangodb/example/graph/ShortestPathInAQLExampleTest.java delete mode 100644 shaded-integration-tests/src/test/native/java/com/arangodb/example/ssl/SslExampleTest.java delete mode 100644 shaded-integration-tests/src/test/native/java/com/arangodb/internal/HostHandlerTest.java delete mode 100644 shaded-integration-tests/src/test/native/java/com/arangodb/internal/QueueTimeMetricsImplTest.java delete mode 100644 shaded-integration-tests/src/test/native/java/com/arangodb/internal/velocystream/CommunicationTest.java delete mode 100644 shaded-integration-tests/src/test/native/java/com/arangodb/mapping/annotations/AnnotatedEntity.java delete mode 100644 shaded-integration-tests/src/test/native/java/com/arangodb/mapping/annotations/ArangoAnnotationsTest.java delete mode 100644 shaded-integration-tests/src/test/native/java/com/arangodb/serde/CustomSerdeTest.java delete mode 100644 shaded-integration-tests/src/test/native/java/com/arangodb/serde/CustomTypeHintTest.java delete mode 100644 shaded-integration-tests/src/test/native/java/com/arangodb/serde/SerdeTest.java delete mode 100644 shaded-integration-tests/src/test/native/java/com/arangodb/util/MapBuilder.java delete mode 100644 shaded-integration-tests/src/test/native/java/com/arangodb/util/MapBuilderTest.java delete mode 100644 shaded-integration-tests/src/test/native/java/com/arangodb/util/TestUtils.java delete mode 100644 shaded-integration-tests/src/test/native/java/com/arangodb/util/UnicodeUtilsTest.java delete mode 100644 shaded-integration-tests/src/test/native/java/perf/Benchmark.java delete mode 100644 shaded-integration-tests/src/test/native/java/perf/SimpleSyncPerfTest.java delete mode 100644 shaded-integration-tests/src/test/native/java/perf/SyncBenchmarkTest.java create mode 120000 shaded-integration-tests/src/test/resources delete mode 100644 shaded-integration-tests/src/test/resources/META-INF/native-image/native-image.properties delete mode 100644 shaded-integration-tests/src/test/resources/META-INF/native-image/reflect-config.json delete mode 100644 shaded-integration-tests/src/test/resources/META-INF/native-image/resource-config.json delete mode 100644 shaded-integration-tests/src/test/resources/META-INF/native-image/serialization-config.json delete mode 100644 shaded-integration-tests/src/test/resources/arangodb-bad.properties delete mode 100644 shaded-integration-tests/src/test/resources/arangodb-config-test.properties delete mode 100644 shaded-integration-tests/src/test/resources/arangodb-with-prefix.properties delete mode 100644 shaded-integration-tests/src/test/resources/arangodb.properties delete mode 100644 shaded-integration-tests/src/test/resources/example.truststore delete mode 100644 shaded-integration-tests/src/test/resources/logback-test.xml diff --git a/shaded-integration-tests/src/test/native/java/com b/shaded-integration-tests/src/test/native/java/com new file mode 120000 index 000000000..9af9cd5c2 --- /dev/null +++ b/shaded-integration-tests/src/test/native/java/com @@ -0,0 +1 @@ +../../../../../driver/src/test/java/com \ No newline at end of file diff --git a/shaded-integration-tests/src/test/native/java/com/arangodb/ArangoCollectionTest.java b/shaded-integration-tests/src/test/native/java/com/arangodb/ArangoCollectionTest.java deleted file mode 100644 index acff3ae3b..000000000 --- a/shaded-integration-tests/src/test/native/java/com/arangodb/ArangoCollectionTest.java +++ /dev/null @@ -1,3220 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb; - -import com.arangodb.entity.*; -import com.arangodb.internal.serde.SerdeUtils; -import com.arangodb.model.*; -import com.arangodb.model.DocumentImportOptions.OnDuplicate; -import com.arangodb.serde.jackson.Id; -import com.arangodb.serde.jackson.JacksonSerde; -import com.arangodb.serde.jackson.Key; -import com.arangodb.serde.jackson.Rev; -import com.arangodb.shaded.fasterxml.jackson.databind.JsonNode; -import com.arangodb.util.MapBuilder; -import com.arangodb.util.RawBytes; -import com.arangodb.util.RawData; -import com.arangodb.util.RawJson; -import com.fasterxml.jackson.annotation.JsonInclude; -import com.fasterxml.jackson.annotation.JsonTypeInfo; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.Arguments; -import org.junit.jupiter.params.provider.MethodSource; - -import java.util.*; -import java.util.stream.Collectors; -import java.util.stream.IntStream; -import java.util.stream.Stream; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.catchThrowable; -import static org.junit.jupiter.api.Assumptions.assumeTrue; - -/** - * @author Mark Vollmary - * @author Michele Rastelli - */ -class ArangoCollectionTest extends BaseJunit5 { - - private static final String COLLECTION_NAME = "ArangoCollectionTest_collection"; - private static final String EDGE_COLLECTION_NAME = "ArangoCollectionTest_edge_collection"; - - private final ObjectMapper mapper = new ObjectMapper(); - - private static Stream cols() { - return dbsStream().map(db -> db.collection(COLLECTION_NAME)).map(Arguments::of); - } - - private static Stream edges() { - return dbsStream().map(db -> db.collection(EDGE_COLLECTION_NAME)).map(Arguments::of); - } - - @BeforeAll - static void init() { - initCollections(COLLECTION_NAME); - initEdgeCollections(EDGE_COLLECTION_NAME); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void insertDocument(ArangoCollection collection) { - final DocumentCreateEntity doc = collection.insertDocument(new BaseDocument(), null); - assertThat(doc).isNotNull(); - assertThat(doc.getId()).isNotNull(); - assertThat(doc.getKey()).isNotNull(); - assertThat(doc.getRev()).isNotNull(); - assertThat(doc.getNew()).isNull(); - assertThat(doc.getId()).isEqualTo(COLLECTION_NAME + "/" + doc.getKey()); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void insertDocumentWithArrayWithNullValues(ArangoCollection collection) { - List arr = Arrays.asList("a", null); - BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); - doc.addAttribute("arr", arr); - - final DocumentCreateEntity insertedDoc = collection.insertDocument(doc, - new DocumentCreateOptions().returnNew(true)); - assertThat(insertedDoc).isNotNull(); - assertThat(insertedDoc.getId()).isNotNull(); - assertThat(insertedDoc.getKey()).isNotNull(); - assertThat(insertedDoc.getRev()).isNotNull(); - assertThat(insertedDoc.getId()).isEqualTo(COLLECTION_NAME + "/" + insertedDoc.getKey()); - //noinspection unchecked - assertThat((List) insertedDoc.getNew().getAttribute("arr")).containsAll(Arrays.asList("a", null)); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void insertDocumentWithNullValues(ArangoCollection collection) { - BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); - doc.addAttribute("null", null); - - final DocumentCreateEntity insertedDoc = collection.insertDocument(doc, - new DocumentCreateOptions().returnNew(true)); - assertThat(insertedDoc).isNotNull(); - assertThat(insertedDoc.getId()).isNotNull(); - assertThat(insertedDoc.getKey()).isNotNull(); - assertThat(insertedDoc.getRev()).isNotNull(); - assertThat(insertedDoc.getId()).isEqualTo(COLLECTION_NAME + "/" + insertedDoc.getKey()); - assertThat(insertedDoc.getNew().getProperties()).containsKey("null"); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void insertDocumentUpdateRev(ArangoCollection collection) { - final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); - final DocumentCreateEntity createResult = collection.insertDocument(doc, null); - assertThat(doc.getRevision()).isNull(); - assertThat(createResult.getRev()).isNotNull(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void insertDocumentReturnNew(ArangoCollection collection) { - final DocumentCreateOptions options = new DocumentCreateOptions().returnNew(true); - final DocumentCreateEntity doc = collection.insertDocument(new BaseDocument(), options); - assertThat(doc).isNotNull(); - assertThat(doc.getId()).isNotNull(); - assertThat(doc.getKey()).isNotNull(); - assertThat(doc.getRev()).isNotNull(); - assertThat(doc.getNew()).isNotNull(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void insertDocumentWithTypeOverwriteModeReplace(ArangoCollection collection) { - assumeTrue(isAtLeastVersion(3, 7)); - assumeTrue(collection.getSerde().getUserSerde() instanceof JacksonSerde, "polymorphic deserialization support" + - " required"); - - String key = UUID.randomUUID().toString(); - Dog dog = new Dog(key, "Teddy"); - Cat cat = new Cat(key, "Luna"); - - final DocumentCreateOptions options = new DocumentCreateOptions() - .returnNew(true) - .returnOld(true) - .overwriteMode(OverwriteMode.replace); - collection.insertDocument(dog, options); - final DocumentCreateEntity doc = collection.insertDocument(cat, options, Animal.class); - assertThat(doc).isNotNull(); - assertThat(doc.getId()).isNotNull(); - assertThat(doc.getKey()).isNotNull().isEqualTo(key); - assertThat(doc.getRev()).isNotNull(); - - assertThat(doc.getOld()) - .isNotNull() - .isInstanceOf(Dog.class); - assertThat(doc.getOld().getKey()).isEqualTo(key); - assertThat(doc.getOld().getName()).isEqualTo("Teddy"); - - assertThat(doc.getNew()) - .isNotNull() - .isInstanceOf(Cat.class); - assertThat(doc.getNew().getKey()).isEqualTo(key); - assertThat(doc.getNew().getName()).isEqualTo("Luna"); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void insertDocumentOverwriteModeIgnore(ArangoCollection collection) { - assumeTrue(isAtLeastVersion(3, 7)); - - String key = "key-" + UUID.randomUUID(); - final BaseDocument doc = new BaseDocument(key); - doc.addAttribute("foo", "a"); - final DocumentCreateEntity meta = collection.insertDocument(doc); - - final BaseDocument doc2 = new BaseDocument(key); - doc2.addAttribute("bar", "b"); - final DocumentCreateEntity insertIgnore = collection.insertDocument(doc2, - new DocumentCreateOptions().overwriteMode(OverwriteMode.ignore)); - - assertThat(insertIgnore).isNotNull(); - assertThat(insertIgnore.getRev()).isEqualTo(meta.getRev()); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void insertDocumentOverwriteModeConflict(ArangoCollection collection) { - assumeTrue(isAtLeastVersion(3, 7)); - - String key = "key-" + UUID.randomUUID(); - final BaseDocument doc = new BaseDocument(key); - doc.addAttribute("foo", "a"); - collection.insertDocument(doc); - - final BaseDocument doc2 = new BaseDocument(key); - Throwable thrown = catchThrowable(() -> collection.insertDocument(doc2, - new DocumentCreateOptions().overwriteMode(OverwriteMode.conflict))); - assertThat(thrown).isInstanceOf(ArangoDBException.class); - ArangoDBException e = (ArangoDBException) thrown; - assertThat(e.getResponseCode()).isEqualTo(409); - assertThat(e.getErrorNum()).isEqualTo(1210); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void insertDocumentOverwriteModeReplace(ArangoCollection collection) { - assumeTrue(isAtLeastVersion(3, 7)); - - String key = "key-" + UUID.randomUUID(); - final BaseDocument doc = new BaseDocument(key); - doc.addAttribute("foo", "a"); - final DocumentCreateEntity meta = collection.insertDocument(doc); - - final BaseDocument doc2 = new BaseDocument(key); - doc2.addAttribute("bar", "b"); - final DocumentCreateEntity repsert = collection.insertDocument(doc2, -new DocumentCreateOptions().overwriteMode(OverwriteMode.replace).returnNew(true)); - - assertThat(repsert).isNotNull(); - assertThat(repsert.getRev()).isNotEqualTo(meta.getRev()); - assertThat(repsert.getNew().getProperties().containsKey("foo")).isFalse(); - assertThat(repsert.getNew().getAttribute("bar")).isEqualTo("b"); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void insertDocumentOverwriteModeUpdate(ArangoCollection collection) { - assumeTrue(isAtLeastVersion(3, 7)); - - final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); - doc.addAttribute("foo", "a"); - final DocumentCreateEntity meta = collection.insertDocument(doc); - - doc.addAttribute("bar", "b"); - final DocumentCreateEntity updated = collection.insertDocument(doc, - new DocumentCreateOptions().overwriteMode(OverwriteMode.update).returnNew(true)); - - assertThat(updated).isNotNull(); - assertThat(updated.getRev()).isNotEqualTo(meta.getRev()); - assertThat(updated.getNew().getAttribute("foo")).isEqualTo("a"); - assertThat(updated.getNew().getAttribute("bar")).isEqualTo("b"); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void insertDocumentOverwriteModeUpdateMergeObjectsFalse(ArangoCollection collection) { - assumeTrue(isAtLeastVersion(3, 7)); - - final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); - Map fieldA = Collections.singletonMap("a", "a"); - doc.addAttribute("foo", fieldA); - final DocumentCreateEntity meta = collection.insertDocument(doc); - - Map fieldB = Collections.singletonMap("b", "b"); - doc.addAttribute("foo", fieldB); - final DocumentCreateEntity updated = collection.insertDocument(doc, - new DocumentCreateOptions().overwriteMode(OverwriteMode.update).mergeObjects(false).returnNew(true)); - - assertThat(updated).isNotNull(); - assertThat(updated.getRev()).isNotEqualTo(meta.getRev()); - assertThat(updated.getNew().getAttribute("foo")).isEqualTo(fieldB); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void insertDocumentOverwriteModeUpdateKeepNullTrue(ArangoCollection collection) { - assumeTrue(isAtLeastVersion(3, 7)); - - final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); - doc.addAttribute("foo", "bar"); - collection.insertDocument(doc); - - doc.updateAttribute("foo", null); - final BaseDocument updated = collection.insertDocument(doc, new DocumentCreateOptions() - .overwriteMode(OverwriteMode.update) - .keepNull(true) - .returnNew(true)).getNew(); - - assertThat(updated.getProperties()).containsEntry("foo", null); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void insertDocumentOverwriteModeUpdateKeepNullFalse(ArangoCollection collection) { - assumeTrue(isAtLeastVersion(3, 7)); - - final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); - doc.addAttribute("foo", "bar"); - collection.insertDocument(doc); - - doc.updateAttribute("foo", null); - final BaseDocument updated = collection.insertDocument(doc, new DocumentCreateOptions() - .overwriteMode(OverwriteMode.update) - .keepNull(false) - .returnNew(true)).getNew(); - - assertThat(updated.getProperties()).doesNotContainKey("foo"); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void insertDocumentWaitForSync(ArangoCollection collection) { - final DocumentCreateOptions options = new DocumentCreateOptions().waitForSync(true); - final DocumentCreateEntity doc = collection.insertDocument(new BaseDocument(), options); - assertThat(doc).isNotNull(); - assertThat(doc.getId()).isNotNull(); - assertThat(doc.getKey()).isNotNull(); - assertThat(doc.getRev()).isNotNull(); - assertThat(doc.getNew()).isNull(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void insertDocumentAsJson(ArangoCollection collection) { - String key = "doc-" + UUID.randomUUID(); - RawJson rawJson = RawJson.of("{\"_key\":\"" + key + "\",\"a\":\"test\"}"); - final DocumentCreateEntity doc = collection.insertDocument(rawJson); - assertThat(doc).isNotNull(); - assertThat(doc.getId()).isEqualTo(collection.name() + "/" + key); - assertThat(doc.getKey()).isEqualTo(key); - assertThat(doc.getRev()).isNotNull(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void insertDocumentAsBytes(ArangoCollection collection) { - String key = "doc-" + UUID.randomUUID(); - Map doc = new HashMap<>(); - doc.put("_key", key); - doc.put("a", "test"); - byte[] bytes = collection.getSerde().serializeUserData(doc); - RawBytes rawJson = RawBytes.of(bytes); - final DocumentCreateEntity createEntity = collection.insertDocument(rawJson, -new DocumentCreateOptions().returnNew(true)); - assertThat(createEntity).isNotNull(); - assertThat(createEntity.getId()).isEqualTo(collection.name() + "/" + key); - assertThat(createEntity.getKey()).isEqualTo(key); - assertThat(createEntity.getRev()).isNotNull(); - assertThat(createEntity.getNew()).isNotNull().isInstanceOf(RawBytes.class); - Map newDoc = collection.getSerde().deserializeUserData(createEntity.getNew().getValue(), - Map.class); - assertThat(newDoc).containsAllEntriesOf(doc); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void insertDocumentSilent(ArangoCollection collection) { - assumeTrue(isSingleServer()); - final DocumentCreateEntity meta = collection.insertDocument(new BaseDocument(), - new DocumentCreateOptions().silent(true)); - assertThat(meta).isNotNull(); - assertThat(meta.getId()).isNull(); - assertThat(meta.getKey()).isNull(); - assertThat(meta.getRev()).isNull(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void insertDocumentSilentDontTouchInstance(ArangoCollection collection) { - assumeTrue(isSingleServer()); - final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); - final String key = "testkey-" + UUID.randomUUID(); - doc.setKey(key); - final DocumentCreateEntity meta = collection.insertDocument(doc, - new DocumentCreateOptions().silent(true)); - assertThat(meta).isNotNull(); - assertThat(meta.getKey()).isNull(); - assertThat(doc.getKey()).isEqualTo(key); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void insertDocumentsSilent(ArangoCollection collection) { - assumeTrue(isSingleServer()); - final MultiDocumentEntity> info = - collection.insertDocuments(Arrays.asList(new BaseDocument(), new BaseDocument()), -new DocumentCreateOptions().silent(true)); - assertThat(info).isNotNull(); - assertThat(info.getDocuments()).isEmpty(); - assertThat(info.getDocumentsAndErrors()).isEmpty(); - assertThat(info.getErrors()).isEmpty(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void getDocument(ArangoCollection collection) { - final DocumentCreateEntity createResult = collection.insertDocument(new BaseDocument(), null); - assertThat(createResult.getKey()).isNotNull(); - final BaseDocument readResult = collection.getDocument(createResult.getKey(), BaseDocument.class, null); - assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); - assertThat(readResult.getId()).isEqualTo(COLLECTION_NAME + "/" + createResult.getKey()); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void getDocumentIfMatch(ArangoCollection collection) { - final DocumentCreateEntity createResult = collection.insertDocument(new BaseDocument(), null); - assertThat(createResult.getKey()).isNotNull(); - final DocumentReadOptions options = new DocumentReadOptions().ifMatch(createResult.getRev()); - final BaseDocument readResult = collection.getDocument(createResult.getKey(), BaseDocument.class, options); - assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); - assertThat(readResult.getId()).isEqualTo(COLLECTION_NAME + "/" + createResult.getKey()); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void getDocumentIfMatchFail(ArangoCollection collection) { - final DocumentCreateEntity createResult = collection.insertDocument(new BaseDocument(), null); - assertThat(createResult.getKey()).isNotNull(); - final DocumentReadOptions options = new DocumentReadOptions().ifMatch("no"); - final BaseDocument document = collection.getDocument(createResult.getKey(), BaseDocument.class, options); - assertThat(document).isNull(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void getDocumentIfNoneMatch(ArangoCollection collection) { - final DocumentCreateEntity createResult = collection.insertDocument(new BaseDocument(), null); - assertThat(createResult.getKey()).isNotNull(); - final DocumentReadOptions options = new DocumentReadOptions().ifNoneMatch("no"); - final BaseDocument readResult = collection.getDocument(createResult.getKey(), BaseDocument.class, options); - assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); - assertThat(readResult.getId()).isEqualTo(COLLECTION_NAME + "/" + createResult.getKey()); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void getDocumentIfNoneMatchFail(ArangoCollection collection) { - final DocumentCreateEntity createResult = collection.insertDocument(new BaseDocument(), null); - assertThat(createResult.getKey()).isNotNull(); - final DocumentReadOptions options = new DocumentReadOptions().ifNoneMatch(createResult.getRev()); - final BaseDocument document = collection.getDocument(createResult.getKey(), BaseDocument.class, options); - assertThat(document).isNull(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void getDocumentAsJson(ArangoCollection collection) { - String key = rnd(); - RawJson rawJson = RawJson.of("{\"_key\":\"" + key + "\",\"a\":\"test\"}"); - collection.insertDocument(rawJson); - final RawJson readResult = collection.getDocument(key, RawJson.class); - assertThat(readResult.getValue()).contains("\"_key\":\"" + key + "\"").contains("\"_id\":\"" + COLLECTION_NAME + "/" + key + "\""); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void getDocumentNotFound(ArangoCollection collection) { - final BaseDocument document = collection.getDocument("no", BaseDocument.class); - assertThat(document).isNull(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void getDocumentNotFoundOptionsDefault(ArangoCollection collection) { - final BaseDocument document = collection.getDocument("no", BaseDocument.class, new DocumentReadOptions()); - assertThat(document).isNull(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void getDocumentNotFoundOptionsNull(ArangoCollection collection) { - final BaseDocument document = collection.getDocument("no", BaseDocument.class, null); - assertThat(document).isNull(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void getDocumentWrongKey(ArangoCollection collection) { - Throwable thrown = catchThrowable(() -> collection.getDocument("no/no", BaseDocument.class)); - assertThat(thrown).isInstanceOf(ArangoDBException.class); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void getDocumentDirtyRead(ArangoCollection collection) throws InterruptedException { - final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); - collection.insertDocument(doc, new DocumentCreateOptions()); - Thread.sleep(2000); - final RawJson document = collection.getDocument(doc.getKey(), RawJson.class, - new DocumentReadOptions().allowDirtyRead(true)); - assertThat(document).isNotNull(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void getDocuments(ArangoCollection collection) { - final Collection values = new ArrayList<>(); - values.add(new BaseDocument("1")); - values.add(new BaseDocument("2")); - values.add(new BaseDocument("3")); - collection.insertDocuments(values); - final MultiDocumentEntity documents = collection.getDocuments(Arrays.asList("1", "2", "3"), -BaseDocument.class); - assertThat(documents).isNotNull(); - assertThat(documents.getDocuments()).hasSize(3); - for (final BaseDocument document : documents.getDocuments()) { - assertThat(document.getId()).isIn(COLLECTION_NAME + "/" + "1", COLLECTION_NAME + "/" + "2", - COLLECTION_NAME + "/" + "3"); - } - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void getDocumentsWithCustomShardingKey(ArangoCollection c) { - ArangoCollection collection = c.db().collection("customShardingKeyCollection"); - if (collection.exists()) collection.drop(); - - collection.create(new CollectionCreateOptions().shardKeys("customField").numberOfShards(10)); - - List values = - IntStream.range(0, 10).mapToObj(String::valueOf).map(key -> new BaseDocument()).peek(it -> it.addAttribute( - "customField", rnd())).collect(Collectors.toList()); - - MultiDocumentEntity> inserted = collection.insertDocuments(values); - List insertedKeys = - inserted.getDocuments().stream().map(DocumentEntity::getKey).collect(Collectors.toList()); - - final Collection documents = -collection.getDocuments(insertedKeys, BaseDocument.class).getDocuments(); - - assertThat(documents).hasSize(10); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void getDocumentsDirtyRead(ArangoCollection collection) { - final Collection values = new ArrayList<>(); - values.add(new BaseDocument("1")); - values.add(new BaseDocument("2")); - values.add(new BaseDocument("3")); - collection.insertDocuments(values); - final MultiDocumentEntity documents = collection.getDocuments(Arrays.asList("1", "2", "3"), - BaseDocument.class, new DocumentReadOptions().allowDirtyRead(true)); - assertThat(documents).isNotNull(); - if (isAtLeastVersion(3, 10)) { - assertThat(documents.isPotentialDirtyRead()).isTrue(); - } - assertThat(documents.getDocuments()).hasSize(3); - for (final BaseDocument document : documents.getDocuments()) { - assertThat(document.getId()).isIn(COLLECTION_NAME + "/" + "1", COLLECTION_NAME + "/" + "2", - COLLECTION_NAME + "/" + "3"); - } - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void getDocumentsNotFound(ArangoCollection collection) { - final MultiDocumentEntity readResult = collection.getDocuments(Collections.singleton("no"), - BaseDocument.class); - assertThat(readResult).isNotNull(); - assertThat(readResult.getDocuments()).isEmpty(); - assertThat(readResult.getErrors()).hasSize(1); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void getDocumentsWrongKey(ArangoCollection collection) { - final MultiDocumentEntity readResult = collection.getDocuments(Collections.singleton("no/no"), - BaseDocument.class); - assertThat(readResult).isNotNull(); - assertThat(readResult.getDocuments()).isEmpty(); - assertThat(readResult.getErrors()).hasSize(1); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void updateDocument(ArangoCollection collection) { - final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); - doc.addAttribute("a", "test"); - doc.addAttribute("c", "test"); - final DocumentCreateEntity createResult = collection.insertDocument(doc, null); - doc.updateAttribute("a", "test1"); - doc.addAttribute("b", "test"); - doc.updateAttribute("c", null); - final DocumentUpdateEntity updateResult = collection.updateDocument(createResult.getKey(), doc, -null); - assertThat(updateResult).isNotNull(); - assertThat(updateResult.getId()).isEqualTo(createResult.getId()); - assertThat(updateResult.getNew()).isNull(); - assertThat(updateResult.getOld()).isNull(); - assertThat(updateResult.getRev()).isNotEqualTo(updateResult.getOldRev()); - assertThat(updateResult.getOldRev()).isEqualTo(createResult.getRev()); - - final BaseDocument readResult = collection.getDocument(createResult.getKey(), BaseDocument.class, null); - assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); - assertThat(readResult.getAttribute("a")).isNotNull(); - assertThat(String.valueOf(readResult.getAttribute("a"))).isEqualTo("test1"); - assertThat(readResult.getAttribute("b")).isNotNull(); - assertThat(String.valueOf(readResult.getAttribute("b"))).isEqualTo("test"); - assertThat(readResult.getRevision()).isEqualTo(updateResult.getRev()); - assertThat(readResult.getProperties()).containsKey("c"); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void updateDocumentWithDifferentReturnType(ArangoCollection collection) { - final String key = "key-" + UUID.randomUUID(); - final BaseDocument doc = new BaseDocument(key); - doc.addAttribute("a", "test"); - collection.insertDocument(doc); - - final DocumentUpdateEntity updateResult = collection.updateDocument(key, -Collections.singletonMap("b", "test"), new DocumentUpdateOptions().returnNew(true), BaseDocument.class); - assertThat(updateResult).isNotNull(); - assertThat(updateResult.getKey()).isEqualTo(key); - BaseDocument updated = updateResult.getNew(); - assertThat(updated).isNotNull(); - assertThat(updated.getAttribute("a")).isEqualTo("test"); - assertThat(updated.getAttribute("b")).isEqualTo("test"); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void updateDocumentUpdateRev(ArangoCollection collection) { - final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); - final DocumentCreateEntity createResult = collection.insertDocument(doc, null); - doc.addAttribute("foo", "bar"); - final DocumentUpdateEntity updateResult = collection.updateDocument(createResult.getKey(), doc, - null); - assertThat(doc.getRevision()).isNull(); - assertThat(createResult.getRev()).isNotNull(); - assertThat(updateResult.getRev()) - .isNotNull() - .isNotEqualTo(createResult.getRev()); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void updateDocumentIfMatch(ArangoCollection collection) { - final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); - doc.addAttribute("a", "test"); - doc.addAttribute("c", "test"); - final DocumentCreateEntity createResult = collection.insertDocument(doc, null); - doc.updateAttribute("a", "test1"); - doc.addAttribute("b", "test"); - doc.updateAttribute("c", null); - final DocumentUpdateOptions options = new DocumentUpdateOptions().ifMatch(createResult.getRev()); - final DocumentUpdateEntity updateResult = collection.updateDocument(createResult.getKey(), doc, - options); - assertThat(updateResult).isNotNull(); - assertThat(updateResult.getId()).isEqualTo(createResult.getId()); - assertThat(updateResult.getRev()).isNotEqualTo(updateResult.getOldRev()); - assertThat(updateResult.getOldRev()).isEqualTo(createResult.getRev()); - - final BaseDocument readResult = collection.getDocument(createResult.getKey(), BaseDocument.class, null); - assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); - assertThat(readResult.getAttribute("a")).isNotNull(); - assertThat(String.valueOf(readResult.getAttribute("a"))).isEqualTo("test1"); - assertThat(readResult.getAttribute("b")).isNotNull(); - assertThat(String.valueOf(readResult.getAttribute("b"))).isEqualTo("test"); - assertThat(readResult.getRevision()).isEqualTo(updateResult.getRev()); - assertThat(readResult.getProperties()).containsKey("c"); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void updateDocumentIfMatchFail(ArangoCollection collection) { - final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); - doc.addAttribute("a", "test"); - doc.addAttribute("c", "test"); - final DocumentCreateEntity createResult = collection.insertDocument(doc, null); - doc.updateAttribute("a", "test1"); - doc.addAttribute("b", "test"); - doc.updateAttribute("c", null); - - final DocumentUpdateOptions options = new DocumentUpdateOptions().ifMatch("no"); - Throwable thrown = catchThrowable(() -> collection.updateDocument(createResult.getKey(), doc, options)); - assertThat(thrown).isInstanceOf(ArangoDBException.class); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void updateDocumentReturnNew(ArangoCollection collection) { - final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); - doc.addAttribute("a", "test"); - final DocumentCreateEntity createResult = collection.insertDocument(doc, null); - doc.updateAttribute("a", "test1"); - doc.addAttribute("b", "test"); - final DocumentUpdateOptions options = new DocumentUpdateOptions().returnNew(true); - final DocumentUpdateEntity updateResult = collection.updateDocument(createResult.getKey(), doc, - options); - assertThat(updateResult).isNotNull(); - assertThat(updateResult.getId()).isEqualTo(createResult.getId()); - assertThat(updateResult.getOldRev()).isEqualTo(createResult.getRev()); - assertThat(updateResult.getNew()).isNotNull(); - assertThat(updateResult.getNew().getKey()).isEqualTo(createResult.getKey()); - assertThat(updateResult.getNew().getRevision()).isNotEqualTo(createResult.getRev()); - assertThat(updateResult.getNew().getAttribute("a")).isNotNull(); - assertThat(String.valueOf(updateResult.getNew().getAttribute("a"))).isEqualTo("test1"); - assertThat(updateResult.getNew().getAttribute("b")).isNotNull(); - assertThat(String.valueOf(updateResult.getNew().getAttribute("b"))).isEqualTo("test"); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void updateDocumentReturnOld(ArangoCollection collection) { - final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); - doc.addAttribute("a", "test"); - final DocumentCreateEntity createResult = collection.insertDocument(doc, null); - doc.updateAttribute("a", "test1"); - doc.addAttribute("b", "test"); - final DocumentUpdateOptions options = new DocumentUpdateOptions().returnOld(true); - final DocumentUpdateEntity updateResult = collection.updateDocument(createResult.getKey(), doc, - options); - assertThat(updateResult).isNotNull(); - assertThat(updateResult.getId()).isEqualTo(createResult.getId()); - assertThat(updateResult.getOldRev()).isEqualTo(createResult.getRev()); - assertThat(updateResult.getOld()).isNotNull(); - assertThat(updateResult.getOld().getKey()).isEqualTo(createResult.getKey()); - assertThat(updateResult.getOld().getRevision()).isEqualTo(createResult.getRev()); - assertThat(updateResult.getOld().getAttribute("a")).isNotNull(); - assertThat(String.valueOf(updateResult.getOld().getAttribute("a"))).isEqualTo("test"); - assertThat(updateResult.getOld().getProperties().keySet()).doesNotContain("b"); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void updateDocumentKeepNullTrue(ArangoCollection collection) { - final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); - doc.addAttribute("a", "test"); - final DocumentCreateEntity createResult = collection.insertDocument(doc, null); - doc.updateAttribute("a", null); - final DocumentUpdateOptions options = new DocumentUpdateOptions().keepNull(true); - final DocumentUpdateEntity updateResult = collection.updateDocument(createResult.getKey(), doc, - options); - assertThat(updateResult).isNotNull(); - assertThat(updateResult.getId()).isEqualTo(createResult.getId()); - assertThat(updateResult.getRev()).isNotEqualTo(updateResult.getOldRev()); - assertThat(updateResult.getOldRev()).isEqualTo(createResult.getRev()); - - final BaseDocument readResult = collection.getDocument(createResult.getKey(), BaseDocument.class, null); - assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); - assertThat(readResult.getProperties()).containsKey("a"); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void updateDocumentKeepNullFalse(ArangoCollection collection) { - final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); - doc.addAttribute("a", "test"); - final DocumentCreateEntity createResult = collection.insertDocument(doc, null); - doc.updateAttribute("a", null); - final DocumentUpdateOptions options = new DocumentUpdateOptions().keepNull(false); - final DocumentUpdateEntity updateResult = collection.updateDocument(createResult.getKey(), doc, - options); - assertThat(updateResult).isNotNull(); - assertThat(updateResult.getId()).isEqualTo(createResult.getId()); - assertThat(updateResult.getRev()).isNotEqualTo(updateResult.getOldRev()); - assertThat(updateResult.getOldRev()).isEqualTo(createResult.getRev()); - - final BaseDocument readResult = collection.getDocument(createResult.getKey(), BaseDocument.class, null); - assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); - assertThat(readResult.getId()).isEqualTo(createResult.getId()); - assertThat(readResult.getRevision()).isNotNull(); - assertThat(readResult.getProperties().keySet()).doesNotContain("a"); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void updateDocumentSerializeNullTrue(ArangoCollection collection) { - final TestUpdateEntity doc = new TestUpdateEntity(); - doc.a = "foo"; - doc.b = "foo"; - final DocumentCreateEntity createResult = collection.insertDocument(doc); - final TestUpdateEntity patchDoc = new TestUpdateEntity(); - patchDoc.a = "bar"; - final DocumentUpdateEntity updateResult = collection.updateDocument(createResult.getKey(), patchDoc); - assertThat(updateResult).isNotNull(); - assertThat(updateResult.getKey()).isEqualTo(createResult.getKey()); - - final BaseDocument readResult = collection.getDocument(createResult.getKey(), BaseDocument.class); - assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); - assertThat(readResult.getProperties()).containsKey("a"); - assertThat(readResult.getAttribute("a")).isEqualTo("bar"); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void updateDocumentSerializeNullFalse(ArangoCollection collection) { - final TestUpdateEntitySerializeNullFalse doc = new TestUpdateEntitySerializeNullFalse(); - doc.a = "foo"; - doc.b = "foo"; - final DocumentCreateEntity createResult = collection.insertDocument(doc); - final TestUpdateEntitySerializeNullFalse patchDoc = new TestUpdateEntitySerializeNullFalse(); - patchDoc.a = "bar"; - final DocumentUpdateEntity updateResult = collection.updateDocument(createResult.getKey(), patchDoc); - assertThat(updateResult).isNotNull(); - assertThat(updateResult.getKey()).isEqualTo(createResult.getKey()); - - final BaseDocument readResult = collection.getDocument(createResult.getKey(), BaseDocument.class); - assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); - assertThat(readResult.getProperties()).containsKeys("a", "b"); - assertThat(readResult.getAttribute("a")).isEqualTo("bar"); - assertThat(readResult.getAttribute("b")).isEqualTo("foo"); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void updateDocumentMergeObjectsTrue(ArangoCollection collection) { - final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); - final Map a = new HashMap<>(); - a.put("a", "test"); - doc.addAttribute("a", a); - final DocumentCreateEntity createResult = collection.insertDocument(doc, null); - a.clear(); - a.put("b", "test"); - doc.updateAttribute("a", a); - final DocumentUpdateOptions options = new DocumentUpdateOptions().mergeObjects(true); - final DocumentUpdateEntity updateResult = collection.updateDocument(createResult.getKey(), doc, -options); - assertThat(updateResult).isNotNull(); - assertThat(updateResult.getId()).isEqualTo(createResult.getId()); - assertThat(updateResult.getRev()).isNotEqualTo(updateResult.getOldRev()); - assertThat(updateResult.getOldRev()).isEqualTo(createResult.getRev()); - - final BaseDocument readResult = collection.getDocument(createResult.getKey(), BaseDocument.class, null); - assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); - final Object aResult = readResult.getAttribute("a"); - assertThat(aResult).isInstanceOf(Map.class); - final Map aMap = (Map) aResult; - assertThat(aMap).containsKeys("a", "b"); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void updateDocumentMergeObjectsFalse(ArangoCollection collection) { - final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); - final Map a = new HashMap<>(); - a.put("a", "test"); - doc.addAttribute("a", a); - final DocumentCreateEntity createResult = collection.insertDocument(doc, null); - a.clear(); - a.put("b", "test"); - doc.updateAttribute("a", a); - final DocumentUpdateOptions options = new DocumentUpdateOptions().mergeObjects(false); - final DocumentUpdateEntity updateResult = collection.updateDocument(createResult.getKey(), doc, - options); - assertThat(updateResult).isNotNull(); - assertThat(updateResult.getId()).isEqualTo(createResult.getId()); - assertThat(updateResult.getRev()).isNotEqualTo(updateResult.getOldRev()); - assertThat(updateResult.getOldRev()).isEqualTo(createResult.getRev()); - - final BaseDocument readResult = collection.getDocument(createResult.getKey(), BaseDocument.class, null); - assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); - final Object aResult = readResult.getAttribute("a"); - assertThat(aResult).isInstanceOf(Map.class); - final Map aMap = (Map) aResult; - assertThat(aMap.keySet()).doesNotContain("a"); - assertThat(aMap).containsKey("b"); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void updateDocumentIgnoreRevsFalse(ArangoCollection collection) { - final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); - doc.addAttribute("a", "test"); - final DocumentCreateEntity createResult = collection.insertDocument(doc, null); - doc.updateAttribute("a", "test1"); - doc.setRevision("no"); - - final DocumentUpdateOptions options = new DocumentUpdateOptions().ignoreRevs(false); - Throwable thrown = catchThrowable(() -> collection.updateDocument(createResult.getKey(), doc, options)); - assertThat(thrown).isInstanceOf(ArangoDBException.class); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void updateDocumentSilent(ArangoCollection collection) { - assumeTrue(isSingleServer()); - final DocumentCreateEntity createResult = collection.insertDocument(new BaseDocument()); - final DocumentUpdateEntity meta = collection.updateDocument(createResult.getKey(), - new BaseDocument(), new DocumentUpdateOptions().silent(true)); - assertThat(meta).isNotNull(); - assertThat(meta.getId()).isNull(); - assertThat(meta.getKey()).isNull(); - assertThat(meta.getRev()).isNull(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void updateDocumentsSilent(ArangoCollection collection) { - assumeTrue(isSingleServer()); - final DocumentCreateEntity createResult = collection.insertDocument(new BaseDocument()); - final MultiDocumentEntity> info = -collection.updateDocuments(Collections.singletonList(new BaseDocument(createResult.getKey())), - new DocumentUpdateOptions().silent(true)); - assertThat(info).isNotNull(); - assertThat(info.getDocuments()).isEmpty(); - assertThat(info.getDocumentsAndErrors()).isEmpty(); - assertThat(info.getErrors()).isEmpty(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void updateNonExistingDocument(ArangoCollection collection) { - final BaseDocument doc = new BaseDocument("test-" + rnd()); - doc.addAttribute("a", "test"); - doc.addAttribute("c", "test"); - - Throwable thrown = catchThrowable(() -> collection.updateDocument(doc.getKey(), doc, null)); - assertThat(thrown).isInstanceOf(ArangoDBException.class); - ArangoDBException e = (ArangoDBException) thrown; - assertThat(e.getResponseCode()).isEqualTo(404); - assertThat(e.getErrorNum()).isEqualTo(1202); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void updateDocumentPreconditionFailed(ArangoCollection collection) { - final BaseDocument doc = new BaseDocument("test-" + rnd()); - doc.addAttribute("foo", "a"); - final DocumentCreateEntity createResult = collection.insertDocument(doc, null); - - doc.updateAttribute("foo", "b"); - collection.updateDocument(doc.getKey(), doc, null); - - doc.updateAttribute("foo", "c"); - Throwable thrown = catchThrowable(() -> collection.updateDocument(doc.getKey(), doc, - new DocumentUpdateOptions().ifMatch(createResult.getRev()))); - assertThat(thrown).isInstanceOf(ArangoDBException.class); - ArangoDBException e = (ArangoDBException) thrown; - assertThat(e.getResponseCode()).isEqualTo(412); - assertThat(e.getErrorNum()).isEqualTo(1200); - BaseDocument readDocument = collection.getDocument(doc.getKey(), BaseDocument.class); - assertThat(readDocument.getAttribute("foo")).isEqualTo("b"); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void replaceDocument(ArangoCollection collection) { - final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); - doc.addAttribute("a", "test"); - final DocumentCreateEntity createResult = collection.insertDocument(doc, null); - doc.removeAttribute("a"); - doc.addAttribute("b", "test"); - final DocumentUpdateEntity replaceResult = collection.replaceDocument(createResult.getKey(), -doc, null); - assertThat(replaceResult).isNotNull(); - assertThat(replaceResult.getId()).isEqualTo(createResult.getId()); - assertThat(replaceResult.getNew()).isNull(); - assertThat(replaceResult.getOld()).isNull(); - assertThat(replaceResult.getRev()).isNotEqualTo(replaceResult.getOldRev()); - assertThat(replaceResult.getOldRev()).isEqualTo(createResult.getRev()); - - final BaseDocument readResult = collection.getDocument(createResult.getKey(), BaseDocument.class, null); - assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); - assertThat(readResult.getRevision()).isEqualTo(replaceResult.getRev()); - assertThat(readResult.getProperties().keySet()).doesNotContain("a"); - assertThat(readResult.getAttribute("b")).isNotNull(); - assertThat(String.valueOf(readResult.getAttribute("b"))).isEqualTo("test"); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void replaceDocumentUpdateRev(ArangoCollection collection) { - final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); - final DocumentCreateEntity createResult = collection.insertDocument(doc, null); - final DocumentUpdateEntity replaceResult = collection.replaceDocument(createResult.getKey(), - doc, null); - assertThat(doc.getRevision()).isNull(); - assertThat(createResult.getRev()).isNotNull(); - assertThat(replaceResult.getRev()) - .isNotNull() - .isNotEqualTo(createResult.getRev()); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void replaceDocumentIfMatch(ArangoCollection collection) { - final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); - doc.addAttribute("a", "test"); - final DocumentCreateEntity createResult = collection.insertDocument(doc, null); - doc.removeAttribute("a"); - doc.addAttribute("b", "test"); - final DocumentReplaceOptions options = new DocumentReplaceOptions().ifMatch(createResult.getRev()); - final DocumentUpdateEntity replaceResult = collection.replaceDocument(createResult.getKey(), - doc, options); - assertThat(replaceResult).isNotNull(); - assertThat(replaceResult.getId()).isEqualTo(createResult.getId()); - assertThat(replaceResult.getRev()).isNotEqualTo(replaceResult.getOldRev()); - assertThat(replaceResult.getOldRev()).isEqualTo(createResult.getRev()); - - final BaseDocument readResult = collection.getDocument(createResult.getKey(), BaseDocument.class, null); - assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); - assertThat(readResult.getRevision()).isEqualTo(replaceResult.getRev()); - assertThat(readResult.getProperties().keySet()).doesNotContain("a"); - assertThat(readResult.getAttribute("b")).isNotNull(); - assertThat(String.valueOf(readResult.getAttribute("b"))).isEqualTo("test"); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void replaceDocumentIfMatchFail(ArangoCollection collection) { - final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); - doc.addAttribute("a", "test"); - final DocumentCreateEntity createResult = collection.insertDocument(doc, null); - doc.removeAttribute("a"); - doc.addAttribute("b", "test"); - - final DocumentReplaceOptions options = new DocumentReplaceOptions().ifMatch("no"); - Throwable thrown = catchThrowable(() -> collection.replaceDocument(createResult.getKey(), doc, options)); - assertThat(thrown).isInstanceOf(ArangoDBException.class); - - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void replaceDocumentIgnoreRevsFalse(ArangoCollection collection) { - final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); - doc.addAttribute("a", "test"); - final DocumentCreateEntity createResult = collection.insertDocument(doc, null); - doc.removeAttribute("a"); - doc.addAttribute("b", "test"); - doc.setRevision("no"); - - final DocumentReplaceOptions options = new DocumentReplaceOptions().ignoreRevs(false); - Throwable thrown = catchThrowable(() -> collection.replaceDocument(createResult.getKey(), doc, options)); - assertThat(thrown).isInstanceOf(ArangoDBException.class); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void replaceDocumentReturnNew(ArangoCollection collection) { - final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); - doc.addAttribute("a", "test"); - final DocumentCreateEntity createResult = collection.insertDocument(doc, null); - doc.removeAttribute("a"); - doc.addAttribute("b", "test"); - final DocumentReplaceOptions options = new DocumentReplaceOptions().returnNew(true); - final DocumentUpdateEntity replaceResult = collection.replaceDocument(createResult.getKey(), -doc, options); - assertThat(replaceResult).isNotNull(); - assertThat(replaceResult.getId()).isEqualTo(createResult.getId()); - assertThat(replaceResult.getOldRev()).isEqualTo(createResult.getRev()); - assertThat(replaceResult.getNew()).isNotNull(); - assertThat(replaceResult.getNew().getKey()).isEqualTo(createResult.getKey()); - assertThat(replaceResult.getNew().getRevision()).isNotEqualTo(createResult.getRev()); - assertThat(replaceResult.getNew().getProperties().keySet()).doesNotContain("a"); - assertThat(replaceResult.getNew().getAttribute("b")).isNotNull(); - assertThat(String.valueOf(replaceResult.getNew().getAttribute("b"))).isEqualTo("test"); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void replaceDocumentReturnOld(ArangoCollection collection) { - final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); - doc.addAttribute("a", "test"); - final DocumentCreateEntity createResult = collection.insertDocument(doc, null); - doc.removeAttribute("a"); - doc.addAttribute("b", "test"); - final DocumentReplaceOptions options = new DocumentReplaceOptions().returnOld(true); - final DocumentUpdateEntity replaceResult = collection.replaceDocument(createResult.getKey(), - doc, options); - assertThat(replaceResult).isNotNull(); - assertThat(replaceResult.getId()).isEqualTo(createResult.getId()); - assertThat(replaceResult.getOldRev()).isEqualTo(createResult.getRev()); - assertThat(replaceResult.getOld()).isNotNull(); - assertThat(replaceResult.getOld().getKey()).isEqualTo(createResult.getKey()); - assertThat(replaceResult.getOld().getRevision()).isEqualTo(createResult.getRev()); - assertThat(replaceResult.getOld().getAttribute("a")).isNotNull(); - assertThat(String.valueOf(replaceResult.getOld().getAttribute("a"))).isEqualTo("test"); - assertThat(replaceResult.getOld().getProperties().keySet()).doesNotContain("b"); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void replaceDocumentSilent(ArangoCollection collection) { - assumeTrue(isSingleServer()); - final DocumentCreateEntity createResult = collection.insertDocument(new BaseDocument()); - final DocumentUpdateEntity meta = collection.replaceDocument(createResult.getKey(), -new BaseDocument(), new DocumentReplaceOptions().silent(true)); - assertThat(meta).isNotNull(); - assertThat(meta.getId()).isNull(); - assertThat(meta.getKey()).isNull(); - assertThat(meta.getRev()).isNull(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void replaceDocumentSilentDontTouchInstance(ArangoCollection collection) { - assumeTrue(isSingleServer()); - final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); - final DocumentCreateEntity createResult = collection.insertDocument(doc); - final DocumentUpdateEntity meta = collection.replaceDocument(createResult.getKey(), doc, - new DocumentReplaceOptions().silent(true)); - assertThat(meta.getRev()).isNull(); - assertThat(doc.getRevision()).isNull(); - assertThat(createResult.getRev()).isNotNull(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void replaceDocumentsSilent(ArangoCollection collection) { - assumeTrue(isSingleServer()); - final DocumentCreateEntity createResult = collection.insertDocument(new BaseDocument()); - final MultiDocumentEntity> info = - collection.replaceDocuments(Collections.singletonList(new BaseDocument(createResult.getKey())), - new DocumentReplaceOptions().silent(true)); - assertThat(info).isNotNull(); - assertThat(info.getDocuments()).isEmpty(); - assertThat(info.getDocumentsAndErrors()).isEmpty(); - assertThat(info.getErrors()).isEmpty(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void deleteDocument(ArangoCollection collection) { - final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); - final DocumentCreateEntity createResult = collection.insertDocument(doc, null); - collection.deleteDocument(createResult.getKey()); - final BaseDocument document = collection.getDocument(createResult.getKey(), BaseDocument.class, null); - assertThat(document).isNull(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void deleteDocumentReturnOld(ArangoCollection collection) { - final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); - doc.addAttribute("a", "test"); - final DocumentCreateEntity createResult = collection.insertDocument(doc, null); - final DocumentDeleteOptions options = new DocumentDeleteOptions().returnOld(true); - final DocumentDeleteEntity deleteResult = collection.deleteDocument(createResult.getKey(), - options, BaseDocument.class); - assertThat(deleteResult.getOld()).isNotNull(); - assertThat(deleteResult.getOld()).isInstanceOf(BaseDocument.class); - assertThat(deleteResult.getOld().getAttribute("a")).isNotNull(); - assertThat(String.valueOf(deleteResult.getOld().getAttribute("a"))).isEqualTo("test"); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void deleteDocumentIfMatch(ArangoCollection collection) { - final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); - final DocumentCreateEntity createResult = collection.insertDocument(doc, null); - final DocumentDeleteOptions options = new DocumentDeleteOptions().ifMatch(createResult.getRev()); - collection.deleteDocument(createResult.getKey(), options); - final BaseDocument document = collection.getDocument(createResult.getKey(), BaseDocument.class, null); - assertThat(document).isNull(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void deleteDocumentIfMatchFail(ArangoCollection collection) { - final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); - final DocumentCreateEntity createResult = collection.insertDocument(doc); - final DocumentDeleteOptions options = new DocumentDeleteOptions().ifMatch("no"); - Throwable thrown = catchThrowable(() -> collection.deleteDocument(createResult.getKey(), options)); - assertThat(thrown).isInstanceOf(ArangoDBException.class); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void deleteDocumentSilent(ArangoCollection collection) { - assumeTrue(isSingleServer()); - final DocumentCreateEntity createResult = collection.insertDocument(new BaseDocument()); - final DocumentDeleteEntity meta = collection.deleteDocument(createResult.getKey(), - new DocumentDeleteOptions().silent(true), BaseDocument.class); - assertThat(meta).isNotNull(); - assertThat(meta.getId()).isNull(); - assertThat(meta.getKey()).isNull(); - assertThat(meta.getRev()).isNull(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void deleteDocumentsSilent(ArangoCollection collection) { - assumeTrue(isSingleServer()); - final DocumentCreateEntity createResult = collection.insertDocument(new BaseDocument()); - final MultiDocumentEntity> info = collection.deleteDocuments( - Collections.singletonList(createResult.getKey()), - new DocumentDeleteOptions().silent(true), - BaseDocument.class); - assertThat(info).isNotNull(); - assertThat(info.getDocuments()).isEmpty(); - assertThat(info.getDocumentsAndErrors()).isEmpty(); - assertThat(info.getErrors()).isEmpty(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void getIndex(ArangoCollection collection) { - final Collection fields = new ArrayList<>(); - fields.add("a"); - final IndexEntity createResult = collection.ensureHashIndex(fields, null); - final IndexEntity readResult = collection.getIndex(createResult.getId()); - assertThat(readResult.getId()).isEqualTo(createResult.getId()); - assertThat(readResult.getType()).isEqualTo(createResult.getType()); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void getIndexByKey(ArangoCollection collection) { - final Collection fields = new ArrayList<>(); - fields.add("a"); - final IndexEntity createResult = collection.ensureHashIndex(fields, null); - final IndexEntity readResult = collection.getIndex(createResult.getId().split("/")[1]); - assertThat(readResult.getId()).isEqualTo(createResult.getId()); - assertThat(readResult.getType()).isEqualTo(createResult.getType()); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void deleteIndex(ArangoCollection collection) { - final Collection fields = new ArrayList<>(); - fields.add("a"); - final IndexEntity createResult = collection.ensureHashIndex(fields, null); - final String id = collection.deleteIndex(createResult.getId()); - assertThat(id).isEqualTo(createResult.getId()); - Throwable thrown = catchThrowable(() -> collection.db().getIndex(id)); - assertThat(thrown).isInstanceOf(ArangoDBException.class); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void deleteIndexByKey(ArangoCollection collection) { - final Collection fields = new ArrayList<>(); - fields.add("a"); - final IndexEntity createResult = collection.ensureHashIndex(fields, null); - final String id = collection.deleteIndex(createResult.getId().split("/")[1]); - assertThat(id).isEqualTo(createResult.getId()); - Throwable thrown = catchThrowable(() -> collection.db().getIndex(id)); - assertThat(thrown).isInstanceOf(ArangoDBException.class); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void createHashIndex(ArangoCollection collection) { - String f1 = "field-" + rnd(); - String f2 = "field-" + rnd(); - final Collection fields = Arrays.asList(f1, f2); - final IndexEntity indexResult = collection.ensureHashIndex(fields, null); - assertThat(indexResult).isNotNull(); - assertThat(indexResult.getConstraint()).isNull(); - assertThat(indexResult.getFields()).contains(f1); - assertThat(indexResult.getFields()).contains(f2); - assertThat(indexResult.getId()).startsWith(COLLECTION_NAME); - assertThat(indexResult.getIsNewlyCreated()).isTrue(); - assertThat(indexResult.getMinLength()).isNull(); - if (isSingleServer()) { - assertThat(indexResult.getSelectivityEstimate()).isPositive(); - } - assertThat(indexResult.getSparse()).isFalse(); - assertThat(indexResult.getType()).isEqualTo(IndexType.hash); - assertThat(indexResult.getUnique()).isFalse(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void createHashIndexWithOptions(ArangoCollection collection) { - assumeTrue(isAtLeastVersion(3, 5)); - - String name = "hashIndex-" + rnd(); - final HashIndexOptions options = new HashIndexOptions(); - options.name(name); - - String f1 = "field-" + rnd(); - String f2 = "field-" + rnd(); - final Collection fields = Arrays.asList(f1, f2); - - final IndexEntity indexResult = collection.ensureHashIndex(fields, options); - assertThat(indexResult).isNotNull(); - assertThat(indexResult.getConstraint()).isNull(); - assertThat(indexResult.getFields()).contains(f1); - assertThat(indexResult.getFields()).contains(f2); - assertThat(indexResult.getId()).startsWith(COLLECTION_NAME); - assertThat(indexResult.getIsNewlyCreated()).isTrue(); - assertThat(indexResult.getMinLength()).isNull(); - if (isSingleServer()) { - assertThat(indexResult.getSelectivityEstimate()).isPositive(); - } - assertThat(indexResult.getSparse()).isFalse(); - assertThat(indexResult.getType()).isEqualTo(IndexType.hash); - assertThat(indexResult.getUnique()).isFalse(); - assertThat(indexResult.getName()).isEqualTo(name); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void createGeoIndex(ArangoCollection collection) { - String f1 = "field-" + rnd(); - final Collection fields = Collections.singletonList(f1); - final IndexEntity indexResult = collection.ensureGeoIndex(fields, null); - assertThat(indexResult).isNotNull(); - assertThat(indexResult.getFields()).contains(f1); - assertThat(indexResult.getId()).startsWith(COLLECTION_NAME); - assertThat(indexResult.getIsNewlyCreated()).isTrue(); - assertThat(indexResult.getMinLength()).isNull(); - assertThat(indexResult.getSparse()).isTrue(); - assertThat(indexResult.getUnique()).isFalse(); - if (isAtLeastVersion(3, 4)) { - assertThat(indexResult.getType()).isEqualTo(IndexType.geo); - } else { - assertThat(indexResult.getType()).isEqualTo(IndexType.geo1); - } - if (isAtLeastVersion(3, 10)) { - assertThat(indexResult.getLegacyPolygons()).isFalse(); - } - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void createGeoIndexWithOptions(ArangoCollection collection) { - assumeTrue(isAtLeastVersion(3, 5)); - - String name = "geoIndex-" + rnd(); - final GeoIndexOptions options = new GeoIndexOptions(); - options.name(name); - - String f1 = "field-" + rnd(); - final Collection fields = Collections.singletonList(f1); - final IndexEntity indexResult = collection.ensureGeoIndex(fields, options); - assertThat(indexResult).isNotNull(); - assertThat(indexResult.getFields()).contains(f1); - assertThat(indexResult.getId()).startsWith(COLLECTION_NAME); - assertThat(indexResult.getIsNewlyCreated()).isTrue(); - assertThat(indexResult.getMinLength()).isNull(); - assertThat(indexResult.getSparse()).isTrue(); - assertThat(indexResult.getUnique()).isFalse(); - if (isAtLeastVersion(3, 4)) { - assertThat(indexResult.getType()).isEqualTo(IndexType.geo); - } else { - assertThat(indexResult.getType()).isEqualTo(IndexType.geo1); - } - assertThat(indexResult.getName()).isEqualTo(name); - if (isAtLeastVersion(3, 10)) { - assertThat(indexResult.getLegacyPolygons()).isFalse(); - } - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void createGeoIndexLegacyPolygons(ArangoCollection collection) { - assumeTrue(isAtLeastVersion(3, 10)); - - String name = "geoIndex-" + rnd(); - final GeoIndexOptions options = new GeoIndexOptions(); - options.name(name); - options.legacyPolygons(true); - - String f1 = "field-" + rnd(); - final Collection fields = Collections.singletonList(f1); - final IndexEntity indexResult = collection.ensureGeoIndex(fields, options); - assertThat(indexResult).isNotNull(); - assertThat(indexResult.getFields()).contains(f1); - assertThat(indexResult.getId()).startsWith(COLLECTION_NAME); - assertThat(indexResult.getIsNewlyCreated()).isTrue(); - assertThat(indexResult.getMinLength()).isNull(); - assertThat(indexResult.getSparse()).isTrue(); - assertThat(indexResult.getUnique()).isFalse(); - if (isAtLeastVersion(3, 4)) { - assertThat(indexResult.getType()).isEqualTo(IndexType.geo); - } else { - assertThat(indexResult.getType()).isEqualTo(IndexType.geo1); - } - assertThat(indexResult.getName()).isEqualTo(name); - if (isAtLeastVersion(3, 10)) { - assertThat(indexResult.getLegacyPolygons()).isTrue(); - } - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void createGeo2Index(ArangoCollection collection) { - String f1 = "field-" + rnd(); - String f2 = "field-" + rnd(); - final Collection fields = Arrays.asList(f1, f2); - - final IndexEntity indexResult = collection.ensureGeoIndex(fields, null); - assertThat(indexResult).isNotNull(); - assertThat(indexResult.getFields()).contains(f1); - assertThat(indexResult.getFields()).contains(f2); - assertThat(indexResult.getId()).startsWith(COLLECTION_NAME); - assertThat(indexResult.getIsNewlyCreated()).isTrue(); - assertThat(indexResult.getMinLength()).isNull(); - assertThat(indexResult.getSparse()).isTrue(); - assertThat(indexResult.getUnique()).isFalse(); - if (isAtLeastVersion(3, 4)) { - assertThat(indexResult.getType()).isEqualTo(IndexType.geo); - } else { - assertThat(indexResult.getType()).isEqualTo(IndexType.geo2); - } - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void createGeo2IndexWithOptions(ArangoCollection collection) { - assumeTrue(isAtLeastVersion(3, 5)); - - String name = "geoIndex-" + rnd(); - final GeoIndexOptions options = new GeoIndexOptions(); - options.name(name); - - String f1 = "field-" + rnd(); - String f2 = "field-" + rnd(); - final Collection fields = Arrays.asList(f1, f2); - - final IndexEntity indexResult = collection.ensureGeoIndex(fields, options); - assertThat(indexResult).isNotNull(); - assertThat(indexResult.getFields()).contains(f1); - assertThat(indexResult.getFields()).contains(f2); - assertThat(indexResult.getId()).startsWith(COLLECTION_NAME); - assertThat(indexResult.getIsNewlyCreated()).isTrue(); - assertThat(indexResult.getMinLength()).isNull(); - assertThat(indexResult.getSparse()).isTrue(); - assertThat(indexResult.getUnique()).isFalse(); - if (isAtLeastVersion(3, 4)) { - assertThat(indexResult.getType()).isEqualTo(IndexType.geo); - } else { - assertThat(indexResult.getType()).isEqualTo(IndexType.geo2); - } - assertThat(indexResult.getName()).isEqualTo(name); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void createSkiplistIndex(ArangoCollection collection) { - String f1 = "field-" + rnd(); - String f2 = "field-" + rnd(); - final Collection fields = Arrays.asList(f1, f2); - final IndexEntity indexResult = collection.ensureSkiplistIndex(fields, null); - assertThat(indexResult).isNotNull(); - assertThat(indexResult.getConstraint()).isNull(); - assertThat(indexResult.getFields()).contains(f1); - assertThat(indexResult.getFields()).contains(f2); - assertThat(indexResult.getId()).startsWith(COLLECTION_NAME); - assertThat(indexResult.getIsNewlyCreated()).isTrue(); - assertThat(indexResult.getMinLength()).isNull(); - assertThat(indexResult.getSparse()).isFalse(); - assertThat(indexResult.getType()).isEqualTo(IndexType.skiplist); - assertThat(indexResult.getUnique()).isFalse(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void createSkiplistIndexWithOptions(ArangoCollection collection) { - assumeTrue(isAtLeastVersion(3, 5)); - - String name = "skiplistIndex-" + rnd(); - final SkiplistIndexOptions options = new SkiplistIndexOptions(); - options.name(name); - - String f1 = "field-" + rnd(); - String f2 = "field-" + rnd(); - final Collection fields = Arrays.asList(f1, f2); - final IndexEntity indexResult = collection.ensureSkiplistIndex(fields, options); - assertThat(indexResult).isNotNull(); - assertThat(indexResult.getConstraint()).isNull(); - assertThat(indexResult.getFields()).contains(f1); - assertThat(indexResult.getFields()).contains(f2); - assertThat(indexResult.getId()).startsWith(COLLECTION_NAME); - assertThat(indexResult.getIsNewlyCreated()).isTrue(); - assertThat(indexResult.getMinLength()).isNull(); - assertThat(indexResult.getSparse()).isFalse(); - assertThat(indexResult.getType()).isEqualTo(IndexType.skiplist); - assertThat(indexResult.getUnique()).isFalse(); - assertThat(indexResult.getName()).isEqualTo(name); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void createPersistentIndex(ArangoCollection collection) { - String f1 = "field-" + rnd(); - String f2 = "field-" + rnd(); - final Collection fields = Arrays.asList(f1, f2); - - final IndexEntity indexResult = collection.ensurePersistentIndex(fields, null); - assertThat(indexResult).isNotNull(); - assertThat(indexResult.getConstraint()).isNull(); - assertThat(indexResult.getFields()).contains(f1); - assertThat(indexResult.getFields()).contains(f2); - assertThat(indexResult.getId()).startsWith(COLLECTION_NAME); - assertThat(indexResult.getIsNewlyCreated()).isTrue(); - assertThat(indexResult.getMinLength()).isNull(); - assertThat(indexResult.getSparse()).isFalse(); - assertThat(indexResult.getType()).isEqualTo(IndexType.persistent); - assertThat(indexResult.getUnique()).isFalse(); - assertThat(indexResult.getDeduplicate()).isTrue(); - if (isAtLeastVersion(3, 10)) { - assertThat(indexResult.getCacheEnabled()).isFalse(); - } - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void createPersistentIndexCacheEnabled(ArangoCollection collection) { - assumeTrue(isAtLeastVersion(3, 10)); - - String f1 = "field-" + rnd(); - String f2 = "field-" + rnd(); - final Collection fields = Arrays.asList(f1, f2); - - final IndexEntity indexResult = collection.ensurePersistentIndex(fields, new PersistentIndexOptions().cacheEnabled(true)); - assertThat(indexResult).isNotNull(); - assertThat(indexResult.getConstraint()).isNull(); - assertThat(indexResult.getFields()).contains(f1); - assertThat(indexResult.getFields()).contains(f2); - assertThat(indexResult.getId()).startsWith(COLLECTION_NAME); - assertThat(indexResult.getIsNewlyCreated()).isTrue(); - assertThat(indexResult.getMinLength()).isNull(); - assertThat(indexResult.getSparse()).isFalse(); - assertThat(indexResult.getType()).isEqualTo(IndexType.persistent); - assertThat(indexResult.getUnique()).isFalse(); - assertThat(indexResult.getDeduplicate()).isTrue(); - assertThat(indexResult.getCacheEnabled()).isTrue(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void createPersistentIndexStoredValues(ArangoCollection collection) { - assumeTrue(isAtLeastVersion(3, 10)); - - String f1 = "field-" + rnd(); - String f2 = "field-" + rnd(); - final Collection fields = Arrays.asList(f1, f2); - - final IndexEntity indexResult = collection.ensurePersistentIndex(fields, new PersistentIndexOptions().storedValues("v1", "v2")); - assertThat(indexResult).isNotNull(); - assertThat(indexResult.getConstraint()).isNull(); - assertThat(indexResult.getFields()).contains(f1); - assertThat(indexResult.getFields()).contains(f2); - assertThat(indexResult.getId()).startsWith(COLLECTION_NAME); - assertThat(indexResult.getIsNewlyCreated()).isTrue(); - assertThat(indexResult.getMinLength()).isNull(); - assertThat(indexResult.getSparse()).isFalse(); - assertThat(indexResult.getType()).isEqualTo(IndexType.persistent); - assertThat(indexResult.getUnique()).isFalse(); - assertThat(indexResult.getDeduplicate()).isTrue(); - assertThat(indexResult.getCacheEnabled()).isFalse(); - assertThat(indexResult.getStoredValues()) - .hasSize(2) - .contains("v1", "v2"); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void createPersistentIndexWithOptions(ArangoCollection collection) { - assumeTrue(isAtLeastVersion(3, 5)); - - String name = "persistentIndex-" + rnd(); - final PersistentIndexOptions options = new PersistentIndexOptions(); - options.name(name); - - String f1 = "field-" + rnd(); - String f2 = "field-" + rnd(); - - final Collection fields = Arrays.asList(f1, f2); - final IndexEntity indexResult = collection.ensurePersistentIndex(fields, options); - assertThat(indexResult).isNotNull(); - assertThat(indexResult.getConstraint()).isNull(); - assertThat(indexResult.getFields()).contains(f1); - assertThat(indexResult.getFields()).contains(f2); - assertThat(indexResult.getId()).startsWith(COLLECTION_NAME); - assertThat(indexResult.getIsNewlyCreated()).isTrue(); - assertThat(indexResult.getMinLength()).isNull(); - assertThat(indexResult.getSparse()).isFalse(); - assertThat(indexResult.getType()).isEqualTo(IndexType.persistent); - assertThat(indexResult.getUnique()).isFalse(); - assertThat(indexResult.getName()).isEqualTo(name); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void createZKDIndex(ArangoCollection collection) { - assumeTrue(isAtLeastVersion(3, 9)); - collection.truncate(); - String f1 = "field-" + rnd(); - String f2 = "field-" + rnd(); - final Collection fields = Arrays.asList(f1, f2); - - final IndexEntity indexResult = collection.ensureZKDIndex(fields, null); - assertThat(indexResult).isNotNull(); - assertThat(indexResult.getConstraint()).isNull(); - assertThat(indexResult.getFields()).contains(f1); - assertThat(indexResult.getFields()).contains(f2); - assertThat(indexResult.getId()).startsWith(COLLECTION_NAME); - assertThat(indexResult.getIsNewlyCreated()).isTrue(); - assertThat(indexResult.getMinLength()).isNull(); - assertThat(indexResult.getType()).isEqualTo(IndexType.zkd); - assertThat(indexResult.getUnique()).isFalse(); - collection.deleteIndex(indexResult.getId()); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void createZKDIndexWithOptions(ArangoCollection collection) { - assumeTrue(isAtLeastVersion(3, 9)); - collection.truncate(); - - String name = "ZKDIndex-" + rnd(); - final ZKDIndexOptions options = - new ZKDIndexOptions().name(name).fieldValueTypes(ZKDIndexOptions.FieldValueTypes.DOUBLE); - - String f1 = "field-" + rnd(); - String f2 = "field-" + rnd(); - - final Collection fields = Arrays.asList(f1, f2); - final IndexEntity indexResult = collection.ensureZKDIndex(fields, options); - assertThat(indexResult).isNotNull(); - assertThat(indexResult.getConstraint()).isNull(); - assertThat(indexResult.getFields()).contains(f1); - assertThat(indexResult.getFields()).contains(f2); - assertThat(indexResult.getId()).startsWith(COLLECTION_NAME); - assertThat(indexResult.getIsNewlyCreated()).isTrue(); - assertThat(indexResult.getMinLength()).isNull(); - assertThat(indexResult.getType()).isEqualTo(IndexType.zkd); - assertThat(indexResult.getUnique()).isFalse(); - assertThat(indexResult.getName()).isEqualTo(name); - collection.deleteIndex(indexResult.getId()); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void indexEstimates(ArangoCollection collection) { - assumeTrue(isAtLeastVersion(3, 8)); - assumeTrue(isSingleServer()); - - String name = "persistentIndex-" + rnd(); - final PersistentIndexOptions options = new PersistentIndexOptions(); - options.name(name); - options.estimates(true); - - String f1 = "field-" + rnd(); - String f2 = "field-" + rnd(); - - final Collection fields = Arrays.asList(f1, f2); - final IndexEntity indexResult = collection.ensurePersistentIndex(fields, options); - assertThat(indexResult).isNotNull(); - assertThat(indexResult.getEstimates()).isTrue(); - assertThat(indexResult.getSelectivityEstimate()).isNotNull(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void indexEstimatesFalse(ArangoCollection collection) { - assumeTrue(isAtLeastVersion(3, 8)); - assumeTrue(isSingleServer()); - - String name = "persistentIndex-" + rnd(); - final PersistentIndexOptions options = new PersistentIndexOptions(); - options.name(name); - options.estimates(false); - - String f1 = "field-" + rnd(); - String f2 = "field-" + rnd(); - - final Collection fields = Arrays.asList(f1, f2); - final IndexEntity indexResult = collection.ensurePersistentIndex(fields, options); - assertThat(indexResult).isNotNull(); - assertThat(indexResult.getEstimates()).isFalse(); - assertThat(indexResult.getSelectivityEstimate()).isNull(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void indexDeduplicate(ArangoCollection collection) { - assumeTrue(isAtLeastVersion(3, 8)); - - String name = "persistentIndex-" + rnd(); - final PersistentIndexOptions options = new PersistentIndexOptions(); - options.name(name); - options.deduplicate(true); - - String f1 = "field-" + rnd(); - String f2 = "field-" + rnd(); - - final Collection fields = Arrays.asList(f1, f2); - final IndexEntity indexResult = collection.ensurePersistentIndex(fields, options); - assertThat(indexResult).isNotNull(); - assertThat(indexResult.getDeduplicate()).isTrue(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void indexDeduplicateFalse(ArangoCollection collection) { - assumeTrue(isAtLeastVersion(3, 8)); - - String name = "persistentIndex-" + rnd(); - final PersistentIndexOptions options = new PersistentIndexOptions(); - options.name(name); - options.deduplicate(false); - - String f1 = "field-" + rnd(); - String f2 = "field-" + rnd(); - - final Collection fields = Arrays.asList(f1, f2); - final IndexEntity indexResult = collection.ensurePersistentIndex(fields, options); - assertThat(indexResult).isNotNull(); - assertThat(indexResult.getDeduplicate()).isFalse(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void createFulltextIndex(ArangoCollection collection) { - String f1 = "field-" + rnd(); - final Collection fields = Collections.singletonList(f1); - final IndexEntity indexResult = collection.ensureFulltextIndex(fields, null); - assertThat(indexResult).isNotNull(); - assertThat(indexResult.getConstraint()).isNull(); - assertThat(indexResult.getFields()).contains(f1); - assertThat(indexResult.getId()).startsWith(COLLECTION_NAME); - assertThat(indexResult.getIsNewlyCreated()).isTrue(); - assertThat(indexResult.getSparse()).isTrue(); - assertThat(indexResult.getType()).isEqualTo(IndexType.fulltext); - assertThat(indexResult.getUnique()).isFalse(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void createFulltextIndexWithOptions(ArangoCollection collection) { - assumeTrue(isAtLeastVersion(3, 5)); - - String name = "fulltextIndex-" + rnd(); - final FulltextIndexOptions options = new FulltextIndexOptions(); - options.name(name); - - String f = "field-" + rnd(); - final Collection fields = Collections.singletonList(f); - final IndexEntity indexResult = collection.ensureFulltextIndex(fields, options); - assertThat(indexResult).isNotNull(); - assertThat(indexResult.getConstraint()).isNull(); - assertThat(indexResult.getFields()).contains(f); - assertThat(indexResult.getId()).startsWith(COLLECTION_NAME); - assertThat(indexResult.getIsNewlyCreated()).isTrue(); - assertThat(indexResult.getSparse()).isTrue(); - assertThat(indexResult.getType()).isEqualTo(IndexType.fulltext); - assertThat(indexResult.getUnique()).isFalse(); - assertThat(indexResult.getName()).isEqualTo(name); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void createTtlIndexWithoutOptions(ArangoCollection collection) { - assumeTrue(isAtLeastVersion(3, 5)); - final Collection fields = new ArrayList<>(); - fields.add("a"); - - Throwable thrown = catchThrowable(() -> collection.ensureTtlIndex(fields, null)); - assertThat(thrown).isInstanceOf(ArangoDBException.class); - ArangoDBException e = (ArangoDBException) thrown; - assertThat(e.getResponseCode()).isEqualTo(400); - assertThat(e.getErrorNum()).isEqualTo(10); - assertThat(e.getMessage()).contains("expireAfter attribute must be a number"); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void createTtlIndexWithOptions(ArangoCollection collection) { - assumeTrue(isAtLeastVersion(3, 5)); - - String f1 = "field-" + rnd(); - final Collection fields = Collections.singletonList(f1); - - String name = "ttlIndex-" + rnd(); - final TtlIndexOptions options = new TtlIndexOptions(); - options.name(name); - options.expireAfter(3600); - - final IndexEntity indexResult = collection.ensureTtlIndex(fields, options); - assertThat(indexResult).isNotNull(); - assertThat(indexResult.getFields()).contains(f1); - assertThat(indexResult.getId()).startsWith(COLLECTION_NAME); - assertThat(indexResult.getIsNewlyCreated()).isTrue(); - assertThat(indexResult.getType()).isEqualTo(IndexType.ttl); - assertThat(indexResult.getExpireAfter()).isEqualTo(3600); - assertThat(indexResult.getName()).isEqualTo(name); - - // revert changes - collection.deleteIndex(indexResult.getId()); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void getIndexes(ArangoCollection collection) { - String f1 = "field-" + rnd(); - final Collection fields = Collections.singletonList(f1); - collection.ensureHashIndex(fields, null); - long matchingIndexes = - collection.getIndexes().stream().filter(i -> i.getType() == IndexType.hash).filter(i -> i.getFields().contains(f1)).count(); - assertThat(matchingIndexes).isEqualTo(1L); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("edges") - void getEdgeIndex(ArangoCollection edgeCollection) { - Collection indexes = edgeCollection.getIndexes(); - long primaryIndexes = indexes.stream().filter(i -> i.getType() == IndexType.primary).count(); - long edgeIndexes = indexes.stream().filter(i -> i.getType() == IndexType.primary).count(); - assertThat(primaryIndexes).isEqualTo(1L); - assertThat(edgeIndexes).isEqualTo(1L); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void exists(ArangoCollection collection) { - assertThat(collection.exists()).isTrue(); - assertThat(collection.db().collection(COLLECTION_NAME + "no").exists()).isFalse(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void truncate(ArangoCollection collection) { - final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); - collection.insertDocument(doc, null); - final BaseDocument readResult = collection.getDocument(doc.getKey(), BaseDocument.class, null); - assertThat(readResult.getKey()).isEqualTo(doc.getKey()); - final CollectionEntity truncateResult = collection.truncate(); - assertThat(truncateResult).isNotNull(); - assertThat(truncateResult.getId()).isNotNull(); - final BaseDocument document = collection.getDocument(doc.getKey(), BaseDocument.class, null); - assertThat(document).isNull(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void getCount(ArangoCollection collection) { - Long initialCount = collection.count().getCount(); - collection.insertDocument(RawJson.of("{}")); - final CollectionPropertiesEntity count = collection.count(); - assertThat(count.getCount()).isEqualTo(initialCount + 1L); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void documentExists(ArangoCollection collection) { - final Boolean existsNot = collection.documentExists(rnd(), null); - assertThat(existsNot).isFalse(); - - String key = rnd(); - RawJson rawJson = RawJson.of("{\"_key\":\"" + key + "\"}"); - collection.insertDocument(rawJson); - final Boolean exists = collection.documentExists(key, null); - assertThat(exists).isTrue(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void documentExistsIfMatch(ArangoCollection collection) { - String key = rnd(); - RawJson rawJson = RawJson.of("{\"_key\":\"" + key + "\"}"); - final DocumentCreateEntity createResult = collection.insertDocument(rawJson); - final DocumentExistsOptions options = new DocumentExistsOptions().ifMatch(createResult.getRev()); - final Boolean exists = collection.documentExists(key, options); - assertThat(exists).isTrue(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void documentExistsIfMatchFail(ArangoCollection collection) { - String key = rnd(); - RawJson rawJson = RawJson.of("{\"_key\":\"" + key + "\"}"); - collection.insertDocument(rawJson); - final DocumentExistsOptions options = new DocumentExistsOptions().ifMatch("no"); - final Boolean exists = collection.documentExists(key, options); - assertThat(exists).isFalse(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void documentExistsIfNoneMatch(ArangoCollection collection) { - String key = rnd(); - RawJson rawJson = RawJson.of("{\"_key\":\"" + key + "\"}"); - collection.insertDocument(rawJson); - final DocumentExistsOptions options = new DocumentExistsOptions().ifNoneMatch("no"); - final Boolean exists = collection.documentExists(key, options); - assertThat(exists).isTrue(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void documentExistsIfNoneMatchFail(ArangoCollection collection) { - String key = rnd(); - RawJson rawJson = RawJson.of("{\"_key\":\"" + key + "\"}"); - final DocumentCreateEntity createResult = collection.insertDocument(rawJson); - final DocumentExistsOptions options = new DocumentExistsOptions().ifNoneMatch(createResult.getRev()); - final Boolean exists = collection.documentExists(key, options); - assertThat(exists).isFalse(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void insertDocuments(ArangoCollection collection) { - final Collection values = Arrays.asList(new BaseDocument(), new BaseDocument(), - new BaseDocument()); - - final MultiDocumentEntity docs = collection.insertDocuments(values); - assertThat(docs).isNotNull(); - assertThat(docs.getDocuments()).isNotNull(); - assertThat(docs.getDocuments()).hasSize(3); - assertThat(docs.getErrors()).isNotNull(); - assertThat(docs.getErrors()).isEmpty(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void insertDocumentsOverwriteModeUpdate(ArangoCollection collection) { - assumeTrue(isAtLeastVersion(3, 7)); - - final BaseDocument doc1 = new BaseDocument(UUID.randomUUID().toString()); - doc1.addAttribute("foo", "a"); - final DocumentCreateEntity meta1 = collection.insertDocument(doc1); - - final BaseDocument doc2 = new BaseDocument(UUID.randomUUID().toString()); - doc2.addAttribute("foo", "a"); - final DocumentCreateEntity meta2 = collection.insertDocument(doc2); - - doc1.addAttribute("bar", "b"); - doc2.addAttribute("bar", "b"); - - final MultiDocumentEntity> repsert = - collection.insertDocuments(Arrays.asList(doc1, doc2), - new DocumentCreateOptions().overwriteMode(OverwriteMode.update).returnNew(true)); - assertThat(repsert).isNotNull(); - assertThat(repsert.getDocuments()).hasSize(2); - assertThat(repsert.getErrors()).isEmpty(); - for (final DocumentCreateEntity documentCreateEntity : repsert.getDocuments()) { - assertThat(documentCreateEntity.getRev()).isNotEqualTo(meta1.getRev()); - assertThat(documentCreateEntity.getRev()).isNotEqualTo(meta2.getRev()); - assertThat(documentCreateEntity.getNew().getAttribute("foo")).isEqualTo("a"); - assertThat(documentCreateEntity.getNew().getAttribute("bar")).isEqualTo("b"); - } - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void insertDocumentsJson(ArangoCollection collection) { - final Collection values = new ArrayList<>(); - values.add(RawJson.of("{}")); - values.add(RawJson.of("{}")); - values.add(RawJson.of("{}")); - final MultiDocumentEntity docs = collection.insertDocuments(values); - assertThat(docs).isNotNull(); - assertThat(docs.getDocuments()).isNotNull(); - assertThat(docs.getDocuments()).hasSize(3); - assertThat(docs.getErrors()).isNotNull(); - assertThat(docs.getErrors()).isEmpty(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void insertDocumentsRawData(ArangoCollection collection) { - final RawData values = RawData.of("[{},{},{}]"); - final MultiDocumentEntity docs = collection.insertDocuments(values); - assertThat(docs).isNotNull(); - assertThat(docs.getDocuments()).isNotNull(); - assertThat(docs.getDocuments()).hasSize(3); - assertThat(docs.getErrors()).isNotNull(); - assertThat(docs.getErrors()).isEmpty(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void insertDocumentsRawDataReturnNew(ArangoCollection collection) { - final RawData values = RawData.of("[{\"aaa\":33},{\"aaa\":33},{\"aaa\":33}]"); - final MultiDocumentEntity> docs = - collection.insertDocuments(values, new DocumentCreateOptions().returnNew(true)); - assertThat(docs).isNotNull(); - assertThat(docs.getDocuments()).isNotNull(); - assertThat(docs.getDocuments()).hasSize(3); - assertThat(docs.getErrors()).isNotNull(); - assertThat(docs.getErrors()).isEmpty(); - - for (final DocumentCreateEntity doc : docs.getDocuments()) { - RawData d = doc.getNew(); - assertThat(d) - .isNotNull() - .isInstanceOf(RawJson.class); - - JsonNode jn = SerdeUtils.INSTANCE.parseJson(((RawJson) d).getValue()); - assertThat(jn.has("aaa")).isTrue(); - assertThat(jn.get("aaa").intValue()).isEqualTo(33); - } - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void insertDocumentsOne(ArangoCollection collection) { - final Collection values = new ArrayList<>(); - values.add(new BaseDocument()); - final MultiDocumentEntity docs = collection.insertDocuments(values); - assertThat(docs).isNotNull(); - assertThat(docs.getDocuments()).isNotNull(); - assertThat(docs.getDocuments()).hasSize(1); - assertThat(docs.getErrors()).isNotNull(); - assertThat(docs.getErrors()).isEmpty(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void insertDocumentsEmpty(ArangoCollection collection) { - final Collection values = new ArrayList<>(); - final MultiDocumentEntity docs = collection.insertDocuments(values); - assertThat(docs).isNotNull(); - assertThat(docs.getDocuments()).isNotNull(); - assertThat(docs.getDocuments()).isEmpty(); - assertThat(docs.getErrors()).isNotNull(); - assertThat(docs.getErrors()).isEmpty(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void insertDocumentsReturnNew(ArangoCollection collection) { - final Collection values = new ArrayList<>(); - values.add(new BaseDocument()); - values.add(new BaseDocument()); - values.add(new BaseDocument()); - final DocumentCreateOptions options = new DocumentCreateOptions().returnNew(true); - final MultiDocumentEntity> docs = collection.insertDocuments(values, - options); - assertThat(docs).isNotNull(); - assertThat(docs.getDocuments()).isNotNull(); - assertThat(docs.getDocuments()).hasSize(3); - assertThat(docs.getErrors()).isNotNull(); - assertThat(docs.getErrors()).isEmpty(); - for (final DocumentCreateEntity doc : docs.getDocuments()) { - assertThat(doc.getNew()).isNotNull(); - final BaseDocument baseDocument = doc.getNew(); - assertThat(baseDocument.getKey()).isNotNull(); - } - - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void insertDocumentsFail(ArangoCollection collection) { - String k1 = rnd(); - String k2 = rnd(); - final Collection values = Arrays.asList(new BaseDocument(k1), new BaseDocument(k2), - new BaseDocument(k2)); - - final MultiDocumentEntity docs = collection.insertDocuments(values); - assertThat(docs).isNotNull(); - assertThat(docs.getDocuments()).isNotNull(); - assertThat(docs.getDocuments()).hasSize(2); - assertThat(docs.getErrors()).isNotNull(); - assertThat(docs.getErrors()).hasSize(1); - assertThat(docs.getErrors().iterator().next().getErrorNum()).isEqualTo(1210); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void importDocuments(ArangoCollection collection) { - final Collection values = Arrays.asList(new BaseDocument(), new BaseDocument(), - new BaseDocument()); - - final DocumentImportEntity docs = collection.importDocuments(values); - assertThat(docs).isNotNull(); - assertThat(docs.getCreated()).isEqualTo(values.size()); - assertThat(docs.getEmpty()).isZero(); - assertThat(docs.getErrors()).isZero(); - assertThat(docs.getIgnored()).isZero(); - assertThat(docs.getUpdated()).isZero(); - assertThat(docs.getDetails()).isEmpty(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void importDocumentsJsonList(ArangoCollection collection) { - final Collection values = Arrays.asList( - RawJson.of("{}"), - RawJson.of("{}"), - RawJson.of("{}") - ); - - final DocumentImportEntity docs = collection.importDocuments(values); - assertThat(docs).isNotNull(); - assertThat(docs.getCreated()).isEqualTo(values.size()); - assertThat(docs.getEmpty()).isZero(); - assertThat(docs.getErrors()).isZero(); - assertThat(docs.getIgnored()).isZero(); - assertThat(docs.getUpdated()).isZero(); - assertThat(docs.getDetails()).isEmpty(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void importDocumentsDuplicateDefaultError(ArangoCollection collection) { - String k1 = rnd(); - String k2 = rnd(); - - final Collection values = Arrays.asList(new BaseDocument(k1), new BaseDocument(k2), -new BaseDocument(k2)); - - final DocumentImportEntity docs = collection.importDocuments(values); - assertThat(docs).isNotNull(); - assertThat(docs.getCreated()).isEqualTo(2); - assertThat(docs.getEmpty()).isZero(); - assertThat(docs.getErrors()).isEqualTo(1); - assertThat(docs.getIgnored()).isZero(); - assertThat(docs.getUpdated()).isZero(); - assertThat(docs.getDetails()).isEmpty(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void importDocumentsDuplicateError(ArangoCollection collection) { - String k1 = rnd(); - String k2 = rnd(); - - final Collection values = Arrays.asList(new BaseDocument(k1), new BaseDocument(k2), - new BaseDocument(k2)); - - final DocumentImportEntity docs = collection.importDocuments(values, - new DocumentImportOptions().onDuplicate(OnDuplicate.error)); - assertThat(docs).isNotNull(); - assertThat(docs.getCreated()).isEqualTo(2); - assertThat(docs.getEmpty()).isZero(); - assertThat(docs.getErrors()).isEqualTo(1); - assertThat(docs.getIgnored()).isZero(); - assertThat(docs.getUpdated()).isZero(); - assertThat(docs.getDetails()).isEmpty(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void importDocumentsDuplicateIgnore(ArangoCollection collection) { - String k1 = rnd(); - String k2 = rnd(); - - final Collection values = Arrays.asList(new BaseDocument(k1), new BaseDocument(k2), - new BaseDocument(k2)); - - final DocumentImportEntity docs = collection.importDocuments(values, - new DocumentImportOptions().onDuplicate(OnDuplicate.ignore)); - assertThat(docs).isNotNull(); - assertThat(docs.getCreated()).isEqualTo(2); - assertThat(docs.getEmpty()).isZero(); - assertThat(docs.getErrors()).isZero(); - assertThat(docs.getIgnored()).isEqualTo(1); - assertThat(docs.getUpdated()).isZero(); - assertThat(docs.getDetails()).isEmpty(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void importDocumentsDuplicateReplace(ArangoCollection collection) { - String k1 = rnd(); - String k2 = rnd(); - - final Collection values = Arrays.asList(new BaseDocument(k1), new BaseDocument(k2), - new BaseDocument(k2)); - - final DocumentImportEntity docs = collection.importDocuments(values, -new DocumentImportOptions().onDuplicate(OnDuplicate.replace)); - assertThat(docs).isNotNull(); - assertThat(docs.getCreated()).isEqualTo(2); - assertThat(docs.getEmpty()).isZero(); - assertThat(docs.getErrors()).isZero(); - assertThat(docs.getIgnored()).isZero(); - assertThat(docs.getUpdated()).isEqualTo(1); - assertThat(docs.getDetails()).isEmpty(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void importDocumentsDuplicateUpdate(ArangoCollection collection) { - String k1 = rnd(); - String k2 = rnd(); - - final Collection values = Arrays.asList(new BaseDocument(k1), new BaseDocument(k2), - new BaseDocument(k2)); - - final DocumentImportEntity docs = collection.importDocuments(values, - new DocumentImportOptions().onDuplicate(OnDuplicate.update)); - assertThat(docs).isNotNull(); - assertThat(docs.getCreated()).isEqualTo(2); - assertThat(docs.getEmpty()).isZero(); - assertThat(docs.getErrors()).isZero(); - assertThat(docs.getIgnored()).isZero(); - assertThat(docs.getUpdated()).isEqualTo(1); - assertThat(docs.getDetails()).isEmpty(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void importDocumentsCompleteFail(ArangoCollection collection) { - String k1 = rnd(); - String k2 = rnd(); - - final Collection values = Arrays.asList(new BaseDocument(k1), new BaseDocument(k2), - new BaseDocument(k2)); - - Throwable thrown = catchThrowable(() -> collection.importDocuments(values, - new DocumentImportOptions().complete(true))); - assertThat(thrown).isInstanceOf(ArangoDBException.class); - ArangoDBException e = (ArangoDBException) thrown; - assertThat(e.getErrorNum()).isEqualTo(1210); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void importDocumentsDetails(ArangoCollection collection) { - String k1 = rnd(); - String k2 = rnd(); - - final Collection values = Arrays.asList(new BaseDocument(k1), new BaseDocument(k2), - new BaseDocument(k2)); - - final DocumentImportEntity docs = collection.importDocuments(values, new DocumentImportOptions().details(true)); - assertThat(docs).isNotNull(); - assertThat(docs.getCreated()).isEqualTo(2); - assertThat(docs.getEmpty()).isZero(); - assertThat(docs.getErrors()).isEqualTo(1); - assertThat(docs.getIgnored()).isZero(); - assertThat(docs.getUpdated()).isZero(); - assertThat(docs.getDetails()).hasSize(1); - assertThat(docs.getDetails().iterator().next()).contains("unique constraint violated"); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void importDocumentsOverwriteFalse(ArangoCollection collection) { - collection.insertDocument(new BaseDocument()); - Long initialCount = collection.count().getCount(); - - final Collection values = new ArrayList<>(); - values.add(new BaseDocument()); - values.add(new BaseDocument()); - collection.importDocuments(values, new DocumentImportOptions().overwrite(false)); - assertThat(collection.count().getCount()).isEqualTo(initialCount + 2L); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void importDocumentsOverwriteTrue(ArangoCollection collection) { - collection.insertDocument(new BaseDocument()); - - final Collection values = new ArrayList<>(); - values.add(new BaseDocument()); - values.add(new BaseDocument()); - collection.importDocuments(values, new DocumentImportOptions().overwrite(true)); - assertThat(collection.count().getCount()).isEqualTo(2L); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("edges") - void importDocumentsFromToPrefix(ArangoCollection edgeCollection) { - final Collection values = new ArrayList<>(); - final String[] keys = {rnd(), rnd()}; - for (String s : keys) { - values.add(new BaseEdgeDocument(s, "from", "to")); - } - assertThat(values).hasSize(keys.length); - - final DocumentImportEntity importResult = edgeCollection.importDocuments(values, - new DocumentImportOptions().fromPrefix("foo").toPrefix("bar")); - assertThat(importResult).isNotNull(); - assertThat(importResult.getCreated()).isEqualTo(values.size()); - for (String key : keys) { - final BaseEdgeDocument doc = edgeCollection.getDocument(key, BaseEdgeDocument.class); - assertThat(doc).isNotNull(); - assertThat(doc.getFrom()).isEqualTo("foo/from"); - assertThat(doc.getTo()).isEqualTo("bar/to"); - } - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void importDocumentsJson(ArangoCollection collection) throws JsonProcessingException { - final String values = mapper.writeValueAsString(Arrays.asList(Collections.singletonMap("_key", rnd()), - Collections.singletonMap("_key", rnd()))); - - final DocumentImportEntity docs = collection.importDocuments(RawData.of(values)); - assertThat(docs).isNotNull(); - assertThat(docs.getCreated()).isEqualTo(2); - assertThat(docs.getEmpty()).isZero(); - assertThat(docs.getErrors()).isZero(); - assertThat(docs.getIgnored()).isZero(); - assertThat(docs.getUpdated()).isZero(); - assertThat(docs.getDetails()).isEmpty(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void importDocumentsJsonDuplicateDefaultError(ArangoCollection collection) throws JsonProcessingException { - String k1 = rnd(); - String k2 = rnd(); - - final String values = mapper.writeValueAsString(Arrays.asList(Collections.singletonMap("_key", k1), - Collections.singletonMap("_key", k2), Collections.singletonMap("_key", k2))); - - final DocumentImportEntity docs = collection.importDocuments(RawData.of(values)); - assertThat(docs).isNotNull(); - assertThat(docs.getCreated()).isEqualTo(2); - assertThat(docs.getEmpty()).isZero(); - assertThat(docs.getErrors()).isEqualTo(1); - assertThat(docs.getIgnored()).isZero(); - assertThat(docs.getUpdated()).isZero(); - assertThat(docs.getDetails()).isEmpty(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void importDocumentsJsonDuplicateError(ArangoCollection collection) throws JsonProcessingException { - String k1 = rnd(); - String k2 = rnd(); - - final String values = mapper.writeValueAsString(Arrays.asList(Collections.singletonMap("_key", k1), - Collections.singletonMap("_key", k2), Collections.singletonMap("_key", k2))); - - final DocumentImportEntity docs = collection.importDocuments(RawData.of(values), - new DocumentImportOptions().onDuplicate(OnDuplicate.error)); - assertThat(docs).isNotNull(); - assertThat(docs.getCreated()).isEqualTo(2); - assertThat(docs.getEmpty()).isZero(); - assertThat(docs.getErrors()).isEqualTo(1); - assertThat(docs.getIgnored()).isZero(); - assertThat(docs.getUpdated()).isZero(); - assertThat(docs.getDetails()).isEmpty(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void importDocumentsJsonDuplicateIgnore(ArangoCollection collection) throws JsonProcessingException { - String k1 = rnd(); - String k2 = rnd(); - - final String values = mapper.writeValueAsString(Arrays.asList(Collections.singletonMap("_key", k1), - Collections.singletonMap("_key", k2), Collections.singletonMap("_key", k2))); - final DocumentImportEntity docs = collection.importDocuments(RawData.of(values), - new DocumentImportOptions().onDuplicate(OnDuplicate.ignore)); - assertThat(docs).isNotNull(); - assertThat(docs.getCreated()).isEqualTo(2); - assertThat(docs.getEmpty()).isZero(); - assertThat(docs.getErrors()).isZero(); - assertThat(docs.getIgnored()).isEqualTo(1); - assertThat(docs.getUpdated()).isZero(); - assertThat(docs.getDetails()).isEmpty(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void importDocumentsJsonDuplicateReplace(ArangoCollection collection) throws JsonProcessingException { - String k1 = rnd(); - String k2 = rnd(); - - final String values = mapper.writeValueAsString(Arrays.asList(Collections.singletonMap("_key", k1), - Collections.singletonMap("_key", k2), Collections.singletonMap("_key", k2))); - - final DocumentImportEntity docs = collection.importDocuments(RawData.of(values), - new DocumentImportOptions().onDuplicate(OnDuplicate.replace)); - assertThat(docs).isNotNull(); - assertThat(docs.getCreated()).isEqualTo(2); - assertThat(docs.getEmpty()).isZero(); - assertThat(docs.getErrors()).isZero(); - assertThat(docs.getIgnored()).isZero(); - assertThat(docs.getUpdated()).isEqualTo(1); - assertThat(docs.getDetails()).isEmpty(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void importDocumentsJsonDuplicateUpdate(ArangoCollection collection) throws JsonProcessingException { - String k1 = rnd(); - String k2 = rnd(); - - final String values = mapper.writeValueAsString(Arrays.asList(Collections.singletonMap("_key", k1), -Collections.singletonMap("_key", k2), Collections.singletonMap("_key", k2))); - - final DocumentImportEntity docs = collection.importDocuments(RawData.of(values), - new DocumentImportOptions().onDuplicate(OnDuplicate.update)); - assertThat(docs).isNotNull(); - assertThat(docs.getCreated()).isEqualTo(2); - assertThat(docs.getEmpty()).isZero(); - assertThat(docs.getErrors()).isZero(); - assertThat(docs.getIgnored()).isZero(); - assertThat(docs.getUpdated()).isEqualTo(1); - assertThat(docs.getDetails()).isEmpty(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void importDocumentsJsonCompleteFail(ArangoCollection collection) { - final String values = "[{\"_key\":\"1\"},{\"_key\":\"2\"},{\"_key\":\"2\"}]"; - Throwable thrown = catchThrowable(() -> collection.importDocuments(RawData.of(values), - new DocumentImportOptions().complete(true))); - assertThat(thrown).isInstanceOf(ArangoDBException.class); - ArangoDBException e = (ArangoDBException) thrown; - assertThat(e.getErrorNum()).isEqualTo(1210); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void importDocumentsJsonDetails(ArangoCollection collection) throws JsonProcessingException { - String k1 = rnd(); - String k2 = rnd(); - - final String values = mapper.writeValueAsString(Arrays.asList(Collections.singletonMap("_key", k1), - Collections.singletonMap("_key", k2), Collections.singletonMap("_key", k2))); - - final DocumentImportEntity docs = collection.importDocuments(RawData.of(values), -new DocumentImportOptions().details(true)); - assertThat(docs).isNotNull(); - assertThat(docs.getCreated()).isEqualTo(2); - assertThat(docs.getEmpty()).isZero(); - assertThat(docs.getErrors()).isEqualTo(1); - assertThat(docs.getIgnored()).isZero(); - assertThat(docs.getUpdated()).isZero(); - assertThat(docs.getDetails()).hasSize(1); - assertThat(docs.getDetails().iterator().next()).contains("unique constraint violated"); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void importDocumentsJsonOverwriteFalse(ArangoCollection collection) throws JsonProcessingException { - collection.insertDocument(new BaseDocument()); - Long initialCount = collection.count().getCount(); - - final String values = mapper.writeValueAsString(Arrays.asList(Collections.singletonMap("_key", rnd()), - Collections.singletonMap("_key", rnd()))); - collection.importDocuments(RawData.of(values), new DocumentImportOptions().overwrite(false)); - assertThat(collection.count().getCount()).isEqualTo(initialCount + 2L); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void importDocumentsJsonOverwriteTrue(ArangoCollection collection) throws JsonProcessingException { - collection.insertDocument(new BaseDocument()); - - final String values = mapper.writeValueAsString(Arrays.asList(Collections.singletonMap("_key", rnd()), - Collections.singletonMap("_key", rnd()))); - collection.importDocuments(RawData.of(values), new DocumentImportOptions().overwrite(true)); - assertThat(collection.count().getCount()).isEqualTo(2L); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("edges") - void importDocumentsJsonFromToPrefix(ArangoCollection edgeCollection) throws JsonProcessingException { - String k1 = UUID.randomUUID().toString(); - String k2 = UUID.randomUUID().toString(); - - final String[] keys = {k1, k2}; - - final String values = mapper.writeValueAsString(Arrays.asList(new MapBuilder().put("_key", k1).put("_from", - "from").put("_to", "to").get(), new MapBuilder().put("_key", k2).put("_from", "from").put("_to", "to").get())); - - final DocumentImportEntity importResult = edgeCollection.importDocuments(RawData.of(values), -new DocumentImportOptions().fromPrefix("foo").toPrefix("bar")); - assertThat(importResult).isNotNull(); - assertThat(importResult.getCreated()).isEqualTo(2); - for (String key : keys) { - final BaseEdgeDocument doc = edgeCollection.getDocument(key, BaseEdgeDocument.class); - assertThat(doc).isNotNull(); - assertThat(doc.getFrom()).isEqualTo("foo/from"); - assertThat(doc.getTo()).isEqualTo("bar/to"); - } - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void deleteDocumentsByKey(ArangoCollection collection) { - final Collection values = new ArrayList<>(); - { - final BaseDocument e = new BaseDocument(UUID.randomUUID().toString()); - e.setKey("1"); - values.add(e); - } - { - final BaseDocument e = new BaseDocument(UUID.randomUUID().toString()); - e.setKey("2"); - values.add(e); - } - collection.insertDocuments(values); - final Collection keys = new ArrayList<>(); - keys.add("1"); - keys.add("2"); - final MultiDocumentEntity> deleteResult = collection.deleteDocuments(keys); - assertThat(deleteResult).isNotNull(); - assertThat(deleteResult.getDocuments()).hasSize(2); - for (final DocumentDeleteEntity i : deleteResult.getDocuments()) { - assertThat(i.getKey()).isIn("1", "2"); - } - assertThat(deleteResult.getErrors()).isEmpty(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void deleteDocumentsRawDataByKeyReturnOld(ArangoCollection collection) { - final RawData values = RawData.of("[{\"_key\":\"1\"},{\"_key\":\"2\"}]"); - collection.insertDocuments(values); - final RawData keys = RawData.of("[\"1\",\"2\"]"); - MultiDocumentEntity> deleteResult = collection.deleteDocuments(keys, - new DocumentDeleteOptions().returnOld(true)); - assertThat(deleteResult).isNotNull(); - assertThat(deleteResult.getDocuments()).hasSize(2); - for (final DocumentDeleteEntity i : deleteResult.getDocuments()) { - assertThat(i.getKey()).isIn("1", "2"); - assertThat(i.getOld()).isNotNull().isInstanceOf(RawJson.class); - JsonNode jn = SerdeUtils.INSTANCE.parseJson(((RawJson) i.getOld()).getValue()); - assertThat(jn.get("_key").asText()).isEqualTo(i.getKey()); - } - assertThat(deleteResult.getErrors()).isEmpty(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void deleteDocumentsByDocuments(ArangoCollection collection) { - final Collection values = new ArrayList<>(); - { - final BaseDocument e = new BaseDocument(UUID.randomUUID().toString()); - e.setKey("1"); - values.add(e); - } - { - final BaseDocument e = new BaseDocument(UUID.randomUUID().toString()); - e.setKey("2"); - values.add(e); - } - collection.insertDocuments(values); - MultiDocumentEntity> deleteResult = collection.deleteDocuments(values); - assertThat(deleteResult).isNotNull(); - assertThat(deleteResult.getDocuments()).hasSize(2); - for (final DocumentDeleteEntity i : deleteResult.getDocuments()) { - assertThat(i.getKey()).isIn("1", "2"); - } - assertThat(deleteResult.getErrors()).isEmpty(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void deleteDocumentsByKeyOne(ArangoCollection collection) { - final Collection values = new ArrayList<>(); - { - final BaseDocument e = new BaseDocument(UUID.randomUUID().toString()); - e.setKey("1"); - values.add(e); - } - collection.insertDocuments(values); - final Collection keys = new ArrayList<>(); - keys.add("1"); - final MultiDocumentEntity> deleteResult = collection.deleteDocuments(keys); - assertThat(deleteResult).isNotNull(); - assertThat(deleteResult.getDocuments()).hasSize(1); - for (final DocumentDeleteEntity i : deleteResult.getDocuments()) { - assertThat(i.getKey()).isEqualTo("1"); - } - assertThat(deleteResult.getErrors()).isEmpty(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void deleteDocumentsByDocumentOne(ArangoCollection collection) { - final Collection values = new ArrayList<>(); - { - final BaseDocument e = new BaseDocument(UUID.randomUUID().toString()); - e.setKey("1"); - values.add(e); - } - collection.insertDocuments(values); - final MultiDocumentEntity> deleteResult = collection.deleteDocuments(values); - assertThat(deleteResult).isNotNull(); - assertThat(deleteResult.getDocuments()).hasSize(1); - for (final DocumentDeleteEntity i : deleteResult.getDocuments()) { - assertThat(i.getKey()).isEqualTo("1"); - } - assertThat(deleteResult.getErrors()).isEmpty(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void deleteDocumentsEmpty(ArangoCollection collection) { - final Collection values = new ArrayList<>(); - collection.insertDocuments(values); - final Collection keys = new ArrayList<>(); - final MultiDocumentEntity deleteResult = collection.deleteDocuments(keys); - assertThat(deleteResult).isNotNull(); - assertThat(deleteResult.getDocuments()).isEmpty(); - assertThat(deleteResult.getErrors()).isEmpty(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void deleteDocumentsByKeyNotExisting(ArangoCollection collection) { - final Collection values = new ArrayList<>(); - collection.insertDocuments(values); - final Collection keys = Arrays.asList(rnd(), rnd()); - - final MultiDocumentEntity deleteResult = collection.deleteDocuments(keys); - assertThat(deleteResult).isNotNull(); - assertThat(deleteResult.getDocuments()).isEmpty(); - assertThat(deleteResult.getErrors()).hasSize(2); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void deleteDocumentsByDocumentsNotExisting(ArangoCollection collection) { - final Collection values = new ArrayList<>(); - { - final BaseDocument e = new BaseDocument(UUID.randomUUID().toString()); - e.setKey("1"); - values.add(e); - } - { - final BaseDocument e = new BaseDocument(UUID.randomUUID().toString()); - e.setKey("2"); - values.add(e); - } - final MultiDocumentEntity deleteResult = collection.deleteDocuments(values); - assertThat(deleteResult).isNotNull(); - assertThat(deleteResult.getDocuments()).isEmpty(); - assertThat(deleteResult.getErrors()).hasSize(2); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void updateDocuments(ArangoCollection collection) { - final Collection values = Arrays.asList(new BaseDocument(rnd()), new BaseDocument(rnd())); - collection.insertDocuments(values); - values.forEach(it -> it.addAttribute("a", "test")); - - final MultiDocumentEntity updateResult = collection.updateDocuments(values); - assertThat(updateResult.getDocuments()).hasSize(2); - assertThat(updateResult.getErrors()).isEmpty(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void updateDocumentsWithDifferentReturnType(ArangoCollection collection) { - List keys = - IntStream.range(0, 3).mapToObj(it -> "key-" + UUID.randomUUID()).collect(Collectors.toList()); - List docs = - keys.stream().map(BaseDocument::new).peek(it -> it.addAttribute("a", "test")).collect(Collectors.toList()); - - collection.insertDocuments(docs); - - List> modifiedDocs = docs.stream().peek(it -> it.addAttribute("b", "test")).map(it -> { - Map map = new HashMap<>(); - map.put("_key", it.getKey()); - map.put("a", it.getAttribute("a")); - map.put("b", it.getAttribute("b")); - return map; - }).collect(Collectors.toList()); - - final MultiDocumentEntity> updateResult = - collection.updateDocuments(modifiedDocs, new DocumentUpdateOptions().returnNew(true), BaseDocument.class); - assertThat(updateResult.getDocuments()).hasSize(3); - assertThat(updateResult.getErrors()).isEmpty(); - assertThat(updateResult.getDocuments().stream()).map(DocumentUpdateEntity::getNew).allMatch(it -> it.getAttribute("a").equals("test")).allMatch(it -> it.getAttribute("b").equals("test")); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void updateDocumentsOne(ArangoCollection collection) { - final Collection values = new ArrayList<>(); - { - final BaseDocument e = new BaseDocument(UUID.randomUUID().toString()); - e.setKey("1"); - values.add(e); - } - collection.insertDocuments(values); - final Collection updatedValues = new ArrayList<>(); - final BaseDocument first = values.iterator().next(); - first.addAttribute("a", "test"); - updatedValues.add(first); - final MultiDocumentEntity updateResult = collection.updateDocuments(updatedValues); - assertThat(updateResult.getDocuments()).hasSize(1); - assertThat(updateResult.getErrors()).isEmpty(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void updateDocumentsEmpty(ArangoCollection collection) { - final Collection values = new ArrayList<>(); - final MultiDocumentEntity updateResult = collection.updateDocuments(values); - assertThat(updateResult.getDocuments()).isEmpty(); - assertThat(updateResult.getErrors()).isEmpty(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void updateDocumentsWithoutKey(ArangoCollection collection) { - final Collection values = new ArrayList<>(); - { - values.add(new BaseDocument("1")); - } - collection.insertDocuments(values); - final Collection updatedValues = new ArrayList<>(); - for (final BaseDocument i : values) { - i.addAttribute("a", "test"); - updatedValues.add(i); - } - updatedValues.add(new BaseDocument()); - final MultiDocumentEntity updateResult = collection.updateDocuments(updatedValues); - assertThat(updateResult.getDocuments()).hasSize(1); - assertThat(updateResult.getErrors()).hasSize(1); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void updateDocumentsJson(ArangoCollection collection) { - final Collection values = new ArrayList<>(); - values.add(RawJson.of("{\"_key\":\"1\"}")); - values.add(RawJson.of("{\"_key\":\"2\"}")); - collection.insertDocuments(values); - - final Collection updatedValues = new ArrayList<>(); - updatedValues.add(RawJson.of("{\"_key\":\"1\", \"foo\":\"bar\"}")); - updatedValues.add(RawJson.of("{\"_key\":\"2\", \"foo\":\"bar\"}")); - final MultiDocumentEntity updateResult = collection.updateDocuments(updatedValues); - assertThat(updateResult.getDocuments()).hasSize(2); - assertThat(updateResult.getErrors()).isEmpty(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void updateDocumentsRawData(ArangoCollection collection) { - final RawData values = RawData.of("[{\"_key\":\"1\"}, {\"_key\":\"2\"}]"); - collection.insertDocuments(values); - - final RawData updatedValues = RawData.of("[{\"_key\":\"1\", \"foo\":\"bar\"}, {\"_key\":\"2\", " + - "\"foo\":\"bar\"}]"); - final MultiDocumentEntity updateResult = collection.updateDocuments(updatedValues); - assertThat(updateResult.getDocuments()).hasSize(2); - assertThat(updateResult.getErrors()).isEmpty(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void updateDocumentsRawDataReturnNew(ArangoCollection collection) { - final RawData values = RawData.of("[{\"_key\":\"1\"}, {\"_key\":\"2\"}]"); - collection.insertDocuments(values); - - final RawData updatedValues = RawData.of("[{\"_key\":\"1\", \"foo\":\"bar\"}, {\"_key\":\"2\", " + - "\"foo\":\"bar\"}]"); - MultiDocumentEntity> updateResult = - collection.updateDocuments(updatedValues, new DocumentUpdateOptions().returnNew(true)); - assertThat(updateResult.getDocuments()).hasSize(2); - assertThat(updateResult.getErrors()).isEmpty(); - for (DocumentUpdateEntity doc : updateResult.getDocuments()) { - RawData d = doc.getNew(); - assertThat(d) - .isNotNull() - .isInstanceOf(RawJson.class); - - JsonNode jn = SerdeUtils.INSTANCE.parseJson(((RawJson) d).getValue()); - assertThat(jn.has("foo")).isTrue(); - assertThat(jn.get("foo").textValue()).isEqualTo("bar"); - } - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void replaceDocuments(ArangoCollection collection) { - final Collection values = new ArrayList<>(); - { - values.add(new BaseDocument("1")); - values.add(new BaseDocument("2")); - } - collection.insertDocuments(values); - final Collection updatedValues = new ArrayList<>(); - for (final BaseDocument i : values) { - i.addAttribute("a", "test"); - updatedValues.add(i); - } - final MultiDocumentEntity updateResult = collection.replaceDocuments(updatedValues); - assertThat(updateResult.getDocuments()).hasSize(2); - assertThat(updateResult.getErrors()).isEmpty(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void replaceDocumentsOne(ArangoCollection collection) { - final Collection values = new ArrayList<>(); - { - final BaseDocument e = new BaseDocument(UUID.randomUUID().toString()); - e.setKey("1"); - values.add(e); - } - collection.insertDocuments(values); - final Collection updatedValues = new ArrayList<>(); - final BaseDocument first = values.iterator().next(); - first.addAttribute("a", "test"); - updatedValues.add(first); - final MultiDocumentEntity updateResult = collection.updateDocuments(updatedValues); - assertThat(updateResult.getDocuments()).hasSize(1); - assertThat(updateResult.getErrors()).isEmpty(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void replaceDocumentsEmpty(ArangoCollection collection) { - final Collection values = new ArrayList<>(); - final MultiDocumentEntity updateResult = collection.updateDocuments(values); - assertThat(updateResult.getDocuments()).isEmpty(); - assertThat(updateResult.getErrors()).isEmpty(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void replaceDocumentsWithoutKey(ArangoCollection collection) { - final Collection values = new ArrayList<>(); - { - values.add(new BaseDocument("1")); - } - collection.insertDocuments(values); - final Collection updatedValues = new ArrayList<>(); - for (final BaseDocument i : values) { - i.addAttribute("a", "test"); - updatedValues.add(i); - } - updatedValues.add(new BaseDocument()); - final MultiDocumentEntity updateResult = collection.updateDocuments(updatedValues); - assertThat(updateResult.getDocuments()).hasSize(1); - assertThat(updateResult.getErrors()).hasSize(1); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void replaceDocumentsJson(ArangoCollection collection) { - final Collection values = new ArrayList<>(); - values.add(RawJson.of("{\"_key\":\"1\"}")); - values.add(RawJson.of("{\"_key\":\"2\"}")); - collection.insertDocuments(values); - - final Collection updatedValues = new ArrayList<>(); - updatedValues.add(RawJson.of("{\"_key\":\"1\", \"foo\":\"bar\"}")); - updatedValues.add(RawJson.of("{\"_key\":\"2\", \"foo\":\"bar\"}")); - final MultiDocumentEntity updateResult = collection.replaceDocuments(updatedValues); - assertThat(updateResult.getDocuments()).hasSize(2); - assertThat(updateResult.getErrors()).isEmpty(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void replaceDocumentsRawData(ArangoCollection collection) { - final RawData values = RawData.of("[{\"_key\":\"1\"}, {\"_key\":\"2\"}]"); - collection.insertDocuments(values); - - final RawData updatedValues = RawData.of("[{\"_key\":\"1\", \"foo\":\"bar\"}, {\"_key\":\"2\", " + - "\"foo\":\"bar\"}]"); - final MultiDocumentEntity updateResult = collection.replaceDocuments(updatedValues); - assertThat(updateResult.getDocuments()).hasSize(2); - assertThat(updateResult.getErrors()).isEmpty(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void replaceDocumentsRawDataReturnNew(ArangoCollection collection) { - final RawData values = RawData.of("[{\"_key\":\"1\"}, {\"_key\":\"2\"}]"); - collection.insertDocuments(values); - - final RawData updatedValues = RawData.of("[{\"_key\":\"1\", \"foo\":\"bar\"}, {\"_key\":\"2\", " + - "\"foo\":\"bar\"}]"); - MultiDocumentEntity> updateResult = - collection.replaceDocuments(updatedValues, new DocumentReplaceOptions().returnNew(true)); - assertThat(updateResult.getDocuments()).hasSize(2); - assertThat(updateResult.getErrors()).isEmpty(); - for (DocumentUpdateEntity doc : updateResult.getDocuments()) { - RawData d = doc.getNew(); - assertThat(d) - .isNotNull() - .isInstanceOf(RawJson.class); - - JsonNode jn = SerdeUtils.INSTANCE.parseJson(((RawJson) d).getValue()); - assertThat(jn.has("foo")).isTrue(); - assertThat(jn.get("foo").textValue()).isEqualTo("bar"); - } - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void getInfo(ArangoCollection collection) { - final CollectionEntity result = collection.getInfo(); - assertThat(result.getName()).isEqualTo(COLLECTION_NAME); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void getPropeties(ArangoCollection collection) { - final CollectionPropertiesEntity result = collection.getProperties(); - assertThat(result.getName()).isEqualTo(COLLECTION_NAME); - assertThat(result.getCount()).isNull(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void changeProperties(ArangoCollection collection) { - final CollectionPropertiesEntity properties = collection.getProperties(); - assertThat(properties.getWaitForSync()).isNotNull(); - if (isAtLeastVersion(3, 7)) { - assertThat(properties.getSchema()).isNull(); - } - - String schemaRule = ("{ " + " \"properties\": {" + " \"number\": {" + " " + -" \"type\": \"number\"" + " }" + " }" + " }").replaceAll("\\s", ""); - String schemaMessage = "The document has problems!"; - - CollectionPropertiesOptions updatedOptions = -new CollectionPropertiesOptions().waitForSync(!properties.getWaitForSync()).schema(new CollectionSchema().setLevel(CollectionSchema.Level.NEW).setMessage(schemaMessage).setRule(schemaRule)); - - final CollectionPropertiesEntity changedProperties = collection.changeProperties(updatedOptions); - assertThat(changedProperties.getWaitForSync()).isNotNull(); - assertThat(changedProperties.getWaitForSync()).isEqualTo(!properties.getWaitForSync()); - if (isAtLeastVersion(3, 7)) { - assertThat(changedProperties.getSchema()).isNotNull(); - assertThat(changedProperties.getSchema().getLevel()).isEqualTo(CollectionSchema.Level.NEW); - assertThat(changedProperties.getSchema().getMessage()).isEqualTo(schemaMessage); - assertThat(changedProperties.getSchema().getRule()).isEqualTo(schemaRule); - } - - // revert changes - CollectionPropertiesEntity revertedProperties = collection.changeProperties(new CollectionPropertiesOptions() - .waitForSync(properties.getWaitForSync()).schema(new CollectionSchema())); - if (isAtLeastVersion(3, 7)) { - assertThat(revertedProperties.getSchema()).isNull(); - } - - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void rename(ArangoCollection collection) { - assumeTrue(isSingleServer()); - ArangoDatabase db = collection.db(); - final CollectionEntity result = collection.rename(COLLECTION_NAME + "1"); - assertThat(result).isNotNull(); - assertThat(result.getName()).isEqualTo(COLLECTION_NAME + "1"); - final CollectionEntity info = db.collection(COLLECTION_NAME + "1").getInfo(); - assertThat(info.getName()).isEqualTo(COLLECTION_NAME + "1"); - Throwable thrown = catchThrowable(() -> db.collection(COLLECTION_NAME).getInfo()); - assertThat(thrown).isInstanceOf(ArangoDBException.class); - ArangoDBException e = (ArangoDBException) thrown; - assertThat(e.getResponseCode()).isEqualTo(404); - db.collection(COLLECTION_NAME + "1").rename(COLLECTION_NAME); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void responsibleShard(ArangoCollection collection) { - assumeTrue(isCluster()); - assumeTrue(isAtLeastVersion(3, 5)); - ShardEntity shard = collection.getResponsibleShard(new BaseDocument("testKey")); - assertThat(shard).isNotNull(); - assertThat(shard.getShardId()).isNotNull(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void renameDontBreaksCollectionHandler(ArangoCollection collection) { - assumeTrue(isSingleServer()); - collection.rename(COLLECTION_NAME + "1"); - assertThat(collection.getInfo()).isNotNull(); - collection.db().collection(COLLECTION_NAME + "1").rename(COLLECTION_NAME); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void getRevision(ArangoCollection collection) { - final CollectionRevisionEntity result = collection.getRevision(); - assertThat(result).isNotNull(); - assertThat(result.getName()).isEqualTo(COLLECTION_NAME); - assertThat(result.getRevision()).isNotNull(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void keyWithSpecialCharacter(ArangoCollection collection) { - final String key = "myKey_-:.@()+,=;$!*'%-" + UUID.randomUUID(); - collection.insertDocument(new BaseDocument(key)); - final BaseDocument doc = collection.getDocument(key, BaseDocument.class); - assertThat(doc).isNotNull(); - assertThat(doc.getKey()).isEqualTo(key); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void alreadyUrlEncodedkey(ArangoCollection collection) { - final String key = "http%3A%2F%2Fexample.com%2F-" + UUID.randomUUID(); - collection.insertDocument(new BaseDocument(key)); - final BaseDocument doc = collection.getDocument(key, BaseDocument.class); - assertThat(doc).isNotNull(); - assertThat(doc.getKey()).isEqualTo(key); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void grantAccessRW(ArangoCollection collection) { - ArangoDB arangoDB = collection.db().arango(); - try { - arangoDB.createUser("user1", "1234", null); - collection.grantAccess("user1", Permissions.RW); - } finally { - arangoDB.deleteUser("user1"); - } - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void grantAccessRO(ArangoCollection collection) { - ArangoDB arangoDB = collection.db().arango(); - try { - arangoDB.createUser("user1", "1234", null); - collection.grantAccess("user1", Permissions.RO); - } finally { - arangoDB.deleteUser("user1"); - } - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void grantAccessNONE(ArangoCollection collection) { - ArangoDB arangoDB = collection.db().arango(); - try { - arangoDB.createUser("user1", "1234", null); - collection.grantAccess("user1", Permissions.NONE); - } finally { - arangoDB.deleteUser("user1"); - } - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void grantAccessUserNotFound(ArangoCollection collection) { - Throwable thrown = catchThrowable(() -> collection.grantAccess("user1", Permissions.RW)); - assertThat(thrown).isInstanceOf(ArangoDBException.class); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void revokeAccess(ArangoCollection collection) { - ArangoDB arangoDB = collection.db().arango(); - try { - arangoDB.createUser("user1", "1234", null); - collection.grantAccess("user1", Permissions.NONE); - } finally { - arangoDB.deleteUser("user1"); - } - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void revokeAccessUserNotFound(ArangoCollection collection) { - Throwable thrown = catchThrowable(() -> collection.grantAccess("user1", Permissions.NONE)); - assertThat(thrown).isInstanceOf(ArangoDBException.class); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void resetAccess(ArangoCollection collection) { - ArangoDB arangoDB = collection.db().arango(); - try { - arangoDB.createUser("user1", "1234", null); - collection.resetAccess("user1"); - } finally { - arangoDB.deleteUser("user1"); - } - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void resetAccessUserNotFound(ArangoCollection collection) { - Throwable thrown = catchThrowable(() -> collection.resetAccess("user1")); - assertThat(thrown).isInstanceOf(ArangoDBException.class); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void getPermissions(ArangoCollection collection) { - assertThat(collection.getPermissions("root")).isEqualTo(Permissions.RW); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void annotationsInParamsAndMethods(ArangoCollection collection) { - assumeTrue(collection.getSerde().getUserSerde() instanceof JacksonSerde, "JacksonSerde only"); - AnnotatedEntity entity = new AnnotatedEntity(UUID.randomUUID().toString()); - AnnotatedEntity doc = collection.insertDocument(entity, new DocumentCreateOptions().returnNew(true)).getNew(); - assertThat(doc).isNotNull(); - assertThat(doc.getKey()).isEqualTo(entity.getKey()); - assertThat(doc.getId()).isNotNull(); - assertThat(doc.getRev()).isNotNull(); - } - - @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, property = "type") - public interface Animal { - String getKey(); - - String getName(); - } - - public static class Dog implements Animal { - - @Key - private String key; - private String name; - - public Dog() { - } - - public Dog(String key, String name) { - this.key = key; - this.name = name; - } - - @Override - public String getKey() { - return key; - } - - public void setKey(String key) { - this.key = key; - } - - @Override - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - } - - public static class Cat implements Animal { - @Key - private String key; - private String name; - - public Cat() { - } - - public Cat(String key, String name) { - this.key = key; - this.name = name; - } - - @Override - public String getKey() { - return key; - } - - public void setKey(String key) { - this.key = key; - } - - @Override - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - } - - public static class TestUpdateEntity { - private String a, b; - - public String getA() { - return a; - } - - public String getB() { - return b; - } - } - - public static class TestUpdateEntitySerializeNullFalse { - private String a, b; - - @JsonInclude(JsonInclude.Include.NON_NULL) - public String getA() { - return a; - } - - @JsonInclude(JsonInclude.Include.NON_NULL) - public String getB() { - return b; - } - } - - public static class AnnotatedEntity { - - private final String key; - private String id; - private String rev; - - public AnnotatedEntity(@Key String key) { - this.key = key; - } - - public String getKey() { - return key; - } - - public String getId() { - return id; - } - - @Id - public void setId(String id) { - this.id = id; - } - - public String getRev() { - return rev; - } - - @Rev - public void setRev(String rev) { - this.rev = rev; - } - } - -} diff --git a/shaded-integration-tests/src/test/native/java/com/arangodb/ArangoCursorTest.java b/shaded-integration-tests/src/test/native/java/com/arangodb/ArangoCursorTest.java deleted file mode 100644 index cfbd98775..000000000 --- a/shaded-integration-tests/src/test/native/java/com/arangodb/ArangoCursorTest.java +++ /dev/null @@ -1,133 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2018 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb; - -import com.arangodb.model.AqlQueryOptions; -import com.fasterxml.jackson.databind.JsonNode; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.MethodSource; - -import java.util.Optional; -import java.util.Set; -import java.util.concurrent.atomic.AtomicLong; -import java.util.stream.Collectors; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * @author Mark Vollmary - * @author Michele Rastelli - */ -class ArangoCursorTest extends BaseJunit5 { - - @BeforeAll - static void init() { - initDB(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void firstStream(ArangoDatabase db) { - final ArangoCursor cursor = db.query("FOR i IN 0..99 RETURN i", JsonNode.class); - final Optional first = cursor.stream().findFirst(); - assertThat(first).isPresent(); - assertThat(first.get().isInt()).isTrue(); - assertThat(first.get().asLong()).isZero(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void next(ArangoDatabase db) { - final ArangoCursor cursor = db.query("FOR i IN 0..99 RETURN i", new AqlQueryOptions().batchSize(5), - JsonNode.class); - while (cursor.hasNext()) { - cursor.next(); - } - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void mapFilterCountStream(ArangoDatabase db) { - final ArangoCursor cursor = db.query("FOR i IN 0..99 RETURN i", JsonNode.class); - final long count = cursor.stream().map(JsonNode::asLong).filter(t -> t < 50).count(); - assertThat(count).isEqualTo(50L); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void mapFilterCollectIntoSetStream(ArangoDatabase db) { - final ArangoCursor cursor = db.query("FOR i IN 0..99 RETURN i", JsonNode.class); - final Set target = cursor.stream().map(JsonNode::asLong).filter(t -> t < 50).collect(Collectors.toSet()); - assertThat(target) - .isNotNull() - .hasSize(50); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void forEach(ArangoDatabase db) { - final AtomicLong i = new AtomicLong(0L); - final ArangoCursor cursor = db.query("FOR i IN 0..99 RETURN i", JsonNode.class); - cursor.forEach(t -> assertThat(t.asLong()).isEqualTo(i.getAndIncrement())); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void mapForeachStream(ArangoDatabase db) { - final AtomicLong i = new AtomicLong(0L); - final ArangoCursor cursor = db.query("FOR i IN 0..99 RETURN i", JsonNode.class); - cursor.stream().map(JsonNode::asLong).forEach(t -> assertThat(t).isEqualTo(i.getAndIncrement())); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void mapFilterForEachStream(ArangoDatabase db) { - final AtomicLong i = new AtomicLong(0L); - final ArangoCursor cursor = db.query("FOR i IN 0..99 RETURN i", JsonNode.class); - cursor.stream().map(JsonNode::asLong).filter(t -> t < 50).forEach(t -> assertThat(t).isEqualTo(i.getAndIncrement())); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void anyMatchStream(ArangoDatabase db) { - final ArangoCursor cursor = db.query("FOR i IN 0..99 RETURN i", JsonNode.class); - final boolean match = cursor.stream().anyMatch(t -> t.asLong() == 50L); - assertThat(match).isTrue(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void noneMatchStream(ArangoDatabase db) { - final ArangoCursor cursor = db.query("FOR i IN 0..99 RETURN i", JsonNode.class); - final boolean match = cursor.stream().noneMatch(t -> t.asLong() == 100L); - assertThat(match).isTrue(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void allMatchStream(ArangoDatabase db) { - final ArangoCursor cursor = db.query("FOR i IN 0..99 RETURN i", JsonNode.class); - final boolean match = cursor.stream().allMatch(t -> t.asLong() < 100L); - assertThat(match).isTrue(); - } - -} diff --git a/shaded-integration-tests/src/test/native/java/com/arangodb/ArangoDBTest.java b/shaded-integration-tests/src/test/native/java/com/arangodb/ArangoDBTest.java deleted file mode 100644 index 522ce6926..000000000 --- a/shaded-integration-tests/src/test/native/java/com/arangodb/ArangoDBTest.java +++ /dev/null @@ -1,666 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb; - -import com.arangodb.config.ConfigUtils; -import com.arangodb.entity.*; -import com.arangodb.internal.serde.SerdeUtils; -import com.arangodb.model.*; -import com.arangodb.model.LogOptions.SortOrder; -import com.arangodb.shaded.fasterxml.jackson.databind.JsonNode; -import com.arangodb.util.RawJson; -import com.arangodb.util.TestUtils; -import org.junit.jupiter.api.AfterAll; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.Disabled; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.MethodSource; - -import java.util.*; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.Executors; -import java.util.stream.Collectors; -import java.util.stream.IntStream; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.catchThrowable; -import static org.junit.jupiter.api.Assumptions.assumeTrue; - -/** - * @author Mark Vollmary - * @author Reşat SABIQ - * @author Michele Rastelli - */ -class ArangoDBTest extends BaseJunit5 { - - private static final DbName DB1 = DbName.of("ArangoDBTest_db1"); - private static final DbName DB2 = DbName.of("ArangoDBTest_db2"); - - private static final String ROOT = "root"; - private static final String PW = "machts der hund"; - - private static Boolean extendedNames; - - @BeforeAll - static void initDBs() { - initDB(DB1); - initDB(DB2); - } - - @AfterAll - static void shutdown() { - dropDB(DB1); - dropDB(DB2); - } - - private boolean supportsExtendedNames(ArangoDB arangoDB) { - if (extendedNames == null) { - try { - ArangoDatabase testDb = arangoDB.db(DbName.of("test-" + TestUtils.generateRandomDbName(20, true))); - testDb.create(); - extendedNames = true; - testDb.drop(); - } catch (ArangoDBException e) { - extendedNames = false; - } - } - return extendedNames; - } - - @ParameterizedTest(name = "{index}") - @MethodSource("arangos") - void getVersion(ArangoDB arangoDB) { - final ArangoDBVersion version = arangoDB.getVersion(); - assertThat(version.getServer()).isNotNull(); - assertThat(version.getVersion()).isNotNull(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("arangos") - void createAndDeleteDatabase(ArangoDB arangoDB) { - final DbName dbName = DbName.of("testDB-" + TestUtils.generateRandomDbName(20, - supportsExtendedNames(arangoDB))); - final Boolean resultCreate; - resultCreate = arangoDB.createDatabase(dbName); - assertThat(resultCreate).isTrue(); - final Boolean resultDelete = arangoDB.db(dbName).drop(); - assertThat(resultDelete).isTrue(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("arangos") - void createWithNotNormalizedName(ArangoDB arangoDB) { - assumeTrue(supportsExtendedNames(arangoDB)); - - final String dbName = "testDB-\u006E\u0303\u00f1"; - DbName normalized = DbName.normalize(dbName); - arangoDB.createDatabase(normalized); - arangoDB.db(normalized).drop(); - - Throwable thrown = catchThrowable(() -> DbName.of(dbName)); - assertThat(thrown) - .isInstanceOf(IllegalArgumentException.class) - .hasMessageContaining("not normalized"); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("arangos") - void createDatabaseWithOptions(ArangoDB arangoDB) { - assumeTrue(isCluster()); - assumeTrue(isAtLeastVersion(3, 6)); - final DbName dbName = DbName.of("testDB-" + TestUtils.generateRandomDbName(20, - supportsExtendedNames(arangoDB))); - final Boolean resultCreate = arangoDB.createDatabase(new DBCreateOptions() - .name(dbName) - .options(new DatabaseOptions() - .writeConcern(2) - .replicationFactor(2) - .sharding("") - ) - ); - assertThat(resultCreate).isTrue(); - - DatabaseEntity info = arangoDB.db(dbName).getInfo(); - assertThat(info.getReplicationFactor().getValue()).isEqualTo(2); - assertThat(info.getWriteConcern()).isEqualTo(2); - assertThat(info.getSharding()).isEmpty(); - - final Boolean resultDelete = arangoDB.db(dbName).drop(); - assertThat(resultDelete).isTrue(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("arangos") - void createDatabaseWithOptionsSatellite(ArangoDB arangoDB) { - assumeTrue(isCluster()); - assumeTrue(isEnterprise()); - assumeTrue(isAtLeastVersion(3, 6)); - - final DbName dbName = DbName.of("testDB-" + TestUtils.generateRandomDbName(20, - supportsExtendedNames(arangoDB))); - final Boolean resultCreate = arangoDB.createDatabase(new DBCreateOptions() - .name(dbName) - .options(new DatabaseOptions() - .writeConcern(2) - .replicationFactor(ReplicationFactor.ofSatellite()) - .sharding("") - ) - ); - assertThat(resultCreate).isTrue(); - - DatabaseEntity info = arangoDB.db(dbName).getInfo(); - assertThat(info.getReplicationFactor()).isEqualTo(ReplicationFactor.ofSatellite()); - assertThat(info.getWriteConcern()).isEqualTo(2); - assertThat(info.getSharding()).isEmpty(); - - final Boolean resultDelete = arangoDB.db(dbName).drop(); - assertThat(resultDelete).isTrue(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("arangos") - void createDatabaseWithUsers(ArangoDB arangoDB) throws InterruptedException { - final DbName dbName = DbName.of("testDB-" + TestUtils.generateRandomDbName(20, - supportsExtendedNames(arangoDB))); - final Map extra = Collections.singletonMap("key", "value"); - final Boolean resultCreate = arangoDB.createDatabase(new DBCreateOptions() - .name(dbName) - .users(Collections.singletonList(new DatabaseUsersOptions() - .active(true) - .username("testUser") - .passwd("testPasswd") - .extra(extra) - )) - ); - assertThat(resultCreate).isTrue(); - - DatabaseEntity info = arangoDB.db(dbName).getInfo(); - assertThat(info.getName()).isEqualTo(dbName.get()); - - Optional retrievedUserOptional = arangoDB.getUsers().stream() - .filter(it -> it.getUser().equals("testUser")) - .findFirst(); - assertThat(retrievedUserOptional).isPresent(); - - UserEntity retrievedUser = retrievedUserOptional.get(); - assertThat(retrievedUser.getActive()).isTrue(); - assertThat(retrievedUser.getExtra()).isEqualTo(extra); - - // needed for active-failover tests only - Thread.sleep(2_000); - - ArangoDB arangoDBTestUser = new ArangoDB.Builder() - .loadProperties(config) - .user("testUser") - .password("testPasswd") - .build(); - - // check if testUser has been created and can access the created db - ArangoCollection collection = arangoDBTestUser.db(dbName).collection("col-" + UUID.randomUUID()); - collection.create(); - arangoDBTestUser.shutdown(); - - final Boolean resultDelete = arangoDB.db(dbName).drop(); - assertThat(resultDelete).isTrue(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("arangos") - void getDatabases(ArangoDB arangoDB) { - Collection dbs = arangoDB.getDatabases(); - assertThat(dbs).contains("_system", DB1.get()); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("arangos") - void getAccessibleDatabases(ArangoDB arangoDB) { - final Collection dbs = arangoDB.getAccessibleDatabases(); - assertThat(dbs).contains("_system"); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("arangos") - void getAccessibleDatabasesFor(ArangoDB arangoDB) { - final Collection dbs = arangoDB.getAccessibleDatabasesFor("root"); - assertThat(dbs).contains("_system"); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("arangos") - void createUser(ArangoDB arangoDB) { - String username = "user-" + UUID.randomUUID(); - final UserEntity result = arangoDB.createUser(username, PW, null); - assertThat(result.getUser()).isEqualTo(username); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("arangos") - void deleteUser(ArangoDB arangoDB) { - String username = "user-" + UUID.randomUUID(); - arangoDB.createUser(username, PW, null); - arangoDB.deleteUser(username); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("arangos") - void getUserRoot(ArangoDB arangoDB) { - final UserEntity user = arangoDB.getUser(ROOT); - assertThat(user.getUser()).isEqualTo(ROOT); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("arangos") - void getUser(ArangoDB arangoDB) { - String username = "user-" + UUID.randomUUID(); - arangoDB.createUser(username, PW, null); - final UserEntity user = arangoDB.getUser(username); - assertThat(user.getUser()).isEqualTo(username); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("arangos") - void getUsersOnlyRoot(ArangoDB arangoDB) { - final Collection users = arangoDB.getUsers(); - assertThat(users).isNotEmpty(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("arangos") - void getUsers(ArangoDB arangoDB) { - String username = "user-" + UUID.randomUUID(); - // Allow & account for pre-existing users other than ROOT: - final Collection initialUsers = arangoDB.getUsers(); - - arangoDB.createUser(username, PW, null); - final Collection users = arangoDB.getUsers(); - assertThat(users).hasSize(initialUsers.size() + 1); - - final List expected = new ArrayList<>(users.size()); - // Add initial users, including root: - for (final UserEntity userEntity : initialUsers) { - expected.add(userEntity.getUser()); - } - // Add username: - expected.add(username); - - for (final UserEntity user : users) { - assertThat(user.getUser()).isIn(expected); - } - } - - @ParameterizedTest(name = "{index}") - @MethodSource("arangos") - void updateUserNoOptions(ArangoDB arangoDB) { - String username = "user-" + UUID.randomUUID(); - arangoDB.createUser(username, PW, null); - arangoDB.updateUser(username, null); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("arangos") - void updateUser(ArangoDB arangoDB) { - String username = "user-" + UUID.randomUUID(); - final Map extra = new HashMap<>(); - extra.put("hund", false); - arangoDB.createUser(username, PW, new UserCreateOptions().extra(extra)); - extra.put("hund", true); - extra.put("mund", true); - final UserEntity user = arangoDB.updateUser(username, new UserUpdateOptions().extra(extra)); - assertThat(user.getExtra()).hasSize(2); - assertThat(user.getExtra()).containsKey("hund"); - assertThat(Boolean.valueOf(String.valueOf(user.getExtra().get("hund")))).isTrue(); - final UserEntity user2 = arangoDB.getUser(username); - assertThat(user2.getExtra()).hasSize(2); - assertThat(user2.getExtra()).containsKey("hund"); - assertThat(Boolean.valueOf(String.valueOf(user2.getExtra().get("hund")))).isTrue(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("arangos") - void replaceUser(ArangoDB arangoDB) { - String username = "user-" + UUID.randomUUID(); - final Map extra = new HashMap<>(); - extra.put("hund", false); - arangoDB.createUser(username, PW, new UserCreateOptions().extra(extra)); - extra.remove("hund"); - extra.put("mund", true); - final UserEntity user = arangoDB.replaceUser(username, new UserUpdateOptions().extra(extra)); - assertThat(user.getExtra()).hasSize(1); - assertThat(user.getExtra()).containsKey("mund"); - assertThat(Boolean.valueOf(String.valueOf(user.getExtra().get("mund")))).isTrue(); - final UserEntity user2 = arangoDB.getUser(username); - assertThat(user2.getExtra()).hasSize(1); - assertThat(user2.getExtra()).containsKey("mund"); - assertThat(Boolean.valueOf(String.valueOf(user2.getExtra().get("mund")))).isTrue(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("arangos") - void updateUserDefaultDatabaseAccess(ArangoDB arangoDB) { - String username = "user-" + UUID.randomUUID(); - arangoDB.createUser(username, PW); - arangoDB.grantDefaultDatabaseAccess(username, Permissions.RW); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("arangos") - void updateUserDefaultCollectionAccess(ArangoDB arangoDB) { - String username = "user-" + UUID.randomUUID(); - arangoDB.createUser(username, PW); - arangoDB.grantDefaultCollectionAccess(username, Permissions.RW); - } - - @Test - void authenticationFailPassword() { - final ArangoDB arangoDB = new ArangoDB.Builder() - .loadProperties(config) - .password("no").jwt(null).build(); - Throwable thrown = catchThrowable(arangoDB::getVersion); - assertThat(thrown).isInstanceOf(ArangoDBException.class); - assertThat(((ArangoDBException) thrown).getResponseCode()).isEqualTo(401); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("arangos") - void authenticationFailUser() { - final ArangoDB arangoDB = new ArangoDB.Builder() - .loadProperties(config) - .user("no").jwt(null).build(); - Throwable thrown = catchThrowable(arangoDB::getVersion); - assertThat(thrown).isInstanceOf(ArangoDBException.class); - assertThat(((ArangoDBException) thrown).getResponseCode()).isEqualTo(401); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("arangos") - void executeGetVersion(ArangoDB arangoDB) { - Request request = Request.builder() - .db(DbName.SYSTEM) - .method(Request.Method.GET) - .path("/_api/version") - .queryParam("details", "true") - .build(); - final Response response = arangoDB.execute(request, RawJson.class); - JsonNode body = SerdeUtils.INSTANCE.parseJson(response.getBody().getValue()); - assertThat(body.get("version").isTextual()).isTrue(); - assertThat(body.get("details").isObject()).isTrue(); - assertThat(response.getResponseCode()).isEqualTo(200); - if (isAtLeastVersion(3, 9)) { - String header = response.getHeaders().get("x-arango-queue-time-seconds"); - assertThat(header).isNotNull(); - } - } - - @ParameterizedTest(name = "{index}") - @MethodSource("arangos") - void getLogEntries(ArangoDB arangoDB) { - assumeTrue(isAtLeastVersion(3, 8)); - final LogEntriesEntity logs = arangoDB.getLogEntries(null); - assertThat(logs.getTotal()).isPositive(); - assertThat(logs.getMessages()).hasSize(logs.getTotal().intValue()); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("arangos") - void getLogEntriesUpto(ArangoDB arangoDB) { - assumeTrue(isAtLeastVersion(3, 8)); - final LogEntriesEntity logsUpto = arangoDB.getLogEntries(new LogOptions().upto(LogLevel.WARNING)); - assertThat(logsUpto.getMessages()) - .map(LogEntriesEntity.Message::getLevel) - .doesNotContain("INFO"); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("arangos") - void getLogEntriesLevel(ArangoDB arangoDB) { - assumeTrue(isAtLeastVersion(3, 8)); - final LogEntriesEntity logsInfo = arangoDB.getLogEntries(new LogOptions().level(LogLevel.INFO)); - assertThat(logsInfo.getMessages()) - .map(LogEntriesEntity.Message::getLevel) - .containsOnly("INFO"); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("arangos") - void getLogEntriesStart(ArangoDB arangoDB) { - assumeTrue(isAtLeastVersion(3, 8)); - final LogEntriesEntity logs = arangoDB.getLogEntries(null); - final Long firstId = logs.getMessages().get(0).getId(); - final LogEntriesEntity logsStart = arangoDB.getLogEntries(new LogOptions().start(firstId + 1)); - assertThat(logsStart.getMessages()) - .map(LogEntriesEntity.Message::getId) - .doesNotContain(firstId); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("arangos") - void getLogEntriesSize(ArangoDB arangoDB) { - assumeTrue(isAtLeastVersion(3, 8)); - final LogEntriesEntity logs = arangoDB.getLogEntries(null); - int count = logs.getMessages().size(); - assertThat(count).isPositive(); - final LogEntriesEntity logsSize = arangoDB.getLogEntries(new LogOptions().size(count - 1)); - assertThat(logsSize.getMessages()).hasSize(count - 1); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("arangos") - void getLogEntriesOffset(ArangoDB arangoDB) { - assumeTrue(isAtLeastVersion(3, 8)); - final LogEntriesEntity logs = arangoDB.getLogEntries(null); - assertThat(logs.getTotal()).isPositive(); - Long firstId = logs.getMessages().get(0).getId(); - final LogEntriesEntity logsOffset = arangoDB.getLogEntries(new LogOptions().offset(1)); - assertThat(logsOffset.getMessages()) - .map(LogEntriesEntity.Message::getId) - .doesNotContain(firstId); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("arangos") - void getLogEntriesSearch(ArangoDB arangoDB) { - assumeTrue(isAtLeastVersion(3, 8)); - final LogEntriesEntity logs = arangoDB.getLogEntries(null); - final LogEntriesEntity logsSearch = arangoDB.getLogEntries(new LogOptions().search(TEST_DB.get())); - assertThat(logs.getTotal()).isGreaterThan(logsSearch.getTotal()); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("arangos") - void getLogEntriesSortAsc(ArangoDB arangoDB) { - assumeTrue(isAtLeastVersion(3, 8)); - final LogEntriesEntity logs = arangoDB.getLogEntries(new LogOptions().sort(SortOrder.asc)); - long lastId = -1; - List ids = logs.getMessages().stream() - .map(LogEntriesEntity.Message::getId) - .collect(Collectors.toList()); - for (final Long id : ids) { - assertThat(id).isGreaterThan(lastId); - lastId = id; - } - } - - @ParameterizedTest(name = "{index}") - @MethodSource("arangos") - void getLogEntriesSortDesc(ArangoDB arangoDB) { - assumeTrue(isAtLeastVersion(3, 8)); - final LogEntriesEntity logs = arangoDB.getLogEntries(new LogOptions().sort(SortOrder.desc)); - long lastId = Long.MAX_VALUE; - List ids = logs.getMessages().stream() - .map(LogEntriesEntity.Message::getId) - .collect(Collectors.toList()); - for (final Long id : ids) { - assertThat(lastId).isGreaterThan(id); - lastId = id; - } - } - - @ParameterizedTest(name = "{index}") - @MethodSource("arangos") - void getLogLevel(ArangoDB arangoDB) { - assumeTrue(isAtLeastVersion(3, 7)); // it fails in 3.6 active-failover (BTS-362) - final LogLevelEntity logLevel = arangoDB.getLogLevel(); - assertThat(logLevel.getAgency()).isEqualTo(LogLevelEntity.LogLevel.INFO); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("arangos") - void setLogLevel(ArangoDB arangoDB) { - assumeTrue(isAtLeastVersion(3, 7)); // it fails in 3.6 active-failover (BTS-362) - final LogLevelEntity entity = new LogLevelEntity(); - try { - entity.setAgency(LogLevelEntity.LogLevel.ERROR); - final LogLevelEntity logLevel = arangoDB.setLogLevel(entity); - assertThat(logLevel.getAgency()).isEqualTo(LogLevelEntity.LogLevel.ERROR); - } finally { - entity.setAgency(LogLevelEntity.LogLevel.INFO); - arangoDB.setLogLevel(entity); - } - } - - @ParameterizedTest(name = "{index}") - @MethodSource("arangos") - void setAllLogLevel(ArangoDB arangoDB) { - assumeTrue(isAtLeastVersion(3, 9)); - final LogLevelEntity entity = new LogLevelEntity(); - try { - entity.setAll(LogLevelEntity.LogLevel.ERROR); - final LogLevelEntity logLevel = arangoDB.setLogLevel(entity); - assertThat(logLevel.getAgency()).isEqualTo(LogLevelEntity.LogLevel.ERROR); - assertThat(logLevel.getQueries()).isEqualTo(LogLevelEntity.LogLevel.ERROR); - LogLevelEntity retrievedLevels = arangoDB.getLogLevel(); - assertThat(retrievedLevels.getAgency()).isEqualTo(LogLevelEntity.LogLevel.ERROR); - } finally { - entity.setAll(LogLevelEntity.LogLevel.INFO); - arangoDB.setLogLevel(entity); - } - } - - @ParameterizedTest(name = "{index}") - @MethodSource("arangos") - void getQueryOptimizerRules(ArangoDB arangoDB) { - assumeTrue(isAtLeastVersion(3, 10)); - final Collection rules = arangoDB.getQueryOptimizerRules(); - assertThat(rules).isNotEmpty(); - for (QueryOptimizerRule rule : rules) { - assertThat(rule).isNotNull(); - assertThat(rule.getName()).isNotNull(); - QueryOptimizerRule.Flags flags = rule.getFlags(); - assertThat(flags.getHidden()).isNotNull(); - assertThat(flags.getClusterOnly()).isNotNull(); - assertThat(flags.getCanBeDisabled()).isNotNull(); - assertThat(flags.getCanCreateAdditionalPlans()).isNotNull(); - assertThat(flags.getDisabledByDefault()).isNotNull(); - assertThat(flags.getEnterpriseOnly()).isNotNull(); - } - } - - @ParameterizedTest(name = "{index}") - @MethodSource("arangos") - void arangoDBException(ArangoDB arangoDB) { - Throwable thrown = catchThrowable(() -> arangoDB.db(DbName.of("no")).getInfo()); - assertThat(thrown).isInstanceOf(ArangoDBException.class); - ArangoDBException e = (ArangoDBException) thrown; - assertThat(e.getResponseCode()).isEqualTo(404); - assertThat(e.getErrorNum()).isEqualTo(1228); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("arangos") - void fallbackHost() { - final ArangoDB arangoDB = new ArangoDB.Builder() - .loadProperties(config) - .host("not-accessible", 8529).host("127.0.0.1", 8529).build(); - final ArangoDBVersion version = arangoDB.getVersion(); - assertThat(version).isNotNull(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("arangos") - void loadproperties() { - Throwable thrown = catchThrowable(() -> new ArangoDB.Builder() - .loadProperties(ConfigUtils.loadConfig("arangodb-bad.properties")) - ); - assertThat(thrown).isInstanceOf(IllegalArgumentException.class); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("arangos") - void loadpropertiesWithPrefix() { - ArangoDB adb = new ArangoDB.Builder() - .loadProperties(ConfigUtils.loadConfig("arangodb-with-prefix.properties", "adb")) - .build(); - adb.getVersion(); - adb.shutdown(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("arangos") - void accessMultipleDatabases(ArangoDB arangoDB) { - final ArangoDBVersion version1 = arangoDB.db(DB1).getVersion(); - assertThat(version1).isNotNull(); - final ArangoDBVersion version2 = arangoDB.db(DB2).getVersion(); - assertThat(version2).isNotNull(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("arangos") - @Disabled("Manual execution only") - void queueTime(ArangoDB arangoDB) throws InterruptedException, ExecutionException { - List> futures = IntStream.range(0, 80) - .mapToObj(i -> CompletableFuture.runAsync( - () -> arangoDB.db().query("RETURN SLEEP(1)", Void.class), - Executors.newFixedThreadPool(80)) - ) - .collect(Collectors.toList()); - for (CompletableFuture f : futures) { - f.get(); - } - - QueueTimeMetrics qt = arangoDB.metrics().getQueueTime(); - double avg = qt.getAvg(); - QueueTimeSample[] values = qt.getValues(); - if (isAtLeastVersion(3, 9)) { - assertThat(values).hasSize(20); - for (int i = 0; i < values.length; i++) { - assertThat(values[i].value).isNotNegative(); - if (i > 0) { - assertThat(values[i].timestamp).isGreaterThanOrEqualTo(values[i - 1].timestamp); - } - } - - if (avg < 0.0) { - System.err.println("avg < 0: " + avg); - System.err.println("got values:"); - for (QueueTimeSample v : values) { - System.err.println(v.value); - } - } - assertThat(avg).isPositive(); - } else { - assertThat(avg).isEqualTo(0.0); - assertThat(values).isEmpty(); - } - - } -} diff --git a/shaded-integration-tests/src/test/native/java/com/arangodb/ArangoDatabaseTest.java b/shaded-integration-tests/src/test/native/java/com/arangodb/ArangoDatabaseTest.java deleted file mode 100644 index bfd9924cd..000000000 --- a/shaded-integration-tests/src/test/native/java/com/arangodb/ArangoDatabaseTest.java +++ /dev/null @@ -1,1413 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb; - -import com.arangodb.entity.*; -import com.arangodb.entity.AqlExecutionExplainEntity.ExecutionPlan; -import com.arangodb.entity.QueryCachePropertiesEntity.CacheMode; -import com.arangodb.model.*; -import com.arangodb.util.MapBuilder; -import com.arangodb.util.RawBytes; -import com.arangodb.util.RawJson; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.node.ArrayNode; -import com.fasterxml.jackson.databind.node.JsonNodeFactory; -import com.fasterxml.jackson.databind.node.ObjectNode; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.MethodSource; - -import java.io.IOException; -import java.util.*; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.Future; -import java.util.concurrent.atomic.AtomicInteger; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.catchThrowable; -import static org.junit.jupiter.api.Assertions.fail; -import static org.junit.jupiter.api.Assumptions.assumeTrue; - - -/** - * @author Mark Vollmary - * @author Michele Rastelli - */ -class ArangoDatabaseTest extends BaseJunit5 { - - private static final String CNAME1 = "ArangoDatabaseTest_collection_1"; - private static final String CNAME2 = "ArangoDatabaseTest_collection_2"; - private static final String ENAMES = "ArangoDatabaseTest_edge_collection"; - - @BeforeAll - static void init() { - BaseJunit5.initDB(); - BaseJunit5.initCollections(CNAME1, CNAME2); - BaseJunit5.initEdgeCollections(ENAMES); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void getVersion(ArangoDatabase db) { - final ArangoDBVersion version = db.getVersion(); - assertThat(version).isNotNull(); - assertThat(version.getServer()).isNotNull(); - assertThat(version.getVersion()).isNotNull(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void getEngine(ArangoDatabase db) { - final ArangoDBEngine engine = db.getEngine(); - assertThat(engine).isNotNull(); - assertThat(engine.getName()).isNotNull(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("arangos") - void exists(ArangoDB arangoDB) { - assertThat(arangoDB.db(TEST_DB).exists()).isTrue(); - assertThat(arangoDB.db(DbName.of("no")).exists()).isFalse(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void getAccessibleDatabases(ArangoDatabase db) { - final Collection dbs = db.getAccessibleDatabases(); - assertThat(dbs).contains("_system"); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void createCollection(ArangoDatabase db) { - String name = "collection-" + rnd(); - final CollectionEntity result = db.createCollection(name, null); - assertThat(result).isNotNull(); - assertThat(result.getId()).isNotNull(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void createCollectionWithReplicationFactor(ArangoDatabase db) { - assumeTrue(isCluster()); - String name = "collection-" + rnd(); - final CollectionEntity result = db - .createCollection(name, new CollectionCreateOptions().replicationFactor(2)); - assertThat(result).isNotNull(); - assertThat(result.getId()).isNotNull(); - CollectionPropertiesEntity props = db.collection(name).getProperties(); - assertThat(props.getReplicationFactor().getValue()).isEqualTo(2); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void createCollectionWithWriteConcern(ArangoDatabase db) { - assumeTrue(isAtLeastVersion(3, 5)); - assumeTrue(isCluster()); - - String name = "collection-" + rnd(); - final CollectionEntity result = db.createCollection(name, - new CollectionCreateOptions().replicationFactor(2).writeConcern(2)); - assertThat(result).isNotNull(); - assertThat(result.getId()).isNotNull(); - CollectionPropertiesEntity props = db.collection(name).getProperties(); - assertThat(props.getReplicationFactor().getValue()).isEqualTo(2); - assertThat(props.getWriteConcern()).isEqualTo(2); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void createSatelliteCollection(ArangoDatabase db) { - assumeTrue(isEnterprise()); - assumeTrue(isCluster()); - - String name = "collection-" + rnd(); - final CollectionEntity result = db - .createCollection(name, new CollectionCreateOptions().replicationFactor(ReplicationFactor.ofSatellite())); - - assertThat(result).isNotNull(); - assertThat(result.getId()).isNotNull(); - CollectionPropertiesEntity props = db.collection(name).getProperties(); - assertThat(props.getReplicationFactor()).isEqualTo(ReplicationFactor.ofSatellite()); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void createCollectionWithNumberOfShards(ArangoDatabase db) { - assumeTrue(isCluster()); - String name = "collection-" + rnd(); - final CollectionEntity result = db - .createCollection(name, new CollectionCreateOptions().numberOfShards(2)); - - assertThat(result).isNotNull(); - assertThat(result.getId()).isNotNull(); - CollectionPropertiesEntity props = db.collection(name).getProperties(); - assertThat(props.getNumberOfShards()).isEqualTo(2); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void createCollectionWithShardingStrategys(ArangoDatabase db) { - assumeTrue(isAtLeastVersion(3, 4)); - assumeTrue(isCluster()); - - String name = "collection-" + rnd(); - final CollectionEntity result = db.createCollection(name, new CollectionCreateOptions() - .shardingStrategy(ShardingStrategy.COMMUNITY_COMPAT.getInternalName())); - - assertThat(result).isNotNull(); - assertThat(result.getId()).isNotNull(); - CollectionPropertiesEntity props = db.collection(name).getProperties(); - assertThat(props.getShardingStrategy()).isEqualTo(ShardingStrategy.COMMUNITY_COMPAT.getInternalName()); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void createCollectionWithSmartJoinAttribute(ArangoDatabase db) { - assumeTrue(isAtLeastVersion(3, 5)); - assumeTrue(isEnterprise()); - assumeTrue(isCluster()); - - String name = "collection-" + rnd(); - final CollectionEntity result = db.createCollection(name, - new CollectionCreateOptions().smartJoinAttribute("test123").shardKeys("_key:")); - assertThat(result).isNotNull(); - assertThat(result.getId()).isNotNull(); - assertThat(db.collection(name).getProperties().getSmartJoinAttribute()).isEqualTo("test123"); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void createCollectionWithSmartJoinAttributeWrong(ArangoDatabase db) { - assumeTrue(isAtLeastVersion(3, 5)); - assumeTrue(isEnterprise()); - assumeTrue(isCluster()); - - String name = "collection-" + rnd(); - - try { - db.createCollection(name, new CollectionCreateOptions().smartJoinAttribute("test123")); - } catch (ArangoDBException e) { - assertThat(e.getErrorNum()).isEqualTo(4006); - assertThat(e.getResponseCode()).isEqualTo(400); - } - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void createCollectionWithNumberOfShardsAndShardKey(ArangoDatabase db) { - assumeTrue(isCluster()); - - String name = "collection-" + rnd(); - final CollectionEntity result = db - .createCollection(name, new CollectionCreateOptions().numberOfShards(2).shardKeys("a")); - assertThat(result).isNotNull(); - assertThat(result.getId()).isNotNull(); - final CollectionPropertiesEntity properties = db.collection(name).getProperties(); - assertThat(properties.getNumberOfShards()).isEqualTo(2); - assertThat(properties.getShardKeys()).hasSize(1); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void createCollectionWithNumberOfShardsAndShardKeys(ArangoDatabase db) { - assumeTrue(isCluster()); - String name = "collection-" + rnd(); - final CollectionEntity result = db.createCollection(name, - new CollectionCreateOptions().numberOfShards(2).shardKeys("a", "b")); - assertThat(result).isNotNull(); - assertThat(result.getId()).isNotNull(); - final CollectionPropertiesEntity properties = db.collection(name).getProperties(); - assertThat(properties.getNumberOfShards()).isEqualTo(2); - assertThat(properties.getShardKeys()).hasSize(2); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void createCollectionWithDistributeShardsLike(ArangoDatabase db) { - assumeTrue(isEnterprise()); - assumeTrue(isCluster()); - - final Integer numberOfShards = 3; - - String name1 = "collection-" + rnd(); - String name2 = "collection-" + rnd(); - db.createCollection(name1, new CollectionCreateOptions().numberOfShards(numberOfShards)); - db.createCollection(name2, new CollectionCreateOptions().distributeShardsLike(name1)); - - assertThat(db.collection(name1).getProperties().getNumberOfShards()).isEqualTo(numberOfShards); - assertThat(db.collection(name2).getProperties().getNumberOfShards()).isEqualTo(numberOfShards); - } - - private void createCollectionWithKeyType(ArangoDatabase db, KeyType keyType) { - String name = "collection-" + rnd(); - db.createCollection(name, new CollectionCreateOptions().keyOptions( - false, - keyType, - null, - null - )); - assertThat(db.collection(name).getProperties().getKeyOptions().getType()).isEqualTo(keyType); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void createCollectionWithKeyTypeAutoincrement(ArangoDatabase db) { - assumeTrue(isSingleServer()); - createCollectionWithKeyType(db, KeyType.autoincrement); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void createCollectionWithKeyTypePadded(ArangoDatabase db) { - assumeTrue(isAtLeastVersion(3, 4)); - createCollectionWithKeyType(db, KeyType.padded); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void createCollectionWithKeyTypeTraditional(ArangoDatabase db) { - createCollectionWithKeyType(db, KeyType.traditional); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void createCollectionWithKeyTypeUuid(ArangoDatabase db) { - assumeTrue(isAtLeastVersion(3, 4)); - createCollectionWithKeyType(db, KeyType.uuid); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void createCollectionWithJsonSchema(ArangoDatabase db) { - assumeTrue(isAtLeastVersion(3, 7)); - String name = "collection-" + rnd(); - String rule = ("{ " + - " \"properties\": {" + - " \"number\": {" + - " \"type\": \"number\"" + - " }" + - " }" + - " }") - .replaceAll("\\s", ""); - String message = "The document has problems!"; - - final CollectionEntity result = db - .createCollection(name, new CollectionCreateOptions() - .schema( - new CollectionSchema() - .setLevel(CollectionSchema.Level.NEW) - .setMessage(message) - .setRule(rule) - ) - ); - assertThat(result.getSchema().getLevel()).isEqualTo(CollectionSchema.Level.NEW); - assertThat(result.getSchema().getRule()).isEqualTo(rule); - assertThat(result.getSchema().getMessage()).isEqualTo(message); - - CollectionPropertiesEntity props = db.collection(name).getProperties(); - assertThat(props.getSchema().getLevel()).isEqualTo(CollectionSchema.Level.NEW); - assertThat(props.getSchema().getRule()).isEqualTo(rule); - assertThat(props.getSchema().getMessage()).isEqualTo(message); - - BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); - doc.addAttribute("number", 33); - db.collection(name).insertDocument(doc); - - BaseDocument wrongDoc = new BaseDocument(UUID.randomUUID().toString()); - wrongDoc.addAttribute("number", "notANumber"); - Throwable thrown = catchThrowable(() -> db.collection(name).insertDocument(wrongDoc)); - assertThat(thrown).isInstanceOf(ArangoDBException.class); - ArangoDBException e = (ArangoDBException) thrown; - - assertThat(e).hasMessageContaining(message); - assertThat(e.getResponseCode()).isEqualTo(400); - assertThat(e.getErrorNum()).isEqualTo(1620); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void createCollectionWithComputedFields(ArangoDatabase db) { - assumeTrue(isAtLeastVersion(3, 10)); - String cName = "collection-" + rnd(); - ComputedValue cv = new ComputedValue() - .name("foo") - .expression("RETURN 11") - .overwrite(false) - .computeOn(ComputedValue.ComputeOn.insert) - .keepNull(false) - .failOnWarning(true); - - final CollectionEntity result = db.createCollection(cName, new CollectionCreateOptions().computedValues(cv)); - - assertThat(result).isNotNull(); - assertThat(result.getComputedValues()) - .hasSize(1) - .contains(cv); - - ComputedValue cv2 = new ComputedValue() - .name("bar") - .expression("RETURN 22") - .overwrite(true) - .computeOn(ComputedValue.ComputeOn.update, ComputedValue.ComputeOn.replace) - .keepNull(true) - .failOnWarning(false); - - db.collection(cName).changeProperties(new CollectionPropertiesOptions().computedValues(cv2)); - - CollectionPropertiesEntity props = db.collection(cName).getProperties(); - assertThat(props.getComputedValues()) - .hasSize(1) - .contains(cv2); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void deleteCollection(ArangoDatabase db) { - String name = "collection-" + rnd(); - db.createCollection(name, null); - db.collection(name).drop(); - Throwable thrown = catchThrowable(() -> db.collection(name).getInfo()); - assertThat(thrown).isInstanceOf(ArangoDBException.class); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void deleteSystemCollection(ArangoDatabase db) { - final String name = "_system_test"; - db.createCollection(name, new CollectionCreateOptions().isSystem(true)); - db.collection(name).drop(true); - Throwable thrown = catchThrowable(() -> db.collection(name).getInfo()); - assertThat(thrown) - .isInstanceOf(ArangoDBException.class) - .extracting(it -> ((ArangoDBException) it).getResponseCode()) - .isEqualTo(404); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void deleteSystemCollectionFail(ArangoDatabase db) { - final String name = "_system_test"; - ArangoCollection collection = db.collection(name); - if (collection.exists()) - collection.drop(true); - - db.createCollection(name, new CollectionCreateOptions().isSystem(true)); - try { - collection.drop(); - fail(); - } catch (final ArangoDBException e) { - assertThat(e.getResponseCode()).isEqualTo(403); - } - collection.drop(true); - try { - collection.getInfo(); - fail(); - } catch (final ArangoDBException e) { - assertThat(e.getResponseCode()).isEqualTo(404); - } - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void getIndex(ArangoDatabase db) { - final Collection fields = Collections.singletonList("field-" + rnd()); - final IndexEntity createResult = db.collection(CNAME1).ensureHashIndex(fields, null); - final IndexEntity readResult = db.getIndex(createResult.getId()); - assertThat(readResult.getId()).isEqualTo(createResult.getId()); - assertThat(readResult.getType()).isEqualTo(createResult.getType()); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void deleteIndex(ArangoDatabase db) { - final Collection fields = Collections.singletonList("field-" + rnd()); - final IndexEntity createResult = db.collection(CNAME1).ensureHashIndex(fields, null); - final String id = db.deleteIndex(createResult.getId()); - assertThat(id).isEqualTo(createResult.getId()); - try { - db.getIndex(id); - fail(); - } catch (final ArangoDBException e) { - assertThat(e.getResponseCode()).isEqualTo(404); - } - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void getCollections(ArangoDatabase db) { - final Collection collections = db.getCollections(null); - long count = collections.stream().map(CollectionEntity::getName).filter(it -> it.equals(CNAME1)).count(); - assertThat(count).isEqualTo(1L); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void getCollectionsExcludeSystem(ArangoDatabase db) { - final CollectionsReadOptions options = new CollectionsReadOptions().excludeSystem(true); - final Collection nonSystemCollections = db.getCollections(options); - final Collection allCollections = db.getCollections(null); - assertThat(allCollections).hasSizeGreaterThan(nonSystemCollections.size()); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("arangos") - void grantAccess(ArangoDB arangoDB) { - String user = "user-" + rnd(); - arangoDB.createUser(user, "1234", null); - arangoDB.db(TEST_DB).grantAccess(user); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("arangos") - void grantAccessRW(ArangoDB arangoDB) { - String user = "user-" + rnd(); - arangoDB.createUser(user, "1234", null); - arangoDB.db(TEST_DB).grantAccess(user, Permissions.RW); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("arangos") - void grantAccessRO(ArangoDB arangoDB) { - String user = "user-" + rnd(); - arangoDB.createUser(user, "1234", null); - arangoDB.db(TEST_DB).grantAccess(user, Permissions.RO); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("arangos") - void grantAccessNONE(ArangoDB arangoDB) { - String user = "user-" + rnd(); - arangoDB.createUser(user, "1234", null); - arangoDB.db(TEST_DB).grantAccess(user, Permissions.NONE); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void grantAccessUserNotFound(ArangoDatabase db) { - String user = "user-" + rnd(); - Throwable thrown = catchThrowable(() -> db.grantAccess(user, Permissions.RW)); - assertThat(thrown).isInstanceOf(ArangoDBException.class); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("arangos") - void revokeAccess(ArangoDB arangoDB) { - String user = "user-" + rnd(); - arangoDB.createUser(user, "1234", null); - arangoDB.db(TEST_DB).revokeAccess(user); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void revokeAccessUserNotFound(ArangoDatabase db) { - String user = "user-" + rnd(); - Throwable thrown = catchThrowable(() -> db.revokeAccess(user)); - assertThat(thrown).isInstanceOf(ArangoDBException.class); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("arangos") - void resetAccess(ArangoDB arangoDB) { - String user = "user-" + rnd(); - arangoDB.createUser(user, "1234", null); - arangoDB.db(TEST_DB).resetAccess(user); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void resetAccessUserNotFound(ArangoDatabase db) { - String user = "user-" + rnd(); - Throwable thrown = catchThrowable(() -> db.resetAccess(user)); - assertThat(thrown).isInstanceOf(ArangoDBException.class); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("arangos") - void grantDefaultCollectionAccess(ArangoDB arangoDB) { - String user = "user-" + rnd(); - arangoDB.createUser(user, "1234"); - arangoDB.db(TEST_DB).grantDefaultCollectionAccess(user, Permissions.RW); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void getPermissions(ArangoDatabase db) { - assertThat(db.getPermissions("root")).isEqualTo(Permissions.RW); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void query(ArangoDatabase db) { - for (int i = 0; i < 10; i++) { - db.collection(CNAME1).insertDocument(new BaseDocument(), null); - } - final ArangoCursor cursor = db.query("for i in " + CNAME1 + " return i._id", null, null, String.class); - assertThat((Object) cursor).isNotNull(); - for (int i = 0; i < 10; i++, cursor.next()) { - assertThat((Iterator) cursor).hasNext(); - } - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void queryWithNullBindVar(ArangoDatabase db) { - final ArangoCursor cursor = db.query("return @foo", Collections.singletonMap("foo", null), null, - Object.class); - assertThat(cursor.hasNext()).isTrue(); - assertThat(cursor.next()).isNull(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void queryForEach(ArangoDatabase db) { - for (int i = 0; i < 10; i++) { - db.collection(CNAME1).insertDocument(new BaseDocument(), null); - } - final ArangoCursor cursor = db.query("for i in " + CNAME1 + " return i._id", null, null, String.class); - assertThat((Object) cursor).isNotNull(); - - int i = 0; - while (cursor.hasNext()) { - cursor.next(); - i++; - } - assertThat(i).isGreaterThanOrEqualTo(10); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void queryWithCount(ArangoDatabase db) { - for (int i = 0; i < 10; i++) { - db.collection(CNAME1).insertDocument(new BaseDocument(), null); - } - - final ArangoCursor cursor = db - .query("for i in " + CNAME1 + " Limit 6 return i._id", null, new AqlQueryOptions().count(true), - String.class); - assertThat((Object) cursor).isNotNull(); - for (int i = 1; i <= 6; i++, cursor.next()) { - assertThat(cursor.hasNext()).isTrue(); - } - assertThat(cursor.getCount()).isEqualTo(6); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void queryWithLimitAndFullCount(ArangoDatabase db) { - for (int i = 0; i < 10; i++) { - db.collection(CNAME1).insertDocument(new BaseDocument(), null); - } - - final ArangoCursor cursor = db - .query("for i in " + CNAME1 + " Limit 5 return i._id", null, new AqlQueryOptions().fullCount(true), - String.class); - assertThat((Object) cursor).isNotNull(); - for (int i = 0; i < 5; i++, cursor.next()) { - assertThat((Iterator) cursor).hasNext(); - } - assertThat(cursor.getStats()).isNotNull(); - assertThat(((Number) cursor.getStats().get("fullCount")).intValue()) - .isGreaterThanOrEqualTo(10); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void queryWithBatchSize(ArangoDatabase db) { - for (int i = 0; i < 10; i++) { - db.collection(CNAME1).insertDocument(new BaseDocument(), null); - } - - final ArangoCursor cursor = db - .query("for i in " + CNAME1 + " return i._id", null, new AqlQueryOptions().batchSize(5).count(true), - String.class); - - assertThat((Object) cursor).isNotNull(); - for (int i = 0; i < 10; i++, cursor.next()) { - assertThat((Iterator) cursor).hasNext(); - } - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void queryIterateWithBatchSize(ArangoDatabase db) { - for (int i = 0; i < 10; i++) { - db.collection(CNAME1).insertDocument(new BaseDocument(), null); - } - - final ArangoCursor cursor = db - .query("for i in " + CNAME1 + " return i._id", null, new AqlQueryOptions().batchSize(5).count(true), - String.class); - - assertThat((Object) cursor).isNotNull(); - final AtomicInteger i = new AtomicInteger(0); - for (; cursor.hasNext(); cursor.next()) { - i.incrementAndGet(); - } - assertThat(i.get()).isGreaterThanOrEqualTo(10); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void queryWithTTL(ArangoDatabase db) throws InterruptedException { - // set TTL to 1 seconds and get the second batch after 2 seconds! - final int ttl = 1; - final int wait = 2; - for (int i = 0; i < 10; i++) { - db.collection(CNAME1).insertDocument(new BaseDocument(), null); - } - - final ArangoCursor cursor = db - .query("for i in " + CNAME1 + " return i._id", null, new AqlQueryOptions().batchSize(5).ttl(ttl), - String.class); - - assertThat((Iterable) cursor).isNotNull(); - - try { - for (int i = 0; i < 10; i++, cursor.next()) { - assertThat(cursor.hasNext()).isTrue(); - if (i == 1) { - Thread.sleep(wait * 1000); - } - } - fail("this should fail"); - } catch (final ArangoDBException ex) { - assertThat(ex.getMessage()).isEqualTo("Response: 404, Error: 1600 - cursor not found"); - } - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void changeQueryCache(ArangoDatabase db) { - QueryCachePropertiesEntity properties = db.getQueryCacheProperties(); - assertThat(properties).isNotNull(); - assertThat(properties.getMode()).isEqualTo(CacheMode.off); - assertThat(properties.getMaxResults()).isPositive(); - - properties.setMode(CacheMode.on); - properties = db.setQueryCacheProperties(properties); - assertThat(properties).isNotNull(); - assertThat(properties.getMode()).isEqualTo(CacheMode.on); - - properties = db.getQueryCacheProperties(); - assertThat(properties.getMode()).isEqualTo(CacheMode.on); - - final QueryCachePropertiesEntity properties2 = new QueryCachePropertiesEntity(); - properties2.setMode(CacheMode.off); - db.setQueryCacheProperties(properties2); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void queryWithCache(ArangoDatabase db) { - assumeTrue(isSingleServer()); - for (int i = 0; i < 10; i++) { - db.collection(CNAME1).insertDocument(new BaseDocument(), null); - } - - final QueryCachePropertiesEntity properties = new QueryCachePropertiesEntity(); - properties.setMode(CacheMode.on); - db.setQueryCacheProperties(properties); - - final ArangoCursor cursor = db - .query("FOR t IN " + CNAME1 + " FILTER t.age >= 10 SORT t.age RETURN t._id", null, - new AqlQueryOptions().cache(true), String.class); - - assertThat((Object) cursor).isNotNull(); - assertThat(cursor.isCached()).isFalse(); - - final ArangoCursor cachedCursor = db - .query("FOR t IN " + CNAME1 + " FILTER t.age >= 10 SORT t.age RETURN t._id", null, - new AqlQueryOptions().cache(true), String.class); - - assertThat((Object) cachedCursor).isNotNull(); - assertThat(cachedCursor.isCached()).isTrue(); - - final QueryCachePropertiesEntity properties2 = new QueryCachePropertiesEntity(); - properties2.setMode(CacheMode.off); - db.setQueryCacheProperties(properties2); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void queryWithMemoryLimit(ArangoDatabase db) { - Throwable thrown = catchThrowable(() -> db.query("RETURN 1..100000", null, - new AqlQueryOptions().memoryLimit(32 * 1024L), String.class)); - assertThat(thrown).isInstanceOf(ArangoDBException.class); - assertThat(((ArangoDBException) thrown).getErrorNum()).isEqualTo(32); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void queryWithFailOnWarningTrue(ArangoDatabase db) { - Throwable thrown = catchThrowable(() -> db.query("RETURN 1 / 0", null, - new AqlQueryOptions().failOnWarning(true), String.class)); - assertThat(thrown).isInstanceOf(ArangoDBException.class); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void queryWithFailOnWarningFalse(ArangoDatabase db) { - final ArangoCursor cursor = db - .query("RETURN 1 / 0", null, new AqlQueryOptions().failOnWarning(false), String.class); - assertThat(cursor.next()).isNull(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void queryWithTimeout(ArangoDatabase db) { - assumeTrue(isAtLeastVersion(3, 6)); - Throwable thrown = catchThrowable(() -> db.query("RETURN SLEEP(1)", null, - new AqlQueryOptions().maxRuntime(0.1), String.class).next()); - assertThat(thrown).isInstanceOf(ArangoDBException.class); - assertThat(((ArangoDBException) thrown).getResponseCode()).isEqualTo(410); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void queryWithMaxWarningCount(ArangoDatabase db) { - final ArangoCursor cursorWithWarnings = db - .query("RETURN 1 / 0", null, new AqlQueryOptions(), String.class); - assertThat(cursorWithWarnings.getWarnings()).hasSize(1); - final ArangoCursor cursorWithLimitedWarnings = db - .query("RETURN 1 / 0", null, new AqlQueryOptions().maxWarningCount(0L), String.class); - final Collection warnings = cursorWithLimitedWarnings.getWarnings(); - assertThat(warnings).isNullOrEmpty(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void queryCursor(ArangoDatabase db) { - final int numbDocs = 10; - for (int i = 0; i < numbDocs; i++) { - db.collection(CNAME1).insertDocument(new BaseDocument(), null); - } - - final int batchSize = 5; - final ArangoCursor cursor = db.query("for i in " + CNAME1 + " return i._id", null, - new AqlQueryOptions().batchSize(batchSize).count(true), String.class); - assertThat((Object) cursor).isNotNull(); - assertThat(cursor.getCount()).isGreaterThanOrEqualTo(numbDocs); - - final ArangoCursor cursor2 = db.cursor(cursor.getId(), String.class); - assertThat((Object) cursor2).isNotNull(); - assertThat(cursor2.getCount()).isGreaterThanOrEqualTo(numbDocs); - assertThat((Iterator) cursor2).hasNext(); - - for (int i = 0; i < batchSize; i++, cursor.next()) { - assertThat((Iterator) cursor).hasNext(); - } - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void changeQueryTrackingProperties(ArangoDatabase db) { - try { - QueryTrackingPropertiesEntity properties = db.getQueryTrackingProperties(); - assertThat(properties).isNotNull(); - assertThat(properties.getEnabled()).isTrue(); - assertThat(properties.getTrackSlowQueries()).isTrue(); - assertThat(properties.getMaxQueryStringLength()).isPositive(); - assertThat(properties.getMaxSlowQueries()).isPositive(); - assertThat(properties.getSlowQueryThreshold()).isPositive(); - properties.setEnabled(false); - properties = db.setQueryTrackingProperties(properties); - assertThat(properties).isNotNull(); - assertThat(properties.getEnabled()).isFalse(); - properties = db.getQueryTrackingProperties(); - assertThat(properties.getEnabled()).isFalse(); - } finally { - final QueryTrackingPropertiesEntity properties = new QueryTrackingPropertiesEntity(); - properties.setEnabled(true); - db.setQueryTrackingProperties(properties); - } - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void queryWithBindVars(ArangoDatabase db) { - for (int i = 0; i < 10; i++) { - final BaseDocument baseDocument = new BaseDocument(UUID.randomUUID().toString()); - baseDocument.addAttribute("age", 20 + i); - db.collection(CNAME1).insertDocument(baseDocument, null); - } - final Map bindVars = new HashMap<>(); - bindVars.put("@coll", CNAME1); - bindVars.put("age", 25); - - final ArangoCursor cursor = db - .query("FOR t IN @@coll FILTER t.age >= @age SORT t.age RETURN t._id", bindVars, null, - String.class); - - assertThat((Object) cursor).isNotNull(); - - for (int i = 0; i < 5; i++, cursor.next()) { - assertThat((Iterator) cursor).hasNext(); - } - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void queryWithRawBindVars(ArangoDatabase db) { - final Map bindVars = new HashMap<>(); - bindVars.put("foo", RawJson.of("\"fooValue\"")); - bindVars.put("bar", RawBytes.of(db.getSerde().serializeUserData(11))); - - final JsonNode res = db.query("RETURN {foo: @foo, bar: @bar}", bindVars, null, JsonNode.class).next(); - - assertThat(res.get("foo").textValue()).isEqualTo("fooValue"); - assertThat(res.get("bar").intValue()).isEqualTo(11); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("arangos") - void queryWithWarning(ArangoDB arangoDB) { - final ArangoCursor cursor = arangoDB.db().query("return 1/0", null, null, String.class); - - assertThat((Object) cursor).isNotNull(); - assertThat(cursor.getWarnings()).isNotNull(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void queryStream(ArangoDatabase db) { - if (isAtLeastVersion(3, 4)) { - final ArangoCursor cursor = db - .query("FOR i IN 1..2 RETURN i", null, new AqlQueryOptions().stream(true).count(true), - Void.class); - assertThat((Object) cursor).isNotNull(); - assertThat(cursor.getCount()).isNull(); - } - } - - @ParameterizedTest(name = "{index}") - @MethodSource("arangos") - void queryClose(ArangoDB arangoDB) throws IOException { - final ArangoCursor cursor = arangoDB.db() - .query("for i in 1..2 return i", null, new AqlQueryOptions().batchSize(1), String.class); - cursor.close(); - AtomicInteger count = new AtomicInteger(); - Throwable thrown = catchThrowable(() -> { - while (cursor.hasNext()) { - cursor.next(); - count.incrementAndGet(); - } - }); - - assertThat(thrown).isInstanceOf(ArangoDBException.class); - assertThat(count).hasValue(1); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void queryNoResults(ArangoDatabase db) throws IOException { - final ArangoCursor cursor = db - .query("FOR i IN @@col RETURN i", new MapBuilder().put("@col", CNAME1).get(), null, - BaseDocument.class); - cursor.close(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void queryWithNullBindParam(ArangoDatabase db) throws IOException { - final ArangoCursor cursor = db.query("FOR i IN @@col FILTER i.test == @test RETURN i", - new MapBuilder().put("@col", CNAME1).put("test", null).get(), null, BaseDocument.class); - cursor.close(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void queryAllowDirtyRead(ArangoDatabase db) throws IOException { - final ArangoCursor cursor = db.query("FOR i IN @@col FILTER i.test == @test RETURN i", - new MapBuilder().put("@col", CNAME1).put("test", null).get(), - new AqlQueryOptions().allowDirtyRead(true), BaseDocument.class); - if (isAtLeastVersion(3, 10)) { - assertThat(cursor.isPotentialDirtyRead()).isTrue(); - } - cursor.close(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void explainQuery(ArangoDatabase db) { - final AqlExecutionExplainEntity explain = db.explainQuery("for i in 1..1 return i", null, null); - assertThat(explain).isNotNull(); - assertThat(explain.getPlan()).isNotNull(); - assertThat(explain.getPlans()).isNull(); - final ExecutionPlan plan = explain.getPlan(); - assertThat(plan.getCollections()).isEmpty(); - assertThat(plan.getEstimatedCost()).isPositive(); - assertThat(plan.getEstimatedNrItems()).isPositive(); - assertThat(plan.getVariables()).hasSize(2); - assertThat(plan.getNodes()).isNotEmpty(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void explainQueryWithBindVars(ArangoDatabase db) { - final AqlExecutionExplainEntity explain = db.explainQuery("for i in 1..1 return @value", - Collections.singletonMap("value", 11), null); - assertThat(explain).isNotNull(); - assertThat(explain.getPlan()).isNotNull(); - assertThat(explain.getPlans()).isNull(); - final ExecutionPlan plan = explain.getPlan(); - assertThat(plan.getCollections()).isEmpty(); - assertThat(plan.getEstimatedCost()).isPositive(); - assertThat(plan.getEstimatedNrItems()).isPositive(); - assertThat(plan.getVariables()).hasSize(3); - assertThat(plan.getNodes()).isNotEmpty(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void explainQueryWithIndexNode(ArangoDatabase db) { - ArangoCollection character = db.collection("got_characters"); - ArangoCollection actor = db.collection("got_actors"); - - if (!character.exists()) - character.create(); - - if (!actor.exists()) - actor.create(); - - String query = "" + - "FOR `character` IN `got_characters` " + - " FOR `actor` IN `got_actors` " + - " FILTER `character`.`actor` == `actor`.`_id` " + - " RETURN `character`"; - - final ExecutionPlan plan = db.explainQuery(query, null, null).getPlan(); - plan.getNodes().stream() - .filter(it -> "IndexNode".equals(it.getType())) - .flatMap(it -> it.getIndexes().stream()) - .forEach(it -> { - assertThat(it.getType()).isEqualTo(IndexType.primary); - assertThat(it.getFields()).contains("_key"); - }); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void parseQuery(ArangoDatabase db) { - final AqlParseEntity parse = db.parseQuery("for i in 1..1 return i"); - assertThat(parse).isNotNull(); - assertThat(parse.getBindVars()).isEmpty(); - assertThat(parse.getCollections()).isEmpty(); - assertThat(parse.getAst()).hasSize(1); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void getCurrentlyRunningQueries(ArangoDatabase db) throws InterruptedException { - String query = "return sleep(1)"; - Thread t = new Thread(() -> db.query(query, null, null, Void.class)); - t.start(); - Thread.sleep(300); - final Collection currentlyRunningQueries = db.getCurrentlyRunningQueries(); - assertThat(currentlyRunningQueries).hasSize(1); - final QueryEntity queryEntity = currentlyRunningQueries.iterator().next(); - assertThat(queryEntity.getQuery()).isEqualTo(query); - assertThat(queryEntity.getState()).isEqualTo(QueryExecutionState.EXECUTING); - t.join(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void killQuery(ArangoDatabase db) throws InterruptedException, ExecutionException { - ExecutorService es = Executors.newSingleThreadExecutor(); - Future future = es.submit(() -> { - try { - db.query("return sleep(5)", null, null, Void.class); - fail(); - } catch (ArangoDBException e) { - assertThat(e.getResponseCode()).isEqualTo(410); - assertThat(e.getErrorNum()).isEqualTo(1500); - assertThat(e.getErrorMessage()).contains("query killed"); - } - }); - Thread.sleep(500); - - Collection currentlyRunningQueries = db.getCurrentlyRunningQueries(); - assertThat(currentlyRunningQueries).hasSize(1); - QueryEntity queryEntity = currentlyRunningQueries.iterator().next(); - assertThat(queryEntity.getState()).isEqualTo(QueryExecutionState.EXECUTING); - db.killQuery(queryEntity.getId()); - - db.getCurrentlyRunningQueries().forEach(q -> - assertThat(q.getState()).isEqualTo(QueryExecutionState.KILLED) - ); - - future.get(); - es.shutdown(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void getAndClearSlowQueries(ArangoDatabase db) { - db.clearSlowQueries(); - - final QueryTrackingPropertiesEntity properties = db.getQueryTrackingProperties(); - final Long slowQueryThreshold = properties.getSlowQueryThreshold(); - properties.setSlowQueryThreshold(1L); - db.setQueryTrackingProperties(properties); - - db.query("return sleep(1.1)", null, null, Void.class); - final Collection slowQueries = db.getSlowQueries(); - assertThat(slowQueries).hasSize(1); - final QueryEntity queryEntity = slowQueries.iterator().next(); - assertThat(queryEntity.getQuery()).isEqualTo("return sleep(1.1)"); - - db.clearSlowQueries(); - assertThat(db.getSlowQueries()).isEmpty(); - properties.setSlowQueryThreshold(slowQueryThreshold); - db.setQueryTrackingProperties(properties); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void createGetDeleteAqlFunction(ArangoDatabase db) { - final Collection aqlFunctionsInitial = db.getAqlFunctions(null); - assertThat(aqlFunctionsInitial).isEmpty(); - try { - db.createAqlFunction("myfunctions::temperature::celsiustofahrenheit", - "function (celsius) { return celsius * 1.8 + 32; }", null); - - final Collection aqlFunctions = db.getAqlFunctions(null); - assertThat(aqlFunctions).hasSizeGreaterThan(aqlFunctionsInitial.size()); - } finally { - final Integer deleteCount = db.deleteAqlFunction("myfunctions::temperature::celsiustofahrenheit", null); - // compatibility with ArangoDB < 3.4 - if (isAtLeastVersion(3, 4)) { - assertThat(deleteCount).isEqualTo(1); - } else { - assertThat(deleteCount).isNull(); - } - final Collection aqlFunctions = db.getAqlFunctions(null); - assertThat(aqlFunctions).hasSize(aqlFunctionsInitial.size()); - } - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void createGetDeleteAqlFunctionWithNamespace(ArangoDatabase db) { - final Collection aqlFunctionsInitial = db.getAqlFunctions(null); - assertThat(aqlFunctionsInitial).isEmpty(); - try { - db.createAqlFunction("myfunctions::temperature::celsiustofahrenheit1", - "function (celsius) { return celsius * 1.8 + 32; }", null); - db.createAqlFunction("myfunctions::temperature::celsiustofahrenheit2", - "function (celsius) { return celsius * 1.8 + 32; }", null); - - } finally { - final Integer deleteCount = db - .deleteAqlFunction("myfunctions::temperature", new AqlFunctionDeleteOptions().group(true)); - // compatibility with ArangoDB < 3.4 - if (isAtLeastVersion(3, 4)) { - assertThat(deleteCount).isEqualTo(2); - } else { - assertThat(deleteCount).isNull(); - } - final Collection aqlFunctions = db.getAqlFunctions(null); - assertThat(aqlFunctions).hasSize(aqlFunctionsInitial.size()); - } - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void createGraph(ArangoDatabase db) { - String name = "graph-" + rnd(); - final GraphEntity result = db.createGraph(name, null, null); - assertThat(result.getName()).isEqualTo(name); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void createGraphSatellite(ArangoDatabase db) { - assumeTrue(isAtLeastVersion(3, 7)); - assumeTrue(isCluster()); - assumeTrue(isEnterprise()); - - String name = "graph-" + rnd(); - final GraphEntity result = db.createGraph(name, null, new GraphCreateOptions().replicationFactor(ReplicationFactor.ofSatellite())); - assertThat(result.getReplicationFactor()).isEqualTo(ReplicationFactor.ofSatellite()); - - GraphEntity info = db.graph(name).getInfo(); - assertThat(info.getReplicationFactor()).isEqualTo(ReplicationFactor.ofSatellite()); - - GraphEntity graph = db.getGraphs().stream().filter(g -> name.equals(g.getName())).findFirst().get(); - assertThat(graph.getReplicationFactor()).isEqualTo(ReplicationFactor.ofSatellite()); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void createGraphReplicationFaktor(ArangoDatabase db) { - assumeTrue(isCluster()); - String name = "graph-" + rnd(); - final String edgeCollection = "edge-" + rnd(); - final String fromCollection = "from-" + rnd(); - final String toCollection = "to-" + rnd(); - final Collection edgeDefinitions = - Collections.singletonList(new EdgeDefinition().collection(edgeCollection).from(fromCollection).to(toCollection)); - final GraphEntity result = db.createGraph(name, edgeDefinitions, new GraphCreateOptions().replicationFactor(2)); - assertThat(result).isNotNull(); - for (final String collection : Arrays.asList(edgeCollection, fromCollection, toCollection)) { - final CollectionPropertiesEntity properties = db.collection(collection).getProperties(); - assertThat(properties.getReplicationFactor().getValue()).isEqualTo(2); - } - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void createGraphNumberOfShards(ArangoDatabase db) { - assumeTrue(isCluster()); - String name = "graph-" + rnd(); - final String edgeCollection = "edge-" + rnd(); - final String fromCollection = "from-" + rnd(); - final String toCollection = "to-" + rnd(); - final Collection edgeDefinitions = - Collections.singletonList(new EdgeDefinition().collection(edgeCollection).from(fromCollection).to(toCollection)); - final GraphEntity result = db - .createGraph(name, edgeDefinitions, new GraphCreateOptions().numberOfShards(2)); - assertThat(result).isNotNull(); - for (final String collection : Arrays.asList(edgeCollection, fromCollection, toCollection)) { - final CollectionPropertiesEntity properties = db.collection(collection).getProperties(); - assertThat(properties.getNumberOfShards()).isEqualTo(2); - } - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void getGraphs(ArangoDatabase db) { - String name = "graph-" + rnd(); - db.createGraph(name, null, null); - final Collection graphs = db.getGraphs(); - assertThat(graphs).hasSizeGreaterThanOrEqualTo(1); - long count = graphs.stream().map(GraphEntity::getName).filter(name::equals).count(); - assertThat(count).isEqualTo(1L); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void transactionString(ArangoDatabase db) { - final TransactionOptions options = new TransactionOptions().params("test"); - final RawJson result = db.transaction("function (params) {return params;}", RawJson.class, options); - assertThat(result.getValue()).isEqualTo("\"test\""); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void transactionNumber(ArangoDatabase db) { - final TransactionOptions options = new TransactionOptions().params(5); - final Integer result = db.transaction("function (params) {return params;}", Integer.class, options); - assertThat(result).isEqualTo(5); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void transactionVPack(ArangoDatabase db) { - final TransactionOptions options = new TransactionOptions().params(JsonNodeFactory.instance.textNode("test")); - final JsonNode result = db.transaction("function (params) {return params;}", JsonNode.class, options); - assertThat(result.isTextual()).isTrue(); - assertThat(result.asText()).isEqualTo("test"); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void transactionJsonObject(ArangoDatabase db) { - ObjectNode params = JsonNodeFactory.instance.objectNode().put("foo", "hello").put("bar", "world"); - final TransactionOptions options = new TransactionOptions().params(params); - final RawJson result = db - .transaction("function (params) { return params['foo'] + ' ' + params['bar'];}", RawJson.class, - options); - assertThat(result.getValue()).isEqualTo("\"hello world\""); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void transactionJsonArray(ArangoDatabase db) { - ArrayNode params = JsonNodeFactory.instance.arrayNode().add("hello").add("world"); - final TransactionOptions options = new TransactionOptions().params(params); - final RawJson result = db - .transaction("function (params) { return params[0] + ' ' + params[1];}", RawJson.class, options); - assertThat(result.getValue()).isEqualTo("\"hello world\""); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void transactionMap(ArangoDatabase db) { - final Map params = new MapBuilder().put("foo", "hello").put("bar", "world").get(); - final TransactionOptions options = new TransactionOptions().params(params); - final RawJson result = db - .transaction("function (params) { return params['foo'] + ' ' + params['bar'];}", RawJson.class, - options); - assertThat(result.getValue()).isEqualTo("\"hello world\""); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void transactionArray(ArangoDatabase db) { - final String[] params = new String[]{"hello", "world"}; - final TransactionOptions options = new TransactionOptions().params(params); - final RawJson result = db - .transaction("function (params) { return params[0] + ' ' + params[1];}", RawJson.class, options); - assertThat(result.getValue()).isEqualTo("\"hello world\""); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void transactionCollection(ArangoDatabase db) { - final Collection params = new ArrayList<>(); - params.add("hello"); - params.add("world"); - final TransactionOptions options = new TransactionOptions().params(params); - final RawJson result = db - .transaction("function (params) { return params[0] + ' ' + params[1];}", RawJson.class, options); - assertThat(result.getValue()).isEqualTo("\"hello world\""); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void transactionInsertJson(ArangoDatabase db) { - String key = "key-" + rnd(); - final TransactionOptions options = new TransactionOptions().params("{\"_key\":\"" + key + "\"}") - .writeCollections(CNAME1); - db.transaction("function (params) { " - + "var db = require('internal').db;" - + "db." + CNAME1 + ".save(JSON.parse(params));" - + "}", Void.class, options); - assertThat(db.collection(CNAME1).getDocument(key, RawJson.class)).isNotNull(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void transactionExclusiveWrite(ArangoDatabase db) { - assumeTrue(isAtLeastVersion(3, 4)); - String key = "key-" + rnd(); - final TransactionOptions options = new TransactionOptions().params("{\"_key\":\"" + key + "\"}") - .exclusiveCollections(CNAME1); - db.transaction("function (params) { " - + "var db = require('internal').db;" - + "db." + CNAME1 + ".save(JSON.parse(params));" - + "}", Void.class, options); - assertThat(db.collection(CNAME1).getDocument(key, RawJson.class)).isNotNull(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void transactionEmpty(ArangoDatabase db) { - db.transaction("function () {}", Void.class, null); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void transactionAllowImplicit(ArangoDatabase db) { - final String action = "function (params) {" + "var db = require('internal').db;" - + "return {'a':db." + CNAME1 + ".all().toArray()[0], 'b':db." + CNAME2 + ".all().toArray()[0]};" - + "}"; - final TransactionOptions options = new TransactionOptions().readCollections(CNAME1); - db.transaction(action, JsonNode.class, options); - options.allowImplicit(false); - Throwable thrown = catchThrowable(() -> db.transaction(action, JsonNode.class, options)); - assertThat(thrown) - .isInstanceOf(ArangoDBException.class) - .extracting(it -> ((ArangoDBException) it).getResponseCode()) - .isEqualTo(400); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void transactionPojoReturn(ArangoDatabase db) { - final String action = "function() { return {'value':'hello world'}; }"; - final TransactionTestEntity res = db.transaction(action, TransactionTestEntity.class, new TransactionOptions()); - assertThat(res).isNotNull(); - assertThat(res.value).isEqualTo("hello world"); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void getInfo(ArangoDatabase db) { - final DatabaseEntity info = db.getInfo(); - assertThat(info).isNotNull(); - assertThat(info.getId()).isNotNull(); - assertThat(info.getName()).isEqualTo(TEST_DB.get()); - assertThat(info.getPath()).isNotNull(); - assertThat(info.getIsSystem()).isFalse(); - - if (isAtLeastVersion(3, 6) && isCluster()) { - assertThat(info.getSharding()).isNotNull(); - assertThat(info.getWriteConcern()).isNotNull(); - assertThat(info.getReplicationFactor()).isNotNull(); - } - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void getDocument(ArangoDatabase db) { - String key = "key-" + rnd(); - final BaseDocument value = new BaseDocument(key); - db.collection(CNAME1).insertDocument(value); - final BaseDocument document = db.getDocument(CNAME1 + "/" + key, BaseDocument.class); - assertThat(document).isNotNull(); - assertThat(document.getKey()).isEqualTo(key); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void shouldIncludeExceptionMessage(ArangoDatabase db) { - assumeTrue(isAtLeastVersion(3, 4)); - - final String exceptionMessage = "My error context"; - final String action = "function (params) {" + "throw '" + exceptionMessage + "';" + "}"; - try { - db.transaction(action, Void.class, null); - fail(); - } catch (final ArangoDBException e) { - assertThat(e.getErrorMessage()).isEqualTo(exceptionMessage); - } - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void getDocumentWrongId(ArangoDatabase db) { - Throwable thrown = catchThrowable(() -> db.getDocument("123", BaseDocument.class)); - assertThat(thrown).isInstanceOf(ArangoDBException.class); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void reloadRouting(ArangoDatabase db) { - db.reloadRouting(); - } - - public static class TransactionTestEntity { - private String value; - - public String getValue() { - return value; - } - - public void setValue(String value) { - this.value = value; - } - } -} diff --git a/shaded-integration-tests/src/test/native/java/com/arangodb/ArangoDocumentUtilTest.java b/shaded-integration-tests/src/test/native/java/com/arangodb/ArangoDocumentUtilTest.java deleted file mode 100644 index 224aea3cc..000000000 --- a/shaded-integration-tests/src/test/native/java/com/arangodb/ArangoDocumentUtilTest.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb; - -import com.arangodb.internal.util.DocumentUtil; -import org.junit.jupiter.api.Test; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.catchThrowable; - -/** - * @author Mark Vollmary - * @author Michele Rastelli - */ -class ArangoDocumentUtilTest { - - @Test - void validateDocumentKeyValid() { - checkDocumentKey("1test"); - checkDocumentKey("test1"); - checkDocumentKey("test-1"); - checkDocumentKey("test_1"); - checkDocumentKey("_test"); - } - - @Test - void validateDocumentKeyInvalidSlash() { - Throwable thrown = catchThrowable(() -> checkDocumentKey("test/test")); - assertThat(thrown).isInstanceOf(ArangoDBException.class); - } - - @Test - void validateDocumentKeyEmpty() { - Throwable thrown = catchThrowable(() -> checkDocumentKey("")); - assertThat(thrown).isInstanceOf(ArangoDBException.class); - } - - private void checkDocumentKey(final String key) throws ArangoDBException { - DocumentUtil.validateDocumentKey(key); - } - - @Test - void validateDocumentIdValid() { - checkDocumentId("1test/1test"); - checkDocumentId("test1/test1"); - checkDocumentId("test-1/test-1"); - checkDocumentId("test_1/test_1"); - checkDocumentId("_test/_test"); - } - - @Test - void validateDocumentIdInvalidWithoutSlash() { - Throwable thrown = catchThrowable(() -> checkDocumentId("test")); - assertThat(thrown).isInstanceOf(ArangoDBException.class); - } - - @Test - void validateDocumentIdEmpty() { - Throwable thrown = catchThrowable(() -> checkDocumentId("")); - assertThat(thrown).isInstanceOf(ArangoDBException.class); - } - - private void checkDocumentId(final String id) throws ArangoDBException { - DocumentUtil.validateDocumentId(id); - } -} diff --git a/shaded-integration-tests/src/test/native/java/com/arangodb/ArangoEdgeCollectionTest.java b/shaded-integration-tests/src/test/native/java/com/arangodb/ArangoEdgeCollectionTest.java deleted file mode 100644 index d25ed0e69..000000000 --- a/shaded-integration-tests/src/test/native/java/com/arangodb/ArangoEdgeCollectionTest.java +++ /dev/null @@ -1,445 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb; - -import com.arangodb.entity.*; -import com.arangodb.model.*; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.Arguments; -import org.junit.jupiter.params.provider.MethodSource; - -import java.util.Arrays; -import java.util.Collections; -import java.util.UUID; -import java.util.stream.Stream; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.catchThrowable; - - -/** - * @author Mark Vollmary - * @author Michele Rastelli - */ -class ArangoEdgeCollectionTest extends BaseJunit5 { - - private static final String GRAPH_NAME = "EdgeCollectionTest_graph"; - private static final String VERTEX_COLLECTION_NAME = "EdgeCollectionTest_vertex_collection"; - private static final String EDGE_COLLECTION_NAME = "EdgeCollectionTest_edge_collection"; - - private static Stream args() { - return dbsStream() - .map(db -> new Object[]{ - db.graph(GRAPH_NAME).vertexCollection(VERTEX_COLLECTION_NAME), - db.graph(GRAPH_NAME).edgeCollection(EDGE_COLLECTION_NAME) - }) - .map(Arguments::of); - } - - @BeforeAll - static void init() { - initCollections(VERTEX_COLLECTION_NAME); - initEdgeCollections(EDGE_COLLECTION_NAME); - initGraph( - GRAPH_NAME, - Collections.singletonList(new EdgeDefinition() - .collection(EDGE_COLLECTION_NAME) - .from(VERTEX_COLLECTION_NAME) - .to(VERTEX_COLLECTION_NAME) - ), - null - ); - } - - private BaseEdgeDocument createEdgeValue(ArangoVertexCollection vertices) { - final VertexEntity v1 = vertices.insertVertex(new BaseDocument()); - final VertexEntity v2 = vertices.insertVertex(new BaseDocument()); - - final BaseEdgeDocument value = new BaseEdgeDocument(); - value.setFrom(v1.getId()); - value.setTo(v2.getId()); - return value; - } - - @ParameterizedTest(name = "{index}") - @MethodSource("args") - void insertEdge(ArangoVertexCollection vertices, ArangoEdgeCollection edges) { - final BaseEdgeDocument value = createEdgeValue(vertices); - final EdgeEntity edge = edges.insertEdge(value); - assertThat(edge).isNotNull(); - final BaseEdgeDocument document = edges.getEdge(edge.getKey(), BaseEdgeDocument.class); - assertThat(document).isNotNull(); - assertThat(document.getKey()).isEqualTo(edge.getKey()); - assertThat(document.getFrom()).isNotNull(); - assertThat(document.getTo()).isNotNull(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("args") - void insertEdgeUpdateRev(ArangoVertexCollection vertices, ArangoEdgeCollection edges) { - final BaseEdgeDocument value = createEdgeValue(vertices); - final EdgeEntity edge = edges.insertEdge(value); - assertThat(value.getRevision()).isNull(); - assertThat(edge.getRev()).isNotNull(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("args") - void insertEdgeViolatingUniqueConstraint(ArangoVertexCollection vertices, ArangoEdgeCollection edges) { - edges.graph().db().collection(EDGE_COLLECTION_NAME) - .ensurePersistentIndex(Arrays.asList("_from", "_to"), new PersistentIndexOptions().unique(true)); - - BaseEdgeDocument edge = createEdgeValue(vertices); - edges.insertEdge(edge); - - try { - edges.insertEdge(edge); - } catch (ArangoDBException e) { - assertThat(e.getResponseCode()).isEqualTo(409); - assertThat(e.getErrorNum()).isEqualTo(1210); - } - } - - @ParameterizedTest(name = "{index}") - @MethodSource("args") - void getEdge(ArangoVertexCollection vertices, ArangoEdgeCollection edges) { - final BaseEdgeDocument value = createEdgeValue(vertices); - final EdgeEntity edge = edges.insertEdge(value); - final BaseEdgeDocument document = edges - .getEdge(edge.getKey(), BaseEdgeDocument.class); - assertThat(document).isNotNull(); - assertThat(document.getKey()).isEqualTo(edge.getKey()); - assertThat(document.getFrom()).isNotNull(); - assertThat(document.getTo()).isNotNull(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("args") - void getEdgeIfMatch(ArangoVertexCollection vertices, ArangoEdgeCollection edges) { - final BaseEdgeDocument value = createEdgeValue(vertices); - final EdgeEntity edge = edges.insertEdge(value); - final GraphDocumentReadOptions options = new GraphDocumentReadOptions().ifMatch(edge.getRev()); - final BaseDocument document = edges.getEdge(edge.getKey(), - BaseDocument.class, options); - assertThat(document).isNotNull(); - assertThat(document.getKey()).isEqualTo(edge.getKey()); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("args") - void getEdgeIfMatchFail(ArangoVertexCollection vertices, ArangoEdgeCollection edges) { - final BaseEdgeDocument value = createEdgeValue(vertices); - final EdgeEntity edge = edges.insertEdge(value); - final GraphDocumentReadOptions options = new GraphDocumentReadOptions().ifMatch("no"); - final BaseEdgeDocument edge2 = edges.getEdge(edge.getKey(), - BaseEdgeDocument.class, options); - assertThat(edge2).isNull(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("args") - void getEdgeIfNoneMatch(ArangoVertexCollection vertices, ArangoEdgeCollection edges) { - final BaseEdgeDocument value = createEdgeValue(vertices); - final EdgeEntity edge = edges.insertEdge(value); - final GraphDocumentReadOptions options = new GraphDocumentReadOptions().ifNoneMatch("no"); - final BaseDocument document = edges.getEdge(edge.getKey(), - BaseDocument.class, options); - assertThat(document).isNotNull(); - assertThat(document.getKey()).isEqualTo(edge.getKey()); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("args") - void getEdgeIfNoneMatchFail(ArangoVertexCollection vertices, ArangoEdgeCollection edges) { - final BaseEdgeDocument value = createEdgeValue(vertices); - final EdgeEntity edge = edges.insertEdge(value); - final GraphDocumentReadOptions options = new GraphDocumentReadOptions().ifNoneMatch(edge.getRev()); - final BaseEdgeDocument edge2 = edges.getEdge(edge.getKey(), - BaseEdgeDocument.class, options); - assertThat(edge2).isNull(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("args") - void replaceEdge(ArangoVertexCollection vertices, ArangoEdgeCollection edges) { - final BaseEdgeDocument doc = createEdgeValue(vertices); - doc.addAttribute("a", "test"); - final EdgeEntity createResult = edges.insertEdge(doc); - doc.removeAttribute("a"); - doc.addAttribute("b", "test"); - final EdgeUpdateEntity replaceResult = edges - .replaceEdge(createResult.getKey(), doc); - assertThat(replaceResult).isNotNull(); - assertThat(replaceResult.getId()).isEqualTo(createResult.getId()); - assertThat(replaceResult.getRev()).isNotEqualTo(replaceResult.getOldRev()); - assertThat(replaceResult.getOldRev()).isEqualTo(createResult.getRev()); - - final BaseEdgeDocument readResult = edges - .getEdge(createResult.getKey(), BaseEdgeDocument.class); - assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); - assertThat(readResult.getRevision()).isEqualTo(replaceResult.getRev()); - assertThat(readResult.getProperties().keySet()).doesNotContain("a"); - assertThat(readResult.getAttribute("b")).isNotNull(); - assertThat(String.valueOf(readResult.getAttribute("b"))).isEqualTo("test"); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("args") - void replaceEdgeUpdateRev(ArangoVertexCollection vertices, ArangoEdgeCollection edges) { - final BaseEdgeDocument doc = createEdgeValue(vertices); - final EdgeEntity createResult = edges.insertEdge(doc); - final EdgeUpdateEntity replaceResult = edges - .replaceEdge(createResult.getKey(), doc); - assertThat(doc.getRevision()).isNull(); - assertThat(createResult.getRev()).isNotNull(); - assertThat(replaceResult.getRev()) - .isNotNull() - .isNotEqualTo(createResult.getRev()); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("args") - void replaceEdgeIfMatch(ArangoVertexCollection vertices, ArangoEdgeCollection edges) { - final BaseEdgeDocument doc = createEdgeValue(vertices); - doc.addAttribute("a", "test"); - final EdgeEntity createResult = edges.insertEdge(doc); - doc.removeAttribute("a"); - doc.addAttribute("b", "test"); - final EdgeReplaceOptions options = new EdgeReplaceOptions().ifMatch(createResult.getRev()); - final EdgeUpdateEntity replaceResult = edges - .replaceEdge(createResult.getKey(), doc, options); - assertThat(replaceResult).isNotNull(); - assertThat(replaceResult.getId()).isEqualTo(createResult.getId()); - assertThat(replaceResult.getRev()).isNotEqualTo(replaceResult.getOldRev()); - assertThat(replaceResult.getOldRev()).isEqualTo(createResult.getRev()); - - final BaseEdgeDocument readResult = edges - .getEdge(createResult.getKey(), BaseEdgeDocument.class); - assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); - assertThat(readResult.getRevision()).isEqualTo(replaceResult.getRev()); - assertThat(readResult.getProperties().keySet()).doesNotContain("a"); - assertThat(readResult.getAttribute("b")).isNotNull(); - assertThat(String.valueOf(readResult.getAttribute("b"))).isEqualTo("test"); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("args") - void replaceEdgeIfMatchFail(ArangoVertexCollection vertices, ArangoEdgeCollection edges) { - final BaseEdgeDocument doc = createEdgeValue(vertices); - doc.addAttribute("a", "test"); - final EdgeEntity createResult = edges.insertEdge(doc); - doc.removeAttribute("a"); - doc.addAttribute("b", "test"); - final EdgeReplaceOptions options = new EdgeReplaceOptions().ifMatch("no"); - Throwable thrown = catchThrowable(() -> edges.replaceEdge(createResult.getKey(), doc, options)); - assertThat(thrown).isInstanceOf(ArangoDBException.class); - ArangoDBException e = (ArangoDBException) thrown; - assertThat(e.getResponseCode()).isEqualTo(412); - assertThat(e.getErrorNum()).isEqualTo(1200); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("args") - void updateEdge(ArangoVertexCollection vertices, ArangoEdgeCollection edges) { - final BaseEdgeDocument doc = createEdgeValue(vertices); - doc.addAttribute("a", "test"); - doc.addAttribute("c", "test"); - final EdgeEntity createResult = edges.insertEdge(doc); - doc.updateAttribute("a", "test1"); - doc.addAttribute("b", "test"); - doc.updateAttribute("c", null); - final EdgeUpdateEntity updateResult = edges - .updateEdge(createResult.getKey(), doc); - assertThat(updateResult).isNotNull(); - assertThat(updateResult.getId()).isEqualTo(createResult.getId()); - assertThat(updateResult.getRev()).isNotEqualTo(updateResult.getOldRev()); - assertThat(updateResult.getOldRev()).isEqualTo(createResult.getRev()); - - final BaseEdgeDocument readResult = edges - .getEdge(createResult.getKey(), BaseEdgeDocument.class); - assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); - assertThat(readResult.getAttribute("a")).isNotNull(); - assertThat(String.valueOf(readResult.getAttribute("a"))).isEqualTo("test1"); - assertThat(readResult.getAttribute("b")).isNotNull(); - assertThat(String.valueOf(readResult.getAttribute("b"))).isEqualTo("test"); - assertThat(readResult.getRevision()).isEqualTo(updateResult.getRev()); - assertThat(readResult.getProperties()).containsKey("c"); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("args") - void updateEdgeUpdateRev(ArangoVertexCollection vertices, ArangoEdgeCollection edges) { - final BaseEdgeDocument doc = createEdgeValue(vertices); - final EdgeEntity createResult = edges.insertEdge(doc); - final EdgeUpdateEntity updateResult = edges - .updateEdge(createResult.getKey(), doc); - assertThat(doc.getRevision()).isNull(); - assertThat(createResult.getRev()).isNotNull(); - assertThat(updateResult.getRev()) - .isNotNull() - .isNotEqualTo(createResult.getRev()); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("args") - void updateEdgeIfMatch(ArangoVertexCollection vertices, ArangoEdgeCollection edges) { - final BaseEdgeDocument doc = createEdgeValue(vertices); - doc.addAttribute("a", "test"); - doc.addAttribute("c", "test"); - final EdgeEntity createResult = edges.insertEdge(doc); - doc.updateAttribute("a", "test1"); - doc.addAttribute("b", "test"); - doc.updateAttribute("c", null); - final EdgeUpdateOptions options = new EdgeUpdateOptions().ifMatch(createResult.getRev()); - final EdgeUpdateEntity updateResult = edges - .updateEdge(createResult.getKey(), doc, options); - assertThat(updateResult).isNotNull(); - assertThat(updateResult.getId()).isEqualTo(createResult.getId()); - assertThat(updateResult.getRev()).isNotEqualTo(updateResult.getOldRev()); - assertThat(updateResult.getOldRev()).isEqualTo(createResult.getRev()); - - final BaseEdgeDocument readResult = edges - .getEdge(createResult.getKey(), BaseEdgeDocument.class); - assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); - assertThat(readResult.getAttribute("a")).isNotNull(); - assertThat(String.valueOf(readResult.getAttribute("a"))).isEqualTo("test1"); - assertThat(readResult.getAttribute("b")).isNotNull(); - assertThat(String.valueOf(readResult.getAttribute("b"))).isEqualTo("test"); - assertThat(readResult.getRevision()).isEqualTo(updateResult.getRev()); - assertThat(readResult.getProperties()).containsKey("c"); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("args") - void updateEdgeIfMatchFail(ArangoVertexCollection vertices, ArangoEdgeCollection edges) { - final BaseEdgeDocument doc = createEdgeValue(vertices); - doc.addAttribute("a", "test"); - doc.addAttribute("c", "test"); - final EdgeEntity createResult = edges.insertEdge(doc); - doc.updateAttribute("a", "test1"); - doc.addAttribute("b", "test"); - doc.updateAttribute("c", null); - final EdgeUpdateOptions options = new EdgeUpdateOptions().ifMatch("no"); - Throwable thrown = catchThrowable(() -> edges.updateEdge(createResult.getKey(), doc, options)); - assertThat(thrown).isInstanceOf(ArangoDBException.class); - ArangoDBException e = (ArangoDBException) thrown; - assertThat(e.getResponseCode()).isEqualTo(412); - assertThat(e.getErrorNum()).isEqualTo(1200); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("args") - void updateEdgeKeepNullTrue(ArangoVertexCollection vertices, ArangoEdgeCollection edges) { - final BaseEdgeDocument doc = createEdgeValue(vertices); - doc.addAttribute("a", "test"); - final EdgeEntity createResult = edges.insertEdge(doc); - doc.updateAttribute("a", null); - final EdgeUpdateOptions options = new EdgeUpdateOptions().keepNull(true); - final EdgeUpdateEntity updateResult = edges - .updateEdge(createResult.getKey(), doc, options); - assertThat(updateResult).isNotNull(); - assertThat(updateResult.getId()).isEqualTo(createResult.getId()); - assertThat(updateResult.getRev()).isNotEqualTo(updateResult.getOldRev()); - assertThat(updateResult.getOldRev()).isEqualTo(createResult.getRev()); - - final BaseEdgeDocument readResult = edges - .getEdge(createResult.getKey(), BaseEdgeDocument.class); - assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); - assertThat(readResult.getProperties().keySet()).hasSize(6); - assertThat(readResult.getProperties()).containsKey("a"); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("args") - void updateEdgeKeepNullFalse(ArangoVertexCollection vertices, ArangoEdgeCollection edges) { - final BaseEdgeDocument doc = createEdgeValue(vertices); - doc.addAttribute("a", "test"); - final EdgeEntity createResult = edges.insertEdge(doc); - doc.updateAttribute("a", null); - final EdgeUpdateOptions options = new EdgeUpdateOptions().keepNull(false); - final EdgeUpdateEntity updateResult = edges - .updateEdge(createResult.getKey(), doc, options); - assertThat(updateResult).isNotNull(); - assertThat(updateResult.getId()).isEqualTo(createResult.getId()); - assertThat(updateResult.getRev()).isNotEqualTo(updateResult.getOldRev()); - assertThat(updateResult.getOldRev()).isEqualTo(createResult.getRev()); - - final BaseEdgeDocument readResult = edges - .getEdge(createResult.getKey(), BaseEdgeDocument.class); - assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); - assertThat(readResult.getId()).isEqualTo(createResult.getId()); - assertThat(readResult.getRevision()).isNotNull(); - assertThat(readResult.getProperties().keySet()).doesNotContain("a"); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("args") - void deleteEdge(ArangoVertexCollection vertices, ArangoEdgeCollection edges) { - final BaseEdgeDocument doc = createEdgeValue(vertices); - final EdgeEntity createResult = edges.insertEdge(doc); - edges.deleteEdge(createResult.getKey()); - final BaseEdgeDocument edge = edges - .getEdge(createResult.getKey(), BaseEdgeDocument.class); - assertThat(edge).isNull(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("args") - void deleteEdgeIfMatch(ArangoVertexCollection vertices, ArangoEdgeCollection edges) { - final BaseEdgeDocument doc = createEdgeValue(vertices); - final EdgeEntity createResult = edges.insertEdge(doc); - final EdgeDeleteOptions options = new EdgeDeleteOptions().ifMatch(createResult.getRev()); - edges.deleteEdge(createResult.getKey(), options); - final BaseEdgeDocument edge = edges - .getEdge(createResult.getKey(), BaseEdgeDocument.class); - assertThat(edge).isNull(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("args") - void deleteEdgeIfMatchFail(ArangoVertexCollection vertices, ArangoEdgeCollection edges) { - final BaseEdgeDocument doc = createEdgeValue(vertices); - final EdgeEntity createResult = edges.insertEdge(doc); - final EdgeDeleteOptions options = new EdgeDeleteOptions().ifMatch("no"); - Throwable thrown = catchThrowable(() -> edges.deleteEdge(createResult.getKey(), options)); - assertThat(thrown).isInstanceOf(ArangoDBException.class); - ArangoDBException e = (ArangoDBException) thrown; - assertThat(e.getResponseCode()).isEqualTo(412); - assertThat(e.getErrorNum()).isEqualTo(1200); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("args") - void edgeKeyWithSpecialChars(ArangoVertexCollection vertices, ArangoEdgeCollection edges) { - final BaseEdgeDocument value = createEdgeValue(vertices); - final String key = "_-:.@()+,=;$!*'%" + UUID.randomUUID(); - value.setKey(key); - final EdgeEntity edge = edges.insertEdge(value); - assertThat(edge).isNotNull(); - final BaseEdgeDocument document = edges.getEdge(edge.getKey(), BaseEdgeDocument.class); - assertThat(document).isNotNull(); - assertThat(document.getKey()).isEqualTo(key); - assertThat(document.getFrom()).isNotNull(); - assertThat(document.getTo()).isNotNull(); - } - -} diff --git a/shaded-integration-tests/src/test/native/java/com/arangodb/ArangoGraphTest.java b/shaded-integration-tests/src/test/native/java/com/arangodb/ArangoGraphTest.java deleted file mode 100644 index 73e56711c..000000000 --- a/shaded-integration-tests/src/test/native/java/com/arangodb/ArangoGraphTest.java +++ /dev/null @@ -1,438 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb; - -import com.arangodb.entity.CollectionPropertiesEntity; -import com.arangodb.entity.EdgeDefinition; -import com.arangodb.entity.GraphEntity; -import com.arangodb.entity.ReplicationFactor; -import com.arangodb.model.GraphCreateOptions; -import com.arangodb.model.VertexCollectionCreateOptions; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.Arguments; -import org.junit.jupiter.params.provider.MethodSource; - -import java.util.*; -import java.util.stream.Stream; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assumptions.assumeTrue; - - -/** - * @author Mark Vollmary - * @author Michele Rastelli - */ -class ArangoGraphTest extends BaseJunit5 { - - private static final String GRAPH_NAME = "ArangoGraphTest_graph"; - - private static final String VERTEX_COL_1 = "ArangoGraphTest_vertex_collection_1"; - private static final String VERTEX_COL_2 = "ArangoGraphTest_vertex_collection_2"; - private static final String VERTEX_COL_3 = "ArangoGraphTest_vertex_collection_3"; - private static final String VERTEX_COL_4 = "ArangoGraphTest_vertex_collection_4"; - - private static final String EDGE_COL_1 = "ArangoGraphTest_edge_collection_1"; - private static final String EDGE_COL_2 = "ArangoGraphTest_edge_collection_2"; - private static final String EDGE_COL_3 = "ArangoGraphTest_edge_collection_3"; - - private static final Integer REPLICATION_FACTOR = 2; - private static final Integer NUMBER_OF_SHARDS = 2; - - private static final EdgeDefinition ed1 = - new EdgeDefinition().collection(EDGE_COL_1).from(VERTEX_COL_1).to(VERTEX_COL_2); - private static final EdgeDefinition ed2 = - new EdgeDefinition().collection(EDGE_COL_2).from(VERTEX_COL_2).to(VERTEX_COL_1, VERTEX_COL_3); - - private static Stream graphs() { - return dbsStream() - .map(db -> db.graph(GRAPH_NAME)) - .map(Arguments::of); - } - - @BeforeAll - static void init() { - final Collection edgeDefinitions = Arrays.asList(ed1, ed2); - - final GraphCreateOptions options = new GraphCreateOptions() - .replicationFactor(REPLICATION_FACTOR) - .numberOfShards(NUMBER_OF_SHARDS); - - initGraph(GRAPH_NAME, edgeDefinitions, options); - } - - - @ParameterizedTest(name = "{index}") - @MethodSource("graphs") - void exists(ArangoGraph graph) { - assertThat(graph.exists()).isTrue(); - assertThat(graph.db().graph(GRAPH_NAME + "no").exists()).isFalse(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void createWithReplicationAndWriteConcern(ArangoDatabase db) { - assumeTrue(isAtLeastVersion(3, 5)); - assumeTrue(isCluster()); - - final Collection edgeDefinitions = new ArrayList<>(); - final GraphEntity graph = db.createGraph(GRAPH_NAME + "_1", edgeDefinitions, - new GraphCreateOptions().isSmart(true).replicationFactor(2).writeConcern(2)); - assertThat(graph).isNotNull(); - assertThat(graph.getName()).isEqualTo(GRAPH_NAME + "_1"); - assertThat(graph.getWriteConcern()).isEqualTo(2); - assertThat(graph.getReplicationFactor().getValue()).isEqualTo(2); - db.graph(GRAPH_NAME + "_1").drop(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void getGraphs(ArangoDatabase db) { - final Collection graphs = db.getGraphs(); - assertThat(graphs.stream().anyMatch(it -> it.getName().equals(GRAPH_NAME))).isTrue(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("graphs") - void getInfo(ArangoGraph graph) { - final GraphEntity info = graph.getInfo(); - assertThat(info).isNotNull(); - assertThat(info.getName()).isEqualTo(GRAPH_NAME); - assertThat(info.getEdgeDefinitions()).hasSize(2); - final Iterator iterator = info.getEdgeDefinitions().iterator(); - final EdgeDefinition e1 = iterator.next(); - assertThat(e1.getCollection()).isEqualTo(EDGE_COL_1); - assertThat(e1.getFrom()).contains(VERTEX_COL_1); - assertThat(e1.getTo()).contains(VERTEX_COL_2); - final EdgeDefinition e2 = iterator.next(); - assertThat(e2.getCollection()).isEqualTo(EDGE_COL_2); - assertThat(e2.getFrom()).contains(VERTEX_COL_2); - assertThat(e2.getTo()).contains(VERTEX_COL_1, VERTEX_COL_3); - assertThat(info.getOrphanCollections()).isEmpty(); - - if (isCluster()) { - for (final String collection : new String[]{EDGE_COL_1, EDGE_COL_2, VERTEX_COL_1, VERTEX_COL_2}) { - final CollectionPropertiesEntity properties = graph.db().collection(collection).getProperties(); - assertThat(properties.getReplicationFactor().getValue()).isEqualTo(REPLICATION_FACTOR); - assertThat(properties.getNumberOfShards()).isEqualTo(NUMBER_OF_SHARDS); - } - } - } - - @ParameterizedTest(name = "{index}") - @MethodSource("graphs") - void getVertexCollections(ArangoGraph graph) { - final Collection vertexCollections = graph.getVertexCollections(); - assertThat(vertexCollections) - .hasSize(3) - .contains(VERTEX_COL_1, VERTEX_COL_2, VERTEX_COL_3); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("graphs") - void addVertexCollection(ArangoGraph graph) { - final GraphEntity g = graph.addVertexCollection(VERTEX_COL_4); - assertThat(g).isNotNull(); - final Collection vertexCollections = graph.getVertexCollections(); - assertThat(vertexCollections).contains(VERTEX_COL_1, VERTEX_COL_2, VERTEX_COL_3, VERTEX_COL_4); - - // revert - graph.vertexCollection(VERTEX_COL_4).drop(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void addSatelliteVertexCollection(ArangoDatabase db) { - assumeTrue(isCluster() || isAtLeastVersion(3, 10)); - assumeTrue(isEnterprise()); - assumeTrue(isAtLeastVersion(3, 9)); - - String v1Name = "vertex-" + rnd(); - - ArangoGraph g = db.graph(GRAPH_NAME + rnd()); - g.create(null, new GraphCreateOptions().isSmart(true).smartGraphAttribute("test")); - g.addVertexCollection(v1Name, new VertexCollectionCreateOptions().satellites(v1Name)); - - Collection vertexCollections = g.getVertexCollections(); - assertThat(vertexCollections).contains(v1Name); - assertThat(db.collection(v1Name).getProperties().getReplicationFactor()).isEqualTo(ReplicationFactor.ofSatellite()); - - // revert - g.drop(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("graphs") - void getEdgeCollections(ArangoGraph graph) { - final Collection edgeCollections = graph.getEdgeDefinitions(); - assertThat(edgeCollections) - .hasSize(2) - .contains(EDGE_COL_1, EDGE_COL_2); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("graphs") - void addEdgeDefinition(ArangoGraph graph) { - EdgeDefinition ed = new EdgeDefinition().collection(EDGE_COL_3).from(VERTEX_COL_1).to(VERTEX_COL_2); - final GraphEntity g = graph.addEdgeDefinition(ed); - assertThat(g).isNotNull(); - final Collection edgeDefinitions = g.getEdgeDefinitions(); - assertThat(edgeDefinitions).hasSize(3); - int count = 0; - for (final EdgeDefinition e : edgeDefinitions) { - if (e.getCollection().equals(EDGE_COL_3)) { - count++; - } - } - assertThat(count).isEqualTo(1); - for (final EdgeDefinition e : edgeDefinitions) { - if (e.getCollection().equals(EDGE_COL_3)) { - assertThat(e.getFrom()).contains(VERTEX_COL_1); - assertThat(e.getTo()).contains(VERTEX_COL_2); - } - } - if (isCluster()) { - final CollectionPropertiesEntity properties = graph.db().collection(EDGE_COL_3).getProperties(); - assertThat(properties.getReplicationFactor().getValue()).isEqualTo(REPLICATION_FACTOR); - assertThat(properties.getNumberOfShards()).isEqualTo(NUMBER_OF_SHARDS); - } - - // revert - graph.removeEdgeDefinition(EDGE_COL_3); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void addSatelliteEdgeDefinition(ArangoDatabase db) { - assumeTrue(isCluster() || isAtLeastVersion(3, 10)); - 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(null, new GraphCreateOptions().isSmart(true).smartGraphAttribute("test")); - g.addEdgeDefinition(ed); - final GraphEntity ge = g.getInfo(); - assertThat(ge).isNotNull(); - final Collection edgeDefinitions = ge.getEdgeDefinitions(); - assertThat(edgeDefinitions).hasSize(1); - EdgeDefinition e = edgeDefinitions.iterator().next(); - assertThat(e.getCollection()).isEqualTo(eName); - assertThat(e.getFrom()).contains(v1Name); - assertThat(e.getTo()).contains(v2Name); - - assertThat(db.collection(v1Name).getProperties().getReplicationFactor()).isEqualTo(ReplicationFactor.ofSatellite()); - - // revert - g.drop(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("graphs") - void replaceEdgeDefinition(ArangoGraph graph) { - final GraphEntity g = graph - .replaceEdgeDefinition(new EdgeDefinition().collection(EDGE_COL_1).from(VERTEX_COL_3).to(VERTEX_COL_4)); - final Collection edgeDefinitions = g.getEdgeDefinitions(); - assertThat(edgeDefinitions).hasSize(2); - int count = 0; - for (final EdgeDefinition e : edgeDefinitions) { - if (e.getCollection().equals(EDGE_COL_1)) { - count++; - } - } - assertThat(count).isEqualTo(1); - for (final EdgeDefinition e : edgeDefinitions) { - if (e.getCollection().equals(EDGE_COL_1)) { - assertThat(e.getFrom()).contains(VERTEX_COL_3); - assertThat(e.getTo()).contains(VERTEX_COL_4); - } - } - - // revert - graph.removeEdgeDefinition(EDGE_COL_1); - graph.vertexCollection(VERTEX_COL_4).drop(); - graph.addEdgeDefinition(ed1); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("graphs") - void removeEdgeDefinition(ArangoGraph graph) { - final GraphEntity g = graph.removeEdgeDefinition(EDGE_COL_1); - final Collection edgeDefinitions = g.getEdgeDefinitions(); - assertThat(edgeDefinitions).hasSize(1); - assertThat(edgeDefinitions.iterator().next().getCollection()).isEqualTo(EDGE_COL_2); - - //revert - graph.addEdgeDefinition(ed1); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void smartGraph(ArangoDatabase db) { - assumeTrue(isEnterprise()); - assumeTrue(isCluster() || isAtLeastVersion(3, 10)); - - final Collection edgeDefinitions = new ArrayList<>(); - edgeDefinitions.add(new EdgeDefinition().collection("smartGraph-edge-" + rnd()).from("smartGraph-vertex-" + rnd()).to("smartGraph-vertex-" + rnd())); - - String graphId = GRAPH_NAME + rnd(); - final GraphEntity g = db.createGraph(graphId, edgeDefinitions, - new GraphCreateOptions().isSmart(true).smartGraphAttribute("test").numberOfShards(2)); - - assertThat(g).isNotNull(); - assertThat(g.getIsSmart()).isTrue(); - assertThat(g.getSmartGraphAttribute()).isEqualTo("test"); - assertThat(g.getNumberOfShards()).isEqualTo(2); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void hybridSmartGraph(ArangoDatabase db) { - assumeTrue(isEnterprise()); - assumeTrue(isCluster() || isAtLeastVersion(3, 10)); - 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).isNotNull(); - assertThat(g.getIsSmart()).isTrue(); - assertThat(g.getSmartGraphAttribute()).isEqualTo("test"); - assertThat(g.getNumberOfShards()).isEqualTo(2); - - assertThat(db.collection(eName).getProperties().getReplicationFactor()).isEqualTo(ReplicationFactor.ofSatellite()); - assertThat(db.collection(v1Name).getProperties().getReplicationFactor()).isEqualTo(ReplicationFactor.ofSatellite()); - assertThat(db.collection(v2Name).getProperties().getReplicationFactor().getValue()).isEqualTo(2); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void disjointSmartGraph(ArangoDatabase db) { - assumeTrue(isEnterprise()); - assumeTrue(isCluster() || isAtLeastVersion(3, 10)); - assumeTrue((isAtLeastVersion(3, 7))); - - final Collection edgeDefinitions = new ArrayList<>(); - edgeDefinitions.add(new EdgeDefinition().collection("smartGraph-edge-" + rnd()).from("smartGraph-vertex-" + rnd()).to("smartGraph-vertex-" + rnd())); - - String graphId = GRAPH_NAME + rnd(); - final GraphEntity g = db.createGraph(graphId, edgeDefinitions, new GraphCreateOptions() - .isSmart(true).isDisjoint(true).smartGraphAttribute("test").numberOfShards(2)); - - assertThat(g).isNotNull(); - assertThat(g.getIsSmart()).isTrue(); - assertThat(g.getIsDisjoint()).isTrue(); - assertThat(g.getSmartGraphAttribute()).isEqualTo("test"); - assertThat(g.getNumberOfShards()).isEqualTo(2); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void hybridDisjointSmartGraph(ArangoDatabase db) { - assumeTrue(isEnterprise()); - assumeTrue(isCluster() || isAtLeastVersion(3, 10)); - 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).isNotNull(); - assertThat(g.getIsSmart()).isTrue(); - assertThat(g.getIsDisjoint()).isTrue(); - assertThat(g.getSmartGraphAttribute()).isEqualTo("test"); - assertThat(g.getNumberOfShards()).isEqualTo(2); - - assertThat(db.collection(v1Name).getProperties().getReplicationFactor()).isEqualTo(ReplicationFactor.ofSatellite()); - assertThat(db.collection(v2Name).getProperties().getReplicationFactor().getValue()).isEqualTo(2); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void enterpriseGraph(ArangoDatabase db) { - assumeTrue(isEnterprise()); - assumeTrue(isCluster() || isAtLeastVersion(3, 10)); - - final Collection edgeDefinitions = new ArrayList<>(); - edgeDefinitions.add(new EdgeDefinition().collection("enterpriseGraph-edge-" + rnd()).from("enterpriseGraph-vertex-" + rnd()).to("enterpriseGraph-vertex-" + rnd())); - - String graphId = GRAPH_NAME + rnd(); - final GraphEntity g = db.createGraph(graphId, edgeDefinitions, new GraphCreateOptions().isSmart(true).numberOfShards(2)); - - assertThat(g).isNotNull(); - assertThat(g.getSmartGraphAttribute()).isNull(); - assertThat(g.getNumberOfShards()).isEqualTo(2); - if (isAtLeastVersion(3, 10)) { - assertThat(g.getIsSmart()).isTrue(); - } else { - assertThat(g.getIsSmart()).isFalse(); - } - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void drop(ArangoDatabase db) { - final String edgeCollection = "edge_" + rnd(); - final String vertexCollection = "vertex_" + rnd(); - final String graphId = GRAPH_NAME + rnd(); - final GraphEntity result = db.graph(graphId).create(Collections - .singleton(new EdgeDefinition().collection(edgeCollection).from(vertexCollection).to(vertexCollection))); - assertThat(result).isNotNull(); - db.graph(graphId).drop(); - assertThat(db.collection(edgeCollection).exists()).isTrue(); - assertThat(db.collection(vertexCollection).exists()).isTrue(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void dropPlusDropCollections(ArangoDatabase db) { - final String edgeCollection = "edge_dropC" + rnd(); - final String vertexCollection = "vertex_dropC" + rnd(); - final String graphId = GRAPH_NAME + "_dropC" + rnd(); - final GraphEntity result = db.graph(graphId).create(Collections - .singleton(new EdgeDefinition().collection(edgeCollection).from(vertexCollection).to(vertexCollection))); - assertThat(result).isNotNull(); - db.graph(graphId).drop(true); - assertThat(db.collection(edgeCollection).exists()).isFalse(); - assertThat(db.collection(vertexCollection).exists()).isFalse(); - } - -} diff --git a/shaded-integration-tests/src/test/native/java/com/arangodb/ArangoSearchTest.java b/shaded-integration-tests/src/test/native/java/com/arangodb/ArangoSearchTest.java deleted file mode 100644 index deaecc588..000000000 --- a/shaded-integration-tests/src/test/native/java/com/arangodb/ArangoSearchTest.java +++ /dev/null @@ -1,1010 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2018 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb; - -import com.arangodb.entity.InvertedIndexField; -import com.arangodb.entity.ViewEntity; -import com.arangodb.entity.ViewType; -import com.arangodb.entity.arangosearch.*; -import com.arangodb.entity.arangosearch.analyzer.*; -import com.arangodb.model.InvertedIndexOptions; -import com.arangodb.model.arangosearch.*; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.MethodSource; - -import java.util.*; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.catchThrowable; -import static org.junit.jupiter.api.Assumptions.assumeTrue; - -/** - * @author Mark Vollmary - * @author Michele Rastelli - */ -class ArangoSearchTest extends BaseJunit5 { - - private static final String COLL_1 = "ArangoSearchTest_view_replace_prop"; - private static final String COLL_2 = "ArangoSearchTest_view_update_prop"; - - @BeforeAll - static void init() { - initCollections(COLL_1, COLL_2); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void exists(ArangoDatabase db) { - assumeTrue(isAtLeastVersion(3, 4)); - String viewName = "view-" + rnd(); - db.createArangoSearch(viewName, new ArangoSearchCreateOptions()); - assertThat(db.arangoSearch(viewName).exists()).isTrue(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void createAndExistsSearchAlias(ArangoDatabase db) { - assumeTrue(isAtLeastVersion(3, 10)); - String viewName = "view-" + rnd(); - db.createSearchAlias(viewName, new SearchAliasCreateOptions()); - assertThat(db.arangoSearch(viewName).exists()).isTrue(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void getInfo(ArangoDatabase db) { - assumeTrue(isAtLeastVersion(3, 4)); - String viewName = "view-" + rnd(); - db.createArangoSearch(viewName, new ArangoSearchCreateOptions()); - final ViewEntity info = db.arangoSearch(viewName).getInfo(); - assertThat(info).isNotNull(); - assertThat(info.getId()).isNotNull(); - assertThat(info.getName()).isEqualTo(viewName); - assertThat(info.getType()).isEqualTo(ViewType.ARANGO_SEARCH); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void drop(ArangoDatabase db) { - assumeTrue(isAtLeastVersion(3, 4)); - String viewName = "view-" + rnd(); - db.createArangoSearch(viewName, new ArangoSearchCreateOptions()); - final ArangoView view = db.arangoSearch(viewName); - view.drop(); - assertThat(view.exists()).isFalse(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void rename(ArangoDatabase db) { - assumeTrue(isSingleServer()); - assumeTrue(isAtLeastVersion(3, 4)); - String viewName = "view-" + rnd(); - final String name = viewName + "_new"; - db.createArangoSearch(name, new ArangoSearchCreateOptions()); - db.arangoSearch(name).rename(viewName); - assertThat(db.arangoSearch(name).exists()).isFalse(); - assertThat(db.arangoSearch(viewName).exists()).isTrue(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void createArangoSearchView(ArangoDatabase db) { - assumeTrue(isAtLeastVersion(3, 4)); - String viewName = "view-" + rnd(); - final ViewEntity info = db.arangoSearch(viewName).create(); - assertThat(info).isNotNull(); - assertThat(info.getId()).isNotNull(); - assertThat(info.getName()).isEqualTo(viewName); - assertThat(info.getType()).isEqualTo(ViewType.ARANGO_SEARCH); - assertThat(db.arangoSearch(viewName).exists()).isTrue(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void createSearchAliasView(ArangoDatabase db) { - assumeTrue(isAtLeastVersion(3, 10)); - String viewName = "view-" + rnd(); - final ViewEntity info = db.searchAlias(viewName).create(); - assertThat(info).isNotNull(); - assertThat(info.getId()).isNotNull(); - assertThat(info.getName()).isEqualTo(viewName); - assertThat(info.getType()).isEqualTo(ViewType.SEARCH_ALIAS); - assertThat(db.searchAlias(viewName).exists()).isTrue(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void createArangoSearchViewWithOptions(ArangoDatabase db) { - assumeTrue(isAtLeastVersion(3, 4)); - String viewName = "view-" + rnd(); - final ArangoSearchCreateOptions options = new ArangoSearchCreateOptions(); - final ViewEntity info = db.arangoSearch(viewName).create(options); - assertThat(info).isNotNull(); - assertThat(info.getId()).isNotNull(); - assertThat(info.getName()).isEqualTo(viewName); - assertThat(info.getType()).isEqualTo(ViewType.ARANGO_SEARCH); - assertThat(db.arangoSearch(viewName).exists()).isTrue(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void createArangoSearchViewWithPrimarySort(ArangoDatabase db) { - assumeTrue(isAtLeastVersion(3, 5)); - String viewName = "view-" + rnd(); - final ArangoSearchCreateOptions options = new ArangoSearchCreateOptions(); - - final PrimarySort primarySort = PrimarySort.on("myFieldName"); - primarySort.ascending(true); - options.primarySort(primarySort); - options.primarySortCompression(ArangoSearchCompression.none); - options.consolidationIntervalMsec(666666L); - StoredValue storedValue = new StoredValue(Arrays.asList("a", "b"), ArangoSearchCompression.none); - options.storedValues(storedValue); - - final ArangoSearch view = db.arangoSearch(viewName); - final ViewEntity info = view.create(options); - assertThat(info).isNotNull(); - assertThat(info.getId()).isNotNull(); - assertThat(info.getName()).isEqualTo(viewName); - assertThat(info.getType()).isEqualTo(ViewType.ARANGO_SEARCH); - assertThat(db.arangoSearch(viewName).exists()).isTrue(); - - if (isAtLeastVersion(3, 7)) { - final ArangoSearchPropertiesEntity properties = view.getProperties(); - assertThat(properties.getPrimarySortCompression()).isEqualTo(ArangoSearchCompression.none); - Collection retrievedStoredValues = properties.getStoredValues(); - assertThat(retrievedStoredValues).isNotNull(); - assertThat(retrievedStoredValues).hasSize(1); - StoredValue retrievedStoredValue = retrievedStoredValues.iterator().next(); - assertThat(retrievedStoredValue).isNotNull(); - assertThat(retrievedStoredValue.getFields()).isEqualTo(storedValue.getFields()); - assertThat(retrievedStoredValue.getCompression()).isEqualTo(storedValue.getCompression()); - } - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void createArangoSearchViewWithCommitIntervalMsec(ArangoDatabase db) { - assumeTrue(isAtLeastVersion(3, 5)); - String viewName = "view-" + rnd(); - final ArangoSearchCreateOptions options = new ArangoSearchCreateOptions(); - options.commitIntervalMsec(666666L); - - final ViewEntity info = db.arangoSearch(viewName).create(options); - assertThat(info).isNotNull(); - assertThat(info.getId()).isNotNull(); - assertThat(info.getName()).isEqualTo(viewName); - assertThat(info.getType()).isEqualTo(ViewType.ARANGO_SEARCH); - assertThat(db.arangoSearch(viewName).exists()).isTrue(); - - // check commit interval msec property - final ArangoSearch view = db.arangoSearch(viewName); - final ArangoSearchPropertiesEntity properties = view.getProperties(); - assertThat(properties.getCommitIntervalMsec()).isEqualTo(666666L); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void createSearchAliasViewWithOptions(ArangoDatabase db) { - assumeTrue(isAtLeastVersion(3, 10)); - String viewName = "view-" + rnd(); - final SearchAliasCreateOptions options = new SearchAliasCreateOptions(); - final ViewEntity info = db.searchAlias(viewName).create(options); - assertThat(info).isNotNull(); - assertThat(info.getId()).isNotNull(); - assertThat(info.getName()).isEqualTo(viewName); - assertThat(info.getType()).isEqualTo(ViewType.SEARCH_ALIAS); - assertThat(db.searchAlias(viewName).exists()).isTrue(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void createSearchAliasViewWithIndexesAndGetProperties(ArangoDatabase db) { - assumeTrue(isAtLeastVersion(3, 10)); - ArangoCollection col = db.collection(COLL_1); - String idxName1 = "idx-" + rnd(); - col.ensureInvertedIndex(new InvertedIndexOptions() - .name(idxName1) - .fields(new InvertedIndexField().name("a" + rnd()))); - - String idxName2 = "idx-" + rnd(); - col.ensureInvertedIndex(new InvertedIndexOptions() - .name(idxName2) - .fields(new InvertedIndexField().name("a" + rnd()))); - - String viewName = "view-" + rnd(); - final SearchAliasCreateOptions options = new SearchAliasCreateOptions() - .indexes( - new SearchAliasIndex(COLL_1, idxName1, SearchAliasIndex.OperationType.add), - new SearchAliasIndex(COLL_1, idxName2, SearchAliasIndex.OperationType.add), - new SearchAliasIndex(COLL_1, idxName2, SearchAliasIndex.OperationType.del) - ); - final ViewEntity info = db.searchAlias(viewName).create(options); - assertThat(info).isNotNull(); - assertThat(info.getId()).isNotNull(); - assertThat(info.getName()).isEqualTo(viewName); - assertThat(info.getType()).isEqualTo(ViewType.SEARCH_ALIAS); - - final SearchAliasPropertiesEntity properties = db.searchAlias(viewName).getProperties(); - assertThat(properties).isNotNull(); - assertThat(properties.getId()).isNotNull(); - assertThat(properties.getName()).isEqualTo(viewName); - assertThat(properties.getType()).isEqualTo(ViewType.SEARCH_ALIAS); - assertThat(properties.getIndexes()) - .isNotNull() - .isNotEmpty() - .anyMatch(i -> i.getCollection().equals(COLL_1) && i.getIndex().equals(idxName1)); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void getArangoSearchViewProperties(ArangoDatabase db) { - assumeTrue(isAtLeastVersion(3, 4)); - String viewName = "view-" + rnd(); - final ArangoSearch view = db.arangoSearch(viewName); - view.create(new ArangoSearchCreateOptions()); - final ArangoSearchPropertiesEntity properties = view.getProperties(); - assertThat(properties).isNotNull(); - assertThat(properties.getId()).isNotNull(); - assertThat(properties.getName()).isEqualTo(viewName); - assertThat(properties.getType()).isEqualTo(ViewType.ARANGO_SEARCH); - assertThat(properties.getConsolidationIntervalMsec()).isNotNull(); - assertThat(properties.getCleanupIntervalStep()).isNotNull(); - final ConsolidationPolicy consolidate = properties.getConsolidationPolicy(); - assertThat(consolidate).isNotNull(); - final Collection links = properties.getLinks(); - assertThat(links).isEmpty(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void updateArangoSearchViewProperties(ArangoDatabase db) { - assumeTrue(isAtLeastVersion(3, 4)); - String viewName = "view-" + rnd(); - final ArangoSearch view = db.arangoSearch(viewName); - view.create(new ArangoSearchCreateOptions()); - final ArangoSearchPropertiesOptions options = new ArangoSearchPropertiesOptions(); - options.cleanupIntervalStep(15L); - options.consolidationIntervalMsec(65000L); - options.consolidationPolicy(ConsolidationPolicy.of(ConsolidationType.BYTES_ACCUM).threshold(1.)); - options.link(CollectionLink.on(COLL_2) - .fields(FieldLink.on("value").analyzers("identity").trackListPositions(true).includeAllFields(true) - .storeValues(StoreValuesType.ID))); - final ArangoSearchPropertiesEntity properties = view.updateProperties(options); - assertThat(properties).isNotNull(); - assertThat(properties.getCleanupIntervalStep()).isEqualTo(15L); - assertThat(properties.getConsolidationIntervalMsec()).isEqualTo(65000L); - final ConsolidationPolicy consolidate = properties.getConsolidationPolicy(); - assertThat(consolidate).isNotNull(); - assertThat(consolidate.getType()).isEqualTo(ConsolidationType.BYTES_ACCUM); - assertThat(consolidate.getThreshold()).isEqualTo(1.); - assertThat(properties.getLinks()).hasSize(1); - final CollectionLink link = properties.getLinks().iterator().next(); - assertThat(link.getName()).isEqualTo(COLL_2); - assertThat(link.getFields()).hasSize(1); - final FieldLink next = link.getFields().iterator().next(); - assertThat(next.getName()).isEqualTo("value"); - assertThat(next.getIncludeAllFields()).isTrue(); - assertThat(next.getTrackListPositions()).isTrue(); - assertThat(next.getStoreValues()).isEqualTo(StoreValuesType.ID); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void updateSearchAliasViewWithIndexesAndGetProperties(ArangoDatabase db) { - assumeTrue(isAtLeastVersion(3, 10)); - ArangoCollection col = db.collection(COLL_1); - String idxName = "idx-" + rnd(); - col.ensureInvertedIndex(new InvertedIndexOptions() - .name(idxName) - .fields(new InvertedIndexField().name("a" + rnd()))); - ArangoCollection col2 = db.collection(COLL_2); - String idxName2 = "idx-" + rnd(); - col2.ensureInvertedIndex(new InvertedIndexOptions() - .name(idxName2) - .fields(new InvertedIndexField().name("a" + rnd()))); - - String viewName = "view-" + rnd(); - final SearchAliasCreateOptions options = new SearchAliasCreateOptions() - .indexes(new SearchAliasIndex(COLL_1, idxName)); - final ViewEntity info = db.searchAlias(viewName).create(options); - db.searchAlias(viewName).updateProperties(new SearchAliasPropertiesOptions() - .indexes(new SearchAliasIndex(COLL_2, idxName2))); - - assertThat(info).isNotNull(); - assertThat(info.getId()).isNotNull(); - assertThat(info.getName()).isEqualTo(viewName); - assertThat(info.getType()).isEqualTo(ViewType.SEARCH_ALIAS); - - final SearchAliasPropertiesEntity properties = db.searchAlias(viewName).getProperties(); - assertThat(properties).isNotNull(); - assertThat(properties.getId()).isNotNull(); - assertThat(properties.getName()).isEqualTo(viewName); - assertThat(properties.getType()).isEqualTo(ViewType.SEARCH_ALIAS); - assertThat(properties.getIndexes()) - .isNotNull() - .isNotEmpty() - .hasSize(2) - .anyMatch(i -> i.getCollection().equals(COLL_1) && i.getIndex().equals(idxName)) - .anyMatch(i -> i.getCollection().equals(COLL_2) && i.getIndex().equals(idxName2)); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void replaceArangoSearchViewProperties(ArangoDatabase db) { - assumeTrue(isAtLeastVersion(3, 4)); - String viewName = "view-" + rnd(); - final ArangoSearch view = db.arangoSearch(viewName); - view.create(new ArangoSearchCreateOptions()); - final ArangoSearchPropertiesOptions options = new ArangoSearchPropertiesOptions(); - options.link(CollectionLink.on(COLL_1) - .fields(FieldLink.on("value").analyzers("identity"))); - final ArangoSearchPropertiesEntity properties = view.replaceProperties(options); - assertThat(properties).isNotNull(); - assertThat(properties.getLinks()).hasSize(1); - final CollectionLink link = properties.getLinks().iterator().next(); - assertThat(link.getName()).isEqualTo(COLL_1); - assertThat(link.getFields()).hasSize(1); - assertThat(link.getFields().iterator().next().getName()).isEqualTo("value"); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void replaceSearchAliasViewWithIndexesAndGetProperties(ArangoDatabase db) { - assumeTrue(isAtLeastVersion(3, 10)); - ArangoCollection col = db.collection(COLL_1); - String idxName = "idx-" + rnd(); - col.ensureInvertedIndex(new InvertedIndexOptions() - .name(idxName) - .fields(new InvertedIndexField().name("a" + rnd()))); - ArangoCollection col2 = db.collection(COLL_2); - String idxName2 = "idx-" + rnd(); - col2.ensureInvertedIndex(new InvertedIndexOptions() - .name(idxName2) - .fields(new InvertedIndexField().name("a" + rnd()))); - - String viewName = "view-" + rnd(); - final SearchAliasCreateOptions options = new SearchAliasCreateOptions() - .indexes(new SearchAliasIndex(COLL_1, idxName)); - final ViewEntity info = db.searchAlias(viewName).create(options); - db.searchAlias(viewName).replaceProperties(new SearchAliasPropertiesOptions() - .indexes(new SearchAliasIndex(COLL_2, idxName2))); - - assertThat(info).isNotNull(); - assertThat(info.getId()).isNotNull(); - assertThat(info.getName()).isEqualTo(viewName); - assertThat(info.getType()).isEqualTo(ViewType.SEARCH_ALIAS); - - final SearchAliasPropertiesEntity properties = db.searchAlias(viewName).getProperties(); - assertThat(properties).isNotNull(); - assertThat(properties.getId()).isNotNull(); - assertThat(properties.getName()).isEqualTo(viewName); - assertThat(properties.getType()).isEqualTo(ViewType.SEARCH_ALIAS); - assertThat(properties.getIndexes()) - .isNotNull() - .isNotEmpty() - .hasSize(1) - .anyMatch(i -> i.getCollection().equals(COLL_2) && i.getIndex().equals(idxName2)); - } - - private void createGetAndDeleteTypedAnalyzer(ArangoDatabase db, SearchAnalyzer analyzer) { - - String fullyQualifiedName = db.dbName().get() + "::" + analyzer.getName(); - analyzer.setName(fullyQualifiedName); - - // createAnalyzer - SearchAnalyzer createdAnalyzer = db.createSearchAnalyzer(analyzer); - assertThat(createdAnalyzer).isEqualTo(analyzer); - - // getAnalyzer - SearchAnalyzer gotAnalyzer = db.getSearchAnalyzer(analyzer.getName()); - assertThat(gotAnalyzer).isEqualTo(analyzer); - - // getAnalyzers - SearchAnalyzer foundAnalyzer = - db.getSearchAnalyzers().stream().filter(it -> it.getName().equals(fullyQualifiedName)) - .findFirst().get(); - assertThat(foundAnalyzer).isEqualTo(analyzer); - - // deleteAnalyzer - AnalyzerDeleteOptions deleteOptions = new AnalyzerDeleteOptions(); - deleteOptions.setForce(true); - - db.deleteSearchAnalyzer(analyzer.getName(), deleteOptions); - - Throwable thrown = catchThrowable(() -> db.getSearchAnalyzer(analyzer.getName())); - assertThat(thrown).isInstanceOf(ArangoDBException.class); - ArangoDBException e = (ArangoDBException) thrown; - assertThat(e.getResponseCode()).isEqualTo(404); - assertThat(e.getErrorNum()).isEqualTo(1202); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void identityAnalyzerTyped(ArangoDatabase db) { - assumeTrue(isAtLeastVersion(3, 5)); - - String name = "test-" + UUID.randomUUID(); - - Set features = new HashSet<>(); - features.add(AnalyzerFeature.frequency); - features.add(AnalyzerFeature.norm); - features.add(AnalyzerFeature.position); - - IdentityAnalyzer analyzer = new IdentityAnalyzer(); - analyzer.setFeatures(features); - analyzer.setName(name); - - createGetAndDeleteTypedAnalyzer(db, analyzer); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void delimiterAnalyzerTyped(ArangoDatabase db) { - assumeTrue(isAtLeastVersion(3, 5)); - - String name = "test-" + UUID.randomUUID(); - - Set features = new HashSet<>(); - features.add(AnalyzerFeature.frequency); - features.add(AnalyzerFeature.norm); - features.add(AnalyzerFeature.position); - - DelimiterAnalyzerProperties properties = new DelimiterAnalyzerProperties(); - properties.setDelimiter("-"); - - DelimiterAnalyzer analyzer = new DelimiterAnalyzer(); - analyzer.setFeatures(features); - analyzer.setName(name); - analyzer.setProperties(properties); - - createGetAndDeleteTypedAnalyzer(db, analyzer); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void stemAnalyzerTyped(ArangoDatabase db) { - assumeTrue(isAtLeastVersion(3, 5)); - - String name = "test-" + UUID.randomUUID(); - - Set features = new HashSet<>(); - features.add(AnalyzerFeature.frequency); - features.add(AnalyzerFeature.norm); - features.add(AnalyzerFeature.position); - - StemAnalyzerProperties properties = new StemAnalyzerProperties(); - properties.setLocale("ru"); - - StemAnalyzer options = new StemAnalyzer(); - options.setFeatures(features); - options.setName(name); - options.setProperties(properties); - - createGetAndDeleteTypedAnalyzer(db, options); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void normAnalyzerTyped(ArangoDatabase db) { - assumeTrue(isAtLeastVersion(3, 5)); - - String name = "test-" + UUID.randomUUID(); - - Set features = new HashSet<>(); - features.add(AnalyzerFeature.frequency); - features.add(AnalyzerFeature.norm); - features.add(AnalyzerFeature.position); - - NormAnalyzerProperties properties = new NormAnalyzerProperties(); - properties.setLocale("ru"); - properties.setAnalyzerCase(SearchAnalyzerCase.lower); - properties.setAccent(true); - - NormAnalyzer options = new NormAnalyzer(); - options.setFeatures(features); - options.setName(name); - options.setProperties(properties); - - createGetAndDeleteTypedAnalyzer(db, options); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void ngramAnalyzerTyped(ArangoDatabase db) { - assumeTrue(isAtLeastVersion(3, 5)); - - String name = "test-" + UUID.randomUUID(); - - Set features = new HashSet<>(); - features.add(AnalyzerFeature.frequency); - features.add(AnalyzerFeature.norm); - features.add(AnalyzerFeature.position); - - NGramAnalyzerProperties properties = new NGramAnalyzerProperties(); - properties.setMax(6L); - properties.setMin(3L); - properties.setPreserveOriginal(true); - - NGramAnalyzer analyzer = new NGramAnalyzer(); - analyzer.setFeatures(features); - analyzer.setName(name); - analyzer.setType(AnalyzerType.ngram); - analyzer.setProperties(properties); - - createGetAndDeleteTypedAnalyzer(db, analyzer); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void enhancedNgramAnalyzerTyped(ArangoDatabase db) { - assumeTrue(isAtLeastVersion(3, 6)); - - String name = "test-" + UUID.randomUUID(); - - Set features = new HashSet<>(); - features.add(AnalyzerFeature.frequency); - features.add(AnalyzerFeature.norm); - features.add(AnalyzerFeature.position); - - NGramAnalyzerProperties properties = new NGramAnalyzerProperties(); - properties.setMax(6L); - properties.setMin(3L); - properties.setPreserveOriginal(true); - properties.setStartMarker("^"); - properties.setEndMarker("^"); - properties.setStreamType(StreamType.utf8); - - NGramAnalyzer analyzer = new NGramAnalyzer(); - analyzer.setFeatures(features); - analyzer.setName(name); - analyzer.setProperties(properties); - - createGetAndDeleteTypedAnalyzer(db, analyzer); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void textAnalyzerTyped(ArangoDatabase db) { - assumeTrue(isAtLeastVersion(3, 5)); - - String name = "test-" + UUID.randomUUID(); - - Set features = new HashSet<>(); - features.add(AnalyzerFeature.frequency); - features.add(AnalyzerFeature.norm); - features.add(AnalyzerFeature.position); - - TextAnalyzerProperties properties = new TextAnalyzerProperties(); - properties.setLocale("ru"); - properties.setAnalyzerCase(SearchAnalyzerCase.lower); - properties.setAccent(true); - properties.setStemming(true); - - TextAnalyzer analyzer = new TextAnalyzer(); - analyzer.setFeatures(features); - analyzer.setName(name); - analyzer.setType(AnalyzerType.text); - analyzer.setProperties(properties); - - createGetAndDeleteTypedAnalyzer(db, analyzer); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void enhancedTextAnalyzerTyped(ArangoDatabase db) { - assumeTrue(isAtLeastVersion(3, 6)); - - String name = "test-" + UUID.randomUUID(); - - Set features = new HashSet<>(); - features.add(AnalyzerFeature.frequency); - features.add(AnalyzerFeature.norm); - features.add(AnalyzerFeature.position); - - EdgeNgram edgeNgram = new EdgeNgram(); - edgeNgram.setMin(2L); - edgeNgram.setMax(100000L); - edgeNgram.setPreserveOriginal(true); - - TextAnalyzerProperties properties = new TextAnalyzerProperties(); - properties.setLocale("ru"); - properties.setAnalyzerCase(SearchAnalyzerCase.lower); - properties.setAccent(true); - properties.setStemming(true); - properties.setEdgeNgram(edgeNgram); - - TextAnalyzer analyzer = new TextAnalyzer(); - analyzer.setFeatures(features); - analyzer.setName(name); - analyzer.setProperties(properties); - - createGetAndDeleteTypedAnalyzer(db, analyzer); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void arangoSearchOptions(ArangoDatabase db) { - assumeTrue(isAtLeastVersion(3, 4)); - String viewName = "view-" + rnd(); - FieldLink field = FieldLink.on("f1").inBackground(true); - if (isEnterprise()) { - field.nested(FieldLink.on("f2")); - } - CollectionLink link = CollectionLink.on(COLL_1) - .analyzers("identity") - .fields(field) - .includeAllFields(true) - .storeValues(StoreValuesType.ID) - .trackListPositions(false) - .inBackground(true) - .cache(true); - - if (isEnterprise()) { - link.nested(FieldLink.on("f3")); - } - ArangoSearchCreateOptions options = new ArangoSearchCreateOptions().link(link); - StoredValue storedValue = new StoredValue(Arrays.asList("a", "b"), ArangoSearchCompression.none, true); - options.storedValues(storedValue); - - final ArangoSearch view = db.arangoSearch(viewName); - view.create(options); - - final ArangoSearchPropertiesEntity properties = view.getProperties(); - assertThat(properties).isNotNull(); - assertThat(properties.getId()).isNotNull(); - assertThat(properties.getName()).isEqualTo(viewName); - assertThat(properties.getType()).isEqualTo(ViewType.ARANGO_SEARCH); - assertThat(properties.getLinks()).isNotEmpty(); - - CollectionLink createdLink = properties.getLinks().iterator().next(); - assertThat(createdLink.getName()).isEqualTo(COLL_1); - assertThat(createdLink.getAnalyzers()).contains("identity"); - assertThat(createdLink.getIncludeAllFields()).isTrue(); - assertThat(createdLink.getStoreValues()).isEqualTo(StoreValuesType.ID); - assertThat(createdLink.getTrackListPositions()).isFalse(); - - if (isEnterprise() && isAtLeastVersion(3, 9, 5) && isLessThanVersion(3, 10)) { - assertThat(createdLink.getCache()).isTrue(); - assertThat(properties.getStoredValues()) - .isNotEmpty() - .allSatisfy(it -> assertThat(it.getCache()).isTrue()); - } - - if (isEnterprise() && isAtLeastVersion(3, 10)) { - assertThat(createdLink.getNested()).isNotEmpty(); - FieldLink nested = createdLink.getNested().iterator().next(); - assertThat(nested.getName()).isEqualTo("f3"); - } - - FieldLink fieldLink = createdLink.getFields().iterator().next(); - assertThat(fieldLink.getName()).isEqualTo("f1"); - if (isEnterprise() && isAtLeastVersion(3, 10)) { - assertThat(fieldLink.getNested()).isNotEmpty(); - FieldLink nested = fieldLink.getNested().iterator().next(); - assertThat(nested.getName()).isEqualTo("f2"); - } - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void pipelineAnalyzer(ArangoDatabase db) { - assumeTrue(isAtLeastVersion(3, 8)); - - // comma delimiter - DelimiterAnalyzerProperties commaDelimiterProperties = new DelimiterAnalyzerProperties(); - commaDelimiterProperties.setDelimiter(","); - - DelimiterAnalyzer commaDelimiter = new DelimiterAnalyzer(); - commaDelimiter.setProperties(commaDelimiterProperties); - - // semicolon delimiter - DelimiterAnalyzerProperties semicolonDelimiterProperties = new DelimiterAnalyzerProperties(); - semicolonDelimiterProperties.setDelimiter(","); - - DelimiterAnalyzer semicolonDelimiter = new DelimiterAnalyzer(); - semicolonDelimiter.setProperties(semicolonDelimiterProperties); - - // stem - StemAnalyzerProperties stemAnalyzerProperties = new StemAnalyzerProperties(); - stemAnalyzerProperties.setLocale("en"); - - StemAnalyzer stemAnalyzer = new StemAnalyzer(); - stemAnalyzer.setProperties(stemAnalyzerProperties); - - // pipeline analyzer - Set features = new HashSet<>(); - features.add(AnalyzerFeature.frequency); - features.add(AnalyzerFeature.norm); - features.add(AnalyzerFeature.position); - - PipelineAnalyzerProperties properties = new PipelineAnalyzerProperties() - .addAnalyzer(commaDelimiter) - .addAnalyzer(semicolonDelimiter) - .addAnalyzer(stemAnalyzer); - - PipelineAnalyzer pipelineAnalyzer = new PipelineAnalyzer(); - pipelineAnalyzer.setName("test-" + UUID.randomUUID()); - pipelineAnalyzer.setProperties(properties); - pipelineAnalyzer.setFeatures(features); - - createGetAndDeleteTypedAnalyzer(db, pipelineAnalyzer); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void stopwordsAnalyzer(ArangoDatabase db) { - assumeTrue(isAtLeastVersion(3, 8)); - - Set features = new HashSet<>(); - features.add(AnalyzerFeature.frequency); - features.add(AnalyzerFeature.norm); - features.add(AnalyzerFeature.position); - - StopwordsAnalyzerProperties properties = new StopwordsAnalyzerProperties() - .addStopwordAsHex("616e64") - .addStopwordAsString("the"); - - assertThat(properties.getStopwordsAsStringList()).contains("and"); - assertThat(properties.getStopwordsAsHexList()).contains("746865"); - - StopwordsAnalyzer analyzer = new StopwordsAnalyzer(); - String name = "test-" + UUID.randomUUID(); - analyzer.setName(name); - analyzer.setProperties(properties); - analyzer.setFeatures(features); - - createGetAndDeleteTypedAnalyzer(db, analyzer); - db.createSearchAnalyzer(analyzer); - Collection res = db.query("RETURN FLATTEN(TOKENS(SPLIT('the fox and the dog and a theater', ' '), " + - "@aName))", - Collections.singletonMap("aName", name), Collection.class).next(); - assertThat(res).containsExactly("fox", "dog", "a", "theater"); - db.deleteSearchAnalyzer(name); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void aqlAnalyzer(ArangoDatabase db) { - assumeTrue(isAtLeastVersion(3, 8)); - - AQLAnalyzerProperties properties = new AQLAnalyzerProperties(); - properties.setBatchSize(2); - properties.setCollapsePositions(true); - properties.setKeepNull(false); - properties.setMemoryLimit(2200L); - properties.setQueryString("RETURN SOUNDEX(@param)"); - properties.setReturnType(AQLAnalyzerProperties.ReturnType.string); - - Set features = new HashSet<>(); - features.add(AnalyzerFeature.frequency); - features.add(AnalyzerFeature.norm); - features.add(AnalyzerFeature.position); - - AQLAnalyzer aqlAnalyzer = new AQLAnalyzer(); - aqlAnalyzer.setName("test-" + UUID.randomUUID()); - aqlAnalyzer.setProperties(properties); - aqlAnalyzer.setFeatures(features); - - createGetAndDeleteTypedAnalyzer(db, aqlAnalyzer); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void geoJsonAnalyzer(ArangoDatabase db) { - assumeTrue(isAtLeastVersion(3, 8)); - - GeoAnalyzerOptions options = new GeoAnalyzerOptions(); - options.setMaxLevel(10); - options.setMaxCells(11); - options.setMinLevel(8); - - GeoJSONAnalyzerProperties properties = new GeoJSONAnalyzerProperties(); - properties.setOptions(options); - properties.setType(GeoJSONAnalyzerProperties.GeoJSONAnalyzerType.point); - - Set features = new HashSet<>(); - features.add(AnalyzerFeature.frequency); - features.add(AnalyzerFeature.norm); - features.add(AnalyzerFeature.position); - - GeoJSONAnalyzer geoJSONAnalyzer = new GeoJSONAnalyzer(); - geoJSONAnalyzer.setName("test-" + UUID.randomUUID()); - geoJSONAnalyzer.setProperties(properties); - geoJSONAnalyzer.setFeatures(features); - - createGetAndDeleteTypedAnalyzer(db, geoJSONAnalyzer); - } - - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void geoPointAnalyzer(ArangoDatabase db) { - assumeTrue(isAtLeastVersion(3, 8)); - - GeoAnalyzerOptions options = new GeoAnalyzerOptions(); - options.setMaxLevel(10); - options.setMaxCells(11); - options.setMinLevel(8); - - GeoPointAnalyzerProperties properties = new GeoPointAnalyzerProperties(); - properties.setLatitude(new String[]{"a", "b", "c"}); - properties.setLongitude(new String[]{"d", "e", "f"}); - properties.setOptions(options); - - Set features = new HashSet<>(); - features.add(AnalyzerFeature.frequency); - features.add(AnalyzerFeature.norm); - features.add(AnalyzerFeature.position); - - GeoPointAnalyzer geoPointAnalyzer = new GeoPointAnalyzer(); - geoPointAnalyzer.setName("test-" + UUID.randomUUID()); - geoPointAnalyzer.setProperties(properties); - geoPointAnalyzer.setFeatures(features); - - createGetAndDeleteTypedAnalyzer(db, geoPointAnalyzer); - } - - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void segmentationAnalyzer(ArangoDatabase db) { - assumeTrue(isAtLeastVersion(3, 9)); - - SegmentationAnalyzerProperties properties = new SegmentationAnalyzerProperties(); - properties.setBreakMode(SegmentationAnalyzerProperties.BreakMode.graphic); - properties.setAnalyzerCase(SearchAnalyzerCase.upper); - - Set features = new HashSet<>(); - features.add(AnalyzerFeature.frequency); - features.add(AnalyzerFeature.norm); - features.add(AnalyzerFeature.position); - - SegmentationAnalyzer segmentationAnalyzer = new SegmentationAnalyzer(); - segmentationAnalyzer.setName("test-" + UUID.randomUUID()); - segmentationAnalyzer.setProperties(properties); - segmentationAnalyzer.setFeatures(features); - - createGetAndDeleteTypedAnalyzer(db, segmentationAnalyzer); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void collationAnalyzer(ArangoDatabase db) { - assumeTrue(isAtLeastVersion(3, 9)); - - CollationAnalyzerProperties properties = new CollationAnalyzerProperties(); - properties.setLocale("ru"); - - Set features = new HashSet<>(); - features.add(AnalyzerFeature.frequency); - features.add(AnalyzerFeature.norm); - features.add(AnalyzerFeature.position); - - CollationAnalyzer collationAnalyzer = new CollationAnalyzer(); - collationAnalyzer.setName("test-" + UUID.randomUUID()); - collationAnalyzer.setProperties(properties); - collationAnalyzer.setFeatures(features); - - createGetAndDeleteTypedAnalyzer(db, collationAnalyzer); - } - - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void classificationAnalyzer(ArangoDatabase db) { - assumeTrue(isAtLeastVersion(3, 10)); - assumeTrue(isEnterprise()); - - ClassificationAnalyzerProperties properties = new ClassificationAnalyzerProperties(); - properties.setModelLocation("/tmp/foo.bin"); - properties.setTopK(2); - properties.setThreshold(.5); - - Set features = new HashSet<>(); - features.add(AnalyzerFeature.frequency); - features.add(AnalyzerFeature.norm); - features.add(AnalyzerFeature.position); - - ClassificationAnalyzer analyzer = new ClassificationAnalyzer(); - analyzer.setName("test-" + UUID.randomUUID()); - analyzer.setProperties(properties); - analyzer.setFeatures(features); - - createGetAndDeleteTypedAnalyzer(db, analyzer); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void nearestNeighborsAnalyzer(ArangoDatabase db) { - assumeTrue(isAtLeastVersion(3, 10)); - assumeTrue(isEnterprise()); - - NearestNeighborsAnalyzerProperties properties = new NearestNeighborsAnalyzerProperties(); - properties.setModelLocation("/tmp/foo.bin"); - properties.setTopK(2); - - Set features = new HashSet<>(); - features.add(AnalyzerFeature.frequency); - features.add(AnalyzerFeature.norm); - features.add(AnalyzerFeature.position); - - NearestNeighborsAnalyzer analyzer = new NearestNeighborsAnalyzer(); - analyzer.setName("test-" + UUID.randomUUID()); - analyzer.setProperties(properties); - analyzer.setFeatures(features); - - createGetAndDeleteTypedAnalyzer(db, analyzer); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void MinHashAnalyzer(ArangoDatabase db) { - assumeTrue(isAtLeastVersion(3, 10)); - assumeTrue(isEnterprise()); - - SegmentationAnalyzerProperties segProperties = new SegmentationAnalyzerProperties(); - segProperties.setBreakMode(SegmentationAnalyzerProperties.BreakMode.alpha); - segProperties.setAnalyzerCase(SearchAnalyzerCase.lower); - - SegmentationAnalyzer segAnalyzer = new SegmentationAnalyzer(); - segAnalyzer.setProperties(segProperties); - - MinHashAnalyzerProperties properties = new MinHashAnalyzerProperties(); - properties.setAnalyzer(segAnalyzer); - properties.setNumHashes(2); - - Set features = new HashSet<>(); - features.add(AnalyzerFeature.frequency); - features.add(AnalyzerFeature.norm); - features.add(AnalyzerFeature.position); - - MinHashAnalyzer analyzer = new MinHashAnalyzer(); - analyzer.setName("test-" + UUID.randomUUID()); - analyzer.setProperties(properties); - analyzer.setFeatures(features); - - createGetAndDeleteTypedAnalyzer(db, analyzer); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void offsetFeature(ArangoDatabase db) { - assumeTrue(isAtLeastVersion(3, 10)); - - String name = "test-" + UUID.randomUUID(); - - Set features = new HashSet<>(); - features.add(AnalyzerFeature.frequency); - features.add(AnalyzerFeature.norm); - features.add(AnalyzerFeature.position); - features.add(AnalyzerFeature.offset); - - IdentityAnalyzer analyzer = new IdentityAnalyzer(); - analyzer.setFeatures(features); - analyzer.setName(name); - - createGetAndDeleteTypedAnalyzer(db, analyzer); - } - -} diff --git a/shaded-integration-tests/src/test/native/java/com/arangodb/ArangoSslTest.java b/shaded-integration-tests/src/test/native/java/com/arangodb/ArangoSslTest.java deleted file mode 100644 index 1c9c2bd3a..000000000 --- a/shaded-integration-tests/src/test/native/java/com/arangodb/ArangoSslTest.java +++ /dev/null @@ -1,101 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb; - -import com.arangodb.entity.ArangoDBVersion; -import org.junit.jupiter.api.Tag; -import org.junit.jupiter.api.condition.EnabledIfSystemProperty; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.EnumSource; - -import javax.net.ssl.KeyManagerFactory; -import javax.net.ssl.SSLContext; -import javax.net.ssl.SSLHandshakeException; -import javax.net.ssl.TrustManagerFactory; -import java.security.KeyStore; -import java.util.List; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.catchThrowable; - - -/** - * @author Mark Vollmary - * @author Michele Rastelli - */ -@Tag("ssl") -@EnabledIfSystemProperty(named = "SslTest", matches = "true") -class ArangoSslTest { - - /* - * a SSL trust store - * - * create the trust store for the self signed certificate: - * keytool -import -alias "my arangodb server cert" -file UnitTests/server.pem -keystore example.truststore - * - * Documentation: - * https://hc.apache.org/httpcomponents-client-ga/httpclient/apidocs/org/apache/http/conn/ssl/SSLSocketFactory.html - */ - private static final String SSL_TRUSTSTORE = "/example.truststore"; - private static final String SSL_TRUSTSTORE_PASSWORD = "12345678"; - - @ParameterizedTest - @EnumSource(Protocol.class) - void connect(Protocol protocol) throws Exception { - final KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType()); - ks.load(this.getClass().getResourceAsStream(SSL_TRUSTSTORE), SSL_TRUSTSTORE_PASSWORD.toCharArray()); - - final KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); - kmf.init(ks, SSL_TRUSTSTORE_PASSWORD.toCharArray()); - - final TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); - tmf.init(ks); - - final SSLContext sc = SSLContext.getInstance("TLS"); - sc.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null); - - final ArangoDB arangoDB = new ArangoDB.Builder() - .useProtocol(protocol) - .host("localhost", 8529) - .password("test") - .useSsl(true) - .sslContext(sc).build(); - final ArangoDBVersion version = arangoDB.getVersion(); - assertThat(version).isNotNull(); - } - - @ParameterizedTest - @EnumSource(Protocol.class) - void connectWithoutValidSslContext(Protocol protocol) { - final ArangoDB arangoDB = new ArangoDB.Builder() - .useProtocol(protocol) - .host("localhost", 8529) - .useSsl(true) - .build(); - Throwable thrown = catchThrowable(arangoDB::getVersion); - assertThat(thrown).isInstanceOf(ArangoDBException.class); - ArangoDBException ex = (ArangoDBException) thrown; - assertThat(ex.getCause()).isInstanceOf(ArangoDBMultipleException.class); - List exceptions = ((ArangoDBMultipleException) ex.getCause()).getExceptions(); - exceptions.forEach(e -> assertThat(e).isInstanceOf(SSLHandshakeException.class)); - } - -} diff --git a/shaded-integration-tests/src/test/native/java/com/arangodb/ArangoVertexCollectionTest.java b/shaded-integration-tests/src/test/native/java/com/arangodb/ArangoVertexCollectionTest.java deleted file mode 100644 index 5b5504d80..000000000 --- a/shaded-integration-tests/src/test/native/java/com/arangodb/ArangoVertexCollectionTest.java +++ /dev/null @@ -1,480 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb; - -import com.arangodb.entity.BaseDocument; -import com.arangodb.entity.VertexEntity; -import com.arangodb.entity.VertexUpdateEntity; -import com.arangodb.model.*; -import com.arangodb.util.RawJson; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.Arguments; -import org.junit.jupiter.params.provider.MethodSource; - -import java.util.Collection; -import java.util.Collections; -import java.util.UUID; -import java.util.stream.Stream; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.catchThrowable; - - -/** - * @author Mark Vollmary - * @author Michele Rastelli - */ -class ArangoVertexCollectionTest extends BaseJunit5 { - - private static final String GRAPH_NAME = "ArangoVertexCollectionTest_graph"; - private static final String COLLECTION_NAME = "ArangoVertexCollectionTest_vertex_collection"; - - private static Stream vertices() { - return dbsStream() - .map(db -> db.graph(GRAPH_NAME).vertexCollection(COLLECTION_NAME)) - .map(Arguments::of); - } - - @BeforeAll - static void init() { - initCollections(COLLECTION_NAME); - initGraph( - GRAPH_NAME, - null, - new GraphCreateOptions().orphanCollections(COLLECTION_NAME) - ); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("vertices") - void dropVertexCollection(ArangoVertexCollection vertices) { - ArangoGraph graph = vertices.graph(); - vertices.drop(); - final Collection vertexCollections = graph.getVertexCollections(); - assertThat(vertexCollections).isEmpty(); - - // revert - graph.addVertexCollection(COLLECTION_NAME); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("vertices") - void insertVertex(ArangoVertexCollection vertices) { - final VertexEntity vertex = vertices - .insertVertex(new BaseDocument(), null); - assertThat(vertex).isNotNull(); - ArangoCollection collection = vertices.graph().db().collection(vertices.name()); - final BaseDocument document = collection - .getDocument(vertex.getKey(), BaseDocument.class, null); - assertThat(document).isNotNull(); - assertThat(document.getKey()).isEqualTo(vertex.getKey()); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("vertices") - void insertVertexViolatingUniqueConstraint(ArangoVertexCollection vertices) { - ArangoCollection collection = vertices.graph().db().collection(vertices.name()); - collection - .ensureSkiplistIndex(Collections.singletonList("field"), - new SkiplistIndexOptions().unique(true).sparse(true)); - - VertexEntity inserted = vertices.insertVertex(RawJson.of("{\"field\": 99}")); - - try { - vertices.insertVertex(RawJson.of("{\"field\": 99}")); - } catch (ArangoDBException e) { - assertThat(e.getResponseCode()).isEqualTo(409); - assertThat(e.getErrorNum()).isEqualTo(1210); - } - - // revert - vertices.deleteVertex(inserted.getKey()); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("vertices") - void duplicateInsertSameObjectVertex(ArangoVertexCollection vertices) { - - // ######################################################### - // Create a new BaseDocument - // ######################################################### - - UUID uuid = UUID.randomUUID(); - BaseDocument bd = new BaseDocument(UUID.randomUUID().toString()); - bd.setKey(uuid.toString()); - bd.addAttribute("name", "Paul"); - - vertices.insertVertex(bd); - - UUID uuid2 = UUID.randomUUID(); - BaseDocument bd2 = new BaseDocument(UUID.randomUUID().toString()); - bd2.setKey(uuid2.toString()); - bd2.addAttribute("name", "Paul"); - - vertices.insertVertex(bd2); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("vertices") - void insertVertexUpdateRev(ArangoVertexCollection vertices) { - final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); - final VertexEntity vertex = vertices.insertVertex(doc, null); - assertThat(doc.getRevision()).isNull(); - assertThat(vertex.getRev()).isNotNull(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("vertices") - void getVertex(ArangoVertexCollection vertices) { - final VertexEntity vertex = vertices - .insertVertex(new BaseDocument(), null); - final BaseDocument document = vertices - .getVertex(vertex.getKey(), BaseDocument.class, null); - assertThat(document).isNotNull(); - assertThat(document.getKey()).isEqualTo(vertex.getKey()); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("vertices") - void getVertexIfMatch(ArangoVertexCollection vertices) { - final VertexEntity vertex = vertices - .insertVertex(new BaseDocument(), null); - final GraphDocumentReadOptions options = new GraphDocumentReadOptions().ifMatch(vertex.getRev()); - final BaseDocument document = vertices - .getVertex(vertex.getKey(), BaseDocument.class, options); - assertThat(document).isNotNull(); - assertThat(document.getKey()).isEqualTo(vertex.getKey()); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("vertices") - void getVertexIfMatchFail(ArangoVertexCollection vertices) { - final VertexEntity vertex = vertices - .insertVertex(new BaseDocument(), null); - final GraphDocumentReadOptions options = new GraphDocumentReadOptions().ifMatch("no"); - final BaseDocument vertex2 = vertices - .getVertex(vertex.getKey(), BaseDocument.class, options); - assertThat(vertex2).isNull(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("vertices") - void getVertexIfNoneMatch(ArangoVertexCollection vertices) { - final VertexEntity vertex = vertices - .insertVertex(new BaseDocument(), null); - final GraphDocumentReadOptions options = new GraphDocumentReadOptions().ifNoneMatch("no"); - final BaseDocument document = vertices - .getVertex(vertex.getKey(), BaseDocument.class, options); - assertThat(document).isNotNull(); - assertThat(document.getKey()).isEqualTo(vertex.getKey()); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("vertices") - void getVertexIfNoneMatchFail(ArangoVertexCollection vertices) { - final VertexEntity vertex = vertices - .insertVertex(new BaseDocument(), null); - final GraphDocumentReadOptions options = new GraphDocumentReadOptions().ifNoneMatch(vertex.getRev()); - final BaseDocument vertex2 = vertices - .getVertex(vertex.getKey(), BaseDocument.class, options); - assertThat(vertex2).isNull(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("vertices") - void replaceVertex(ArangoVertexCollection vertices) { - final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); - doc.addAttribute("a", "test"); - final VertexEntity createResult = vertices - .insertVertex(doc, null); - doc.removeAttribute("a"); - doc.addAttribute("b", "test"); - final VertexUpdateEntity replaceResult = vertices - .replaceVertex(createResult.getKey(), doc, null); - assertThat(replaceResult).isNotNull(); - assertThat(replaceResult.getId()).isEqualTo(createResult.getId()); - assertThat(replaceResult.getRev()).isNotEqualTo(replaceResult.getOldRev()); - assertThat(replaceResult.getOldRev()).isEqualTo(createResult.getRev()); - - final BaseDocument readResult = vertices - .getVertex(createResult.getKey(), BaseDocument.class, null); - assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); - assertThat(readResult.getRevision()).isEqualTo(replaceResult.getRev()); - assertThat(readResult.getProperties().keySet()).doesNotContain("a"); - assertThat(readResult.getAttribute("b")).isNotNull(); - assertThat(String.valueOf(readResult.getAttribute("b"))).isEqualTo("test"); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("vertices") - void replaceVertexUpdateRev(ArangoVertexCollection vertices) { - final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); - final VertexEntity createResult = vertices - .insertVertex(doc, null); - final VertexUpdateEntity replaceResult = vertices - .replaceVertex(createResult.getKey(), doc, null); - assertThat(doc.getRevision()).isNull(); - assertThat(createResult.getRev()).isNotNull(); - assertThat(replaceResult.getRev()) - .isNotNull() - .isNotEqualTo(createResult.getRev()); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("vertices") - void replaceVertexIfMatch(ArangoVertexCollection vertices) { - final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); - doc.addAttribute("a", "test"); - final VertexEntity createResult = vertices - .insertVertex(doc, null); - doc.removeAttribute("a"); - doc.addAttribute("b", "test"); - final VertexReplaceOptions options = new VertexReplaceOptions().ifMatch(createResult.getRev()); - final VertexUpdateEntity replaceResult = vertices - .replaceVertex(createResult.getKey(), doc, options); - assertThat(replaceResult).isNotNull(); - assertThat(replaceResult.getId()).isEqualTo(createResult.getId()); - assertThat(replaceResult.getRev()).isNotEqualTo(replaceResult.getOldRev()); - assertThat(replaceResult.getOldRev()).isEqualTo(createResult.getRev()); - - final BaseDocument readResult = vertices - .getVertex(createResult.getKey(), BaseDocument.class, null); - assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); - assertThat(readResult.getRevision()).isEqualTo(replaceResult.getRev()); - assertThat(readResult.getProperties().keySet()).doesNotContain("a"); - assertThat(readResult.getAttribute("b")).isNotNull(); - assertThat(String.valueOf(readResult.getAttribute("b"))).isEqualTo("test"); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("vertices") - void replaceVertexIfMatchFail(ArangoVertexCollection vertices) { - final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); - doc.addAttribute("a", "test"); - final VertexEntity createResult = vertices - .insertVertex(doc, null); - doc.removeAttribute("a"); - doc.addAttribute("b", "test"); - final VertexReplaceOptions options = new VertexReplaceOptions().ifMatch("no"); - Throwable thrown = catchThrowable(() -> vertices.replaceVertex(createResult.getKey(), doc, options)); - assertThat(thrown).isInstanceOf(ArangoDBException.class); - ArangoDBException e = (ArangoDBException) thrown; - assertThat(e.getResponseCode()).isEqualTo(412); - assertThat(e.getErrorNum()).isEqualTo(1200); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("vertices") - void updateVertex(ArangoVertexCollection vertices) { - final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); - doc.addAttribute("a", "test"); - doc.addAttribute("c", "test"); - final VertexEntity createResult = vertices - .insertVertex(doc, null); - doc.updateAttribute("a", "test1"); - doc.addAttribute("b", "test"); - doc.updateAttribute("c", null); - final VertexUpdateEntity updateResult = vertices - .updateVertex(createResult.getKey(), doc, null); - assertThat(updateResult).isNotNull(); - assertThat(updateResult.getId()).isEqualTo(createResult.getId()); - assertThat(updateResult.getRev()).isNotEqualTo(updateResult.getOldRev()); - assertThat(updateResult.getOldRev()).isEqualTo(createResult.getRev()); - - final BaseDocument readResult = vertices - .getVertex(createResult.getKey(), BaseDocument.class, null); - assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); - assertThat(readResult.getAttribute("a")).isNotNull(); - assertThat(String.valueOf(readResult.getAttribute("a"))).isEqualTo("test1"); - assertThat(readResult.getAttribute("b")).isNotNull(); - assertThat(String.valueOf(readResult.getAttribute("b"))).isEqualTo("test"); - assertThat(readResult.getRevision()).isEqualTo(updateResult.getRev()); - assertThat(readResult.getProperties()).containsKey("c"); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("vertices") - void updateVertexUpdateRev(ArangoVertexCollection vertices) { - final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); - final VertexEntity createResult = vertices - .insertVertex(doc, null); - doc.addAttribute("foo", "bar"); - final VertexUpdateEntity updateResult = vertices - .updateVertex(createResult.getKey(), doc, null); - assertThat(doc.getRevision()).isNull(); - assertThat(createResult.getRev()).isNotNull(); - assertThat(updateResult.getRev()) - .isNotNull() - .isNotEqualTo(createResult.getRev()); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("vertices") - void updateVertexIfMatch(ArangoVertexCollection vertices) { - final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); - doc.addAttribute("a", "test"); - doc.addAttribute("c", "test"); - final VertexEntity createResult = vertices - .insertVertex(doc, null); - doc.updateAttribute("a", "test1"); - doc.addAttribute("b", "test"); - doc.updateAttribute("c", null); - final VertexUpdateOptions options = new VertexUpdateOptions().ifMatch(createResult.getRev()); - final VertexUpdateEntity updateResult = vertices - .updateVertex(createResult.getKey(), doc, options); - assertThat(updateResult).isNotNull(); - assertThat(updateResult.getId()).isEqualTo(createResult.getId()); - assertThat(updateResult.getRev()).isNotEqualTo(updateResult.getOldRev()); - assertThat(updateResult.getOldRev()).isEqualTo(createResult.getRev()); - - final BaseDocument readResult = vertices - .getVertex(createResult.getKey(), BaseDocument.class, null); - assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); - assertThat(readResult.getAttribute("a")).isNotNull(); - assertThat(String.valueOf(readResult.getAttribute("a"))).isEqualTo("test1"); - assertThat(readResult.getAttribute("b")).isNotNull(); - assertThat(String.valueOf(readResult.getAttribute("b"))).isEqualTo("test"); - assertThat(readResult.getRevision()).isEqualTo(updateResult.getRev()); - assertThat(readResult.getProperties()).containsKey("c"); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("vertices") - void updateVertexIfMatchFail(ArangoVertexCollection vertices) { - final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); - doc.addAttribute("a", "test"); - doc.addAttribute("c", "test"); - final VertexEntity createResult = vertices - .insertVertex(doc, null); - doc.updateAttribute("a", "test1"); - doc.addAttribute("b", "test"); - doc.updateAttribute("c", null); - final VertexUpdateOptions options = new VertexUpdateOptions().ifMatch("no"); - - Throwable thrown = catchThrowable(() -> vertices.updateVertex(createResult.getKey(), doc, options)); - assertThat(thrown).isInstanceOf(ArangoDBException.class); - ArangoDBException e = (ArangoDBException) thrown; - assertThat(e.getResponseCode()).isEqualTo(412); - assertThat(e.getErrorNum()).isEqualTo(1200); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("vertices") - void updateVertexKeepNullTrue(ArangoVertexCollection vertices) { - final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); - doc.addAttribute("a", "test"); - final VertexEntity createResult = vertices - .insertVertex(doc, null); - doc.updateAttribute("a", null); - final VertexUpdateOptions options = new VertexUpdateOptions().keepNull(true); - final VertexUpdateEntity updateResult = vertices - .updateVertex(createResult.getKey(), doc, options); - assertThat(updateResult).isNotNull(); - assertThat(updateResult.getId()).isEqualTo(createResult.getId()); - assertThat(updateResult.getRev()).isNotEqualTo(updateResult.getOldRev()); - assertThat(updateResult.getOldRev()).isEqualTo(createResult.getRev()); - - final BaseDocument readResult = vertices - .getVertex(createResult.getKey(), BaseDocument.class, null); - assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); - assertThat(readResult.getProperties().keySet()).hasSize(4); - assertThat(readResult.getProperties()).containsKey("a"); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("vertices") - void updateVertexKeepNullFalse(ArangoVertexCollection vertices) { - final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); - doc.addAttribute("a", "test"); - final VertexEntity createResult = vertices - .insertVertex(doc, null); - doc.updateAttribute("a", null); - final VertexUpdateOptions options = new VertexUpdateOptions().keepNull(false); - final VertexUpdateEntity updateResult = vertices - .updateVertex(createResult.getKey(), doc, options); - assertThat(updateResult).isNotNull(); - assertThat(updateResult.getId()).isEqualTo(createResult.getId()); - assertThat(updateResult.getRev()).isNotEqualTo(updateResult.getOldRev()); - assertThat(updateResult.getOldRev()).isEqualTo(createResult.getRev()); - - final BaseDocument readResult = vertices - .getVertex(createResult.getKey(), BaseDocument.class, null); - assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); - assertThat(readResult.getId()).isEqualTo(createResult.getId()); - assertThat(readResult.getRevision()).isNotNull(); - assertThat(readResult.getProperties().keySet()).doesNotContain("a"); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("vertices") - void deleteVertex(ArangoVertexCollection vertices) { - final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); - final VertexEntity createResult = vertices - .insertVertex(doc, null); - vertices.deleteVertex(createResult.getKey(), null); - final BaseDocument vertex = vertices - .getVertex(createResult.getKey(), BaseDocument.class, null); - assertThat(vertex).isNull(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("vertices") - void deleteVertexIfMatch(ArangoVertexCollection vertices) { - final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); - final VertexEntity createResult = vertices - .insertVertex(doc, null); - final VertexDeleteOptions options = new VertexDeleteOptions().ifMatch(createResult.getRev()); - vertices.deleteVertex(createResult.getKey(), options); - final BaseDocument vertex = vertices - .getVertex(createResult.getKey(), BaseDocument.class, null); - assertThat(vertex).isNull(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("vertices") - void deleteVertexIfMatchFail(ArangoVertexCollection vertices) { - final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); - final VertexEntity createResult = vertices - .insertVertex(doc, null); - final VertexDeleteOptions options = new VertexDeleteOptions().ifMatch("no"); - Throwable thrown = catchThrowable(() -> vertices.deleteVertex(createResult.getKey(), options)); - assertThat(thrown).isInstanceOf(ArangoDBException.class); - ArangoDBException e = (ArangoDBException) thrown; - assertThat(e.getResponseCode()).isEqualTo(412); - assertThat(e.getErrorNum()).isEqualTo(1200); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("vertices") - void vertexKeyWithSpecialChars(ArangoVertexCollection vertices) { - final String key = "_-:.@()+,=;$!*'%" + UUID.randomUUID(); - final VertexEntity vertex = vertices - .insertVertex(new BaseDocument(key), null); - assertThat(vertex).isNotNull(); - ArangoCollection collection = vertices.graph().db().collection(vertices.name()); - final BaseDocument document = collection - .getDocument(vertex.getKey(), BaseDocument.class, null); - assertThat(document).isNotNull(); - assertThat(document.getKey()).isEqualTo(key); - } - -} diff --git a/shaded-integration-tests/src/test/native/java/com/arangodb/ArangoViewTest.java b/shaded-integration-tests/src/test/native/java/com/arangodb/ArangoViewTest.java deleted file mode 100644 index 09121b7ff..000000000 --- a/shaded-integration-tests/src/test/native/java/com/arangodb/ArangoViewTest.java +++ /dev/null @@ -1,114 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2018 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb; - -import com.arangodb.entity.ViewEntity; -import com.arangodb.entity.ViewType; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.MethodSource; - -import java.util.Collection; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assumptions.assumeTrue; - - -/** - * @author Mark Vollmary - * @author Michele Rastelli - */ -class ArangoViewTest extends BaseJunit5 { - - @BeforeAll - static void init() { - initDB(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void exists(ArangoDatabase db) { - String name = "view-" + rnd(); - db.createView(name, ViewType.ARANGO_SEARCH); - assertThat(db.view(name).exists()).isTrue(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void getInfo(ArangoDatabase db) { - String name = "view-" + rnd(); - db.createView(name, ViewType.ARANGO_SEARCH); - final ViewEntity info = db.view(name).getInfo(); - assertThat(info).isNotNull(); - assertThat(info.getId()).isNotNull(); - assertThat(info.getName()).isEqualTo(name); - assertThat(info.getType()).isEqualTo(ViewType.ARANGO_SEARCH); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void getInfoSearchAlias(ArangoDatabase db) { - assumeTrue(isAtLeastVersion(3, 10)); - String name = "view-" + rnd(); - db.createView(name, ViewType.SEARCH_ALIAS); - final ViewEntity info = db.view(name).getInfo(); - assertThat(info).isNotNull(); - assertThat(info.getId()).isNotNull(); - assertThat(info.getName()).isEqualTo(name); - assertThat(info.getType()).isEqualTo(ViewType.SEARCH_ALIAS); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void getViews(ArangoDatabase db) { - assumeTrue(isAtLeastVersion(3, 10)); - String name1 = "view-" + rnd(); - String name2 = "view-" + rnd(); - db.createView(name1, ViewType.ARANGO_SEARCH); - db.createView(name2, ViewType.SEARCH_ALIAS); - Collection views = db.getViews(); - assertThat(views).extracting(ViewEntity::getName).contains(name1, name2); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void drop(ArangoDatabase db) { - String name = "view-" + rnd(); - db.createView(name, ViewType.ARANGO_SEARCH); - final ArangoView view = db.view(name); - view.drop(); - assertThat(view.exists()).isFalse(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void rename(ArangoDatabase db) { - assumeTrue(isSingleServer()); - String oldName = "view-" + rnd(); - String newName = "view-" + rnd(); - - db.createView(oldName, ViewType.ARANGO_SEARCH); - db.view(oldName).rename(newName); - assertThat(db.view(oldName).exists()).isFalse(); - assertThat(db.view(newName).exists()).isTrue(); - } - -} diff --git a/shaded-integration-tests/src/test/native/java/com/arangodb/BaseJunit5.java b/shaded-integration-tests/src/test/native/java/com/arangodb/BaseJunit5.java deleted file mode 100644 index 3e6c8e30a..000000000 --- a/shaded-integration-tests/src/test/native/java/com/arangodb/BaseJunit5.java +++ /dev/null @@ -1,129 +0,0 @@ -package com.arangodb; - -import com.arangodb.config.ArangoConfigProperties; -import com.arangodb.config.ConfigUtils; -import com.arangodb.entity.*; -import com.arangodb.model.CollectionCreateOptions; -import com.arangodb.model.GraphCreateOptions; -import com.arangodb.util.TestUtils; -import org.junit.jupiter.api.AfterAll; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.params.provider.Arguments; - -import java.util.Arrays; -import java.util.Collection; -import java.util.List; -import java.util.UUID; -import java.util.stream.Stream; - -class BaseJunit5 { - protected static final DbName TEST_DB = DbName.of("java_driver_test_db"); - protected static final ArangoConfigProperties config = ConfigUtils.loadConfig(); - private static final List adbs = Arrays.asList( - new ArangoDB.Builder().loadProperties(config).useProtocol(Protocol.VST).build(), - new ArangoDB.Builder().loadProperties(config).useProtocol(Protocol.HTTP_VPACK).build(), - new ArangoDB.Builder().loadProperties(config).useProtocol(Protocol.HTTP_JSON).build(), - new ArangoDB.Builder().loadProperties(config).useProtocol(Protocol.HTTP2_VPACK).build(), - new ArangoDB.Builder().loadProperties(config).useProtocol(Protocol.HTTP2_JSON).build() - ); - - protected static Stream dbsStream() { - return adbs.stream().map(adb -> adb.db(TEST_DB)); - } - - protected static Stream arangos() { - return adbs.stream().map(Arguments::of); - } - - protected static Stream dbs() { - return dbsStream().map(Arguments::of); - } - - static ArangoDatabase initDB(DbName name) { - ArangoDatabase database = adbs.get(0).db(name); - if (!database.exists()) - database.create(); - return database; - } - - static ArangoDatabase initDB() { - return initDB(TEST_DB); - } - - static void dropDB(DbName name) { - ArangoDatabase database = adbs.get(0).db(name); - if (database.exists()) - database.drop(); - } - - static void initGraph(String name, Collection edgeDefinitions, GraphCreateOptions options) { - ArangoDatabase db = initDB(); - db.createGraph(name, edgeDefinitions, options); - } - - static void initCollections(String... collections) { - ArangoDatabase db = initDB(); - for (String collection : collections) { - if (db.collection(collection).exists()) - db.collection(collection).drop(); - db.createCollection(collection, null); - } - } - - static void initEdgeCollections(String... collections) { - ArangoDatabase db = initDB(); - for (String collection : collections) { - if (db.collection(collection).exists()) - db.collection(collection).drop(); - db.createCollection(collection, new CollectionCreateOptions().type(CollectionType.EDGES)); - } - } - - @BeforeAll - static void init() { - dropDB(TEST_DB); - } - - @AfterAll - static void shutdown() { - dropDB(TEST_DB); - } - - static String rnd() { - return UUID.randomUUID().toString(); - } - - boolean isAtLeastVersion(final int major, final int minor) { - return isAtLeastVersion(major, minor, 0); - } - - boolean isAtLeastVersion(final int major, final int minor, final int patch) { - return TestUtils.isAtLeastVersion(adbs.get(0).getVersion().getVersion(), major, minor, patch); - } - - boolean isLessThanVersion(final int major, final int minor) { - return isLessThanVersion(major, minor, 0); - } - - boolean isLessThanVersion(final int major, final int minor, final int patch) { - return TestUtils.isLessThanVersion(adbs.get(0).getVersion().getVersion(), major, minor, patch); - } - - boolean isStorageEngine(ArangoDBEngine.StorageEngineName name) { - return name.equals(adbs.get(0).getEngine().getName()); - } - - boolean isSingleServer() { - return adbs.get(0).getRole() == ServerRole.SINGLE; - } - - boolean isCluster() { - return adbs.get(0).getRole() == ServerRole.COORDINATOR; - } - - boolean isEnterprise() { - return adbs.get(0).getVersion().getLicense() == License.ENTERPRISE; - } - - -} diff --git a/shaded-integration-tests/src/test/native/java/com/arangodb/ConcurrencyTests.java b/shaded-integration-tests/src/test/native/java/com/arangodb/ConcurrencyTests.java deleted file mode 100644 index 3efdacc9c..000000000 --- a/shaded-integration-tests/src/test/native/java/com/arangodb/ConcurrencyTests.java +++ /dev/null @@ -1,34 +0,0 @@ -package com.arangodb; - -import com.arangodb.config.ConfigUtils; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.EnumSource; - -import java.util.List; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.stream.Collectors; -import java.util.stream.IntStream; - -class ConcurrencyTests { - - @ParameterizedTest - @EnumSource(Protocol.class) - void concurrentPendingRequests(Protocol protocol) throws ExecutionException, InterruptedException { - ExecutorService es = Executors.newFixedThreadPool(10); - ArangoDB adb = new ArangoDB.Builder() - .loadProperties(ConfigUtils.loadConfig()) - .useProtocol(protocol).build(); - List> futures = IntStream.range(0, 10) - .mapToObj(__ -> CompletableFuture.runAsync(() -> adb.db().query("RETURN SLEEP(1)", Void.class), es)) - .collect(Collectors.toList()); - for (CompletableFuture f : futures) { - f.get(); - } - adb.shutdown(); - es.shutdown(); - } - -} diff --git a/shaded-integration-tests/src/test/native/java/com/arangodb/DocumentTest.java b/shaded-integration-tests/src/test/native/java/com/arangodb/DocumentTest.java deleted file mode 100644 index 0ce14ff53..000000000 --- a/shaded-integration-tests/src/test/native/java/com/arangodb/DocumentTest.java +++ /dev/null @@ -1,138 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb; - -import com.arangodb.entity.BaseDocument; -import com.arangodb.entity.DocumentCreateEntity; -import com.arangodb.util.RawJson; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.Arguments; -import org.junit.jupiter.params.provider.MethodSource; - -import java.util.Map; -import java.util.UUID; -import java.util.stream.Stream; - -import static org.assertj.core.api.Assertions.assertThat; - - -/** - * @author Mark Vollmary - * @author Michele Rastelli - */ -class DocumentTest extends BaseJunit5 { - - private static final String COLLECTION_NAME = "DocumentTest_collection"; - - private static Stream cols() { - return dbsStream() - .map(db -> db.collection(COLLECTION_NAME)) - .map(Arguments::of); - } - - - @BeforeAll - static void init() { - initCollections(COLLECTION_NAME); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void insertAsJson(ArangoCollection collection) { - //@formatter:off - final RawJson json = RawJson.of( - "{" - + "\"article\": {" - + "\"artist\": \"PREGARDIEN/RHEINISCHE KANTOREI/DAS\"," - + "\"releaseDate\": \"1970-01-01\"," - + "\"composer\": \"BACH\"," - + "\"format\": \"CD\"," - + "\"vat\": \"H\"," - + "\"carriers\": 1," - + "\"label\": \"CAPRICCIO\"," - + "\"title\": \"BACH ST MATTHEW PASSION BWV244\"," - + "\"barcode\": [" - + "\"4006408600466\"" - + "]," - + "\"conductor\": \"MAX, H.\"" - + "}," - + "\"stock\": {" - + "\"status\": \"RMV\"," - + "\"lastUpdate\": \"2016-11-01 00:00\"" - + "}" - + "}" - ); - //@formatter:on - final DocumentCreateEntity createResult = collection.insertDocument(json); - final BaseDocument doc = collection.getDocument(createResult.getKey(), BaseDocument.class); - assertThat(doc).isNotNull(); - final Object article = doc.getAttribute("article"); - assertThat(article).isNotNull(); - final Object artist = ((Map) article).get("artist"); - assertThat(artist).isNotNull(); - assertThat(artist.toString()).isEqualTo("PREGARDIEN/RHEINISCHE KANTOREI/DAS"); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void insertAsBaseDocument(ArangoCollection collection) { - final BaseDocument document = new BaseDocument(UUID.randomUUID().toString()); - { - final BaseDocument article = new BaseDocument(UUID.randomUUID().toString()); - document.addAttribute("article", article); - article.addAttribute("artist", "PREGARDIEN/RHEINISCHE KANTOREI/DAS"); - article.addAttribute("releaseDate", "1970-01-01"); - article.addAttribute("composer", "BACH"); - article.addAttribute("format", "CD"); - article.addAttribute("vat", "H"); - article.addAttribute("carriers", 1); - article.addAttribute("label", "CAPRICCIO"); - article.addAttribute("title", "BACH ST MATTHEW PASSION BWV244"); - article.addAttribute("barcode", new String[]{"4006408600466"}); - article.addAttribute("conductor", "MAX, H."); - final BaseDocument stock = new BaseDocument(UUID.randomUUID().toString()); - document.addAttribute("stock", stock); - stock.addAttribute("status", "RMV"); - stock.addAttribute("lastUpdate", "2016-11-01 00:00"); - } - final DocumentCreateEntity createResult = collection.insertDocument(document); - final BaseDocument doc = collection.getDocument(createResult.getKey(), BaseDocument.class); - assertThat(doc).isNotNull(); - final Object article = doc.getAttribute("article"); - assertThat(article).isNotNull(); - final Object artist = ((Map) article).get("artist"); - assertThat(artist).isNotNull(); - assertThat(artist.toString()).isEqualTo("PREGARDIEN/RHEINISCHE KANTOREI/DAS"); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void documentKeyWithSpecialChars(ArangoCollection collection) { - final String key = "_-:.@()+,=;$!*'%" + UUID.randomUUID(); - final BaseDocument document = new BaseDocument(key); - final DocumentCreateEntity createResult = collection.insertDocument(document); - final BaseDocument doc = collection.getDocument(createResult.getKey(), BaseDocument.class); - assertThat(doc).isNotNull(); - assertThat(doc.getKey()).isEqualTo(key); - } - -} diff --git a/shaded-integration-tests/src/test/native/java/com/arangodb/InvertedIndexTest.java b/shaded-integration-tests/src/test/native/java/com/arangodb/InvertedIndexTest.java deleted file mode 100644 index e96bc70ef..000000000 --- a/shaded-integration-tests/src/test/native/java/com/arangodb/InvertedIndexTest.java +++ /dev/null @@ -1,194 +0,0 @@ -package com.arangodb; - -import com.arangodb.entity.*; -import com.arangodb.entity.arangosearch.*; -import com.arangodb.entity.arangosearch.analyzer.DelimiterAnalyzer; -import com.arangodb.entity.arangosearch.analyzer.DelimiterAnalyzerProperties; -import com.arangodb.model.InvertedIndexOptions; -import com.arangodb.model.PersistentIndexOptions; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.Arguments; -import org.junit.jupiter.params.provider.MethodSource; - -import java.util.*; -import java.util.stream.Stream; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assumptions.assumeTrue; - -public class InvertedIndexTest extends BaseJunit5 { - - private static final String COLLECTION_NAME = "InvertedIndexTest_collection"; - - private static Stream cols() { - return dbsStream().map(db -> db.collection(COLLECTION_NAME)).map(Arguments::of); - } - - @BeforeAll - static void init() { - initCollections(COLLECTION_NAME); - } - - private void createAnalyzer(String analyzerName, ArangoDatabase db) { - Set features = new HashSet<>(); - features.add(AnalyzerFeature.frequency); - features.add(AnalyzerFeature.norm); - features.add(AnalyzerFeature.position); - - DelimiterAnalyzer da = new DelimiterAnalyzer(); - da.setName(analyzerName); - da.setFeatures(features); - DelimiterAnalyzerProperties props = new DelimiterAnalyzerProperties(); - props.setDelimiter("-"); - da.setProperties(props); - - db.createSearchAnalyzer(da); - } - - private InvertedIndexOptions createOptions(String analyzerName) { - InvertedIndexField field = new InvertedIndexField() - .name("foo") - .analyzer(AnalyzerType.identity.toString()) - .includeAllFields(true) - .searchField(false) - .trackListPositions(false) - .features( - AnalyzerFeature.position, - AnalyzerFeature.frequency, - AnalyzerFeature.norm, - AnalyzerFeature.offset - ); - - if (isEnterprise()) { - field.nested( - new InvertedIndexField() - .name("bar") - .analyzer(analyzerName) - .searchField(true) - .features(AnalyzerFeature.position, AnalyzerFeature.frequency) - .nested( - new InvertedIndexField() - .name("baz") - .analyzer(AnalyzerType.identity.toString()) - .searchField(false) - .features(AnalyzerFeature.frequency) - ) - ); - } - - return new InvertedIndexOptions() - .name("invertedIndex-" + UUID.randomUUID()) - .inBackground(true) - .parallelism(5) - .primarySort(new InvertedIndexPrimarySort() - .fields( - new InvertedIndexPrimarySort.Field("f1", InvertedIndexPrimarySort.Field.Direction.asc), - new InvertedIndexPrimarySort.Field("f2", InvertedIndexPrimarySort.Field.Direction.desc) - ) - .compression(ArangoSearchCompression.lz4) - ) - .storedValues(new StoredValue(Arrays.asList("f3", "f4"), ArangoSearchCompression.none)) - .analyzer(analyzerName) - .features(AnalyzerFeature.position, AnalyzerFeature.frequency) - .includeAllFields(false) - .trackListPositions(true) - .searchField(true) - .fields(field) - .consolidationIntervalMsec(11L) - .commitIntervalMsec(22L) - .cleanupIntervalStep(33L) - .consolidationPolicy(ConsolidationPolicy.of(ConsolidationType.TIER) - .segmentsMin(3L) - .segmentsMax(44L) - .segmentsBytesMax(55555L) - .segmentsBytesFloor(666L) - .minScore(77L) - ) - .writebufferIdle(44L) - .writebufferActive(55L) - .writebufferSizeMax(66L); - } - - private void assertCorrectIndexEntity(InvertedIndexEntity indexResult, InvertedIndexOptions options) { - assertThat(indexResult).isNotNull(); - assertThat(indexResult.getId()).isNotNull().isNotEmpty(); - // FIXME: in single server this is null - // assertThat(indexResult.getIsNewlyCreated()).isTrue(); - assertThat(indexResult.getUnique()).isFalse(); - assertThat(indexResult.getSparse()).isTrue(); - assertThat(indexResult.getVersion()).isNotNull(); - assertThat(indexResult.getCode()).isNotNull(); - assertThat(indexResult.getType()).isEqualTo(IndexType.inverted); - assertThat(indexResult.getName()).isEqualTo(options.getName()); - assertThat(indexResult.getFields()).containsExactlyElementsOf(options.getFields()); - assertThat(indexResult.getSearchField()).isEqualTo(options.getSearchField()); - assertThat(indexResult.getStoredValues()).containsExactlyElementsOf(options.getStoredValues()); - assertThat(indexResult.getPrimarySort()).isEqualTo(options.getPrimarySort()); - assertThat(indexResult.getAnalyzer()).isEqualTo(options.getAnalyzer()); - assertThat(indexResult.getFeatures()).hasSameElementsAs(options.getFeatures()); - assertThat(indexResult.getIncludeAllFields()).isEqualTo(options.getIncludeAllFields()); - assertThat(indexResult.getTrackListPositions()).isEqualTo(options.getTrackListPositions()); - assertThat(indexResult.getCleanupIntervalStep()).isEqualTo(options.getCleanupIntervalStep()); - assertThat(indexResult.getCommitIntervalMsec()).isEqualTo(options.getCommitIntervalMsec()); - assertThat(indexResult.getConsolidationIntervalMsec()).isEqualTo(options.getConsolidationIntervalMsec()); - assertThat(indexResult.getConsolidationPolicy()).isEqualTo(options.getConsolidationPolicy()); - assertThat(indexResult.getWritebufferIdle()).isEqualTo(options.getWritebufferIdle()); - assertThat(indexResult.getWritebufferActive()).isEqualTo(options.getWritebufferActive()); - assertThat(indexResult.getWritebufferSizeMax()).isEqualTo(options.getWritebufferSizeMax()); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void createAndGetInvertedIndex(ArangoCollection collection) { - assumeTrue(isAtLeastVersion(3, 10)); - String analyzerName = "delimiter-" + UUID.randomUUID(); - createAnalyzer(analyzerName, collection.db()); - InvertedIndexOptions options = createOptions(analyzerName); - InvertedIndexEntity created = collection.ensureInvertedIndex(options); - assertCorrectIndexEntity(created, options); - InvertedIndexEntity loadedIndex = collection.getInvertedIndex(created.getName()); - assertCorrectIndexEntity(loadedIndex, options); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void getInvertedIndexesShouldNotReturnOtherIndexTypes(ArangoCollection collection) { - assumeTrue(isAtLeastVersion(3, 10)); - - // create persistent index - collection.ensurePersistentIndex(Collections.singletonList("foo"), new PersistentIndexOptions().name("persistentIndex")); - - // create inverted index - String analyzerName = "delimiter-" + UUID.randomUUID(); - createAnalyzer(analyzerName, collection.db()); - InvertedIndexOptions options = createOptions(analyzerName); - InvertedIndexEntity created = collection.ensureInvertedIndex(options); - - Collection loadedIndexes = collection.getInvertedIndexes(); - assertThat(loadedIndexes).map(InvertedIndexEntity::getName) - .doesNotContain("persistentIndex") - .contains(created.getName()); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void getIndexesShouldNotReturnInvertedIndexes(ArangoCollection collection) { - assumeTrue(isAtLeastVersion(3, 10)); - - // create persistent index - collection.ensurePersistentIndex(Collections.singletonList("foo"), new PersistentIndexOptions().name("persistentIndex")); - - // create inverted index - String analyzerName = "delimiter-" + UUID.randomUUID(); - createAnalyzer(analyzerName, collection.db()); - InvertedIndexOptions options = createOptions(analyzerName); - InvertedIndexEntity created = collection.ensureInvertedIndex(options); - - Collection loadedIndexes = collection.getIndexes(); - assertThat(loadedIndexes).map(IndexEntity::getName) - .doesNotContain(created.getName()) - .contains("persistentIndex"); - } - -} diff --git a/shaded-integration-tests/src/test/native/java/com/arangodb/JwtAuthTest.java b/shaded-integration-tests/src/test/native/java/com/arangodb/JwtAuthTest.java deleted file mode 100644 index d2127e7ba..000000000 --- a/shaded-integration-tests/src/test/native/java/com/arangodb/JwtAuthTest.java +++ /dev/null @@ -1,97 +0,0 @@ -package com.arangodb; - -import com.arangodb.config.ConfigUtils; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.EnumSource; - -import java.util.HashMap; -import java.util.Map; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.catchThrowable; -import static org.junit.jupiter.api.Assumptions.assumeTrue; - - -/** - * @author Michele Rastelli - */ -class JwtAuthTest { - - private volatile static String jwt; - - @BeforeAll - static void init() { - ArangoDB arangoDB = new ArangoDB.Builder() - .loadProperties(ConfigUtils.loadConfig()) - .build(); - jwt = getJwt(arangoDB); - arangoDB.shutdown(); - } - - private static String getJwt(ArangoDB arangoDB) { - Map reqBody = new HashMap<>(); - reqBody.put("username", "root"); - reqBody.put("password", "test"); - - Request req = Request.builder() - .db(DbName.SYSTEM) - .method(Request.Method.POST) - .path("/_open/auth") - .body(reqBody) - .build(); - - Response resp = arangoDB.execute(req, Map.class); - return (String) resp.getBody().get("jwt"); - } - - @ParameterizedTest - @EnumSource(Protocol.class) - void notAuthenticated(Protocol protocol) { - ArangoDB arangoDB = getBuilder(protocol).build(); - Throwable thrown = catchThrowable(arangoDB::getVersion); - assertThat(thrown).isInstanceOf(ArangoDBException.class); - ArangoDBException e = (ArangoDBException) thrown; - assertThat(e.getResponseCode()).isEqualTo(401); - arangoDB.shutdown(); - } - - @ParameterizedTest - @EnumSource(Protocol.class) - void authenticated(Protocol protocol) { - ArangoDB arangoDB = getBuilder(protocol) - .jwt(jwt) - .build(); - arangoDB.getVersion(); - arangoDB.shutdown(); - } - - @ParameterizedTest - @EnumSource(Protocol.class) - void updateJwt(Protocol protocol) { - assumeTrue(protocol != Protocol.VST, "DE-423"); - ArangoDB arangoDB = getBuilder(protocol) - .jwt(jwt) - .build(); - arangoDB.getVersion(); - arangoDB.updateJwt("bla"); - - Throwable thrown = catchThrowable(arangoDB::getVersion); - assertThat(thrown).isInstanceOf(ArangoDBException.class); - ArangoDBException e = (ArangoDBException) thrown; - assertThat(e.getResponseCode()).isEqualTo(401); - - arangoDB.updateJwt(jwt); - arangoDB.getVersion(); - arangoDB.shutdown(); - } - - private ArangoDB.Builder getBuilder(Protocol protocol) { - return new ArangoDB.Builder() - .loadProperties(ConfigUtils.loadConfig()) - .useProtocol(protocol) - .jwt(null) // unset credentials from properties file - .user(null) // unset credentials from properties file - .password(null); // unset credentials from properties file - } -} diff --git a/shaded-integration-tests/src/test/native/java/com/arangodb/ParallelTest.java b/shaded-integration-tests/src/test/native/java/com/arangodb/ParallelTest.java deleted file mode 100644 index 9c4b98f96..000000000 --- a/shaded-integration-tests/src/test/native/java/com/arangodb/ParallelTest.java +++ /dev/null @@ -1,42 +0,0 @@ -package com.arangodb; - -import com.arangodb.config.ConfigUtils; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.EnumSource; - -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.Future; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assumptions.assumeTrue; - -class ParallelTest { - - @ParameterizedTest(name = "{index}") - @EnumSource(Protocol.class) - void connectionParallelism(Protocol protocol) throws InterruptedException { - // test that connections are internally async and can have multiple pending requests - // BTS-1102: the server does not run pipelined HTTP/1.1 requests in parallel - assumeTrue(protocol != Protocol.HTTP_JSON && protocol != Protocol.HTTP_VPACK); - ArangoDB adb = new ArangoDB.Builder() - .loadProperties(ConfigUtils.loadConfig()) - .useProtocol(protocol) - .maxConnections(1) - .build(); - - ExecutorService es = Executors.newFixedThreadPool(3); - List> tasks = new ArrayList<>(); - for (int i = 0; i < 3; i++) { - tasks.add(es.submit(() -> adb.db().query("return sleep(1)", Void.class))); - } - - Thread.sleep(2_000); - assertThat(tasks).allMatch(Future::isDone); - adb.shutdown(); - es.shutdown(); - } - -} diff --git a/shaded-integration-tests/src/test/native/java/com/arangodb/SerializableTest.java b/shaded-integration-tests/src/test/native/java/com/arangodb/SerializableTest.java deleted file mode 100644 index 17b1ec1da..000000000 --- a/shaded-integration-tests/src/test/native/java/com/arangodb/SerializableTest.java +++ /dev/null @@ -1,65 +0,0 @@ -package com.arangodb; - -import com.arangodb.entity.ErrorEntity; -import com.arangodb.internal.net.ArangoDBRedirectException; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.node.JsonNodeFactory; -import org.junit.jupiter.api.Test; - -import java.io.*; -import java.util.Collections; -import java.util.List; - -import static org.assertj.core.api.Assertions.assertThat; - -class SerializableTest { - - @Test - void serializeArangoDBException() throws IOException, ClassNotFoundException { - ObjectMapper mapper = new ObjectMapper(); - JsonNode jn = JsonNodeFactory.instance.objectNode() - .put("errorMessage", "boomError") - .put("exception", "boomException") - .put("code", 11) - .put("errorNum", 22); - ErrorEntity ee = mapper.readerFor(ErrorEntity.class).readValue(jn); - ArangoDBException e = new ArangoDBException(ee); - - ArangoDBException e2 = roundTrip(e); - assertThat(e2.getException()).isEqualTo(e.getException()); - assertThat(e2.getResponseCode()).isEqualTo(e.getResponseCode()); - assertThat(e2.getErrorNum()).isEqualTo(e.getErrorNum()); - assertThat(e2.getRequestId()).isEqualTo(e.getRequestId()); - } - - @Test - void serializeArangoDBRedirectException() throws IOException, ClassNotFoundException { - ArangoDBRedirectException e = new ArangoDBRedirectException("foo", "bar"); - ArangoDBRedirectException e2 = roundTrip(e); - assertThat(e2.getMessage()).isEqualTo(e.getMessage()); - assertThat(e2.getLocation()).isEqualTo(e.getLocation()); - } - - @Test - void serializeArangoDBMultipleException() throws IOException, ClassNotFoundException { - List exceptions = Collections.singletonList(new RuntimeException("foo")); - ArangoDBMultipleException e = new ArangoDBMultipleException(exceptions); - ArangoDBMultipleException e2 = roundTrip(e); - assertThat(e2.getExceptions()).hasSize(1); - assertThat(e2.getExceptions().iterator().next().getMessage()).isEqualTo("foo"); - } - - private T roundTrip(T input) throws IOException, ClassNotFoundException { - ByteArrayOutputStream os = new ByteArrayOutputStream(); - ObjectOutputStream objectOutputStream = new ObjectOutputStream(os); - objectOutputStream.writeObject(input); - - InputStream is = new ByteArrayInputStream(os.toByteArray()); - ObjectInputStream objectInputStream = new ObjectInputStream(is); - T output = (T) objectInputStream.readObject(); - objectInputStream.close(); - - return output; - } -} diff --git a/shaded-integration-tests/src/test/native/java/com/arangodb/StreamTransactionConflictsTest.java b/shaded-integration-tests/src/test/native/java/com/arangodb/StreamTransactionConflictsTest.java deleted file mode 100644 index 1e5ed62df..000000000 --- a/shaded-integration-tests/src/test/native/java/com/arangodb/StreamTransactionConflictsTest.java +++ /dev/null @@ -1,119 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb; - -import com.arangodb.entity.ArangoDBEngine; -import com.arangodb.entity.BaseDocument; -import com.arangodb.entity.StreamTransactionEntity; -import com.arangodb.model.DocumentCreateOptions; -import com.arangodb.model.StreamTransactionOptions; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.MethodSource; - -import java.util.UUID; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.catchThrowable; -import static org.junit.jupiter.api.Assumptions.assumeTrue; - - -/** - * @author Michele Rastelli - */ -class StreamTransactionConflictsTest extends BaseJunit5 { - - private static final String COLLECTION_NAME = "db_concurrent_stream_transactions_test-" + UUID.randomUUID(); - - @BeforeAll - static void init() { - initCollections(COLLECTION_NAME); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void conflictOnInsertDocumentWithNotYetCommittedTx(ArangoDatabase db) { - assumeTrue(isSingleServer()); - assumeTrue(isAtLeastVersion(3, 5)); - assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); - - StreamTransactionEntity tx1 = db.beginStreamTransaction( - new StreamTransactionOptions().readCollections(COLLECTION_NAME).writeCollections(COLLECTION_NAME)); - - StreamTransactionEntity tx2 = db.beginStreamTransaction( - new StreamTransactionOptions().readCollections(COLLECTION_NAME).writeCollections(COLLECTION_NAME)); - - String key = UUID.randomUUID().toString(); - - // insert a document from within tx1 - db.collection(COLLECTION_NAME) - .insertDocument(new BaseDocument(key), new DocumentCreateOptions().streamTransactionId(tx1.getId())); - - // insert conflicting document from within tx2 - Throwable thrown = catchThrowable(() -> db.collection(COLLECTION_NAME).insertDocument(new BaseDocument(key), - new DocumentCreateOptions().streamTransactionId(tx2.getId()))); - assertThat(thrown).isInstanceOf(ArangoDBException.class); - ArangoDBException e = (ArangoDBException) thrown; - - if (isAtLeastVersion(3, 8)) { - assertThat(e.getResponseCode()).isEqualTo(409); - assertThat(e.getErrorNum()).isEqualTo(1200); - } - - db.abortStreamTransaction(tx1.getId()); - db.abortStreamTransaction(tx2.getId()); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void conflictOnInsertDocumentWithAlreadyCommittedTx(ArangoDatabase db) { - assumeTrue(isSingleServer()); - assumeTrue(isAtLeastVersion(3, 5)); - assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); - - StreamTransactionEntity tx1 = db.beginStreamTransaction( - new StreamTransactionOptions().readCollections(COLLECTION_NAME).writeCollections(COLLECTION_NAME)); - - StreamTransactionEntity tx2 = db.beginStreamTransaction( - new StreamTransactionOptions().readCollections(COLLECTION_NAME).writeCollections(COLLECTION_NAME)); - - String key = UUID.randomUUID().toString(); - - // insert a document from within tx1 - db.collection(COLLECTION_NAME) - .insertDocument(new BaseDocument(key), new DocumentCreateOptions().streamTransactionId(tx1.getId())); - - // commit tx1 - db.commitStreamTransaction(tx1.getId()); - - // insert conflicting document from within tx2 - Throwable thrown = catchThrowable(() -> db.collection(COLLECTION_NAME).insertDocument(new BaseDocument(key), - new DocumentCreateOptions().streamTransactionId(tx2.getId()))); - assertThat(thrown).isInstanceOf(ArangoDBException.class); - ArangoDBException e = (ArangoDBException) thrown; - if (isAtLeastVersion(3, 8)) { - assertThat(e.getResponseCode()).isEqualTo(409); - assertThat(e.getErrorNum()).isEqualTo(1200); - } - - db.abortStreamTransaction(tx2.getId()); - } -} diff --git a/shaded-integration-tests/src/test/native/java/com/arangodb/StreamTransactionGraphTest.java b/shaded-integration-tests/src/test/native/java/com/arangodb/StreamTransactionGraphTest.java deleted file mode 100644 index e4d73fa33..000000000 --- a/shaded-integration-tests/src/test/native/java/com/arangodb/StreamTransactionGraphTest.java +++ /dev/null @@ -1,407 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb; - -import com.arangodb.entity.*; -import com.arangodb.model.*; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.Arguments; -import org.junit.jupiter.params.provider.MethodSource; - -import java.util.Collections; -import java.util.UUID; -import java.util.stream.Stream; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assumptions.assumeTrue; - - -/** - * @author Michele Rastelli - */ -class StreamTransactionGraphTest extends BaseJunit5 { - - private static final String GRAPH_NAME = "graph_stream_transaction_graph_test"; - private static final String EDGE_COLLECTION = "edge_collection_stream_transaction_graph_test"; - private static final String VERTEX_COLLECTION_1 = "vertex_collection_1_stream_transaction_graph_test"; - private static final String VERTEX_COLLECTION_2 = "vertex_collection_2_stream_transaction_graph_test"; - - private static Stream vertices() { - return dbsStream() - .map(db -> db.graph(GRAPH_NAME).vertexCollection(VERTEX_COLLECTION_1)) - .map(Arguments::of); - } - - private static Stream edges() { - return dbsStream() - .map(db -> db.graph(GRAPH_NAME).edgeCollection(EDGE_COLLECTION)) - .map(Arguments::of); - } - - @BeforeAll - static void init() { - initDB(); - initGraph(GRAPH_NAME, Collections.singletonList(new EdgeDefinition() - .collection(EDGE_COLLECTION).from(VERTEX_COLLECTION_1).to(VERTEX_COLLECTION_2) - ), null); - } - - private BaseEdgeDocument createEdgeValue(String streamTransactionId, ArangoGraph graph) { - ArangoVertexCollection vertexCollection1 = graph.vertexCollection(VERTEX_COLLECTION_1); - ArangoVertexCollection vertexCollection2 = graph.vertexCollection(VERTEX_COLLECTION_2); - VertexEntity v1 = vertexCollection1.insertVertex(new BaseDocument(), - new VertexCreateOptions().streamTransactionId(streamTransactionId)); - VertexEntity v2 = vertexCollection2.insertVertex(new BaseDocument(), - new VertexCreateOptions().streamTransactionId(streamTransactionId)); - BaseEdgeDocument value = new BaseEdgeDocument(); - value.setFrom(v1.getId()); - value.setTo(v2.getId()); - return value; - } - - @ParameterizedTest(name = "{index}") - @MethodSource("vertices") - void getVertex(ArangoVertexCollection vertexCollection1) { - assumeTrue(isSingleServer()); - assumeTrue(isAtLeastVersion(3, 5)); - assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); - - ArangoDatabase db = vertexCollection1.graph().db(); - StreamTransactionEntity tx = db - .beginStreamTransaction(new StreamTransactionOptions() - .readCollections(VERTEX_COLLECTION_1, VERTEX_COLLECTION_2, EDGE_COLLECTION) - .writeCollections(VERTEX_COLLECTION_1, VERTEX_COLLECTION_2, EDGE_COLLECTION)); - - // insert a vertex from outside the tx - VertexEntity createdVertex = vertexCollection1.insertVertex(new BaseDocument()); - - // assert that the vertex is not found from within the tx - assertThat(vertexCollection1.getVertex(createdVertex.getKey(), BaseDocument.class, - new GraphDocumentReadOptions().streamTransactionId(tx.getId()))).isNull(); - - db.abortStreamTransaction(tx.getId()); - } - - - @ParameterizedTest(name = "{index}") - @MethodSource("vertices") - void createVertex(ArangoVertexCollection vertexCollection1) { - assumeTrue(isSingleServer()); - assumeTrue(isAtLeastVersion(3, 5)); - assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); - - ArangoDatabase db = vertexCollection1.graph().db(); - StreamTransactionEntity tx = db.beginStreamTransaction( - new StreamTransactionOptions() - .readCollections(VERTEX_COLLECTION_1, VERTEX_COLLECTION_2, EDGE_COLLECTION) - .writeCollections(VERTEX_COLLECTION_1, VERTEX_COLLECTION_2, EDGE_COLLECTION)); - - // insert a vertex from within the tx - VertexEntity createdVertex = vertexCollection1.insertVertex(new BaseDocument(), - new VertexCreateOptions().streamTransactionId(tx.getId())); - - // assert that the vertex is not found from outside the tx - assertThat(vertexCollection1.getVertex(createdVertex.getKey(), BaseDocument.class, null)).isNull(); - - // assert that the vertex is found from within the tx - assertThat(vertexCollection1.getVertex(createdVertex.getKey(), BaseDocument.class, - new GraphDocumentReadOptions().streamTransactionId(tx.getId()))).isNotNull(); - - db.commitStreamTransaction(tx.getId()); - - // assert that the vertex is found after commit - assertThat(vertexCollection1.getVertex(createdVertex.getKey(), BaseDocument.class, null)).isNotNull(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("vertices") - void replaceVertex(ArangoVertexCollection vertexCollection1) { - assumeTrue(isSingleServer()); - assumeTrue(isAtLeastVersion(3, 5)); - assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); - - BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); - doc.addAttribute("test", "foo"); - - VertexEntity createdVertex = vertexCollection1.insertVertex(doc, null); - - ArangoDatabase db = vertexCollection1.graph().db(); - StreamTransactionEntity tx = db.beginStreamTransaction( - new StreamTransactionOptions() - .readCollections(VERTEX_COLLECTION_1, VERTEX_COLLECTION_2, EDGE_COLLECTION) - .writeCollections(VERTEX_COLLECTION_1, VERTEX_COLLECTION_2, EDGE_COLLECTION)); - - // replace vertex from within the tx - doc.updateAttribute("test", "bar"); - vertexCollection1.replaceVertex(createdVertex.getKey(), doc, - new VertexReplaceOptions().streamTransactionId(tx.getId())); - - // assert that the vertex has not been replaced from outside the tx - assertThat(vertexCollection1.getVertex(createdVertex.getKey(), BaseDocument.class, null) - .getProperties()).containsEntry("test", "foo"); - - // assert that the vertex has been replaced from within the tx - assertThat(vertexCollection1.getVertex(createdVertex.getKey(), BaseDocument.class, - new GraphDocumentReadOptions().streamTransactionId(tx.getId())).getProperties()).containsEntry("test" - , "bar"); - - db.commitStreamTransaction(tx.getId()); - - // assert that the vertex has been replaced after commit - assertThat(vertexCollection1.getVertex(createdVertex.getKey(), BaseDocument.class, null) - .getProperties()).containsEntry("test", "bar"); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("vertices") - void updateVertex(ArangoVertexCollection vertexCollection1) { - assumeTrue(isSingleServer()); - assumeTrue(isAtLeastVersion(3, 5)); - assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); - - BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); - doc.addAttribute("test", "foo"); - - VertexEntity createdDoc = vertexCollection1.insertVertex(doc, null); - - ArangoDatabase db = vertexCollection1.graph().db(); - StreamTransactionEntity tx = db.beginStreamTransaction( - new StreamTransactionOptions() - .readCollections(VERTEX_COLLECTION_1, VERTEX_COLLECTION_2, EDGE_COLLECTION) - .writeCollections(VERTEX_COLLECTION_1, VERTEX_COLLECTION_2, EDGE_COLLECTION)); - - // update vertex from within the tx - doc.updateAttribute("test", "bar"); - vertexCollection1.updateVertex(createdDoc.getKey(), doc, - new VertexUpdateOptions().streamTransactionId(tx.getId())); - - // assert that the vertex has not been updated from outside the tx - assertThat(vertexCollection1.getVertex(createdDoc.getKey(), BaseDocument.class, null) - .getProperties()).containsEntry("test", "foo"); - - // assert that the vertex has been updated from within the tx - assertThat(vertexCollection1.getVertex(createdDoc.getKey(), BaseDocument.class, - new GraphDocumentReadOptions().streamTransactionId(tx.getId())).getProperties()).containsEntry("test" - , "bar"); - - db.commitStreamTransaction(tx.getId()); - - // assert that the vertex has been updated after commit - assertThat(vertexCollection1.getVertex(createdDoc.getKey(), BaseDocument.class, null) - .getProperties()).containsEntry("test", "bar"); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("vertices") - void deleteVertex(ArangoVertexCollection vertexCollection1) { - assumeTrue(isSingleServer()); - assumeTrue(isAtLeastVersion(3, 5)); - assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); - - VertexEntity createdDoc = vertexCollection1.insertVertex(new BaseDocument(), null); - - ArangoDatabase db = vertexCollection1.graph().db(); - StreamTransactionEntity tx = db.beginStreamTransaction( - new StreamTransactionOptions() - .readCollections(VERTEX_COLLECTION_1, VERTEX_COLLECTION_2, EDGE_COLLECTION) - .writeCollections(VERTEX_COLLECTION_1, VERTEX_COLLECTION_2, EDGE_COLLECTION)); - - // delete vertex from within the tx - vertexCollection1.deleteVertex(createdDoc.getKey(), new VertexDeleteOptions().streamTransactionId(tx.getId())); - - // assert that the vertex has not been deleted from outside the tx - assertThat(vertexCollection1.getVertex(createdDoc.getKey(), BaseDocument.class, null)).isNotNull(); - - // assert that the vertex has been deleted from within the tx - assertThat(vertexCollection1.getVertex(createdDoc.getKey(), BaseDocument.class, - new GraphDocumentReadOptions().streamTransactionId(tx.getId()))).isNull(); - - db.commitStreamTransaction(tx.getId()); - - // assert that the vertex has been deleted after commit - assertThat(vertexCollection1.getVertex(createdDoc.getKey(), BaseDocument.class, null)).isNull(); - } - - - @ParameterizedTest(name = "{index}") - @MethodSource("edges") - void getEdge(ArangoEdgeCollection edgeCollection) { - assumeTrue(isSingleServer()); - assumeTrue(isAtLeastVersion(3, 5)); - assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); - - ArangoDatabase db = edgeCollection.graph().db(); - StreamTransactionEntity tx = db - .beginStreamTransaction(new StreamTransactionOptions() - .readCollections(VERTEX_COLLECTION_1, VERTEX_COLLECTION_2, EDGE_COLLECTION) - .writeCollections(VERTEX_COLLECTION_1, VERTEX_COLLECTION_2, EDGE_COLLECTION)); - - // insert an edge from outside the tx - EdgeEntity createdEdge = edgeCollection.insertEdge(createEdgeValue(null, edgeCollection.graph())); - - // assert that the edge is not found from within the tx - assertThat(edgeCollection.getEdge(createdEdge.getKey(), BaseEdgeDocument.class, - new GraphDocumentReadOptions().streamTransactionId(tx.getId()))).isNull(); - - db.abortStreamTransaction(tx.getId()); - } - - - @ParameterizedTest(name = "{index}") - @MethodSource("edges") - void createEdge(ArangoEdgeCollection edgeCollection) { - assumeTrue(isSingleServer()); - assumeTrue(isAtLeastVersion(3, 5)); - assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); - - ArangoDatabase db = edgeCollection.graph().db(); - StreamTransactionEntity tx = db.beginStreamTransaction( - new StreamTransactionOptions() - .readCollections(VERTEX_COLLECTION_1, VERTEX_COLLECTION_2, EDGE_COLLECTION) - .writeCollections(VERTEX_COLLECTION_1, VERTEX_COLLECTION_2, EDGE_COLLECTION)); - - // insert an edge from within the tx - EdgeEntity createdEdge = edgeCollection.insertEdge(createEdgeValue(tx.getId(), edgeCollection.graph()), - new EdgeCreateOptions().streamTransactionId(tx.getId())); - - // assert that the edge is not found from outside the tx - assertThat(edgeCollection.getEdge(createdEdge.getKey(), BaseEdgeDocument.class, null)).isNull(); - - // assert that the edge is found from within the tx - assertThat(edgeCollection.getEdge(createdEdge.getKey(), BaseEdgeDocument.class, - new GraphDocumentReadOptions().streamTransactionId(tx.getId()))).isNotNull(); - - db.commitStreamTransaction(tx.getId()); - - // assert that the edge is found after commit - assertThat(edgeCollection.getEdge(createdEdge.getKey(), BaseEdgeDocument.class, null)).isNotNull(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("edges") - void replaceEdge(ArangoEdgeCollection edgeCollection) { - assumeTrue(isSingleServer()); - assumeTrue(isAtLeastVersion(3, 5)); - assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); - - BaseEdgeDocument doc = createEdgeValue(null, edgeCollection.graph()); - doc.addAttribute("test", "foo"); - - EdgeEntity createdEdge = edgeCollection.insertEdge(doc, null); - - ArangoDatabase db = edgeCollection.graph().db(); - StreamTransactionEntity tx = db.beginStreamTransaction( - new StreamTransactionOptions() - .readCollections(VERTEX_COLLECTION_1, VERTEX_COLLECTION_2, EDGE_COLLECTION) - .writeCollections(VERTEX_COLLECTION_1, VERTEX_COLLECTION_2, EDGE_COLLECTION)); - - // replace edge from within the tx - doc.updateAttribute("test", "bar"); - edgeCollection.replaceEdge(createdEdge.getKey(), doc, - new EdgeReplaceOptions().streamTransactionId(tx.getId())); - - // assert that the edge has not been replaced from outside the tx - assertThat(edgeCollection.getEdge(createdEdge.getKey(), BaseEdgeDocument.class, null) - .getProperties()).containsEntry("test", "foo"); - - // assert that the edge has been replaced from within the tx - assertThat(edgeCollection.getEdge(createdEdge.getKey(), BaseEdgeDocument.class, - new GraphDocumentReadOptions().streamTransactionId(tx.getId())).getProperties()).containsEntry("test" - , "bar"); - - db.commitStreamTransaction(tx.getId()); - - // assert that the edge has been replaced after commit - assertThat(edgeCollection.getEdge(createdEdge.getKey(), BaseEdgeDocument.class, null) - .getProperties()).containsEntry("test", "bar"); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("edges") - void updateEdge(ArangoEdgeCollection edgeCollection) { - assumeTrue(isSingleServer()); - assumeTrue(isAtLeastVersion(3, 5)); - assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); - - BaseEdgeDocument doc = createEdgeValue(null, edgeCollection.graph()); - doc.addAttribute("test", "foo"); - - EdgeEntity createdDoc = edgeCollection.insertEdge(doc, null); - - ArangoDatabase db = edgeCollection.graph().db(); - StreamTransactionEntity tx = db.beginStreamTransaction( - new StreamTransactionOptions() - .readCollections(VERTEX_COLLECTION_1, VERTEX_COLLECTION_2, EDGE_COLLECTION) - .writeCollections(VERTEX_COLLECTION_1, VERTEX_COLLECTION_2, EDGE_COLLECTION)); - - // update edge from within the tx - doc.updateAttribute("test", "bar"); - edgeCollection.updateEdge(createdDoc.getKey(), doc, new EdgeUpdateOptions().streamTransactionId(tx.getId())); - - // assert that the edge has not been updated from outside the tx - assertThat(edgeCollection.getEdge(createdDoc.getKey(), BaseEdgeDocument.class, null) - .getProperties()).containsEntry("test", "foo"); - - // assert that the edge has been updated from within the tx - assertThat(edgeCollection.getEdge(createdDoc.getKey(), BaseEdgeDocument.class, - new GraphDocumentReadOptions().streamTransactionId(tx.getId())).getProperties()).containsEntry("test" - , "bar"); - - db.commitStreamTransaction(tx.getId()); - - // assert that the edge has been updated after commit - assertThat(edgeCollection.getEdge(createdDoc.getKey(), BaseEdgeDocument.class, null) - .getProperties()).containsEntry("test", "bar"); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("edges") - void deleteEdge(ArangoEdgeCollection edgeCollection) { - assumeTrue(isSingleServer()); - assumeTrue(isAtLeastVersion(3, 5)); - assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); - - EdgeEntity createdDoc = edgeCollection.insertEdge(createEdgeValue(null, edgeCollection.graph()), null); - - ArangoDatabase db = edgeCollection.graph().db(); - StreamTransactionEntity tx = db.beginStreamTransaction( - new StreamTransactionOptions() - .readCollections(VERTEX_COLLECTION_1, VERTEX_COLLECTION_2, EDGE_COLLECTION) - .writeCollections(VERTEX_COLLECTION_1, VERTEX_COLLECTION_2, EDGE_COLLECTION)); - - // delete edge from within the tx - edgeCollection.deleteEdge(createdDoc.getKey(), new EdgeDeleteOptions().streamTransactionId(tx.getId())); - - // assert that the edge has not been deleted from outside the tx - assertThat(edgeCollection.getEdge(createdDoc.getKey(), BaseEdgeDocument.class, null)).isNotNull(); - - // assert that the edge has been deleted from within the tx - assertThat(edgeCollection.getEdge(createdDoc.getKey(), BaseEdgeDocument.class, - new GraphDocumentReadOptions().streamTransactionId(tx.getId()))).isNull(); - - db.commitStreamTransaction(tx.getId()); - - // assert that the edge has been deleted after commit - assertThat(edgeCollection.getEdge(createdDoc.getKey(), BaseEdgeDocument.class, null)).isNull(); - } - -} diff --git a/shaded-integration-tests/src/test/native/java/com/arangodb/StreamTransactionTest.java b/shaded-integration-tests/src/test/native/java/com/arangodb/StreamTransactionTest.java deleted file mode 100644 index 3b47d9222..000000000 --- a/shaded-integration-tests/src/test/native/java/com/arangodb/StreamTransactionTest.java +++ /dev/null @@ -1,820 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb; - -import com.arangodb.entity.*; -import com.arangodb.model.*; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.MethodSource; - -import java.io.IOException; -import java.util.*; -import java.util.stream.Collectors; -import java.util.stream.IntStream; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.catchThrowable; -import static org.junit.jupiter.api.Assumptions.assumeTrue; - -/** - * @author Michele Rastelli - */ -class StreamTransactionTest extends BaseJunit5 { - - private static final String COLLECTION_NAME = "StreamTransactionTest_collection"; - - @BeforeAll - static void init() { - initCollections(COLLECTION_NAME); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void beginStreamTransaction(ArangoDatabase db) { - assumeTrue(isSingleServer()); - assumeTrue(isAtLeastVersion(3, 5)); - assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); - - StreamTransactionEntity tx = db.beginStreamTransaction(null); - assertThat(tx.getId()).isNotNull(); - assertThat(tx.getStatus()).isEqualTo(StreamTransactionStatus.running); - db.abortStreamTransaction(tx.getId()); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void beginStreamTransactionWithNonExistingCollectionsShouldThrow(ArangoDatabase db) { - assumeTrue(isSingleServer()); - assumeTrue(isAtLeastVersion(3, 5)); - assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); - Throwable thrown = catchThrowable(() -> - db.beginStreamTransaction(new StreamTransactionOptions().writeCollections("notExistingCollection"))); - assertThat(thrown).isInstanceOf(ArangoDBException.class); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void abortStreamTransaction(ArangoDatabase db) { - assumeTrue(isSingleServer()); - assumeTrue(isAtLeastVersion(3, 5)); - assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); - - StreamTransactionEntity begunTx = db.beginStreamTransaction(null); - StreamTransactionEntity abortedTx = db.abortStreamTransaction(begunTx.getId()); - - assertThat(abortedTx.getId()).isNotNull(); - assertThat(abortedTx.getId()).isEqualTo(begunTx.getId()); - assertThat(abortedTx.getStatus()).isEqualTo(StreamTransactionStatus.aborted); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void abortStreamTransactionTwice(ArangoDatabase db) { - assumeTrue(isSingleServer()); - assumeTrue(isAtLeastVersion(3, 5)); - assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); - - StreamTransactionEntity begunTx = db.beginStreamTransaction(null); - db.abortStreamTransaction(begunTx.getId()); - db.abortStreamTransaction(begunTx.getId()); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void abortStreamTransactionWhenTransactionIdDoesNotExistsShouldThrow(ArangoDatabase db) { - assumeTrue(isSingleServer()); - assumeTrue(isAtLeastVersion(3, 5)); - assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); - Throwable thrown = catchThrowable(() -> db.abortStreamTransaction("000000")); - assertThat(thrown).isInstanceOf(ArangoDBException.class); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void abortStreamTransactionWithInvalidTransactionIdShouldThrow(ArangoDatabase db) { - assumeTrue(isSingleServer()); - assumeTrue(isAtLeastVersion(3, 5)); - assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); - Throwable thrown = catchThrowable(() -> db.abortStreamTransaction("invalidTransactionId")); - assertThat(thrown).isInstanceOf(ArangoDBException.class); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void abortCommittedStreamTransactionShouldThrow(ArangoDatabase db) { - assumeTrue(isSingleServer()); - assumeTrue(isAtLeastVersion(3, 5)); - assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); - - StreamTransactionEntity createdTx = db.beginStreamTransaction(null); - db.commitStreamTransaction(createdTx.getId()); - Throwable thrown = catchThrowable(() -> db.abortStreamTransaction(createdTx.getId())); - assertThat(thrown).isInstanceOf(ArangoDBException.class); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void getStreamTransaction(ArangoDatabase db) { - assumeTrue(isSingleServer()); - assumeTrue(isAtLeastVersion(3, 5)); - assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); - - StreamTransactionEntity createdTx = db.beginStreamTransaction(null); - StreamTransactionEntity gotTx = db.getStreamTransaction(createdTx.getId()); - - assertThat(gotTx.getId()).isNotNull(); - assertThat(gotTx.getId()).isEqualTo(createdTx.getId()); - assertThat(gotTx.getStatus()).isEqualTo(StreamTransactionStatus.running); - - db.abortStreamTransaction(createdTx.getId()); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void getStreamTransactionWhenTransactionIdDoesNotExistsShouldThrow(ArangoDatabase db) { - assumeTrue(isSingleServer()); - assumeTrue(isAtLeastVersion(3, 5)); - assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); - - Throwable thrown = catchThrowable(() -> db.getStreamTransaction("000000")); - assertThat(thrown).isInstanceOf(ArangoDBException.class); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void getStreamTransactionWithInvalidTransactionIdShouldThrow(ArangoDatabase db) { - assumeTrue(isSingleServer()); - assumeTrue(isAtLeastVersion(3, 5)); - assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); - - Throwable thrown = catchThrowable(() -> db.getStreamTransaction("invalidTransactionId")); - assertThat(thrown).isInstanceOf(ArangoDBException.class); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void commitStreamTransaction(ArangoDatabase db) { - assumeTrue(isSingleServer()); - assumeTrue(isAtLeastVersion(3, 5)); - assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); - - StreamTransactionEntity createdTx = db.beginStreamTransaction(null); - StreamTransactionEntity committedTx = db.commitStreamTransaction(createdTx.getId()); - - assertThat(committedTx.getId()).isNotNull(); - assertThat(committedTx.getId()).isEqualTo(createdTx.getId()); - assertThat(committedTx.getStatus()).isEqualTo(StreamTransactionStatus.committed); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void commitStreamTransactionTwice(ArangoDatabase db) { - assumeTrue(isSingleServer()); - assumeTrue(isAtLeastVersion(3, 5)); - assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); - - StreamTransactionEntity createdTx = db.beginStreamTransaction(null); - db.commitStreamTransaction(createdTx.getId()); - db.commitStreamTransaction(createdTx.getId()); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void commitStreamTransactionWhenTransactionIdDoesNotExistsShouldThrow(ArangoDatabase db) { - assumeTrue(isSingleServer()); - assumeTrue(isAtLeastVersion(3, 5)); - assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); - - Throwable thrown = catchThrowable(() -> db.commitStreamTransaction("000000")); - assertThat(thrown).isInstanceOf(ArangoDBException.class); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void commitStreamTransactionWithInvalidTransactionIdShouldThrow(ArangoDatabase db) { - assumeTrue(isSingleServer()); - assumeTrue(isAtLeastVersion(3, 5)); - assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); - - Throwable thrown = catchThrowable(() -> db.commitStreamTransaction("invalidTransactionId")); - assertThat(thrown).isInstanceOf(ArangoDBException.class); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void commitAbortedStreamTransactionShouldThrow(ArangoDatabase db) { - assumeTrue(isSingleServer()); - assumeTrue(isAtLeastVersion(3, 5)); - assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); - - StreamTransactionEntity createdTx = db.beginStreamTransaction(null); - db.abortStreamTransaction(createdTx.getId()); - Throwable thrown = catchThrowable(() -> db.commitStreamTransaction(createdTx.getId())); - assertThat(thrown).isInstanceOf(ArangoDBException.class); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void getDocument(ArangoDatabase db) { - assumeTrue(isSingleServer()); - assumeTrue(isAtLeastVersion(3, 5)); - assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); - - StreamTransactionEntity tx = db - .beginStreamTransaction(new StreamTransactionOptions().readCollections(COLLECTION_NAME)); - ArangoCollection collection = db.collection(COLLECTION_NAME); - - // insert a document from outside the tx - DocumentCreateEntity externalDoc = collection - .insertDocument(new BaseDocument(), null); - - // assert that the document is not found from within the tx - assertThat(collection.getDocument(externalDoc.getKey(), BaseDocument.class, - new DocumentReadOptions().streamTransactionId(tx.getId()))).isNull(); - - db.abortStreamTransaction(tx.getId()); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void getDocumentWithNonExistingTransactionIdShouldThrow(ArangoDatabase db) { - assumeTrue(isSingleServer()); - assumeTrue(isAtLeastVersion(3, 5)); - assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); - - ArangoCollection collection = db.collection(COLLECTION_NAME); - - Throwable thrown = catchThrowable(() -> collection - .getDocument("docId", BaseDocument.class, new DocumentReadOptions().streamTransactionId("123456"))); - assertThat(thrown).isInstanceOf(ArangoDBException.class); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void getDocumentWithInvalidTransactionIdShouldThrow(ArangoDatabase db) { - assumeTrue(isSingleServer()); - assumeTrue(isAtLeastVersion(3, 5)); - assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); - - ArangoCollection collection = db.collection(COLLECTION_NAME); - Throwable thrown = catchThrowable(() -> collection - .getDocument("docId", BaseDocument.class, new DocumentReadOptions().streamTransactionId("abcde"))); - assertThat(thrown).isInstanceOf(ArangoDBException.class); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void getDocuments(ArangoDatabase db) { - assumeTrue(isSingleServer()); - assumeTrue(isAtLeastVersion(3, 5)); - assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); - - StreamTransactionEntity tx = db - .beginStreamTransaction(new StreamTransactionOptions().readCollections(COLLECTION_NAME)); - ArangoCollection collection = db.collection(COLLECTION_NAME); - - // insert documents from outside the tx - DocumentCreateEntity externalDoc1 = collection - .insertDocument(new BaseDocument(), null); - - DocumentCreateEntity externalDoc2 = collection - .insertDocument(new BaseDocument(), null); - - // assert that the documents are not found from within the tx - MultiDocumentEntity documents = collection - .getDocuments(Arrays.asList(externalDoc1.getId(), externalDoc2.getId()), BaseDocument.class, - new DocumentReadOptions().streamTransactionId(tx.getId())); - - assertThat(documents.getDocuments()).isEmpty(); - - db.abortStreamTransaction(tx.getId()); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void insertDocument(ArangoDatabase db) { - assumeTrue(isSingleServer()); - assumeTrue(isAtLeastVersion(3, 5)); - assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); - - StreamTransactionEntity tx = db.beginStreamTransaction( - new StreamTransactionOptions().readCollections(COLLECTION_NAME).writeCollections(COLLECTION_NAME)); - ArangoCollection collection = db.collection(COLLECTION_NAME); - - // insert a document from within the tx - DocumentCreateEntity txDoc = collection - .insertDocument(new BaseDocument(), new DocumentCreateOptions().streamTransactionId(tx.getId())); - - // assert that the document is not found from outside the tx - assertThat(collection.getDocument(txDoc.getKey(), BaseDocument.class, null)).isNull(); - - // assert that the document is found from within the tx - assertThat(collection.getDocument(txDoc.getKey(), BaseDocument.class, - new DocumentReadOptions().streamTransactionId(tx.getId()))).isNotNull(); - - db.commitStreamTransaction(tx.getId()); - - // assert that the document is found after commit - assertThat(collection.getDocument(txDoc.getKey(), BaseDocument.class, null)).isNotNull(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void insertDocuments(ArangoDatabase db) { - assumeTrue(isSingleServer()); - assumeTrue(isAtLeastVersion(3, 5)); - assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); - - StreamTransactionEntity tx = db.beginStreamTransaction( - new StreamTransactionOptions().readCollections(COLLECTION_NAME).writeCollections(COLLECTION_NAME)); - ArangoCollection collection = db.collection(COLLECTION_NAME); - - // insert documents from within the tx - MultiDocumentEntity> txDocs = collection - .insertDocuments(Arrays.asList(new BaseDocument(), new BaseDocument(), new BaseDocument()), - new DocumentCreateOptions().streamTransactionId(tx.getId())); - - List keys = txDocs.getDocuments().stream().map(DocumentEntity::getKey).collect(Collectors.toList()); - - // assert that the documents are not found from outside the tx - assertThat(collection.getDocuments(keys, BaseDocument.class, null).getDocuments()).isEmpty(); - - // assert that the documents are found from within the tx - assertThat(collection - .getDocuments(keys, BaseDocument.class, new DocumentReadOptions().streamTransactionId(tx.getId())) - .getDocuments()).hasSize(keys.size()); - - db.commitStreamTransaction(tx.getId()); - - // assert that the document is found after commit - assertThat(collection.getDocuments(keys, BaseDocument.class, null).getDocuments()).hasSize(keys.size()); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void replaceDocument(ArangoDatabase db) { - assumeTrue(isSingleServer()); - assumeTrue(isAtLeastVersion(3, 5)); - assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); - - BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); - doc.addAttribute("test", "foo"); - - ArangoCollection collection = db.collection(COLLECTION_NAME); - DocumentCreateEntity createdDoc = collection.insertDocument(doc, null); - - StreamTransactionEntity tx = db.beginStreamTransaction( - new StreamTransactionOptions().readCollections(COLLECTION_NAME).writeCollections(COLLECTION_NAME)); - - // replace document from within the tx - doc.updateAttribute("test", "bar"); - collection.replaceDocument(createdDoc.getKey(), doc, - new DocumentReplaceOptions().streamTransactionId(tx.getId())); - - // assert that the document has not been replaced from outside the tx - assertThat(collection.getDocument(createdDoc.getKey(), BaseDocument.class, null) - .getProperties()).containsEntry("test", "foo"); - - // assert that the document has been replaced from within the tx - assertThat(collection.getDocument(createdDoc.getKey(), BaseDocument.class, - new DocumentReadOptions().streamTransactionId(tx.getId())).getProperties()).containsEntry("test", - "bar"); - - db.commitStreamTransaction(tx.getId()); - - // assert that the document has been replaced after commit - assertThat(collection.getDocument(createdDoc.getKey(), BaseDocument.class, null) - .getProperties()).containsEntry("test", "bar"); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void replaceDocuments(ArangoDatabase db) { - assumeTrue(isSingleServer()); - assumeTrue(isAtLeastVersion(3, 5)); - assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); - - List docs = IntStream.range(0, 3).mapToObj(it -> new BaseDocument()) - .peek(doc -> doc.addAttribute("test", "foo")).collect(Collectors.toList()); - - ArangoCollection collection = db.collection(COLLECTION_NAME); - List createdDocs = collection - .insertDocuments(docs, new DocumentCreateOptions().returnNew(true)).getDocuments().stream() - .map(DocumentCreateEntity::getNew).collect(Collectors.toList()); - - List keys = createdDocs.stream().map(BaseDocument::getKey).collect(Collectors.toList()); - - StreamTransactionEntity tx = db.beginStreamTransaction( - new StreamTransactionOptions().readCollections(COLLECTION_NAME).writeCollections(COLLECTION_NAME)); - - List modifiedDocs = createdDocs.stream().peek(doc -> { - doc.updateAttribute("test", "bar"); - }).collect(Collectors.toList()); - - // replace document from within the tx - collection - .replaceDocuments(modifiedDocs, new DocumentReplaceOptions().streamTransactionId(tx.getId())); - - // assert that the documents has not been replaced from outside the tx - collection.getDocuments(keys, BaseDocument.class, null).getDocuments().stream() - .map(it -> ((String) it.getAttribute("test"))) - .forEach(it -> assertThat(it).isEqualTo("foo")); - - // assert that the document has been replaced from within the tx - collection - .getDocuments(keys, BaseDocument.class, new DocumentReadOptions().streamTransactionId(tx.getId())) - .getDocuments().stream().map(it -> ((String) it.getAttribute("test"))) - .forEach(it -> assertThat(it).isEqualTo("bar")); - - db.commitStreamTransaction(tx.getId()); - - // assert that the document has been replaced after commit - collection.getDocuments(keys, BaseDocument.class, null).getDocuments().stream() - .map(it -> ((String) it.getAttribute("test"))) - .forEach(it -> assertThat(it).isEqualTo("bar")); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void updateDocument(ArangoDatabase db) { - assumeTrue(isSingleServer()); - assumeTrue(isAtLeastVersion(3, 5)); - assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); - - BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); - doc.addAttribute("test", "foo"); - - ArangoCollection collection = db.collection(COLLECTION_NAME); - DocumentCreateEntity createdDoc = collection.insertDocument(doc, null); - - StreamTransactionEntity tx = db.beginStreamTransaction( - new StreamTransactionOptions().readCollections(COLLECTION_NAME).writeCollections(COLLECTION_NAME)); - - // update document from within the tx - doc.updateAttribute("test", "bar"); - collection - .updateDocument(createdDoc.getKey(), doc, new DocumentUpdateOptions().streamTransactionId(tx.getId())); - - // assert that the document has not been updated from outside the tx - assertThat(collection.getDocument(createdDoc.getKey(), BaseDocument.class, null) - .getProperties()).containsEntry("test", "foo"); - - // assert that the document has been updated from within the tx - assertThat(collection.getDocument(createdDoc.getKey(), BaseDocument.class, - new DocumentReadOptions().streamTransactionId(tx.getId())).getProperties()).containsEntry("test", "bar") - ; - - db.commitStreamTransaction(tx.getId()); - - // assert that the document has been updated after commit - assertThat(collection.getDocument(createdDoc.getKey(), BaseDocument.class, null) - .getProperties()).containsEntry("test", "bar"); - - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void updateDocuments(ArangoDatabase db) { - assumeTrue(isSingleServer()); - assumeTrue(isAtLeastVersion(3, 5)); - assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); - - List docs = IntStream.range(0, 3).mapToObj(it -> new BaseDocument()) - .peek(doc -> doc.addAttribute("test", "foo")).collect(Collectors.toList()); - - ArangoCollection collection = db.collection(COLLECTION_NAME); - List createdDocs = collection - .insertDocuments(docs, new DocumentCreateOptions().returnNew(true)).getDocuments().stream() - .map(DocumentCreateEntity::getNew).collect(Collectors.toList()); - - List keys = createdDocs.stream().map(BaseDocument::getKey).collect(Collectors.toList()); - - StreamTransactionEntity tx = db.beginStreamTransaction( - new StreamTransactionOptions().readCollections(COLLECTION_NAME).writeCollections(COLLECTION_NAME)); - - List modifiedDocs = createdDocs.stream().peek(doc -> { - doc.updateAttribute("test", "bar"); - }).collect(Collectors.toList()); - - // update documents from within the tx - collection - .updateDocuments(modifiedDocs, new DocumentUpdateOptions().streamTransactionId(tx.getId())); - - // assert that the documents have not been updated from outside the tx - collection.getDocuments(keys, BaseDocument.class, null).getDocuments().stream() - .map(it -> ((String) it.getAttribute("test"))) - .forEach(it -> assertThat(it).isEqualTo("foo")); - - // assert that the documents have been updated from within the tx - collection - .getDocuments(keys, BaseDocument.class, new DocumentReadOptions().streamTransactionId(tx.getId())) - .getDocuments().stream().map(it -> ((String) it.getAttribute("test"))) - .forEach(it -> assertThat(it).isEqualTo("bar")); - - db.commitStreamTransaction(tx.getId()); - - // assert that the document has been updated after commit - collection.getDocuments(keys, BaseDocument.class, null).getDocuments().stream() - .map(it -> ((String) it.getAttribute("test"))) - .forEach(it -> assertThat(it).isEqualTo("bar")); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void deleteDocument(ArangoDatabase db) { - assumeTrue(isSingleServer()); - assumeTrue(isAtLeastVersion(3, 5)); - assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); - - ArangoCollection collection = db.collection(COLLECTION_NAME); - DocumentCreateEntity createdDoc = collection - .insertDocument(new BaseDocument(), null); - - StreamTransactionEntity tx = db.beginStreamTransaction( - new StreamTransactionOptions().readCollections(COLLECTION_NAME).writeCollections(COLLECTION_NAME)); - - // delete document from within the tx - collection - .deleteDocument(createdDoc.getKey(), new DocumentDeleteOptions().streamTransactionId(tx.getId())); - - // assert that the document has not been deleted from outside the tx - assertThat(collection.getDocument(createdDoc.getKey(), BaseDocument.class, null)).isNotNull(); - - // assert that the document has been deleted from within the tx - assertThat(collection.getDocument(createdDoc.getKey(), BaseDocument.class, - new DocumentReadOptions().streamTransactionId(tx.getId()))).isNull(); - - db.commitStreamTransaction(tx.getId()); - - // assert that the document has been deleted after commit - assertThat(collection.getDocument(createdDoc.getKey(), BaseDocument.class, null)).isNull(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void deleteDocuments(ArangoDatabase db) { - assumeTrue(isSingleServer()); - assumeTrue(isAtLeastVersion(3, 5)); - assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); - - ArangoCollection collection = db.collection(COLLECTION_NAME); - List keys = collection - .insertDocuments(Arrays.asList(new BaseDocument(), new BaseDocument(), new BaseDocument())) - .getDocuments().stream().map(DocumentEntity::getKey).collect(Collectors.toList()); - - StreamTransactionEntity tx = db.beginStreamTransaction( - new StreamTransactionOptions().readCollections(COLLECTION_NAME).writeCollections(COLLECTION_NAME)); - - // delete document from within the tx - collection - .deleteDocuments(keys, new DocumentDeleteOptions().streamTransactionId(tx.getId())); - - // assert that the documents has not been deleted from outside the tx - assertThat(collection.getDocuments(keys, BaseDocument.class, null).getDocuments()).hasSize(keys.size()); - - // assert that the document has been deleted from within the tx - assertThat(collection - .getDocuments(keys, BaseDocument.class, new DocumentReadOptions().streamTransactionId(tx.getId())) - .getDocuments()).isEmpty(); - - db.commitStreamTransaction(tx.getId()); - - // assert that the document has been deleted after commit - assertThat(collection.getDocuments(keys, BaseDocument.class, null).getDocuments()).isEmpty(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void documentExists(ArangoDatabase db) { - assumeTrue(isSingleServer()); - assumeTrue(isAtLeastVersion(3, 5)); - assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); - - StreamTransactionEntity tx = db - .beginStreamTransaction(new StreamTransactionOptions().readCollections(COLLECTION_NAME)); - ArangoCollection collection = db.collection(COLLECTION_NAME); - - // insert a document from outside the tx - DocumentCreateEntity externalDoc = collection - .insertDocument(new BaseDocument(), null); - - // assert that the document is not found from within the tx - assertThat(collection - .documentExists(externalDoc.getKey(), new DocumentExistsOptions().streamTransactionId(tx.getId()))).isFalse(); - - db.abortStreamTransaction(tx.getId()); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void count(ArangoDatabase db) { - assumeTrue(isSingleServer()); - assumeTrue(isAtLeastVersion(3, 5)); - assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); - - ArangoCollection collection = db.collection(COLLECTION_NAME); - Long initialCount = collection.count().getCount(); - - StreamTransactionEntity tx = db - .beginStreamTransaction(new StreamTransactionOptions().readCollections(COLLECTION_NAME)); - - // insert a document from outside the tx - collection.insertDocument(new BaseDocument(), null); - - // assert that the document is not counted from within the tx - assertThat(collection.count(new CollectionCountOptions().streamTransactionId(tx.getId())) - .getCount()).isEqualTo(initialCount); - - db.abortStreamTransaction(tx.getId()); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void truncate(ArangoDatabase db) { - assumeTrue(isSingleServer()); - assumeTrue(isAtLeastVersion(3, 5)); - assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); - - ArangoCollection collection = db.collection(COLLECTION_NAME); - collection.insertDocument(new BaseDocument(), null); - - StreamTransactionEntity tx = db.beginStreamTransaction( - new StreamTransactionOptions().readCollections(COLLECTION_NAME).writeCollections(COLLECTION_NAME)); - - // truncate document from within the tx - collection.truncate(new CollectionTruncateOptions().streamTransactionId(tx.getId())); - - // assert that the collection has not been truncated from outside the tx - assertThat(collection.count().getCount()).isPositive(); - - // assert that the collection has been truncated from within the tx - assertThat(collection.count(new CollectionCountOptions().streamTransactionId(tx.getId())) - .getCount()).isZero(); - - db.commitStreamTransaction(tx.getId()); - - // assert that the collection has been truncated after commit - assertThat(collection.count().getCount()).isZero(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void createCursor(ArangoDatabase db) { - assumeTrue(isSingleServer()); - assumeTrue(isAtLeastVersion(3, 5)); - assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); - - StreamTransactionEntity tx = db - .beginStreamTransaction(new StreamTransactionOptions().readCollections(COLLECTION_NAME)); - ArangoCollection collection = db.collection(COLLECTION_NAME); - - // insert a document from outside the tx - DocumentCreateEntity externalDoc = collection - .insertDocument(new BaseDocument(), null); - - final Map bindVars = new HashMap<>(); - bindVars.put("@collection", COLLECTION_NAME); - bindVars.put("key", externalDoc.getKey()); - - ArangoCursor cursor = db - .query("FOR doc IN @@collection FILTER doc._key == @key RETURN doc", bindVars, - new AqlQueryOptions().streamTransactionId(tx.getId()), BaseDocument.class); - - // assert that the document is not found from within the tx - assertThat(cursor.hasNext()).isFalse(); - - db.abortStreamTransaction(tx.getId()); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void nextCursor(ArangoDatabase db) { - assumeTrue(isSingleServer()); - assumeTrue(isAtLeastVersion(3, 5)); - assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); - - StreamTransactionEntity tx = db.beginStreamTransaction( - new StreamTransactionOptions().readCollections(COLLECTION_NAME).writeCollections(COLLECTION_NAME)); - ArangoCollection collection = db.collection(COLLECTION_NAME); - - // insert documents from within the tx - List keys = collection - .insertDocuments(IntStream.range(0, 10).mapToObj(it -> new BaseDocument()).collect(Collectors.toList()), - new DocumentCreateOptions().streamTransactionId(tx.getId())).getDocuments().stream() - .map(DocumentEntity::getKey).collect(Collectors.toList()); - - final Map bindVars = new HashMap<>(); - bindVars.put("@collection", COLLECTION_NAME); - bindVars.put("keys", keys); - - ArangoCursor cursor = db - .query("FOR doc IN @@collection FILTER CONTAINS_ARRAY(@keys, doc._key) RETURN doc", bindVars, - new AqlQueryOptions().streamTransactionId(tx.getId()).batchSize(2), BaseDocument.class); - - List docs = cursor.asListRemaining(); - - // assert that all the keys are returned from the query - assertThat(docs.stream().map(BaseDocument::getKey).collect(Collectors.toList())).containsAll(keys); - - db.abortStreamTransaction(tx.getId()); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void getStreamTransactions(ArangoDatabase db) { - assumeTrue(isSingleServer()); - assumeTrue(isAtLeastVersion(3, 5)); - assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); - - StreamTransactionEntity tx1 = db.beginStreamTransaction(null); - StreamTransactionEntity tx2 = db.beginStreamTransaction(null); - - List createdIds = Arrays.asList(tx1.getId(), tx2.getId()); - Set gotTxs = db.getStreamTransactions().stream(). - filter(it -> createdIds.contains(it.getId())).collect(Collectors.toSet()); - - assertThat(gotTxs).hasSameSizeAs(createdIds); - assertThat(gotTxs.stream() - .allMatch(it -> it.getState() == StreamTransactionStatus.running)).isTrue(); - - db.abortStreamTransaction(tx1.getId()); - db.abortStreamTransaction(tx2.getId()); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void transactionAllowImplicitFalse(ArangoDatabase db) { - assumeTrue(isSingleServer()); - assumeTrue(isAtLeastVersion(3, 5)); - assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); - - StreamTransactionEntity tx = db - .beginStreamTransaction(new StreamTransactionOptions().allowImplicit(false)); - ArangoCollection collection = db.collection(COLLECTION_NAME); - - // insert a document from outside the tx - DocumentCreateEntity externalDoc = collection - .insertDocument(new BaseDocument(), null); - - // assert that we cannot read from collection - Throwable thrown = catchThrowable(() -> collection.getDocument(externalDoc.getKey(), BaseDocument.class, - new DocumentReadOptions().streamTransactionId(tx.getId()))); - assertThat(thrown).isInstanceOf(ArangoDBException.class); - ArangoDBException e = (ArangoDBException) thrown; - assertThat(e.getResponseCode()).isEqualTo(400); - assertThat(e.getErrorNum()).isEqualTo(1652); - assertThat(e.getMessage()).contains("unregistered collection used in transaction"); - - db.abortStreamTransaction(tx.getId()); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void transactionDirtyRead(ArangoDatabase db) throws IOException { - assumeTrue(isCluster()); - assumeTrue(isAtLeastVersion(3, 10)); - - ArangoCollection collection = db.collection(COLLECTION_NAME); - DocumentCreateEntity doc = collection.insertDocument(new BaseDocument()); - - StreamTransactionEntity tx = db - .beginStreamTransaction(new StreamTransactionOptions() - .readCollections(COLLECTION_NAME) - .allowDirtyRead(true)); - - MultiDocumentEntity readDocs = collection.getDocuments(Collections.singletonList(doc.getKey()), - BaseDocument.class, - new DocumentReadOptions().streamTransactionId(tx.getId())); - - assertThat(readDocs.isPotentialDirtyRead()).isTrue(); - assertThat(readDocs.getDocuments()).hasSize(1); - - final ArangoCursor cursor = db.query("FOR i IN @@col RETURN i", - Collections.singletonMap("@col", COLLECTION_NAME), - new AqlQueryOptions().streamTransactionId(tx.getId()), BaseDocument.class); - assertThat(cursor.isPotentialDirtyRead()).isTrue(); - cursor.close(); - - db.abortStreamTransaction(tx.getId()); - } - -} diff --git a/shaded-integration-tests/src/test/native/java/com/arangodb/async/ArangoCollectionTest.java b/shaded-integration-tests/src/test/native/java/com/arangodb/async/ArangoCollectionTest.java deleted file mode 100644 index 720b1d261..000000000 --- a/shaded-integration-tests/src/test/native/java/com/arangodb/async/ArangoCollectionTest.java +++ /dev/null @@ -1,2514 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.async; - -import com.arangodb.ArangoDBException; -import com.arangodb.entity.*; -import com.arangodb.internal.serde.SerdeUtils; -import com.arangodb.model.*; -import com.arangodb.model.DocumentImportOptions.OnDuplicate; -import com.arangodb.serde.jackson.JacksonSerde; -import com.arangodb.serde.jackson.Key; -import com.arangodb.shaded.fasterxml.jackson.databind.JsonNode; -import com.arangodb.util.RawData; -import com.arangodb.util.RawJson; -import com.fasterxml.jackson.annotation.JsonTypeInfo; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.Test; - -import java.util.*; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ExecutionException; -import java.util.stream.Collectors; -import java.util.stream.IntStream; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.catchThrowable; -import static org.junit.jupiter.api.Assertions.fail; -import static org.junit.jupiter.api.Assumptions.assumeTrue; - -/** - * @author Mark Vollmary - * @author Michele Rastelli - */ -class ArangoCollectionTest extends BaseTest { - - private static final String COLLECTION_NAME = "db_collection_test"; - - ArangoCollectionTest() throws ExecutionException, InterruptedException { - ArangoCollectionAsync collection = db.collection(COLLECTION_NAME); - if (!collection.exists().get()) { - collection.create().get(); - } - } - - @BeforeAll - static void setup() throws InterruptedException, ExecutionException { - db.createCollection(COLLECTION_NAME, null).get(); - } - - @AfterEach - void teardown() throws InterruptedException, ExecutionException { - db.collection(COLLECTION_NAME).drop().get(); - } - - @Test - void create() throws InterruptedException, ExecutionException { - final CollectionEntity result = db.collection(COLLECTION_NAME + "_1").create().get(); - assertThat(result).isNotNull(); - assertThat(result.getId()).isNotNull(); - db.collection(COLLECTION_NAME + "_1").drop().get(); - } - - @Test - void insertDocument() throws InterruptedException, ExecutionException { - db.collection(COLLECTION_NAME) - .insertDocument(new BaseDocument(), null) - .whenComplete((doc, ex) -> { - assertThat(ex).isNull(); - assertThat(doc.getId()).isNotNull(); - assertThat(doc.getKey()).isNotNull(); - assertThat(doc.getRev()).isNotNull(); - assertThat(doc.getNew()).isNull(); - assertThat(doc.getId()).isEqualTo(COLLECTION_NAME + "/" + doc.getKey()); - }) - .get(); - } - - @Test - void insertDocumentReturnNew() throws InterruptedException, ExecutionException { - final DocumentCreateOptions options = new DocumentCreateOptions().returnNew(true); - db.collection(COLLECTION_NAME) - .insertDocument(new BaseDocument(), options) - .whenComplete((doc, ex) -> { - assertThat(doc).isNotNull(); - assertThat(doc.getId()).isNotNull(); - assertThat(doc.getKey()).isNotNull(); - assertThat(doc.getRev()).isNotNull(); - assertThat(doc.getNew()).isNotNull(); - }) - .get(); - } - - @Test - void insertDocumentWithTypeOverwriteModeReplace() throws InterruptedException, ExecutionException { - assumeTrue(isAtLeastVersion(3, 7)); - assumeTrue(db.getSerde().getUserSerde() instanceof JacksonSerde, "polymorphic deserialization support " + - "required"); - ArangoCollectionAsync collection = db.collection(COLLECTION_NAME); - String key = UUID.randomUUID().toString(); - Dog dog = new Dog(key, "Teddy"); - Cat cat = new Cat(key, "Luna"); - - final DocumentCreateOptions options = new DocumentCreateOptions() - .returnNew(true) - .returnOld(true) - .overwriteMode(OverwriteMode.replace); - collection.insertDocument(dog, options).get(); - final DocumentCreateEntity doc = collection.insertDocument(cat, options, Animal.class).get(); - assertThat(doc).isNotNull(); - assertThat(doc.getId()).isNotNull(); - assertThat(doc.getKey()).isNotNull().isEqualTo(key); - assertThat(doc.getRev()).isNotNull(); - - assertThat(doc.getOld()) - .isNotNull() - .isInstanceOf(Dog.class); - assertThat(doc.getOld().getKey()).isEqualTo(key); - assertThat(doc.getOld().getName()).isEqualTo("Teddy"); - - assertThat(doc.getNew()) - .isNotNull() - .isInstanceOf(Cat.class); - assertThat(doc.getNew().getKey()).isEqualTo(key); - assertThat(doc.getNew().getName()).isEqualTo("Luna"); - } - - @Test - void insertDocumentWaitForSync() throws InterruptedException, ExecutionException { - final DocumentCreateOptions options = new DocumentCreateOptions().waitForSync(true); - db.collection(COLLECTION_NAME) - .insertDocument(new BaseDocument(), options) - .whenComplete((doc, ex) -> { - assertThat(doc).isNotNull(); - assertThat(doc.getId()).isNotNull(); - assertThat(doc.getKey()).isNotNull(); - assertThat(doc.getRev()).isNotNull(); - assertThat(doc.getNew()).isNull(); - }) - .get(); - } - - @Test - void insertDocumentAsJson() throws InterruptedException, ExecutionException { - db.collection(COLLECTION_NAME) - .insertDocument(RawJson.of("{\"_key\":\"docRaw\",\"a\":\"test\"}"), null) - .whenComplete((doc, ex) -> { - assertThat(doc).isNotNull(); - assertThat(doc.getId()).isNotNull(); - assertThat(doc.getKey()).isNotNull(); - assertThat(doc.getRev()).isNotNull(); - }) - .get(); - } - - @Test - void getDocument() throws InterruptedException, ExecutionException { - final DocumentCreateEntity createResult = db.collection(COLLECTION_NAME) - .insertDocument(new BaseDocument(), null).get(); - assertThat(createResult.getKey()).isNotNull(); - db.collection(COLLECTION_NAME).getDocument(createResult.getKey(), BaseDocument.class, null) - .whenComplete((readResult, ex) -> { - assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); - assertThat(readResult.getId()).isEqualTo(COLLECTION_NAME + "/" + createResult.getKey()); - }) - .get(); - } - - @Test - void getDocumentIfMatch() throws InterruptedException, ExecutionException { - final DocumentCreateEntity createResult = db.collection(COLLECTION_NAME) - .insertDocument(new BaseDocument(), null).get(); - assertThat(createResult.getKey()).isNotNull(); - final DocumentReadOptions options = new DocumentReadOptions().ifMatch(createResult.getRev()); - db.collection(COLLECTION_NAME).getDocument(createResult.getKey(), BaseDocument.class, options) - .whenComplete((readResult, ex) -> { - assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); - assertThat(readResult.getId()).isEqualTo(COLLECTION_NAME + "/" + createResult.getKey()); - }) - .get(); - } - - @Test - void getDocumentIfMatchFail() throws InterruptedException, ExecutionException { - final DocumentCreateEntity createResult = db.collection(COLLECTION_NAME) - .insertDocument(new BaseDocument(), null).get(); - assertThat(createResult.getKey()).isNotNull(); - final DocumentReadOptions options = new DocumentReadOptions().ifMatch("no"); - db.collection(COLLECTION_NAME).getDocument(createResult.getKey(), BaseDocument.class, options) - .whenComplete((doc, ex) -> assertThat(doc).isNull()) - .get(); - } - - @Test - void getDocumentIfNoneMatch() throws InterruptedException, ExecutionException { - final DocumentCreateEntity createResult = db.collection(COLLECTION_NAME) - .insertDocument(new BaseDocument(), null).get(); - assertThat(createResult.getKey()).isNotNull(); - final DocumentReadOptions options = new DocumentReadOptions().ifNoneMatch("no"); - db.collection(COLLECTION_NAME).getDocument(createResult.getKey(), BaseDocument.class, options) - .whenComplete((readResult, ex) -> { - assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); - assertThat(readResult.getId()).isEqualTo(COLLECTION_NAME + "/" + createResult.getKey()); - }) - .get(); - } - - @Test - void getDocumentIfNoneMatchFail() throws InterruptedException, ExecutionException { - final DocumentCreateEntity createResult = db.collection(COLLECTION_NAME) - .insertDocument(new BaseDocument(), null).get(); - assertThat(createResult.getKey()).isNotNull(); - final DocumentReadOptions options = new DocumentReadOptions().ifNoneMatch(createResult.getRev()); - db.collection(COLLECTION_NAME).getDocument(createResult.getKey(), BaseDocument.class, options) - .whenComplete((doc, ex) -> assertThat(doc).isNull()) - .get(); - } - - @Test - void getDocumentAsJson() throws InterruptedException, ExecutionException { - db.collection(COLLECTION_NAME).insertDocument(RawJson.of("{\"_key\":\"docRaw\",\"a\":\"test\"}")).get(); - db.collection(COLLECTION_NAME).getDocument("docRaw", RawJson.class) - .whenComplete((readResult, ex) -> { - assertThat(readResult.getValue().contains("\"_key\":\"docRaw\"")).isEqualTo(true); - assertThat(readResult.getValue().contains("\"_id\":\"db_collection_test/docRaw\"")).isEqualTo(true); - }) - .get(); - } - - @Test - void getDocumentNotFound() throws InterruptedException, ExecutionException { - db.collection(COLLECTION_NAME).getDocument("no", BaseDocument.class) - .whenComplete((doc, ex) -> assertThat(doc).isNull()) - .get(); - } - - @Test - void getDocumentWrongKey() { - Throwable thrown = catchThrowable(() -> db.collection(COLLECTION_NAME).getDocument("no/no", - BaseDocument.class)); - assertThat(thrown).isInstanceOf(ArangoDBException.class); - } - - @Test - void getDocuments() throws InterruptedException, ExecutionException { - final Collection values = new ArrayList<>(); - values.add(new BaseDocument("1")); - values.add(new BaseDocument("2")); - values.add(new BaseDocument("3")); - db.collection(COLLECTION_NAME).insertDocuments(values).get(); - final MultiDocumentEntity documents = db.collection(COLLECTION_NAME) - .getDocuments(Arrays.asList("1", "2", "3"), BaseDocument.class).get(); - assertThat(documents).isNotNull(); - assertThat(documents.getDocuments()).hasSize(3); - for (final BaseDocument document : documents.getDocuments()) { - assertThat(document.getId()).isIn(COLLECTION_NAME + "/" + "1", COLLECTION_NAME + "/" + "2", - COLLECTION_NAME + "/" + "3"); - } - } - - @Test - void getDocumentsNotFound() throws InterruptedException, ExecutionException { - final MultiDocumentEntity readResult = db.collection(COLLECTION_NAME) - .getDocuments(Collections.singleton("no"), BaseDocument.class).get(); - assertThat(readResult).isNotNull(); - assertThat(readResult.getDocuments()).isEmpty(); - assertThat(readResult.getErrors()).hasSize(1); - } - - @Test - void getDocumentsWrongKey() throws InterruptedException, ExecutionException { - final MultiDocumentEntity readResult = db.collection(COLLECTION_NAME) - .getDocuments(Collections.singleton("no/no"), BaseDocument.class).get(); - assertThat(readResult).isNotNull(); - assertThat(readResult.getDocuments()).isEmpty(); - assertThat(readResult.getErrors()).hasSize(1); - } - - @Test - void updateDocument() throws InterruptedException, ExecutionException { - final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); - doc.addAttribute("a", "test"); - doc.addAttribute("c", "test"); - final DocumentCreateEntity createResult = db.collection(COLLECTION_NAME).insertDocument(doc, null) - .get(); - doc.updateAttribute("a", "test1"); - doc.addAttribute("b", "test"); - doc.updateAttribute("c", null); - - final CompletableFuture> f = db.collection(COLLECTION_NAME) - .updateDocument(createResult.getKey(), doc, null); - f.whenComplete((updateResult, ex) -> { - assertThat(updateResult).isNotNull(); - assertThat(updateResult.getId()).isEqualTo(createResult.getId()); - assertThat(updateResult.getNew()).isNull(); - assertThat(updateResult.getOld()).isNull(); - assertThat(updateResult.getRev()).isNotEqualTo(updateResult.getOldRev()); - assertThat(updateResult.getOldRev()).isEqualTo(createResult.getRev()); - }).get(); - final DocumentUpdateEntity updateResult = f.get(); - - final BaseDocument readResult = db.collection(COLLECTION_NAME) - .getDocument(createResult.getKey(), BaseDocument.class, null).get(); - assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); - assertThat(readResult.getAttribute("a")).isNotNull(); - assertThat(String.valueOf(readResult.getAttribute("a"))).isEqualTo("test1"); - assertThat(readResult.getAttribute("b")).isNotNull(); - assertThat(String.valueOf(readResult.getAttribute("b"))).isEqualTo("test"); - assertThat(readResult.getRevision()).isEqualTo(updateResult.getRev()); - assertThat(readResult.getProperties()).containsKey("c"); - } - - @Test - void updateDocumentWithDifferentReturnType() throws ExecutionException, InterruptedException { - ArangoCollectionAsync collection = db.collection(COLLECTION_NAME); - final String key = "key-" + UUID.randomUUID(); - final BaseDocument doc = new BaseDocument(key); - doc.addAttribute("a", "test"); - collection.insertDocument(doc).get(); - - final DocumentUpdateEntity updateResult = collection - .updateDocument(key, Collections.singletonMap("b", "test"), - new DocumentUpdateOptions().returnNew(true), BaseDocument.class).get(); - assertThat(updateResult).isNotNull(); - assertThat(updateResult.getKey()).isEqualTo(key); - BaseDocument updated = updateResult.getNew(); - assertThat(updated).isNotNull(); - assertThat(updated.getAttribute("a")).isEqualTo("test"); - assertThat(updated.getAttribute("b")).isEqualTo("test"); - } - - @Test - void updateDocumentIfMatch() throws InterruptedException, ExecutionException { - final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); - doc.addAttribute("a", "test"); - doc.addAttribute("c", "test"); - final DocumentCreateEntity createResult = db.collection(COLLECTION_NAME).insertDocument(doc, null) - .get(); - doc.updateAttribute("a", "test1"); - doc.addAttribute("b", "test"); - doc.updateAttribute("c", null); - final DocumentUpdateOptions options = new DocumentUpdateOptions().ifMatch(createResult.getRev()); - final CompletableFuture> f = db.collection(COLLECTION_NAME) - .updateDocument(createResult.getKey(), doc, options); - assertThat(f).isNotNull(); - f.whenComplete((updateResult, ex) -> { - assertThat(updateResult).isNotNull(); - assertThat(updateResult.getId()).isEqualTo(createResult.getId()); - assertThat(updateResult.getRev()).isNotEqualTo(updateResult.getOldRev()); - assertThat(updateResult.getOldRev()).isEqualTo(createResult.getRev()); - }).get(); - final DocumentUpdateEntity updateResult = f.get(); - - final BaseDocument readResult = db.collection(COLLECTION_NAME) - .getDocument(createResult.getKey(), BaseDocument.class, null).get(); - assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); - assertThat(readResult.getAttribute("a")).isNotNull(); - assertThat(String.valueOf(readResult.getAttribute("a"))).isEqualTo("test1"); - assertThat(readResult.getAttribute("b")).isNotNull(); - assertThat(String.valueOf(readResult.getAttribute("b"))).isEqualTo("test"); - assertThat(readResult.getRevision()).isEqualTo(updateResult.getRev()); - assertThat(readResult.getProperties()).containsKey("c"); - } - - @Test - void updateDocumentIfMatchFail() throws InterruptedException, ExecutionException { - final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); - doc.addAttribute("a", "test"); - doc.addAttribute("c", "test"); - final DocumentCreateEntity createResult = db.collection(COLLECTION_NAME).insertDocument(doc, null) - .get(); - doc.updateAttribute("a", "test1"); - doc.addAttribute("b", "test"); - doc.updateAttribute("c", null); - try { - final DocumentUpdateOptions options = new DocumentUpdateOptions().ifMatch("no"); - db.collection(COLLECTION_NAME).updateDocument(createResult.getKey(), doc, options).get(); - fail(); - } catch (final ExecutionException e) { - assertThat(e.getCause()).isInstanceOf(ArangoDBException.class); - } - } - - @Test - void updateDocumentReturnNew() throws InterruptedException, ExecutionException { - final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); - doc.addAttribute("a", "test"); - final DocumentCreateEntity createResult = db.collection(COLLECTION_NAME).insertDocument(doc, null) - .get(); - doc.updateAttribute("a", "test1"); - doc.addAttribute("b", "test"); - final DocumentUpdateOptions options = new DocumentUpdateOptions().returnNew(true); - db.collection(COLLECTION_NAME).updateDocument(createResult.getKey(), doc, options) - .whenComplete((updateResult, ex) -> { - assertThat(updateResult).isNotNull(); - assertThat(updateResult.getId()).isEqualTo(createResult.getId()); - assertThat(updateResult.getOldRev()).isEqualTo(createResult.getRev()); - assertThat(updateResult.getNew()).isNotNull(); - assertThat(updateResult.getNew().getKey()).isEqualTo(createResult.getKey()); - assertThat(updateResult.getNew().getRevision()).isNotEqualTo(createResult.getRev()); - assertThat(updateResult.getNew().getAttribute("a")).isNotNull(); - assertThat(String.valueOf(updateResult.getNew().getAttribute("a"))).isEqualTo("test1"); - assertThat(updateResult.getNew().getAttribute("b")).isNotNull(); - assertThat(String.valueOf(updateResult.getNew().getAttribute("b"))).isEqualTo("test"); - }) - .get(); - } - - @Test - void updateDocumentReturnOld() throws InterruptedException, ExecutionException { - final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); - doc.addAttribute("a", "test"); - final DocumentCreateEntity createResult = db.collection(COLLECTION_NAME).insertDocument(doc, null) - .get(); - doc.updateAttribute("a", "test1"); - doc.addAttribute("b", "test"); - final DocumentUpdateOptions options = new DocumentUpdateOptions().returnOld(true); - db.collection(COLLECTION_NAME).updateDocument(createResult.getKey(), doc, options) - .whenComplete((updateResult, ex) -> { - assertThat(updateResult).isNotNull(); - assertThat(updateResult.getId()).isEqualTo(createResult.getId()); - assertThat(updateResult.getOldRev()).isEqualTo(createResult.getRev()); - assertThat(updateResult.getOld()).isNotNull(); - assertThat(updateResult.getOld().getKey()).isEqualTo(createResult.getKey()); - assertThat(updateResult.getOld().getRevision()).isEqualTo(createResult.getRev()); - assertThat(updateResult.getOld().getAttribute("a")).isNotNull(); - assertThat(String.valueOf(updateResult.getOld().getAttribute("a"))).isEqualTo("test"); - assertThat(updateResult.getOld().getProperties().keySet()).doesNotContain("b"); - }) - .get(); - } - - @Test - void updateDocumentKeepNullTrue() throws InterruptedException, ExecutionException { - final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); - doc.addAttribute("a", "test"); - final DocumentCreateEntity createResult = db.collection(COLLECTION_NAME).insertDocument(doc, null) - .get(); - doc.updateAttribute("a", null); - final DocumentUpdateOptions options = new DocumentUpdateOptions().keepNull(true); - db.collection(COLLECTION_NAME).updateDocument(createResult.getKey(), doc, options) - .whenComplete((updateResult, ex) -> { - assertThat(updateResult).isNotNull(); - assertThat(updateResult.getId()).isEqualTo(createResult.getId()); - assertThat(updateResult.getRev()).isNotEqualTo(updateResult.getOldRev()); - assertThat(updateResult.getOldRev()).isEqualTo(createResult.getRev()); - }) - .get(); - - final BaseDocument readResult = db.collection(COLLECTION_NAME) - .getDocument(createResult.getKey(), BaseDocument.class, null).get(); - assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); - assertThat(readResult.getProperties()).containsKey("a"); - } - - @Test - void updateDocumentKeepNullFalse() throws InterruptedException, ExecutionException { - final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); - doc.addAttribute("a", "test"); - final DocumentCreateEntity createResult = db.collection(COLLECTION_NAME).insertDocument(doc, null) - .get(); - doc.updateAttribute("a", null); - final DocumentUpdateOptions options = new DocumentUpdateOptions().keepNull(false); - db.collection(COLLECTION_NAME).updateDocument(createResult.getKey(), doc, options) - .whenComplete((updateResult, ex) -> { - assertThat(updateResult).isNotNull(); - assertThat(updateResult.getId()).isEqualTo(createResult.getId()); - assertThat(updateResult.getRev()).isNotEqualTo(updateResult.getOldRev()); - assertThat(updateResult.getOldRev()).isEqualTo(createResult.getRev()); - }) - .get(); - - final BaseDocument readResult = db.collection(COLLECTION_NAME) - .getDocument(createResult.getKey(), BaseDocument.class, null).get(); - assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); - assertThat(readResult.getId()).isEqualTo(createResult.getId()); - assertThat(readResult.getRevision()).isNotNull(); - assertThat(readResult.getProperties().keySet()).doesNotContain("a"); - } - - @Test - void updateDocumentMergeObjectsTrue() throws InterruptedException, ExecutionException { - final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); - final Map a = new HashMap<>(); - a.put("a", "test"); - doc.addAttribute("a", a); - final DocumentCreateEntity createResult = db.collection(COLLECTION_NAME).insertDocument(doc, null) - .get(); - a.clear(); - a.put("b", "test"); - doc.updateAttribute("a", a); - final DocumentUpdateOptions options = new DocumentUpdateOptions().mergeObjects(true); - db.collection(COLLECTION_NAME).updateDocument(createResult.getKey(), doc, options) - .whenComplete((updateResult, ex) -> { - assertThat(updateResult).isNotNull(); - assertThat(updateResult.getId()).isEqualTo(createResult.getId()); - assertThat(updateResult.getRev()).isNotEqualTo(updateResult.getOldRev()); - assertThat(updateResult.getOldRev()).isEqualTo(createResult.getRev()); - }) - .get(); - - final BaseDocument readResult = db.collection(COLLECTION_NAME) - .getDocument(createResult.getKey(), BaseDocument.class, null).get(); - assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); - final Object aResult = readResult.getAttribute("a"); - assertThat(aResult).isInstanceOf(Map.class); - final Map aMap = (Map) aResult; - assertThat(aMap).containsKey("a"); - assertThat(aMap).containsKey("b"); - } - - @Test - void updateDocumentMergeObjectsFalse() throws InterruptedException, ExecutionException { - final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); - final Map a = new HashMap<>(); - a.put("a", "test"); - doc.addAttribute("a", a); - final DocumentCreateEntity createResult = db.collection(COLLECTION_NAME).insertDocument(doc, null) - .get(); - a.clear(); - a.put("b", "test"); - doc.updateAttribute("a", a); - final DocumentUpdateOptions options = new DocumentUpdateOptions().mergeObjects(false); - db.collection(COLLECTION_NAME).updateDocument(createResult.getKey(), doc, options) - .whenComplete((updateResult, ex) -> { - assertThat(updateResult).isNotNull(); - assertThat(updateResult.getId()).isEqualTo(createResult.getId()); - assertThat(updateResult.getRev()).isNotEqualTo(updateResult.getOldRev()); - assertThat(updateResult.getOldRev()).isEqualTo(createResult.getRev()); - }) - .get(); - - final BaseDocument readResult = db.collection(COLLECTION_NAME) - .getDocument(createResult.getKey(), BaseDocument.class, null).get(); - assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); - final Object aResult = readResult.getAttribute("a"); - assertThat(aResult).isInstanceOf(Map.class); - final Map aMap = (Map) aResult; - assertThat(aMap.keySet()).doesNotContain("a"); - assertThat(aMap).containsKey("b"); - } - - @Test - void updateDocumentIgnoreRevsFalse() throws InterruptedException, ExecutionException { - final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); - doc.addAttribute("a", "test"); - final DocumentCreateEntity createResult = db.collection(COLLECTION_NAME).insertDocument(doc, null) - .get(); - doc.updateAttribute("a", "test1"); - doc.setRevision("no"); - try { - final DocumentUpdateOptions options = new DocumentUpdateOptions().ignoreRevs(false); - db.collection(COLLECTION_NAME).updateDocument(createResult.getKey(), doc, options).get(); - fail(); - } catch (final ExecutionException e) { - assertThat(e.getCause()).isInstanceOf(ArangoDBException.class); - } - } - - @Test - void replaceDocument() throws InterruptedException, ExecutionException { - final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); - doc.addAttribute("a", "test"); - final DocumentCreateEntity createResult = db.collection(COLLECTION_NAME).insertDocument(doc, null) - .get(); - doc.removeAttribute("a"); - doc.addAttribute("b", "test"); - final CompletableFuture> f = db.collection(COLLECTION_NAME) - .replaceDocument(createResult.getKey(), doc, null); - f.whenComplete((replaceResult, ex) -> { - assertThat(replaceResult).isNotNull(); - assertThat(replaceResult.getId()).isEqualTo(createResult.getId()); - assertThat(replaceResult.getNew()).isNull(); - assertThat(replaceResult.getOld()).isNull(); - assertThat(replaceResult.getRev()).isNotEqualTo(replaceResult.getOldRev()); - assertThat(replaceResult.getOldRev()).isEqualTo(createResult.getRev()); - }).get(); - final DocumentUpdateEntity replaceResult = f.get(); - - final BaseDocument readResult = db.collection(COLLECTION_NAME) - .getDocument(createResult.getKey(), BaseDocument.class, null).get(); - assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); - assertThat(readResult.getRevision()).isEqualTo(replaceResult.getRev()); - assertThat(readResult.getProperties().keySet()).doesNotContain("a"); - assertThat(readResult.getAttribute("b")).isNotNull(); - assertThat(String.valueOf(readResult.getAttribute("b"))).isEqualTo("test"); - } - - @Test - void replaceDocumentIfMatch() throws InterruptedException, ExecutionException { - final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); - doc.addAttribute("a", "test"); - final DocumentCreateEntity createResult = db.collection(COLLECTION_NAME).insertDocument(doc, null) - .get(); - doc.removeAttribute("a"); - doc.addAttribute("b", "test"); - final DocumentReplaceOptions options = new DocumentReplaceOptions().ifMatch(createResult.getRev()); - final CompletableFuture> f = db.collection(COLLECTION_NAME) - .replaceDocument(createResult.getKey(), doc, options); - f.whenComplete((replaceResult, ex) -> { - assertThat(replaceResult).isNotNull(); - assertThat(replaceResult.getId()).isEqualTo(createResult.getId()); - assertThat(replaceResult.getRev()).isNotEqualTo(replaceResult.getOldRev()); - assertThat(replaceResult.getOldRev()).isEqualTo(createResult.getRev()); - }).get(); - final DocumentUpdateEntity replaceResult = f.get(); - - final BaseDocument readResult = db.collection(COLLECTION_NAME) - .getDocument(createResult.getKey(), BaseDocument.class, null).get(); - assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); - assertThat(readResult.getRevision()).isEqualTo(replaceResult.getRev()); - assertThat(readResult.getProperties().keySet()).doesNotContain("a"); - assertThat(readResult.getAttribute("b")).isNotNull(); - assertThat(String.valueOf(readResult.getAttribute("b"))).isEqualTo("test"); - } - - @Test - void replaceDocumentIfMatchFail() throws InterruptedException, ExecutionException { - final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); - doc.addAttribute("a", "test"); - final DocumentCreateEntity createResult = db.collection(COLLECTION_NAME).insertDocument(doc, null) - .get(); - doc.removeAttribute("a"); - doc.addAttribute("b", "test"); - try { - final DocumentReplaceOptions options = new DocumentReplaceOptions().ifMatch("no"); - db.collection(COLLECTION_NAME).replaceDocument(createResult.getKey(), doc, options).get(); - fail(); - } catch (final ExecutionException e) { - assertThat(e.getCause()).isInstanceOf(ArangoDBException.class); - } - } - - @Test - void replaceDocumentIgnoreRevsFalse() throws InterruptedException, ExecutionException { - final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); - doc.addAttribute("a", "test"); - final DocumentCreateEntity createResult = db.collection(COLLECTION_NAME).insertDocument(doc, null) - .get(); - doc.removeAttribute("a"); - doc.addAttribute("b", "test"); - doc.setRevision("no"); - try { - final DocumentReplaceOptions options = new DocumentReplaceOptions().ignoreRevs(false); - db.collection(COLLECTION_NAME).replaceDocument(createResult.getKey(), doc, options).get(); - fail(); - } catch (final ExecutionException e) { - assertThat(e.getCause()).isInstanceOf(ArangoDBException.class); - } - } - - @Test - void replaceDocumentReturnNew() throws InterruptedException, ExecutionException { - final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); - doc.addAttribute("a", "test"); - final DocumentCreateEntity createResult = db.collection(COLLECTION_NAME).insertDocument(doc, null) - .get(); - doc.removeAttribute("a"); - doc.addAttribute("b", "test"); - final DocumentReplaceOptions options = new DocumentReplaceOptions().returnNew(true); - db.collection(COLLECTION_NAME).replaceDocument(createResult.getKey(), doc, options) - .whenComplete((replaceResult, ex) -> { - assertThat(replaceResult).isNotNull(); - assertThat(replaceResult.getId()).isEqualTo(createResult.getId()); - assertThat(replaceResult.getOldRev()).isEqualTo(createResult.getRev()); - assertThat(replaceResult.getNew()).isNotNull(); - assertThat(replaceResult.getNew().getKey()).isEqualTo(createResult.getKey()); - assertThat(replaceResult.getNew().getRevision()).isNotEqualTo(createResult.getRev()); - assertThat(replaceResult.getNew().getProperties().keySet()).doesNotContain("a"); - assertThat(replaceResult.getNew().getAttribute("b")).isNotNull(); - assertThat(String.valueOf(replaceResult.getNew().getAttribute("b"))).isEqualTo("test"); - }) - .get(); - } - - @Test - void replaceDocumentReturnOld() throws InterruptedException, ExecutionException { - final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); - doc.addAttribute("a", "test"); - final DocumentCreateEntity createResult = db.collection(COLLECTION_NAME).insertDocument(doc, null) - .get(); - doc.removeAttribute("a"); - doc.addAttribute("b", "test"); - final DocumentReplaceOptions options = new DocumentReplaceOptions().returnOld(true); - db.collection(COLLECTION_NAME).replaceDocument(createResult.getKey(), doc, options) - .whenComplete((replaceResult, ex) -> { - assertThat(replaceResult).isNotNull(); - assertThat(replaceResult.getId()).isEqualTo(createResult.getId()); - assertThat(replaceResult.getOldRev()).isEqualTo(createResult.getRev()); - assertThat(replaceResult.getOld()).isNotNull(); - assertThat(replaceResult.getOld().getKey()).isEqualTo(createResult.getKey()); - assertThat(replaceResult.getOld().getRevision()).isEqualTo(createResult.getRev()); - assertThat(replaceResult.getOld().getAttribute("a")).isNotNull(); - assertThat(String.valueOf(replaceResult.getOld().getAttribute("a"))).isEqualTo("test"); - assertThat(replaceResult.getOld().getProperties().keySet()).doesNotContain("b"); - }) - .get(); - } - - @Test - void deleteDocument() throws InterruptedException, ExecutionException { - final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); - final DocumentCreateEntity createResult = db.collection(COLLECTION_NAME).insertDocument(doc, null) - .get(); - db.collection(COLLECTION_NAME).deleteDocument(createResult.getKey()).get(); - db.collection(COLLECTION_NAME).getDocument(createResult.getKey(), BaseDocument.class, null) - .whenComplete((document, ex) -> assertThat(document).isNull()) - .get(); - } - - @Test - void deleteDocumentReturnOld() throws InterruptedException, ExecutionException { - final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); - doc.addAttribute("a", "test"); - final DocumentCreateEntity createResult = db.collection(COLLECTION_NAME).insertDocument(doc, null) - .get(); - final DocumentDeleteOptions options = new DocumentDeleteOptions().returnOld(true); - db.collection(COLLECTION_NAME).deleteDocument(createResult.getKey(), options, BaseDocument.class) - .whenComplete((deleteResult, ex) -> { - assertThat(deleteResult.getOld()).isNotNull(); - assertThat(deleteResult.getOld()).isInstanceOf(BaseDocument.class); - assertThat(deleteResult.getOld().getAttribute("a")).isNotNull(); - assertThat(String.valueOf(deleteResult.getOld().getAttribute("a"))).isEqualTo("test"); - }) - .get(); - } - - @Test - void deleteDocumentIfMatch() throws InterruptedException, ExecutionException { - final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); - final DocumentCreateEntity createResult = db.collection(COLLECTION_NAME).insertDocument(doc, null) - .get(); - final DocumentDeleteOptions options = new DocumentDeleteOptions().ifMatch(createResult.getRev()); - db.collection(COLLECTION_NAME).deleteDocument(createResult.getKey(), options).get(); - db.collection(COLLECTION_NAME).getDocument(createResult.getKey(), BaseDocument.class, null) - .whenComplete((document, ex) -> assertThat(document).isNull()) - .get(); - } - - @Test - void deleteDocumentIfMatchFail() throws InterruptedException, ExecutionException { - final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); - final DocumentCreateEntity createResult = db.collection(COLLECTION_NAME).insertDocument(doc, null) - .get(); - final DocumentDeleteOptions options = new DocumentDeleteOptions().ifMatch("no"); - try { - db.collection(COLLECTION_NAME).deleteDocument(createResult.getKey(), options).get(); - fail(); - } catch (final ExecutionException e) { - assertThat(e.getCause()).isInstanceOf(ArangoDBException.class); - } - } - - @Test - void getIndex() throws InterruptedException, ExecutionException { - final Collection fields = new ArrayList<>(); - fields.add("a"); - final IndexEntity createResult = db.collection(COLLECTION_NAME).ensureHashIndex(fields, null).get(); - db.collection(COLLECTION_NAME).getIndex(createResult.getId()) - .whenComplete((readResult, ex) -> { - assertThat(readResult.getId()).isEqualTo(createResult.getId()); - assertThat(readResult.getType()).isEqualTo(createResult.getType()); - }) - .get(); - } - - @Test - void getIndexByKey() throws InterruptedException, ExecutionException { - final Collection fields = new ArrayList<>(); - fields.add("a"); - final IndexEntity createResult = db.collection(COLLECTION_NAME).ensureHashIndex(fields, null).get(); - db.collection(COLLECTION_NAME).getIndex(createResult.getId().split("/")[1]) - .whenComplete((readResult, ex) -> { - assertThat(readResult.getId()).isEqualTo(createResult.getId()); - assertThat(readResult.getType()).isEqualTo(createResult.getType()); - }) - .get(); - } - - @Test - void deleteIndex() throws InterruptedException, ExecutionException { - final Collection fields = new ArrayList<>(); - fields.add("deleteIndexField"); - final IndexEntity createResult = db.collection(COLLECTION_NAME).ensureHashIndex(fields, null).get(); - db.getIndex(createResult.getId()).get(); - db.collection(COLLECTION_NAME).deleteIndex(createResult.getId()) - .whenComplete((id, ex) -> { - assertThat(id).isEqualTo(createResult.getId()); - try { - db.getIndex(id).get(); - fail(); - } catch (final InterruptedException exception) { - exception.printStackTrace(); - fail(); - } catch (final ExecutionException exception) { - assertThat(exception.getCause()).isInstanceOf(ArangoDBException.class); - } - }) - .get(); - } - - @Test - void deleteIndexByKey() throws InterruptedException, ExecutionException { - final Collection fields = new ArrayList<>(); - fields.add("deleteIndexByKeyField"); - final IndexEntity createResult = db.collection(COLLECTION_NAME).ensureHashIndex(fields, null).get(); - db.getIndex(createResult.getId()).get(); - db.collection(COLLECTION_NAME).deleteIndex(createResult.getId().split("/")[1]) - .whenComplete((id, ex) -> { - assertThat(id).isEqualTo(createResult.getId()); - try { - db.getIndex(id).get(); - fail(); - } catch (final InterruptedException exception) { - exception.printStackTrace(); - fail(); - } catch (final ExecutionException exception) { - assertThat(exception.getCause()).isInstanceOf(ArangoDBException.class); - } - }) - .get(); - } - - @Test - void createHashIndex() throws InterruptedException, ExecutionException { - final boolean singleServer = isSingleServer(); - final Collection fields = new ArrayList<>(); - fields.add("a"); - fields.add("b"); - db.collection(COLLECTION_NAME).ensureHashIndex(fields, null) - .whenComplete((indexResult, ex) -> { - assertThat(indexResult).isNotNull(); - assertThat(indexResult.getConstraint()).isNull(); - assertThat(indexResult.getFields()).contains("a"); - assertThat(indexResult.getFields()).contains("b"); - assertThat(indexResult.getGeoJson()).isNull(); - assertThat(indexResult.getId()).startsWith(COLLECTION_NAME); - assertThat(indexResult.getIsNewlyCreated()).isEqualTo(true); - assertThat(indexResult.getMinLength()).isNull(); - if (singleServer) { - assertThat(indexResult.getSelectivityEstimate()).isEqualTo(1.0); - } - assertThat(indexResult.getSparse()).isEqualTo(false); - assertThat(indexResult.getType()).isEqualTo(IndexType.hash); - assertThat(indexResult.getUnique()).isEqualTo(false); - }) - .get(); - } - - @Test - void createHashIndexWithOptions() throws ExecutionException, InterruptedException { - assumeTrue(isAtLeastVersion(3, 5)); - final HashIndexOptions options = new HashIndexOptions(); - options.name("myHashIndex"); - - final Collection fields = new ArrayList<>(); - fields.add("a"); - fields.add("b"); - final IndexEntity indexResult = db.collection(COLLECTION_NAME).ensureHashIndex(fields, options).get(); - assertThat(indexResult).isNotNull(); - assertThat(indexResult.getConstraint()).isNull(); - assertThat(indexResult.getFields()).contains("a"); - assertThat(indexResult.getFields()).contains("b"); - assertThat(indexResult.getId()).startsWith(COLLECTION_NAME); - assertThat(indexResult.getIsNewlyCreated()).isTrue(); - assertThat(indexResult.getMinLength()).isNull(); - if (isSingleServer()) { - assertThat(indexResult.getSelectivityEstimate()).isEqualTo(1.); - } - assertThat(indexResult.getSparse()).isFalse(); - assertThat(indexResult.getType()).isEqualTo(IndexType.hash); - assertThat(indexResult.getUnique()).isFalse(); - assertThat(indexResult.getName()).isEqualTo("myHashIndex"); - } - - @Test - void createGeoIndex() throws InterruptedException, ExecutionException { - final Collection fields = new ArrayList<>(); - fields.add("a"); - db.collection(COLLECTION_NAME).ensureGeoIndex(fields, null) - .whenComplete((indexResult, ex) -> { - assertThat(indexResult).isNotNull(); - assertThat(indexResult.getFields()).contains("a"); - assertThat(indexResult.getGeoJson()).isEqualTo(false); - assertThat(indexResult.getId()).startsWith(COLLECTION_NAME); - assertThat(indexResult.getIsNewlyCreated()).isEqualTo(true); - assertThat(indexResult.getMinLength()).isNull(); - assertThat(indexResult.getSelectivityEstimate()).isNull(); - assertThat(indexResult.getSparse()).isEqualTo(true); - assertThat(indexResult.getType()).isIn(IndexType.geo, IndexType.geo1); - assertThat(indexResult.getUnique()).isEqualTo(false); - }) - .get(); - } - - @Test - void createGeoIndexWithOptions() throws ExecutionException, InterruptedException { - assumeTrue(isAtLeastVersion(3, 5)); - final GeoIndexOptions options = new GeoIndexOptions(); - options.name("myGeoIndex1"); - - final Collection fields = new ArrayList<>(); - fields.add("a"); - final IndexEntity indexResult = db.collection(COLLECTION_NAME).ensureGeoIndex(fields, options).get(); - assertThat(indexResult).isNotNull(); - assertThat(indexResult.getFields()).contains("a"); - assertThat(indexResult.getId()).startsWith(COLLECTION_NAME); - assertThat(indexResult.getIsNewlyCreated()).isTrue(); - assertThat(indexResult.getMinLength()).isNull(); - assertThat(indexResult.getSparse()).isTrue(); - assertThat(indexResult.getUnique()).isFalse(); - if (isAtLeastVersion(3, 4)) { - assertThat(indexResult.getType()).isEqualTo(IndexType.geo); - } else { - assertThat(indexResult.getType()).isEqualTo(IndexType.geo1); - } - assertThat(indexResult.getName()).isEqualTo("myGeoIndex1"); - } - - @Test - void createGeo2Index() throws ExecutionException, InterruptedException { - final Collection fields = new ArrayList<>(); - fields.add("a"); - fields.add("b"); - db.collection(COLLECTION_NAME).ensureGeoIndex(fields, null).whenComplete((indexResult, ex) -> { - assertThat(indexResult).isNotNull(); - assertThat(indexResult.getFields()).contains("a"); - assertThat(indexResult.getFields()).contains("b"); - assertThat(indexResult.getId()).startsWith(COLLECTION_NAME); - assertThat(indexResult.getIsNewlyCreated()).isEqualTo(true); - assertThat(indexResult.getMinLength()).isNull(); - assertThat(indexResult.getSparse()).isEqualTo(true); - assertThat(indexResult.getUnique()).isEqualTo(false); - try { - if (isAtLeastVersion(3, 4)) { - assertThat(indexResult.getType()).isEqualTo(IndexType.geo); - } else { - assertThat(indexResult.getType()).isEqualTo(IndexType.geo2); - } - } catch (InterruptedException | ExecutionException e) { - e.printStackTrace(); - fail(); - } - }).get(); - } - - @Test - void createGeo2IndexWithOptions() throws ExecutionException, InterruptedException { - assumeTrue(isAtLeastVersion(3, 5)); - final GeoIndexOptions options = new GeoIndexOptions(); - options.name("myGeoIndex2"); - - final Collection fields = new ArrayList<>(); - fields.add("a"); - fields.add("b"); - final IndexEntity indexResult = db.collection(COLLECTION_NAME).ensureGeoIndex(fields, options).get(); - assertThat(indexResult).isNotNull(); - assertThat(indexResult.getFields()).contains("a"); - assertThat(indexResult.getFields()).contains("b"); - assertThat(indexResult.getId()).startsWith(COLLECTION_NAME); - assertThat(indexResult.getIsNewlyCreated()).isTrue(); - assertThat(indexResult.getMinLength()).isNull(); - assertThat(indexResult.getSparse()).isTrue(); - assertThat(indexResult.getUnique()).isFalse(); - if (isAtLeastVersion(3, 4)) { - assertThat(indexResult.getType()).isEqualTo(IndexType.geo); - } else { - assertThat(indexResult.getType()).isEqualTo(IndexType.geo2); - } - assertThat(indexResult.getName()).isEqualTo("myGeoIndex2"); - } - - @Test - void createSkiplistIndex() throws InterruptedException, ExecutionException { - final Collection fields = new ArrayList<>(); - fields.add("a"); - fields.add("b"); - db.collection(COLLECTION_NAME).ensureSkiplistIndex(fields, null) - .whenComplete((indexResult, ex) -> { - assertThat(indexResult).isNotNull(); - assertThat(indexResult.getConstraint()).isNull(); - assertThat(indexResult.getFields()).contains("a"); - assertThat(indexResult.getFields()).contains("b"); - assertThat(indexResult.getGeoJson()).isNull(); - assertThat(indexResult.getId()).startsWith(COLLECTION_NAME); - assertThat(indexResult.getIsNewlyCreated()).isEqualTo(true); - assertThat(indexResult.getMinLength()).isNull(); - assertThat(indexResult.getSparse()).isEqualTo(false); - assertThat(indexResult.getType()).isEqualTo(IndexType.skiplist); - assertThat(indexResult.getUnique()).isEqualTo(false); - }) - .get(); - } - - @Test - void createSkiplistIndexWithOptions() throws ExecutionException, InterruptedException { - assumeTrue(isAtLeastVersion(3, 5)); - final SkiplistIndexOptions options = new SkiplistIndexOptions(); - options.name("mySkiplistIndex"); - - final Collection fields = new ArrayList<>(); - fields.add("a"); - fields.add("b"); - final IndexEntity indexResult = db.collection(COLLECTION_NAME).ensureSkiplistIndex(fields, options).get(); - assertThat(indexResult).isNotNull(); - assertThat(indexResult.getConstraint()).isNull(); - assertThat(indexResult.getFields()).contains("a"); - assertThat(indexResult.getFields()).contains("b"); - assertThat(indexResult.getId()).startsWith(COLLECTION_NAME); - assertThat(indexResult.getIsNewlyCreated()).isTrue(); - assertThat(indexResult.getMinLength()).isNull(); - assertThat(indexResult.getSparse()).isFalse(); - assertThat(indexResult.getType()).isEqualTo(IndexType.skiplist); - assertThat(indexResult.getUnique()).isFalse(); - assertThat(indexResult.getName()).isEqualTo("mySkiplistIndex"); - } - - @Test - void createPersistentIndex() throws InterruptedException, ExecutionException { - final Collection fields = new ArrayList<>(); - fields.add("a"); - fields.add("b"); - db.collection(COLLECTION_NAME).ensurePersistentIndex(fields, null) - .whenComplete((indexResult, ex) -> { - assertThat(indexResult).isNotNull(); - assertThat(indexResult.getConstraint()).isNull(); - assertThat(indexResult.getFields()).contains("a"); - assertThat(indexResult.getFields()).contains("b"); - assertThat(indexResult.getGeoJson()).isNull(); - assertThat(indexResult.getId()).startsWith(COLLECTION_NAME); - assertThat(indexResult.getIsNewlyCreated()).isEqualTo(true); - assertThat(indexResult.getMinLength()).isNull(); - assertThat(indexResult.getSparse()).isEqualTo(false); - assertThat(indexResult.getType()).isEqualTo(IndexType.persistent); - assertThat(indexResult.getUnique()).isEqualTo(false); - assertThat(indexResult.getDeduplicate()).isTrue(); - }) - .get(); - } - - @Test - void createPersistentIndexWithOptions() throws ExecutionException, InterruptedException { - assumeTrue(isAtLeastVersion(3, 5)); - final PersistentIndexOptions options = new PersistentIndexOptions(); - options.name("myPersistentIndex"); - - final Collection fields = new ArrayList<>(); - fields.add("a"); - fields.add("b"); - final IndexEntity indexResult = db.collection(COLLECTION_NAME).ensurePersistentIndex(fields, options).get(); - assertThat(indexResult).isNotNull(); - assertThat(indexResult.getConstraint()).isNull(); - assertThat(indexResult.getFields()).contains("a"); - assertThat(indexResult.getFields()).contains("b"); - assertThat(indexResult.getId()).startsWith(COLLECTION_NAME); - assertThat(indexResult.getIsNewlyCreated()).isTrue(); - assertThat(indexResult.getMinLength()).isNull(); - assertThat(indexResult.getSparse()).isFalse(); - assertThat(indexResult.getType()).isEqualTo(IndexType.persistent); - assertThat(indexResult.getUnique()).isFalse(); - assertThat(indexResult.getName()).isEqualTo("myPersistentIndex"); - } - - @Test - void indexDeduplicate() throws ExecutionException, InterruptedException { - assumeTrue(isAtLeastVersion(3, 8)); - - String name = "persistentIndex-" + rnd(); - final PersistentIndexOptions options = new PersistentIndexOptions(); - options.name(name); - options.deduplicate(true); - - String f1 = "field-" + rnd(); - String f2 = "field-" + rnd(); - - final Collection fields = Arrays.asList(f1, f2); - final IndexEntity indexResult = db.collection(COLLECTION_NAME).ensurePersistentIndex(fields, options).get(); - assertThat(indexResult).isNotNull(); - assertThat(indexResult.getDeduplicate()).isTrue(); - } - - @Test - void indexDeduplicateFalse() throws ExecutionException, InterruptedException { - assumeTrue(isAtLeastVersion(3, 8)); - - String name = "persistentIndex-" + rnd(); - final PersistentIndexOptions options = new PersistentIndexOptions(); - options.name(name); - options.deduplicate(false); - - String f1 = "field-" + rnd(); - String f2 = "field-" + rnd(); - - final Collection fields = Arrays.asList(f1, f2); - final IndexEntity indexResult = db.collection(COLLECTION_NAME).ensurePersistentIndex(fields, options).get(); - assertThat(indexResult).isNotNull(); - assertThat(indexResult.getDeduplicate()).isFalse(); - } - - @Test - void createFulltextIndex() throws InterruptedException, ExecutionException { - final Collection fields = new ArrayList<>(); - fields.add("a"); - db.collection(COLLECTION_NAME).ensureFulltextIndex(fields, null) - .whenComplete((indexResult, ex) -> { - assertThat(indexResult).isNotNull(); - assertThat(indexResult.getConstraint()).isNull(); - assertThat(indexResult.getFields()).contains("a"); - assertThat(indexResult.getGeoJson()).isNull(); - assertThat(indexResult.getId()).startsWith(COLLECTION_NAME); - assertThat(indexResult.getIsNewlyCreated()).isEqualTo(true); - assertThat(indexResult.getSelectivityEstimate()).isNull(); - assertThat(indexResult.getSparse()).isEqualTo(true); - assertThat(indexResult.getType()).isEqualTo(IndexType.fulltext); - assertThat(indexResult.getUnique()).isEqualTo(false); - }) - .get(); - } - - @Test - void createFulltextIndexWithOptions() throws ExecutionException, InterruptedException { - assumeTrue(isAtLeastVersion(3, 5)); - final FulltextIndexOptions options = new FulltextIndexOptions(); - options.name("myFulltextIndex"); - - final Collection fields = new ArrayList<>(); - fields.add("a"); - final IndexEntity indexResult = db.collection(COLLECTION_NAME).ensureFulltextIndex(fields, options).get(); - assertThat(indexResult).isNotNull(); - assertThat(indexResult.getConstraint()).isNull(); - assertThat(indexResult.getFields()).contains("a"); - assertThat(indexResult.getId()).startsWith(COLLECTION_NAME); - assertThat(indexResult.getIsNewlyCreated()).isTrue(); - assertThat(indexResult.getSparse()).isTrue(); - assertThat(indexResult.getType()).isEqualTo(IndexType.fulltext); - assertThat(indexResult.getUnique()).isFalse(); - assertThat(indexResult.getName()).isEqualTo("myFulltextIndex"); - } - - @Test - void createTtlIndexWithoutOptions() throws ExecutionException, InterruptedException { - assumeTrue(isAtLeastVersion(3, 5)); - final Collection fields = new ArrayList<>(); - fields.add("a"); - try { - db.collection(COLLECTION_NAME).ensureTtlIndex(fields, null).get(); - fail(); - } catch (ExecutionException e) { - assertThat(e.getCause()).isInstanceOf(ArangoDBException.class); - assertThat(e.getCause().getMessage()).contains("expireAfter attribute must be a number"); - assertThat(((ArangoDBException) e.getCause()).getResponseCode()).isEqualTo(400); - assertThat(((ArangoDBException) e.getCause()).getErrorNum()).isEqualTo(10); - } - } - - @Test - void createTtlIndexWithOptions() throws ExecutionException, InterruptedException { - assumeTrue(isAtLeastVersion(3, 5)); - final Collection fields = new ArrayList<>(); - fields.add("a"); - - final TtlIndexOptions options = new TtlIndexOptions(); - options.name("myTtlIndex"); - options.expireAfter(3600); - - final IndexEntity indexResult = db.collection(COLLECTION_NAME).ensureTtlIndex(fields, options).get(); - assertThat(indexResult).isNotNull(); - assertThat(indexResult.getFields()).contains("a"); - assertThat(indexResult.getId()).startsWith(COLLECTION_NAME); - assertThat(indexResult.getIsNewlyCreated()).isTrue(); - assertThat(indexResult.getType()).isEqualTo(IndexType.ttl); - assertThat(indexResult.getExpireAfter()).isEqualTo(3600); - assertThat(indexResult.getName()).isEqualTo("myTtlIndex"); - } - - @Test - void createZKDIndex() throws InterruptedException, ExecutionException { - assumeTrue(isAtLeastVersion(3, 9)); - db.collection(COLLECTION_NAME).truncate().get(); - - final Collection fields = new ArrayList<>(); - fields.add("a"); - fields.add("b"); - IndexEntity indexResult = db.collection(COLLECTION_NAME).ensureZKDIndex(fields, null).get(); - assertThat(indexResult).isNotNull(); - assertThat(indexResult.getConstraint()).isNull(); - assertThat(indexResult.getFields()).contains("a"); - assertThat(indexResult.getFields()).contains("b"); - assertThat(indexResult.getGeoJson()).isNull(); - assertThat(indexResult.getId()).startsWith(COLLECTION_NAME); - assertThat(indexResult.getIsNewlyCreated()).isTrue(); - assertThat(indexResult.getMinLength()).isNull(); - assertThat(indexResult.getType()).isEqualTo(IndexType.zkd); - assertThat(indexResult.getUnique()).isFalse(); - db.collection(COLLECTION_NAME).deleteIndex(indexResult.getId()).get(); - } - - @Test - void createZKDIndexWithOptions() throws ExecutionException, InterruptedException { - assumeTrue(isAtLeastVersion(3, 9)); - db.collection(COLLECTION_NAME).truncate().get(); - - final ZKDIndexOptions options = new ZKDIndexOptions() - .name("myZKDIndex") - .fieldValueTypes(ZKDIndexOptions.FieldValueTypes.DOUBLE); - - final Collection fields = new ArrayList<>(); - fields.add("a"); - fields.add("b"); - final IndexEntity indexResult = db.collection(COLLECTION_NAME).ensureZKDIndex(fields, options).get(); - assertThat(indexResult).isNotNull(); - assertThat(indexResult.getConstraint()).isNull(); - assertThat(indexResult.getFields()).contains("a"); - assertThat(indexResult.getFields()).contains("b"); - assertThat(indexResult.getId()).startsWith(COLLECTION_NAME); - assertThat(indexResult.getIsNewlyCreated()).isTrue(); - assertThat(indexResult.getMinLength()).isNull(); - assertThat(indexResult.getType()).isEqualTo(IndexType.zkd); - assertThat(indexResult.getUnique()).isFalse(); - assertThat(indexResult.getName()).isEqualTo("myZKDIndex"); - db.collection(COLLECTION_NAME).deleteIndex(indexResult.getId()).get(); - } - - @Test - void getIndexes() throws InterruptedException, ExecutionException { - final int initialIndexCount = db.collection(COLLECTION_NAME).getIndexes().get().size(); - final Collection fields = new ArrayList<>(); - fields.add("a"); - db.collection(COLLECTION_NAME).ensureHashIndex(fields, null).get(); - db.collection(COLLECTION_NAME).getIndexes() - .whenComplete((indexes, ex) -> { - assertThat(indexes).isNotNull(); - assertThat(indexes.size()).isEqualTo(initialIndexCount + 1); - for (final IndexEntity i : indexes) { - if (i.getType() == IndexType.hash) { - assertThat(i.getFields().size()).isEqualTo(1); - assertThat(i.getFields()).contains("a"); - } - } - }) - .get(); - } - - @Test - void exists() throws InterruptedException, ExecutionException { - assertThat(db.collection(COLLECTION_NAME).exists().get()).isTrue(); - assertThat(db.collection(COLLECTION_NAME + "no").exists().get()).isFalse(); - } - - @Test - void truncate() throws InterruptedException, ExecutionException { - final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); - db.collection(COLLECTION_NAME).insertDocument(doc, null).get(); - final BaseDocument readResult = db.collection(COLLECTION_NAME) - .getDocument(doc.getKey(), BaseDocument.class, null).get(); - assertThat(readResult.getKey()).isEqualTo(doc.getKey()); - db.collection(COLLECTION_NAME).truncate() - .whenComplete((truncateResult, ex) -> { - assertThat(truncateResult).isNotNull(); - assertThat(truncateResult.getId()).isNotNull(); - }) - .get(); - final BaseDocument document = db.collection(COLLECTION_NAME).getDocument(doc.getKey(), BaseDocument.class, null) - .get(); - assertThat(document).isNull(); - } - - @Test - void getCount() throws InterruptedException, ExecutionException { - db.collection(COLLECTION_NAME).count() - .whenComplete((countEmpty, ex) -> { - assertThat(countEmpty).isNotNull(); - assertThat(countEmpty.getCount()).isEqualTo(0L); - }) - .get(); - - db.collection(COLLECTION_NAME).insertDocument(RawJson.of("{}"), null).get(); - - db.collection(COLLECTION_NAME).count() - .whenComplete((count, ex) -> assertThat(count.getCount()).isEqualTo(1L)) - .get(); - } - - @Test - void documentExists() throws InterruptedException, ExecutionException { - db.collection(COLLECTION_NAME).documentExists("no", null) - .whenComplete((existsNot, ex) -> assertThat(existsNot).isEqualTo(false)) - .get(); - - db.collection(COLLECTION_NAME).insertDocument(RawJson.of("{\"_key\":\"abc\"}")).get(); - - db.collection(COLLECTION_NAME).documentExists("abc", null) - .whenComplete((exists, ex) -> assertThat(exists).isEqualTo(true)) - .get(); - } - - @Test - void documentExistsIfMatch() throws InterruptedException, ExecutionException { - final DocumentCreateEntity createResult = db.collection(COLLECTION_NAME) - .insertDocument(RawJson.of("{\"_key\":\"abc\"}")).get(); - final DocumentExistsOptions options = new DocumentExistsOptions().ifMatch(createResult.getRev()); - db.collection(COLLECTION_NAME).documentExists("abc", options) - .whenComplete((exists, ex) -> assertThat(exists).isEqualTo(true)) - .get(); - } - - @Test - void documentExistsIfMatchFail() throws InterruptedException, ExecutionException { - db.collection(COLLECTION_NAME).insertDocument(RawJson.of("{\"_key\":\"abc\"}")).get(); - final DocumentExistsOptions options = new DocumentExistsOptions().ifMatch("no"); - db.collection(COLLECTION_NAME).documentExists("abc", options) - .whenComplete((exists, ex) -> assertThat(exists).isEqualTo(false)) - .get(); - } - - @Test - void documentExistsIfNoneMatch() throws InterruptedException, ExecutionException { - db.collection(COLLECTION_NAME).insertDocument(RawJson.of("{\"_key\":\"abc\"}")).get(); - final DocumentExistsOptions options = new DocumentExistsOptions().ifNoneMatch("no"); - db.collection(COLLECTION_NAME).documentExists("abc", options) - .whenComplete((exists, ex) -> assertThat(exists).isEqualTo(true)) - .get(); - } - - @Test - void documentExistsIfNoneMatchFail() throws InterruptedException, ExecutionException { - final DocumentCreateEntity createResult = db.collection(COLLECTION_NAME) - .insertDocument(RawJson.of("{\"_key\":\"abc\"}")).get(); - final DocumentExistsOptions options = new DocumentExistsOptions().ifNoneMatch(createResult.getRev()); - db.collection(COLLECTION_NAME).documentExists("abc", options) - .whenComplete((exists, ex) -> assertThat(exists).isEqualTo(false)) - .get(); - } - - @Test - void insertDocuments() throws InterruptedException, ExecutionException { - final Collection values = new ArrayList<>(); - values.add(new BaseDocument()); - values.add(new BaseDocument()); - values.add(new BaseDocument()); - db.collection(COLLECTION_NAME).insertDocuments(values) - .whenComplete((docs, ex) -> { - assertThat(docs).isNotNull(); - assertThat(docs.getDocuments()).isNotNull(); - assertThat(docs.getDocuments().size()).isEqualTo(3); - assertThat(docs.getErrors()).isNotNull(); - assertThat(docs.getErrors().size()).isEqualTo(0); - }) - .get(); - } - - @Test - void insertDocumentsOne() throws InterruptedException, ExecutionException { - final Collection values = new ArrayList<>(); - values.add(new BaseDocument()); - db.collection(COLLECTION_NAME).insertDocuments(values) - .whenComplete((docs, ex) -> { - assertThat(docs).isNotNull(); - assertThat(docs.getDocuments()).isNotNull(); - assertThat(docs.getDocuments().size()).isEqualTo(1); - assertThat(docs.getErrors()).isNotNull(); - assertThat(docs.getErrors().size()).isEqualTo(0); - }) - .get(); - } - - @Test - void insertDocumentsEmpty() throws InterruptedException, ExecutionException { - final Collection values = new ArrayList<>(); - db.collection(COLLECTION_NAME).insertDocuments(values) - .whenComplete((docs, ex) -> { - assertThat(docs).isNotNull(); - assertThat(docs.getDocuments()).isNotNull(); - assertThat(docs.getDocuments().size()).isEqualTo(0); - assertThat(docs.getErrors()).isNotNull(); - assertThat(docs.getErrors().size()).isEqualTo(0); - }) - .get(); - } - - @Test - void insertDocumentsReturnNew() throws InterruptedException, ExecutionException { - final Collection values = new ArrayList<>(); - values.add(new BaseDocument()); - values.add(new BaseDocument()); - values.add(new BaseDocument()); - final DocumentCreateOptions options = new DocumentCreateOptions().returnNew(true); - db.collection(COLLECTION_NAME).insertDocuments(values, options) - .whenComplete((docs, ex) -> { - assertThat(docs).isNotNull(); - assertThat(docs.getDocuments()).isNotNull(); - assertThat(docs.getDocuments().size()).isEqualTo(3); - assertThat(docs.getErrors()).isNotNull(); - assertThat(docs.getErrors().size()).isEqualTo(0); - for (final DocumentCreateEntity doc : docs.getDocuments()) { - assertThat(doc.getNew()).isNotNull(); - final BaseDocument baseDocument = doc.getNew(); - assertThat(baseDocument.getKey()).isNotNull(); - } - }) - .get(); - } - - @Test - void insertDocumentsFail() throws InterruptedException, ExecutionException { - final Collection values = new ArrayList<>(); - values.add(new BaseDocument("1")); - values.add(new BaseDocument("2")); - values.add(new BaseDocument("2")); - db.collection(COLLECTION_NAME).insertDocuments(values) - .whenComplete((docs, ex) -> { - assertThat(docs).isNotNull(); - assertThat(docs.getDocuments()).isNotNull(); - assertThat(docs.getDocuments().size()).isEqualTo(2); - assertThat(docs.getErrors()).isNotNull(); - assertThat(docs.getErrors().size()).isEqualTo(1); - assertThat(docs.getErrors().iterator().next().getErrorNum()).isEqualTo(1210); - }) - .get(); - } - - @Test - void insertDocumentsRawData() throws ExecutionException, InterruptedException { - final RawData values = RawData.of("[{},{},{}]"); - final MultiDocumentEntity docs = db.collection(COLLECTION_NAME).insertDocuments(values).get(); - assertThat(docs).isNotNull(); - assertThat(docs.getDocuments()).isNotNull(); - assertThat(docs.getDocuments()).hasSize(3); - assertThat(docs.getErrors()).isNotNull(); - assertThat(docs.getErrors()).isEmpty(); - } - - @Test - void insertDocumentsRawDataReturnNew() throws ExecutionException, InterruptedException { - final RawData values = RawData.of("[{\"aaa\":33},{\"aaa\":33},{\"aaa\":33}]"); - final MultiDocumentEntity> docs = - db.collection(COLLECTION_NAME).insertDocuments(values, new DocumentCreateOptions().returnNew(true)).get(); - assertThat(docs).isNotNull(); - assertThat(docs.getDocuments()).isNotNull(); - assertThat(docs.getDocuments()).hasSize(3); - assertThat(docs.getErrors()).isNotNull(); - assertThat(docs.getErrors()).isEmpty(); - - for (final DocumentCreateEntity doc : docs.getDocuments()) { - RawData d = doc.getNew(); - assertThat(d) - .isNotNull() - .isInstanceOf(RawJson.class); - - JsonNode jn = SerdeUtils.INSTANCE.parseJson(((RawJson) d).getValue()); - assertThat(jn.has("aaa")).isTrue(); - assertThat(jn.get("aaa").intValue()).isEqualTo(33); - } - } - - @Test - void importDocuments() throws InterruptedException, ExecutionException { - final Collection values = new ArrayList<>(); - values.add(new BaseDocument()); - values.add(new BaseDocument()); - values.add(new BaseDocument()); - db.collection(COLLECTION_NAME).importDocuments(values) - .whenComplete((docs, ex) -> { - assertThat(docs).isNotNull(); - assertThat(docs.getCreated()).isEqualTo(values.size()); - assertThat(docs.getEmpty()).isEqualTo(0); - assertThat(docs.getErrors()).isEqualTo(0); - assertThat(docs.getIgnored()).isEqualTo(0); - assertThat(docs.getUpdated()).isEqualTo(0); - assertThat(docs.getDetails()).isEmpty(); - }) - .get(); - } - - @Test - void importDocumentsDuplicateDefaultError() throws InterruptedException, ExecutionException { - final Collection values = new ArrayList<>(); - values.add(new BaseDocument("1")); - values.add(new BaseDocument("2")); - values.add(new BaseDocument("2")); - db.collection(COLLECTION_NAME).importDocuments(values) - .whenComplete((docs, ex) -> { - assertThat(docs).isNotNull(); - assertThat(docs.getCreated()).isEqualTo(2); - assertThat(docs.getEmpty()).isEqualTo(0); - assertThat(docs.getErrors()).isEqualTo(1); - assertThat(docs.getIgnored()).isEqualTo(0); - assertThat(docs.getUpdated()).isEqualTo(0); - assertThat(docs.getDetails()).isEmpty(); - }) - .get(); - } - - @Test - void importDocumentsDuplicateError() throws InterruptedException, ExecutionException { - final Collection values = new ArrayList<>(); - values.add(new BaseDocument("1")); - values.add(new BaseDocument("2")); - values.add(new BaseDocument("2")); - db.collection(COLLECTION_NAME).importDocuments(values, -new DocumentImportOptions().onDuplicate(OnDuplicate.error)) - .whenComplete((docs, ex) -> { - assertThat(docs).isNotNull(); - assertThat(docs.getCreated()).isEqualTo(2); - assertThat(docs.getEmpty()).isEqualTo(0); - assertThat(docs.getErrors()).isEqualTo(1); - assertThat(docs.getIgnored()).isEqualTo(0); - assertThat(docs.getUpdated()).isEqualTo(0); - assertThat(docs.getDetails()).isEmpty(); - }) - .get(); - } - - @Test - void importDocumentsDuplicateIgnore() throws InterruptedException, ExecutionException { - final Collection values = new ArrayList<>(); - values.add(new BaseDocument("1")); - values.add(new BaseDocument("2")); - values.add(new BaseDocument("2")); - db.collection(COLLECTION_NAME).importDocuments(values, - new DocumentImportOptions().onDuplicate(OnDuplicate.ignore)) - .whenComplete((docs, ex) -> { - assertThat(docs).isNotNull(); - assertThat(docs.getCreated()).isEqualTo(2); - assertThat(docs.getEmpty()).isEqualTo(0); - assertThat(docs.getErrors()).isEqualTo(0); - assertThat(docs.getIgnored()).isEqualTo(1); - assertThat(docs.getUpdated()).isEqualTo(0); - assertThat(docs.getDetails()).isEmpty(); - }) - .get(); - } - - @Test - void importDocumentsDuplicateReplace() throws InterruptedException, ExecutionException { - final Collection values = new ArrayList<>(); - values.add(new BaseDocument("1")); - values.add(new BaseDocument("2")); - values.add(new BaseDocument("2")); - db.collection(COLLECTION_NAME).importDocuments(values, -new DocumentImportOptions().onDuplicate(OnDuplicate.replace)) - .whenComplete((docs, ex) -> { - assertThat(docs).isNotNull(); - assertThat(docs.getCreated()).isEqualTo(2); - assertThat(docs.getEmpty()).isEqualTo(0); - assertThat(docs.getErrors()).isEqualTo(0); - assertThat(docs.getIgnored()).isEqualTo(0); - assertThat(docs.getUpdated()).isEqualTo(1); - assertThat(docs.getDetails()).isEmpty(); - }) - .get(); - } - - @Test - void importDocumentsDuplicateUpdate() throws InterruptedException, ExecutionException { - final Collection values = new ArrayList<>(); - values.add(new BaseDocument("1")); - values.add(new BaseDocument("2")); - values.add(new BaseDocument("2")); - db.collection(COLLECTION_NAME).importDocuments(values, - new DocumentImportOptions().onDuplicate(OnDuplicate.update)) - .whenComplete((docs, ex) -> { - assertThat(docs).isNotNull(); - assertThat(docs.getCreated()).isEqualTo(2); - assertThat(docs.getEmpty()).isEqualTo(0); - assertThat(docs.getErrors()).isEqualTo(0); - assertThat(docs.getIgnored()).isEqualTo(0); - assertThat(docs.getUpdated()).isEqualTo(1); - assertThat(docs.getDetails()).isEmpty(); - }) - .get(); - } - - @Test - void importDocumentsCompleteFail() throws InterruptedException { - final Collection values = new ArrayList<>(); - values.add(new BaseDocument("1")); - values.add(new BaseDocument("2")); - values.add(new BaseDocument("2")); - try { - db.collection(COLLECTION_NAME).importDocuments(values, new DocumentImportOptions().complete(true)).get(); - fail(); - } catch (ExecutionException e) { - assertThat(e.getCause()).isInstanceOf(ArangoDBException.class); - assertThat(((ArangoDBException) e.getCause()).getErrorNum()).isEqualTo(1210); - } - } - - @Test - void importDocumentsDetails() throws InterruptedException, ExecutionException { - final Collection values = new ArrayList<>(); - values.add(new BaseDocument("1")); - values.add(new BaseDocument("2")); - values.add(new BaseDocument("2")); - db.collection(COLLECTION_NAME).importDocuments(values, new DocumentImportOptions().details(true)) - .whenComplete((docs, ex) -> { - assertThat(docs).isNotNull(); - assertThat(docs.getCreated()).isEqualTo(2); - assertThat(docs.getEmpty()).isEqualTo(0); - assertThat(docs.getErrors()).isEqualTo(1); - assertThat(docs.getIgnored()).isEqualTo(0); - assertThat(docs.getUpdated()).isEqualTo(0); - assertThat(docs.getDetails().size()).isEqualTo(1); - assertThat(docs.getDetails().iterator().next()).contains("unique constraint violated"); - }) - .get(); - } - - @Test - void importDocumentsOverwriteFalse() throws InterruptedException, ExecutionException { - final ArangoCollectionAsync collection = db.collection(COLLECTION_NAME); - collection.insertDocument(new BaseDocument()).get(); - assertThat(collection.count().get().getCount()).isEqualTo(1L); - - final Collection values = new ArrayList<>(); - values.add(new BaseDocument()); - values.add(new BaseDocument()); - collection.importDocuments(values, new DocumentImportOptions().overwrite(false)).get(); - assertThat(collection.count().get().getCount()).isEqualTo(3L); - } - - @Test - void importDocumentsOverwriteTrue() throws InterruptedException, ExecutionException { - final ArangoCollectionAsync collection = db.collection(COLLECTION_NAME); - collection.insertDocument(new BaseDocument()).get(); - assertThat(collection.count().get().getCount()).isEqualTo(1L); - - final Collection values = new ArrayList<>(); - values.add(new BaseDocument()); - values.add(new BaseDocument()); - collection.importDocuments(values, new DocumentImportOptions().overwrite(true)).get(); - assertThat(collection.count().get().getCount()).isEqualTo(2L); - } - - @Test - void importDocumentsFromToPrefix() throws InterruptedException, ExecutionException { - db.createCollection(COLLECTION_NAME + "_edge", new CollectionCreateOptions().type(CollectionType.EDGES)).get(); - final ArangoCollectionAsync collection = db.collection(COLLECTION_NAME + "_edge"); - try { - final Collection values = new ArrayList<>(); - final String[] keys = {"1", "2"}; - for (String s : keys) { - values.add(new BaseEdgeDocument(s, "from", "to")); - } - assertThat(values).hasSize(keys.length); - - final DocumentImportEntity importResult = collection - .importDocuments(values, new DocumentImportOptions().fromPrefix("foo").toPrefix("bar")).get(); - assertThat(importResult).isNotNull(); - assertThat(importResult.getCreated()).isEqualTo(values.size()); - for (String key : keys) { - BaseEdgeDocument doc; - doc = collection.getDocument(key, BaseEdgeDocument.class).get(); - assertThat(doc).isNotNull(); - assertThat(doc.getFrom()).isEqualTo("foo/from"); - assertThat(doc.getTo()).isEqualTo("bar/to"); - } - } finally { - collection.drop().get(); - } - } - - @Test - void importDocumentsJson() throws InterruptedException, ExecutionException { - final String values = "[{\"_key\":\"1\"},{\"_key\":\"2\"}]"; - db.collection(COLLECTION_NAME).importDocuments(RawData.of(values)) - .whenComplete((docs, ex) -> { - assertThat(docs).isNotNull(); - assertThat(docs.getCreated()).isEqualTo(2); - assertThat(docs.getEmpty()).isEqualTo(0); - assertThat(docs.getErrors()).isEqualTo(0); - assertThat(docs.getIgnored()).isEqualTo(0); - assertThat(docs.getUpdated()).isEqualTo(0); - assertThat(docs.getDetails()).isEmpty(); - }) - .get(); - } - - @Test - void importDocumentsJsonDuplicateDefaultError() throws InterruptedException, ExecutionException { - final String values = "[{\"_key\":\"1\"},{\"_key\":\"2\"},{\"_key\":\"2\"}]"; - db.collection(COLLECTION_NAME).importDocuments(RawData.of(values)) - .whenComplete((docs, ex) -> { - assertThat(docs).isNotNull(); - assertThat(docs.getCreated()).isEqualTo(2); - assertThat(docs.getEmpty()).isEqualTo(0); - assertThat(docs.getErrors()).isEqualTo(1); - assertThat(docs.getIgnored()).isEqualTo(0); - assertThat(docs.getUpdated()).isEqualTo(0); - assertThat(docs.getDetails()).isEmpty(); - }) - .get(); - } - - @Test - void importDocumentsJsonDuplicateError() throws InterruptedException, ExecutionException { - final String values = "[{\"_key\":\"1\"},{\"_key\":\"2\"},{\"_key\":\"2\"}]"; - db.collection(COLLECTION_NAME).importDocuments(RawData.of(values), - new DocumentImportOptions().onDuplicate(OnDuplicate.error)) - .whenComplete((docs, ex) -> { - assertThat(docs).isNotNull(); - assertThat(docs.getCreated()).isEqualTo(2); - assertThat(docs.getEmpty()).isEqualTo(0); - assertThat(docs.getErrors()).isEqualTo(1); - assertThat(docs.getIgnored()).isEqualTo(0); - assertThat(docs.getUpdated()).isEqualTo(0); - assertThat(docs.getDetails()).isEmpty(); - }) - .get(); - } - - @Test - void importDocumentsJsonDuplicateIgnore() throws InterruptedException, ExecutionException { - final String values = "[{\"_key\":\"1\"},{\"_key\":\"2\"},{\"_key\":\"2\"}]"; - db.collection(COLLECTION_NAME).importDocuments(RawData.of(values), - new DocumentImportOptions().onDuplicate(OnDuplicate.ignore)) - .whenComplete((docs, ex) -> { - assertThat(docs).isNotNull(); - assertThat(docs.getCreated()).isEqualTo(2); - assertThat(docs.getEmpty()).isEqualTo(0); - assertThat(docs.getErrors()).isEqualTo(0); - assertThat(docs.getIgnored()).isEqualTo(1); - assertThat(docs.getUpdated()).isEqualTo(0); - assertThat(docs.getDetails()).isEmpty(); - }) - .get(); - } - - @Test - void importDocumentsJsonDuplicateReplace() throws InterruptedException, ExecutionException { - final String values = "[{\"_key\":\"1\"},{\"_key\":\"2\"},{\"_key\":\"2\"}]"; - db.collection(COLLECTION_NAME).importDocuments(RawData.of(values), - new DocumentImportOptions().onDuplicate(OnDuplicate.replace)) - .whenComplete((docs, ex) -> { - assertThat(docs).isNotNull(); - assertThat(docs.getCreated()).isEqualTo(2); - assertThat(docs.getEmpty()).isEqualTo(0); - assertThat(docs.getErrors()).isEqualTo(0); - assertThat(docs.getIgnored()).isEqualTo(0); - assertThat(docs.getUpdated()).isEqualTo(1); - assertThat(docs.getDetails()).isEmpty(); - }) - .get(); - } - - @Test - void importDocumentsJsonDuplicateUpdate() throws InterruptedException, ExecutionException { - final String values = "[{\"_key\":\"1\"},{\"_key\":\"2\"},{\"_key\":\"2\"}]"; - db.collection(COLLECTION_NAME).importDocuments(RawData.of(values), - new DocumentImportOptions().onDuplicate(OnDuplicate.update)) - .whenComplete((docs, ex) -> { - assertThat(docs).isNotNull(); - assertThat(docs.getCreated()).isEqualTo(2); - assertThat(docs.getEmpty()).isEqualTo(0); - assertThat(docs.getErrors()).isEqualTo(0); - assertThat(docs.getIgnored()).isEqualTo(0); - assertThat(docs.getUpdated()).isEqualTo(1); - assertThat(docs.getDetails()).isEmpty(); - }) - .get(); - } - - @Test - void importDocumentsJsonCompleteFail() throws InterruptedException { - final String values = "[{\"_key\":\"1\"},{\"_key\":\"2\"},{\"_key\":\"2\"}]"; - try { - db.collection(COLLECTION_NAME).importDocuments(RawData.of(values), - new DocumentImportOptions().complete(true)).get(); - fail(); - } catch (ExecutionException e) { - assertThat(e.getCause()).isInstanceOf(ArangoDBException.class); - assertThat(((ArangoDBException) e.getCause()).getErrorNum()).isEqualTo(1210); - } - } - - @Test - void importDocumentsJsonDetails() throws InterruptedException, ExecutionException { - final String values = "[{\"_key\":\"1\"},{\"_key\":\"2\"},{\"_key\":\"2\"}]"; - db.collection(COLLECTION_NAME).importDocuments(RawData.of(values), new DocumentImportOptions().details(true)) - .whenComplete((docs, ex) -> { - assertThat(docs).isNotNull(); - assertThat(docs.getCreated()).isEqualTo(2); - assertThat(docs.getEmpty()).isEqualTo(0); - assertThat(docs.getErrors()).isEqualTo(1); - assertThat(docs.getIgnored()).isEqualTo(0); - assertThat(docs.getUpdated()).isEqualTo(0); - assertThat(docs.getDetails().size()).isEqualTo(1); - assertThat(docs.getDetails().iterator().next()).contains("unique constraint violated"); - }) - .get(); - } - - @Test - void importDocumentsJsonOverwriteFalse() throws InterruptedException, ExecutionException { - final ArangoCollectionAsync collection = db.collection(COLLECTION_NAME); - collection.insertDocument(new BaseDocument()).get(); - assertThat(collection.count().get().getCount()).isEqualTo(1L); - - final String values = "[{\"_key\":\"1\"},{\"_key\":\"2\"}]"; - collection.importDocuments(RawData.of(values), new DocumentImportOptions().overwrite(false)).get(); - assertThat(collection.count().get().getCount()).isEqualTo(3L); - } - - @Test - void importDocumentsJsonOverwriteTrue() throws InterruptedException, ExecutionException { - final ArangoCollectionAsync collection = db.collection(COLLECTION_NAME); - collection.insertDocument(new BaseDocument()).get(); - assertThat(collection.count().get().getCount()).isEqualTo(1L); - - final String values = "[{\"_key\":\"1\"},{\"_key\":\"2\"}]"; - collection.importDocuments(RawData.of(values), new DocumentImportOptions().overwrite(true)).get(); - assertThat(collection.count().get().getCount()).isEqualTo(2L); - } - - @Test - void importDocumentsJsonFromToPrefix() throws InterruptedException, ExecutionException { - db.createCollection(COLLECTION_NAME + "_edge", new CollectionCreateOptions().type(CollectionType.EDGES)).get(); - final ArangoCollectionAsync collection = db.collection(COLLECTION_NAME + "_edge"); - try { - final String[] keys = {"1", "2"}; - final String values = "[{\"_key\":\"1\",\"_from\":\"from\",\"_to\":\"to\"},{\"_key\":\"2\"," + - "\"_from\":\"from\",\"_to\":\"to\"}]"; - - final DocumentImportEntity importResult = collection - .importDocuments(RawData.of(values), - new DocumentImportOptions().fromPrefix("foo").toPrefix("bar")).get(); - assertThat(importResult).isNotNull(); - assertThat(importResult.getCreated()).isEqualTo(2); - for (String key : keys) { - BaseEdgeDocument doc; - doc = collection.getDocument(key, BaseEdgeDocument.class).get(); - assertThat(doc).isNotNull(); - assertThat(doc.getFrom()).isEqualTo("foo/from"); - assertThat(doc.getTo()).isEqualTo("bar/to"); - } - } finally { - collection.drop().get(); - } - } - - @Test - void deleteDocumentsByKey() throws InterruptedException, ExecutionException { - final Collection values = new ArrayList<>(); - { - final BaseDocument e = new BaseDocument(UUID.randomUUID().toString()); - e.setKey("1"); - values.add(e); - } - { - final BaseDocument e = new BaseDocument(UUID.randomUUID().toString()); - e.setKey("2"); - values.add(e); - } - db.collection(COLLECTION_NAME).insertDocuments(values).get(); - final Collection keys = new ArrayList<>(); - keys.add("1"); - keys.add("2"); - db.collection(COLLECTION_NAME).deleteDocuments(keys) - .whenComplete((deleteResult, ex) -> { - assertThat(deleteResult).isNotNull(); - assertThat(deleteResult.getDocuments().size()).isEqualTo(2); - for (final DocumentDeleteEntity i : deleteResult.getDocuments()) { - assertThat(i.getKey()).isIn("1", "2"); - } - assertThat(deleteResult.getErrors().size()).isEqualTo(0); - }) - .get(); - } - - @Test - void deleteDocumentsByDocuments() throws InterruptedException, ExecutionException { - final Collection values = new ArrayList<>(); - { - final BaseDocument e = new BaseDocument(UUID.randomUUID().toString()); - e.setKey("1"); - values.add(e); - } - { - final BaseDocument e = new BaseDocument(UUID.randomUUID().toString()); - e.setKey("2"); - values.add(e); - } - db.collection(COLLECTION_NAME).insertDocuments(values).get(); - db.collection(COLLECTION_NAME).deleteDocuments(values) - .whenComplete((deleteResult, ex) -> { - assertThat(deleteResult).isNotNull(); - assertThat(deleteResult.getDocuments().size()).isEqualTo(2); - for (final DocumentDeleteEntity i : deleteResult.getDocuments()) { - assertThat(i.getKey()).isIn("1", "2"); - } - assertThat(deleteResult.getErrors().size()).isEqualTo(0); - }) - .get(); - } - - @Test - void deleteDocumentsByKeyOne() throws InterruptedException, ExecutionException { - final Collection values = new ArrayList<>(); - { - final BaseDocument e = new BaseDocument(UUID.randomUUID().toString()); - e.setKey("1"); - values.add(e); - } - db.collection(COLLECTION_NAME).insertDocuments(values).get(); - final Collection keys = new ArrayList<>(); - keys.add("1"); - db.collection(COLLECTION_NAME).deleteDocuments(keys) - .whenComplete((deleteResult, ex) -> { - assertThat(deleteResult).isNotNull(); - assertThat(deleteResult.getDocuments().size()).isEqualTo(1); - for (final DocumentDeleteEntity i : deleteResult.getDocuments()) { - assertThat(i.getKey()).isEqualTo("1"); - } - assertThat(deleteResult.getErrors().size()).isEqualTo(0); - }) - .get(); - } - - @Test - void deleteDocumentsByDocumentOne() throws InterruptedException, ExecutionException { - final Collection values = new ArrayList<>(); - { - final BaseDocument e = new BaseDocument(UUID.randomUUID().toString()); - e.setKey("1"); - values.add(e); - } - db.collection(COLLECTION_NAME).insertDocuments(values).get(); - db.collection(COLLECTION_NAME).deleteDocuments(values) - .whenComplete((deleteResult, ex) -> { - assertThat(deleteResult).isNotNull(); - assertThat(deleteResult.getDocuments().size()).isEqualTo(1); - for (final DocumentDeleteEntity i : deleteResult.getDocuments()) { - assertThat(i.getKey()).isEqualTo("1"); - } - assertThat(deleteResult.getErrors().size()).isEqualTo(0); - }) - .get(); - } - - @Test - void deleteDocumentsEmpty() throws InterruptedException, ExecutionException { - final Collection values = new ArrayList<>(); - db.collection(COLLECTION_NAME).insertDocuments(values).get(); - final Collection keys = new ArrayList<>(); - db.collection(COLLECTION_NAME).deleteDocuments(keys) - .whenComplete((deleteResult, ex) -> { - assertThat(deleteResult).isNotNull(); - assertThat(deleteResult.getDocuments().size()).isEqualTo(0); - assertThat(deleteResult.getErrors().size()).isEqualTo(0); - }) - .get(); - } - - @Test - void deleteDocumentsByKeyNotExisting() throws InterruptedException, ExecutionException { - final Collection values = new ArrayList<>(); - db.collection(COLLECTION_NAME).insertDocuments(values).get(); - final Collection keys = new ArrayList<>(); - keys.add("1"); - keys.add("2"); - db.collection(COLLECTION_NAME).deleteDocuments(keys) - .whenComplete((deleteResult, ex) -> { - assertThat(deleteResult).isNotNull(); - assertThat(deleteResult.getDocuments().size()).isEqualTo(0); - assertThat(deleteResult.getErrors().size()).isEqualTo(2); - }) - .get(); - } - - @Test - void deleteDocumentsByDocumentsNotExisting() throws InterruptedException, ExecutionException { - final Collection values = new ArrayList<>(); - { - final BaseDocument e = new BaseDocument(UUID.randomUUID().toString()); - e.setKey("1"); - values.add(e); - } - { - final BaseDocument e = new BaseDocument(UUID.randomUUID().toString()); - e.setKey("2"); - values.add(e); - } - db.collection(COLLECTION_NAME).deleteDocuments(values) - .whenComplete((deleteResult, ex) -> { - assertThat(deleteResult).isNotNull(); - assertThat(deleteResult.getDocuments().size()).isEqualTo(0); - assertThat(deleteResult.getErrors().size()).isEqualTo(2); - }) - .get(); - } - - @Test - void deleteDocumentsRawDataByKeyReturnOld() throws ExecutionException, InterruptedException { - ArangoCollectionAsync collection = db.collection(COLLECTION_NAME); - final RawData values = RawData.of("[{\"_key\":\"1\"},{\"_key\":\"2\"}]"); - collection.insertDocuments(values).get(); - final RawData keys = RawData.of("[\"1\",\"2\"]"); - MultiDocumentEntity> deleteResult = collection.deleteDocuments(keys, - new DocumentDeleteOptions().returnOld(true)).get(); - assertThat(deleteResult).isNotNull(); - assertThat(deleteResult.getDocuments()).hasSize(2); - for (final DocumentDeleteEntity i : deleteResult.getDocuments()) { - assertThat(i.getKey()).isIn("1", "2"); - assertThat(i.getOld()).isNotNull().isInstanceOf(RawJson.class); - JsonNode jn = SerdeUtils.INSTANCE.parseJson(((RawJson) i.getOld()).getValue()); - assertThat(jn.get("_key").asText()).isEqualTo(i.getKey()); - } - assertThat(deleteResult.getErrors()).isEmpty(); - } - - @Test - void updateDocuments() throws InterruptedException, ExecutionException { - final Collection values = new ArrayList<>(); - { - final BaseDocument e = new BaseDocument(UUID.randomUUID().toString()); - e.setKey("1"); - values.add(e); - } - { - final BaseDocument e = new BaseDocument(UUID.randomUUID().toString()); - e.setKey("2"); - values.add(e); - } - db.collection(COLLECTION_NAME).insertDocuments(values).get(); - final Collection updatedValues = new ArrayList<>(); - for (final BaseDocument i : values) { - i.addAttribute("a", "test"); - updatedValues.add(i); - } - db.collection(COLLECTION_NAME).updateDocuments(updatedValues) - .whenComplete((updateResult, ex) -> { - assertThat(updateResult.getDocuments().size()).isEqualTo(2); - assertThat(updateResult.getErrors().size()).isEqualTo(0); - }) - .get(); - } - - @Test - void updateDocumentsWithDifferentReturnType() throws ExecutionException, InterruptedException { - ArangoCollectionAsync collection = db.collection(COLLECTION_NAME); - List keys = - IntStream.range(0, 3).mapToObj(it -> "key-" + UUID.randomUUID()).collect(Collectors.toList()); - List docs = keys.stream() - .map(BaseDocument::new) - .peek(it -> it.addAttribute("a", "test")) - .collect(Collectors.toList()); - - collection.insertDocuments(docs).get(); - - List> modifiedDocs = docs.stream() - .peek(it -> it.addAttribute("b", "test")) - .map(it -> { - Map map = new HashMap<>(); - map.put("_key", it.getKey()); - map.put("a", it.getAttribute("a")); - map.put("b", it.getAttribute("b")); - return map; - }) - .collect(Collectors.toList()); - - final MultiDocumentEntity> updateResult = collection - .updateDocuments(modifiedDocs, new DocumentUpdateOptions().returnNew(true), BaseDocument.class).get(); - assertThat(updateResult.getDocuments()).hasSize(3); - assertThat(updateResult.getErrors()).isEmpty(); - assertThat(updateResult.getDocuments().stream().map(DocumentUpdateEntity::getNew) - .allMatch(it -> it.getAttribute("a").equals("test") && it.getAttribute("b").equals("test"))) - .isTrue(); - } - - @Test - void updateDocumentsOne() throws InterruptedException, ExecutionException { - final Collection values = new ArrayList<>(); - { - final BaseDocument e = new BaseDocument(UUID.randomUUID().toString()); - e.setKey("1"); - values.add(e); - } - db.collection(COLLECTION_NAME).insertDocuments(values).get(); - final Collection updatedValues = new ArrayList<>(); - final BaseDocument first = values.iterator().next(); - first.addAttribute("a", "test"); - updatedValues.add(first); - db.collection(COLLECTION_NAME).updateDocuments(updatedValues) - .whenComplete((updateResult, ex) -> { - assertThat(updateResult.getDocuments().size()).isEqualTo(1); - assertThat(updateResult.getErrors().size()).isEqualTo(0); - }) - .get(); - } - - @Test - void updateDocumentsEmpty() throws InterruptedException, ExecutionException { - final Collection values = new ArrayList<>(); - db.collection(COLLECTION_NAME).updateDocuments(values) - .whenComplete((updateResult, ex) -> { - assertThat(updateResult.getDocuments().size()).isEqualTo(0); - assertThat(updateResult.getErrors().size()).isEqualTo(0); - }) - .get(); - } - - @Test - void updateDocumentsWithoutKey() throws InterruptedException, ExecutionException { - final Collection values = new ArrayList<>(); - { - values.add(new BaseDocument("1")); - } - db.collection(COLLECTION_NAME).insertDocuments(values).get(); - final Collection updatedValues = new ArrayList<>(); - for (final BaseDocument i : values) { - i.addAttribute("a", "test"); - updatedValues.add(i); - } - updatedValues.add(new BaseDocument()); - db.collection(COLLECTION_NAME).updateDocuments(updatedValues) - .whenComplete((updateResult, ex) -> { - assertThat(updateResult.getDocuments().size()).isEqualTo(1); - assertThat(updateResult.getErrors().size()).isEqualTo(1); - }) - .get(); - } - - @Test - void updateDocumentsRawData() throws ExecutionException, InterruptedException { - ArangoCollectionAsync collection = db.collection(COLLECTION_NAME); - final RawData values = RawData.of("[{\"_key\":\"1\"}, {\"_key\":\"2\"}]"); - collection.insertDocuments(values).get(); - - final RawData updatedValues = RawData.of("[{\"_key\":\"1\", \"foo\":\"bar\"}, {\"_key\":\"2\", " + - "\"foo\":\"bar\"}]"); - final MultiDocumentEntity updateResult = collection.updateDocuments(updatedValues).get(); - assertThat(updateResult.getDocuments()).hasSize(2); - assertThat(updateResult.getErrors()).isEmpty(); - } - - @Test - void updateDocumentsRawDataReturnNew() throws ExecutionException, InterruptedException { - ArangoCollectionAsync collection = db.collection(COLLECTION_NAME); - final RawData values = RawData.of("[{\"_key\":\"1\"}, {\"_key\":\"2\"}]"); - collection.insertDocuments(values).get(); - - final RawData updatedValues = RawData.of("[{\"_key\":\"1\", \"foo\":\"bar\"}, {\"_key\":\"2\", " + -"\"foo\":\"bar\"}]"); - MultiDocumentEntity> updateResult = - collection.updateDocuments(updatedValues, new DocumentUpdateOptions().returnNew(true)).get(); - assertThat(updateResult.getDocuments()).hasSize(2); - assertThat(updateResult.getErrors()).isEmpty(); - for (DocumentUpdateEntity doc : updateResult.getDocuments()) { - RawData d = doc.getNew(); - assertThat(d) - .isNotNull() - .isInstanceOf(RawJson.class); - - JsonNode jn = SerdeUtils.INSTANCE.parseJson(((RawJson) d).getValue()); - assertThat(jn.has("foo")).isTrue(); - assertThat(jn.get("foo").textValue()).isEqualTo("bar"); - } - } - - @Test - void replaceDocuments() throws InterruptedException, ExecutionException { - final Collection values = new ArrayList<>(); - { - values.add(new BaseDocument("1")); - values.add(new BaseDocument("2")); - } - db.collection(COLLECTION_NAME).insertDocuments(values).get(); - final Collection updatedValues = new ArrayList<>(); - for (final BaseDocument i : values) { - i.addAttribute("a", "test"); - updatedValues.add(i); - } - db.collection(COLLECTION_NAME).replaceDocuments(updatedValues) - .whenComplete((updateResult, ex) -> { - assertThat(updateResult.getDocuments().size()).isEqualTo(2); - assertThat(updateResult.getErrors().size()).isEqualTo(0); - }) - .get(); - } - - @Test - void replaceDocumentsOne() throws InterruptedException, ExecutionException { - final Collection values = new ArrayList<>(); - { - final BaseDocument e = new BaseDocument(UUID.randomUUID().toString()); - e.setKey("1"); - values.add(e); - } - db.collection(COLLECTION_NAME).insertDocuments(values).get(); - final Collection updatedValues = new ArrayList<>(); - final BaseDocument first = values.iterator().next(); - first.addAttribute("a", "test"); - updatedValues.add(first); - db.collection(COLLECTION_NAME).updateDocuments(updatedValues) - .whenComplete((updateResult, ex) -> { - assertThat(updateResult.getDocuments().size()).isEqualTo(1); - assertThat(updateResult.getErrors().size()).isEqualTo(0); - }) - .get(); - } - - @Test - void replaceDocumentsEmpty() throws InterruptedException, ExecutionException { - final Collection values = new ArrayList<>(); - db.collection(COLLECTION_NAME).updateDocuments(values) - .whenComplete((updateResult, ex) -> { - assertThat(updateResult.getDocuments().size()).isEqualTo(0); - assertThat(updateResult.getErrors().size()).isEqualTo(0); - }) - .get(); - } - - @Test - void replaceDocumentsWithoutKey() throws InterruptedException, ExecutionException { - final Collection values = new ArrayList<>(); - { - values.add(new BaseDocument("1")); - } - db.collection(COLLECTION_NAME).insertDocuments(values).get(); - final Collection updatedValues = new ArrayList<>(); - for (final BaseDocument i : values) { - i.addAttribute("a", "test"); - updatedValues.add(i); - } - updatedValues.add(new BaseDocument()); - db.collection(COLLECTION_NAME).updateDocuments(updatedValues) - .whenComplete((updateResult, ex) -> { - assertThat(updateResult.getDocuments().size()).isEqualTo(1); - assertThat(updateResult.getErrors().size()).isEqualTo(1); - }) - .get(); - } - - @Test - void replaceDocumentsRawData() throws ExecutionException, InterruptedException { - ArangoCollectionAsync collection = db.collection(COLLECTION_NAME); - - final RawData values = RawData.of("[{\"_key\":\"1\"}, {\"_key\":\"2\"}]"); - collection.insertDocuments(values).get(); - - final RawData updatedValues = RawData.of("[{\"_key\":\"1\", \"foo\":\"bar\"}, {\"_key\":\"2\", " + -"\"foo\":\"bar\"}]"); - final MultiDocumentEntity updateResult = collection.replaceDocuments(updatedValues).get(); - assertThat(updateResult.getDocuments()).hasSize(2); - assertThat(updateResult.getErrors()).isEmpty(); - } - - @Test - void replaceDocumentsRawDataReturnNew() throws ExecutionException, InterruptedException { - ArangoCollectionAsync collection = db.collection(COLLECTION_NAME); - - final RawData values = RawData.of("[{\"_key\":\"1\"}, {\"_key\":\"2\"}]"); - collection.insertDocuments(values).get(); - - final RawData updatedValues = RawData.of("[{\"_key\":\"1\", \"foo\":\"bar\"}, {\"_key\":\"2\", " + - "\"foo\":\"bar\"}]"); - MultiDocumentEntity> updateResult = - collection.replaceDocuments(updatedValues, new DocumentReplaceOptions().returnNew(true)).get(); - assertThat(updateResult.getDocuments()).hasSize(2); - assertThat(updateResult.getErrors()).isEmpty(); - for (DocumentUpdateEntity doc : updateResult.getDocuments()) { - RawData d = doc.getNew(); - assertThat(d) - .isNotNull() - .isInstanceOf(RawJson.class); - - JsonNode jn = SerdeUtils.INSTANCE.parseJson(((RawJson) d).getValue()); - assertThat(jn.has("foo")).isTrue(); - assertThat(jn.get("foo").textValue()).isEqualTo("bar"); - } - } - - @Test - void getInfo() throws InterruptedException, ExecutionException { - db.collection(COLLECTION_NAME).getInfo() - .whenComplete((result, ex) -> assertThat(result.getName()).isEqualTo(COLLECTION_NAME)) - .get(); - } - - @Test - void getPropeties() throws InterruptedException, ExecutionException { - db.collection(COLLECTION_NAME).getProperties() - .whenComplete((result, ex) -> { - assertThat(result.getName()).isEqualTo(COLLECTION_NAME); - assertThat(result.getCount()).isNull(); - }) - .get(); - } - - @Test - void changeProperties() throws InterruptedException, ExecutionException { - final String collection = COLLECTION_NAME + "_prop"; - try { - db.createCollection(collection).get(); - final CollectionPropertiesEntity properties = db.collection(collection).getProperties().get(); - assertThat(properties.getWaitForSync()).isNotNull(); - final CollectionPropertiesOptions options = new CollectionPropertiesOptions(); - options.waitForSync(!properties.getWaitForSync()); - db.collection(collection).changeProperties(options) - .whenComplete((changedProperties, ex) -> { - assertThat(changedProperties.getWaitForSync()).isNotNull(); - assertThat(changedProperties.getWaitForSync()).isNotEqualTo(properties.getWaitForSync()); - }) - .get(); - } finally { - db.collection(collection).drop().get(); - } - } - - @Test - void rename() throws InterruptedException, ExecutionException { - assumeTrue(isSingleServer()); - db.collection(COLLECTION_NAME).rename(COLLECTION_NAME + "1") - .whenComplete((result, ex) -> { - assertThat(result).isNotNull(); - assertThat(result.getName()).isEqualTo(COLLECTION_NAME + "1"); - }) - .get(); - final CollectionEntity info = db.collection(COLLECTION_NAME + "1").getInfo().get(); - assertThat(info.getName()).isEqualTo(COLLECTION_NAME + "1"); - try { - db.collection(COLLECTION_NAME).getInfo().get(); - fail(); - } catch (final ExecutionException e) { - assertThat(e.getCause()).isInstanceOf(ArangoDBException.class); - } - db.collection(COLLECTION_NAME + "1").rename(COLLECTION_NAME).get(); - } - - @Test - void responsibleShard() throws ExecutionException, InterruptedException { - assumeTrue(isCluster()); - assumeTrue(isAtLeastVersion(3, 5)); - ShardEntity shard = db.collection(COLLECTION_NAME).getResponsibleShard(new BaseDocument("testKey")).get(); - assertThat(shard).isNotNull(); - assertThat(shard.getShardId()).isNotNull(); - } - - @Test - void getRevision() throws InterruptedException, ExecutionException { - db.collection(COLLECTION_NAME).getRevision() - .whenComplete((result, ex) -> { - assertThat(result).isNotNull(); - assertThat(result.getName()).isEqualTo(COLLECTION_NAME); - assertThat(result.getRevision()).isNotNull(); - }) - .get(); - } - - @Test - void grantAccessRW() throws InterruptedException, ExecutionException { - try { - arangoDB.createUser("user1", "1234", null).get(); - db.collection(COLLECTION_NAME).grantAccess("user1", Permissions.RW).get(); - } finally { - arangoDB.deleteUser("user1").get(); - } - } - - @Test - void grantAccessRO() throws InterruptedException, ExecutionException { - try { - arangoDB.createUser("user1", "1234", null).get(); - db.collection(COLLECTION_NAME).grantAccess("user1", Permissions.RO).get(); - } finally { - arangoDB.deleteUser("user1").get(); - } - } - - @Test - void grantAccessNONE() throws InterruptedException, ExecutionException { - try { - arangoDB.createUser("user1", "1234", null).get(); - db.collection(COLLECTION_NAME).grantAccess("user1", Permissions.NONE).get(); - } finally { - arangoDB.deleteUser("user1").get(); - } - } - - @Test - void grantAccessUserNotFound() { - Throwable thrown = - catchThrowable(() -> db.collection(COLLECTION_NAME).grantAccess("user1", Permissions.RW).get()); - assertThat(thrown).isInstanceOf(ExecutionException.class); - } - - @Test - void revokeAccess() throws InterruptedException, ExecutionException { - try { - arangoDB.createUser("user1", "1234", null).get(); - db.collection(COLLECTION_NAME).grantAccess("user1", Permissions.NONE).get(); - } finally { - arangoDB.deleteUser("user1").get(); - } - } - - @Test - void revokeAccessUserNotFound() { - Throwable thrown = - catchThrowable(() -> db.collection(COLLECTION_NAME).grantAccess("user1", Permissions.NONE).get()); - assertThat(thrown).isInstanceOf(ExecutionException.class); - } - - @Test - void resetAccess() throws InterruptedException, ExecutionException { - try { - arangoDB.createUser("user1", "1234", null).get(); - db.collection(COLLECTION_NAME).resetAccess("user1").get(); - } finally { - arangoDB.deleteUser("user1").get(); - } - } - - @Test - void resetAccessUserNotFound() { - Throwable thrown = catchThrowable(() -> db.collection(COLLECTION_NAME).resetAccess("user1").get()); - assertThat(thrown).isInstanceOf(ExecutionException.class); - } - - @Test - void getPermissions() throws InterruptedException, ExecutionException { - assertThat(db.collection(COLLECTION_NAME).getPermissions("root").get()).isEqualTo(Permissions.RW); - } - - @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, property = "type") - public interface Animal { - String getKey(); - - String getName(); - } - - public static class Dog implements Animal { - - @Key - private String key; - private String name; - - public Dog() { - } - - public Dog(String key, String name) { - this.key = key; - this.name = name; - } - - @Override - public String getKey() { - return key; - } - - public void setKey(String key) { - this.key = key; - } - - @Override - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - } - - public static class Cat implements Animal { - @Key - private String key; - private String name; - - public Cat() { - } - - public Cat(String key, String name) { - this.key = key; - this.name = name; - } - - @Override - public String getKey() { - return key; - } - - public void setKey(String key) { - this.key = key; - } - - @Override - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - } -} diff --git a/shaded-integration-tests/src/test/native/java/com/arangodb/async/ArangoDBTest.java b/shaded-integration-tests/src/test/native/java/com/arangodb/async/ArangoDBTest.java deleted file mode 100644 index 2a76db54c..000000000 --- a/shaded-integration-tests/src/test/native/java/com/arangodb/async/ArangoDBTest.java +++ /dev/null @@ -1,566 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.async; - -import com.arangodb.*; -import com.arangodb.config.ConfigUtils; -import com.arangodb.entity.*; -import com.arangodb.internal.serde.SerdeUtils; -import com.arangodb.model.*; -import com.arangodb.util.RawJson; -import com.arangodb.util.TestUtils; -import org.junit.jupiter.api.Disabled; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.Timeout; - -import java.util.Collection; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ExecutionException; -import java.util.stream.Collectors; -import java.util.stream.IntStream; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.fail; -import static org.junit.jupiter.api.Assumptions.assumeTrue; - -/** - * @author Mark Vollmary - * @author Michele Rastelli - */ -class ArangoDBTest { - - private static final String ROOT = "root"; - private static final String USER = "mit dem mund"; - private static final String PW = "machts der hund"; - private static Boolean extendedNames; - - private final ArangoDBAsync arangoDB = new ArangoDBAsync.Builder() - .loadProperties(ConfigUtils.loadConfig()) - .build(); - private final ArangoDB arangoDBSync = new ArangoDB.Builder() - .loadProperties(ConfigUtils.loadConfig()) - .build(); - - private boolean isEnterprise() { - return arangoDBSync.getVersion().getLicense() == License.ENTERPRISE; - } - - private boolean isCluster() { - return arangoDBSync.getRole() == ServerRole.COORDINATOR; - } - - private boolean isAtLeastVersion(final int major, final int minor) { - return com.arangodb.util.TestUtils.isAtLeastVersion(arangoDBSync.getVersion().getVersion(), major, minor, 0); - } - - private boolean isLessThanVersion(final int major, final int minor) { - return com.arangodb.util.TestUtils.isLessThanVersion(arangoDBSync.getVersion().getVersion(), major, minor, 0); - } - - private boolean supportsExtendedNames() { - if (extendedNames == null) { - try { - ArangoDatabase testDb = arangoDBSync.db(DbName.of("test-" + TestUtils.generateRandomDbName(20, true))); - testDb.create(); - extendedNames = true; - testDb.drop(); - } catch (ArangoDBException e) { - extendedNames = false; - } - } - return extendedNames; - } - - @Test - void getVersion() throws InterruptedException, ExecutionException { - arangoDB.getVersion() - .whenComplete((version, ex) -> { - assertThat(version).isNotNull(); - assertThat(version.getServer()).isNotNull(); - assertThat(version.getVersion()).isNotNull(); - }) - .get(); - } - - @Test - @Timeout(2) - void nestedGetVersion() { - for (int i = 0; i < 100; i++) { - try { - arangoDB.getVersion() - .whenComplete((v1, ex1) -> { - assertThat(v1).isNotNull(); - assertThat(v1.getServer()).isNotNull(); - assertThat(v1.getVersion()).isNotNull(); - try { - arangoDB.getVersion() - .whenComplete((v2, ex2) -> { - assertThat(v2).isNotNull(); - assertThat(v2.getServer()).isNotNull(); - assertThat(v2.getVersion()).isNotNull(); - try { - arangoDB.getVersion() - .whenComplete((v3, ex3) -> { - assertThat(v3).isNotNull(); - assertThat(v3.getServer()).isNotNull(); - assertThat(v3.getVersion()).isNotNull(); - }) - .get(); - } catch (InterruptedException | ExecutionException e) { - e.printStackTrace(); - fail(); - } - }) - .get(); - } catch (InterruptedException | ExecutionException e) { - e.printStackTrace(); - fail(); - } - }) - .get(); - } catch (InterruptedException | ExecutionException e) { - e.printStackTrace(); - fail(); - } - } - } - - @Test - void createDatabase() throws InterruptedException, ExecutionException { - arangoDB.createDatabase(BaseTest.TEST_DB) - .whenComplete((result, ex) -> assertThat(result).isEqualTo(true)) - .get(); - arangoDB.db(BaseTest.TEST_DB).drop().get(); - } - - @Test - void createDatabaseWithOptions() throws ExecutionException, InterruptedException { - assumeTrue(isCluster()); - assumeTrue(isAtLeastVersion(3, 6)); - - final DbName dbName = DbName.of("testDB-" + TestUtils.generateRandomDbName(20, supportsExtendedNames())); - final Boolean resultCreate = arangoDB.createDatabase(new DBCreateOptions() - .name(dbName) - .options(new DatabaseOptions() - .writeConcern(2) - .replicationFactor(2) - .sharding("") - ) - ).get(); - assertThat(resultCreate).isTrue(); - - DatabaseEntity info = arangoDB.db(dbName).getInfo().get(); - assertThat(info.getReplicationFactor().getValue()).isEqualTo(2); - assertThat(info.getWriteConcern()).isEqualTo(2); - assertThat(info.getSharding()).isEmpty(); - - final Boolean resultDelete = arangoDB.db(dbName).drop().get(); - assertThat(resultDelete).isTrue(); - } - - @Test - void createDatabaseWithOptionsSatellite() throws ExecutionException, InterruptedException { - assumeTrue(isCluster()); - assumeTrue(isEnterprise()); - assumeTrue(isAtLeastVersion(3, 6)); - - final DbName dbName = DbName.of("testDB-" + TestUtils.generateRandomDbName(20, supportsExtendedNames())); - final Boolean resultCreate = arangoDB.createDatabase(new DBCreateOptions() - .name(dbName) - .options(new DatabaseOptions() - .writeConcern(2) - .replicationFactor(ReplicationFactor.ofSatellite()) - .sharding("") - ) - ).get(); - assertThat(resultCreate).isTrue(); - - DatabaseEntity info = arangoDB.db(dbName).getInfo().get(); - assertThat(info.getReplicationFactor()).isEqualTo(ReplicationFactor.ofSatellite()); - assertThat(info.getWriteConcern()).isEqualTo(2); - assertThat(info.getSharding()).isEmpty(); - - final Boolean resultDelete = arangoDB.db(dbName).drop().get(); - assertThat(resultDelete).isTrue(); - } - - @Test - void deleteDatabase() throws InterruptedException, ExecutionException { - final Boolean resultCreate = arangoDB.createDatabase(BaseTest.TEST_DB).get(); - assertThat(resultCreate).isTrue(); - arangoDB.db(BaseTest.TEST_DB).drop() - .whenComplete((resultDelete, ex) -> assertThat(resultDelete).isEqualTo(true)) - .get(); - } - - @Test - void getDatabases() throws InterruptedException, ExecutionException { - Collection dbs = arangoDB.getDatabases().get(); - assertThat(dbs).isNotNull(); - assertThat(dbs).isNotEmpty(); - final int dbCount = dbs.size(); - assertThat(dbs).contains("_system"); - arangoDB.createDatabase(BaseTest.TEST_DB).get(); - dbs = arangoDB.getDatabases().get(); - assertThat(dbs).hasSizeGreaterThan(dbCount); - assertThat(dbs).contains("_system"); - assertThat(dbs).contains(BaseTest.TEST_DB.get()); - arangoDB.db(BaseTest.TEST_DB).drop().get(); - } - - @Test - void getAccessibleDatabases() throws InterruptedException, ExecutionException { - arangoDB.getAccessibleDatabases() - .whenComplete((dbs, ex) -> { - assertThat(dbs).isNotNull(); - assertThat(dbs).isNotEmpty(); - assertThat(dbs).contains("_system"); - }) - .get(); - } - - @Test - void getAccessibleDatabasesFor() throws InterruptedException, ExecutionException { - arangoDB.getAccessibleDatabasesFor("root") - .whenComplete((dbs, ex) -> { - assertThat(dbs).isNotNull(); - assertThat(dbs).isNotNull(); - assertThat(dbs).isNotEmpty(); - assertThat(dbs).contains("_system"); - }) - .get(); - } - - @Test - void createUser() throws InterruptedException, ExecutionException { - try { - arangoDB.createUser(USER, PW, null) - .whenComplete((result, ex) -> { - assertThat(result).isNotNull(); - assertThat(result.getUser()).isEqualTo(USER); - }) - .get(); - } finally { - arangoDB.deleteUser(USER).get(); - } - } - - @Test - void deleteUser() throws InterruptedException, ExecutionException { - arangoDB.createUser(USER, PW, null).get(); - arangoDB.deleteUser(USER).get(); - } - - @Test - void getUserRoot() throws InterruptedException, ExecutionException { - arangoDB.getUser(ROOT) - .whenComplete((user, ex) -> { - assertThat(user).isNotNull(); - assertThat(user.getUser()).isEqualTo(ROOT); - }) - .get(); - } - - @Test - void getUser() throws InterruptedException, ExecutionException { - try { - arangoDB.createUser(USER, PW, null).get(); - arangoDB.getUser(USER) - .whenComplete((user, ex) -> assertThat(user.getUser()).isEqualTo(USER)) - .get(); - } finally { - arangoDB.deleteUser(USER).get(); - } - - } - - @Test - void getUsersOnlyRoot() throws InterruptedException, ExecutionException { - arangoDB.getUsers() - .whenComplete((users, ex) -> { - assertThat(users).isNotNull(); - assertThat(users).isNotEmpty(); - }) - .get(); - } - - @Test - void getUsers() throws InterruptedException, ExecutionException { - try { - arangoDB.createUser(USER, PW, null).get(); - arangoDB.getUsers() - .whenComplete((users, ex) -> { - assertThat(users).isNotNull(); - assertThat(users).hasSizeGreaterThanOrEqualTo(2); - assertThat( - users.stream().map(UserEntity::getUser).collect(Collectors.toList()) - ).contains(ROOT, USER); - }) - .get(); - } finally { - arangoDB.deleteUser(USER).get(); - } - } - - @Test - void updateUserNoOptions() throws InterruptedException, ExecutionException { - try { - arangoDB.createUser(USER, PW, null).get(); - arangoDB.updateUser(USER, null).get(); - } finally { - arangoDB.deleteUser(USER).get(); - } - } - - @Test - void updateUser() throws InterruptedException, ExecutionException { - try { - final Map extra = new HashMap<>(); - extra.put("hund", false); - arangoDB.createUser(USER, PW, new UserCreateOptions().extra(extra)).get(); - extra.put("hund", true); - extra.put("mund", true); - { - arangoDB.updateUser(USER, new UserUpdateOptions().extra(extra)) - .whenComplete((user, ex) -> { - assertThat(user).isNotNull(); - assertThat(user.getExtra()).hasSize(2); - assertThat(user.getExtra().get("hund")).isNotNull(); - assertThat(Boolean.valueOf(String.valueOf(user.getExtra().get("hund")))).isTrue(); - }) - .get(); - } - arangoDB.getUser(USER) - .whenComplete((user2, ex) -> { - assertThat(user2.getExtra()).hasSize(2); - assertThat(user2.getExtra().get("hund")).isNotNull(); - assertThat(Boolean.valueOf(String.valueOf(user2.getExtra().get("hund")))).isTrue(); - }) - .get(); - } finally { - arangoDB.deleteUser(USER).get(); - } - } - - @Test - void replaceUser() throws InterruptedException, ExecutionException { - try { - final Map extra = new HashMap<>(); - extra.put("hund", false); - arangoDB.createUser(USER, PW, new UserCreateOptions().extra(extra)).get(); - extra.remove("hund"); - extra.put("mund", true); - { - arangoDB.replaceUser(USER, new UserUpdateOptions().extra(extra)) - .whenComplete((user, ex) -> { - assertThat(user).isNotNull(); - assertThat(user.getExtra()).hasSize(1); - assertThat(user.getExtra().get("mund")).isNotNull(); - assertThat(Boolean.valueOf(String.valueOf(user.getExtra().get("mund")))).isTrue(); - }) - .get(); - } - { - arangoDB.getUser(USER) - .whenComplete((user2, ex) -> { - assertThat(user2.getExtra()).hasSize(1); - assertThat(user2.getExtra().get("mund")).isNotNull(); - assertThat(Boolean.valueOf(String.valueOf(user2.getExtra().get("mund")))).isTrue(); - }) - .get(); - } - } finally { - arangoDB.deleteUser(USER).get(); - } - } - - @Test - void updateUserDefaultDatabaseAccess() throws InterruptedException, ExecutionException { - try { - arangoDB.createUser(USER, PW).get(); - arangoDB.grantDefaultDatabaseAccess(USER, Permissions.RW).get(); - } finally { - arangoDB.deleteUser(USER).get(); - } - } - - @Test - void updateUserDefaultCollectionAccess() throws InterruptedException, ExecutionException { - try { - arangoDB.createUser(USER, PW).get(); - arangoDB.grantDefaultCollectionAccess(USER, Permissions.RW).get(); - } finally { - arangoDB.deleteUser(USER).get(); - } - } - - @Test - void authenticationFailPassword() throws InterruptedException { - final ArangoDBAsync arangoDB = new ArangoDBAsync.Builder() - .loadProperties(ConfigUtils.loadConfig()) - .password("no").jwt(null).build(); - try { - arangoDB.getVersion().get(); - fail(); - } catch (final ExecutionException exception) { - assertThat(exception.getCause()).isInstanceOf(ArangoDBException.class); - } - } - - @Test - void authenticationFailUser() throws InterruptedException { - final ArangoDBAsync arangoDB = new ArangoDBAsync.Builder() - .loadProperties(ConfigUtils.loadConfig()) - .user("no").jwt(null).build(); - try { - arangoDB.getVersion().get(); - fail(); - } catch (final ExecutionException exception) { - assertThat(exception.getCause()).isInstanceOf(ArangoDBException.class); - } - } - - @Test - void execute() throws InterruptedException, ExecutionException { - arangoDB - .execute(Request.builder() - .db(DbName.SYSTEM) - .method(Request.Method.GET) - .path("/_api/version") - .build(), RawJson.class) - .whenComplete((response, ex) -> { - assertThat(response.getBody()).isNotNull(); - assertThat(SerdeUtils.INSTANCE.parseJson(response.getBody().getValue()).get("version").isTextual()).isTrue(); - }) - .get(); - } - - @Test - void execute_acquireHostList_enabled() throws InterruptedException, ExecutionException { - final ArangoDBAsync arangoDB = new ArangoDBAsync.Builder() - .loadProperties(ConfigUtils.loadConfig()) - .acquireHostList(true).build(); - arangoDB - .execute(Request.builder() - .db(DbName.SYSTEM) - .method(Request.Method.GET) - .path("/_api/version") - .build(), RawJson.class) - .whenComplete((response, ex) -> { - assertThat(response.getBody()).isNotNull(); - assertThat(SerdeUtils.INSTANCE.parseJson(response.getBody().getValue()).get("version").isTextual()).isTrue(); - }) - .get(); - } - - @Test - void getLogEntries() throws InterruptedException, ExecutionException { - assumeTrue(isAtLeastVersion(3, 8)); - arangoDB.getLogEntries(null) - .whenComplete((logs, ex) -> { - assertThat(logs).isNotNull(); - assertThat(logs.getTotal()).isPositive(); - assertThat((long) logs.getMessages().size()).isEqualTo(logs.getTotal()); - }) - .get(); - } - - @Test - void getLogLevel() throws InterruptedException, ExecutionException { - assumeTrue(isAtLeastVersion(3, 7)); // it fails in 3.6 active-failover (BTS-362) - arangoDB.getLogLevel() - .whenComplete((logLevel, ex) -> { - assertThat(logLevel).isNotNull(); - assertThat(logLevel.getAgency()).isEqualTo(LogLevelEntity.LogLevel.INFO); - }) - .get(); - } - - @Test - void setLogLevel() throws InterruptedException, ExecutionException { - assumeTrue(isAtLeastVersion(3, 7)); // it fails in 3.6 active-failover (BTS-362) - final LogLevelEntity entity = new LogLevelEntity(); - try { - entity.setAgency(LogLevelEntity.LogLevel.ERROR); - arangoDB.setLogLevel(entity) - .whenComplete((logLevel, ex) -> { - assertThat(logLevel).isNotNull(); - assertThat(logLevel.getAgency()).isEqualTo(LogLevelEntity.LogLevel.ERROR); - }) - .get(); - } finally { - entity.setAgency(LogLevelEntity.LogLevel.INFO); - arangoDB.setLogLevel(entity).get(); - } - } - - @Test - @Disabled("Manual execution only") - void queueTime() throws InterruptedException, ExecutionException { - List>> reqs = IntStream.range(0, 80) - .mapToObj(__ -> arangoDB.db().query("RETURN SLEEP(1)", Void.class)) - .collect(Collectors.toList()); - for (CompletableFuture> req : reqs) { - req.get(); - } - - QueueTimeMetrics qt = arangoDB.metrics().getQueueTime(); - double avg = qt.getAvg(); - QueueTimeSample[] values = qt.getValues(); - if (isAtLeastVersion(3, 9)) { - assertThat(values).hasSize(20); - for (int i = 0; i < values.length; i++) { - assertThat(values[i]).isNotNull(); - assertThat(values[i].value).isGreaterThanOrEqualTo(0.0); - if (i > 0) { - assertThat(values[i].timestamp).isGreaterThanOrEqualTo(values[i - 1].timestamp); - } - } - assertThat(avg).isGreaterThan(0.0); - } else { - assertThat(avg).isEqualTo(0.0); - assertThat(values).isEmpty(); - } - } - - @Test - void getQueryOptimizerRules() throws ExecutionException, InterruptedException { - assumeTrue(isAtLeastVersion(3, 10)); - final Collection rules = arangoDB.getQueryOptimizerRules().get(); - assertThat(rules).isNotEmpty(); - for (QueryOptimizerRule rule : rules) { - assertThat(rule).isNotNull(); - assertThat(rule.getName()).isNotNull(); - QueryOptimizerRule.Flags flags = rule.getFlags(); - assertThat(flags.getHidden()).isNotNull(); - assertThat(flags.getClusterOnly()).isNotNull(); - assertThat(flags.getCanBeDisabled()).isNotNull(); - assertThat(flags.getCanCreateAdditionalPlans()).isNotNull(); - assertThat(flags.getDisabledByDefault()).isNotNull(); - assertThat(flags.getEnterpriseOnly()).isNotNull(); - } - } - - -} diff --git a/shaded-integration-tests/src/test/native/java/com/arangodb/async/ArangoDatabaseTest.java b/shaded-integration-tests/src/test/native/java/com/arangodb/async/ArangoDatabaseTest.java deleted file mode 100644 index a12bf84ec..000000000 --- a/shaded-integration-tests/src/test/native/java/com/arangodb/async/ArangoDatabaseTest.java +++ /dev/null @@ -1,1024 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.async; - -import com.arangodb.ArangoDBException; -import com.arangodb.DbName; -import com.arangodb.entity.AqlExecutionExplainEntity.ExecutionPlan; -import com.arangodb.entity.*; -import com.arangodb.entity.AqlParseEntity.AstNode; -import com.arangodb.entity.QueryCachePropertiesEntity.CacheMode; -import com.arangodb.model.*; -import com.arangodb.util.RawJson; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.node.JsonNodeFactory; -import org.junit.jupiter.api.Disabled; -import org.junit.jupiter.api.Test; - -import java.io.IOException; -import java.util.*; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.atomic.AtomicInteger; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.catchThrowable; -import static org.junit.jupiter.api.Assertions.fail; -import static org.junit.jupiter.api.Assumptions.assumeTrue; - - -/** - * @author Mark Vollmary - * @author Michele Rastelli - */ -class ArangoDatabaseTest extends BaseTest { - - private static final String COLLECTION_NAME = "db_test"; - private static final String GRAPH_NAME = "graph_test"; - - @Test - void create() throws InterruptedException, ExecutionException { - try { - final Boolean result = arangoDB.db(DbName.of(BaseTest.TEST_DB.get() + "_1")).create().get(); - assertThat(result).isTrue(); - } finally { - arangoDB.db(DbName.of(BaseTest.TEST_DB.get() + "_1")).drop().get(); - } - } - - @Test - void getVersion() throws InterruptedException, ExecutionException { - db.getVersion() - .whenComplete((version, ex) -> { - assertThat(version).isNotNull(); - assertThat(version.getServer()).isNotNull(); - assertThat(version.getVersion()).isNotNull(); - }) - .get(); - } - - @Test - void getEngine() throws ExecutionException, InterruptedException { - final ArangoDBEngine engine = db.getEngine().get(); - assertThat(engine).isNotNull(); - assertThat(engine.getName()).isNotNull(); - } - - @Test - void exists() throws InterruptedException, ExecutionException { - assertThat(db.exists().get()).isTrue(); - assertThat(arangoDB.db(DbName.of("no")).exists().get()).isFalse(); - } - - @Test - void getAccessibleDatabases() throws InterruptedException, ExecutionException { - db.getAccessibleDatabases() - .whenComplete((dbs, ex) -> { - assertThat(dbs).isNotNull(); - assertThat(dbs.size()).isGreaterThan(0); - assertThat(dbs).contains("_system"); - }) - .get(); - } - - @Test - void createCollection() throws InterruptedException, ExecutionException { - db.createCollection(COLLECTION_NAME, null) - .whenComplete((result, ex) -> { - assertThat(result).isNotNull(); - assertThat(result.getId()).isNotNull(); - }) - .get(); - db.collection(COLLECTION_NAME).drop().get(); - } - - @Test - void createCollectionWithReplicationFactor() throws InterruptedException, ExecutionException { - assumeTrue(isCluster()); - final CollectionEntity result = db - .createCollection(COLLECTION_NAME, new CollectionCreateOptions().replicationFactor(2)).get(); - assertThat(result).isNotNull(); - assertThat(result.getId()).isNotNull(); - assertThat(db.collection(COLLECTION_NAME).getProperties().get().getReplicationFactor().getValue()).isEqualTo(2); - db.collection(COLLECTION_NAME).drop().get(); - } - - @Test - void createCollectionWithWriteConcern() throws ExecutionException, InterruptedException { - assumeTrue(isAtLeastVersion(3, 5)); - assumeTrue(isCluster()); - - final CollectionEntity result = db.createCollection(COLLECTION_NAME, - new CollectionCreateOptions().replicationFactor(2).writeConcern(2)).get(); - assertThat(result).isNotNull(); - assertThat(result.getId()).isNotNull(); - assertThat(db.collection(COLLECTION_NAME).getProperties().get().getReplicationFactor().getValue()).isEqualTo(2); - assertThat(db.collection(COLLECTION_NAME).getProperties().get().getWriteConcern()).isEqualTo(2); - db.collection(COLLECTION_NAME).drop(); - } - - @Test - void createCollectionWithNumberOfShards() throws InterruptedException, ExecutionException { - assumeTrue(isCluster()); - final CollectionEntity result = db - .createCollection(COLLECTION_NAME, new CollectionCreateOptions().numberOfShards(2)).get(); - assertThat(result).isNotNull(); - assertThat(result.getId()).isNotNull(); - assertThat(db.collection(COLLECTION_NAME).getProperties().get().getNumberOfShards()).isEqualTo(2); - db.collection(COLLECTION_NAME).drop().get(); - } - - @Test - void createCollectionWithNumberOfShardsAndShardKey() throws InterruptedException, ExecutionException { - assumeTrue(isCluster()); - final CollectionEntity result = db - .createCollection(COLLECTION_NAME, new CollectionCreateOptions().numberOfShards(2).shardKeys("a")) - .get(); - assertThat(result).isNotNull(); - assertThat(result.getId()).isNotNull(); - final CollectionPropertiesEntity properties = db.collection(COLLECTION_NAME).getProperties().get(); - assertThat(properties.getNumberOfShards()).isEqualTo(2); - assertThat(properties.getShardKeys()).hasSize(1); - db.collection(COLLECTION_NAME).drop().get(); - } - - @Test - void createCollectionWithNumberOfShardsAndShardKeys() throws InterruptedException, ExecutionException { - assumeTrue(isCluster()); - final CollectionEntity result = db.createCollection(COLLECTION_NAME, - new CollectionCreateOptions().numberOfShards(2).shardKeys("a", "b")).get(); - assertThat(result).isNotNull(); - assertThat(result.getId()).isNotNull(); - final CollectionPropertiesEntity properties = db.collection(COLLECTION_NAME).getProperties().get(); - assertThat(properties.getNumberOfShards()).isEqualTo(2); - assertThat(properties.getShardKeys()).hasSize(2); - db.collection(COLLECTION_NAME).drop().get(); - } - - @Test - void deleteCollection() throws InterruptedException, ExecutionException { - db.createCollection(COLLECTION_NAME, null).get(); - db.collection(COLLECTION_NAME).drop().get(); - try { - db.collection(COLLECTION_NAME).getInfo().get(); - fail(); - } catch (final ExecutionException e) { - assertThat(e.getCause()).isInstanceOf(ArangoDBException.class); - } - } - - @Test - void deleteSystemCollection() throws InterruptedException, ExecutionException { - final String name = "_system_test"; - db.createCollection(name, new CollectionCreateOptions().isSystem(true)).get(); - db.collection(name).drop(true).get(); - try { - db.collection(name).getInfo().get(); - fail(); - } catch (final ExecutionException e) { - assertThat(e.getCause()).isInstanceOf(ArangoDBException.class); - } - } - - @Test - void deleteSystemCollectionFail() throws InterruptedException, ExecutionException { - final String name = "_system_test"; - db.createCollection(name, new CollectionCreateOptions().isSystem(true)).get(); - try { - db.collection(name).drop().get(); - fail(); - } catch (final ExecutionException e) { - assertThat(e.getCause()).isInstanceOf(ArangoDBException.class); - } - db.collection(name).drop(true).get(); - try { - db.collection(name).getInfo().get(); - fail(); - } catch (final ExecutionException e) { - assertThat(e.getCause()).isInstanceOf(ArangoDBException.class); - } - } - - @Test - void getIndex() throws InterruptedException, ExecutionException { - db.createCollection(COLLECTION_NAME, null).get(); - final Collection fields = new ArrayList<>(); - fields.add("a"); - final IndexEntity createResult = db.collection(COLLECTION_NAME).ensureHashIndex(fields, null).get(); - db.getIndex(createResult.getId()) - .whenComplete((readResult, ex) -> { - assertThat(readResult.getId()).isEqualTo(createResult.getId()); - assertThat(readResult.getType()).isEqualTo(createResult.getType()); - }) - .get(); - db.collection(COLLECTION_NAME).drop().get(); - } - - @Test - void deleteIndex() throws InterruptedException, ExecutionException { - try { - db.createCollection(COLLECTION_NAME, null).get(); - final Collection fields = new ArrayList<>(); - fields.add("a"); - final IndexEntity createResult = db.collection(COLLECTION_NAME).ensureHashIndex(fields, null).get(); - db.deleteIndex(createResult.getId()) - .whenComplete((id, ex) -> { - assertThat(id).isEqualTo(createResult.getId()); - try { - db.getIndex(id).get(); - fail(); - } catch (InterruptedException e) { - fail(); - } catch (ExecutionException e) { - assertThat(e.getCause()).isInstanceOf(ArangoDBException.class); - } - }) - .get(); - } finally { - db.collection(COLLECTION_NAME).drop().get(); - } - } - - @Test - void getCollections() throws InterruptedException, ExecutionException { - try { - final Collection systemCollections = db.getCollections(null).get(); - db.createCollection(COLLECTION_NAME + "1", null).get(); - db.createCollection(COLLECTION_NAME + "2", null).get(); - db.getCollections(null) - .whenComplete((collections, ex) -> { - assertThat(collections.size()).isEqualTo(2 + systemCollections.size()); - assertThat(collections).isNotNull(); - }) - .get(); - } finally { - db.collection(COLLECTION_NAME + "1").drop().get(); - db.collection(COLLECTION_NAME + "2").drop().get(); - } - } - - @Test - void getCollectionsExcludeSystem() throws InterruptedException, ExecutionException { - try { - final CollectionsReadOptions options = new CollectionsReadOptions().excludeSystem(true); - final Collection systemCollections = db.getCollections(options).get(); - assertThat(systemCollections).isEmpty(); - db.createCollection(COLLECTION_NAME + "1", null).get(); - db.createCollection(COLLECTION_NAME + "2", null).get(); - db.getCollections(options) - .whenComplete((collections, ex) -> { - assertThat(collections.size()).isEqualTo(2); - assertThat(collections).isNotNull(); - }) - .get(); - } finally { - db.collection(COLLECTION_NAME + "1").drop().get(); - db.collection(COLLECTION_NAME + "2").drop().get(); - } - } - - @Test - void grantAccess() throws InterruptedException, ExecutionException { - try { - arangoDB.createUser("user1", "1234", null).get(); - db.grantAccess("user1").get(); - } finally { - arangoDB.deleteUser("user1").get(); - } - } - - @Test - void grantAccessRW() throws InterruptedException, ExecutionException { - try { - arangoDB.createUser("user1", "1234", null).get(); - db.grantAccess("user1", Permissions.RW).get(); - } finally { - arangoDB.deleteUser("user1").get(); - } - } - - @Test - void grantAccessRO() throws InterruptedException, ExecutionException { - try { - arangoDB.createUser("user1", "1234", null).get(); - db.grantAccess("user1", Permissions.RO).get(); - } finally { - arangoDB.deleteUser("user1").get(); - } - } - - @Test - void grantAccessNONE() throws InterruptedException, ExecutionException { - try { - arangoDB.createUser("user1", "1234", null).get(); - db.grantAccess("user1", Permissions.NONE).get(); - } finally { - arangoDB.deleteUser("user1").get(); - } - } - - @Test - void grantAccessUserNotFound() { - Throwable thrown = catchThrowable(() -> db.grantAccess("user1", Permissions.RW).get()); - assertThat(thrown).isInstanceOf(ExecutionException.class); - } - - @Test - void revokeAccess() throws InterruptedException, ExecutionException { - try { - arangoDB.createUser("user1", "1234", null).get(); - db.revokeAccess("user1").get(); - } finally { - arangoDB.deleteUser("user1").get(); - } - } - - @Test - void revokeAccessUserNotFound() { - Throwable thrown = catchThrowable(() -> db.revokeAccess("user1").get()); - assertThat(thrown).isInstanceOf(ExecutionException.class); - } - - @Test - void resetAccess() throws InterruptedException, ExecutionException { - try { - arangoDB.createUser("user1", "1234", null).get(); - db.resetAccess("user1").get(); - } finally { - arangoDB.deleteUser("user1").get(); - } - } - - @Test - void resetAccessUserNotFound() { - Throwable thrown = catchThrowable(() -> db.resetAccess("user1").get()); - assertThat(thrown).isInstanceOf(ExecutionException.class); - } - - @Test - void grantDefaultCollectionAccess() throws InterruptedException, ExecutionException { - try { - arangoDB.createUser("user1", "1234").get(); - db.grantDefaultCollectionAccess("user1", Permissions.RW).get(); - } finally { - arangoDB.deleteUser("user1").get(); - } - } - - @Test - void getPermissions() throws InterruptedException, ExecutionException { - assertThat(db.getPermissions("root").get()).isEqualTo(Permissions.RW); - } - - @Test - void query() throws InterruptedException, ExecutionException { - try { - db.createCollection(COLLECTION_NAME, null).get(); - for (int i = 0; i < 10; i++) { - db.collection(COLLECTION_NAME).insertDocument(new BaseDocument(), null).get(); - } - db.query("for i in db_test return i._id", null, null, String.class) - .whenComplete((cursor, ex) -> { - for (int i = 0; i < 10; i++, cursor.next()) { - assertThat(cursor.hasNext()).isEqualTo(true); - } - }) - .get(); - } finally { - db.collection(COLLECTION_NAME).drop().get(); - } - } - - @Test - void queryForEach() throws InterruptedException, ExecutionException { - try { - db.createCollection(COLLECTION_NAME, null).get(); - for (int i = 0; i < 10; i++) { - db.collection(COLLECTION_NAME).insertDocument(new BaseDocument(), null).get(); - } - db.query("for i in db_test return i._id", null, null, String.class) - .whenComplete((cursor, ex) -> { - final AtomicInteger i = new AtomicInteger(0); - cursor.forEachRemaining(e -> i.incrementAndGet()); - assertThat(i.get()).isEqualTo(10); - }) - .get(); - } finally { - db.collection(COLLECTION_NAME).drop().get(); - } - } - - @Test - void queryStream() throws InterruptedException, ExecutionException { - try { - db.createCollection(COLLECTION_NAME, null).get(); - for (int i = 0; i < 10; i++) { - db.collection(COLLECTION_NAME).insertDocument(new BaseDocument(), null).get(); - } - db.query("for i in db_test return i._id", null, null, String.class) - .whenComplete((cursor, ex) -> { - final AtomicInteger i = new AtomicInteger(0); - cursor.forEachRemaining(e -> i.incrementAndGet()); - assertThat(i.get()).isEqualTo(10); - }) - .get(); - } finally { - db.collection(COLLECTION_NAME).drop().get(); - } - } - - @Test - void queryWithTimeout() throws ExecutionException, InterruptedException { - assumeTrue(isAtLeastVersion(3, 6)); - - try { - db.query("RETURN SLEEP(1)", null, new AqlQueryOptions().maxRuntime(0.1), String.class).get().next(); - fail(); - } catch (ExecutionException e) { - assertThat(e.getCause()).isInstanceOf(ArangoDBException.class); - assertThat(((ArangoDBException) e.getCause()).getResponseCode()).isEqualTo(410); - } - } - - @Test - void queryWithCount() throws InterruptedException, ExecutionException { - try { - db.createCollection(COLLECTION_NAME, null).get(); - for (int i = 0; i < 10; i++) { - db.collection(COLLECTION_NAME).insertDocument(new BaseDocument(), null).get(); - } - - db.query("for i in db_test Limit 6 return i._id", null, new AqlQueryOptions().count(true), String.class) - .whenComplete((cursor, ex) -> { - for (int i = 0; i < 6; i++, cursor.next()) { - assertThat(cursor.hasNext()).isEqualTo(true); - } - assertThat(cursor.getCount()).isEqualTo(6); - }) - .get(); - } finally { - db.collection(COLLECTION_NAME).drop().get(); - } - } - - @Test - void queryWithLimitAndFullCount() throws InterruptedException, ExecutionException { - try { - db.createCollection(COLLECTION_NAME, null).get(); - for (int i = 0; i < 10; i++) { - db.collection(COLLECTION_NAME).insertDocument(new BaseDocument(), null).get(); - } - - db.query("for i in db_test Limit 5 return i._id", null, new AqlQueryOptions().fullCount(true), String.class) - .whenComplete((cursor, ex) -> { - for (int i = 0; i < 5; i++, cursor.next()) { - assertThat(cursor.hasNext()).isEqualTo(true); - } - assertThat(cursor.getStats()).isNotNull(); - assertThat(((Number) cursor.getStats().get("fullCount")).intValue()) - .isGreaterThanOrEqualTo(10); - }) - .get(); - } finally { - db.collection(COLLECTION_NAME).drop().get(); - } - } - - @Test - void queryWithBatchSize() throws InterruptedException, ExecutionException { - try { - db.createCollection(COLLECTION_NAME, null).get(); - for (int i = 0; i < 10; i++) { - db.collection(COLLECTION_NAME).insertDocument(new BaseDocument(), null).get(); - } - final ArangoCursorAsync cursor = db.query("for i in db_test return i._id", null, - new AqlQueryOptions().batchSize(5).count(true), String.class).get(); - for (int i = 0; i < 10; i++, cursor.next()) { - assertThat(cursor.hasNext()).isTrue(); - } - } finally { - db.collection(COLLECTION_NAME).drop().get(); - } - } - - @Test - void queryStreamWithBatchSize() throws InterruptedException, ExecutionException { - try { - db.createCollection(COLLECTION_NAME, null).get(); - for (int i = 0; i < 10; i++) { - db.collection(COLLECTION_NAME).insertDocument(new BaseDocument(), null).get(); - } - final ArangoCursorAsync cursor = db.query("for i in db_test return i._id", null, - new AqlQueryOptions().batchSize(5).count(true), String.class).get(); - final AtomicInteger i = new AtomicInteger(0); - cursor.streamRemaining().forEach(e -> i.incrementAndGet()); - assertThat(i.get()).isEqualTo(10); - } finally { - db.collection(COLLECTION_NAME).drop().get(); - } - } - - /** - * ignored. takes to long - */ - @Test - @Disabled - void queryWithTTL() throws InterruptedException, ExecutionException { - // set TTL to 1 seconds and get the second batch after 2 seconds! - final int ttl = 1; - final int wait = 2; - try { - db.createCollection(COLLECTION_NAME, null).get(); - for (int i = 0; i < 10; i++) { - db.collection(COLLECTION_NAME).insertDocument(new BaseDocument(), null).get(); - } - final ArangoCursorAsync cursor = db.query("for i in db_test return i._id", null, - new AqlQueryOptions().batchSize(5).ttl(ttl), String.class).get(); - for (int i = 0; i < 10; i++, cursor.next()) { - assertThat(cursor.hasNext()).isTrue(); - if (i == 1) { - Thread.sleep(wait * 1000); - } - } - fail(); - } catch (final ArangoDBException ex) { - assertThat(ex.getResponseCode()).isEqualTo(404); - assertThat(ex.getErrorNum()).isEqualTo(1600); - } finally { - db.collection(COLLECTION_NAME).drop().get(); - } - } - - @Test - void changeQueryCache() throws InterruptedException, ExecutionException { - try { - QueryCachePropertiesEntity properties = db.getQueryCacheProperties().get(); - assertThat(properties).isNotNull(); - assertThat(properties.getMode()).isEqualTo(CacheMode.off); - assertThat(properties.getMaxResults()).isPositive(); - - properties.setMode(CacheMode.on); - properties = db.setQueryCacheProperties(properties).get(); - assertThat(properties).isNotNull(); - assertThat(properties.getMode()).isEqualTo(CacheMode.on); - - properties = db.getQueryCacheProperties().get(); - assertThat(properties.getMode()).isEqualTo(CacheMode.on); - } finally { - final QueryCachePropertiesEntity properties = new QueryCachePropertiesEntity(); - properties.setMode(CacheMode.off); - db.setQueryCacheProperties(properties).get(); - } - } - - @Test - void queryWithCache() throws InterruptedException, ExecutionException { - assumeTrue(isSingleServer()); - try { - db.createCollection(COLLECTION_NAME, null).get(); - for (int i = 0; i < 10; i++) { - db.collection(COLLECTION_NAME).insertDocument(new BaseDocument(), null).get(); - } - - final QueryCachePropertiesEntity properties = new QueryCachePropertiesEntity(); - properties.setMode(CacheMode.on); - db.setQueryCacheProperties(properties).get(); - - final ArangoCursorAsync cursor = db - .query("FOR t IN db_test FILTER t.age >= 10 SORT t.age RETURN t._id", null, - new AqlQueryOptions().cache(true), String.class) - .get(); - - assertThat(cursor.isCached()).isFalse(); - - final ArangoCursorAsync cachedCursor = db - .query("FOR t IN db_test FILTER t.age >= 10 SORT t.age RETURN t._id", null, - new AqlQueryOptions().cache(true), String.class) - .get(); - - assertThat(cachedCursor.isCached()).isTrue(); - - } finally { - db.collection(COLLECTION_NAME).drop().get(); - final QueryCachePropertiesEntity properties = new QueryCachePropertiesEntity(); - properties.setMode(CacheMode.off); - db.setQueryCacheProperties(properties).get(); - } - } - - @Test - void queryCursor() throws InterruptedException, ExecutionException { - try { - db.createCollection(COLLECTION_NAME, null).get(); - final int numbDocs = 10; - for (int i = 0; i < numbDocs; i++) { - db.collection(COLLECTION_NAME).insertDocument(new BaseDocument(), null).get(); - } - - final int batchSize = 5; - final ArangoCursorAsync cursor = db.query("for i in db_test return i._id", null, - new AqlQueryOptions().batchSize(batchSize).count(true), String.class).get(); - assertThat(cursor.getCount()).isEqualTo(numbDocs); - - final ArangoCursorAsync cursor2 = db.cursor(cursor.getId(), String.class).get(); - assertThat(cursor2.getCount()).isEqualTo(numbDocs); - assertThat(cursor2.hasNext()).isTrue(); - - for (int i = 0; i < batchSize; i++, cursor.next()) { - assertThat(cursor.hasNext()).isTrue(); - } - } finally { - db.collection(COLLECTION_NAME).drop().get(); - } - } - - @Test - void changeQueryTrackingProperties() throws InterruptedException, ExecutionException { - try { - QueryTrackingPropertiesEntity properties = db.getQueryTrackingProperties().get(); - assertThat(properties).isNotNull(); - assertThat(properties.getEnabled()).isTrue(); - assertThat(properties.getTrackSlowQueries()).isTrue(); - assertThat(properties.getMaxQueryStringLength()).isPositive(); - assertThat(properties.getMaxSlowQueries()).isPositive(); - assertThat(properties.getSlowQueryThreshold()).isPositive(); - properties.setEnabled(false); - properties = db.setQueryTrackingProperties(properties).get(); - assertThat(properties).isNotNull(); - assertThat(properties.getEnabled()).isFalse(); - properties = db.getQueryTrackingProperties().get(); - assertThat(properties.getEnabled()).isFalse(); - } finally { - final QueryTrackingPropertiesEntity properties = new QueryTrackingPropertiesEntity(); - properties.setEnabled(true); - db.setQueryTrackingProperties(properties).get(); - } - } - - @Test - void queryWithBindVars() throws InterruptedException, ExecutionException { - try { - db.createCollection(COLLECTION_NAME, null).get(); - for (int i = 0; i < 10; i++) { - final BaseDocument baseDocument = new BaseDocument(UUID.randomUUID().toString()); - baseDocument.addAttribute("age", 20 + i); - db.collection(COLLECTION_NAME).insertDocument(baseDocument, null).get(); - } - final Map bindVars = new HashMap<>(); - bindVars.put("@coll", COLLECTION_NAME); - bindVars.put("age", 25); - db.query("FOR t IN @@coll FILTER t.age >= @age SORT t.age RETURN t._id", bindVars, null, String.class) - .whenComplete((cursor, ex) -> { - for (int i = 0; i < 5; i++, cursor.next()) { - assertThat(cursor.hasNext()).isEqualTo(true); - } - }) - .get(); - } finally { - db.collection(COLLECTION_NAME).drop().get(); - } - } - - @Test - void queryWithWarning() throws InterruptedException, ExecutionException { - arangoDB.db().query("return 1/0", null, null, String.class) - .whenComplete((cursor, ex) -> { - assertThat(cursor.getWarnings()).isNotNull(); - assertThat(cursor.getWarnings()).isNotEmpty(); - }) - .get(); - } - - @Test - void queryClose() throws IOException, InterruptedException, ExecutionException { - final ArangoCursorAsync cursor = arangoDB.db() - .query("for i in 1..2 return i", null, new AqlQueryOptions().batchSize(1), String.class).get(); - cursor.close(); - int count = 0; - try { - for (; cursor.hasNext(); cursor.next(), count++) { - } - fail(); - } catch (final ArangoDBException e) { - assertThat(count).isEqualTo(1); - } - - } - - @Test - void explainQuery() throws InterruptedException, ExecutionException { - arangoDB.db().explainQuery("for i in 1..1 return i", null, null) - .whenComplete((explain, ex) -> { - assertThat(explain).isNotNull(); - assertThat(explain.getPlan()).isNotNull(); - assertThat(explain.getPlans()).isNull(); - final ExecutionPlan plan = explain.getPlan(); - assertThat(plan.getCollections().size()).isEqualTo(0); - assertThat(plan.getEstimatedCost()).isGreaterThan(0); - assertThat(plan.getEstimatedNrItems()).isGreaterThan(0); - assertThat(plan.getVariables().size()).isEqualTo(2); - assertThat(plan.getNodes().size()).isGreaterThan(0); - }) - .get(); - } - - @Test - void parseQuery() throws InterruptedException, ExecutionException { - assumeTrue(isAtLeastVersion(3, 4)); - arangoDB.db().parseQuery("for i in _apps return i") - .whenComplete((parse, ex) -> { - assertThat(parse).isNotNull(); - assertThat(parse.getBindVars()).isEmpty(); - assertThat(parse.getCollections().size()).isEqualTo(1); - assertThat(parse.getCollections().iterator().next()).isEqualTo("_apps"); - assertThat(parse.getAst().size()).isEqualTo(1); - final AstNode root = parse.getAst().iterator().next(); - assertThat(root.getType()).isEqualTo("root"); - assertThat(root.getName()).isNull(); - assertThat(root.getSubNodes()).isNotNull(); - assertThat(root.getSubNodes().size()).isEqualTo(2); - final Iterator iterator = root.getSubNodes().iterator(); - final AstNode for_ = iterator.next(); - assertThat(for_.getType()).isEqualTo("for"); - assertThat(for_.getSubNodes()).isNotNull(); - assertThat(for_.getSubNodes().size()).isEqualTo(3); - final Iterator iterator2 = for_.getSubNodes().iterator(); - final AstNode first = iterator2.next(); - assertThat(first.getType()).isEqualTo("variable"); - assertThat(first.getName()).isEqualTo("i"); - final AstNode second = iterator2.next(); - assertThat(second.getType()).isEqualTo("collection"); - assertThat(second.getName()).isEqualTo("_apps"); - final AstNode return_ = iterator.next(); - assertThat(return_.getType()).isEqualTo("return"); - assertThat(return_.getSubNodes()).isNotNull(); - assertThat(return_.getSubNodes().size()).isEqualTo(1); - assertThat(return_.getSubNodes().iterator().next().getType()).isEqualTo("reference"); - assertThat(return_.getSubNodes().iterator().next().getName()).isEqualTo("i"); - }) - .get(); - } - - @Test - @Disabled - void getAndClearSlowQueries() throws InterruptedException, ExecutionException { - final QueryTrackingPropertiesEntity properties = db.getQueryTrackingProperties().get(); - final Long slowQueryThreshold = properties.getSlowQueryThreshold(); - try { - properties.setSlowQueryThreshold(1L); - db.setQueryTrackingProperties(properties); - - db.query("return sleep(1.1)", null, null, Void.class); - final Collection slowQueries = db.getSlowQueries().get(); - assertThat(slowQueries).isNotNull(); - assertThat(slowQueries).hasSize(1); - final QueryEntity queryEntity = slowQueries.iterator().next(); - assertThat(queryEntity.getQuery()).isEqualTo("return sleep(1.1)"); - - db.clearSlowQueries().get(); - assertThat(db.getSlowQueries().get().size()).isZero(); - } finally { - properties.setSlowQueryThreshold(slowQueryThreshold); - db.setQueryTrackingProperties(properties); - } - } - - @Test - void createGetDeleteAqlFunction() throws InterruptedException, ExecutionException { - final Collection aqlFunctionsInitial = db.getAqlFunctions(null).get(); - assertThat(aqlFunctionsInitial).isEmpty(); - try { - db.createAqlFunction("myfunctions::temperature::celsiustofahrenheit", - "function (celsius) { return celsius * 1.8 + 32; }", null).get(); - - final Collection aqlFunctions = db.getAqlFunctions(null).get(); - assertThat(aqlFunctions).hasSizeGreaterThan(aqlFunctionsInitial.size()); - } finally { - final Integer deleteCount = db.deleteAqlFunction("myfunctions::temperature::celsiustofahrenheit", null) - .get(); - // compatibility with ArangoDB < 3.4 - if (isAtLeastVersion(3, 4)) { - assertThat(deleteCount).isEqualTo(1); - } else { - assertThat(deleteCount).isNull(); - } - - final Collection aqlFunctions = db.getAqlFunctions(null).get(); - assertThat(aqlFunctions).hasSameSizeAs(aqlFunctionsInitial); - } - } - - @Test - void createGetDeleteAqlFunctionWithNamespace() throws InterruptedException, ExecutionException { - final Collection aqlFunctionsInitial = db.getAqlFunctions(null).get(); - assertThat(aqlFunctionsInitial).isEmpty(); - try { - db.createAqlFunction("myfunctions::temperature::celsiustofahrenheit1", - "function (celsius) { return celsius * 1.8 + 32; }", null).get(); - db.createAqlFunction("myfunctions::temperature::celsiustofahrenheit2", - "function (celsius) { return celsius * 1.8 + 32; }", null).get(); - - } finally { - db.deleteAqlFunction("myfunctions::temperature", new AqlFunctionDeleteOptions().group(true)).get(); - - final Collection aqlFunctions = db.getAqlFunctions(null).get(); - assertThat(aqlFunctions).hasSameSizeAs(aqlFunctionsInitial); - } - } - - @Test - void createGraph() throws InterruptedException, ExecutionException { - try { - db.createGraph(GRAPH_NAME, null, null) - .whenComplete((result, ex) -> { - assertThat(result).isNotNull(); - assertThat(result.getName()).isEqualTo(GRAPH_NAME); - }) - .get(); - } finally { - db.graph(GRAPH_NAME).drop().get(); - } - } - - @Test - void getGraphs() throws InterruptedException, ExecutionException { - try { - db.createGraph(GRAPH_NAME, null, null).get(); - db.getGraphs() - .whenComplete((graphs, ex) -> { - assertThat(graphs).isNotNull(); - assertThat(graphs.size()).isEqualTo(1); - }) - .get(); - } finally { - db.graph(GRAPH_NAME).drop().get(); - } - } - - @Test - void transactionString() throws InterruptedException, ExecutionException { - final TransactionOptions options = new TransactionOptions().params("test"); - db.transaction("function (params) {return params;}", RawJson.class, options) - .whenComplete((result, ex) -> assertThat(result.getValue()).isEqualTo("\"test\"")) - .get(); - } - - @Test - void transactionNumber() throws InterruptedException, ExecutionException { - final TransactionOptions options = new TransactionOptions().params(5); - db.transaction("function (params) {return params;}", Integer.class, options) - .whenComplete((result, ex) -> assertThat(result).isEqualTo(5)) - .get(); - } - - @Test - void transactionJsonNode() throws InterruptedException, ExecutionException { - final TransactionOptions options = new TransactionOptions().params(JsonNodeFactory.instance.textNode("test")); - db.transaction("function (params) {return params;}", JsonNode.class, options) - .whenComplete((result, ex) -> { - assertThat(result.isTextual()).isEqualTo(true); - assertThat(result.asText()).isEqualTo("test"); - }) - .get(); - } - - @Test - void transactionEmpty() throws InterruptedException, ExecutionException { - db.transaction("function () {}", Void.class, null).get(); - } - - @Test - void transactionAllowImplicit() throws InterruptedException, ExecutionException { - try { - db.createCollection("someCollection", null).get(); - db.createCollection("someOtherCollection", null).get(); - final String action = "function (params) {" + "var db = require('internal').db;" - + "return {'a':db.someCollection.all().toArray()[0], 'b':db.someOtherCollection.all().toArray()" + - "[0]};" - + "}"; - final TransactionOptions options = new TransactionOptions().readCollections("someCollection"); - db.transaction(action, Void.class, options).get(); - try { - options.allowImplicit(false); - db.transaction(action, Void.class, options).get(); - fail(); - } catch (final ExecutionException e) { - assertThat(e.getCause()).isInstanceOf(ArangoDBException.class); - } - } finally { - db.collection("someCollection").drop().get(); - db.collection("someOtherCollection").drop().get(); - } - } - - @Test - void transactionPojoReturn() throws ExecutionException, InterruptedException { - final String action = "function() { return {'value':'hello world'}; }"; - db.transaction(action, TransactionTestEntity.class, new TransactionOptions()) - .whenComplete((res, ex) -> { - assertThat(res).isNotNull(); - assertThat(res.value).isEqualTo("hello world"); - }) - .get(); - } - - @Test - void getInfo() throws InterruptedException, ExecutionException { - final CompletableFuture f = db.getInfo(); - assertThat(f).isNotNull(); - f.whenComplete((info, ex) -> { - assertThat(info).isNotNull(); - assertThat(info.getId()).isNotNull(); - assertThat(info.getName()).isEqualTo(TEST_DB.get()); - assertThat(info.getPath()).isNotNull(); - assertThat(info.getIsSystem()).isFalse(); - - try { - if (isAtLeastVersion(3, 6) && isCluster()) { - assertThat(info.getSharding()).isNotNull(); - assertThat(info.getWriteConcern()).isNotNull(); - assertThat(info.getReplicationFactor()).isNotNull(); - } - } catch (InterruptedException | ExecutionException e) { - e.printStackTrace(); - fail(); - } - - }); - f.get(); - } - - @Test - void getDocument() throws InterruptedException, ExecutionException { - String collectionName = COLLECTION_NAME + "getDocument"; - db.createCollection(collectionName).get(); - final BaseDocument value = new BaseDocument(UUID.randomUUID().toString()); - value.setKey("123"); - db.collection(collectionName).insertDocument(value).get(); - db.getDocument(collectionName + "/123", BaseDocument.class) - .whenComplete((document, ex) -> { - assertThat(document).isNotNull(); - assertThat(document.getKey()).isEqualTo("123"); - }) - .get(); - db.collection(collectionName).drop().get(); - } - - @Test - void shouldIncludeExceptionMessage() throws InterruptedException, ExecutionException { - final String exceptionMessage = "My error context"; - final String action = "function (params) {" + "throw '" + exceptionMessage + "';" + "}"; - try { - db.transaction(action, Void.class, null).get(); - fail(); - } catch (final ExecutionException e) { - assertThat(e.getCause()).isInstanceOf(ArangoDBException.class); - ArangoDBException cause = ((ArangoDBException) e.getCause()); - assertThat(cause.getErrorNum()).isEqualTo(1650); - if (isAtLeastVersion(3, 4)) { - assertThat(cause.getErrorMessage()).isEqualTo(exceptionMessage); - } - } - } - - @Test - void getDocumentWrongId() { - Throwable thrown = catchThrowable(() -> db.getDocument("123", BaseDocument.class).get()); - assertThat(thrown).isInstanceOf(ArangoDBException.class); - } - - @Test - void reloadRouting() throws InterruptedException, ExecutionException { - db.reloadRouting().get(); - } - - public static class TransactionTestEntity { - private String value; - - public TransactionTestEntity() { - super(); - } - - public String getValue() { - return value; - } - } -} diff --git a/shaded-integration-tests/src/test/native/java/com/arangodb/async/ArangoEdgeCollectionTest.java b/shaded-integration-tests/src/test/native/java/com/arangodb/async/ArangoEdgeCollectionTest.java deleted file mode 100644 index e1b106875..000000000 --- a/shaded-integration-tests/src/test/native/java/com/arangodb/async/ArangoEdgeCollectionTest.java +++ /dev/null @@ -1,367 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.async; - -import com.arangodb.ArangoDBException; -import com.arangodb.entity.*; -import com.arangodb.model.*; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.Test; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.concurrent.ExecutionException; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.fail; - -/** - * @author Mark Vollmary - */ -class ArangoEdgeCollectionTest extends BaseTest { - - private static final String GRAPH_NAME = "db_collection_test"; - private static final String EDGE_COLLECTION_NAME = "db_edge_collection_test"; - private static final String VERTEX_COLLECTION_NAME = "db_vertex_collection_test"; - - @BeforeAll - static void setup() throws InterruptedException, ExecutionException { - if (!db.collection(VERTEX_COLLECTION_NAME).exists().get()) { - db.createCollection(VERTEX_COLLECTION_NAME, null).get(); - } - if (!db.collection(EDGE_COLLECTION_NAME).exists().get()) { - db.createCollection(EDGE_COLLECTION_NAME, new CollectionCreateOptions().type(CollectionType.EDGES)).get(); - } - final Collection edgeDefinitions = new ArrayList<>(); - edgeDefinitions.add(new EdgeDefinition().collection(EDGE_COLLECTION_NAME).from(VERTEX_COLLECTION_NAME) - .to(VERTEX_COLLECTION_NAME)); - db.createGraph(GRAPH_NAME, edgeDefinitions, null).get(); - } - - @AfterEach - void teardown() throws InterruptedException, ExecutionException { - for (final String collection : new String[]{VERTEX_COLLECTION_NAME, EDGE_COLLECTION_NAME}) { - db.collection(collection).truncate().get(); - } - } - - private BaseEdgeDocument createEdgeValue() throws InterruptedException, ExecutionException { - final VertexEntity v1 = db.graph(GRAPH_NAME).vertexCollection(VERTEX_COLLECTION_NAME) - .insertVertex(new BaseDocument(), null).get(); - final VertexEntity v2 = db.graph(GRAPH_NAME).vertexCollection(VERTEX_COLLECTION_NAME) - .insertVertex(new BaseDocument(), null).get(); - - final BaseEdgeDocument value = new BaseEdgeDocument(); - value.setFrom(v1.getId()); - value.setTo(v2.getId()); - return value; - } - - @Test - void insertEdge() throws InterruptedException, ExecutionException { - final BaseEdgeDocument value = createEdgeValue(); - final EdgeEntity edge = db.graph(GRAPH_NAME).edgeCollection(EDGE_COLLECTION_NAME).insertEdge(value, null).get(); - assertThat(edge).isNotNull(); - final BaseEdgeDocument document = db.collection(EDGE_COLLECTION_NAME) - .getDocument(edge.getKey(), BaseEdgeDocument.class, null).get(); - assertThat(document).isNotNull(); - assertThat(document.getKey()).isEqualTo(edge.getKey()); - } - - @Test - void getEdge() throws InterruptedException, ExecutionException { - final BaseEdgeDocument value = createEdgeValue(); - final EdgeEntity edge = db.graph(GRAPH_NAME).edgeCollection(EDGE_COLLECTION_NAME).insertEdge(value, null).get(); - final BaseDocument document = db.graph(GRAPH_NAME).edgeCollection(EDGE_COLLECTION_NAME) - .getEdge(edge.getKey(), BaseDocument.class, null).get(); - assertThat(document).isNotNull(); - assertThat(document.getKey()).isEqualTo(edge.getKey()); - } - - @Test - void getEdgeIfMatch() throws InterruptedException, ExecutionException { - final BaseEdgeDocument value = createEdgeValue(); - final EdgeEntity edge = db.graph(GRAPH_NAME).edgeCollection(EDGE_COLLECTION_NAME).insertEdge(value, null).get(); - final GraphDocumentReadOptions options = new GraphDocumentReadOptions().ifMatch(edge.getRev()); - final BaseDocument document = db.graph(GRAPH_NAME).edgeCollection(EDGE_COLLECTION_NAME) - .getEdge(edge.getKey(), BaseDocument.class, options).get(); - assertThat(document).isNotNull(); - assertThat(document.getKey()).isEqualTo(edge.getKey()); - } - - @Test - void getEdgeIfMatchFail() throws InterruptedException, ExecutionException { - final BaseEdgeDocument value = createEdgeValue(); - final EdgeEntity edge = db.graph(GRAPH_NAME).edgeCollection(EDGE_COLLECTION_NAME).insertEdge(value, null).get(); - final GraphDocumentReadOptions options = new GraphDocumentReadOptions().ifMatch("no"); - BaseEdgeDocument doc = db.graph(GRAPH_NAME).edgeCollection(EDGE_COLLECTION_NAME) - .getEdge(edge.getKey(), BaseEdgeDocument.class, options).get(); - assertThat(doc).isNull(); - } - - @Test - void getEdgeIfNoneMatch() throws InterruptedException, ExecutionException { - final BaseEdgeDocument value = createEdgeValue(); - final EdgeEntity edge = db.graph(GRAPH_NAME).edgeCollection(EDGE_COLLECTION_NAME).insertEdge(value, null).get(); - final GraphDocumentReadOptions options = new GraphDocumentReadOptions().ifNoneMatch("no"); - final BaseDocument document = db.graph(GRAPH_NAME).edgeCollection(EDGE_COLLECTION_NAME) - .getEdge(edge.getKey(), BaseDocument.class, options).get(); - assertThat(document).isNotNull(); - assertThat(document.getKey()).isEqualTo(edge.getKey()); - } - - @Test - void getEdgeIfNoneMatchFail() throws InterruptedException, ExecutionException { - final BaseEdgeDocument value = createEdgeValue(); - final EdgeEntity edge = db.graph(GRAPH_NAME).edgeCollection(EDGE_COLLECTION_NAME).insertEdge(value, null).get(); - final GraphDocumentReadOptions options = new GraphDocumentReadOptions().ifNoneMatch(edge.getRev()); - BaseEdgeDocument doc = db.graph(GRAPH_NAME).edgeCollection(EDGE_COLLECTION_NAME) - .getEdge(edge.getKey(), BaseEdgeDocument.class, options).get(); - assertThat(doc).isNull(); - } - - @Test - void replaceEdge() throws InterruptedException, ExecutionException { - final BaseEdgeDocument doc = createEdgeValue(); - doc.addAttribute("a", "test"); - final EdgeEntity createResult = db.graph(GRAPH_NAME).edgeCollection(EDGE_COLLECTION_NAME).insertEdge(doc, null) - .get(); - doc.removeAttribute("a"); - doc.addAttribute("b", "test"); - final EdgeUpdateEntity replaceResult = db.graph(GRAPH_NAME).edgeCollection(EDGE_COLLECTION_NAME) - .replaceEdge(createResult.getKey(), doc, null).get(); - assertThat(replaceResult).isNotNull(); - assertThat(replaceResult.getId()).isEqualTo(createResult.getId()); - assertThat(replaceResult.getRev()).isNotEqualTo(replaceResult.getOldRev()); - assertThat(replaceResult.getOldRev()).isEqualTo(createResult.getRev()); - - final BaseEdgeDocument readResult = db.graph(GRAPH_NAME).edgeCollection(EDGE_COLLECTION_NAME) - .getEdge(createResult.getKey(), BaseEdgeDocument.class, null).get(); - assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); - assertThat(readResult.getRevision()).isEqualTo(replaceResult.getRev()); - assertThat(readResult.getProperties().keySet()).doesNotContain("a"); - assertThat(readResult.getAttribute("b")).isNotNull(); - assertThat(String.valueOf(readResult.getAttribute("b"))).isEqualTo("test"); - } - - @Test - void replaceEdgeIfMatch() throws InterruptedException, ExecutionException { - final BaseEdgeDocument doc = createEdgeValue(); - doc.addAttribute("a", "test"); - final EdgeEntity createResult = db.graph(GRAPH_NAME).edgeCollection(EDGE_COLLECTION_NAME).insertEdge(doc, null) - .get(); - doc.removeAttribute("a"); - doc.addAttribute("b", "test"); - final EdgeReplaceOptions options = new EdgeReplaceOptions().ifMatch(createResult.getRev()); - final EdgeUpdateEntity replaceResult = db.graph(GRAPH_NAME).edgeCollection(EDGE_COLLECTION_NAME) - .replaceEdge(createResult.getKey(), doc, options).get(); - assertThat(replaceResult).isNotNull(); - assertThat(replaceResult.getId()).isEqualTo(createResult.getId()); - assertThat(replaceResult.getRev()).isNotEqualTo(replaceResult.getOldRev()); - assertThat(replaceResult.getOldRev()).isEqualTo(createResult.getRev()); - - final BaseEdgeDocument readResult = db.graph(GRAPH_NAME).edgeCollection(EDGE_COLLECTION_NAME) - .getEdge(createResult.getKey(), BaseEdgeDocument.class, null).get(); - assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); - assertThat(readResult.getRevision()).isEqualTo(replaceResult.getRev()); - assertThat(readResult.getProperties().keySet()).doesNotContain("a"); - assertThat(readResult.getAttribute("b")).isNotNull(); - assertThat(String.valueOf(readResult.getAttribute("b"))).isEqualTo("test"); - } - - @Test - void replaceEdgeIfMatchFail() throws InterruptedException, ExecutionException { - final BaseEdgeDocument doc = createEdgeValue(); - doc.addAttribute("a", "test"); - final EdgeEntity createResult = db.graph(GRAPH_NAME).edgeCollection(EDGE_COLLECTION_NAME).insertEdge(doc, null) - .get(); - doc.removeAttribute("a"); - doc.addAttribute("b", "test"); - try { - final EdgeReplaceOptions options = new EdgeReplaceOptions().ifMatch("no"); - db.graph(GRAPH_NAME).edgeCollection(EDGE_COLLECTION_NAME).replaceEdge(createResult.getKey(), doc, options) - .get(); - fail(); - } catch (final ExecutionException e) { - assertThat(e.getCause()).isInstanceOf(ArangoDBException.class); - } - } - - @Test - void updateEdge() throws InterruptedException, ExecutionException { - final BaseEdgeDocument doc = createEdgeValue(); - doc.addAttribute("a", "test"); - doc.addAttribute("c", "test"); - final EdgeEntity createResult = db.graph(GRAPH_NAME).edgeCollection(EDGE_COLLECTION_NAME).insertEdge(doc, null) - .get(); - doc.updateAttribute("a", "test1"); - doc.addAttribute("b", "test"); - doc.updateAttribute("c", null); - final EdgeUpdateEntity updateResult = db.graph(GRAPH_NAME).edgeCollection(EDGE_COLLECTION_NAME) - .updateEdge(createResult.getKey(), doc, null).get(); - assertThat(updateResult).isNotNull(); - assertThat(updateResult.getId()).isEqualTo(createResult.getId()); - assertThat(updateResult.getRev()).isNotEqualTo(updateResult.getOldRev()); - assertThat(updateResult.getOldRev()).isEqualTo(createResult.getRev()); - - final BaseEdgeDocument readResult = db.graph(GRAPH_NAME).edgeCollection(EDGE_COLLECTION_NAME) - .getEdge(createResult.getKey(), BaseEdgeDocument.class, null).get(); - assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); - assertThat(readResult.getAttribute("a")).isNotNull(); - assertThat(String.valueOf(readResult.getAttribute("a"))).isEqualTo("test1"); - assertThat(readResult.getAttribute("b")).isNotNull(); - assertThat(String.valueOf(readResult.getAttribute("b"))).isEqualTo("test"); - assertThat(readResult.getRevision()).isEqualTo(updateResult.getRev()); - assertThat(readResult.getProperties()).containsKey("c"); - } - - @Test - void updateEdgeIfMatch() throws InterruptedException, ExecutionException { - final BaseEdgeDocument doc = createEdgeValue(); - doc.addAttribute("a", "test"); - doc.addAttribute("c", "test"); - final EdgeEntity createResult = db.graph(GRAPH_NAME).edgeCollection(EDGE_COLLECTION_NAME).insertEdge(doc, null) - .get(); - doc.updateAttribute("a", "test1"); - doc.addAttribute("b", "test"); - doc.updateAttribute("c", null); - final EdgeUpdateOptions options = new EdgeUpdateOptions().ifMatch(createResult.getRev()); - final EdgeUpdateEntity updateResult = db.graph(GRAPH_NAME).edgeCollection(EDGE_COLLECTION_NAME) - .updateEdge(createResult.getKey(), doc, options).get(); - assertThat(updateResult).isNotNull(); - assertThat(updateResult.getId()).isEqualTo(createResult.getId()); - assertThat(updateResult.getRev()).isNotEqualTo(updateResult.getOldRev()); - assertThat(updateResult.getOldRev()).isEqualTo(createResult.getRev()); - - final BaseEdgeDocument readResult = db.graph(GRAPH_NAME).edgeCollection(EDGE_COLLECTION_NAME) - .getEdge(createResult.getKey(), BaseEdgeDocument.class, null).get(); - assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); - assertThat(readResult.getAttribute("a")).isNotNull(); - assertThat(String.valueOf(readResult.getAttribute("a"))).isEqualTo("test1"); - assertThat(readResult.getAttribute("b")).isNotNull(); - assertThat(String.valueOf(readResult.getAttribute("b"))).isEqualTo("test"); - assertThat(readResult.getRevision()).isEqualTo(updateResult.getRev()); - assertThat(readResult.getProperties()).containsKey("c"); - } - - @Test - void updateEdgeIfMatchFail() throws InterruptedException, ExecutionException { - final BaseEdgeDocument doc = createEdgeValue(); - doc.addAttribute("a", "test"); - doc.addAttribute("c", "test"); - final EdgeEntity createResult = db.graph(GRAPH_NAME).edgeCollection(EDGE_COLLECTION_NAME).insertEdge(doc, null) - .get(); - doc.updateAttribute("a", "test1"); - doc.addAttribute("b", "test"); - doc.updateAttribute("c", null); - try { - final EdgeUpdateOptions options = new EdgeUpdateOptions().ifMatch("no"); - db.graph(GRAPH_NAME).edgeCollection(EDGE_COLLECTION_NAME).updateEdge(createResult.getKey(), doc, options) - .get(); - fail(); - } catch (final ExecutionException e) { - assertThat(e.getCause()).isInstanceOf(ArangoDBException.class); - } - } - - @Test - void updateEdgeKeepNullTrue() throws InterruptedException, ExecutionException { - final BaseEdgeDocument doc = createEdgeValue(); - doc.addAttribute("a", "test"); - final EdgeEntity createResult = db.graph(GRAPH_NAME).edgeCollection(EDGE_COLLECTION_NAME).insertEdge(doc, null) - .get(); - doc.updateAttribute("a", null); - final EdgeUpdateOptions options = new EdgeUpdateOptions().keepNull(true); - final EdgeUpdateEntity updateResult = db.graph(GRAPH_NAME).edgeCollection(EDGE_COLLECTION_NAME) - .updateEdge(createResult.getKey(), doc, options).get(); - assertThat(updateResult).isNotNull(); - assertThat(updateResult.getId()).isEqualTo(createResult.getId()); - assertThat(updateResult.getRev()).isNotEqualTo(updateResult.getOldRev()); - assertThat(updateResult.getOldRev()).isEqualTo(createResult.getRev()); - - final BaseEdgeDocument readResult = db.graph(GRAPH_NAME).edgeCollection(EDGE_COLLECTION_NAME) - .getEdge(createResult.getKey(), BaseEdgeDocument.class, null).get(); - assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); - assertThat(readResult.getProperties().keySet()).hasSize(6); - assertThat(readResult.getProperties()).containsKey("a"); - } - - @Test - void updateEdgeKeepNullFalse() throws InterruptedException, ExecutionException { - final BaseEdgeDocument doc = createEdgeValue(); - doc.addAttribute("a", "test"); - final EdgeEntity createResult = db.graph(GRAPH_NAME).edgeCollection(EDGE_COLLECTION_NAME).insertEdge(doc, null) - .get(); - doc.updateAttribute("a", null); - final EdgeUpdateOptions options = new EdgeUpdateOptions().keepNull(false); - final EdgeUpdateEntity updateResult = db.graph(GRAPH_NAME).edgeCollection(EDGE_COLLECTION_NAME) - .updateEdge(createResult.getKey(), doc, options).get(); - assertThat(updateResult).isNotNull(); - assertThat(updateResult.getId()).isEqualTo(createResult.getId()); - assertThat(updateResult.getRev()).isNotEqualTo(updateResult.getOldRev()); - assertThat(updateResult.getOldRev()).isEqualTo(createResult.getRev()); - - final BaseEdgeDocument readResult = db.graph(GRAPH_NAME).edgeCollection(EDGE_COLLECTION_NAME) - .getEdge(createResult.getKey(), BaseEdgeDocument.class, null).get(); - assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); - assertThat(readResult.getId()).isEqualTo(createResult.getId()); - assertThat(readResult.getRevision()).isNotNull(); - assertThat(readResult.getProperties().keySet()).doesNotContain("a"); - } - - @Test - void deleteEdge() throws InterruptedException, ExecutionException { - final BaseEdgeDocument doc = createEdgeValue(); - final EdgeEntity createResult = db.graph(GRAPH_NAME).edgeCollection(EDGE_COLLECTION_NAME).insertEdge(doc, null) - .get(); - db.graph(GRAPH_NAME).edgeCollection(EDGE_COLLECTION_NAME).deleteEdge(createResult.getKey(), null).get(); - BaseEdgeDocument res = db.graph(GRAPH_NAME).edgeCollection(EDGE_COLLECTION_NAME) - .getEdge(createResult.getKey(), BaseEdgeDocument.class, new GraphDocumentReadOptions()).get(); - assertThat(res).isNull(); - } - - @Test - void deleteEdgeIfMatch() throws InterruptedException, ExecutionException { - final BaseEdgeDocument doc = createEdgeValue(); - final EdgeEntity createResult = db.graph(GRAPH_NAME).edgeCollection(EDGE_COLLECTION_NAME).insertEdge(doc, null) - .get(); - final EdgeDeleteOptions options = new EdgeDeleteOptions().ifMatch(createResult.getRev()); - db.graph(GRAPH_NAME).edgeCollection(EDGE_COLLECTION_NAME).deleteEdge(createResult.getKey(), options).get(); - BaseEdgeDocument res = db.graph(GRAPH_NAME).edgeCollection(EDGE_COLLECTION_NAME) - .getEdge(createResult.getKey(), BaseEdgeDocument.class, new GraphDocumentReadOptions()).get(); - assertThat(res).isNull(); - } - - @Test - void deleteEdgeIfMatchFail() throws InterruptedException, ExecutionException { - final BaseEdgeDocument doc = createEdgeValue(); - final EdgeEntity createResult = db.graph(GRAPH_NAME).edgeCollection(EDGE_COLLECTION_NAME).insertEdge(doc, null) - .get(); - final EdgeDeleteOptions options = new EdgeDeleteOptions().ifMatch("no"); - try { - db.graph(GRAPH_NAME).edgeCollection(EDGE_COLLECTION_NAME).deleteEdge(createResult.getKey(), options).get(); - fail(); - } catch (final ExecutionException e) { - assertThat(e.getCause()).isInstanceOf(ArangoDBException.class); - } - } -} diff --git a/shaded-integration-tests/src/test/native/java/com/arangodb/async/ArangoGraphTest.java b/shaded-integration-tests/src/test/native/java/com/arangodb/async/ArangoGraphTest.java deleted file mode 100644 index beed0bf10..000000000 --- a/shaded-integration-tests/src/test/native/java/com/arangodb/async/ArangoGraphTest.java +++ /dev/null @@ -1,387 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.async; - -import com.arangodb.entity.*; -import com.arangodb.model.GraphCreateOptions; -import com.arangodb.model.VertexCollectionCreateOptions; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.Test; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.Iterator; -import java.util.concurrent.ExecutionException; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assumptions.assumeTrue; - -/** - * @author Mark Vollmary - */ -class ArangoGraphTest extends BaseTest { - - private static final String GRAPH_NAME = "db_collection_test"; - private static final String EDGE_COL_1 = "db_edge1_collection_test"; - private static final String EDGE_COL_2 = "db_edge2_collection_test"; - private static final String EDGE_COL_3 = "db_edge3_collection_test"; - private static final String VERTEX_COL_1 = "db_vertex1_collection_test"; - private static final String VERTEX_COL_2 = "db_vertex2_collection_test"; - private static final String VERTEX_COL_3 = "db_vertex3_collection_test"; - private static final String VERTEX_COL_4 = "db_vertex4_collection_test"; - private static final Integer REPLICATION_FACTOR = 2; - private static final Integer NUMBER_OF_SHARDS = 2; - - @BeforeAll - static void setup() throws InterruptedException, ExecutionException { - if (db.graph(GRAPH_NAME).exists().get()) { - db.graph(GRAPH_NAME).drop().get(); - } - final Collection edgeDefinitions = new ArrayList<>(); - edgeDefinitions.add(new EdgeDefinition().collection(EDGE_COL_1).from(VERTEX_COL_1).to(VERTEX_COL_2)); - edgeDefinitions - .add(new EdgeDefinition().collection(EDGE_COL_2).from(VERTEX_COL_2).to(VERTEX_COL_1, VERTEX_COL_3)); - final GraphCreateOptions options = new GraphCreateOptions(); - if (arangoDB.getRole().get() != ServerRole.SINGLE) { - options.replicationFactor(REPLICATION_FACTOR).numberOfShards(NUMBER_OF_SHARDS); - } - db.createGraph(GRAPH_NAME, edgeDefinitions, options).get(); - } - - @AfterEach - void teardown() throws InterruptedException, ExecutionException { - for (final String collection : new String[]{EDGE_COL_1, EDGE_COL_2, VERTEX_COL_1, VERTEX_COL_2, VERTEX_COL_3, - VERTEX_COL_4}) { - final ArangoCollectionAsync c = db.collection(collection); - if (c.exists().get()) { - c.truncate().get(); - } - } - } - - @Test - void create() throws InterruptedException, ExecutionException { - try { - final GraphEntity result = db.graph(GRAPH_NAME + "_1").create(null).get(); - assertThat(result).isNotNull(); - assertThat(result.getName()).isEqualTo(GRAPH_NAME + "_1"); - } finally { - db.graph(GRAPH_NAME + "_1").drop().get(); - } - } - - @Test - void createWithReplicationAndWriteConcern() throws ExecutionException, InterruptedException { - assumeTrue(isAtLeastVersion(3, 5)); - assumeTrue(isCluster()); - final Collection edgeDefinitions = new ArrayList<>(); - final GraphEntity graph = db.createGraph(GRAPH_NAME + "_1", edgeDefinitions, - new GraphCreateOptions().isSmart(true).replicationFactor(2).writeConcern(2)).get(); - assertThat(graph).isNotNull(); - assertThat(graph.getName()).isEqualTo(GRAPH_NAME + "_1"); - assertThat(graph.getWriteConcern()).isEqualTo(2); - assertThat(graph.getReplicationFactor().getValue()).isEqualTo(2); - db.graph(GRAPH_NAME + "_1").drop(); - } - - @Test - void getGraphs() throws InterruptedException, ExecutionException { - final Collection graphs = db.getGraphs().get(); - assertThat(graphs).isNotNull(); - assertThat(graphs).isNotEmpty(); - } - - @Test - void getInfo() throws InterruptedException, ExecutionException { - final GraphEntity info = db.graph(GRAPH_NAME).getInfo().get(); - assertThat(info).isNotNull(); - assertThat(info.getName()).isEqualTo(GRAPH_NAME); - assertThat(info.getEdgeDefinitions()).hasSize(2); - final Iterator iterator = info.getEdgeDefinitions().iterator(); - final EdgeDefinition e1 = iterator.next(); - assertThat(e1.getCollection()).isEqualTo(EDGE_COL_1); - assertThat(e1.getFrom()).contains(VERTEX_COL_1); - assertThat(e1.getTo()).contains(VERTEX_COL_2); - final EdgeDefinition e2 = iterator.next(); - assertThat(e2.getCollection()).isEqualTo(EDGE_COL_2); - assertThat(e2.getFrom()).contains(VERTEX_COL_2); - assertThat(e2.getTo()).contains(VERTEX_COL_1, VERTEX_COL_3); - assertThat(info.getOrphanCollections()).isEmpty(); - - if (isCluster()) { - for (final String collection : new String[]{VERTEX_COL_1, VERTEX_COL_2}) { - final CollectionPropertiesEntity properties = db.collection(collection).getProperties().get(); - assertThat(properties.getReplicationFactor().getValue()).isEqualTo(REPLICATION_FACTOR); - assertThat(properties.getNumberOfShards()).isEqualTo(NUMBER_OF_SHARDS); - } - for (final String collection : new String[]{EDGE_COL_1, EDGE_COL_2}) { - final CollectionPropertiesEntity properties = db.collection(collection).getProperties().get(); - assertThat(properties.getReplicationFactor().getValue()).isEqualTo(REPLICATION_FACTOR); - } - } - } - - @Test - void getVertexCollections() throws InterruptedException, ExecutionException { - final Collection vertexCollections = db.graph(GRAPH_NAME).getVertexCollections().get(); - assertThat(vertexCollections).isNotNull(); - assertThat(vertexCollections).hasSize(3); - assertThat(vertexCollections).contains(VERTEX_COL_1, VERTEX_COL_2, VERTEX_COL_3); - } - - @Test - void addVertexCollection() throws InterruptedException, ExecutionException { - final GraphEntity graph = db.graph(GRAPH_NAME).addVertexCollection(VERTEX_COL_4).get(); - assertThat(graph).isNotNull(); - final Collection vertexCollections = db.graph(GRAPH_NAME).getVertexCollections().get(); - assertThat(vertexCollections).contains(VERTEX_COL_1, VERTEX_COL_2, VERTEX_COL_3, VERTEX_COL_4); - setup(); - } - - @Test - 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(null, new GraphCreateOptions().isSmart(true).smartGraphAttribute("test")).get(); - g.addVertexCollection(v1Name, new VertexCollectionCreateOptions().satellites(v1Name)).get(); - - Collection vertexCollections = g.getVertexCollections().get(); - assertThat(vertexCollections).contains(v1Name); - assertThat(db.collection(v1Name).getProperties().get().getReplicationFactor()).isEqualTo(ReplicationFactor.ofSatellite()); - - // revert - g.drop().get(); - } - - @Test - void getEdgeCollections() throws InterruptedException, ExecutionException { - final Collection edgeCollections = db.graph(GRAPH_NAME).getEdgeDefinitions().get(); - assertThat(edgeCollections).isNotNull(); - assertThat(edgeCollections).hasSize(2); - assertThat(edgeCollections).contains(EDGE_COL_1, EDGE_COL_2); - } - - @Test - void addEdgeDefinition() throws InterruptedException, ExecutionException { - final GraphEntity graph = db.graph(GRAPH_NAME) - .addEdgeDefinition(new EdgeDefinition().collection(EDGE_COL_3).from(VERTEX_COL_1).to(VERTEX_COL_2)) - .get(); - assertThat(graph).isNotNull(); - final Collection edgeDefinitions = graph.getEdgeDefinitions(); - assertThat(edgeDefinitions).hasSize(3); - int count = 0; - for (final EdgeDefinition e : edgeDefinitions) { - if (e.getCollection().equals(EDGE_COL_3)) { - count++; - } - } - assertThat(count).isEqualTo(1); - for (final EdgeDefinition e : edgeDefinitions) { - if (e.getCollection().equals(EDGE_COL_3)) { - assertThat(e.getFrom()).contains(VERTEX_COL_1); - assertThat(e.getTo()).contains(VERTEX_COL_2); - } - } - if (isCluster()) { - final CollectionPropertiesEntity properties = db.collection(EDGE_COL_3).getProperties().get(); - assertThat(properties.getReplicationFactor().getValue()).isEqualTo(REPLICATION_FACTOR); - assertThat(properties.getNumberOfShards()).isEqualTo(NUMBER_OF_SHARDS); - } - setup(); - } - - @Test - 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(null, new GraphCreateOptions().isSmart(true).smartGraphAttribute("test")).get(); - g.addEdgeDefinition(ed).get(); - final GraphEntity ge = g.getInfo().get(); - assertThat(ge).isNotNull(); - final Collection edgeDefinitions = ge.getEdgeDefinitions(); - assertThat(edgeDefinitions).hasSize(1); - EdgeDefinition e = edgeDefinitions.iterator().next(); - assertThat(e.getCollection()).isEqualTo(eName); - assertThat(e.getFrom()).contains(v1Name); - assertThat(e.getTo()).contains(v2Name); - - assertThat(db.collection(v1Name).getProperties().get().getReplicationFactor()).isEqualTo(ReplicationFactor.ofSatellite()); - - // revert - g.drop().get(); - } - - @Test - void replaceEdgeDefinition() throws InterruptedException, ExecutionException { - final GraphEntity graph = db.graph(GRAPH_NAME) - .replaceEdgeDefinition(new EdgeDefinition().collection(EDGE_COL_1).from(VERTEX_COL_3).to(VERTEX_COL_4)) - .get(); - final Collection edgeDefinitions = graph.getEdgeDefinitions(); - assertThat(edgeDefinitions).hasSize(2); - int count = 0; - for (final EdgeDefinition e : edgeDefinitions) { - if (e.getCollection().equals(EDGE_COL_1)) { - count++; - } - } - assertThat(count).isEqualTo(1); - for (final EdgeDefinition e : edgeDefinitions) { - if (e.getCollection().equals(EDGE_COL_1)) { - assertThat(e.getFrom()).contains(VERTEX_COL_3); - assertThat(e.getTo()).contains(VERTEX_COL_4); - } - } - setup(); - } - - @Test - void removeEdgeDefinition() throws InterruptedException, ExecutionException { - final GraphEntity graph = db.graph(GRAPH_NAME).removeEdgeDefinition(EDGE_COL_1).get(); - final Collection edgeDefinitions = graph.getEdgeDefinitions(); - assertThat(edgeDefinitions).hasSize(1); - assertThat(edgeDefinitions.iterator().next().getCollection()).isEqualTo(EDGE_COL_2); - setup(); - } - - @Test - void smartGraph() throws InterruptedException, ExecutionException { - assumeTrue(isCluster()); - assumeTrue(isEnterprise()); - for (final String collection : new String[]{EDGE_COL_1, EDGE_COL_2, VERTEX_COL_1, VERTEX_COL_2, - VERTEX_COL_3, VERTEX_COL_4}) { - if (db.collection(collection).exists().get()) { - db.collection(collection).drop().get(); - } - } - final Collection edgeDefinitions = new ArrayList<>(); - edgeDefinitions.add(new EdgeDefinition().collection(EDGE_COL_1).from(VERTEX_COL_1).to(VERTEX_COL_2)); - 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)) - .get(); - assertThat(graph).isNotNull(); - assertThat(graph.getIsSmart()).isTrue(); - assertThat(graph.getSmartGraphAttribute()).isEqualTo("test"); - assertThat(graph.getNumberOfShards()).isEqualTo(2); - if (db.graph(GRAPH_NAME + "_smart").exists().get()) { - db.graph(GRAPH_NAME + "_smart").drop().get(); - } - } - - @Test - 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).isNotNull(); - assertThat(g.getIsSmart()).isTrue(); - assertThat(g.getSmartGraphAttribute()).isEqualTo("test"); - assertThat(g.getNumberOfShards()).isEqualTo(2); - - assertThat(db.collection(eName).getProperties().get().getReplicationFactor()).isEqualTo(ReplicationFactor.ofSatellite()); - assertThat(db.collection(v1Name).getProperties().get().getReplicationFactor()).isEqualTo(ReplicationFactor.ofSatellite()); - assertThat(db.collection(v2Name).getProperties().get().getReplicationFactor().getValue()).isEqualTo(2); - } - - @Test - 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).isNotNull(); - assertThat(g.getIsSmart()).isTrue(); - assertThat(g.getIsDisjoint()).isTrue(); - assertThat(g.getSmartGraphAttribute()).isEqualTo("test"); - assertThat(g.getNumberOfShards()).isEqualTo(2); - - assertThat(db.collection(v1Name).getProperties().get().getReplicationFactor()).isEqualTo(ReplicationFactor.ofSatellite()); - assertThat(db.collection(v2Name).getProperties().get().getReplicationFactor().getValue()).isEqualTo(2); - } - - @Test - 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))) - .get(); - assertThat(result).isNotNull(); - db.graph(graph).drop().get(); - assertThat(db.collection(edgeCollection).exists().get()).isTrue(); - assertThat(db.collection(vertexCollection).exists().get()).isTrue(); - } - - @Test - void dropPlusDropCollections() throws InterruptedException, ExecutionException { - final String edgeCollection = "edge_dropC"; - 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))) - .get(); - assertThat(result).isNotNull(); - db.graph(graph).drop(true).get(); - assertThat(db.collection(edgeCollection).exists().get()).isFalse(); - assertThat(db.collection(vertexCollection).exists().get()).isFalse(); - } -} diff --git a/shaded-integration-tests/src/test/native/java/com/arangodb/async/ArangoRouteTest.java b/shaded-integration-tests/src/test/native/java/com/arangodb/async/ArangoRouteTest.java deleted file mode 100644 index 772e593f5..000000000 --- a/shaded-integration-tests/src/test/native/java/com/arangodb/async/ArangoRouteTest.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2018 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.async; - -import com.arangodb.ArangoDBException; -import com.arangodb.entity.BaseDocument; -import com.arangodb.internal.ArangoRequestParam; -import org.junit.jupiter.api.Test; - -import java.util.UUID; -import java.util.concurrent.ExecutionException; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.fail; - -/** - * @author Mark Vollmary - */ -class ArangoRouteTest extends BaseTest { - - /* - @Test - void get() throws InterruptedException, ExecutionException { - final Response res = db.route("/_api/version").get().get(); - assertThat(res.getBody().get("version").isString()).isEqualTo(true); - }*/ - - /* - @Test - void withHeader() throws InterruptedException, ExecutionException { - final ArangoCollectionAsync collection = db.collection("route-test-col"); - try { - collection.create(); - final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); - collection.insertDocument(doc).get(); - db.route("/_api/document", doc.getId()).withHeader(ArangoRequestParam.IF_NONE_MATCH, doc.getRevision()) - .get().get(); - fail(); - } catch (final ExecutionException e) { - assertThat(e.getCause() instanceof ArangoDBException).isEqualTo(true); - } finally { - collection.drop(); - } - } - */ - - @Test - void withParentHeader() throws InterruptedException, ExecutionException { - final ArangoCollectionAsync collection = db.collection("route-test-col"); - try { - collection.create().get(); - final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); - collection.insertDocument(doc).get(); - db.route("/_api/document").withHeader(ArangoRequestParam.IF_NONE_MATCH, doc.getRevision()) - .route(doc.getId()).get().get(); - fail(); - } catch (final ExecutionException e) { - assertThat(e.getCause()).isInstanceOf(ArangoDBException.class); - } - collection.drop().get(); - } - -} diff --git a/shaded-integration-tests/src/test/native/java/com/arangodb/async/ArangoSearchTest.java b/shaded-integration-tests/src/test/native/java/com/arangodb/async/ArangoSearchTest.java deleted file mode 100644 index 84dc1ba01..000000000 --- a/shaded-integration-tests/src/test/native/java/com/arangodb/async/ArangoSearchTest.java +++ /dev/null @@ -1,551 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2018 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.async; - -import com.arangodb.ArangoDBException; -import com.arangodb.entity.InvertedIndexField; -import com.arangodb.entity.ViewEntity; -import com.arangodb.entity.ViewType; -import com.arangodb.entity.arangosearch.*; -import com.arangodb.entity.arangosearch.analyzer.*; -import com.arangodb.model.InvertedIndexOptions; -import com.arangodb.model.arangosearch.*; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.Test; - -import java.util.Collection; -import java.util.HashSet; -import java.util.Set; -import java.util.UUID; -import java.util.concurrent.ExecutionException; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.fail; -import static org.junit.jupiter.api.Assumptions.assumeTrue; - -/** - * @author Mark Vollmary - */ - -class ArangoSearchTest extends BaseTest { - - private static final String VIEW_NAME = "view_test"; - private static final String COLL_1 = "view_update_prop_test_collection"; - private static final String COLL_2 = "view_replace_prop_test_collection"; - - @BeforeAll - static void setup() throws InterruptedException, ExecutionException { - if (!isAtLeastVersion(arangoDB, 3, 4)) - return; - db.createArangoSearch(VIEW_NAME, new ArangoSearchCreateOptions()).get(); - db.createCollection(COLL_1).get(); - db.createCollection(COLL_2).get(); - } - - @Test - void exists() throws InterruptedException, ExecutionException { - assumeTrue(isAtLeastVersion(3, 4)); - assertThat(db.arangoSearch(VIEW_NAME).exists().get()).isTrue(); - } - - @Test - void createAndExistsSearchAlias() throws ExecutionException, InterruptedException { - assumeTrue(isAtLeastVersion(3, 10)); - String viewName = "view-" + rnd(); - db.createSearchAlias(viewName, new SearchAliasCreateOptions()).get(); - assertThat(db.arangoSearch(viewName).exists().get()).isTrue(); - } - - @Test - void getInfo() throws InterruptedException, ExecutionException { - assumeTrue(isAtLeastVersion(3, 4)); - final ViewEntity info = db.arangoSearch(VIEW_NAME).getInfo().get(); - assertThat(info).isNotNull(); - assertThat(info.getId()).isNotNull(); - assertThat(info.getName()).isEqualTo(VIEW_NAME); - assertThat(info.getType()).isEqualTo(ViewType.ARANGO_SEARCH); - } - - @Test - void drop() throws InterruptedException, ExecutionException { - assumeTrue(isAtLeastVersion(3, 4)); - final String name = VIEW_NAME + "_droptest"; - db.createArangoSearch(name, new ArangoSearchCreateOptions()).get(); - final ArangoViewAsync view = db.arangoSearch(name); - view.drop().get(); - assertThat(view.exists().get()).isFalse(); - } - - @Test - void rename() throws InterruptedException, ExecutionException { - assumeTrue(isSingleServer()); - assumeTrue(isAtLeastVersion(3, 4)); - final String name = VIEW_NAME + "_renametest"; - final String newName = name + "_new"; - db.createArangoSearch(name, new ArangoSearchCreateOptions()).get(); - db.arangoSearch(name).rename(newName).get(); - assertThat(db.arangoSearch(name).exists().get()).isFalse(); - assertThat(db.arangoSearch(newName).exists().get()).isTrue(); - } - - @Test - void createArangoSearchView() throws InterruptedException, ExecutionException { - assumeTrue(isAtLeastVersion(3, 4)); - final String name = VIEW_NAME + "_createtest"; - final ViewEntity info = db.arangoSearch(name).create().get(); - assertThat(info).isNotNull(); - assertThat(info.getId()).isNotNull(); - assertThat(info.getName()).isEqualTo(name); - assertThat(info.getType()).isEqualTo(ViewType.ARANGO_SEARCH); - assertThat(db.arangoSearch(name).exists().get()).isTrue(); - } - - @Test - void createSearchAliasView() throws ExecutionException, InterruptedException { - assumeTrue(isAtLeastVersion(3, 10)); - String viewName = "view-" + rnd(); - final ViewEntity info = db.searchAlias(viewName).create().get(); - assertThat(info).isNotNull(); - assertThat(info.getId()).isNotNull(); - assertThat(info.getName()).isEqualTo(viewName); - assertThat(info.getType()).isEqualTo(ViewType.SEARCH_ALIAS); - assertThat(db.searchAlias(viewName).exists().get()).isTrue(); - } - - @Test - void createArangoSearchViewWithOptions() throws InterruptedException, ExecutionException { - assumeTrue(isAtLeastVersion(3, 4)); - final String name = VIEW_NAME + "_createtest_withotpions"; - final ViewEntity info = db.arangoSearch(name).create(new ArangoSearchCreateOptions()).get(); - assertThat(info).isNotNull(); - assertThat(info.getId()).isNotNull(); - assertThat(info.getName()).isEqualTo(name); - assertThat(info.getType()).isEqualTo(ViewType.ARANGO_SEARCH); - assertThat(db.arangoSearch(name).exists().get()).isTrue(); - } - - @Test - void createArangoSearchViewWithPrimarySort() throws ExecutionException, InterruptedException { - assumeTrue(isAtLeastVersion(3, 5)); - final String name = "createWithPrimarySort"; - final ArangoSearchCreateOptions options = new ArangoSearchCreateOptions(); - - final PrimarySort primarySort = PrimarySort.on("myFieldName"); - primarySort.ascending(true); - options.primarySort(primarySort); - options.consolidationIntervalMsec(666666L); - - final ViewEntity info = db.arangoSearch(name).create(options).get(); - assertThat(info).isNotNull(); - assertThat(info.getId()).isNotNull(); - assertThat(info.getName()).isEqualTo(name); - assertThat(info.getType()).isEqualTo(ViewType.ARANGO_SEARCH); - assertThat(db.arangoSearch(name).exists().get()).isTrue(); - } - - @Test - void createArangoSearchViewWithCommitIntervalMsec() throws ExecutionException, InterruptedException { - assumeTrue(isAtLeastVersion(3, 5)); - final String name = "createWithCommitIntervalMsec"; - final ArangoSearchCreateOptions options = new ArangoSearchCreateOptions(); - options.commitIntervalMsec(666666L); - - final ViewEntity info = db.arangoSearch(name).create(options).get(); - assertThat(info).isNotNull(); - assertThat(info.getId()).isNotNull(); - assertThat(info.getName()).isEqualTo(name); - assertThat(info.getType()).isEqualTo(ViewType.ARANGO_SEARCH); - assertThat(db.arangoSearch(name).exists().get()).isTrue(); - - // check commit interval msec property - final ArangoSearchAsync view = db.arangoSearch(name); - final ArangoSearchPropertiesEntity properties = view.getProperties().get(); - assertThat(properties.getCommitIntervalMsec()).isEqualTo(666666L); - } - - @Test - void createSearchAliasViewWithOptions() throws ExecutionException, InterruptedException { - assumeTrue(isAtLeastVersion(3, 10)); - String viewName = "view-" + rnd(); - final SearchAliasCreateOptions options = new SearchAliasCreateOptions(); - final ViewEntity info = db.searchAlias(viewName).create(options).get(); - assertThat(info).isNotNull(); - assertThat(info.getId()).isNotNull(); - assertThat(info.getName()).isEqualTo(viewName); - assertThat(info.getType()).isEqualTo(ViewType.SEARCH_ALIAS); - assertThat(db.searchAlias(viewName).exists().get()).isTrue(); - } - - @Test - void createSearchAliasViewWithIndexesAndGetProperties() throws ExecutionException, InterruptedException { - assumeTrue(isAtLeastVersion(3, 10)); - ArangoCollectionAsync col = db.collection(COLL_1); - String idxName = "idx-" + rnd(); - col.ensureInvertedIndex(new InvertedIndexOptions() - .name(idxName) - .fields(new InvertedIndexField().name("a" + rnd()))) - .get(); - String viewName = "view-" + rnd(); - final SearchAliasCreateOptions options = new SearchAliasCreateOptions() - .indexes(new SearchAliasIndex(COLL_1, idxName)); - final ViewEntity info = db.searchAlias(viewName).create(options).get(); - assertThat(info).isNotNull(); - assertThat(info.getId()).isNotNull(); - assertThat(info.getName()).isEqualTo(viewName); - assertThat(info.getType()).isEqualTo(ViewType.SEARCH_ALIAS); - - final SearchAliasPropertiesEntity properties = db.searchAlias(viewName).getProperties().get(); - assertThat(properties).isNotNull(); - assertThat(properties.getId()).isNotNull(); - assertThat(properties.getName()).isEqualTo(viewName); - assertThat(properties.getType()).isEqualTo(ViewType.SEARCH_ALIAS); - assertThat(properties.getIndexes()) - .isNotNull() - .isNotEmpty() - .anyMatch(i -> i.getCollection().equals(COLL_1) && i.getIndex().equals(idxName)); - } - - @Test - void getArangoSearchViewProperties() throws InterruptedException, ExecutionException { - assumeTrue(isAtLeastVersion(3, 4)); - final String name = VIEW_NAME + "_getpropertiestest"; - final ArangoSearchAsync view = db.arangoSearch(name); - view.create(new ArangoSearchCreateOptions()).get(); - final ArangoSearchPropertiesEntity properties = view.getProperties().get(); - assertThat(properties).isNotNull(); - assertThat(properties.getId()).isNotNull(); - assertThat(properties.getName()).isEqualTo(name); - assertThat(properties.getType()).isEqualTo(ViewType.ARANGO_SEARCH); - assertThat(properties.getConsolidationIntervalMsec()).isNotNull(); - assertThat(properties.getCleanupIntervalStep()).isNotNull(); - final ConsolidationPolicy consolidate = properties.getConsolidationPolicy(); - assertThat(consolidate).isNotNull(); - final Collection links = properties.getLinks(); - assertThat(links).isEmpty(); - } - - @Test - void updateArangoSearchViewProperties() throws InterruptedException, ExecutionException { - assumeTrue(isAtLeastVersion(3, 4)); - final String name = VIEW_NAME + "_updatepropertiestest"; - final ArangoSearchAsync view = db.arangoSearch(name); - view.create(new ArangoSearchCreateOptions()).get(); - final ArangoSearchPropertiesOptions options = new ArangoSearchPropertiesOptions(); - options.cleanupIntervalStep(15L); - options.consolidationIntervalMsec(65000L); - options.consolidationPolicy(ConsolidationPolicy.of(ConsolidationType.BYTES_ACCUM).threshold(1.)); - options.link( - CollectionLink.on("view_update_prop_test_collection").fields(FieldLink.on("value").analyzers("identity") - .trackListPositions(true).includeAllFields(true).storeValues(StoreValuesType.ID))); - final ArangoSearchPropertiesEntity properties = view.updateProperties(options).get(); - assertThat(properties).isNotNull(); - assertThat(properties.getCleanupIntervalStep()).isEqualTo(15L); - assertThat(properties.getConsolidationIntervalMsec()).isEqualTo(65000L); - final ConsolidationPolicy consolidate = properties.getConsolidationPolicy(); - assertThat(consolidate).isNotNull(); - assertThat(consolidate.getType()).isEqualTo(ConsolidationType.BYTES_ACCUM); - assertThat(consolidate.getThreshold()).isEqualTo(1.); - assertThat(properties.getLinks()).hasSize(1); - final CollectionLink link = properties.getLinks().iterator().next(); - assertThat(link.getName()).isEqualTo("view_update_prop_test_collection"); - assertThat(link.getFields()).hasSize(1); - final FieldLink next = link.getFields().iterator().next(); - assertThat(next.getName()).isEqualTo("value"); - assertThat(next.getIncludeAllFields()).isTrue(); - assertThat(next.getTrackListPositions()).isTrue(); - assertThat(next.getStoreValues()).isEqualTo(StoreValuesType.ID); - } - - @Test - void updateSearchAliasViewWithIndexesAndGetProperties() throws ExecutionException, InterruptedException { - assumeTrue(isAtLeastVersion(3, 10)); - ArangoCollectionAsync col = db.collection(COLL_1); - String idxName = "idx-" + rnd(); - col.ensureInvertedIndex(new InvertedIndexOptions() - .name(idxName) - .fields(new InvertedIndexField().name("a" + rnd()))) - .get(); - ArangoCollectionAsync col2 = db.collection(COLL_2); - String idxName2 = "idx-" + rnd(); - col2.ensureInvertedIndex(new InvertedIndexOptions() - .name(idxName2) - .fields(new InvertedIndexField().name("a" + rnd()))) - .get(); - - String viewName = "view-" + rnd(); - final SearchAliasCreateOptions options = new SearchAliasCreateOptions() - .indexes(new SearchAliasIndex(COLL_1, idxName)); - final ViewEntity info = db.searchAlias(viewName).create(options).get(); - db.searchAlias(viewName).updateProperties(new SearchAliasPropertiesOptions() - .indexes(new SearchAliasIndex(COLL_2, idxName2))).get(); - - assertThat(info).isNotNull(); - assertThat(info.getId()).isNotNull(); - assertThat(info.getName()).isEqualTo(viewName); - assertThat(info.getType()).isEqualTo(ViewType.SEARCH_ALIAS); - - final SearchAliasPropertiesEntity properties = db.searchAlias(viewName).getProperties().get(); - assertThat(properties).isNotNull(); - assertThat(properties.getId()).isNotNull(); - assertThat(properties.getName()).isEqualTo(viewName); - assertThat(properties.getType()).isEqualTo(ViewType.SEARCH_ALIAS); - assertThat(properties.getIndexes()) - .isNotNull() - .isNotEmpty() - .hasSize(2) - .anyMatch(i -> i.getCollection().equals(COLL_1) && i.getIndex().equals(idxName)) - .anyMatch(i -> i.getCollection().equals(COLL_2) && i.getIndex().equals(idxName2)); - } - - @Test - void replaceArangoSearchViewProperties() throws InterruptedException, ExecutionException { - assumeTrue(isAtLeastVersion(3, 4)); - final String name = VIEW_NAME + "_replacepropertiestest"; - final ArangoSearchAsync view = db.arangoSearch(name); - view.create(new ArangoSearchCreateOptions()).get(); - final ArangoSearchPropertiesOptions options = new ArangoSearchPropertiesOptions(); - options.link( - CollectionLink.on("view_replace_prop_test_collection").fields(FieldLink.on("value").analyzers( - "identity"))); - final ArangoSearchPropertiesEntity properties = view.replaceProperties(options).get(); - assertThat(properties).isNotNull(); - assertThat(properties.getLinks()).hasSize(1); - final CollectionLink link = properties.getLinks().iterator().next(); - assertThat(link.getName()).isEqualTo("view_replace_prop_test_collection"); - assertThat(link.getFields()).hasSize(1); - assertThat(link.getFields().iterator().next().getName()).isEqualTo("value"); - } - - @Test - void replaceSearchAliasViewWithIndexesAndGetProperties() throws ExecutionException, InterruptedException { - assumeTrue(isAtLeastVersion(3, 10)); - ArangoCollectionAsync col = db.collection(COLL_1); - String idxName = "idx-" + rnd(); - col.ensureInvertedIndex(new InvertedIndexOptions() - .name(idxName) - .fields(new InvertedIndexField().name("a" + rnd()))) - .get(); - ArangoCollectionAsync col2 = db.collection(COLL_2); - String idxName2 = "idx-" + rnd(); - col2.ensureInvertedIndex(new InvertedIndexOptions() - .name(idxName2) - .fields(new InvertedIndexField().name("a" + rnd()))) - .get(); - - String viewName = "view-" + rnd(); - final SearchAliasCreateOptions options = new SearchAliasCreateOptions() - .indexes(new SearchAliasIndex(COLL_1, idxName)); - final ViewEntity info = db.searchAlias(viewName).create(options).get(); - db.searchAlias(viewName).replaceProperties(new SearchAliasPropertiesOptions() - .indexes(new SearchAliasIndex(COLL_2, idxName2))).get(); - - assertThat(info).isNotNull(); - assertThat(info.getId()).isNotNull(); - assertThat(info.getName()).isEqualTo(viewName); - assertThat(info.getType()).isEqualTo(ViewType.SEARCH_ALIAS); - - final SearchAliasPropertiesEntity properties = db.searchAlias(viewName).getProperties().get(); - assertThat(properties).isNotNull(); - assertThat(properties.getId()).isNotNull(); - assertThat(properties.getName()).isEqualTo(viewName); - assertThat(properties.getType()).isEqualTo(ViewType.SEARCH_ALIAS); - assertThat(properties.getIndexes()) - .isNotNull() - .isNotEmpty() - .hasSize(1) - .anyMatch(i -> i.getCollection().equals(COLL_2) && i.getIndex().equals(idxName2)); - } - - private void createGetAndDeleteTypedAnalyzer(SearchAnalyzer analyzer) throws ExecutionException, - InterruptedException { - - String fullyQualifiedName = db.dbName().get() + "::" + analyzer.getName(); - analyzer.setName(fullyQualifiedName); - - // createAnalyzer - SearchAnalyzer createdAnalyzer = db.createSearchAnalyzer(analyzer).get(); - assertThat(createdAnalyzer).isEqualTo(analyzer); - - // getAnalyzer - SearchAnalyzer gotAnalyzer = db.getSearchAnalyzer(analyzer.getName()).get(); - assertThat(gotAnalyzer).isEqualTo(analyzer); - - // getAnalyzers - SearchAnalyzer foundAnalyzer = - db.getSearchAnalyzers().get().stream().filter(it -> it.getName().equals(fullyQualifiedName)) - .findFirst().get(); - assertThat(foundAnalyzer).isEqualTo(analyzer); - - // deleteAnalyzer - AnalyzerDeleteOptions deleteOptions = new AnalyzerDeleteOptions(); - deleteOptions.setForce(true); - - db.deleteSearchAnalyzer(analyzer.getName(), deleteOptions).get(); - - try { - db.getSearchAnalyzer(analyzer.getName()).get(); - fail("deleted analyzer should not be found!"); - } catch (ExecutionException e) { - assertThat(e.getCause()).isInstanceOf(ArangoDBException.class); - assertThat(((ArangoDBException) e.getCause()).getResponseCode()).isEqualTo(404); - assertThat(((ArangoDBException) e.getCause()).getErrorNum()).isEqualTo(1202); - } - - } - - @Test - void identityAnalyzerTyped() throws ExecutionException, InterruptedException { - assumeTrue(isAtLeastVersion(3, 5)); - - String name = "test-" + UUID.randomUUID(); - - Set features = new HashSet<>(); - features.add(AnalyzerFeature.frequency); - features.add(AnalyzerFeature.norm); - features.add(AnalyzerFeature.position); - - IdentityAnalyzer analyzer = new IdentityAnalyzer(); - analyzer.setFeatures(features); - analyzer.setName(name); - - createGetAndDeleteTypedAnalyzer(analyzer); - } - - @Test - void delimiterAnalyzerTyped() throws ExecutionException, InterruptedException { - assumeTrue(isAtLeastVersion(3, 5)); - - String name = "test-" + UUID.randomUUID(); - - Set features = new HashSet<>(); - features.add(AnalyzerFeature.frequency); - features.add(AnalyzerFeature.norm); - features.add(AnalyzerFeature.position); - - DelimiterAnalyzerProperties properties = new DelimiterAnalyzerProperties(); - properties.setDelimiter("-"); - - DelimiterAnalyzer analyzer = new DelimiterAnalyzer(); - analyzer.setFeatures(features); - analyzer.setName(name); - analyzer.setProperties(properties); - - createGetAndDeleteTypedAnalyzer(analyzer); - } - - @Test - void stemAnalyzerTyped() throws ExecutionException, InterruptedException { - assumeTrue(isAtLeastVersion(3, 5)); - - String name = "test-" + UUID.randomUUID(); - - Set features = new HashSet<>(); - features.add(AnalyzerFeature.frequency); - features.add(AnalyzerFeature.norm); - features.add(AnalyzerFeature.position); - - StemAnalyzerProperties properties = new StemAnalyzerProperties(); - properties.setLocale("ru"); - - StemAnalyzer options = new StemAnalyzer(); - options.setFeatures(features); - options.setName(name); - options.setProperties(properties); - - createGetAndDeleteTypedAnalyzer(options); - } - - @Test - void normAnalyzerTyped() throws ExecutionException, InterruptedException { - assumeTrue(isAtLeastVersion(3, 5)); - - String name = "test-" + UUID.randomUUID(); - - Set features = new HashSet<>(); - features.add(AnalyzerFeature.frequency); - features.add(AnalyzerFeature.norm); - features.add(AnalyzerFeature.position); - - NormAnalyzerProperties properties = new NormAnalyzerProperties(); - properties.setLocale("ru"); - properties.setAnalyzerCase(SearchAnalyzerCase.lower); - properties.setAccent(true); - - NormAnalyzer options = new NormAnalyzer(); - options.setFeatures(features); - options.setName(name); - options.setProperties(properties); - - createGetAndDeleteTypedAnalyzer(options); - } - - @Test - void ngramAnalyzerTyped() throws ExecutionException, InterruptedException { - assumeTrue(isAtLeastVersion(3, 5)); - - String name = "test-" + UUID.randomUUID(); - - Set features = new HashSet<>(); - features.add(AnalyzerFeature.frequency); - features.add(AnalyzerFeature.norm); - features.add(AnalyzerFeature.position); - - NGramAnalyzerProperties properties = new NGramAnalyzerProperties(); - properties.setMax(6L); - properties.setMin(3L); - properties.setPreserveOriginal(true); - - NGramAnalyzer analyzer = new NGramAnalyzer(); - analyzer.setFeatures(features); - analyzer.setName(name); - analyzer.setType(AnalyzerType.ngram); - analyzer.setProperties(properties); - - createGetAndDeleteTypedAnalyzer(analyzer); - } - - @Test - void textAnalyzerTyped() throws ExecutionException, InterruptedException { - assumeTrue(isAtLeastVersion(3, 5)); - - String name = "test-" + UUID.randomUUID(); - - Set features = new HashSet<>(); - features.add(AnalyzerFeature.frequency); - features.add(AnalyzerFeature.norm); - features.add(AnalyzerFeature.position); - - TextAnalyzerProperties properties = new TextAnalyzerProperties(); - properties.setLocale("ru"); - properties.setAnalyzerCase(SearchAnalyzerCase.lower); - properties.setAccent(true); - properties.setStemming(true); - - TextAnalyzer analyzer = new TextAnalyzer(); - analyzer.setFeatures(features); - analyzer.setName(name); - analyzer.setType(AnalyzerType.text); - analyzer.setProperties(properties); - - createGetAndDeleteTypedAnalyzer(analyzer); - } - -} diff --git a/shaded-integration-tests/src/test/native/java/com/arangodb/async/ArangoVertexCollectionTest.java b/shaded-integration-tests/src/test/native/java/com/arangodb/async/ArangoVertexCollectionTest.java deleted file mode 100644 index 4da5b6735..000000000 --- a/shaded-integration-tests/src/test/native/java/com/arangodb/async/ArangoVertexCollectionTest.java +++ /dev/null @@ -1,356 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.async; - -import com.arangodb.ArangoDBException; -import com.arangodb.entity.BaseDocument; -import com.arangodb.entity.VertexEntity; -import com.arangodb.entity.VertexUpdateEntity; -import com.arangodb.model.*; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.Test; - -import java.util.Collection; -import java.util.UUID; -import java.util.concurrent.ExecutionException; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.fail; - -/** - * @author Mark Vollmary - */ -class ArangoVertexCollectionTest extends BaseTest { - - private static final String GRAPH_NAME = "db_collection_test"; - private static final String COLLECTION_NAME = "db_vertex_collection_test"; - - @BeforeAll - static void setup() throws InterruptedException, ExecutionException { - if (!db.collection(COLLECTION_NAME).exists().get()) { - db.createCollection(COLLECTION_NAME, null).get(); - } - final GraphCreateOptions options = new GraphCreateOptions().orphanCollections(COLLECTION_NAME); - db.createGraph(GRAPH_NAME, null, options).get(); - } - - @AfterEach - void teardown() throws InterruptedException, ExecutionException { - db.collection(COLLECTION_NAME).truncate().get(); - } - - @Test - void dropVertexCollection() throws InterruptedException, ExecutionException { - db.graph(GRAPH_NAME).vertexCollection(COLLECTION_NAME).drop().get(); - final Collection vertexCollections = db.graph(GRAPH_NAME).getVertexCollections().get(); - assertThat(vertexCollections).doesNotContain(COLLECTION_NAME); - } - - @Test - void insertVertex() throws InterruptedException, ExecutionException { - final VertexEntity vertex = db.graph(GRAPH_NAME).vertexCollection(COLLECTION_NAME) - .insertVertex(new BaseDocument(), null).get(); - assertThat(vertex).isNotNull(); - final BaseDocument document = db.collection(COLLECTION_NAME) - .getDocument(vertex.getKey(), BaseDocument.class, null).get(); - assertThat(document).isNotNull(); - assertThat(document.getKey()).isEqualTo(vertex.getKey()); - } - - @Test - void getVertex() throws InterruptedException, ExecutionException { - final VertexEntity vertex = db.graph(GRAPH_NAME).vertexCollection(COLLECTION_NAME) - .insertVertex(new BaseDocument(), null).get(); - final BaseDocument document = db.graph(GRAPH_NAME).vertexCollection(COLLECTION_NAME) - .getVertex(vertex.getKey(), BaseDocument.class, null).get(); - assertThat(document).isNotNull(); - assertThat(document.getKey()).isEqualTo(vertex.getKey()); - } - - @Test - void getVertexIfMatch() throws InterruptedException, ExecutionException { - final VertexEntity vertex = db.graph(GRAPH_NAME).vertexCollection(COLLECTION_NAME) - .insertVertex(new BaseDocument(), null).get(); - final GraphDocumentReadOptions options = new GraphDocumentReadOptions().ifMatch(vertex.getRev()); - final BaseDocument document = db.graph(GRAPH_NAME).vertexCollection(COLLECTION_NAME) - .getVertex(vertex.getKey(), BaseDocument.class, options).get(); - assertThat(document).isNotNull(); - assertThat(document.getKey()).isEqualTo(vertex.getKey()); - } - - @Test - void getVertexIfMatchFail() throws InterruptedException, ExecutionException { - final VertexEntity vertex = db.graph(GRAPH_NAME).vertexCollection(COLLECTION_NAME) - .insertVertex(new BaseDocument(), null).get(); - final GraphDocumentReadOptions options = new GraphDocumentReadOptions().ifMatch("no"); - BaseDocument res = db.graph(GRAPH_NAME).vertexCollection(COLLECTION_NAME) - .getVertex(vertex.getKey(), BaseDocument.class, options).get(); - assertThat(res).isNull(); - } - - @Test - void getVertexIfNoneMatch() throws InterruptedException, ExecutionException { - final VertexEntity vertex = db.graph(GRAPH_NAME).vertexCollection(COLLECTION_NAME) - .insertVertex(new BaseDocument(), null).get(); - final GraphDocumentReadOptions options = new GraphDocumentReadOptions().ifNoneMatch("no"); - final BaseDocument document = db.graph(GRAPH_NAME).vertexCollection(COLLECTION_NAME) - .getVertex(vertex.getKey(), BaseDocument.class, options).get(); - assertThat(document).isNotNull(); - assertThat(document.getKey()).isEqualTo(vertex.getKey()); - } - - @Test - void getVertexIfNoneMatchFail() throws InterruptedException, ExecutionException { - final VertexEntity vertex = db.graph(GRAPH_NAME).vertexCollection(COLLECTION_NAME) - .insertVertex(new BaseDocument(), null).get(); - final GraphDocumentReadOptions options = new GraphDocumentReadOptions().ifNoneMatch(vertex.getRev()); - BaseDocument res = db.graph(GRAPH_NAME).vertexCollection(COLLECTION_NAME) - .getVertex(vertex.getKey(), BaseDocument.class, options).get(); - assertThat(res).isNull(); - } - - @Test - void replaceVertex() throws InterruptedException, ExecutionException { - final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); - doc.addAttribute("a", "test"); - final VertexEntity createResult = db.graph(GRAPH_NAME).vertexCollection(COLLECTION_NAME).insertVertex(doc, null) - .get(); - doc.removeAttribute("a"); - doc.addAttribute("b", "test"); - final VertexUpdateEntity replaceResult = db.graph(GRAPH_NAME).vertexCollection(COLLECTION_NAME) - .replaceVertex(createResult.getKey(), doc, null).get(); - assertThat(replaceResult).isNotNull(); - assertThat(replaceResult.getId()).isEqualTo(createResult.getId()); - assertThat(replaceResult.getRev()).isNotEqualTo(replaceResult.getOldRev()); - assertThat(replaceResult.getOldRev()).isEqualTo(createResult.getRev()); - - final BaseDocument readResult = db.graph(GRAPH_NAME).vertexCollection(COLLECTION_NAME) - .getVertex(createResult.getKey(), BaseDocument.class, null).get(); - assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); - assertThat(readResult.getRevision()).isEqualTo(replaceResult.getRev()); - assertThat(readResult.getProperties().keySet()).doesNotContain("a"); - assertThat(readResult.getAttribute("b")).isNotNull(); - assertThat(String.valueOf(readResult.getAttribute("b"))).isEqualTo("test"); - } - - @Test - void replaceVertexIfMatch() throws InterruptedException, ExecutionException { - final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); - doc.addAttribute("a", "test"); - final VertexEntity createResult = db.graph(GRAPH_NAME).vertexCollection(COLLECTION_NAME).insertVertex(doc, null) - .get(); - doc.removeAttribute("a"); - doc.addAttribute("b", "test"); - final VertexReplaceOptions options = new VertexReplaceOptions().ifMatch(createResult.getRev()); - final VertexUpdateEntity replaceResult = db.graph(GRAPH_NAME).vertexCollection(COLLECTION_NAME) - .replaceVertex(createResult.getKey(), doc, options).get(); - assertThat(replaceResult).isNotNull(); - assertThat(replaceResult.getId()).isEqualTo(createResult.getId()); - assertThat(replaceResult.getRev()).isNotEqualTo(replaceResult.getOldRev()); - assertThat(replaceResult.getOldRev()).isEqualTo(createResult.getRev()); - - final BaseDocument readResult = db.graph(GRAPH_NAME).vertexCollection(COLLECTION_NAME) - .getVertex(createResult.getKey(), BaseDocument.class, null).get(); - assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); - assertThat(readResult.getRevision()).isEqualTo(replaceResult.getRev()); - assertThat(readResult.getProperties().keySet()).doesNotContain("a"); - assertThat(readResult.getAttribute("b")).isNotNull(); - assertThat(String.valueOf(readResult.getAttribute("b"))).isEqualTo("test"); - } - - @Test - void replaceVertexIfMatchFail() throws InterruptedException, ExecutionException { - final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); - doc.addAttribute("a", "test"); - final VertexEntity createResult = db.graph(GRAPH_NAME).vertexCollection(COLLECTION_NAME).insertVertex(doc, null) - .get(); - doc.removeAttribute("a"); - doc.addAttribute("b", "test"); - try { - final VertexReplaceOptions options = new VertexReplaceOptions().ifMatch("no"); - db.graph(GRAPH_NAME).vertexCollection(COLLECTION_NAME).replaceVertex(createResult.getKey(), doc, options) - .get(); - fail(); - } catch (final ExecutionException e) { - assertThat(e.getCause()).isInstanceOf(ArangoDBException.class); - } - } - - @Test - void updateVertex() throws InterruptedException, ExecutionException { - final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); - doc.addAttribute("a", "test"); - doc.addAttribute("c", "test"); - final VertexEntity createResult = db.graph(GRAPH_NAME).vertexCollection(COLLECTION_NAME).insertVertex(doc, null) - .get(); - doc.updateAttribute("a", "test1"); - doc.addAttribute("b", "test"); - doc.updateAttribute("c", null); - final VertexUpdateEntity updateResult = db.graph(GRAPH_NAME).vertexCollection(COLLECTION_NAME) - .updateVertex(createResult.getKey(), doc, null).get(); - assertThat(updateResult).isNotNull(); - assertThat(updateResult.getId()).isEqualTo(createResult.getId()); - assertThat(updateResult.getRev()).isNotEqualTo(updateResult.getOldRev()); - assertThat(updateResult.getOldRev()).isEqualTo(createResult.getRev()); - - final BaseDocument readResult = db.graph(GRAPH_NAME).vertexCollection(COLLECTION_NAME) - .getVertex(createResult.getKey(), BaseDocument.class, null).get(); - assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); - assertThat(readResult.getAttribute("a")).isNotNull(); - assertThat(String.valueOf(readResult.getAttribute("a"))).isEqualTo("test1"); - assertThat(readResult.getAttribute("b")).isNotNull(); - assertThat(String.valueOf(readResult.getAttribute("b"))).isEqualTo("test"); - assertThat(readResult.getRevision()).isEqualTo(updateResult.getRev()); - assertThat(readResult.getProperties()).containsKey("c"); - } - - @Test - void updateVertexIfMatch() throws InterruptedException, ExecutionException { - final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); - doc.addAttribute("a", "test"); - doc.addAttribute("c", "test"); - final VertexEntity createResult = db.graph(GRAPH_NAME).vertexCollection(COLLECTION_NAME).insertVertex(doc, null) - .get(); - doc.updateAttribute("a", "test1"); - doc.addAttribute("b", "test"); - doc.updateAttribute("c", null); - final VertexUpdateOptions options = new VertexUpdateOptions().ifMatch(createResult.getRev()); - final VertexUpdateEntity updateResult = db.graph(GRAPH_NAME).vertexCollection(COLLECTION_NAME) - .updateVertex(createResult.getKey(), doc, options).get(); - assertThat(updateResult).isNotNull(); - assertThat(updateResult.getId()).isEqualTo(createResult.getId()); - assertThat(updateResult.getRev()).isNotEqualTo(updateResult.getOldRev()); - assertThat(updateResult.getOldRev()).isEqualTo(createResult.getRev()); - - final BaseDocument readResult = db.graph(GRAPH_NAME).vertexCollection(COLLECTION_NAME) - .getVertex(createResult.getKey(), BaseDocument.class, null).get(); - assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); - assertThat(readResult.getAttribute("a")).isNotNull(); - assertThat(String.valueOf(readResult.getAttribute("a"))).isEqualTo("test1"); - assertThat(readResult.getAttribute("b")).isNotNull(); - assertThat(String.valueOf(readResult.getAttribute("b"))).isEqualTo("test"); - assertThat(readResult.getRevision()).isEqualTo(updateResult.getRev()); - assertThat(readResult.getProperties()).containsKey("c"); - } - - @Test - void updateVertexIfMatchFail() throws InterruptedException, ExecutionException { - final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); - doc.addAttribute("a", "test"); - doc.addAttribute("c", "test"); - final VertexEntity createResult = db.graph(GRAPH_NAME).vertexCollection(COLLECTION_NAME).insertVertex(doc, null) - .get(); - doc.updateAttribute("a", "test1"); - doc.addAttribute("b", "test"); - doc.updateAttribute("c", null); - try { - final VertexUpdateOptions options = new VertexUpdateOptions().ifMatch("no"); - db.graph(GRAPH_NAME).vertexCollection(COLLECTION_NAME).updateVertex(createResult.getKey(), doc, options) - .get(); - fail(); - } catch (final ExecutionException e) { - assertThat(e.getCause()).isInstanceOf(ArangoDBException.class); - } - } - - @Test - void updateVertexKeepNullTrue() throws InterruptedException, ExecutionException { - final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); - doc.addAttribute("a", "test"); - final VertexEntity createResult = db.graph(GRAPH_NAME).vertexCollection(COLLECTION_NAME).insertVertex(doc, null) - .get(); - doc.updateAttribute("a", null); - final VertexUpdateOptions options = new VertexUpdateOptions().keepNull(true); - final VertexUpdateEntity updateResult = db.graph(GRAPH_NAME).vertexCollection(COLLECTION_NAME) - .updateVertex(createResult.getKey(), doc, options).get(); - assertThat(updateResult).isNotNull(); - assertThat(updateResult.getId()).isEqualTo(createResult.getId()); - assertThat(updateResult.getRev()).isNotEqualTo(updateResult.getOldRev()); - assertThat(updateResult.getOldRev()).isEqualTo(createResult.getRev()); - - final BaseDocument readResult = db.graph(GRAPH_NAME).vertexCollection(COLLECTION_NAME) - .getVertex(createResult.getKey(), BaseDocument.class, null).get(); - assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); - assertThat(readResult.getProperties().keySet()).hasSize(4); - assertThat(readResult.getProperties()).containsKey("a"); - } - - @Test - void updateVertexKeepNullFalse() throws InterruptedException, ExecutionException { - final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); - doc.addAttribute("a", "test"); - final VertexEntity createResult = db.graph(GRAPH_NAME).vertexCollection(COLLECTION_NAME).insertVertex(doc, null) - .get(); - doc.updateAttribute("a", null); - final VertexUpdateOptions options = new VertexUpdateOptions().keepNull(false); - final VertexUpdateEntity updateResult = db.graph(GRAPH_NAME).vertexCollection(COLLECTION_NAME) - .updateVertex(createResult.getKey(), doc, options).get(); - assertThat(updateResult).isNotNull(); - assertThat(updateResult.getId()).isEqualTo(createResult.getId()); - assertThat(updateResult.getRev()).isNotEqualTo(updateResult.getOldRev()); - assertThat(updateResult.getOldRev()).isEqualTo(createResult.getRev()); - - final BaseDocument readResult = db.graph(GRAPH_NAME).vertexCollection(COLLECTION_NAME) - .getVertex(createResult.getKey(), BaseDocument.class, null).get(); - assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); - assertThat(readResult.getId()).isEqualTo(createResult.getId()); - assertThat(readResult.getRevision()).isNotNull(); - assertThat(readResult.getProperties().keySet()).doesNotContain("a"); - } - - @Test - void deleteVertex() throws InterruptedException, ExecutionException { - final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); - final VertexEntity createResult = db.graph(GRAPH_NAME).vertexCollection(COLLECTION_NAME).insertVertex(doc, null) - .get(); - db.graph(GRAPH_NAME).vertexCollection(COLLECTION_NAME).deleteVertex(createResult.getKey(), null).get(); - BaseDocument res = db.graph(GRAPH_NAME).vertexCollection(COLLECTION_NAME) - .getVertex(createResult.getKey(), BaseDocument.class, new GraphDocumentReadOptions()).get(); - assertThat(res).isNull(); - } - - @Test - void deleteVertexIfMatch() throws InterruptedException, ExecutionException { - final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); - final VertexEntity createResult = db.graph(GRAPH_NAME).vertexCollection(COLLECTION_NAME).insertVertex(doc, null) - .get(); - final VertexDeleteOptions options = new VertexDeleteOptions().ifMatch(createResult.getRev()); - db.graph(GRAPH_NAME).vertexCollection(COLLECTION_NAME).deleteVertex(createResult.getKey(), options).get(); - BaseDocument res = db.graph(GRAPH_NAME).vertexCollection(COLLECTION_NAME) - .getVertex(createResult.getKey(), BaseDocument.class, new GraphDocumentReadOptions()).get(); - assertThat(res).isNull(); - } - - @Test - void deleteVertexIfMatchFail() throws InterruptedException, ExecutionException { - final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); - final VertexEntity createResult = db.graph(GRAPH_NAME).vertexCollection(COLLECTION_NAME).insertVertex(doc, null) - .get(); - final VertexDeleteOptions options = new VertexDeleteOptions().ifMatch("no"); - try { - db.graph(GRAPH_NAME).vertexCollection(COLLECTION_NAME).deleteVertex(createResult.getKey(), options).get(); - fail(); - } catch (final ExecutionException e) { - assertThat(e.getCause()).isInstanceOf(ArangoDBException.class); - } - } -} diff --git a/shaded-integration-tests/src/test/native/java/com/arangodb/async/ArangoViewTest.java b/shaded-integration-tests/src/test/native/java/com/arangodb/async/ArangoViewTest.java deleted file mode 100644 index 8bc81b238..000000000 --- a/shaded-integration-tests/src/test/native/java/com/arangodb/async/ArangoViewTest.java +++ /dev/null @@ -1,86 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2018 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.async; - -import com.arangodb.entity.ViewEntity; -import com.arangodb.entity.ViewType; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.Test; - -import java.util.concurrent.ExecutionException; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assumptions.assumeTrue; - -/** - * @author Mark Vollmary - */ - -class ArangoViewTest extends BaseTest { - - private static final String VIEW_NAME = "view_test"; - - @BeforeAll - static void setup() throws InterruptedException, ExecutionException { - if (!isAtLeastVersion(arangoDB, 3, 4)) - return; - db.createView(VIEW_NAME, ViewType.ARANGO_SEARCH).get(); - } - - @Test - void exists() throws InterruptedException, ExecutionException { - assumeTrue(isAtLeastVersion(3, 4)); - assertThat(db.view(VIEW_NAME).exists().get()).isTrue(); - } - - @Test - void getInfo() throws InterruptedException, ExecutionException { - assumeTrue(isAtLeastVersion(3, 4)); - final ViewEntity info = db.view(VIEW_NAME).getInfo().get(); - assertThat(info).isNotNull(); - assertThat(info.getId()).isNotNull(); - assertThat(info.getName()).isEqualTo(VIEW_NAME); - assertThat(info.getType()).isEqualTo(ViewType.ARANGO_SEARCH); - } - - @Test - void drop() throws InterruptedException, ExecutionException { - assumeTrue(isAtLeastVersion(3, 4)); - final String name = VIEW_NAME + "_droptest"; - db.createView(name, ViewType.ARANGO_SEARCH).get(); - final ArangoViewAsync view = db.view(name); - view.drop().get(); - assertThat(view.exists().get()).isFalse(); - } - - @Test - void rename() throws InterruptedException, ExecutionException { - assumeTrue(isSingleServer()); - assumeTrue(isAtLeastVersion(3, 4)); - final String name = VIEW_NAME + "_renametest"; - final String newName = name + "_new"; - db.createView(name, ViewType.ARANGO_SEARCH).get(); - db.view(name).rename(newName).get(); - assertThat(db.view(name).exists().get()).isFalse(); - assertThat(db.view(newName).exists().get()).isTrue(); - } - -} diff --git a/shaded-integration-tests/src/test/native/java/com/arangodb/async/BaseTest.java b/shaded-integration-tests/src/test/native/java/com/arangodb/async/BaseTest.java deleted file mode 100644 index 261996ab9..000000000 --- a/shaded-integration-tests/src/test/native/java/com/arangodb/async/BaseTest.java +++ /dev/null @@ -1,119 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.async; - -import com.arangodb.DbName; -import com.arangodb.config.ArangoConfigProperties; -import com.arangodb.config.ConfigUtils; -import com.arangodb.entity.ArangoDBEngine; -import com.arangodb.entity.License; -import com.arangodb.entity.ServerRole; -import com.arangodb.util.TestUtils; -import org.junit.jupiter.api.AfterAll; -import org.junit.jupiter.api.BeforeAll; - -import java.util.UUID; -import java.util.concurrent.ExecutionException; - - -/** - * @author Mark Vollmary - */ -public abstract class BaseTest { - protected static final ArangoConfigProperties config = ConfigUtils.loadConfig(); - static final DbName TEST_DB = DbName.of("java_driver_test_db"); - static ArangoDBAsync arangoDB; - static ArangoDatabaseAsync db; - - @BeforeAll - static void init() throws InterruptedException, ExecutionException { - if (arangoDB == null) { - arangoDB = new ArangoDBAsync.Builder() - .loadProperties(ConfigUtils.loadConfig()) - .build(); - } - - if (arangoDB.db(TEST_DB).exists().get()) { - arangoDB.db(TEST_DB).drop().get(); - } - - arangoDB.createDatabase(TEST_DB).get(); - BaseTest.db = arangoDB.db(TEST_DB); - } - - @AfterAll - static void shutdown() throws InterruptedException, ExecutionException { - arangoDB.db(TEST_DB).drop().get(); - arangoDB.shutdown(); - 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); - } - - protected static boolean isAtLeastVersion(final ArangoDBAsync arangoDB, final int major, final int minor) - throws InterruptedException, ExecutionException { - return isAtLeastVersion(arangoDB, major, minor, 0); - } - - protected boolean isAtLeastVersion(final int major, final int minor, final int patch) throws InterruptedException - , ExecutionException { - return isAtLeastVersion(arangoDB, major, minor, patch); - } - - protected boolean isAtLeastVersion(final int major, final int minor) throws InterruptedException, - ExecutionException { - return isAtLeastVersion(major, minor, 0); - } - - boolean isLessThanVersion(final int major, final int minor) throws ExecutionException, InterruptedException { - return isLessThanVersion(major, minor, 0); - } - - boolean isLessThanVersion(final int major, final int minor, final int patch) throws ExecutionException, InterruptedException { - return TestUtils.isLessThanVersion(db.getVersion().get().getVersion(), major, minor, patch); - } - - boolean isStorageEngine(ArangoDBEngine.StorageEngineName name) throws ExecutionException, InterruptedException { - return name.equals(db.getEngine().get().getName()); - } - - boolean isSingleServer() throws ExecutionException, InterruptedException { - return (arangoDB.getRole().get() == ServerRole.SINGLE); - } - - boolean isCluster() throws ExecutionException, InterruptedException { - return arangoDB.getRole().get() == ServerRole.COORDINATOR; - } - - boolean isEnterprise() throws ExecutionException, InterruptedException { - return arangoDB.getVersion().get().getLicense() == License.ENTERPRISE; - } - -} diff --git a/shaded-integration-tests/src/test/native/java/com/arangodb/async/CommunicationTest.java b/shaded-integration-tests/src/test/native/java/com/arangodb/async/CommunicationTest.java deleted file mode 100644 index 0b2b6c962..000000000 --- a/shaded-integration-tests/src/test/native/java/com/arangodb/async/CommunicationTest.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.async; - -import org.junit.jupiter.api.Disabled; -import org.junit.jupiter.api.Test; - -import java.util.concurrent.CompletableFuture; - -import static org.assertj.core.api.Assertions.assertThat; - - -/** - * @author Mark Vollmary - */ -class CommunicationTest { - - @Test - @Disabled - void disconnect() { - final ArangoDBAsync arangoDB = new ArangoDBAsync.Builder().build(); - final CompletableFuture> result = arangoDB.db().query("return sleep(1)", null, null, - null); - arangoDB.shutdown(); - assertThat(result.isCompletedExceptionally()).isEqualTo(true); - } - -} diff --git a/shaded-integration-tests/src/test/native/java/com/arangodb/async/ConcurrencyTest.java b/shaded-integration-tests/src/test/native/java/com/arangodb/async/ConcurrencyTest.java deleted file mode 100644 index f0643c2ca..000000000 --- a/shaded-integration-tests/src/test/native/java/com/arangodb/async/ConcurrencyTest.java +++ /dev/null @@ -1,94 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.async; - - -import com.arangodb.async.internal.ArangoExecutorAsync; -import com.arangodb.entity.ArangoDBVersion; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Disabled; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.Timeout; - -import java.util.List; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ExecutionException; -import java.util.stream.Collectors; -import java.util.stream.IntStream; - -import static org.junit.jupiter.api.Assertions.fail; - - -/** - * @author Michele Rastelli - */ -class ConcurrencyTest { - - private ArangoDBAsync arangoDB; - - @BeforeEach - void initialize() { - arangoDB = new ArangoDBAsync.Builder().build(); - } - - /** - * FIXME: make the user executor configurable in com.arangodb.internal.ArangoExecutorAsync::execute - * (eg. this test passes using a CachedThreadPool) - */ - @Disabled - @Test - @Timeout(2) - void executorLimit() { - List> futures = IntStream.range(0, 20) - .mapToObj(i -> arangoDB.getVersion() - .whenComplete((dbVersion, ex) -> { - System.out.println(Thread.currentThread().getName()); - try { - Thread.sleep(1000); - } catch (InterruptedException e) { - e.printStackTrace(); - } - })) - .collect(Collectors.toList()); - - futures.forEach(future -> { - try { - future.get(); - } catch (InterruptedException | ExecutionException e) { - e.printStackTrace(); - fail(); - } - }); - } - - - /** - * outgoing requests should be queued in the {@link ArangoExecutorAsync} outgoingExecutor - */ - @Disabled - @Test - @Timeout(1) - void outgoingRequestsParallelismTest() { - for (int i = 0; i < 50_000; i++) { - arangoDB.getVersion(); - } - } -} diff --git a/shaded-integration-tests/src/test/native/java/com/arangodb/async/ConcurrencyTests.java b/shaded-integration-tests/src/test/native/java/com/arangodb/async/ConcurrencyTests.java deleted file mode 100644 index 278486efc..000000000 --- a/shaded-integration-tests/src/test/native/java/com/arangodb/async/ConcurrencyTests.java +++ /dev/null @@ -1,29 +0,0 @@ -package com.arangodb.async; - - -import com.arangodb.config.ConfigUtils; -import org.junit.jupiter.api.Test; - -import java.util.List; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ExecutionException; -import java.util.stream.Collectors; -import java.util.stream.IntStream; - -class ConcurrencyTests { - - @Test - void concurrentPendingRequests() throws ExecutionException, InterruptedException { - ArangoDBAsync adb = new ArangoDBAsync.Builder() - .loadProperties(ConfigUtils.loadConfig()) - .build(); - List>> reqs = IntStream.range(0, 10) - .mapToObj(__ -> adb.db().query("RETURN SLEEP(1)", Void.class)) - .collect(Collectors.toList()); - for (CompletableFuture> req : reqs) { - req.get(); - } - adb.shutdown(); - } - -} diff --git a/shaded-integration-tests/src/test/native/java/com/arangodb/async/InvertedIndexTest.java b/shaded-integration-tests/src/test/native/java/com/arangodb/async/InvertedIndexTest.java deleted file mode 100644 index e4451f77c..000000000 --- a/shaded-integration-tests/src/test/native/java/com/arangodb/async/InvertedIndexTest.java +++ /dev/null @@ -1,199 +0,0 @@ -package com.arangodb.async; - -import com.arangodb.entity.*; -import com.arangodb.entity.arangosearch.*; -import com.arangodb.entity.arangosearch.analyzer.DelimiterAnalyzer; -import com.arangodb.entity.arangosearch.analyzer.DelimiterAnalyzerProperties; -import com.arangodb.model.InvertedIndexOptions; -import com.arangodb.model.PersistentIndexOptions; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.Test; - -import java.util.*; -import java.util.concurrent.ExecutionException; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assumptions.assumeTrue; - -public class InvertedIndexTest extends BaseTest { - - private static final String COLLECTION_NAME = "InvertedIndexTestAsync_collection"; - - InvertedIndexTest() throws ExecutionException, InterruptedException { - ArangoCollectionAsync collection = db.collection(COLLECTION_NAME); - if (!collection.exists().get()) { - collection.create().get(); - } - } - - @BeforeAll - static void setup() throws InterruptedException, ExecutionException { - db.createCollection(COLLECTION_NAME, null).get(); - } - - @AfterEach - void teardown() throws InterruptedException, ExecutionException { - db.collection(COLLECTION_NAME).drop().get(); - } - - - private void createAnalyzer(String analyzerName, ArangoDatabaseAsync db) throws ExecutionException, InterruptedException { - Set features = new HashSet<>(); - features.add(AnalyzerFeature.frequency); - features.add(AnalyzerFeature.norm); - features.add(AnalyzerFeature.position); - - DelimiterAnalyzer da = new DelimiterAnalyzer(); - da.setName(analyzerName); - da.setFeatures(features); - DelimiterAnalyzerProperties props = new DelimiterAnalyzerProperties(); - props.setDelimiter("-"); - da.setProperties(props); - - db.createSearchAnalyzer(da).get(); - } - - private InvertedIndexOptions createOptions(String analyzerName) throws ExecutionException, InterruptedException { - InvertedIndexField field = new InvertedIndexField() - .name("foo") - .analyzer(AnalyzerType.identity.toString()) - .includeAllFields(true) - .searchField(false) - .trackListPositions(false) - .features( - AnalyzerFeature.position, - AnalyzerFeature.frequency, - AnalyzerFeature.norm, - AnalyzerFeature.offset - ); - - if (isEnterprise()) { - field.nested( - new InvertedIndexField() - .name("bar") - .analyzer(analyzerName) - .searchField(true) - .features(AnalyzerFeature.position, AnalyzerFeature.frequency) - .nested( - new InvertedIndexField() - .name("baz") - .analyzer(AnalyzerType.identity.toString()) - .searchField(false) - .features(AnalyzerFeature.frequency) - ) - ); - } - - return new InvertedIndexOptions() - .name("invertedIndex-" + UUID.randomUUID()) - .inBackground(true) - .parallelism(5) - .primarySort(new InvertedIndexPrimarySort() - .fields( - new InvertedIndexPrimarySort.Field("f1", InvertedIndexPrimarySort.Field.Direction.asc), - new InvertedIndexPrimarySort.Field("f2", InvertedIndexPrimarySort.Field.Direction.desc) - ) - .compression(ArangoSearchCompression.lz4) - ) - .storedValues(new StoredValue(Arrays.asList("f3", "f4"), ArangoSearchCompression.none)) - .analyzer(analyzerName) - .features(AnalyzerFeature.position, AnalyzerFeature.frequency) - .includeAllFields(false) - .trackListPositions(true) - .searchField(true) - .fields(field) - .consolidationIntervalMsec(11L) - .commitIntervalMsec(22L) - .cleanupIntervalStep(33L) - .consolidationPolicy(ConsolidationPolicy.of(ConsolidationType.BYTES_ACCUM).threshold(1.)) - .writebufferIdle(44L) - .writebufferActive(55L) - .writebufferSizeMax(66L); - } - - private void assertCorrectIndexEntity(InvertedIndexEntity indexResult, InvertedIndexOptions options) { - assertThat(indexResult).isNotNull(); - assertThat(indexResult.getId()).isNotNull().isNotEmpty(); - // FIXME: in single server this is null - // assertThat(indexResult.getIsNewlyCreated()).isTrue(); - assertThat(indexResult.getUnique()).isFalse(); - assertThat(indexResult.getSparse()).isTrue(); - assertThat(indexResult.getVersion()).isNotNull(); - assertThat(indexResult.getCode()).isNotNull(); - assertThat(indexResult.getType()).isEqualTo(IndexType.inverted); - assertThat(indexResult.getName()).isEqualTo(options.getName()); - assertThat(indexResult.getFields()).containsExactlyElementsOf(options.getFields()); - assertThat(indexResult.getSearchField()).isEqualTo(options.getSearchField()); - assertThat(indexResult.getStoredValues()).containsExactlyElementsOf(options.getStoredValues()); - assertThat(indexResult.getPrimarySort()).isEqualTo(options.getPrimarySort()); - assertThat(indexResult.getAnalyzer()).isEqualTo(options.getAnalyzer()); - assertThat(indexResult.getFeatures()).hasSameElementsAs(options.getFeatures()); - assertThat(indexResult.getIncludeAllFields()).isEqualTo(options.getIncludeAllFields()); - assertThat(indexResult.getTrackListPositions()).isEqualTo(options.getTrackListPositions()); - assertThat(indexResult.getCleanupIntervalStep()).isEqualTo(options.getCleanupIntervalStep()); - assertThat(indexResult.getCommitIntervalMsec()).isEqualTo(options.getCommitIntervalMsec()); - assertThat(indexResult.getConsolidationIntervalMsec()).isEqualTo(options.getConsolidationIntervalMsec()); - assertThat(indexResult.getConsolidationPolicy()).isEqualTo(options.getConsolidationPolicy()); - assertThat(indexResult.getWritebufferIdle()).isEqualTo(options.getWritebufferIdle()); - assertThat(indexResult.getWritebufferActive()).isEqualTo(options.getWritebufferActive()); - assertThat(indexResult.getWritebufferSizeMax()).isEqualTo(options.getWritebufferSizeMax()); - } - - @Test - void createAndGetInvertedIndex() throws ExecutionException, InterruptedException { - assumeTrue(isAtLeastVersion(3, 10)); - - ArangoCollectionAsync collection = db.collection(COLLECTION_NAME); - String analyzerName = "delimiter-" + UUID.randomUUID(); - createAnalyzer(analyzerName, collection.db()); - InvertedIndexOptions options = createOptions(analyzerName); - InvertedIndexEntity created = collection.ensureInvertedIndex(options).get(); - assertCorrectIndexEntity(created, options); - InvertedIndexEntity loadedIndex = collection.getInvertedIndex(created.getName()).get(); - assertCorrectIndexEntity(loadedIndex, options); - } - - @Test - void getInvertedIndexesShouldNotReturnOtherIndexTypes() throws ExecutionException, InterruptedException { - assumeTrue(isAtLeastVersion(3, 10)); - - ArangoCollectionAsync collection = db.collection(COLLECTION_NAME); - - // create persistent index - collection.ensurePersistentIndex(Collections.singletonList("foo"), new PersistentIndexOptions().name("persistentIndex")); - - // create inverted index - String analyzerName = "delimiter-" + UUID.randomUUID(); - createAnalyzer(analyzerName, collection.db()); - InvertedIndexOptions options = createOptions(analyzerName); - InvertedIndexEntity created = collection.ensureInvertedIndex(options).get(); - - Collection loadedIndexes = collection.getInvertedIndexes().get(); - assertThat(loadedIndexes).map(InvertedIndexEntity::getName) - .doesNotContain("persistentIndex") - .contains(created.getName()); - } - - @Test - void getIndexesShouldNotReturnInvertedIndexes() throws ExecutionException, InterruptedException { - assumeTrue(isAtLeastVersion(3, 10)); - - ArangoCollectionAsync collection = db.collection(COLLECTION_NAME); - - // create persistent index - collection.ensurePersistentIndex(Collections.singletonList("foo"), new PersistentIndexOptions().name("persistentIndex")).get(); - - // create inverted index - String analyzerName = "delimiter-" + UUID.randomUUID(); - createAnalyzer(analyzerName, collection.db()); - InvertedIndexOptions options = createOptions(analyzerName); - InvertedIndexEntity created = collection.ensureInvertedIndex(options).get(); - - Collection loadedIndexes = collection.getIndexes().get(); - assertThat(loadedIndexes).map(IndexEntity::getName) - .doesNotContain(created.getName()) - .contains("persistentIndex"); - } - -} diff --git a/shaded-integration-tests/src/test/native/java/com/arangodb/async/JwtAuthTest.java b/shaded-integration-tests/src/test/native/java/com/arangodb/async/JwtAuthTest.java deleted file mode 100644 index 04bbfc98d..000000000 --- a/shaded-integration-tests/src/test/native/java/com/arangodb/async/JwtAuthTest.java +++ /dev/null @@ -1,103 +0,0 @@ -package com.arangodb.async; - -import com.arangodb.*; -import com.arangodb.config.ConfigUtils; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.Disabled; -import org.junit.jupiter.api.Test; - -import java.util.HashMap; -import java.util.Map; -import java.util.concurrent.ExecutionException; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.fail; - -class JwtAuthTest { - - private static String jwt; - private ArangoDBAsync arangoDB; - - @BeforeAll - static void init() { - ArangoDB arangoDB = new ArangoDB.Builder() - .loadProperties(ConfigUtils.loadConfig()) - .build(); - jwt = getJwt(arangoDB); - arangoDB.shutdown(); - } - - private static String getJwt(ArangoDB arangoDB) { - Map reqBody = new HashMap<>(); - reqBody.put("username", "root"); - reqBody.put("password", "test"); - - Request req = Request.builder() - .db(DbName.SYSTEM) - .method(Request.Method.POST) - .path("/_open/auth") - .body(reqBody) - .build(); - - Response resp = arangoDB.execute(req, Map.class); - return (String) resp.getBody().get("jwt"); - } - - @AfterEach - void after() { - if (arangoDB != null) - arangoDB.shutdown(); - } - - @Test - void notAuthenticated() throws InterruptedException { - arangoDB = getBuilder().build(); - try { - arangoDB.getVersion().get(); - fail(); - } catch (ExecutionException e) { - assertThat(e.getCause()).isInstanceOf(ArangoDBException.class); - assertThat(((ArangoDBException) e.getCause()).getResponseCode()).isEqualTo(401); - } - arangoDB.shutdown(); - } - - @Test - void authenticated() throws ExecutionException, InterruptedException { - arangoDB = getBuilder() - .jwt(jwt) - .build(); - arangoDB.getVersion().get(); - arangoDB.shutdown(); - } - - @Test - @Disabled("DE-423") - void updateJwt() throws ExecutionException, InterruptedException { - arangoDB = getBuilder() - .jwt(jwt) - .build(); - arangoDB.getVersion().get(); - arangoDB.updateJwt("bla"); - try { - arangoDB.getVersion().get(); - fail(); - } catch (ExecutionException e) { - assertThat(e.getCause()).isInstanceOf(ArangoDBException.class); - assertThat(((ArangoDBException) e.getCause()).getResponseCode()).isEqualTo(401); - } - - arangoDB.updateJwt(jwt); - arangoDB.getVersion().get(); - arangoDB.shutdown(); - } - - private ArangoDBAsync.Builder getBuilder() { - return new ArangoDBAsync.Builder() - .loadProperties(ConfigUtils.loadConfig()) - .jwt(null) // unset credentials from properties file - .user(null) // unset credentials from properties file - .password(null); // unset credentials from properties file - } -} diff --git a/shaded-integration-tests/src/test/native/java/com/arangodb/async/StreamTransactionConflictsTest.java b/shaded-integration-tests/src/test/native/java/com/arangodb/async/StreamTransactionConflictsTest.java deleted file mode 100644 index 659781ae2..000000000 --- a/shaded-integration-tests/src/test/native/java/com/arangodb/async/StreamTransactionConflictsTest.java +++ /dev/null @@ -1,120 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.async; - -import com.arangodb.ArangoDBException; -import com.arangodb.entity.ArangoDBEngine; -import com.arangodb.entity.BaseDocument; -import com.arangodb.entity.StreamTransactionEntity; -import com.arangodb.model.DocumentCreateOptions; -import com.arangodb.model.StreamTransactionOptions; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.Test; - -import java.util.UUID; -import java.util.concurrent.ExecutionException; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.fail; -import static org.junit.jupiter.api.Assumptions.assumeTrue; - -/** - * @author Michele Rastelli - */ -class StreamTransactionConflictsTest extends BaseTest { - - private static final String COLLECTION_NAME = "db_concurrent_stream_transactions_test"; - - public StreamTransactionConflictsTest() throws ExecutionException, InterruptedException { - if (db.collection(COLLECTION_NAME).exists().get()) - db.collection(COLLECTION_NAME).drop().get(); - - db.createCollection(COLLECTION_NAME, null).get(); - } - - @AfterEach - void teardown() throws ExecutionException, InterruptedException { - if (db.collection(COLLECTION_NAME).exists().get()) - db.collection(COLLECTION_NAME).drop().get(); - } - - @Test - void conflictOnInsertDocumentWithNotYetCommittedTx() throws ExecutionException, InterruptedException { - assumeTrue(isAtLeastVersion(3, 5)); - assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); - - StreamTransactionEntity tx1 = db.beginStreamTransaction( - new StreamTransactionOptions().readCollections(COLLECTION_NAME).writeCollections(COLLECTION_NAME)).get(); - - StreamTransactionEntity tx2 = db.beginStreamTransaction( - new StreamTransactionOptions().readCollections(COLLECTION_NAME).writeCollections(COLLECTION_NAME)).get(); - - String key = UUID.randomUUID().toString(); - - // insert a document from within tx1 - db.collection(COLLECTION_NAME) - .insertDocument(new BaseDocument(key), new DocumentCreateOptions().streamTransactionId(tx1.getId())).get(); - - try { - // insert conflicting document from within tx2 - db.collection(COLLECTION_NAME).insertDocument(new BaseDocument(key), - new DocumentCreateOptions().streamTransactionId(tx2.getId())).get(); - fail(); - } catch (ExecutionException e) { - assertThat(e.getCause()).isInstanceOf(ArangoDBException.class); - } - - db.abortStreamTransaction(tx1.getId()).get(); - db.abortStreamTransaction(tx2.getId()).get(); - } - - @Test - void conflictOnInsertDocumentWithAlreadyCommittedTx() throws ExecutionException, InterruptedException { - assumeTrue(isAtLeastVersion(3, 5)); - assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); - - StreamTransactionEntity tx1 = db.beginStreamTransaction( - new StreamTransactionOptions().readCollections(COLLECTION_NAME).writeCollections(COLLECTION_NAME)).get(); - - StreamTransactionEntity tx2 = db.beginStreamTransaction( - new StreamTransactionOptions().readCollections(COLLECTION_NAME).writeCollections(COLLECTION_NAME)).get(); - - String key = UUID.randomUUID().toString(); - - // insert a document from within tx1 - db.collection(COLLECTION_NAME) - .insertDocument(new BaseDocument(key), new DocumentCreateOptions().streamTransactionId(tx1.getId())).get(); - - // commit tx1 - db.commitStreamTransaction(tx1.getId()).get(); - - try { - // insert conflicting document from within tx2 - db.collection(COLLECTION_NAME).insertDocument(new BaseDocument(key), - new DocumentCreateOptions().streamTransactionId(tx2.getId())).get(); - fail(); - } catch (ExecutionException e) { - assertThat(e.getCause()).isInstanceOf(ArangoDBException.class); - } - - db.abortStreamTransaction(tx2.getId()).get(); - } -} diff --git a/shaded-integration-tests/src/test/native/java/com/arangodb/async/StreamTransactionGraphTest.java b/shaded-integration-tests/src/test/native/java/com/arangodb/async/StreamTransactionGraphTest.java deleted file mode 100644 index 60ee6ea11..000000000 --- a/shaded-integration-tests/src/test/native/java/com/arangodb/async/StreamTransactionGraphTest.java +++ /dev/null @@ -1,398 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.async; - - -import com.arangodb.entity.*; -import com.arangodb.model.*; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.Test; - -import java.util.Collections; -import java.util.UUID; -import java.util.concurrent.ExecutionException; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assumptions.assumeTrue; - - -/** - * @author Michele Rastelli - */ -class StreamTransactionGraphTest extends BaseTest { - - private static final String GRAPH_NAME = "graph_stream_transaction_graph_test"; - private static final String EDGE_COLLECTION = "edge_collection_stream_transaction_graph_test"; - private static final String VERTEX_COLLECTION_1 = "vertex_collection_1_stream_transaction_graph_test"; - private static final String VERTEX_COLLECTION_2 = "vertex_collection_2_stream_transaction_graph_test"; - - private final ArangoGraphAsync graph; - private final ArangoVertexCollectionAsync vertexCollection1; - private final ArangoVertexCollectionAsync vertexCollection2; - private final ArangoEdgeCollectionAsync edgeCollection; - - public StreamTransactionGraphTest() throws ExecutionException, InterruptedException { - - graph = db.graph(GRAPH_NAME); - - if (graph.exists().get()) - graph.drop().get(); - - graph.create(Collections.singletonList(new EdgeDefinition().collection(EDGE_COLLECTION).from(VERTEX_COLLECTION_1).to(VERTEX_COLLECTION_2))).get(); - - vertexCollection1 = graph.vertexCollection(VERTEX_COLLECTION_1); - vertexCollection2 = graph.vertexCollection(VERTEX_COLLECTION_2); - edgeCollection = graph.edgeCollection(EDGE_COLLECTION); - } - - @AfterEach - void teardown() throws ExecutionException, InterruptedException { - if (graph.exists().get()) - graph.drop().get(); - if (db.collection(EDGE_COLLECTION).exists().get()) - db.collection(EDGE_COLLECTION).drop().get(); - if (db.collection(VERTEX_COLLECTION_1).exists().get()) - db.collection(VERTEX_COLLECTION_1).drop().get(); - if (db.collection(VERTEX_COLLECTION_2).exists().get()) - db.collection(VERTEX_COLLECTION_2).drop().get(); - } - - private BaseEdgeDocument createEdgeValue(String streamTransactionId) throws ExecutionException, - InterruptedException { - final VertexEntity v1 = vertexCollection1.insertVertex(new BaseDocument(), - new VertexCreateOptions().streamTransactionId(streamTransactionId)).get(); - final VertexEntity v2 = vertexCollection2.insertVertex(new BaseDocument(), - new VertexCreateOptions().streamTransactionId(streamTransactionId)).get(); - final BaseEdgeDocument value = new BaseEdgeDocument(); - value.setFrom(v1.getId()); - value.setTo(v2.getId()); - return value; - } - - @Test - void getVertex() throws ExecutionException, InterruptedException { - assumeTrue(isSingleServer()); - assumeTrue(isAtLeastVersion(3, 5)); - assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); - - StreamTransactionEntity tx = db - .beginStreamTransaction(new StreamTransactionOptions() - .readCollections(VERTEX_COLLECTION_1, VERTEX_COLLECTION_2, EDGE_COLLECTION) - .writeCollections(VERTEX_COLLECTION_1, VERTEX_COLLECTION_2, EDGE_COLLECTION)).get(); - - // insert a vertex from outside the tx - VertexEntity createdVertex = vertexCollection1.insertVertex(new BaseDocument()).get(); - - // assert that the vertex is not found from within the tx - assertThat(vertexCollection1.getVertex(createdVertex.getKey(), BaseDocument.class, - new GraphDocumentReadOptions().streamTransactionId(tx.getId())).get()).isNull(); - - db.abortStreamTransaction(tx.getId()).get(); - } - - - @Test - void createVertex() throws ExecutionException, InterruptedException { - assumeTrue(isSingleServer()); - assumeTrue(isAtLeastVersion(3, 5)); - assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); - - StreamTransactionEntity tx = db.beginStreamTransaction( - new StreamTransactionOptions() - .readCollections(VERTEX_COLLECTION_1, VERTEX_COLLECTION_2, EDGE_COLLECTION) - .writeCollections(VERTEX_COLLECTION_1, VERTEX_COLLECTION_2, EDGE_COLLECTION)).get(); - - // insert a vertex from within the tx - VertexEntity createdVertex = vertexCollection1.insertVertex(new BaseDocument(), - new VertexCreateOptions().streamTransactionId(tx.getId())).get(); - - // assert that the vertex is not found from outside the tx - assertThat(vertexCollection1.getVertex(createdVertex.getKey(), BaseDocument.class, null).get()).isNull(); - - // assert that the vertex is found from within the tx - assertThat(vertexCollection1.getVertex(createdVertex.getKey(), BaseDocument.class, - new GraphDocumentReadOptions().streamTransactionId(tx.getId())).get()).isNotNull(); - - db.commitStreamTransaction(tx.getId()).get(); - - // assert that the vertex is found after commit - assertThat(vertexCollection1.getVertex(createdVertex.getKey(), BaseDocument.class, null).get()).isNotNull(); - } - - @Test - void replaceVertex() throws ExecutionException, InterruptedException { - assumeTrue(isSingleServer()); - assumeTrue(isAtLeastVersion(3, 5)); - assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); - - BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); - doc.addAttribute("test", "foo"); - - VertexEntity createdVertex = vertexCollection1.insertVertex(doc, null).get(); - - StreamTransactionEntity tx = db.beginStreamTransaction( - new StreamTransactionOptions() - .readCollections(VERTEX_COLLECTION_1, VERTEX_COLLECTION_2, EDGE_COLLECTION) - .writeCollections(VERTEX_COLLECTION_1, VERTEX_COLLECTION_2, EDGE_COLLECTION)).get(); - - // replace vertex from within the tx - doc.updateAttribute("test", "bar"); - vertexCollection1.replaceVertex(createdVertex.getKey(), doc, - new VertexReplaceOptions().streamTransactionId(tx.getId())).get(); - - // assert that the vertex has not been replaced from outside the tx - assertThat(vertexCollection1.getVertex(createdVertex.getKey(), BaseDocument.class, null).get() - .getProperties()).containsEntry("test", "foo"); - - // assert that the vertex has been replaced from within the tx - assertThat(vertexCollection1.getVertex(createdVertex.getKey(), BaseDocument.class, - new GraphDocumentReadOptions().streamTransactionId(tx.getId())).get().getProperties()).containsEntry( - "test", "bar"); - - db.commitStreamTransaction(tx.getId()).get(); - - // assert that the vertex has been replaced after commit - assertThat(vertexCollection1.getVertex(createdVertex.getKey(), BaseDocument.class, null).get() - .getProperties()).containsEntry("test", "bar"); - } - - @Test - void updateVertex() throws ExecutionException, InterruptedException { - assumeTrue(isSingleServer()); - assumeTrue(isAtLeastVersion(3, 5)); - assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); - - BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); - doc.addAttribute("test", "foo"); - - VertexEntity createdDoc = vertexCollection1.insertVertex(doc, null).get(); - - StreamTransactionEntity tx = db.beginStreamTransaction( - new StreamTransactionOptions() - .readCollections(VERTEX_COLLECTION_1, VERTEX_COLLECTION_2, EDGE_COLLECTION) - .writeCollections(VERTEX_COLLECTION_1, VERTEX_COLLECTION_2, EDGE_COLLECTION)).get(); - - // update vertex from within the tx - doc.updateAttribute("test", "bar"); - vertexCollection1.updateVertex(createdDoc.getKey(), doc, - new VertexUpdateOptions().streamTransactionId(tx.getId())).get(); - - // assert that the vertex has not been updated from outside the tx - assertThat(vertexCollection1.getVertex(createdDoc.getKey(), BaseDocument.class, null).get() - .getProperties()).containsEntry("test", "foo"); - - // assert that the vertex has been updated from within the tx - assertThat(vertexCollection1.getVertex(createdDoc.getKey(), BaseDocument.class, - new GraphDocumentReadOptions().streamTransactionId(tx.getId())).get().getProperties()).containsEntry( - "test", "bar"); - - db.commitStreamTransaction(tx.getId()).get(); - - // assert that the vertex has been updated after commit - assertThat(vertexCollection1.getVertex(createdDoc.getKey(), BaseDocument.class, null).get() - .getProperties()).containsEntry("test", "bar"); - } - - @Test - void deleteVertex() throws ExecutionException, InterruptedException { - assumeTrue(isSingleServer()); - assumeTrue(isAtLeastVersion(3, 5)); - assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); - - VertexEntity createdDoc = vertexCollection1.insertVertex(new BaseDocument(), null).get(); - - StreamTransactionEntity tx = db.beginStreamTransaction( - new StreamTransactionOptions() - .readCollections(VERTEX_COLLECTION_1, VERTEX_COLLECTION_2, EDGE_COLLECTION) - .writeCollections(VERTEX_COLLECTION_1, VERTEX_COLLECTION_2, EDGE_COLLECTION)).get(); - - // delete vertex from within the tx - vertexCollection1.deleteVertex(createdDoc.getKey(), - new VertexDeleteOptions().streamTransactionId(tx.getId())).get(); - - // assert that the vertex has not been deleted from outside the tx - assertThat(vertexCollection1.getVertex(createdDoc.getKey(), BaseDocument.class, null).get()).isNotNull(); - - // assert that the vertex has been deleted from within the tx - assertThat(vertexCollection1.getVertex(createdDoc.getKey(), BaseDocument.class, - new GraphDocumentReadOptions().streamTransactionId(tx.getId())).get()).isNull(); - - db.commitStreamTransaction(tx.getId()).get(); - - // assert that the vertex has been deleted after commit - assertThat(vertexCollection1.getVertex(createdDoc.getKey(), BaseDocument.class, null).get()).isNull(); - } - - - @Test - void getEdge() throws ExecutionException, InterruptedException { - assumeTrue(isSingleServer()); - assumeTrue(isAtLeastVersion(3, 5)); - assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); - - StreamTransactionEntity tx = db - .beginStreamTransaction(new StreamTransactionOptions() - .readCollections(VERTEX_COLLECTION_1, VERTEX_COLLECTION_2, EDGE_COLLECTION) - .writeCollections(VERTEX_COLLECTION_1, VERTEX_COLLECTION_2, EDGE_COLLECTION)).get(); - - // insert an edge from outside the tx - EdgeEntity createdEdge = edgeCollection.insertEdge(createEdgeValue(null)).get(); - - // assert that the edge is not found from within the tx - assertThat(edgeCollection.getEdge(createdEdge.getKey(), BaseEdgeDocument.class, - new GraphDocumentReadOptions().streamTransactionId(tx.getId())).get()).isNull(); - - db.abortStreamTransaction(tx.getId()).get(); - } - - - @Test - void createEdge() throws ExecutionException, InterruptedException { - assumeTrue(isSingleServer()); - assumeTrue(isAtLeastVersion(3, 5)); - assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); - - StreamTransactionEntity tx = db.beginStreamTransaction( - new StreamTransactionOptions() - .readCollections(VERTEX_COLLECTION_1, VERTEX_COLLECTION_2, EDGE_COLLECTION) - .writeCollections(VERTEX_COLLECTION_1, VERTEX_COLLECTION_2, EDGE_COLLECTION)).get(); - - // insert an edge from within the tx - EdgeEntity createdEdge = edgeCollection.insertEdge(createEdgeValue(tx.getId()), - new EdgeCreateOptions().streamTransactionId(tx.getId())).get(); - - // assert that the edge is not found from outside the tx - assertThat(edgeCollection.getEdge(createdEdge.getKey(), BaseEdgeDocument.class, null).get()).isNull(); - - // assert that the edge is found from within the tx - assertThat(edgeCollection.getEdge(createdEdge.getKey(), BaseEdgeDocument.class, - new GraphDocumentReadOptions().streamTransactionId(tx.getId())).get()).isNotNull(); - - db.commitStreamTransaction(tx.getId()).get(); - - // assert that the edge is found after commit - assertThat(edgeCollection.getEdge(createdEdge.getKey(), BaseEdgeDocument.class, null).get()).isNotNull(); - } - - @Test - void replaceEdge() throws ExecutionException, InterruptedException { - assumeTrue(isSingleServer()); - assumeTrue(isAtLeastVersion(3, 5)); - assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); - - BaseEdgeDocument doc = createEdgeValue(null); - doc.addAttribute("test", "foo"); - - EdgeEntity createdEdge = edgeCollection.insertEdge(doc, null).get(); - - StreamTransactionEntity tx = db.beginStreamTransaction( - new StreamTransactionOptions() - .readCollections(VERTEX_COLLECTION_1, VERTEX_COLLECTION_2, EDGE_COLLECTION) - .writeCollections(VERTEX_COLLECTION_1, VERTEX_COLLECTION_2, EDGE_COLLECTION)).get(); - - // replace edge from within the tx - doc.updateAttribute("test", "bar"); - edgeCollection.replaceEdge(createdEdge.getKey(), doc, - new EdgeReplaceOptions().streamTransactionId(tx.getId())).get(); - - // assert that the edge has not been replaced from outside the tx - assertThat(edgeCollection.getEdge(createdEdge.getKey(), BaseEdgeDocument.class, null).get() - .getProperties()).containsEntry("test", "foo"); - - // assert that the edge has been replaced from within the tx - assertThat(edgeCollection.getEdge(createdEdge.getKey(), BaseEdgeDocument.class, - new GraphDocumentReadOptions().streamTransactionId(tx.getId())).get().getProperties()).containsEntry( - "test", "bar"); - - db.commitStreamTransaction(tx.getId()).get(); - - // assert that the edge has been replaced after commit - assertThat(edgeCollection.getEdge(createdEdge.getKey(), BaseEdgeDocument.class, null).get() - .getProperties()).containsEntry("test", "bar"); - } - - @Test - void updateEdge() throws ExecutionException, InterruptedException { - assumeTrue(isSingleServer()); - assumeTrue(isAtLeastVersion(3, 5)); - assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); - - BaseEdgeDocument doc = createEdgeValue(null); - doc.addAttribute("test", "foo"); - - EdgeEntity createdDoc = edgeCollection.insertEdge(doc, null).get(); - - StreamTransactionEntity tx = db.beginStreamTransaction( - new StreamTransactionOptions() - .readCollections(VERTEX_COLLECTION_1, VERTEX_COLLECTION_2, EDGE_COLLECTION) - .writeCollections(VERTEX_COLLECTION_1, VERTEX_COLLECTION_2, EDGE_COLLECTION)).get(); - - // update edge from within the tx - doc.updateAttribute("test", "bar"); - edgeCollection.updateEdge(createdDoc.getKey(), doc, new EdgeUpdateOptions().streamTransactionId(tx.getId())) - .get(); - - // assert that the edge has not been updated from outside the tx - assertThat(edgeCollection.getEdge(createdDoc.getKey(), BaseEdgeDocument.class, null).get() - .getProperties()).containsEntry("test", "foo"); - - // assert that the edge has been updated from within the tx - assertThat(edgeCollection.getEdge(createdDoc.getKey(), BaseEdgeDocument.class, - new GraphDocumentReadOptions().streamTransactionId(tx.getId())).get().getProperties()).containsEntry( - "test", "bar"); - - db.commitStreamTransaction(tx.getId()).get(); - - // assert that the edge has been updated after commit - assertThat(edgeCollection.getEdge(createdDoc.getKey(), BaseEdgeDocument.class, null).get() - .getProperties()).containsEntry("test", "bar"); - } - - @Test - void deleteEdge() throws ExecutionException, InterruptedException { - assumeTrue(isSingleServer()); - assumeTrue(isAtLeastVersion(3, 5)); - assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); - - EdgeEntity createdDoc = edgeCollection.insertEdge(createEdgeValue(null), null).get(); - - StreamTransactionEntity tx = db.beginStreamTransaction( - new StreamTransactionOptions() - .readCollections(VERTEX_COLLECTION_1, VERTEX_COLLECTION_2, EDGE_COLLECTION) - .writeCollections(VERTEX_COLLECTION_1, VERTEX_COLLECTION_2, EDGE_COLLECTION)).get(); - - // delete edge from within the tx - edgeCollection.deleteEdge(createdDoc.getKey(), new EdgeDeleteOptions().streamTransactionId(tx.getId())).get(); - - // assert that the edge has not been deleted from outside the tx - assertThat(edgeCollection.getEdge(createdDoc.getKey(), BaseEdgeDocument.class, null).get()).isNotNull(); - - // assert that the edge has been deleted from within the tx - assertThat(edgeCollection.getEdge(createdDoc.getKey(), BaseEdgeDocument.class, - new GraphDocumentReadOptions().streamTransactionId(tx.getId())).get()).isNull(); - - db.commitStreamTransaction(tx.getId()).get(); - - // assert that the edge has been deleted after commit - assertThat(edgeCollection.getEdge(createdDoc.getKey(), BaseEdgeDocument.class, null).get()).isNull(); - } - -} diff --git a/shaded-integration-tests/src/test/native/java/com/arangodb/async/StreamTransactionTest.java b/shaded-integration-tests/src/test/native/java/com/arangodb/async/StreamTransactionTest.java deleted file mode 100644 index 658bab18b..000000000 --- a/shaded-integration-tests/src/test/native/java/com/arangodb/async/StreamTransactionTest.java +++ /dev/null @@ -1,362 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.async; - -import com.arangodb.ArangoDBException; -import com.arangodb.entity.*; -import com.arangodb.model.DocumentCreateOptions; -import com.arangodb.model.DocumentReadOptions; -import com.arangodb.model.StreamTransactionOptions; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.Test; - -import java.util.Arrays; -import java.util.List; -import java.util.Set; -import java.util.concurrent.ExecutionException; -import java.util.stream.Collectors; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.fail; -import static org.junit.jupiter.api.Assumptions.assumeTrue; - -/** - * @author Michele Rastelli - */ -class StreamTransactionTest extends BaseTest { - - private static final String COLLECTION_NAME = "db_stream_transaction_test"; - - public StreamTransactionTest() throws ExecutionException, InterruptedException { - if (db.collection(COLLECTION_NAME).exists().get()) - db.collection(COLLECTION_NAME).drop().get(); - - db.createCollection(COLLECTION_NAME, null).get(); - } - - @AfterEach - void teardown() throws ExecutionException, InterruptedException { - if (db.collection(COLLECTION_NAME).exists().get()) - db.collection(COLLECTION_NAME).drop().get(); - } - - @Test - void beginStreamTransaction() throws ExecutionException, InterruptedException { - assumeTrue(isSingleServer()); - assumeTrue(isAtLeastVersion(3, 5)); - assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); - - StreamTransactionEntity tx = db.beginStreamTransaction(null).get(); - assertThat(tx.getId()).isNotNull(); - assertThat(tx.getStatus()).isEqualTo(StreamTransactionStatus.running); - db.abortStreamTransaction(tx.getId()).get(); - } - - @Test - void beginStreamTransactionWithNonExistingCollectionsShouldThrow() throws ExecutionException, InterruptedException { - assumeTrue(isSingleServer()); - assumeTrue(isAtLeastVersion(3, 5)); - assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); - - try { - db.beginStreamTransaction(new StreamTransactionOptions().writeCollections("notExistingCollection")).get(); - fail(); - } catch (ExecutionException e) { - assertThat(e.getCause()).isInstanceOf(ArangoDBException.class); - } - } - - @Test - void abortStreamTransaction() throws ExecutionException, InterruptedException { - assumeTrue(isSingleServer()); - assumeTrue(isAtLeastVersion(3, 5)); - assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); - - StreamTransactionEntity begunTx = db.beginStreamTransaction(null).get(); - StreamTransactionEntity abortedTx = db.abortStreamTransaction(begunTx.getId()).get(); - - assertThat(abortedTx.getId()).isNotNull(); - assertThat(abortedTx.getId()).isEqualTo(begunTx.getId()); - assertThat(abortedTx.getStatus()).isEqualTo(StreamTransactionStatus.aborted); - } - - @Test - void abortStreamTransactionTwice() throws ExecutionException, InterruptedException { - assumeTrue(isSingleServer()); - assumeTrue(isAtLeastVersion(3, 5)); - assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); - - StreamTransactionEntity begunTx = db.beginStreamTransaction(null).get(); - db.abortStreamTransaction(begunTx.getId()).get(); - db.abortStreamTransaction(begunTx.getId()).get(); - } - - @Test - void abortStreamTransactionWhenTransactionIdDoesNotExistsShouldThrow() throws ExecutionException, - InterruptedException { - assumeTrue(isSingleServer()); - assumeTrue(isAtLeastVersion(3, 5)); - assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); - - try { - db.abortStreamTransaction("000000").get(); - fail(); - } catch (ExecutionException e) { - assertThat(e.getCause()).isInstanceOf(ArangoDBException.class); - } - } - - @Test - void abortStreamTransactionWithInvalidTransactionIdShouldThrow() throws ExecutionException, InterruptedException { - assumeTrue(isSingleServer()); - assumeTrue(isAtLeastVersion(3, 5)); - assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); - - try { - db.abortStreamTransaction("invalidTransactionId").get(); - fail(); - } catch (ExecutionException e) { - assertThat(e.getCause()).isInstanceOf(ArangoDBException.class); - } - } - - @Test - void abortCommittedStreamTransactionShouldThrow() throws ExecutionException, InterruptedException { - assumeTrue(isSingleServer()); - assumeTrue(isAtLeastVersion(3, 5)); - assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); - - StreamTransactionEntity createdTx = db.beginStreamTransaction(null).get(); - db.commitStreamTransaction(createdTx.getId()).get(); - - try { - db.abortStreamTransaction(createdTx.getId()).get(); - fail(); - } catch (ExecutionException e) { - assertThat(e.getCause()).isInstanceOf(ArangoDBException.class); - } - } - - @Test - void getStreamTransaction() throws ExecutionException, InterruptedException { - assumeTrue(isSingleServer()); - assumeTrue(isAtLeastVersion(3, 5)); - assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); - - StreamTransactionEntity createdTx = db.beginStreamTransaction(null).get(); - StreamTransactionEntity gotTx = db.getStreamTransaction(createdTx.getId()).get(); - - assertThat(gotTx.getId()).isNotNull(); - assertThat(gotTx.getId()).isEqualTo(createdTx.getId()); - assertThat(gotTx.getStatus()).isEqualTo(StreamTransactionStatus.running); - - db.abortStreamTransaction(createdTx.getId()).get(); - } - - @Test - void getStreamTransactionWhenTransactionIdDoesNotExistsShouldThrow() throws ExecutionException, - InterruptedException { - assumeTrue(isSingleServer()); - assumeTrue(isAtLeastVersion(3, 5)); - assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); - - try { - db.getStreamTransaction("000000").get(); - fail(); - } catch (ExecutionException e) { - assertThat(e.getCause()).isInstanceOf(ArangoDBException.class); - } - } - - @Test - void getStreamTransactionWithInvalidTransactionIdShouldThrow() throws ExecutionException, InterruptedException { - assumeTrue(isSingleServer()); - assumeTrue(isAtLeastVersion(3, 5)); - assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); - - try { - db.getStreamTransaction("invalidTransactionId").get(); - fail(); - } catch (ExecutionException e) { - assertThat(e.getCause()).isInstanceOf(ArangoDBException.class); - } - } - - @Test - void commitStreamTransaction() throws ExecutionException, InterruptedException { - assumeTrue(isSingleServer()); - assumeTrue(isAtLeastVersion(3, 5)); - assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); - - StreamTransactionEntity createdTx = db.beginStreamTransaction(null).get(); - StreamTransactionEntity committedTx = db.commitStreamTransaction(createdTx.getId()).get(); - - assertThat(committedTx.getId()).isNotNull(); - assertThat(committedTx.getId()).isEqualTo(createdTx.getId()); - assertThat(committedTx.getStatus()).isEqualTo(StreamTransactionStatus.committed); - } - - @Test - void commitStreamTransactionTwice() throws ExecutionException, InterruptedException { - assumeTrue(isSingleServer()); - assumeTrue(isAtLeastVersion(3, 5)); - assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); - - StreamTransactionEntity createdTx = db.beginStreamTransaction(null).get(); - db.commitStreamTransaction(createdTx.getId()).get(); - db.commitStreamTransaction(createdTx.getId()).get(); - } - - @Test - void commitStreamTransactionWhenTransactionIdDoesNotExistsShouldThrow() throws ExecutionException, - InterruptedException { - assumeTrue(isSingleServer()); - assumeTrue(isAtLeastVersion(3, 5)); - assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); - - try { - db.commitStreamTransaction("000000").get(); - fail(); - } catch (ExecutionException e) { - assertThat(e.getCause()).isInstanceOf(ArangoDBException.class); - } - } - - @Test - void commitStreamTransactionWithInvalidTransactionIdShouldThrow() throws ExecutionException, InterruptedException { - assumeTrue(isSingleServer()); - assumeTrue(isAtLeastVersion(3, 5)); - assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); - - try { - db.commitStreamTransaction("invalidTransactionId").get(); - fail(); - } catch (ExecutionException e) { - assertThat(e.getCause()).isInstanceOf(ArangoDBException.class); - } - } - - @Test - void commitAbortedStreamTransactionShouldThrow() throws ExecutionException, InterruptedException { - assumeTrue(isSingleServer()); - assumeTrue(isAtLeastVersion(3, 5)); - assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); - - StreamTransactionEntity createdTx = db.beginStreamTransaction(null).get(); - db.abortStreamTransaction(createdTx.getId()).get(); - - try { - db.commitStreamTransaction(createdTx.getId()).get(); - fail(); - } catch (ExecutionException e) { - assertThat(e.getCause()).isInstanceOf(ArangoDBException.class); - } - } - - @Test - void getDocument() throws ExecutionException, InterruptedException { - assumeTrue(isSingleServer()); - assumeTrue(isAtLeastVersion(3, 5)); - assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); - - StreamTransactionEntity tx = db - .beginStreamTransaction(new StreamTransactionOptions().readCollections(COLLECTION_NAME)).get(); - - // insert a document from outside the tx - DocumentCreateEntity externalDoc = db.collection(COLLECTION_NAME) - .insertDocument(new BaseDocument(), null).get(); - - // assert that the document is not found from within the tx - assertThat(db.collection(COLLECTION_NAME).getDocument(externalDoc.getKey(), BaseDocument.class, - new DocumentReadOptions().streamTransactionId(tx.getId())).get()).isNull(); - - db.abortStreamTransaction(tx.getId()).get(); - } - - @Test - void getDocumentWithNonExistingTransactionIdShouldThrow() throws ExecutionException, InterruptedException { - assumeTrue(isSingleServer()); - assumeTrue(isAtLeastVersion(3, 5)); - assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); - - try { - db.collection(COLLECTION_NAME) - .getDocument("docId", BaseDocument.class, new DocumentReadOptions().streamTransactionId("123456")) - .get(); - fail(); - } catch (ExecutionException e) { - assertThat(e.getCause()).isInstanceOf(ArangoDBException.class); - } - } - - @Test - void insertDocumentWithNonExistingTransactionIdShouldThrow() throws ExecutionException, InterruptedException { - assumeTrue(isSingleServer()); - assumeTrue(isAtLeastVersion(3, 5)); - assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); - - try { - db.collection(COLLECTION_NAME) - .insertDocument(new BaseDocument(), new DocumentCreateOptions().streamTransactionId("123456")).get(); - fail(); - } catch (ExecutionException e) { - assertThat(e.getCause()).isInstanceOf(ArangoDBException.class); - } - } - - @Test - void getDocumentWithInvalidTransactionIdShouldThrow() throws ExecutionException, InterruptedException { - assumeTrue(isSingleServer()); - assumeTrue(isAtLeastVersion(3, 5)); - assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); - - try { - db.collection(COLLECTION_NAME) - .getDocument("docId", BaseDocument.class, new DocumentReadOptions().streamTransactionId("abcde")) - .get(); - fail(); - } catch (ExecutionException e) { - assertThat(e.getCause()).isInstanceOf(ArangoDBException.class); - } - } - - @Test - void getStreamTransactions() throws ExecutionException, InterruptedException { - assumeTrue(isSingleServer()); - assumeTrue(isAtLeastVersion(3, 5)); - assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); - - StreamTransactionEntity tx1 = db.beginStreamTransaction(null).get(); - StreamTransactionEntity tx2 = db.beginStreamTransaction(null).get(); - - List createdIds = Arrays.asList(tx1.getId(), tx2.getId()); - Set gotTxs = db.getStreamTransactions().get().stream(). - filter(it -> createdIds.contains(it.getId())).collect(Collectors.toSet()); - - assertThat(gotTxs).hasSameSizeAs(createdIds); - assertThat(gotTxs.stream() - .allMatch(it -> it.getState() == StreamTransactionStatus.running)).isTrue(); - - db.abortStreamTransaction(tx1.getId()).get(); - db.abortStreamTransaction(tx2.getId()).get(); - } - -} diff --git a/shaded-integration-tests/src/test/native/java/com/arangodb/async/debug/ConsolidationIntervalMsecTest.java b/shaded-integration-tests/src/test/native/java/com/arangodb/async/debug/ConsolidationIntervalMsecTest.java deleted file mode 100644 index 330ce8eb9..000000000 --- a/shaded-integration-tests/src/test/native/java/com/arangodb/async/debug/ConsolidationIntervalMsecTest.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.async.debug; - -import com.arangodb.DbName; -import com.arangodb.async.ArangoDBAsync; -import com.arangodb.async.ArangoDatabaseAsync; -import com.arangodb.async.BaseTest; -import com.arangodb.entity.ViewEntity; -import com.arangodb.entity.ViewType; -import com.arangodb.entity.arangosearch.ArangoSearchPropertiesEntity; -import com.arangodb.entity.arangosearch.CollectionLink; -import com.arangodb.entity.arangosearch.FieldLink; -import com.arangodb.model.arangosearch.ArangoSearchCreateOptions; -import org.junit.jupiter.api.Test; - -import java.util.concurrent.ExecutionException; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assumptions.assumeTrue; - -/** - * @author Michele Rastelli - *

    - * https://github.com/arangodb/arangodb-java-driver-async/issues/15 - */ -class ConsolidationIntervalMsecTest extends BaseTest { - - @Test - void consolidationIntervalMsec() throws ExecutionException, InterruptedException { - assumeTrue(isAtLeastVersion(3, 4)); - - ArangoDBAsync arango = new ArangoDBAsync.Builder() - .loadProperties(config) - .user("root") - .password("test") - .build(); - - ArangoDatabaseAsync db = arango.db(DbName.of("database_of_things")); - if (db.exists().join()) { - db.drop().join(); - } - - db.create().join(); - db.collection("Thing").create().join(); - - ViewEntity result = db.createArangoSearch("ThingsSearchView", new ArangoSearchCreateOptions() - .consolidationIntervalMsec(60000L) //<== This line breaks it - .link(CollectionLink.on("Thing") - .fields(FieldLink.on("name") - .analyzers("identity")))) - .join(); - - assertThat(result.getName()).isEqualTo("ThingsSearchView"); - assertThat(result.getType()).isEqualTo(ViewType.ARANGO_SEARCH); - - ArangoSearchPropertiesEntity props = db.arangoSearch("ThingsSearchView").getProperties().join(); - assertThat(props.getName()).isEqualTo("ThingsSearchView"); - assertThat(props.getConsolidationIntervalMsec()).isEqualTo(60000L); - assertThat(props.getLinks().iterator().hasNext()).isTrue(); - assertThat(props.getLinks().iterator().next().getName()).isEqualTo("Thing"); - } - -} diff --git a/shaded-integration-tests/src/test/native/java/com/arangodb/async/example/ExampleBase.java b/shaded-integration-tests/src/test/native/java/com/arangodb/async/example/ExampleBase.java deleted file mode 100644 index 7881fd617..000000000 --- a/shaded-integration-tests/src/test/native/java/com/arangodb/async/example/ExampleBase.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.async.example; - -import com.arangodb.DbName; -import com.arangodb.async.ArangoCollectionAsync; -import com.arangodb.async.ArangoDBAsync; -import com.arangodb.async.ArangoDatabaseAsync; -import com.arangodb.config.ConfigUtils; -import org.junit.jupiter.api.AfterAll; -import org.junit.jupiter.api.BeforeAll; - -import java.util.concurrent.ExecutionException; - -/** - * @author Mark Vollmary - */ -public class ExampleBase { - - protected static final String COLLECTION_NAME = "json_example_collection"; - private static final DbName DB_NAME = DbName.of("json_example_db"); - protected static ArangoDatabaseAsync db; - protected static ArangoCollectionAsync collection; - private static ArangoDBAsync arangoDB; - - @BeforeAll - static void setUp() throws InterruptedException, ExecutionException { - arangoDB = new ArangoDBAsync.Builder() - .loadProperties(ConfigUtils.loadConfig()) - .build(); - if (arangoDB.db(DB_NAME).exists().get()) { - arangoDB.db(DB_NAME).drop().get(); - } - arangoDB.createDatabase(DB_NAME).get(); - db = arangoDB.db(DB_NAME); - db.createCollection(COLLECTION_NAME).get(); - collection = db.collection(COLLECTION_NAME); - } - - @AfterAll - static void tearDown() throws InterruptedException, ExecutionException { - db.drop().get(); - arangoDB.shutdown(); - } - -} diff --git a/shaded-integration-tests/src/test/native/java/com/arangodb/async/example/document/AqlQueryWithSpecialReturnTypesExampleTest.java b/shaded-integration-tests/src/test/native/java/com/arangodb/async/example/document/AqlQueryWithSpecialReturnTypesExampleTest.java deleted file mode 100644 index 9ab6624df..000000000 --- a/shaded-integration-tests/src/test/native/java/com/arangodb/async/example/document/AqlQueryWithSpecialReturnTypesExampleTest.java +++ /dev/null @@ -1,128 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.async.example.document; - -import com.arangodb.async.example.ExampleBase; -import com.arangodb.entity.BaseDocument; -import com.fasterxml.jackson.databind.node.ArrayNode; -import com.fasterxml.jackson.databind.node.ObjectNode; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.Test; - -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.UUID; -import java.util.concurrent.ExecutionException; - -import static org.assertj.core.api.Assertions.assertThat; - - -/** - * @author Mark Vollmary - */ -class AqlQueryWithSpecialReturnTypesExampleTest extends ExampleBase { - - @BeforeAll - static void before() throws InterruptedException, ExecutionException { - createExamples(); - } - - private static void createExamples() throws InterruptedException, ExecutionException { - for (int i = 0; i < 100; i++) { - final BaseDocument value = new BaseDocument(UUID.randomUUID().toString()); - value.addAttribute("name", "TestUser" + i); - value.addAttribute("gender", (i % 2) == 0 ? Gender.MALE : Gender.FEMALE); - value.addAttribute("age", i + 10); - db.collection(COLLECTION_NAME).insertDocument(value).get(); - } - } - - @Test - void aqlWithLimitQueryAsJsonObject() throws InterruptedException, ExecutionException { - final String query = "FOR t IN " + COLLECTION_NAME - + " FILTER t.age >= 20 && t.age < 30 && t.gender == @gender RETURN t"; - final Map bindVars = Collections.singletonMap("gender", Gender.FEMALE); - db.query(query, bindVars, null, ObjectNode.class) - .whenComplete((cursor, ex) -> cursor.forEachRemaining(node -> { - assertThat(node.get("name").asText()).isIn("TestUser11", "TestUser13", "TestUser15", "TestUser17" - , "TestUser19"); - assertThat(node.get("gender").asText()).isEqualTo(Gender.FEMALE.name()); - assertThat(node.get("age").asInt()).isIn(21, 23, 25, 27, 29); - })) - .get(); - } - - @Test - void aqlWithLimitQueryAsArrayNode() throws InterruptedException, ExecutionException { - final String query = "FOR t IN " + COLLECTION_NAME - + " FILTER t.age >= 20 && t.age < 30 && t.gender == @gender RETURN [t.name, t.gender, t.age]"; - final Map bindVars = Collections.singletonMap("gender", Gender.FEMALE); - db.query(query, bindVars, null, ArrayNode.class) - .whenComplete((cursor, ex) -> cursor.forEachRemaining(arrNode -> { - assertThat(arrNode.get(0).asText()).isIn("TestUser11", "TestUser13", "TestUser15", "TestUser17", - "TestUser19"); - assertThat(arrNode.get(1).asText()).isEqualTo(Gender.FEMALE.name()); - assertThat(arrNode.get(2).asInt()).isIn(21, 23, 25, 27, 29); - })) - .get(); - } - - @Test - void aqlWithLimitQueryAsMap() throws InterruptedException, ExecutionException { - final String query = "FOR t IN " + COLLECTION_NAME - + " FILTER t.age >= 20 && t.age < 30 && t.gender == @gender RETURN t"; - final Map bindVars = Collections.singletonMap("gender", Gender.FEMALE); - db.query(query, bindVars, null, Map.class) - .whenComplete((cursor, ex) -> cursor.forEachRemaining(map -> { - assertThat(map.get("name")).isNotNull(); - assertThat(String.valueOf(map.get("name"))).isIn("TestUser11", "TestUser13", "TestUser15", - "TestUser17", "TestUser19"); - assertThat(map.get("gender")).isNotNull(); - assertThat(String.valueOf(map.get("gender"))).isEqualTo(Gender.FEMALE.name()); - assertThat(map.get("age")).isNotNull(); - assertThat(Long.valueOf(map.get("age").toString())).isIn(21L, 23L, 25L, 27L, 29L); - })) - .get(); - } - - @Test - void aqlWithLimitQueryAsList() throws InterruptedException, ExecutionException { - final String query = "FOR t IN " + COLLECTION_NAME - + " FILTER t.age >= 20 && t.age < 30 && t.gender == @gender RETURN [t.name, t.gender, t.age]"; - final Map bindVars = Collections.singletonMap("gender", Gender.FEMALE); - db.query(query, bindVars, null, List.class) - .whenComplete((cursor, ex) -> cursor.forEachRemaining(list -> { - assertThat(list.get(0)).isNotNull(); - assertThat(String.valueOf(list.get(0))).isIn("TestUser11", "TestUser13", "TestUser15", - "TestUser17", "TestUser19"); - assertThat(list.get(1)).isNotNull(); - assertThat(Gender.valueOf(String.valueOf(list.get(1)))).isEqualTo(Gender.FEMALE); - assertThat(list.get(2)).isNotNull(); - assertThat(Long.valueOf(String.valueOf(list.get(2)))).isIn(21L, 23L, 25L, 27L, 29L); - })) - .get(); - } - - public enum Gender { - MALE, FEMALE - } -} diff --git a/shaded-integration-tests/src/test/native/java/com/arangodb/async/example/document/GetDocumentExampleTest.java b/shaded-integration-tests/src/test/native/java/com/arangodb/async/example/document/GetDocumentExampleTest.java deleted file mode 100644 index 11ef3c63f..000000000 --- a/shaded-integration-tests/src/test/native/java/com/arangodb/async/example/document/GetDocumentExampleTest.java +++ /dev/null @@ -1,94 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.async.example.document; - -import com.arangodb.async.example.ExampleBase; -import com.arangodb.entity.BaseDocument; -import com.arangodb.util.RawJson; -import com.fasterxml.jackson.databind.JsonNode; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.Test; - -import java.util.UUID; -import java.util.concurrent.ExecutionException; - -import static org.assertj.core.api.Assertions.assertThat; - - -/** - * @author Mark Vollmary - */ -class GetDocumentExampleTest extends ExampleBase { - - private static String key = null; - - @BeforeAll - static void before() throws InterruptedException, ExecutionException { - final BaseDocument value = new BaseDocument(UUID.randomUUID().toString()); - value.addAttribute("foo", "bar"); - key = collection.insertDocument(value).get().getKey(); - } - - @Test - void getAsBean() throws InterruptedException, ExecutionException { - collection.getDocument(key, TestEntity.class) - .whenComplete((doc, ex) -> { - assertThat(doc).isNotNull(); - assertThat(doc.getFoo()).isEqualTo("bar"); - }) - .get(); - } - - @Test - void getAsBaseDocument() throws InterruptedException, ExecutionException { - collection.getDocument(key, BaseDocument.class) - .whenComplete((doc, ex) -> { - assertThat(doc).isNotNull(); - assertThat(doc.getAttribute("foo")).isNotNull(); - assertThat(String.valueOf(doc.getAttribute("foo"))).isEqualTo("bar"); - }) - .get(); - } - - @Test - void getAsVPack() throws InterruptedException, ExecutionException { - collection.getDocument(key, JsonNode.class) - .whenComplete((doc, ex) -> { - assertThat(doc).isNotNull(); - assertThat(doc.get("foo").isTextual()).isEqualTo(true); - assertThat(doc.get("foo").asText()).isEqualTo("bar"); - }) - .get(); - } - - @Test - void getAsJson() throws InterruptedException, ExecutionException { - collection.getDocument(key, RawJson.class) - .whenComplete((doc, ex) -> { - assertThat(doc.getValue()) - .isNotNull() - .contains("foo") - .contains("bar"); - }) - .get(); - } - -} diff --git a/shaded-integration-tests/src/test/native/java/com/arangodb/async/example/document/ImportDocumentExampleTest.java b/shaded-integration-tests/src/test/native/java/com/arangodb/async/example/document/ImportDocumentExampleTest.java deleted file mode 100644 index dacf1bd87..000000000 --- a/shaded-integration-tests/src/test/native/java/com/arangodb/async/example/document/ImportDocumentExampleTest.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.async.example.document; - -import com.arangodb.async.example.ExampleBase; -import com.arangodb.entity.DocumentImportEntity; -import com.arangodb.model.DocumentImportOptions; -import org.junit.jupiter.api.Test; - -import java.util.List; -import java.util.UUID; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.atomic.AtomicLong; -import java.util.stream.Collectors; -import java.util.stream.IntStream; -import java.util.stream.Stream; - -import static org.junit.jupiter.api.Assertions.fail; - -/** - * @author Michele Rastelli - */ -class ImportDocumentExampleTest extends ExampleBase { - - private static final int MAX_PENDING_REQUESTS = 10; - - @Test - void importDocument() { - AtomicLong pendingReqsCount = new AtomicLong(); - - Stream> chunks = IntStream.range(0, 100) - .mapToObj(i -> IntStream.range(0, 500) - .mapToObj(it -> new TestEntity(UUID.randomUUID().toString())).collect(Collectors.toList()) - ); - - List> completableFutures = chunks - .map(p -> { - // wait for pending requests - while (pendingReqsCount.get() > MAX_PENDING_REQUESTS) { - try { - Thread.sleep(10); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - - pendingReqsCount.incrementAndGet(); - return collection.importDocuments(p, new DocumentImportOptions()) - .thenApply(it -> { - pendingReqsCount.decrementAndGet(); - return it; - }); - } - ) - .collect(Collectors.toList()); - - completableFutures.forEach(cf -> { - try { - cf.get(); - } catch (InterruptedException | ExecutionException e) { - e.printStackTrace(); - fail(); - } - }); - - } - -} diff --git a/shaded-integration-tests/src/test/native/java/com/arangodb/async/example/document/InsertDocumentExampleTest.java b/shaded-integration-tests/src/test/native/java/com/arangodb/async/example/document/InsertDocumentExampleTest.java deleted file mode 100644 index e55eda546..000000000 --- a/shaded-integration-tests/src/test/native/java/com/arangodb/async/example/document/InsertDocumentExampleTest.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.async.example.document; - -import com.arangodb.async.example.ExampleBase; -import com.arangodb.entity.BaseDocument; -import com.arangodb.util.RawJson; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.node.ObjectNode; -import org.junit.jupiter.api.Test; - -import java.util.UUID; -import java.util.concurrent.ExecutionException; - -import static org.assertj.core.api.Assertions.assertThat; - - -/** - * @author Mark Vollmary - */ -class InsertDocumentExampleTest extends ExampleBase { - - @Test - void insertBean() throws ExecutionException, InterruptedException { - collection.insertDocument(new TestEntity("bar")) - .whenComplete((doc, ex) -> assertThat(doc.getKey()).isNotNull()) - .get(); - } - - @Test - void insertBaseDocument() throws ExecutionException, InterruptedException { - final BaseDocument value = new BaseDocument(UUID.randomUUID().toString()); - value.addAttribute("foo", "bar"); - collection.insertDocument(value) - .whenComplete((doc, ex) -> assertThat(doc.getKey()).isNotNull()) - .get(); - } - - @Test - void insertJsonNode() throws ExecutionException, InterruptedException { - ObjectMapper mapper = new ObjectMapper(); - ObjectNode node = mapper.createObjectNode(); - node.put("foo", "bar"); - collection.insertDocument(node) - .whenComplete((doc, ex) -> assertThat(doc.getKey()).isNotNull()) - .get(); - } - - @Test - void insertJson() throws ExecutionException, InterruptedException { - collection.insertDocument(RawJson.of("{\"foo\":\"bar\"}")) - .whenComplete((doc, ex) -> assertThat(doc.getKey()).isNotNull()) - .get(); - } - -} diff --git a/shaded-integration-tests/src/test/native/java/com/arangodb/async/example/document/TestEntity.java b/shaded-integration-tests/src/test/native/java/com/arangodb/async/example/document/TestEntity.java deleted file mode 100644 index 2ef89c19f..000000000 --- a/shaded-integration-tests/src/test/native/java/com/arangodb/async/example/document/TestEntity.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.async.example.document; - -/** - * @author Mark Vollmary - */ -public class TestEntity { - - private String foo; - - public TestEntity() { - super(); - } - - public TestEntity(final String foo) { - super(); - this.foo = foo; - } - - public String getFoo() { - return foo; - } - - void setFoo(final String foo) { - this.foo = foo; - } - -} diff --git a/shaded-integration-tests/src/test/native/java/com/arangodb/async/example/graph/AQLActorsAndMoviesExampleTest.java b/shaded-integration-tests/src/test/native/java/com/arangodb/async/example/graph/AQLActorsAndMoviesExampleTest.java deleted file mode 100644 index d21f78f02..000000000 --- a/shaded-integration-tests/src/test/native/java/com/arangodb/async/example/graph/AQLActorsAndMoviesExampleTest.java +++ /dev/null @@ -1,605 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.async.example.graph; - -import com.arangodb.DbName; -import com.arangodb.async.ArangoCollectionAsync; -import com.arangodb.async.ArangoCursorAsync; -import com.arangodb.async.ArangoDBAsync; -import com.arangodb.async.ArangoDatabaseAsync; -import com.arangodb.config.ConfigUtils; -import com.arangodb.entity.BaseDocument; -import com.arangodb.entity.BaseEdgeDocument; -import com.arangodb.entity.CollectionType; -import com.arangodb.entity.DocumentCreateEntity; -import com.arangodb.model.CollectionCreateOptions; -import com.fasterxml.jackson.annotation.JsonCreator; -import com.fasterxml.jackson.annotation.JsonProperty; -import org.junit.jupiter.api.AfterAll; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.Test; - -import java.util.UUID; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ExecutionException; - -import static org.assertj.core.api.Assertions.assertThat; - - -/** - * @author Mark Vollmary - * @see - * AQL Example Queries on an - * Actors and Movies Database - */ -class AQLActorsAndMoviesExampleTest { - - private static final DbName TEST_DB = DbName.of("actors_movies_test_db"); - private static ArangoDBAsync arangoDB; - private static ArangoDatabaseAsync db; - - @BeforeAll - static void setUp() throws InterruptedException, ExecutionException { - arangoDB = new ArangoDBAsync.Builder() - .loadProperties(ConfigUtils.loadConfig()) - .build(); - if (arangoDB.db(TEST_DB).exists().get()) { - arangoDB.db(TEST_DB).drop().get(); - } - arangoDB.createDatabase(TEST_DB).get(); - db = arangoDB.db(TEST_DB); - createData(); - } - - @AfterAll - static void tearDown() throws InterruptedException, ExecutionException { - db.drop().get(); - arangoDB.shutdown(); - } - - private static DocumentCreateEntity saveMovie( - final ArangoCollectionAsync movies, - final String key, - final String title, - final int released, - final String tagline) throws InterruptedException, ExecutionException { - final BaseDocument value = new BaseDocument(UUID.randomUUID().toString()); - value.setKey(key); - value.addAttribute("title", title); - value.addAttribute("released", released); - value.addAttribute("tagline", tagline); - return movies.insertDocument(value).get(); - } - - private static DocumentCreateEntity saveActor( - final ArangoCollectionAsync actors, - final String key, - final String name, - final int born) throws InterruptedException, ExecutionException { - final BaseDocument value = new BaseDocument(UUID.randomUUID().toString()); - value.setKey(key); - value.addAttribute("name", name); - value.addAttribute("born", born); - return actors.insertDocument(value).get(); - } - - private static void saveActsIn( - final ArangoCollectionAsync actsIn, - final String actor, - final String movie, - final String[] roles, - final int year) throws InterruptedException, ExecutionException { - final BaseEdgeDocument value = new BaseEdgeDocument(); - value.setFrom(actor); - value.setTo(movie); - value.addAttribute("roles", roles); - value.addAttribute("year", year); - actsIn.insertDocument(value).get(); - } - - private static void createData() throws InterruptedException, ExecutionException { - db.createCollection("actors").get(); - final ArangoCollectionAsync actors = db.collection("actors"); - db.createCollection("movies").get(); - final ArangoCollectionAsync movies = db.collection("movies"); - db.createCollection("actsIn", new CollectionCreateOptions().type(CollectionType.EDGES)).get(); - final ArangoCollectionAsync actsIn = db.collection("actsIn"); - - final String theMatrix = saveMovie(movies, "TheMatrix", "The Matrix", 1999, "Welcome to the Real World") - .getId(); - final String keanu = saveActor(actors, "Keanu", "Keanu Reeves", 1964).getId(); - final String carrie = saveActor(actors, "Carrie", "Carrie-Anne Moss", 1967).getId(); - final String laurence = saveActor(actors, "Laurence", "Laurence Fishburne", 1961).getId(); - final String hugo = saveActor(actors, "Hugo", "Hugo Weaving", 1960).getId(); - final String emil = saveActor(actors, "Emil", "Emil Eifrem", 1978).getId(); - - saveActsIn(actsIn, keanu, theMatrix, new String[]{"Neo"}, 1999); - saveActsIn(actsIn, carrie, theMatrix, new String[]{"Trinity"}, 1999); - saveActsIn(actsIn, laurence, theMatrix, new String[]{"Morpheus"}, 1999); - saveActsIn(actsIn, hugo, theMatrix, new String[]{"Agent Smith"}, 1999); - saveActsIn(actsIn, emil, theMatrix, new String[]{"Emil"}, 1999); - - final String theMatrixReloaded = saveMovie(movies, "TheMatrixReloaded", "The Matrix Reloaded", 2003, - "Free your mind").getId(); - saveActsIn(actsIn, keanu, theMatrixReloaded, new String[]{"Neo"}, 2003); - saveActsIn(actsIn, carrie, theMatrixReloaded, new String[]{"Trinity"}, 2003); - saveActsIn(actsIn, laurence, theMatrixReloaded, new String[]{"Morpheus"}, 2003); - saveActsIn(actsIn, hugo, theMatrixReloaded, new String[]{"Agent Smith"}, 2003); - - final String theMatrixRevolutions = saveMovie(movies, "TheMatrixRevolutions", "The Matrix Revolutions", 2003, - "Everything that has a beginning has an end").getId(); - saveActsIn(actsIn, keanu, theMatrixRevolutions, new String[]{"Neo"}, 2003); - saveActsIn(actsIn, carrie, theMatrixRevolutions, new String[]{"Trinity"}, 2003); - saveActsIn(actsIn, laurence, theMatrixRevolutions, new String[]{"Morpheus"}, 2003); - saveActsIn(actsIn, hugo, theMatrixRevolutions, new String[]{"Agent Smith"}, 2003); - - final String theDevilsAdvocate = saveMovie(movies, "TheDevilsAdvocate", "The Devil's Advocate", 1997, - "Evil has its winning ways").getId(); - final String charlize = saveActor(actors, "Charlize", "Charlize Theron", 1975).getId(); - final String al = saveActor(actors, "Al", "Al Pacino", 1940).getId(); - saveActsIn(actsIn, keanu, theDevilsAdvocate, new String[]{"Kevin Lomax"}, 1997); - saveActsIn(actsIn, charlize, theDevilsAdvocate, new String[]{"Mary Ann Lomax"}, 1997); - saveActsIn(actsIn, al, theDevilsAdvocate, new String[]{"John Milton"}, 1997); - - final String AFewGoodMen = saveMovie(movies, "AFewGoodMen", "A Few Good Men", 1992, - "In the heart of the nation's capital, in a courthouse of the U.S. government, one man will stop at " + - "nothing to keep his honor, and one will stop at nothing to find the truth.") - .getId(); - final String tomC = saveActor(actors, "TomC", "Tom Cruise", 1962).getId(); - final String jackN = saveActor(actors, "JackN", "Jack Nicholson", 1937).getId(); - final String demiM = saveActor(actors, "DemiM", "Demi Moore", 1962).getId(); - final String kevinB = saveActor(actors, "KevinB", "Kevin Bacon", 1958).getId(); - final String kieferS = saveActor(actors, "KieferS", "Kiefer Sutherland", 1966).getId(); - final String noahW = saveActor(actors, "NoahW", "Noah Wyle", 1971).getId(); - final String cubaG = saveActor(actors, "CubaG", "Cuba Gooding Jr.", 1968).getId(); - final String kevinP = saveActor(actors, "KevinP", "Kevin Pollak", 1957).getId(); - final String jTW = saveActor(actors, "JTW", "J.T. Walsh", 1943).getId(); - final String jamesM = saveActor(actors, "JamesM", "James Marshall", 1967).getId(); - final String christopherG = saveActor(actors, "ChristopherG", "Christopher Guest", 1948).getId(); - saveActsIn(actsIn, tomC, AFewGoodMen, new String[]{"Lt. Daniel Kaffee"}, 1992); - saveActsIn(actsIn, jackN, AFewGoodMen, new String[]{"Col. Nathan R. Jessup"}, 1992); - saveActsIn(actsIn, demiM, AFewGoodMen, new String[]{"Lt. Cdr. JoAnne Galloway"}, 1992); - saveActsIn(actsIn, kevinB, AFewGoodMen, new String[]{"Capt. Jack Ross"}, 1992); - saveActsIn(actsIn, kieferS, AFewGoodMen, new String[]{"Lt. Jonathan Kendrick"}, 1992); - saveActsIn(actsIn, noahW, AFewGoodMen, new String[]{"Cpl. Jeffrey Barnes"}, 1992); - saveActsIn(actsIn, cubaG, AFewGoodMen, new String[]{"Cpl. Carl Hammaker"}, 1992); - saveActsIn(actsIn, kevinP, AFewGoodMen, new String[]{"Lt. Sam Weinberg"}, 1992); - saveActsIn(actsIn, jTW, AFewGoodMen, new String[]{"Lt. Col. Matthew Andrew Markinson"}, 1992); - saveActsIn(actsIn, jamesM, AFewGoodMen, new String[]{"Pfc. Louden Downey"}, 1992); - saveActsIn(actsIn, christopherG, AFewGoodMen, new String[]{"Dr. Stone"}, 1992); - - final String topGun = saveMovie(movies, "TopGun", "Top Gun", 1986, "I feel the need, the need for speed.") - .getId(); - final String kellyM = saveActor(actors, "KellyM", "Kelly McGillis", 1957).getId(); - final String valK = saveActor(actors, "ValK", "Val Kilmer", 1959).getId(); - final String anthonyE = saveActor(actors, "AnthonyE", "Anthony Edwards", 1962).getId(); - final String tomS = saveActor(actors, "TomS", "Tom Skerritt", 1933).getId(); - final String megR = saveActor(actors, "MegR", "Meg Ryan", 1961).getId(); - saveActsIn(actsIn, tomC, topGun, new String[]{"Maverick"}, 1986); - saveActsIn(actsIn, kellyM, topGun, new String[]{"Charlie"}, 1986); - saveActsIn(actsIn, valK, topGun, new String[]{"Iceman"}, 1986); - saveActsIn(actsIn, anthonyE, topGun, new String[]{"Goose"}, 1986); - saveActsIn(actsIn, tomS, topGun, new String[]{"Viper"}, 1986); - saveActsIn(actsIn, megR, topGun, new String[]{"Carole"}, 1986); - - final String jerryMaguire = saveMovie(movies, "JerryMaguire", "Jerry Maguire", 2000, - "The rest of his life begins now.").getId(); - final String reneeZ = saveActor(actors, "ReneeZ", "Renee Zellweger", 1969).getId(); - final String kellyP = saveActor(actors, "KellyP", "Kelly Preston", 1962).getId(); - final String jerryO = saveActor(actors, "JerryO", "Jerry O'Connell", 1974).getId(); - final String jayM = saveActor(actors, "JayM", "Jay Mohr", 1970).getId(); - final String bonnieH = saveActor(actors, "BonnieH", "Bonnie Hunt", 1961).getId(); - final String reginaK = saveActor(actors, "ReginaK", "Regina King", 1971).getId(); - final String jonathanL = saveActor(actors, "JonathanL", "Jonathan Lipnicki", 1996).getId(); - saveActsIn(actsIn, tomC, jerryMaguire, new String[]{"Jerry Maguire"}, 2000); - saveActsIn(actsIn, cubaG, jerryMaguire, new String[]{"Rod Tidwell"}, 2000); - saveActsIn(actsIn, reneeZ, jerryMaguire, new String[]{"Dorothy Boyd"}, 2000); - saveActsIn(actsIn, kellyP, jerryMaguire, new String[]{"Avery Bishop"}, 2000); - saveActsIn(actsIn, jerryO, jerryMaguire, new String[]{"Frank Cushman"}, 2000); - saveActsIn(actsIn, jayM, jerryMaguire, new String[]{"Bob Sugar"}, 2000); - saveActsIn(actsIn, bonnieH, jerryMaguire, new String[]{"Laurel Boyd"}, 2000); - saveActsIn(actsIn, reginaK, jerryMaguire, new String[]{"Marcee Tidwell"}, 2000); - saveActsIn(actsIn, jonathanL, jerryMaguire, new String[]{"Ray Boyd"}, 2000); - - final String standByMe = saveMovie(movies, "StandByMe", "Stand By Me", 1986, - "For some, it's the last real taste of innocence, and the first real taste of life. But for everyone," + - " it's the time that memories are made of.") - .getId(); - final String riverP = saveActor(actors, "RiverP", "River Phoenix", 1970).getId(); - final String coreyF = saveActor(actors, "CoreyF", "Corey Feldman", 1971).getId(); - final String wilW = saveActor(actors, "WilW", "Wil Wheaton", 1972).getId(); - final String johnC = saveActor(actors, "JohnC", "John Cusack", 1966).getId(); - final String marshallB = saveActor(actors, "MarshallB", "Marshall Bell", 1942).getId(); - saveActsIn(actsIn, wilW, standByMe, new String[]{"Gordie Lachance"}, 1986); - saveActsIn(actsIn, riverP, standByMe, new String[]{"Chris Chambers"}, 1986); - saveActsIn(actsIn, jerryO, standByMe, new String[]{"Vern Tessio"}, 1986); - saveActsIn(actsIn, coreyF, standByMe, new String[]{"Teddy Duchamp"}, 1986); - saveActsIn(actsIn, johnC, standByMe, new String[]{"Denny Lachance"}, 1986); - saveActsIn(actsIn, kieferS, standByMe, new String[]{"Ace Merrill"}, 1986); - saveActsIn(actsIn, marshallB, standByMe, new String[]{"Mr. Lachance"}, 1986); - - final String asGoodAsItGets = saveMovie(movies, "AsGoodAsItGets", "As Good as It Gets", 1997, - "A comedy from the heart that goes for the throat.").getId(); - final String helenH = saveActor(actors, "HelenH", "Helen Hunt", 1963).getId(); - final String gregK = saveActor(actors, "GregK", "Greg Kinnear", 1963).getId(); - saveActsIn(actsIn, jackN, asGoodAsItGets, new String[]{"Melvin Udall"}, 1997); - saveActsIn(actsIn, helenH, asGoodAsItGets, new String[]{"Carol Connelly"}, 1997); - saveActsIn(actsIn, gregK, asGoodAsItGets, new String[]{"Simon Bishop"}, 1997); - saveActsIn(actsIn, cubaG, asGoodAsItGets, new String[]{"Frank Sachs"}, 1997); - - final String whatDreamsMayCome = saveMovie(movies, "WhatDreamsMayCome", "What Dreams May Come", 1998, - "After life there is more. The end is just the beginning.").getId(); - final String annabellaS = saveActor(actors, "AnnabellaS", "Annabella Sciorra", 1960).getId(); - final String maxS = saveActor(actors, "MaxS", "Max von Sydow", 1929).getId(); - final String wernerH = saveActor(actors, "WernerH", "Werner Herzog", 1942).getId(); - final String robin = saveActor(actors, "Robin", "Robin Williams", 1951).getId(); - saveActsIn(actsIn, robin, whatDreamsMayCome, new String[]{"Chris Nielsen"}, 1998); - saveActsIn(actsIn, cubaG, whatDreamsMayCome, new String[]{"Albert Lewis"}, 1998); - saveActsIn(actsIn, annabellaS, whatDreamsMayCome, new String[]{"Annie Collins-Nielsen"}, 1998); - saveActsIn(actsIn, maxS, whatDreamsMayCome, new String[]{"The Tracker"}, 1998); - saveActsIn(actsIn, wernerH, whatDreamsMayCome, new String[]{"The Face"}, 1998); - - final String snowFallingonCedars = saveMovie(movies, "SnowFallingonCedars", "Snow Falling on Cedars", 1999, - "First loves last. Forever.").getId(); - final String ethanH = saveActor(actors, "EthanH", "Ethan Hawke", 1970).getId(); - final String rickY = saveActor(actors, "RickY", "Rick Yune", 1971).getId(); - final String jamesC = saveActor(actors, "JamesC", "James Cromwell", 1940).getId(); - saveActsIn(actsIn, ethanH, snowFallingonCedars, new String[]{"Ishmael Chambers"}, 1999); - saveActsIn(actsIn, rickY, snowFallingonCedars, new String[]{"Kazuo Miyamoto"}, 1999); - saveActsIn(actsIn, maxS, snowFallingonCedars, new String[]{"Nels Gudmundsson"}, 1999); - saveActsIn(actsIn, jamesC, snowFallingonCedars, new String[]{"Judge Fielding"}, 1999); - - final String youveGotMail = saveMovie(movies, "YouveGotMail", "You've Got Mail", 1998, - "At odds in life... in love on-line.").getId(); - final String parkerP = saveActor(actors, "ParkerP", "Parker Posey", 1968).getId(); - final String daveC = saveActor(actors, "DaveC", "Dave Chappelle", 1973).getId(); - final String steveZ = saveActor(actors, "SteveZ", "Steve Zahn", 1967).getId(); - final String tomH = saveActor(actors, "TomH", "Tom Hanks", 1956).getId(); - saveActsIn(actsIn, tomH, youveGotMail, new String[]{"Joe Fox"}, 1998); - saveActsIn(actsIn, megR, youveGotMail, new String[]{"Kathleen Kelly"}, 1998); - saveActsIn(actsIn, gregK, youveGotMail, new String[]{"Frank Navasky"}, 1998); - saveActsIn(actsIn, parkerP, youveGotMail, new String[]{"Patricia Eden"}, 1998); - saveActsIn(actsIn, daveC, youveGotMail, new String[]{"Kevin Jackson"}, 1998); - saveActsIn(actsIn, steveZ, youveGotMail, new String[]{"George Pappas"}, 1998); - - final String sleeplessInSeattle = saveMovie(movies, "SleeplessInSeattle", "Sleepless in Seattle", 1993, - "What if someone you never met, someone you never saw, someone you never knew was the only someone " + - "for you?") - .getId(); - final String ritaW = saveActor(actors, "RitaW", "Rita Wilson", 1956).getId(); - final String billPull = saveActor(actors, "BillPull", "Bill Pullman", 1953).getId(); - final String victorG = saveActor(actors, "VictorG", "Victor Garber", 1949).getId(); - final String rosieO = saveActor(actors, "RosieO", "Rosie O'Donnell", 1962).getId(); - saveActsIn(actsIn, tomH, sleeplessInSeattle, new String[]{"Sam Baldwin"}, 1993); - saveActsIn(actsIn, megR, sleeplessInSeattle, new String[]{"Annie Reed"}, 1993); - saveActsIn(actsIn, ritaW, sleeplessInSeattle, new String[]{"Suzy"}, 1993); - saveActsIn(actsIn, billPull, sleeplessInSeattle, new String[]{"Walter"}, 1993); - saveActsIn(actsIn, victorG, sleeplessInSeattle, new String[]{"Greg"}, 1993); - saveActsIn(actsIn, rosieO, sleeplessInSeattle, new String[]{"Becky"}, 1993); - - final String joeVersustheVolcano = saveMovie(movies, "JoeVersustheVolcano", "Joe Versus the Volcano", 1990, - "A story of love, lava and burning desire.").getId(); - final String nathan = saveActor(actors, "Nathan", "Nathan Lane", 1956).getId(); - saveActsIn(actsIn, tomH, joeVersustheVolcano, new String[]{"Joe Banks"}, 1990); - saveActsIn(actsIn, megR, joeVersustheVolcano, - new String[]{"DeDe', 'Angelica Graynamore', 'Patricia Graynamore"}, 1990); - saveActsIn(actsIn, nathan, joeVersustheVolcano, new String[]{"Baw"}, 1990); - - final String whenHarryMetSally = saveMovie(movies, "WhenHarryMetSally", "When Harry Met Sally", 1998, - "At odds in life... in love on-line.").getId(); - final String billyC = saveActor(actors, "BillyC", "Billy Crystal", 1948).getId(); - final String carrieF = saveActor(actors, "CarrieF", "Carrie Fisher", 1956).getId(); - final String brunoK = saveActor(actors, "BrunoK", "Bruno Kirby", 1949).getId(); - saveActsIn(actsIn, billyC, whenHarryMetSally, new String[]{"Harry Burns"}, 1998); - saveActsIn(actsIn, megR, whenHarryMetSally, new String[]{"Sally Albright"}, 1998); - saveActsIn(actsIn, carrieF, whenHarryMetSally, new String[]{"Marie"}, 1998); - saveActsIn(actsIn, brunoK, whenHarryMetSally, new String[]{"Jess"}, 1998); - } - - /** - * @throws ExecutionException - * @throws InterruptedException - * @see AQL - * Example Queries on an Actors and Movies Database - */ - @Test - void allActorsActsInMovie1or2() throws InterruptedException, ExecutionException { - final CompletableFuture> f = db.query( - "WITH actors, movies FOR x IN ANY 'movies/TheMatrix' actsIn OPTIONS {bfs: true, uniqueVertices: " + - "'global'} RETURN x._id", - null, null, String.class); - f.whenComplete((cursor, ex) -> assertThat(cursor.asListRemaining()).contains("actors/Keanu", "actors/Hugo", - "actors/Emil", "actors/Carrie", "actors/Laurence")).get(); - } - - /** - * @throws ExecutionException - * @throws InterruptedException - * @see AQL - * Example Queries on an Actors and Movies Database - */ - @Test - void allActorsActsInMovie1or2UnionDistinct() throws InterruptedException, ExecutionException { - final CompletableFuture> f = db.query( - "WITH actors, movies FOR x IN UNION_DISTINCT ((FOR y IN ANY 'movies/TheMatrix' actsIn OPTIONS {bfs: " + - "true, uniqueVertices: 'global'} RETURN y._id), (FOR y IN ANY 'movies/TheDevilsAdvocate' " + - "actsIn OPTIONS {bfs: true, uniqueVertices: 'global'} RETURN y._id)) RETURN x", - null, null, String.class); - f.whenComplete((cursor, ex) -> assertThat(cursor.asListRemaining()).contains( - "actors/Emil", "actors/Hugo", "actors/Carrie", - "actors/Laurence", "actors/Keanu", "actors/Al", "actors/Charlize")).get(); - } - - /** - * @throws ExecutionException - * @throws InterruptedException - * @see AQL - * Example Queries on an Actors and Movies Database - */ - @Test - void allActorsActsInMovie1and2() throws InterruptedException, ExecutionException { - final CompletableFuture> f = db.query( - "WITH actors, movies FOR x IN INTERSECTION ((FOR y IN ANY 'movies/TheMatrix' actsIn OPTIONS {bfs: " + - "true, uniqueVertices: 'global'} RETURN y._id), (FOR y IN ANY 'movies/TheDevilsAdvocate' " + - "actsIn OPTIONS {bfs: true, uniqueVertices: 'global'} RETURN y._id)) RETURN x", - null, null, String.class); - f.whenComplete((cursor, ex) -> assertThat(cursor.asListRemaining()).contains("actors/Keanu")).get(); - } - - /** - * @throws ExecutionException - * @throws InterruptedException - * @see AQL - * Example Queries on an Actors and Movies Database - */ - @Test - void allMoviesBetweenActor1andActor2() throws InterruptedException, ExecutionException { - final CompletableFuture> f = db.query( - "WITH actors, movies FOR x IN INTERSECTION ((FOR y IN ANY 'actors/Hugo' actsIn OPTIONS {bfs: true, " + - "uniqueVertices: 'global'} RETURN y._id), (FOR y IN ANY 'actors/Keanu' actsIn OPTIONS {bfs: " + - "true, uniqueVertices: 'global'} RETURN y._id)) RETURN x", - null, null, String.class); - f.whenComplete((cursor, ex) -> assertThat(cursor.asListRemaining()).contains("movies/TheMatrixRevolutions", - "movies/TheMatrixReloaded", "movies/TheMatrix")).get(); - } - - /** - * @throws ExecutionException - * @throws InterruptedException - * @see AQL - * Example Queries on an Actors and Movies Database - */ - @Test - void allActorsWhoActedIn3orMoreMovies() throws InterruptedException, ExecutionException { - final CompletableFuture> f = db.query( - "FOR x IN actsIn COLLECT actor = x._from WITH COUNT INTO counter FILTER counter >= 3 RETURN {actor: " + - "actor, movies: counter}", - null, null, Actor.class); - f.whenComplete((cursor, ex) -> assertThat(cursor.asListRemaining()).contains( - new Actor("actors/Carrie", 3), new Actor("actors/CubaG", 4), new Actor("actors/Hugo", 3), - new Actor("actors/Keanu", 4), new Actor("actors/Laurence", 3), new Actor("actors/MegR", 5), - new Actor("actors/TomC", 3), new Actor("actors/TomH", 3))).get(); - } - - /** - * @throws ExecutionException - * @throws InterruptedException - * @see AQL - * Example Queries on an Actors and Movies Database - */ - @Test - void allMoviesWhereExactly6ActorsActedIn() throws InterruptedException, ExecutionException { - final CompletableFuture> f = db.query( - "FOR x IN actsIn COLLECT movie = x._to WITH COUNT INTO counter FILTER counter == 6 RETURN movie", null, - null, String.class); - f.whenComplete((cursor, ex) -> assertThat(cursor.asListRemaining()).contains("movies/SleeplessInSeattle", - "movies/TopGun", "movies/YouveGotMail")).get(); - } - - /** - * @throws ExecutionException - * @throws InterruptedException - * @see AQL - * Example Queries on an Actors and Movies Database - */ - @Test - void theNumberOfActorsByMovie() throws InterruptedException, ExecutionException { - final CompletableFuture> f = db.query( - "FOR x IN actsIn COLLECT movie = x._to WITH COUNT INTO counter RETURN {movie: movie, actors: counter}", - null, null, Movie.class); - f.whenComplete((cursor, ex) -> assertThat(cursor.asListRemaining()).contains( - new Movie("movies/AFewGoodMen", 11), new Movie("movies/AsGoodAsItGets", 4), - new Movie("movies/JerryMaguire", 9), new Movie("movies/JoeVersustheVolcano", 3), - new Movie("movies/SleeplessInSeattle", 6), new Movie("movies/SnowFallingonCedars", 4), - new Movie("movies/StandByMe", 7), new Movie("movies/TheDevilsAdvocate", 3), - new Movie("movies/TheMatrix", 5), new Movie("movies/TheMatrixReloaded", 4), - new Movie("movies/TheMatrixRevolutions", 4), new Movie("movies/TopGun", 6), - new Movie("movies/WhatDreamsMayCome", 5), new Movie("movies/WhenHarryMetSally", 4), - new Movie("movies/YouveGotMail", 6))).get(); - } - - /** - * @throws ExecutionException - * @throws InterruptedException - * @see AQL - * Example Queries on an Actors and Movies Database - */ - @Test - void theNumberOfMoviesByActor() throws InterruptedException, ExecutionException { - final CompletableFuture> f = db.query( - "FOR x IN actsIn COLLECT actor = x._from WITH COUNT INTO counter RETURN {actor: actor, movies: " + - "counter}", - null, null, Actor.class); - f.whenComplete((cursor, ex) -> assertThat(cursor.asListRemaining()).contains( - new Actor("actors/Al", 1), new Actor("actors/AnnabellaS", 1), new Actor("actors/AnthonyE", 1), - new Actor("actors/BillPull", 1), new Actor("actors/BillyC", 1), new Actor("actors/BonnieH", 1), - new Actor("actors/BrunoK", 1), new Actor("actors/Carrie", 3), new Actor("actors/CarrieF", 1), - new Actor("actors/Charlize", 1), new Actor("actors/ChristopherG", 1), new Actor("actors/CoreyF", 1), - new Actor("actors/CubaG", 4), new Actor("actors/DaveC", 1), new Actor("actors/DemiM", 1), - new Actor("actors/Emil", 1), new Actor("actors/EthanH", 1), new Actor("actors/GregK", 2), - new Actor("actors/HelenH", 1), new Actor("actors/Hugo", 3), new Actor("actors/JackN", 2), - new Actor("actors/JamesC", 1), new Actor("actors/JamesM", 1), new Actor("actors/JayM", 1), - new Actor("actors/JerryO", 2), new Actor("actors/JohnC", 1), new Actor("actors/JonathanL", 1), - new Actor("actors/JTW", 1), new Actor("actors/Keanu", 4), new Actor("actors/KellyM", 1), - new Actor("actors/KellyP", 1), new Actor("actors/KevinB", 1), new Actor("actors/KevinP", 1), - new Actor("actors/KieferS", 2), new Actor("actors/Laurence", 3), new Actor("actors/MarshallB", 1), - new Actor("actors/MaxS", 2), new Actor("actors/MegR", 5), new Actor("actors/Nathan", 1), - new Actor("actors/NoahW", 1), new Actor("actors/ParkerP", 1), new Actor("actors/ReginaK", 1), - new Actor("actors/ReneeZ", 1), new Actor("actors/RickY", 1), new Actor("actors/RitaW", 1), - new Actor("actors/RiverP", 1), new Actor("actors/Robin", 1), new Actor("actors/RosieO", 1), - new Actor("actors/SteveZ", 1), new Actor("actors/TomC", 3), new Actor("actors/TomH", 3), - new Actor("actors/TomS", 1), new Actor("actors/ValK", 1), new Actor("actors/VictorG", 1), - new Actor("actors/WernerH", 1), new Actor("actors/WilW", 1))).get(); - } - - /** - * @throws ExecutionException - * @throws InterruptedException - * @see AQL - * Example Queries on an Actors and Movies Database - */ - @Test - void theNumberOfMoviesActedInBetween2005and2010byActor() throws InterruptedException, ExecutionException { - final CompletableFuture> f = db.query( - "FOR x IN actsIn FILTER x.year >= 1990 && x.year <= 1995 COLLECT actor = x._from WITH COUNT INTO " + - "counter RETURN {actor: actor, movies: counter}", - null, null, Actor.class); - f.whenComplete((cursor, ex) -> assertThat(cursor.asListRemaining()).contains( - new Actor("actors/BillPull", 1), new Actor("actors/ChristopherG", 1), - new Actor("actors/CubaG", 1), new Actor("actors/DemiM", 1), new Actor("actors/JackN", 1), - new Actor("actors/JamesM", 1), new Actor("actors/JTW", 1), new Actor("actors/KevinB", 1), - new Actor("actors/KieferS", 1), new Actor("actors/MegR", 2), new Actor("actors/Nathan", 1), - new Actor("actors/NoahW", 1), new Actor("actors/RitaW", 1), new Actor("actors/RosieO", 1), - new Actor("actors/TomC", 1), new Actor("actors/TomH", 2), new Actor("actors/VictorG", 1))).get(); - } - - public static class Actor { - private final String actor; - private final Integer movies; - - - @JsonCreator - public Actor(@JsonProperty("actor") final String actor, @JsonProperty("movies") final Integer movies) { - super(); - this.actor = actor; - this.movies = movies; - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((actor == null) ? 0 : actor.hashCode()); - result = prime * result + ((movies == null) ? 0 : movies.hashCode()); - return result; - } - - @Override - public boolean equals(final Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (getClass() != obj.getClass()) { - return false; - } - final Actor other = (Actor) obj; - if (actor == null) { - if (other.actor != null) { - return false; - } - } else if (!actor.equals(other.actor)) { - return false; - } - if (movies == null) { - return other.movies == null; - } else return movies.equals(other.movies); - } - - } - - public static class Movie { - private final String movie; - private final Integer actors; - - @JsonCreator - public Movie(@JsonProperty("movie") final String movie, @JsonProperty("actors") final Integer actors) { - super(); - this.movie = movie; - this.actors = actors; - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((actors == null) ? 0 : actors.hashCode()); - result = prime * result + ((movie == null) ? 0 : movie.hashCode()); - return result; - } - - @Override - public boolean equals(final Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (getClass() != obj.getClass()) { - return false; - } - final Movie other = (Movie) obj; - if (actors == null) { - if (other.actors != null) { - return false; - } - } else if (!actors.equals(other.actors)) { - return false; - } - if (movie == null) { - return other.movie == null; - } else return movie.equals(other.movie); - } - - } - -} diff --git a/shaded-integration-tests/src/test/native/java/com/arangodb/async/example/graph/BaseGraphTest.java b/shaded-integration-tests/src/test/native/java/com/arangodb/async/example/graph/BaseGraphTest.java deleted file mode 100644 index 41a4e6edf..000000000 --- a/shaded-integration-tests/src/test/native/java/com/arangodb/async/example/graph/BaseGraphTest.java +++ /dev/null @@ -1,116 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.async.example.graph; - -import com.arangodb.DbName; -import com.arangodb.async.ArangoDBAsync; -import com.arangodb.async.ArangoDatabaseAsync; -import com.arangodb.config.ConfigUtils; -import com.arangodb.entity.EdgeDefinition; -import com.arangodb.entity.VertexEntity; -import org.junit.jupiter.api.AfterAll; -import org.junit.jupiter.api.BeforeAll; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.concurrent.ExecutionException; - -/** - * @author Mark Vollmary - */ -public abstract class BaseGraphTest { - - private static final DbName TEST_DB = DbName.of("java_driver_graph_test_db"); - private static final String GRAPH_NAME = "traversalGraph"; - private static final String EDGE_COLLECTION_NAME = "edges"; - private static final String VERTEX_COLLECTION_NAME = "circles"; - static ArangoDatabaseAsync db; - private static ArangoDBAsync arangoDB; - - @BeforeAll - static void init() throws InterruptedException, ExecutionException { - if (arangoDB == null) { - arangoDB = new ArangoDBAsync.Builder() - .loadProperties(ConfigUtils.loadConfig()) - .build(); - } - if (arangoDB.db(TEST_DB).exists().get()) { - arangoDB.db(TEST_DB).drop().get(); - } - arangoDB.createDatabase(TEST_DB).get(); - BaseGraphTest.db = arangoDB.db(TEST_DB); - - final Collection edgeDefinitions = new ArrayList<>(); - final EdgeDefinition edgeDefinition = new EdgeDefinition().collection(EDGE_COLLECTION_NAME) - .from(VERTEX_COLLECTION_NAME).to(VERTEX_COLLECTION_NAME); - edgeDefinitions.add(edgeDefinition); - db.createGraph(GRAPH_NAME, edgeDefinitions, null).get(); - addExampleElements(); - } - - @AfterAll - static void shutdown() throws InterruptedException, ExecutionException { - arangoDB.db(TEST_DB).drop().get(); - arangoDB.shutdown(); - arangoDB = null; - } - - private static void addExampleElements() throws InterruptedException, ExecutionException { - - // Add circle circles - final VertexEntity vA = createVertex(new Circle("A", "1")); - final VertexEntity vB = createVertex(new Circle("B", "2")); - final VertexEntity vC = createVertex(new Circle("C", "3")); - final VertexEntity vD = createVertex(new Circle("D", "4")); - final VertexEntity vE = createVertex(new Circle("E", "5")); - final VertexEntity vF = createVertex(new Circle("F", "6")); - final VertexEntity vG = createVertex(new Circle("G", "7")); - final VertexEntity vH = createVertex(new Circle("H", "8")); - final VertexEntity vI = createVertex(new Circle("I", "9")); - final VertexEntity vJ = createVertex(new Circle("J", "10")); - final VertexEntity vK = createVertex(new Circle("K", "11")); - - // Add relevant edges - left branch: - saveEdge(new CircleEdge(vA.getId(), vB.getId(), false, true, "left_bar")); - saveEdge(new CircleEdge(vB.getId(), vC.getId(), false, true, "left_blarg")); - saveEdge(new CircleEdge(vC.getId(), vD.getId(), false, true, "left_blorg")); - saveEdge(new CircleEdge(vB.getId(), vE.getId(), false, true, "left_blub")); - saveEdge(new CircleEdge(vE.getId(), vF.getId(), false, true, "left_schubi")); - - // Add relevant edges - right branch: - saveEdge(new CircleEdge(vA.getId(), vG.getId(), false, true, "right_foo")); - saveEdge(new CircleEdge(vG.getId(), vH.getId(), false, true, "right_blob")); - saveEdge(new CircleEdge(vH.getId(), vI.getId(), false, true, "right_blub")); - saveEdge(new CircleEdge(vG.getId(), vJ.getId(), false, true, "right_zip")); - saveEdge(new CircleEdge(vJ.getId(), vK.getId(), false, true, "right_zup")); - } - - private static void saveEdge(final CircleEdge edge) - throws InterruptedException, ExecutionException { - db.graph(GRAPH_NAME).edgeCollection(EDGE_COLLECTION_NAME).insertEdge(edge).get(); - } - - private static VertexEntity createVertex(final Circle vertex) - throws InterruptedException, ExecutionException { - return db.graph(GRAPH_NAME).vertexCollection(VERTEX_COLLECTION_NAME).insertVertex(vertex).get(); - } - -} diff --git a/shaded-integration-tests/src/test/native/java/com/arangodb/async/example/graph/Circle.java b/shaded-integration-tests/src/test/native/java/com/arangodb/async/example/graph/Circle.java deleted file mode 100644 index e828aaeb3..000000000 --- a/shaded-integration-tests/src/test/native/java/com/arangodb/async/example/graph/Circle.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.async.example.graph; - -import com.arangodb.serde.jackson.Id; -import com.arangodb.serde.jackson.Key; -import com.arangodb.serde.jackson.Rev; - -/** - * @author a-brandt - */ -class Circle { - - @Id - private String id; - - @Key - private String key; - - @Rev - private String revision; - - private String label; - - public Circle(String key, String label) { - this.key = key; - this.label = label; - } - - public String getId() { - return id; - } - - void setId(String id) { - this.id = id; - } - - public String getKey() { - return key; - } - - void setKey(String key) { - this.key = key; - } - - public String getRevision() { - return revision; - } - - void setRevision(String revision) { - this.revision = revision; - } - - public String getLabel() { - return label; - } - - void setLabel(String label) { - this.label = label; - } - -} diff --git a/shaded-integration-tests/src/test/native/java/com/arangodb/async/example/graph/CircleEdge.java b/shaded-integration-tests/src/test/native/java/com/arangodb/async/example/graph/CircleEdge.java deleted file mode 100644 index bfaa65210..000000000 --- a/shaded-integration-tests/src/test/native/java/com/arangodb/async/example/graph/CircleEdge.java +++ /dev/null @@ -1,122 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.async.example.graph; - -import com.arangodb.serde.jackson.*; - -/** - * @author a-brandt - */ -class CircleEdge { - - @Id - private String id; - - @Key - private String key; - - @Rev - private String revision; - - @From - private String from; - - @To - private String to; - - private Boolean theFalse; - private Boolean theTruth; - private String label; - - public CircleEdge(final String from, final String to, final Boolean theFalse, final Boolean theTruth, - final String label) { - this.from = from; - this.to = to; - this.theFalse = theFalse; - this.theTruth = theTruth; - this.label = label; - } - - public String getId() { - return id; - } - - void setId(String id) { - this.id = id; - } - - public String getKey() { - return key; - } - - void setKey(String key) { - this.key = key; - } - - public String getRevision() { - return revision; - } - - void setRevision(String revision) { - this.revision = revision; - } - - public String getFrom() { - return from; - } - - void setFrom(String from) { - this.from = from; - } - - public String getTo() { - return to; - } - - void setTo(String to) { - this.to = to; - } - - public Boolean getTheFalse() { - return theFalse; - } - - void setTheFalse(Boolean theFalse) { - this.theFalse = theFalse; - } - - public Boolean getTheTruth() { - return theTruth; - } - - void setTheTruth(Boolean theTruth) { - this.theTruth = theTruth; - } - - public String getLabel() { - return label; - } - - void setLabel(String label) { - this.label = label; - } - -} diff --git a/shaded-integration-tests/src/test/native/java/com/arangodb/async/example/graph/GraphTraversalsInAQLExampleTest.java b/shaded-integration-tests/src/test/native/java/com/arangodb/async/example/graph/GraphTraversalsInAQLExampleTest.java deleted file mode 100644 index b3628f572..000000000 --- a/shaded-integration-tests/src/test/native/java/com/arangodb/async/example/graph/GraphTraversalsInAQLExampleTest.java +++ /dev/null @@ -1,122 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.async.example.graph; - -import com.arangodb.async.ArangoCursorAsync; -import org.junit.jupiter.api.Test; - -import java.util.Collection; -import java.util.concurrent.ExecutionException; - -import static org.assertj.core.api.Assertions.assertThat; - - -/** - * Graph traversals in AQL - * - * @author a-brandt - * @see Graph traversals in AQL - */ -class GraphTraversalsInAQLExampleTest extends BaseGraphTest { - - @Test - void queryAllVertices() throws InterruptedException, ExecutionException { - String queryString = "FOR v IN 1..3 OUTBOUND 'circles/A' GRAPH 'traversalGraph' RETURN v._key"; - ArangoCursorAsync cursor = db.query(queryString, null, null, String.class).get(); - Collection result = cursor.asListRemaining(); - assertThat(result).hasSize(10); - - queryString = "WITH circles FOR v IN 1..3 OUTBOUND 'circles/A' edges RETURN v._key"; - cursor = db.query(queryString, null, null, String.class).get(); - result = cursor.asListRemaining(); - assertThat(result).hasSize(10); - } - - @Test - void queryDepthTwo() throws InterruptedException, ExecutionException { - String queryString = "FOR v IN 2..2 OUTBOUND 'circles/A' GRAPH 'traversalGraph' return v._key"; - ArangoCursorAsync cursor = db.query(queryString, null, null, String.class).get(); - Collection result = cursor.asListRemaining(); - assertThat(result).hasSize(4); - assertThat(result).contains("C", "E", "H", "J"); - - queryString = "FOR v IN 2 OUTBOUND 'circles/A' GRAPH 'traversalGraph' return v._key"; - cursor = db.query(queryString, null, null, String.class).get(); - result = cursor.asListRemaining(); - assertThat(result).hasSize(4); - assertThat(result).contains("C", "E", "H", "J"); - } - - @Test - void queryWithFilter() throws InterruptedException, ExecutionException { - String queryString = "FOR v, e, p IN 1..3 OUTBOUND 'circles/A' GRAPH 'traversalGraph' FILTER p.vertices[1]" + - "._key != 'G' RETURN v._key"; - ArangoCursorAsync cursor = db.query(queryString, null, null, String.class).get(); - Collection result = cursor.asListRemaining(); - assertThat(result).hasSize(5); - assertThat(result).contains("B", "C", "D", "E", "F"); - - queryString = "FOR v, e, p IN 1..3 OUTBOUND 'circles/A' GRAPH 'traversalGraph' FILTER p.edges[0].label != " + - "'right_foo' RETURN v._key"; - cursor = db.query(queryString, null, null, String.class).get(); - result = cursor.asListRemaining(); - assertThat(result).hasSize(5); - assertThat(result).contains("B", "C", "D", "E", "F"); - - queryString = "FOR v,e,p IN 1..3 OUTBOUND 'circles/A' GRAPH 'traversalGraph' FILTER p.vertices[1]._key != 'G'" + - " FILTER p.edges[1].label != 'left_blub' return v._key"; - cursor = db.query(queryString, null, null, String.class).get(); - - result = cursor.asListRemaining(); - assertThat(result).hasSize(3); - assertThat(result).contains("B", "C", "D"); - - queryString = "FOR v,e,p IN 1..3 OUTBOUND 'circles/A' GRAPH 'traversalGraph' FILTER p.vertices[1]._key != 'G'" + - " AND p.edges[1].label != 'left_blub' return v._key"; - cursor = db.query(queryString, null, null, String.class).get(); - result = cursor.asListRemaining(); - assertThat(result).hasSize(3); - assertThat(result).contains("B", "C", "D"); - } - - @Test - void queryOutboundInbound() throws InterruptedException, ExecutionException { - String queryString = "FOR v IN 1..3 OUTBOUND 'circles/E' GRAPH 'traversalGraph' return v._key"; - ArangoCursorAsync cursor = db.query(queryString, null, null, String.class).get(); - Collection result = cursor.asListRemaining(); - assertThat(result).hasSize(1); - assertThat(result).contains("F"); - - queryString = "FOR v IN 1..3 INBOUND 'circles/E' GRAPH 'traversalGraph' return v._key"; - cursor = db.query(queryString, null, null, String.class).get(); - result = cursor.asListRemaining(); - assertThat(result).hasSize(2); - assertThat(result).contains("B", "A"); - - queryString = "FOR v IN 1..3 ANY 'circles/E' GRAPH 'traversalGraph' return v._key"; - cursor = db.query(queryString, null, null, String.class).get(); - - result = cursor.asListRemaining(); - assertThat(result).hasSize(6); - assertThat(result).contains("F", "B", "C", "D", "A", "G"); - } - -} diff --git a/shaded-integration-tests/src/test/native/java/com/arangodb/async/example/graph/ShortestPathInAQLExampleTest.java b/shaded-integration-tests/src/test/native/java/com/arangodb/async/example/graph/ShortestPathInAQLExampleTest.java deleted file mode 100644 index 515f8e13f..000000000 --- a/shaded-integration-tests/src/test/native/java/com/arangodb/async/example/graph/ShortestPathInAQLExampleTest.java +++ /dev/null @@ -1,106 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.async.example.graph; - -import com.arangodb.async.ArangoCursorAsync; -import org.junit.jupiter.api.Test; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; -import java.util.concurrent.ExecutionException; - -import static org.assertj.core.api.Assertions.assertThat; - - -/** - * Shortest Path in AQL - * - * @author a-brandt - * @see Shortest Path in AQL - */ -class ShortestPathInAQLExampleTest extends BaseGraphTest { - - @Test - void queryShortestPathFromAToD() throws InterruptedException, ExecutionException { - String queryString = "FOR v, e IN OUTBOUND SHORTEST_PATH 'circles/A' TO 'circles/D' GRAPH 'traversalGraph' " + - "RETURN {'vertex': v._key, 'edge': e._key}"; - ArangoCursorAsync cursor = db.query(queryString, null, null, Pair.class).get(); - final Collection collection = toVertexCollection(cursor); - assertThat(collection).hasSize(4); - assertThat(collection).contains("A", "B", "C", "D"); - - queryString = "WITH circles FOR v, e IN OUTBOUND SHORTEST_PATH 'circles/A' TO 'circles/D' edges RETURN " + - "{'vertex': v._key, 'edge': e._key}"; - db.query(queryString, null, null, Pair.class).get(); - assertThat(collection).hasSize(4); - assertThat(collection).contains("A", "B", "C", "D"); - } - - @Test - void queryShortestPathByFilter() throws InterruptedException, ExecutionException { - String queryString = "FOR a IN circles FILTER a._key == 'A' FOR d IN circles FILTER d._key == 'D' FOR v, e IN" + - " OUTBOUND SHORTEST_PATH a TO d GRAPH 'traversalGraph' RETURN {'vertex':v._key, 'edge':e._key}"; - ArangoCursorAsync cursor = db.query(queryString, null, null, Pair.class).get(); - final Collection collection = toVertexCollection(cursor); - assertThat(collection).hasSize(4); - assertThat(collection).contains("A", "B", "C", "D"); - - queryString = "FOR a IN circles FILTER a._key == 'A' FOR d IN circles FILTER d._key == 'D' FOR v, e IN " + - "OUTBOUND SHORTEST_PATH a TO d edges RETURN {'vertex': v._key, 'edge': e._key}"; - db.query(queryString, null, null, Pair.class).get(); - assertThat(collection).hasSize(4); - assertThat(collection).contains("A", "B", "C", "D"); - } - - private Collection toVertexCollection(final ArangoCursorAsync cursor) { - final List result = new ArrayList<>(); - while (cursor.hasNext()) { - final Pair pair = cursor.next(); - result.add(pair.getVertex()); - } - return result; - } - - public static class Pair { - - private String vertex; - private String edge; - - public String getVertex() { - return vertex; - } - - void setVertex(final String vertex) { - this.vertex = vertex; - } - - public String getEdge() { - return edge; - } - - void setEdge(final String edge) { - this.edge = edge; - } - - } - -} diff --git a/shaded-integration-tests/src/test/native/java/com/arangodb/async/example/ssl/SslExampleTest.java b/shaded-integration-tests/src/test/native/java/com/arangodb/async/example/ssl/SslExampleTest.java deleted file mode 100644 index c90175310..000000000 --- a/shaded-integration-tests/src/test/native/java/com/arangodb/async/example/ssl/SslExampleTest.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.async.example.ssl; - -import com.arangodb.async.ArangoDBAsync; -import com.arangodb.entity.ArangoDBVersion; -import org.junit.jupiter.api.Tag; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.condition.EnabledIfSystemProperty; - -import javax.net.ssl.KeyManagerFactory; -import javax.net.ssl.SSLContext; -import javax.net.ssl.TrustManagerFactory; -import java.security.KeyStore; - -import static org.assertj.core.api.Assertions.assertThat; - - -/** - * @author Mark Vollmary - */ -@Tag("ssl") -@EnabledIfSystemProperty(named = "SslTest", matches = "true") -class SslExampleTest { - - /*- - * a SSL trust store - * - * create the trust store for the self signed certificate: - * keytool -import -alias "my arangodb server cert" -file UnitTests/server.pem -keystore example.truststore - * - * Documentation: - * https://hc.apache.org/httpcomponents-client-ga/httpclient/apidocs/org/apache/http/conn/ssl/SSLSocketFactory.html - */ - private static final String SSL_TRUSTSTORE = "/example.truststore"; - private static final String SSL_TRUSTSTORE_PASSWORD = "12345678"; - - @Test - void connect() throws Exception { - final KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType()); - ks.load(this.getClass().getResourceAsStream(SSL_TRUSTSTORE), SSL_TRUSTSTORE_PASSWORD.toCharArray()); - - final KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); - kmf.init(ks, SSL_TRUSTSTORE_PASSWORD.toCharArray()); - - final TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); - tmf.init(ks); - - final SSLContext sc = SSLContext.getInstance("TLS"); - sc.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null); - - final ArangoDBAsync arangoDB = new ArangoDBAsync.Builder() - .host("localhost", 8529) - .password("test") - .useSsl(true) - .sslContext(sc).build(); - final ArangoDBVersion version = arangoDB.getVersion().get(); - assertThat(version).isNotNull(); - } - -} diff --git a/shaded-integration-tests/src/test/native/java/com/arangodb/async/serde/CustomSerdeTest.java b/shaded-integration-tests/src/test/native/java/com/arangodb/async/serde/CustomSerdeTest.java deleted file mode 100644 index 6756ef847..000000000 --- a/shaded-integration-tests/src/test/native/java/com/arangodb/async/serde/CustomSerdeTest.java +++ /dev/null @@ -1,177 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.async.serde; - - -import com.arangodb.DbName; -import com.arangodb.async.ArangoCollectionAsync; -import com.arangodb.async.ArangoDBAsync; -import com.arangodb.async.ArangoDatabaseAsync; -import com.arangodb.config.ConfigUtils; -import com.arangodb.model.DocumentCreateOptions; -import com.arangodb.ContentType; -import com.arangodb.serde.jackson.JacksonSerde; -import com.arangodb.serde.jackson.JacksonSerdeProvider; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -import java.math.BigInteger; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; -import java.util.UUID; -import java.util.concurrent.ExecutionException; - -import static com.fasterxml.jackson.databind.DeserializationFeature.USE_BIG_INTEGER_FOR_INTS; -import static com.fasterxml.jackson.databind.SerializationFeature.WRITE_SINGLE_ELEM_ARRAYS_UNWRAPPED; -import static org.assertj.core.api.Assertions.assertThat; - - -/** - * @author Michele Rastelli - */ -class CustomSerdeTest { - - private static final String COLLECTION_NAME = "collection"; - - private ArangoDatabaseAsync db; - private ArangoCollectionAsync collection; - - @BeforeEach - void init() throws ExecutionException, InterruptedException { - JacksonSerde serde = new JacksonSerdeProvider().of(ContentType.VPACK); - serde.configure((mapper) -> { - mapper.configure(WRITE_SINGLE_ELEM_ARRAYS_UNWRAPPED, true); - mapper.configure(USE_BIG_INTEGER_FOR_INTS, true); - }); - ArangoDBAsync arangoDB = new ArangoDBAsync.Builder() - .loadProperties(ConfigUtils.loadConfig()) - .serde(serde).build(); - - DbName TEST_DB = DbName.of("custom-serde-test"); - db = arangoDB.db(TEST_DB); - if (!db.exists().get()) { - db.create().get(); - } - - collection = db.collection(COLLECTION_NAME); - if (!collection.exists().get()) { - collection.create().get(); - } - } - - @AfterEach - void shutdown() throws ExecutionException, InterruptedException { - db.drop().get(); - } - - @Test - void aqlSerialization() throws ExecutionException, InterruptedException { - String key = "test-" + UUID.randomUUID(); - - Map doc = new HashMap<>(); - doc.put("_key", key); - doc.put("arr", Collections.singletonList("hello")); - doc.put("int", 10); - - HashMap params = new HashMap<>(); - params.put("doc", doc); - params.put("@collection", COLLECTION_NAME); - - Map result = db.query( - "INSERT @doc INTO @@collection RETURN NEW", - params, - Map.class - ).get().next(); - - assertThat(result.get("arr")).isInstanceOf(String.class); - assertThat(result.get("arr")).isEqualTo("hello"); - assertThat(result.get("int")).isInstanceOf(BigInteger.class); - assertThat(result.get("int")).isEqualTo(BigInteger.valueOf(10)); - } - - @Test - void aqlDeserialization() throws ExecutionException, InterruptedException { - String key = "test-" + UUID.randomUUID(); - - Map doc = new HashMap<>(); - doc.put("_key", key); - doc.put("arr", Collections.singletonList("hello")); - doc.put("int", 10); - - collection.insertDocument(doc).get(); - - final Map result = db.query( - "RETURN DOCUMENT(@docId)", - Collections.singletonMap("docId", COLLECTION_NAME + "/" + key), - Map.class - ).get().next(); - - assertThat(result.get("arr")).isInstanceOf(String.class); - assertThat(result.get("arr")).isEqualTo("hello"); - assertThat(result.get("int")).isInstanceOf(BigInteger.class); - assertThat(result.get("int")).isEqualTo(BigInteger.valueOf(10)); - } - - @Test - void insertDocument() throws ExecutionException, InterruptedException { - String key = "test-" + UUID.randomUUID(); - - Map doc = new HashMap<>(); - doc.put("_key", key); - doc.put("arr", Collections.singletonList("hello")); - doc.put("int", 10); - - Map result = collection.insertDocument( - doc, - new DocumentCreateOptions().returnNew(true) - ).get().getNew(); - - assertThat(result.get("arr")).isInstanceOf(String.class); - assertThat(result.get("arr")).isEqualTo("hello"); - assertThat(result.get("int")).isInstanceOf(BigInteger.class); - assertThat(result.get("int")).isEqualTo(BigInteger.valueOf(10)); - } - - @Test - void getDocument() throws ExecutionException, InterruptedException { - String key = "test-" + UUID.randomUUID(); - - Map doc = new HashMap<>(); - doc.put("_key", key); - doc.put("arr", Collections.singletonList("hello")); - doc.put("int", 10); - - collection.insertDocument(doc).get(); - - final Map result = db.collection(COLLECTION_NAME).getDocument( - key, - Map.class, - null).get(); - - assertThat(result.get("arr")).isInstanceOf(String.class); - assertThat(result.get("arr")).isEqualTo("hello"); - assertThat(result.get("int")).isInstanceOf(BigInteger.class); - assertThat(result.get("int")).isEqualTo(BigInteger.valueOf(10)); - } - -} diff --git a/shaded-integration-tests/src/test/native/java/com/arangodb/config/ConfigUtils.java b/shaded-integration-tests/src/test/native/java/com/arangodb/config/ConfigUtils.java deleted file mode 100644 index 7f15d6270..000000000 --- a/shaded-integration-tests/src/test/native/java/com/arangodb/config/ConfigUtils.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.arangodb.config; - - -public class ConfigUtils { - - public static ArangoConfigProperties loadConfig() { - return ArangoConfigProperties.fromFile(); - } - - public static ArangoConfigProperties loadConfig(final String location) { - return ArangoConfigProperties.fromFile(location); - } - - public static ArangoConfigProperties loadConfig(final String location, final String prefix) { - return ArangoConfigProperties.fromFile(location, prefix); - } - -} diff --git a/shaded-integration-tests/src/test/native/java/com/arangodb/example/ExampleBase.java b/shaded-integration-tests/src/test/native/java/com/arangodb/example/ExampleBase.java deleted file mode 100644 index 01399b1cb..000000000 --- a/shaded-integration-tests/src/test/native/java/com/arangodb/example/ExampleBase.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.example; - -import com.arangodb.ArangoCollection; -import com.arangodb.ArangoDB; -import com.arangodb.ArangoDatabase; -import com.arangodb.DbName; -import com.arangodb.config.ConfigUtils; -import org.junit.jupiter.api.AfterAll; -import org.junit.jupiter.api.BeforeAll; - -/** - * @author Mark Vollmary - */ -public class ExampleBase { - - protected static final String COLLECTION_NAME = "json_example_collection"; - private static final String DB_NAME = "json_example_db"; - protected static ArangoDatabase db; - protected static ArangoCollection collection; - private static ArangoDB arangoDB; - - @BeforeAll - static void setUp() { - arangoDB = new ArangoDB.Builder() - .loadProperties(ConfigUtils.loadConfig()) - .build(); - DbName dbName = DbName.of(DB_NAME); - if (arangoDB.db(dbName).exists()) - arangoDB.db(dbName).drop(); - arangoDB.createDatabase(dbName); - db = arangoDB.db(dbName); - db.createCollection(COLLECTION_NAME); - collection = db.collection(COLLECTION_NAME); - } - - @AfterAll - static void tearDown() { - db.drop(); - arangoDB.shutdown(); - } - -} diff --git a/shaded-integration-tests/src/test/native/java/com/arangodb/example/FirstProject.java b/shaded-integration-tests/src/test/native/java/com/arangodb/example/FirstProject.java deleted file mode 100644 index 454bfabc7..000000000 --- a/shaded-integration-tests/src/test/native/java/com/arangodb/example/FirstProject.java +++ /dev/null @@ -1,134 +0,0 @@ -package com.arangodb.example; - -import com.arangodb.*; -import com.arangodb.entity.BaseDocument; -import com.arangodb.entity.CollectionEntity; -import com.fasterxml.jackson.databind.JsonNode; - -import java.util.Collections; -import java.util.Map; -import java.util.UUID; - -public class FirstProject { - - public static void main(final String[] args) { - final ArangoDB arangoDB = new ArangoDB.Builder().user("root").build(); - - // create database - final DbName dbName = DbName.of("mydb"); - try { - arangoDB.createDatabase(dbName); - System.out.println("Database created: " + dbName); - } catch (final ArangoDBException e) { - System.err.println("Failed to create database: " + dbName + "; " + e.getMessage()); - } - - // create collection - final String collectionName = "firstCollection"; - try { - final CollectionEntity myArangoCollection = arangoDB.db(dbName).createCollection(collectionName); - System.out.println("Collection created: " + myArangoCollection.getName()); - } catch (final ArangoDBException e) { - System.err.println("Failed to create collection: " + collectionName + "; " + e.getMessage()); - } - - // creating a document - final BaseDocument myObject = new BaseDocument(UUID.randomUUID().toString()); - myObject.setKey("myKey"); - myObject.addAttribute("a", "Foo"); - myObject.addAttribute("b", 42); - try { - arangoDB.db(dbName).collection(collectionName).insertDocument(myObject); - System.out.println("Document created"); - } catch (final ArangoDBException e) { - System.err.println("Failed to create document. " + e.getMessage()); - } - - // read a document - try { - final BaseDocument myDocument = arangoDB.db(dbName).collection(collectionName).getDocument("myKey", - BaseDocument.class); - System.out.println("Key: " + myDocument.getKey()); - System.out.println("Attribute a: " + myDocument.getAttribute("a")); - System.out.println("Attribute b: " + myDocument.getAttribute("b")); - } catch (final ArangoDBException e) { - System.err.println("Failed to get document: myKey; " + e.getMessage()); - } - - // read a document as JsonNode - try { - final JsonNode myDocument = arangoDB.db(dbName).collection(collectionName).getDocument("myKey", - JsonNode.class); - System.out.println("Key: " + myDocument.get("_key").textValue()); - System.out.println("Attribute a: " + myDocument.get("a").textValue()); - System.out.println("Attribute b: " + myDocument.get("b").textValue()); - } catch (final ArangoDBException e) { - System.err.println("Failed to get document: myKey; " + e.getMessage()); - } - - // update a document - myObject.addAttribute("c", "Bar"); - try { - arangoDB.db(dbName).collection(collectionName).updateDocument("myKey", myObject); - } catch (final ArangoDBException e) { - System.err.println("Failed to update document. " + e.getMessage()); - } - - // read the document again - try { - final BaseDocument myUpdatedDocument = arangoDB.db(dbName).collection(collectionName).getDocument("myKey", - BaseDocument.class); - System.out.println("Key: " + myUpdatedDocument.getKey()); - System.out.println("Attribute a: " + myUpdatedDocument.getAttribute("a")); - System.out.println("Attribute b: " + myUpdatedDocument.getAttribute("b")); - System.out.println("Attribute c: " + myUpdatedDocument.getAttribute("c")); - } catch (final ArangoDBException e) { - System.err.println("Failed to get document: myKey; " + e.getMessage()); - } - - // delete a document - try { - arangoDB.db(dbName).collection(collectionName).deleteDocument("myKey"); - } catch (final ArangoDBException e) { - System.err.println("Failed to delete document. " + e.getMessage()); - } - - // create some documents for the next step - final ArangoCollection collection = arangoDB.db(dbName).collection(collectionName); - for (int i = 0; i < 10; i++) { - final BaseDocument value = new BaseDocument(UUID.randomUUID().toString()); - value.setKey(String.valueOf(i)); - value.addAttribute("name", "Homer"); - collection.insertDocument(value); - } - - // execute AQL queries - try { - final String query = "FOR t IN firstCollection FILTER t.name == @name RETURN t"; - final Map bindVars = Collections.singletonMap("name", "Homer"); - final ArangoCursor cursor = arangoDB.db(dbName).query(query, bindVars, null, - BaseDocument.class); - while (cursor.hasNext()) { - System.out.println("Key: " + cursor.next().getKey()); - } - } catch (final ArangoDBException e) { - System.err.println("Failed to execute query. " + e.getMessage()); - } - - // delete a document with AQL - try { - final String query = "FOR t IN firstCollection FILTER t.name == @name " - + "REMOVE t IN firstCollection LET removed = OLD RETURN removed"; - final Map bindVars = Collections.singletonMap("name", "Homer"); - final ArangoCursor cursor = arangoDB.db(dbName).query(query, bindVars, null, - BaseDocument.class); - while (cursor.hasNext()) { - System.out.println("Removed document " + cursor.next().getKey()); - } - } catch (final ArangoDBException e) { - System.err.println("Failed to execute query. " + e.getMessage()); - } - - } - -} diff --git a/shaded-integration-tests/src/test/native/java/com/arangodb/example/document/AqlQueryWithSpecialReturnTypesExampleTest.java b/shaded-integration-tests/src/test/native/java/com/arangodb/example/document/AqlQueryWithSpecialReturnTypesExampleTest.java deleted file mode 100644 index 9c9279c28..000000000 --- a/shaded-integration-tests/src/test/native/java/com/arangodb/example/document/AqlQueryWithSpecialReturnTypesExampleTest.java +++ /dev/null @@ -1,132 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.example.document; - -import com.arangodb.ArangoCursor; -import com.arangodb.entity.BaseDocument; -import com.arangodb.example.ExampleBase; -import com.fasterxml.jackson.databind.node.ArrayNode; -import com.fasterxml.jackson.databind.node.ObjectNode; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.Test; - -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.UUID; - -import static org.assertj.core.api.Assertions.assertThat; - - -/** - * @author Mark Vollmary - */ -class AqlQueryWithSpecialReturnTypesExampleTest extends ExampleBase { - - @BeforeAll - static void before() { - createExamples(); - } - - private static void createExamples() { - for (int i = 0; i < 100; i++) { - final BaseDocument value = new BaseDocument(UUID.randomUUID().toString()); - value.addAttribute("name", "TestUser" + i); - value.addAttribute("gender", (i % 2) == 0 ? Gender.MALE : Gender.FEMALE); - value.addAttribute("age", i + 10); - db.collection(COLLECTION_NAME).insertDocument(value); - } - } - - @Test - void aqlWithLimitQueryAsJsonObject() { - final String query = "FOR t IN " + COLLECTION_NAME - + " FILTER t.age >= 20 && t.age < 30 && t.gender == @gender RETURN t"; - final Map bindVars = Collections.singletonMap("gender", Gender.FEMALE); - final ArangoCursor cursor = db.query(query, bindVars, null, ObjectNode.class); - assertThat((Object) cursor).isNotNull(); - while (cursor.hasNext()) { - final ObjectNode vpack = cursor.next(); - assertThat(vpack.get("name").asText()) - .isIn("TestUser11", "TestUser13", "TestUser15", "TestUser17", "TestUser19"); - assertThat(vpack.get("gender").asText()).isEqualTo(Gender.FEMALE.name()); - assertThat(vpack.get("age").asInt()).isIn(21, 23, 25, 27, 29); - } - } - - @Test - void aqlWithLimitQueryAsJsonArray() { - final String query = "FOR t IN " + COLLECTION_NAME - + " FILTER t.age >= 20 && t.age < 30 && t.gender == @gender RETURN [t.name, t.gender, t.age]"; - final Map bindVars = Collections.singletonMap("gender", Gender.FEMALE); - final ArangoCursor cursor = db.query(query, bindVars, null, ArrayNode.class); - assertThat((Object) cursor).isNotNull(); - while (cursor.hasNext()) { - final ArrayNode arrNode = cursor.next(); - assertThat(arrNode.get(0).asText()) - .isIn("TestUser11", "TestUser13", "TestUser15", "TestUser17", "TestUser19"); - assertThat(arrNode.get(1).asText()).isEqualTo(Gender.FEMALE.name()); - assertThat(arrNode.get(2).asInt()).isIn(21, 23, 25, 27, 29); - } - } - - @Test - void aqlWithLimitQueryAsMap() { - final String query = "FOR t IN " + COLLECTION_NAME - + " FILTER t.age >= 20 && t.age < 30 && t.gender == @gender RETURN t"; - final Map bindVars = Collections.singletonMap("gender", Gender.FEMALE); - final ArangoCursor cursor = db.query(query, bindVars, null, Map.class); - assertThat((Object) cursor).isNotNull(); - while (cursor.hasNext()) { - final Map map = cursor.next(); - assertThat(map.get("name")).isNotNull(); - assertThat(String.valueOf(map.get("name"))) - .isIn("TestUser11", "TestUser13", "TestUser15", "TestUser17", "TestUser19"); - assertThat(map.get("gender")).isNotNull(); - assertThat(String.valueOf(map.get("gender"))).isEqualTo(Gender.FEMALE.name()); - assertThat(map.get("age")).isNotNull(); - assertThat(Long.valueOf(map.get("age").toString())).isIn(21L, 23L, 25L, 27L, 29L); - } - } - - @Test - void aqlWithLimitQueryAsList() { - final String query = "FOR t IN " + COLLECTION_NAME - + " FILTER t.age >= 20 && t.age < 30 && t.gender == @gender RETURN [t.name, t.gender, t.age]"; - final Map bindVars = Collections.singletonMap("gender", Gender.FEMALE); - final ArangoCursor cursor = db.query(query, bindVars, null, List.class); - assertThat((Object) cursor).isNotNull(); - while (cursor.hasNext()) { - final List list = cursor.next(); - assertThat(list.get(0)).isNotNull(); - assertThat(String.valueOf(list.get(0))) - .isIn("TestUser11", "TestUser13", "TestUser15", "TestUser17", "TestUser19"); - assertThat(list.get(1)).isNotNull(); - assertThat(Gender.valueOf(String.valueOf(list.get(1)))).isEqualTo(Gender.FEMALE); - assertThat(list.get(2)).isNotNull(); - assertThat(Long.valueOf(String.valueOf(list.get(2)))).isIn(21L, 23L, 25L, 27L, 29L); - } - } - - enum Gender { - MALE, FEMALE - } -} diff --git a/shaded-integration-tests/src/test/native/java/com/arangodb/example/document/GetDocumentExampleTest.java b/shaded-integration-tests/src/test/native/java/com/arangodb/example/document/GetDocumentExampleTest.java deleted file mode 100644 index dc7318139..000000000 --- a/shaded-integration-tests/src/test/native/java/com/arangodb/example/document/GetDocumentExampleTest.java +++ /dev/null @@ -1,98 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.example.document; - -import com.arangodb.entity.BaseDocument; -import com.arangodb.example.ExampleBase; -import com.arangodb.util.RawBytes; -import com.arangodb.util.RawJson; -import com.fasterxml.jackson.databind.JsonNode; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.Test; - -import java.util.Map; -import java.util.UUID; - -import static org.assertj.core.api.Assertions.assertThat; - - -/** - * @author Mark Vollmary - */ -class GetDocumentExampleTest extends ExampleBase { - - private static String key = null; - - @BeforeAll - static void before() { - final BaseDocument value = new BaseDocument(UUID.randomUUID().toString()); - value.addAttribute("foo", "bar"); - key = collection.insertDocument(value).getKey(); - } - - @Test - void getAsBean() { - final TestEntity doc = collection.getDocument(key, TestEntity.class); - assertThat(doc).isNotNull(); - assertThat(doc.getFoo()).isEqualTo("bar"); - } - - @Test - void getAsBaseDocument() { - final BaseDocument doc = collection.getDocument(key, BaseDocument.class); - assertThat(doc).isNotNull(); - assertThat(doc.getAttribute("foo")).isNotNull(); - assertThat(String.valueOf(doc.getAttribute("foo"))).isEqualTo("bar"); - } - - @Test - void getAsMap() { - final Map doc = collection.getDocument(key, Map.class); - assertThat(doc).isNotNull(); - assertThat(doc.get("foo")).isNotNull(); - assertThat(String.valueOf(doc.get("foo"))).isEqualTo("bar"); - } - - @Test - void getAsJsonNode() { - final JsonNode doc = collection.getDocument(key, JsonNode.class); - assertThat(doc).isNotNull(); - assertThat(doc.get("foo").isTextual()).isTrue(); - assertThat(doc.get("foo").asText()).isEqualTo("bar"); - } - - @Test - void getAsJson() { - final RawJson doc = collection.getDocument(key, RawJson.class); - assertThat(doc.getValue()).isNotNull() - .contains("foo") - .contains("bar"); - } - - @Test - void getAsBytes() { - final RawBytes doc = collection.getDocument(key, RawBytes.class); - assertThat(doc.getValue()).isNotNull(); - Map mapDoc = collection.getSerde().deserializeUserData(doc.getValue(), Map.class); - assertThat(mapDoc).containsEntry("foo", "bar"); - } - -} diff --git a/shaded-integration-tests/src/test/native/java/com/arangodb/example/document/InsertDocumentExampleTest.java b/shaded-integration-tests/src/test/native/java/com/arangodb/example/document/InsertDocumentExampleTest.java deleted file mode 100644 index 000b6ddd6..000000000 --- a/shaded-integration-tests/src/test/native/java/com/arangodb/example/document/InsertDocumentExampleTest.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.example.document; - -import com.arangodb.entity.BaseDocument; -import com.arangodb.entity.DocumentCreateEntity; -import com.arangodb.example.ExampleBase; -import com.arangodb.util.RawJson; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.node.ObjectNode; -import org.junit.jupiter.api.Test; - -import java.util.UUID; - -import static org.assertj.core.api.Assertions.assertThat; - - -/** - * @author Mark Vollmary - */ -class InsertDocumentExampleTest extends ExampleBase { - - @Test - void insertBean() { - final DocumentCreateEntity doc = collection.insertDocument(new TestEntity("bar")); - assertThat(doc.getKey()).isNotNull(); - } - - @Test - void insertBaseDocument() { - final BaseDocument value = new BaseDocument(UUID.randomUUID().toString()); - value.addAttribute("foo", "bar"); - final DocumentCreateEntity doc = collection.insertDocument(value); - assertThat(doc.getKey()).isNotNull(); - } - - @Test - void insertJsonNode() { - ObjectMapper mapper = new ObjectMapper(); - ObjectNode node = mapper.createObjectNode(); - node.put("foo", "bar"); - final DocumentCreateEntity doc = collection.insertDocument(node); - assertThat(doc.getKey()).isNotNull(); - } - - @Test - void insertJson() { - final DocumentCreateEntity doc = collection.insertDocument(RawJson.of("{\"foo\":\"bar\"}")); - assertThat(doc.getKey()).isNotNull(); - } - -} diff --git a/shaded-integration-tests/src/test/native/java/com/arangodb/example/document/TestEntity.java b/shaded-integration-tests/src/test/native/java/com/arangodb/example/document/TestEntity.java deleted file mode 100644 index 8a59c2b60..000000000 --- a/shaded-integration-tests/src/test/native/java/com/arangodb/example/document/TestEntity.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.example.document; - -/** - * @author Mark Vollmary - */ -public class TestEntity { - - private String foo; - - public TestEntity() { - super(); - } - - public TestEntity(final String foo) { - super(); - this.foo = foo; - } - - public String getFoo() { - return foo; - } - - public void setFoo(final String foo) { - this.foo = foo; - } - -} diff --git a/shaded-integration-tests/src/test/native/java/com/arangodb/example/graph/AQLActorsAndMoviesExampleTest.java b/shaded-integration-tests/src/test/native/java/com/arangodb/example/graph/AQLActorsAndMoviesExampleTest.java deleted file mode 100644 index c23b4097d..000000000 --- a/shaded-integration-tests/src/test/native/java/com/arangodb/example/graph/AQLActorsAndMoviesExampleTest.java +++ /dev/null @@ -1,581 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.example.graph; - -import com.arangodb.*; -import com.arangodb.config.ConfigUtils; -import com.arangodb.entity.BaseDocument; -import com.arangodb.entity.BaseEdgeDocument; -import com.arangodb.entity.CollectionType; -import com.arangodb.entity.DocumentCreateEntity; -import com.arangodb.model.CollectionCreateOptions; -import com.fasterxml.jackson.annotation.JsonCreator; -import com.fasterxml.jackson.annotation.JsonProperty; -import org.junit.jupiter.api.AfterAll; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.Test; - -import java.util.UUID; - -import static org.assertj.core.api.Assertions.assertThat; - - -/** - * @author Mark Vollmary - * @see - * AQL Example Queries on an - * Actors and Movies Database - */ -class AQLActorsAndMoviesExampleTest { - - private static final DbName TEST_DB = DbName.of("actors_movies_test_db"); - private static ArangoDB arangoDB; - private static ArangoDatabase db; - - @BeforeAll - static void setUp() { - arangoDB = new ArangoDB.Builder() - .loadProperties(ConfigUtils.loadConfig()) - .build(); - if (arangoDB.db(TEST_DB).exists()) - arangoDB.db(TEST_DB).drop(); - arangoDB.createDatabase(TEST_DB); - db = arangoDB.db(TEST_DB); - createData(); - } - - @AfterAll - static void tearDown() { - db.drop(); - arangoDB.shutdown(); - } - - private static DocumentCreateEntity saveMovie( - final ArangoCollection movies, - final String key, - final String title, - final int released, - final String tagline) { - final BaseDocument value = new BaseDocument(UUID.randomUUID().toString()); - value.setKey(key); - value.addAttribute("title", title); - value.addAttribute("released", released); - value.addAttribute("tagline", tagline); - return movies.insertDocument(value); - } - - private static DocumentCreateEntity saveActor( - final ArangoCollection actors, - final String key, - final String name, - final int born) { - final BaseDocument value = new BaseDocument(UUID.randomUUID().toString()); - value.setKey(key); - value.addAttribute("name", name); - value.addAttribute("born", born); - return actors.insertDocument(value); - } - - private static void saveActsIn( - final ArangoCollection actsIn, - final String actor, - final String movie, - final String[] roles, - final int year) { - final BaseEdgeDocument value = new BaseEdgeDocument(); - value.setFrom(actor); - value.setTo(movie); - value.addAttribute("roles", roles); - value.addAttribute("year", year); - actsIn.insertDocument(value); - } - - private static void createData() { - db.createCollection("actors"); - final ArangoCollection actors = db.collection("actors"); - db.createCollection("movies"); - final ArangoCollection movies = db.collection("movies"); - db.createCollection("actsIn", new CollectionCreateOptions().type(CollectionType.EDGES)); - final ArangoCollection actsIn = db.collection("actsIn"); - - final String theMatrix = saveMovie(movies, "TheMatrix", "The Matrix", 1999, "Welcome to the Real World") - .getId(); - final String keanu = saveActor(actors, "Keanu", "Keanu Reeves", 1964).getId(); - final String carrie = saveActor(actors, "Carrie", "Carrie-Anne Moss", 1967).getId(); - final String laurence = saveActor(actors, "Laurence", "Laurence Fishburne", 1961).getId(); - final String hugo = saveActor(actors, "Hugo", "Hugo Weaving", 1960).getId(); - final String emil = saveActor(actors, "Emil", "Emil Eifrem", 1978).getId(); - - saveActsIn(actsIn, keanu, theMatrix, new String[]{"Neo"}, 1999); - saveActsIn(actsIn, carrie, theMatrix, new String[]{"Trinity"}, 1999); - saveActsIn(actsIn, laurence, theMatrix, new String[]{"Morpheus"}, 1999); - saveActsIn(actsIn, hugo, theMatrix, new String[]{"Agent Smith"}, 1999); - saveActsIn(actsIn, emil, theMatrix, new String[]{"Emil"}, 1999); - - final String theMatrixReloaded = saveMovie(movies, "TheMatrixReloaded", "The Matrix Reloaded", 2003, - "Free your mind").getId(); - saveActsIn(actsIn, keanu, theMatrixReloaded, new String[]{"Neo"}, 2003); - saveActsIn(actsIn, carrie, theMatrixReloaded, new String[]{"Trinity"}, 2003); - saveActsIn(actsIn, laurence, theMatrixReloaded, new String[]{"Morpheus"}, 2003); - saveActsIn(actsIn, hugo, theMatrixReloaded, new String[]{"Agent Smith"}, 2003); - - final String theMatrixRevolutions = saveMovie(movies, "TheMatrixRevolutions", "The Matrix Revolutions", 2003, - "Everything that has a beginning has an end").getId(); - saveActsIn(actsIn, keanu, theMatrixRevolutions, new String[]{"Neo"}, 2003); - saveActsIn(actsIn, carrie, theMatrixRevolutions, new String[]{"Trinity"}, 2003); - saveActsIn(actsIn, laurence, theMatrixRevolutions, new String[]{"Morpheus"}, 2003); - saveActsIn(actsIn, hugo, theMatrixRevolutions, new String[]{"Agent Smith"}, 2003); - - final String theDevilsAdvocate = saveMovie(movies, "TheDevilsAdvocate", "The Devil's Advocate", 1997, - "Evil has its winning ways").getId(); - final String charlize = saveActor(actors, "Charlize", "Charlize Theron", 1975).getId(); - final String al = saveActor(actors, "Al", "Al Pacino", 1940).getId(); - saveActsIn(actsIn, keanu, theDevilsAdvocate, new String[]{"Kevin Lomax"}, 1997); - saveActsIn(actsIn, charlize, theDevilsAdvocate, new String[]{"Mary Ann Lomax"}, 1997); - saveActsIn(actsIn, al, theDevilsAdvocate, new String[]{"John Milton"}, 1997); - - final String AFewGoodMen = saveMovie(movies, "AFewGoodMen", "A Few Good Men", 1992, - "In the heart of the nation's capital, in a courthouse of the U.S. government, one man will stop at " + - "nothing to keep his honor, and one will stop at nothing to find the truth.") - .getId(); - final String tomC = saveActor(actors, "TomC", "Tom Cruise", 1962).getId(); - final String jackN = saveActor(actors, "JackN", "Jack Nicholson", 1937).getId(); - final String demiM = saveActor(actors, "DemiM", "Demi Moore", 1962).getId(); - final String kevinB = saveActor(actors, "KevinB", "Kevin Bacon", 1958).getId(); - final String kieferS = saveActor(actors, "KieferS", "Kiefer Sutherland", 1966).getId(); - final String noahW = saveActor(actors, "NoahW", "Noah Wyle", 1971).getId(); - final String cubaG = saveActor(actors, "CubaG", "Cuba Gooding Jr.", 1968).getId(); - final String kevinP = saveActor(actors, "KevinP", "Kevin Pollak", 1957).getId(); - final String jTW = saveActor(actors, "JTW", "J.T. Walsh", 1943).getId(); - final String jamesM = saveActor(actors, "JamesM", "James Marshall", 1967).getId(); - final String christopherG = saveActor(actors, "ChristopherG", "Christopher Guest", 1948).getId(); - saveActsIn(actsIn, tomC, AFewGoodMen, new String[]{"Lt. Daniel Kaffee"}, 1992); - saveActsIn(actsIn, jackN, AFewGoodMen, new String[]{"Col. Nathan R. Jessup"}, 1992); - saveActsIn(actsIn, demiM, AFewGoodMen, new String[]{"Lt. Cdr. JoAnne Galloway"}, 1992); - saveActsIn(actsIn, kevinB, AFewGoodMen, new String[]{"Capt. Jack Ross"}, 1992); - saveActsIn(actsIn, kieferS, AFewGoodMen, new String[]{"Lt. Jonathan Kendrick"}, 1992); - saveActsIn(actsIn, noahW, AFewGoodMen, new String[]{"Cpl. Jeffrey Barnes"}, 1992); - saveActsIn(actsIn, cubaG, AFewGoodMen, new String[]{"Cpl. Carl Hammaker"}, 1992); - saveActsIn(actsIn, kevinP, AFewGoodMen, new String[]{"Lt. Sam Weinberg"}, 1992); - saveActsIn(actsIn, jTW, AFewGoodMen, new String[]{"Lt. Col. Matthew Andrew Markinson"}, 1992); - saveActsIn(actsIn, jamesM, AFewGoodMen, new String[]{"Pfc. Louden Downey"}, 1992); - saveActsIn(actsIn, christopherG, AFewGoodMen, new String[]{"Dr. Stone"}, 1992); - - final String topGun = saveMovie(movies, "TopGun", "Top Gun", 1986, "I feel the need, the need for speed.") - .getId(); - final String kellyM = saveActor(actors, "KellyM", "Kelly McGillis", 1957).getId(); - final String valK = saveActor(actors, "ValK", "Val Kilmer", 1959).getId(); - final String anthonyE = saveActor(actors, "AnthonyE", "Anthony Edwards", 1962).getId(); - final String tomS = saveActor(actors, "TomS", "Tom Skerritt", 1933).getId(); - final String megR = saveActor(actors, "MegR", "Meg Ryan", 1961).getId(); - saveActsIn(actsIn, tomC, topGun, new String[]{"Maverick"}, 1986); - saveActsIn(actsIn, kellyM, topGun, new String[]{"Charlie"}, 1986); - saveActsIn(actsIn, valK, topGun, new String[]{"Iceman"}, 1986); - saveActsIn(actsIn, anthonyE, topGun, new String[]{"Goose"}, 1986); - saveActsIn(actsIn, tomS, topGun, new String[]{"Viper"}, 1986); - saveActsIn(actsIn, megR, topGun, new String[]{"Carole"}, 1986); - - final String jerryMaguire = saveMovie(movies, "JerryMaguire", "Jerry Maguire", 2000, - "The rest of his life begins now.").getId(); - final String reneeZ = saveActor(actors, "ReneeZ", "Renee Zellweger", 1969).getId(); - final String kellyP = saveActor(actors, "KellyP", "Kelly Preston", 1962).getId(); - final String jerryO = saveActor(actors, "JerryO", "Jerry O'Connell", 1974).getId(); - final String jayM = saveActor(actors, "JayM", "Jay Mohr", 1970).getId(); - final String bonnieH = saveActor(actors, "BonnieH", "Bonnie Hunt", 1961).getId(); - final String reginaK = saveActor(actors, "ReginaK", "Regina King", 1971).getId(); - final String jonathanL = saveActor(actors, "JonathanL", "Jonathan Lipnicki", 1996).getId(); - saveActsIn(actsIn, tomC, jerryMaguire, new String[]{"Jerry Maguire"}, 2000); - saveActsIn(actsIn, cubaG, jerryMaguire, new String[]{"Rod Tidwell"}, 2000); - saveActsIn(actsIn, reneeZ, jerryMaguire, new String[]{"Dorothy Boyd"}, 2000); - saveActsIn(actsIn, kellyP, jerryMaguire, new String[]{"Avery Bishop"}, 2000); - saveActsIn(actsIn, jerryO, jerryMaguire, new String[]{"Frank Cushman"}, 2000); - saveActsIn(actsIn, jayM, jerryMaguire, new String[]{"Bob Sugar"}, 2000); - saveActsIn(actsIn, bonnieH, jerryMaguire, new String[]{"Laurel Boyd"}, 2000); - saveActsIn(actsIn, reginaK, jerryMaguire, new String[]{"Marcee Tidwell"}, 2000); - saveActsIn(actsIn, jonathanL, jerryMaguire, new String[]{"Ray Boyd"}, 2000); - - final String standByMe = saveMovie(movies, "StandByMe", "Stand By Me", 1986, - "For some, it's the last real taste of innocence, and the first real taste of life. But for everyone," + - " it's the time that memories are made of.") - .getId(); - final String riverP = saveActor(actors, "RiverP", "River Phoenix", 1970).getId(); - final String coreyF = saveActor(actors, "CoreyF", "Corey Feldman", 1971).getId(); - final String wilW = saveActor(actors, "WilW", "Wil Wheaton", 1972).getId(); - final String johnC = saveActor(actors, "JohnC", "John Cusack", 1966).getId(); - final String marshallB = saveActor(actors, "MarshallB", "Marshall Bell", 1942).getId(); - saveActsIn(actsIn, wilW, standByMe, new String[]{"Gordie Lachance"}, 1986); - saveActsIn(actsIn, riverP, standByMe, new String[]{"Chris Chambers"}, 1986); - saveActsIn(actsIn, jerryO, standByMe, new String[]{"Vern Tessio"}, 1986); - saveActsIn(actsIn, coreyF, standByMe, new String[]{"Teddy Duchamp"}, 1986); - saveActsIn(actsIn, johnC, standByMe, new String[]{"Denny Lachance"}, 1986); - saveActsIn(actsIn, kieferS, standByMe, new String[]{"Ace Merrill"}, 1986); - saveActsIn(actsIn, marshallB, standByMe, new String[]{"Mr. Lachance"}, 1986); - - final String asGoodAsItGets = saveMovie(movies, "AsGoodAsItGets", "As Good as It Gets", 1997, - "A comedy from the heart that goes for the throat.").getId(); - final String helenH = saveActor(actors, "HelenH", "Helen Hunt", 1963).getId(); - final String gregK = saveActor(actors, "GregK", "Greg Kinnear", 1963).getId(); - saveActsIn(actsIn, jackN, asGoodAsItGets, new String[]{"Melvin Udall"}, 1997); - saveActsIn(actsIn, helenH, asGoodAsItGets, new String[]{"Carol Connelly"}, 1997); - saveActsIn(actsIn, gregK, asGoodAsItGets, new String[]{"Simon Bishop"}, 1997); - saveActsIn(actsIn, cubaG, asGoodAsItGets, new String[]{"Frank Sachs"}, 1997); - - final String whatDreamsMayCome = saveMovie(movies, "WhatDreamsMayCome", "What Dreams May Come", 1998, - "After life there is more. The end is just the beginning.").getId(); - final String annabellaS = saveActor(actors, "AnnabellaS", "Annabella Sciorra", 1960).getId(); - final String maxS = saveActor(actors, "MaxS", "Max von Sydow", 1929).getId(); - final String wernerH = saveActor(actors, "WernerH", "Werner Herzog", 1942).getId(); - final String robin = saveActor(actors, "Robin", "Robin Williams", 1951).getId(); - saveActsIn(actsIn, robin, whatDreamsMayCome, new String[]{"Chris Nielsen"}, 1998); - saveActsIn(actsIn, cubaG, whatDreamsMayCome, new String[]{"Albert Lewis"}, 1998); - saveActsIn(actsIn, annabellaS, whatDreamsMayCome, new String[]{"Annie Collins-Nielsen"}, 1998); - saveActsIn(actsIn, maxS, whatDreamsMayCome, new String[]{"The Tracker"}, 1998); - saveActsIn(actsIn, wernerH, whatDreamsMayCome, new String[]{"The Face"}, 1998); - - final String snowFallingonCedars = saveMovie(movies, "SnowFallingonCedars", "Snow Falling on Cedars", 1999, - "First loves last. Forever.").getId(); - final String ethanH = saveActor(actors, "EthanH", "Ethan Hawke", 1970).getId(); - final String rickY = saveActor(actors, "RickY", "Rick Yune", 1971).getId(); - final String jamesC = saveActor(actors, "JamesC", "James Cromwell", 1940).getId(); - saveActsIn(actsIn, ethanH, snowFallingonCedars, new String[]{"Ishmael Chambers"}, 1999); - saveActsIn(actsIn, rickY, snowFallingonCedars, new String[]{"Kazuo Miyamoto"}, 1999); - saveActsIn(actsIn, maxS, snowFallingonCedars, new String[]{"Nels Gudmundsson"}, 1999); - saveActsIn(actsIn, jamesC, snowFallingonCedars, new String[]{"Judge Fielding"}, 1999); - - final String youveGotMail = saveMovie(movies, "YouveGotMail", "You've Got Mail", 1998, - "At odds in life... in love on-line.").getId(); - final String parkerP = saveActor(actors, "ParkerP", "Parker Posey", 1968).getId(); - final String daveC = saveActor(actors, "DaveC", "Dave Chappelle", 1973).getId(); - final String steveZ = saveActor(actors, "SteveZ", "Steve Zahn", 1967).getId(); - final String tomH = saveActor(actors, "TomH", "Tom Hanks", 1956).getId(); - saveActsIn(actsIn, tomH, youveGotMail, new String[]{"Joe Fox"}, 1998); - saveActsIn(actsIn, megR, youveGotMail, new String[]{"Kathleen Kelly"}, 1998); - saveActsIn(actsIn, gregK, youveGotMail, new String[]{"Frank Navasky"}, 1998); - saveActsIn(actsIn, parkerP, youveGotMail, new String[]{"Patricia Eden"}, 1998); - saveActsIn(actsIn, daveC, youveGotMail, new String[]{"Kevin Jackson"}, 1998); - saveActsIn(actsIn, steveZ, youveGotMail, new String[]{"George Pappas"}, 1998); - - final String sleeplessInSeattle = saveMovie(movies, "SleeplessInSeattle", "Sleepless in Seattle", 1993, - "What if someone you never met, someone you never saw, someone you never knew was the only someone " + - "for you?") - .getId(); - final String ritaW = saveActor(actors, "RitaW", "Rita Wilson", 1956).getId(); - final String billPull = saveActor(actors, "BillPull", "Bill Pullman", 1953).getId(); - final String victorG = saveActor(actors, "VictorG", "Victor Garber", 1949).getId(); - final String rosieO = saveActor(actors, "RosieO", "Rosie O'Donnell", 1962).getId(); - saveActsIn(actsIn, tomH, sleeplessInSeattle, new String[]{"Sam Baldwin"}, 1993); - saveActsIn(actsIn, megR, sleeplessInSeattle, new String[]{"Annie Reed"}, 1993); - saveActsIn(actsIn, ritaW, sleeplessInSeattle, new String[]{"Suzy"}, 1993); - saveActsIn(actsIn, billPull, sleeplessInSeattle, new String[]{"Walter"}, 1993); - saveActsIn(actsIn, victorG, sleeplessInSeattle, new String[]{"Greg"}, 1993); - saveActsIn(actsIn, rosieO, sleeplessInSeattle, new String[]{"Becky"}, 1993); - - final String joeVersustheVolcano = saveMovie(movies, "JoeVersustheVolcano", "Joe Versus the Volcano", 1990, - "A story of love, lava and burning desire.").getId(); - final String nathan = saveActor(actors, "Nathan", "Nathan Lane", 1956).getId(); - saveActsIn(actsIn, tomH, joeVersustheVolcano, new String[]{"Joe Banks"}, 1990); - saveActsIn(actsIn, megR, joeVersustheVolcano, - new String[]{"DeDe', 'Angelica Graynamore', 'Patricia Graynamore"}, 1990); - saveActsIn(actsIn, nathan, joeVersustheVolcano, new String[]{"Baw"}, 1990); - - final String whenHarryMetSally = saveMovie(movies, "WhenHarryMetSally", "When Harry Met Sally", 1998, - "At odds in life... in love on-line.").getId(); - final String billyC = saveActor(actors, "BillyC", "Billy Crystal", 1948).getId(); - final String carrieF = saveActor(actors, "CarrieF", "Carrie Fisher", 1956).getId(); - final String brunoK = saveActor(actors, "BrunoK", "Bruno Kirby", 1949).getId(); - saveActsIn(actsIn, billyC, whenHarryMetSally, new String[]{"Harry Burns"}, 1998); - saveActsIn(actsIn, megR, whenHarryMetSally, new String[]{"Sally Albright"}, 1998); - saveActsIn(actsIn, carrieF, whenHarryMetSally, new String[]{"Marie"}, 1998); - saveActsIn(actsIn, brunoK, whenHarryMetSally, new String[]{"Jess"}, 1998); - } - - /** - * @see AQL - * Example Queries on an Actors and Movies Database - */ - @Test - void allActorsActsInMovie1or2() { - final ArangoCursor cursor = db.query( - "WITH actors, movies FOR x IN ANY 'movies/TheMatrix' actsIn OPTIONS {bfs: true, uniqueVertices: " + - "'global'} RETURN x._id", - null, null, String.class); - assertThat(cursor.asListRemaining()) - .contains("actors/Keanu", "actors/Hugo", "actors/Emil", "actors/Carrie", "actors/Laurence"); - } - - /** - * @see AQL - * Example Queries on an Actors and Movies Database - */ - @Test - void allActorsActsInMovie1or2UnionDistinct() { - final ArangoCursor cursor = db.query( - "WITH actors, movies FOR x IN UNION_DISTINCT ((FOR y IN ANY 'movies/TheMatrix' actsIn OPTIONS {bfs: " + - "true, uniqueVertices: 'global'} RETURN y._id), (FOR y IN ANY 'movies/TheDevilsAdvocate' " + - "actsIn OPTIONS {bfs: true, uniqueVertices: 'global'} RETURN y._id)) RETURN x", - null, null, String.class); - assertThat(cursor.asListRemaining()).contains("actors/Emil", "actors/Hugo", "actors/Carrie", "actors/Laurence", - "actors/Keanu", "actors/Al", "actors/Charlize"); - } - - /** - * @see AQL - * Example Queries on an Actors and Movies Database - */ - @Test - void allActorsActsInMovie1and2() { - final ArangoCursor cursor = db.query( - "WITH actors, movies FOR x IN INTERSECTION ((FOR y IN ANY 'movies/TheMatrix' actsIn OPTIONS {bfs: " + - "true, uniqueVertices: 'global'} RETURN y._id), (FOR y IN ANY 'movies/TheDevilsAdvocate' " + - "actsIn OPTIONS {bfs: true, uniqueVertices: 'global'} RETURN y._id)) RETURN x", - null, null, String.class); - assertThat(cursor.asListRemaining()).contains("actors/Keanu"); - } - - /** - * @see AQL - * Example Queries on an Actors and Movies Database - */ - @Test - void allMoviesBetweenActor1andActor2() { - final ArangoCursor cursor = db.query( - "WITH actors, movies FOR x IN INTERSECTION ((FOR y IN ANY 'actors/Hugo' actsIn OPTIONS {bfs: true, " + - "uniqueVertices: 'global'} RETURN y._id), (FOR y IN ANY 'actors/Keanu' actsIn OPTIONS {bfs: " + - "true, uniqueVertices: 'global'} RETURN y._id)) RETURN x", - null, null, String.class); - assertThat(cursor.asListRemaining()) - .contains("movies/TheMatrixRevolutions", "movies/TheMatrixReloaded", "movies/TheMatrix"); - } - - /** - * @see AQL - * Example Queries on an Actors and Movies Database - */ - @Test - void allActorsWhoActedIn3orMoreMovies() { - final ArangoCursor cursor = db.query( - "FOR x IN actsIn COLLECT actor = x._from WITH COUNT INTO counter FILTER counter >= 3 RETURN {actor: " + - "actor, movies: counter}", - null, null, Actor.class); - assertThat(cursor.asListRemaining()) - .contains(new Actor("actors/Carrie", 3), new Actor("actors/CubaG", 4), new Actor("actors/Hugo", 3), - new Actor("actors/Keanu", 4), new Actor("actors/Laurence", 3), new Actor("actors/MegR", 5), - new Actor("actors/TomC", 3), new Actor("actors/TomH", 3)); - } - - /** - * @see AQL - * Example Queries on an Actors and Movies Database - */ - @Test - void allMoviesWhereExactly6ActorsActedIn() { - final ArangoCursor cursor = db.query( - "FOR x IN actsIn COLLECT movie = x._to WITH COUNT INTO counter FILTER counter == 6 RETURN movie", null, - null, String.class); - assertThat(cursor.asListRemaining()) - .contains("movies/SleeplessInSeattle", "movies/TopGun", "movies/YouveGotMail"); - } - - /** - * @see AQL - * Example Queries on an Actors and Movies Database - */ - @Test - void theNumberOfActorsByMovie() { - final ArangoCursor cursor = db.query( - "FOR x IN actsIn COLLECT movie = x._to WITH COUNT INTO counter RETURN {movie: movie, actors: counter}", - null, null, Movie.class); - assertThat(cursor.asListRemaining()) - .contains(new Movie("movies/AFewGoodMen", 11), new Movie("movies/AsGoodAsItGets", 4), - new Movie("movies/JerryMaguire", 9), new Movie("movies/JoeVersustheVolcano", 3), - new Movie("movies/SleeplessInSeattle", 6), new Movie("movies/SnowFallingonCedars", 4), - new Movie("movies/StandByMe", 7), new Movie("movies/TheDevilsAdvocate", 3), - new Movie("movies/TheMatrix", 5), new Movie("movies/TheMatrixReloaded", 4), - new Movie("movies/TheMatrixRevolutions", 4), new Movie("movies/TopGun", 6), - new Movie("movies/WhatDreamsMayCome", 5), new Movie("movies/WhenHarryMetSally", 4), - new Movie("movies/YouveGotMail", 6)); - } - - /** - * @see AQL - * Example Queries on an Actors and Movies Database - */ - @Test - void theNumberOfMoviesByActor() { - final ArangoCursor cursor = db.query( - "FOR x IN actsIn COLLECT actor = x._from WITH COUNT INTO counter RETURN {actor: actor, movies: " + - "counter}", - null, null, Actor.class); - assertThat(cursor.asListRemaining()) - .contains(new Actor("actors/Al", 1), new Actor("actors/AnnabellaS", 1), new Actor("actors/AnthonyE", 1), - new Actor("actors/BillPull", 1), new Actor("actors/BillyC", 1), new Actor("actors/BonnieH", 1), - new Actor("actors/BrunoK", 1), new Actor("actors/Carrie", 3), new Actor("actors/CarrieF", 1), - new Actor("actors/Charlize", 1), new Actor("actors/ChristopherG", 1), new Actor("actors" + - "/CoreyF", 1), - new Actor("actors/CubaG", 4), new Actor("actors/DaveC", 1), new Actor("actors/DemiM", 1), - new Actor("actors/Emil", 1), new Actor("actors/EthanH", 1), new Actor("actors/GregK", 2), - new Actor("actors/HelenH", 1), new Actor("actors/Hugo", 3), new Actor("actors/JackN", 2), - new Actor("actors/JamesC", 1), new Actor("actors/JamesM", 1), new Actor("actors/JayM", 1), - new Actor("actors/JerryO", 2), new Actor("actors/JohnC", 1), new Actor("actors/JonathanL", 1), - new Actor("actors/JTW", 1), new Actor("actors/Keanu", 4), new Actor("actors/KellyM", 1), - new Actor("actors/KellyP", 1), new Actor("actors/KevinB", 1), new Actor("actors/KevinP", 1), - new Actor("actors/KieferS", 2), new Actor("actors/Laurence", 3), new Actor("actors/MarshallB" - , 1), - new Actor("actors/MaxS", 2), new Actor("actors/MegR", 5), new Actor("actors/Nathan", 1), - new Actor("actors/NoahW", 1), new Actor("actors/ParkerP", 1), new Actor("actors/ReginaK", 1), - new Actor("actors/ReneeZ", 1), new Actor("actors/RickY", 1), new Actor("actors/RitaW", 1), - new Actor("actors/RiverP", 1), new Actor("actors/Robin", 1), new Actor("actors/RosieO", 1), - new Actor("actors/SteveZ", 1), new Actor("actors/TomC", 3), new Actor("actors/TomH", 3), - new Actor("actors/TomS", 1), new Actor("actors/ValK", 1), new Actor("actors/VictorG", 1), - new Actor("actors/WernerH", 1), new Actor("actors/WilW", 1)); - } - - /** - * @see AQL - * Example Queries on an Actors and Movies Database - */ - @Test - void theNumberOfMoviesActedInBetween2005and2010byActor() { - final ArangoCursor cursor = db.query( - "FOR x IN actsIn FILTER x.year >= 1990 && x.year <= 1995 COLLECT actor = x._from WITH COUNT INTO " + - "counter RETURN {actor: actor, movies: counter}", - null, null, Actor.class); - assertThat(cursor.asListRemaining()) - .contains(new Actor("actors/BillPull", 1), new Actor("actors/ChristopherG", 1), new Actor("actors" + - "/CubaG", 1), - new Actor("actors/DemiM", 1), new Actor("actors/JackN", 1), new Actor("actors/JamesM", 1), - new Actor("actors/JTW", 1), new Actor("actors/KevinB", 1), new Actor("actors/KieferS", 1), - new Actor("actors/MegR", 2), new Actor("actors/Nathan", 1), new Actor("actors/NoahW", 1), - new Actor("actors/RitaW", 1), new Actor("actors/RosieO", 1), new Actor("actors/TomC", 1), - new Actor("actors/TomH", 2), new Actor("actors/VictorG", 1)); - } - - public static class Actor { - private final String actor; - private final Integer movies; - - @JsonCreator - Actor(@JsonProperty("actor") final String actor, @JsonProperty("movies") final Integer movies) { - super(); - this.actor = actor; - this.movies = movies; - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((actor == null) ? 0 : actor.hashCode()); - result = prime * result + ((movies == null) ? 0 : movies.hashCode()); - return result; - } - - @Override - public boolean equals(final Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (getClass() != obj.getClass()) { - return false; - } - final Actor other = (Actor) obj; - if (actor == null) { - if (other.actor != null) { - return false; - } - } else if (!actor.equals(other.actor)) { - return false; - } - if (movies == null) { - return other.movies == null; - } else return movies.equals(other.movies); - } - - } - - public static class Movie { - private final String movie; - private final Integer actors; - - @JsonCreator - public Movie(@JsonProperty("movie") final String movie, @JsonProperty("actors") final Integer actors) { - super(); - this.movie = movie; - this.actors = actors; - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((actors == null) ? 0 : actors.hashCode()); - result = prime * result + ((movie == null) ? 0 : movie.hashCode()); - return result; - } - - @Override - public boolean equals(final Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (getClass() != obj.getClass()) { - return false; - } - final Movie other = (Movie) obj; - if (actors == null) { - if (other.actors != null) { - return false; - } - } else if (!actors.equals(other.actors)) { - return false; - } - if (movie == null) { - return other.movie == null; - } else return movie.equals(other.movie); - } - - } - -} diff --git a/shaded-integration-tests/src/test/native/java/com/arangodb/example/graph/BaseGraphTest.java b/shaded-integration-tests/src/test/native/java/com/arangodb/example/graph/BaseGraphTest.java deleted file mode 100644 index 8b742e52d..000000000 --- a/shaded-integration-tests/src/test/native/java/com/arangodb/example/graph/BaseGraphTest.java +++ /dev/null @@ -1,114 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.example.graph; - -import com.arangodb.ArangoDB; -import com.arangodb.ArangoDBException; -import com.arangodb.ArangoDatabase; -import com.arangodb.DbName; -import com.arangodb.config.ConfigUtils; -import com.arangodb.entity.EdgeDefinition; -import com.arangodb.entity.VertexEntity; -import org.junit.jupiter.api.AfterAll; -import org.junit.jupiter.api.BeforeAll; - -import java.util.ArrayList; -import java.util.Collection; - -/** - * @author Mark Vollmary - */ -abstract class BaseGraphTest { - - private static final DbName TEST_DB = DbName.of("java_driver_graph_test_db"); - private static final String GRAPH_NAME = "traversalGraph"; - private static final String EDGE_COLLECTION_NAME = "edges"; - private static final String VERTEX_COLLECTION_NAME = "circles"; - static ArangoDatabase db; - private static ArangoDB arangoDB; - - @BeforeAll - static void init() { - if (arangoDB == null) { - arangoDB = new ArangoDB.Builder() - .loadProperties(ConfigUtils.loadConfig()) - .build(); - } - if (arangoDB.db(TEST_DB).exists()) - arangoDB.db(TEST_DB).drop(); - arangoDB.createDatabase(TEST_DB); - BaseGraphTest.db = arangoDB.db(TEST_DB); - - final Collection edgeDefinitions = new ArrayList<>(); - final EdgeDefinition edgeDefinition = new EdgeDefinition().collection(EDGE_COLLECTION_NAME) - .from(VERTEX_COLLECTION_NAME).to(VERTEX_COLLECTION_NAME); - edgeDefinitions.add(edgeDefinition); - if (!db.graph(GRAPH_NAME).exists()) - db.createGraph(GRAPH_NAME, edgeDefinitions, null); - addExampleElements(); - } - - @AfterAll - static void shutdown() { - arangoDB.db(TEST_DB).drop(); - arangoDB.shutdown(); - arangoDB = null; - } - - private static void addExampleElements() throws ArangoDBException { - - // Add circle circles - final VertexEntity vA = createVertex(new Circle("A", "1")); - final VertexEntity vB = createVertex(new Circle("B", "2")); - final VertexEntity vC = createVertex(new Circle("C", "3")); - final VertexEntity vD = createVertex(new Circle("D", "4")); - final VertexEntity vE = createVertex(new Circle("E", "5")); - final VertexEntity vF = createVertex(new Circle("F", "6")); - final VertexEntity vG = createVertex(new Circle("G", "7")); - final VertexEntity vH = createVertex(new Circle("H", "8")); - final VertexEntity vI = createVertex(new Circle("I", "9")); - final VertexEntity vJ = createVertex(new Circle("J", "10")); - final VertexEntity vK = createVertex(new Circle("K", "11")); - - // Add relevant edges - left branch: - saveEdge(new CircleEdge(vA.getId(), vB.getId(), false, true, "left_bar")); - saveEdge(new CircleEdge(vB.getId(), vC.getId(), false, true, "left_blarg")); - saveEdge(new CircleEdge(vC.getId(), vD.getId(), false, true, "left_blorg")); - saveEdge(new CircleEdge(vB.getId(), vE.getId(), false, true, "left_blub")); - saveEdge(new CircleEdge(vE.getId(), vF.getId(), false, true, "left_schubi")); - - // Add relevant edges - right branch: - saveEdge(new CircleEdge(vA.getId(), vG.getId(), false, true, "right_foo")); - saveEdge(new CircleEdge(vG.getId(), vH.getId(), false, true, "right_blob")); - saveEdge(new CircleEdge(vH.getId(), vI.getId(), false, true, "right_blub")); - saveEdge(new CircleEdge(vG.getId(), vJ.getId(), false, true, "right_zip")); - saveEdge(new CircleEdge(vJ.getId(), vK.getId(), false, true, "right_zup")); - } - - private static void saveEdge(final CircleEdge edge) throws ArangoDBException { - db.graph(GRAPH_NAME).edgeCollection(EDGE_COLLECTION_NAME).insertEdge(edge); - } - - private static VertexEntity createVertex(final Circle vertex) throws ArangoDBException { - return db.graph(GRAPH_NAME).vertexCollection(VERTEX_COLLECTION_NAME).insertVertex(vertex); - } - -} diff --git a/shaded-integration-tests/src/test/native/java/com/arangodb/example/graph/Circle.java b/shaded-integration-tests/src/test/native/java/com/arangodb/example/graph/Circle.java deleted file mode 100644 index f40783bdd..000000000 --- a/shaded-integration-tests/src/test/native/java/com/arangodb/example/graph/Circle.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.example.graph; - -import com.arangodb.serde.jackson.Id; -import com.arangodb.serde.jackson.Key; -import com.arangodb.serde.jackson.Rev; - -/** - * @author a-brandt - */ -class Circle { - - @Id - private String id; - - @Key - private String key; - - @Rev - private String revision; - - private String label; - - public Circle(String key, String label) { - this.key = key; - this.label = label; - } - - public String getId() { - return id; - } - - public void setId(String id) { - this.id = id; - } - - public String getKey() { - return key; - } - - public void setKey(String key) { - this.key = key; - } - - public String getRevision() { - return revision; - } - - public void setRevision(String revision) { - this.revision = revision; - } - - public String getLabel() { - return label; - } - - public void setLabel(String label) { - this.label = label; - } - -} diff --git a/shaded-integration-tests/src/test/native/java/com/arangodb/example/graph/CircleEdge.java b/shaded-integration-tests/src/test/native/java/com/arangodb/example/graph/CircleEdge.java deleted file mode 100644 index 96afa9f00..000000000 --- a/shaded-integration-tests/src/test/native/java/com/arangodb/example/graph/CircleEdge.java +++ /dev/null @@ -1,122 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.example.graph; - -import com.arangodb.serde.jackson.*; - -/** - * @author a-brandt - */ -class CircleEdge { - - @Id - private String id; - - @Key - private String key; - - @Rev - private String revision; - - @From - private String from; - - @To - private String to; - - private Boolean theFalse; - private Boolean theTruth; - private String label; - - public CircleEdge(final String from, final String to, final Boolean theFalse, final Boolean theTruth, - final String label) { - this.from = from; - this.to = to; - this.theFalse = theFalse; - this.theTruth = theTruth; - this.label = label; - } - - public String getId() { - return id; - } - - public void setId(String id) { - this.id = id; - } - - public String getKey() { - return key; - } - - public void setKey(String key) { - this.key = key; - } - - public String getRevision() { - return revision; - } - - public void setRevision(String revision) { - this.revision = revision; - } - - public String getFrom() { - return from; - } - - public void setFrom(String from) { - this.from = from; - } - - public String getTo() { - return to; - } - - public void setTo(String to) { - this.to = to; - } - - public Boolean getTheFalse() { - return theFalse; - } - - public void setTheFalse(Boolean theFalse) { - this.theFalse = theFalse; - } - - public Boolean getTheTruth() { - return theTruth; - } - - public void setTheTruth(Boolean theTruth) { - this.theTruth = theTruth; - } - - public String getLabel() { - return label; - } - - public void setLabel(String label) { - this.label = label; - } - -} diff --git a/shaded-integration-tests/src/test/native/java/com/arangodb/example/graph/GraphTraversalsInAQLExampleTest.java b/shaded-integration-tests/src/test/native/java/com/arangodb/example/graph/GraphTraversalsInAQLExampleTest.java deleted file mode 100644 index 94e48a307..000000000 --- a/shaded-integration-tests/src/test/native/java/com/arangodb/example/graph/GraphTraversalsInAQLExampleTest.java +++ /dev/null @@ -1,113 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.example.graph; - -import com.arangodb.ArangoCursor; -import com.arangodb.ArangoDBException; -import org.junit.jupiter.api.Test; - -import java.util.Collection; - -import static org.assertj.core.api.Assertions.assertThat; - - -/** - * Graph traversals in AQL - * - * @author a-brandt - * @see Graph traversals in AQL - */ -class GraphTraversalsInAQLExampleTest extends BaseGraphTest { - - @Test - void queryAllVertices() throws ArangoDBException { - String queryString = "FOR v IN 1..3 OUTBOUND 'circles/A' GRAPH 'traversalGraph' RETURN v._key"; - ArangoCursor cursor = db.query(queryString, null, null, String.class); - Collection result = cursor.asListRemaining(); - assertThat(result).hasSize(10); - - queryString = "WITH circles FOR v IN 1..3 OUTBOUND 'circles/A' edges RETURN v._key"; - cursor = db.query(queryString, null, null, String.class); - result = cursor.asListRemaining(); - assertThat(result).hasSize(10); - } - - @Test - void queryDepthTwo() throws ArangoDBException { - String queryString = "FOR v IN 2..2 OUTBOUND 'circles/A' GRAPH 'traversalGraph' return v._key"; - ArangoCursor cursor = db.query(queryString, null, null, String.class); - Collection result = cursor.asListRemaining(); - assertThat(result).containsExactlyInAnyOrder("C", "E", "H", "J"); - - queryString = "FOR v IN 2 OUTBOUND 'circles/A' GRAPH 'traversalGraph' return v._key"; - cursor = db.query(queryString, null, null, String.class); - result = cursor.asListRemaining(); - assertThat(result).containsExactlyInAnyOrder("C", "E", "H", "J"); - } - - @Test - void queryWithFilter() throws ArangoDBException { - String queryString = "FOR v, e, p IN 1..3 OUTBOUND 'circles/A' GRAPH 'traversalGraph' FILTER p.vertices[1]" + - "._key != 'G' RETURN v._key"; - ArangoCursor cursor = db.query(queryString, null, null, String.class); - Collection result = cursor.asListRemaining(); - assertThat(result).containsExactlyInAnyOrder("B", "C", "D", "E", "F"); - - queryString = "FOR v, e, p IN 1..3 OUTBOUND 'circles/A' GRAPH 'traversalGraph' FILTER p.edges[0].label != " + - "'right_foo' RETURN v._key"; - cursor = db.query(queryString, null, null, String.class); - result = cursor.asListRemaining(); - assertThat(result).containsExactlyInAnyOrder("B", "C", "D", "E", "F"); - - queryString = "FOR v,e,p IN 1..3 OUTBOUND 'circles/A' GRAPH 'traversalGraph' FILTER p.vertices[1]._key != 'G'" + - " FILTER p.edges[1].label != 'left_blub' return v._key"; - cursor = db.query(queryString, null, null, String.class); - - result = cursor.asListRemaining(); - assertThat(result).containsExactlyInAnyOrder("B", "C", "D"); - - queryString = "FOR v,e,p IN 1..3 OUTBOUND 'circles/A' GRAPH 'traversalGraph' FILTER p.vertices[1]._key != 'G'" + - " AND p.edges[1].label != 'left_blub' return v._key"; - cursor = db.query(queryString, null, null, String.class); - result = cursor.asListRemaining(); - assertThat(result).containsExactlyInAnyOrder("B", "C", "D"); - } - - @Test - void queryOutboundInbound() throws ArangoDBException { - String queryString = "FOR v IN 1..3 OUTBOUND 'circles/E' GRAPH 'traversalGraph' return v._key"; - ArangoCursor cursor = db.query(queryString, null, null, String.class); - Collection result = cursor.asListRemaining(); - assertThat(result).containsExactlyInAnyOrder("F"); - - queryString = "FOR v IN 1..3 INBOUND 'circles/E' GRAPH 'traversalGraph' return v._key"; - cursor = db.query(queryString, null, null, String.class); - result = cursor.asListRemaining(); - assertThat(result).containsExactlyInAnyOrder("B", "A"); - - queryString = "FOR v IN 1..3 ANY 'circles/E' GRAPH 'traversalGraph' return v._key"; - cursor = db.query(queryString, null, null, String.class); - - result = cursor.asListRemaining(); - assertThat(result).containsExactlyInAnyOrder("F", "B", "C", "D", "A", "G"); - } - -} diff --git a/shaded-integration-tests/src/test/native/java/com/arangodb/example/graph/ShortestPathInAQLExampleTest.java b/shaded-integration-tests/src/test/native/java/com/arangodb/example/graph/ShortestPathInAQLExampleTest.java deleted file mode 100644 index aecf7321a..000000000 --- a/shaded-integration-tests/src/test/native/java/com/arangodb/example/graph/ShortestPathInAQLExampleTest.java +++ /dev/null @@ -1,105 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.example.graph; - -import com.arangodb.ArangoCursor; -import com.arangodb.ArangoDBException; -import org.junit.jupiter.api.Test; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * Shortest Path in AQL - * - * @author a-brandt - * @see Shortest Path in AQL - */ -class ShortestPathInAQLExampleTest extends BaseGraphTest { - - @Test - void queryShortestPathFromAToD() throws ArangoDBException { - String queryString = "FOR v, e IN OUTBOUND SHORTEST_PATH 'circles/A' TO 'circles/D' GRAPH 'traversalGraph' " + - "RETURN {'vertex': v._key, 'edge': e._key}"; - ArangoCursor cursor = db.query(queryString, null, null, Pair.class); - final Collection collection = toVertexCollection(cursor); - assertThat(collection.size()).isEqualTo(4); - assertThat(collection).containsExactlyInAnyOrder("A", "B", "C", "D"); - - queryString = "WITH circles FOR v, e IN OUTBOUND SHORTEST_PATH 'circles/A' TO 'circles/D' edges RETURN " + - "{'vertex': v._key, 'edge': e._key}"; - db.query(queryString, null, null, Pair.class); - assertThat(collection.size()).isEqualTo(4); - assertThat(collection).containsExactlyInAnyOrder("A", "B", "C", "D"); - } - - @Test - void queryShortestPathByFilter() throws ArangoDBException { - String queryString = "FOR a IN circles FILTER a._key == 'A' FOR d IN circles FILTER d._key == 'D' FOR v, e IN" + - " OUTBOUND SHORTEST_PATH a TO d GRAPH 'traversalGraph' RETURN {'vertex':v._key, 'edge':e._key}"; - ArangoCursor cursor = db.query(queryString, null, null, Pair.class); - final Collection collection = toVertexCollection(cursor); - assertThat(collection.size()).isEqualTo(4); - assertThat(collection).containsExactlyInAnyOrder("A", "B", "C", "D"); - - queryString = "FOR a IN circles FILTER a._key == 'A' FOR d IN circles FILTER d._key == 'D' FOR v, e IN " + - "OUTBOUND SHORTEST_PATH a TO d edges RETURN {'vertex': v._key, 'edge': e._key}"; - db.query(queryString, null, null, Pair.class); - assertThat(collection.size()).isEqualTo(4); - assertThat(collection).containsExactlyInAnyOrder("A", "B", "C", "D"); - } - - private Collection toVertexCollection(final ArangoCursor cursor) { - final List result = new ArrayList<>(); - while (cursor.hasNext()) { - final Pair pair = cursor.next(); - result.add(pair.getVertex()); - } - return result; - } - - public static class Pair { - - private String vertex; - private String edge; - - String getVertex() { - return vertex; - } - - void setVertex(final String vertex) { - this.vertex = vertex; - } - - String getEdge() { - return edge; - } - - void setEdge(final String edge) { - this.edge = edge; - } - - } - -} diff --git a/shaded-integration-tests/src/test/native/java/com/arangodb/example/ssl/SslExampleTest.java b/shaded-integration-tests/src/test/native/java/com/arangodb/example/ssl/SslExampleTest.java deleted file mode 100644 index b3f97ff16..000000000 --- a/shaded-integration-tests/src/test/native/java/com/arangodb/example/ssl/SslExampleTest.java +++ /dev/null @@ -1,128 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.example.ssl; - -import com.arangodb.ArangoDB; -import com.arangodb.ArangoDBException; -import com.arangodb.ArangoDBMultipleException; -import com.arangodb.Protocol; -import com.arangodb.entity.ArangoDBVersion; -import org.junit.jupiter.api.Tag; -import org.junit.jupiter.api.condition.EnabledIfSystemProperty; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.EnumSource; - -import javax.net.ssl.*; -import java.security.KeyStore; -import java.util.List; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.catchThrowable; -import static org.junit.jupiter.api.Assumptions.assumeTrue; - -/** - * @author Mark Vollmary - * @author Michele Rastelli - */ -@Tag("ssl") -@EnabledIfSystemProperty(named = "SslTest", matches = "true") -class SslExampleTest { - - /*- - * a SSL trust store - * - * create the trust store for the self signed certificate: - * keytool -import -alias "my arangodb server cert" -file server.pem -keystore example.truststore - * - * Documentation: - * https://hc.apache.org/httpcomponents-client-ga/httpclient/apidocs/org/apache/http/conn/ssl/SSLSocketFactory.html - */ - private static final String SSL_TRUSTSTORE = "/example.truststore"; - private static final String SSL_TRUSTSTORE_PASSWORD = "12345678"; - - @ParameterizedTest - @EnumSource(Protocol.class) - void connect(Protocol protocol) throws Exception { - final ArangoDB arangoDB = new ArangoDB.Builder() - .host("localhost", 8529) - .password("test") - .useSsl(true) - .sslContext(createSslContext()) - .useProtocol(protocol) - .build(); - final ArangoDBVersion version = arangoDB.getVersion(); - assertThat(version).isNotNull(); - System.out.println(version.getVersion()); - } - - @ParameterizedTest - @EnumSource(Protocol.class) - void noopHostnameVerifier(Protocol protocol) throws Exception { - final ArangoDB arangoDB = new ArangoDB.Builder() - .host("127.0.0.1", 8529) - .password("test") - .useSsl(true) - .sslContext(createSslContext()) - .verifyHost(false) - .useProtocol(protocol) - .build(); - final ArangoDBVersion version = arangoDB.getVersion(); - assertThat(version).isNotNull(); - System.out.println(version.getVersion()); - } - - @ParameterizedTest - @EnumSource(Protocol.class) - void hostnameVerifierFailure(Protocol protocol) throws Exception { - assumeTrue(protocol != Protocol.VST, "VST does not support hostname verification"); - final ArangoDB arangoDB = new ArangoDB.Builder() - .host("127.0.0.1", 8529) - .password("test") - .useSsl(true) - .sslContext(createSslContext()) - .verifyHost(true) - .useProtocol(protocol) - .build(); - Throwable thrown = catchThrowable(arangoDB::getVersion); - assertThat(thrown).isInstanceOf(ArangoDBException.class); - ArangoDBException ex = (ArangoDBException) thrown; - assertThat(ex.getCause()).isInstanceOf(ArangoDBMultipleException.class); - List exceptions = ((ArangoDBMultipleException) ex.getCause()).getExceptions(); - exceptions.forEach(e -> assertThat(e).isInstanceOf(SSLHandshakeException.class)); - } - - private SSLContext createSslContext() throws Exception { - final KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType()); - ks.load(this.getClass().getResourceAsStream(SSL_TRUSTSTORE), SSL_TRUSTSTORE_PASSWORD.toCharArray()); - - final KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); - kmf.init(ks, SSL_TRUSTSTORE_PASSWORD.toCharArray()); - - final TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); - tmf.init(ks); - - final SSLContext sc = SSLContext.getInstance("TLS"); - sc.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null); - - return sc; - } - -} diff --git a/shaded-integration-tests/src/test/native/java/com/arangodb/internal/HostHandlerTest.java b/shaded-integration-tests/src/test/native/java/com/arangodb/internal/HostHandlerTest.java deleted file mode 100644 index 973d3a7c1..000000000 --- a/shaded-integration-tests/src/test/native/java/com/arangodb/internal/HostHandlerTest.java +++ /dev/null @@ -1,190 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.internal; - -import com.arangodb.ArangoDBException; -import com.arangodb.ArangoDBMultipleException; -import com.arangodb.config.HostDescription; -import com.arangodb.internal.net.*; -import com.arangodb.internal.serde.InternalSerde; -import org.junit.jupiter.api.Test; - -import java.util.List; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.fail; - -/** - * @author Mark Vollmary - */ -class HostHandlerTest { - - private static final ConnectionPool mockCP = new ConnectionPool() { - @Override - public Connection createConnection(HostDescription host) { - return null; - } - - @Override - public Connection connection() { - return null; - } - - @Override - public void setJwt(String jwt) { - - } - - @Override - public void close() { - - } - }; - - private static final Host HOST_0 = new HostImpl(mockCP, new HostDescription("127.0.0.1", 8529)); - private static final HostResolver SINGLE_HOST = new HostResolver() { - - @Override - public HostSet resolve(final boolean initial, final boolean closeConnections) { - - HostSet set = new HostSet(); - set.addHost(HOST_0); - return set; - } - - @Override - public void init(ArangoExecutorSync executor, InternalSerde arangoSerialization) { - - } - - }; - private static final Host HOST_1 = new HostImpl(mockCP, new HostDescription("127.0.0.2", 8529)); - private static final Host HOST_2 = new HostImpl(mockCP, new HostDescription("127.0.0.3", 8529)); - private static final HostResolver MULTIPLE_HOSTS = new HostResolver() { - - @Override - public HostSet resolve(final boolean initial, final boolean closeConnections) { - - HostSet set = new HostSet(); - set.addHost(HOST_0); - set.addHost(HOST_1); - set.addHost(HOST_2); - return set; - } - - @Override - public void init(ArangoExecutorSync executor, InternalSerde arangoSerialization) { - - } - - }; - - @Test - void fallbackHostHandlerSingleHost() { - final HostHandler handler = new FallbackHostHandler(SINGLE_HOST); - assertThat(handler.get(null, null)).isEqualTo(HOST_0); - handler.fail(new RuntimeException()); - assertThat(handler.get(null, null)).isEqualTo(HOST_0); - } - - @Test - void fallbackHostHandlerMultipleHosts() { - final HostHandler handler = new FallbackHostHandler(MULTIPLE_HOSTS); - for (int i = 0; i < 3; i++) { - assertThat(handler.get(null, null)).isEqualTo(HOST_0); - handler.fail(new RuntimeException("HOST_0 failed")); - assertThat(handler.get(null, null)).isEqualTo(HOST_1); - handler.fail(new RuntimeException("HOST_1 failed")); - assertThat(handler.get(null, null)).isEqualTo(HOST_2); - handler.fail(new RuntimeException("HOST_2 failed")); - if (i < 2) { - assertThat(handler.get(null, null)).isEqualTo(HOST_0); - } else { - try { - handler.get(null, null); - fail(); - } catch (ArangoDBException e) { - assertThat(e.getCause()).isNotNull(); - assertThat(e.getCause()).isInstanceOf(ArangoDBMultipleException.class); - List exceptions = ((ArangoDBMultipleException) e.getCause()).getExceptions(); - assertThat(exceptions.get(0)).isInstanceOf(RuntimeException.class); - assertThat(exceptions.get(0).getMessage()).isEqualTo("HOST_0 failed"); - assertThat(exceptions.get(1)).isInstanceOf(RuntimeException.class); - assertThat(exceptions.get(1).getMessage()).isEqualTo("HOST_1 failed"); - assertThat(exceptions.get(2)).isInstanceOf(RuntimeException.class); - assertThat(exceptions.get(2).getMessage()).isEqualTo("HOST_2 failed"); - } - } - } - } - - @Test - void randomHostHandlerSingleHost() { - final HostHandler handler = new RandomHostHandler(SINGLE_HOST, new FallbackHostHandler(SINGLE_HOST)); - assertThat(handler.get(null, null)).isEqualTo(HOST_0); - handler.fail(new RuntimeException()); - assertThat(handler.get(null, null)).isEqualTo(HOST_0); - } - - @Test - void randomHostHandlerMultipleHosts() { - final HostHandler handler = new RandomHostHandler(MULTIPLE_HOSTS, new FallbackHostHandler(MULTIPLE_HOSTS)); - - final Host pick0 = handler.get(null, null); - assertThat(pick0).isIn(HOST_0, HOST_1, HOST_2); - handler.fail(new RuntimeException()); - - final Host pick1 = handler.get(null, null); - assertThat(pick1).isIn(HOST_0, HOST_1, HOST_2); - handler.success(); - - final Host pick3 = handler.get(null, null); - assertThat(pick3) - .isIn(HOST_0, HOST_1, HOST_2) - .isEqualTo(pick1); - } - - @Test - void roundRobinHostHandlerSingleHost() { - final HostHandler handler = new RoundRobinHostHandler(SINGLE_HOST); - assertThat(handler.get(null, null)).isEqualTo(HOST_0); - handler.fail(new RuntimeException()); - assertThat(handler.get(null, null)).isEqualTo(HOST_0); - } - - @Test - void roundRobinHostHandlerMultipleHosts() { - final HostHandler handler = new RoundRobinHostHandler(MULTIPLE_HOSTS); - final Host pick0 = handler.get(null, null); - assertThat(pick0).isIn(HOST_0, HOST_1, HOST_2); - final Host pick1 = handler.get(null, null); - assertThat(pick1) - .isIn(HOST_0, HOST_1, HOST_2) - .isNotEqualTo(pick0); - final Host pick2 = handler.get(null, null); - assertThat(pick2) - .isIn(HOST_0, HOST_1, HOST_2) - .isNotIn(pick0, pick1); - final Host pick4 = handler.get(null, null); - assertThat(pick4).isEqualTo(pick0); - } - -} diff --git a/shaded-integration-tests/src/test/native/java/com/arangodb/internal/QueueTimeMetricsImplTest.java b/shaded-integration-tests/src/test/native/java/com/arangodb/internal/QueueTimeMetricsImplTest.java deleted file mode 100644 index 7c4ca4c8a..000000000 --- a/shaded-integration-tests/src/test/native/java/com/arangodb/internal/QueueTimeMetricsImplTest.java +++ /dev/null @@ -1,61 +0,0 @@ -package com.arangodb.internal; - -import com.arangodb.model.QueueTimeSample; -import org.junit.jupiter.api.Test; - -import java.util.Arrays; -import java.util.Random; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.within; - - -class QueueTimeMetricsImplTest { - private final static int QSIZE = 1024; - private final Random rnd = new Random(); - private final QueueTimeMetricsImpl q = new QueueTimeMetricsImpl(QSIZE); - - @Test - void halfSizeTest() { - testQueue(QSIZE / 2); - } - - @Test - void fullSizeTest() { - testQueue(QSIZE); - } - - @Test - void emptySizeTest() { - testQueue(0); - } - - @Test - void overSizeTest() { - testQueue((int) (QSIZE * 1.2)); - testQueue((int) (QSIZE * 3000.4)); - } - - private void testQueue(int size) { - q.clear(); - for (int i = 0; i < size; i++) { - q.add(new QueueTimeSample(i, rnd.nextDouble())); - } - QueueTimeSample[] values = q.getValues(); - assertThat(values).hasSize(Math.min(size, QSIZE)); - assertThat(q.getAvg()).isEqualTo(getAvg(values), within(1.0E-12)); - assertThat(q.getAvg()).isGreaterThanOrEqualTo(0.0); - - for (int i = 0; i < values.length; i++) { - assertThat(values[i]).isNotNull(); - if (i > 0) { - assertThat(values[i].timestamp).isGreaterThan(values[i - 1].timestamp); - } - } - } - - private double getAvg(QueueTimeSample[] elements) { - return Arrays.stream(elements).mapToDouble(it -> it.value).average().orElse(0.0); - } - -} \ No newline at end of file diff --git a/shaded-integration-tests/src/test/native/java/com/arangodb/internal/velocystream/CommunicationTest.java b/shaded-integration-tests/src/test/native/java/com/arangodb/internal/velocystream/CommunicationTest.java deleted file mode 100644 index 58a87bd71..000000000 --- a/shaded-integration-tests/src/test/native/java/com/arangodb/internal/velocystream/CommunicationTest.java +++ /dev/null @@ -1,113 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.internal.velocystream; - -import com.arangodb.ArangoDB; -import com.arangodb.ArangoDatabase; -import com.arangodb.config.ConfigUtils; -import com.arangodb.entity.ArangoDBVersion; -import org.junit.jupiter.api.Test; - -import java.util.Collection; -import java.util.Iterator; -import java.util.concurrent.ConcurrentLinkedQueue; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * @author Mark Vollmary - */ -class CommunicationTest { - - private static final String FAST = "fast"; - private static final String SLOW = "slow"; - - @Test - void chunkSizeSmall() { - final ArangoDB arangoDB = new ArangoDB.Builder() - .loadProperties(ConfigUtils.loadConfig()) - .chunksize(20).build(); - final ArangoDBVersion version = arangoDB.getVersion(); - assertThat(version).isNotNull(); - } - - @Test - void multiThread() throws Exception { - final ArangoDB arangoDB = new ArangoDB.Builder() - .loadProperties(ConfigUtils.loadConfig()) - .build(); - arangoDB.getUsers(); // authentication and active-failover connection redirect to master - - final Collection result = new ConcurrentLinkedQueue<>(); - final Thread fast = new Thread(() -> { - arangoDB.db().query("return sleep(0.1)", null, null, null); - result.add(FAST); - }); - final Thread slow = new Thread(() -> { - arangoDB.db().query("return sleep(0.5)", null, null, null); - result.add(SLOW); - }); - slow.start(); - fast.start(); - - slow.join(); - fast.join(); - - assertThat(result.size()).isEqualTo(2); - final Iterator iterator = result.iterator(); - assertThat(iterator.next()).isEqualTo(FAST); - assertThat(iterator.next()).isEqualTo(SLOW); - } - - @Test - void multiThreadSameDatabases() throws Exception { - final ArangoDB arangoDB = new ArangoDB.Builder() - .loadProperties(ConfigUtils.loadConfig()) - .build(); - arangoDB.getUsers(); // authentication and active-failover connection redirect to master - - final ArangoDatabase db = arangoDB.db(); - - final Collection result = new ConcurrentLinkedQueue<>(); - final Thread t1 = new Thread(() -> { - db.query("return sleep(0.1)", null, null, null); - result.add("1"); - }); - final Thread t2 = new Thread(() -> { - db.query("return sleep(0.1)", null, null, null); - result.add("1"); - }); - t2.start(); - t1.start(); - t2.join(); - t1.join(); - assertThat(result.size()).isEqualTo(2); - } - - @Test - void defaultMaxConnection() { - final ArangoDB arangoDB = new ArangoDB.Builder() - .loadProperties(ConfigUtils.loadConfig()) - .maxConnections(null).build(); - final ArangoDBVersion version = arangoDB.getVersion(); - assertThat(version).isNotNull(); - } -} diff --git a/shaded-integration-tests/src/test/native/java/com/arangodb/mapping/annotations/AnnotatedEntity.java b/shaded-integration-tests/src/test/native/java/com/arangodb/mapping/annotations/AnnotatedEntity.java deleted file mode 100644 index f26fb6f25..000000000 --- a/shaded-integration-tests/src/test/native/java/com/arangodb/mapping/annotations/AnnotatedEntity.java +++ /dev/null @@ -1,81 +0,0 @@ -package com.arangodb.mapping.annotations; - -import com.arangodb.serde.jackson.*; - -import java.util.Objects; - -public class AnnotatedEntity { - - @Id - private String id; - - @Key - private String key; - - @Rev - private String rev; - - @From - private String from; - - @To - private String to; - - public AnnotatedEntity() { - } - - public String getId() { - return id; - } - - public void setId(String id) { - this.id = id; - } - - public String getKey() { - return key; - } - - public void setKey(String key) { - this.key = key; - } - - public String getRev() { - return rev; - } - - public void setRev(String rev) { - this.rev = rev; - } - - public String getFrom() { - return from; - } - - public void setFrom(String from) { - this.from = from; - } - - public String getTo() { - return to; - } - - public void setTo(String to) { - this.to = to; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - AnnotatedEntity that = (AnnotatedEntity) o; - return Objects.equals(getId(), that.getId()) && Objects.equals(getKey(), that.getKey()) && Objects - .equals(getRev(), that.getRev()) && Objects.equals(getFrom(), that.getFrom()) && Objects - .equals(getTo(), that.getTo()); - } - - @Override - public int hashCode() { - return Objects.hash(getId(), getKey(), getRev(), getFrom(), getTo()); - } -} diff --git a/shaded-integration-tests/src/test/native/java/com/arangodb/mapping/annotations/ArangoAnnotationsTest.java b/shaded-integration-tests/src/test/native/java/com/arangodb/mapping/annotations/ArangoAnnotationsTest.java deleted file mode 100644 index 084f67ba9..000000000 --- a/shaded-integration-tests/src/test/native/java/com/arangodb/mapping/annotations/ArangoAnnotationsTest.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.mapping.annotations; - -import com.arangodb.ContentType; -import com.arangodb.serde.ArangoSerde; -import com.arangodb.serde.jackson.JacksonSerdeProvider; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.EnumSource; - -import java.util.Map; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * @author Michele Rastelli - */ -class ArangoAnnotationsTest { - - @ParameterizedTest - @EnumSource(ContentType.class) - void documentFieldAnnotations(ContentType contentType) { - ArangoSerde mapper = new JacksonSerdeProvider().of(contentType); - - AnnotatedEntity e = new AnnotatedEntity(); - e.setId("Id"); - e.setKey("Key"); - e.setRev("Rev"); - e.setFrom("From"); - e.setTo("To"); - - byte[] serialized = mapper.serialize(e); - Map deserialized = mapper.deserialize(serialized, Map.class); - assertThat(deserialized) - .containsEntry("_id", e.getId()) - .containsEntry("_key", e.getKey()) - .containsEntry("_rev", e.getRev()) - .containsEntry("_from", e.getFrom()) - .containsEntry("_to", e.getTo()) - .hasSize(5); - - AnnotatedEntity deserializedEntity = mapper.deserialize(serialized, AnnotatedEntity.class); - assertThat(deserializedEntity).isEqualTo(e); - } - -} diff --git a/shaded-integration-tests/src/test/native/java/com/arangodb/serde/CustomSerdeTest.java b/shaded-integration-tests/src/test/native/java/com/arangodb/serde/CustomSerdeTest.java deleted file mode 100644 index 4e42730ba..000000000 --- a/shaded-integration-tests/src/test/native/java/com/arangodb/serde/CustomSerdeTest.java +++ /dev/null @@ -1,242 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.serde; - - -import com.arangodb.*; -import com.arangodb.config.ConfigUtils; -import com.arangodb.internal.serde.InternalSerde; -import com.arangodb.model.DocumentCreateOptions; -import com.arangodb.serde.jackson.JacksonSerde; -import com.arangodb.serde.jackson.JacksonSerdeProvider; -import com.fasterxml.jackson.core.JsonGenerator; -import com.fasterxml.jackson.core.JsonParser; -import com.fasterxml.jackson.databind.*; -import com.fasterxml.jackson.databind.annotation.JsonSerialize; -import com.fasterxml.jackson.databind.module.SimpleModule; -import org.junit.jupiter.api.AfterAll; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.Test; - -import java.io.IOException; -import java.math.BigInteger; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; -import java.util.UUID; - -import static com.fasterxml.jackson.databind.DeserializationFeature.USE_BIG_INTEGER_FOR_INTS; -import static com.fasterxml.jackson.databind.SerializationFeature.WRITE_SINGLE_ELEM_ARRAYS_UNWRAPPED; -import static org.assertj.core.api.Assertions.assertThat; - - -/** - * @author Michele Rastelli - */ -class CustomSerdeTest { - - private static final String COLLECTION_NAME = "collection"; - private static final String PERSON_SERIALIZER_ADDED_PREFIX = "MyNameIs"; - private static final String PERSON_DESERIALIZER_ADDED_PREFIX = "Hello"; - - private static ArangoDB arangoDB; - private static ArangoDatabase db; - private static ArangoCollection collection; - - @BeforeAll - static void init() { - JacksonSerde serde = new JacksonSerdeProvider().of(ContentType.VPACK); - serde.configure((mapper) -> { - mapper.configure(WRITE_SINGLE_ELEM_ARRAYS_UNWRAPPED, true); - mapper.configure(USE_BIG_INTEGER_FOR_INTS, true); - SimpleModule module = new SimpleModule("PersonModule"); - module.addDeserializer(Person.class, new PersonDeserializer()); - mapper.registerModule(module); - }); - arangoDB = new ArangoDB.Builder() - .loadProperties(ConfigUtils.loadConfig()) - .useProtocol(Protocol.VST) - .serde(serde).build(); - - db = arangoDB.db(DbName.of("custom-serde-test")); - if (!db.exists()) { - db.create(); - } - - collection = db.collection(COLLECTION_NAME); - if (!collection.exists()) { - collection.create(); - } - } - - @AfterAll - static void shutdown() { - if (db.exists()) - db.drop(); - } - - @Test - void customPersonDeserializer() { - Person person = new Person(); - person.name = "Joe"; - Person result = collection.insertDocument( - person, - new DocumentCreateOptions().returnNew(true) - ).getNew(); - assertThat(result.name).isEqualTo(PERSON_DESERIALIZER_ADDED_PREFIX + PERSON_SERIALIZER_ADDED_PREFIX + person.name); - } - - @Test - void manualCustomPersonDeserializer() { - Person person = new Person(); - person.name = "Joe"; - InternalSerde serialization = arangoDB.getSerde(); - byte[] serialized = serialization.serializeUserData(person); - Person deserializedPerson = serialization.deserializeUserData(serialized, Person.class); - assertThat(deserializedPerson.name).isEqualTo(PERSON_DESERIALIZER_ADDED_PREFIX + PERSON_SERIALIZER_ADDED_PREFIX + person.name); - } - - @Test - void aqlSerialization() { - String key = "test-" + UUID.randomUUID(); - - Map doc = new HashMap<>(); - doc.put("_key", key); - doc.put("arr", Collections.singletonList("hello")); - doc.put("int", 10); - - HashMap params = new HashMap<>(); - params.put("doc", doc); - params.put("@collection", COLLECTION_NAME); - - Map result = db.query( - "INSERT @doc INTO @@collection RETURN NEW", - params, - Map.class - ).next(); - - assertThat(result.get("arr")).isInstanceOf(String.class); - assertThat(result.get("arr")).isEqualTo("hello"); - assertThat(result.get("int")).isInstanceOf(BigInteger.class); - assertThat(result.get("int")).isEqualTo(BigInteger.valueOf(10)); - } - - @Test - void aqlDeserialization() { - String key = "test-" + UUID.randomUUID(); - - Map doc = new HashMap<>(); - doc.put("_key", key); - doc.put("arr", Collections.singletonList("hello")); - doc.put("int", 10); - - collection.insertDocument(doc); - - final Map result = db.query( - "RETURN DOCUMENT(@docId)", - Collections.singletonMap("docId", COLLECTION_NAME + "/" + key), - Map.class - ).next(); - - assertThat(result.get("arr")).isInstanceOf(String.class); - assertThat(result.get("arr")).isEqualTo("hello"); - assertThat(result.get("int")).isInstanceOf(BigInteger.class); - assertThat(result.get("int")).isEqualTo(BigInteger.valueOf(10)); - } - - @Test - void insertDocument() { - String key = "test-" + UUID.randomUUID(); - - Map doc = new HashMap<>(); - doc.put("_key", key); - doc.put("arr", Collections.singletonList("hello")); - doc.put("int", 10); - - Map result = collection.insertDocument( - doc, - new DocumentCreateOptions().returnNew(true) - ).getNew(); - - assertThat(result.get("arr")).isInstanceOf(String.class); - assertThat(result.get("arr")).isEqualTo("hello"); - assertThat(result.get("int")).isInstanceOf(BigInteger.class); - assertThat(result.get("int")).isEqualTo(BigInteger.valueOf(10)); - } - - @Test - void getDocument() { - String key = "test-" + UUID.randomUUID(); - - Map doc = new HashMap<>(); - doc.put("_key", key); - doc.put("arr", Collections.singletonList("hello")); - doc.put("int", 10); - - collection.insertDocument(doc); - - final Map result = db.collection(COLLECTION_NAME).getDocument( - key, - Map.class, - null); - - assertThat(result.get("arr")).isInstanceOf(String.class); - assertThat(result.get("arr")).isEqualTo("hello"); - assertThat(result.get("int")).isInstanceOf(BigInteger.class); - assertThat(result.get("int")).isEqualTo(BigInteger.valueOf(10)); - } - - @Test - void parseNullString() { - final String json = arangoDB.getSerde().deserializeUserData(arangoDB.getSerde().serializeUserData(null), - String.class); - assertThat(json).isNull(); - } - - static class PersonSerializer extends JsonSerializer { - @Override - public void serialize(Person value, JsonGenerator gen, SerializerProvider serializers) throws IOException { - gen.writeStartObject(); - gen.writeFieldName("name"); - gen.writeString(PERSON_SERIALIZER_ADDED_PREFIX + value.name); - gen.writeEndObject(); - } - } - - static class PersonDeserializer extends JsonDeserializer { - @Override - public Person deserialize(JsonParser parser, DeserializationContext ctx) throws IOException { - Person person = new Person(); - JsonNode rootNode = parser.getCodec().readTree(parser); - JsonNode nameNode = rootNode.get("name"); - if (nameNode != null && nameNode.isTextual()) { - person.name = PERSON_DESERIALIZER_ADDED_PREFIX + nameNode.asText(); - } - return person; - } - } - - @JsonSerialize(using = PersonSerializer.class) - static class Person { - String name; - } - -} diff --git a/shaded-integration-tests/src/test/native/java/com/arangodb/serde/CustomTypeHintTest.java b/shaded-integration-tests/src/test/native/java/com/arangodb/serde/CustomTypeHintTest.java deleted file mode 100644 index f8f79f444..000000000 --- a/shaded-integration-tests/src/test/native/java/com/arangodb/serde/CustomTypeHintTest.java +++ /dev/null @@ -1,145 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.serde; - - -import com.arangodb.ArangoCollection; -import com.arangodb.ArangoDB; -import com.arangodb.ArangoDatabase; -import com.arangodb.DbName; -import com.arangodb.config.ConfigUtils; -import com.arangodb.model.DocumentCreateOptions; -import com.arangodb.serde.jackson.Key; -import com.fasterxml.jackson.annotation.JsonTypeInfo; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -import static org.assertj.core.api.Assertions.assertThat; - - -/** - * @author Michele Rastelli - */ -class CustomTypeHintTest { - - private static final String COLLECTION_NAME = "collection"; - private ArangoDatabase db; - private ArangoCollection collection; - - @BeforeEach - void init() { - ArangoDB arangoDB = new ArangoDB.Builder() - .loadProperties(ConfigUtils.loadConfig()) - .build(); - - db = arangoDB.db(DbName.of("custom-serde-test")); - if (!db.exists()) { - db.create(); - } - - collection = db.collection(COLLECTION_NAME); - if (!collection.exists()) { - collection.create(); - } - } - - @AfterEach - void shutdown() { - if (db.exists()) - db.drop(); - } - - @Test - void insertDocument() { - Gorilla gorilla = new Gorilla(); - gorilla.setName("kingKong"); - - Zoo doc = new Zoo(); - doc.setAnimal(gorilla); - - Zoo insertedDoc = collection.insertDocument( - doc, - new DocumentCreateOptions().returnNew(true) - ).getNew(); - - assertThat((insertedDoc.getAnimal().getName())).isEqualTo("kingKong"); - - String key = insertedDoc.getKey(); - - // in the db a document like this is created: - // { - // "animal": { - // "type": "com.arangodb.serde.CustomTypeHintTest$Gorilla", - // "name": "kingKong" - // } - // } - - final Zoo readDoc = collection.getDocument( - key, - Zoo.class, - null); - - assertThat((readDoc.getAnimal().getName())).isEqualTo("kingKong"); - } - - @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, property = "type") - public interface Animal { - String getName(); - } - - public static class Gorilla implements Animal { - private String name; - - @Override - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - } - - public static class Zoo { - - @Key - private String key; - - private Animal animal; - - public String getKey() { - return key; - } - - public void setKey(String key) { - this.key = key; - } - - public Animal getAnimal() { - return animal; - } - - public void setAnimal(Animal animal) { - this.animal = animal; - } - } -} diff --git a/shaded-integration-tests/src/test/native/java/com/arangodb/serde/SerdeTest.java b/shaded-integration-tests/src/test/native/java/com/arangodb/serde/SerdeTest.java deleted file mode 100644 index ab225bd23..000000000 --- a/shaded-integration-tests/src/test/native/java/com/arangodb/serde/SerdeTest.java +++ /dev/null @@ -1,41 +0,0 @@ -package com.arangodb.serde; - -import com.arangodb.ContentType; -import com.arangodb.internal.serde.InternalSerde; -import com.arangodb.internal.serde.InternalSerdeProvider; -import com.arangodb.internal.serde.SerdeUtils; -import com.arangodb.shaded.fasterxml.jackson.databind.node.JsonNodeFactory; -import com.arangodb.shaded.fasterxml.jackson.databind.node.ObjectNode; -import com.arangodb.util.RawBytes; -import com.arangodb.util.RawJson; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.EnumSource; - -import static org.assertj.core.api.Assertions.assertThat; - - -class SerdeTest { - - @ParameterizedTest - @EnumSource(ContentType.class) - void rawJsonSerde(ContentType type) { - InternalSerde s = new InternalSerdeProvider().of(type); - ObjectNode node = JsonNodeFactory.instance.objectNode().put("foo", "bar"); - RawJson raw = RawJson.of(SerdeUtils.INSTANCE.writeJson(node)); - byte[] serialized = s.serialize(raw); - RawJson deserialized = s.deserialize(serialized, RawJson.class); - assertThat(deserialized).isEqualTo(raw); - } - - @ParameterizedTest - @EnumSource(ContentType.class) - void rawBytesSerde(ContentType type) { - InternalSerde s = new InternalSerdeProvider().of(type); - ObjectNode node = JsonNodeFactory.instance.objectNode().put("foo", "bar"); - RawBytes raw = RawBytes.of(s.serialize(node)); - byte[] serialized = s.serialize(raw); - RawBytes deserialized = s.deserialize(serialized, RawBytes.class); - assertThat(deserialized).isEqualTo(raw); - } - -} diff --git a/shaded-integration-tests/src/test/native/java/com/arangodb/util/MapBuilder.java b/shaded-integration-tests/src/test/native/java/com/arangodb/util/MapBuilder.java deleted file mode 100644 index 61d05865e..000000000 --- a/shaded-integration-tests/src/test/native/java/com/arangodb/util/MapBuilder.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.util; - -import java.util.LinkedHashMap; -import java.util.Map; - -/** - * @author Mark Vollmary - */ -public class MapBuilder { - - private final Map map; - - public MapBuilder() { - super(); - map = new LinkedHashMap<>(); - } - - public MapBuilder put(final String key, final Object value) { - map.put(key, value); - return this; - } - - public Map get() { - return map; - } -} diff --git a/shaded-integration-tests/src/test/native/java/com/arangodb/util/MapBuilderTest.java b/shaded-integration-tests/src/test/native/java/com/arangodb/util/MapBuilderTest.java deleted file mode 100644 index 0496a685a..000000000 --- a/shaded-integration-tests/src/test/native/java/com/arangodb/util/MapBuilderTest.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.util; - - -import org.junit.jupiter.api.Test; - -import java.util.Map; - -import static org.assertj.core.api.Assertions.assertThat; - - -/** - * @author Mark Vollmary - */ -class MapBuilderTest { - - @Test - void build() { - final Map map = new MapBuilder().put("foo", "bar").get(); - assertThat(map).hasSize(1); - assertThat(map.get("foo")).isNotNull(); - assertThat(map).containsEntry("foo", "bar"); - } -} diff --git a/shaded-integration-tests/src/test/native/java/com/arangodb/util/TestUtils.java b/shaded-integration-tests/src/test/native/java/com/arangodb/util/TestUtils.java deleted file mode 100644 index a8faab73a..000000000 --- a/shaded-integration-tests/src/test/native/java/com/arangodb/util/TestUtils.java +++ /dev/null @@ -1,112 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - - -package com.arangodb.util; - - -import java.util.ArrayList; -import java.util.List; -import java.util.Random; -import java.util.UUID; - -/** - * @author Michele Rastelli - */ -public final class TestUtils { - - private static final String[] allChars = TestUtils.generateAllInputChars(); - private static final Random r = new Random(); - - private TestUtils() { - } - - /** - * Parses {@param version} and checks whether it is greater or equal to - * <{@param otherMajor}, {@param otherMinor}, {@param otherPatch}> - * comparing the corresponding version components in lexicographical order. - */ - public static boolean isAtLeastVersion(final String version, final int otherMajor, final int otherMinor, - final int otherPatch) { - return compareVersion(version, otherMajor, otherMinor, otherPatch) >= 0; - } - - /** - * Parses {@param version} and checks whether it is less than - * <{@param otherMajor}, {@param otherMinor}, {@param otherPatch}> - * comparing the corresponding version components in lexicographical order. - */ - public static boolean isLessThanVersion(final String version, final int otherMajor, final int otherMinor, - final int otherPatch) { - return compareVersion(version, otherMajor, otherMinor, otherPatch) < 0; - } - - private static int compareVersion(final String version, final int otherMajor, final int otherMinor, - final int otherPatch) { - String[] parts = version.split("-")[0].split("\\."); - - int major = Integer.parseInt(parts[0]); - int minor = Integer.parseInt(parts[1]); - int patch = Integer.parseInt(parts[2]); - - int majorComparison = Integer.compare(major, otherMajor); - if (majorComparison != 0) { - return majorComparison; - } - - int minorComparison = Integer.compare(minor, otherMinor); - if (minorComparison != 0) { - return minorComparison; - } - - return Integer.compare(patch, otherPatch); - } - - private static String[] generateAllInputChars() { - List list = new ArrayList<>(); - for (int codePoint = 0; codePoint < Character.MAX_CODE_POINT + 1; codePoint++) { - String s = new String(Character.toChars(codePoint)); - if (codePoint == 47 || // '/' - codePoint == 58 || // ':' - Character.isISOControl(codePoint) || - Character.isLowSurrogate(s.charAt(0)) || - (Character.isHighSurrogate(s.charAt(0)) && s.length() == 1)) { - continue; - } - list.add(s); - } - return list.toArray(new String[0]); - } - - public static String generateRandomDbName(int length, boolean extendedNames) { - if (extendedNames) { - int max = allChars.length; - StringBuilder sb = new StringBuilder(); - for (int i = 0; i < length; i++) { - String allChar = allChars[r.nextInt(max)]; - sb.append(allChar); - } - return UnicodeUtils.normalize(sb.toString()); - } else { - return UUID.randomUUID().toString(); - } - } - -} diff --git a/shaded-integration-tests/src/test/native/java/com/arangodb/util/UnicodeUtilsTest.java b/shaded-integration-tests/src/test/native/java/com/arangodb/util/UnicodeUtilsTest.java deleted file mode 100644 index b295223bd..000000000 --- a/shaded-integration-tests/src/test/native/java/com/arangodb/util/UnicodeUtilsTest.java +++ /dev/null @@ -1,60 +0,0 @@ -package com.arangodb.util; - -import com.arangodb.internal.util.EncodeUtils; -import org.graalvm.home.Version; -import org.graalvm.nativeimage.ImageInfo; -import org.graalvm.polyglot.Context; -import org.graalvm.polyglot.Value; -import org.junit.jupiter.api.AfterAll; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.Test; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assumptions.assumeFalse; -import static org.junit.jupiter.api.Assumptions.assumeTrue; - - -class UnicodeUtilsTest { - - private static final String encodeFn = "(function encode(x){return encodeURIComponent(x);})"; - private static final String normalizeFn = "(function normalize(x){return x.normalize('NFC');})"; - private static Context context; - private static Value jsEncoder; - private static Value jsNormalizer; - - @BeforeAll - static void beforeClass() { - assumeFalse(ImageInfo.inImageCode(), "skipped in native mode"); - assumeTrue(Version.getCurrent().isRelease(), "This test requires GraalVM"); - context = Context.create(); - jsEncoder = context.eval("js", encodeFn); - jsNormalizer = context.eval("js", normalizeFn); - } - - @AfterAll - static void afterClass() { - if (context != null) - context.close(); - } - - @Test - void normalizeShouldBehaveAsJs() { - for (int i = 0; i < 10_000; i++) { - String value = TestUtils.generateRandomDbName(100, true); - String jsNormalized = jsNormalizer.execute(value).as(String.class); - String javaNormalized = UnicodeUtils.normalize(value); - assertThat(javaNormalized).isEqualTo(jsNormalized); - } - } - - @Test - void encodeURIComponentShouldBehaveAsJs() { - for (int i = 0; i < 10_000; i++) { - String value = TestUtils.generateRandomDbName(100, true); - String jsEncoded = jsEncoder.execute(value).as(String.class); - String driverJavaEncoded = EncodeUtils.encodeURIComponent(value); - assertThat(driverJavaEncoded).isEqualTo(jsEncoded); - } - } - -} \ No newline at end of file diff --git a/shaded-integration-tests/src/test/native/java/perf/Benchmark.java b/shaded-integration-tests/src/test/native/java/perf/Benchmark.java deleted file mode 100644 index 8fade9e17..000000000 --- a/shaded-integration-tests/src/test/native/java/perf/Benchmark.java +++ /dev/null @@ -1,123 +0,0 @@ -package perf; - -import java.util.Date; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.atomic.AtomicInteger; - -public abstract class Benchmark { - - private static final int SYNC_THREADS = 128; - private final CountDownLatch completed = new CountDownLatch(1); - private volatile Long startTime = null; - private volatile Long endTime = null; - private volatile int targetCount = Integer.MAX_VALUE; - private final AtomicInteger counter = new AtomicInteger(); - private final ExecutorService es = Executors.newFixedThreadPool(SYNC_THREADS); - private final int warmupDurationSeconds; - private final int numberOfRequests; - - public Benchmark(int warmupDurationSeconds, int numberOfRequests) { - this.warmupDurationSeconds = warmupDurationSeconds; - this.numberOfRequests = numberOfRequests; - } - - public void run() { - // warmup - startBenchmark(); - - // start monitor / warmup - startMonitor(); - - // start benchmark - startMeasuring(); - } - - private void startMonitor() { - for (int i = 0; i < warmupDurationSeconds; i++) { - counter.set(0); - long start = new Date().getTime(); - try { - Thread.sleep(1_000); - } catch (InterruptedException e) { - e.printStackTrace(); - } - - long current = new Date().getTime(); - long elapsed = current - start; - double reqsPerSec = 1_000.0 * counter.get() / elapsed; - System.out.println("reqs/s: \t" + reqsPerSec); - } - } - - private void startBenchmark() { - start(); - new Thread(() -> { - try { - completed.await(); - // wait graceful shutdown - Thread.sleep(1_000); - } catch (InterruptedException e) { - e.printStackTrace(); - } - // force shutdown - es.shutdown(); - shutdown(); - }).start(); - } - - private void startMeasuring() { - counter.set(0); - targetCount = numberOfRequests; - startTime = System.currentTimeMillis(); - } - - public long waitComplete() { - try { - completed.await(); - } catch (InterruptedException e) { - e.printStackTrace(); - } - return endTime - startTime; - } - - /** - * @return req/s - */ - public long getThroughput() { - return targetCount * 1000L / (endTime - startTime); - } - - /** - * notify the success of #count requests - * - * @return whether more requests should be performed - */ - private boolean success() { - if (endTime != null) return false; - if (counter.addAndGet(1) >= targetCount) { - endTime = System.currentTimeMillis(); - completed.countDown(); - return false; - } - return true; - } - - private void start() { - for (int i = 0; i < SYNC_THREADS; i++) { - es.execute(() -> { - boolean more = true; - while (more) { - sendRequest(); - more = success(); - } - }); - } - } - - protected abstract void sendRequest(); - - protected abstract void shutdown(); - -} diff --git a/shaded-integration-tests/src/test/native/java/perf/SimpleSyncPerfTest.java b/shaded-integration-tests/src/test/native/java/perf/SimpleSyncPerfTest.java deleted file mode 100644 index 2d230779f..000000000 --- a/shaded-integration-tests/src/test/native/java/perf/SimpleSyncPerfTest.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed 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. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package perf; - -import com.arangodb.ArangoDB; -import com.arangodb.Protocol; -import org.junit.jupiter.api.Disabled; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.EnumSource; - -import java.util.Date; - -/** - * @author Michele Rastelli - */ -@Disabled -class SimpleSyncPerfTest { - private static final int REPETITIONS = 50_000; - - private void doGetVersion(ArangoDB arangoDB) { - for (int i = 0; i < REPETITIONS; i++) { - arangoDB.getVersion(); - } - } - - @ParameterizedTest - @EnumSource(Protocol.class) - void getVersion(Protocol protocol) throws InterruptedException { - ArangoDB arangoDB = new ArangoDB.Builder().useProtocol(protocol).build(); - // warmup - doGetVersion(arangoDB); - - long start = new Date().getTime(); - doGetVersion(arangoDB); - long end = new Date().getTime(); - System.out.println("elapsed ms: " + (end - start)); - Thread.sleep(5000); - } -} diff --git a/shaded-integration-tests/src/test/native/java/perf/SyncBenchmarkTest.java b/shaded-integration-tests/src/test/native/java/perf/SyncBenchmarkTest.java deleted file mode 100644 index f30ef331a..000000000 --- a/shaded-integration-tests/src/test/native/java/perf/SyncBenchmarkTest.java +++ /dev/null @@ -1,71 +0,0 @@ -package perf; - -import com.arangodb.ArangoDB; -import com.arangodb.DbName; -import com.arangodb.Protocol; -import com.arangodb.Request; -import org.junit.jupiter.api.Disabled; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.EnumSource; - -@Disabled -public class SyncBenchmarkTest { - private final int warmupDurationSeconds = 15; - private final int numberOfRequests = 1_000_000; - - @ParameterizedTest - @EnumSource(Protocol.class) - void getVersion(Protocol protocol) { - System.out.println("-----------------------------------------"); - System.out.println("--- getVersion(): " + protocol); - System.out.println("-----------------------------------------"); - - ArangoDB adb = new ArangoDB.Builder().useProtocol(protocol).build(); - Benchmark benchmark = new Benchmark(warmupDurationSeconds, numberOfRequests) { - @Override - protected void sendRequest() { - adb.getVersion(); - } - - @Override - protected void shutdown() { - adb.shutdown(); - } - }; - benchmark.run(); - System.out.println("elapsed time [ms]: \t" + benchmark.waitComplete()); - System.out.println("throughput [req/s]: \t" + benchmark.getThroughput()); - } - - @ParameterizedTest - @EnumSource(Protocol.class) - void getVersionWithDetails(Protocol protocol) { - System.out.println("-----------------------------------------"); - System.out.println("--- getVersion w/ details: " + protocol); - System.out.println("-----------------------------------------"); - - ArangoDB adb = new ArangoDB.Builder().useProtocol(protocol).build(); - Benchmark benchmark = new Benchmark(warmupDurationSeconds, numberOfRequests) { - private final Request request = Request.builder() - .db(DbName.SYSTEM) - .method(Request.Method.GET) - .path("/_api/version") - .queryParam("details", "true") - .build(); - - @Override - protected void sendRequest() { - adb.execute(request, Void.class); - } - - @Override - protected void shutdown() { - adb.shutdown(); - } - }; - benchmark.run(); - System.out.println("elapsed time [ms]: \t" + benchmark.waitComplete()); - System.out.println("throughput [req/s]: \t" + benchmark.getThroughput()); - } - -} diff --git a/shaded-integration-tests/src/test/resources b/shaded-integration-tests/src/test/resources new file mode 120000 index 000000000..88e279d36 --- /dev/null +++ b/shaded-integration-tests/src/test/resources @@ -0,0 +1 @@ +../../../driver/src/test/resources \ No newline at end of file diff --git a/shaded-integration-tests/src/test/resources/META-INF/native-image/native-image.properties b/shaded-integration-tests/src/test/resources/META-INF/native-image/native-image.properties deleted file mode 100644 index b039368e7..000000000 --- a/shaded-integration-tests/src/test/resources/META-INF/native-image/native-image.properties +++ /dev/null @@ -1,8 +0,0 @@ -Args=\ - -H:ResourceConfigurationResources=${.}/resource-config.json \ - -H:ReflectionConfigurationResources=${.}/reflect-config.json \ - -H:SerializationConfigurationResources=${.}/serialization-config.json \ - --initialize-at-build-time=\ - ch.qos.logback,\ - org.slf4j,\ - org.junit.platform.engine.TestTag diff --git a/shaded-integration-tests/src/test/resources/META-INF/native-image/reflect-config.json b/shaded-integration-tests/src/test/resources/META-INF/native-image/reflect-config.json deleted file mode 100644 index e8a1f86bc..000000000 --- a/shaded-integration-tests/src/test/resources/META-INF/native-image/reflect-config.json +++ /dev/null @@ -1,359 +0,0 @@ -[ - { - "name":"org.junit.jupiter.engine.extension.TimeoutInvocationFactory$SingleThreadExecutorResource", - "methods":[{"name":"","parameterTypes":[] }] - }, - { - "name": "org.junit.jupiter.engine.extension.TimeoutInvocationFactory$SingleThreadExecutorResource", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "ch.qos.logback.classic.encoder.PatternLayoutEncoder", - "allPublicMethods": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "ch.qos.logback.classic.pattern.DateConverter", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "ch.qos.logback.classic.pattern.LevelConverter", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "ch.qos.logback.classic.pattern.LineSeparatorConverter", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "ch.qos.logback.classic.pattern.LoggerConverter", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "ch.qos.logback.classic.pattern.MessageConverter", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "ch.qos.logback.classic.pattern.ThreadConverter", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "ch.qos.logback.core.ConsoleAppender", - "allPublicMethods": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "com.arangodb.ArangoCollectionTest$TestUpdateEntity", - "allDeclaredFields":true, - "allDeclaredMethods":true, - "allPublicMethods":true, - "allDeclaredConstructors":true, - "allDeclaredClasses":true - }, - { - "name": "com.arangodb.ArangoCollectionTest$TestUpdateEntitySerializeNullFalse", - "allDeclaredFields":true, - "allDeclaredMethods":true, - "allPublicMethods":true, - "allDeclaredConstructors":true, - "allDeclaredClasses":true - }, - { - "name": "com.arangodb.ArangoDatabaseTest$TransactionTestEntity", - "allDeclaredFields": true, - "allDeclaredMethods": true, - "allPublicMethods": true, - "allDeclaredConstructors": true, - "allDeclaredClasses": true - }, - { - "name": "com.arangodb.async.ArangoDatabaseTest$TransactionTestEntity", - "allDeclaredFields": true, - "allDeclaredMethods": true, - "allPublicMethods": true, - "allDeclaredConstructors": true, - "allDeclaredClasses": true - }, - { - "name": "com.arangodb.async.example.document.AqlQueryWithSpecialReturnTypesExampleTest$Gender", - "allDeclaredFields": true, - "allDeclaredMethods": true, - "allPublicMethods": true, - "allDeclaredClasses": true - }, - { - "name": "com.arangodb.async.example.document.TestEntity", - "allDeclaredFields": true, - "allDeclaredMethods": true, - "allPublicMethods": true, - "allDeclaredConstructors": true, - "allDeclaredClasses": true - }, - { - "name": "com.arangodb.async.example.graph.AQLActorsAndMoviesExampleTest$Actor", - "allDeclaredFields": true, - "allDeclaredMethods": true, - "allPublicMethods": true, - "allDeclaredConstructors": true, - "allDeclaredClasses": true - }, - { - "name": "com.arangodb.async.example.graph.AQLActorsAndMoviesExampleTest$Movie", - "allDeclaredFields": true, - "allDeclaredMethods": true, - "allPublicMethods": true, - "allDeclaredConstructors": true, - "allDeclaredClasses": true - }, - { - "name": "com.arangodb.async.example.graph.Circle", - "allDeclaredFields": true, - "allDeclaredMethods": true, - "allPublicMethods": true, - "allDeclaredConstructors": true, - "allDeclaredClasses": true - }, - { - "name": "com.arangodb.async.example.graph.CircleEdge", - "allDeclaredFields": true, - "allDeclaredMethods": true, - "allPublicMethods": true, - "allDeclaredConstructors": true, - "allDeclaredClasses": true - }, - { - "name": "com.arangodb.async.example.graph.ShortestPathInAQLExampleTest$Pair", - "allDeclaredFields": true, - "allDeclaredMethods": true, - "allPublicMethods": true, - "allDeclaredConstructors": true, - "allDeclaredClasses": true - }, - { - "name": "com.arangodb.example.document.AqlQueryWithSpecialReturnTypesExampleTest$Gender", - "allDeclaredFields": true, - "allDeclaredMethods": true, - "allPublicMethods": true, - "allDeclaredClasses": true - }, - { - "name": "com.arangodb.example.document.TestEntity", - "allDeclaredFields": true, - "allDeclaredMethods": true, - "allPublicMethods": true, - "allDeclaredConstructors": true, - "allDeclaredClasses": true - }, - { - "name": "com.arangodb.example.graph.AQLActorsAndMoviesExampleTest$Actor", - "allDeclaredFields": true, - "allDeclaredMethods": true, - "allPublicMethods": true, - "allDeclaredConstructors": true, - "allDeclaredClasses": true - }, - { - "name": "com.arangodb.example.graph.AQLActorsAndMoviesExampleTest$Movie", - "allDeclaredFields": true, - "allDeclaredMethods": true, - "allPublicMethods": true, - "allDeclaredConstructors": true, - "allDeclaredClasses": true - }, - { - "name": "com.arangodb.example.graph.Circle", - "allDeclaredFields": true, - "allDeclaredMethods": true, - "allPublicMethods": true, - "allDeclaredConstructors": true, - "allDeclaredClasses": true - }, - { - "name": "com.arangodb.example.graph.CircleEdge", - "allDeclaredFields": true, - "allDeclaredMethods": true, - "allPublicMethods": true, - "allDeclaredConstructors": true, - "allDeclaredClasses": true - }, - { - "name": "com.arangodb.example.graph.ShortestPathInAQLExampleTest$Pair", - "allDeclaredFields": true, - "allDeclaredMethods": true, - "allPublicMethods": true, - "allDeclaredConstructors": true, - "allDeclaredClasses": true - }, - { - "name": "com.arangodb.serde.CustomSerdeTest$Person", - "allDeclaredFields": true, - "allDeclaredMethods": true, - "allPublicMethods": true, - "allDeclaredClasses": true - }, - { - "name": "com.arangodb.serde.CustomSerdeTest$PersonDeserializer", - "allDeclaredMethods": true, - "allPublicMethods": true, - "allDeclaredClasses": true - }, - { - "name": "com.arangodb.serde.CustomSerdeTest$PersonSerializer", - "allDeclaredMethods": true, - "allPublicMethods": true, - "allDeclaredClasses": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "com.arangodb.serde.CustomTypeHintTest$Animal", - "allDeclaredMethods": true, - "allPublicMethods": true, - "allDeclaredClasses": true - }, - { - "name": "com.arangodb.serde.CustomTypeHintTest$Gorilla", - "allDeclaredFields": true, - "allDeclaredMethods": true, - "allPublicMethods": true, - "allDeclaredConstructors": true, - "allDeclaredClasses": true - }, - { - "name": "com.arangodb.serde.CustomTypeHintTest$Zoo", - "allDeclaredFields": true, - "allDeclaredMethods": true, - "allPublicMethods": true, - "allDeclaredConstructors": true, - "allDeclaredClasses": true - }, - { - "name": "java.util.HashSet", - "allDeclaredMethods": true, - "allDeclaredConstructors": true - }, - { - "name": "com.arangodb.mapping.annotations.AnnotatedEntity", - "allDeclaredFields": true, - "allDeclaredMethods": true, - "allDeclaredConstructors": true - }, - { - "name": "com.fasterxml.jackson.databind.deser.std.DateDeserializers$SqlDateDeserializer", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "com.fasterxml.jackson.databind.ser.std.SqlDateSerializer", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name":"com.arangodb.async.ArangoCollectionTest$Animal", - "allDeclaredMethods":true, - "allPublicMethods":true, - "allDeclaredClasses":true - }, - { - "name":"com.arangodb.async.ArangoCollectionTest$Cat", - "allDeclaredFields":true, - "allDeclaredMethods":true, - "allPublicMethods":true, - "allDeclaredConstructors":true, - "allDeclaredClasses":true - }, - { - "name":"com.arangodb.async.ArangoCollectionTest$Dog", - "allDeclaredFields":true, - "allDeclaredMethods":true, - "allPublicMethods":true, - "allDeclaredConstructors":true, - "allDeclaredClasses":true - }, - { - "name":"com.arangodb.ArangoCollectionTest$Animal", - "allDeclaredMethods":true, - "allPublicMethods":true, - "allDeclaredClasses":true - }, - { - "name":"com.arangodb.ArangoCollectionTest$AnnotatedEntity", - "allDeclaredFields":true, - "allDeclaredMethods":true, - "allPublicMethods":true, - "allDeclaredConstructors":true, - "allDeclaredClasses":true - }, - { - "name":"com.arangodb.ArangoCollectionTest$Cat", - "allDeclaredFields":true, - "allDeclaredMethods":true, - "allPublicMethods":true, - "allDeclaredConstructors":true, - "allDeclaredClasses":true - }, - { - "name":"com.arangodb.ArangoCollectionTest$Dog", - "allDeclaredFields":true, - "allDeclaredMethods":true, - "allPublicMethods":true, - "allDeclaredConstructors":true, - "allDeclaredClasses":true - } -] diff --git a/shaded-integration-tests/src/test/resources/META-INF/native-image/resource-config.json b/shaded-integration-tests/src/test/resources/META-INF/native-image/resource-config.json deleted file mode 100644 index a6eea307e..000000000 --- a/shaded-integration-tests/src/test/resources/META-INF/native-image/resource-config.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "resources": { - "includes": [ - { - "pattern": "\\Qarangodb.properties\\E" - }, - { - "pattern": "\\Qarangodb-bad.properties\\E" - }, - { - "pattern": "\\Qarangodb-bad2.properties\\E" - }, - { - "pattern":"\\Qarangodb-with-prefix.properties\\E" - }, - { - "pattern": "\\Qlogback-test.xml\\E" - }, - { - "pattern": "\\Qexample.truststore\\E" - } - ] - }, - "bundles": [] -} diff --git a/shaded-integration-tests/src/test/resources/META-INF/native-image/serialization-config.json b/shaded-integration-tests/src/test/resources/META-INF/native-image/serialization-config.json deleted file mode 100644 index 8c832f7ba..000000000 --- a/shaded-integration-tests/src/test/resources/META-INF/native-image/serialization-config.json +++ /dev/null @@ -1,26 +0,0 @@ -[ - { - "name": "java.lang.Exception" - }, - { - "name": "java.lang.RuntimeException" - }, - { - "name": "java.lang.StackTraceElement" - }, - { - "name": "java.lang.StackTraceElement[]" - }, - { - "name": "java.lang.String" - }, - { - "name": "java.lang.Throwable" - }, - { - "name": "java.util.Collections$EmptyList" - }, - { - "name": "java.util.Collections$SingletonList" - } -] diff --git a/shaded-integration-tests/src/test/resources/arangodb-bad.properties b/shaded-integration-tests/src/test/resources/arangodb-bad.properties deleted file mode 100644 index 2b2743531..000000000 --- a/shaded-integration-tests/src/test/resources/arangodb-bad.properties +++ /dev/null @@ -1 +0,0 @@ -arangodb.hosts=127.0.0.1:8529,127.0.0.1:fail \ No newline at end of file diff --git a/shaded-integration-tests/src/test/resources/arangodb-config-test.properties b/shaded-integration-tests/src/test/resources/arangodb-config-test.properties deleted file mode 100644 index 23c912293..000000000 --- a/shaded-integration-tests/src/test/resources/arangodb-config-test.properties +++ /dev/null @@ -1,17 +0,0 @@ -adb.hosts=aaa:1111,bbb:2222 -adb.protocol=HTTP_VPACK -adb.user=testUser -adb.password=testPassword -adb.jwt=testJwt -adb.timeout=9876 -adb.useSsl=true -adb.verifyHost=false -adb.vstChunkSize=1234 -adb.maxConnections=123 -adb.connectionTtl=12345 -adb.keepAliveInterval=123456 -adb.acquireHostList=true -adb.acquireHostListInterval=1234567 -adb.loadBalancingStrategy=ROUND_ROBIN -adb.responseQueueTimeSamples=12345678 - diff --git a/shaded-integration-tests/src/test/resources/arangodb-with-prefix.properties b/shaded-integration-tests/src/test/resources/arangodb-with-prefix.properties deleted file mode 100644 index 36fb2d0a5..000000000 --- a/shaded-integration-tests/src/test/resources/arangodb-with-prefix.properties +++ /dev/null @@ -1,3 +0,0 @@ -adb.hosts=172.28.0.1:8529 -adb.acquireHostList=true -adb.password=test diff --git a/shaded-integration-tests/src/test/resources/arangodb.properties b/shaded-integration-tests/src/test/resources/arangodb.properties deleted file mode 100644 index fa580e439..000000000 --- a/shaded-integration-tests/src/test/resources/arangodb.properties +++ /dev/null @@ -1,5 +0,0 @@ -arangodb.hosts=172.28.0.1:8529 -arangodb.acquireHostList=true -arangodb.password=test -arangodb.timeout=30000 -arangodb.responseQueueTimeSamples=20 diff --git a/shaded-integration-tests/src/test/resources/example.truststore b/shaded-integration-tests/src/test/resources/example.truststore deleted file mode 100644 index e683a48b8a25067c921385081a3a930eae74f05a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2251 zcmchYc{J1w7sux}E5;y8B}*YomhrQUl4Zh33fZ&o%D!YgWO-yNOR|<_MwZAv^b|$1 z4p~c&WULXdElUw2YK+JGyyv{{b58%i=iKif_w&a+_k8a?_p;VlYY+$odLZC$akyT0 z4Y(Fa^b8>$pwM`R4<`hI06-Fa59C5}$RPnZAPYSN00;=21pnMR(%M&}Km!(L7TSc* z=$^fFKa5!fuSahq`Sr?``myydFdA9qeJmmU%K3y1N=h%0vMB{%-vm;*#xs}G*+Y{B z1BAKeQf>IA?PRq(J09eo^7pmNV*73U_o12+&ZolmB6Odb@>Fv{X(@(B&7|!Q&6~bh zU|rD7uu*l}%BNB0Av&LZ-NA^wVP{Q~p-e|fe2mM?9(V)l-=NHZtmjlR;JnoZbH^6;I2x zuKt3aE+TJ;G@`t`#4Z| zV(PfByq(zoF>?>64;uFPiCYl_4(UEV+D-vu&?Jv`z6`JIaJVF^`$I8JT_~CR`ybak zs|<83L@1XJ|Mr!_Q3QAL3|g?ZRM@|pu~QU#U*3Mh?)hN;38dZdz9M3$N&-hCbUC!W zy6W}rjrOyXh{!1Y!q5#`l;yjxpd_($j6&bFalp7%>|w*rD8?u$Dh& zhnSbYn_C9^KZI4oO|C@uU;DM zeKFHuyIJkq3qz`NinbLonP@6!SM5oD^KM7--m1mebq!*|XLSFzd1@6ByH*gJvOXod zH(Fa0OMrFT9^zUL3W;j}s@jGgH(}Ld$d13z1c5n|g z#CZC9>E{QEdUS@gVr4$eW#)5!Fvef**m+kO1IeTQTkGnF*;IXR#@P^h>uB1?T8f9l zr7nuXJP=c;1XRnGLp;L^qGVuR?(%y3 zBiXKS^_-a7&Y+XIiSqrZG|eVmJ@Yauyy9v<2k%l1o2_D#SyFQ9DZwvLIi{<~&y2e| z*c&;Uk#49GV{c=HXX)`R1nH?@$Cv3G?s`F>?XWK2phUwn8+Z>HZX#f`9DGwFBcuQa z6Ksuo$<(Ph+Z!V9>&Y%Um2N{yOPy5o9}FXPf`6hU9@10%d#=vbCzn<`|9u=0Hdq{} z4uQa8KoTqxBthK^VNd`Hg@=Q+&L9TKE*p0t?mGqm&0z-(P=n;%EsHAidXK+eN>UKvkDxea0 zp#P-*_kKu#_&+T_vtC@ko6OJq($nC3Il0R9b)`T|= z(TxpI;UvM~h;ya`j%K$|DveUkqwOgxNgW`~(B`skW_svLblMZd>t(7~!=6F@g`yRh zy~z;$fyd*DmFg$PXLh0{VrXUhDcn#P00D}{z~i9E!7N3%;D_P-?KS)7I!>)kVlVg? zCil$0Y`yt5{huZt?A3vZ07N{{S9^WVja*wIE@lvVMTo9J=QQJLe0*qjRXJ9<+`E4);>i4nt=K)EXsJ@Ens#;)OFz`Z~h}JB90br*0qe?J@UWS#m<`(ucTBh(~WY zT&qusDCN_NPebRa37L7#jufzt-IZ~Y0Fs64s48}{7E*XyrWW9KvG9JHWT9Luz zG78>gPEO>WFbehVA~h|BOCn7Dn0iJ@Vu^MxM|7z9?a7_m(|c`x0-q`#d>rb?oD+4F zL~7~s-r&?vRV+qho|h!e+L~La@@Qp~zfF1($h`xXcX)*5h6zn^@?GOf`Rr7t&~Bju mlH*f^c*Ep6%5+rI!$=hPYi diff --git a/shaded-integration-tests/src/test/resources/logback-test.xml b/shaded-integration-tests/src/test/resources/logback-test.xml deleted file mode 100644 index b1d65b196..000000000 --- a/shaded-integration-tests/src/test/resources/logback-test.xml +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n - - - - - - - - - - - From eda129b820af12fc0e2b5b0440bb4a0807a4ee4e Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Tue, 21 Feb 2023 09:45:06 +0100 Subject: [PATCH 250/254] [DE-436] reuse code in shaded integration tests --- .github/workflows/test.yml | 2 +- driver/pom.xml | 6 ----- .../java/com/arangodb/PackageVersionTest.java | 21 +++------------ .../java/com/arangodb/config/ConfigUtils.java | 20 -------------- .../util => graalvm}/UnicodeUtilsTest.java | 4 ++- .../ArangoConfigPropertiesMPImpl.java | 4 ++- .../ConfigMPDefaultsTest.java} | 7 ++--- .../ConfigTest.java => mp/ConfigMPTest.java} | 8 +++--- driver/src/test/java/mp/ConfigUtilsMP.java | 26 +++++++++++++++++++ 9 files changed, 45 insertions(+), 53 deletions(-) rename driver/src/test/java/{com/arangodb/util => graalvm}/UnicodeUtilsTest.java (95%) rename driver/src/test/java/{com/arangodb/config => mp}/ArangoConfigPropertiesMPImpl.java (97%) rename driver/src/test/java/{com/arangodb/config/ConfigDefaultsTest.java => mp/ConfigMPDefaultsTest.java} (86%) rename driver/src/test/java/{com/arangodb/config/ConfigTest.java => mp/ConfigMPTest.java} (92%) create mode 100644 driver/src/test/java/mp/ConfigUtilsMP.java diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index a4d9b52ab..d4bef6589 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -129,7 +129,7 @@ jobs: - name: Info run: mvn -version - name: Test - run: mvn -e --no-transfer-progress -am -pl driver test -Dtest=com.arangodb.util.UnicodeUtilsTest -Dsurefire.failIfNoSpecifiedTests=false + run: mvn -e --no-transfer-progress -am -pl driver test -Dtest=graalvm.UnicodeUtilsTest -Dsurefire.failIfNoSpecifiedTests=false test-jwt: timeout-minutes: 20 diff --git a/driver/pom.xml b/driver/pom.xml index 4c865a1a1..65493fdc8 100644 --- a/driver/pom.xml +++ b/driver/pom.xml @@ -157,12 +157,6 @@ 22.3.0 test - - ru.lanwen.verbalregex - java-verbal-expressions - 1.8 - test - io.smallrye.config smallrye-config-core diff --git a/driver/src/test/java/com/arangodb/PackageVersionTest.java b/driver/src/test/java/com/arangodb/PackageVersionTest.java index afef0ee5c..b77408364 100644 --- a/driver/src/test/java/com/arangodb/PackageVersionTest.java +++ b/driver/src/test/java/com/arangodb/PackageVersionTest.java @@ -5,31 +5,16 @@ import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.EnumSource; -import static ru.lanwen.verbalregex.VerbalExpression.regex; - -import ru.lanwen.verbalregex.VerbalExpression; - import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assumptions.assumeTrue; class PackageVersionTest extends BaseJunit5 { + private static final String EXPECTED_VERSION = "7.0.0-ALPHA.2"; + @Test void packageVersion() { - VerbalExpression testRegex = regex() - .startOfLine() - // major - .digit().atLeast(1) - .then(".") - // minor - .digit().atLeast(1) - .then(".") - // patch - .digit().atLeast(1) - .maybe(regex().anything()) - .endOfLine() - .build(); - assertThat(PackageVersion.VERSION).matches(testRegex.toString()); + assertThat(PackageVersion.VERSION).isEqualTo(EXPECTED_VERSION); } @ParameterizedTest diff --git a/driver/src/test/java/com/arangodb/config/ConfigUtils.java b/driver/src/test/java/com/arangodb/config/ConfigUtils.java index 99b12ca34..0b7dca677 100644 --- a/driver/src/test/java/com/arangodb/config/ConfigUtils.java +++ b/driver/src/test/java/com/arangodb/config/ConfigUtils.java @@ -1,27 +1,7 @@ package com.arangodb.config; -import io.smallrye.config.PropertiesConfigSourceProvider; -import io.smallrye.config.SmallRyeConfig; -import io.smallrye.config.SmallRyeConfigBuilder; - public class ConfigUtils { - public static ArangoConfigProperties loadConfigMP() { - return loadConfigMP("arangodb.properties"); - } - - public static ArangoConfigProperties loadConfigMP(final String location) { - return loadConfigMP(location, "arangodb"); - } - - public static ArangoConfigProperties loadConfigMP(final String location, final String prefix) { - SmallRyeConfig cfg = new SmallRyeConfigBuilder() - .withSources(new PropertiesConfigSourceProvider(location, ConfigUtils.class.getClassLoader(), false)) - .withMapping(ArangoConfigPropertiesMPImpl.class, prefix) - .build(); - return cfg.getConfigMapping(ArangoConfigPropertiesMPImpl.class, prefix); - } - public static ArangoConfigProperties loadConfig() { return ArangoConfigProperties.fromFile(); } diff --git a/driver/src/test/java/com/arangodb/util/UnicodeUtilsTest.java b/driver/src/test/java/graalvm/UnicodeUtilsTest.java similarity index 95% rename from driver/src/test/java/com/arangodb/util/UnicodeUtilsTest.java rename to driver/src/test/java/graalvm/UnicodeUtilsTest.java index b295223bd..66cbbff39 100644 --- a/driver/src/test/java/com/arangodb/util/UnicodeUtilsTest.java +++ b/driver/src/test/java/graalvm/UnicodeUtilsTest.java @@ -1,6 +1,8 @@ -package com.arangodb.util; +package graalvm; import com.arangodb.internal.util.EncodeUtils; +import com.arangodb.util.TestUtils; +import com.arangodb.util.UnicodeUtils; import org.graalvm.home.Version; import org.graalvm.nativeimage.ImageInfo; import org.graalvm.polyglot.Context; diff --git a/driver/src/test/java/com/arangodb/config/ArangoConfigPropertiesMPImpl.java b/driver/src/test/java/mp/ArangoConfigPropertiesMPImpl.java similarity index 97% rename from driver/src/test/java/com/arangodb/config/ArangoConfigPropertiesMPImpl.java rename to driver/src/test/java/mp/ArangoConfigPropertiesMPImpl.java index 940d0a2dd..21f6fe850 100644 --- a/driver/src/test/java/com/arangodb/config/ArangoConfigPropertiesMPImpl.java +++ b/driver/src/test/java/mp/ArangoConfigPropertiesMPImpl.java @@ -1,6 +1,8 @@ -package com.arangodb.config; +package mp; import com.arangodb.Protocol; +import com.arangodb.config.ArangoConfigProperties; +import com.arangodb.config.HostDescription; import com.arangodb.entity.LoadBalancingStrategy; import java.util.List; diff --git a/driver/src/test/java/com/arangodb/config/ConfigDefaultsTest.java b/driver/src/test/java/mp/ConfigMPDefaultsTest.java similarity index 86% rename from driver/src/test/java/com/arangodb/config/ConfigDefaultsTest.java rename to driver/src/test/java/mp/ConfigMPDefaultsTest.java index fc65af6e4..5e32807c2 100644 --- a/driver/src/test/java/com/arangodb/config/ConfigDefaultsTest.java +++ b/driver/src/test/java/mp/ConfigMPDefaultsTest.java @@ -1,16 +1,17 @@ -package com.arangodb.config; +package mp; +import com.arangodb.config.ArangoConfigProperties; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.condition.DisabledInNativeImage; import static org.assertj.core.api.Assertions.assertThat; @DisabledInNativeImage -class ConfigDefaultsTest { +class ConfigMPDefaultsTest { @Test void defaultValues() { - ArangoConfigProperties config = ConfigUtils.loadConfigMP("arangodb.properties", "wrong"); + ArangoConfigProperties config = ConfigUtilsMP.loadConfigMP("arangodb.properties", "wrong"); checkResult(config); } diff --git a/driver/src/test/java/com/arangodb/config/ConfigTest.java b/driver/src/test/java/mp/ConfigMPTest.java similarity index 92% rename from driver/src/test/java/com/arangodb/config/ConfigTest.java rename to driver/src/test/java/mp/ConfigMPTest.java index 8aa4c3188..c26c26171 100644 --- a/driver/src/test/java/com/arangodb/config/ConfigTest.java +++ b/driver/src/test/java/mp/ConfigMPTest.java @@ -1,6 +1,8 @@ -package com.arangodb.config; +package mp; import com.arangodb.Protocol; +import com.arangodb.config.ArangoConfigProperties; +import com.arangodb.config.HostDescription; import com.arangodb.entity.LoadBalancingStrategy; import org.assertj.core.api.InstanceOfAssertFactories; import org.junit.jupiter.api.Test; @@ -9,7 +11,7 @@ import static org.assertj.core.api.Assertions.assertThat; @DisabledInNativeImage -class ConfigTest { +class ConfigMPTest { private final HostDescription hostA = new HostDescription("aaa", 1111); private final HostDescription hostB = new HostDescription("bbb", 2222); private final Protocol protocol = Protocol.HTTP_VPACK; @@ -30,7 +32,7 @@ class ConfigTest { @Test void readConfig() { - ArangoConfigProperties config = ConfigUtils.loadConfigMP("arangodb-config-test.properties", "adb"); + ArangoConfigProperties config = ConfigUtilsMP.loadConfigMP("arangodb-config-test.properties", "adb"); checkResult(config); } diff --git a/driver/src/test/java/mp/ConfigUtilsMP.java b/driver/src/test/java/mp/ConfigUtilsMP.java new file mode 100644 index 000000000..dabd62cde --- /dev/null +++ b/driver/src/test/java/mp/ConfigUtilsMP.java @@ -0,0 +1,26 @@ +package mp; + +import com.arangodb.config.ArangoConfigProperties; +import io.smallrye.config.PropertiesConfigSourceProvider; +import io.smallrye.config.SmallRyeConfig; +import io.smallrye.config.SmallRyeConfigBuilder; + +public class ConfigUtilsMP { + + public static ArangoConfigProperties loadConfigMP() { + return loadConfigMP("arangodb.properties"); + } + + public static ArangoConfigProperties loadConfigMP(final String location) { + return loadConfigMP(location, "arangodb"); + } + + public static ArangoConfigProperties loadConfigMP(final String location, final String prefix) { + SmallRyeConfig cfg = new SmallRyeConfigBuilder() + .withSources(new PropertiesConfigSourceProvider(location, ConfigUtilsMP.class.getClassLoader(), false)) + .withMapping(ArangoConfigPropertiesMPImpl.class, prefix) + .build(); + return cfg.getConfigMapping(ArangoConfigPropertiesMPImpl.class, prefix); + } + +} From 45e01189bdc187eb85a77913ad2cabceebc78bf7 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Tue, 21 Feb 2023 11:15:38 +0100 Subject: [PATCH 251/254] [DE-436] reuse code in shaded integration tests --- shaded-integration-tests/pom.xml | 56 +++++++++++++++++++++++++++++++- 1 file changed, 55 insertions(+), 1 deletion(-) diff --git a/shaded-integration-tests/pom.xml b/shaded-integration-tests/pom.xml index 2f0bb93ff..2c7e8da7f 100644 --- a/shaded-integration-tests/pom.xml +++ b/shaded-integration-tests/pom.xml @@ -113,7 +113,7 @@ native - src/test/native/java + ${project.build.directory}/generated-sources/replacer jackson @@ -130,6 +130,60 @@ jackson-serde-vpack + + + + com.google.code.maven-replacer-plugin + replacer + 1.5.3 + + + generate-test-sources + + replace + + + + + ${project.basedir}/src/test/native/java + ** + ${project.build.directory}/generated-test-sources + replacer + + **/CustomSerdeTest.**,**/SerdeTest.**,**/SerializableTest.** + + + + com.fasterxml.jackson.databind.JsonNode + com.arangodb.shaded.fasterxml.jackson.databind.JsonNode + + + com.fasterxml.jackson.databind.ObjectNode + com.arangodb.shaded.fasterxml.jackson.databind.ObjectNode + + + + + + org.codehaus.mojo + build-helper-maven-plugin + 3.3.0 + + + generate-test-sources + + add-test-source + + + + ${project.build.directory}/generated-test-sources/replacer + + + + + + + From 90c4d4e458754c5f8233b15da244b65cb6c22e99 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Tue, 21 Feb 2023 11:48:34 +0100 Subject: [PATCH 252/254] fix native tests --- .../com.arangodb/arangodb-java-driver/reflect-config.json | 6 ++++++ .../arangodb-java-driver-shaded/reflect-config.json | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/driver/src/main/resources/META-INF/native-image/com.arangodb/arangodb-java-driver/reflect-config.json b/driver/src/main/resources/META-INF/native-image/com.arangodb/arangodb-java-driver/reflect-config.json index 6ff37492a..f4b9641c1 100644 --- a/driver/src/main/resources/META-INF/native-image/com.arangodb/arangodb-java-driver/reflect-config.json +++ b/driver/src/main/resources/META-INF/native-image/com.arangodb/arangodb-java-driver/reflect-config.json @@ -569,6 +569,12 @@ "allDeclaredMethods": true, "allDeclaredConstructors": true }, + { + "name": "com.arangodb.entity.CursorStats", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, { "name": "com.arangodb.entity.arangosearch.analyzer.StemAnalyzerProperties", "allDeclaredFields": true, diff --git a/shaded/src/main/resources/META-INF/native-image/com.arangodb/arangodb-java-driver-shaded/reflect-config.json b/shaded/src/main/resources/META-INF/native-image/com.arangodb/arangodb-java-driver-shaded/reflect-config.json index 6ff37492a..f4b9641c1 100644 --- a/shaded/src/main/resources/META-INF/native-image/com.arangodb/arangodb-java-driver-shaded/reflect-config.json +++ b/shaded/src/main/resources/META-INF/native-image/com.arangodb/arangodb-java-driver-shaded/reflect-config.json @@ -569,6 +569,12 @@ "allDeclaredMethods": true, "allDeclaredConstructors": true }, + { + "name": "com.arangodb.entity.CursorStats", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, { "name": "com.arangodb.entity.arangosearch.analyzer.StemAnalyzerProperties", "allDeclaredFields": true, From b6c269b0ca1039071e87a302bc4abb3aa892bd6d Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Tue, 21 Feb 2023 12:07:00 +0100 Subject: [PATCH 253/254] rm references to vpack --- driver/src/test/java/com/arangodb/ArangoDatabaseTest.java | 2 +- .../async/example/document/GetDocumentExampleTest.java | 2 +- .../AqlQueryWithSpecialReturnTypesExampleTest.java | 8 ++++---- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/driver/src/test/java/com/arangodb/ArangoDatabaseTest.java b/driver/src/test/java/com/arangodb/ArangoDatabaseTest.java index ce900828b..504679120 100644 --- a/driver/src/test/java/com/arangodb/ArangoDatabaseTest.java +++ b/driver/src/test/java/com/arangodb/ArangoDatabaseTest.java @@ -1224,7 +1224,7 @@ void transactionNumber(ArangoDatabase db) { @ParameterizedTest(name = "{index}") @MethodSource("dbs") - void transactionVPack(ArangoDatabase db) { + void transactionJsonNode(ArangoDatabase db) { final TransactionOptions options = new TransactionOptions().params(JsonNodeFactory.instance.textNode("test")); final JsonNode result = db.transaction("function (params) {return params;}", JsonNode.class, options); assertThat(result.isTextual()).isTrue(); diff --git a/driver/src/test/java/com/arangodb/async/example/document/GetDocumentExampleTest.java b/driver/src/test/java/com/arangodb/async/example/document/GetDocumentExampleTest.java index 11ef3c63f..01a6c149d 100644 --- a/driver/src/test/java/com/arangodb/async/example/document/GetDocumentExampleTest.java +++ b/driver/src/test/java/com/arangodb/async/example/document/GetDocumentExampleTest.java @@ -69,7 +69,7 @@ void getAsBaseDocument() throws InterruptedException, ExecutionException { } @Test - void getAsVPack() throws InterruptedException, ExecutionException { + void getAsJsonNode() throws InterruptedException, ExecutionException { collection.getDocument(key, JsonNode.class) .whenComplete((doc, ex) -> { assertThat(doc).isNotNull(); diff --git a/driver/src/test/java/com/arangodb/example/document/AqlQueryWithSpecialReturnTypesExampleTest.java b/driver/src/test/java/com/arangodb/example/document/AqlQueryWithSpecialReturnTypesExampleTest.java index 9c9279c28..69d213ac4 100644 --- a/driver/src/test/java/com/arangodb/example/document/AqlQueryWithSpecialReturnTypesExampleTest.java +++ b/driver/src/test/java/com/arangodb/example/document/AqlQueryWithSpecialReturnTypesExampleTest.java @@ -64,11 +64,11 @@ void aqlWithLimitQueryAsJsonObject() { final ArangoCursor cursor = db.query(query, bindVars, null, ObjectNode.class); assertThat((Object) cursor).isNotNull(); while (cursor.hasNext()) { - final ObjectNode vpack = cursor.next(); - assertThat(vpack.get("name").asText()) + final ObjectNode node = cursor.next(); + assertThat(node.get("name").asText()) .isIn("TestUser11", "TestUser13", "TestUser15", "TestUser17", "TestUser19"); - assertThat(vpack.get("gender").asText()).isEqualTo(Gender.FEMALE.name()); - assertThat(vpack.get("age").asInt()).isIn(21, 23, 25, 27, 29); + assertThat(node.get("gender").asText()).isEqualTo(Gender.FEMALE.name()); + assertThat(node.get("age").asInt()).isIn(21, 23, 25, 27, 29); } } From 5fe48343698212a3d861e21a88b3a43c1ac38622 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Tue, 21 Feb 2023 13:20:10 +0100 Subject: [PATCH 254/254] test fix --- driver/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/driver/pom.xml b/driver/pom.xml index 65493fdc8..3481759bd 100644 --- a/driver/pom.xml +++ b/driver/pom.xml @@ -34,7 +34,7 @@ maven-compiler-plugin - com/arangodb/util/UnicodeUtilsTest.java + graalvm/UnicodeUtilsTest.java

    t`^k9;Xlat; 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

  • t`^k9;Xlat; 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